18657 lines
1.5 MiB
18657 lines
1.5 MiB
(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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||
var YList;
|
||
|
||
YList = (function() {
|
||
function YList(list) {
|
||
if (list == null) {
|
||
this._list = [];
|
||
} else if (list.constructor === Array) {
|
||
this._list = list;
|
||
} else {
|
||
throw new Error("Y.List expects an Array as a parameter");
|
||
}
|
||
}
|
||
|
||
YList.prototype._name = "List";
|
||
|
||
YList.prototype._getModel = function(types, ops) {
|
||
if (this._model == null) {
|
||
this._model = new ops.ListManager(this).execute();
|
||
this._model.insert(0, this._list);
|
||
}
|
||
delete this._list;
|
||
return this._model;
|
||
};
|
||
|
||
YList.prototype._setModel = function(_model) {
|
||
this._model = _model;
|
||
return delete this._list;
|
||
};
|
||
|
||
YList.prototype.val = function() {
|
||
return this._model.val.apply(this._model, arguments);
|
||
};
|
||
|
||
YList.prototype.ref = function() {
|
||
return this._model.ref.apply(this._model, arguments);
|
||
};
|
||
|
||
YList.prototype.observe = function() {
|
||
this._model.observe.apply(this._model, arguments);
|
||
return this;
|
||
};
|
||
|
||
YList.prototype.unobserve = function() {
|
||
this._model.unobserve.apply(this._model, arguments);
|
||
return this;
|
||
};
|
||
|
||
YList.prototype.insert = function(position, content) {
|
||
if (typeof position !== "number") {
|
||
throw new Error("Y.List.insert expects a Number as the first parameter!");
|
||
}
|
||
this._model.insert(position, [content]);
|
||
return this;
|
||
};
|
||
|
||
YList.prototype.insertContents = function(position, contents) {
|
||
if (typeof position !== "number") {
|
||
throw new Error("Y.List.insert expects a Number as the first parameter!");
|
||
}
|
||
this._model.insert(position, contents);
|
||
return this;
|
||
};
|
||
|
||
YList.prototype["delete"] = function(position, length) {
|
||
this._model["delete"](position, length);
|
||
return this;
|
||
};
|
||
|
||
YList.prototype.push = function(content) {
|
||
this._model.push(content);
|
||
return this;
|
||
};
|
||
|
||
return YList;
|
||
|
||
})();
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
if (window.Y != null) {
|
||
window.Y.List = YList;
|
||
} else {
|
||
throw new Error("You must first import Y!");
|
||
}
|
||
}
|
||
|
||
if (typeof module !== "undefined" && module !== null) {
|
||
module.exports = YList;
|
||
}
|
||
|
||
|
||
},{}],2:[function(require,module,exports){
|
||
module.exports = require('./lib/chai');
|
||
|
||
},{"./lib/chai":3}],3:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
var used = []
|
||
, exports = module.exports = {};
|
||
|
||
/*!
|
||
* Chai version
|
||
*/
|
||
|
||
exports.version = '2.2.0';
|
||
|
||
/*!
|
||
* Assertion Error
|
||
*/
|
||
|
||
exports.AssertionError = require('assertion-error');
|
||
|
||
/*!
|
||
* Utils for plugins (not exported)
|
||
*/
|
||
|
||
var util = require('./chai/utils');
|
||
|
||
/**
|
||
* # .use(function)
|
||
*
|
||
* Provides a way to extend the internals of Chai
|
||
*
|
||
* @param {Function}
|
||
* @returns {this} for chaining
|
||
* @api public
|
||
*/
|
||
|
||
exports.use = function (fn) {
|
||
if (!~used.indexOf(fn)) {
|
||
fn(this, util);
|
||
used.push(fn);
|
||
}
|
||
|
||
return this;
|
||
};
|
||
|
||
/*!
|
||
* Utility Functions
|
||
*/
|
||
|
||
exports.util = util;
|
||
|
||
/*!
|
||
* Configuration
|
||
*/
|
||
|
||
var config = require('./chai/config');
|
||
exports.config = config;
|
||
|
||
/*!
|
||
* Primary `Assertion` prototype
|
||
*/
|
||
|
||
var assertion = require('./chai/assertion');
|
||
exports.use(assertion);
|
||
|
||
/*!
|
||
* Core Assertions
|
||
*/
|
||
|
||
var core = require('./chai/core/assertions');
|
||
exports.use(core);
|
||
|
||
/*!
|
||
* Expect interface
|
||
*/
|
||
|
||
var expect = require('./chai/interface/expect');
|
||
exports.use(expect);
|
||
|
||
/*!
|
||
* Should interface
|
||
*/
|
||
|
||
var should = require('./chai/interface/should');
|
||
exports.use(should);
|
||
|
||
/*!
|
||
* Assert interface
|
||
*/
|
||
|
||
var assert = require('./chai/interface/assert');
|
||
exports.use(assert);
|
||
|
||
},{"./chai/assertion":4,"./chai/config":5,"./chai/core/assertions":6,"./chai/interface/assert":7,"./chai/interface/expect":8,"./chai/interface/should":9,"./chai/utils":22,"assertion-error":31}],4:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* http://chaijs.com
|
||
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
var config = require('./config');
|
||
|
||
module.exports = function (_chai, util) {
|
||
/*!
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var AssertionError = _chai.AssertionError
|
||
, flag = util.flag;
|
||
|
||
/*!
|
||
* Module export.
|
||
*/
|
||
|
||
_chai.Assertion = Assertion;
|
||
|
||
/*!
|
||
* Assertion Constructor
|
||
*
|
||
* Creates object for chaining.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
function Assertion (obj, msg, stack) {
|
||
flag(this, 'ssfi', stack || arguments.callee);
|
||
flag(this, 'object', obj);
|
||
flag(this, 'message', msg);
|
||
}
|
||
|
||
Object.defineProperty(Assertion, 'includeStack', {
|
||
get: function() {
|
||
console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
|
||
return config.includeStack;
|
||
},
|
||
set: function(value) {
|
||
console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
|
||
config.includeStack = value;
|
||
}
|
||
});
|
||
|
||
Object.defineProperty(Assertion, 'showDiff', {
|
||
get: function() {
|
||
console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
|
||
return config.showDiff;
|
||
},
|
||
set: function(value) {
|
||
console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
|
||
config.showDiff = value;
|
||
}
|
||
});
|
||
|
||
Assertion.addProperty = function (name, fn) {
|
||
util.addProperty(this.prototype, name, fn);
|
||
};
|
||
|
||
Assertion.addMethod = function (name, fn) {
|
||
util.addMethod(this.prototype, name, fn);
|
||
};
|
||
|
||
Assertion.addChainableMethod = function (name, fn, chainingBehavior) {
|
||
util.addChainableMethod(this.prototype, name, fn, chainingBehavior);
|
||
};
|
||
|
||
Assertion.overwriteProperty = function (name, fn) {
|
||
util.overwriteProperty(this.prototype, name, fn);
|
||
};
|
||
|
||
Assertion.overwriteMethod = function (name, fn) {
|
||
util.overwriteMethod(this.prototype, name, fn);
|
||
};
|
||
|
||
Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) {
|
||
util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior);
|
||
};
|
||
|
||
/*!
|
||
* ### .assert(expression, message, negateMessage, expected, actual)
|
||
*
|
||
* Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass.
|
||
*
|
||
* @name assert
|
||
* @param {Philosophical} expression to be tested
|
||
* @param {String or Function} message or function that returns message to display if expression fails
|
||
* @param {String or Function} negatedMessage or function that returns negatedMessage to display if negated expression fails
|
||
* @param {Mixed} expected value (remember to check for negation)
|
||
* @param {Mixed} actual (optional) will default to `this.obj`
|
||
* @param {Boolean} showDiff (optional) when set to `true`, assert will display a diff in addition to the message if expression fails
|
||
* @api private
|
||
*/
|
||
|
||
Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) {
|
||
var ok = util.test(this, arguments);
|
||
if (true !== showDiff) showDiff = false;
|
||
if (true !== config.showDiff) showDiff = false;
|
||
|
||
if (!ok) {
|
||
var msg = util.getMessage(this, arguments)
|
||
, actual = util.getActual(this, arguments);
|
||
throw new AssertionError(msg, {
|
||
actual: actual
|
||
, expected: expected
|
||
, showDiff: showDiff
|
||
}, (config.includeStack) ? this.assert : flag(this, 'ssfi'));
|
||
}
|
||
};
|
||
|
||
/*!
|
||
* ### ._obj
|
||
*
|
||
* Quick reference to stored `actual` value for plugin developers.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Object.defineProperty(Assertion.prototype, '_obj',
|
||
{ get: function () {
|
||
return flag(this, 'object');
|
||
}
|
||
, set: function (val) {
|
||
flag(this, 'object', val);
|
||
}
|
||
});
|
||
};
|
||
|
||
},{"./config":5}],5:[function(require,module,exports){
|
||
module.exports = {
|
||
|
||
/**
|
||
* ### config.includeStack
|
||
*
|
||
* User configurable property, influences whether stack trace
|
||
* is included in Assertion error message. Default of false
|
||
* suppresses stack trace in the error message.
|
||
*
|
||
* chai.config.includeStack = true; // enable stack on error
|
||
*
|
||
* @param {Boolean}
|
||
* @api public
|
||
*/
|
||
|
||
includeStack: false,
|
||
|
||
/**
|
||
* ### config.showDiff
|
||
*
|
||
* User configurable property, influences whether or not
|
||
* the `showDiff` flag should be included in the thrown
|
||
* AssertionErrors. `false` will always be `false`; `true`
|
||
* will be true when the assertion has requested a diff
|
||
* be shown.
|
||
*
|
||
* @param {Boolean}
|
||
* @api public
|
||
*/
|
||
|
||
showDiff: true,
|
||
|
||
/**
|
||
* ### config.truncateThreshold
|
||
*
|
||
* User configurable property, sets length threshold for actual and
|
||
* expected values in assertion errors. If this threshold is exceeded, for
|
||
* example for large data structures, the value is replaced with something
|
||
* like `[ Array(3) ]` or `{ Object (prop1, prop2) }`.
|
||
*
|
||
* Set it to zero if you want to disable truncating altogether.
|
||
*
|
||
* This is especially userful when doing assertions on arrays: having this
|
||
* set to a reasonable large value makes the failure messages readily
|
||
* inspectable.
|
||
*
|
||
* chai.config.truncateThreshold = 0; // disable truncating
|
||
*
|
||
* @param {Number}
|
||
* @api public
|
||
*/
|
||
|
||
truncateThreshold: 40
|
||
|
||
};
|
||
|
||
},{}],6:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* http://chaijs.com
|
||
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
module.exports = function (chai, _) {
|
||
var Assertion = chai.Assertion
|
||
, toString = Object.prototype.toString
|
||
, flag = _.flag;
|
||
|
||
/**
|
||
* ### Language Chains
|
||
*
|
||
* The following are provided as chainable getters to
|
||
* improve the readability of your assertions. They
|
||
* do not provide testing capabilities unless they
|
||
* have been overwritten by a plugin.
|
||
*
|
||
* **Chains**
|
||
*
|
||
* - to
|
||
* - be
|
||
* - been
|
||
* - is
|
||
* - that
|
||
* - which
|
||
* - and
|
||
* - has
|
||
* - have
|
||
* - with
|
||
* - at
|
||
* - of
|
||
* - same
|
||
*
|
||
* @name language chains
|
||
* @api public
|
||
*/
|
||
|
||
[ 'to', 'be', 'been'
|
||
, 'is', 'and', 'has', 'have'
|
||
, 'with', 'that', 'which', 'at'
|
||
, 'of', 'same' ].forEach(function (chain) {
|
||
Assertion.addProperty(chain, function () {
|
||
return this;
|
||
});
|
||
});
|
||
|
||
/**
|
||
* ### .not
|
||
*
|
||
* Negates any of assertions following in the chain.
|
||
*
|
||
* expect(foo).to.not.equal('bar');
|
||
* expect(goodFn).to.not.throw(Error);
|
||
* expect({ foo: 'baz' }).to.have.property('foo')
|
||
* .and.not.equal('bar');
|
||
*
|
||
* @name not
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('not', function () {
|
||
flag(this, 'negate', true);
|
||
});
|
||
|
||
/**
|
||
* ### .deep
|
||
*
|
||
* Sets the `deep` flag, later used by the `equal` and
|
||
* `property` assertions.
|
||
*
|
||
* expect(foo).to.deep.equal({ bar: 'baz' });
|
||
* expect({ foo: { bar: { baz: 'quux' } } })
|
||
* .to.have.deep.property('foo.bar.baz', 'quux');
|
||
*
|
||
* `.deep.property` special characters can be escaped
|
||
* by adding two slashes before the `.` or `[]`.
|
||
*
|
||
* var deepCss = { '.link': { '[target]': 42 }};
|
||
* expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
|
||
*
|
||
* @name deep
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('deep', function () {
|
||
flag(this, 'deep', true);
|
||
});
|
||
|
||
/**
|
||
* ### .any
|
||
*
|
||
* Sets the `any` flag, (opposite of the `all` flag)
|
||
* later used in the `keys` assertion.
|
||
*
|
||
* expect(foo).to.have.any.keys('bar', 'baz');
|
||
*
|
||
* @name any
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('any', function () {
|
||
flag(this, 'any', true);
|
||
flag(this, 'all', false)
|
||
});
|
||
|
||
|
||
/**
|
||
* ### .all
|
||
*
|
||
* Sets the `all` flag (opposite of the `any` flag)
|
||
* later used by the `keys` assertion.
|
||
*
|
||
* expect(foo).to.have.all.keys('bar', 'baz');
|
||
*
|
||
* @name all
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('all', function () {
|
||
flag(this, 'all', true);
|
||
flag(this, 'any', false);
|
||
});
|
||
|
||
/**
|
||
* ### .a(type)
|
||
*
|
||
* The `a` and `an` assertions are aliases that can be
|
||
* used either as language chains or to assert a value's
|
||
* type.
|
||
*
|
||
* // typeof
|
||
* expect('test').to.be.a('string');
|
||
* expect({ foo: 'bar' }).to.be.an('object');
|
||
* expect(null).to.be.a('null');
|
||
* expect(undefined).to.be.an('undefined');
|
||
*
|
||
* // language chain
|
||
* expect(foo).to.be.an.instanceof(Foo);
|
||
*
|
||
* @name a
|
||
* @alias an
|
||
* @param {String} type
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function an (type, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
type = type.toLowerCase();
|
||
var obj = flag(this, 'object')
|
||
, article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
|
||
|
||
this.assert(
|
||
type === _.type(obj)
|
||
, 'expected #{this} to be ' + article + type
|
||
, 'expected #{this} not to be ' + article + type
|
||
);
|
||
}
|
||
|
||
Assertion.addChainableMethod('an', an);
|
||
Assertion.addChainableMethod('a', an);
|
||
|
||
/**
|
||
* ### .include(value)
|
||
*
|
||
* The `include` and `contain` assertions can be used as either property
|
||
* based language chains or as methods to assert the inclusion of an object
|
||
* in an array or a substring in a string. When used as language chains,
|
||
* they toggle the `contains` flag for the `keys` assertion.
|
||
*
|
||
* expect([1,2,3]).to.include(2);
|
||
* expect('foobar').to.contain('foo');
|
||
* expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
|
||
*
|
||
* @name include
|
||
* @alias contain
|
||
* @alias includes
|
||
* @alias contains
|
||
* @param {Object|String|Number} obj
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function includeChainingBehavior () {
|
||
flag(this, 'contains', true);
|
||
}
|
||
|
||
function include (val, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
var expected = false;
|
||
if (_.type(obj) === 'array' && _.type(val) === 'object') {
|
||
for (var i in obj) {
|
||
if (_.eql(obj[i], val)) {
|
||
expected = true;
|
||
break;
|
||
}
|
||
}
|
||
} else if (_.type(val) === 'object') {
|
||
if (!flag(this, 'negate')) {
|
||
for (var k in val) new Assertion(obj).property(k, val[k]);
|
||
return;
|
||
}
|
||
var subset = {};
|
||
for (var k in val) subset[k] = obj[k];
|
||
expected = _.eql(subset, val);
|
||
} else {
|
||
expected = obj && ~obj.indexOf(val);
|
||
}
|
||
this.assert(
|
||
expected
|
||
, 'expected #{this} to include ' + _.inspect(val)
|
||
, 'expected #{this} to not include ' + _.inspect(val));
|
||
}
|
||
|
||
Assertion.addChainableMethod('include', include, includeChainingBehavior);
|
||
Assertion.addChainableMethod('contain', include, includeChainingBehavior);
|
||
Assertion.addChainableMethod('contains', include, includeChainingBehavior);
|
||
Assertion.addChainableMethod('includes', include, includeChainingBehavior);
|
||
|
||
/**
|
||
* ### .ok
|
||
*
|
||
* Asserts that the target is truthy.
|
||
*
|
||
* expect('everthing').to.be.ok;
|
||
* expect(1).to.be.ok;
|
||
* expect(false).to.not.be.ok;
|
||
* expect(undefined).to.not.be.ok;
|
||
* expect(null).to.not.be.ok;
|
||
*
|
||
* @name ok
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('ok', function () {
|
||
this.assert(
|
||
flag(this, 'object')
|
||
, 'expected #{this} to be truthy'
|
||
, 'expected #{this} to be falsy');
|
||
});
|
||
|
||
/**
|
||
* ### .true
|
||
*
|
||
* Asserts that the target is `true`.
|
||
*
|
||
* expect(true).to.be.true;
|
||
* expect(1).to.not.be.true;
|
||
*
|
||
* @name true
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('true', function () {
|
||
this.assert(
|
||
true === flag(this, 'object')
|
||
, 'expected #{this} to be true'
|
||
, 'expected #{this} to be false'
|
||
, this.negate ? false : true
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .false
|
||
*
|
||
* Asserts that the target is `false`.
|
||
*
|
||
* expect(false).to.be.false;
|
||
* expect(0).to.not.be.false;
|
||
*
|
||
* @name false
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('false', function () {
|
||
this.assert(
|
||
false === flag(this, 'object')
|
||
, 'expected #{this} to be false'
|
||
, 'expected #{this} to be true'
|
||
, this.negate ? true : false
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .null
|
||
*
|
||
* Asserts that the target is `null`.
|
||
*
|
||
* expect(null).to.be.null;
|
||
* expect(undefined).not.to.be.null;
|
||
*
|
||
* @name null
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('null', function () {
|
||
this.assert(
|
||
null === flag(this, 'object')
|
||
, 'expected #{this} to be null'
|
||
, 'expected #{this} not to be null'
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .undefined
|
||
*
|
||
* Asserts that the target is `undefined`.
|
||
*
|
||
* expect(undefined).to.be.undefined;
|
||
* expect(null).to.not.be.undefined;
|
||
*
|
||
* @name undefined
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('undefined', function () {
|
||
this.assert(
|
||
undefined === flag(this, 'object')
|
||
, 'expected #{this} to be undefined'
|
||
, 'expected #{this} not to be undefined'
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .exist
|
||
*
|
||
* Asserts that the target is neither `null` nor `undefined`.
|
||
*
|
||
* var foo = 'hi'
|
||
* , bar = null
|
||
* , baz;
|
||
*
|
||
* expect(foo).to.exist;
|
||
* expect(bar).to.not.exist;
|
||
* expect(baz).to.not.exist;
|
||
*
|
||
* @name exist
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('exist', function () {
|
||
this.assert(
|
||
null != flag(this, 'object')
|
||
, 'expected #{this} to exist'
|
||
, 'expected #{this} to not exist'
|
||
);
|
||
});
|
||
|
||
|
||
/**
|
||
* ### .empty
|
||
*
|
||
* Asserts that the target's length is `0`. For arrays and strings, it checks
|
||
* the `length` property. For objects, it gets the count of
|
||
* enumerable keys.
|
||
*
|
||
* expect([]).to.be.empty;
|
||
* expect('').to.be.empty;
|
||
* expect({}).to.be.empty;
|
||
*
|
||
* @name empty
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('empty', function () {
|
||
var obj = flag(this, 'object')
|
||
, expected = obj;
|
||
|
||
if (Array.isArray(obj) || 'string' === typeof object) {
|
||
expected = obj.length;
|
||
} else if (typeof obj === 'object') {
|
||
expected = Object.keys(obj).length;
|
||
}
|
||
|
||
this.assert(
|
||
!expected
|
||
, 'expected #{this} to be empty'
|
||
, 'expected #{this} not to be empty'
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .arguments
|
||
*
|
||
* Asserts that the target is an arguments object.
|
||
*
|
||
* function test () {
|
||
* expect(arguments).to.be.arguments;
|
||
* }
|
||
*
|
||
* @name arguments
|
||
* @alias Arguments
|
||
* @api public
|
||
*/
|
||
|
||
function checkArguments () {
|
||
var obj = flag(this, 'object')
|
||
, type = Object.prototype.toString.call(obj);
|
||
this.assert(
|
||
'[object Arguments]' === type
|
||
, 'expected #{this} to be arguments but got ' + type
|
||
, 'expected #{this} to not be arguments'
|
||
);
|
||
}
|
||
|
||
Assertion.addProperty('arguments', checkArguments);
|
||
Assertion.addProperty('Arguments', checkArguments);
|
||
|
||
/**
|
||
* ### .equal(value)
|
||
*
|
||
* Asserts that the target is strictly equal (`===`) to `value`.
|
||
* Alternately, if the `deep` flag is set, asserts that
|
||
* the target is deeply equal to `value`.
|
||
*
|
||
* expect('hello').to.equal('hello');
|
||
* expect(42).to.equal(42);
|
||
* expect(1).to.not.equal(true);
|
||
* expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
|
||
* expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
|
||
*
|
||
* @name equal
|
||
* @alias equals
|
||
* @alias eq
|
||
* @alias deep.equal
|
||
* @param {Mixed} value
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertEqual (val, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
if (flag(this, 'deep')) {
|
||
return this.eql(val);
|
||
} else {
|
||
this.assert(
|
||
val === obj
|
||
, 'expected #{this} to equal #{exp}'
|
||
, 'expected #{this} to not equal #{exp}'
|
||
, val
|
||
, this._obj
|
||
, true
|
||
);
|
||
}
|
||
}
|
||
|
||
Assertion.addMethod('equal', assertEqual);
|
||
Assertion.addMethod('equals', assertEqual);
|
||
Assertion.addMethod('eq', assertEqual);
|
||
|
||
/**
|
||
* ### .eql(value)
|
||
*
|
||
* Asserts that the target is deeply equal to `value`.
|
||
*
|
||
* expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
|
||
* expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);
|
||
*
|
||
* @name eql
|
||
* @alias eqls
|
||
* @param {Mixed} value
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertEql(obj, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
this.assert(
|
||
_.eql(obj, flag(this, 'object'))
|
||
, 'expected #{this} to deeply equal #{exp}'
|
||
, 'expected #{this} to not deeply equal #{exp}'
|
||
, obj
|
||
, this._obj
|
||
, true
|
||
);
|
||
}
|
||
|
||
Assertion.addMethod('eql', assertEql);
|
||
Assertion.addMethod('eqls', assertEql);
|
||
|
||
/**
|
||
* ### .above(value)
|
||
*
|
||
* Asserts that the target is greater than `value`.
|
||
*
|
||
* expect(10).to.be.above(5);
|
||
*
|
||
* Can also be used in conjunction with `length` to
|
||
* assert a minimum length. The benefit being a
|
||
* more informative error message than if the length
|
||
* was supplied directly.
|
||
*
|
||
* expect('foo').to.have.length.above(2);
|
||
* expect([ 1, 2, 3 ]).to.have.length.above(2);
|
||
*
|
||
* @name above
|
||
* @alias gt
|
||
* @alias greaterThan
|
||
* @param {Number} value
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertAbove (n, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
if (flag(this, 'doLength')) {
|
||
new Assertion(obj, msg).to.have.property('length');
|
||
var len = obj.length;
|
||
this.assert(
|
||
len > n
|
||
, 'expected #{this} to have a length above #{exp} but got #{act}'
|
||
, 'expected #{this} to not have a length above #{exp}'
|
||
, n
|
||
, len
|
||
);
|
||
} else {
|
||
this.assert(
|
||
obj > n
|
||
, 'expected #{this} to be above ' + n
|
||
, 'expected #{this} to be at most ' + n
|
||
);
|
||
}
|
||
}
|
||
|
||
Assertion.addMethod('above', assertAbove);
|
||
Assertion.addMethod('gt', assertAbove);
|
||
Assertion.addMethod('greaterThan', assertAbove);
|
||
|
||
/**
|
||
* ### .least(value)
|
||
*
|
||
* Asserts that the target is greater than or equal to `value`.
|
||
*
|
||
* expect(10).to.be.at.least(10);
|
||
*
|
||
* Can also be used in conjunction with `length` to
|
||
* assert a minimum length. The benefit being a
|
||
* more informative error message than if the length
|
||
* was supplied directly.
|
||
*
|
||
* expect('foo').to.have.length.of.at.least(2);
|
||
* expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);
|
||
*
|
||
* @name least
|
||
* @alias gte
|
||
* @param {Number} value
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertLeast (n, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
if (flag(this, 'doLength')) {
|
||
new Assertion(obj, msg).to.have.property('length');
|
||
var len = obj.length;
|
||
this.assert(
|
||
len >= n
|
||
, 'expected #{this} to have a length at least #{exp} but got #{act}'
|
||
, 'expected #{this} to have a length below #{exp}'
|
||
, n
|
||
, len
|
||
);
|
||
} else {
|
||
this.assert(
|
||
obj >= n
|
||
, 'expected #{this} to be at least ' + n
|
||
, 'expected #{this} to be below ' + n
|
||
);
|
||
}
|
||
}
|
||
|
||
Assertion.addMethod('least', assertLeast);
|
||
Assertion.addMethod('gte', assertLeast);
|
||
|
||
/**
|
||
* ### .below(value)
|
||
*
|
||
* Asserts that the target is less than `value`.
|
||
*
|
||
* expect(5).to.be.below(10);
|
||
*
|
||
* Can also be used in conjunction with `length` to
|
||
* assert a maximum length. The benefit being a
|
||
* more informative error message than if the length
|
||
* was supplied directly.
|
||
*
|
||
* expect('foo').to.have.length.below(4);
|
||
* expect([ 1, 2, 3 ]).to.have.length.below(4);
|
||
*
|
||
* @name below
|
||
* @alias lt
|
||
* @alias lessThan
|
||
* @param {Number} value
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertBelow (n, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
if (flag(this, 'doLength')) {
|
||
new Assertion(obj, msg).to.have.property('length');
|
||
var len = obj.length;
|
||
this.assert(
|
||
len < n
|
||
, 'expected #{this} to have a length below #{exp} but got #{act}'
|
||
, 'expected #{this} to not have a length below #{exp}'
|
||
, n
|
||
, len
|
||
);
|
||
} else {
|
||
this.assert(
|
||
obj < n
|
||
, 'expected #{this} to be below ' + n
|
||
, 'expected #{this} to be at least ' + n
|
||
);
|
||
}
|
||
}
|
||
|
||
Assertion.addMethod('below', assertBelow);
|
||
Assertion.addMethod('lt', assertBelow);
|
||
Assertion.addMethod('lessThan', assertBelow);
|
||
|
||
/**
|
||
* ### .most(value)
|
||
*
|
||
* Asserts that the target is less than or equal to `value`.
|
||
*
|
||
* expect(5).to.be.at.most(5);
|
||
*
|
||
* Can also be used in conjunction with `length` to
|
||
* assert a maximum length. The benefit being a
|
||
* more informative error message than if the length
|
||
* was supplied directly.
|
||
*
|
||
* expect('foo').to.have.length.of.at.most(4);
|
||
* expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
|
||
*
|
||
* @name most
|
||
* @alias lte
|
||
* @param {Number} value
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertMost (n, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
if (flag(this, 'doLength')) {
|
||
new Assertion(obj, msg).to.have.property('length');
|
||
var len = obj.length;
|
||
this.assert(
|
||
len <= n
|
||
, 'expected #{this} to have a length at most #{exp} but got #{act}'
|
||
, 'expected #{this} to have a length above #{exp}'
|
||
, n
|
||
, len
|
||
);
|
||
} else {
|
||
this.assert(
|
||
obj <= n
|
||
, 'expected #{this} to be at most ' + n
|
||
, 'expected #{this} to be above ' + n
|
||
);
|
||
}
|
||
}
|
||
|
||
Assertion.addMethod('most', assertMost);
|
||
Assertion.addMethod('lte', assertMost);
|
||
|
||
/**
|
||
* ### .within(start, finish)
|
||
*
|
||
* Asserts that the target is within a range.
|
||
*
|
||
* expect(7).to.be.within(5,10);
|
||
*
|
||
* Can also be used in conjunction with `length` to
|
||
* assert a length range. The benefit being a
|
||
* more informative error message than if the length
|
||
* was supplied directly.
|
||
*
|
||
* expect('foo').to.have.length.within(2,4);
|
||
* expect([ 1, 2, 3 ]).to.have.length.within(2,4);
|
||
*
|
||
* @name within
|
||
* @param {Number} start lowerbound inclusive
|
||
* @param {Number} finish upperbound inclusive
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('within', function (start, finish, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object')
|
||
, range = start + '..' + finish;
|
||
if (flag(this, 'doLength')) {
|
||
new Assertion(obj, msg).to.have.property('length');
|
||
var len = obj.length;
|
||
this.assert(
|
||
len >= start && len <= finish
|
||
, 'expected #{this} to have a length within ' + range
|
||
, 'expected #{this} to not have a length within ' + range
|
||
);
|
||
} else {
|
||
this.assert(
|
||
obj >= start && obj <= finish
|
||
, 'expected #{this} to be within ' + range
|
||
, 'expected #{this} to not be within ' + range
|
||
);
|
||
}
|
||
});
|
||
|
||
/**
|
||
* ### .instanceof(constructor)
|
||
*
|
||
* Asserts that the target is an instance of `constructor`.
|
||
*
|
||
* var Tea = function (name) { this.name = name; }
|
||
* , Chai = new Tea('chai');
|
||
*
|
||
* expect(Chai).to.be.an.instanceof(Tea);
|
||
* expect([ 1, 2, 3 ]).to.be.instanceof(Array);
|
||
*
|
||
* @name instanceof
|
||
* @param {Constructor} constructor
|
||
* @param {String} message _optional_
|
||
* @alias instanceOf
|
||
* @api public
|
||
*/
|
||
|
||
function assertInstanceOf (constructor, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var name = _.getName(constructor);
|
||
this.assert(
|
||
flag(this, 'object') instanceof constructor
|
||
, 'expected #{this} to be an instance of ' + name
|
||
, 'expected #{this} to not be an instance of ' + name
|
||
);
|
||
};
|
||
|
||
Assertion.addMethod('instanceof', assertInstanceOf);
|
||
Assertion.addMethod('instanceOf', assertInstanceOf);
|
||
|
||
/**
|
||
* ### .property(name, [value])
|
||
*
|
||
* Asserts that the target has a property `name`, optionally asserting that
|
||
* the value of that property is strictly equal to `value`.
|
||
* If the `deep` flag is set, you can use dot- and bracket-notation for deep
|
||
* references into objects and arrays.
|
||
*
|
||
* // simple referencing
|
||
* var obj = { foo: 'bar' };
|
||
* expect(obj).to.have.property('foo');
|
||
* expect(obj).to.have.property('foo', 'bar');
|
||
*
|
||
* // deep referencing
|
||
* var deepObj = {
|
||
* green: { tea: 'matcha' }
|
||
* , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
|
||
* };
|
||
*
|
||
* expect(deepObj).to.have.deep.property('green.tea', 'matcha');
|
||
* expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
|
||
* expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');
|
||
*
|
||
* You can also use an array as the starting point of a `deep.property`
|
||
* assertion, or traverse nested arrays.
|
||
*
|
||
* var arr = [
|
||
* [ 'chai', 'matcha', 'konacha' ]
|
||
* , [ { tea: 'chai' }
|
||
* , { tea: 'matcha' }
|
||
* , { tea: 'konacha' } ]
|
||
* ];
|
||
*
|
||
* expect(arr).to.have.deep.property('[0][1]', 'matcha');
|
||
* expect(arr).to.have.deep.property('[1][2].tea', 'konacha');
|
||
*
|
||
* Furthermore, `property` changes the subject of the assertion
|
||
* to be the value of that property from the original object. This
|
||
* permits for further chainable assertions on that property.
|
||
*
|
||
* expect(obj).to.have.property('foo')
|
||
* .that.is.a('string');
|
||
* expect(deepObj).to.have.property('green')
|
||
* .that.is.an('object')
|
||
* .that.deep.equals({ tea: 'matcha' });
|
||
* expect(deepObj).to.have.property('teas')
|
||
* .that.is.an('array')
|
||
* .with.deep.property('[2]')
|
||
* .that.deep.equals({ tea: 'konacha' });
|
||
*
|
||
* Note that dots and bracket in `name` must be backslash-escaped when
|
||
* the `deep` flag is set, while they must NOT be escaped when the `deep`
|
||
* flag is not set.
|
||
*
|
||
* // simple referencing
|
||
* var css = { '.link[target]': 42 };
|
||
* expect(css).to.have.property('.link[target]', 42);
|
||
*
|
||
* // deep referencing
|
||
* var deepCss = { '.link': { '[target]': 42 }};
|
||
* expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
|
||
*
|
||
* @name property
|
||
* @alias deep.property
|
||
* @param {String} name
|
||
* @param {Mixed} value (optional)
|
||
* @param {String} message _optional_
|
||
* @returns value of property for chaining
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('property', function (name, val, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
|
||
var isDeep = !!flag(this, 'deep')
|
||
, descriptor = isDeep ? 'deep property ' : 'property '
|
||
, negate = flag(this, 'negate')
|
||
, obj = flag(this, 'object')
|
||
, pathInfo = isDeep ? _.getPathInfo(name, obj) : null
|
||
, hasProperty = isDeep
|
||
? pathInfo.exists
|
||
: _.hasProperty(name, obj)
|
||
, value = isDeep
|
||
? pathInfo.value
|
||
: obj[name];
|
||
|
||
if (negate && undefined !== val) {
|
||
if (undefined === value) {
|
||
msg = (msg != null) ? msg + ': ' : '';
|
||
throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));
|
||
}
|
||
} else {
|
||
this.assert(
|
||
hasProperty
|
||
, 'expected #{this} to have a ' + descriptor + _.inspect(name)
|
||
, 'expected #{this} to not have ' + descriptor + _.inspect(name));
|
||
}
|
||
|
||
if (undefined !== val) {
|
||
this.assert(
|
||
val === value
|
||
, 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
|
||
, 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'
|
||
, val
|
||
, value
|
||
);
|
||
}
|
||
|
||
flag(this, 'object', value);
|
||
});
|
||
|
||
|
||
/**
|
||
* ### .ownProperty(name)
|
||
*
|
||
* Asserts that the target has an own property `name`.
|
||
*
|
||
* expect('test').to.have.ownProperty('length');
|
||
*
|
||
* @name ownProperty
|
||
* @alias haveOwnProperty
|
||
* @param {String} name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertOwnProperty (name, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
this.assert(
|
||
obj.hasOwnProperty(name)
|
||
, 'expected #{this} to have own property ' + _.inspect(name)
|
||
, 'expected #{this} to not have own property ' + _.inspect(name)
|
||
);
|
||
}
|
||
|
||
Assertion.addMethod('ownProperty', assertOwnProperty);
|
||
Assertion.addMethod('haveOwnProperty', assertOwnProperty);
|
||
|
||
/**
|
||
* ### .length(value)
|
||
*
|
||
* Asserts that the target's `length` property has
|
||
* the expected value.
|
||
*
|
||
* expect([ 1, 2, 3]).to.have.length(3);
|
||
* expect('foobar').to.have.length(6);
|
||
*
|
||
* Can also be used as a chain precursor to a value
|
||
* comparison for the length property.
|
||
*
|
||
* expect('foo').to.have.length.above(2);
|
||
* expect([ 1, 2, 3 ]).to.have.length.above(2);
|
||
* expect('foo').to.have.length.below(4);
|
||
* expect([ 1, 2, 3 ]).to.have.length.below(4);
|
||
* expect('foo').to.have.length.within(2,4);
|
||
* expect([ 1, 2, 3 ]).to.have.length.within(2,4);
|
||
*
|
||
* @name length
|
||
* @alias lengthOf
|
||
* @param {Number} length
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertLengthChain () {
|
||
flag(this, 'doLength', true);
|
||
}
|
||
|
||
function assertLength (n, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
new Assertion(obj, msg).to.have.property('length');
|
||
var len = obj.length;
|
||
|
||
this.assert(
|
||
len == n
|
||
, 'expected #{this} to have a length of #{exp} but got #{act}'
|
||
, 'expected #{this} to not have a length of #{act}'
|
||
, n
|
||
, len
|
||
);
|
||
}
|
||
|
||
Assertion.addChainableMethod('length', assertLength, assertLengthChain);
|
||
Assertion.addMethod('lengthOf', assertLength);
|
||
|
||
/**
|
||
* ### .match(regexp)
|
||
*
|
||
* Asserts that the target matches a regular expression.
|
||
*
|
||
* expect('foobar').to.match(/^foo/);
|
||
*
|
||
* @name match
|
||
* @param {RegExp} RegularExpression
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('match', function (re, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
this.assert(
|
||
re.exec(obj)
|
||
, 'expected #{this} to match ' + re
|
||
, 'expected #{this} not to match ' + re
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .string(string)
|
||
*
|
||
* Asserts that the string target contains another string.
|
||
*
|
||
* expect('foobar').to.have.string('bar');
|
||
*
|
||
* @name string
|
||
* @param {String} string
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('string', function (str, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
new Assertion(obj, msg).is.a('string');
|
||
|
||
this.assert(
|
||
~obj.indexOf(str)
|
||
, 'expected #{this} to contain ' + _.inspect(str)
|
||
, 'expected #{this} to not contain ' + _.inspect(str)
|
||
);
|
||
});
|
||
|
||
|
||
/**
|
||
* ### .keys(key1, [key2], [...])
|
||
*
|
||
* Asserts that the target contains any or all of the passed-in keys.
|
||
* Use in combination with `any`, `all`, `contains`, or `have` will affect
|
||
* what will pass.
|
||
*
|
||
* When used in conjunction with `any`, at least one key that is passed
|
||
* in must exist in the target object. This is regardless whether or not
|
||
* the `have` or `contain` qualifiers are used. Note, either `any` or `all`
|
||
* should be used in the assertion. If neither are used, the assertion is
|
||
* defaulted to `all`.
|
||
*
|
||
* When both `all` and `contain` are used, the target object must have at
|
||
* least all of the passed-in keys but may have more keys not listed.
|
||
*
|
||
* When both `all` and `have` are used, the target object must both contain
|
||
* all of the passed-in keys AND the number of keys in the target object must
|
||
* match the number of keys passed in (in other words, a target object must
|
||
* have all and only all of the passed-in keys).
|
||
*
|
||
* expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz');
|
||
* expect({ foo: 1, bar: 2 }).to.have.any.keys('foo');
|
||
* expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz');
|
||
* expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']);
|
||
* expect({ foo: 1, bar: 2 }).to.contain.any.keys({'foo': 6});
|
||
* expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']);
|
||
* expect({ foo: 1, bar: 2 }).to.have.all.keys({'bar': 6, 'foo', 7});
|
||
* expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']);
|
||
* expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys([{'bar': 6}}]);
|
||
*
|
||
*
|
||
* @name keys
|
||
* @alias key
|
||
* @param {String...|Array|Object} keys
|
||
* @api public
|
||
*/
|
||
|
||
function assertKeys (keys) {
|
||
var obj = flag(this, 'object')
|
||
, str
|
||
, ok = true
|
||
, mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments';
|
||
|
||
switch (_.type(keys)) {
|
||
case "array":
|
||
if (arguments.length > 1) throw (new Error(mixedArgsMsg));
|
||
break;
|
||
case "object":
|
||
if (arguments.length > 1) throw (new Error(mixedArgsMsg));
|
||
keys = Object.keys(keys);
|
||
break;
|
||
default:
|
||
keys = Array.prototype.slice.call(arguments);
|
||
}
|
||
|
||
if (!keys.length) throw new Error('keys required');
|
||
|
||
var actual = Object.keys(obj)
|
||
, expected = keys
|
||
, len = keys.length
|
||
, any = flag(this, 'any')
|
||
, all = flag(this, 'all');
|
||
|
||
if (!any && !all) {
|
||
all = true;
|
||
}
|
||
|
||
// Has any
|
||
if (any) {
|
||
var intersection = expected.filter(function(key) {
|
||
return ~actual.indexOf(key);
|
||
});
|
||
ok = intersection.length > 0;
|
||
}
|
||
|
||
// Has all
|
||
if (all) {
|
||
ok = keys.every(function(key){
|
||
return ~actual.indexOf(key);
|
||
});
|
||
if (!flag(this, 'negate') && !flag(this, 'contains')) {
|
||
ok = ok && keys.length == actual.length;
|
||
}
|
||
}
|
||
|
||
// Key string
|
||
if (len > 1) {
|
||
keys = keys.map(function(key){
|
||
return _.inspect(key);
|
||
});
|
||
var last = keys.pop();
|
||
if (all) {
|
||
str = keys.join(', ') + ', and ' + last;
|
||
}
|
||
if (any) {
|
||
str = keys.join(', ') + ', or ' + last;
|
||
}
|
||
} else {
|
||
str = _.inspect(keys[0]);
|
||
}
|
||
|
||
// Form
|
||
str = (len > 1 ? 'keys ' : 'key ') + str;
|
||
|
||
// Have / include
|
||
str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;
|
||
|
||
// Assertion
|
||
this.assert(
|
||
ok
|
||
, 'expected #{this} to ' + str
|
||
, 'expected #{this} to not ' + str
|
||
, expected.slice(0).sort()
|
||
, actual.sort()
|
||
, true
|
||
);
|
||
}
|
||
|
||
Assertion.addMethod('keys', assertKeys);
|
||
Assertion.addMethod('key', assertKeys);
|
||
|
||
/**
|
||
* ### .throw(constructor)
|
||
*
|
||
* Asserts that the function target will throw a specific error, or specific type of error
|
||
* (as determined using `instanceof`), optionally with a RegExp or string inclusion test
|
||
* for the error's message.
|
||
*
|
||
* var err = new ReferenceError('This is a bad function.');
|
||
* var fn = function () { throw err; }
|
||
* expect(fn).to.throw(ReferenceError);
|
||
* expect(fn).to.throw(Error);
|
||
* expect(fn).to.throw(/bad function/);
|
||
* expect(fn).to.not.throw('good function');
|
||
* expect(fn).to.throw(ReferenceError, /bad function/);
|
||
* expect(fn).to.throw(err);
|
||
* expect(fn).to.not.throw(new RangeError('Out of range.'));
|
||
*
|
||
* Please note that when a throw expectation is negated, it will check each
|
||
* parameter independently, starting with error constructor type. The appropriate way
|
||
* to check for the existence of a type of error but for a message that does not match
|
||
* is to use `and`.
|
||
*
|
||
* expect(fn).to.throw(ReferenceError)
|
||
* .and.not.throw(/good function/);
|
||
*
|
||
* @name throw
|
||
* @alias throws
|
||
* @alias Throw
|
||
* @param {ErrorConstructor} constructor
|
||
* @param {String|RegExp} expected error message
|
||
* @param {String} message _optional_
|
||
* @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
|
||
* @returns error for chaining (null if no error)
|
||
* @api public
|
||
*/
|
||
|
||
function assertThrows (constructor, errMsg, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
new Assertion(obj, msg).is.a('function');
|
||
|
||
var thrown = false
|
||
, desiredError = null
|
||
, name = null
|
||
, thrownError = null;
|
||
|
||
if (arguments.length === 0) {
|
||
errMsg = null;
|
||
constructor = null;
|
||
} else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
|
||
errMsg = constructor;
|
||
constructor = null;
|
||
} else if (constructor && constructor instanceof Error) {
|
||
desiredError = constructor;
|
||
constructor = null;
|
||
errMsg = null;
|
||
} else if (typeof constructor === 'function') {
|
||
name = constructor.prototype.name || constructor.name;
|
||
if (name === 'Error' && constructor !== Error) {
|
||
name = (new constructor()).name;
|
||
}
|
||
} else {
|
||
constructor = null;
|
||
}
|
||
|
||
try {
|
||
obj();
|
||
} catch (err) {
|
||
// first, check desired error
|
||
if (desiredError) {
|
||
this.assert(
|
||
err === desiredError
|
||
, 'expected #{this} to throw #{exp} but #{act} was thrown'
|
||
, 'expected #{this} to not throw #{exp}'
|
||
, (desiredError instanceof Error ? desiredError.toString() : desiredError)
|
||
, (err instanceof Error ? err.toString() : err)
|
||
);
|
||
|
||
flag(this, 'object', err);
|
||
return this;
|
||
}
|
||
|
||
// next, check constructor
|
||
if (constructor) {
|
||
this.assert(
|
||
err instanceof constructor
|
||
, 'expected #{this} to throw #{exp} but #{act} was thrown'
|
||
, 'expected #{this} to not throw #{exp} but #{act} was thrown'
|
||
, name
|
||
, (err instanceof Error ? err.toString() : err)
|
||
);
|
||
|
||
if (!errMsg) {
|
||
flag(this, 'object', err);
|
||
return this;
|
||
}
|
||
}
|
||
|
||
// next, check message
|
||
var message = 'object' === _.type(err) && "message" in err
|
||
? err.message
|
||
: '' + err;
|
||
|
||
if ((message != null) && errMsg && errMsg instanceof RegExp) {
|
||
this.assert(
|
||
errMsg.exec(message)
|
||
, 'expected #{this} to throw error matching #{exp} but got #{act}'
|
||
, 'expected #{this} to throw error not matching #{exp}'
|
||
, errMsg
|
||
, message
|
||
);
|
||
|
||
flag(this, 'object', err);
|
||
return this;
|
||
} else if ((message != null) && errMsg && 'string' === typeof errMsg) {
|
||
this.assert(
|
||
~message.indexOf(errMsg)
|
||
, 'expected #{this} to throw error including #{exp} but got #{act}'
|
||
, 'expected #{this} to throw error not including #{act}'
|
||
, errMsg
|
||
, message
|
||
);
|
||
|
||
flag(this, 'object', err);
|
||
return this;
|
||
} else {
|
||
thrown = true;
|
||
thrownError = err;
|
||
}
|
||
}
|
||
|
||
var actuallyGot = ''
|
||
, expectedThrown = name !== null
|
||
? name
|
||
: desiredError
|
||
? '#{exp}' //_.inspect(desiredError)
|
||
: 'an error';
|
||
|
||
if (thrown) {
|
||
actuallyGot = ' but #{act} was thrown'
|
||
}
|
||
|
||
this.assert(
|
||
thrown === true
|
||
, 'expected #{this} to throw ' + expectedThrown + actuallyGot
|
||
, 'expected #{this} to not throw ' + expectedThrown + actuallyGot
|
||
, (desiredError instanceof Error ? desiredError.toString() : desiredError)
|
||
, (thrownError instanceof Error ? thrownError.toString() : thrownError)
|
||
);
|
||
|
||
flag(this, 'object', thrownError);
|
||
};
|
||
|
||
Assertion.addMethod('throw', assertThrows);
|
||
Assertion.addMethod('throws', assertThrows);
|
||
Assertion.addMethod('Throw', assertThrows);
|
||
|
||
/**
|
||
* ### .respondTo(method)
|
||
*
|
||
* Asserts that the object or class target will respond to a method.
|
||
*
|
||
* Klass.prototype.bar = function(){};
|
||
* expect(Klass).to.respondTo('bar');
|
||
* expect(obj).to.respondTo('bar');
|
||
*
|
||
* To check if a constructor will respond to a static function,
|
||
* set the `itself` flag.
|
||
*
|
||
* Klass.baz = function(){};
|
||
* expect(Klass).itself.to.respondTo('baz');
|
||
*
|
||
* @name respondTo
|
||
* @param {String} method
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('respondTo', function (method, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object')
|
||
, itself = flag(this, 'itself')
|
||
, context = ('function' === _.type(obj) && !itself)
|
||
? obj.prototype[method]
|
||
: obj[method];
|
||
|
||
this.assert(
|
||
'function' === typeof context
|
||
, 'expected #{this} to respond to ' + _.inspect(method)
|
||
, 'expected #{this} to not respond to ' + _.inspect(method)
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .itself
|
||
*
|
||
* Sets the `itself` flag, later used by the `respondTo` assertion.
|
||
*
|
||
* function Foo() {}
|
||
* Foo.bar = function() {}
|
||
* Foo.prototype.baz = function() {}
|
||
*
|
||
* expect(Foo).itself.to.respondTo('bar');
|
||
* expect(Foo).itself.not.to.respondTo('baz');
|
||
*
|
||
* @name itself
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('itself', function () {
|
||
flag(this, 'itself', true);
|
||
});
|
||
|
||
/**
|
||
* ### .satisfy(method)
|
||
*
|
||
* Asserts that the target passes a given truth test.
|
||
*
|
||
* expect(1).to.satisfy(function(num) { return num > 0; });
|
||
*
|
||
* @name satisfy
|
||
* @param {Function} matcher
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('satisfy', function (matcher, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
var result = matcher(obj);
|
||
this.assert(
|
||
result
|
||
, 'expected #{this} to satisfy ' + _.objDisplay(matcher)
|
||
, 'expected #{this} to not satisfy' + _.objDisplay(matcher)
|
||
, this.negate ? false : true
|
||
, result
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .closeTo(expected, delta)
|
||
*
|
||
* Asserts that the target is equal `expected`, to within a +/- `delta` range.
|
||
*
|
||
* expect(1.5).to.be.closeTo(1, 0.5);
|
||
*
|
||
* @name closeTo
|
||
* @param {Number} expected
|
||
* @param {Number} delta
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('closeTo', function (expected, delta, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
|
||
new Assertion(obj, msg).is.a('number');
|
||
if (_.type(expected) !== 'number' || _.type(delta) !== 'number') {
|
||
throw new Error('the arguments to closeTo must be numbers');
|
||
}
|
||
|
||
this.assert(
|
||
Math.abs(obj - expected) <= delta
|
||
, 'expected #{this} to be close to ' + expected + ' +/- ' + delta
|
||
, 'expected #{this} not to be close to ' + expected + ' +/- ' + delta
|
||
);
|
||
});
|
||
|
||
function isSubsetOf(subset, superset, cmp) {
|
||
return subset.every(function(elem) {
|
||
if (!cmp) return superset.indexOf(elem) !== -1;
|
||
|
||
return superset.some(function(elem2) {
|
||
return cmp(elem, elem2);
|
||
});
|
||
})
|
||
}
|
||
|
||
/**
|
||
* ### .members(set)
|
||
*
|
||
* Asserts that the target is a superset of `set`,
|
||
* or that the target and `set` have the same strictly-equal (===) members.
|
||
* Alternately, if the `deep` flag is set, set members are compared for deep
|
||
* equality.
|
||
*
|
||
* expect([1, 2, 3]).to.include.members([3, 2]);
|
||
* expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
|
||
*
|
||
* expect([4, 2]).to.have.members([2, 4]);
|
||
* expect([5, 2]).to.not.have.members([5, 2, 1]);
|
||
*
|
||
* expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]);
|
||
*
|
||
* @name members
|
||
* @param {Array} set
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('members', function (subset, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
|
||
new Assertion(obj).to.be.an('array');
|
||
new Assertion(subset).to.be.an('array');
|
||
|
||
var cmp = flag(this, 'deep') ? _.eql : undefined;
|
||
|
||
if (flag(this, 'contains')) {
|
||
return this.assert(
|
||
isSubsetOf(subset, obj, cmp)
|
||
, 'expected #{this} to be a superset of #{act}'
|
||
, 'expected #{this} to not be a superset of #{act}'
|
||
, obj
|
||
, subset
|
||
);
|
||
}
|
||
|
||
this.assert(
|
||
isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp)
|
||
, 'expected #{this} to have the same members as #{act}'
|
||
, 'expected #{this} to not have the same members as #{act}'
|
||
, obj
|
||
, subset
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .change(function)
|
||
*
|
||
* Asserts that a function changes an object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val += 3 };
|
||
* var noChangeFn = function() { return 'foo' + 'bar'; }
|
||
* expect(fn).to.change(obj, 'val');
|
||
* expect(noChangFn).to.not.change(obj, 'val')
|
||
*
|
||
* @name change
|
||
* @alias changes
|
||
* @alias Change
|
||
* @param {String} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertChanges (object, prop, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var fn = flag(this, 'object');
|
||
new Assertion(object, msg).to.have.property(prop);
|
||
new Assertion(fn).is.a('function');
|
||
|
||
var initial = object[prop];
|
||
fn();
|
||
|
||
this.assert(
|
||
initial !== object[prop]
|
||
, 'expected .' + prop + ' to change'
|
||
, 'expected .' + prop + ' to not change'
|
||
);
|
||
}
|
||
|
||
Assertion.addChainableMethod('change', assertChanges);
|
||
Assertion.addChainableMethod('changes', assertChanges);
|
||
|
||
/**
|
||
* ### .increase(function)
|
||
*
|
||
* Asserts that a function increases an object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 15 };
|
||
* expect(fn).to.increase(obj, 'val');
|
||
*
|
||
* @name increase
|
||
* @alias increases
|
||
* @alias Increase
|
||
* @param {String} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertIncreases (object, prop, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var fn = flag(this, 'object');
|
||
new Assertion(object, msg).to.have.property(prop);
|
||
new Assertion(fn).is.a('function');
|
||
|
||
var initial = object[prop];
|
||
fn();
|
||
|
||
this.assert(
|
||
object[prop] - initial > 0
|
||
, 'expected .' + prop + ' to increase'
|
||
, 'expected .' + prop + ' to not increase'
|
||
);
|
||
}
|
||
|
||
Assertion.addChainableMethod('increase', assertIncreases);
|
||
Assertion.addChainableMethod('increases', assertIncreases);
|
||
|
||
/**
|
||
* ### .decrease(function)
|
||
*
|
||
* Asserts that a function decreases an object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 5 };
|
||
* expect(fn).to.decrease(obj, 'val');
|
||
*
|
||
* @name decrease
|
||
* @alias decreases
|
||
* @alias Decrease
|
||
* @param {String} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertDecreases (object, prop, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var fn = flag(this, 'object');
|
||
new Assertion(object, msg).to.have.property(prop);
|
||
new Assertion(fn).is.a('function');
|
||
|
||
var initial = object[prop];
|
||
fn();
|
||
|
||
this.assert(
|
||
object[prop] - initial < 0
|
||
, 'expected .' + prop + ' to decrease'
|
||
, 'expected .' + prop + ' to not decrease'
|
||
);
|
||
}
|
||
|
||
Assertion.addChainableMethod('decrease', assertDecreases);
|
||
Assertion.addChainableMethod('decreases', assertDecreases);
|
||
|
||
};
|
||
|
||
},{}],7:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
|
||
module.exports = function (chai, util) {
|
||
|
||
/*!
|
||
* Chai dependencies.
|
||
*/
|
||
|
||
var Assertion = chai.Assertion
|
||
, flag = util.flag;
|
||
|
||
/*!
|
||
* Module export.
|
||
*/
|
||
|
||
/**
|
||
* ### assert(expression, message)
|
||
*
|
||
* Write your own test expressions.
|
||
*
|
||
* assert('foo' !== 'bar', 'foo is not bar');
|
||
* assert(Array.isArray([]), 'empty arrays are arrays');
|
||
*
|
||
* @param {Mixed} expression to test for truthiness
|
||
* @param {String} message to display on error
|
||
* @name assert
|
||
* @api public
|
||
*/
|
||
|
||
var assert = chai.assert = function (express, errmsg) {
|
||
var test = new Assertion(null, null, chai.assert);
|
||
test.assert(
|
||
express
|
||
, errmsg
|
||
, '[ negation message unavailable ]'
|
||
);
|
||
};
|
||
|
||
/**
|
||
* ### .fail(actual, expected, [message], [operator])
|
||
*
|
||
* Throw a failure. Node.js `assert` module-compatible.
|
||
*
|
||
* @name fail
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @param {String} operator
|
||
* @api public
|
||
*/
|
||
|
||
assert.fail = function (actual, expected, message, operator) {
|
||
message = message || 'assert.fail()';
|
||
throw new chai.AssertionError(message, {
|
||
actual: actual
|
||
, expected: expected
|
||
, operator: operator
|
||
}, assert.fail);
|
||
};
|
||
|
||
/**
|
||
* ### .ok(object, [message])
|
||
*
|
||
* Asserts that `object` is truthy.
|
||
*
|
||
* assert.ok('everything', 'everything is ok');
|
||
* assert.ok(false, 'this will fail');
|
||
*
|
||
* @name ok
|
||
* @param {Mixed} object to test
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.ok = function (val, msg) {
|
||
new Assertion(val, msg).is.ok;
|
||
};
|
||
|
||
/**
|
||
* ### .notOk(object, [message])
|
||
*
|
||
* Asserts that `object` is falsy.
|
||
*
|
||
* assert.notOk('everything', 'this will fail');
|
||
* assert.notOk(false, 'this will pass');
|
||
*
|
||
* @name notOk
|
||
* @param {Mixed} object to test
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notOk = function (val, msg) {
|
||
new Assertion(val, msg).is.not.ok;
|
||
};
|
||
|
||
/**
|
||
* ### .equal(actual, expected, [message])
|
||
*
|
||
* Asserts non-strict equality (`==`) of `actual` and `expected`.
|
||
*
|
||
* assert.equal(3, '3', '== coerces values to strings');
|
||
*
|
||
* @name equal
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.equal = function (act, exp, msg) {
|
||
var test = new Assertion(act, msg, assert.equal);
|
||
|
||
test.assert(
|
||
exp == flag(test, 'object')
|
||
, 'expected #{this} to equal #{exp}'
|
||
, 'expected #{this} to not equal #{act}'
|
||
, exp
|
||
, act
|
||
);
|
||
};
|
||
|
||
/**
|
||
* ### .notEqual(actual, expected, [message])
|
||
*
|
||
* Asserts non-strict inequality (`!=`) of `actual` and `expected`.
|
||
*
|
||
* assert.notEqual(3, 4, 'these numbers are not equal');
|
||
*
|
||
* @name notEqual
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notEqual = function (act, exp, msg) {
|
||
var test = new Assertion(act, msg, assert.notEqual);
|
||
|
||
test.assert(
|
||
exp != flag(test, 'object')
|
||
, 'expected #{this} to not equal #{exp}'
|
||
, 'expected #{this} to equal #{act}'
|
||
, exp
|
||
, act
|
||
);
|
||
};
|
||
|
||
/**
|
||
* ### .strictEqual(actual, expected, [message])
|
||
*
|
||
* Asserts strict equality (`===`) of `actual` and `expected`.
|
||
*
|
||
* assert.strictEqual(true, true, 'these booleans are strictly equal');
|
||
*
|
||
* @name strictEqual
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.strictEqual = function (act, exp, msg) {
|
||
new Assertion(act, msg).to.equal(exp);
|
||
};
|
||
|
||
/**
|
||
* ### .notStrictEqual(actual, expected, [message])
|
||
*
|
||
* Asserts strict inequality (`!==`) of `actual` and `expected`.
|
||
*
|
||
* assert.notStrictEqual(3, '3', 'no coercion for strict equality');
|
||
*
|
||
* @name notStrictEqual
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notStrictEqual = function (act, exp, msg) {
|
||
new Assertion(act, msg).to.not.equal(exp);
|
||
};
|
||
|
||
/**
|
||
* ### .deepEqual(actual, expected, [message])
|
||
*
|
||
* Asserts that `actual` is deeply equal to `expected`.
|
||
*
|
||
* assert.deepEqual({ tea: 'green' }, { tea: 'green' });
|
||
*
|
||
* @name deepEqual
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.deepEqual = function (act, exp, msg) {
|
||
new Assertion(act, msg).to.eql(exp);
|
||
};
|
||
|
||
/**
|
||
* ### .notDeepEqual(actual, expected, [message])
|
||
*
|
||
* Assert that `actual` is not deeply equal to `expected`.
|
||
*
|
||
* assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });
|
||
*
|
||
* @name notDeepEqual
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notDeepEqual = function (act, exp, msg) {
|
||
new Assertion(act, msg).to.not.eql(exp);
|
||
};
|
||
|
||
/**
|
||
* ### .isTrue(value, [message])
|
||
*
|
||
* Asserts that `value` is true.
|
||
*
|
||
* var teaServed = true;
|
||
* assert.isTrue(teaServed, 'the tea has been served');
|
||
*
|
||
* @name isTrue
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isAbove = function (val, abv, msg) {
|
||
new Assertion(val, msg).to.be.above(abv);
|
||
};
|
||
|
||
/**
|
||
* ### .isAbove(valueToCheck, valueToBeAbove, [message])
|
||
*
|
||
* Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove`
|
||
*
|
||
* assert.isAbove(5, 2, '5 is strictly greater than 2');
|
||
*
|
||
* @name isAbove
|
||
* @param {Mixed} valueToCheck
|
||
* @param {Mixed} valueToBeAbove
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isBelow = function (val, blw, msg) {
|
||
new Assertion(val, msg).to.be.below(blw);
|
||
};
|
||
|
||
/**
|
||
* ### .isBelow(valueToCheck, valueToBeBelow, [message])
|
||
*
|
||
* Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow`
|
||
*
|
||
* assert.isBelow(3, 6, '3 is strictly less than 6');
|
||
*
|
||
* @name isBelow
|
||
* @param {Mixed} valueToCheck
|
||
* @param {Mixed} valueToBeBelow
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isTrue = function (val, msg) {
|
||
new Assertion(val, msg).is['true'];
|
||
};
|
||
|
||
/**
|
||
* ### .isFalse(value, [message])
|
||
*
|
||
* Asserts that `value` is false.
|
||
*
|
||
* var teaServed = false;
|
||
* assert.isFalse(teaServed, 'no tea yet? hmm...');
|
||
*
|
||
* @name isFalse
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isFalse = function (val, msg) {
|
||
new Assertion(val, msg).is['false'];
|
||
};
|
||
|
||
/**
|
||
* ### .isNull(value, [message])
|
||
*
|
||
* Asserts that `value` is null.
|
||
*
|
||
* assert.isNull(err, 'there was no error');
|
||
*
|
||
* @name isNull
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNull = function (val, msg) {
|
||
new Assertion(val, msg).to.equal(null);
|
||
};
|
||
|
||
/**
|
||
* ### .isNotNull(value, [message])
|
||
*
|
||
* Asserts that `value` is not null.
|
||
*
|
||
* var tea = 'tasty chai';
|
||
* assert.isNotNull(tea, 'great, time for tea!');
|
||
*
|
||
* @name isNotNull
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotNull = function (val, msg) {
|
||
new Assertion(val, msg).to.not.equal(null);
|
||
};
|
||
|
||
/**
|
||
* ### .isUndefined(value, [message])
|
||
*
|
||
* Asserts that `value` is `undefined`.
|
||
*
|
||
* var tea;
|
||
* assert.isUndefined(tea, 'no tea defined');
|
||
*
|
||
* @name isUndefined
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isUndefined = function (val, msg) {
|
||
new Assertion(val, msg).to.equal(undefined);
|
||
};
|
||
|
||
/**
|
||
* ### .isDefined(value, [message])
|
||
*
|
||
* Asserts that `value` is not `undefined`.
|
||
*
|
||
* var tea = 'cup of chai';
|
||
* assert.isDefined(tea, 'tea has been defined');
|
||
*
|
||
* @name isDefined
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isDefined = function (val, msg) {
|
||
new Assertion(val, msg).to.not.equal(undefined);
|
||
};
|
||
|
||
/**
|
||
* ### .isFunction(value, [message])
|
||
*
|
||
* Asserts that `value` is a function.
|
||
*
|
||
* function serveTea() { return 'cup of tea'; };
|
||
* assert.isFunction(serveTea, 'great, we can have tea now');
|
||
*
|
||
* @name isFunction
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isFunction = function (val, msg) {
|
||
new Assertion(val, msg).to.be.a('function');
|
||
};
|
||
|
||
/**
|
||
* ### .isNotFunction(value, [message])
|
||
*
|
||
* Asserts that `value` is _not_ a function.
|
||
*
|
||
* var serveTea = [ 'heat', 'pour', 'sip' ];
|
||
* assert.isNotFunction(serveTea, 'great, we have listed the steps');
|
||
*
|
||
* @name isNotFunction
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotFunction = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.a('function');
|
||
};
|
||
|
||
/**
|
||
* ### .isObject(value, [message])
|
||
*
|
||
* Asserts that `value` is an object (as revealed by
|
||
* `Object.prototype.toString`).
|
||
*
|
||
* var selection = { name: 'Chai', serve: 'with spices' };
|
||
* assert.isObject(selection, 'tea selection is an object');
|
||
*
|
||
* @name isObject
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isObject = function (val, msg) {
|
||
new Assertion(val, msg).to.be.a('object');
|
||
};
|
||
|
||
/**
|
||
* ### .isNotObject(value, [message])
|
||
*
|
||
* Asserts that `value` is _not_ an object.
|
||
*
|
||
* var selection = 'chai'
|
||
* assert.isNotObject(selection, 'tea selection is not an object');
|
||
* assert.isNotObject(null, 'null is not an object');
|
||
*
|
||
* @name isNotObject
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotObject = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.a('object');
|
||
};
|
||
|
||
/**
|
||
* ### .isArray(value, [message])
|
||
*
|
||
* Asserts that `value` is an array.
|
||
*
|
||
* var menu = [ 'green', 'chai', 'oolong' ];
|
||
* assert.isArray(menu, 'what kind of tea do we want?');
|
||
*
|
||
* @name isArray
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isArray = function (val, msg) {
|
||
new Assertion(val, msg).to.be.an('array');
|
||
};
|
||
|
||
/**
|
||
* ### .isNotArray(value, [message])
|
||
*
|
||
* Asserts that `value` is _not_ an array.
|
||
*
|
||
* var menu = 'green|chai|oolong';
|
||
* assert.isNotArray(menu, 'what kind of tea do we want?');
|
||
*
|
||
* @name isNotArray
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotArray = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.an('array');
|
||
};
|
||
|
||
/**
|
||
* ### .isString(value, [message])
|
||
*
|
||
* Asserts that `value` is a string.
|
||
*
|
||
* var teaOrder = 'chai';
|
||
* assert.isString(teaOrder, 'order placed');
|
||
*
|
||
* @name isString
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isString = function (val, msg) {
|
||
new Assertion(val, msg).to.be.a('string');
|
||
};
|
||
|
||
/**
|
||
* ### .isNotString(value, [message])
|
||
*
|
||
* Asserts that `value` is _not_ a string.
|
||
*
|
||
* var teaOrder = 4;
|
||
* assert.isNotString(teaOrder, 'order placed');
|
||
*
|
||
* @name isNotString
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotString = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.a('string');
|
||
};
|
||
|
||
/**
|
||
* ### .isNumber(value, [message])
|
||
*
|
||
* Asserts that `value` is a number.
|
||
*
|
||
* var cups = 2;
|
||
* assert.isNumber(cups, 'how many cups');
|
||
*
|
||
* @name isNumber
|
||
* @param {Number} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNumber = function (val, msg) {
|
||
new Assertion(val, msg).to.be.a('number');
|
||
};
|
||
|
||
/**
|
||
* ### .isNotNumber(value, [message])
|
||
*
|
||
* Asserts that `value` is _not_ a number.
|
||
*
|
||
* var cups = '2 cups please';
|
||
* assert.isNotNumber(cups, 'how many cups');
|
||
*
|
||
* @name isNotNumber
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotNumber = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.a('number');
|
||
};
|
||
|
||
/**
|
||
* ### .isBoolean(value, [message])
|
||
*
|
||
* Asserts that `value` is a boolean.
|
||
*
|
||
* var teaReady = true
|
||
* , teaServed = false;
|
||
*
|
||
* assert.isBoolean(teaReady, 'is the tea ready');
|
||
* assert.isBoolean(teaServed, 'has tea been served');
|
||
*
|
||
* @name isBoolean
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isBoolean = function (val, msg) {
|
||
new Assertion(val, msg).to.be.a('boolean');
|
||
};
|
||
|
||
/**
|
||
* ### .isNotBoolean(value, [message])
|
||
*
|
||
* Asserts that `value` is _not_ a boolean.
|
||
*
|
||
* var teaReady = 'yep'
|
||
* , teaServed = 'nope';
|
||
*
|
||
* assert.isNotBoolean(teaReady, 'is the tea ready');
|
||
* assert.isNotBoolean(teaServed, 'has tea been served');
|
||
*
|
||
* @name isNotBoolean
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotBoolean = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.a('boolean');
|
||
};
|
||
|
||
/**
|
||
* ### .typeOf(value, name, [message])
|
||
*
|
||
* Asserts that `value`'s type is `name`, as determined by
|
||
* `Object.prototype.toString`.
|
||
*
|
||
* assert.typeOf({ tea: 'chai' }, 'object', 'we have an object');
|
||
* assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array');
|
||
* assert.typeOf('tea', 'string', 'we have a string');
|
||
* assert.typeOf(/tea/, 'regexp', 'we have a regular expression');
|
||
* assert.typeOf(null, 'null', 'we have a null');
|
||
* assert.typeOf(undefined, 'undefined', 'we have an undefined');
|
||
*
|
||
* @name typeOf
|
||
* @param {Mixed} value
|
||
* @param {String} name
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.typeOf = function (val, type, msg) {
|
||
new Assertion(val, msg).to.be.a(type);
|
||
};
|
||
|
||
/**
|
||
* ### .notTypeOf(value, name, [message])
|
||
*
|
||
* Asserts that `value`'s type is _not_ `name`, as determined by
|
||
* `Object.prototype.toString`.
|
||
*
|
||
* assert.notTypeOf('tea', 'number', 'strings are not numbers');
|
||
*
|
||
* @name notTypeOf
|
||
* @param {Mixed} value
|
||
* @param {String} typeof name
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notTypeOf = function (val, type, msg) {
|
||
new Assertion(val, msg).to.not.be.a(type);
|
||
};
|
||
|
||
/**
|
||
* ### .instanceOf(object, constructor, [message])
|
||
*
|
||
* Asserts that `value` is an instance of `constructor`.
|
||
*
|
||
* var Tea = function (name) { this.name = name; }
|
||
* , chai = new Tea('chai');
|
||
*
|
||
* assert.instanceOf(chai, Tea, 'chai is an instance of tea');
|
||
*
|
||
* @name instanceOf
|
||
* @param {Object} object
|
||
* @param {Constructor} constructor
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.instanceOf = function (val, type, msg) {
|
||
new Assertion(val, msg).to.be.instanceOf(type);
|
||
};
|
||
|
||
/**
|
||
* ### .notInstanceOf(object, constructor, [message])
|
||
*
|
||
* Asserts `value` is not an instance of `constructor`.
|
||
*
|
||
* var Tea = function (name) { this.name = name; }
|
||
* , chai = new String('chai');
|
||
*
|
||
* assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea');
|
||
*
|
||
* @name notInstanceOf
|
||
* @param {Object} object
|
||
* @param {Constructor} constructor
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notInstanceOf = function (val, type, msg) {
|
||
new Assertion(val, msg).to.not.be.instanceOf(type);
|
||
};
|
||
|
||
/**
|
||
* ### .include(haystack, needle, [message])
|
||
*
|
||
* Asserts that `haystack` includes `needle`. Works
|
||
* for strings and arrays.
|
||
*
|
||
* assert.include('foobar', 'bar', 'foobar contains string "bar"');
|
||
* assert.include([ 1, 2, 3 ], 3, 'array contains value');
|
||
*
|
||
* @name include
|
||
* @param {Array|String} haystack
|
||
* @param {Mixed} needle
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.include = function (exp, inc, msg) {
|
||
new Assertion(exp, msg, assert.include).include(inc);
|
||
};
|
||
|
||
/**
|
||
* ### .notInclude(haystack, needle, [message])
|
||
*
|
||
* Asserts that `haystack` does not include `needle`. Works
|
||
* for strings and arrays.
|
||
*i
|
||
* assert.notInclude('foobar', 'baz', 'string not include substring');
|
||
* assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value');
|
||
*
|
||
* @name notInclude
|
||
* @param {Array|String} haystack
|
||
* @param {Mixed} needle
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notInclude = function (exp, inc, msg) {
|
||
new Assertion(exp, msg, assert.notInclude).not.include(inc);
|
||
};
|
||
|
||
/**
|
||
* ### .match(value, regexp, [message])
|
||
*
|
||
* Asserts that `value` matches the regular expression `regexp`.
|
||
*
|
||
* assert.match('foobar', /^foo/, 'regexp matches');
|
||
*
|
||
* @name match
|
||
* @param {Mixed} value
|
||
* @param {RegExp} regexp
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.match = function (exp, re, msg) {
|
||
new Assertion(exp, msg).to.match(re);
|
||
};
|
||
|
||
/**
|
||
* ### .notMatch(value, regexp, [message])
|
||
*
|
||
* Asserts that `value` does not match the regular expression `regexp`.
|
||
*
|
||
* assert.notMatch('foobar', /^foo/, 'regexp does not match');
|
||
*
|
||
* @name notMatch
|
||
* @param {Mixed} value
|
||
* @param {RegExp} regexp
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notMatch = function (exp, re, msg) {
|
||
new Assertion(exp, msg).to.not.match(re);
|
||
};
|
||
|
||
/**
|
||
* ### .property(object, property, [message])
|
||
*
|
||
* Asserts that `object` has a property named by `property`.
|
||
*
|
||
* assert.property({ tea: { green: 'matcha' }}, 'tea');
|
||
*
|
||
* @name property
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.property = function (obj, prop, msg) {
|
||
new Assertion(obj, msg).to.have.property(prop);
|
||
};
|
||
|
||
/**
|
||
* ### .notProperty(object, property, [message])
|
||
*
|
||
* Asserts that `object` does _not_ have a property named by `property`.
|
||
*
|
||
* assert.notProperty({ tea: { green: 'matcha' }}, 'coffee');
|
||
*
|
||
* @name notProperty
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notProperty = function (obj, prop, msg) {
|
||
new Assertion(obj, msg).to.not.have.property(prop);
|
||
};
|
||
|
||
/**
|
||
* ### .deepProperty(object, property, [message])
|
||
*
|
||
* Asserts that `object` has a property named by `property`, which can be a
|
||
* string using dot- and bracket-notation for deep reference.
|
||
*
|
||
* assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green');
|
||
*
|
||
* @name deepProperty
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.deepProperty = function (obj, prop, msg) {
|
||
new Assertion(obj, msg).to.have.deep.property(prop);
|
||
};
|
||
|
||
/**
|
||
* ### .notDeepProperty(object, property, [message])
|
||
*
|
||
* Asserts that `object` does _not_ have a property named by `property`, which
|
||
* can be a string using dot- and bracket-notation for deep reference.
|
||
*
|
||
* assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong');
|
||
*
|
||
* @name notDeepProperty
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notDeepProperty = function (obj, prop, msg) {
|
||
new Assertion(obj, msg).to.not.have.deep.property(prop);
|
||
};
|
||
|
||
/**
|
||
* ### .propertyVal(object, property, value, [message])
|
||
*
|
||
* Asserts that `object` has a property named by `property` with value given
|
||
* by `value`.
|
||
*
|
||
* assert.propertyVal({ tea: 'is good' }, 'tea', 'is good');
|
||
*
|
||
* @name propertyVal
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.propertyVal = function (obj, prop, val, msg) {
|
||
new Assertion(obj, msg).to.have.property(prop, val);
|
||
};
|
||
|
||
/**
|
||
* ### .propertyNotVal(object, property, value, [message])
|
||
*
|
||
* Asserts that `object` has a property named by `property`, but with a value
|
||
* different from that given by `value`.
|
||
*
|
||
* assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad');
|
||
*
|
||
* @name propertyNotVal
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.propertyNotVal = function (obj, prop, val, msg) {
|
||
new Assertion(obj, msg).to.not.have.property(prop, val);
|
||
};
|
||
|
||
/**
|
||
* ### .deepPropertyVal(object, property, value, [message])
|
||
*
|
||
* Asserts that `object` has a property named by `property` with value given
|
||
* by `value`. `property` can use dot- and bracket-notation for deep
|
||
* reference.
|
||
*
|
||
* assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha');
|
||
*
|
||
* @name deepPropertyVal
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.deepPropertyVal = function (obj, prop, val, msg) {
|
||
new Assertion(obj, msg).to.have.deep.property(prop, val);
|
||
};
|
||
|
||
/**
|
||
* ### .deepPropertyNotVal(object, property, value, [message])
|
||
*
|
||
* Asserts that `object` has a property named by `property`, but with a value
|
||
* different from that given by `value`. `property` can use dot- and
|
||
* bracket-notation for deep reference.
|
||
*
|
||
* assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha');
|
||
*
|
||
* @name deepPropertyNotVal
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.deepPropertyNotVal = function (obj, prop, val, msg) {
|
||
new Assertion(obj, msg).to.not.have.deep.property(prop, val);
|
||
};
|
||
|
||
/**
|
||
* ### .lengthOf(object, length, [message])
|
||
*
|
||
* Asserts that `object` has a `length` property with the expected value.
|
||
*
|
||
* assert.lengthOf([1,2,3], 3, 'array has length of 3');
|
||
* assert.lengthOf('foobar', 5, 'string has length of 6');
|
||
*
|
||
* @name lengthOf
|
||
* @param {Mixed} object
|
||
* @param {Number} length
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.lengthOf = function (exp, len, msg) {
|
||
new Assertion(exp, msg).to.have.length(len);
|
||
};
|
||
|
||
/**
|
||
* ### .throws(function, [constructor/string/regexp], [string/regexp], [message])
|
||
*
|
||
* Asserts that `function` will throw an error that is an instance of
|
||
* `constructor`, or alternately that it will throw an error with message
|
||
* matching `regexp`.
|
||
*
|
||
* assert.throw(fn, 'function throws a reference error');
|
||
* assert.throw(fn, /function throws a reference error/);
|
||
* assert.throw(fn, ReferenceError);
|
||
* assert.throw(fn, ReferenceError, 'function throws a reference error');
|
||
* assert.throw(fn, ReferenceError, /function throws a reference error/);
|
||
*
|
||
* @name throws
|
||
* @alias throw
|
||
* @alias Throw
|
||
* @param {Function} function
|
||
* @param {ErrorConstructor} constructor
|
||
* @param {RegExp} regexp
|
||
* @param {String} message
|
||
* @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
|
||
* @api public
|
||
*/
|
||
|
||
assert.Throw = function (fn, errt, errs, msg) {
|
||
if ('string' === typeof errt || errt instanceof RegExp) {
|
||
errs = errt;
|
||
errt = null;
|
||
}
|
||
|
||
var assertErr = new Assertion(fn, msg).to.Throw(errt, errs);
|
||
return flag(assertErr, 'object');
|
||
};
|
||
|
||
/**
|
||
* ### .doesNotThrow(function, [constructor/regexp], [message])
|
||
*
|
||
* Asserts that `function` will _not_ throw an error that is an instance of
|
||
* `constructor`, or alternately that it will not throw an error with message
|
||
* matching `regexp`.
|
||
*
|
||
* assert.doesNotThrow(fn, Error, 'function does not throw');
|
||
*
|
||
* @name doesNotThrow
|
||
* @param {Function} function
|
||
* @param {ErrorConstructor} constructor
|
||
* @param {RegExp} regexp
|
||
* @param {String} message
|
||
* @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
|
||
* @api public
|
||
*/
|
||
|
||
assert.doesNotThrow = function (fn, type, msg) {
|
||
if ('string' === typeof type) {
|
||
msg = type;
|
||
type = null;
|
||
}
|
||
|
||
new Assertion(fn, msg).to.not.Throw(type);
|
||
};
|
||
|
||
/**
|
||
* ### .operator(val1, operator, val2, [message])
|
||
*
|
||
* Compares two values using `operator`.
|
||
*
|
||
* assert.operator(1, '<', 2, 'everything is ok');
|
||
* assert.operator(1, '>', 2, 'this will fail');
|
||
*
|
||
* @name operator
|
||
* @param {Mixed} val1
|
||
* @param {String} operator
|
||
* @param {Mixed} val2
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.operator = function (val, operator, val2, msg) {
|
||
var ok;
|
||
switch(operator) {
|
||
case '==':
|
||
ok = val == val2;
|
||
break;
|
||
case '===':
|
||
ok = val === val2;
|
||
break;
|
||
case '>':
|
||
ok = val > val2;
|
||
break;
|
||
case '>=':
|
||
ok = val >= val2;
|
||
break;
|
||
case '<':
|
||
ok = val < val2;
|
||
break;
|
||
case '<=':
|
||
ok = val <= val2;
|
||
break;
|
||
case '!=':
|
||
ok = val != val2;
|
||
break;
|
||
case '!==':
|
||
ok = val !== val2;
|
||
break;
|
||
default:
|
||
throw new Error('Invalid operator "' + operator + '"');
|
||
}
|
||
var test = new Assertion(ok, msg);
|
||
test.assert(
|
||
true === flag(test, 'object')
|
||
, 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2)
|
||
, 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) );
|
||
};
|
||
|
||
/**
|
||
* ### .closeTo(actual, expected, delta, [message])
|
||
*
|
||
* Asserts that the target is equal `expected`, to within a +/- `delta` range.
|
||
*
|
||
* assert.closeTo(1.5, 1, 0.5, 'numbers are close');
|
||
*
|
||
* @name closeTo
|
||
* @param {Number} actual
|
||
* @param {Number} expected
|
||
* @param {Number} delta
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.closeTo = function (act, exp, delta, msg) {
|
||
new Assertion(act, msg).to.be.closeTo(exp, delta);
|
||
};
|
||
|
||
/**
|
||
* ### .sameMembers(set1, set2, [message])
|
||
*
|
||
* Asserts that `set1` and `set2` have the same members.
|
||
* Order is not taken into account.
|
||
*
|
||
* assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members');
|
||
*
|
||
* @name sameMembers
|
||
* @param {Array} set1
|
||
* @param {Array} set2
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.sameMembers = function (set1, set2, msg) {
|
||
new Assertion(set1, msg).to.have.same.members(set2);
|
||
}
|
||
|
||
/**
|
||
* ### .sameDeepMembers(set1, set2, [message])
|
||
*
|
||
* Asserts that `set1` and `set2` have the same members - using a deep equality checking.
|
||
* Order is not taken into account.
|
||
*
|
||
* assert.sameDeepMembers([ {b: 3}, {a: 2}, {c: 5} ], [ {c: 5}, {b: 3}, {a: 2} ], 'same deep members');
|
||
*
|
||
* @name sameDeepMembers
|
||
* @param {Array} set1
|
||
* @param {Array} set2
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.sameDeepMembers = function (set1, set2, msg) {
|
||
new Assertion(set1, msg).to.have.same.deep.members(set2);
|
||
}
|
||
|
||
/**
|
||
* ### .includeMembers(superset, subset, [message])
|
||
*
|
||
* Asserts that `subset` is included in `superset`.
|
||
* Order is not taken into account.
|
||
*
|
||
* assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members');
|
||
*
|
||
* @name includeMembers
|
||
* @param {Array} superset
|
||
* @param {Array} subset
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.includeMembers = function (superset, subset, msg) {
|
||
new Assertion(superset, msg).to.include.members(subset);
|
||
}
|
||
|
||
/**
|
||
* ### .changes(function, object, property)
|
||
*
|
||
* Asserts that a function changes the value of a property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 22 };
|
||
* assert.changes(fn, obj, 'val');
|
||
*
|
||
* @name changes
|
||
* @param {Function} modifier function
|
||
* @param {Object} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
assert.changes = function (fn, obj, prop) {
|
||
new Assertion(fn).to.change(obj, prop);
|
||
}
|
||
|
||
/**
|
||
* ### .doesNotChange(function, object, property)
|
||
*
|
||
* Asserts that a function does not changes the value of a property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { console.log('foo'); };
|
||
* assert.doesNotChange(fn, obj, 'val');
|
||
*
|
||
* @name doesNotChange
|
||
* @param {Function} modifier function
|
||
* @param {Object} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
assert.doesNotChange = function (fn, obj, prop) {
|
||
new Assertion(fn).to.not.change(obj, prop);
|
||
}
|
||
|
||
/**
|
||
* ### .increases(function, object, property)
|
||
*
|
||
* Asserts that a function increases an object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 13 };
|
||
* assert.increases(fn, obj, 'val');
|
||
*
|
||
* @name increases
|
||
* @param {Function} modifier function
|
||
* @param {Object} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
assert.increases = function (fn, obj, prop) {
|
||
new Assertion(fn).to.increase(obj, prop);
|
||
}
|
||
|
||
/**
|
||
* ### .doesNotIncrease(function, object, property)
|
||
*
|
||
* Asserts that a function does not increase object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 8 };
|
||
* assert.doesNotIncrease(fn, obj, 'val');
|
||
*
|
||
* @name doesNotIncrease
|
||
* @param {Function} modifier function
|
||
* @param {Object} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
assert.doesNotIncrease = function (fn, obj, prop) {
|
||
new Assertion(fn).to.not.increase(obj, prop);
|
||
}
|
||
|
||
/**
|
||
* ### .decreases(function, object, property)
|
||
*
|
||
* Asserts that a function decreases an object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 5 };
|
||
* assert.decreases(fn, obj, 'val');
|
||
*
|
||
* @name decreases
|
||
* @param {Function} modifier function
|
||
* @param {Object} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
assert.decreases = function (fn, obj, prop) {
|
||
new Assertion(fn).to.decrease(obj, prop);
|
||
}
|
||
|
||
/**
|
||
* ### .doesNotDecrease(function, object, property)
|
||
*
|
||
* Asserts that a function does not decreases an object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 15 };
|
||
* assert.doesNotDecrease(fn, obj, 'val');
|
||
*
|
||
* @name doesNotDecrease
|
||
* @param {Function} modifier function
|
||
* @param {Object} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
assert.doesNotDecrease = function (fn, obj, prop) {
|
||
new Assertion(fn).to.not.decrease(obj, prop);
|
||
}
|
||
|
||
/*!
|
||
* Undocumented / untested
|
||
*/
|
||
|
||
assert.ifError = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.ok;
|
||
};
|
||
|
||
/*!
|
||
* Aliases.
|
||
*/
|
||
|
||
(function alias(name, as){
|
||
assert[as] = assert[name];
|
||
return alias;
|
||
})
|
||
('Throw', 'throw')
|
||
('Throw', 'throws');
|
||
};
|
||
|
||
},{}],8:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
module.exports = function (chai, util) {
|
||
chai.expect = function (val, message) {
|
||
return new chai.Assertion(val, message);
|
||
};
|
||
|
||
/**
|
||
* ### .fail(actual, expected, [message], [operator])
|
||
*
|
||
* Throw a failure.
|
||
*
|
||
* @name fail
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @param {String} operator
|
||
* @api public
|
||
*/
|
||
|
||
chai.expect.fail = function (actual, expected, message, operator) {
|
||
message = message || 'expect.fail()';
|
||
throw new chai.AssertionError(message, {
|
||
actual: actual
|
||
, expected: expected
|
||
, operator: operator
|
||
}, chai.expect.fail);
|
||
};
|
||
};
|
||
|
||
},{}],9:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
module.exports = function (chai, util) {
|
||
var Assertion = chai.Assertion;
|
||
|
||
function loadShould () {
|
||
// explicitly define this method as function as to have it's name to include as `ssfi`
|
||
function shouldGetter() {
|
||
if (this instanceof String || this instanceof Number || this instanceof Boolean ) {
|
||
return new Assertion(this.valueOf(), null, shouldGetter);
|
||
}
|
||
return new Assertion(this, null, shouldGetter);
|
||
}
|
||
function shouldSetter(value) {
|
||
// See https://github.com/chaijs/chai/issues/86: this makes
|
||
// `whatever.should = someValue` actually set `someValue`, which is
|
||
// especially useful for `global.should = require('chai').should()`.
|
||
//
|
||
// Note that we have to use [[DefineProperty]] instead of [[Put]]
|
||
// since otherwise we would trigger this very setter!
|
||
Object.defineProperty(this, 'should', {
|
||
value: value,
|
||
enumerable: true,
|
||
configurable: true,
|
||
writable: true
|
||
});
|
||
}
|
||
// modify Object.prototype to have `should`
|
||
Object.defineProperty(Object.prototype, 'should', {
|
||
set: shouldSetter
|
||
, get: shouldGetter
|
||
, configurable: true
|
||
});
|
||
|
||
var should = {};
|
||
|
||
/**
|
||
* ### .fail(actual, expected, [message], [operator])
|
||
*
|
||
* Throw a failure.
|
||
*
|
||
* @name fail
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @param {String} operator
|
||
* @api public
|
||
*/
|
||
|
||
should.fail = function (actual, expected, message, operator) {
|
||
message = message || 'should.fail()';
|
||
throw new chai.AssertionError(message, {
|
||
actual: actual
|
||
, expected: expected
|
||
, operator: operator
|
||
}, should.fail);
|
||
};
|
||
|
||
should.equal = function (val1, val2, msg) {
|
||
new Assertion(val1, msg).to.equal(val2);
|
||
};
|
||
|
||
should.Throw = function (fn, errt, errs, msg) {
|
||
new Assertion(fn, msg).to.Throw(errt, errs);
|
||
};
|
||
|
||
should.exist = function (val, msg) {
|
||
new Assertion(val, msg).to.exist;
|
||
}
|
||
|
||
// negation
|
||
should.not = {}
|
||
|
||
should.not.equal = function (val1, val2, msg) {
|
||
new Assertion(val1, msg).to.not.equal(val2);
|
||
};
|
||
|
||
should.not.Throw = function (fn, errt, errs, msg) {
|
||
new Assertion(fn, msg).to.not.Throw(errt, errs);
|
||
};
|
||
|
||
should.not.exist = function (val, msg) {
|
||
new Assertion(val, msg).to.not.exist;
|
||
}
|
||
|
||
should['throw'] = should['Throw'];
|
||
should.not['throw'] = should.not['Throw'];
|
||
|
||
return should;
|
||
};
|
||
|
||
chai.should = loadShould;
|
||
chai.Should = loadShould;
|
||
};
|
||
|
||
},{}],10:[function(require,module,exports){
|
||
/*!
|
||
* Chai - addChainingMethod utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/*!
|
||
* Module dependencies
|
||
*/
|
||
|
||
var transferFlags = require('./transferFlags');
|
||
var flag = require('./flag');
|
||
var config = require('../config');
|
||
|
||
/*!
|
||
* Module variables
|
||
*/
|
||
|
||
// Check whether `__proto__` is supported
|
||
var hasProtoSupport = '__proto__' in Object;
|
||
|
||
// Without `__proto__` support, this module will need to add properties to a function.
|
||
// However, some Function.prototype methods cannot be overwritten,
|
||
// and there seems no easy cross-platform way to detect them (@see chaijs/chai/issues/69).
|
||
var excludeNames = /^(?:length|name|arguments|caller)$/;
|
||
|
||
// Cache `Function` properties
|
||
var call = Function.prototype.call,
|
||
apply = Function.prototype.apply;
|
||
|
||
/**
|
||
* ### addChainableMethod (ctx, name, method, chainingBehavior)
|
||
*
|
||
* Adds a method to an object, such that the method can also be chained.
|
||
*
|
||
* utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) {
|
||
* var obj = utils.flag(this, 'object');
|
||
* new chai.Assertion(obj).to.be.equal(str);
|
||
* });
|
||
*
|
||
* Can also be accessed directly from `chai.Assertion`.
|
||
*
|
||
* chai.Assertion.addChainableMethod('foo', fn, chainingBehavior);
|
||
*
|
||
* The result can then be used as both a method assertion, executing both `method` and
|
||
* `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`.
|
||
*
|
||
* expect(fooStr).to.be.foo('bar');
|
||
* expect(fooStr).to.be.foo.equal('foo');
|
||
*
|
||
* @param {Object} ctx object to which the method is added
|
||
* @param {String} name of method to add
|
||
* @param {Function} method function to be used for `name`, when called
|
||
* @param {Function} chainingBehavior function to be called every time the property is accessed
|
||
* @name addChainableMethod
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function (ctx, name, method, chainingBehavior) {
|
||
if (typeof chainingBehavior !== 'function') {
|
||
chainingBehavior = function () { };
|
||
}
|
||
|
||
var chainableBehavior = {
|
||
method: method
|
||
, chainingBehavior: chainingBehavior
|
||
};
|
||
|
||
// save the methods so we can overwrite them later, if we need to.
|
||
if (!ctx.__methods) {
|
||
ctx.__methods = {};
|
||
}
|
||
ctx.__methods[name] = chainableBehavior;
|
||
|
||
Object.defineProperty(ctx, name,
|
||
{ get: function () {
|
||
chainableBehavior.chainingBehavior.call(this);
|
||
|
||
var assert = function assert() {
|
||
var old_ssfi = flag(this, 'ssfi');
|
||
if (old_ssfi && config.includeStack === false)
|
||
flag(this, 'ssfi', assert);
|
||
var result = chainableBehavior.method.apply(this, arguments);
|
||
return result === undefined ? this : result;
|
||
};
|
||
|
||
// Use `__proto__` if available
|
||
if (hasProtoSupport) {
|
||
// Inherit all properties from the object by replacing the `Function` prototype
|
||
var prototype = assert.__proto__ = Object.create(this);
|
||
// Restore the `call` and `apply` methods from `Function`
|
||
prototype.call = call;
|
||
prototype.apply = apply;
|
||
}
|
||
// Otherwise, redefine all properties (slow!)
|
||
else {
|
||
var asserterNames = Object.getOwnPropertyNames(ctx);
|
||
asserterNames.forEach(function (asserterName) {
|
||
if (!excludeNames.test(asserterName)) {
|
||
var pd = Object.getOwnPropertyDescriptor(ctx, asserterName);
|
||
Object.defineProperty(assert, asserterName, pd);
|
||
}
|
||
});
|
||
}
|
||
|
||
transferFlags(this, assert);
|
||
return assert;
|
||
}
|
||
, configurable: true
|
||
});
|
||
};
|
||
|
||
},{"../config":5,"./flag":13,"./transferFlags":29}],11:[function(require,module,exports){
|
||
/*!
|
||
* Chai - addMethod utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
var config = require('../config');
|
||
|
||
/**
|
||
* ### .addMethod (ctx, name, method)
|
||
*
|
||
* Adds a method to the prototype of an object.
|
||
*
|
||
* utils.addMethod(chai.Assertion.prototype, 'foo', function (str) {
|
||
* var obj = utils.flag(this, 'object');
|
||
* new chai.Assertion(obj).to.be.equal(str);
|
||
* });
|
||
*
|
||
* Can also be accessed directly from `chai.Assertion`.
|
||
*
|
||
* chai.Assertion.addMethod('foo', fn);
|
||
*
|
||
* Then can be used as any other assertion.
|
||
*
|
||
* expect(fooStr).to.be.foo('bar');
|
||
*
|
||
* @param {Object} ctx object to which the method is added
|
||
* @param {String} name of method to add
|
||
* @param {Function} method function to be used for name
|
||
* @name addMethod
|
||
* @api public
|
||
*/
|
||
var flag = require('./flag');
|
||
|
||
module.exports = function (ctx, name, method) {
|
||
ctx[name] = function () {
|
||
var old_ssfi = flag(this, 'ssfi');
|
||
if (old_ssfi && config.includeStack === false)
|
||
flag(this, 'ssfi', ctx[name]);
|
||
var result = method.apply(this, arguments);
|
||
return result === undefined ? this : result;
|
||
};
|
||
};
|
||
|
||
},{"../config":5,"./flag":13}],12:[function(require,module,exports){
|
||
/*!
|
||
* Chai - addProperty utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* ### addProperty (ctx, name, getter)
|
||
*
|
||
* Adds a property to the prototype of an object.
|
||
*
|
||
* utils.addProperty(chai.Assertion.prototype, 'foo', function () {
|
||
* var obj = utils.flag(this, 'object');
|
||
* new chai.Assertion(obj).to.be.instanceof(Foo);
|
||
* });
|
||
*
|
||
* Can also be accessed directly from `chai.Assertion`.
|
||
*
|
||
* chai.Assertion.addProperty('foo', fn);
|
||
*
|
||
* Then can be used as any other assertion.
|
||
*
|
||
* expect(myFoo).to.be.foo;
|
||
*
|
||
* @param {Object} ctx object to which the property is added
|
||
* @param {String} name of property to add
|
||
* @param {Function} getter function to be used for name
|
||
* @name addProperty
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function (ctx, name, getter) {
|
||
Object.defineProperty(ctx, name,
|
||
{ get: function () {
|
||
var result = getter.call(this);
|
||
return result === undefined ? this : result;
|
||
}
|
||
, configurable: true
|
||
});
|
||
};
|
||
|
||
},{}],13:[function(require,module,exports){
|
||
/*!
|
||
* Chai - flag utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* ### flag(object, key, [value])
|
||
*
|
||
* Get or set a flag value on an object. If a
|
||
* value is provided it will be set, else it will
|
||
* return the currently set value or `undefined` if
|
||
* the value is not set.
|
||
*
|
||
* utils.flag(this, 'foo', 'bar'); // setter
|
||
* utils.flag(this, 'foo'); // getter, returns `bar`
|
||
*
|
||
* @param {Object} object constructed Assertion
|
||
* @param {String} key
|
||
* @param {Mixed} value (optional)
|
||
* @name flag
|
||
* @api private
|
||
*/
|
||
|
||
module.exports = function (obj, key, value) {
|
||
var flags = obj.__flags || (obj.__flags = Object.create(null));
|
||
if (arguments.length === 3) {
|
||
flags[key] = value;
|
||
} else {
|
||
return flags[key];
|
||
}
|
||
};
|
||
|
||
},{}],14:[function(require,module,exports){
|
||
/*!
|
||
* Chai - getActual utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* # getActual(object, [actual])
|
||
*
|
||
* Returns the `actual` value for an Assertion
|
||
*
|
||
* @param {Object} object (constructed Assertion)
|
||
* @param {Arguments} chai.Assertion.prototype.assert arguments
|
||
*/
|
||
|
||
module.exports = function (obj, args) {
|
||
return args.length > 4 ? args[4] : obj._obj;
|
||
};
|
||
|
||
},{}],15:[function(require,module,exports){
|
||
/*!
|
||
* Chai - getEnumerableProperties utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* ### .getEnumerableProperties(object)
|
||
*
|
||
* This allows the retrieval of enumerable property names of an object,
|
||
* inherited or not.
|
||
*
|
||
* @param {Object} object
|
||
* @returns {Array}
|
||
* @name getEnumerableProperties
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function getEnumerableProperties(object) {
|
||
var result = [];
|
||
for (var name in object) {
|
||
result.push(name);
|
||
}
|
||
return result;
|
||
};
|
||
|
||
},{}],16:[function(require,module,exports){
|
||
/*!
|
||
* Chai - message composition utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/*!
|
||
* Module dependancies
|
||
*/
|
||
|
||
var flag = require('./flag')
|
||
, getActual = require('./getActual')
|
||
, inspect = require('./inspect')
|
||
, objDisplay = require('./objDisplay');
|
||
|
||
/**
|
||
* ### .getMessage(object, message, negateMessage)
|
||
*
|
||
* Construct the error message based on flags
|
||
* and template tags. Template tags will return
|
||
* a stringified inspection of the object referenced.
|
||
*
|
||
* Message template tags:
|
||
* - `#{this}` current asserted object
|
||
* - `#{act}` actual value
|
||
* - `#{exp}` expected value
|
||
*
|
||
* @param {Object} object (constructed Assertion)
|
||
* @param {Arguments} chai.Assertion.prototype.assert arguments
|
||
* @name getMessage
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function (obj, args) {
|
||
var negate = flag(obj, 'negate')
|
||
, val = flag(obj, 'object')
|
||
, expected = args[3]
|
||
, actual = getActual(obj, args)
|
||
, msg = negate ? args[2] : args[1]
|
||
, flagMsg = flag(obj, 'message');
|
||
|
||
if(typeof msg === "function") msg = msg();
|
||
msg = msg || '';
|
||
msg = msg
|
||
.replace(/#{this}/g, objDisplay(val))
|
||
.replace(/#{act}/g, objDisplay(actual))
|
||
.replace(/#{exp}/g, objDisplay(expected));
|
||
|
||
return flagMsg ? flagMsg + ': ' + msg : msg;
|
||
};
|
||
|
||
},{"./flag":13,"./getActual":14,"./inspect":23,"./objDisplay":24}],17:[function(require,module,exports){
|
||
/*!
|
||
* Chai - getName utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* # getName(func)
|
||
*
|
||
* Gets the name of a function, in a cross-browser way.
|
||
*
|
||
* @param {Function} a function (usually a constructor)
|
||
*/
|
||
|
||
module.exports = function (func) {
|
||
if (func.name) return func.name;
|
||
|
||
var match = /^\s?function ([^(]*)\(/.exec(func);
|
||
return match && match[1] ? match[1] : "";
|
||
};
|
||
|
||
},{}],18:[function(require,module,exports){
|
||
/*!
|
||
* Chai - getPathInfo utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
var hasProperty = require('./hasProperty');
|
||
|
||
/**
|
||
* ### .getPathInfo(path, object)
|
||
*
|
||
* This allows the retrieval of property info in an
|
||
* object given a string path.
|
||
*
|
||
* The path info consists of an object with the
|
||
* following properties:
|
||
*
|
||
* * parent - The parent object of the property referenced by `path`
|
||
* * name - The name of the final property, a number if it was an array indexer
|
||
* * value - The value of the property, if it exists, otherwise `undefined`
|
||
* * exists - Whether the property exists or not
|
||
*
|
||
* @param {String} path
|
||
* @param {Object} object
|
||
* @returns {Object} info
|
||
* @name getPathInfo
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function getPathInfo(path, obj) {
|
||
var parsed = parsePath(path),
|
||
last = parsed[parsed.length - 1];
|
||
|
||
var info = {
|
||
parent: parsed.length > 1 ? _getPathValue(parsed, obj, parsed.length - 1) : obj,
|
||
name: last.p || last.i,
|
||
value: _getPathValue(parsed, obj),
|
||
};
|
||
info.exists = hasProperty(info.name, info.parent);
|
||
|
||
return info;
|
||
};
|
||
|
||
|
||
/*!
|
||
* ## parsePath(path)
|
||
*
|
||
* Helper function used to parse string object
|
||
* paths. Use in conjunction with `_getPathValue`.
|
||
*
|
||
* var parsed = parsePath('myobject.property.subprop');
|
||
*
|
||
* ### Paths:
|
||
*
|
||
* * Can be as near infinitely deep and nested
|
||
* * Arrays are also valid using the formal `myobject.document[3].property`.
|
||
* * Literal dots and brackets (not delimiter) must be backslash-escaped.
|
||
*
|
||
* @param {String} path
|
||
* @returns {Object} parsed
|
||
* @api private
|
||
*/
|
||
|
||
function parsePath (path) {
|
||
var str = path.replace(/([^\\])\[/g, '$1.[')
|
||
, parts = str.match(/(\\\.|[^.]+?)+/g);
|
||
return parts.map(function (value) {
|
||
var re = /^\[(\d+)\]$/
|
||
, mArr = re.exec(value);
|
||
if (mArr) return { i: parseFloat(mArr[1]) };
|
||
else return { p: value.replace(/\\([.\[\]])/g, '$1') };
|
||
});
|
||
}
|
||
|
||
|
||
/*!
|
||
* ## _getPathValue(parsed, obj)
|
||
*
|
||
* Helper companion function for `.parsePath` that returns
|
||
* the value located at the parsed address.
|
||
*
|
||
* var value = getPathValue(parsed, obj);
|
||
*
|
||
* @param {Object} parsed definition from `parsePath`.
|
||
* @param {Object} object to search against
|
||
* @param {Number} object to search against
|
||
* @returns {Object|Undefined} value
|
||
* @api private
|
||
*/
|
||
|
||
function _getPathValue (parsed, obj, index) {
|
||
var tmp = obj
|
||
, res;
|
||
|
||
index = (index === undefined ? parsed.length : index);
|
||
|
||
for (var i = 0, l = index; i < l; i++) {
|
||
var part = parsed[i];
|
||
if (tmp) {
|
||
if ('undefined' !== typeof part.p)
|
||
tmp = tmp[part.p];
|
||
else if ('undefined' !== typeof part.i)
|
||
tmp = tmp[part.i];
|
||
if (i == (l - 1)) res = tmp;
|
||
} else {
|
||
res = undefined;
|
||
}
|
||
}
|
||
return res;
|
||
}
|
||
|
||
},{"./hasProperty":21}],19:[function(require,module,exports){
|
||
/*!
|
||
* Chai - getPathValue utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* @see https://github.com/logicalparadox/filtr
|
||
* MIT Licensed
|
||
*/
|
||
|
||
var getPathInfo = require('./getPathInfo');
|
||
|
||
/**
|
||
* ### .getPathValue(path, object)
|
||
*
|
||
* This allows the retrieval of values in an
|
||
* object given a string path.
|
||
*
|
||
* var obj = {
|
||
* prop1: {
|
||
* arr: ['a', 'b', 'c']
|
||
* , str: 'Hello'
|
||
* }
|
||
* , prop2: {
|
||
* arr: [ { nested: 'Universe' } ]
|
||
* , str: 'Hello again!'
|
||
* }
|
||
* }
|
||
*
|
||
* The following would be the results.
|
||
*
|
||
* getPathValue('prop1.str', obj); // Hello
|
||
* getPathValue('prop1.att[2]', obj); // b
|
||
* getPathValue('prop2.arr[0].nested', obj); // Universe
|
||
*
|
||
* @param {String} path
|
||
* @param {Object} object
|
||
* @returns {Object} value or `undefined`
|
||
* @name getPathValue
|
||
* @api public
|
||
*/
|
||
module.exports = function(path, obj) {
|
||
var info = getPathInfo(path, obj);
|
||
return info.value;
|
||
};
|
||
|
||
},{"./getPathInfo":18}],20:[function(require,module,exports){
|
||
/*!
|
||
* Chai - getProperties utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* ### .getProperties(object)
|
||
*
|
||
* This allows the retrieval of property names of an object, enumerable or not,
|
||
* inherited or not.
|
||
*
|
||
* @param {Object} object
|
||
* @returns {Array}
|
||
* @name getProperties
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function getProperties(object) {
|
||
var result = Object.getOwnPropertyNames(subject);
|
||
|
||
function addProperty(property) {
|
||
if (result.indexOf(property) === -1) {
|
||
result.push(property);
|
||
}
|
||
}
|
||
|
||
var proto = Object.getPrototypeOf(subject);
|
||
while (proto !== null) {
|
||
Object.getOwnPropertyNames(proto).forEach(addProperty);
|
||
proto = Object.getPrototypeOf(proto);
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
},{}],21:[function(require,module,exports){
|
||
/*!
|
||
* Chai - hasProperty utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
var type = require('./type');
|
||
|
||
/**
|
||
* ### .hasProperty(object, name)
|
||
*
|
||
* This allows checking whether an object has
|
||
* named property or numeric array index.
|
||
*
|
||
* Basically does the same thing as the `in`
|
||
* operator but works properly with natives
|
||
* and null/undefined values.
|
||
*
|
||
* var obj = {
|
||
* arr: ['a', 'b', 'c']
|
||
* , str: 'Hello'
|
||
* }
|
||
*
|
||
* The following would be the results.
|
||
*
|
||
* hasProperty('str', obj); // true
|
||
* hasProperty('constructor', obj); // true
|
||
* hasProperty('bar', obj); // false
|
||
*
|
||
* hasProperty('length', obj.str); // true
|
||
* hasProperty(1, obj.str); // true
|
||
* hasProperty(5, obj.str); // false
|
||
*
|
||
* hasProperty('length', obj.arr); // true
|
||
* hasProperty(2, obj.arr); // true
|
||
* hasProperty(3, obj.arr); // false
|
||
*
|
||
* @param {Objuect} object
|
||
* @param {String|Number} name
|
||
* @returns {Boolean} whether it exists
|
||
* @name getPathInfo
|
||
* @api public
|
||
*/
|
||
|
||
var literals = {
|
||
'number': Number
|
||
, 'string': String
|
||
};
|
||
|
||
module.exports = function hasProperty(name, obj) {
|
||
var ot = type(obj);
|
||
|
||
// Bad Object, obviously no props at all
|
||
if(ot === 'null' || ot === 'undefined')
|
||
return false;
|
||
|
||
// The `in` operator does not work with certain literals
|
||
// box these before the check
|
||
if(literals[ot] && typeof obj !== 'object')
|
||
obj = new literals[ot](obj);
|
||
|
||
return name in obj;
|
||
};
|
||
|
||
},{"./type":30}],22:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/*!
|
||
* Main exports
|
||
*/
|
||
|
||
var exports = module.exports = {};
|
||
|
||
/*!
|
||
* test utility
|
||
*/
|
||
|
||
exports.test = require('./test');
|
||
|
||
/*!
|
||
* type utility
|
||
*/
|
||
|
||
exports.type = require('./type');
|
||
|
||
/*!
|
||
* message utility
|
||
*/
|
||
|
||
exports.getMessage = require('./getMessage');
|
||
|
||
/*!
|
||
* actual utility
|
||
*/
|
||
|
||
exports.getActual = require('./getActual');
|
||
|
||
/*!
|
||
* Inspect util
|
||
*/
|
||
|
||
exports.inspect = require('./inspect');
|
||
|
||
/*!
|
||
* Object Display util
|
||
*/
|
||
|
||
exports.objDisplay = require('./objDisplay');
|
||
|
||
/*!
|
||
* Flag utility
|
||
*/
|
||
|
||
exports.flag = require('./flag');
|
||
|
||
/*!
|
||
* Flag transferring utility
|
||
*/
|
||
|
||
exports.transferFlags = require('./transferFlags');
|
||
|
||
/*!
|
||
* Deep equal utility
|
||
*/
|
||
|
||
exports.eql = require('deep-eql');
|
||
|
||
/*!
|
||
* Deep path value
|
||
*/
|
||
|
||
exports.getPathValue = require('./getPathValue');
|
||
|
||
/*!
|
||
* Deep path info
|
||
*/
|
||
|
||
exports.getPathInfo = require('./getPathInfo');
|
||
|
||
/*!
|
||
* Check if a property exists
|
||
*/
|
||
|
||
exports.hasProperty = require('./hasProperty');
|
||
|
||
/*!
|
||
* Function name
|
||
*/
|
||
|
||
exports.getName = require('./getName');
|
||
|
||
/*!
|
||
* add Property
|
||
*/
|
||
|
||
exports.addProperty = require('./addProperty');
|
||
|
||
/*!
|
||
* add Method
|
||
*/
|
||
|
||
exports.addMethod = require('./addMethod');
|
||
|
||
/*!
|
||
* overwrite Property
|
||
*/
|
||
|
||
exports.overwriteProperty = require('./overwriteProperty');
|
||
|
||
/*!
|
||
* overwrite Method
|
||
*/
|
||
|
||
exports.overwriteMethod = require('./overwriteMethod');
|
||
|
||
/*!
|
||
* Add a chainable method
|
||
*/
|
||
|
||
exports.addChainableMethod = require('./addChainableMethod');
|
||
|
||
/*!
|
||
* Overwrite chainable method
|
||
*/
|
||
|
||
exports.overwriteChainableMethod = require('./overwriteChainableMethod');
|
||
|
||
|
||
},{"./addChainableMethod":10,"./addMethod":11,"./addProperty":12,"./flag":13,"./getActual":14,"./getMessage":16,"./getName":17,"./getPathInfo":18,"./getPathValue":19,"./hasProperty":21,"./inspect":23,"./objDisplay":24,"./overwriteChainableMethod":25,"./overwriteMethod":26,"./overwriteProperty":27,"./test":28,"./transferFlags":29,"./type":30,"deep-eql":32}],23:[function(require,module,exports){
|
||
// This is (almost) directly from Node.js utils
|
||
// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js
|
||
|
||
var getName = require('./getName');
|
||
var getProperties = require('./getProperties');
|
||
var getEnumerableProperties = require('./getEnumerableProperties');
|
||
|
||
module.exports = inspect;
|
||
|
||
/**
|
||
* Echos the value of a value. Trys to print the value out
|
||
* in the best way possible given the different types.
|
||
*
|
||
* @param {Object} obj The object to print out.
|
||
* @param {Boolean} showHidden Flag that shows hidden (not enumerable)
|
||
* properties of objects.
|
||
* @param {Number} depth Depth in which to descend in object. Default is 2.
|
||
* @param {Boolean} colors Flag to turn on ANSI escape codes to color the
|
||
* output. Default is false (no coloring).
|
||
*/
|
||
function inspect(obj, showHidden, depth, colors) {
|
||
var ctx = {
|
||
showHidden: showHidden,
|
||
seen: [],
|
||
stylize: function (str) { return str; }
|
||
};
|
||
return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth));
|
||
}
|
||
|
||
// Returns true if object is a DOM element.
|
||
var isDOMElement = function (object) {
|
||
if (typeof HTMLElement === 'object') {
|
||
return object instanceof HTMLElement;
|
||
} else {
|
||
return object &&
|
||
typeof object === 'object' &&
|
||
object.nodeType === 1 &&
|
||
typeof object.nodeName === 'string';
|
||
}
|
||
};
|
||
|
||
function formatValue(ctx, value, recurseTimes) {
|
||
// Provide a hook for user-specified inspect functions.
|
||
// Check that value is an object with an inspect function on it
|
||
if (value && typeof value.inspect === 'function' &&
|
||
// Filter out the util module, it's inspect function is special
|
||
value.inspect !== exports.inspect &&
|
||
// Also filter out any prototype objects using the circular check.
|
||
!(value.constructor && value.constructor.prototype === value)) {
|
||
var ret = value.inspect(recurseTimes);
|
||
if (typeof ret !== 'string') {
|
||
ret = formatValue(ctx, ret, recurseTimes);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// Primitive types cannot have properties
|
||
var primitive = formatPrimitive(ctx, value);
|
||
if (primitive) {
|
||
return primitive;
|
||
}
|
||
|
||
// If this is a DOM element, try to get the outer HTML.
|
||
if (isDOMElement(value)) {
|
||
if ('outerHTML' in value) {
|
||
return value.outerHTML;
|
||
// This value does not have an outerHTML attribute,
|
||
// it could still be an XML element
|
||
} else {
|
||
// Attempt to serialize it
|
||
try {
|
||
if (document.xmlVersion) {
|
||
var xmlSerializer = new XMLSerializer();
|
||
return xmlSerializer.serializeToString(value);
|
||
} else {
|
||
// Firefox 11- do not support outerHTML
|
||
// It does, however, support innerHTML
|
||
// Use the following to render the element
|
||
var ns = "http://www.w3.org/1999/xhtml";
|
||
var container = document.createElementNS(ns, '_');
|
||
|
||
container.appendChild(value.cloneNode(false));
|
||
html = container.innerHTML
|
||
.replace('><', '>' + value.innerHTML + '<');
|
||
container.innerHTML = '';
|
||
return html;
|
||
}
|
||
} catch (err) {
|
||
// This could be a non-native DOM implementation,
|
||
// continue with the normal flow:
|
||
// printing the element as if it is an object.
|
||
}
|
||
}
|
||
}
|
||
|
||
// Look up the keys of the object.
|
||
var visibleKeys = getEnumerableProperties(value);
|
||
var keys = ctx.showHidden ? getProperties(value) : visibleKeys;
|
||
|
||
// Some type of object without properties can be shortcutted.
|
||
// In IE, errors have a single `stack` property, or if they are vanilla `Error`,
|
||
// a `stack` plus `description` property; ignore those for consistency.
|
||
if (keys.length === 0 || (isError(value) && (
|
||
(keys.length === 1 && keys[0] === 'stack') ||
|
||
(keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack')
|
||
))) {
|
||
if (typeof value === 'function') {
|
||
var name = getName(value);
|
||
var nameSuffix = name ? ': ' + name : '';
|
||
return ctx.stylize('[Function' + nameSuffix + ']', 'special');
|
||
}
|
||
if (isRegExp(value)) {
|
||
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||
}
|
||
if (isDate(value)) {
|
||
return ctx.stylize(Date.prototype.toUTCString.call(value), 'date');
|
||
}
|
||
if (isError(value)) {
|
||
return formatError(value);
|
||
}
|
||
}
|
||
|
||
var base = '', array = false, braces = ['{', '}'];
|
||
|
||
// Make Array say that they are Array
|
||
if (isArray(value)) {
|
||
array = true;
|
||
braces = ['[', ']'];
|
||
}
|
||
|
||
// Make functions say that they are functions
|
||
if (typeof value === 'function') {
|
||
var name = getName(value);
|
||
var nameSuffix = name ? ': ' + name : '';
|
||
base = ' [Function' + nameSuffix + ']';
|
||
}
|
||
|
||
// Make RegExps say that they are RegExps
|
||
if (isRegExp(value)) {
|
||
base = ' ' + RegExp.prototype.toString.call(value);
|
||
}
|
||
|
||
// Make dates with properties first say the date
|
||
if (isDate(value)) {
|
||
base = ' ' + Date.prototype.toUTCString.call(value);
|
||
}
|
||
|
||
// Make error with message first say the error
|
||
if (isError(value)) {
|
||
return formatError(value);
|
||
}
|
||
|
||
if (keys.length === 0 && (!array || value.length == 0)) {
|
||
return braces[0] + base + braces[1];
|
||
}
|
||
|
||
if (recurseTimes < 0) {
|
||
if (isRegExp(value)) {
|
||
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||
} else {
|
||
return ctx.stylize('[Object]', 'special');
|
||
}
|
||
}
|
||
|
||
ctx.seen.push(value);
|
||
|
||
var output;
|
||
if (array) {
|
||
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
|
||
} else {
|
||
output = keys.map(function(key) {
|
||
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
|
||
});
|
||
}
|
||
|
||
ctx.seen.pop();
|
||
|
||
return reduceToSingleString(output, base, braces);
|
||
}
|
||
|
||
|
||
function formatPrimitive(ctx, value) {
|
||
switch (typeof value) {
|
||
case 'undefined':
|
||
return ctx.stylize('undefined', 'undefined');
|
||
|
||
case 'string':
|
||
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
||
.replace(/'/g, "\\'")
|
||
.replace(/\\"/g, '"') + '\'';
|
||
return ctx.stylize(simple, 'string');
|
||
|
||
case 'number':
|
||
if (value === 0 && (1/value) === -Infinity) {
|
||
return ctx.stylize('-0', 'number');
|
||
}
|
||
return ctx.stylize('' + value, 'number');
|
||
|
||
case 'boolean':
|
||
return ctx.stylize('' + value, 'boolean');
|
||
}
|
||
// For some reason typeof null is "object", so special case here.
|
||
if (value === null) {
|
||
return ctx.stylize('null', 'null');
|
||
}
|
||
}
|
||
|
||
|
||
function formatError(value) {
|
||
return '[' + Error.prototype.toString.call(value) + ']';
|
||
}
|
||
|
||
|
||
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
|
||
var output = [];
|
||
for (var i = 0, l = value.length; i < l; ++i) {
|
||
if (Object.prototype.hasOwnProperty.call(value, String(i))) {
|
||
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||
String(i), true));
|
||
} else {
|
||
output.push('');
|
||
}
|
||
}
|
||
keys.forEach(function(key) {
|
||
if (!key.match(/^\d+$/)) {
|
||
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||
key, true));
|
||
}
|
||
});
|
||
return output;
|
||
}
|
||
|
||
|
||
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
|
||
var name, str;
|
||
if (value.__lookupGetter__) {
|
||
if (value.__lookupGetter__(key)) {
|
||
if (value.__lookupSetter__(key)) {
|
||
str = ctx.stylize('[Getter/Setter]', 'special');
|
||
} else {
|
||
str = ctx.stylize('[Getter]', 'special');
|
||
}
|
||
} else {
|
||
if (value.__lookupSetter__(key)) {
|
||
str = ctx.stylize('[Setter]', 'special');
|
||
}
|
||
}
|
||
}
|
||
if (visibleKeys.indexOf(key) < 0) {
|
||
name = '[' + key + ']';
|
||
}
|
||
if (!str) {
|
||
if (ctx.seen.indexOf(value[key]) < 0) {
|
||
if (recurseTimes === null) {
|
||
str = formatValue(ctx, value[key], null);
|
||
} else {
|
||
str = formatValue(ctx, value[key], recurseTimes - 1);
|
||
}
|
||
if (str.indexOf('\n') > -1) {
|
||
if (array) {
|
||
str = str.split('\n').map(function(line) {
|
||
return ' ' + line;
|
||
}).join('\n').substr(2);
|
||
} else {
|
||
str = '\n' + str.split('\n').map(function(line) {
|
||
return ' ' + line;
|
||
}).join('\n');
|
||
}
|
||
}
|
||
} else {
|
||
str = ctx.stylize('[Circular]', 'special');
|
||
}
|
||
}
|
||
if (typeof name === 'undefined') {
|
||
if (array && key.match(/^\d+$/)) {
|
||
return str;
|
||
}
|
||
name = JSON.stringify('' + key);
|
||
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
||
name = name.substr(1, name.length - 2);
|
||
name = ctx.stylize(name, 'name');
|
||
} else {
|
||
name = name.replace(/'/g, "\\'")
|
||
.replace(/\\"/g, '"')
|
||
.replace(/(^"|"$)/g, "'");
|
||
name = ctx.stylize(name, 'string');
|
||
}
|
||
}
|
||
|
||
return name + ': ' + str;
|
||
}
|
||
|
||
|
||
function reduceToSingleString(output, base, braces) {
|
||
var numLinesEst = 0;
|
||
var length = output.reduce(function(prev, cur) {
|
||
numLinesEst++;
|
||
if (cur.indexOf('\n') >= 0) numLinesEst++;
|
||
return prev + cur.length + 1;
|
||
}, 0);
|
||
|
||
if (length > 60) {
|
||
return braces[0] +
|
||
(base === '' ? '' : base + '\n ') +
|
||
' ' +
|
||
output.join(',\n ') +
|
||
' ' +
|
||
braces[1];
|
||
}
|
||
|
||
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
||
}
|
||
|
||
function isArray(ar) {
|
||
return Array.isArray(ar) ||
|
||
(typeof ar === 'object' && objectToString(ar) === '[object Array]');
|
||
}
|
||
|
||
function isRegExp(re) {
|
||
return typeof re === 'object' && objectToString(re) === '[object RegExp]';
|
||
}
|
||
|
||
function isDate(d) {
|
||
return typeof d === 'object' && objectToString(d) === '[object Date]';
|
||
}
|
||
|
||
function isError(e) {
|
||
return typeof e === 'object' && objectToString(e) === '[object Error]';
|
||
}
|
||
|
||
function objectToString(o) {
|
||
return Object.prototype.toString.call(o);
|
||
}
|
||
|
||
},{"./getEnumerableProperties":15,"./getName":17,"./getProperties":20}],24:[function(require,module,exports){
|
||
/*!
|
||
* Chai - flag utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/*!
|
||
* Module dependancies
|
||
*/
|
||
|
||
var inspect = require('./inspect');
|
||
var config = require('../config');
|
||
|
||
/**
|
||
* ### .objDisplay (object)
|
||
*
|
||
* Determines if an object or an array matches
|
||
* criteria to be inspected in-line for error
|
||
* messages or should be truncated.
|
||
*
|
||
* @param {Mixed} javascript object to inspect
|
||
* @name objDisplay
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function (obj) {
|
||
var str = inspect(obj)
|
||
, type = Object.prototype.toString.call(obj);
|
||
|
||
if (config.truncateThreshold && str.length >= config.truncateThreshold) {
|
||
if (type === '[object Function]') {
|
||
return !obj.name || obj.name === ''
|
||
? '[Function]'
|
||
: '[Function: ' + obj.name + ']';
|
||
} else if (type === '[object Array]') {
|
||
return '[ Array(' + obj.length + ') ]';
|
||
} else if (type === '[object Object]') {
|
||
var keys = Object.keys(obj)
|
||
, kstr = keys.length > 2
|
||
? keys.splice(0, 2).join(', ') + ', ...'
|
||
: keys.join(', ');
|
||
return '{ Object (' + kstr + ') }';
|
||
} else {
|
||
return str;
|
||
}
|
||
} else {
|
||
return str;
|
||
}
|
||
};
|
||
|
||
},{"../config":5,"./inspect":23}],25:[function(require,module,exports){
|
||
/*!
|
||
* Chai - overwriteChainableMethod utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* ### overwriteChainableMethod (ctx, name, method, chainingBehavior)
|
||
*
|
||
* Overwites an already existing chainable method
|
||
* and provides access to the previous function or
|
||
* property. Must return functions to be used for
|
||
* name.
|
||
*
|
||
* utils.overwriteChainableMethod(chai.Assertion.prototype, 'length',
|
||
* function (_super) {
|
||
* }
|
||
* , function (_super) {
|
||
* }
|
||
* );
|
||
*
|
||
* Can also be accessed directly from `chai.Assertion`.
|
||
*
|
||
* chai.Assertion.overwriteChainableMethod('foo', fn, fn);
|
||
*
|
||
* Then can be used as any other assertion.
|
||
*
|
||
* expect(myFoo).to.have.length(3);
|
||
* expect(myFoo).to.have.length.above(3);
|
||
*
|
||
* @param {Object} ctx object whose method / property is to be overwritten
|
||
* @param {String} name of method / property to overwrite
|
||
* @param {Function} method function that returns a function to be used for name
|
||
* @param {Function} chainingBehavior function that returns a function to be used for property
|
||
* @name overwriteChainableMethod
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function (ctx, name, method, chainingBehavior) {
|
||
var chainableBehavior = ctx.__methods[name];
|
||
|
||
var _chainingBehavior = chainableBehavior.chainingBehavior;
|
||
chainableBehavior.chainingBehavior = function () {
|
||
var result = chainingBehavior(_chainingBehavior).call(this);
|
||
return result === undefined ? this : result;
|
||
};
|
||
|
||
var _method = chainableBehavior.method;
|
||
chainableBehavior.method = function () {
|
||
var result = method(_method).apply(this, arguments);
|
||
return result === undefined ? this : result;
|
||
};
|
||
};
|
||
|
||
},{}],26:[function(require,module,exports){
|
||
/*!
|
||
* Chai - overwriteMethod utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* ### overwriteMethod (ctx, name, fn)
|
||
*
|
||
* Overwites an already existing method and provides
|
||
* access to previous function. Must return function
|
||
* to be used for name.
|
||
*
|
||
* utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) {
|
||
* return function (str) {
|
||
* var obj = utils.flag(this, 'object');
|
||
* if (obj instanceof Foo) {
|
||
* new chai.Assertion(obj.value).to.equal(str);
|
||
* } else {
|
||
* _super.apply(this, arguments);
|
||
* }
|
||
* }
|
||
* });
|
||
*
|
||
* Can also be accessed directly from `chai.Assertion`.
|
||
*
|
||
* chai.Assertion.overwriteMethod('foo', fn);
|
||
*
|
||
* Then can be used as any other assertion.
|
||
*
|
||
* expect(myFoo).to.equal('bar');
|
||
*
|
||
* @param {Object} ctx object whose method is to be overwritten
|
||
* @param {String} name of method to overwrite
|
||
* @param {Function} method function that returns a function to be used for name
|
||
* @name overwriteMethod
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function (ctx, name, method) {
|
||
var _method = ctx[name]
|
||
, _super = function () { return this; };
|
||
|
||
if (_method && 'function' === typeof _method)
|
||
_super = _method;
|
||
|
||
ctx[name] = function () {
|
||
var result = method(_super).apply(this, arguments);
|
||
return result === undefined ? this : result;
|
||
}
|
||
};
|
||
|
||
},{}],27:[function(require,module,exports){
|
||
/*!
|
||
* Chai - overwriteProperty utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* ### overwriteProperty (ctx, name, fn)
|
||
*
|
||
* Overwites an already existing property getter and provides
|
||
* access to previous value. Must return function to use as getter.
|
||
*
|
||
* utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) {
|
||
* return function () {
|
||
* var obj = utils.flag(this, 'object');
|
||
* if (obj instanceof Foo) {
|
||
* new chai.Assertion(obj.name).to.equal('bar');
|
||
* } else {
|
||
* _super.call(this);
|
||
* }
|
||
* }
|
||
* });
|
||
*
|
||
*
|
||
* Can also be accessed directly from `chai.Assertion`.
|
||
*
|
||
* chai.Assertion.overwriteProperty('foo', fn);
|
||
*
|
||
* Then can be used as any other assertion.
|
||
*
|
||
* expect(myFoo).to.be.ok;
|
||
*
|
||
* @param {Object} ctx object whose property is to be overwritten
|
||
* @param {String} name of property to overwrite
|
||
* @param {Function} getter function that returns a getter function to be used for name
|
||
* @name overwriteProperty
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function (ctx, name, getter) {
|
||
var _get = Object.getOwnPropertyDescriptor(ctx, name)
|
||
, _super = function () {};
|
||
|
||
if (_get && 'function' === typeof _get.get)
|
||
_super = _get.get
|
||
|
||
Object.defineProperty(ctx, name,
|
||
{ get: function () {
|
||
var result = getter(_super).call(this);
|
||
return result === undefined ? this : result;
|
||
}
|
||
, configurable: true
|
||
});
|
||
};
|
||
|
||
},{}],28:[function(require,module,exports){
|
||
/*!
|
||
* Chai - test utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/*!
|
||
* Module dependancies
|
||
*/
|
||
|
||
var flag = require('./flag');
|
||
|
||
/**
|
||
* # test(object, expression)
|
||
*
|
||
* Test and object for expression.
|
||
*
|
||
* @param {Object} object (constructed Assertion)
|
||
* @param {Arguments} chai.Assertion.prototype.assert arguments
|
||
*/
|
||
|
||
module.exports = function (obj, args) {
|
||
var negate = flag(obj, 'negate')
|
||
, expr = args[0];
|
||
return negate ? !expr : expr;
|
||
};
|
||
|
||
},{"./flag":13}],29:[function(require,module,exports){
|
||
/*!
|
||
* Chai - transferFlags utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* ### transferFlags(assertion, object, includeAll = true)
|
||
*
|
||
* Transfer all the flags for `assertion` to `object`. If
|
||
* `includeAll` is set to `false`, then the base Chai
|
||
* assertion flags (namely `object`, `ssfi`, and `message`)
|
||
* will not be transferred.
|
||
*
|
||
*
|
||
* var newAssertion = new Assertion();
|
||
* utils.transferFlags(assertion, newAssertion);
|
||
*
|
||
* var anotherAsseriton = new Assertion(myObj);
|
||
* utils.transferFlags(assertion, anotherAssertion, false);
|
||
*
|
||
* @param {Assertion} assertion the assertion to transfer the flags from
|
||
* @param {Object} object the object to transfer the flags to; usually a new assertion
|
||
* @param {Boolean} includeAll
|
||
* @name transferFlags
|
||
* @api private
|
||
*/
|
||
|
||
module.exports = function (assertion, object, includeAll) {
|
||
var flags = assertion.__flags || (assertion.__flags = Object.create(null));
|
||
|
||
if (!object.__flags) {
|
||
object.__flags = Object.create(null);
|
||
}
|
||
|
||
includeAll = arguments.length === 3 ? includeAll : true;
|
||
|
||
for (var flag in flags) {
|
||
if (includeAll ||
|
||
(flag !== 'object' && flag !== 'ssfi' && flag != 'message')) {
|
||
object.__flags[flag] = flags[flag];
|
||
}
|
||
}
|
||
};
|
||
|
||
},{}],30:[function(require,module,exports){
|
||
/*!
|
||
* Chai - type utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/*!
|
||
* Detectable javascript natives
|
||
*/
|
||
|
||
var natives = {
|
||
'[object Arguments]': 'arguments'
|
||
, '[object Array]': 'array'
|
||
, '[object Date]': 'date'
|
||
, '[object Function]': 'function'
|
||
, '[object Number]': 'number'
|
||
, '[object RegExp]': 'regexp'
|
||
, '[object String]': 'string'
|
||
};
|
||
|
||
/**
|
||
* ### type(object)
|
||
*
|
||
* Better implementation of `typeof` detection that can
|
||
* be used cross-browser. Handles the inconsistencies of
|
||
* Array, `null`, and `undefined` detection.
|
||
*
|
||
* utils.type({}) // 'object'
|
||
* utils.type(null) // `null'
|
||
* utils.type(undefined) // `undefined`
|
||
* utils.type([]) // `array`
|
||
*
|
||
* @param {Mixed} object to detect type of
|
||
* @name type
|
||
* @api private
|
||
*/
|
||
|
||
module.exports = function (obj) {
|
||
var str = Object.prototype.toString.call(obj);
|
||
if (natives[str]) return natives[str];
|
||
if (obj === null) return 'null';
|
||
if (obj === undefined) return 'undefined';
|
||
if (obj === Object(obj)) return 'object';
|
||
return typeof obj;
|
||
};
|
||
|
||
},{}],31:[function(require,module,exports){
|
||
/*!
|
||
* assertion-error
|
||
* Copyright(c) 2013 Jake Luer <jake@qualiancy.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/*!
|
||
* Return a function that will copy properties from
|
||
* one object to another excluding any originally
|
||
* listed. Returned function will create a new `{}`.
|
||
*
|
||
* @param {String} excluded properties ...
|
||
* @return {Function}
|
||
*/
|
||
|
||
function exclude () {
|
||
var excludes = [].slice.call(arguments);
|
||
|
||
function excludeProps (res, obj) {
|
||
Object.keys(obj).forEach(function (key) {
|
||
if (!~excludes.indexOf(key)) res[key] = obj[key];
|
||
});
|
||
}
|
||
|
||
return function extendExclude () {
|
||
var args = [].slice.call(arguments)
|
||
, i = 0
|
||
, res = {};
|
||
|
||
for (; i < args.length; i++) {
|
||
excludeProps(res, args[i]);
|
||
}
|
||
|
||
return res;
|
||
};
|
||
};
|
||
|
||
/*!
|
||
* Primary Exports
|
||
*/
|
||
|
||
module.exports = AssertionError;
|
||
|
||
/**
|
||
* ### AssertionError
|
||
*
|
||
* An extension of the JavaScript `Error` constructor for
|
||
* assertion and validation scenarios.
|
||
*
|
||
* @param {String} message
|
||
* @param {Object} properties to include (optional)
|
||
* @param {callee} start stack function (optional)
|
||
*/
|
||
|
||
function AssertionError (message, _props, ssf) {
|
||
var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON')
|
||
, props = extend(_props || {});
|
||
|
||
// default values
|
||
this.message = message || 'Unspecified AssertionError';
|
||
this.showDiff = false;
|
||
|
||
// copy from properties
|
||
for (var key in props) {
|
||
this[key] = props[key];
|
||
}
|
||
|
||
// capture stack trace
|
||
ssf = ssf || arguments.callee;
|
||
if (ssf && Error.captureStackTrace) {
|
||
Error.captureStackTrace(this, ssf);
|
||
}
|
||
}
|
||
|
||
/*!
|
||
* Inherit from Error.prototype
|
||
*/
|
||
|
||
AssertionError.prototype = Object.create(Error.prototype);
|
||
|
||
/*!
|
||
* Statically set name
|
||
*/
|
||
|
||
AssertionError.prototype.name = 'AssertionError';
|
||
|
||
/*!
|
||
* Ensure correct constructor
|
||
*/
|
||
|
||
AssertionError.prototype.constructor = AssertionError;
|
||
|
||
/**
|
||
* Allow errors to be converted to JSON for static transfer.
|
||
*
|
||
* @param {Boolean} include stack (default: `true`)
|
||
* @return {Object} object that can be `JSON.stringify`
|
||
*/
|
||
|
||
AssertionError.prototype.toJSON = function (stack) {
|
||
var extend = exclude('constructor', 'toJSON', 'stack')
|
||
, props = extend({ name: this.name }, this);
|
||
|
||
// include stack if exists and not turned off
|
||
if (false !== stack && this.stack) {
|
||
props.stack = this.stack;
|
||
}
|
||
|
||
return props;
|
||
};
|
||
|
||
},{}],32:[function(require,module,exports){
|
||
module.exports = require('./lib/eql');
|
||
|
||
},{"./lib/eql":33}],33:[function(require,module,exports){
|
||
/*!
|
||
* deep-eql
|
||
* Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/*!
|
||
* Module dependencies
|
||
*/
|
||
|
||
var type = require('type-detect');
|
||
|
||
/*!
|
||
* Buffer.isBuffer browser shim
|
||
*/
|
||
|
||
var Buffer;
|
||
try { Buffer = require('buffer').Buffer; }
|
||
catch(ex) {
|
||
Buffer = {};
|
||
Buffer.isBuffer = function() { return false; }
|
||
}
|
||
|
||
/*!
|
||
* Primary Export
|
||
*/
|
||
|
||
module.exports = deepEqual;
|
||
|
||
/**
|
||
* Assert super-strict (egal) equality between
|
||
* two objects of any type.
|
||
*
|
||
* @param {Mixed} a
|
||
* @param {Mixed} b
|
||
* @param {Array} memoised (optional)
|
||
* @return {Boolean} equal match
|
||
*/
|
||
|
||
function deepEqual(a, b, m) {
|
||
if (sameValue(a, b)) {
|
||
return true;
|
||
} else if ('date' === type(a)) {
|
||
return dateEqual(a, b);
|
||
} else if ('regexp' === type(a)) {
|
||
return regexpEqual(a, b);
|
||
} else if (Buffer.isBuffer(a)) {
|
||
return bufferEqual(a, b);
|
||
} else if ('arguments' === type(a)) {
|
||
return argumentsEqual(a, b, m);
|
||
} else if (!typeEqual(a, b)) {
|
||
return false;
|
||
} else if (('object' !== type(a) && 'object' !== type(b))
|
||
&& ('array' !== type(a) && 'array' !== type(b))) {
|
||
return sameValue(a, b);
|
||
} else {
|
||
return objectEqual(a, b, m);
|
||
}
|
||
}
|
||
|
||
/*!
|
||
* Strict (egal) equality test. Ensures that NaN always
|
||
* equals NaN and `-0` does not equal `+0`.
|
||
*
|
||
* @param {Mixed} a
|
||
* @param {Mixed} b
|
||
* @return {Boolean} equal match
|
||
*/
|
||
|
||
function sameValue(a, b) {
|
||
if (a === b) return a !== 0 || 1 / a === 1 / b;
|
||
return a !== a && b !== b;
|
||
}
|
||
|
||
/*!
|
||
* Compare the types of two given objects and
|
||
* return if they are equal. Note that an Array
|
||
* has a type of `array` (not `object`) and arguments
|
||
* have a type of `arguments` (not `array`/`object`).
|
||
*
|
||
* @param {Mixed} a
|
||
* @param {Mixed} b
|
||
* @return {Boolean} result
|
||
*/
|
||
|
||
function typeEqual(a, b) {
|
||
return type(a) === type(b);
|
||
}
|
||
|
||
/*!
|
||
* Compare two Date objects by asserting that
|
||
* the time values are equal using `saveValue`.
|
||
*
|
||
* @param {Date} a
|
||
* @param {Date} b
|
||
* @return {Boolean} result
|
||
*/
|
||
|
||
function dateEqual(a, b) {
|
||
if ('date' !== type(b)) return false;
|
||
return sameValue(a.getTime(), b.getTime());
|
||
}
|
||
|
||
/*!
|
||
* Compare two regular expressions by converting them
|
||
* to string and checking for `sameValue`.
|
||
*
|
||
* @param {RegExp} a
|
||
* @param {RegExp} b
|
||
* @return {Boolean} result
|
||
*/
|
||
|
||
function regexpEqual(a, b) {
|
||
if ('regexp' !== type(b)) return false;
|
||
return sameValue(a.toString(), b.toString());
|
||
}
|
||
|
||
/*!
|
||
* Assert deep equality of two `arguments` objects.
|
||
* Unfortunately, these must be sliced to arrays
|
||
* prior to test to ensure no bad behavior.
|
||
*
|
||
* @param {Arguments} a
|
||
* @param {Arguments} b
|
||
* @param {Array} memoize (optional)
|
||
* @return {Boolean} result
|
||
*/
|
||
|
||
function argumentsEqual(a, b, m) {
|
||
if ('arguments' !== type(b)) return false;
|
||
a = [].slice.call(a);
|
||
b = [].slice.call(b);
|
||
return deepEqual(a, b, m);
|
||
}
|
||
|
||
/*!
|
||
* Get enumerable properties of a given object.
|
||
*
|
||
* @param {Object} a
|
||
* @return {Array} property names
|
||
*/
|
||
|
||
function enumerable(a) {
|
||
var res = [];
|
||
for (var key in a) res.push(key);
|
||
return res;
|
||
}
|
||
|
||
/*!
|
||
* Simple equality for flat iterable objects
|
||
* such as Arrays or Node.js buffers.
|
||
*
|
||
* @param {Iterable} a
|
||
* @param {Iterable} b
|
||
* @return {Boolean} result
|
||
*/
|
||
|
||
function iterableEqual(a, b) {
|
||
if (a.length !== b.length) return false;
|
||
|
||
var i = 0;
|
||
var match = true;
|
||
|
||
for (; i < a.length; i++) {
|
||
if (a[i] !== b[i]) {
|
||
match = false;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return match;
|
||
}
|
||
|
||
/*!
|
||
* Extension to `iterableEqual` specifically
|
||
* for Node.js Buffers.
|
||
*
|
||
* @param {Buffer} a
|
||
* @param {Mixed} b
|
||
* @return {Boolean} result
|
||
*/
|
||
|
||
function bufferEqual(a, b) {
|
||
if (!Buffer.isBuffer(b)) return false;
|
||
return iterableEqual(a, b);
|
||
}
|
||
|
||
/*!
|
||
* Block for `objectEqual` ensuring non-existing
|
||
* values don't get in.
|
||
*
|
||
* @param {Mixed} object
|
||
* @return {Boolean} result
|
||
*/
|
||
|
||
function isValue(a) {
|
||
return a !== null && a !== undefined;
|
||
}
|
||
|
||
/*!
|
||
* Recursively check the equality of two objects.
|
||
* Once basic sameness has been established it will
|
||
* defer to `deepEqual` for each enumerable key
|
||
* in the object.
|
||
*
|
||
* @param {Mixed} a
|
||
* @param {Mixed} b
|
||
* @return {Boolean} result
|
||
*/
|
||
|
||
function objectEqual(a, b, m) {
|
||
if (!isValue(a) || !isValue(b)) {
|
||
return false;
|
||
}
|
||
|
||
if (a.prototype !== b.prototype) {
|
||
return false;
|
||
}
|
||
|
||
var i;
|
||
if (m) {
|
||
for (i = 0; i < m.length; i++) {
|
||
if ((m[i][0] === a && m[i][1] === b)
|
||
|| (m[i][0] === b && m[i][1] === a)) {
|
||
return true;
|
||
}
|
||
}
|
||
} else {
|
||
m = [];
|
||
}
|
||
|
||
try {
|
||
var ka = enumerable(a);
|
||
var kb = enumerable(b);
|
||
} catch (ex) {
|
||
return false;
|
||
}
|
||
|
||
ka.sort();
|
||
kb.sort();
|
||
|
||
if (!iterableEqual(ka, kb)) {
|
||
return false;
|
||
}
|
||
|
||
m.push([ a, b ]);
|
||
|
||
var key;
|
||
for (i = ka.length - 1; i >= 0; i--) {
|
||
key = ka[i];
|
||
if (!deepEqual(a[key], b[key], m)) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
},{"buffer":110,"type-detect":34}],34:[function(require,module,exports){
|
||
module.exports = require('./lib/type');
|
||
|
||
},{"./lib/type":35}],35:[function(require,module,exports){
|
||
/*!
|
||
* type-detect
|
||
* Copyright(c) 2013 jake luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/*!
|
||
* Primary Exports
|
||
*/
|
||
|
||
var exports = module.exports = getType;
|
||
|
||
/*!
|
||
* Detectable javascript natives
|
||
*/
|
||
|
||
var natives = {
|
||
'[object Array]': 'array'
|
||
, '[object RegExp]': 'regexp'
|
||
, '[object Function]': 'function'
|
||
, '[object Arguments]': 'arguments'
|
||
, '[object Date]': 'date'
|
||
};
|
||
|
||
/**
|
||
* ### typeOf (obj)
|
||
*
|
||
* Use several different techniques to determine
|
||
* the type of object being tested.
|
||
*
|
||
*
|
||
* @param {Mixed} object
|
||
* @return {String} object type
|
||
* @api public
|
||
*/
|
||
|
||
function getType (obj) {
|
||
var str = Object.prototype.toString.call(obj);
|
||
if (natives[str]) return natives[str];
|
||
if (obj === null) return 'null';
|
||
if (obj === undefined) return 'undefined';
|
||
if (obj === Object(obj)) return 'object';
|
||
return typeof obj;
|
||
}
|
||
|
||
exports.Library = Library;
|
||
|
||
/**
|
||
* ### Library
|
||
*
|
||
* Create a repository for custom type detection.
|
||
*
|
||
* ```js
|
||
* var lib = new type.Library;
|
||
* ```
|
||
*
|
||
*/
|
||
|
||
function Library () {
|
||
this.tests = {};
|
||
}
|
||
|
||
/**
|
||
* #### .of (obj)
|
||
*
|
||
* Expose replacement `typeof` detection to the library.
|
||
*
|
||
* ```js
|
||
* if ('string' === lib.of('hello world')) {
|
||
* // ...
|
||
* }
|
||
* ```
|
||
*
|
||
* @param {Mixed} object to test
|
||
* @return {String} type
|
||
*/
|
||
|
||
Library.prototype.of = getType;
|
||
|
||
/**
|
||
* #### .define (type, test)
|
||
*
|
||
* Add a test to for the `.test()` assertion.
|
||
*
|
||
* Can be defined as a regular expression:
|
||
*
|
||
* ```js
|
||
* lib.define('int', /^[0-9]+$/);
|
||
* ```
|
||
*
|
||
* ... or as a function:
|
||
*
|
||
* ```js
|
||
* lib.define('bln', function (obj) {
|
||
* if ('boolean' === lib.of(obj)) return true;
|
||
* var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ];
|
||
* if ('string' === lib.of(obj)) obj = obj.toLowerCase();
|
||
* return !! ~blns.indexOf(obj);
|
||
* });
|
||
* ```
|
||
*
|
||
* @param {String} type
|
||
* @param {RegExp|Function} test
|
||
* @api public
|
||
*/
|
||
|
||
Library.prototype.define = function (type, test) {
|
||
if (arguments.length === 1) return this.tests[type];
|
||
this.tests[type] = test;
|
||
return this;
|
||
};
|
||
|
||
/**
|
||
* #### .test (obj, test)
|
||
*
|
||
* Assert that an object is of type. Will first
|
||
* check natives, and if that does not pass it will
|
||
* use the user defined custom tests.
|
||
*
|
||
* ```js
|
||
* assert(lib.test('1', 'int'));
|
||
* assert(lib.test('yes', 'bln'));
|
||
* ```
|
||
*
|
||
* @param {Mixed} object
|
||
* @param {String} type
|
||
* @return {Boolean} result
|
||
* @api public
|
||
*/
|
||
|
||
Library.prototype.test = function (obj, type) {
|
||
if (type === getType(obj)) return true;
|
||
var test = this.tests[type];
|
||
|
||
if (test && 'regexp' === getType(test)) {
|
||
return test.test(obj);
|
||
} else if (test && 'function' === getType(test)) {
|
||
return test(obj);
|
||
} else {
|
||
throw new ReferenceError('Type test "' + type + '" not defined or invalid.');
|
||
}
|
||
};
|
||
|
||
},{}],36:[function(require,module,exports){
|
||
(function (sinonChai) {
|
||
"use strict";
|
||
|
||
// Module systems magic dance.
|
||
|
||
/* istanbul ignore else */
|
||
if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
|
||
// NodeJS
|
||
module.exports = sinonChai;
|
||
} else if (typeof define === "function" && define.amd) {
|
||
// AMD
|
||
define(function () {
|
||
return sinonChai;
|
||
});
|
||
} else {
|
||
// Other environment (usually <script> tag): plug in to global chai instance directly.
|
||
chai.use(sinonChai);
|
||
}
|
||
}(function sinonChai(chai, utils) {
|
||
"use strict";
|
||
|
||
var slice = Array.prototype.slice;
|
||
|
||
function isSpy(putativeSpy) {
|
||
return typeof putativeSpy === "function" &&
|
||
typeof putativeSpy.getCall === "function" &&
|
||
typeof putativeSpy.calledWithExactly === "function";
|
||
}
|
||
|
||
function timesInWords(count) {
|
||
return count === 1 ? "once" :
|
||
count === 2 ? "twice" :
|
||
count === 3 ? "thrice" :
|
||
(count || 0) + " times";
|
||
}
|
||
|
||
function isCall(putativeCall) {
|
||
return putativeCall && isSpy(putativeCall.proxy);
|
||
}
|
||
|
||
function assertCanWorkWith(assertion) {
|
||
if (!isSpy(assertion._obj) && !isCall(assertion._obj)) {
|
||
throw new TypeError(utils.inspect(assertion._obj) + " is not a spy or a call to a spy!");
|
||
}
|
||
}
|
||
|
||
function getMessages(spy, action, nonNegatedSuffix, always, args) {
|
||
var verbPhrase = always ? "always have " : "have ";
|
||
nonNegatedSuffix = nonNegatedSuffix || "";
|
||
if (isSpy(spy.proxy)) {
|
||
spy = spy.proxy;
|
||
}
|
||
|
||
function printfArray(array) {
|
||
return spy.printf.apply(spy, array);
|
||
}
|
||
|
||
return {
|
||
affirmative: function () {
|
||
return printfArray(["expected %n to " + verbPhrase + action + nonNegatedSuffix].concat(args));
|
||
},
|
||
negative: function () {
|
||
return printfArray(["expected %n to not " + verbPhrase + action].concat(args));
|
||
}
|
||
};
|
||
}
|
||
|
||
function sinonProperty(name, action, nonNegatedSuffix) {
|
||
utils.addProperty(chai.Assertion.prototype, name, function () {
|
||
assertCanWorkWith(this);
|
||
|
||
var messages = getMessages(this._obj, action, nonNegatedSuffix, false);
|
||
this.assert(this._obj[name], messages.affirmative, messages.negative);
|
||
});
|
||
}
|
||
|
||
function sinonPropertyAsBooleanMethod(name, action, nonNegatedSuffix) {
|
||
utils.addMethod(chai.Assertion.prototype, name, function (arg) {
|
||
assertCanWorkWith(this);
|
||
|
||
var messages = getMessages(this._obj, action, nonNegatedSuffix, false, [timesInWords(arg)]);
|
||
this.assert(this._obj[name] === arg, messages.affirmative, messages.negative);
|
||
});
|
||
}
|
||
|
||
function createSinonMethodHandler(sinonName, action, nonNegatedSuffix) {
|
||
return function () {
|
||
assertCanWorkWith(this);
|
||
|
||
var alwaysSinonMethod = "always" + sinonName[0].toUpperCase() + sinonName.substring(1);
|
||
var shouldBeAlways = utils.flag(this, "always") && typeof this._obj[alwaysSinonMethod] === "function";
|
||
var sinonMethod = shouldBeAlways ? alwaysSinonMethod : sinonName;
|
||
|
||
var messages = getMessages(this._obj, action, nonNegatedSuffix, shouldBeAlways, slice.call(arguments));
|
||
this.assert(this._obj[sinonMethod].apply(this._obj, arguments), messages.affirmative, messages.negative);
|
||
};
|
||
}
|
||
|
||
function sinonMethodAsProperty(name, action, nonNegatedSuffix) {
|
||
var handler = createSinonMethodHandler(name, action, nonNegatedSuffix);
|
||
utils.addProperty(chai.Assertion.prototype, name, handler);
|
||
}
|
||
|
||
function exceptionalSinonMethod(chaiName, sinonName, action, nonNegatedSuffix) {
|
||
var handler = createSinonMethodHandler(sinonName, action, nonNegatedSuffix);
|
||
utils.addMethod(chai.Assertion.prototype, chaiName, handler);
|
||
}
|
||
|
||
function sinonMethod(name, action, nonNegatedSuffix) {
|
||
exceptionalSinonMethod(name, name, action, nonNegatedSuffix);
|
||
}
|
||
|
||
utils.addProperty(chai.Assertion.prototype, "always", function () {
|
||
utils.flag(this, "always", true);
|
||
});
|
||
|
||
sinonProperty("called", "been called", " at least once, but it was never called");
|
||
sinonPropertyAsBooleanMethod("callCount", "been called exactly %1", ", but it was called %c%C");
|
||
sinonProperty("calledOnce", "been called exactly once", ", but it was called %c%C");
|
||
sinonProperty("calledTwice", "been called exactly twice", ", but it was called %c%C");
|
||
sinonProperty("calledThrice", "been called exactly thrice", ", but it was called %c%C");
|
||
sinonMethodAsProperty("calledWithNew", "been called with new");
|
||
sinonMethod("calledBefore", "been called before %1");
|
||
sinonMethod("calledAfter", "been called after %1");
|
||
sinonMethod("calledOn", "been called with %1 as this", ", but it was called with %t instead");
|
||
sinonMethod("calledWith", "been called with arguments %*", "%C");
|
||
sinonMethod("calledWithExactly", "been called with exact arguments %*", "%C");
|
||
sinonMethod("calledWithMatch", "been called with arguments matching %*", "%C");
|
||
sinonMethod("returned", "returned %1");
|
||
exceptionalSinonMethod("thrown", "threw", "thrown %1");
|
||
}));
|
||
|
||
},{}],37:[function(require,module,exports){
|
||
/**
|
||
* Sinon core utilities. For internal use only.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
var sinon = (function () {
|
||
var sinon;
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
sinon = module.exports = require("./sinon/util/core");
|
||
require("./sinon/extend");
|
||
require("./sinon/typeOf");
|
||
require("./sinon/times_in_words");
|
||
require("./sinon/spy");
|
||
require("./sinon/call");
|
||
require("./sinon/behavior");
|
||
require("./sinon/stub");
|
||
require("./sinon/mock");
|
||
require("./sinon/collection");
|
||
require("./sinon/assert");
|
||
require("./sinon/sandbox");
|
||
require("./sinon/test");
|
||
require("./sinon/test_case");
|
||
require("./sinon/match");
|
||
require("./sinon/format");
|
||
require("./sinon/log_error");
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
sinon = module.exports;
|
||
} else {
|
||
sinon = {};
|
||
}
|
||
|
||
return sinon;
|
||
}());
|
||
|
||
},{"./sinon/assert":38,"./sinon/behavior":39,"./sinon/call":40,"./sinon/collection":41,"./sinon/extend":42,"./sinon/format":43,"./sinon/log_error":44,"./sinon/match":45,"./sinon/mock":46,"./sinon/sandbox":47,"./sinon/spy":48,"./sinon/stub":49,"./sinon/test":50,"./sinon/test_case":51,"./sinon/times_in_words":52,"./sinon/typeOf":53,"./sinon/util/core":54}],38:[function(require,module,exports){
|
||
(function (global){
|
||
/**
|
||
* @depend times_in_words.js
|
||
* @depend util/core.js
|
||
* @depend match.js
|
||
* @depend format.js
|
||
*/
|
||
/**
|
||
* Assertions matching the test spy retrieval interface.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon, global) {
|
||
var slice = Array.prototype.slice;
|
||
|
||
function makeApi(sinon) {
|
||
var assert;
|
||
|
||
function verifyIsStub() {
|
||
var method;
|
||
|
||
for (var i = 0, l = arguments.length; i < l; ++i) {
|
||
method = arguments[i];
|
||
|
||
if (!method) {
|
||
assert.fail("fake is not a spy");
|
||
}
|
||
|
||
if (method.proxy) {
|
||
verifyIsStub(method.proxy);
|
||
} else {
|
||
if (typeof method != "function") {
|
||
assert.fail(method + " is not a function");
|
||
}
|
||
|
||
if (typeof method.getCall != "function") {
|
||
assert.fail(method + " is not stubbed");
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
function failAssertion(object, msg) {
|
||
object = object || global;
|
||
var failMethod = object.fail || assert.fail;
|
||
failMethod.call(object, msg);
|
||
}
|
||
|
||
function mirrorPropAsAssertion(name, method, message) {
|
||
if (arguments.length == 2) {
|
||
message = method;
|
||
method = name;
|
||
}
|
||
|
||
assert[name] = function (fake) {
|
||
verifyIsStub(fake);
|
||
|
||
var args = slice.call(arguments, 1);
|
||
var failed = false;
|
||
|
||
if (typeof method == "function") {
|
||
failed = !method(fake);
|
||
} else {
|
||
failed = typeof fake[method] == "function" ?
|
||
!fake[method].apply(fake, args) : !fake[method];
|
||
}
|
||
|
||
if (failed) {
|
||
failAssertion(this, (fake.printf || fake.proxy.printf).apply(fake, [message].concat(args)));
|
||
} else {
|
||
assert.pass(name);
|
||
}
|
||
};
|
||
}
|
||
|
||
function exposedName(prefix, prop) {
|
||
return !prefix || /^fail/.test(prop) ? prop :
|
||
prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
|
||
}
|
||
|
||
assert = {
|
||
failException: "AssertError",
|
||
|
||
fail: function fail(message) {
|
||
var error = new Error(message);
|
||
error.name = this.failException || assert.failException;
|
||
|
||
throw error;
|
||
},
|
||
|
||
pass: function pass(assertion) {},
|
||
|
||
callOrder: function assertCallOrder() {
|
||
verifyIsStub.apply(null, arguments);
|
||
var expected = "", actual = "";
|
||
|
||
if (!sinon.calledInOrder(arguments)) {
|
||
try {
|
||
expected = [].join.call(arguments, ", ");
|
||
var calls = slice.call(arguments);
|
||
var i = calls.length;
|
||
while (i) {
|
||
if (!calls[--i].called) {
|
||
calls.splice(i, 1);
|
||
}
|
||
}
|
||
actual = sinon.orderByFirstCall(calls).join(", ");
|
||
} catch (e) {
|
||
// If this fails, we'll just fall back to the blank string
|
||
}
|
||
|
||
failAssertion(this, "expected " + expected + " to be " +
|
||
"called in order but were called as " + actual);
|
||
} else {
|
||
assert.pass("callOrder");
|
||
}
|
||
},
|
||
|
||
callCount: function assertCallCount(method, count) {
|
||
verifyIsStub(method);
|
||
|
||
if (method.callCount != count) {
|
||
var msg = "expected %n to be called " + sinon.timesInWords(count) +
|
||
" but was called %c%C";
|
||
failAssertion(this, method.printf(msg));
|
||
} else {
|
||
assert.pass("callCount");
|
||
}
|
||
},
|
||
|
||
expose: function expose(target, options) {
|
||
if (!target) {
|
||
throw new TypeError("target is null or undefined");
|
||
}
|
||
|
||
var o = options || {};
|
||
var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
|
||
var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
|
||
|
||
for (var method in this) {
|
||
if (method != "expose" && (includeFail || !/^(fail)/.test(method))) {
|
||
target[exposedName(prefix, method)] = this[method];
|
||
}
|
||
}
|
||
|
||
return target;
|
||
},
|
||
|
||
match: function match(actual, expectation) {
|
||
var matcher = sinon.match(expectation);
|
||
if (matcher.test(actual)) {
|
||
assert.pass("match");
|
||
} else {
|
||
var formatted = [
|
||
"expected value to match",
|
||
" expected = " + sinon.format(expectation),
|
||
" actual = " + sinon.format(actual)
|
||
]
|
||
failAssertion(this, formatted.join("\n"));
|
||
}
|
||
}
|
||
};
|
||
|
||
mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
|
||
mirrorPropAsAssertion("notCalled", function (spy) { return !spy.called; },
|
||
"expected %n to not have been called but was called %c%C");
|
||
mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
|
||
mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
|
||
mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
|
||
mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
|
||
mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
|
||
mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
|
||
mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
|
||
mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
|
||
mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
|
||
mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
|
||
mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
|
||
mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
|
||
mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
|
||
mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
|
||
mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
|
||
mirrorPropAsAssertion("threw", "%n did not throw exception%C");
|
||
mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
|
||
|
||
sinon.assert = assert;
|
||
return assert;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./match");
|
||
require("./format");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
|
||
}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"./format":43,"./match":45,"./util/core":54}],39:[function(require,module,exports){
|
||
(function (process){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend extend.js
|
||
*/
|
||
/**
|
||
* Stub behavior
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @author Tim Fischbach (mail@timfischbach.de)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
var slice = Array.prototype.slice;
|
||
var join = Array.prototype.join;
|
||
var useLeftMostCallback = -1;
|
||
var useRightMostCallback = -2;
|
||
|
||
var nextTick = (function () {
|
||
if (typeof process === "object" && typeof process.nextTick === "function") {
|
||
return process.nextTick;
|
||
} else if (typeof setImmediate === "function") {
|
||
return setImmediate;
|
||
} else {
|
||
return function (callback) {
|
||
setTimeout(callback, 0);
|
||
};
|
||
}
|
||
})();
|
||
|
||
function throwsException(error, message) {
|
||
if (typeof error == "string") {
|
||
this.exception = new Error(message || "");
|
||
this.exception.name = error;
|
||
} else if (!error) {
|
||
this.exception = new Error("Error");
|
||
} else {
|
||
this.exception = error;
|
||
}
|
||
|
||
return this;
|
||
}
|
||
|
||
function getCallback(behavior, args) {
|
||
var callArgAt = behavior.callArgAt;
|
||
|
||
if (callArgAt >= 0) {
|
||
return args[callArgAt];
|
||
}
|
||
|
||
var argumentList;
|
||
|
||
if (callArgAt === useLeftMostCallback) {
|
||
argumentList = args;
|
||
}
|
||
|
||
if (callArgAt === useRightMostCallback) {
|
||
argumentList = slice.call(args).reverse();
|
||
}
|
||
|
||
var callArgProp = behavior.callArgProp;
|
||
|
||
for (var i = 0, l = argumentList.length; i < l; ++i) {
|
||
if (!callArgProp && typeof argumentList[i] == "function") {
|
||
return argumentList[i];
|
||
}
|
||
|
||
if (callArgProp && argumentList[i] &&
|
||
typeof argumentList[i][callArgProp] == "function") {
|
||
return argumentList[i][callArgProp];
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function makeApi(sinon) {
|
||
function getCallbackError(behavior, func, args) {
|
||
if (behavior.callArgAt < 0) {
|
||
var msg;
|
||
|
||
if (behavior.callArgProp) {
|
||
msg = sinon.functionName(behavior.stub) +
|
||
" expected to yield to '" + behavior.callArgProp +
|
||
"', but no object with such a property was passed.";
|
||
} else {
|
||
msg = sinon.functionName(behavior.stub) +
|
||
" expected to yield, but no callback was passed.";
|
||
}
|
||
|
||
if (args.length > 0) {
|
||
msg += " Received [" + join.call(args, ", ") + "]";
|
||
}
|
||
|
||
return msg;
|
||
}
|
||
|
||
return "argument at index " + behavior.callArgAt + " is not a function: " + func;
|
||
}
|
||
|
||
function callCallback(behavior, args) {
|
||
if (typeof behavior.callArgAt == "number") {
|
||
var func = getCallback(behavior, args);
|
||
|
||
if (typeof func != "function") {
|
||
throw new TypeError(getCallbackError(behavior, func, args));
|
||
}
|
||
|
||
if (behavior.callbackAsync) {
|
||
nextTick(function () {
|
||
func.apply(behavior.callbackContext, behavior.callbackArguments);
|
||
});
|
||
} else {
|
||
func.apply(behavior.callbackContext, behavior.callbackArguments);
|
||
}
|
||
}
|
||
}
|
||
|
||
var proto = {
|
||
create: function create(stub) {
|
||
var behavior = sinon.extend({}, sinon.behavior);
|
||
delete behavior.create;
|
||
behavior.stub = stub;
|
||
|
||
return behavior;
|
||
},
|
||
|
||
isPresent: function isPresent() {
|
||
return (typeof this.callArgAt == "number" ||
|
||
this.exception ||
|
||
typeof this.returnArgAt == "number" ||
|
||
this.returnThis ||
|
||
this.returnValueDefined);
|
||
},
|
||
|
||
invoke: function invoke(context, args) {
|
||
callCallback(this, args);
|
||
|
||
if (this.exception) {
|
||
throw this.exception;
|
||
} else if (typeof this.returnArgAt == "number") {
|
||
return args[this.returnArgAt];
|
||
} else if (this.returnThis) {
|
||
return context;
|
||
}
|
||
|
||
return this.returnValue;
|
||
},
|
||
|
||
onCall: function onCall(index) {
|
||
return this.stub.onCall(index);
|
||
},
|
||
|
||
onFirstCall: function onFirstCall() {
|
||
return this.stub.onFirstCall();
|
||
},
|
||
|
||
onSecondCall: function onSecondCall() {
|
||
return this.stub.onSecondCall();
|
||
},
|
||
|
||
onThirdCall: function onThirdCall() {
|
||
return this.stub.onThirdCall();
|
||
},
|
||
|
||
withArgs: function withArgs(/* arguments */) {
|
||
throw new Error("Defining a stub by invoking \"stub.onCall(...).withArgs(...)\" is not supported. " +
|
||
"Use \"stub.withArgs(...).onCall(...)\" to define sequential behavior for calls with certain arguments.");
|
||
},
|
||
|
||
callsArg: function callsArg(pos) {
|
||
if (typeof pos != "number") {
|
||
throw new TypeError("argument index is not number");
|
||
}
|
||
|
||
this.callArgAt = pos;
|
||
this.callbackArguments = [];
|
||
this.callbackContext = undefined;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
callsArgOn: function callsArgOn(pos, context) {
|
||
if (typeof pos != "number") {
|
||
throw new TypeError("argument index is not number");
|
||
}
|
||
if (typeof context != "object") {
|
||
throw new TypeError("argument context is not an object");
|
||
}
|
||
|
||
this.callArgAt = pos;
|
||
this.callbackArguments = [];
|
||
this.callbackContext = context;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
callsArgWith: function callsArgWith(pos) {
|
||
if (typeof pos != "number") {
|
||
throw new TypeError("argument index is not number");
|
||
}
|
||
|
||
this.callArgAt = pos;
|
||
this.callbackArguments = slice.call(arguments, 1);
|
||
this.callbackContext = undefined;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
callsArgOnWith: function callsArgWith(pos, context) {
|
||
if (typeof pos != "number") {
|
||
throw new TypeError("argument index is not number");
|
||
}
|
||
if (typeof context != "object") {
|
||
throw new TypeError("argument context is not an object");
|
||
}
|
||
|
||
this.callArgAt = pos;
|
||
this.callbackArguments = slice.call(arguments, 2);
|
||
this.callbackContext = context;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
yields: function () {
|
||
this.callArgAt = useLeftMostCallback;
|
||
this.callbackArguments = slice.call(arguments, 0);
|
||
this.callbackContext = undefined;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
yieldsRight: function () {
|
||
this.callArgAt = useRightMostCallback;
|
||
this.callbackArguments = slice.call(arguments, 0);
|
||
this.callbackContext = undefined;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
yieldsOn: function (context) {
|
||
if (typeof context != "object") {
|
||
throw new TypeError("argument context is not an object");
|
||
}
|
||
|
||
this.callArgAt = useLeftMostCallback;
|
||
this.callbackArguments = slice.call(arguments, 1);
|
||
this.callbackContext = context;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
yieldsTo: function (prop) {
|
||
this.callArgAt = useLeftMostCallback;
|
||
this.callbackArguments = slice.call(arguments, 1);
|
||
this.callbackContext = undefined;
|
||
this.callArgProp = prop;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
yieldsToOn: function (prop, context) {
|
||
if (typeof context != "object") {
|
||
throw new TypeError("argument context is not an object");
|
||
}
|
||
|
||
this.callArgAt = useLeftMostCallback;
|
||
this.callbackArguments = slice.call(arguments, 2);
|
||
this.callbackContext = context;
|
||
this.callArgProp = prop;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
throws: throwsException,
|
||
throwsException: throwsException,
|
||
|
||
returns: function returns(value) {
|
||
this.returnValue = value;
|
||
this.returnValueDefined = true;
|
||
|
||
return this;
|
||
},
|
||
|
||
returnsArg: function returnsArg(pos) {
|
||
if (typeof pos != "number") {
|
||
throw new TypeError("argument index is not number");
|
||
}
|
||
|
||
this.returnArgAt = pos;
|
||
|
||
return this;
|
||
},
|
||
|
||
returnsThis: function returnsThis() {
|
||
this.returnThis = true;
|
||
|
||
return this;
|
||
}
|
||
};
|
||
|
||
// create asynchronous versions of callsArg* and yields* methods
|
||
for (var method in proto) {
|
||
// need to avoid creating anotherasync versions of the newly added async methods
|
||
if (proto.hasOwnProperty(method) &&
|
||
method.match(/^(callsArg|yields)/) &&
|
||
!method.match(/Async/)) {
|
||
proto[method + "Async"] = (function (syncFnName) {
|
||
return function () {
|
||
var result = this[syncFnName].apply(this, arguments);
|
||
this.callbackAsync = true;
|
||
return result;
|
||
};
|
||
})(method);
|
||
}
|
||
}
|
||
|
||
sinon.behavior = proto;
|
||
return proto;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./extend");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
}).call(this,require("VCmEsw"))
|
||
},{"./extend":42,"./util/core":54,"VCmEsw":114}],40:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend match.js
|
||
* @depend format.js
|
||
*/
|
||
/**
|
||
* Spy calls
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @author Maximilian Antoni (mail@maxantoni.de)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
* Copyright (c) 2013 Maximilian Antoni
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
function throwYieldError(proxy, text, args) {
|
||
var msg = sinon.functionName(proxy) + text;
|
||
if (args.length) {
|
||
msg += " Received [" + slice.call(args).join(", ") + "]";
|
||
}
|
||
throw new Error(msg);
|
||
}
|
||
|
||
var slice = Array.prototype.slice;
|
||
|
||
var callProto = {
|
||
calledOn: function calledOn(thisValue) {
|
||
if (sinon.match && sinon.match.isMatcher(thisValue)) {
|
||
return thisValue.test(this.thisValue);
|
||
}
|
||
return this.thisValue === thisValue;
|
||
},
|
||
|
||
calledWith: function calledWith() {
|
||
var l = arguments.length;
|
||
if (l > this.args.length) {
|
||
return false;
|
||
}
|
||
for (var i = 0; i < l; i += 1) {
|
||
if (!sinon.deepEqual(arguments[i], this.args[i])) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
},
|
||
|
||
calledWithMatch: function calledWithMatch() {
|
||
var l = arguments.length;
|
||
if (l > this.args.length) {
|
||
return false;
|
||
}
|
||
for (var i = 0; i < l; i += 1) {
|
||
var actual = this.args[i];
|
||
var expectation = arguments[i];
|
||
if (!sinon.match || !sinon.match(expectation).test(actual)) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
},
|
||
|
||
calledWithExactly: function calledWithExactly() {
|
||
return arguments.length == this.args.length &&
|
||
this.calledWith.apply(this, arguments);
|
||
},
|
||
|
||
notCalledWith: function notCalledWith() {
|
||
return !this.calledWith.apply(this, arguments);
|
||
},
|
||
|
||
notCalledWithMatch: function notCalledWithMatch() {
|
||
return !this.calledWithMatch.apply(this, arguments);
|
||
},
|
||
|
||
returned: function returned(value) {
|
||
return sinon.deepEqual(value, this.returnValue);
|
||
},
|
||
|
||
threw: function threw(error) {
|
||
if (typeof error === "undefined" || !this.exception) {
|
||
return !!this.exception;
|
||
}
|
||
|
||
return this.exception === error || this.exception.name === error;
|
||
},
|
||
|
||
calledWithNew: function calledWithNew() {
|
||
return this.proxy.prototype && this.thisValue instanceof this.proxy;
|
||
},
|
||
|
||
calledBefore: function (other) {
|
||
return this.callId < other.callId;
|
||
},
|
||
|
||
calledAfter: function (other) {
|
||
return this.callId > other.callId;
|
||
},
|
||
|
||
callArg: function (pos) {
|
||
this.args[pos]();
|
||
},
|
||
|
||
callArgOn: function (pos, thisValue) {
|
||
this.args[pos].apply(thisValue);
|
||
},
|
||
|
||
callArgWith: function (pos) {
|
||
this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
|
||
},
|
||
|
||
callArgOnWith: function (pos, thisValue) {
|
||
var args = slice.call(arguments, 2);
|
||
this.args[pos].apply(thisValue, args);
|
||
},
|
||
|
||
yield: function () {
|
||
this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
|
||
},
|
||
|
||
yieldOn: function (thisValue) {
|
||
var args = this.args;
|
||
for (var i = 0, l = args.length; i < l; ++i) {
|
||
if (typeof args[i] === "function") {
|
||
args[i].apply(thisValue, slice.call(arguments, 1));
|
||
return;
|
||
}
|
||
}
|
||
throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
|
||
},
|
||
|
||
yieldTo: function (prop) {
|
||
this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
|
||
},
|
||
|
||
yieldToOn: function (prop, thisValue) {
|
||
var args = this.args;
|
||
for (var i = 0, l = args.length; i < l; ++i) {
|
||
if (args[i] && typeof args[i][prop] === "function") {
|
||
args[i][prop].apply(thisValue, slice.call(arguments, 2));
|
||
return;
|
||
}
|
||
}
|
||
throwYieldError(this.proxy, " cannot yield to '" + prop +
|
||
"' since no callback was passed.", args);
|
||
},
|
||
|
||
toString: function () {
|
||
var callStr = this.proxy.toString() + "(";
|
||
var args = [];
|
||
|
||
for (var i = 0, l = this.args.length; i < l; ++i) {
|
||
args.push(sinon.format(this.args[i]));
|
||
}
|
||
|
||
callStr = callStr + args.join(", ") + ")";
|
||
|
||
if (typeof this.returnValue != "undefined") {
|
||
callStr += " => " + sinon.format(this.returnValue);
|
||
}
|
||
|
||
if (this.exception) {
|
||
callStr += " !" + this.exception.name;
|
||
|
||
if (this.exception.message) {
|
||
callStr += "(" + this.exception.message + ")";
|
||
}
|
||
}
|
||
|
||
return callStr;
|
||
}
|
||
};
|
||
|
||
callProto.invokeCallback = callProto.yield;
|
||
|
||
function createSpyCall(spy, thisValue, args, returnValue, exception, id) {
|
||
if (typeof id !== "number") {
|
||
throw new TypeError("Call id is not a number");
|
||
}
|
||
var proxyCall = sinon.create(callProto);
|
||
proxyCall.proxy = spy;
|
||
proxyCall.thisValue = thisValue;
|
||
proxyCall.args = args;
|
||
proxyCall.returnValue = returnValue;
|
||
proxyCall.exception = exception;
|
||
proxyCall.callId = id;
|
||
|
||
return proxyCall;
|
||
}
|
||
createSpyCall.toString = callProto.toString; // used by mocks
|
||
|
||
sinon.spyCall = createSpyCall;
|
||
return createSpyCall;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./match");
|
||
require("./format");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./format":43,"./match":45,"./util/core":54}],41:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend spy.js
|
||
* @depend stub.js
|
||
* @depend mock.js
|
||
*/
|
||
/**
|
||
* Collections of stubs, spies and mocks.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
var push = [].push;
|
||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||
|
||
function getFakes(fakeCollection) {
|
||
if (!fakeCollection.fakes) {
|
||
fakeCollection.fakes = [];
|
||
}
|
||
|
||
return fakeCollection.fakes;
|
||
}
|
||
|
||
function each(fakeCollection, method) {
|
||
var fakes = getFakes(fakeCollection);
|
||
|
||
for (var i = 0, l = fakes.length; i < l; i += 1) {
|
||
if (typeof fakes[i][method] == "function") {
|
||
fakes[i][method]();
|
||
}
|
||
}
|
||
}
|
||
|
||
function compact(fakeCollection) {
|
||
var fakes = getFakes(fakeCollection);
|
||
var i = 0;
|
||
while (i < fakes.length) {
|
||
fakes.splice(i, 1);
|
||
}
|
||
}
|
||
|
||
function makeApi(sinon) {
|
||
var collection = {
|
||
verify: function resolve() {
|
||
each(this, "verify");
|
||
},
|
||
|
||
restore: function restore() {
|
||
each(this, "restore");
|
||
compact(this);
|
||
},
|
||
|
||
reset: function restore() {
|
||
each(this, "reset");
|
||
},
|
||
|
||
verifyAndRestore: function verifyAndRestore() {
|
||
var exception;
|
||
|
||
try {
|
||
this.verify();
|
||
} catch (e) {
|
||
exception = e;
|
||
}
|
||
|
||
this.restore();
|
||
|
||
if (exception) {
|
||
throw exception;
|
||
}
|
||
},
|
||
|
||
add: function add(fake) {
|
||
push.call(getFakes(this), fake);
|
||
return fake;
|
||
},
|
||
|
||
spy: function spy() {
|
||
return this.add(sinon.spy.apply(sinon, arguments));
|
||
},
|
||
|
||
stub: function stub(object, property, value) {
|
||
if (property) {
|
||
var original = object[property];
|
||
|
||
if (typeof original != "function") {
|
||
if (!hasOwnProperty.call(object, property)) {
|
||
throw new TypeError("Cannot stub non-existent own property " + property);
|
||
}
|
||
|
||
object[property] = value;
|
||
|
||
return this.add({
|
||
restore: function () {
|
||
object[property] = original;
|
||
}
|
||
});
|
||
}
|
||
}
|
||
if (!property && !!object && typeof object == "object") {
|
||
var stubbedObj = sinon.stub.apply(sinon, arguments);
|
||
|
||
for (var prop in stubbedObj) {
|
||
if (typeof stubbedObj[prop] === "function") {
|
||
this.add(stubbedObj[prop]);
|
||
}
|
||
}
|
||
|
||
return stubbedObj;
|
||
}
|
||
|
||
return this.add(sinon.stub.apply(sinon, arguments));
|
||
},
|
||
|
||
mock: function mock() {
|
||
return this.add(sinon.mock.apply(sinon, arguments));
|
||
},
|
||
|
||
inject: function inject(obj) {
|
||
var col = this;
|
||
|
||
obj.spy = function () {
|
||
return col.spy.apply(col, arguments);
|
||
};
|
||
|
||
obj.stub = function () {
|
||
return col.stub.apply(col, arguments);
|
||
};
|
||
|
||
obj.mock = function () {
|
||
return col.mock.apply(col, arguments);
|
||
};
|
||
|
||
return obj;
|
||
}
|
||
};
|
||
|
||
sinon.collection = collection;
|
||
return collection;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./mock");
|
||
require("./spy");
|
||
require("./stub");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./mock":46,"./spy":48,"./stub":49,"./util/core":54}],42:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
|
||
// Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
|
||
var hasDontEnumBug = (function () {
|
||
var obj = {
|
||
constructor: function () {
|
||
return "0";
|
||
},
|
||
toString: function () {
|
||
return "1";
|
||
},
|
||
valueOf: function () {
|
||
return "2";
|
||
},
|
||
toLocaleString: function () {
|
||
return "3";
|
||
},
|
||
prototype: function () {
|
||
return "4";
|
||
},
|
||
isPrototypeOf: function () {
|
||
return "5";
|
||
},
|
||
propertyIsEnumerable: function () {
|
||
return "6";
|
||
},
|
||
hasOwnProperty: function () {
|
||
return "7";
|
||
},
|
||
length: function () {
|
||
return "8";
|
||
},
|
||
unique: function () {
|
||
return "9"
|
||
}
|
||
};
|
||
|
||
var result = [];
|
||
for (var prop in obj) {
|
||
result.push(obj[prop]());
|
||
}
|
||
return result.join("") !== "0123456789";
|
||
})();
|
||
|
||
/* Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will
|
||
* override properties in previous sources.
|
||
*
|
||
* target - The Object to extend
|
||
* sources - Objects to copy properties from.
|
||
*
|
||
* Returns the extended target
|
||
*/
|
||
function extend(target /*, sources */) {
|
||
var sources = Array.prototype.slice.call(arguments, 1),
|
||
source, i, prop;
|
||
|
||
for (i = 0; i < sources.length; i++) {
|
||
source = sources[i];
|
||
|
||
for (prop in source) {
|
||
if (source.hasOwnProperty(prop)) {
|
||
target[prop] = source[prop];
|
||
}
|
||
}
|
||
|
||
// Make sure we copy (own) toString method even when in JScript with DontEnum bug
|
||
// See https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
|
||
if (hasDontEnumBug && source.hasOwnProperty("toString") && source.toString !== target.toString) {
|
||
target.toString = source.toString;
|
||
}
|
||
}
|
||
|
||
return target;
|
||
};
|
||
|
||
sinon.extend = extend;
|
||
return sinon.extend;
|
||
}
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./util/core":54}],43:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
*/
|
||
/**
|
||
* Format functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2014 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon, formatio) {
|
||
function makeApi(sinon) {
|
||
function valueFormatter(value) {
|
||
return "" + value;
|
||
}
|
||
|
||
function getFormatioFormatter() {
|
||
var formatter = formatio.configure({
|
||
quoteStrings: false,
|
||
limitChildrenCount: 250
|
||
});
|
||
|
||
function format() {
|
||
return formatter.ascii.apply(formatter, arguments);
|
||
};
|
||
|
||
return format;
|
||
}
|
||
|
||
function getNodeFormatter(value) {
|
||
function format(value) {
|
||
return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
|
||
};
|
||
|
||
try {
|
||
var util = require("util");
|
||
} catch (e) {
|
||
/* Node, but no util module - would be very old, but better safe than sorry */
|
||
}
|
||
|
||
return util ? format : valueFormatter;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function",
|
||
formatter;
|
||
|
||
if (isNode) {
|
||
try {
|
||
formatio = require("formatio");
|
||
} catch (e) {}
|
||
}
|
||
|
||
if (formatio) {
|
||
formatter = getFormatioFormatter()
|
||
} else if (isNode) {
|
||
formatter = getNodeFormatter();
|
||
} else {
|
||
formatter = valueFormatter;
|
||
}
|
||
|
||
sinon.format = formatter;
|
||
return sinon.format;
|
||
}
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(
|
||
(typeof sinon == "object" && sinon || null),
|
||
(typeof formatio == "object" && formatio)
|
||
));
|
||
|
||
},{"./util/core":54,"formatio":61,"util":116}],44:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
*/
|
||
/**
|
||
* Logs errors
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2014 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
// cache a reference to setTimeout, so that our reference won't be stubbed out
|
||
// when using fake timers and errors will still get logged
|
||
// https://github.com/cjohansen/Sinon.JS/issues/381
|
||
var realSetTimeout = setTimeout;
|
||
|
||
function makeApi(sinon) {
|
||
|
||
function log() {}
|
||
|
||
function logError(label, err) {
|
||
var msg = label + " threw exception: ";
|
||
|
||
sinon.log(msg + "[" + err.name + "] " + err.message);
|
||
|
||
if (err.stack) {
|
||
sinon.log(err.stack);
|
||
}
|
||
|
||
logError.setTimeout(function () {
|
||
err.message = msg + err.message;
|
||
throw err;
|
||
}, 0);
|
||
};
|
||
|
||
// wrap realSetTimeout with something we can stub in tests
|
||
logError.setTimeout = function (func, timeout) {
|
||
realSetTimeout(func, timeout);
|
||
}
|
||
|
||
var exports = {};
|
||
exports.log = sinon.log = log;
|
||
exports.logError = sinon.logError = logError;
|
||
|
||
return exports;
|
||
}
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./util/core":54}],45:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend typeOf.js
|
||
*/
|
||
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
|
||
/*global module, require, sinon*/
|
||
/**
|
||
* Match functions
|
||
*
|
||
* @author Maximilian Antoni (mail@maxantoni.de)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2012 Maximilian Antoni
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
function assertType(value, type, name) {
|
||
var actual = sinon.typeOf(value);
|
||
if (actual !== type) {
|
||
throw new TypeError("Expected type of " + name + " to be " +
|
||
type + ", but was " + actual);
|
||
}
|
||
}
|
||
|
||
var matcher = {
|
||
toString: function () {
|
||
return this.message;
|
||
}
|
||
};
|
||
|
||
function isMatcher(object) {
|
||
return matcher.isPrototypeOf(object);
|
||
}
|
||
|
||
function matchObject(expectation, actual) {
|
||
if (actual === null || actual === undefined) {
|
||
return false;
|
||
}
|
||
for (var key in expectation) {
|
||
if (expectation.hasOwnProperty(key)) {
|
||
var exp = expectation[key];
|
||
var act = actual[key];
|
||
if (match.isMatcher(exp)) {
|
||
if (!exp.test(act)) {
|
||
return false;
|
||
}
|
||
} else if (sinon.typeOf(exp) === "object") {
|
||
if (!matchObject(exp, act)) {
|
||
return false;
|
||
}
|
||
} else if (!sinon.deepEqual(exp, act)) {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
matcher.or = function (m2) {
|
||
if (!arguments.length) {
|
||
throw new TypeError("Matcher expected");
|
||
} else if (!isMatcher(m2)) {
|
||
m2 = match(m2);
|
||
}
|
||
var m1 = this;
|
||
var or = sinon.create(matcher);
|
||
or.test = function (actual) {
|
||
return m1.test(actual) || m2.test(actual);
|
||
};
|
||
or.message = m1.message + ".or(" + m2.message + ")";
|
||
return or;
|
||
};
|
||
|
||
matcher.and = function (m2) {
|
||
if (!arguments.length) {
|
||
throw new TypeError("Matcher expected");
|
||
} else if (!isMatcher(m2)) {
|
||
m2 = match(m2);
|
||
}
|
||
var m1 = this;
|
||
var and = sinon.create(matcher);
|
||
and.test = function (actual) {
|
||
return m1.test(actual) && m2.test(actual);
|
||
};
|
||
and.message = m1.message + ".and(" + m2.message + ")";
|
||
return and;
|
||
};
|
||
|
||
var match = function (expectation, message) {
|
||
var m = sinon.create(matcher);
|
||
var type = sinon.typeOf(expectation);
|
||
switch (type) {
|
||
case "object":
|
||
if (typeof expectation.test === "function") {
|
||
m.test = function (actual) {
|
||
return expectation.test(actual) === true;
|
||
};
|
||
m.message = "match(" + sinon.functionName(expectation.test) + ")";
|
||
return m;
|
||
}
|
||
var str = [];
|
||
for (var key in expectation) {
|
||
if (expectation.hasOwnProperty(key)) {
|
||
str.push(key + ": " + expectation[key]);
|
||
}
|
||
}
|
||
m.test = function (actual) {
|
||
return matchObject(expectation, actual);
|
||
};
|
||
m.message = "match(" + str.join(", ") + ")";
|
||
break;
|
||
case "number":
|
||
m.test = function (actual) {
|
||
return expectation == actual;
|
||
};
|
||
break;
|
||
case "string":
|
||
m.test = function (actual) {
|
||
if (typeof actual !== "string") {
|
||
return false;
|
||
}
|
||
return actual.indexOf(expectation) !== -1;
|
||
};
|
||
m.message = "match(\"" + expectation + "\")";
|
||
break;
|
||
case "regexp":
|
||
m.test = function (actual) {
|
||
if (typeof actual !== "string") {
|
||
return false;
|
||
}
|
||
return expectation.test(actual);
|
||
};
|
||
break;
|
||
case "function":
|
||
m.test = expectation;
|
||
if (message) {
|
||
m.message = message;
|
||
} else {
|
||
m.message = "match(" + sinon.functionName(expectation) + ")";
|
||
}
|
||
break;
|
||
default:
|
||
m.test = function (actual) {
|
||
return sinon.deepEqual(expectation, actual);
|
||
};
|
||
}
|
||
if (!m.message) {
|
||
m.message = "match(" + expectation + ")";
|
||
}
|
||
return m;
|
||
};
|
||
|
||
match.isMatcher = isMatcher;
|
||
|
||
match.any = match(function () {
|
||
return true;
|
||
}, "any");
|
||
|
||
match.defined = match(function (actual) {
|
||
return actual !== null && actual !== undefined;
|
||
}, "defined");
|
||
|
||
match.truthy = match(function (actual) {
|
||
return !!actual;
|
||
}, "truthy");
|
||
|
||
match.falsy = match(function (actual) {
|
||
return !actual;
|
||
}, "falsy");
|
||
|
||
match.same = function (expectation) {
|
||
return match(function (actual) {
|
||
return expectation === actual;
|
||
}, "same(" + expectation + ")");
|
||
};
|
||
|
||
match.typeOf = function (type) {
|
||
assertType(type, "string", "type");
|
||
return match(function (actual) {
|
||
return sinon.typeOf(actual) === type;
|
||
}, "typeOf(\"" + type + "\")");
|
||
};
|
||
|
||
match.instanceOf = function (type) {
|
||
assertType(type, "function", "type");
|
||
return match(function (actual) {
|
||
return actual instanceof type;
|
||
}, "instanceOf(" + sinon.functionName(type) + ")");
|
||
};
|
||
|
||
function createPropertyMatcher(propertyTest, messagePrefix) {
|
||
return function (property, value) {
|
||
assertType(property, "string", "property");
|
||
var onlyProperty = arguments.length === 1;
|
||
var message = messagePrefix + "(\"" + property + "\"";
|
||
if (!onlyProperty) {
|
||
message += ", " + value;
|
||
}
|
||
message += ")";
|
||
return match(function (actual) {
|
||
if (actual === undefined || actual === null ||
|
||
!propertyTest(actual, property)) {
|
||
return false;
|
||
}
|
||
return onlyProperty || sinon.deepEqual(value, actual[property]);
|
||
}, message);
|
||
};
|
||
}
|
||
|
||
match.has = createPropertyMatcher(function (actual, property) {
|
||
if (typeof actual === "object") {
|
||
return property in actual;
|
||
}
|
||
return actual[property] !== undefined;
|
||
}, "has");
|
||
|
||
match.hasOwn = createPropertyMatcher(function (actual, property) {
|
||
return actual.hasOwnProperty(property);
|
||
}, "hasOwn");
|
||
|
||
match.bool = match.typeOf("boolean");
|
||
match.number = match.typeOf("number");
|
||
match.string = match.typeOf("string");
|
||
match.object = match.typeOf("object");
|
||
match.func = match.typeOf("function");
|
||
match.array = match.typeOf("array");
|
||
match.regexp = match.typeOf("regexp");
|
||
match.date = match.typeOf("date");
|
||
|
||
sinon.match = match;
|
||
return match;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./typeOf");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./typeOf":53,"./util/core":54}],46:[function(require,module,exports){
|
||
/**
|
||
* @depend times_in_words.js
|
||
* @depend util/core.js
|
||
* @depend call.js
|
||
* @depend extend.js
|
||
* @depend match.js
|
||
* @depend spy.js
|
||
* @depend stub.js
|
||
* @depend format.js
|
||
*/
|
||
/**
|
||
* Mock functions.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
var push = [].push;
|
||
var match = sinon.match;
|
||
|
||
function mock(object) {
|
||
if (!object) {
|
||
return sinon.expectation.create("Anonymous mock");
|
||
}
|
||
|
||
return mock.create(object);
|
||
}
|
||
|
||
function each(collection, callback) {
|
||
if (!collection) {
|
||
return;
|
||
}
|
||
|
||
for (var i = 0, l = collection.length; i < l; i += 1) {
|
||
callback(collection[i]);
|
||
}
|
||
}
|
||
|
||
sinon.extend(mock, {
|
||
create: function create(object) {
|
||
if (!object) {
|
||
throw new TypeError("object is null");
|
||
}
|
||
|
||
var mockObject = sinon.extend({}, mock);
|
||
mockObject.object = object;
|
||
delete mockObject.create;
|
||
|
||
return mockObject;
|
||
},
|
||
|
||
expects: function expects(method) {
|
||
if (!method) {
|
||
throw new TypeError("method is falsy");
|
||
}
|
||
|
||
if (!this.expectations) {
|
||
this.expectations = {};
|
||
this.proxies = [];
|
||
}
|
||
|
||
if (!this.expectations[method]) {
|
||
this.expectations[method] = [];
|
||
var mockObject = this;
|
||
|
||
sinon.wrapMethod(this.object, method, function () {
|
||
return mockObject.invokeMethod(method, this, arguments);
|
||
});
|
||
|
||
push.call(this.proxies, method);
|
||
}
|
||
|
||
var expectation = sinon.expectation.create(method);
|
||
push.call(this.expectations[method], expectation);
|
||
|
||
return expectation;
|
||
},
|
||
|
||
restore: function restore() {
|
||
var object = this.object;
|
||
|
||
each(this.proxies, function (proxy) {
|
||
if (typeof object[proxy].restore == "function") {
|
||
object[proxy].restore();
|
||
}
|
||
});
|
||
},
|
||
|
||
verify: function verify() {
|
||
var expectations = this.expectations || {};
|
||
var messages = [], met = [];
|
||
|
||
each(this.proxies, function (proxy) {
|
||
each(expectations[proxy], function (expectation) {
|
||
if (!expectation.met()) {
|
||
push.call(messages, expectation.toString());
|
||
} else {
|
||
push.call(met, expectation.toString());
|
||
}
|
||
});
|
||
});
|
||
|
||
this.restore();
|
||
|
||
if (messages.length > 0) {
|
||
sinon.expectation.fail(messages.concat(met).join("\n"));
|
||
} else if (met.length > 0) {
|
||
sinon.expectation.pass(messages.concat(met).join("\n"));
|
||
}
|
||
|
||
return true;
|
||
},
|
||
|
||
invokeMethod: function invokeMethod(method, thisValue, args) {
|
||
var expectations = this.expectations && this.expectations[method];
|
||
var length = expectations && expectations.length || 0, i;
|
||
|
||
for (i = 0; i < length; i += 1) {
|
||
if (!expectations[i].met() &&
|
||
expectations[i].allowsCall(thisValue, args)) {
|
||
return expectations[i].apply(thisValue, args);
|
||
}
|
||
}
|
||
|
||
var messages = [], available, exhausted = 0;
|
||
|
||
for (i = 0; i < length; i += 1) {
|
||
if (expectations[i].allowsCall(thisValue, args)) {
|
||
available = available || expectations[i];
|
||
} else {
|
||
exhausted += 1;
|
||
}
|
||
push.call(messages, " " + expectations[i].toString());
|
||
}
|
||
|
||
if (exhausted === 0) {
|
||
return available.apply(thisValue, args);
|
||
}
|
||
|
||
messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
|
||
proxy: method,
|
||
args: args
|
||
}));
|
||
|
||
sinon.expectation.fail(messages.join("\n"));
|
||
}
|
||
});
|
||
|
||
var times = sinon.timesInWords;
|
||
var slice = Array.prototype.slice;
|
||
|
||
function callCountInWords(callCount) {
|
||
if (callCount == 0) {
|
||
return "never called";
|
||
} else {
|
||
return "called " + times(callCount);
|
||
}
|
||
}
|
||
|
||
function expectedCallCountInWords(expectation) {
|
||
var min = expectation.minCalls;
|
||
var max = expectation.maxCalls;
|
||
|
||
if (typeof min == "number" && typeof max == "number") {
|
||
var str = times(min);
|
||
|
||
if (min != max) {
|
||
str = "at least " + str + " and at most " + times(max);
|
||
}
|
||
|
||
return str;
|
||
}
|
||
|
||
if (typeof min == "number") {
|
||
return "at least " + times(min);
|
||
}
|
||
|
||
return "at most " + times(max);
|
||
}
|
||
|
||
function receivedMinCalls(expectation) {
|
||
var hasMinLimit = typeof expectation.minCalls == "number";
|
||
return !hasMinLimit || expectation.callCount >= expectation.minCalls;
|
||
}
|
||
|
||
function receivedMaxCalls(expectation) {
|
||
if (typeof expectation.maxCalls != "number") {
|
||
return false;
|
||
}
|
||
|
||
return expectation.callCount == expectation.maxCalls;
|
||
}
|
||
|
||
function verifyMatcher(possibleMatcher, arg) {
|
||
if (match && match.isMatcher(possibleMatcher)) {
|
||
return possibleMatcher.test(arg);
|
||
} else {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
sinon.expectation = {
|
||
minCalls: 1,
|
||
maxCalls: 1,
|
||
|
||
create: function create(methodName) {
|
||
var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
|
||
delete expectation.create;
|
||
expectation.method = methodName;
|
||
|
||
return expectation;
|
||
},
|
||
|
||
invoke: function invoke(func, thisValue, args) {
|
||
this.verifyCallAllowed(thisValue, args);
|
||
|
||
return sinon.spy.invoke.apply(this, arguments);
|
||
},
|
||
|
||
atLeast: function atLeast(num) {
|
||
if (typeof num != "number") {
|
||
throw new TypeError("'" + num + "' is not number");
|
||
}
|
||
|
||
if (!this.limitsSet) {
|
||
this.maxCalls = null;
|
||
this.limitsSet = true;
|
||
}
|
||
|
||
this.minCalls = num;
|
||
|
||
return this;
|
||
},
|
||
|
||
atMost: function atMost(num) {
|
||
if (typeof num != "number") {
|
||
throw new TypeError("'" + num + "' is not number");
|
||
}
|
||
|
||
if (!this.limitsSet) {
|
||
this.minCalls = null;
|
||
this.limitsSet = true;
|
||
}
|
||
|
||
this.maxCalls = num;
|
||
|
||
return this;
|
||
},
|
||
|
||
never: function never() {
|
||
return this.exactly(0);
|
||
},
|
||
|
||
once: function once() {
|
||
return this.exactly(1);
|
||
},
|
||
|
||
twice: function twice() {
|
||
return this.exactly(2);
|
||
},
|
||
|
||
thrice: function thrice() {
|
||
return this.exactly(3);
|
||
},
|
||
|
||
exactly: function exactly(num) {
|
||
if (typeof num != "number") {
|
||
throw new TypeError("'" + num + "' is not a number");
|
||
}
|
||
|
||
this.atLeast(num);
|
||
return this.atMost(num);
|
||
},
|
||
|
||
met: function met() {
|
||
return !this.failed && receivedMinCalls(this);
|
||
},
|
||
|
||
verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
|
||
if (receivedMaxCalls(this)) {
|
||
this.failed = true;
|
||
sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
|
||
}
|
||
|
||
if ("expectedThis" in this && this.expectedThis !== thisValue) {
|
||
sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
|
||
this.expectedThis);
|
||
}
|
||
|
||
if (!("expectedArguments" in this)) {
|
||
return;
|
||
}
|
||
|
||
if (!args) {
|
||
sinon.expectation.fail(this.method + " received no arguments, expected " +
|
||
sinon.format(this.expectedArguments));
|
||
}
|
||
|
||
if (args.length < this.expectedArguments.length) {
|
||
sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
|
||
"), expected " + sinon.format(this.expectedArguments));
|
||
}
|
||
|
||
if (this.expectsExactArgCount &&
|
||
args.length != this.expectedArguments.length) {
|
||
sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
|
||
"), expected " + sinon.format(this.expectedArguments));
|
||
}
|
||
|
||
for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
|
||
|
||
if (!verifyMatcher(this.expectedArguments[i], args[i])) {
|
||
sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
|
||
", didn't match " + this.expectedArguments.toString());
|
||
}
|
||
|
||
if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
|
||
sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
|
||
", expected " + sinon.format(this.expectedArguments));
|
||
}
|
||
}
|
||
},
|
||
|
||
allowsCall: function allowsCall(thisValue, args) {
|
||
if (this.met() && receivedMaxCalls(this)) {
|
||
return false;
|
||
}
|
||
|
||
if ("expectedThis" in this && this.expectedThis !== thisValue) {
|
||
return false;
|
||
}
|
||
|
||
if (!("expectedArguments" in this)) {
|
||
return true;
|
||
}
|
||
|
||
args = args || [];
|
||
|
||
if (args.length < this.expectedArguments.length) {
|
||
return false;
|
||
}
|
||
|
||
if (this.expectsExactArgCount &&
|
||
args.length != this.expectedArguments.length) {
|
||
return false;
|
||
}
|
||
|
||
for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
|
||
if (!verifyMatcher(this.expectedArguments[i], args[i])) {
|
||
return false;
|
||
}
|
||
|
||
if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
},
|
||
|
||
withArgs: function withArgs() {
|
||
this.expectedArguments = slice.call(arguments);
|
||
return this;
|
||
},
|
||
|
||
withExactArgs: function withExactArgs() {
|
||
this.withArgs.apply(this, arguments);
|
||
this.expectsExactArgCount = true;
|
||
return this;
|
||
},
|
||
|
||
on: function on(thisValue) {
|
||
this.expectedThis = thisValue;
|
||
return this;
|
||
},
|
||
|
||
toString: function () {
|
||
var args = (this.expectedArguments || []).slice();
|
||
|
||
if (!this.expectsExactArgCount) {
|
||
push.call(args, "[...]");
|
||
}
|
||
|
||
var callStr = sinon.spyCall.toString.call({
|
||
proxy: this.method || "anonymous mock expectation",
|
||
args: args
|
||
});
|
||
|
||
var message = callStr.replace(", [...", "[, ...") + " " +
|
||
expectedCallCountInWords(this);
|
||
|
||
if (this.met()) {
|
||
return "Expectation met: " + message;
|
||
}
|
||
|
||
return "Expected " + message + " (" +
|
||
callCountInWords(this.callCount) + ")";
|
||
},
|
||
|
||
verify: function verify() {
|
||
if (!this.met()) {
|
||
sinon.expectation.fail(this.toString());
|
||
} else {
|
||
sinon.expectation.pass(this.toString());
|
||
}
|
||
|
||
return true;
|
||
},
|
||
|
||
pass: function pass(message) {
|
||
sinon.assert.pass(message);
|
||
},
|
||
|
||
fail: function fail(message) {
|
||
var exception = new Error(message);
|
||
exception.name = "ExpectationError";
|
||
|
||
throw exception;
|
||
}
|
||
};
|
||
|
||
sinon.mock = mock;
|
||
return mock;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./times_in_words");
|
||
require("./call");
|
||
require("./extend");
|
||
require("./match");
|
||
require("./spy");
|
||
require("./stub");
|
||
require("./format");
|
||
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./call":40,"./extend":42,"./format":43,"./match":45,"./spy":48,"./stub":49,"./times_in_words":52,"./util/core":54}],47:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend extend.js
|
||
* @depend collection.js
|
||
* @depend util/fake_timers.js
|
||
* @depend util/fake_server_with_clock.js
|
||
*/
|
||
/**
|
||
* Manages fake collections as well as fake utilities such as Sinon's
|
||
* timers and fake XHR implementation in one convenient object.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function () {
|
||
function makeApi(sinon) {
|
||
var push = [].push;
|
||
|
||
function exposeValue(sandbox, config, key, value) {
|
||
if (!value) {
|
||
return;
|
||
}
|
||
|
||
if (config.injectInto && !(key in config.injectInto)) {
|
||
config.injectInto[key] = value;
|
||
sandbox.injectedKeys.push(key);
|
||
} else {
|
||
push.call(sandbox.args, value);
|
||
}
|
||
}
|
||
|
||
function prepareSandboxFromConfig(config) {
|
||
var sandbox = sinon.create(sinon.sandbox);
|
||
|
||
if (config.useFakeServer) {
|
||
if (typeof config.useFakeServer == "object") {
|
||
sandbox.serverPrototype = config.useFakeServer;
|
||
}
|
||
|
||
sandbox.useFakeServer();
|
||
}
|
||
|
||
if (config.useFakeTimers) {
|
||
if (typeof config.useFakeTimers == "object") {
|
||
sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
|
||
} else {
|
||
sandbox.useFakeTimers();
|
||
}
|
||
}
|
||
|
||
return sandbox;
|
||
}
|
||
|
||
sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
|
||
useFakeTimers: function useFakeTimers() {
|
||
this.clock = sinon.useFakeTimers.apply(sinon, arguments);
|
||
|
||
return this.add(this.clock);
|
||
},
|
||
|
||
serverPrototype: sinon.fakeServer,
|
||
|
||
useFakeServer: function useFakeServer() {
|
||
var proto = this.serverPrototype || sinon.fakeServer;
|
||
|
||
if (!proto || !proto.create) {
|
||
return null;
|
||
}
|
||
|
||
this.server = proto.create();
|
||
return this.add(this.server);
|
||
},
|
||
|
||
inject: function (obj) {
|
||
sinon.collection.inject.call(this, obj);
|
||
|
||
if (this.clock) {
|
||
obj.clock = this.clock;
|
||
}
|
||
|
||
if (this.server) {
|
||
obj.server = this.server;
|
||
obj.requests = this.server.requests;
|
||
}
|
||
|
||
obj.match = sinon.match;
|
||
|
||
return obj;
|
||
},
|
||
|
||
restore: function () {
|
||
sinon.collection.restore.apply(this, arguments);
|
||
this.restoreContext();
|
||
},
|
||
|
||
restoreContext: function () {
|
||
if (this.injectedKeys) {
|
||
for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
|
||
delete this.injectInto[this.injectedKeys[i]];
|
||
}
|
||
this.injectedKeys = [];
|
||
}
|
||
},
|
||
|
||
create: function (config) {
|
||
if (!config) {
|
||
return sinon.create(sinon.sandbox);
|
||
}
|
||
|
||
var sandbox = prepareSandboxFromConfig(config);
|
||
sandbox.args = sandbox.args || [];
|
||
sandbox.injectedKeys = [];
|
||
sandbox.injectInto = config.injectInto;
|
||
var prop, value, exposed = sandbox.inject({});
|
||
|
||
if (config.properties) {
|
||
for (var i = 0, l = config.properties.length; i < l; i++) {
|
||
prop = config.properties[i];
|
||
value = exposed[prop] || prop == "sandbox" && sandbox;
|
||
exposeValue(sandbox, config, prop, value);
|
||
}
|
||
} else {
|
||
exposeValue(sandbox, config, "sandbox", value);
|
||
}
|
||
|
||
return sandbox;
|
||
},
|
||
|
||
match: sinon.match
|
||
});
|
||
|
||
sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
|
||
|
||
return sinon.sandbox;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./extend");
|
||
require("./util/fake_server_with_clock");
|
||
require("./util/fake_timers");
|
||
require("./collection");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}());
|
||
|
||
},{"./collection":41,"./extend":42,"./util/core":54,"./util/fake_server_with_clock":57,"./util/fake_timers":58}],48:[function(require,module,exports){
|
||
/**
|
||
* @depend times_in_words.js
|
||
* @depend util/core.js
|
||
* @depend extend.js
|
||
* @depend call.js
|
||
* @depend format.js
|
||
*/
|
||
/**
|
||
* Spy functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
|
||
function makeApi(sinon) {
|
||
var push = Array.prototype.push;
|
||
var slice = Array.prototype.slice;
|
||
var callId = 0;
|
||
|
||
function spy(object, property, types) {
|
||
if (!property && typeof object == "function") {
|
||
return spy.create(object);
|
||
}
|
||
|
||
if (!object && !property) {
|
||
return spy.create(function () { });
|
||
}
|
||
|
||
if (types) {
|
||
var methodDesc = sinon.getPropertyDescriptor(object, property);
|
||
for (var i = 0; i < types.length; i++) {
|
||
methodDesc[types[i]] = spy.create(methodDesc[types[i]]);
|
||
}
|
||
return sinon.wrapMethod(object, property, methodDesc);
|
||
} else {
|
||
var method = object[property];
|
||
return sinon.wrapMethod(object, property, spy.create(method));
|
||
}
|
||
}
|
||
|
||
function matchingFake(fakes, args, strict) {
|
||
if (!fakes) {
|
||
return;
|
||
}
|
||
|
||
for (var i = 0, l = fakes.length; i < l; i++) {
|
||
if (fakes[i].matches(args, strict)) {
|
||
return fakes[i];
|
||
}
|
||
}
|
||
}
|
||
|
||
function incrementCallCount() {
|
||
this.called = true;
|
||
this.callCount += 1;
|
||
this.notCalled = false;
|
||
this.calledOnce = this.callCount == 1;
|
||
this.calledTwice = this.callCount == 2;
|
||
this.calledThrice = this.callCount == 3;
|
||
}
|
||
|
||
function createCallProperties() {
|
||
this.firstCall = this.getCall(0);
|
||
this.secondCall = this.getCall(1);
|
||
this.thirdCall = this.getCall(2);
|
||
this.lastCall = this.getCall(this.callCount - 1);
|
||
}
|
||
|
||
var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
|
||
function createProxy(func, proxyLength) {
|
||
// Retain the function length:
|
||
var p;
|
||
if (proxyLength) {
|
||
eval("p = (function proxy(" + vars.substring(0, proxyLength * 2 - 1) +
|
||
") { return p.invoke(func, this, slice.call(arguments)); });");
|
||
} else {
|
||
p = function proxy() {
|
||
return p.invoke(func, this, slice.call(arguments));
|
||
};
|
||
}
|
||
return p;
|
||
}
|
||
|
||
var uuid = 0;
|
||
|
||
// Public API
|
||
var spyApi = {
|
||
reset: function () {
|
||
if (this.invoking) {
|
||
var err = new Error("Cannot reset Sinon function while invoking it. " +
|
||
"Move the call to .reset outside of the callback.");
|
||
err.name = "InvalidResetException";
|
||
throw err;
|
||
}
|
||
|
||
this.called = false;
|
||
this.notCalled = true;
|
||
this.calledOnce = false;
|
||
this.calledTwice = false;
|
||
this.calledThrice = false;
|
||
this.callCount = 0;
|
||
this.firstCall = null;
|
||
this.secondCall = null;
|
||
this.thirdCall = null;
|
||
this.lastCall = null;
|
||
this.args = [];
|
||
this.returnValues = [];
|
||
this.thisValues = [];
|
||
this.exceptions = [];
|
||
this.callIds = [];
|
||
if (this.fakes) {
|
||
for (var i = 0; i < this.fakes.length; i++) {
|
||
this.fakes[i].reset();
|
||
}
|
||
}
|
||
|
||
return this;
|
||
},
|
||
|
||
create: function create(func, spyLength) {
|
||
var name;
|
||
|
||
if (typeof func != "function") {
|
||
func = function () { };
|
||
} else {
|
||
name = sinon.functionName(func);
|
||
}
|
||
|
||
if (!spyLength) {
|
||
spyLength = func.length;
|
||
}
|
||
|
||
var proxy = createProxy(func, spyLength);
|
||
|
||
sinon.extend(proxy, spy);
|
||
delete proxy.create;
|
||
sinon.extend(proxy, func);
|
||
|
||
proxy.reset();
|
||
proxy.prototype = func.prototype;
|
||
proxy.displayName = name || "spy";
|
||
proxy.toString = sinon.functionToString;
|
||
proxy.instantiateFake = sinon.spy.create;
|
||
proxy.id = "spy#" + uuid++;
|
||
|
||
return proxy;
|
||
},
|
||
|
||
invoke: function invoke(func, thisValue, args) {
|
||
var matching = matchingFake(this.fakes, args);
|
||
var exception, returnValue;
|
||
|
||
incrementCallCount.call(this);
|
||
push.call(this.thisValues, thisValue);
|
||
push.call(this.args, args);
|
||
push.call(this.callIds, callId++);
|
||
|
||
// Make call properties available from within the spied function:
|
||
createCallProperties.call(this);
|
||
|
||
try {
|
||
this.invoking = true;
|
||
|
||
if (matching) {
|
||
returnValue = matching.invoke(func, thisValue, args);
|
||
} else {
|
||
returnValue = (this.func || func).apply(thisValue, args);
|
||
}
|
||
|
||
var thisCall = this.getCall(this.callCount - 1);
|
||
if (thisCall.calledWithNew() && typeof returnValue !== "object") {
|
||
returnValue = thisValue;
|
||
}
|
||
} catch (e) {
|
||
exception = e;
|
||
} finally {
|
||
delete this.invoking;
|
||
}
|
||
|
||
push.call(this.exceptions, exception);
|
||
push.call(this.returnValues, returnValue);
|
||
|
||
// Make return value and exception available in the calls:
|
||
createCallProperties.call(this);
|
||
|
||
if (exception !== undefined) {
|
||
throw exception;
|
||
}
|
||
|
||
return returnValue;
|
||
},
|
||
|
||
named: function named(name) {
|
||
this.displayName = name;
|
||
return this;
|
||
},
|
||
|
||
getCall: function getCall(i) {
|
||
if (i < 0 || i >= this.callCount) {
|
||
return null;
|
||
}
|
||
|
||
return sinon.spyCall(this, this.thisValues[i], this.args[i],
|
||
this.returnValues[i], this.exceptions[i],
|
||
this.callIds[i]);
|
||
},
|
||
|
||
getCalls: function () {
|
||
var calls = [];
|
||
var i;
|
||
|
||
for (i = 0; i < this.callCount; i++) {
|
||
calls.push(this.getCall(i));
|
||
}
|
||
|
||
return calls;
|
||
},
|
||
|
||
calledBefore: function calledBefore(spyFn) {
|
||
if (!this.called) {
|
||
return false;
|
||
}
|
||
|
||
if (!spyFn.called) {
|
||
return true;
|
||
}
|
||
|
||
return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
|
||
},
|
||
|
||
calledAfter: function calledAfter(spyFn) {
|
||
if (!this.called || !spyFn.called) {
|
||
return false;
|
||
}
|
||
|
||
return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
|
||
},
|
||
|
||
withArgs: function () {
|
||
var args = slice.call(arguments);
|
||
|
||
if (this.fakes) {
|
||
var match = matchingFake(this.fakes, args, true);
|
||
|
||
if (match) {
|
||
return match;
|
||
}
|
||
} else {
|
||
this.fakes = [];
|
||
}
|
||
|
||
var original = this;
|
||
var fake = this.instantiateFake();
|
||
fake.matchingAguments = args;
|
||
fake.parent = this;
|
||
push.call(this.fakes, fake);
|
||
|
||
fake.withArgs = function () {
|
||
return original.withArgs.apply(original, arguments);
|
||
};
|
||
|
||
for (var i = 0; i < this.args.length; i++) {
|
||
if (fake.matches(this.args[i])) {
|
||
incrementCallCount.call(fake);
|
||
push.call(fake.thisValues, this.thisValues[i]);
|
||
push.call(fake.args, this.args[i]);
|
||
push.call(fake.returnValues, this.returnValues[i]);
|
||
push.call(fake.exceptions, this.exceptions[i]);
|
||
push.call(fake.callIds, this.callIds[i]);
|
||
}
|
||
}
|
||
createCallProperties.call(fake);
|
||
|
||
return fake;
|
||
},
|
||
|
||
matches: function (args, strict) {
|
||
var margs = this.matchingAguments;
|
||
|
||
if (margs.length <= args.length &&
|
||
sinon.deepEqual(margs, args.slice(0, margs.length))) {
|
||
return !strict || margs.length == args.length;
|
||
}
|
||
},
|
||
|
||
printf: function (format) {
|
||
var spy = this;
|
||
var args = slice.call(arguments, 1);
|
||
var formatter;
|
||
|
||
return (format || "").replace(/%(.)/g, function (match, specifyer) {
|
||
formatter = spyApi.formatters[specifyer];
|
||
|
||
if (typeof formatter == "function") {
|
||
return formatter.call(null, spy, args);
|
||
} else if (!isNaN(parseInt(specifyer, 10))) {
|
||
return sinon.format(args[specifyer - 1]);
|
||
}
|
||
|
||
return "%" + specifyer;
|
||
});
|
||
}
|
||
};
|
||
|
||
function delegateToCalls(method, matchAny, actual, notCalled) {
|
||
spyApi[method] = function () {
|
||
if (!this.called) {
|
||
if (notCalled) {
|
||
return notCalled.apply(this, arguments);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
var currentCall;
|
||
var matches = 0;
|
||
|
||
for (var i = 0, l = this.callCount; i < l; i += 1) {
|
||
currentCall = this.getCall(i);
|
||
|
||
if (currentCall[actual || method].apply(currentCall, arguments)) {
|
||
matches += 1;
|
||
|
||
if (matchAny) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
return matches === this.callCount;
|
||
};
|
||
}
|
||
|
||
delegateToCalls("calledOn", true);
|
||
delegateToCalls("alwaysCalledOn", false, "calledOn");
|
||
delegateToCalls("calledWith", true);
|
||
delegateToCalls("calledWithMatch", true);
|
||
delegateToCalls("alwaysCalledWith", false, "calledWith");
|
||
delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
|
||
delegateToCalls("calledWithExactly", true);
|
||
delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
|
||
delegateToCalls("neverCalledWith", false, "notCalledWith",
|
||
function () { return true; });
|
||
delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch",
|
||
function () { return true; });
|
||
delegateToCalls("threw", true);
|
||
delegateToCalls("alwaysThrew", false, "threw");
|
||
delegateToCalls("returned", true);
|
||
delegateToCalls("alwaysReturned", false, "returned");
|
||
delegateToCalls("calledWithNew", true);
|
||
delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
|
||
delegateToCalls("callArg", false, "callArgWith", function () {
|
||
throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
|
||
});
|
||
spyApi.callArgWith = spyApi.callArg;
|
||
delegateToCalls("callArgOn", false, "callArgOnWith", function () {
|
||
throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
|
||
});
|
||
spyApi.callArgOnWith = spyApi.callArgOn;
|
||
delegateToCalls("yield", false, "yield", function () {
|
||
throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
|
||
});
|
||
// "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
|
||
spyApi.invokeCallback = spyApi.yield;
|
||
delegateToCalls("yieldOn", false, "yieldOn", function () {
|
||
throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
|
||
});
|
||
delegateToCalls("yieldTo", false, "yieldTo", function (property) {
|
||
throw new Error(this.toString() + " cannot yield to '" + property +
|
||
"' since it was not yet invoked.");
|
||
});
|
||
delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
|
||
throw new Error(this.toString() + " cannot yield to '" + property +
|
||
"' since it was not yet invoked.");
|
||
});
|
||
|
||
spyApi.formatters = {
|
||
c: function (spy) {
|
||
return sinon.timesInWords(spy.callCount);
|
||
},
|
||
|
||
n: function (spy) {
|
||
return spy.toString();
|
||
},
|
||
|
||
C: function (spy) {
|
||
var calls = [];
|
||
|
||
for (var i = 0, l = spy.callCount; i < l; ++i) {
|
||
var stringifiedCall = " " + spy.getCall(i).toString();
|
||
if (/\n/.test(calls[i - 1])) {
|
||
stringifiedCall = "\n" + stringifiedCall;
|
||
}
|
||
push.call(calls, stringifiedCall);
|
||
}
|
||
|
||
return calls.length > 0 ? "\n" + calls.join("\n") : "";
|
||
},
|
||
|
||
t: function (spy) {
|
||
var objects = [];
|
||
|
||
for (var i = 0, l = spy.callCount; i < l; ++i) {
|
||
push.call(objects, sinon.format(spy.thisValues[i]));
|
||
}
|
||
|
||
return objects.join(", ");
|
||
},
|
||
|
||
"*": function (spy, args) {
|
||
var formatted = [];
|
||
|
||
for (var i = 0, l = args.length; i < l; ++i) {
|
||
push.call(formatted, sinon.format(args[i]));
|
||
}
|
||
|
||
return formatted.join(", ");
|
||
}
|
||
};
|
||
|
||
sinon.extend(spy, spyApi);
|
||
|
||
spy.spyCall = sinon.spyCall;
|
||
sinon.spy = spy;
|
||
|
||
return spy;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./call");
|
||
require("./extend");
|
||
require("./times_in_words");
|
||
require("./format");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./call":40,"./extend":42,"./format":43,"./times_in_words":52,"./util/core":54}],49:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend extend.js
|
||
* @depend spy.js
|
||
* @depend behavior.js
|
||
*/
|
||
/**
|
||
* Stub functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
function stub(object, property, func) {
|
||
if (!!func && typeof func != "function" && typeof func != "object") {
|
||
throw new TypeError("Custom stub should be a function or a property descriptor");
|
||
}
|
||
|
||
var wrapper;
|
||
|
||
if (func) {
|
||
if (typeof func == "function") {
|
||
wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
|
||
} else {
|
||
wrapper = func;
|
||
if (sinon.spy && sinon.spy.create) {
|
||
var types = sinon.objectKeys(wrapper);
|
||
for (var i = 0; i < types.length; i++) {
|
||
wrapper[types[i]] = sinon.spy.create(wrapper[types[i]]);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
var stubLength = 0;
|
||
if (typeof object == "object" && typeof object[property] == "function") {
|
||
stubLength = object[property].length;
|
||
}
|
||
wrapper = stub.create(stubLength);
|
||
}
|
||
|
||
if (!object && typeof property === "undefined") {
|
||
return sinon.stub.create();
|
||
}
|
||
|
||
if (typeof property === "undefined" && typeof object == "object") {
|
||
for (var prop in object) {
|
||
if (typeof object[prop] === "function") {
|
||
stub(object, prop);
|
||
}
|
||
}
|
||
|
||
return object;
|
||
}
|
||
|
||
return sinon.wrapMethod(object, property, wrapper);
|
||
}
|
||
|
||
function getDefaultBehavior(stub) {
|
||
return stub.defaultBehavior || getParentBehaviour(stub) || sinon.behavior.create(stub);
|
||
}
|
||
|
||
function getParentBehaviour(stub) {
|
||
return (stub.parent && getCurrentBehavior(stub.parent));
|
||
}
|
||
|
||
function getCurrentBehavior(stub) {
|
||
var behavior = stub.behaviors[stub.callCount - 1];
|
||
return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stub);
|
||
}
|
||
|
||
var uuid = 0;
|
||
|
||
var proto = {
|
||
create: function create(stubLength) {
|
||
var functionStub = function () {
|
||
return getCurrentBehavior(functionStub).invoke(this, arguments);
|
||
};
|
||
|
||
functionStub.id = "stub#" + uuid++;
|
||
var orig = functionStub;
|
||
functionStub = sinon.spy.create(functionStub, stubLength);
|
||
functionStub.func = orig;
|
||
|
||
sinon.extend(functionStub, stub);
|
||
functionStub.instantiateFake = sinon.stub.create;
|
||
functionStub.displayName = "stub";
|
||
functionStub.toString = sinon.functionToString;
|
||
|
||
functionStub.defaultBehavior = null;
|
||
functionStub.behaviors = [];
|
||
|
||
return functionStub;
|
||
},
|
||
|
||
resetBehavior: function () {
|
||
var i;
|
||
|
||
this.defaultBehavior = null;
|
||
this.behaviors = [];
|
||
|
||
delete this.returnValue;
|
||
delete this.returnArgAt;
|
||
this.returnThis = false;
|
||
|
||
if (this.fakes) {
|
||
for (i = 0; i < this.fakes.length; i++) {
|
||
this.fakes[i].resetBehavior();
|
||
}
|
||
}
|
||
},
|
||
|
||
onCall: function onCall(index) {
|
||
if (!this.behaviors[index]) {
|
||
this.behaviors[index] = sinon.behavior.create(this);
|
||
}
|
||
|
||
return this.behaviors[index];
|
||
},
|
||
|
||
onFirstCall: function onFirstCall() {
|
||
return this.onCall(0);
|
||
},
|
||
|
||
onSecondCall: function onSecondCall() {
|
||
return this.onCall(1);
|
||
},
|
||
|
||
onThirdCall: function onThirdCall() {
|
||
return this.onCall(2);
|
||
}
|
||
};
|
||
|
||
for (var method in sinon.behavior) {
|
||
if (sinon.behavior.hasOwnProperty(method) &&
|
||
!proto.hasOwnProperty(method) &&
|
||
method != "create" &&
|
||
method != "withArgs" &&
|
||
method != "invoke") {
|
||
proto[method] = (function (behaviorMethod) {
|
||
return function () {
|
||
this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
|
||
this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
|
||
return this;
|
||
};
|
||
}(method));
|
||
}
|
||
}
|
||
|
||
sinon.extend(stub, proto);
|
||
sinon.stub = stub;
|
||
|
||
return stub;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./behavior");
|
||
require("./spy");
|
||
require("./extend");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./behavior":39,"./extend":42,"./spy":48,"./util/core":54}],50:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend sandbox.js
|
||
*/
|
||
/**
|
||
* Test function, sandboxes fakes
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
var slice = Array.prototype.slice;
|
||
|
||
function test(callback) {
|
||
var type = typeof callback;
|
||
|
||
if (type != "function") {
|
||
throw new TypeError("sinon.test needs to wrap a test function, got " + type);
|
||
}
|
||
|
||
function sinonSandboxedTest() {
|
||
var config = sinon.getConfig(sinon.config);
|
||
config.injectInto = config.injectIntoThis && this || config.injectInto;
|
||
var sandbox = sinon.sandbox.create(config);
|
||
var args = slice.call(arguments);
|
||
var oldDone = args.length && args[args.length - 1];
|
||
var exception, result;
|
||
|
||
if (typeof oldDone == "function") {
|
||
args[args.length - 1] = function sinonDone(result) {
|
||
if (result) {
|
||
sandbox.restore();
|
||
throw exception;
|
||
} else {
|
||
sandbox.verifyAndRestore();
|
||
}
|
||
oldDone(result);
|
||
};
|
||
}
|
||
|
||
try {
|
||
result = callback.apply(this, args.concat(sandbox.args));
|
||
} catch (e) {
|
||
exception = e;
|
||
}
|
||
|
||
if (typeof oldDone != "function") {
|
||
if (typeof exception !== "undefined") {
|
||
sandbox.restore();
|
||
throw exception;
|
||
} else {
|
||
sandbox.verifyAndRestore();
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
if (callback.length) {
|
||
return function sinonAsyncSandboxedTest(callback) {
|
||
return sinonSandboxedTest.apply(this, arguments);
|
||
};
|
||
}
|
||
|
||
return sinonSandboxedTest;
|
||
}
|
||
|
||
test.config = {
|
||
injectIntoThis: true,
|
||
injectInto: null,
|
||
properties: ["spy", "stub", "mock", "clock", "server", "requests"],
|
||
useFakeTimers: true,
|
||
useFakeServer: true
|
||
};
|
||
|
||
sinon.test = test;
|
||
return test;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./sandbox");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (sinon) {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./sandbox":47,"./util/core":54}],51:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend test.js
|
||
*/
|
||
/**
|
||
* Test case, sandboxes all test functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function createTest(property, setUp, tearDown) {
|
||
return function () {
|
||
if (setUp) {
|
||
setUp.apply(this, arguments);
|
||
}
|
||
|
||
var exception, result;
|
||
|
||
try {
|
||
result = property.apply(this, arguments);
|
||
} catch (e) {
|
||
exception = e;
|
||
}
|
||
|
||
if (tearDown) {
|
||
tearDown.apply(this, arguments);
|
||
}
|
||
|
||
if (exception) {
|
||
throw exception;
|
||
}
|
||
|
||
return result;
|
||
};
|
||
}
|
||
|
||
function makeApi(sinon) {
|
||
function testCase(tests, prefix) {
|
||
/*jsl:ignore*/
|
||
if (!tests || typeof tests != "object") {
|
||
throw new TypeError("sinon.testCase needs an object with test functions");
|
||
}
|
||
/*jsl:end*/
|
||
|
||
prefix = prefix || "test";
|
||
var rPrefix = new RegExp("^" + prefix);
|
||
var methods = {}, testName, property, method;
|
||
var setUp = tests.setUp;
|
||
var tearDown = tests.tearDown;
|
||
|
||
for (testName in tests) {
|
||
if (tests.hasOwnProperty(testName)) {
|
||
property = tests[testName];
|
||
|
||
if (/^(setUp|tearDown)$/.test(testName)) {
|
||
continue;
|
||
}
|
||
|
||
if (typeof property == "function" && rPrefix.test(testName)) {
|
||
method = property;
|
||
|
||
if (setUp || tearDown) {
|
||
method = createTest(property, setUp, tearDown);
|
||
}
|
||
|
||
methods[testName] = sinon.test(method);
|
||
} else {
|
||
methods[testName] = tests[testName];
|
||
}
|
||
}
|
||
}
|
||
|
||
return methods;
|
||
}
|
||
|
||
sinon.testCase = testCase;
|
||
return testCase;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./test");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./test":50,"./util/core":54}],52:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
|
||
function timesInWords(count) {
|
||
switch (count) {
|
||
case 1:
|
||
return "once";
|
||
case 2:
|
||
return "twice";
|
||
case 3:
|
||
return "thrice";
|
||
default:
|
||
return (count || 0) + " times";
|
||
}
|
||
}
|
||
|
||
sinon.timesInWords = timesInWords;
|
||
return sinon.timesInWords;
|
||
}
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./util/core":54}],53:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
*/
|
||
/**
|
||
* Format functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2014 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon, formatio) {
|
||
function makeApi(sinon) {
|
||
function typeOf(value) {
|
||
if (value === null) {
|
||
return "null";
|
||
} else if (value === undefined) {
|
||
return "undefined";
|
||
}
|
||
var string = Object.prototype.toString.call(value);
|
||
return string.substring(8, string.length - 1).toLowerCase();
|
||
};
|
||
|
||
sinon.typeOf = typeOf;
|
||
return sinon.typeOf;
|
||
}
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(
|
||
(typeof sinon == "object" && sinon || null),
|
||
(typeof formatio == "object" && formatio)
|
||
));
|
||
|
||
},{"./util/core":54}],54:[function(require,module,exports){
|
||
/**
|
||
* @depend ../../sinon.js
|
||
*/
|
||
/**
|
||
* Sinon core utilities. For internal use only.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
var div = typeof document != "undefined" && document.createElement("div");
|
||
var hasOwn = Object.prototype.hasOwnProperty;
|
||
|
||
function isDOMNode(obj) {
|
||
var success = false;
|
||
|
||
try {
|
||
obj.appendChild(div);
|
||
success = div.parentNode == obj;
|
||
} catch (e) {
|
||
return false;
|
||
} finally {
|
||
try {
|
||
obj.removeChild(div);
|
||
} catch (e) {
|
||
// Remove failed, not much we can do about that
|
||
}
|
||
}
|
||
|
||
return success;
|
||
}
|
||
|
||
function isElement(obj) {
|
||
return div && obj && obj.nodeType === 1 && isDOMNode(obj);
|
||
}
|
||
|
||
function isFunction(obj) {
|
||
return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
|
||
}
|
||
|
||
function isReallyNaN(val) {
|
||
return typeof val === "number" && isNaN(val);
|
||
}
|
||
|
||
function mirrorProperties(target, source) {
|
||
for (var prop in source) {
|
||
if (!hasOwn.call(target, prop)) {
|
||
target[prop] = source[prop];
|
||
}
|
||
}
|
||
}
|
||
|
||
function isRestorable(obj) {
|
||
return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
|
||
}
|
||
|
||
// Cheap way to detect if we have ES5 support.
|
||
var hasES5Support = "keys" in Object;
|
||
|
||
function makeApi(sinon) {
|
||
sinon.wrapMethod = function wrapMethod(object, property, method) {
|
||
if (!object) {
|
||
throw new TypeError("Should wrap property of object");
|
||
}
|
||
|
||
if (typeof method != "function" && typeof method != "object") {
|
||
throw new TypeError("Method wrapper should be a function or a property descriptor");
|
||
}
|
||
|
||
function checkWrappedMethod(wrappedMethod) {
|
||
if (!isFunction(wrappedMethod)) {
|
||
error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
|
||
property + " as function");
|
||
} else if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
|
||
error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
|
||
} else if (wrappedMethod.calledBefore) {
|
||
var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
|
||
error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
|
||
}
|
||
|
||
if (error) {
|
||
if (wrappedMethod && wrappedMethod.stackTrace) {
|
||
error.stack += "\n--------------\n" + wrappedMethod.stackTrace;
|
||
}
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
var error, wrappedMethod;
|
||
|
||
// IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
|
||
// when using hasOwn.call on objects from other frames.
|
||
var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
|
||
|
||
if (hasES5Support) {
|
||
var methodDesc = (typeof method == "function") ? {value: method} : method,
|
||
wrappedMethodDesc = sinon.getPropertyDescriptor(object, property),
|
||
i;
|
||
|
||
if (!wrappedMethodDesc) {
|
||
error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
|
||
property + " as function");
|
||
} else if (wrappedMethodDesc.restore && wrappedMethodDesc.restore.sinon) {
|
||
error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
|
||
}
|
||
if (error) {
|
||
if (wrappedMethodDesc && wrappedMethodDesc.stackTrace) {
|
||
error.stack += "\n--------------\n" + wrappedMethodDesc.stackTrace;
|
||
}
|
||
throw error;
|
||
}
|
||
|
||
var types = sinon.objectKeys(methodDesc);
|
||
for (i = 0; i < types.length; i++) {
|
||
wrappedMethod = wrappedMethodDesc[types[i]];
|
||
checkWrappedMethod(wrappedMethod);
|
||
}
|
||
|
||
mirrorProperties(methodDesc, wrappedMethodDesc);
|
||
for (i = 0; i < types.length; i++) {
|
||
mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]);
|
||
}
|
||
Object.defineProperty(object, property, methodDesc);
|
||
} else {
|
||
wrappedMethod = object[property];
|
||
checkWrappedMethod(wrappedMethod);
|
||
object[property] = method;
|
||
method.displayName = property;
|
||
}
|
||
|
||
method.displayName = property;
|
||
|
||
// Set up a stack trace which can be used later to find what line of
|
||
// code the original method was created on.
|
||
method.stackTrace = (new Error("Stack Trace for original")).stack;
|
||
|
||
method.restore = function () {
|
||
// For prototype properties try to reset by delete first.
|
||
// If this fails (ex: localStorage on mobile safari) then force a reset
|
||
// via direct assignment.
|
||
if (!owned) {
|
||
try {
|
||
delete object[property];
|
||
} catch (e) {}
|
||
// For native code functions `delete` fails without throwing an error
|
||
// on Chrome < 43, PhantomJS, etc.
|
||
// Use strict equality comparison to check failures then force a reset
|
||
// via direct assignment.
|
||
if (object[property] === method) {
|
||
object[property] = wrappedMethod;
|
||
}
|
||
} else if (hasES5Support) {
|
||
Object.defineProperty(object, property, wrappedMethodDesc);
|
||
}
|
||
|
||
if (!hasES5Support && object[property] === method) {
|
||
object[property] = wrappedMethod;
|
||
}
|
||
};
|
||
|
||
method.restore.sinon = true;
|
||
|
||
if (!hasES5Support) {
|
||
mirrorProperties(method, wrappedMethod);
|
||
}
|
||
|
||
return method;
|
||
};
|
||
|
||
sinon.create = function create(proto) {
|
||
var F = function () {};
|
||
F.prototype = proto;
|
||
return new F();
|
||
};
|
||
|
||
sinon.deepEqual = function deepEqual(a, b) {
|
||
if (sinon.match && sinon.match.isMatcher(a)) {
|
||
return a.test(b);
|
||
}
|
||
|
||
if (typeof a != "object" || typeof b != "object") {
|
||
if (isReallyNaN(a) && isReallyNaN(b)) {
|
||
return true;
|
||
} else {
|
||
return a === b;
|
||
}
|
||
}
|
||
|
||
if (isElement(a) || isElement(b)) {
|
||
return a === b;
|
||
}
|
||
|
||
if (a === b) {
|
||
return true;
|
||
}
|
||
|
||
if ((a === null && b !== null) || (a !== null && b === null)) {
|
||
return false;
|
||
}
|
||
|
||
if (a instanceof RegExp && b instanceof RegExp) {
|
||
return (a.source === b.source) && (a.global === b.global) &&
|
||
(a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
|
||
}
|
||
|
||
var aString = Object.prototype.toString.call(a);
|
||
if (aString != Object.prototype.toString.call(b)) {
|
||
return false;
|
||
}
|
||
|
||
if (aString == "[object Date]") {
|
||
return a.valueOf() === b.valueOf();
|
||
}
|
||
|
||
var prop, aLength = 0, bLength = 0;
|
||
|
||
if (aString == "[object Array]" && a.length !== b.length) {
|
||
return false;
|
||
}
|
||
|
||
for (prop in a) {
|
||
aLength += 1;
|
||
|
||
if (!(prop in b)) {
|
||
return false;
|
||
}
|
||
|
||
if (!deepEqual(a[prop], b[prop])) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
for (prop in b) {
|
||
bLength += 1;
|
||
}
|
||
|
||
return aLength == bLength;
|
||
};
|
||
|
||
sinon.functionName = function functionName(func) {
|
||
var name = func.displayName || func.name;
|
||
|
||
// Use function decomposition as a last resort to get function
|
||
// name. Does not rely on function decomposition to work - if it
|
||
// doesn't debugging will be slightly less informative
|
||
// (i.e. toString will say 'spy' rather than 'myFunc').
|
||
if (!name) {
|
||
var matches = func.toString().match(/function ([^\s\(]+)/);
|
||
name = matches && matches[1];
|
||
}
|
||
|
||
return name;
|
||
};
|
||
|
||
sinon.functionToString = function toString() {
|
||
if (this.getCall && this.callCount) {
|
||
var thisValue, prop, i = this.callCount;
|
||
|
||
while (i--) {
|
||
thisValue = this.getCall(i).thisValue;
|
||
|
||
for (prop in thisValue) {
|
||
if (thisValue[prop] === this) {
|
||
return prop;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return this.displayName || "sinon fake";
|
||
};
|
||
|
||
sinon.objectKeys = function objectKeys(obj) {
|
||
if (obj !== Object(obj)) {
|
||
throw new TypeError("sinon.objectKeys called on a non-object");
|
||
}
|
||
|
||
var keys = [];
|
||
var key;
|
||
for (key in obj) {
|
||
if (hasOwn.call(obj, key)) {
|
||
keys.push(key);
|
||
}
|
||
}
|
||
|
||
return keys;
|
||
};
|
||
|
||
sinon.getPropertyDescriptor = function getPropertyDescriptor(object, property) {
|
||
var proto = object, descriptor;
|
||
while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
|
||
proto = Object.getPrototypeOf(proto);
|
||
}
|
||
return descriptor;
|
||
}
|
||
|
||
sinon.getConfig = function (custom) {
|
||
var config = {};
|
||
custom = custom || {};
|
||
var defaults = sinon.defaultConfig;
|
||
|
||
for (var prop in defaults) {
|
||
if (defaults.hasOwnProperty(prop)) {
|
||
config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
|
||
}
|
||
}
|
||
|
||
return config;
|
||
};
|
||
|
||
sinon.defaultConfig = {
|
||
injectIntoThis: true,
|
||
injectInto: null,
|
||
properties: ["spy", "stub", "mock", "clock", "server", "requests"],
|
||
useFakeTimers: true,
|
||
useFakeServer: true
|
||
};
|
||
|
||
sinon.timesInWords = function timesInWords(count) {
|
||
return count == 1 && "once" ||
|
||
count == 2 && "twice" ||
|
||
count == 3 && "thrice" ||
|
||
(count || 0) + " times";
|
||
};
|
||
|
||
sinon.calledInOrder = function (spies) {
|
||
for (var i = 1, l = spies.length; i < l; i++) {
|
||
if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
};
|
||
|
||
sinon.orderByFirstCall = function (spies) {
|
||
return spies.sort(function (a, b) {
|
||
// uuid, won't ever be equal
|
||
var aCall = a.getCall(0);
|
||
var bCall = b.getCall(0);
|
||
var aId = aCall && aCall.callId || -1;
|
||
var bId = bCall && bCall.callId || -1;
|
||
|
||
return aId < bId ? -1 : 1;
|
||
});
|
||
};
|
||
|
||
sinon.createStubInstance = function (constructor) {
|
||
if (typeof constructor !== "function") {
|
||
throw new TypeError("The constructor should be a function.");
|
||
}
|
||
return sinon.stub(sinon.create(constructor.prototype));
|
||
};
|
||
|
||
sinon.restore = function (object) {
|
||
if (object !== null && typeof object === "object") {
|
||
for (var prop in object) {
|
||
if (isRestorable(object[prop])) {
|
||
object[prop].restore();
|
||
}
|
||
}
|
||
} else if (isRestorable(object)) {
|
||
object.restore();
|
||
}
|
||
};
|
||
|
||
return sinon;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports) {
|
||
makeApi(exports);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{}],55:[function(require,module,exports){
|
||
/**
|
||
* Minimal Event interface implementation
|
||
*
|
||
* Original implementation by Sven Fuchs: https://gist.github.com/995028
|
||
* Modifications and tests by Christian Johansen.
|
||
*
|
||
* @author Sven Fuchs (svenfuchs@artweb-design.de)
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2011 Sven Fuchs, Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
if (typeof sinon == "undefined") {
|
||
this.sinon = {};
|
||
}
|
||
|
||
(function () {
|
||
var push = [].push;
|
||
|
||
function makeApi(sinon) {
|
||
sinon.Event = function Event(type, bubbles, cancelable, target) {
|
||
this.initEvent(type, bubbles, cancelable, target);
|
||
};
|
||
|
||
sinon.Event.prototype = {
|
||
initEvent: function (type, bubbles, cancelable, target) {
|
||
this.type = type;
|
||
this.bubbles = bubbles;
|
||
this.cancelable = cancelable;
|
||
this.target = target;
|
||
},
|
||
|
||
stopPropagation: function () {},
|
||
|
||
preventDefault: function () {
|
||
this.defaultPrevented = true;
|
||
}
|
||
};
|
||
|
||
sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
|
||
this.initEvent(type, false, false, target);
|
||
this.loaded = progressEventRaw.loaded || null;
|
||
this.total = progressEventRaw.total || null;
|
||
this.lengthComputable = !!progressEventRaw.total;
|
||
};
|
||
|
||
sinon.ProgressEvent.prototype = new sinon.Event();
|
||
|
||
sinon.ProgressEvent.prototype.constructor = sinon.ProgressEvent;
|
||
|
||
sinon.CustomEvent = function CustomEvent(type, customData, target) {
|
||
this.initEvent(type, false, false, target);
|
||
this.detail = customData.detail || null;
|
||
};
|
||
|
||
sinon.CustomEvent.prototype = new sinon.Event();
|
||
|
||
sinon.CustomEvent.prototype.constructor = sinon.CustomEvent;
|
||
|
||
sinon.EventTarget = {
|
||
addEventListener: function addEventListener(event, listener) {
|
||
this.eventListeners = this.eventListeners || {};
|
||
this.eventListeners[event] = this.eventListeners[event] || [];
|
||
push.call(this.eventListeners[event], listener);
|
||
},
|
||
|
||
removeEventListener: function removeEventListener(event, listener) {
|
||
var listeners = this.eventListeners && this.eventListeners[event] || [];
|
||
|
||
for (var i = 0, l = listeners.length; i < l; ++i) {
|
||
if (listeners[i] == listener) {
|
||
return listeners.splice(i, 1);
|
||
}
|
||
}
|
||
},
|
||
|
||
dispatchEvent: function dispatchEvent(event) {
|
||
var type = event.type;
|
||
var listeners = this.eventListeners && this.eventListeners[type] || [];
|
||
|
||
for (var i = 0; i < listeners.length; i++) {
|
||
if (typeof listeners[i] == "function") {
|
||
listeners[i].call(this, event);
|
||
} else {
|
||
listeners[i].handleEvent(event);
|
||
}
|
||
}
|
||
|
||
return !!event.defaultPrevented;
|
||
}
|
||
};
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require) {
|
||
var sinon = require("./core");
|
||
makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require);
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}());
|
||
|
||
},{"./core":54}],56:[function(require,module,exports){
|
||
/**
|
||
* @depend fake_xdomain_request.js
|
||
* @depend fake_xml_http_request.js
|
||
* @depend ../format.js
|
||
* @depend ../log_error.js
|
||
*/
|
||
/**
|
||
* The Sinon "server" mimics a web server that receives requests from
|
||
* sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
|
||
* both synchronously and asynchronously. To respond synchronuously, canned
|
||
* answers have to be provided upfront.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
if (typeof sinon == "undefined") {
|
||
var sinon = {};
|
||
}
|
||
|
||
(function () {
|
||
var push = [].push;
|
||
function F() {}
|
||
|
||
function create(proto) {
|
||
F.prototype = proto;
|
||
return new F();
|
||
}
|
||
|
||
function responseArray(handler) {
|
||
var response = handler;
|
||
|
||
if (Object.prototype.toString.call(handler) != "[object Array]") {
|
||
response = [200, {}, handler];
|
||
}
|
||
|
||
if (typeof response[2] != "string") {
|
||
throw new TypeError("Fake server response body should be string, but was " +
|
||
typeof response[2]);
|
||
}
|
||
|
||
return response;
|
||
}
|
||
|
||
var wloc = typeof window !== "undefined" ? window.location : {};
|
||
var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
|
||
|
||
function matchOne(response, reqMethod, reqUrl) {
|
||
var rmeth = response.method;
|
||
var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
|
||
var url = response.url;
|
||
var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
|
||
|
||
return matchMethod && matchUrl;
|
||
}
|
||
|
||
function match(response, request) {
|
||
var requestUrl = request.url;
|
||
|
||
if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
|
||
requestUrl = requestUrl.replace(rCurrLoc, "");
|
||
}
|
||
|
||
if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
|
||
if (typeof response.response == "function") {
|
||
var ru = response.url;
|
||
var args = [request].concat(ru && typeof ru.exec == "function" ? ru.exec(requestUrl).slice(1) : []);
|
||
return response.response.apply(response, args);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
function makeApi(sinon) {
|
||
sinon.fakeServer = {
|
||
create: function () {
|
||
var server = create(this);
|
||
if (!sinon.xhr.supportsCORS) {
|
||
this.xhr = sinon.useFakeXDomainRequest();
|
||
} else {
|
||
this.xhr = sinon.useFakeXMLHttpRequest();
|
||
}
|
||
server.requests = [];
|
||
|
||
this.xhr.onCreate = function (xhrObj) {
|
||
server.addRequest(xhrObj);
|
||
};
|
||
|
||
return server;
|
||
},
|
||
|
||
addRequest: function addRequest(xhrObj) {
|
||
var server = this;
|
||
push.call(this.requests, xhrObj);
|
||
|
||
xhrObj.onSend = function () {
|
||
server.handleRequest(this);
|
||
|
||
if (server.respondImmediately) {
|
||
server.respond();
|
||
} else if (server.autoRespond && !server.responding) {
|
||
setTimeout(function () {
|
||
server.responding = false;
|
||
server.respond();
|
||
}, server.autoRespondAfter || 10);
|
||
|
||
server.responding = true;
|
||
}
|
||
};
|
||
},
|
||
|
||
getHTTPMethod: function getHTTPMethod(request) {
|
||
if (this.fakeHTTPMethods && /post/i.test(request.method)) {
|
||
var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
|
||
return !!matches ? matches[1] : request.method;
|
||
}
|
||
|
||
return request.method;
|
||
},
|
||
|
||
handleRequest: function handleRequest(xhr) {
|
||
if (xhr.async) {
|
||
if (!this.queue) {
|
||
this.queue = [];
|
||
}
|
||
|
||
push.call(this.queue, xhr);
|
||
} else {
|
||
this.processRequest(xhr);
|
||
}
|
||
},
|
||
|
||
log: function log(response, request) {
|
||
var str;
|
||
|
||
str = "Request:\n" + sinon.format(request) + "\n\n";
|
||
str += "Response:\n" + sinon.format(response) + "\n\n";
|
||
|
||
sinon.log(str);
|
||
},
|
||
|
||
respondWith: function respondWith(method, url, body) {
|
||
if (arguments.length == 1 && typeof method != "function") {
|
||
this.response = responseArray(method);
|
||
return;
|
||
}
|
||
|
||
if (!this.responses) { this.responses = []; }
|
||
|
||
if (arguments.length == 1) {
|
||
body = method;
|
||
url = method = null;
|
||
}
|
||
|
||
if (arguments.length == 2) {
|
||
body = url;
|
||
url = method;
|
||
method = null;
|
||
}
|
||
|
||
push.call(this.responses, {
|
||
method: method,
|
||
url: url,
|
||
response: typeof body == "function" ? body : responseArray(body)
|
||
});
|
||
},
|
||
|
||
respond: function respond() {
|
||
if (arguments.length > 0) {
|
||
this.respondWith.apply(this, arguments);
|
||
}
|
||
|
||
var queue = this.queue || [];
|
||
var requests = queue.splice(0, queue.length);
|
||
var request;
|
||
|
||
while (request = requests.shift()) {
|
||
this.processRequest(request);
|
||
}
|
||
},
|
||
|
||
processRequest: function processRequest(request) {
|
||
try {
|
||
if (request.aborted) {
|
||
return;
|
||
}
|
||
|
||
var response = this.response || [404, {}, ""];
|
||
|
||
if (this.responses) {
|
||
for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
|
||
if (match.call(this, this.responses[i], request)) {
|
||
response = this.responses[i].response;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (request.readyState != 4) {
|
||
this.log(response, request);
|
||
|
||
request.respond(response[0], response[1], response[2]);
|
||
}
|
||
} catch (e) {
|
||
sinon.logError("Fake server request processing", e);
|
||
}
|
||
},
|
||
|
||
restore: function restore() {
|
||
return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
|
||
}
|
||
};
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./core");
|
||
require("./fake_xdomain_request");
|
||
require("./fake_xml_http_request");
|
||
require("../format");
|
||
makeApi(sinon);
|
||
module.exports = sinon;
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}());
|
||
|
||
},{"../format":43,"./core":54,"./fake_xdomain_request":59,"./fake_xml_http_request":60}],57:[function(require,module,exports){
|
||
/**
|
||
* @depend fake_server.js
|
||
* @depend fake_timers.js
|
||
*/
|
||
/**
|
||
* Add-on for sinon.fakeServer that automatically handles a fake timer along with
|
||
* the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
|
||
* 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
|
||
* it polls the object for completion with setInterval. Dispite the direct
|
||
* motivation, there is nothing jQuery-specific in this file, so it can be used
|
||
* in any environment where the ajax implementation depends on setInterval or
|
||
* setTimeout.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function () {
|
||
function makeApi(sinon) {
|
||
function Server() {}
|
||
Server.prototype = sinon.fakeServer;
|
||
|
||
sinon.fakeServerWithClock = new Server();
|
||
|
||
sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
|
||
if (xhr.async) {
|
||
if (typeof setTimeout.clock == "object") {
|
||
this.clock = setTimeout.clock;
|
||
} else {
|
||
this.clock = sinon.useFakeTimers();
|
||
this.resetClock = true;
|
||
}
|
||
|
||
if (!this.longestTimeout) {
|
||
var clockSetTimeout = this.clock.setTimeout;
|
||
var clockSetInterval = this.clock.setInterval;
|
||
var server = this;
|
||
|
||
this.clock.setTimeout = function (fn, timeout) {
|
||
server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
|
||
|
||
return clockSetTimeout.apply(this, arguments);
|
||
};
|
||
|
||
this.clock.setInterval = function (fn, timeout) {
|
||
server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
|
||
|
||
return clockSetInterval.apply(this, arguments);
|
||
};
|
||
}
|
||
}
|
||
|
||
return sinon.fakeServer.addRequest.call(this, xhr);
|
||
};
|
||
|
||
sinon.fakeServerWithClock.respond = function respond() {
|
||
var returnVal = sinon.fakeServer.respond.apply(this, arguments);
|
||
|
||
if (this.clock) {
|
||
this.clock.tick(this.longestTimeout || 0);
|
||
this.longestTimeout = 0;
|
||
|
||
if (this.resetClock) {
|
||
this.clock.restore();
|
||
this.resetClock = false;
|
||
}
|
||
}
|
||
|
||
return returnVal;
|
||
};
|
||
|
||
sinon.fakeServerWithClock.restore = function restore() {
|
||
if (this.clock) {
|
||
this.clock.restore();
|
||
}
|
||
|
||
return sinon.fakeServer.restore.apply(this, arguments);
|
||
};
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require) {
|
||
var sinon = require("./core");
|
||
require("./fake_server");
|
||
require("./fake_timers");
|
||
makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require);
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}());
|
||
|
||
},{"./core":54,"./fake_server":56,"./fake_timers":58}],58:[function(require,module,exports){
|
||
(function (global){
|
||
/*global lolex */
|
||
|
||
/**
|
||
* Fake timer API
|
||
* setTimeout
|
||
* setInterval
|
||
* clearTimeout
|
||
* clearInterval
|
||
* tick
|
||
* reset
|
||
* Date
|
||
*
|
||
* Inspired by jsUnitMockTimeOut from JsUnit
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
if (typeof sinon == "undefined") {
|
||
var sinon = {};
|
||
}
|
||
|
||
(function (global) {
|
||
function makeApi(sinon, lol) {
|
||
var llx = typeof lolex !== "undefined" ? lolex : lol;
|
||
|
||
sinon.useFakeTimers = function () {
|
||
var now, methods = Array.prototype.slice.call(arguments);
|
||
|
||
if (typeof methods[0] === "string") {
|
||
now = 0;
|
||
} else {
|
||
now = methods.shift();
|
||
}
|
||
|
||
var clock = llx.install(now || 0, methods);
|
||
clock.restore = clock.uninstall;
|
||
return clock;
|
||
};
|
||
|
||
sinon.clock = {
|
||
create: function (now) {
|
||
return llx.createClock(now);
|
||
}
|
||
};
|
||
|
||
sinon.timers = {
|
||
setTimeout: setTimeout,
|
||
clearTimeout: clearTimeout,
|
||
setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
|
||
clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate : undefined),
|
||
setInterval: setInterval,
|
||
clearInterval: clearInterval,
|
||
Date: Date
|
||
};
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, epxorts, module, lolex) {
|
||
var sinon = require("./core");
|
||
makeApi(sinon, lolex);
|
||
module.exports = sinon;
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module, require("lolex"));
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof global != "undefined" && typeof global !== "function" ? global : this));
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"./core":54,"lolex":63}],59:[function(require,module,exports){
|
||
/**
|
||
* @depend core.js
|
||
* @depend ../extend.js
|
||
* @depend event.js
|
||
* @depend ../log_error.js
|
||
*/
|
||
/**
|
||
* Fake XDomainRequest object
|
||
*/
|
||
"use strict";
|
||
|
||
if (typeof sinon == "undefined") {
|
||
this.sinon = {};
|
||
}
|
||
|
||
// wrapper for global
|
||
(function (global) {
|
||
var xdr = { XDomainRequest: global.XDomainRequest };
|
||
xdr.GlobalXDomainRequest = global.XDomainRequest;
|
||
xdr.supportsXDR = typeof xdr.GlobalXDomainRequest != "undefined";
|
||
xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest : false;
|
||
|
||
function makeApi(sinon) {
|
||
sinon.xdr = xdr;
|
||
|
||
function FakeXDomainRequest() {
|
||
this.readyState = FakeXDomainRequest.UNSENT;
|
||
this.requestBody = null;
|
||
this.requestHeaders = {};
|
||
this.status = 0;
|
||
this.timeout = null;
|
||
|
||
if (typeof FakeXDomainRequest.onCreate == "function") {
|
||
FakeXDomainRequest.onCreate(this);
|
||
}
|
||
}
|
||
|
||
function verifyState(xdr) {
|
||
if (xdr.readyState !== FakeXDomainRequest.OPENED) {
|
||
throw new Error("INVALID_STATE_ERR");
|
||
}
|
||
|
||
if (xdr.sendFlag) {
|
||
throw new Error("INVALID_STATE_ERR");
|
||
}
|
||
}
|
||
|
||
function verifyRequestSent(xdr) {
|
||
if (xdr.readyState == FakeXDomainRequest.UNSENT) {
|
||
throw new Error("Request not sent");
|
||
}
|
||
if (xdr.readyState == FakeXDomainRequest.DONE) {
|
||
throw new Error("Request done");
|
||
}
|
||
}
|
||
|
||
function verifyResponseBodyType(body) {
|
||
if (typeof body != "string") {
|
||
var error = new Error("Attempted to respond to fake XDomainRequest with " +
|
||
body + ", which is not a string.");
|
||
error.name = "InvalidBodyException";
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
sinon.extend(FakeXDomainRequest.prototype, sinon.EventTarget, {
|
||
open: function open(method, url) {
|
||
this.method = method;
|
||
this.url = url;
|
||
|
||
this.responseText = null;
|
||
this.sendFlag = false;
|
||
|
||
this.readyStateChange(FakeXDomainRequest.OPENED);
|
||
},
|
||
|
||
readyStateChange: function readyStateChange(state) {
|
||
this.readyState = state;
|
||
var eventName = "";
|
||
switch (this.readyState) {
|
||
case FakeXDomainRequest.UNSENT:
|
||
break;
|
||
case FakeXDomainRequest.OPENED:
|
||
break;
|
||
case FakeXDomainRequest.LOADING:
|
||
if (this.sendFlag) {
|
||
//raise the progress event
|
||
eventName = "onprogress";
|
||
}
|
||
break;
|
||
case FakeXDomainRequest.DONE:
|
||
if (this.isTimeout) {
|
||
eventName = "ontimeout"
|
||
} else if (this.errorFlag || (this.status < 200 || this.status > 299)) {
|
||
eventName = "onerror";
|
||
} else {
|
||
eventName = "onload"
|
||
}
|
||
break;
|
||
}
|
||
|
||
// raising event (if defined)
|
||
if (eventName) {
|
||
if (typeof this[eventName] == "function") {
|
||
try {
|
||
this[eventName]();
|
||
} catch (e) {
|
||
sinon.logError("Fake XHR " + eventName + " handler", e);
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
send: function send(data) {
|
||
verifyState(this);
|
||
|
||
if (!/^(get|head)$/i.test(this.method)) {
|
||
this.requestBody = data;
|
||
}
|
||
this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
|
||
|
||
this.errorFlag = false;
|
||
this.sendFlag = true;
|
||
this.readyStateChange(FakeXDomainRequest.OPENED);
|
||
|
||
if (typeof this.onSend == "function") {
|
||
this.onSend(this);
|
||
}
|
||
},
|
||
|
||
abort: function abort() {
|
||
this.aborted = true;
|
||
this.responseText = null;
|
||
this.errorFlag = true;
|
||
|
||
if (this.readyState > sinon.FakeXDomainRequest.UNSENT && this.sendFlag) {
|
||
this.readyStateChange(sinon.FakeXDomainRequest.DONE);
|
||
this.sendFlag = false;
|
||
}
|
||
},
|
||
|
||
setResponseBody: function setResponseBody(body) {
|
||
verifyRequestSent(this);
|
||
verifyResponseBodyType(body);
|
||
|
||
var chunkSize = this.chunkSize || 10;
|
||
var index = 0;
|
||
this.responseText = "";
|
||
|
||
do {
|
||
this.readyStateChange(FakeXDomainRequest.LOADING);
|
||
this.responseText += body.substring(index, index + chunkSize);
|
||
index += chunkSize;
|
||
} while (index < body.length);
|
||
|
||
this.readyStateChange(FakeXDomainRequest.DONE);
|
||
},
|
||
|
||
respond: function respond(status, contentType, body) {
|
||
// content-type ignored, since XDomainRequest does not carry this
|
||
// we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease
|
||
// test integration across browsers
|
||
this.status = typeof status == "number" ? status : 200;
|
||
this.setResponseBody(body || "");
|
||
},
|
||
|
||
simulatetimeout: function simulatetimeout() {
|
||
this.status = 0;
|
||
this.isTimeout = true;
|
||
// Access to this should actually throw an error
|
||
this.responseText = undefined;
|
||
this.readyStateChange(FakeXDomainRequest.DONE);
|
||
}
|
||
});
|
||
|
||
sinon.extend(FakeXDomainRequest, {
|
||
UNSENT: 0,
|
||
OPENED: 1,
|
||
LOADING: 3,
|
||
DONE: 4
|
||
});
|
||
|
||
sinon.useFakeXDomainRequest = function useFakeXDomainRequest() {
|
||
sinon.FakeXDomainRequest.restore = function restore(keepOnCreate) {
|
||
if (xdr.supportsXDR) {
|
||
global.XDomainRequest = xdr.GlobalXDomainRequest;
|
||
}
|
||
|
||
delete sinon.FakeXDomainRequest.restore;
|
||
|
||
if (keepOnCreate !== true) {
|
||
delete sinon.FakeXDomainRequest.onCreate;
|
||
}
|
||
};
|
||
if (xdr.supportsXDR) {
|
||
global.XDomainRequest = sinon.FakeXDomainRequest;
|
||
}
|
||
return sinon.FakeXDomainRequest;
|
||
};
|
||
|
||
sinon.FakeXDomainRequest = FakeXDomainRequest;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./core");
|
||
require("../extend");
|
||
require("./event");
|
||
require("../log_error");
|
||
makeApi(sinon);
|
||
module.exports = sinon;
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
})(this);
|
||
|
||
},{"../extend":42,"../log_error":44,"./core":54,"./event":55}],60:[function(require,module,exports){
|
||
(function (global){
|
||
/**
|
||
* @depend core.js
|
||
* @depend ../extend.js
|
||
* @depend event.js
|
||
* @depend ../log_error.js
|
||
*/
|
||
/**
|
||
* Fake XMLHttpRequest object
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (global) {
|
||
|
||
var supportsProgress = typeof ProgressEvent !== "undefined";
|
||
var supportsCustomEvent = typeof CustomEvent !== "undefined";
|
||
var sinonXhr = { XMLHttpRequest: global.XMLHttpRequest };
|
||
sinonXhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
|
||
sinonXhr.GlobalActiveXObject = global.ActiveXObject;
|
||
sinonXhr.supportsActiveX = typeof sinonXhr.GlobalActiveXObject != "undefined";
|
||
sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest != "undefined";
|
||
sinonXhr.workingXHR = sinonXhr.supportsXHR ? sinonXhr.GlobalXMLHttpRequest : sinonXhr.supportsActiveX
|
||
? function () { return new sinonXhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0") } : false;
|
||
sinonXhr.supportsCORS = sinonXhr.supportsXHR && "withCredentials" in (new sinonXhr.GlobalXMLHttpRequest());
|
||
|
||
/*jsl:ignore*/
|
||
var unsafeHeaders = {
|
||
"Accept-Charset": true,
|
||
"Accept-Encoding": true,
|
||
Connection: true,
|
||
"Content-Length": true,
|
||
Cookie: true,
|
||
Cookie2: true,
|
||
"Content-Transfer-Encoding": true,
|
||
Date: true,
|
||
Expect: true,
|
||
Host: true,
|
||
"Keep-Alive": true,
|
||
Referer: true,
|
||
TE: true,
|
||
Trailer: true,
|
||
"Transfer-Encoding": true,
|
||
Upgrade: true,
|
||
"User-Agent": true,
|
||
Via: true
|
||
};
|
||
/*jsl:end*/
|
||
|
||
function FakeXMLHttpRequest() {
|
||
this.readyState = FakeXMLHttpRequest.UNSENT;
|
||
this.requestHeaders = {};
|
||
this.requestBody = null;
|
||
this.status = 0;
|
||
this.statusText = "";
|
||
this.upload = new UploadProgress();
|
||
if (sinonXhr.supportsCORS) {
|
||
this.withCredentials = false;
|
||
}
|
||
|
||
var xhr = this;
|
||
var events = ["loadstart", "load", "abort", "loadend"];
|
||
|
||
function addEventListener(eventName) {
|
||
xhr.addEventListener(eventName, function (event) {
|
||
var listener = xhr["on" + eventName];
|
||
|
||
if (listener && typeof listener == "function") {
|
||
listener.call(this, event);
|
||
}
|
||
});
|
||
}
|
||
|
||
for (var i = events.length - 1; i >= 0; i--) {
|
||
addEventListener(events[i]);
|
||
}
|
||
|
||
if (typeof FakeXMLHttpRequest.onCreate == "function") {
|
||
FakeXMLHttpRequest.onCreate(this);
|
||
}
|
||
}
|
||
|
||
// An upload object is created for each
|
||
// FakeXMLHttpRequest and allows upload
|
||
// events to be simulated using uploadProgress
|
||
// and uploadError.
|
||
function UploadProgress() {
|
||
this.eventListeners = {
|
||
progress: [],
|
||
load: [],
|
||
abort: [],
|
||
error: []
|
||
}
|
||
}
|
||
|
||
UploadProgress.prototype.addEventListener = function addEventListener(event, listener) {
|
||
this.eventListeners[event].push(listener);
|
||
};
|
||
|
||
UploadProgress.prototype.removeEventListener = function removeEventListener(event, listener) {
|
||
var listeners = this.eventListeners[event] || [];
|
||
|
||
for (var i = 0, l = listeners.length; i < l; ++i) {
|
||
if (listeners[i] == listener) {
|
||
return listeners.splice(i, 1);
|
||
}
|
||
}
|
||
};
|
||
|
||
UploadProgress.prototype.dispatchEvent = function dispatchEvent(event) {
|
||
var listeners = this.eventListeners[event.type] || [];
|
||
|
||
for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
|
||
listener(event);
|
||
}
|
||
};
|
||
|
||
function verifyState(xhr) {
|
||
if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
|
||
throw new Error("INVALID_STATE_ERR");
|
||
}
|
||
|
||
if (xhr.sendFlag) {
|
||
throw new Error("INVALID_STATE_ERR");
|
||
}
|
||
}
|
||
|
||
function getHeader(headers, header) {
|
||
header = header.toLowerCase();
|
||
|
||
for (var h in headers) {
|
||
if (h.toLowerCase() == header) {
|
||
return h;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
// filtering to enable a white-list version of Sinon FakeXhr,
|
||
// where whitelisted requests are passed through to real XHR
|
||
function each(collection, callback) {
|
||
if (!collection) {
|
||
return;
|
||
}
|
||
|
||
for (var i = 0, l = collection.length; i < l; i += 1) {
|
||
callback(collection[i]);
|
||
}
|
||
}
|
||
function some(collection, callback) {
|
||
for (var index = 0; index < collection.length; index++) {
|
||
if (callback(collection[index]) === true) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
// largest arity in XHR is 5 - XHR#open
|
||
var apply = function (obj, method, args) {
|
||
switch (args.length) {
|
||
case 0: return obj[method]();
|
||
case 1: return obj[method](args[0]);
|
||
case 2: return obj[method](args[0], args[1]);
|
||
case 3: return obj[method](args[0], args[1], args[2]);
|
||
case 4: return obj[method](args[0], args[1], args[2], args[3]);
|
||
case 5: return obj[method](args[0], args[1], args[2], args[3], args[4]);
|
||
}
|
||
};
|
||
|
||
FakeXMLHttpRequest.filters = [];
|
||
FakeXMLHttpRequest.addFilter = function addFilter(fn) {
|
||
this.filters.push(fn)
|
||
};
|
||
var IE6Re = /MSIE 6/;
|
||
FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) {
|
||
var xhr = new sinonXhr.workingXHR();
|
||
each([
|
||
"open",
|
||
"setRequestHeader",
|
||
"send",
|
||
"abort",
|
||
"getResponseHeader",
|
||
"getAllResponseHeaders",
|
||
"addEventListener",
|
||
"overrideMimeType",
|
||
"removeEventListener"
|
||
], function (method) {
|
||
fakeXhr[method] = function () {
|
||
return apply(xhr, method, arguments);
|
||
};
|
||
});
|
||
|
||
var copyAttrs = function (args) {
|
||
each(args, function (attr) {
|
||
try {
|
||
fakeXhr[attr] = xhr[attr]
|
||
} catch (e) {
|
||
if (!IE6Re.test(navigator.userAgent)) {
|
||
throw e;
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
var stateChange = function stateChange() {
|
||
fakeXhr.readyState = xhr.readyState;
|
||
if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
|
||
copyAttrs(["status", "statusText"]);
|
||
}
|
||
if (xhr.readyState >= FakeXMLHttpRequest.LOADING) {
|
||
copyAttrs(["responseText", "response"]);
|
||
}
|
||
if (xhr.readyState === FakeXMLHttpRequest.DONE) {
|
||
copyAttrs(["responseXML"]);
|
||
}
|
||
if (fakeXhr.onreadystatechange) {
|
||
fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
|
||
}
|
||
};
|
||
|
||
if (xhr.addEventListener) {
|
||
for (var event in fakeXhr.eventListeners) {
|
||
if (fakeXhr.eventListeners.hasOwnProperty(event)) {
|
||
each(fakeXhr.eventListeners[event], function (handler) {
|
||
xhr.addEventListener(event, handler);
|
||
});
|
||
}
|
||
}
|
||
xhr.addEventListener("readystatechange", stateChange);
|
||
} else {
|
||
xhr.onreadystatechange = stateChange;
|
||
}
|
||
apply(xhr, "open", xhrArgs);
|
||
};
|
||
FakeXMLHttpRequest.useFilters = false;
|
||
|
||
function verifyRequestOpened(xhr) {
|
||
if (xhr.readyState != FakeXMLHttpRequest.OPENED) {
|
||
throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
|
||
}
|
||
}
|
||
|
||
function verifyRequestSent(xhr) {
|
||
if (xhr.readyState == FakeXMLHttpRequest.DONE) {
|
||
throw new Error("Request done");
|
||
}
|
||
}
|
||
|
||
function verifyHeadersReceived(xhr) {
|
||
if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
|
||
throw new Error("No headers received");
|
||
}
|
||
}
|
||
|
||
function verifyResponseBodyType(body) {
|
||
if (typeof body != "string") {
|
||
var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
|
||
body + ", which is not a string.");
|
||
error.name = "InvalidBodyException";
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
FakeXMLHttpRequest.parseXML = function parseXML(text) {
|
||
var xmlDoc;
|
||
|
||
if (typeof DOMParser != "undefined") {
|
||
var parser = new DOMParser();
|
||
xmlDoc = parser.parseFromString(text, "text/xml");
|
||
} else {
|
||
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
|
||
xmlDoc.async = "false";
|
||
xmlDoc.loadXML(text);
|
||
}
|
||
|
||
return xmlDoc;
|
||
};
|
||
|
||
FakeXMLHttpRequest.statusCodes = {
|
||
100: "Continue",
|
||
101: "Switching Protocols",
|
||
200: "OK",
|
||
201: "Created",
|
||
202: "Accepted",
|
||
203: "Non-Authoritative Information",
|
||
204: "No Content",
|
||
205: "Reset Content",
|
||
206: "Partial Content",
|
||
207: "Multi-Status",
|
||
300: "Multiple Choice",
|
||
301: "Moved Permanently",
|
||
302: "Found",
|
||
303: "See Other",
|
||
304: "Not Modified",
|
||
305: "Use Proxy",
|
||
307: "Temporary Redirect",
|
||
400: "Bad Request",
|
||
401: "Unauthorized",
|
||
402: "Payment Required",
|
||
403: "Forbidden",
|
||
404: "Not Found",
|
||
405: "Method Not Allowed",
|
||
406: "Not Acceptable",
|
||
407: "Proxy Authentication Required",
|
||
408: "Request Timeout",
|
||
409: "Conflict",
|
||
410: "Gone",
|
||
411: "Length Required",
|
||
412: "Precondition Failed",
|
||
413: "Request Entity Too Large",
|
||
414: "Request-URI Too Long",
|
||
415: "Unsupported Media Type",
|
||
416: "Requested Range Not Satisfiable",
|
||
417: "Expectation Failed",
|
||
422: "Unprocessable Entity",
|
||
500: "Internal Server Error",
|
||
501: "Not Implemented",
|
||
502: "Bad Gateway",
|
||
503: "Service Unavailable",
|
||
504: "Gateway Timeout",
|
||
505: "HTTP Version Not Supported"
|
||
};
|
||
|
||
function makeApi(sinon) {
|
||
sinon.xhr = sinonXhr;
|
||
|
||
sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
|
||
async: true,
|
||
|
||
open: function open(method, url, async, username, password) {
|
||
this.method = method;
|
||
this.url = url;
|
||
this.async = typeof async == "boolean" ? async : true;
|
||
this.username = username;
|
||
this.password = password;
|
||
this.responseText = null;
|
||
this.responseXML = null;
|
||
this.requestHeaders = {};
|
||
this.sendFlag = false;
|
||
|
||
if (FakeXMLHttpRequest.useFilters === true) {
|
||
var xhrArgs = arguments;
|
||
var defake = some(FakeXMLHttpRequest.filters, function (filter) {
|
||
return filter.apply(this, xhrArgs)
|
||
});
|
||
if (defake) {
|
||
return FakeXMLHttpRequest.defake(this, arguments);
|
||
}
|
||
}
|
||
this.readyStateChange(FakeXMLHttpRequest.OPENED);
|
||
},
|
||
|
||
readyStateChange: function readyStateChange(state) {
|
||
this.readyState = state;
|
||
|
||
if (typeof this.onreadystatechange == "function") {
|
||
try {
|
||
this.onreadystatechange();
|
||
} catch (e) {
|
||
sinon.logError("Fake XHR onreadystatechange handler", e);
|
||
}
|
||
}
|
||
|
||
this.dispatchEvent(new sinon.Event("readystatechange"));
|
||
|
||
switch (this.readyState) {
|
||
case FakeXMLHttpRequest.DONE:
|
||
this.dispatchEvent(new sinon.Event("load", false, false, this));
|
||
this.dispatchEvent(new sinon.Event("loadend", false, false, this));
|
||
this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
|
||
if (supportsProgress) {
|
||
this.upload.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
|
||
this.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
|
||
}
|
||
break;
|
||
}
|
||
},
|
||
|
||
setRequestHeader: function setRequestHeader(header, value) {
|
||
verifyState(this);
|
||
|
||
if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
|
||
throw new Error("Refused to set unsafe header \"" + header + "\"");
|
||
}
|
||
|
||
if (this.requestHeaders[header]) {
|
||
this.requestHeaders[header] += "," + value;
|
||
} else {
|
||
this.requestHeaders[header] = value;
|
||
}
|
||
},
|
||
|
||
// Helps testing
|
||
setResponseHeaders: function setResponseHeaders(headers) {
|
||
verifyRequestOpened(this);
|
||
this.responseHeaders = {};
|
||
|
||
for (var header in headers) {
|
||
if (headers.hasOwnProperty(header)) {
|
||
this.responseHeaders[header] = headers[header];
|
||
}
|
||
}
|
||
|
||
if (this.async) {
|
||
this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
|
||
} else {
|
||
this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
|
||
}
|
||
},
|
||
|
||
// Currently treats ALL data as a DOMString (i.e. no Document)
|
||
send: function send(data) {
|
||
verifyState(this);
|
||
|
||
if (!/^(get|head)$/i.test(this.method)) {
|
||
var contentType = getHeader(this.requestHeaders, "Content-Type");
|
||
if (this.requestHeaders[contentType]) {
|
||
var value = this.requestHeaders[contentType].split(";");
|
||
this.requestHeaders[contentType] = value[0] + ";charset=utf-8";
|
||
} else if (!(data instanceof FormData)) {
|
||
this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
|
||
}
|
||
|
||
this.requestBody = data;
|
||
}
|
||
|
||
this.errorFlag = false;
|
||
this.sendFlag = this.async;
|
||
this.readyStateChange(FakeXMLHttpRequest.OPENED);
|
||
|
||
if (typeof this.onSend == "function") {
|
||
this.onSend(this);
|
||
}
|
||
|
||
this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
|
||
},
|
||
|
||
abort: function abort() {
|
||
this.aborted = true;
|
||
this.responseText = null;
|
||
this.errorFlag = true;
|
||
this.requestHeaders = {};
|
||
|
||
if (this.readyState > FakeXMLHttpRequest.UNSENT && this.sendFlag) {
|
||
this.readyStateChange(FakeXMLHttpRequest.DONE);
|
||
this.sendFlag = false;
|
||
}
|
||
|
||
this.readyState = FakeXMLHttpRequest.UNSENT;
|
||
|
||
this.dispatchEvent(new sinon.Event("abort", false, false, this));
|
||
|
||
this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
|
||
|
||
if (typeof this.onerror === "function") {
|
||
this.onerror();
|
||
}
|
||
},
|
||
|
||
getResponseHeader: function getResponseHeader(header) {
|
||
if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
|
||
return null;
|
||
}
|
||
|
||
if (/^Set-Cookie2?$/i.test(header)) {
|
||
return null;
|
||
}
|
||
|
||
header = getHeader(this.responseHeaders, header);
|
||
|
||
return this.responseHeaders[header] || null;
|
||
},
|
||
|
||
getAllResponseHeaders: function getAllResponseHeaders() {
|
||
if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
|
||
return "";
|
||
}
|
||
|
||
var headers = "";
|
||
|
||
for (var header in this.responseHeaders) {
|
||
if (this.responseHeaders.hasOwnProperty(header) &&
|
||
!/^Set-Cookie2?$/i.test(header)) {
|
||
headers += header + ": " + this.responseHeaders[header] + "\r\n";
|
||
}
|
||
}
|
||
|
||
return headers;
|
||
},
|
||
|
||
setResponseBody: function setResponseBody(body) {
|
||
verifyRequestSent(this);
|
||
verifyHeadersReceived(this);
|
||
verifyResponseBodyType(body);
|
||
|
||
var chunkSize = this.chunkSize || 10;
|
||
var index = 0;
|
||
this.responseText = "";
|
||
|
||
do {
|
||
if (this.async) {
|
||
this.readyStateChange(FakeXMLHttpRequest.LOADING);
|
||
}
|
||
|
||
this.responseText += body.substring(index, index + chunkSize);
|
||
index += chunkSize;
|
||
} while (index < body.length);
|
||
|
||
var type = this.getResponseHeader("Content-Type");
|
||
|
||
if (this.responseText &&
|
||
(!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
|
||
try {
|
||
this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
|
||
} catch (e) {
|
||
// Unable to parse XML - no biggie
|
||
}
|
||
}
|
||
|
||
this.readyStateChange(FakeXMLHttpRequest.DONE);
|
||
},
|
||
|
||
respond: function respond(status, headers, body) {
|
||
this.status = typeof status == "number" ? status : 200;
|
||
this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
|
||
this.setResponseHeaders(headers || {});
|
||
this.setResponseBody(body || "");
|
||
},
|
||
|
||
uploadProgress: function uploadProgress(progressEventRaw) {
|
||
if (supportsProgress) {
|
||
this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
|
||
}
|
||
},
|
||
|
||
downloadProgress: function downloadProgress(progressEventRaw) {
|
||
if (supportsProgress) {
|
||
this.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
|
||
}
|
||
},
|
||
|
||
uploadError: function uploadError(error) {
|
||
if (supportsCustomEvent) {
|
||
this.upload.dispatchEvent(new sinon.CustomEvent("error", {detail: error}));
|
||
}
|
||
}
|
||
});
|
||
|
||
sinon.extend(FakeXMLHttpRequest, {
|
||
UNSENT: 0,
|
||
OPENED: 1,
|
||
HEADERS_RECEIVED: 2,
|
||
LOADING: 3,
|
||
DONE: 4
|
||
});
|
||
|
||
sinon.useFakeXMLHttpRequest = function () {
|
||
FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
|
||
if (sinonXhr.supportsXHR) {
|
||
global.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest;
|
||
}
|
||
|
||
if (sinonXhr.supportsActiveX) {
|
||
global.ActiveXObject = sinonXhr.GlobalActiveXObject;
|
||
}
|
||
|
||
delete FakeXMLHttpRequest.restore;
|
||
|
||
if (keepOnCreate !== true) {
|
||
delete FakeXMLHttpRequest.onCreate;
|
||
}
|
||
};
|
||
if (sinonXhr.supportsXHR) {
|
||
global.XMLHttpRequest = FakeXMLHttpRequest;
|
||
}
|
||
|
||
if (sinonXhr.supportsActiveX) {
|
||
global.ActiveXObject = function ActiveXObject(objId) {
|
||
if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
|
||
|
||
return new FakeXMLHttpRequest();
|
||
}
|
||
|
||
return new sinonXhr.GlobalActiveXObject(objId);
|
||
};
|
||
}
|
||
|
||
return FakeXMLHttpRequest;
|
||
};
|
||
|
||
sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./core");
|
||
require("../extend");
|
||
require("./event");
|
||
require("../log_error");
|
||
makeApi(sinon);
|
||
module.exports = sinon;
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (typeof sinon === "undefined") {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
|
||
})(typeof global !== "undefined" ? global : this);
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"../extend":42,"../log_error":44,"./core":54,"./event":55}],61:[function(require,module,exports){
|
||
(function (global){
|
||
((typeof define === "function" && define.amd && function (m) {
|
||
define("formatio", ["samsam"], m);
|
||
}) || (typeof module === "object" && function (m) {
|
||
module.exports = m(require("samsam"));
|
||
}) || function (m) { this.formatio = m(this.samsam); }
|
||
)(function (samsam) {
|
||
"use strict";
|
||
|
||
var formatio = {
|
||
excludeConstructors: ["Object", /^.$/],
|
||
quoteStrings: true,
|
||
limitChildrenCount: 0
|
||
};
|
||
|
||
var hasOwn = Object.prototype.hasOwnProperty;
|
||
|
||
var specialObjects = [];
|
||
if (typeof global !== "undefined") {
|
||
specialObjects.push({ object: global, value: "[object global]" });
|
||
}
|
||
if (typeof document !== "undefined") {
|
||
specialObjects.push({
|
||
object: document,
|
||
value: "[object HTMLDocument]"
|
||
});
|
||
}
|
||
if (typeof window !== "undefined") {
|
||
specialObjects.push({ object: window, value: "[object Window]" });
|
||
}
|
||
|
||
function functionName(func) {
|
||
if (!func) { return ""; }
|
||
if (func.displayName) { return func.displayName; }
|
||
if (func.name) { return func.name; }
|
||
var matches = func.toString().match(/function\s+([^\(]+)/m);
|
||
return (matches && matches[1]) || "";
|
||
}
|
||
|
||
function constructorName(f, object) {
|
||
var name = functionName(object && object.constructor);
|
||
var excludes = f.excludeConstructors ||
|
||
formatio.excludeConstructors || [];
|
||
|
||
var i, l;
|
||
for (i = 0, l = excludes.length; i < l; ++i) {
|
||
if (typeof excludes[i] === "string" && excludes[i] === name) {
|
||
return "";
|
||
} else if (excludes[i].test && excludes[i].test(name)) {
|
||
return "";
|
||
}
|
||
}
|
||
|
||
return name;
|
||
}
|
||
|
||
function isCircular(object, objects) {
|
||
if (typeof object !== "object") { return false; }
|
||
var i, l;
|
||
for (i = 0, l = objects.length; i < l; ++i) {
|
||
if (objects[i] === object) { return true; }
|
||
}
|
||
return false;
|
||
}
|
||
|
||
function ascii(f, object, processed, indent) {
|
||
if (typeof object === "string") {
|
||
var qs = f.quoteStrings;
|
||
var quote = typeof qs !== "boolean" || qs;
|
||
return processed || quote ? '"' + object + '"' : object;
|
||
}
|
||
|
||
if (typeof object === "function" && !(object instanceof RegExp)) {
|
||
return ascii.func(object);
|
||
}
|
||
|
||
processed = processed || [];
|
||
|
||
if (isCircular(object, processed)) { return "[Circular]"; }
|
||
|
||
if (Object.prototype.toString.call(object) === "[object Array]") {
|
||
return ascii.array.call(f, object, processed);
|
||
}
|
||
|
||
if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
|
||
if (samsam.isElement(object)) { return ascii.element(object); }
|
||
|
||
if (typeof object.toString === "function" &&
|
||
object.toString !== Object.prototype.toString) {
|
||
return object.toString();
|
||
}
|
||
|
||
var i, l;
|
||
for (i = 0, l = specialObjects.length; i < l; i++) {
|
||
if (object === specialObjects[i].object) {
|
||
return specialObjects[i].value;
|
||
}
|
||
}
|
||
|
||
return ascii.object.call(f, object, processed, indent);
|
||
}
|
||
|
||
ascii.func = function (func) {
|
||
return "function " + functionName(func) + "() {}";
|
||
};
|
||
|
||
ascii.array = function (array, processed) {
|
||
processed = processed || [];
|
||
processed.push(array);
|
||
var pieces = [];
|
||
var i, l;
|
||
l = (this.limitChildrenCount > 0) ?
|
||
Math.min(this.limitChildrenCount, array.length) : array.length;
|
||
|
||
for (i = 0; i < l; ++i) {
|
||
pieces.push(ascii(this, array[i], processed));
|
||
}
|
||
|
||
if(l < array.length)
|
||
pieces.push("[... " + (array.length - l) + " more elements]");
|
||
|
||
return "[" + pieces.join(", ") + "]";
|
||
};
|
||
|
||
ascii.object = function (object, processed, indent) {
|
||
processed = processed || [];
|
||
processed.push(object);
|
||
indent = indent || 0;
|
||
var pieces = [], properties = samsam.keys(object).sort();
|
||
var length = 3;
|
||
var prop, str, obj, i, k, l;
|
||
l = (this.limitChildrenCount > 0) ?
|
||
Math.min(this.limitChildrenCount, properties.length) : properties.length;
|
||
|
||
for (i = 0; i < l; ++i) {
|
||
prop = properties[i];
|
||
obj = object[prop];
|
||
|
||
if (isCircular(obj, processed)) {
|
||
str = "[Circular]";
|
||
} else {
|
||
str = ascii(this, obj, processed, indent + 2);
|
||
}
|
||
|
||
str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
|
||
length += str.length;
|
||
pieces.push(str);
|
||
}
|
||
|
||
var cons = constructorName(this, object);
|
||
var prefix = cons ? "[" + cons + "] " : "";
|
||
var is = "";
|
||
for (i = 0, k = indent; i < k; ++i) { is += " "; }
|
||
|
||
if(l < properties.length)
|
||
pieces.push("[... " + (properties.length - l) + " more elements]");
|
||
|
||
if (length + indent > 80) {
|
||
return prefix + "{\n " + is + pieces.join(",\n " + is) + "\n" +
|
||
is + "}";
|
||
}
|
||
return prefix + "{ " + pieces.join(", ") + " }";
|
||
};
|
||
|
||
ascii.element = function (element) {
|
||
var tagName = element.tagName.toLowerCase();
|
||
var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
|
||
|
||
for (i = 0, l = attrs.length; i < l; ++i) {
|
||
attr = attrs.item(i);
|
||
attrName = attr.nodeName.toLowerCase().replace("html:", "");
|
||
val = attr.nodeValue;
|
||
if (attrName !== "contenteditable" || val !== "inherit") {
|
||
if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
|
||
}
|
||
}
|
||
|
||
var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
|
||
var content = element.innerHTML;
|
||
|
||
if (content.length > 20) {
|
||
content = content.substr(0, 20) + "[...]";
|
||
}
|
||
|
||
var res = formatted + pairs.join(" ") + ">" + content +
|
||
"</" + tagName + ">";
|
||
|
||
return res.replace(/ contentEditable="inherit"/, "");
|
||
};
|
||
|
||
function Formatio(options) {
|
||
for (var opt in options) {
|
||
this[opt] = options[opt];
|
||
}
|
||
}
|
||
|
||
Formatio.prototype = {
|
||
functionName: functionName,
|
||
|
||
configure: function (options) {
|
||
return new Formatio(options);
|
||
},
|
||
|
||
constructorName: function (object) {
|
||
return constructorName(this, object);
|
||
},
|
||
|
||
ascii: function (object, processed, indent) {
|
||
return ascii(this, object, processed, indent);
|
||
}
|
||
};
|
||
|
||
return Formatio.prototype;
|
||
});
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"samsam":62}],62:[function(require,module,exports){
|
||
((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
|
||
(typeof module === "object" &&
|
||
function (m) { module.exports = m(); }) || // Node
|
||
function (m) { this.samsam = m(); } // Browser globals
|
||
)(function () {
|
||
var o = Object.prototype;
|
||
var div = typeof document !== "undefined" && document.createElement("div");
|
||
|
||
function isNaN(value) {
|
||
// Unlike global isNaN, this avoids type coercion
|
||
// typeof check avoids IE host object issues, hat tip to
|
||
// lodash
|
||
var val = value; // JsLint thinks value !== value is "weird"
|
||
return typeof value === "number" && value !== val;
|
||
}
|
||
|
||
function getClass(value) {
|
||
// Returns the internal [[Class]] by calling Object.prototype.toString
|
||
// with the provided value as this. Return value is a string, naming the
|
||
// internal class, e.g. "Array"
|
||
return o.toString.call(value).split(/[ \]]/)[1];
|
||
}
|
||
|
||
/**
|
||
* @name samsam.isArguments
|
||
* @param Object object
|
||
*
|
||
* Returns ``true`` if ``object`` is an ``arguments`` object,
|
||
* ``false`` otherwise.
|
||
*/
|
||
function isArguments(object) {
|
||
if (getClass(object) === 'Arguments') { return true; }
|
||
if (typeof object !== "object" || typeof object.length !== "number" ||
|
||
getClass(object) === "Array") {
|
||
return false;
|
||
}
|
||
if (typeof object.callee == "function") { return true; }
|
||
try {
|
||
object[object.length] = 6;
|
||
delete object[object.length];
|
||
} catch (e) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* @name samsam.isElement
|
||
* @param Object object
|
||
*
|
||
* Returns ``true`` if ``object`` is a DOM element node. Unlike
|
||
* Underscore.js/lodash, this function will return ``false`` if ``object``
|
||
* is an *element-like* object, i.e. a regular object with a ``nodeType``
|
||
* property that holds the value ``1``.
|
||
*/
|
||
function isElement(object) {
|
||
if (!object || object.nodeType !== 1 || !div) { return false; }
|
||
try {
|
||
object.appendChild(div);
|
||
object.removeChild(div);
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* @name samsam.keys
|
||
* @param Object object
|
||
*
|
||
* Return an array of own property names.
|
||
*/
|
||
function keys(object) {
|
||
var ks = [], prop;
|
||
for (prop in object) {
|
||
if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
|
||
}
|
||
return ks;
|
||
}
|
||
|
||
/**
|
||
* @name samsam.isDate
|
||
* @param Object value
|
||
*
|
||
* Returns true if the object is a ``Date``, or *date-like*. Duck typing
|
||
* of date objects work by checking that the object has a ``getTime``
|
||
* function whose return value equals the return value from the object's
|
||
* ``valueOf``.
|
||
*/
|
||
function isDate(value) {
|
||
return typeof value.getTime == "function" &&
|
||
value.getTime() == value.valueOf();
|
||
}
|
||
|
||
/**
|
||
* @name samsam.isNegZero
|
||
* @param Object value
|
||
*
|
||
* Returns ``true`` if ``value`` is ``-0``.
|
||
*/
|
||
function isNegZero(value) {
|
||
return value === 0 && 1 / value === -Infinity;
|
||
}
|
||
|
||
/**
|
||
* @name samsam.equal
|
||
* @param Object obj1
|
||
* @param Object obj2
|
||
*
|
||
* Returns ``true`` if two objects are strictly equal. Compared to
|
||
* ``===`` there are two exceptions:
|
||
*
|
||
* - NaN is considered equal to NaN
|
||
* - -0 and +0 are not considered equal
|
||
*/
|
||
function identical(obj1, obj2) {
|
||
if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
|
||
return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @name samsam.deepEqual
|
||
* @param Object obj1
|
||
* @param Object obj2
|
||
*
|
||
* Deep equal comparison. Two values are "deep equal" if:
|
||
*
|
||
* - They are equal, according to samsam.identical
|
||
* - They are both date objects representing the same time
|
||
* - They are both arrays containing elements that are all deepEqual
|
||
* - They are objects with the same set of properties, and each property
|
||
* in ``obj1`` is deepEqual to the corresponding property in ``obj2``
|
||
*
|
||
* Supports cyclic objects.
|
||
*/
|
||
function deepEqualCyclic(obj1, obj2) {
|
||
|
||
// used for cyclic comparison
|
||
// contain already visited objects
|
||
var objects1 = [],
|
||
objects2 = [],
|
||
// contain pathes (position in the object structure)
|
||
// of the already visited objects
|
||
// indexes same as in objects arrays
|
||
paths1 = [],
|
||
paths2 = [],
|
||
// contains combinations of already compared objects
|
||
// in the manner: { "$1['ref']$2['ref']": true }
|
||
compared = {};
|
||
|
||
/**
|
||
* used to check, if the value of a property is an object
|
||
* (cyclic logic is only needed for objects)
|
||
* only needed for cyclic logic
|
||
*/
|
||
function isObject(value) {
|
||
|
||
if (typeof value === 'object' && value !== null &&
|
||
!(value instanceof Boolean) &&
|
||
!(value instanceof Date) &&
|
||
!(value instanceof Number) &&
|
||
!(value instanceof RegExp) &&
|
||
!(value instanceof String)) {
|
||
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* returns the index of the given object in the
|
||
* given objects array, -1 if not contained
|
||
* only needed for cyclic logic
|
||
*/
|
||
function getIndex(objects, obj) {
|
||
|
||
var i;
|
||
for (i = 0; i < objects.length; i++) {
|
||
if (objects[i] === obj) {
|
||
return i;
|
||
}
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
// does the recursion for the deep equal check
|
||
return (function deepEqual(obj1, obj2, path1, path2) {
|
||
var type1 = typeof obj1;
|
||
var type2 = typeof obj2;
|
||
|
||
// == null also matches undefined
|
||
if (obj1 === obj2 ||
|
||
isNaN(obj1) || isNaN(obj2) ||
|
||
obj1 == null || obj2 == null ||
|
||
type1 !== "object" || type2 !== "object") {
|
||
|
||
return identical(obj1, obj2);
|
||
}
|
||
|
||
// Elements are only equal if identical(expected, actual)
|
||
if (isElement(obj1) || isElement(obj2)) { return false; }
|
||
|
||
var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
|
||
if (isDate1 || isDate2) {
|
||
if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
|
||
if (obj1.toString() !== obj2.toString()) { return false; }
|
||
}
|
||
|
||
var class1 = getClass(obj1);
|
||
var class2 = getClass(obj2);
|
||
var keys1 = keys(obj1);
|
||
var keys2 = keys(obj2);
|
||
|
||
if (isArguments(obj1) || isArguments(obj2)) {
|
||
if (obj1.length !== obj2.length) { return false; }
|
||
} else {
|
||
if (type1 !== type2 || class1 !== class2 ||
|
||
keys1.length !== keys2.length) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
var key, i, l,
|
||
// following vars are used for the cyclic logic
|
||
value1, value2,
|
||
isObject1, isObject2,
|
||
index1, index2,
|
||
newPath1, newPath2;
|
||
|
||
for (i = 0, l = keys1.length; i < l; i++) {
|
||
key = keys1[i];
|
||
if (!o.hasOwnProperty.call(obj2, key)) {
|
||
return false;
|
||
}
|
||
|
||
// Start of the cyclic logic
|
||
|
||
value1 = obj1[key];
|
||
value2 = obj2[key];
|
||
|
||
isObject1 = isObject(value1);
|
||
isObject2 = isObject(value2);
|
||
|
||
// determine, if the objects were already visited
|
||
// (it's faster to check for isObject first, than to
|
||
// get -1 from getIndex for non objects)
|
||
index1 = isObject1 ? getIndex(objects1, value1) : -1;
|
||
index2 = isObject2 ? getIndex(objects2, value2) : -1;
|
||
|
||
// determine the new pathes of the objects
|
||
// - for non cyclic objects the current path will be extended
|
||
// by current property name
|
||
// - for cyclic objects the stored path is taken
|
||
newPath1 = index1 !== -1
|
||
? paths1[index1]
|
||
: path1 + '[' + JSON.stringify(key) + ']';
|
||
newPath2 = index2 !== -1
|
||
? paths2[index2]
|
||
: path2 + '[' + JSON.stringify(key) + ']';
|
||
|
||
// stop recursion if current objects are already compared
|
||
if (compared[newPath1 + newPath2]) {
|
||
return true;
|
||
}
|
||
|
||
// remember the current objects and their pathes
|
||
if (index1 === -1 && isObject1) {
|
||
objects1.push(value1);
|
||
paths1.push(newPath1);
|
||
}
|
||
if (index2 === -1 && isObject2) {
|
||
objects2.push(value2);
|
||
paths2.push(newPath2);
|
||
}
|
||
|
||
// remember that the current objects are already compared
|
||
if (isObject1 && isObject2) {
|
||
compared[newPath1 + newPath2] = true;
|
||
}
|
||
|
||
// End of cyclic logic
|
||
|
||
// neither value1 nor value2 is a cycle
|
||
// continue with next level
|
||
if (!deepEqual(value1, value2, newPath1, newPath2)) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
|
||
}(obj1, obj2, '$1', '$2'));
|
||
}
|
||
|
||
var match;
|
||
|
||
function arrayContains(array, subset) {
|
||
if (subset.length === 0) { return true; }
|
||
var i, l, j, k;
|
||
for (i = 0, l = array.length; i < l; ++i) {
|
||
if (match(array[i], subset[0])) {
|
||
for (j = 0, k = subset.length; j < k; ++j) {
|
||
if (!match(array[i + j], subset[j])) { return false; }
|
||
}
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* @name samsam.match
|
||
* @param Object object
|
||
* @param Object matcher
|
||
*
|
||
* Compare arbitrary value ``object`` with matcher.
|
||
*/
|
||
match = function match(object, matcher) {
|
||
if (matcher && typeof matcher.test === "function") {
|
||
return matcher.test(object);
|
||
}
|
||
|
||
if (typeof matcher === "function") {
|
||
return matcher(object) === true;
|
||
}
|
||
|
||
if (typeof matcher === "string") {
|
||
matcher = matcher.toLowerCase();
|
||
var notNull = typeof object === "string" || !!object;
|
||
return notNull &&
|
||
(String(object)).toLowerCase().indexOf(matcher) >= 0;
|
||
}
|
||
|
||
if (typeof matcher === "number") {
|
||
return matcher === object;
|
||
}
|
||
|
||
if (typeof matcher === "boolean") {
|
||
return matcher === object;
|
||
}
|
||
|
||
if (typeof(matcher) === "undefined") {
|
||
return typeof(object) === "undefined";
|
||
}
|
||
|
||
if (matcher === null) {
|
||
return object === null;
|
||
}
|
||
|
||
if (getClass(object) === "Array" && getClass(matcher) === "Array") {
|
||
return arrayContains(object, matcher);
|
||
}
|
||
|
||
if (matcher && typeof matcher === "object") {
|
||
if (matcher === object) {
|
||
return true;
|
||
}
|
||
var prop;
|
||
for (prop in matcher) {
|
||
var value = object[prop];
|
||
if (typeof value === "undefined" &&
|
||
typeof object.getAttribute === "function") {
|
||
value = object.getAttribute(prop);
|
||
}
|
||
if (matcher[prop] === null || typeof matcher[prop] === 'undefined') {
|
||
if (value !== matcher[prop]) {
|
||
return false;
|
||
}
|
||
} else if (typeof value === "undefined" || !match(value, matcher[prop])) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
throw new Error("Matcher was not a string, a number, a " +
|
||
"function, a boolean or an object");
|
||
};
|
||
|
||
return {
|
||
isArguments: isArguments,
|
||
isElement: isElement,
|
||
isDate: isDate,
|
||
isNegZero: isNegZero,
|
||
identical: identical,
|
||
deepEqual: deepEqualCyclic,
|
||
match: match,
|
||
keys: keys
|
||
};
|
||
});
|
||
|
||
},{}],63:[function(require,module,exports){
|
||
(function (global){
|
||
/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
|
||
/*global global*/
|
||
/**
|
||
* @author Christian Johansen (christian@cjohansen.no) and contributors
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2014 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
// node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
|
||
// browsers, a number.
|
||
// see https://github.com/cjohansen/Sinon.JS/pull/436
|
||
var timeoutResult = setTimeout(function() {}, 0);
|
||
var addTimerReturnsObject = typeof timeoutResult === "object";
|
||
clearTimeout(timeoutResult);
|
||
|
||
var NativeDate = Date;
|
||
var id = 1;
|
||
|
||
/**
|
||
* Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
|
||
* number of milliseconds. This is used to support human-readable strings passed
|
||
* to clock.tick()
|
||
*/
|
||
function parseTime(str) {
|
||
if (!str) {
|
||
return 0;
|
||
}
|
||
|
||
var strings = str.split(":");
|
||
var l = strings.length, i = l;
|
||
var ms = 0, parsed;
|
||
|
||
if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
|
||
throw new Error("tick only understands numbers and 'h:m:s'");
|
||
}
|
||
|
||
while (i--) {
|
||
parsed = parseInt(strings[i], 10);
|
||
|
||
if (parsed >= 60) {
|
||
throw new Error("Invalid time " + str);
|
||
}
|
||
|
||
ms += parsed * Math.pow(60, (l - i - 1));
|
||
}
|
||
|
||
return ms * 1000;
|
||
}
|
||
|
||
/**
|
||
* Used to grok the `now` parameter to createClock.
|
||
*/
|
||
function getEpoch(epoch) {
|
||
if (!epoch) { return 0; }
|
||
if (typeof epoch.getTime === "function") { return epoch.getTime(); }
|
||
if (typeof epoch === "number") { return epoch; }
|
||
throw new TypeError("now should be milliseconds since UNIX epoch");
|
||
}
|
||
|
||
function inRange(from, to, timer) {
|
||
return timer && timer.callAt >= from && timer.callAt <= to;
|
||
}
|
||
|
||
function mirrorDateProperties(target, source) {
|
||
if (source.now) {
|
||
target.now = function now() {
|
||
return target.clock.now;
|
||
};
|
||
} else {
|
||
delete target.now;
|
||
}
|
||
|
||
if (source.toSource) {
|
||
target.toSource = function toSource() {
|
||
return source.toSource();
|
||
};
|
||
} else {
|
||
delete target.toSource;
|
||
}
|
||
|
||
target.toString = function toString() {
|
||
return source.toString();
|
||
};
|
||
|
||
target.prototype = source.prototype;
|
||
target.parse = source.parse;
|
||
target.UTC = source.UTC;
|
||
target.prototype.toUTCString = source.prototype.toUTCString;
|
||
|
||
for (var prop in source) {
|
||
if (source.hasOwnProperty(prop)) {
|
||
target[prop] = source[prop];
|
||
}
|
||
}
|
||
|
||
return target;
|
||
}
|
||
|
||
function createDate() {
|
||
function ClockDate(year, month, date, hour, minute, second, ms) {
|
||
// Defensive and verbose to avoid potential harm in passing
|
||
// explicit undefined when user does not pass argument
|
||
switch (arguments.length) {
|
||
case 0:
|
||
return new NativeDate(ClockDate.clock.now);
|
||
case 1:
|
||
return new NativeDate(year);
|
||
case 2:
|
||
return new NativeDate(year, month);
|
||
case 3:
|
||
return new NativeDate(year, month, date);
|
||
case 4:
|
||
return new NativeDate(year, month, date, hour);
|
||
case 5:
|
||
return new NativeDate(year, month, date, hour, minute);
|
||
case 6:
|
||
return new NativeDate(year, month, date, hour, minute, second);
|
||
default:
|
||
return new NativeDate(year, month, date, hour, minute, second, ms);
|
||
}
|
||
}
|
||
|
||
return mirrorDateProperties(ClockDate, NativeDate);
|
||
}
|
||
|
||
function addTimer(clock, timer) {
|
||
if (typeof timer.func === "undefined") {
|
||
throw new Error("Callback must be provided to timer calls");
|
||
}
|
||
|
||
if (!clock.timers) {
|
||
clock.timers = {};
|
||
}
|
||
|
||
timer.id = id++;
|
||
timer.createdAt = clock.now;
|
||
timer.callAt = clock.now + (timer.delay || 0);
|
||
|
||
clock.timers[timer.id] = timer;
|
||
|
||
if (addTimerReturnsObject) {
|
||
return {
|
||
id: timer.id,
|
||
ref: function() {},
|
||
unref: function() {}
|
||
};
|
||
}
|
||
else {
|
||
return timer.id;
|
||
}
|
||
}
|
||
|
||
function firstTimerInRange(clock, from, to) {
|
||
var timers = clock.timers, timer = null;
|
||
|
||
for (var id in timers) {
|
||
if (!inRange(from, to, timers[id])) {
|
||
continue;
|
||
}
|
||
|
||
if (!timer || ~compareTimers(timer, timers[id])) {
|
||
timer = timers[id];
|
||
}
|
||
}
|
||
|
||
return timer;
|
||
}
|
||
|
||
function compareTimers(a, b) {
|
||
// Sort first by absolute timing
|
||
if (a.callAt < b.callAt) {
|
||
return -1;
|
||
}
|
||
if (a.callAt > b.callAt) {
|
||
return 1;
|
||
}
|
||
|
||
// Sort next by immediate, immediate timers take precedence
|
||
if (a.immediate && !b.immediate) {
|
||
return -1;
|
||
}
|
||
if (!a.immediate && b.immediate) {
|
||
return 1;
|
||
}
|
||
|
||
// Sort next by creation time, earlier-created timers take precedence
|
||
if (a.createdAt < b.createdAt) {
|
||
return -1;
|
||
}
|
||
if (a.createdAt > b.createdAt) {
|
||
return 1;
|
||
}
|
||
|
||
// Sort next by id, lower-id timers take precedence
|
||
if (a.id < b.id) {
|
||
return -1;
|
||
}
|
||
if (a.id > b.id) {
|
||
return 1;
|
||
}
|
||
|
||
// As timer ids are unique, no fallback `0` is necessary
|
||
}
|
||
|
||
function callTimer(clock, timer) {
|
||
if (typeof timer.interval == "number") {
|
||
clock.timers[timer.id].callAt += timer.interval;
|
||
} else {
|
||
delete clock.timers[timer.id];
|
||
}
|
||
|
||
try {
|
||
if (typeof timer.func == "function") {
|
||
timer.func.apply(null, timer.args);
|
||
} else {
|
||
eval(timer.func);
|
||
}
|
||
} catch (e) {
|
||
var exception = e;
|
||
}
|
||
|
||
if (!clock.timers[timer.id]) {
|
||
if (exception) {
|
||
throw exception;
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (exception) {
|
||
throw exception;
|
||
}
|
||
}
|
||
|
||
function uninstall(clock, target) {
|
||
var method;
|
||
|
||
for (var i = 0, l = clock.methods.length; i < l; i++) {
|
||
method = clock.methods[i];
|
||
|
||
if (target[method].hadOwnProperty) {
|
||
target[method] = clock["_" + method];
|
||
} else {
|
||
try {
|
||
delete target[method];
|
||
} catch (e) {}
|
||
}
|
||
}
|
||
|
||
// Prevent multiple executions which will completely remove these props
|
||
clock.methods = [];
|
||
}
|
||
|
||
function hijackMethod(target, method, clock) {
|
||
clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
|
||
clock["_" + method] = target[method];
|
||
|
||
if (method == "Date") {
|
||
var date = mirrorDateProperties(clock[method], target[method]);
|
||
target[method] = date;
|
||
} else {
|
||
target[method] = function () {
|
||
return clock[method].apply(clock, arguments);
|
||
};
|
||
|
||
for (var prop in clock[method]) {
|
||
if (clock[method].hasOwnProperty(prop)) {
|
||
target[method][prop] = clock[method][prop];
|
||
}
|
||
}
|
||
}
|
||
|
||
target[method].clock = clock;
|
||
}
|
||
|
||
var timers = {
|
||
setTimeout: setTimeout,
|
||
clearTimeout: clearTimeout,
|
||
setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
|
||
clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
|
||
setInterval: setInterval,
|
||
clearInterval: clearInterval,
|
||
Date: Date
|
||
};
|
||
|
||
var keys = Object.keys || function (obj) {
|
||
var ks = [];
|
||
for (var key in obj) {
|
||
ks.push(key);
|
||
}
|
||
return ks;
|
||
};
|
||
|
||
exports.timers = timers;
|
||
|
||
var createClock = exports.createClock = function (now) {
|
||
var clock = {
|
||
now: getEpoch(now),
|
||
timeouts: {},
|
||
Date: createDate()
|
||
};
|
||
|
||
clock.Date.clock = clock;
|
||
|
||
clock.setTimeout = function setTimeout(func, timeout) {
|
||
return addTimer(clock, {
|
||
func: func,
|
||
args: Array.prototype.slice.call(arguments, 2),
|
||
delay: timeout
|
||
});
|
||
};
|
||
|
||
clock.clearTimeout = function clearTimeout(timerId) {
|
||
if (!timerId) {
|
||
// null appears to be allowed in most browsers, and appears to be
|
||
// relied upon by some libraries, like Bootstrap carousel
|
||
return;
|
||
}
|
||
if (!clock.timers) {
|
||
clock.timers = [];
|
||
}
|
||
// in Node, timerId is an object with .ref()/.unref(), and
|
||
// its .id field is the actual timer id.
|
||
if (typeof timerId === "object") {
|
||
timerId = timerId.id
|
||
}
|
||
if (timerId in clock.timers) {
|
||
delete clock.timers[timerId];
|
||
}
|
||
};
|
||
|
||
clock.setInterval = function setInterval(func, timeout) {
|
||
return addTimer(clock, {
|
||
func: func,
|
||
args: Array.prototype.slice.call(arguments, 2),
|
||
delay: timeout,
|
||
interval: timeout
|
||
});
|
||
};
|
||
|
||
clock.clearInterval = function clearInterval(timerId) {
|
||
clock.clearTimeout(timerId);
|
||
};
|
||
|
||
clock.setImmediate = function setImmediate(func) {
|
||
return addTimer(clock, {
|
||
func: func,
|
||
args: Array.prototype.slice.call(arguments, 1),
|
||
immediate: true
|
||
});
|
||
};
|
||
|
||
clock.clearImmediate = function clearImmediate(timerId) {
|
||
clock.clearTimeout(timerId);
|
||
};
|
||
|
||
clock.tick = function tick(ms) {
|
||
ms = typeof ms == "number" ? ms : parseTime(ms);
|
||
var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now;
|
||
var timer = firstTimerInRange(clock, tickFrom, tickTo);
|
||
|
||
var firstException;
|
||
while (timer && tickFrom <= tickTo) {
|
||
if (clock.timers[timer.id]) {
|
||
tickFrom = clock.now = timer.callAt;
|
||
try {
|
||
callTimer(clock, timer);
|
||
} catch (e) {
|
||
firstException = firstException || e;
|
||
}
|
||
}
|
||
|
||
timer = firstTimerInRange(clock, previous, tickTo);
|
||
previous = tickFrom;
|
||
}
|
||
|
||
clock.now = tickTo;
|
||
|
||
if (firstException) {
|
||
throw firstException;
|
||
}
|
||
|
||
return clock.now;
|
||
};
|
||
|
||
clock.reset = function reset() {
|
||
clock.timers = {};
|
||
};
|
||
|
||
return clock;
|
||
};
|
||
|
||
exports.install = function install(target, now, toFake) {
|
||
if (typeof target === "number") {
|
||
toFake = now;
|
||
now = target;
|
||
target = null;
|
||
}
|
||
|
||
if (!target) {
|
||
target = global;
|
||
}
|
||
|
||
var clock = createClock(now);
|
||
|
||
clock.uninstall = function () {
|
||
uninstall(clock, target);
|
||
};
|
||
|
||
clock.methods = toFake || [];
|
||
|
||
if (clock.methods.length === 0) {
|
||
clock.methods = keys(timers);
|
||
}
|
||
|
||
for (var i = 0, l = clock.methods.length; i < l; i++) {
|
||
hijackMethod(target, clock.methods[i], clock);
|
||
}
|
||
|
||
return clock;
|
||
};
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{}],64:[function(require,module,exports){
|
||
// Underscore.js 1.8.3
|
||
// http://underscorejs.org
|
||
// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||
// Underscore may be freely distributed under the MIT license.
|
||
|
||
(function() {
|
||
|
||
// Baseline setup
|
||
// --------------
|
||
|
||
// Establish the root object, `window` in the browser, or `exports` on the server.
|
||
var root = this;
|
||
|
||
// Save the previous value of the `_` variable.
|
||
var previousUnderscore = root._;
|
||
|
||
// Save bytes in the minified (but not gzipped) version:
|
||
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
|
||
|
||
// Create quick reference variables for speed access to core prototypes.
|
||
var
|
||
push = ArrayProto.push,
|
||
slice = ArrayProto.slice,
|
||
toString = ObjProto.toString,
|
||
hasOwnProperty = ObjProto.hasOwnProperty;
|
||
|
||
// All **ECMAScript 5** native function implementations that we hope to use
|
||
// are declared here.
|
||
var
|
||
nativeIsArray = Array.isArray,
|
||
nativeKeys = Object.keys,
|
||
nativeBind = FuncProto.bind,
|
||
nativeCreate = Object.create;
|
||
|
||
// Naked function reference for surrogate-prototype-swapping.
|
||
var Ctor = function(){};
|
||
|
||
// Create a safe reference to the Underscore object for use below.
|
||
var _ = function(obj) {
|
||
if (obj instanceof _) return obj;
|
||
if (!(this instanceof _)) return new _(obj);
|
||
this._wrapped = obj;
|
||
};
|
||
|
||
// Export the Underscore object for **Node.js**, with
|
||
// backwards-compatibility for the old `require()` API. If we're in
|
||
// the browser, add `_` as a global object.
|
||
if (typeof exports !== 'undefined') {
|
||
if (typeof module !== 'undefined' && module.exports) {
|
||
exports = module.exports = _;
|
||
}
|
||
exports._ = _;
|
||
} else {
|
||
root._ = _;
|
||
}
|
||
|
||
// Current version.
|
||
_.VERSION = '1.8.3';
|
||
|
||
// Internal function that returns an efficient (for current engines) version
|
||
// of the passed-in callback, to be repeatedly applied in other Underscore
|
||
// functions.
|
||
var optimizeCb = function(func, context, argCount) {
|
||
if (context === void 0) return func;
|
||
switch (argCount == null ? 3 : argCount) {
|
||
case 1: return function(value) {
|
||
return func.call(context, value);
|
||
};
|
||
case 2: return function(value, other) {
|
||
return func.call(context, value, other);
|
||
};
|
||
case 3: return function(value, index, collection) {
|
||
return func.call(context, value, index, collection);
|
||
};
|
||
case 4: return function(accumulator, value, index, collection) {
|
||
return func.call(context, accumulator, value, index, collection);
|
||
};
|
||
}
|
||
return function() {
|
||
return func.apply(context, arguments);
|
||
};
|
||
};
|
||
|
||
// A mostly-internal function to generate callbacks that can be applied
|
||
// to each element in a collection, returning the desired result — either
|
||
// identity, an arbitrary callback, a property matcher, or a property accessor.
|
||
var cb = function(value, context, argCount) {
|
||
if (value == null) return _.identity;
|
||
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
|
||
if (_.isObject(value)) return _.matcher(value);
|
||
return _.property(value);
|
||
};
|
||
_.iteratee = function(value, context) {
|
||
return cb(value, context, Infinity);
|
||
};
|
||
|
||
// An internal function for creating assigner functions.
|
||
var createAssigner = function(keysFunc, undefinedOnly) {
|
||
return function(obj) {
|
||
var length = arguments.length;
|
||
if (length < 2 || obj == null) return obj;
|
||
for (var index = 1; index < length; index++) {
|
||
var source = arguments[index],
|
||
keys = keysFunc(source),
|
||
l = keys.length;
|
||
for (var i = 0; i < l; i++) {
|
||
var key = keys[i];
|
||
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
|
||
}
|
||
}
|
||
return obj;
|
||
};
|
||
};
|
||
|
||
// An internal function for creating a new object that inherits from another.
|
||
var baseCreate = function(prototype) {
|
||
if (!_.isObject(prototype)) return {};
|
||
if (nativeCreate) return nativeCreate(prototype);
|
||
Ctor.prototype = prototype;
|
||
var result = new Ctor;
|
||
Ctor.prototype = null;
|
||
return result;
|
||
};
|
||
|
||
var property = function(key) {
|
||
return function(obj) {
|
||
return obj == null ? void 0 : obj[key];
|
||
};
|
||
};
|
||
|
||
// Helper for collection methods to determine whether a collection
|
||
// should be iterated as an array or as an object
|
||
// Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
|
||
// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
|
||
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
|
||
var getLength = property('length');
|
||
var isArrayLike = function(collection) {
|
||
var length = getLength(collection);
|
||
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
|
||
};
|
||
|
||
// Collection Functions
|
||
// --------------------
|
||
|
||
// The cornerstone, an `each` implementation, aka `forEach`.
|
||
// Handles raw objects in addition to array-likes. Treats all
|
||
// sparse array-likes as if they were dense.
|
||
_.each = _.forEach = function(obj, iteratee, context) {
|
||
iteratee = optimizeCb(iteratee, context);
|
||
var i, length;
|
||
if (isArrayLike(obj)) {
|
||
for (i = 0, length = obj.length; i < length; i++) {
|
||
iteratee(obj[i], i, obj);
|
||
}
|
||
} else {
|
||
var keys = _.keys(obj);
|
||
for (i = 0, length = keys.length; i < length; i++) {
|
||
iteratee(obj[keys[i]], keys[i], obj);
|
||
}
|
||
}
|
||
return obj;
|
||
};
|
||
|
||
// Return the results of applying the iteratee to each element.
|
||
_.map = _.collect = function(obj, iteratee, context) {
|
||
iteratee = cb(iteratee, context);
|
||
var keys = !isArrayLike(obj) && _.keys(obj),
|
||
length = (keys || obj).length,
|
||
results = Array(length);
|
||
for (var index = 0; index < length; index++) {
|
||
var currentKey = keys ? keys[index] : index;
|
||
results[index] = iteratee(obj[currentKey], currentKey, obj);
|
||
}
|
||
return results;
|
||
};
|
||
|
||
// Create a reducing function iterating left or right.
|
||
function createReduce(dir) {
|
||
// Optimized iterator function as using arguments.length
|
||
// in the main function will deoptimize the, see #1991.
|
||
function iterator(obj, iteratee, memo, keys, index, length) {
|
||
for (; index >= 0 && index < length; index += dir) {
|
||
var currentKey = keys ? keys[index] : index;
|
||
memo = iteratee(memo, obj[currentKey], currentKey, obj);
|
||
}
|
||
return memo;
|
||
}
|
||
|
||
return function(obj, iteratee, memo, context) {
|
||
iteratee = optimizeCb(iteratee, context, 4);
|
||
var keys = !isArrayLike(obj) && _.keys(obj),
|
||
length = (keys || obj).length,
|
||
index = dir > 0 ? 0 : length - 1;
|
||
// Determine the initial value if none is provided.
|
||
if (arguments.length < 3) {
|
||
memo = obj[keys ? keys[index] : index];
|
||
index += dir;
|
||
}
|
||
return iterator(obj, iteratee, memo, keys, index, length);
|
||
};
|
||
}
|
||
|
||
// **Reduce** builds up a single result from a list of values, aka `inject`,
|
||
// or `foldl`.
|
||
_.reduce = _.foldl = _.inject = createReduce(1);
|
||
|
||
// The right-associative version of reduce, also known as `foldr`.
|
||
_.reduceRight = _.foldr = createReduce(-1);
|
||
|
||
// Return the first value which passes a truth test. Aliased as `detect`.
|
||
_.find = _.detect = function(obj, predicate, context) {
|
||
var key;
|
||
if (isArrayLike(obj)) {
|
||
key = _.findIndex(obj, predicate, context);
|
||
} else {
|
||
key = _.findKey(obj, predicate, context);
|
||
}
|
||
if (key !== void 0 && key !== -1) return obj[key];
|
||
};
|
||
|
||
// Return all the elements that pass a truth test.
|
||
// Aliased as `select`.
|
||
_.filter = _.select = function(obj, predicate, context) {
|
||
var results = [];
|
||
predicate = cb(predicate, context);
|
||
_.each(obj, function(value, index, list) {
|
||
if (predicate(value, index, list)) results.push(value);
|
||
});
|
||
return results;
|
||
};
|
||
|
||
// Return all the elements for which a truth test fails.
|
||
_.reject = function(obj, predicate, context) {
|
||
return _.filter(obj, _.negate(cb(predicate)), context);
|
||
};
|
||
|
||
// Determine whether all of the elements match a truth test.
|
||
// Aliased as `all`.
|
||
_.every = _.all = function(obj, predicate, context) {
|
||
predicate = cb(predicate, context);
|
||
var keys = !isArrayLike(obj) && _.keys(obj),
|
||
length = (keys || obj).length;
|
||
for (var index = 0; index < length; index++) {
|
||
var currentKey = keys ? keys[index] : index;
|
||
if (!predicate(obj[currentKey], currentKey, obj)) return false;
|
||
}
|
||
return true;
|
||
};
|
||
|
||
// Determine if at least one element in the object matches a truth test.
|
||
// Aliased as `any`.
|
||
_.some = _.any = function(obj, predicate, context) {
|
||
predicate = cb(predicate, context);
|
||
var keys = !isArrayLike(obj) && _.keys(obj),
|
||
length = (keys || obj).length;
|
||
for (var index = 0; index < length; index++) {
|
||
var currentKey = keys ? keys[index] : index;
|
||
if (predicate(obj[currentKey], currentKey, obj)) return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
// Determine if the array or object contains a given item (using `===`).
|
||
// Aliased as `includes` and `include`.
|
||
_.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
|
||
if (!isArrayLike(obj)) obj = _.values(obj);
|
||
if (typeof fromIndex != 'number' || guard) fromIndex = 0;
|
||
return _.indexOf(obj, item, fromIndex) >= 0;
|
||
};
|
||
|
||
// Invoke a method (with arguments) on every item in a collection.
|
||
_.invoke = function(obj, method) {
|
||
var args = slice.call(arguments, 2);
|
||
var isFunc = _.isFunction(method);
|
||
return _.map(obj, function(value) {
|
||
var func = isFunc ? method : value[method];
|
||
return func == null ? func : func.apply(value, args);
|
||
});
|
||
};
|
||
|
||
// Convenience version of a common use case of `map`: fetching a property.
|
||
_.pluck = function(obj, key) {
|
||
return _.map(obj, _.property(key));
|
||
};
|
||
|
||
// Convenience version of a common use case of `filter`: selecting only objects
|
||
// containing specific `key:value` pairs.
|
||
_.where = function(obj, attrs) {
|
||
return _.filter(obj, _.matcher(attrs));
|
||
};
|
||
|
||
// Convenience version of a common use case of `find`: getting the first object
|
||
// containing specific `key:value` pairs.
|
||
_.findWhere = function(obj, attrs) {
|
||
return _.find(obj, _.matcher(attrs));
|
||
};
|
||
|
||
// Return the maximum element (or element-based computation).
|
||
_.max = function(obj, iteratee, context) {
|
||
var result = -Infinity, lastComputed = -Infinity,
|
||
value, computed;
|
||
if (iteratee == null && obj != null) {
|
||
obj = isArrayLike(obj) ? obj : _.values(obj);
|
||
for (var i = 0, length = obj.length; i < length; i++) {
|
||
value = obj[i];
|
||
if (value > result) {
|
||
result = value;
|
||
}
|
||
}
|
||
} else {
|
||
iteratee = cb(iteratee, context);
|
||
_.each(obj, function(value, index, list) {
|
||
computed = iteratee(value, index, list);
|
||
if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
|
||
result = value;
|
||
lastComputed = computed;
|
||
}
|
||
});
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Return the minimum element (or element-based computation).
|
||
_.min = function(obj, iteratee, context) {
|
||
var result = Infinity, lastComputed = Infinity,
|
||
value, computed;
|
||
if (iteratee == null && obj != null) {
|
||
obj = isArrayLike(obj) ? obj : _.values(obj);
|
||
for (var i = 0, length = obj.length; i < length; i++) {
|
||
value = obj[i];
|
||
if (value < result) {
|
||
result = value;
|
||
}
|
||
}
|
||
} else {
|
||
iteratee = cb(iteratee, context);
|
||
_.each(obj, function(value, index, list) {
|
||
computed = iteratee(value, index, list);
|
||
if (computed < lastComputed || computed === Infinity && result === Infinity) {
|
||
result = value;
|
||
lastComputed = computed;
|
||
}
|
||
});
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Shuffle a collection, using the modern version of the
|
||
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
|
||
_.shuffle = function(obj) {
|
||
var set = isArrayLike(obj) ? obj : _.values(obj);
|
||
var length = set.length;
|
||
var shuffled = Array(length);
|
||
for (var index = 0, rand; index < length; index++) {
|
||
rand = _.random(0, index);
|
||
if (rand !== index) shuffled[index] = shuffled[rand];
|
||
shuffled[rand] = set[index];
|
||
}
|
||
return shuffled;
|
||
};
|
||
|
||
// Sample **n** random values from a collection.
|
||
// If **n** is not specified, returns a single random element.
|
||
// The internal `guard` argument allows it to work with `map`.
|
||
_.sample = function(obj, n, guard) {
|
||
if (n == null || guard) {
|
||
if (!isArrayLike(obj)) obj = _.values(obj);
|
||
return obj[_.random(obj.length - 1)];
|
||
}
|
||
return _.shuffle(obj).slice(0, Math.max(0, n));
|
||
};
|
||
|
||
// Sort the object's values by a criterion produced by an iteratee.
|
||
_.sortBy = function(obj, iteratee, context) {
|
||
iteratee = cb(iteratee, context);
|
||
return _.pluck(_.map(obj, function(value, index, list) {
|
||
return {
|
||
value: value,
|
||
index: index,
|
||
criteria: iteratee(value, index, list)
|
||
};
|
||
}).sort(function(left, right) {
|
||
var a = left.criteria;
|
||
var b = right.criteria;
|
||
if (a !== b) {
|
||
if (a > b || a === void 0) return 1;
|
||
if (a < b || b === void 0) return -1;
|
||
}
|
||
return left.index - right.index;
|
||
}), 'value');
|
||
};
|
||
|
||
// An internal function used for aggregate "group by" operations.
|
||
var group = function(behavior) {
|
||
return function(obj, iteratee, context) {
|
||
var result = {};
|
||
iteratee = cb(iteratee, context);
|
||
_.each(obj, function(value, index) {
|
||
var key = iteratee(value, index, obj);
|
||
behavior(result, value, key);
|
||
});
|
||
return result;
|
||
};
|
||
};
|
||
|
||
// Groups the object's values by a criterion. Pass either a string attribute
|
||
// to group by, or a function that returns the criterion.
|
||
_.groupBy = group(function(result, value, key) {
|
||
if (_.has(result, key)) result[key].push(value); else result[key] = [value];
|
||
});
|
||
|
||
// Indexes the object's values by a criterion, similar to `groupBy`, but for
|
||
// when you know that your index values will be unique.
|
||
_.indexBy = group(function(result, value, key) {
|
||
result[key] = value;
|
||
});
|
||
|
||
// Counts instances of an object that group by a certain criterion. Pass
|
||
// either a string attribute to count by, or a function that returns the
|
||
// criterion.
|
||
_.countBy = group(function(result, value, key) {
|
||
if (_.has(result, key)) result[key]++; else result[key] = 1;
|
||
});
|
||
|
||
// Safely create a real, live array from anything iterable.
|
||
_.toArray = function(obj) {
|
||
if (!obj) return [];
|
||
if (_.isArray(obj)) return slice.call(obj);
|
||
if (isArrayLike(obj)) return _.map(obj, _.identity);
|
||
return _.values(obj);
|
||
};
|
||
|
||
// Return the number of elements in an object.
|
||
_.size = function(obj) {
|
||
if (obj == null) return 0;
|
||
return isArrayLike(obj) ? obj.length : _.keys(obj).length;
|
||
};
|
||
|
||
// Split a collection into two arrays: one whose elements all satisfy the given
|
||
// predicate, and one whose elements all do not satisfy the predicate.
|
||
_.partition = function(obj, predicate, context) {
|
||
predicate = cb(predicate, context);
|
||
var pass = [], fail = [];
|
||
_.each(obj, function(value, key, obj) {
|
||
(predicate(value, key, obj) ? pass : fail).push(value);
|
||
});
|
||
return [pass, fail];
|
||
};
|
||
|
||
// Array Functions
|
||
// ---------------
|
||
|
||
// Get the first element of an array. Passing **n** will return the first N
|
||
// values in the array. Aliased as `head` and `take`. The **guard** check
|
||
// allows it to work with `_.map`.
|
||
_.first = _.head = _.take = function(array, n, guard) {
|
||
if (array == null) return void 0;
|
||
if (n == null || guard) return array[0];
|
||
return _.initial(array, array.length - n);
|
||
};
|
||
|
||
// Returns everything but the last entry of the array. Especially useful on
|
||
// the arguments object. Passing **n** will return all the values in
|
||
// the array, excluding the last N.
|
||
_.initial = function(array, n, guard) {
|
||
return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
|
||
};
|
||
|
||
// Get the last element of an array. Passing **n** will return the last N
|
||
// values in the array.
|
||
_.last = function(array, n, guard) {
|
||
if (array == null) return void 0;
|
||
if (n == null || guard) return array[array.length - 1];
|
||
return _.rest(array, Math.max(0, array.length - n));
|
||
};
|
||
|
||
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
|
||
// Especially useful on the arguments object. Passing an **n** will return
|
||
// the rest N values in the array.
|
||
_.rest = _.tail = _.drop = function(array, n, guard) {
|
||
return slice.call(array, n == null || guard ? 1 : n);
|
||
};
|
||
|
||
// Trim out all falsy values from an array.
|
||
_.compact = function(array) {
|
||
return _.filter(array, _.identity);
|
||
};
|
||
|
||
// Internal implementation of a recursive `flatten` function.
|
||
var flatten = function(input, shallow, strict, startIndex) {
|
||
var output = [], idx = 0;
|
||
for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
|
||
var value = input[i];
|
||
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
|
||
//flatten current level of array or arguments object
|
||
if (!shallow) value = flatten(value, shallow, strict);
|
||
var j = 0, len = value.length;
|
||
output.length += len;
|
||
while (j < len) {
|
||
output[idx++] = value[j++];
|
||
}
|
||
} else if (!strict) {
|
||
output[idx++] = value;
|
||
}
|
||
}
|
||
return output;
|
||
};
|
||
|
||
// Flatten out an array, either recursively (by default), or just one level.
|
||
_.flatten = function(array, shallow) {
|
||
return flatten(array, shallow, false);
|
||
};
|
||
|
||
// Return a version of the array that does not contain the specified value(s).
|
||
_.without = function(array) {
|
||
return _.difference(array, slice.call(arguments, 1));
|
||
};
|
||
|
||
// Produce a duplicate-free version of the array. If the array has already
|
||
// been sorted, you have the option of using a faster algorithm.
|
||
// Aliased as `unique`.
|
||
_.uniq = _.unique = function(array, isSorted, iteratee, context) {
|
||
if (!_.isBoolean(isSorted)) {
|
||
context = iteratee;
|
||
iteratee = isSorted;
|
||
isSorted = false;
|
||
}
|
||
if (iteratee != null) iteratee = cb(iteratee, context);
|
||
var result = [];
|
||
var seen = [];
|
||
for (var i = 0, length = getLength(array); i < length; i++) {
|
||
var value = array[i],
|
||
computed = iteratee ? iteratee(value, i, array) : value;
|
||
if (isSorted) {
|
||
if (!i || seen !== computed) result.push(value);
|
||
seen = computed;
|
||
} else if (iteratee) {
|
||
if (!_.contains(seen, computed)) {
|
||
seen.push(computed);
|
||
result.push(value);
|
||
}
|
||
} else if (!_.contains(result, value)) {
|
||
result.push(value);
|
||
}
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Produce an array that contains the union: each distinct element from all of
|
||
// the passed-in arrays.
|
||
_.union = function() {
|
||
return _.uniq(flatten(arguments, true, true));
|
||
};
|
||
|
||
// Produce an array that contains every item shared between all the
|
||
// passed-in arrays.
|
||
_.intersection = function(array) {
|
||
var result = [];
|
||
var argsLength = arguments.length;
|
||
for (var i = 0, length = getLength(array); i < length; i++) {
|
||
var item = array[i];
|
||
if (_.contains(result, item)) continue;
|
||
for (var j = 1; j < argsLength; j++) {
|
||
if (!_.contains(arguments[j], item)) break;
|
||
}
|
||
if (j === argsLength) result.push(item);
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Take the difference between one array and a number of other arrays.
|
||
// Only the elements present in just the first array will remain.
|
||
_.difference = function(array) {
|
||
var rest = flatten(arguments, true, true, 1);
|
||
return _.filter(array, function(value){
|
||
return !_.contains(rest, value);
|
||
});
|
||
};
|
||
|
||
// Zip together multiple lists into a single array -- elements that share
|
||
// an index go together.
|
||
_.zip = function() {
|
||
return _.unzip(arguments);
|
||
};
|
||
|
||
// Complement of _.zip. Unzip accepts an array of arrays and groups
|
||
// each array's elements on shared indices
|
||
_.unzip = function(array) {
|
||
var length = array && _.max(array, getLength).length || 0;
|
||
var result = Array(length);
|
||
|
||
for (var index = 0; index < length; index++) {
|
||
result[index] = _.pluck(array, index);
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Converts lists into objects. Pass either a single array of `[key, value]`
|
||
// pairs, or two parallel arrays of the same length -- one of keys, and one of
|
||
// the corresponding values.
|
||
_.object = function(list, values) {
|
||
var result = {};
|
||
for (var i = 0, length = getLength(list); i < length; i++) {
|
||
if (values) {
|
||
result[list[i]] = values[i];
|
||
} else {
|
||
result[list[i][0]] = list[i][1];
|
||
}
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Generator function to create the findIndex and findLastIndex functions
|
||
function createPredicateIndexFinder(dir) {
|
||
return function(array, predicate, context) {
|
||
predicate = cb(predicate, context);
|
||
var length = getLength(array);
|
||
var index = dir > 0 ? 0 : length - 1;
|
||
for (; index >= 0 && index < length; index += dir) {
|
||
if (predicate(array[index], index, array)) return index;
|
||
}
|
||
return -1;
|
||
};
|
||
}
|
||
|
||
// Returns the first index on an array-like that passes a predicate test
|
||
_.findIndex = createPredicateIndexFinder(1);
|
||
_.findLastIndex = createPredicateIndexFinder(-1);
|
||
|
||
// Use a comparator function to figure out the smallest index at which
|
||
// an object should be inserted so as to maintain order. Uses binary search.
|
||
_.sortedIndex = function(array, obj, iteratee, context) {
|
||
iteratee = cb(iteratee, context, 1);
|
||
var value = iteratee(obj);
|
||
var low = 0, high = getLength(array);
|
||
while (low < high) {
|
||
var mid = Math.floor((low + high) / 2);
|
||
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
|
||
}
|
||
return low;
|
||
};
|
||
|
||
// Generator function to create the indexOf and lastIndexOf functions
|
||
function createIndexFinder(dir, predicateFind, sortedIndex) {
|
||
return function(array, item, idx) {
|
||
var i = 0, length = getLength(array);
|
||
if (typeof idx == 'number') {
|
||
if (dir > 0) {
|
||
i = idx >= 0 ? idx : Math.max(idx + length, i);
|
||
} else {
|
||
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
|
||
}
|
||
} else if (sortedIndex && idx && length) {
|
||
idx = sortedIndex(array, item);
|
||
return array[idx] === item ? idx : -1;
|
||
}
|
||
if (item !== item) {
|
||
idx = predicateFind(slice.call(array, i, length), _.isNaN);
|
||
return idx >= 0 ? idx + i : -1;
|
||
}
|
||
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
|
||
if (array[idx] === item) return idx;
|
||
}
|
||
return -1;
|
||
};
|
||
}
|
||
|
||
// Return the position of the first occurrence of an item in an array,
|
||
// or -1 if the item is not included in the array.
|
||
// If the array is large and already in sort order, pass `true`
|
||
// for **isSorted** to use binary search.
|
||
_.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
|
||
_.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
|
||
|
||
// Generate an integer Array containing an arithmetic progression. A port of
|
||
// the native Python `range()` function. See
|
||
// [the Python documentation](http://docs.python.org/library/functions.html#range).
|
||
_.range = function(start, stop, step) {
|
||
if (stop == null) {
|
||
stop = start || 0;
|
||
start = 0;
|
||
}
|
||
step = step || 1;
|
||
|
||
var length = Math.max(Math.ceil((stop - start) / step), 0);
|
||
var range = Array(length);
|
||
|
||
for (var idx = 0; idx < length; idx++, start += step) {
|
||
range[idx] = start;
|
||
}
|
||
|
||
return range;
|
||
};
|
||
|
||
// Function (ahem) Functions
|
||
// ------------------
|
||
|
||
// Determines whether to execute a function as a constructor
|
||
// or a normal function with the provided arguments
|
||
var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
|
||
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
|
||
var self = baseCreate(sourceFunc.prototype);
|
||
var result = sourceFunc.apply(self, args);
|
||
if (_.isObject(result)) return result;
|
||
return self;
|
||
};
|
||
|
||
// Create a function bound to a given object (assigning `this`, and arguments,
|
||
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
|
||
// available.
|
||
_.bind = function(func, context) {
|
||
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
|
||
if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
|
||
var args = slice.call(arguments, 2);
|
||
var bound = function() {
|
||
return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
|
||
};
|
||
return bound;
|
||
};
|
||
|
||
// Partially apply a function by creating a version that has had some of its
|
||
// arguments pre-filled, without changing its dynamic `this` context. _ acts
|
||
// as a placeholder, allowing any combination of arguments to be pre-filled.
|
||
_.partial = function(func) {
|
||
var boundArgs = slice.call(arguments, 1);
|
||
var bound = function() {
|
||
var position = 0, length = boundArgs.length;
|
||
var args = Array(length);
|
||
for (var i = 0; i < length; i++) {
|
||
args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
|
||
}
|
||
while (position < arguments.length) args.push(arguments[position++]);
|
||
return executeBound(func, bound, this, this, args);
|
||
};
|
||
return bound;
|
||
};
|
||
|
||
// Bind a number of an object's methods to that object. Remaining arguments
|
||
// are the method names to be bound. Useful for ensuring that all callbacks
|
||
// defined on an object belong to it.
|
||
_.bindAll = function(obj) {
|
||
var i, length = arguments.length, key;
|
||
if (length <= 1) throw new Error('bindAll must be passed function names');
|
||
for (i = 1; i < length; i++) {
|
||
key = arguments[i];
|
||
obj[key] = _.bind(obj[key], obj);
|
||
}
|
||
return obj;
|
||
};
|
||
|
||
// Memoize an expensive function by storing its results.
|
||
_.memoize = function(func, hasher) {
|
||
var memoize = function(key) {
|
||
var cache = memoize.cache;
|
||
var address = '' + (hasher ? hasher.apply(this, arguments) : key);
|
||
if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
|
||
return cache[address];
|
||
};
|
||
memoize.cache = {};
|
||
return memoize;
|
||
};
|
||
|
||
// Delays a function for the given number of milliseconds, and then calls
|
||
// it with the arguments supplied.
|
||
_.delay = function(func, wait) {
|
||
var args = slice.call(arguments, 2);
|
||
return setTimeout(function(){
|
||
return func.apply(null, args);
|
||
}, wait);
|
||
};
|
||
|
||
// Defers a function, scheduling it to run after the current call stack has
|
||
// cleared.
|
||
_.defer = _.partial(_.delay, _, 1);
|
||
|
||
// Returns a function, that, when invoked, will only be triggered at most once
|
||
// during a given window of time. Normally, the throttled function will run
|
||
// as much as it can, without ever going more than once per `wait` duration;
|
||
// but if you'd like to disable the execution on the leading edge, pass
|
||
// `{leading: false}`. To disable execution on the trailing edge, ditto.
|
||
_.throttle = function(func, wait, options) {
|
||
var context, args, result;
|
||
var timeout = null;
|
||
var previous = 0;
|
||
if (!options) options = {};
|
||
var later = function() {
|
||
previous = options.leading === false ? 0 : _.now();
|
||
timeout = null;
|
||
result = func.apply(context, args);
|
||
if (!timeout) context = args = null;
|
||
};
|
||
return function() {
|
||
var now = _.now();
|
||
if (!previous && options.leading === false) previous = now;
|
||
var remaining = wait - (now - previous);
|
||
context = this;
|
||
args = arguments;
|
||
if (remaining <= 0 || remaining > wait) {
|
||
if (timeout) {
|
||
clearTimeout(timeout);
|
||
timeout = null;
|
||
}
|
||
previous = now;
|
||
result = func.apply(context, args);
|
||
if (!timeout) context = args = null;
|
||
} else if (!timeout && options.trailing !== false) {
|
||
timeout = setTimeout(later, remaining);
|
||
}
|
||
return result;
|
||
};
|
||
};
|
||
|
||
// Returns a function, that, as long as it continues to be invoked, will not
|
||
// be triggered. The function will be called after it stops being called for
|
||
// N milliseconds. If `immediate` is passed, trigger the function on the
|
||
// leading edge, instead of the trailing.
|
||
_.debounce = function(func, wait, immediate) {
|
||
var timeout, args, context, timestamp, result;
|
||
|
||
var later = function() {
|
||
var last = _.now() - timestamp;
|
||
|
||
if (last < wait && last >= 0) {
|
||
timeout = setTimeout(later, wait - last);
|
||
} else {
|
||
timeout = null;
|
||
if (!immediate) {
|
||
result = func.apply(context, args);
|
||
if (!timeout) context = args = null;
|
||
}
|
||
}
|
||
};
|
||
|
||
return function() {
|
||
context = this;
|
||
args = arguments;
|
||
timestamp = _.now();
|
||
var callNow = immediate && !timeout;
|
||
if (!timeout) timeout = setTimeout(later, wait);
|
||
if (callNow) {
|
||
result = func.apply(context, args);
|
||
context = args = null;
|
||
}
|
||
|
||
return result;
|
||
};
|
||
};
|
||
|
||
// Returns the first function passed as an argument to the second,
|
||
// allowing you to adjust arguments, run code before and after, and
|
||
// conditionally execute the original function.
|
||
_.wrap = function(func, wrapper) {
|
||
return _.partial(wrapper, func);
|
||
};
|
||
|
||
// Returns a negated version of the passed-in predicate.
|
||
_.negate = function(predicate) {
|
||
return function() {
|
||
return !predicate.apply(this, arguments);
|
||
};
|
||
};
|
||
|
||
// Returns a function that is the composition of a list of functions, each
|
||
// consuming the return value of the function that follows.
|
||
_.compose = function() {
|
||
var args = arguments;
|
||
var start = args.length - 1;
|
||
return function() {
|
||
var i = start;
|
||
var result = args[start].apply(this, arguments);
|
||
while (i--) result = args[i].call(this, result);
|
||
return result;
|
||
};
|
||
};
|
||
|
||
// Returns a function that will only be executed on and after the Nth call.
|
||
_.after = function(times, func) {
|
||
return function() {
|
||
if (--times < 1) {
|
||
return func.apply(this, arguments);
|
||
}
|
||
};
|
||
};
|
||
|
||
// Returns a function that will only be executed up to (but not including) the Nth call.
|
||
_.before = function(times, func) {
|
||
var memo;
|
||
return function() {
|
||
if (--times > 0) {
|
||
memo = func.apply(this, arguments);
|
||
}
|
||
if (times <= 1) func = null;
|
||
return memo;
|
||
};
|
||
};
|
||
|
||
// Returns a function that will be executed at most one time, no matter how
|
||
// often you call it. Useful for lazy initialization.
|
||
_.once = _.partial(_.before, 2);
|
||
|
||
// Object Functions
|
||
// ----------------
|
||
|
||
// Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
|
||
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
|
||
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
|
||
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
|
||
|
||
function collectNonEnumProps(obj, keys) {
|
||
var nonEnumIdx = nonEnumerableProps.length;
|
||
var constructor = obj.constructor;
|
||
var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
|
||
|
||
// Constructor is a special case.
|
||
var prop = 'constructor';
|
||
if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
|
||
|
||
while (nonEnumIdx--) {
|
||
prop = nonEnumerableProps[nonEnumIdx];
|
||
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
|
||
keys.push(prop);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Retrieve the names of an object's own properties.
|
||
// Delegates to **ECMAScript 5**'s native `Object.keys`
|
||
_.keys = function(obj) {
|
||
if (!_.isObject(obj)) return [];
|
||
if (nativeKeys) return nativeKeys(obj);
|
||
var keys = [];
|
||
for (var key in obj) if (_.has(obj, key)) keys.push(key);
|
||
// Ahem, IE < 9.
|
||
if (hasEnumBug) collectNonEnumProps(obj, keys);
|
||
return keys;
|
||
};
|
||
|
||
// Retrieve all the property names of an object.
|
||
_.allKeys = function(obj) {
|
||
if (!_.isObject(obj)) return [];
|
||
var keys = [];
|
||
for (var key in obj) keys.push(key);
|
||
// Ahem, IE < 9.
|
||
if (hasEnumBug) collectNonEnumProps(obj, keys);
|
||
return keys;
|
||
};
|
||
|
||
// Retrieve the values of an object's properties.
|
||
_.values = function(obj) {
|
||
var keys = _.keys(obj);
|
||
var length = keys.length;
|
||
var values = Array(length);
|
||
for (var i = 0; i < length; i++) {
|
||
values[i] = obj[keys[i]];
|
||
}
|
||
return values;
|
||
};
|
||
|
||
// Returns the results of applying the iteratee to each element of the object
|
||
// In contrast to _.map it returns an object
|
||
_.mapObject = function(obj, iteratee, context) {
|
||
iteratee = cb(iteratee, context);
|
||
var keys = _.keys(obj),
|
||
length = keys.length,
|
||
results = {},
|
||
currentKey;
|
||
for (var index = 0; index < length; index++) {
|
||
currentKey = keys[index];
|
||
results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
|
||
}
|
||
return results;
|
||
};
|
||
|
||
// Convert an object into a list of `[key, value]` pairs.
|
||
_.pairs = function(obj) {
|
||
var keys = _.keys(obj);
|
||
var length = keys.length;
|
||
var pairs = Array(length);
|
||
for (var i = 0; i < length; i++) {
|
||
pairs[i] = [keys[i], obj[keys[i]]];
|
||
}
|
||
return pairs;
|
||
};
|
||
|
||
// Invert the keys and values of an object. The values must be serializable.
|
||
_.invert = function(obj) {
|
||
var result = {};
|
||
var keys = _.keys(obj);
|
||
for (var i = 0, length = keys.length; i < length; i++) {
|
||
result[obj[keys[i]]] = keys[i];
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Return a sorted list of the function names available on the object.
|
||
// Aliased as `methods`
|
||
_.functions = _.methods = function(obj) {
|
||
var names = [];
|
||
for (var key in obj) {
|
||
if (_.isFunction(obj[key])) names.push(key);
|
||
}
|
||
return names.sort();
|
||
};
|
||
|
||
// Extend a given object with all the properties in passed-in object(s).
|
||
_.extend = createAssigner(_.allKeys);
|
||
|
||
// Assigns a given object with all the own properties in the passed-in object(s)
|
||
// (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
|
||
_.extendOwn = _.assign = createAssigner(_.keys);
|
||
|
||
// Returns the first key on an object that passes a predicate test
|
||
_.findKey = function(obj, predicate, context) {
|
||
predicate = cb(predicate, context);
|
||
var keys = _.keys(obj), key;
|
||
for (var i = 0, length = keys.length; i < length; i++) {
|
||
key = keys[i];
|
||
if (predicate(obj[key], key, obj)) return key;
|
||
}
|
||
};
|
||
|
||
// Return a copy of the object only containing the whitelisted properties.
|
||
_.pick = function(object, oiteratee, context) {
|
||
var result = {}, obj = object, iteratee, keys;
|
||
if (obj == null) return result;
|
||
if (_.isFunction(oiteratee)) {
|
||
keys = _.allKeys(obj);
|
||
iteratee = optimizeCb(oiteratee, context);
|
||
} else {
|
||
keys = flatten(arguments, false, false, 1);
|
||
iteratee = function(value, key, obj) { return key in obj; };
|
||
obj = Object(obj);
|
||
}
|
||
for (var i = 0, length = keys.length; i < length; i++) {
|
||
var key = keys[i];
|
||
var value = obj[key];
|
||
if (iteratee(value, key, obj)) result[key] = value;
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Return a copy of the object without the blacklisted properties.
|
||
_.omit = function(obj, iteratee, context) {
|
||
if (_.isFunction(iteratee)) {
|
||
iteratee = _.negate(iteratee);
|
||
} else {
|
||
var keys = _.map(flatten(arguments, false, false, 1), String);
|
||
iteratee = function(value, key) {
|
||
return !_.contains(keys, key);
|
||
};
|
||
}
|
||
return _.pick(obj, iteratee, context);
|
||
};
|
||
|
||
// Fill in a given object with default properties.
|
||
_.defaults = createAssigner(_.allKeys, true);
|
||
|
||
// Creates an object that inherits from the given prototype object.
|
||
// If additional properties are provided then they will be added to the
|
||
// created object.
|
||
_.create = function(prototype, props) {
|
||
var result = baseCreate(prototype);
|
||
if (props) _.extendOwn(result, props);
|
||
return result;
|
||
};
|
||
|
||
// Create a (shallow-cloned) duplicate of an object.
|
||
_.clone = function(obj) {
|
||
if (!_.isObject(obj)) return obj;
|
||
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
|
||
};
|
||
|
||
// Invokes interceptor with the obj, and then returns obj.
|
||
// The primary purpose of this method is to "tap into" a method chain, in
|
||
// order to perform operations on intermediate results within the chain.
|
||
_.tap = function(obj, interceptor) {
|
||
interceptor(obj);
|
||
return obj;
|
||
};
|
||
|
||
// Returns whether an object has a given set of `key:value` pairs.
|
||
_.isMatch = function(object, attrs) {
|
||
var keys = _.keys(attrs), length = keys.length;
|
||
if (object == null) return !length;
|
||
var obj = Object(object);
|
||
for (var i = 0; i < length; i++) {
|
||
var key = keys[i];
|
||
if (attrs[key] !== obj[key] || !(key in obj)) return false;
|
||
}
|
||
return true;
|
||
};
|
||
|
||
|
||
// Internal recursive comparison function for `isEqual`.
|
||
var eq = function(a, b, aStack, bStack) {
|
||
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
||
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
|
||
if (a === b) return a !== 0 || 1 / a === 1 / b;
|
||
// A strict comparison is necessary because `null == undefined`.
|
||
if (a == null || b == null) return a === b;
|
||
// Unwrap any wrapped objects.
|
||
if (a instanceof _) a = a._wrapped;
|
||
if (b instanceof _) b = b._wrapped;
|
||
// Compare `[[Class]]` names.
|
||
var className = toString.call(a);
|
||
if (className !== toString.call(b)) return false;
|
||
switch (className) {
|
||
// Strings, numbers, regular expressions, dates, and booleans are compared by value.
|
||
case '[object RegExp]':
|
||
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
|
||
case '[object String]':
|
||
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
|
||
// equivalent to `new String("5")`.
|
||
return '' + a === '' + b;
|
||
case '[object Number]':
|
||
// `NaN`s are equivalent, but non-reflexive.
|
||
// Object(NaN) is equivalent to NaN
|
||
if (+a !== +a) return +b !== +b;
|
||
// An `egal` comparison is performed for other numeric values.
|
||
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
|
||
case '[object Date]':
|
||
case '[object Boolean]':
|
||
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
|
||
// millisecond representations. Note that invalid dates with millisecond representations
|
||
// of `NaN` are not equivalent.
|
||
return +a === +b;
|
||
}
|
||
|
||
var areArrays = className === '[object Array]';
|
||
if (!areArrays) {
|
||
if (typeof a != 'object' || typeof b != 'object') return false;
|
||
|
||
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
|
||
// from different frames are.
|
||
var aCtor = a.constructor, bCtor = b.constructor;
|
||
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
|
||
_.isFunction(bCtor) && bCtor instanceof bCtor)
|
||
&& ('constructor' in a && 'constructor' in b)) {
|
||
return false;
|
||
}
|
||
}
|
||
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
||
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
||
|
||
// Initializing stack of traversed objects.
|
||
// It's done here since we only need them for objects and arrays comparison.
|
||
aStack = aStack || [];
|
||
bStack = bStack || [];
|
||
var length = aStack.length;
|
||
while (length--) {
|
||
// Linear search. Performance is inversely proportional to the number of
|
||
// unique nested structures.
|
||
if (aStack[length] === a) return bStack[length] === b;
|
||
}
|
||
|
||
// Add the first object to the stack of traversed objects.
|
||
aStack.push(a);
|
||
bStack.push(b);
|
||
|
||
// Recursively compare objects and arrays.
|
||
if (areArrays) {
|
||
// Compare array lengths to determine if a deep comparison is necessary.
|
||
length = a.length;
|
||
if (length !== b.length) return false;
|
||
// Deep compare the contents, ignoring non-numeric properties.
|
||
while (length--) {
|
||
if (!eq(a[length], b[length], aStack, bStack)) return false;
|
||
}
|
||
} else {
|
||
// Deep compare objects.
|
||
var keys = _.keys(a), key;
|
||
length = keys.length;
|
||
// Ensure that both objects contain the same number of properties before comparing deep equality.
|
||
if (_.keys(b).length !== length) return false;
|
||
while (length--) {
|
||
// Deep compare each member
|
||
key = keys[length];
|
||
if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
|
||
}
|
||
}
|
||
// Remove the first object from the stack of traversed objects.
|
||
aStack.pop();
|
||
bStack.pop();
|
||
return true;
|
||
};
|
||
|
||
// Perform a deep comparison to check if two objects are equal.
|
||
_.isEqual = function(a, b) {
|
||
return eq(a, b);
|
||
};
|
||
|
||
// Is a given array, string, or object empty?
|
||
// An "empty" object has no enumerable own-properties.
|
||
_.isEmpty = function(obj) {
|
||
if (obj == null) return true;
|
||
if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
|
||
return _.keys(obj).length === 0;
|
||
};
|
||
|
||
// Is a given value a DOM element?
|
||
_.isElement = function(obj) {
|
||
return !!(obj && obj.nodeType === 1);
|
||
};
|
||
|
||
// Is a given value an array?
|
||
// Delegates to ECMA5's native Array.isArray
|
||
_.isArray = nativeIsArray || function(obj) {
|
||
return toString.call(obj) === '[object Array]';
|
||
};
|
||
|
||
// Is a given variable an object?
|
||
_.isObject = function(obj) {
|
||
var type = typeof obj;
|
||
return type === 'function' || type === 'object' && !!obj;
|
||
};
|
||
|
||
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
|
||
_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
|
||
_['is' + name] = function(obj) {
|
||
return toString.call(obj) === '[object ' + name + ']';
|
||
};
|
||
});
|
||
|
||
// Define a fallback version of the method in browsers (ahem, IE < 9), where
|
||
// there isn't any inspectable "Arguments" type.
|
||
if (!_.isArguments(arguments)) {
|
||
_.isArguments = function(obj) {
|
||
return _.has(obj, 'callee');
|
||
};
|
||
}
|
||
|
||
// Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
|
||
// IE 11 (#1621), and in Safari 8 (#1929).
|
||
if (typeof /./ != 'function' && typeof Int8Array != 'object') {
|
||
_.isFunction = function(obj) {
|
||
return typeof obj == 'function' || false;
|
||
};
|
||
}
|
||
|
||
// Is a given object a finite number?
|
||
_.isFinite = function(obj) {
|
||
return isFinite(obj) && !isNaN(parseFloat(obj));
|
||
};
|
||
|
||
// Is the given value `NaN`? (NaN is the only number which does not equal itself).
|
||
_.isNaN = function(obj) {
|
||
return _.isNumber(obj) && obj !== +obj;
|
||
};
|
||
|
||
// Is a given value a boolean?
|
||
_.isBoolean = function(obj) {
|
||
return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
|
||
};
|
||
|
||
// Is a given value equal to null?
|
||
_.isNull = function(obj) {
|
||
return obj === null;
|
||
};
|
||
|
||
// Is a given variable undefined?
|
||
_.isUndefined = function(obj) {
|
||
return obj === void 0;
|
||
};
|
||
|
||
// Shortcut function for checking if an object has a given property directly
|
||
// on itself (in other words, not on a prototype).
|
||
_.has = function(obj, key) {
|
||
return obj != null && hasOwnProperty.call(obj, key);
|
||
};
|
||
|
||
// Utility Functions
|
||
// -----------------
|
||
|
||
// Run Underscore.js in *noConflict* mode, returning the `_` variable to its
|
||
// previous owner. Returns a reference to the Underscore object.
|
||
_.noConflict = function() {
|
||
root._ = previousUnderscore;
|
||
return this;
|
||
};
|
||
|
||
// Keep the identity function around for default iteratees.
|
||
_.identity = function(value) {
|
||
return value;
|
||
};
|
||
|
||
// Predicate-generating functions. Often useful outside of Underscore.
|
||
_.constant = function(value) {
|
||
return function() {
|
||
return value;
|
||
};
|
||
};
|
||
|
||
_.noop = function(){};
|
||
|
||
_.property = property;
|
||
|
||
// Generates a function for a given object that returns a given property.
|
||
_.propertyOf = function(obj) {
|
||
return obj == null ? function(){} : function(key) {
|
||
return obj[key];
|
||
};
|
||
};
|
||
|
||
// Returns a predicate for checking whether an object has a given set of
|
||
// `key:value` pairs.
|
||
_.matcher = _.matches = function(attrs) {
|
||
attrs = _.extendOwn({}, attrs);
|
||
return function(obj) {
|
||
return _.isMatch(obj, attrs);
|
||
};
|
||
};
|
||
|
||
// Run a function **n** times.
|
||
_.times = function(n, iteratee, context) {
|
||
var accum = Array(Math.max(0, n));
|
||
iteratee = optimizeCb(iteratee, context, 1);
|
||
for (var i = 0; i < n; i++) accum[i] = iteratee(i);
|
||
return accum;
|
||
};
|
||
|
||
// Return a random integer between min and max (inclusive).
|
||
_.random = function(min, max) {
|
||
if (max == null) {
|
||
max = min;
|
||
min = 0;
|
||
}
|
||
return min + Math.floor(Math.random() * (max - min + 1));
|
||
};
|
||
|
||
// A (possibly faster) way to get the current timestamp as an integer.
|
||
_.now = Date.now || function() {
|
||
return new Date().getTime();
|
||
};
|
||
|
||
// List of HTML entities for escaping.
|
||
var escapeMap = {
|
||
'&': '&',
|
||
'<': '<',
|
||
'>': '>',
|
||
'"': '"',
|
||
"'": ''',
|
||
'`': '`'
|
||
};
|
||
var unescapeMap = _.invert(escapeMap);
|
||
|
||
// Functions for escaping and unescaping strings to/from HTML interpolation.
|
||
var createEscaper = function(map) {
|
||
var escaper = function(match) {
|
||
return map[match];
|
||
};
|
||
// Regexes for identifying a key that needs to be escaped
|
||
var source = '(?:' + _.keys(map).join('|') + ')';
|
||
var testRegexp = RegExp(source);
|
||
var replaceRegexp = RegExp(source, 'g');
|
||
return function(string) {
|
||
string = string == null ? '' : '' + string;
|
||
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
|
||
};
|
||
};
|
||
_.escape = createEscaper(escapeMap);
|
||
_.unescape = createEscaper(unescapeMap);
|
||
|
||
// If the value of the named `property` is a function then invoke it with the
|
||
// `object` as context; otherwise, return it.
|
||
_.result = function(object, property, fallback) {
|
||
var value = object == null ? void 0 : object[property];
|
||
if (value === void 0) {
|
||
value = fallback;
|
||
}
|
||
return _.isFunction(value) ? value.call(object) : value;
|
||
};
|
||
|
||
// Generate a unique integer id (unique within the entire client session).
|
||
// Useful for temporary DOM ids.
|
||
var idCounter = 0;
|
||
_.uniqueId = function(prefix) {
|
||
var id = ++idCounter + '';
|
||
return prefix ? prefix + id : id;
|
||
};
|
||
|
||
// By default, Underscore uses ERB-style template delimiters, change the
|
||
// following template settings to use alternative delimiters.
|
||
_.templateSettings = {
|
||
evaluate : /<%([\s\S]+?)%>/g,
|
||
interpolate : /<%=([\s\S]+?)%>/g,
|
||
escape : /<%-([\s\S]+?)%>/g
|
||
};
|
||
|
||
// When customizing `templateSettings`, if you don't want to define an
|
||
// interpolation, evaluation or escaping regex, we need one that is
|
||
// guaranteed not to match.
|
||
var noMatch = /(.)^/;
|
||
|
||
// Certain characters need to be escaped so that they can be put into a
|
||
// string literal.
|
||
var escapes = {
|
||
"'": "'",
|
||
'\\': '\\',
|
||
'\r': 'r',
|
||
'\n': 'n',
|
||
'\u2028': 'u2028',
|
||
'\u2029': 'u2029'
|
||
};
|
||
|
||
var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
|
||
|
||
var escapeChar = function(match) {
|
||
return '\\' + escapes[match];
|
||
};
|
||
|
||
// JavaScript micro-templating, similar to John Resig's implementation.
|
||
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
||
// and correctly escapes quotes within interpolated code.
|
||
// NB: `oldSettings` only exists for backwards compatibility.
|
||
_.template = function(text, settings, oldSettings) {
|
||
if (!settings && oldSettings) settings = oldSettings;
|
||
settings = _.defaults({}, settings, _.templateSettings);
|
||
|
||
// Combine delimiters into one regular expression via alternation.
|
||
var matcher = RegExp([
|
||
(settings.escape || noMatch).source,
|
||
(settings.interpolate || noMatch).source,
|
||
(settings.evaluate || noMatch).source
|
||
].join('|') + '|$', 'g');
|
||
|
||
// Compile the template source, escaping string literals appropriately.
|
||
var index = 0;
|
||
var source = "__p+='";
|
||
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
|
||
source += text.slice(index, offset).replace(escaper, escapeChar);
|
||
index = offset + match.length;
|
||
|
||
if (escape) {
|
||
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
|
||
} else if (interpolate) {
|
||
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
|
||
} else if (evaluate) {
|
||
source += "';\n" + evaluate + "\n__p+='";
|
||
}
|
||
|
||
// Adobe VMs need the match returned to produce the correct offest.
|
||
return match;
|
||
});
|
||
source += "';\n";
|
||
|
||
// If a variable is not specified, place data values in local scope.
|
||
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
|
||
|
||
source = "var __t,__p='',__j=Array.prototype.join," +
|
||
"print=function(){__p+=__j.call(arguments,'');};\n" +
|
||
source + 'return __p;\n';
|
||
|
||
try {
|
||
var render = new Function(settings.variable || 'obj', '_', source);
|
||
} catch (e) {
|
||
e.source = source;
|
||
throw e;
|
||
}
|
||
|
||
var template = function(data) {
|
||
return render.call(this, data, _);
|
||
};
|
||
|
||
// Provide the compiled source as a convenience for precompilation.
|
||
var argument = settings.variable || 'obj';
|
||
template.source = 'function(' + argument + '){\n' + source + '}';
|
||
|
||
return template;
|
||
};
|
||
|
||
// Add a "chain" function. Start chaining a wrapped Underscore object.
|
||
_.chain = function(obj) {
|
||
var instance = _(obj);
|
||
instance._chain = true;
|
||
return instance;
|
||
};
|
||
|
||
// OOP
|
||
// ---------------
|
||
// If Underscore is called as a function, it returns a wrapped object that
|
||
// can be used OO-style. This wrapper holds altered versions of all the
|
||
// underscore functions. Wrapped objects may be chained.
|
||
|
||
// Helper function to continue chaining intermediate results.
|
||
var result = function(instance, obj) {
|
||
return instance._chain ? _(obj).chain() : obj;
|
||
};
|
||
|
||
// Add your own custom functions to the Underscore object.
|
||
_.mixin = function(obj) {
|
||
_.each(_.functions(obj), function(name) {
|
||
var func = _[name] = obj[name];
|
||
_.prototype[name] = function() {
|
||
var args = [this._wrapped];
|
||
push.apply(args, arguments);
|
||
return result(this, func.apply(_, args));
|
||
};
|
||
});
|
||
};
|
||
|
||
// Add all of the Underscore functions to the wrapper object.
|
||
_.mixin(_);
|
||
|
||
// Add all mutator Array functions to the wrapper.
|
||
_.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
||
var method = ArrayProto[name];
|
||
_.prototype[name] = function() {
|
||
var obj = this._wrapped;
|
||
method.apply(obj, arguments);
|
||
if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
|
||
return result(this, obj);
|
||
};
|
||
});
|
||
|
||
// Add all accessor Array functions to the wrapper.
|
||
_.each(['concat', 'join', 'slice'], function(name) {
|
||
var method = ArrayProto[name];
|
||
_.prototype[name] = function() {
|
||
return result(this, method.apply(this._wrapped, arguments));
|
||
};
|
||
});
|
||
|
||
// Extracts the result from a wrapped and chained object.
|
||
_.prototype.value = function() {
|
||
return this._wrapped;
|
||
};
|
||
|
||
// Provide unwrapping proxy for some methods used in engine operations
|
||
// such as arithmetic and JSON stringification.
|
||
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
|
||
|
||
_.prototype.toString = function() {
|
||
return '' + this._wrapped;
|
||
};
|
||
|
||
// AMD registration happens at the end for compatibility with AMD loaders
|
||
// that may not enforce next-turn semantics on modules. Even though general
|
||
// practice for AMD registration is to be anonymous, underscore registers
|
||
// as a named module because, like jQuery, it is a base library that is
|
||
// popular enough to be bundled in a third party lib, but not be part of
|
||
// an AMD load request. Those cases could generate an error when an
|
||
// anonymous define() is called outside of a loader request.
|
||
if (typeof define === 'function' && define.amd) {
|
||
define('underscore', [], function() {
|
||
return _;
|
||
});
|
||
}
|
||
}.call(this));
|
||
|
||
},{}],65:[function(require,module,exports){
|
||
var Connector, ListTest, TestSuite, Y, chai, expect, should, sinon, sinonChai, _,
|
||
__hasProp = {}.hasOwnProperty,
|
||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||
|
||
chai = require('chai');
|
||
|
||
expect = chai.expect;
|
||
|
||
should = chai.should();
|
||
|
||
sinon = require('sinon');
|
||
|
||
sinonChai = require('sinon-chai');
|
||
|
||
_ = require("underscore");
|
||
|
||
chai.use(sinonChai);
|
||
|
||
Y = require("../../yjs/lib/y");
|
||
|
||
Y.List = require("../lib/y-list");
|
||
|
||
Connector = require("../../y-test/lib/y-test.coffee");
|
||
|
||
TestSuite = require("../../yjs/test/object-test");
|
||
|
||
ListTest = (function(_super) {
|
||
__extends(ListTest, _super);
|
||
|
||
function ListTest(suffix) {
|
||
ListTest.__super__.constructor.call(this, suffix, Y);
|
||
}
|
||
|
||
ListTest.prototype.type = "ListTest";
|
||
|
||
ListTest.prototype.makeNewUser = function(userId) {
|
||
var conn;
|
||
conn = new Connector(userId);
|
||
return new Y(conn);
|
||
};
|
||
|
||
ListTest.prototype.initUsers = function(u) {
|
||
return u.val("ListTest", new Y.List());
|
||
};
|
||
|
||
ListTest.prototype.getRandomRoot = function(user_num) {
|
||
return this.users[user_num].val("ListTest");
|
||
};
|
||
|
||
ListTest.prototype.getContent = function(user_num) {
|
||
return this.users[user_num].val("ListTest").val();
|
||
};
|
||
|
||
return ListTest;
|
||
|
||
})(TestSuite);
|
||
|
||
describe("List Test", function() {
|
||
this.timeout(500000);
|
||
beforeEach(function(done) {
|
||
this.yTest = new ListTest();
|
||
return done();
|
||
});
|
||
it("can handle many engines, many operations, concurrently (random)", function() {
|
||
console.log("");
|
||
return this.yTest.run();
|
||
});
|
||
it("simple multi-char insert", function() {
|
||
var u;
|
||
u = this.yTest.users[0].val("ListTest");
|
||
u.insertContents(0, ['a', 'b', 'c']);
|
||
u = this.yTest.users[1].val("ListTest");
|
||
u.insert(0, 'x');
|
||
u.insertContents(1, ['y', 'z']);
|
||
this.yTest.compareAll();
|
||
u["delete"](0, 1);
|
||
this.yTest.compareAll();
|
||
return expect(u.val().join("")).to.equal("bcxyz");
|
||
});
|
||
it("Observers work on shared List (insert type observers, local and foreign)", function() {
|
||
var last_task, observer1, observer2, u, v;
|
||
u = this.yTest.users[0].val("ListTest", new Y.List("my awesome List".split(""))).val("ListTest");
|
||
this.yTest.flushAll();
|
||
last_task = null;
|
||
observer1 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("insert");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.value).to.equal("a");
|
||
expect(change.position).to.equal(1);
|
||
expect(change.changedBy).to.equal('0');
|
||
return last_task = "observer1";
|
||
};
|
||
u.observe(observer1);
|
||
u.insert(1, "a");
|
||
expect(last_task).to.equal("observer1");
|
||
u.unobserve(observer1);
|
||
observer2 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("insert");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.value).to.equal("x");
|
||
expect(change.position).to.equal(0);
|
||
expect(change.changedBy).to.equal('1');
|
||
return last_task = "observer2";
|
||
};
|
||
u.observe(observer2);
|
||
v = this.yTest.users[1].val("ListTest");
|
||
v.insert(0, "x");
|
||
this.yTest.flushAll();
|
||
expect(last_task).to.equal("observer2");
|
||
return u.unobserve(observer2);
|
||
});
|
||
it("Observers work on shared List (delete type observers, local and foreign)", function() {
|
||
var last_task, observer1, observer2, u, v;
|
||
u = this.yTest.users[0].val("ListTest", new Y.List("my awesome List".split(""))).val("ListTest");
|
||
this.yTest.flushAll();
|
||
last_task = null;
|
||
observer1 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("delete");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.position).to.equal(1);
|
||
expect(change.length).to.equal(1);
|
||
expect(change.changedBy).to.equal('0');
|
||
return last_task = "observer1";
|
||
};
|
||
u.observe(observer1);
|
||
u["delete"](1, 1);
|
||
expect(last_task).to.equal("observer1");
|
||
u.unobserve(observer1);
|
||
observer2 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("delete");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.position).to.equal(0);
|
||
expect(change.length).to.equal(1);
|
||
expect(change.changedBy).to.equal('1');
|
||
return last_task = "observer2";
|
||
};
|
||
u.observe(observer2);
|
||
v = this.yTest.users[1].val("ListTest");
|
||
v["delete"](0, 1);
|
||
this.yTest.flushAll();
|
||
expect(last_task).to.equal("observer2");
|
||
return u.unobserve(observer2);
|
||
});
|
||
it("can handle many engines, many operations, concurrently (random)", function() {
|
||
console.log("testiy deleted this TODO:dtrn");
|
||
return this.yTest.run();
|
||
});
|
||
return it("handles double-late-join", function() {
|
||
var ops1, ops2, test, u1, u2;
|
||
test = new ListTest("double");
|
||
test.run();
|
||
this.yTest.run();
|
||
u1 = test.users[0];
|
||
u2 = this.yTest.users[1];
|
||
ops1 = u1._model.HB._encode();
|
||
ops2 = u2._model.HB._encode();
|
||
u1._model.engine.applyOp(ops2, true);
|
||
u2._model.engine.applyOp(ops1, true);
|
||
return this.yTest.compare(u1, u2);
|
||
});
|
||
});
|
||
|
||
module.exports = ListTest;
|
||
|
||
|
||
},{"../../y-test/lib/y-test.coffee":66,"../../yjs/lib/y":75,"../../yjs/test/object-test":147,"../lib/y-list":1,"chai":2,"sinon":37,"sinon-chai":36,"underscore":64}],66:[function(require,module,exports){
|
||
var TestConnector;
|
||
|
||
TestConnector = (function() {
|
||
function TestConnector(id) {
|
||
var options;
|
||
this.id = id;
|
||
options = {
|
||
syncMethod: "syncAll",
|
||
role: "slave",
|
||
user_id: this.id,
|
||
perform_send_again: false
|
||
};
|
||
this.on_bound_to_y = (function(_this) {
|
||
return function() {
|
||
_this.init(options);
|
||
_this.execution_order = [];
|
||
_this.receive_buffer = {};
|
||
return _this.receive_handlers.push(function(user, message) {
|
||
return _this.execution_order.push(message);
|
||
});
|
||
};
|
||
})(this);
|
||
}
|
||
|
||
TestConnector.prototype.join = function(conn) {
|
||
var c, cid, _ref, _results;
|
||
if (this.connections[conn.id] == null) {
|
||
this.connections[conn.id] = {
|
||
conn: conn
|
||
};
|
||
this.userJoined(conn.id, "slave");
|
||
conn.join(this);
|
||
this.flushAll();
|
||
conn.flushAll();
|
||
this.flushAll();
|
||
conn.flushAll();
|
||
_ref = conn.connections;
|
||
_results = [];
|
||
for (cid in _ref) {
|
||
c = _ref[cid];
|
||
if (this.connections[cid] == null) {
|
||
_results.push(this.join(c.conn));
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
}
|
||
};
|
||
|
||
TestConnector.prototype.getOpsInExecutionOrder = function() {
|
||
return this.execution_order;
|
||
};
|
||
|
||
TestConnector.prototype.send = function(uid, message) {
|
||
var rb, _name;
|
||
if ((message.sync_step != null) && false) {
|
||
return this.receiveMessage(uid, message);
|
||
} else {
|
||
rb = this.connections[uid].conn.receive_buffer;
|
||
if (rb[_name = this.id] == null) {
|
||
rb[_name] = [];
|
||
}
|
||
return rb[this.id].push(message);
|
||
}
|
||
};
|
||
|
||
TestConnector.prototype.broadcast = function(message) {
|
||
var c, name, _ref, _results;
|
||
_ref = this.connections;
|
||
_results = [];
|
||
for (name in _ref) {
|
||
c = _ref[name];
|
||
_results.push(this.send(name, message));
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
TestConnector.prototype.flushOne = function(uid) {
|
||
var message, _ref;
|
||
if (((_ref = this.receive_buffer[uid]) != null ? _ref.length : void 0) > 0) {
|
||
message = this.receive_buffer[uid].shift();
|
||
return this.receiveMessage(uid, message);
|
||
}
|
||
};
|
||
|
||
TestConnector.prototype.flushOneRandom = function() {
|
||
var c, cid, connlist, i;
|
||
connlist = (function() {
|
||
var _ref, _results;
|
||
_ref = this.receive_buffer;
|
||
_results = [];
|
||
for (cid in _ref) {
|
||
c = _ref[cid];
|
||
_results.push(cid);
|
||
}
|
||
return _results;
|
||
}).call(this);
|
||
i = Math.ceil(Math.random() * connlist.length - 0.5);
|
||
return this.flushOne(connlist[i]);
|
||
};
|
||
|
||
TestConnector.prototype.flushAll = function() {
|
||
var message, messages, n, _i, _len, _ref;
|
||
_ref = this.receive_buffer;
|
||
for (n in _ref) {
|
||
messages = _ref[n];
|
||
for (_i = 0, _len = messages.length; _i < _len; _i++) {
|
||
message = messages[_i];
|
||
this.receiveMessage(n, message);
|
||
}
|
||
}
|
||
return this.receive_buffer = {};
|
||
};
|
||
|
||
return TestConnector;
|
||
|
||
})();
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
if (typeof Y === "undefined" || Y === null) {
|
||
throw new Error("You must import Y first!");
|
||
} else {
|
||
window.Y.TestConnector = TestConnector;
|
||
}
|
||
}
|
||
|
||
if (typeof module !== "undefined" && module !== null) {
|
||
module.exports = TestConnector;
|
||
}
|
||
|
||
|
||
},{}],67:[function(require,module,exports){
|
||
var YText;
|
||
|
||
YText = (function() {
|
||
function YText(text) {
|
||
this.textfields = [];
|
||
if (text == null) {
|
||
this._text = "";
|
||
} else if (text.constructor === String) {
|
||
this._text = text;
|
||
} else {
|
||
throw new Error("Y.Text expects a String as a constructor");
|
||
}
|
||
}
|
||
|
||
YText.prototype._name = "Text";
|
||
|
||
YText.prototype._getModel = function(types, ops) {
|
||
if (this._model == null) {
|
||
this._model = new ops.ListManager(this).execute();
|
||
this.insert(0, this._text);
|
||
}
|
||
delete this._text;
|
||
return this._model;
|
||
};
|
||
|
||
YText.prototype._setModel = function(_model) {
|
||
this._model = _model;
|
||
return delete this._text;
|
||
};
|
||
|
||
YText.prototype.val = function() {
|
||
return this._model.fold("", function(left, o) {
|
||
return left + o.val();
|
||
});
|
||
};
|
||
|
||
YText.prototype.observe = function() {
|
||
return this._model.observe.apply(this._model, arguments);
|
||
};
|
||
|
||
YText.prototype.unobserve = function() {
|
||
return this._model.unobserve.apply(this._model, arguments);
|
||
};
|
||
|
||
YText.prototype.toString = function() {
|
||
return this.val();
|
||
};
|
||
|
||
YText.prototype.insert = function(position, content) {
|
||
var ith;
|
||
if (content.constructor !== String) {
|
||
throw new Error("Y.String.insert expects a String as the second parameter!");
|
||
}
|
||
if (typeof position !== "number") {
|
||
throw new Error("Y.String.insert expects a Number as the first parameter!");
|
||
}
|
||
if (content.length > 0) {
|
||
ith = this._model.getOperationByPosition(position);
|
||
return this._model.insertAfter(ith, content);
|
||
}
|
||
};
|
||
|
||
YText.prototype["delete"] = function(position, length) {
|
||
return this._model["delete"](position, length);
|
||
};
|
||
|
||
YText.prototype.bind = function(textfield, dom_root) {
|
||
var createRange, creator_token, t, word, writeContent, writeRange, _i, _len, _ref;
|
||
if (dom_root == null) {
|
||
dom_root = window;
|
||
}
|
||
if (dom_root.getSelection == null) {
|
||
dom_root = window;
|
||
}
|
||
_ref = this.textfields;
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
t = _ref[_i];
|
||
if (t === textfield) {
|
||
return;
|
||
}
|
||
}
|
||
creator_token = false;
|
||
word = this;
|
||
textfield.value = this.val();
|
||
this.textfields.push(textfield);
|
||
if ((textfield.selectionStart != null) && (textfield.setSelectionRange != null)) {
|
||
createRange = function(fix) {
|
||
var left, right;
|
||
left = textfield.selectionStart;
|
||
right = textfield.selectionEnd;
|
||
if (fix != null) {
|
||
left = fix(left);
|
||
right = fix(right);
|
||
}
|
||
return {
|
||
left: left,
|
||
right: right
|
||
};
|
||
};
|
||
writeRange = function(range) {
|
||
writeContent(word.val());
|
||
return textfield.setSelectionRange(range.left, range.right);
|
||
};
|
||
writeContent = function(content) {
|
||
return textfield.value = content;
|
||
};
|
||
} else {
|
||
createRange = function(fix) {
|
||
var clength, edited_element, range, s;
|
||
range = {};
|
||
s = dom_root.getSelection();
|
||
clength = textfield.textContent.length;
|
||
range.left = Math.min(s.anchorOffset, clength);
|
||
range.right = Math.min(s.focusOffset, clength);
|
||
if (fix != null) {
|
||
range.left = fix(range.left);
|
||
range.right = fix(range.right);
|
||
}
|
||
edited_element = s.focusNode;
|
||
if (edited_element === textfield || edited_element === textfield.childNodes[0]) {
|
||
range.isReal = true;
|
||
} else {
|
||
range.isReal = false;
|
||
}
|
||
return range;
|
||
};
|
||
writeRange = function(range) {
|
||
var r, s, textnode;
|
||
writeContent(word.val());
|
||
textnode = textfield.childNodes[0];
|
||
if (range.isReal && (textnode != null)) {
|
||
if (range.left < 0) {
|
||
range.left = 0;
|
||
}
|
||
range.right = Math.max(range.left, range.right);
|
||
if (range.right > textnode.length) {
|
||
range.right = textnode.length;
|
||
}
|
||
range.left = Math.min(range.left, range.right);
|
||
r = document.createRange();
|
||
r.setStart(textnode, range.left);
|
||
r.setEnd(textnode, range.right);
|
||
s = window.getSelection();
|
||
s.removeAllRanges();
|
||
return s.addRange(r);
|
||
}
|
||
};
|
||
writeContent = function(content) {
|
||
var c, content_array, i, _j, _len1, _results;
|
||
content_array = content.replace(new RegExp("\n", 'g'), " ").split(" ");
|
||
textfield.innerText = "";
|
||
_results = [];
|
||
for (i = _j = 0, _len1 = content_array.length; _j < _len1; i = ++_j) {
|
||
c = content_array[i];
|
||
textfield.innerText += c;
|
||
if (i !== content_array.length - 1) {
|
||
_results.push(textfield.innerHTML += ' ');
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
}
|
||
writeContent(this.val());
|
||
this.observe(function(events) {
|
||
var event, fix, o_pos, r, _j, _len1, _results;
|
||
_results = [];
|
||
for (_j = 0, _len1 = events.length; _j < _len1; _j++) {
|
||
event = events[_j];
|
||
if (!creator_token) {
|
||
if (event.type === "insert") {
|
||
o_pos = event.position;
|
||
fix = function(cursor) {
|
||
if (cursor <= o_pos) {
|
||
return cursor;
|
||
} else {
|
||
cursor += 1;
|
||
return cursor;
|
||
}
|
||
};
|
||
r = createRange(fix);
|
||
_results.push(writeRange(r));
|
||
} else if (event.type === "delete") {
|
||
o_pos = event.position;
|
||
fix = function(cursor) {
|
||
if (cursor < o_pos) {
|
||
return cursor;
|
||
} else {
|
||
cursor -= 1;
|
||
return cursor;
|
||
}
|
||
};
|
||
r = createRange(fix);
|
||
_results.push(writeRange(r));
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
});
|
||
textfield.onkeypress = function(event) {
|
||
var char, diff, pos, r;
|
||
if (word.is_deleted) {
|
||
textfield.onkeypress = null;
|
||
return true;
|
||
}
|
||
creator_token = true;
|
||
char = null;
|
||
if (event.keyCode === 13) {
|
||
char = '\n';
|
||
} else if (event.key != null) {
|
||
if (event.charCode === 32) {
|
||
char = " ";
|
||
} else {
|
||
char = event.key;
|
||
}
|
||
} else {
|
||
char = window.String.fromCharCode(event.keyCode);
|
||
}
|
||
if (char.length > 1) {
|
||
return true;
|
||
} else if (char.length > 0) {
|
||
r = createRange();
|
||
pos = Math.min(r.left, r.right);
|
||
diff = Math.abs(r.right - r.left);
|
||
word["delete"](pos, diff);
|
||
word.insert(pos, char);
|
||
r.left = pos + char.length;
|
||
r.right = r.left;
|
||
writeRange(r);
|
||
}
|
||
event.preventDefault();
|
||
creator_token = false;
|
||
return false;
|
||
};
|
||
textfield.onpaste = function(event) {
|
||
if (word.is_deleted) {
|
||
textfield.onpaste = null;
|
||
return true;
|
||
}
|
||
return event.preventDefault();
|
||
};
|
||
textfield.oncut = function(event) {
|
||
if (word.is_deleted) {
|
||
textfield.oncut = null;
|
||
return true;
|
||
}
|
||
return event.preventDefault();
|
||
};
|
||
return textfield.onkeydown = function(event) {
|
||
var del_length, diff, new_pos, pos, r, val;
|
||
creator_token = true;
|
||
if (word.is_deleted) {
|
||
textfield.onkeydown = null;
|
||
return true;
|
||
}
|
||
r = createRange();
|
||
pos = Math.min(r.left, r.right, word.val().length);
|
||
diff = Math.abs(r.left - r.right);
|
||
if ((event.keyCode != null) && event.keyCode === 8) {
|
||
if (diff > 0) {
|
||
word["delete"](pos, diff);
|
||
r.left = pos;
|
||
r.right = pos;
|
||
writeRange(r);
|
||
} else {
|
||
if ((event.ctrlKey != null) && event.ctrlKey) {
|
||
val = word.val();
|
||
new_pos = pos;
|
||
del_length = 0;
|
||
if (pos > 0) {
|
||
new_pos--;
|
||
del_length++;
|
||
}
|
||
while (new_pos > 0 && val[new_pos] !== " " && val[new_pos] !== '\n') {
|
||
new_pos--;
|
||
del_length++;
|
||
}
|
||
word["delete"](new_pos, pos - new_pos);
|
||
r.left = new_pos;
|
||
r.right = new_pos;
|
||
writeRange(r);
|
||
} else {
|
||
if (pos > 0) {
|
||
word["delete"](pos - 1, 1);
|
||
r.left = pos - 1;
|
||
r.right = pos - 1;
|
||
writeRange(r);
|
||
}
|
||
}
|
||
}
|
||
event.preventDefault();
|
||
creator_token = false;
|
||
return false;
|
||
} else if ((event.keyCode != null) && event.keyCode === 46) {
|
||
if (diff > 0) {
|
||
word["delete"](pos, diff);
|
||
r.left = pos;
|
||
r.right = pos;
|
||
writeRange(r);
|
||
} else {
|
||
word["delete"](pos, 1);
|
||
r.left = pos;
|
||
r.right = pos;
|
||
writeRange(r);
|
||
}
|
||
event.preventDefault();
|
||
creator_token = false;
|
||
return false;
|
||
} else {
|
||
creator_token = false;
|
||
return true;
|
||
}
|
||
};
|
||
};
|
||
|
||
return YText;
|
||
|
||
})();
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
if (window.Y != null) {
|
||
window.Y.Text = YText;
|
||
} else {
|
||
throw new Error("You must first import Y!");
|
||
}
|
||
}
|
||
|
||
if (typeof module !== "undefined" && module !== null) {
|
||
module.exports = YText;
|
||
}
|
||
|
||
|
||
},{}],68:[function(require,module,exports){
|
||
var ConnectorClass, adaptConnector;
|
||
|
||
ConnectorClass = require("./ConnectorClass");
|
||
|
||
adaptConnector = function(connector, engine, HB, execution_listener) {
|
||
var applyHB, encode_state_vector, f, getHB, getStateVector, name, parse_state_vector, send_;
|
||
for (name in ConnectorClass) {
|
||
f = ConnectorClass[name];
|
||
connector[name] = f;
|
||
}
|
||
connector.setIsBoundToY();
|
||
send_ = function(o) {
|
||
if ((o.uid.creator === HB.getUserId()) && (typeof o.uid.op_number !== "string") && (HB.getUserId() !== "_temp")) {
|
||
return connector.broadcast(o);
|
||
}
|
||
};
|
||
if (connector.invokeSync != null) {
|
||
HB.setInvokeSyncHandler(connector.invokeSync);
|
||
}
|
||
execution_listener.push(send_);
|
||
encode_state_vector = function(v) {
|
||
var value, _results;
|
||
_results = [];
|
||
for (name in v) {
|
||
value = v[name];
|
||
_results.push({
|
||
user: name,
|
||
state: value
|
||
});
|
||
}
|
||
return _results;
|
||
};
|
||
parse_state_vector = function(v) {
|
||
var s, state_vector, _i, _len;
|
||
state_vector = {};
|
||
for (_i = 0, _len = v.length; _i < _len; _i++) {
|
||
s = v[_i];
|
||
state_vector[s.user] = s.state;
|
||
}
|
||
return state_vector;
|
||
};
|
||
getStateVector = function() {
|
||
return encode_state_vector(HB.getOperationCounter());
|
||
};
|
||
getHB = function(v) {
|
||
var hb, json, state_vector;
|
||
state_vector = parse_state_vector(v);
|
||
hb = HB._encode(state_vector);
|
||
json = {
|
||
hb: hb,
|
||
state_vector: encode_state_vector(HB.getOperationCounter())
|
||
};
|
||
return json;
|
||
};
|
||
applyHB = function(hb, fromHB) {
|
||
return engine.applyOp(hb, fromHB);
|
||
};
|
||
connector.getStateVector = getStateVector;
|
||
connector.getHB = getHB;
|
||
connector.applyHB = applyHB;
|
||
if (connector.receive_handlers == null) {
|
||
connector.receive_handlers = [];
|
||
}
|
||
return connector.receive_handlers.push(function(sender, op) {
|
||
if (op.uid.creator !== HB.getUserId()) {
|
||
return engine.applyOp(op);
|
||
}
|
||
});
|
||
};
|
||
|
||
module.exports = adaptConnector;
|
||
|
||
|
||
},{"./ConnectorClass":69}],69:[function(require,module,exports){
|
||
module.exports = {
|
||
init: function(options) {
|
||
var req;
|
||
req = (function(_this) {
|
||
return function(name, choices) {
|
||
if (options[name] != null) {
|
||
if ((choices == null) || choices.some(function(c) {
|
||
return c === options[name];
|
||
})) {
|
||
return _this[name] = options[name];
|
||
} else {
|
||
throw new Error("You can set the '" + name + "' option to one of the following choices: " + JSON.encode(choices));
|
||
}
|
||
} else {
|
||
throw new Error("You must specify " + name + ", when initializing the Connector!");
|
||
}
|
||
};
|
||
})(this);
|
||
req("syncMethod", ["syncAll", "master-slave"]);
|
||
req("role", ["master", "slave"]);
|
||
req("user_id");
|
||
if (typeof this.on_user_id_set === "function") {
|
||
this.on_user_id_set(this.user_id);
|
||
}
|
||
if (options.perform_send_again != null) {
|
||
this.perform_send_again = options.perform_send_again;
|
||
} else {
|
||
this.perform_send_again = true;
|
||
}
|
||
if (this.role === "master") {
|
||
this.syncMethod = "syncAll";
|
||
}
|
||
this.is_synced = false;
|
||
this.connections = {};
|
||
if (this.receive_handlers == null) {
|
||
this.receive_handlers = [];
|
||
}
|
||
this.connections = {};
|
||
this.current_sync_target = null;
|
||
this.sent_hb_to_all_users = false;
|
||
return this.is_initialized = true;
|
||
},
|
||
isRoleMaster: function() {
|
||
return this.role === "master";
|
||
},
|
||
isRoleSlave: function() {
|
||
return this.role === "slave";
|
||
},
|
||
findNewSyncTarget: function() {
|
||
var c, user, _ref;
|
||
this.current_sync_target = null;
|
||
if (this.syncMethod === "syncAll") {
|
||
_ref = this.connections;
|
||
for (user in _ref) {
|
||
c = _ref[user];
|
||
if (!c.is_synced) {
|
||
this.performSync(user);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (this.current_sync_target == null) {
|
||
this.setStateSynced();
|
||
}
|
||
return null;
|
||
},
|
||
userLeft: function(user) {
|
||
delete this.connections[user];
|
||
return this.findNewSyncTarget();
|
||
},
|
||
userJoined: function(user, role) {
|
||
var _base;
|
||
if (role == null) {
|
||
throw new Error("Internal: You must specify the role of the joined user! E.g. userJoined('uid:3939','slave')");
|
||
}
|
||
if ((_base = this.connections)[user] == null) {
|
||
_base[user] = {};
|
||
}
|
||
this.connections[user].is_synced = false;
|
||
if ((!this.is_synced) || this.syncMethod === "syncAll") {
|
||
if (this.syncMethod === "syncAll") {
|
||
return this.performSync(user);
|
||
} else if (role === "master") {
|
||
return this.performSyncWithMaster(user);
|
||
}
|
||
}
|
||
},
|
||
whenSynced: function(args) {
|
||
if (args.constructore === Function) {
|
||
args = [args];
|
||
}
|
||
if (this.is_synced) {
|
||
return args[0].apply(this, args.slice(1));
|
||
} else {
|
||
if (this.compute_when_synced == null) {
|
||
this.compute_when_synced = [];
|
||
}
|
||
return this.compute_when_synced.push(args);
|
||
}
|
||
},
|
||
onReceive: function(f) {
|
||
return this.receive_handlers.push(f);
|
||
},
|
||
|
||
/*
|
||
* Broadcast a message to all connected peers.
|
||
* @param message {Object} The message to broadcast.
|
||
*
|
||
broadcast: (message)->
|
||
throw new Error "You must implement broadcast!"
|
||
|
||
*
|
||
* Send a message to a peer, or set of peers
|
||
*
|
||
send: (peer_s, message)->
|
||
throw new Error "You must implement send!"
|
||
*/
|
||
performSync: function(user) {
|
||
var hb, o, _hb, _i, _len;
|
||
if (this.current_sync_target == null) {
|
||
this.current_sync_target = user;
|
||
this.send(user, {
|
||
sync_step: "getHB",
|
||
send_again: "true",
|
||
data: []
|
||
});
|
||
if (!this.sent_hb_to_all_users) {
|
||
this.sent_hb_to_all_users = true;
|
||
hb = this.getHB([]).hb;
|
||
_hb = [];
|
||
for (_i = 0, _len = hb.length; _i < _len; _i++) {
|
||
o = hb[_i];
|
||
_hb.push(o);
|
||
if (_hb.length > 10) {
|
||
this.broadcast({
|
||
sync_step: "applyHB_",
|
||
data: _hb
|
||
});
|
||
_hb = [];
|
||
}
|
||
}
|
||
return this.broadcast({
|
||
sync_step: "applyHB",
|
||
data: _hb
|
||
});
|
||
}
|
||
}
|
||
},
|
||
performSyncWithMaster: function(user) {
|
||
var hb, o, _hb, _i, _len;
|
||
this.current_sync_target = user;
|
||
this.send(user, {
|
||
sync_step: "getHB",
|
||
send_again: "true",
|
||
data: []
|
||
});
|
||
hb = this.getHB([]).hb;
|
||
_hb = [];
|
||
for (_i = 0, _len = hb.length; _i < _len; _i++) {
|
||
o = hb[_i];
|
||
_hb.push(o);
|
||
if (_hb.length > 10) {
|
||
this.broadcast({
|
||
sync_step: "applyHB_",
|
||
data: _hb
|
||
});
|
||
_hb = [];
|
||
}
|
||
}
|
||
return this.broadcast({
|
||
sync_step: "applyHB",
|
||
data: _hb
|
||
});
|
||
},
|
||
setStateSynced: function() {
|
||
var f, _i, _len, _ref;
|
||
if (!this.is_synced) {
|
||
this.is_synced = true;
|
||
if (this.compute_when_synced != null) {
|
||
_ref = this.compute_when_synced;
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
f = _ref[_i];
|
||
f();
|
||
}
|
||
delete this.compute_when_synced;
|
||
}
|
||
return null;
|
||
}
|
||
},
|
||
receiveMessage: function(sender, res) {
|
||
var data, f, hb, o, sendApplyHB, send_again, _hb, _i, _j, _len, _len1, _ref, _results;
|
||
if (res.sync_step == null) {
|
||
_ref = this.receive_handlers;
|
||
_results = [];
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
f = _ref[_i];
|
||
_results.push(f(sender, res));
|
||
}
|
||
return _results;
|
||
} else {
|
||
if (sender === this.user_id) {
|
||
return;
|
||
}
|
||
if (res.sync_step === "getHB") {
|
||
data = this.getHB(res.data);
|
||
hb = data.hb;
|
||
_hb = [];
|
||
if (this.is_synced) {
|
||
sendApplyHB = (function(_this) {
|
||
return function(m) {
|
||
return _this.send(sender, m);
|
||
};
|
||
})(this);
|
||
} else {
|
||
sendApplyHB = (function(_this) {
|
||
return function(m) {
|
||
return _this.broadcast(m);
|
||
};
|
||
})(this);
|
||
}
|
||
for (_j = 0, _len1 = hb.length; _j < _len1; _j++) {
|
||
o = hb[_j];
|
||
_hb.push(o);
|
||
if (_hb.length > 10) {
|
||
sendApplyHB({
|
||
sync_step: "applyHB_",
|
||
data: _hb
|
||
});
|
||
_hb = [];
|
||
}
|
||
}
|
||
sendApplyHB({
|
||
sync_step: "applyHB",
|
||
data: _hb
|
||
});
|
||
if ((res.send_again != null) && this.perform_send_again) {
|
||
send_again = (function(_this) {
|
||
return function(sv) {
|
||
return function() {
|
||
hb = _this.getHB(sv).hb;
|
||
return _this.send(sender, {
|
||
sync_step: "applyHB",
|
||
data: hb,
|
||
sent_again: "true"
|
||
});
|
||
};
|
||
};
|
||
})(this)(data.state_vector);
|
||
return setTimeout(send_again, 3000);
|
||
}
|
||
} else if (res.sync_step === "applyHB") {
|
||
this.applyHB(res.data, sender === this.current_sync_target);
|
||
if ((this.syncMethod === "syncAll" || (res.sent_again != null)) && (!this.is_synced) && ((this.current_sync_target === sender) || (this.current_sync_target == null))) {
|
||
this.connections[sender].is_synced = true;
|
||
return this.findNewSyncTarget();
|
||
}
|
||
} else if (res.sync_step === "applyHB_") {
|
||
return this.applyHB(res.data, sender === this.current_sync_target);
|
||
}
|
||
}
|
||
},
|
||
parseMessageFromXml: function(m) {
|
||
var parse_array, parse_object;
|
||
parse_array = function(node) {
|
||
var n, _i, _len, _ref, _results;
|
||
_ref = node.children;
|
||
_results = [];
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
n = _ref[_i];
|
||
if (n.getAttribute("isArray") === "true") {
|
||
_results.push(parse_array(n));
|
||
} else {
|
||
_results.push(parse_object(n));
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
parse_object = function(node) {
|
||
var int, json, n, name, value, _i, _len, _ref, _ref1;
|
||
json = {};
|
||
_ref = node.attrs;
|
||
for (name in _ref) {
|
||
value = _ref[name];
|
||
int = parseInt(value);
|
||
if (isNaN(int) || ("" + int) !== value) {
|
||
json[name] = value;
|
||
} else {
|
||
json[name] = int;
|
||
}
|
||
}
|
||
_ref1 = node.children;
|
||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||
n = _ref1[_i];
|
||
name = n.name;
|
||
if (n.getAttribute("isArray") === "true") {
|
||
json[name] = parse_array(n);
|
||
} else {
|
||
json[name] = parse_object(n);
|
||
}
|
||
}
|
||
return json;
|
||
};
|
||
return parse_object(m);
|
||
},
|
||
encodeMessageToXml: function(m, json) {
|
||
var encode_array, encode_object;
|
||
encode_object = function(m, json) {
|
||
var name, value;
|
||
for (name in json) {
|
||
value = json[name];
|
||
if (value == null) {
|
||
|
||
} else if (value.constructor === Object) {
|
||
encode_object(m.c(name), value);
|
||
} else if (value.constructor === Array) {
|
||
encode_array(m.c(name), value);
|
||
} else {
|
||
m.setAttribute(name, value);
|
||
}
|
||
}
|
||
return m;
|
||
};
|
||
encode_array = function(m, array) {
|
||
var e, _i, _len;
|
||
m.setAttribute("isArray", "true");
|
||
for (_i = 0, _len = array.length; _i < _len; _i++) {
|
||
e = array[_i];
|
||
if (e.constructor === Object) {
|
||
encode_object(m.c("array-element"), e);
|
||
} else {
|
||
encode_array(m.c("array-element"), e);
|
||
}
|
||
}
|
||
return m;
|
||
};
|
||
if (json.constructor === Object) {
|
||
return encode_object(m.c("y", {
|
||
xmlns: "http://y.ninja/connector-stanza"
|
||
}), json);
|
||
} else if (json.constructor === Array) {
|
||
return encode_array(m.c("y", {
|
||
xmlns: "http://y.ninja/connector-stanza"
|
||
}), json);
|
||
} else {
|
||
throw new Error("I can't encode this json!");
|
||
}
|
||
},
|
||
setIsBoundToY: function() {
|
||
if (typeof this.on_bound_to_y === "function") {
|
||
this.on_bound_to_y();
|
||
}
|
||
delete this.when_bound_to_y;
|
||
return this.is_bound_to_y = true;
|
||
}
|
||
};
|
||
|
||
|
||
},{}],70:[function(require,module,exports){
|
||
var Engine;
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
window.unprocessed_counter = 0;
|
||
}
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
window.unprocessed_exec_counter = 0;
|
||
}
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
window.unprocessed_types = [];
|
||
}
|
||
|
||
Engine = (function() {
|
||
function Engine(HB, types) {
|
||
this.HB = HB;
|
||
this.types = types;
|
||
this.unprocessed_ops = [];
|
||
}
|
||
|
||
Engine.prototype.parseOperation = function(json) {
|
||
var type;
|
||
type = this.types[json.type];
|
||
if ((type != null ? type.parse : void 0) != null) {
|
||
return type.parse(json);
|
||
} else {
|
||
throw new Error("You forgot to specify a parser for type " + json.type + ". The message is " + (JSON.stringify(json)) + ".");
|
||
}
|
||
};
|
||
|
||
|
||
/*
|
||
applyOpsBundle: (ops_json)->
|
||
ops = []
|
||
for o in ops_json
|
||
ops.push @parseOperation o
|
||
for o in ops
|
||
if not o.execute()
|
||
@unprocessed_ops.push o
|
||
@tryUnprocessed()
|
||
*/
|
||
|
||
Engine.prototype.applyOpsCheckDouble = function(ops_json) {
|
||
var o, _i, _len, _results;
|
||
_results = [];
|
||
for (_i = 0, _len = ops_json.length; _i < _len; _i++) {
|
||
o = ops_json[_i];
|
||
if (this.HB.getOperation(o.uid) == null) {
|
||
_results.push(this.applyOp(o));
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
Engine.prototype.applyOps = function(ops_json) {
|
||
return this.applyOp(ops_json);
|
||
};
|
||
|
||
Engine.prototype.applyOp = function(op_json_array, fromHB) {
|
||
var o, op_json, _i, _len;
|
||
if (fromHB == null) {
|
||
fromHB = false;
|
||
}
|
||
if (op_json_array.constructor !== Array) {
|
||
op_json_array = [op_json_array];
|
||
}
|
||
for (_i = 0, _len = op_json_array.length; _i < _len; _i++) {
|
||
op_json = op_json_array[_i];
|
||
if (fromHB) {
|
||
op_json.fromHB = "true";
|
||
}
|
||
o = this.parseOperation(op_json);
|
||
o.parsed_from_json = op_json;
|
||
if (op_json.fromHB != null) {
|
||
o.fromHB = op_json.fromHB;
|
||
}
|
||
if (this.HB.getOperation(o) != null) {
|
||
|
||
} else if (((!this.HB.isExpectedOperation(o)) && (o.fromHB == null)) || (!o.execute())) {
|
||
this.unprocessed_ops.push(o);
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
window.unprocessed_types.push(o.type);
|
||
}
|
||
}
|
||
}
|
||
return this.tryUnprocessed();
|
||
};
|
||
|
||
Engine.prototype.tryUnprocessed = function() {
|
||
var old_length, op, unprocessed, _i, _len, _ref;
|
||
while (true) {
|
||
old_length = this.unprocessed_ops.length;
|
||
unprocessed = [];
|
||
_ref = this.unprocessed_ops;
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
op = _ref[_i];
|
||
if (this.HB.getOperation(op) != null) {
|
||
|
||
} else if ((!this.HB.isExpectedOperation(op) && (op.fromHB == null)) || (!op.execute())) {
|
||
unprocessed.push(op);
|
||
}
|
||
}
|
||
this.unprocessed_ops = unprocessed;
|
||
if (this.unprocessed_ops.length === old_length) {
|
||
break;
|
||
}
|
||
}
|
||
if (this.unprocessed_ops.length !== 0) {
|
||
return this.HB.invokeSync();
|
||
}
|
||
};
|
||
|
||
return Engine;
|
||
|
||
})();
|
||
|
||
module.exports = Engine;
|
||
|
||
|
||
},{}],71:[function(require,module,exports){
|
||
var HistoryBuffer,
|
||
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||
|
||
HistoryBuffer = (function() {
|
||
function HistoryBuffer(user_id) {
|
||
this.user_id = user_id;
|
||
this.emptyGarbage = __bind(this.emptyGarbage, this);
|
||
this.operation_counter = {};
|
||
this.buffer = {};
|
||
this.change_listeners = [];
|
||
this.garbage = [];
|
||
this.trash = [];
|
||
this.performGarbageCollection = true;
|
||
this.garbageCollectTimeout = 30000;
|
||
this.reserved_identifier_counter = 0;
|
||
setTimeout(this.emptyGarbage, this.garbageCollectTimeout);
|
||
}
|
||
|
||
HistoryBuffer.prototype.resetUserId = function(id) {
|
||
var o, o_name, own;
|
||
own = this.buffer[this.user_id];
|
||
if (own != null) {
|
||
for (o_name in own) {
|
||
o = own[o_name];
|
||
if (o.uid.creator != null) {
|
||
o.uid.creator = id;
|
||
}
|
||
if (o.uid.alt != null) {
|
||
o.uid.alt.creator = id;
|
||
}
|
||
}
|
||
if (this.buffer[id] != null) {
|
||
throw new Error("You are re-assigning an old user id - this is not (yet) possible!");
|
||
}
|
||
this.buffer[id] = own;
|
||
delete this.buffer[this.user_id];
|
||
}
|
||
if (this.operation_counter[this.user_id] != null) {
|
||
this.operation_counter[id] = this.operation_counter[this.user_id];
|
||
delete this.operation_counter[this.user_id];
|
||
}
|
||
return this.user_id = id;
|
||
};
|
||
|
||
HistoryBuffer.prototype.emptyGarbage = function() {
|
||
var o, _i, _len, _ref;
|
||
_ref = this.garbage;
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
o = _ref[_i];
|
||
if (typeof o.cleanup === "function") {
|
||
o.cleanup();
|
||
}
|
||
}
|
||
this.garbage = this.trash;
|
||
this.trash = [];
|
||
if (this.garbageCollectTimeout !== -1) {
|
||
this.garbageCollectTimeoutId = setTimeout(this.emptyGarbage, this.garbageCollectTimeout);
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
HistoryBuffer.prototype.getUserId = function() {
|
||
return this.user_id;
|
||
};
|
||
|
||
HistoryBuffer.prototype.addToGarbageCollector = function() {
|
||
var o, _i, _len, _results;
|
||
if (this.performGarbageCollection) {
|
||
_results = [];
|
||
for (_i = 0, _len = arguments.length; _i < _len; _i++) {
|
||
o = arguments[_i];
|
||
if (o != null) {
|
||
_results.push(this.garbage.push(o));
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
}
|
||
};
|
||
|
||
HistoryBuffer.prototype.stopGarbageCollection = function() {
|
||
this.performGarbageCollection = false;
|
||
this.setManualGarbageCollect();
|
||
this.garbage = [];
|
||
return this.trash = [];
|
||
};
|
||
|
||
HistoryBuffer.prototype.setManualGarbageCollect = function() {
|
||
this.garbageCollectTimeout = -1;
|
||
clearTimeout(this.garbageCollectTimeoutId);
|
||
return this.garbageCollectTimeoutId = void 0;
|
||
};
|
||
|
||
HistoryBuffer.prototype.setGarbageCollectTimeout = function(garbageCollectTimeout) {
|
||
this.garbageCollectTimeout = garbageCollectTimeout;
|
||
};
|
||
|
||
HistoryBuffer.prototype.getReservedUniqueIdentifier = function() {
|
||
return {
|
||
creator: '_',
|
||
op_number: "_" + (this.reserved_identifier_counter++)
|
||
};
|
||
};
|
||
|
||
HistoryBuffer.prototype.getOperationCounter = function(user_id) {
|
||
var ctn, res, user, _ref;
|
||
if (user_id == null) {
|
||
res = {};
|
||
_ref = this.operation_counter;
|
||
for (user in _ref) {
|
||
ctn = _ref[user];
|
||
res[user] = ctn;
|
||
}
|
||
return res;
|
||
} else {
|
||
return this.operation_counter[user_id];
|
||
}
|
||
};
|
||
|
||
HistoryBuffer.prototype.isExpectedOperation = function(o) {
|
||
var _base, _name;
|
||
if ((_base = this.operation_counter)[_name = o.uid.creator] == null) {
|
||
_base[_name] = 0;
|
||
}
|
||
o.uid.op_number <= this.operation_counter[o.uid.creator];
|
||
return true;
|
||
};
|
||
|
||
HistoryBuffer.prototype._encode = function(state_vector) {
|
||
var json, o, o_json, o_next, o_number, o_prev, u_name, unknown, user, _ref;
|
||
if (state_vector == null) {
|
||
state_vector = {};
|
||
}
|
||
json = [];
|
||
unknown = function(user, o_number) {
|
||
if ((user == null) || (o_number == null)) {
|
||
throw new Error("dah!");
|
||
}
|
||
return (state_vector[user] == null) || state_vector[user] <= o_number;
|
||
};
|
||
_ref = this.buffer;
|
||
for (u_name in _ref) {
|
||
user = _ref[u_name];
|
||
if (u_name === "_") {
|
||
continue;
|
||
}
|
||
for (o_number in user) {
|
||
o = user[o_number];
|
||
if ((o.uid.noOperation == null) && unknown(u_name, o_number)) {
|
||
o_json = o._encode();
|
||
if (o.next_cl != null) {
|
||
o_next = o.next_cl;
|
||
while ((o_next.next_cl != null) && unknown(o_next.uid.creator, o_next.uid.op_number)) {
|
||
o_next = o_next.next_cl;
|
||
}
|
||
o_json.next = o_next.getUid();
|
||
} else if (o.prev_cl != null) {
|
||
o_prev = o.prev_cl;
|
||
while ((o_prev.prev_cl != null) && unknown(o_prev.uid.creator, o_prev.uid.op_number)) {
|
||
o_prev = o_prev.prev_cl;
|
||
}
|
||
o_json.prev = o_prev.getUid();
|
||
}
|
||
json.push(o_json);
|
||
}
|
||
}
|
||
}
|
||
return json;
|
||
};
|
||
|
||
HistoryBuffer.prototype.getNextOperationIdentifier = function(user_id) {
|
||
var uid;
|
||
if (user_id == null) {
|
||
user_id = this.user_id;
|
||
}
|
||
if (this.operation_counter[user_id] == null) {
|
||
this.operation_counter[user_id] = 0;
|
||
}
|
||
uid = {
|
||
'creator': user_id,
|
||
'op_number': this.operation_counter[user_id]
|
||
};
|
||
this.operation_counter[user_id]++;
|
||
return uid;
|
||
};
|
||
|
||
HistoryBuffer.prototype.getOperation = function(uid) {
|
||
var o, _ref;
|
||
if (uid.uid != null) {
|
||
uid = uid.uid;
|
||
}
|
||
o = (_ref = this.buffer[uid.creator]) != null ? _ref[uid.op_number] : void 0;
|
||
if ((uid.sub != null) && (o != null)) {
|
||
return o.retrieveSub(uid.sub);
|
||
} else {
|
||
return o;
|
||
}
|
||
};
|
||
|
||
HistoryBuffer.prototype.addOperation = function(o) {
|
||
if (this.buffer[o.uid.creator] == null) {
|
||
this.buffer[o.uid.creator] = {};
|
||
}
|
||
if (this.buffer[o.uid.creator][o.uid.op_number] != null) {
|
||
throw new Error("You must not overwrite operations!");
|
||
}
|
||
if ((o.uid.op_number.constructor !== String) && (!this.isExpectedOperation(o)) && (o.fromHB == null)) {
|
||
throw new Error("this operation was not expected!");
|
||
}
|
||
this.addToCounter(o);
|
||
this.buffer[o.uid.creator][o.uid.op_number] = o;
|
||
return o;
|
||
};
|
||
|
||
HistoryBuffer.prototype.removeOperation = function(o) {
|
||
var _ref;
|
||
return (_ref = this.buffer[o.uid.creator]) != null ? delete _ref[o.uid.op_number] : void 0;
|
||
};
|
||
|
||
HistoryBuffer.prototype.setInvokeSyncHandler = function(f) {
|
||
return this.invokeSync = f;
|
||
};
|
||
|
||
HistoryBuffer.prototype.invokeSync = function() {};
|
||
|
||
HistoryBuffer.prototype.renewStateVector = function(state_vector) {
|
||
var state, user, _results;
|
||
_results = [];
|
||
for (user in state_vector) {
|
||
state = state_vector[user];
|
||
if (((this.operation_counter[user] == null) || (this.operation_counter[user] < state_vector[user])) && (state_vector[user] != null)) {
|
||
_results.push(this.operation_counter[user] = state_vector[user]);
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
HistoryBuffer.prototype.addToCounter = function(o) {
|
||
var _base, _name;
|
||
if ((_base = this.operation_counter)[_name = o.uid.creator] == null) {
|
||
_base[_name] = 0;
|
||
}
|
||
if (o.uid.creator !== this.getUserId()) {
|
||
if (o.uid.op_number === this.operation_counter[o.uid.creator]) {
|
||
this.operation_counter[o.uid.creator]++;
|
||
}
|
||
while (this.buffer[o.uid.creator][this.operation_counter[o.uid.creator]] != null) {
|
||
this.operation_counter[o.uid.creator]++;
|
||
}
|
||
return void 0;
|
||
}
|
||
};
|
||
|
||
return HistoryBuffer;
|
||
|
||
})();
|
||
|
||
module.exports = HistoryBuffer;
|
||
|
||
|
||
},{}],72:[function(require,module,exports){
|
||
var YObject;
|
||
|
||
YObject = (function() {
|
||
function YObject(_object) {
|
||
var name, val, _ref;
|
||
this._object = _object != null ? _object : {};
|
||
if (this._object.constructor === Object) {
|
||
_ref = this._object;
|
||
for (name in _ref) {
|
||
val = _ref[name];
|
||
if (val.constructor === Object) {
|
||
this._object[name] = new YObject(val);
|
||
}
|
||
}
|
||
} else {
|
||
throw new Error("Y.Object accepts Json Objects only");
|
||
}
|
||
}
|
||
|
||
YObject.prototype._name = "Object";
|
||
|
||
YObject.prototype._getModel = function(types, ops) {
|
||
var n, o, _ref;
|
||
if (this._model == null) {
|
||
this._model = new ops.MapManager(this).execute();
|
||
_ref = this._object;
|
||
for (n in _ref) {
|
||
o = _ref[n];
|
||
this._model.val(n, o);
|
||
}
|
||
}
|
||
delete this._object;
|
||
return this._model;
|
||
};
|
||
|
||
YObject.prototype._setModel = function(_model) {
|
||
this._model = _model;
|
||
return delete this._object;
|
||
};
|
||
|
||
YObject.prototype.observe = function(f) {
|
||
this._model.observe(f);
|
||
return this;
|
||
};
|
||
|
||
YObject.prototype.unobserve = function(f) {
|
||
this._model.unobserve(f);
|
||
return this;
|
||
};
|
||
|
||
YObject.prototype.val = function(name, content) {
|
||
var n, res, v, _ref;
|
||
if (this._model != null) {
|
||
return this._model.val.apply(this._model, arguments);
|
||
} else {
|
||
if (content != null) {
|
||
return this._object[name] = content;
|
||
} else if (name != null) {
|
||
return this._object[name];
|
||
} else {
|
||
res = {};
|
||
_ref = this._object;
|
||
for (n in _ref) {
|
||
v = _ref[n];
|
||
res[n] = v;
|
||
}
|
||
return res;
|
||
}
|
||
}
|
||
};
|
||
|
||
YObject.prototype["delete"] = function(name) {
|
||
this._model["delete"](name);
|
||
return this;
|
||
};
|
||
|
||
return YObject;
|
||
|
||
})();
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
if (window.Y != null) {
|
||
window.Y.Object = YObject;
|
||
} else {
|
||
throw new Error("You must first import Y!");
|
||
}
|
||
}
|
||
|
||
if (typeof module !== "undefined" && module !== null) {
|
||
module.exports = YObject;
|
||
}
|
||
|
||
|
||
},{}],73:[function(require,module,exports){
|
||
var __slice = [].slice,
|
||
__hasProp = {}.hasOwnProperty,
|
||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||
|
||
module.exports = function() {
|
||
var execution_listener, ops;
|
||
ops = {};
|
||
execution_listener = [];
|
||
ops.Operation = (function() {
|
||
function Operation(custom_type, uid, content, content_operations) {
|
||
var name, op;
|
||
if (custom_type != null) {
|
||
this.custom_type = custom_type;
|
||
}
|
||
this.is_deleted = false;
|
||
this.garbage_collected = false;
|
||
this.event_listeners = [];
|
||
if (uid != null) {
|
||
this.uid = uid;
|
||
}
|
||
if (content === void 0) {
|
||
|
||
} else if ((content != null) && (content.creator != null)) {
|
||
this.saveOperation('content', content);
|
||
} else {
|
||
this.content = content;
|
||
}
|
||
if (content_operations != null) {
|
||
this.content_operations = {};
|
||
for (name in content_operations) {
|
||
op = content_operations[name];
|
||
this.saveOperation(name, op, 'content_operations');
|
||
}
|
||
}
|
||
}
|
||
|
||
Operation.prototype.type = "Operation";
|
||
|
||
Operation.prototype.getContent = function(name) {
|
||
var content, n, v, _ref, _ref1;
|
||
if (this.content != null) {
|
||
if (this.content.getCustomType != null) {
|
||
return this.content.getCustomType();
|
||
} else if (this.content.constructor === Object) {
|
||
if (name != null) {
|
||
if (this.content[name] != null) {
|
||
return this.content[name];
|
||
} else {
|
||
return this.content_operations[name].getCustomType();
|
||
}
|
||
} else {
|
||
content = {};
|
||
_ref = this.content;
|
||
for (n in _ref) {
|
||
v = _ref[n];
|
||
content[n] = v;
|
||
}
|
||
if (this.content_operations != null) {
|
||
_ref1 = this.content_operations;
|
||
for (n in _ref1) {
|
||
v = _ref1[n];
|
||
v = v.getCustomType();
|
||
content[n] = v;
|
||
}
|
||
}
|
||
return content;
|
||
}
|
||
} else {
|
||
return this.content;
|
||
}
|
||
} else {
|
||
return this.content;
|
||
}
|
||
};
|
||
|
||
Operation.prototype.retrieveSub = function() {
|
||
throw new Error("sub properties are not enable on this operation type!");
|
||
};
|
||
|
||
Operation.prototype.observe = function(f) {
|
||
return this.event_listeners.push(f);
|
||
};
|
||
|
||
Operation.prototype.unobserve = function(f) {
|
||
return this.event_listeners = this.event_listeners.filter(function(g) {
|
||
return f !== g;
|
||
});
|
||
};
|
||
|
||
Operation.prototype.deleteAllObservers = function() {
|
||
return this.event_listeners = [];
|
||
};
|
||
|
||
Operation.prototype["delete"] = function() {
|
||
(new ops.Delete(void 0, this)).execute();
|
||
return null;
|
||
};
|
||
|
||
Operation.prototype.callEvent = function() {
|
||
var callon;
|
||
if (this.custom_type != null) {
|
||
callon = this.getCustomType();
|
||
} else {
|
||
callon = this;
|
||
}
|
||
return this.forwardEvent.apply(this, [callon].concat(__slice.call(arguments)));
|
||
};
|
||
|
||
Operation.prototype.forwardEvent = function() {
|
||
var args, f, op, _i, _len, _ref, _results;
|
||
op = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
||
_ref = this.event_listeners;
|
||
_results = [];
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
f = _ref[_i];
|
||
_results.push(f.call.apply(f, [op].concat(__slice.call(args))));
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
Operation.prototype.isDeleted = function() {
|
||
return this.is_deleted;
|
||
};
|
||
|
||
Operation.prototype.applyDelete = function(garbagecollect) {
|
||
if (garbagecollect == null) {
|
||
garbagecollect = true;
|
||
}
|
||
if (!this.garbage_collected) {
|
||
this.is_deleted = true;
|
||
if (garbagecollect) {
|
||
this.garbage_collected = true;
|
||
return this.HB.addToGarbageCollector(this);
|
||
}
|
||
}
|
||
};
|
||
|
||
Operation.prototype.cleanup = function() {
|
||
this.HB.removeOperation(this);
|
||
return this.deleteAllObservers();
|
||
};
|
||
|
||
Operation.prototype.setParent = function(parent) {
|
||
this.parent = parent;
|
||
};
|
||
|
||
Operation.prototype.getParent = function() {
|
||
return this.parent;
|
||
};
|
||
|
||
Operation.prototype.getUid = function() {
|
||
var map_uid;
|
||
if (this.uid.noOperation == null) {
|
||
return this.uid;
|
||
} else {
|
||
if (this.uid.alt != null) {
|
||
map_uid = this.uid.alt.cloneUid();
|
||
map_uid.sub = this.uid.sub;
|
||
return map_uid;
|
||
} else {
|
||
return void 0;
|
||
}
|
||
}
|
||
};
|
||
|
||
Operation.prototype.cloneUid = function() {
|
||
var n, uid, v, _ref;
|
||
uid = {};
|
||
_ref = this.getUid();
|
||
for (n in _ref) {
|
||
v = _ref[n];
|
||
uid[n] = v;
|
||
}
|
||
return uid;
|
||
};
|
||
|
||
Operation.prototype.execute = function() {
|
||
var l, _i, _len;
|
||
if (this.validateSavedOperations()) {
|
||
this.is_executed = true;
|
||
if (this.uid == null) {
|
||
this.uid = this.HB.getNextOperationIdentifier();
|
||
}
|
||
if (this.uid.noOperation == null) {
|
||
this.HB.addOperation(this);
|
||
for (_i = 0, _len = execution_listener.length; _i < _len; _i++) {
|
||
l = execution_listener[_i];
|
||
l(this._encode());
|
||
}
|
||
}
|
||
return this;
|
||
} else {
|
||
return false;
|
||
}
|
||
};
|
||
|
||
Operation.prototype.saveOperation = function(name, op, base) {
|
||
var dest, last_path, path, paths, _base, _i, _len;
|
||
if (base == null) {
|
||
base = "this";
|
||
}
|
||
if ((op != null) && (op._getModel != null)) {
|
||
op = op._getModel(this.custom_types, this.operations);
|
||
}
|
||
if (op == null) {
|
||
|
||
} else if ((op.execute != null) || !((op.op_number != null) && (op.creator != null))) {
|
||
if (base === "this") {
|
||
return this[name] = op;
|
||
} else {
|
||
dest = this[base];
|
||
paths = name.split("/");
|
||
last_path = paths.pop();
|
||
for (_i = 0, _len = paths.length; _i < _len; _i++) {
|
||
path = paths[_i];
|
||
dest = dest[path];
|
||
}
|
||
return dest[last_path] = op;
|
||
}
|
||
} else {
|
||
if (this.unchecked == null) {
|
||
this.unchecked = {};
|
||
}
|
||
if ((_base = this.unchecked)[base] == null) {
|
||
_base[base] = {};
|
||
}
|
||
return this.unchecked[base][name] = op;
|
||
}
|
||
};
|
||
|
||
Operation.prototype.validateSavedOperations = function() {
|
||
var base, base_name, dest, last_path, name, op, op_uid, path, paths, success, uninstantiated, _i, _len, _ref;
|
||
uninstantiated = {};
|
||
success = true;
|
||
_ref = this.unchecked;
|
||
for (base_name in _ref) {
|
||
base = _ref[base_name];
|
||
for (name in base) {
|
||
op_uid = base[name];
|
||
op = this.HB.getOperation(op_uid);
|
||
if (op) {
|
||
if (base_name === "this") {
|
||
this[name] = op;
|
||
} else {
|
||
dest = this[base_name];
|
||
paths = name.split("/");
|
||
last_path = paths.pop();
|
||
for (_i = 0, _len = paths.length; _i < _len; _i++) {
|
||
path = paths[_i];
|
||
dest = dest[path];
|
||
}
|
||
dest[last_path] = op;
|
||
}
|
||
} else {
|
||
if (uninstantiated[base_name] == null) {
|
||
uninstantiated[base_name] = {};
|
||
}
|
||
uninstantiated[base_name][name] = op_uid;
|
||
success = false;
|
||
}
|
||
}
|
||
}
|
||
if (!success) {
|
||
this.unchecked = uninstantiated;
|
||
return false;
|
||
} else {
|
||
delete this.unchecked;
|
||
return this;
|
||
}
|
||
};
|
||
|
||
Operation.prototype.getCustomType = function() {
|
||
var Type, t, _i, _len, _ref;
|
||
if (this.custom_type == null) {
|
||
return this;
|
||
} else {
|
||
if (this.custom_type.constructor === String) {
|
||
Type = this.custom_types;
|
||
_ref = this.custom_type.split(".");
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
t = _ref[_i];
|
||
Type = Type[t];
|
||
}
|
||
this.custom_type = new Type();
|
||
this.custom_type._setModel(this);
|
||
}
|
||
return this.custom_type;
|
||
}
|
||
};
|
||
|
||
Operation.prototype._encode = function(json) {
|
||
var n, o, operations, _ref, _ref1;
|
||
if (json == null) {
|
||
json = {};
|
||
}
|
||
json.type = this.type;
|
||
json.uid = this.getUid();
|
||
if (this.custom_type != null) {
|
||
if (this.custom_type.constructor === String) {
|
||
json.custom_type = this.custom_type;
|
||
} else {
|
||
json.custom_type = this.custom_type._name;
|
||
}
|
||
}
|
||
if (((_ref = this.content) != null ? _ref.getUid : void 0) != null) {
|
||
json.content = this.content.getUid();
|
||
} else {
|
||
json.content = this.content;
|
||
}
|
||
if (this.content_operations != null) {
|
||
operations = {};
|
||
_ref1 = this.content_operations;
|
||
for (n in _ref1) {
|
||
o = _ref1[n];
|
||
if (o._getModel != null) {
|
||
o = o._getModel(this.custom_types, this.operations);
|
||
}
|
||
operations[n] = o.getUid();
|
||
}
|
||
json.content_operations = operations;
|
||
}
|
||
return json;
|
||
};
|
||
|
||
return Operation;
|
||
|
||
})();
|
||
ops.Delete = (function(_super) {
|
||
__extends(Delete, _super);
|
||
|
||
function Delete(custom_type, uid, deletes) {
|
||
this.saveOperation('deletes', deletes);
|
||
Delete.__super__.constructor.call(this, custom_type, uid);
|
||
}
|
||
|
||
Delete.prototype.type = "Delete";
|
||
|
||
Delete.prototype._encode = function() {
|
||
return {
|
||
'type': "Delete",
|
||
'uid': this.getUid(),
|
||
'deletes': this.deletes.getUid()
|
||
};
|
||
};
|
||
|
||
Delete.prototype.execute = function() {
|
||
var res;
|
||
if (this.validateSavedOperations()) {
|
||
res = Delete.__super__.execute.apply(this, arguments);
|
||
if (res) {
|
||
this.deletes.applyDelete(this);
|
||
}
|
||
return res;
|
||
} else {
|
||
return false;
|
||
}
|
||
};
|
||
|
||
return Delete;
|
||
|
||
})(ops.Operation);
|
||
ops.Delete.parse = function(o) {
|
||
var deletes_uid, uid;
|
||
uid = o['uid'], deletes_uid = o['deletes'];
|
||
return new this(null, uid, deletes_uid);
|
||
};
|
||
ops.Insert = (function(_super) {
|
||
__extends(Insert, _super);
|
||
|
||
function Insert(custom_type, content, content_operations, parent, uid, prev_cl, next_cl, origin) {
|
||
this.saveOperation('parent', parent);
|
||
this.saveOperation('prev_cl', prev_cl);
|
||
this.saveOperation('next_cl', next_cl);
|
||
if (origin != null) {
|
||
this.saveOperation('origin', origin);
|
||
} else {
|
||
this.saveOperation('origin', prev_cl);
|
||
}
|
||
Insert.__super__.constructor.call(this, custom_type, uid, content, content_operations);
|
||
}
|
||
|
||
Insert.prototype.type = "Insert";
|
||
|
||
Insert.prototype.val = function() {
|
||
return this.getContent();
|
||
};
|
||
|
||
Insert.prototype.getNext = function(i) {
|
||
var n;
|
||
if (i == null) {
|
||
i = 1;
|
||
}
|
||
n = this;
|
||
while (i > 0 && n.is_deleted && (n.next_cl != null)) {
|
||
n = n.next_cl;
|
||
if (!n.is_deleted) {
|
||
i--;
|
||
}
|
||
}
|
||
return n;
|
||
};
|
||
|
||
Insert.prototype.getPrev = function(i) {
|
||
var n;
|
||
if (i == null) {
|
||
i = 1;
|
||
}
|
||
n = this;
|
||
while (i > 0 && n.is_deleted && (n.prev_cl != null)) {
|
||
n = n.prev_cl;
|
||
if (!n.is_deleted) {
|
||
i--;
|
||
}
|
||
}
|
||
return n;
|
||
};
|
||
|
||
Insert.prototype.applyDelete = function(o) {
|
||
var callLater, garbagecollect;
|
||
if (this.deleted_by == null) {
|
||
this.deleted_by = [];
|
||
}
|
||
callLater = false;
|
||
if ((this.parent != null) && !this.is_deleted && (o != null)) {
|
||
callLater = true;
|
||
}
|
||
if (o != null) {
|
||
this.deleted_by.push(o);
|
||
}
|
||
garbagecollect = false;
|
||
if (this.next_cl.isDeleted()) {
|
||
garbagecollect = true;
|
||
}
|
||
Insert.__super__.applyDelete.call(this, garbagecollect);
|
||
if (callLater) {
|
||
this.parent.callOperationSpecificDeleteEvents(this, o);
|
||
}
|
||
if ((this.prev_cl != null) && this.prev_cl.isDeleted()) {
|
||
return this.prev_cl.applyDelete();
|
||
}
|
||
};
|
||
|
||
Insert.prototype.cleanup = function() {
|
||
var d, o, _i, _len, _ref;
|
||
if (this.next_cl.isDeleted()) {
|
||
_ref = this.deleted_by;
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
d = _ref[_i];
|
||
d.cleanup();
|
||
}
|
||
o = this.next_cl;
|
||
while (o.type !== "Delimiter") {
|
||
if (o.origin === this) {
|
||
o.origin = this.prev_cl;
|
||
}
|
||
o = o.next_cl;
|
||
}
|
||
this.prev_cl.next_cl = this.next_cl;
|
||
this.next_cl.prev_cl = this.prev_cl;
|
||
if (this.content instanceof ops.Operation && !(this.content instanceof ops.Insert)) {
|
||
this.content.referenced_by--;
|
||
if (this.content.referenced_by <= 0 && !this.content.is_deleted) {
|
||
this.content.applyDelete();
|
||
}
|
||
}
|
||
delete this.content;
|
||
return Insert.__super__.cleanup.apply(this, arguments);
|
||
}
|
||
};
|
||
|
||
Insert.prototype.getDistanceToOrigin = function() {
|
||
var d, o;
|
||
d = 0;
|
||
o = this.prev_cl;
|
||
while (true) {
|
||
if (this.origin === o) {
|
||
break;
|
||
}
|
||
d++;
|
||
o = o.prev_cl;
|
||
}
|
||
return d;
|
||
};
|
||
|
||
Insert.prototype.execute = function() {
|
||
var distance_to_origin, i, o, _base;
|
||
if (!this.validateSavedOperations()) {
|
||
return false;
|
||
} else {
|
||
if (this.content instanceof ops.Operation) {
|
||
this.content.insert_parent = this;
|
||
if ((_base = this.content).referenced_by == null) {
|
||
_base.referenced_by = 0;
|
||
}
|
||
this.content.referenced_by++;
|
||
}
|
||
if (this.parent != null) {
|
||
if (this.prev_cl == null) {
|
||
this.prev_cl = this.parent.beginning;
|
||
}
|
||
if (this.origin == null) {
|
||
this.origin = this.prev_cl;
|
||
} else if (this.origin === "Delimiter") {
|
||
this.origin = this.parent.beginning;
|
||
}
|
||
if (this.next_cl == null) {
|
||
this.next_cl = this.parent.end;
|
||
}
|
||
}
|
||
if (this.prev_cl != null) {
|
||
distance_to_origin = this.getDistanceToOrigin();
|
||
o = this.prev_cl.next_cl;
|
||
i = distance_to_origin;
|
||
while (true) {
|
||
if (o !== this.next_cl) {
|
||
if (o.getDistanceToOrigin() === i) {
|
||
if (o.uid.creator < this.uid.creator) {
|
||
this.prev_cl = o;
|
||
distance_to_origin = i + 1;
|
||
} else {
|
||
|
||
}
|
||
} else if (o.getDistanceToOrigin() < i) {
|
||
if (i - distance_to_origin <= o.getDistanceToOrigin()) {
|
||
this.prev_cl = o;
|
||
distance_to_origin = i + 1;
|
||
} else {
|
||
|
||
}
|
||
} else {
|
||
break;
|
||
}
|
||
i++;
|
||
o = o.next_cl;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
this.next_cl = this.prev_cl.next_cl;
|
||
this.prev_cl.next_cl = this;
|
||
this.next_cl.prev_cl = this;
|
||
}
|
||
this.setParent(this.prev_cl.getParent());
|
||
Insert.__super__.execute.apply(this, arguments);
|
||
this.parent.callOperationSpecificInsertEvents(this);
|
||
return this;
|
||
}
|
||
};
|
||
|
||
Insert.prototype.getPosition = function() {
|
||
var position, prev;
|
||
position = 0;
|
||
prev = this.prev_cl;
|
||
while (true) {
|
||
if (prev instanceof ops.Delimiter) {
|
||
break;
|
||
}
|
||
if (!prev.isDeleted()) {
|
||
position++;
|
||
}
|
||
prev = prev.prev_cl;
|
||
}
|
||
return position;
|
||
};
|
||
|
||
Insert.prototype._encode = function(json) {
|
||
if (json == null) {
|
||
json = {};
|
||
}
|
||
json.prev = this.prev_cl.getUid();
|
||
json.next = this.next_cl.getUid();
|
||
if (this.origin.type === "Delimiter") {
|
||
json.origin = "Delimiter";
|
||
} else if (this.origin !== this.prev_cl) {
|
||
json.origin = this.origin.getUid();
|
||
}
|
||
json.parent = this.parent.getUid();
|
||
return Insert.__super__._encode.call(this, json);
|
||
};
|
||
|
||
return Insert;
|
||
|
||
})(ops.Operation);
|
||
ops.Insert.parse = function(json) {
|
||
var content, content_operations, next, origin, parent, prev, uid;
|
||
content = json['content'], content_operations = json['content_operations'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], parent = json['parent'];
|
||
return new this(null, content, content_operations, parent, uid, prev, next, origin);
|
||
};
|
||
ops.Delimiter = (function(_super) {
|
||
__extends(Delimiter, _super);
|
||
|
||
function Delimiter(prev_cl, next_cl, origin) {
|
||
this.saveOperation('prev_cl', prev_cl);
|
||
this.saveOperation('next_cl', next_cl);
|
||
this.saveOperation('origin', prev_cl);
|
||
Delimiter.__super__.constructor.call(this, null, {
|
||
noOperation: true
|
||
});
|
||
}
|
||
|
||
Delimiter.prototype.type = "Delimiter";
|
||
|
||
Delimiter.prototype.applyDelete = function() {
|
||
var o;
|
||
Delimiter.__super__.applyDelete.call(this);
|
||
o = this.prev_cl;
|
||
while (o != null) {
|
||
o.applyDelete();
|
||
o = o.prev_cl;
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
Delimiter.prototype.cleanup = function() {
|
||
return Delimiter.__super__.cleanup.call(this);
|
||
};
|
||
|
||
Delimiter.prototype.execute = function() {
|
||
var _ref, _ref1;
|
||
if (((_ref = this.unchecked) != null ? _ref['next_cl'] : void 0) != null) {
|
||
return Delimiter.__super__.execute.apply(this, arguments);
|
||
} else if ((_ref1 = this.unchecked) != null ? _ref1['prev_cl'] : void 0) {
|
||
if (this.validateSavedOperations()) {
|
||
if (this.prev_cl.next_cl != null) {
|
||
throw new Error("Probably duplicated operations");
|
||
}
|
||
this.prev_cl.next_cl = this;
|
||
return Delimiter.__super__.execute.apply(this, arguments);
|
||
} else {
|
||
return false;
|
||
}
|
||
} else if ((this.prev_cl != null) && (this.prev_cl.next_cl == null)) {
|
||
delete this.prev_cl.unchecked.next_cl;
|
||
this.prev_cl.next_cl = this;
|
||
return Delimiter.__super__.execute.apply(this, arguments);
|
||
} else if ((this.prev_cl != null) || (this.next_cl != null) || true) {
|
||
return Delimiter.__super__.execute.apply(this, arguments);
|
||
}
|
||
};
|
||
|
||
Delimiter.prototype._encode = function() {
|
||
var _ref, _ref1;
|
||
return {
|
||
'type': this.type,
|
||
'uid': this.getUid(),
|
||
'prev': (_ref = this.prev_cl) != null ? _ref.getUid() : void 0,
|
||
'next': (_ref1 = this.next_cl) != null ? _ref1.getUid() : void 0
|
||
};
|
||
};
|
||
|
||
return Delimiter;
|
||
|
||
})(ops.Operation);
|
||
ops.Delimiter.parse = function(json) {
|
||
var next, prev, uid;
|
||
uid = json['uid'], prev = json['prev'], next = json['next'];
|
||
return new this(uid, prev, next);
|
||
};
|
||
return {
|
||
'operations': ops,
|
||
'execution_listener': execution_listener
|
||
};
|
||
};
|
||
|
||
|
||
},{}],74:[function(require,module,exports){
|
||
var basic_ops_uninitialized,
|
||
__hasProp = {}.hasOwnProperty,
|
||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||
|
||
basic_ops_uninitialized = require("./Basic");
|
||
|
||
module.exports = function() {
|
||
var basic_ops, ops;
|
||
basic_ops = basic_ops_uninitialized();
|
||
ops = basic_ops.operations;
|
||
ops.MapManager = (function(_super) {
|
||
__extends(MapManager, _super);
|
||
|
||
function MapManager(custom_type, uid, content, content_operations) {
|
||
this._map = {};
|
||
MapManager.__super__.constructor.call(this, custom_type, uid, content, content_operations);
|
||
}
|
||
|
||
MapManager.prototype.type = "MapManager";
|
||
|
||
MapManager.prototype.applyDelete = function() {
|
||
var name, p, _ref;
|
||
_ref = this._map;
|
||
for (name in _ref) {
|
||
p = _ref[name];
|
||
p.applyDelete();
|
||
}
|
||
return MapManager.__super__.applyDelete.call(this);
|
||
};
|
||
|
||
MapManager.prototype.cleanup = function() {
|
||
return MapManager.__super__.cleanup.call(this);
|
||
};
|
||
|
||
MapManager.prototype.map = function(f) {
|
||
var n, v, _ref;
|
||
_ref = this._map;
|
||
for (n in _ref) {
|
||
v = _ref[n];
|
||
f(n, v);
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
MapManager.prototype.val = function(name, content) {
|
||
var o, prop, rep, res, result, _ref;
|
||
if (arguments.length > 1) {
|
||
if ((content != null) && (content._getModel != null)) {
|
||
rep = content._getModel(this.custom_types, this.operations);
|
||
} else {
|
||
rep = content;
|
||
}
|
||
this.retrieveSub(name).replace(rep);
|
||
return this.getCustomType();
|
||
} else if (name != null) {
|
||
prop = this._map[name];
|
||
if ((prop != null) && !prop.isContentDeleted()) {
|
||
res = prop.val();
|
||
if (res instanceof ops.Operation) {
|
||
return res.getCustomType();
|
||
} else {
|
||
return res;
|
||
}
|
||
} else {
|
||
return void 0;
|
||
}
|
||
} else {
|
||
result = {};
|
||
_ref = this._map;
|
||
for (name in _ref) {
|
||
o = _ref[name];
|
||
if (!o.isContentDeleted()) {
|
||
result[name] = o.val();
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
};
|
||
|
||
MapManager.prototype["delete"] = function(name) {
|
||
var _ref;
|
||
if ((_ref = this._map[name]) != null) {
|
||
_ref.deleteContent();
|
||
}
|
||
return this;
|
||
};
|
||
|
||
MapManager.prototype.retrieveSub = function(property_name) {
|
||
var event_properties, event_this, rm, rm_uid;
|
||
if (this._map[property_name] == null) {
|
||
event_properties = {
|
||
name: property_name
|
||
};
|
||
event_this = this;
|
||
rm_uid = {
|
||
noOperation: true,
|
||
sub: property_name,
|
||
alt: this
|
||
};
|
||
rm = new ops.ReplaceManager(null, event_properties, event_this, rm_uid);
|
||
this._map[property_name] = rm;
|
||
rm.setParent(this, property_name);
|
||
rm.execute();
|
||
}
|
||
return this._map[property_name];
|
||
};
|
||
|
||
return MapManager;
|
||
|
||
})(ops.Operation);
|
||
ops.MapManager.parse = function(json) {
|
||
var content, content_operations, custom_type, uid;
|
||
uid = json['uid'], custom_type = json['custom_type'], content = json['content'], content_operations = json['content_operations'];
|
||
return new this(custom_type, uid, content, content_operations);
|
||
};
|
||
ops.ListManager = (function(_super) {
|
||
__extends(ListManager, _super);
|
||
|
||
function ListManager(custom_type, uid, content, content_operations) {
|
||
this.beginning = new ops.Delimiter(void 0, void 0);
|
||
this.end = new ops.Delimiter(this.beginning, void 0);
|
||
this.beginning.next_cl = this.end;
|
||
this.beginning.execute();
|
||
this.end.execute();
|
||
ListManager.__super__.constructor.call(this, custom_type, uid, content, content_operations);
|
||
}
|
||
|
||
ListManager.prototype.type = "ListManager";
|
||
|
||
ListManager.prototype.applyDelete = function() {
|
||
var o;
|
||
o = this.beginning;
|
||
while (o != null) {
|
||
o.applyDelete();
|
||
o = o.next_cl;
|
||
}
|
||
return ListManager.__super__.applyDelete.call(this);
|
||
};
|
||
|
||
ListManager.prototype.cleanup = function() {
|
||
return ListManager.__super__.cleanup.call(this);
|
||
};
|
||
|
||
ListManager.prototype.toJson = function(transform_to_value) {
|
||
var i, o, val, _i, _len, _results;
|
||
if (transform_to_value == null) {
|
||
transform_to_value = false;
|
||
}
|
||
val = this.val();
|
||
_results = [];
|
||
for (o = _i = 0, _len = val.length; _i < _len; o = ++_i) {
|
||
i = val[o];
|
||
if (o instanceof ops.Object) {
|
||
_results.push(o.toJson(transform_to_value));
|
||
} else if (o instanceof ops.ListManager) {
|
||
_results.push(o.toJson(transform_to_value));
|
||
} else if (transform_to_value && o instanceof ops.Operation) {
|
||
_results.push(o.val());
|
||
} else {
|
||
_results.push(o);
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
ListManager.prototype.execute = function() {
|
||
if (this.validateSavedOperations()) {
|
||
this.beginning.setParent(this);
|
||
this.end.setParent(this);
|
||
return ListManager.__super__.execute.apply(this, arguments);
|
||
} else {
|
||
return false;
|
||
}
|
||
};
|
||
|
||
ListManager.prototype.getLastOperation = function() {
|
||
return this.end.prev_cl;
|
||
};
|
||
|
||
ListManager.prototype.getFirstOperation = function() {
|
||
return this.beginning.next_cl;
|
||
};
|
||
|
||
ListManager.prototype.toArray = function() {
|
||
var o, result;
|
||
o = this.beginning.next_cl;
|
||
result = [];
|
||
while (o !== this.end) {
|
||
if (!o.is_deleted) {
|
||
result.push(o.val());
|
||
}
|
||
o = o.next_cl;
|
||
}
|
||
return result;
|
||
};
|
||
|
||
ListManager.prototype.map = function(f) {
|
||
var o, result;
|
||
o = this.beginning.next_cl;
|
||
result = [];
|
||
while (o !== this.end) {
|
||
if (!o.is_deleted) {
|
||
result.push(f(o));
|
||
}
|
||
o = o.next_cl;
|
||
}
|
||
return result;
|
||
};
|
||
|
||
ListManager.prototype.fold = function(init, f) {
|
||
var o;
|
||
o = this.beginning.next_cl;
|
||
while (o !== this.end) {
|
||
if (!o.is_deleted) {
|
||
init = f(init, o);
|
||
}
|
||
o = o.next_cl;
|
||
}
|
||
return init;
|
||
};
|
||
|
||
ListManager.prototype.val = function(pos) {
|
||
var o;
|
||
if (pos != null) {
|
||
o = this.getOperationByPosition(pos + 1);
|
||
if (!(o instanceof ops.Delimiter)) {
|
||
return o.val();
|
||
} else {
|
||
throw new Error("this position does not exist");
|
||
}
|
||
} else {
|
||
return this.toArray();
|
||
}
|
||
};
|
||
|
||
ListManager.prototype.ref = function(pos) {
|
||
var o;
|
||
if (pos != null) {
|
||
o = this.getOperationByPosition(pos + 1);
|
||
if (!(o instanceof ops.Delimiter)) {
|
||
return o;
|
||
} else {
|
||
return null;
|
||
}
|
||
} else {
|
||
throw new Error("you must specify a position parameter");
|
||
}
|
||
};
|
||
|
||
ListManager.prototype.getOperationByPosition = function(position) {
|
||
var o;
|
||
o = this.beginning;
|
||
while (true) {
|
||
if (o instanceof ops.Delimiter && (o.prev_cl != null)) {
|
||
o = o.prev_cl;
|
||
while (o.isDeleted() && (o.prev_cl != null)) {
|
||
o = o.prev_cl;
|
||
}
|
||
break;
|
||
}
|
||
if (position <= 0 && !o.isDeleted()) {
|
||
break;
|
||
}
|
||
o = o.next_cl;
|
||
if (!o.isDeleted()) {
|
||
position -= 1;
|
||
}
|
||
}
|
||
return o;
|
||
};
|
||
|
||
ListManager.prototype.push = function(content) {
|
||
return this.insertAfter(this.end.prev_cl, [content]);
|
||
};
|
||
|
||
ListManager.prototype.insertAfter = function(left, contents) {
|
||
var c, right, tmp, _i, _len;
|
||
right = left.next_cl;
|
||
while (right.isDeleted()) {
|
||
right = right.next_cl;
|
||
}
|
||
left = right.prev_cl;
|
||
if (contents instanceof ops.Operation) {
|
||
(new ops.Insert(null, content, null, void 0, void 0, left, right)).execute();
|
||
} else {
|
||
for (_i = 0, _len = contents.length; _i < _len; _i++) {
|
||
c = contents[_i];
|
||
if ((c != null) && (c._name != null) && (c._getModel != null)) {
|
||
c = c._getModel(this.custom_types, this.operations);
|
||
}
|
||
tmp = (new ops.Insert(null, c, null, void 0, void 0, left, right)).execute();
|
||
left = tmp;
|
||
}
|
||
}
|
||
return this;
|
||
};
|
||
|
||
ListManager.prototype.insert = function(position, contents) {
|
||
var ith;
|
||
ith = this.getOperationByPosition(position);
|
||
return this.insertAfter(ith, contents);
|
||
};
|
||
|
||
ListManager.prototype["delete"] = function(position, length) {
|
||
var d, delete_ops, i, o, _i;
|
||
if (length == null) {
|
||
length = 1;
|
||
}
|
||
o = this.getOperationByPosition(position + 1);
|
||
delete_ops = [];
|
||
for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) {
|
||
if (o instanceof ops.Delimiter) {
|
||
break;
|
||
}
|
||
d = (new ops.Delete(null, void 0, o)).execute();
|
||
o = o.next_cl;
|
||
while ((!(o instanceof ops.Delimiter)) && o.isDeleted()) {
|
||
o = o.next_cl;
|
||
}
|
||
delete_ops.push(d._encode());
|
||
}
|
||
return this;
|
||
};
|
||
|
||
ListManager.prototype.callOperationSpecificInsertEvents = function(op) {
|
||
var getContentType;
|
||
getContentType = function(content) {
|
||
if (content instanceof ops.Operation) {
|
||
return content.getCustomType();
|
||
} else {
|
||
return content;
|
||
}
|
||
};
|
||
return this.callEvent([
|
||
{
|
||
type: "insert",
|
||
reference: op,
|
||
position: op.getPosition(),
|
||
object: this.getCustomType(),
|
||
changedBy: op.uid.creator,
|
||
value: getContentType(op.val())
|
||
}
|
||
]);
|
||
};
|
||
|
||
ListManager.prototype.callOperationSpecificDeleteEvents = function(op, del_op) {
|
||
return this.callEvent([
|
||
{
|
||
type: "delete",
|
||
reference: op,
|
||
position: op.getPosition(),
|
||
object: this.getCustomType(),
|
||
length: 1,
|
||
changedBy: del_op.uid.creator,
|
||
oldValue: op.val()
|
||
}
|
||
]);
|
||
};
|
||
|
||
return ListManager;
|
||
|
||
})(ops.Operation);
|
||
ops.ListManager.parse = function(json) {
|
||
var content, content_operations, custom_type, uid;
|
||
uid = json['uid'], custom_type = json['custom_type'], content = json['content'], content_operations = json['content_operations'];
|
||
return new this(custom_type, uid, content, content_operations);
|
||
};
|
||
ops.Composition = (function(_super) {
|
||
__extends(Composition, _super);
|
||
|
||
function Composition(custom_type, _composition_value, composition_value_operations, uid, tmp_composition_ref) {
|
||
var n, o;
|
||
this._composition_value = _composition_value;
|
||
Composition.__super__.constructor.call(this, custom_type, uid);
|
||
if (tmp_composition_ref != null) {
|
||
this.tmp_composition_ref = tmp_composition_ref;
|
||
} else {
|
||
this.composition_ref = this.end.prev_cl;
|
||
}
|
||
if (composition_value_operations != null) {
|
||
this.composition_value_operations = {};
|
||
for (n in composition_value_operations) {
|
||
o = composition_value_operations[n];
|
||
this.saveOperation(n, o, '_composition_value');
|
||
}
|
||
}
|
||
}
|
||
|
||
Composition.prototype.type = "Composition";
|
||
|
||
Composition.prototype.execute = function() {
|
||
if (this.validateSavedOperations()) {
|
||
this.getCustomType()._setCompositionValue(this._composition_value);
|
||
delete this._composition_value;
|
||
return Composition.__super__.execute.apply(this, arguments);
|
||
} else {
|
||
return false;
|
||
}
|
||
};
|
||
|
||
Composition.prototype.callOperationSpecificInsertEvents = function(op) {
|
||
var o;
|
||
if (this.tmp_composition_ref != null) {
|
||
if (op.uid.creator === this.tmp_composition_ref.creator && op.uid.op_number === this.tmp_composition_ref.op_number) {
|
||
this.composition_ref = op;
|
||
delete this.tmp_composition_ref;
|
||
o = op.next_cl;
|
||
while (o.next_cl != null) {
|
||
if (!o.isDeleted()) {
|
||
this.callOperationSpecificInsertEvents(o);
|
||
}
|
||
o = o.next_cl;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
if (this.composition_ref.next_cl === op) {
|
||
op.undo_delta = this.getCustomType()._apply(op.val());
|
||
} else {
|
||
o = this.end.prev_cl;
|
||
while (o !== op) {
|
||
this.getCustomType()._unapply(o.undo_delta);
|
||
o = o.prev_cl;
|
||
}
|
||
while (o !== this.end) {
|
||
o.undo_delta = this.getCustomType()._apply(o.val());
|
||
o = o.next_cl;
|
||
}
|
||
}
|
||
this.composition_ref = this.end.prev_cl;
|
||
return this.callEvent([
|
||
{
|
||
type: "update",
|
||
changedBy: op.uid.creator,
|
||
newValue: this.val()
|
||
}
|
||
]);
|
||
};
|
||
|
||
Composition.prototype.callOperationSpecificDeleteEvents = function(op, del_op) {};
|
||
|
||
Composition.prototype.applyDelta = function(delta, operations) {
|
||
(new ops.Insert(null, delta, operations, this, null, this.end.prev_cl, this.end)).execute();
|
||
return void 0;
|
||
};
|
||
|
||
Composition.prototype._encode = function(json) {
|
||
var custom, n, o, _ref;
|
||
if (json == null) {
|
||
json = {};
|
||
}
|
||
custom = this.getCustomType()._getCompositionValue();
|
||
json.composition_value = custom.composition_value;
|
||
if (custom.composition_value_operations != null) {
|
||
json.composition_value_operations = {};
|
||
_ref = custom.composition_value_operations;
|
||
for (n in _ref) {
|
||
o = _ref[n];
|
||
json.composition_value_operations[n] = o.getUid();
|
||
}
|
||
}
|
||
if (this.composition_ref != null) {
|
||
json.composition_ref = this.composition_ref.getUid();
|
||
} else {
|
||
json.composition_ref = this.tmp_composition_ref;
|
||
}
|
||
return Composition.__super__._encode.call(this, json);
|
||
};
|
||
|
||
return Composition;
|
||
|
||
})(ops.ListManager);
|
||
ops.Composition.parse = function(json) {
|
||
var composition_ref, composition_value, composition_value_operations, custom_type, uid;
|
||
uid = json['uid'], custom_type = json['custom_type'], composition_value = json['composition_value'], composition_value_operations = json['composition_value_operations'], composition_ref = json['composition_ref'];
|
||
return new this(custom_type, composition_value, composition_value_operations, uid, composition_ref);
|
||
};
|
||
ops.ReplaceManager = (function(_super) {
|
||
__extends(ReplaceManager, _super);
|
||
|
||
function ReplaceManager(custom_type, event_properties, event_this, uid) {
|
||
this.event_properties = event_properties;
|
||
this.event_this = event_this;
|
||
if (this.event_properties['object'] == null) {
|
||
this.event_properties['object'] = this.event_this.getCustomType();
|
||
}
|
||
ReplaceManager.__super__.constructor.call(this, custom_type, uid);
|
||
}
|
||
|
||
ReplaceManager.prototype.type = "ReplaceManager";
|
||
|
||
ReplaceManager.prototype.callEventDecorator = function(events) {
|
||
var event, name, prop, _i, _len, _ref;
|
||
if (!this.isDeleted()) {
|
||
for (_i = 0, _len = events.length; _i < _len; _i++) {
|
||
event = events[_i];
|
||
_ref = this.event_properties;
|
||
for (name in _ref) {
|
||
prop = _ref[name];
|
||
event[name] = prop;
|
||
}
|
||
}
|
||
this.event_this.callEvent(events);
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
ReplaceManager.prototype.callOperationSpecificInsertEvents = function(op) {
|
||
var old_value;
|
||
if (op.next_cl.type === "Delimiter" && op.prev_cl.type !== "Delimiter") {
|
||
if (!op.is_deleted) {
|
||
old_value = op.prev_cl.val();
|
||
this.callEventDecorator([
|
||
{
|
||
type: "update",
|
||
changedBy: op.uid.creator,
|
||
oldValue: old_value
|
||
}
|
||
]);
|
||
}
|
||
op.prev_cl.applyDelete();
|
||
} else if (op.next_cl.type !== "Delimiter") {
|
||
op.applyDelete();
|
||
} else {
|
||
this.callEventDecorator([
|
||
{
|
||
type: "add",
|
||
changedBy: op.uid.creator
|
||
}
|
||
]);
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
ReplaceManager.prototype.callOperationSpecificDeleteEvents = function(op, del_op) {
|
||
if (op.next_cl.type === "Delimiter") {
|
||
return this.callEventDecorator([
|
||
{
|
||
type: "delete",
|
||
changedBy: del_op.uid.creator,
|
||
oldValue: op.val()
|
||
}
|
||
]);
|
||
}
|
||
};
|
||
|
||
ReplaceManager.prototype.replace = function(content, replaceable_uid) {
|
||
var o, relp;
|
||
o = this.getLastOperation();
|
||
relp = (new ops.Insert(null, content, null, this, replaceable_uid, o, o.next_cl)).execute();
|
||
return void 0;
|
||
};
|
||
|
||
ReplaceManager.prototype.isContentDeleted = function() {
|
||
return this.getLastOperation().isDeleted();
|
||
};
|
||
|
||
ReplaceManager.prototype.deleteContent = function() {
|
||
(new ops.Delete(null, void 0, this.getLastOperation().uid)).execute();
|
||
return void 0;
|
||
};
|
||
|
||
ReplaceManager.prototype.val = function() {
|
||
var o;
|
||
o = this.getLastOperation();
|
||
return typeof o.val === "function" ? o.val() : void 0;
|
||
};
|
||
|
||
return ReplaceManager;
|
||
|
||
})(ops.ListManager);
|
||
return basic_ops;
|
||
};
|
||
|
||
|
||
},{"./Basic":73}],75:[function(require,module,exports){
|
||
var Engine, HistoryBuffer, adaptConnector, createY, structured_ops_uninitialized;
|
||
|
||
structured_ops_uninitialized = require("./Operations/Structured");
|
||
|
||
HistoryBuffer = require("./HistoryBuffer");
|
||
|
||
Engine = require("./Engine");
|
||
|
||
adaptConnector = require("./ConnectorAdapter");
|
||
|
||
createY = function(connector) {
|
||
var HB, ct, engine, model, ops, ops_manager, user_id;
|
||
user_id = null;
|
||
if (connector.user_id != null) {
|
||
user_id = connector.user_id;
|
||
} else {
|
||
user_id = "_temp";
|
||
connector.on_user_id_set = function(id) {
|
||
user_id = id;
|
||
return HB.resetUserId(id);
|
||
};
|
||
}
|
||
HB = new HistoryBuffer(user_id);
|
||
ops_manager = structured_ops_uninitialized(HB, this.constructor);
|
||
ops = ops_manager.operations;
|
||
engine = new Engine(HB, ops);
|
||
adaptConnector(connector, engine, HB, ops_manager.execution_listener);
|
||
ops.Operation.prototype.HB = HB;
|
||
ops.Operation.prototype.operations = ops;
|
||
ops.Operation.prototype.engine = engine;
|
||
ops.Operation.prototype.connector = connector;
|
||
ops.Operation.prototype.custom_types = this.constructor;
|
||
ct = new createY.Object();
|
||
model = new ops.MapManager(ct, HB.getReservedUniqueIdentifier()).execute();
|
||
ct._setModel(model);
|
||
return ct;
|
||
};
|
||
|
||
module.exports = createY;
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
window.Y = createY;
|
||
}
|
||
|
||
createY.Object = require("./ObjectType");
|
||
|
||
|
||
},{"./ConnectorAdapter":68,"./Engine":70,"./HistoryBuffer":71,"./ObjectType":72,"./Operations/Structured":74}],76:[function(require,module,exports){
|
||
module.exports=require(2)
|
||
},{"./lib/chai":77}],77:[function(require,module,exports){
|
||
module.exports=require(3)
|
||
},{"./chai/assertion":78,"./chai/config":79,"./chai/core/assertions":80,"./chai/interface/assert":81,"./chai/interface/expect":82,"./chai/interface/should":83,"./chai/utils":96,"assertion-error":105}],78:[function(require,module,exports){
|
||
module.exports=require(4)
|
||
},{"./config":79}],79:[function(require,module,exports){
|
||
module.exports=require(5)
|
||
},{}],80:[function(require,module,exports){
|
||
module.exports=require(6)
|
||
},{}],81:[function(require,module,exports){
|
||
module.exports=require(7)
|
||
},{}],82:[function(require,module,exports){
|
||
module.exports=require(8)
|
||
},{}],83:[function(require,module,exports){
|
||
module.exports=require(9)
|
||
},{}],84:[function(require,module,exports){
|
||
module.exports=require(10)
|
||
},{"../config":79,"./flag":87,"./transferFlags":103}],85:[function(require,module,exports){
|
||
module.exports=require(11)
|
||
},{"../config":79,"./flag":87}],86:[function(require,module,exports){
|
||
module.exports=require(12)
|
||
},{}],87:[function(require,module,exports){
|
||
module.exports=require(13)
|
||
},{}],88:[function(require,module,exports){
|
||
module.exports=require(14)
|
||
},{}],89:[function(require,module,exports){
|
||
module.exports=require(15)
|
||
},{}],90:[function(require,module,exports){
|
||
module.exports=require(16)
|
||
},{"./flag":87,"./getActual":88,"./inspect":97,"./objDisplay":98}],91:[function(require,module,exports){
|
||
module.exports=require(17)
|
||
},{}],92:[function(require,module,exports){
|
||
module.exports=require(18)
|
||
},{"./hasProperty":95}],93:[function(require,module,exports){
|
||
module.exports=require(19)
|
||
},{"./getPathInfo":92}],94:[function(require,module,exports){
|
||
module.exports=require(20)
|
||
},{}],95:[function(require,module,exports){
|
||
module.exports=require(21)
|
||
},{"./type":104}],96:[function(require,module,exports){
|
||
module.exports=require(22)
|
||
},{"./addChainableMethod":84,"./addMethod":85,"./addProperty":86,"./flag":87,"./getActual":88,"./getMessage":90,"./getName":91,"./getPathInfo":92,"./getPathValue":93,"./hasProperty":95,"./inspect":97,"./objDisplay":98,"./overwriteChainableMethod":99,"./overwriteMethod":100,"./overwriteProperty":101,"./test":102,"./transferFlags":103,"./type":104,"deep-eql":106}],97:[function(require,module,exports){
|
||
module.exports=require(23)
|
||
},{"./getEnumerableProperties":89,"./getName":91,"./getProperties":94}],98:[function(require,module,exports){
|
||
module.exports=require(24)
|
||
},{"../config":79,"./inspect":97}],99:[function(require,module,exports){
|
||
module.exports=require(25)
|
||
},{}],100:[function(require,module,exports){
|
||
module.exports=require(26)
|
||
},{}],101:[function(require,module,exports){
|
||
module.exports=require(27)
|
||
},{}],102:[function(require,module,exports){
|
||
module.exports=require(28)
|
||
},{"./flag":87}],103:[function(require,module,exports){
|
||
module.exports=require(29)
|
||
},{}],104:[function(require,module,exports){
|
||
module.exports=require(30)
|
||
},{}],105:[function(require,module,exports){
|
||
module.exports=require(31)
|
||
},{}],106:[function(require,module,exports){
|
||
module.exports=require(32)
|
||
},{"./lib/eql":107}],107:[function(require,module,exports){
|
||
module.exports=require(33)
|
||
},{"buffer":110,"type-detect":108}],108:[function(require,module,exports){
|
||
module.exports=require(34)
|
||
},{"./lib/type":109}],109:[function(require,module,exports){
|
||
module.exports=require(35)
|
||
},{}],110:[function(require,module,exports){
|
||
/*!
|
||
* The buffer module from node.js, for the browser.
|
||
*
|
||
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
||
* @license MIT
|
||
*/
|
||
|
||
var base64 = require('base64-js')
|
||
var ieee754 = require('ieee754')
|
||
|
||
exports.Buffer = Buffer
|
||
exports.SlowBuffer = Buffer
|
||
exports.INSPECT_MAX_BYTES = 50
|
||
Buffer.poolSize = 8192
|
||
|
||
/**
|
||
* If `Buffer._useTypedArrays`:
|
||
* === true Use Uint8Array implementation (fastest)
|
||
* === false Use Object implementation (compatible down to IE6)
|
||
*/
|
||
Buffer._useTypedArrays = (function () {
|
||
// Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+,
|
||
// Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding
|
||
// properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support
|
||
// because we need to be able to add all the node Buffer API methods. This is an issue
|
||
// in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438
|
||
try {
|
||
var buf = new ArrayBuffer(0)
|
||
var arr = new Uint8Array(buf)
|
||
arr.foo = function () { return 42 }
|
||
return 42 === arr.foo() &&
|
||
typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray`
|
||
} catch (e) {
|
||
return false
|
||
}
|
||
})()
|
||
|
||
/**
|
||
* Class: Buffer
|
||
* =============
|
||
*
|
||
* The Buffer constructor returns instances of `Uint8Array` that are augmented
|
||
* with function properties for all the node `Buffer` API functions. We use
|
||
* `Uint8Array` so that square bracket notation works as expected -- it returns
|
||
* a single octet.
|
||
*
|
||
* By augmenting the instances, we can avoid modifying the `Uint8Array`
|
||
* prototype.
|
||
*/
|
||
function Buffer (subject, encoding, noZero) {
|
||
if (!(this instanceof Buffer))
|
||
return new Buffer(subject, encoding, noZero)
|
||
|
||
var type = typeof subject
|
||
|
||
// Workaround: node's base64 implementation allows for non-padded strings
|
||
// while base64-js does not.
|
||
if (encoding === 'base64' && type === 'string') {
|
||
subject = stringtrim(subject)
|
||
while (subject.length % 4 !== 0) {
|
||
subject = subject + '='
|
||
}
|
||
}
|
||
|
||
// Find the length
|
||
var length
|
||
if (type === 'number')
|
||
length = coerce(subject)
|
||
else if (type === 'string')
|
||
length = Buffer.byteLength(subject, encoding)
|
||
else if (type === 'object')
|
||
length = coerce(subject.length) // assume that object is array-like
|
||
else
|
||
throw new Error('First argument needs to be a number, array or string.')
|
||
|
||
var buf
|
||
if (Buffer._useTypedArrays) {
|
||
// Preferred: Return an augmented `Uint8Array` instance for best performance
|
||
buf = Buffer._augment(new Uint8Array(length))
|
||
} else {
|
||
// Fallback: Return THIS instance of Buffer (created by `new`)
|
||
buf = this
|
||
buf.length = length
|
||
buf._isBuffer = true
|
||
}
|
||
|
||
var i
|
||
if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') {
|
||
// Speed optimization -- use set if we're copying from a typed array
|
||
buf._set(subject)
|
||
} else if (isArrayish(subject)) {
|
||
// Treat array-ish objects as a byte array
|
||
for (i = 0; i < length; i++) {
|
||
if (Buffer.isBuffer(subject))
|
||
buf[i] = subject.readUInt8(i)
|
||
else
|
||
buf[i] = subject[i]
|
||
}
|
||
} else if (type === 'string') {
|
||
buf.write(subject, 0, encoding)
|
||
} else if (type === 'number' && !Buffer._useTypedArrays && !noZero) {
|
||
for (i = 0; i < length; i++) {
|
||
buf[i] = 0
|
||
}
|
||
}
|
||
|
||
return buf
|
||
}
|
||
|
||
// STATIC METHODS
|
||
// ==============
|
||
|
||
Buffer.isEncoding = function (encoding) {
|
||
switch (String(encoding).toLowerCase()) {
|
||
case 'hex':
|
||
case 'utf8':
|
||
case 'utf-8':
|
||
case 'ascii':
|
||
case 'binary':
|
||
case 'base64':
|
||
case 'raw':
|
||
case 'ucs2':
|
||
case 'ucs-2':
|
||
case 'utf16le':
|
||
case 'utf-16le':
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
Buffer.isBuffer = function (b) {
|
||
return !!(b !== null && b !== undefined && b._isBuffer)
|
||
}
|
||
|
||
Buffer.byteLength = function (str, encoding) {
|
||
var ret
|
||
str = str + ''
|
||
switch (encoding || 'utf8') {
|
||
case 'hex':
|
||
ret = str.length / 2
|
||
break
|
||
case 'utf8':
|
||
case 'utf-8':
|
||
ret = utf8ToBytes(str).length
|
||
break
|
||
case 'ascii':
|
||
case 'binary':
|
||
case 'raw':
|
||
ret = str.length
|
||
break
|
||
case 'base64':
|
||
ret = base64ToBytes(str).length
|
||
break
|
||
case 'ucs2':
|
||
case 'ucs-2':
|
||
case 'utf16le':
|
||
case 'utf-16le':
|
||
ret = str.length * 2
|
||
break
|
||
default:
|
||
throw new Error('Unknown encoding')
|
||
}
|
||
return ret
|
||
}
|
||
|
||
Buffer.concat = function (list, totalLength) {
|
||
assert(isArray(list), 'Usage: Buffer.concat(list, [totalLength])\n' +
|
||
'list should be an Array.')
|
||
|
||
if (list.length === 0) {
|
||
return new Buffer(0)
|
||
} else if (list.length === 1) {
|
||
return list[0]
|
||
}
|
||
|
||
var i
|
||
if (typeof totalLength !== 'number') {
|
||
totalLength = 0
|
||
for (i = 0; i < list.length; i++) {
|
||
totalLength += list[i].length
|
||
}
|
||
}
|
||
|
||
var buf = new Buffer(totalLength)
|
||
var pos = 0
|
||
for (i = 0; i < list.length; i++) {
|
||
var item = list[i]
|
||
item.copy(buf, pos)
|
||
pos += item.length
|
||
}
|
||
return buf
|
||
}
|
||
|
||
// BUFFER INSTANCE METHODS
|
||
// =======================
|
||
|
||
function _hexWrite (buf, string, offset, length) {
|
||
offset = Number(offset) || 0
|
||
var remaining = buf.length - offset
|
||
if (!length) {
|
||
length = remaining
|
||
} else {
|
||
length = Number(length)
|
||
if (length > remaining) {
|
||
length = remaining
|
||
}
|
||
}
|
||
|
||
// must be an even number of digits
|
||
var strLen = string.length
|
||
assert(strLen % 2 === 0, 'Invalid hex string')
|
||
|
||
if (length > strLen / 2) {
|
||
length = strLen / 2
|
||
}
|
||
for (var i = 0; i < length; i++) {
|
||
var byte = parseInt(string.substr(i * 2, 2), 16)
|
||
assert(!isNaN(byte), 'Invalid hex string')
|
||
buf[offset + i] = byte
|
||
}
|
||
Buffer._charsWritten = i * 2
|
||
return i
|
||
}
|
||
|
||
function _utf8Write (buf, string, offset, length) {
|
||
var charsWritten = Buffer._charsWritten =
|
||
blitBuffer(utf8ToBytes(string), buf, offset, length)
|
||
return charsWritten
|
||
}
|
||
|
||
function _asciiWrite (buf, string, offset, length) {
|
||
var charsWritten = Buffer._charsWritten =
|
||
blitBuffer(asciiToBytes(string), buf, offset, length)
|
||
return charsWritten
|
||
}
|
||
|
||
function _binaryWrite (buf, string, offset, length) {
|
||
return _asciiWrite(buf, string, offset, length)
|
||
}
|
||
|
||
function _base64Write (buf, string, offset, length) {
|
||
var charsWritten = Buffer._charsWritten =
|
||
blitBuffer(base64ToBytes(string), buf, offset, length)
|
||
return charsWritten
|
||
}
|
||
|
||
function _utf16leWrite (buf, string, offset, length) {
|
||
var charsWritten = Buffer._charsWritten =
|
||
blitBuffer(utf16leToBytes(string), buf, offset, length)
|
||
return charsWritten
|
||
}
|
||
|
||
Buffer.prototype.write = function (string, offset, length, encoding) {
|
||
// Support both (string, offset, length, encoding)
|
||
// and the legacy (string, encoding, offset, length)
|
||
if (isFinite(offset)) {
|
||
if (!isFinite(length)) {
|
||
encoding = length
|
||
length = undefined
|
||
}
|
||
} else { // legacy
|
||
var swap = encoding
|
||
encoding = offset
|
||
offset = length
|
||
length = swap
|
||
}
|
||
|
||
offset = Number(offset) || 0
|
||
var remaining = this.length - offset
|
||
if (!length) {
|
||
length = remaining
|
||
} else {
|
||
length = Number(length)
|
||
if (length > remaining) {
|
||
length = remaining
|
||
}
|
||
}
|
||
encoding = String(encoding || 'utf8').toLowerCase()
|
||
|
||
var ret
|
||
switch (encoding) {
|
||
case 'hex':
|
||
ret = _hexWrite(this, string, offset, length)
|
||
break
|
||
case 'utf8':
|
||
case 'utf-8':
|
||
ret = _utf8Write(this, string, offset, length)
|
||
break
|
||
case 'ascii':
|
||
ret = _asciiWrite(this, string, offset, length)
|
||
break
|
||
case 'binary':
|
||
ret = _binaryWrite(this, string, offset, length)
|
||
break
|
||
case 'base64':
|
||
ret = _base64Write(this, string, offset, length)
|
||
break
|
||
case 'ucs2':
|
||
case 'ucs-2':
|
||
case 'utf16le':
|
||
case 'utf-16le':
|
||
ret = _utf16leWrite(this, string, offset, length)
|
||
break
|
||
default:
|
||
throw new Error('Unknown encoding')
|
||
}
|
||
return ret
|
||
}
|
||
|
||
Buffer.prototype.toString = function (encoding, start, end) {
|
||
var self = this
|
||
|
||
encoding = String(encoding || 'utf8').toLowerCase()
|
||
start = Number(start) || 0
|
||
end = (end !== undefined)
|
||
? Number(end)
|
||
: end = self.length
|
||
|
||
// Fastpath empty strings
|
||
if (end === start)
|
||
return ''
|
||
|
||
var ret
|
||
switch (encoding) {
|
||
case 'hex':
|
||
ret = _hexSlice(self, start, end)
|
||
break
|
||
case 'utf8':
|
||
case 'utf-8':
|
||
ret = _utf8Slice(self, start, end)
|
||
break
|
||
case 'ascii':
|
||
ret = _asciiSlice(self, start, end)
|
||
break
|
||
case 'binary':
|
||
ret = _binarySlice(self, start, end)
|
||
break
|
||
case 'base64':
|
||
ret = _base64Slice(self, start, end)
|
||
break
|
||
case 'ucs2':
|
||
case 'ucs-2':
|
||
case 'utf16le':
|
||
case 'utf-16le':
|
||
ret = _utf16leSlice(self, start, end)
|
||
break
|
||
default:
|
||
throw new Error('Unknown encoding')
|
||
}
|
||
return ret
|
||
}
|
||
|
||
Buffer.prototype.toJSON = function () {
|
||
return {
|
||
type: 'Buffer',
|
||
data: Array.prototype.slice.call(this._arr || this, 0)
|
||
}
|
||
}
|
||
|
||
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
|
||
Buffer.prototype.copy = function (target, target_start, start, end) {
|
||
var source = this
|
||
|
||
if (!start) start = 0
|
||
if (!end && end !== 0) end = this.length
|
||
if (!target_start) target_start = 0
|
||
|
||
// Copy 0 bytes; we're done
|
||
if (end === start) return
|
||
if (target.length === 0 || source.length === 0) return
|
||
|
||
// Fatal error conditions
|
||
assert(end >= start, 'sourceEnd < sourceStart')
|
||
assert(target_start >= 0 && target_start < target.length,
|
||
'targetStart out of bounds')
|
||
assert(start >= 0 && start < source.length, 'sourceStart out of bounds')
|
||
assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds')
|
||
|
||
// Are we oob?
|
||
if (end > this.length)
|
||
end = this.length
|
||
if (target.length - target_start < end - start)
|
||
end = target.length - target_start + start
|
||
|
||
var len = end - start
|
||
|
||
if (len < 100 || !Buffer._useTypedArrays) {
|
||
for (var i = 0; i < len; i++)
|
||
target[i + target_start] = this[i + start]
|
||
} else {
|
||
target._set(this.subarray(start, start + len), target_start)
|
||
}
|
||
}
|
||
|
||
function _base64Slice (buf, start, end) {
|
||
if (start === 0 && end === buf.length) {
|
||
return base64.fromByteArray(buf)
|
||
} else {
|
||
return base64.fromByteArray(buf.slice(start, end))
|
||
}
|
||
}
|
||
|
||
function _utf8Slice (buf, start, end) {
|
||
var res = ''
|
||
var tmp = ''
|
||
end = Math.min(buf.length, end)
|
||
|
||
for (var i = start; i < end; i++) {
|
||
if (buf[i] <= 0x7F) {
|
||
res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])
|
||
tmp = ''
|
||
} else {
|
||
tmp += '%' + buf[i].toString(16)
|
||
}
|
||
}
|
||
|
||
return res + decodeUtf8Char(tmp)
|
||
}
|
||
|
||
function _asciiSlice (buf, start, end) {
|
||
var ret = ''
|
||
end = Math.min(buf.length, end)
|
||
|
||
for (var i = start; i < end; i++)
|
||
ret += String.fromCharCode(buf[i])
|
||
return ret
|
||
}
|
||
|
||
function _binarySlice (buf, start, end) {
|
||
return _asciiSlice(buf, start, end)
|
||
}
|
||
|
||
function _hexSlice (buf, start, end) {
|
||
var len = buf.length
|
||
|
||
if (!start || start < 0) start = 0
|
||
if (!end || end < 0 || end > len) end = len
|
||
|
||
var out = ''
|
||
for (var i = start; i < end; i++) {
|
||
out += toHex(buf[i])
|
||
}
|
||
return out
|
||
}
|
||
|
||
function _utf16leSlice (buf, start, end) {
|
||
var bytes = buf.slice(start, end)
|
||
var res = ''
|
||
for (var i = 0; i < bytes.length; i += 2) {
|
||
res += String.fromCharCode(bytes[i] + bytes[i+1] * 256)
|
||
}
|
||
return res
|
||
}
|
||
|
||
Buffer.prototype.slice = function (start, end) {
|
||
var len = this.length
|
||
start = clamp(start, len, 0)
|
||
end = clamp(end, len, len)
|
||
|
||
if (Buffer._useTypedArrays) {
|
||
return Buffer._augment(this.subarray(start, end))
|
||
} else {
|
||
var sliceLen = end - start
|
||
var newBuf = new Buffer(sliceLen, undefined, true)
|
||
for (var i = 0; i < sliceLen; i++) {
|
||
newBuf[i] = this[i + start]
|
||
}
|
||
return newBuf
|
||
}
|
||
}
|
||
|
||
// `get` will be removed in Node 0.13+
|
||
Buffer.prototype.get = function (offset) {
|
||
console.log('.get() is deprecated. Access using array indexes instead.')
|
||
return this.readUInt8(offset)
|
||
}
|
||
|
||
// `set` will be removed in Node 0.13+
|
||
Buffer.prototype.set = function (v, offset) {
|
||
console.log('.set() is deprecated. Access using array indexes instead.')
|
||
return this.writeUInt8(v, offset)
|
||
}
|
||
|
||
Buffer.prototype.readUInt8 = function (offset, noAssert) {
|
||
if (!noAssert) {
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset < this.length, 'Trying to read beyond buffer length')
|
||
}
|
||
|
||
if (offset >= this.length)
|
||
return
|
||
|
||
return this[offset]
|
||
}
|
||
|
||
function _readUInt16 (buf, offset, littleEndian, noAssert) {
|
||
if (!noAssert) {
|
||
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')
|
||
}
|
||
|
||
var len = buf.length
|
||
if (offset >= len)
|
||
return
|
||
|
||
var val
|
||
if (littleEndian) {
|
||
val = buf[offset]
|
||
if (offset + 1 < len)
|
||
val |= buf[offset + 1] << 8
|
||
} else {
|
||
val = buf[offset] << 8
|
||
if (offset + 1 < len)
|
||
val |= buf[offset + 1]
|
||
}
|
||
return val
|
||
}
|
||
|
||
Buffer.prototype.readUInt16LE = function (offset, noAssert) {
|
||
return _readUInt16(this, offset, true, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.readUInt16BE = function (offset, noAssert) {
|
||
return _readUInt16(this, offset, false, noAssert)
|
||
}
|
||
|
||
function _readUInt32 (buf, offset, littleEndian, noAssert) {
|
||
if (!noAssert) {
|
||
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
|
||
}
|
||
|
||
var len = buf.length
|
||
if (offset >= len)
|
||
return
|
||
|
||
var val
|
||
if (littleEndian) {
|
||
if (offset + 2 < len)
|
||
val = buf[offset + 2] << 16
|
||
if (offset + 1 < len)
|
||
val |= buf[offset + 1] << 8
|
||
val |= buf[offset]
|
||
if (offset + 3 < len)
|
||
val = val + (buf[offset + 3] << 24 >>> 0)
|
||
} else {
|
||
if (offset + 1 < len)
|
||
val = buf[offset + 1] << 16
|
||
if (offset + 2 < len)
|
||
val |= buf[offset + 2] << 8
|
||
if (offset + 3 < len)
|
||
val |= buf[offset + 3]
|
||
val = val + (buf[offset] << 24 >>> 0)
|
||
}
|
||
return val
|
||
}
|
||
|
||
Buffer.prototype.readUInt32LE = function (offset, noAssert) {
|
||
return _readUInt32(this, offset, true, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.readUInt32BE = function (offset, noAssert) {
|
||
return _readUInt32(this, offset, false, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.readInt8 = function (offset, noAssert) {
|
||
if (!noAssert) {
|
||
assert(offset !== undefined && offset !== null,
|
||
'missing offset')
|
||
assert(offset < this.length, 'Trying to read beyond buffer length')
|
||
}
|
||
|
||
if (offset >= this.length)
|
||
return
|
||
|
||
var neg = this[offset] & 0x80
|
||
if (neg)
|
||
return (0xff - this[offset] + 1) * -1
|
||
else
|
||
return this[offset]
|
||
}
|
||
|
||
function _readInt16 (buf, offset, littleEndian, noAssert) {
|
||
if (!noAssert) {
|
||
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')
|
||
}
|
||
|
||
var len = buf.length
|
||
if (offset >= len)
|
||
return
|
||
|
||
var val = _readUInt16(buf, offset, littleEndian, true)
|
||
var neg = val & 0x8000
|
||
if (neg)
|
||
return (0xffff - val + 1) * -1
|
||
else
|
||
return val
|
||
}
|
||
|
||
Buffer.prototype.readInt16LE = function (offset, noAssert) {
|
||
return _readInt16(this, offset, true, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.readInt16BE = function (offset, noAssert) {
|
||
return _readInt16(this, offset, false, noAssert)
|
||
}
|
||
|
||
function _readInt32 (buf, offset, littleEndian, noAssert) {
|
||
if (!noAssert) {
|
||
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
|
||
}
|
||
|
||
var len = buf.length
|
||
if (offset >= len)
|
||
return
|
||
|
||
var val = _readUInt32(buf, offset, littleEndian, true)
|
||
var neg = val & 0x80000000
|
||
if (neg)
|
||
return (0xffffffff - val + 1) * -1
|
||
else
|
||
return val
|
||
}
|
||
|
||
Buffer.prototype.readInt32LE = function (offset, noAssert) {
|
||
return _readInt32(this, offset, true, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.readInt32BE = function (offset, noAssert) {
|
||
return _readInt32(this, offset, false, noAssert)
|
||
}
|
||
|
||
function _readFloat (buf, offset, littleEndian, noAssert) {
|
||
if (!noAssert) {
|
||
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
|
||
assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')
|
||
}
|
||
|
||
return ieee754.read(buf, offset, littleEndian, 23, 4)
|
||
}
|
||
|
||
Buffer.prototype.readFloatLE = function (offset, noAssert) {
|
||
return _readFloat(this, offset, true, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.readFloatBE = function (offset, noAssert) {
|
||
return _readFloat(this, offset, false, noAssert)
|
||
}
|
||
|
||
function _readDouble (buf, offset, littleEndian, noAssert) {
|
||
if (!noAssert) {
|
||
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
|
||
assert(offset + 7 < buf.length, 'Trying to read beyond buffer length')
|
||
}
|
||
|
||
return ieee754.read(buf, offset, littleEndian, 52, 8)
|
||
}
|
||
|
||
Buffer.prototype.readDoubleLE = function (offset, noAssert) {
|
||
return _readDouble(this, offset, true, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.readDoubleBE = function (offset, noAssert) {
|
||
return _readDouble(this, offset, false, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.writeUInt8 = function (value, offset, noAssert) {
|
||
if (!noAssert) {
|
||
assert(value !== undefined && value !== null, 'missing value')
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset < this.length, 'trying to write beyond buffer length')
|
||
verifuint(value, 0xff)
|
||
}
|
||
|
||
if (offset >= this.length) return
|
||
|
||
this[offset] = value
|
||
}
|
||
|
||
function _writeUInt16 (buf, value, offset, littleEndian, noAssert) {
|
||
if (!noAssert) {
|
||
assert(value !== undefined && value !== null, 'missing value')
|
||
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset + 1 < buf.length, 'trying to write beyond buffer length')
|
||
verifuint(value, 0xffff)
|
||
}
|
||
|
||
var len = buf.length
|
||
if (offset >= len)
|
||
return
|
||
|
||
for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) {
|
||
buf[offset + i] =
|
||
(value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
|
||
(littleEndian ? i : 1 - i) * 8
|
||
}
|
||
}
|
||
|
||
Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) {
|
||
_writeUInt16(this, value, offset, true, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) {
|
||
_writeUInt16(this, value, offset, false, noAssert)
|
||
}
|
||
|
||
function _writeUInt32 (buf, value, offset, littleEndian, noAssert) {
|
||
if (!noAssert) {
|
||
assert(value !== undefined && value !== null, 'missing value')
|
||
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset + 3 < buf.length, 'trying to write beyond buffer length')
|
||
verifuint(value, 0xffffffff)
|
||
}
|
||
|
||
var len = buf.length
|
||
if (offset >= len)
|
||
return
|
||
|
||
for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) {
|
||
buf[offset + i] =
|
||
(value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
|
||
}
|
||
}
|
||
|
||
Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) {
|
||
_writeUInt32(this, value, offset, true, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) {
|
||
_writeUInt32(this, value, offset, false, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.writeInt8 = function (value, offset, noAssert) {
|
||
if (!noAssert) {
|
||
assert(value !== undefined && value !== null, 'missing value')
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset < this.length, 'Trying to write beyond buffer length')
|
||
verifsint(value, 0x7f, -0x80)
|
||
}
|
||
|
||
if (offset >= this.length)
|
||
return
|
||
|
||
if (value >= 0)
|
||
this.writeUInt8(value, offset, noAssert)
|
||
else
|
||
this.writeUInt8(0xff + value + 1, offset, noAssert)
|
||
}
|
||
|
||
function _writeInt16 (buf, value, offset, littleEndian, noAssert) {
|
||
if (!noAssert) {
|
||
assert(value !== undefined && value !== null, 'missing value')
|
||
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset + 1 < buf.length, 'Trying to write beyond buffer length')
|
||
verifsint(value, 0x7fff, -0x8000)
|
||
}
|
||
|
||
var len = buf.length
|
||
if (offset >= len)
|
||
return
|
||
|
||
if (value >= 0)
|
||
_writeUInt16(buf, value, offset, littleEndian, noAssert)
|
||
else
|
||
_writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.writeInt16LE = function (value, offset, noAssert) {
|
||
_writeInt16(this, value, offset, true, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.writeInt16BE = function (value, offset, noAssert) {
|
||
_writeInt16(this, value, offset, false, noAssert)
|
||
}
|
||
|
||
function _writeInt32 (buf, value, offset, littleEndian, noAssert) {
|
||
if (!noAssert) {
|
||
assert(value !== undefined && value !== null, 'missing value')
|
||
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')
|
||
verifsint(value, 0x7fffffff, -0x80000000)
|
||
}
|
||
|
||
var len = buf.length
|
||
if (offset >= len)
|
||
return
|
||
|
||
if (value >= 0)
|
||
_writeUInt32(buf, value, offset, littleEndian, noAssert)
|
||
else
|
||
_writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.writeInt32LE = function (value, offset, noAssert) {
|
||
_writeInt32(this, value, offset, true, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.writeInt32BE = function (value, offset, noAssert) {
|
||
_writeInt32(this, value, offset, false, noAssert)
|
||
}
|
||
|
||
function _writeFloat (buf, value, offset, littleEndian, noAssert) {
|
||
if (!noAssert) {
|
||
assert(value !== undefined && value !== null, 'missing value')
|
||
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')
|
||
verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38)
|
||
}
|
||
|
||
var len = buf.length
|
||
if (offset >= len)
|
||
return
|
||
|
||
ieee754.write(buf, value, offset, littleEndian, 23, 4)
|
||
}
|
||
|
||
Buffer.prototype.writeFloatLE = function (value, offset, noAssert) {
|
||
_writeFloat(this, value, offset, true, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.writeFloatBE = function (value, offset, noAssert) {
|
||
_writeFloat(this, value, offset, false, noAssert)
|
||
}
|
||
|
||
function _writeDouble (buf, value, offset, littleEndian, noAssert) {
|
||
if (!noAssert) {
|
||
assert(value !== undefined && value !== null, 'missing value')
|
||
assert(typeof littleEndian === 'boolean', 'missing or invalid endian')
|
||
assert(offset !== undefined && offset !== null, 'missing offset')
|
||
assert(offset + 7 < buf.length,
|
||
'Trying to write beyond buffer length')
|
||
verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308)
|
||
}
|
||
|
||
var len = buf.length
|
||
if (offset >= len)
|
||
return
|
||
|
||
ieee754.write(buf, value, offset, littleEndian, 52, 8)
|
||
}
|
||
|
||
Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) {
|
||
_writeDouble(this, value, offset, true, noAssert)
|
||
}
|
||
|
||
Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) {
|
||
_writeDouble(this, value, offset, false, noAssert)
|
||
}
|
||
|
||
// fill(value, start=0, end=buffer.length)
|
||
Buffer.prototype.fill = function (value, start, end) {
|
||
if (!value) value = 0
|
||
if (!start) start = 0
|
||
if (!end) end = this.length
|
||
|
||
if (typeof value === 'string') {
|
||
value = value.charCodeAt(0)
|
||
}
|
||
|
||
assert(typeof value === 'number' && !isNaN(value), 'value is not a number')
|
||
assert(end >= start, 'end < start')
|
||
|
||
// Fill 0 bytes; we're done
|
||
if (end === start) return
|
||
if (this.length === 0) return
|
||
|
||
assert(start >= 0 && start < this.length, 'start out of bounds')
|
||
assert(end >= 0 && end <= this.length, 'end out of bounds')
|
||
|
||
for (var i = start; i < end; i++) {
|
||
this[i] = value
|
||
}
|
||
}
|
||
|
||
Buffer.prototype.inspect = function () {
|
||
var out = []
|
||
var len = this.length
|
||
for (var i = 0; i < len; i++) {
|
||
out[i] = toHex(this[i])
|
||
if (i === exports.INSPECT_MAX_BYTES) {
|
||
out[i + 1] = '...'
|
||
break
|
||
}
|
||
}
|
||
return '<Buffer ' + out.join(' ') + '>'
|
||
}
|
||
|
||
/**
|
||
* Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
|
||
* Added in Node 0.12. Only available in browsers that support ArrayBuffer.
|
||
*/
|
||
Buffer.prototype.toArrayBuffer = function () {
|
||
if (typeof Uint8Array !== 'undefined') {
|
||
if (Buffer._useTypedArrays) {
|
||
return (new Buffer(this)).buffer
|
||
} else {
|
||
var buf = new Uint8Array(this.length)
|
||
for (var i = 0, len = buf.length; i < len; i += 1)
|
||
buf[i] = this[i]
|
||
return buf.buffer
|
||
}
|
||
} else {
|
||
throw new Error('Buffer.toArrayBuffer not supported in this browser')
|
||
}
|
||
}
|
||
|
||
// HELPER FUNCTIONS
|
||
// ================
|
||
|
||
function stringtrim (str) {
|
||
if (str.trim) return str.trim()
|
||
return str.replace(/^\s+|\s+$/g, '')
|
||
}
|
||
|
||
var BP = Buffer.prototype
|
||
|
||
/**
|
||
* Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
|
||
*/
|
||
Buffer._augment = function (arr) {
|
||
arr._isBuffer = true
|
||
|
||
// save reference to original Uint8Array get/set methods before overwriting
|
||
arr._get = arr.get
|
||
arr._set = arr.set
|
||
|
||
// deprecated, will be removed in node 0.13+
|
||
arr.get = BP.get
|
||
arr.set = BP.set
|
||
|
||
arr.write = BP.write
|
||
arr.toString = BP.toString
|
||
arr.toLocaleString = BP.toString
|
||
arr.toJSON = BP.toJSON
|
||
arr.copy = BP.copy
|
||
arr.slice = BP.slice
|
||
arr.readUInt8 = BP.readUInt8
|
||
arr.readUInt16LE = BP.readUInt16LE
|
||
arr.readUInt16BE = BP.readUInt16BE
|
||
arr.readUInt32LE = BP.readUInt32LE
|
||
arr.readUInt32BE = BP.readUInt32BE
|
||
arr.readInt8 = BP.readInt8
|
||
arr.readInt16LE = BP.readInt16LE
|
||
arr.readInt16BE = BP.readInt16BE
|
||
arr.readInt32LE = BP.readInt32LE
|
||
arr.readInt32BE = BP.readInt32BE
|
||
arr.readFloatLE = BP.readFloatLE
|
||
arr.readFloatBE = BP.readFloatBE
|
||
arr.readDoubleLE = BP.readDoubleLE
|
||
arr.readDoubleBE = BP.readDoubleBE
|
||
arr.writeUInt8 = BP.writeUInt8
|
||
arr.writeUInt16LE = BP.writeUInt16LE
|
||
arr.writeUInt16BE = BP.writeUInt16BE
|
||
arr.writeUInt32LE = BP.writeUInt32LE
|
||
arr.writeUInt32BE = BP.writeUInt32BE
|
||
arr.writeInt8 = BP.writeInt8
|
||
arr.writeInt16LE = BP.writeInt16LE
|
||
arr.writeInt16BE = BP.writeInt16BE
|
||
arr.writeInt32LE = BP.writeInt32LE
|
||
arr.writeInt32BE = BP.writeInt32BE
|
||
arr.writeFloatLE = BP.writeFloatLE
|
||
arr.writeFloatBE = BP.writeFloatBE
|
||
arr.writeDoubleLE = BP.writeDoubleLE
|
||
arr.writeDoubleBE = BP.writeDoubleBE
|
||
arr.fill = BP.fill
|
||
arr.inspect = BP.inspect
|
||
arr.toArrayBuffer = BP.toArrayBuffer
|
||
|
||
return arr
|
||
}
|
||
|
||
// slice(start, end)
|
||
function clamp (index, len, defaultValue) {
|
||
if (typeof index !== 'number') return defaultValue
|
||
index = ~~index; // Coerce to integer.
|
||
if (index >= len) return len
|
||
if (index >= 0) return index
|
||
index += len
|
||
if (index >= 0) return index
|
||
return 0
|
||
}
|
||
|
||
function coerce (length) {
|
||
// Coerce length to a number (possibly NaN), round up
|
||
// in case it's fractional (e.g. 123.456) then do a
|
||
// double negate to coerce a NaN to 0. Easy, right?
|
||
length = ~~Math.ceil(+length)
|
||
return length < 0 ? 0 : length
|
||
}
|
||
|
||
function isArray (subject) {
|
||
return (Array.isArray || function (subject) {
|
||
return Object.prototype.toString.call(subject) === '[object Array]'
|
||
})(subject)
|
||
}
|
||
|
||
function isArrayish (subject) {
|
||
return isArray(subject) || Buffer.isBuffer(subject) ||
|
||
subject && typeof subject === 'object' &&
|
||
typeof subject.length === 'number'
|
||
}
|
||
|
||
function toHex (n) {
|
||
if (n < 16) return '0' + n.toString(16)
|
||
return n.toString(16)
|
||
}
|
||
|
||
function utf8ToBytes (str) {
|
||
var byteArray = []
|
||
for (var i = 0; i < str.length; i++) {
|
||
var b = str.charCodeAt(i)
|
||
if (b <= 0x7F)
|
||
byteArray.push(str.charCodeAt(i))
|
||
else {
|
||
var start = i
|
||
if (b >= 0xD800 && b <= 0xDFFF) i++
|
||
var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%')
|
||
for (var j = 0; j < h.length; j++)
|
||
byteArray.push(parseInt(h[j], 16))
|
||
}
|
||
}
|
||
return byteArray
|
||
}
|
||
|
||
function asciiToBytes (str) {
|
||
var byteArray = []
|
||
for (var i = 0; i < str.length; i++) {
|
||
// Node's code seems to be doing this and not & 0x7F..
|
||
byteArray.push(str.charCodeAt(i) & 0xFF)
|
||
}
|
||
return byteArray
|
||
}
|
||
|
||
function utf16leToBytes (str) {
|
||
var c, hi, lo
|
||
var byteArray = []
|
||
for (var i = 0; i < str.length; i++) {
|
||
c = str.charCodeAt(i)
|
||
hi = c >> 8
|
||
lo = c % 256
|
||
byteArray.push(lo)
|
||
byteArray.push(hi)
|
||
}
|
||
|
||
return byteArray
|
||
}
|
||
|
||
function base64ToBytes (str) {
|
||
return base64.toByteArray(str)
|
||
}
|
||
|
||
function blitBuffer (src, dst, offset, length) {
|
||
var pos
|
||
for (var i = 0; i < length; i++) {
|
||
if ((i + offset >= dst.length) || (i >= src.length))
|
||
break
|
||
dst[i + offset] = src[i]
|
||
}
|
||
return i
|
||
}
|
||
|
||
function decodeUtf8Char (str) {
|
||
try {
|
||
return decodeURIComponent(str)
|
||
} catch (err) {
|
||
return String.fromCharCode(0xFFFD) // UTF 8 invalid char
|
||
}
|
||
}
|
||
|
||
/*
|
||
* We have to make sure that the value is a valid integer. This means that it
|
||
* is non-negative. It has no fractional component and that it does not
|
||
* exceed the maximum allowed value.
|
||
*/
|
||
function verifuint (value, max) {
|
||
assert(typeof value === 'number', 'cannot write a non-number as a number')
|
||
assert(value >= 0, 'specified a negative value for writing an unsigned value')
|
||
assert(value <= max, 'value is larger than maximum value for type')
|
||
assert(Math.floor(value) === value, 'value has a fractional component')
|
||
}
|
||
|
||
function verifsint (value, max, min) {
|
||
assert(typeof value === 'number', 'cannot write a non-number as a number')
|
||
assert(value <= max, 'value larger than maximum allowed value')
|
||
assert(value >= min, 'value smaller than minimum allowed value')
|
||
assert(Math.floor(value) === value, 'value has a fractional component')
|
||
}
|
||
|
||
function verifIEEE754 (value, max, min) {
|
||
assert(typeof value === 'number', 'cannot write a non-number as a number')
|
||
assert(value <= max, 'value larger than maximum allowed value')
|
||
assert(value >= min, 'value smaller than minimum allowed value')
|
||
}
|
||
|
||
function assert (test, message) {
|
||
if (!test) throw new Error(message || 'Failed assertion')
|
||
}
|
||
|
||
},{"base64-js":111,"ieee754":112}],111:[function(require,module,exports){
|
||
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||
|
||
;(function (exports) {
|
||
'use strict';
|
||
|
||
var Arr = (typeof Uint8Array !== 'undefined')
|
||
? Uint8Array
|
||
: Array
|
||
|
||
var PLUS = '+'.charCodeAt(0)
|
||
var SLASH = '/'.charCodeAt(0)
|
||
var NUMBER = '0'.charCodeAt(0)
|
||
var LOWER = 'a'.charCodeAt(0)
|
||
var UPPER = 'A'.charCodeAt(0)
|
||
var PLUS_URL_SAFE = '-'.charCodeAt(0)
|
||
var SLASH_URL_SAFE = '_'.charCodeAt(0)
|
||
|
||
function decode (elt) {
|
||
var code = elt.charCodeAt(0)
|
||
if (code === PLUS ||
|
||
code === PLUS_URL_SAFE)
|
||
return 62 // '+'
|
||
if (code === SLASH ||
|
||
code === SLASH_URL_SAFE)
|
||
return 63 // '/'
|
||
if (code < NUMBER)
|
||
return -1 //no match
|
||
if (code < NUMBER + 10)
|
||
return code - NUMBER + 26 + 26
|
||
if (code < UPPER + 26)
|
||
return code - UPPER
|
||
if (code < LOWER + 26)
|
||
return code - LOWER + 26
|
||
}
|
||
|
||
function b64ToByteArray (b64) {
|
||
var i, j, l, tmp, placeHolders, arr
|
||
|
||
if (b64.length % 4 > 0) {
|
||
throw new Error('Invalid string. Length must be a multiple of 4')
|
||
}
|
||
|
||
// the number of equal signs (place holders)
|
||
// if there are two placeholders, than the two characters before it
|
||
// represent one byte
|
||
// if there is only one, then the three characters before it represent 2 bytes
|
||
// this is just a cheap hack to not do indexOf twice
|
||
var len = b64.length
|
||
placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
|
||
|
||
// base64 is 4/3 + up to two characters of the original data
|
||
arr = new Arr(b64.length * 3 / 4 - placeHolders)
|
||
|
||
// if there are placeholders, only get up to the last complete 4 chars
|
||
l = placeHolders > 0 ? b64.length - 4 : b64.length
|
||
|
||
var L = 0
|
||
|
||
function push (v) {
|
||
arr[L++] = v
|
||
}
|
||
|
||
for (i = 0, j = 0; i < l; i += 4, j += 3) {
|
||
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
|
||
push((tmp & 0xFF0000) >> 16)
|
||
push((tmp & 0xFF00) >> 8)
|
||
push(tmp & 0xFF)
|
||
}
|
||
|
||
if (placeHolders === 2) {
|
||
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
|
||
push(tmp & 0xFF)
|
||
} else if (placeHolders === 1) {
|
||
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
|
||
push((tmp >> 8) & 0xFF)
|
||
push(tmp & 0xFF)
|
||
}
|
||
|
||
return arr
|
||
}
|
||
|
||
function uint8ToBase64 (uint8) {
|
||
var i,
|
||
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
|
||
output = "",
|
||
temp, length
|
||
|
||
function encode (num) {
|
||
return lookup.charAt(num)
|
||
}
|
||
|
||
function tripletToBase64 (num) {
|
||
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
|
||
}
|
||
|
||
// go through the array every three bytes, we'll deal with trailing stuff later
|
||
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
|
||
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
|
||
output += tripletToBase64(temp)
|
||
}
|
||
|
||
// pad the end with zeros, but make sure to not forget the extra bytes
|
||
switch (extraBytes) {
|
||
case 1:
|
||
temp = uint8[uint8.length - 1]
|
||
output += encode(temp >> 2)
|
||
output += encode((temp << 4) & 0x3F)
|
||
output += '=='
|
||
break
|
||
case 2:
|
||
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
|
||
output += encode(temp >> 10)
|
||
output += encode((temp >> 4) & 0x3F)
|
||
output += encode((temp << 2) & 0x3F)
|
||
output += '='
|
||
break
|
||
}
|
||
|
||
return output
|
||
}
|
||
|
||
exports.toByteArray = b64ToByteArray
|
||
exports.fromByteArray = uint8ToBase64
|
||
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
|
||
|
||
},{}],112:[function(require,module,exports){
|
||
exports.read = function(buffer, offset, isLE, mLen, nBytes) {
|
||
var e, m,
|
||
eLen = nBytes * 8 - mLen - 1,
|
||
eMax = (1 << eLen) - 1,
|
||
eBias = eMax >> 1,
|
||
nBits = -7,
|
||
i = isLE ? (nBytes - 1) : 0,
|
||
d = isLE ? -1 : 1,
|
||
s = buffer[offset + i];
|
||
|
||
i += d;
|
||
|
||
e = s & ((1 << (-nBits)) - 1);
|
||
s >>= (-nBits);
|
||
nBits += eLen;
|
||
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
|
||
|
||
m = e & ((1 << (-nBits)) - 1);
|
||
e >>= (-nBits);
|
||
nBits += mLen;
|
||
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
|
||
|
||
if (e === 0) {
|
||
e = 1 - eBias;
|
||
} else if (e === eMax) {
|
||
return m ? NaN : ((s ? -1 : 1) * Infinity);
|
||
} else {
|
||
m = m + Math.pow(2, mLen);
|
||
e = e - eBias;
|
||
}
|
||
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
|
||
};
|
||
|
||
exports.write = function(buffer, value, offset, isLE, mLen, nBytes) {
|
||
var e, m, c,
|
||
eLen = nBytes * 8 - mLen - 1,
|
||
eMax = (1 << eLen) - 1,
|
||
eBias = eMax >> 1,
|
||
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
|
||
i = isLE ? 0 : (nBytes - 1),
|
||
d = isLE ? 1 : -1,
|
||
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
|
||
|
||
value = Math.abs(value);
|
||
|
||
if (isNaN(value) || value === Infinity) {
|
||
m = isNaN(value) ? 1 : 0;
|
||
e = eMax;
|
||
} else {
|
||
e = Math.floor(Math.log(value) / Math.LN2);
|
||
if (value * (c = Math.pow(2, -e)) < 1) {
|
||
e--;
|
||
c *= 2;
|
||
}
|
||
if (e + eBias >= 1) {
|
||
value += rt / c;
|
||
} else {
|
||
value += rt * Math.pow(2, 1 - eBias);
|
||
}
|
||
if (value * c >= 2) {
|
||
e++;
|
||
c /= 2;
|
||
}
|
||
|
||
if (e + eBias >= eMax) {
|
||
m = 0;
|
||
e = eMax;
|
||
} else if (e + eBias >= 1) {
|
||
m = (value * c - 1) * Math.pow(2, mLen);
|
||
e = e + eBias;
|
||
} else {
|
||
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
|
||
e = 0;
|
||
}
|
||
}
|
||
|
||
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
|
||
|
||
e = (e << mLen) | m;
|
||
eLen += mLen;
|
||
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
|
||
|
||
buffer[offset + i - d] |= s * 128;
|
||
};
|
||
|
||
},{}],113:[function(require,module,exports){
|
||
if (typeof Object.create === 'function') {
|
||
// implementation from standard node.js 'util' module
|
||
module.exports = function inherits(ctor, superCtor) {
|
||
ctor.super_ = superCtor
|
||
ctor.prototype = Object.create(superCtor.prototype, {
|
||
constructor: {
|
||
value: ctor,
|
||
enumerable: false,
|
||
writable: true,
|
||
configurable: true
|
||
}
|
||
});
|
||
};
|
||
} else {
|
||
// old school shim for old browsers
|
||
module.exports = function inherits(ctor, superCtor) {
|
||
ctor.super_ = superCtor
|
||
var TempCtor = function () {}
|
||
TempCtor.prototype = superCtor.prototype
|
||
ctor.prototype = new TempCtor()
|
||
ctor.prototype.constructor = ctor
|
||
}
|
||
}
|
||
|
||
},{}],114:[function(require,module,exports){
|
||
// shim for using process in browser
|
||
|
||
var process = module.exports = {};
|
||
|
||
process.nextTick = (function () {
|
||
var canSetImmediate = typeof window !== 'undefined'
|
||
&& window.setImmediate;
|
||
var canPost = typeof window !== 'undefined'
|
||
&& window.postMessage && window.addEventListener
|
||
;
|
||
|
||
if (canSetImmediate) {
|
||
return function (f) { return window.setImmediate(f) };
|
||
}
|
||
|
||
if (canPost) {
|
||
var queue = [];
|
||
window.addEventListener('message', function (ev) {
|
||
var source = ev.source;
|
||
if ((source === window || source === null) && ev.data === 'process-tick') {
|
||
ev.stopPropagation();
|
||
if (queue.length > 0) {
|
||
var fn = queue.shift();
|
||
fn();
|
||
}
|
||
}
|
||
}, true);
|
||
|
||
return function nextTick(fn) {
|
||
queue.push(fn);
|
||
window.postMessage('process-tick', '*');
|
||
};
|
||
}
|
||
|
||
return function nextTick(fn) {
|
||
setTimeout(fn, 0);
|
||
};
|
||
})();
|
||
|
||
process.title = 'browser';
|
||
process.browser = true;
|
||
process.env = {};
|
||
process.argv = [];
|
||
|
||
function noop() {}
|
||
|
||
process.on = noop;
|
||
process.addListener = noop;
|
||
process.once = noop;
|
||
process.off = noop;
|
||
process.removeListener = noop;
|
||
process.removeAllListeners = noop;
|
||
process.emit = noop;
|
||
|
||
process.binding = function (name) {
|
||
throw new Error('process.binding is not supported');
|
||
}
|
||
|
||
// TODO(shtylman)
|
||
process.cwd = function () { return '/' };
|
||
process.chdir = function (dir) {
|
||
throw new Error('process.chdir is not supported');
|
||
};
|
||
|
||
},{}],115:[function(require,module,exports){
|
||
module.exports = function isBuffer(arg) {
|
||
return arg && typeof arg === 'object'
|
||
&& typeof arg.copy === 'function'
|
||
&& typeof arg.fill === 'function'
|
||
&& typeof arg.readUInt8 === 'function';
|
||
}
|
||
},{}],116:[function(require,module,exports){
|
||
(function (process,global){
|
||
// Copyright Joyent, Inc. and other Node contributors.
|
||
//
|
||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||
// copy of this software and associated documentation files (the
|
||
// "Software"), to deal in the Software without restriction, including
|
||
// without limitation the rights to use, copy, modify, merge, publish,
|
||
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
||
// persons to whom the Software is furnished to do so, subject to the
|
||
// following conditions:
|
||
//
|
||
// The above copyright notice and this permission notice shall be included
|
||
// in all copies or substantial portions of the Software.
|
||
//
|
||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
||
var formatRegExp = /%[sdj%]/g;
|
||
exports.format = function(f) {
|
||
if (!isString(f)) {
|
||
var objects = [];
|
||
for (var i = 0; i < arguments.length; i++) {
|
||
objects.push(inspect(arguments[i]));
|
||
}
|
||
return objects.join(' ');
|
||
}
|
||
|
||
var i = 1;
|
||
var args = arguments;
|
||
var len = args.length;
|
||
var str = String(f).replace(formatRegExp, function(x) {
|
||
if (x === '%%') return '%';
|
||
if (i >= len) return x;
|
||
switch (x) {
|
||
case '%s': return String(args[i++]);
|
||
case '%d': return Number(args[i++]);
|
||
case '%j':
|
||
try {
|
||
return JSON.stringify(args[i++]);
|
||
} catch (_) {
|
||
return '[Circular]';
|
||
}
|
||
default:
|
||
return x;
|
||
}
|
||
});
|
||
for (var x = args[i]; i < len; x = args[++i]) {
|
||
if (isNull(x) || !isObject(x)) {
|
||
str += ' ' + x;
|
||
} else {
|
||
str += ' ' + inspect(x);
|
||
}
|
||
}
|
||
return str;
|
||
};
|
||
|
||
|
||
// Mark that a method should not be used.
|
||
// Returns a modified function which warns once by default.
|
||
// If --no-deprecation is set, then it is a no-op.
|
||
exports.deprecate = function(fn, msg) {
|
||
// Allow for deprecating things in the process of starting up.
|
||
if (isUndefined(global.process)) {
|
||
return function() {
|
||
return exports.deprecate(fn, msg).apply(this, arguments);
|
||
};
|
||
}
|
||
|
||
if (process.noDeprecation === true) {
|
||
return fn;
|
||
}
|
||
|
||
var warned = false;
|
||
function deprecated() {
|
||
if (!warned) {
|
||
if (process.throwDeprecation) {
|
||
throw new Error(msg);
|
||
} else if (process.traceDeprecation) {
|
||
console.trace(msg);
|
||
} else {
|
||
console.error(msg);
|
||
}
|
||
warned = true;
|
||
}
|
||
return fn.apply(this, arguments);
|
||
}
|
||
|
||
return deprecated;
|
||
};
|
||
|
||
|
||
var debugs = {};
|
||
var debugEnviron;
|
||
exports.debuglog = function(set) {
|
||
if (isUndefined(debugEnviron))
|
||
debugEnviron = process.env.NODE_DEBUG || '';
|
||
set = set.toUpperCase();
|
||
if (!debugs[set]) {
|
||
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
|
||
var pid = process.pid;
|
||
debugs[set] = function() {
|
||
var msg = exports.format.apply(exports, arguments);
|
||
console.error('%s %d: %s', set, pid, msg);
|
||
};
|
||
} else {
|
||
debugs[set] = function() {};
|
||
}
|
||
}
|
||
return debugs[set];
|
||
};
|
||
|
||
|
||
/**
|
||
* Echos the value of a value. Trys to print the value out
|
||
* in the best way possible given the different types.
|
||
*
|
||
* @param {Object} obj The object to print out.
|
||
* @param {Object} opts Optional options object that alters the output.
|
||
*/
|
||
/* legacy: obj, showHidden, depth, colors*/
|
||
function inspect(obj, opts) {
|
||
// default options
|
||
var ctx = {
|
||
seen: [],
|
||
stylize: stylizeNoColor
|
||
};
|
||
// legacy...
|
||
if (arguments.length >= 3) ctx.depth = arguments[2];
|
||
if (arguments.length >= 4) ctx.colors = arguments[3];
|
||
if (isBoolean(opts)) {
|
||
// legacy...
|
||
ctx.showHidden = opts;
|
||
} else if (opts) {
|
||
// got an "options" object
|
||
exports._extend(ctx, opts);
|
||
}
|
||
// set default options
|
||
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
|
||
if (isUndefined(ctx.depth)) ctx.depth = 2;
|
||
if (isUndefined(ctx.colors)) ctx.colors = false;
|
||
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
|
||
if (ctx.colors) ctx.stylize = stylizeWithColor;
|
||
return formatValue(ctx, obj, ctx.depth);
|
||
}
|
||
exports.inspect = inspect;
|
||
|
||
|
||
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
|
||
inspect.colors = {
|
||
'bold' : [1, 22],
|
||
'italic' : [3, 23],
|
||
'underline' : [4, 24],
|
||
'inverse' : [7, 27],
|
||
'white' : [37, 39],
|
||
'grey' : [90, 39],
|
||
'black' : [30, 39],
|
||
'blue' : [34, 39],
|
||
'cyan' : [36, 39],
|
||
'green' : [32, 39],
|
||
'magenta' : [35, 39],
|
||
'red' : [31, 39],
|
||
'yellow' : [33, 39]
|
||
};
|
||
|
||
// Don't use 'blue' not visible on cmd.exe
|
||
inspect.styles = {
|
||
'special': 'cyan',
|
||
'number': 'yellow',
|
||
'boolean': 'yellow',
|
||
'undefined': 'grey',
|
||
'null': 'bold',
|
||
'string': 'green',
|
||
'date': 'magenta',
|
||
// "name": intentionally not styling
|
||
'regexp': 'red'
|
||
};
|
||
|
||
|
||
function stylizeWithColor(str, styleType) {
|
||
var style = inspect.styles[styleType];
|
||
|
||
if (style) {
|
||
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
|
||
'\u001b[' + inspect.colors[style][1] + 'm';
|
||
} else {
|
||
return str;
|
||
}
|
||
}
|
||
|
||
|
||
function stylizeNoColor(str, styleType) {
|
||
return str;
|
||
}
|
||
|
||
|
||
function arrayToHash(array) {
|
||
var hash = {};
|
||
|
||
array.forEach(function(val, idx) {
|
||
hash[val] = true;
|
||
});
|
||
|
||
return hash;
|
||
}
|
||
|
||
|
||
function formatValue(ctx, value, recurseTimes) {
|
||
// Provide a hook for user-specified inspect functions.
|
||
// Check that value is an object with an inspect function on it
|
||
if (ctx.customInspect &&
|
||
value &&
|
||
isFunction(value.inspect) &&
|
||
// Filter out the util module, it's inspect function is special
|
||
value.inspect !== exports.inspect &&
|
||
// Also filter out any prototype objects using the circular check.
|
||
!(value.constructor && value.constructor.prototype === value)) {
|
||
var ret = value.inspect(recurseTimes, ctx);
|
||
if (!isString(ret)) {
|
||
ret = formatValue(ctx, ret, recurseTimes);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// Primitive types cannot have properties
|
||
var primitive = formatPrimitive(ctx, value);
|
||
if (primitive) {
|
||
return primitive;
|
||
}
|
||
|
||
// Look up the keys of the object.
|
||
var keys = Object.keys(value);
|
||
var visibleKeys = arrayToHash(keys);
|
||
|
||
if (ctx.showHidden) {
|
||
keys = Object.getOwnPropertyNames(value);
|
||
}
|
||
|
||
// IE doesn't make error fields non-enumerable
|
||
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
|
||
if (isError(value)
|
||
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
|
||
return formatError(value);
|
||
}
|
||
|
||
// Some type of object without properties can be shortcutted.
|
||
if (keys.length === 0) {
|
||
if (isFunction(value)) {
|
||
var name = value.name ? ': ' + value.name : '';
|
||
return ctx.stylize('[Function' + name + ']', 'special');
|
||
}
|
||
if (isRegExp(value)) {
|
||
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||
}
|
||
if (isDate(value)) {
|
||
return ctx.stylize(Date.prototype.toString.call(value), 'date');
|
||
}
|
||
if (isError(value)) {
|
||
return formatError(value);
|
||
}
|
||
}
|
||
|
||
var base = '', array = false, braces = ['{', '}'];
|
||
|
||
// Make Array say that they are Array
|
||
if (isArray(value)) {
|
||
array = true;
|
||
braces = ['[', ']'];
|
||
}
|
||
|
||
// Make functions say that they are functions
|
||
if (isFunction(value)) {
|
||
var n = value.name ? ': ' + value.name : '';
|
||
base = ' [Function' + n + ']';
|
||
}
|
||
|
||
// Make RegExps say that they are RegExps
|
||
if (isRegExp(value)) {
|
||
base = ' ' + RegExp.prototype.toString.call(value);
|
||
}
|
||
|
||
// Make dates with properties first say the date
|
||
if (isDate(value)) {
|
||
base = ' ' + Date.prototype.toUTCString.call(value);
|
||
}
|
||
|
||
// Make error with message first say the error
|
||
if (isError(value)) {
|
||
base = ' ' + formatError(value);
|
||
}
|
||
|
||
if (keys.length === 0 && (!array || value.length == 0)) {
|
||
return braces[0] + base + braces[1];
|
||
}
|
||
|
||
if (recurseTimes < 0) {
|
||
if (isRegExp(value)) {
|
||
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||
} else {
|
||
return ctx.stylize('[Object]', 'special');
|
||
}
|
||
}
|
||
|
||
ctx.seen.push(value);
|
||
|
||
var output;
|
||
if (array) {
|
||
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
|
||
} else {
|
||
output = keys.map(function(key) {
|
||
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
|
||
});
|
||
}
|
||
|
||
ctx.seen.pop();
|
||
|
||
return reduceToSingleString(output, base, braces);
|
||
}
|
||
|
||
|
||
function formatPrimitive(ctx, value) {
|
||
if (isUndefined(value))
|
||
return ctx.stylize('undefined', 'undefined');
|
||
if (isString(value)) {
|
||
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
||
.replace(/'/g, "\\'")
|
||
.replace(/\\"/g, '"') + '\'';
|
||
return ctx.stylize(simple, 'string');
|
||
}
|
||
if (isNumber(value))
|
||
return ctx.stylize('' + value, 'number');
|
||
if (isBoolean(value))
|
||
return ctx.stylize('' + value, 'boolean');
|
||
// For some reason typeof null is "object", so special case here.
|
||
if (isNull(value))
|
||
return ctx.stylize('null', 'null');
|
||
}
|
||
|
||
|
||
function formatError(value) {
|
||
return '[' + Error.prototype.toString.call(value) + ']';
|
||
}
|
||
|
||
|
||
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
|
||
var output = [];
|
||
for (var i = 0, l = value.length; i < l; ++i) {
|
||
if (hasOwnProperty(value, String(i))) {
|
||
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||
String(i), true));
|
||
} else {
|
||
output.push('');
|
||
}
|
||
}
|
||
keys.forEach(function(key) {
|
||
if (!key.match(/^\d+$/)) {
|
||
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||
key, true));
|
||
}
|
||
});
|
||
return output;
|
||
}
|
||
|
||
|
||
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
|
||
var name, str, desc;
|
||
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
|
||
if (desc.get) {
|
||
if (desc.set) {
|
||
str = ctx.stylize('[Getter/Setter]', 'special');
|
||
} else {
|
||
str = ctx.stylize('[Getter]', 'special');
|
||
}
|
||
} else {
|
||
if (desc.set) {
|
||
str = ctx.stylize('[Setter]', 'special');
|
||
}
|
||
}
|
||
if (!hasOwnProperty(visibleKeys, key)) {
|
||
name = '[' + key + ']';
|
||
}
|
||
if (!str) {
|
||
if (ctx.seen.indexOf(desc.value) < 0) {
|
||
if (isNull(recurseTimes)) {
|
||
str = formatValue(ctx, desc.value, null);
|
||
} else {
|
||
str = formatValue(ctx, desc.value, recurseTimes - 1);
|
||
}
|
||
if (str.indexOf('\n') > -1) {
|
||
if (array) {
|
||
str = str.split('\n').map(function(line) {
|
||
return ' ' + line;
|
||
}).join('\n').substr(2);
|
||
} else {
|
||
str = '\n' + str.split('\n').map(function(line) {
|
||
return ' ' + line;
|
||
}).join('\n');
|
||
}
|
||
}
|
||
} else {
|
||
str = ctx.stylize('[Circular]', 'special');
|
||
}
|
||
}
|
||
if (isUndefined(name)) {
|
||
if (array && key.match(/^\d+$/)) {
|
||
return str;
|
||
}
|
||
name = JSON.stringify('' + key);
|
||
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
||
name = name.substr(1, name.length - 2);
|
||
name = ctx.stylize(name, 'name');
|
||
} else {
|
||
name = name.replace(/'/g, "\\'")
|
||
.replace(/\\"/g, '"')
|
||
.replace(/(^"|"$)/g, "'");
|
||
name = ctx.stylize(name, 'string');
|
||
}
|
||
}
|
||
|
||
return name + ': ' + str;
|
||
}
|
||
|
||
|
||
function reduceToSingleString(output, base, braces) {
|
||
var numLinesEst = 0;
|
||
var length = output.reduce(function(prev, cur) {
|
||
numLinesEst++;
|
||
if (cur.indexOf('\n') >= 0) numLinesEst++;
|
||
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
|
||
}, 0);
|
||
|
||
if (length > 60) {
|
||
return braces[0] +
|
||
(base === '' ? '' : base + '\n ') +
|
||
' ' +
|
||
output.join(',\n ') +
|
||
' ' +
|
||
braces[1];
|
||
}
|
||
|
||
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
||
}
|
||
|
||
|
||
// NOTE: These type checking functions intentionally don't use `instanceof`
|
||
// because it is fragile and can be easily faked with `Object.create()`.
|
||
function isArray(ar) {
|
||
return Array.isArray(ar);
|
||
}
|
||
exports.isArray = isArray;
|
||
|
||
function isBoolean(arg) {
|
||
return typeof arg === 'boolean';
|
||
}
|
||
exports.isBoolean = isBoolean;
|
||
|
||
function isNull(arg) {
|
||
return arg === null;
|
||
}
|
||
exports.isNull = isNull;
|
||
|
||
function isNullOrUndefined(arg) {
|
||
return arg == null;
|
||
}
|
||
exports.isNullOrUndefined = isNullOrUndefined;
|
||
|
||
function isNumber(arg) {
|
||
return typeof arg === 'number';
|
||
}
|
||
exports.isNumber = isNumber;
|
||
|
||
function isString(arg) {
|
||
return typeof arg === 'string';
|
||
}
|
||
exports.isString = isString;
|
||
|
||
function isSymbol(arg) {
|
||
return typeof arg === 'symbol';
|
||
}
|
||
exports.isSymbol = isSymbol;
|
||
|
||
function isUndefined(arg) {
|
||
return arg === void 0;
|
||
}
|
||
exports.isUndefined = isUndefined;
|
||
|
||
function isRegExp(re) {
|
||
return isObject(re) && objectToString(re) === '[object RegExp]';
|
||
}
|
||
exports.isRegExp = isRegExp;
|
||
|
||
function isObject(arg) {
|
||
return typeof arg === 'object' && arg !== null;
|
||
}
|
||
exports.isObject = isObject;
|
||
|
||
function isDate(d) {
|
||
return isObject(d) && objectToString(d) === '[object Date]';
|
||
}
|
||
exports.isDate = isDate;
|
||
|
||
function isError(e) {
|
||
return isObject(e) &&
|
||
(objectToString(e) === '[object Error]' || e instanceof Error);
|
||
}
|
||
exports.isError = isError;
|
||
|
||
function isFunction(arg) {
|
||
return typeof arg === 'function';
|
||
}
|
||
exports.isFunction = isFunction;
|
||
|
||
function isPrimitive(arg) {
|
||
return arg === null ||
|
||
typeof arg === 'boolean' ||
|
||
typeof arg === 'number' ||
|
||
typeof arg === 'string' ||
|
||
typeof arg === 'symbol' || // ES6 symbol
|
||
typeof arg === 'undefined';
|
||
}
|
||
exports.isPrimitive = isPrimitive;
|
||
|
||
exports.isBuffer = require('./support/isBuffer');
|
||
|
||
function objectToString(o) {
|
||
return Object.prototype.toString.call(o);
|
||
}
|
||
|
||
|
||
function pad(n) {
|
||
return n < 10 ? '0' + n.toString(10) : n.toString(10);
|
||
}
|
||
|
||
|
||
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
|
||
'Oct', 'Nov', 'Dec'];
|
||
|
||
// 26 Feb 16:19:34
|
||
function timestamp() {
|
||
var d = new Date();
|
||
var time = [pad(d.getHours()),
|
||
pad(d.getMinutes()),
|
||
pad(d.getSeconds())].join(':');
|
||
return [d.getDate(), months[d.getMonth()], time].join(' ');
|
||
}
|
||
|
||
|
||
// log is just a thin wrapper to console.log that prepends a timestamp
|
||
exports.log = function() {
|
||
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
|
||
};
|
||
|
||
|
||
/**
|
||
* Inherit the prototype methods from one constructor into another.
|
||
*
|
||
* The Function.prototype.inherits from lang.js rewritten as a standalone
|
||
* function (not on Function.prototype). NOTE: If this file is to be loaded
|
||
* during bootstrapping this function needs to be rewritten using some native
|
||
* functions as prototype setup using normal JavaScript does not work as
|
||
* expected during bootstrapping (see mirror.js in r114903).
|
||
*
|
||
* @param {function} ctor Constructor function which needs to inherit the
|
||
* prototype.
|
||
* @param {function} superCtor Constructor function to inherit prototype from.
|
||
*/
|
||
exports.inherits = require('inherits');
|
||
|
||
exports._extend = function(origin, add) {
|
||
// Don't do anything if add isn't an object
|
||
if (!add || !isObject(add)) return origin;
|
||
|
||
var keys = Object.keys(add);
|
||
var i = keys.length;
|
||
while (i--) {
|
||
origin[keys[i]] = add[keys[i]];
|
||
}
|
||
return origin;
|
||
};
|
||
|
||
function hasOwnProperty(obj, prop) {
|
||
return Object.prototype.hasOwnProperty.call(obj, prop);
|
||
}
|
||
|
||
}).call(this,require("VCmEsw"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"./support/isBuffer":115,"VCmEsw":114,"inherits":113}],117:[function(require,module,exports){
|
||
module.exports=require(36)
|
||
},{}],118:[function(require,module,exports){
|
||
module.exports=require(37)
|
||
},{"./sinon/assert":119,"./sinon/behavior":120,"./sinon/call":121,"./sinon/collection":122,"./sinon/extend":123,"./sinon/format":124,"./sinon/log_error":125,"./sinon/match":126,"./sinon/mock":127,"./sinon/sandbox":128,"./sinon/spy":129,"./sinon/stub":130,"./sinon/test":131,"./sinon/test_case":132,"./sinon/times_in_words":133,"./sinon/typeOf":134,"./sinon/util/core":135}],119:[function(require,module,exports){
|
||
module.exports=require(38)
|
||
},{"./format":124,"./match":126,"./util/core":135}],120:[function(require,module,exports){
|
||
module.exports=require(39)
|
||
},{"./extend":123,"./util/core":135,"VCmEsw":114}],121:[function(require,module,exports){
|
||
module.exports=require(40)
|
||
},{"./format":124,"./match":126,"./util/core":135}],122:[function(require,module,exports){
|
||
module.exports=require(41)
|
||
},{"./mock":127,"./spy":129,"./stub":130,"./util/core":135}],123:[function(require,module,exports){
|
||
module.exports=require(42)
|
||
},{"./util/core":135}],124:[function(require,module,exports){
|
||
module.exports=require(43)
|
||
},{"./util/core":135,"formatio":142,"util":116}],125:[function(require,module,exports){
|
||
module.exports=require(44)
|
||
},{"./util/core":135}],126:[function(require,module,exports){
|
||
module.exports=require(45)
|
||
},{"./typeOf":134,"./util/core":135}],127:[function(require,module,exports){
|
||
module.exports=require(46)
|
||
},{"./call":121,"./extend":123,"./format":124,"./match":126,"./spy":129,"./stub":130,"./times_in_words":133,"./util/core":135}],128:[function(require,module,exports){
|
||
module.exports=require(47)
|
||
},{"./collection":122,"./extend":123,"./util/core":135,"./util/fake_server_with_clock":138,"./util/fake_timers":139}],129:[function(require,module,exports){
|
||
module.exports=require(48)
|
||
},{"./call":121,"./extend":123,"./format":124,"./times_in_words":133,"./util/core":135}],130:[function(require,module,exports){
|
||
module.exports=require(49)
|
||
},{"./behavior":120,"./extend":123,"./spy":129,"./util/core":135}],131:[function(require,module,exports){
|
||
module.exports=require(50)
|
||
},{"./sandbox":128,"./util/core":135}],132:[function(require,module,exports){
|
||
module.exports=require(51)
|
||
},{"./test":131,"./util/core":135}],133:[function(require,module,exports){
|
||
module.exports=require(52)
|
||
},{"./util/core":135}],134:[function(require,module,exports){
|
||
module.exports=require(53)
|
||
},{"./util/core":135}],135:[function(require,module,exports){
|
||
module.exports=require(54)
|
||
},{}],136:[function(require,module,exports){
|
||
module.exports=require(55)
|
||
},{"./core":135}],137:[function(require,module,exports){
|
||
module.exports=require(56)
|
||
},{"../format":124,"./core":135,"./fake_xdomain_request":140,"./fake_xml_http_request":141}],138:[function(require,module,exports){
|
||
module.exports=require(57)
|
||
},{"./core":135,"./fake_server":137,"./fake_timers":139}],139:[function(require,module,exports){
|
||
module.exports=require(58)
|
||
},{"./core":135,"lolex":144}],140:[function(require,module,exports){
|
||
module.exports=require(59)
|
||
},{"../extend":123,"../log_error":125,"./core":135,"./event":136}],141:[function(require,module,exports){
|
||
module.exports=require(60)
|
||
},{"../extend":123,"../log_error":125,"./core":135,"./event":136}],142:[function(require,module,exports){
|
||
module.exports=require(61)
|
||
},{"samsam":143}],143:[function(require,module,exports){
|
||
module.exports=require(62)
|
||
},{}],144:[function(require,module,exports){
|
||
module.exports=require(63)
|
||
},{}],145:[function(require,module,exports){
|
||
module.exports=require(64)
|
||
},{}],146:[function(require,module,exports){
|
||
var Connector, Test, Y, chai, expect, sinon, sinonChai, _,
|
||
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||
|
||
chai = require('chai');
|
||
|
||
expect = chai.expect;
|
||
|
||
sinon = require('sinon');
|
||
|
||
sinonChai = require('sinon-chai');
|
||
|
||
_ = require("underscore");
|
||
|
||
chai.use(sinonChai);
|
||
|
||
Connector = require("../../y-test/lib/y-test.coffee");
|
||
|
||
Y = null;
|
||
|
||
module.exports = Test = (function() {
|
||
function Test(name_suffix, Yjs) {
|
||
var gf, t, _i, _j, _len, _len1, _ref, _ref1;
|
||
this.name_suffix = name_suffix != null ? name_suffix : "";
|
||
this.applyRandomOp = __bind(this.applyRandomOp, this);
|
||
this.generateRandomOp = __bind(this.generateRandomOp, this);
|
||
this.getGeneratingFunctions = __bind(this.getGeneratingFunctions, this);
|
||
Y = Yjs;
|
||
this.number_of_test_cases_multiplier = 1;
|
||
this.repeat_this = 1 * this.number_of_test_cases_multiplier;
|
||
this.doSomething_amount = 123 * this.number_of_test_cases_multiplier;
|
||
this.number_of_engines = 5 + this.number_of_test_cases_multiplier - 1;
|
||
this.time = 0;
|
||
this.ops = 0;
|
||
this.time_now = 0;
|
||
this.max_depth = 3;
|
||
this.debug = false;
|
||
this.reinitialize();
|
||
_ref = this.getGeneratingFunctions(0);
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
gf = _ref[_i];
|
||
if (!((gf.types != null) && (gf.f != null))) {
|
||
throw new Error("Generating Functions are not initialized properly!");
|
||
}
|
||
_ref1 = gf.types;
|
||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||
t = _ref1[_j];
|
||
if (t == null) {
|
||
throw new Error("You havent includedt this type in Y (do require 'y-whatever')");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Test.prototype.reinitialize = function() {
|
||
var i, u, user, _i, _j, _len, _ref, _ref1;
|
||
this.users = [];
|
||
for (i = _i = 0, _ref = this.number_of_engines; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
|
||
u = this.makeNewUser(i + this.name_suffix);
|
||
_ref1 = this.users;
|
||
for (_j = 0, _len = _ref1.length; _j < _len; _j++) {
|
||
user = _ref1[_j];
|
||
u._model.connector.join(user._model.connector);
|
||
}
|
||
this.users.push(u);
|
||
}
|
||
if (typeof this.initUsers === "function") {
|
||
this.initUsers(this.users[0]);
|
||
}
|
||
return this.flushAll();
|
||
};
|
||
|
||
Test.prototype.makeNewUser = function(user) {
|
||
user._model.HB.stopGarbageCollection();
|
||
return user;
|
||
};
|
||
|
||
Test.prototype.getSomeUser = function() {
|
||
var i;
|
||
i = _.random(0, this.users.length - 1);
|
||
return this.users[i];
|
||
};
|
||
|
||
Test.prototype.getRandomText = function(chars, min_length) {
|
||
var length, nextchar, text;
|
||
if (min_length == null) {
|
||
min_length = 0;
|
||
}
|
||
if (chars == null) {
|
||
chars = "abcdefghijklmnopqrstuvwxyz";
|
||
}
|
||
length = _.random(min_length, 10);
|
||
nextchar = chars[_.random(0, chars.length - 1)];
|
||
text = "";
|
||
_(length).times(function() {
|
||
return text += nextchar;
|
||
});
|
||
return text;
|
||
};
|
||
|
||
Test.prototype.getRandomObject = function() {
|
||
var key1, key2, result, val1, val2;
|
||
result = {};
|
||
key1 = this.getRandomKey();
|
||
key2 = this.getRandomKey();
|
||
val1 = this.getRandomText();
|
||
val2 = null;
|
||
if (_.random(0, 1) === 1) {
|
||
val2 = this.getRandomObject();
|
||
} else {
|
||
val2 = this.getRandomText();
|
||
}
|
||
result[key1] = val1;
|
||
result[key2] = val2;
|
||
return result;
|
||
};
|
||
|
||
Test.prototype.getRandomKey = function() {
|
||
return this.getRandomText([1, 2, 'x', 'y'], 1);
|
||
};
|
||
|
||
Test.prototype.getGeneratingFunctions = function(user_num) {
|
||
var types;
|
||
types = this.users[user_num]._model.operations;
|
||
return [];
|
||
};
|
||
|
||
Test.prototype.getRandomRoot = function(user_num) {
|
||
throw new Error("implement me!");
|
||
};
|
||
|
||
Test.prototype.compare = function(o1, o2, depth) {
|
||
var i, name, o, val, _i, _j, _len, _len1, _ref, _ref1, _results, _results1, _results2;
|
||
if (depth == null) {
|
||
depth = this.max_depth + 1;
|
||
}
|
||
if (o1 === o2 || depth <= 0) {
|
||
return true;
|
||
} else if ((o1._name != null) && o1._name !== o2._name) {
|
||
throw new Error("different types");
|
||
} else if (o1._model != null) {
|
||
return this.compare(o1._model, o2._model, depth);
|
||
} else if (o1.type === "MapManager") {
|
||
_ref = o1.val();
|
||
_results = [];
|
||
for (name in _ref) {
|
||
val = _ref[name];
|
||
_results.push(this.compare(val, o2.val(name), depth - 1));
|
||
}
|
||
return _results;
|
||
} else if (o1.type === "ListManager") {
|
||
_ref1 = o1.val();
|
||
_results1 = [];
|
||
for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {
|
||
val = _ref1[i];
|
||
_results1.push(this.compare(val, o2.val(i), depth - 1));
|
||
}
|
||
return _results1;
|
||
} else if (o1.constructor === Array && o2.constructor === Array) {
|
||
if (o1.length !== o2.length) {
|
||
throw new Error("The Arrays do not have the same size!");
|
||
}
|
||
_results2 = [];
|
||
for (i = _j = 0, _len1 = o1.length; _j < _len1; i = ++_j) {
|
||
o = o1[i];
|
||
_results2.push(this.compare(o, o2[i], depth - 1));
|
||
}
|
||
return _results2;
|
||
} else if (o1 !== o2) {
|
||
throw new Error("different values");
|
||
} else {
|
||
throw new Error("I don't know what to do .. ");
|
||
}
|
||
};
|
||
|
||
Test.prototype.generateRandomOp = function(user_num) {
|
||
var choices, i, y;
|
||
y = this.getRandomRoot(user_num);
|
||
choices = this.getGeneratingFunctions(user_num).filter(function(gf) {
|
||
return _.some(gf.types, function(type) {
|
||
return y instanceof type;
|
||
});
|
||
});
|
||
if (choices.length === 0) {
|
||
console.dir(y);
|
||
throw new Error("You forgot to specify a test generation methot for this Operation! (" + y.type + ")");
|
||
}
|
||
i = _.random(0, choices.length - 1);
|
||
return choices[i].f(y);
|
||
};
|
||
|
||
Test.prototype.applyRandomOp = function(user_num) {
|
||
var user;
|
||
user = this.users[user_num];
|
||
return user._model.connector.flushOneRandom();
|
||
};
|
||
|
||
Test.prototype.doSomething = function() {
|
||
var choice, choices, user_num;
|
||
user_num = _.random(this.number_of_engines - 1);
|
||
choices = [this.applyRandomOp, this.generateRandomOp];
|
||
choice = _.random(choices.length - 1);
|
||
return choices[choice](user_num);
|
||
};
|
||
|
||
Test.prototype.flushAll = function(final) {
|
||
var ops, user, user_number, _i, _j, _len, _len1, _ref, _ref1, _results;
|
||
final = false;
|
||
if (this.users.length <= 1 || !final) {
|
||
_ref = this.users;
|
||
_results = [];
|
||
for (user_number = _i = 0, _len = _ref.length; _i < _len; user_number = ++_i) {
|
||
user = _ref[user_number];
|
||
_results.push(user._model.connector.flushAll());
|
||
}
|
||
return _results;
|
||
} else {
|
||
_ref1 = this.users.slice(1);
|
||
for (user_number = _j = 0, _len1 = _ref1.length; _j < _len1; user_number = ++_j) {
|
||
user = _ref1[user_number];
|
||
user._model.connector.flushAll();
|
||
}
|
||
ops = this.users[1].getHistoryBuffer()._encode(this.users[0].HB.getOperationCounter());
|
||
return this.users[0].engine.applyOpsCheckDouble(ops);
|
||
}
|
||
};
|
||
|
||
Test.prototype.compareAll = function(test_number) {
|
||
var i, j, number_of_created_operations, ops, ops_per_msek, printOpsInExecutionOrder, u, _i, _j, _k, _len, _ref, _ref1, _ref2, _results;
|
||
this.flushAll(true);
|
||
this.time += (new Date()).getTime() - this.time_now;
|
||
number_of_created_operations = 0;
|
||
for (i = _i = 0, _ref = this.users.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
|
||
number_of_created_operations += this.users[i]._model.connector.getOpsInExecutionOrder().length;
|
||
}
|
||
this.ops += number_of_created_operations * this.users.length;
|
||
ops_per_msek = Math.floor(this.ops / this.time);
|
||
if (test_number != null) {
|
||
console.log(("" + test_number + "/" + this.repeat_this + ": " + number_of_created_operations + " were created and applied on (" + this.users.length + ") users ops in a different order.") + (" Over all we consumed " + this.ops + " operations in " + (this.time / 1000) + " seconds (" + ops_per_msek + " ops/msek)."));
|
||
}
|
||
_results = [];
|
||
for (i = _j = 0, _ref1 = this.users.length - 1; 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
|
||
if (this.debug) {
|
||
if (!_.isEqual(this.getContent(i), this.getContent(i + 1))) {
|
||
printOpsInExecutionOrder = (function(_this) {
|
||
return function(otnumber, otherotnumber) {
|
||
var j, o, ops, s, _k, _l, _len, _len1;
|
||
ops = _.filter(_this.users[otnumber]._model.connector.getOpsInExecutionOrder(), function(o) {
|
||
return typeof o.uid.op_name !== 'string' && o.uid.creator !== '_';
|
||
});
|
||
for (j = _k = 0, _len = ops.length; _k < _len; j = ++_k) {
|
||
s = ops[j];
|
||
console.log(("op" + j + " = ") + (JSON.stringify(s)));
|
||
}
|
||
console.log("");
|
||
s = "ops = [";
|
||
for (j = _l = 0, _len1 = ops.length; _l < _len1; j = ++_l) {
|
||
o = ops[j];
|
||
if (j !== 0) {
|
||
s += ", ";
|
||
}
|
||
s += "op" + j;
|
||
}
|
||
s += "]";
|
||
console.log(s);
|
||
console.log("@test_user.engine.applyOps ops");
|
||
console.log("expect(@test_user.val('name').val()).to.equal(\"" + (_this.users[otherotnumber].val('name').val()) + "\")");
|
||
return ops;
|
||
};
|
||
})(this);
|
||
console.log("");
|
||
console.log("Found an OT Puzzle!");
|
||
console.log("OT states:");
|
||
_ref2 = this.users;
|
||
for (j = _k = 0, _len = _ref2.length; _k < _len; j = ++_k) {
|
||
u = _ref2[j];
|
||
console.log(("OT" + j + ": ") + u.val('name').val());
|
||
}
|
||
console.log("\nOT execution order (" + i + "," + (i + 1) + "):");
|
||
printOpsInExecutionOrder(i, i + 1);
|
||
console.log("");
|
||
ops = printOpsInExecutionOrder(i + 1, i);
|
||
console.log("");
|
||
}
|
||
}
|
||
_results.push(expect(this.compare(this.users[i], this.users[i + 1])).to.not.be.undefined);
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
Test.prototype.run = function() {
|
||
var i, times, u, _i, _j, _k, _l, _len, _ref, _ref1, _ref2, _ref3, _results;
|
||
if (this.debug) {
|
||
console.log('');
|
||
}
|
||
_results = [];
|
||
for (times = _i = 1, _ref = this.repeat_this; 1 <= _ref ? _i <= _ref : _i >= _ref; times = 1 <= _ref ? ++_i : --_i) {
|
||
this.time_now = (new Date).getTime();
|
||
for (i = _j = 1, _ref1 = Math.floor(this.doSomething_amount / 2); 1 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 1 <= _ref1 ? ++_j : --_j) {
|
||
this.doSomething();
|
||
}
|
||
this.flushAll(false);
|
||
_ref2 = this.users;
|
||
for (_k = 0, _len = _ref2.length; _k < _len; _k++) {
|
||
u = _ref2[_k];
|
||
u._model.HB.emptyGarbage();
|
||
}
|
||
for (i = _l = 1, _ref3 = Math.floor(this.doSomething_amount / 2); 1 <= _ref3 ? _l <= _ref3 : _l >= _ref3; i = 1 <= _ref3 ? ++_l : --_l) {
|
||
this.doSomething();
|
||
}
|
||
this.compareAll(times);
|
||
this.testHBencoding();
|
||
if (times !== this.repeat_this) {
|
||
_results.push(this.reinitialize());
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
Test.prototype.testHBencoding = function() {
|
||
this.users[this.users.length] = this.makeNewUser(-1.);
|
||
this.users[this.users.length - 1]._model.HB.renewStateVector(this.users[0]._model.HB.getOperationCounter());
|
||
this.users[this.users.length - 1]._model.engine.applyOps(this.users[0]._model.HB._encode());
|
||
return expect(this.compare(this.users[this.users.length - 1], this.users[0])).to.not.be.undefined;
|
||
};
|
||
|
||
return Test;
|
||
|
||
})();
|
||
|
||
|
||
},{"../../y-test/lib/y-test.coffee":66,"chai":76,"sinon":118,"sinon-chai":117,"underscore":145}],147:[function(require,module,exports){
|
||
var ObjectTest, TestSuite, Y, chai, expect, should, sinon, sinonChai, _,
|
||
__hasProp = {}.hasOwnProperty,
|
||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||
|
||
chai = require('chai');
|
||
|
||
expect = chai.expect;
|
||
|
||
should = chai.should();
|
||
|
||
sinon = require('sinon');
|
||
|
||
sinonChai = require('sinon-chai');
|
||
|
||
_ = require("underscore");
|
||
|
||
chai.use(sinonChai);
|
||
|
||
Y = require("../lib/y.coffee");
|
||
|
||
Y.Test = require("../../y-test/lib/y-test.coffee");
|
||
|
||
Y.Text = require("../../y-text/lib/y-text");
|
||
|
||
Y.List = require("../../y-list/lib/y-list");
|
||
|
||
TestSuite = require("./TestSuite");
|
||
|
||
ObjectTest = (function(_super) {
|
||
__extends(ObjectTest, _super);
|
||
|
||
function ObjectTest(suffix) {
|
||
ObjectTest.__super__.constructor.call(this, suffix, Y);
|
||
}
|
||
|
||
ObjectTest.prototype.makeNewUser = function(userId) {
|
||
var conn;
|
||
conn = new Y.Test(userId);
|
||
return ObjectTest.__super__.makeNewUser.call(this, new Y(conn));
|
||
};
|
||
|
||
ObjectTest.prototype.type = "ObjectTest";
|
||
|
||
ObjectTest.prototype.getRandomRoot = function(user_num, root, depth) {
|
||
var elems, oname, p, val;
|
||
if (depth == null) {
|
||
depth = this.max_depth;
|
||
}
|
||
if (root == null) {
|
||
root = this.users[user_num];
|
||
}
|
||
if (depth === 0 || _.random(0, 1) === 1) {
|
||
return root;
|
||
} else {
|
||
depth--;
|
||
elems = null;
|
||
if (root._name === "Object") {
|
||
elems = (function() {
|
||
var _ref, _results;
|
||
_ref = root.val();
|
||
_results = [];
|
||
for (oname in _ref) {
|
||
val = _ref[oname];
|
||
_results.push(val);
|
||
}
|
||
return _results;
|
||
})();
|
||
} else if (root._name === "Array") {
|
||
elems = root.val();
|
||
} else {
|
||
return root;
|
||
}
|
||
elems = elems.filter(function(elem) {
|
||
return (elem != null) && ((elem._name === "Array") || (elem._name === "Object"));
|
||
});
|
||
if (elems.length === 0) {
|
||
return root;
|
||
} else {
|
||
p = elems[_.random(0, elems.length - 1)];
|
||
return this.getRandomRoot(user_num, p, depth);
|
||
}
|
||
}
|
||
};
|
||
|
||
ObjectTest.prototype.getGeneratingFunctions = function(user_num) {
|
||
return ObjectTest.__super__.getGeneratingFunctions.call(this, user_num).concat([
|
||
{
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var key, list, name, o;
|
||
list = (function() {
|
||
var _ref, _results;
|
||
_ref = y.val();
|
||
_results = [];
|
||
for (name in _ref) {
|
||
o = _ref[name];
|
||
_results.push(name);
|
||
}
|
||
return _results;
|
||
})();
|
||
if (list.length > 0) {
|
||
key = list[_.random(0, list.length - 1)];
|
||
return y["delete"](key);
|
||
}
|
||
};
|
||
})(this),
|
||
types: [Y.Object]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
return y.val(_this.getRandomKey(), new Y.Object(_this.getRandomObject()));
|
||
};
|
||
})(this),
|
||
types: [Y.Object]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
return y.val(_this.getRandomKey(), new Y.Text(_this.getRandomText()));
|
||
};
|
||
})(this),
|
||
types: [Y.Object]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
return y.val(_this.getRandomKey(), new Y.List(_this.getRandomText().split("")));
|
||
};
|
||
})(this),
|
||
types: [Y.Object]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var i, list;
|
||
list = y.val();
|
||
if (list.length > 0) {
|
||
i = _.random(0, list.length - 1);
|
||
return y["delete"](i);
|
||
}
|
||
};
|
||
})(this),
|
||
types: [Y.List]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var l;
|
||
l = y.val().length;
|
||
return y.insert(_.random(0, l - 1), new Y.Object(_this.getRandomObject()));
|
||
};
|
||
})(this),
|
||
types: [Y.List]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var l;
|
||
l = y.val().length;
|
||
return y.insert(_.random(0, l - 1), new Y.Text(_this.getRandomText()));
|
||
};
|
||
})(this),
|
||
types: [Y.List]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var l;
|
||
l = y.val().length;
|
||
return y.insert(_.random(0, l - 1), new Y.List(_this.getRandomText().split("")));
|
||
};
|
||
})(this),
|
||
types: [Y.List]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var l;
|
||
l = y.val().length;
|
||
return y.insert(_.random(0, l - 1), _.random(0, 42));
|
||
};
|
||
})(this),
|
||
types: [Y.List]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
return y.val(_this.getRandomKey(), _this.getRandomRoot(user_num));
|
||
};
|
||
})(this),
|
||
types: [Y.Object]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var l;
|
||
l = y.val().length;
|
||
return y.insert(_.random(0, l - 1), _this.getRandomRoot(user_num));
|
||
};
|
||
})(this),
|
||
types: [Y.List]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
y;
|
||
var pos;
|
||
pos = _.random(0, y.val().length - 1);
|
||
y.insert(pos, _this.getRandomText());
|
||
return null;
|
||
};
|
||
})(this),
|
||
types: [Y.Text]
|
||
}, {
|
||
f: function(y) {
|
||
var length, ops1, pos;
|
||
if (y.val().length > 0) {
|
||
pos = _.random(0, y.val().length - 1);
|
||
length = _.random(0, y.val().length - pos);
|
||
ops1 = y["delete"](pos, length);
|
||
}
|
||
return void 0;
|
||
},
|
||
types: [Y.Text]
|
||
}
|
||
]);
|
||
};
|
||
|
||
return ObjectTest;
|
||
|
||
})(TestSuite);
|
||
|
||
module.exports = ObjectTest;
|
||
|
||
describe("Object Test", function() {
|
||
this.timeout(500000);
|
||
beforeEach(function(done) {
|
||
this.yTest = new ObjectTest();
|
||
this.users = this.yTest.users;
|
||
this.test_user = this.yTest.makeNewUser("test_user");
|
||
return done();
|
||
});
|
||
it("can handle many engines, many operations, concurrently (random)", function() {
|
||
console.log("");
|
||
return this.yTest.run();
|
||
});
|
||
it("has a working test suite", function() {
|
||
return this.yTest.compareAll();
|
||
});
|
||
it("handles double-late-join", function() {
|
||
var ops1, ops2, test, u1, u2;
|
||
test = new ObjectTest("double");
|
||
test.run();
|
||
this.yTest.run();
|
||
u1 = test.users[0];
|
||
u2 = this.yTest.users[1];
|
||
ops1 = u1._model.HB._encode();
|
||
ops2 = u2._model.HB._encode();
|
||
u1._model.engine.applyOp(ops2, true);
|
||
u2._model.engine.applyOp(ops1, true);
|
||
return expect(this.yTest.compare(u1, u2)).to.not.be.undefined;
|
||
});
|
||
it("can handle creaton of complex json (1)", function() {
|
||
var q;
|
||
this.yTest.users[0].val('a', new Y.Text('q'));
|
||
this.yTest.users[1].val('a', new Y.Text('t'));
|
||
this.yTest.compareAll();
|
||
q = this.yTest.users[2].val('a');
|
||
q.insert(0, 'A');
|
||
this.yTest.compareAll();
|
||
return expect(this.yTest.getSomeUser().val("a").val()).to.equal("At");
|
||
});
|
||
it("can handle creaton of complex json (2)", function() {
|
||
var q;
|
||
this.yTest.getSomeUser().val('x', new Y.Object({
|
||
'a': 'b'
|
||
}));
|
||
this.yTest.getSomeUser().val('a', new Y.Object({
|
||
'a': {
|
||
q: new Y.Text("dtrndtrtdrntdrnrtdnrtdnrtdnrtdnrdnrdt")
|
||
}
|
||
}));
|
||
this.yTest.getSomeUser().val('b', new Y.Object({
|
||
'a': {}
|
||
}));
|
||
this.yTest.getSomeUser().val('c', new Y.Object({
|
||
'a': 'c'
|
||
}));
|
||
this.yTest.getSomeUser().val('c', new Y.Object({
|
||
'a': 'b'
|
||
}));
|
||
this.yTest.compareAll();
|
||
q = this.yTest.getSomeUser().val("a").val("a").val("q");
|
||
q.insert(0, 'A');
|
||
this.yTest.compareAll();
|
||
return expect(this.yTest.getSomeUser().val("a").val("a").val("q").val()).to.equal("Adtrndtrtdrntdrnrtdnrtdnrtdnrtdnrdnrdt");
|
||
});
|
||
it("can handle creaton of complex json (3)", function() {
|
||
var w;
|
||
this.yTest.users[0].val('l', new Y.List([1, 2, 3]));
|
||
this.yTest.users[1].val('l', new Y.List([4, 5, 6]));
|
||
this.yTest.compareAll();
|
||
this.yTest.users[2].val('l').insert(0, 'A');
|
||
w = this.yTest.users[1].val('l').insert(0, new Y.Text('B')).val(0);
|
||
w.insert(1, "C");
|
||
expect(w.val()).to.equal("BC");
|
||
return this.yTest.compareAll();
|
||
});
|
||
it("handles immutables and primitive data types", function() {
|
||
this.yTest.getSomeUser().val('string', "text");
|
||
this.yTest.getSomeUser().val('number', 4);
|
||
this.yTest.getSomeUser().val('object', new Y.Object({
|
||
q: "rr"
|
||
}));
|
||
this.yTest.getSomeUser().val('null', null);
|
||
this.yTest.compareAll();
|
||
expect(this.yTest.getSomeUser().val('string')).to.equal("text");
|
||
expect(this.yTest.getSomeUser().val('number')).to.equal(4);
|
||
expect(this.yTest.getSomeUser().val('object').val('q')).to.equal("rr");
|
||
return expect(this.yTest.getSomeUser().val('null') === null).to.be.ok;
|
||
});
|
||
it("handles immutables and primitive data types (2)", function() {
|
||
this.yTest.users[0].val('string', "text");
|
||
this.yTest.users[1].val('number', 4);
|
||
this.yTest.users[2].val('object', new Y.Object({
|
||
q: "rr"
|
||
}));
|
||
this.yTest.users[0].val('null', null);
|
||
this.yTest.compareAll();
|
||
expect(this.yTest.getSomeUser().val('string')).to.equal("text");
|
||
expect(this.yTest.getSomeUser().val('number')).to.equal(4);
|
||
expect(this.yTest.getSomeUser().val('object').val('q')).to.equal("rr");
|
||
return expect(this.yTest.getSomeUser().val('null') === null).to.be.ok;
|
||
});
|
||
it("Observers work on JSON Types (add type observers, local and foreign)", function() {
|
||
var last_task, observer1, observer2, u, v;
|
||
u = this.yTest.users[0];
|
||
this.yTest.flushAll();
|
||
last_task = null;
|
||
observer1 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("add");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.changedBy).to.equal('0');
|
||
expect(change.name).to.equal("newStuff");
|
||
return last_task = "observer1";
|
||
};
|
||
u.observe(observer1);
|
||
u.val("newStuff", new Y.Text("someStuff"));
|
||
expect(last_task).to.equal("observer1");
|
||
u.unobserve(observer1);
|
||
observer2 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("add");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.changedBy).to.equal('1');
|
||
expect(change.name).to.equal("moreStuff");
|
||
return last_task = "observer2";
|
||
};
|
||
u.observe(observer2);
|
||
v = this.yTest.users[1];
|
||
v.val("moreStuff", "someMoreStuff");
|
||
this.yTest.flushAll();
|
||
expect(last_task).to.equal("observer2");
|
||
return u.unobserve(observer2);
|
||
});
|
||
it("Observers work on JSON Types (update type observers, local and foreign)", function() {
|
||
var last_task, observer1, observer2, u, v;
|
||
u = this.yTest.users[0].val("newStuff", new Y.Text("oldStuff")).val("moreStuff", new Y.Text("moreOldStuff"));
|
||
this.yTest.flushAll();
|
||
last_task = null;
|
||
observer1 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("update");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.changedBy).to.equal('0');
|
||
expect(change.name).to.equal("newStuff");
|
||
expect(change.oldValue.val()).to.equal("oldStuff");
|
||
return last_task = "observer1";
|
||
};
|
||
u.observe(observer1);
|
||
u.val("newStuff", "someStuff");
|
||
expect(last_task).to.equal("observer1");
|
||
u.unobserve(observer1);
|
||
observer2 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("update");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.changedBy).to.equal('1');
|
||
expect(change.name).to.equal("moreStuff");
|
||
expect(change.oldValue.val()).to.equal("moreOldStuff");
|
||
return last_task = "observer2";
|
||
};
|
||
u.observe(observer2);
|
||
v = this.yTest.users[1];
|
||
v.val("moreStuff", "someMoreStuff");
|
||
this.yTest.flushAll();
|
||
expect(last_task).to.equal("observer2");
|
||
return u.unobserve(observer2);
|
||
});
|
||
it("Observers work on JSON Types (delete type observers, local and foreign)", function() {
|
||
var last_task, observer1, observer2, u, v;
|
||
u = this.yTest.users[0].val("newStuff", new Y.Text("oldStuff")).val("moreStuff", new Y.Text("moreOldStuff"));
|
||
this.yTest.flushAll();
|
||
last_task = null;
|
||
observer1 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("delete");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.changedBy).to.equal('0');
|
||
expect(change.name).to.equal("newStuff");
|
||
expect(change.oldValue.val()).to.equal("oldStuff");
|
||
return last_task = "observer1";
|
||
};
|
||
u.observe(observer1);
|
||
u["delete"]("newStuff");
|
||
expect(last_task).to.equal("observer1");
|
||
u.unobserve(observer1);
|
||
observer2 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("delete");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.changedBy).to.equal('1');
|
||
expect(change.name).to.equal("moreStuff");
|
||
expect(change.oldValue.val()).to.equal("moreOldStuff");
|
||
return last_task = "observer2";
|
||
};
|
||
u.observe(observer2);
|
||
v = this.yTest.users[1];
|
||
v["delete"]("moreStuff");
|
||
this.yTest.flushAll();
|
||
expect(last_task).to.equal("observer2");
|
||
return u.unobserve(observer2);
|
||
});
|
||
return it("can handle circular JSON", function() {
|
||
var u;
|
||
u = this.yTest.users[0];
|
||
u.val("me", u);
|
||
this.yTest.compareAll();
|
||
u.val("stuff", new Y.Object({
|
||
x: true
|
||
}));
|
||
u.val("same_stuff", u.val("stuff"));
|
||
u.val("same_stuff").val("x", 5);
|
||
expect(u.val("same_stuff").val("x")).to.equal(5);
|
||
this.yTest.compareAll();
|
||
u.val("stuff").val("y", u.val("stuff"));
|
||
return this.yTest.compareAll();
|
||
});
|
||
});
|
||
|
||
|
||
},{"../../y-list/lib/y-list":1,"../../y-test/lib/y-test.coffee":66,"../../y-text/lib/y-text":67,"../lib/y.coffee":75,"./TestSuite":146,"chai":76,"sinon":118,"sinon-chai":117,"underscore":145}]},{},[65])
|
||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIkg6XFxHaXRIdWJcXHlqc1xcbm9kZV9tb2R1bGVzXFxndWxwLWJyb3dzZXJpZnlcXG5vZGVfbW9kdWxlc1xcYnJvd3NlcmlmeVxcbm9kZV9tb2R1bGVzXFxicm93c2VyLXBhY2tcXF9wcmVsdWRlLmpzIiwiSDpcXEdpdEh1YlxceS1saXN0XFxsaWJcXHktbGlzdC5jb2ZmZWUiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9jaGFpL2luZGV4LmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvYXNzZXJ0aW9uLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS9jb25maWcuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL2NvcmUvYXNzZXJ0aW9ucy5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvaW50ZXJmYWNlL2Fzc2VydC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvaW50ZXJmYWNlL2V4cGVjdC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvaW50ZXJmYWNlL3Nob3VsZC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvYWRkQ2hhaW5hYmxlTWV0aG9kLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9hZGRNZXRob2QuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2FkZFByb3BlcnR5LmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9mbGFnLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9nZXRBY3R1YWwuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2dldEVudW1lcmFibGVQcm9wZXJ0aWVzLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9nZXRNZXNzYWdlLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9nZXROYW1lLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9nZXRQYXRoSW5mby5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvZ2V0UGF0aFZhbHVlLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9nZXRQcm9wZXJ0aWVzLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9oYXNQcm9wZXJ0eS5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvaW5kZXguanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2luc3BlY3QuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL29iakRpc3BsYXkuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL292ZXJ3cml0ZUNoYWluYWJsZU1ldGhvZC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvb3ZlcndyaXRlTWV0aG9kLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9vdmVyd3JpdGVQcm9wZXJ0eS5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvdGVzdC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvdHJhbnNmZXJGbGFncy5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvdHlwZS5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbm9kZV9tb2R1bGVzL2Fzc2VydGlvbi1lcnJvci9pbmRleC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbm9kZV9tb2R1bGVzL2RlZXAtZXFsL2luZGV4LmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvY2hhaS9ub2RlX21vZHVsZXMvZGVlcC1lcWwvbGliL2VxbC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbm9kZV9tb2R1bGVzL2RlZXAtZXFsL25vZGVfbW9kdWxlcy90eXBlLWRldGVjdC9pbmRleC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL2NoYWkvbm9kZV9tb2R1bGVzL2RlZXAtZXFsL25vZGVfbW9kdWxlcy90eXBlLWRldGVjdC9saWIvdHlwZS5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL3Npbm9uLWNoYWkvbGliL3Npbm9uLWNoYWkuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24uanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vYXNzZXJ0LmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL2JlaGF2aW9yLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL2NhbGwuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vY29sbGVjdGlvbi5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi9leHRlbmQuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vZm9ybWF0LmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL2xvZ19lcnJvci5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi9tYXRjaC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi9tb2NrLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL3NhbmRib3guanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vc3B5LmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL3N0dWIuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vdGVzdC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi90ZXN0X2Nhc2UuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vdGltZXNfaW5fd29yZHMuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vdHlwZU9mLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL3V0aWwvY29yZS5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi91dGlsL2V2ZW50LmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL3V0aWwvZmFrZV9zZXJ2ZXIuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vdXRpbC9mYWtlX3NlcnZlcl93aXRoX2Nsb2NrLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL3V0aWwvZmFrZV90aW1lcnMuanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vdXRpbC9mYWtlX3hkb21haW5fcmVxdWVzdC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi91dGlsL2Zha2VfeG1sX2h0dHBfcmVxdWVzdC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL3Npbm9uL25vZGVfbW9kdWxlcy9mb3JtYXRpby9saWIvZm9ybWF0aW8uanMiLCJIOi9HaXRIdWIveS1saXN0L25vZGVfbW9kdWxlcy9zaW5vbi9ub2RlX21vZHVsZXMvZm9ybWF0aW8vbm9kZV9tb2R1bGVzL3NhbXNhbS9saWIvc2Ftc2FtLmpzIiwiSDovR2l0SHViL3ktbGlzdC9ub2RlX21vZHVsZXMvc2lub24vbm9kZV9tb2R1bGVzL2xvbGV4L3NyYy9sb2xleC5qcyIsIkg6L0dpdEh1Yi95LWxpc3Qvbm9kZV9tb2R1bGVzL3VuZGVyc2NvcmUvdW5kZXJzY29yZS5qcyIsIkg6XFxHaXRIdWJcXHktbGlzdFxcdGVzdFxcbGlzdC10ZXN0LmNvZmZlZSIsIkg6XFxHaXRIdWJcXHktdGVzdFxcbGliXFx5LXRlc3QuY29mZmVlIiwiSDpcXEdpdEh1YlxceS10ZXh0XFxsaWJcXHktdGV4dC5jb2ZmZWUiLCJIOlxcR2l0SHViXFx5anNcXGxpYlxcQ29ubmVjdG9yQWRhcHRlci5jb2ZmZWUiLCJIOlxcR2l0SHViXFx5anNcXGxpYlxcQ29ubmVjdG9yQ2xhc3MuY29mZmVlIiwiSDpcXEdpdEh1YlxceWpzXFxsaWJcXEVuZ2luZS5jb2ZmZWUiLCJIOlxcR2l0SHViXFx5anNcXGxpYlxcSGlzdG9yeUJ1ZmZlci5jb2ZmZWUiLCJIOlxcR2l0SHViXFx5anNcXGxpYlxcT2JqZWN0VHlwZS5jb2ZmZWUiLCJIOlxcR2l0SHViXFx5anNcXGxpYlxcT3BlcmF0aW9uc1xcQmFzaWMuY29mZmVlIiwiSDpcXEdpdEh1YlxceWpzXFxsaWJcXE9wZXJhdGlvbnNcXFN0cnVjdHVyZWQuY29mZmVlIiwiSDpcXEdpdEh1YlxceWpzXFxsaWJcXHkuY29mZmVlIiwiSDovR2l0SHViL3lqcy9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9idWZmZXIvaW5kZXguanMiLCJIOi9HaXRIdWIveWpzL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9ub2RlX21vZHVsZXMvYmFzZTY0LWpzL2xpYi9iNjQuanMiLCJIOi9HaXRIdWIveWpzL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9ub2RlX21vZHVsZXMvaWVlZTc1NC9pbmRleC5qcyIsIkg6L0dpdEh1Yi95anMvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvaW5oZXJpdHMvaW5oZXJpdHNfYnJvd3Nlci5qcyIsIkg6L0dpdEh1Yi95anMvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwiSDovR2l0SHViL3lqcy9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3N1cHBvcnQvaXNCdWZmZXJCcm93c2VyLmpzIiwiSDovR2l0SHViL3lqcy9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3V0aWwuanMiLCJIOlxcR2l0SHViXFx5anNcXHRlc3RcXFRlc3RTdWl0ZS5jb2ZmZWUiLCJIOlxcR2l0SHViXFx5anNcXHRlc3RcXG9iamVjdC10ZXN0LmNvZmZlZSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBLElBQUEsS0FBQTs7QUFBQTtBQU1lLEVBQUEsZUFBQyxJQUFELEdBQUE7QUFDWCxJQUFBLElBQU8sWUFBUDtBQUNFLE1BQUEsSUFBQyxDQUFBLEtBQUQsR0FBUyxFQUFULENBREY7S0FBQSxNQUVLLElBQUcsSUFBSSxDQUFDLFdBQUwsS0FBb0IsS0FBdkI7QUFDSCxNQUFBLElBQUMsQ0FBQSxLQUFELEdBQVMsSUFBVCxDQURHO0tBQUEsTUFBQTtBQUdILFlBQVUsSUFBQSxLQUFBLENBQU0sd0NBQU4sQ0FBVixDQUhHO0tBSE07RUFBQSxDQUFiOztBQUFBLGtCQVFBLEtBQUEsR0FBTyxNQVJQLENBQUE7O0FBQUEsa0JBVUEsU0FBQSxHQUFXLFNBQUMsS0FBRCxFQUFRLEdBQVIsR0FBQTtBQUNULElBQUEsSUFBTyxtQkFBUDtBQUNFLE1BQUEsSUFBQyxDQUFBLE1BQUQsR0FBYyxJQUFBLEdBQUcsQ0FBQyxXQUFKLENBQWdCLElBQWhCLENBQWtCLENBQUMsT0FBbkIsQ0FBQSxDQUFkLENBQUE7QUFBQSxNQUNBLElBQUMsQ0FBQSxNQUFNLENBQUMsTUFBUixDQUFlLENBQWYsRUFBa0IsSUFBQyxDQUFBLEtBQW5CLENBREEsQ0FERjtLQUFBO0FBQUEsSUFHQSxNQUFBLENBQUEsSUFBUSxDQUFBLEtBSFIsQ0FBQTtXQUlBLElBQUMsQ0FBQSxPQUxRO0VBQUEsQ0FWWCxDQUFBOztBQUFBLGtCQWlCQSxTQUFBLEdBQVcsU0FBRSxN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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25JQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hoREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL3VDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3VUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlHQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqUUE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5UEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeGNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RZQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFBBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5bUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL1lBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeGFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFD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O0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNybENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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QUFJLElBQUMsQ0FBQSxLQUFLLENBQUMsS0FBTSxDQUFBLENBQUEsQ0FBakIsQ0FBQTtBQUFBLElBQ0EsQ0FBQyxDQUFDLEdBQUYsQ0FBTSxJQUFOLEVBQVksQ0FBWixDQURBLENBQUE7QUFBQSxJQUVBLElBQUMsQ0FBQSxLQUFLLENBQUMsVUFBUCxDQUFBLENBRkEsQ0FBQTtBQUFBLElBR0EsQ0FBQyxDQUFDLEdBQUYsQ0FBTSxPQUFOLEVBQW1CLElBQUEsQ0FBQyxDQUFDLE1BQUYsQ0FBUztBQUFBLE1BQUMsQ0FBQSxFQUFHLElBQUo7S0FBVCxDQUFuQixDQUhBLENBQUE7QUFBQSxJQUlBLENBQUMsQ0FBQyxHQUFGLENBQU0sWUFBTixFQUFvQixDQUFDLENBQUMsR0FBRixDQUFNLE9BQU4sQ0FBcEIsQ0FKQSxDQUFBO0FBQUEsSUFLQSxDQUFDLENBQUMsR0FBRixDQUFNLFlBQU4sQ0FBbUIsQ0FBQyxHQUFwQixDQUF3QixHQUF4QixFQUE2QixDQUE3QixDQUxBLENBQUE7QUFBQSxJQU1BLE1BQUEsQ0FBTyxDQUFDLENBQUMsR0FBRixDQUFNLFlBQU4sQ0FBbUIsQ0FBQyxHQUFwQixDQUF3QixHQUF4QixDQUFQLENBQW9DLENBQUMsRUFBRSxDQUFDLEtBQXhDLENBQThDLENBQTlDLENBTkEsQ0FBQTtBQUFBLElBT0EsSUFBQyxDQUFBLEtBQUssQ0FBQyxVQUFQLENBQUEsQ0FQQSxDQUFBO0FBQUEsSUFRQSxDQUFDLENBQUMsR0FBRixDQUFNLE9BQU4sQ0FBYyxDQUFDLEdBQWYsQ0FBbUIsR0FBbkIsRUFBd0IsQ0FBQyxDQUFDLEdBQUYsQ0FBTSxPQUFOLENBQXhCLENBUkEsQ0FBQTtXQVNBLElBQUMsQ0FBQSxLQUFLLENBQUMsVUFBUCxDQUFBLEVBVjZCO0VBQUEsQ0FBL0IsRUF4THNCO0FBQUEsQ0FBeEIsQ0E5SEEsQ0FBQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpfXZhciBmPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChmLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGYsZi5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJjbGFzcyBZTGlzdFxyXG5cclxuICAjXHJcbiAgIyBAcHJpdmF0ZVxyXG4gICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxyXG4gICNcclxuICBjb25zdHJ1Y3RvcjogKGxpc3QpLT5cclxuICAgIGlmIG5vdCBsaXN0P1xyXG4gICAgICBAX2xpc3QgPSBbXVxyXG4gICAgZWxzZSBpZiBsaXN0LmNvbnN0cnVjdG9yIGlzIEFycmF5XHJcbiAgICAgIEBfbGlzdCA9IGxpc3RcclxuICAgIGVsc2VcclxuICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWS5MaXN0IGV4cGVjdHMgYW4gQXJyYXkgYXMgYSBwYXJhbWV0ZXJcIlxyXG5cclxuICBfbmFtZTogXCJMaXN0XCJcclxuXHJcbiAgX2dldE1vZGVsOiAodHlwZXMsIG9wcyktPlxyXG4gICAgaWYgbm90IEBfbW9kZWw/XHJcbiAgICAgIEBfbW9kZWwgPSBuZXcgb3BzLkxpc3RNYW5hZ2VyKEApLmV4ZWN1dGUoKVxyXG4gICAgICBAX21vZGVsLmluc2VydCAwLCBAX2xpc3RcclxuICAgIGRlbGV0ZSBAX2xpc3RcclxuICAgIEBfbW9kZWxcclxuXHJcbiAgX3NldE1vZGVsOiAoQF9tb2RlbCktPlxyXG4gICAgZGVsZXRlIEBfbGlzdFxyXG5cclxuICB2YWw6ICgpLT5cclxuICAgIEBfbW9kZWwudmFsLmFwcGx5IEBfbW9kZWwsIGFyZ3VtZW50c1xyXG5cclxuICByZWY6ICgpLT5cclxuICAgIEBfbW9kZWwucmVmLmFwcGx5IEBfbW9kZWwsIGFyZ3VtZW50c1xyXG5cclxuXHJcbiAgb2JzZXJ2ZTogKCktPlxyXG4gICAgQF9tb2RlbC5vYnNlcnZlLmFwcGx5IEBfbW9kZWwsIGFyZ3VtZW50c1xyXG4gICAgQFxyXG5cclxuICB1bm9ic2VydmU6ICgpLT5cclxuICAgIEBfbW9kZWwudW5vYnNlcnZlLmFwcGx5IEBfbW9kZWwsIGFyZ3VtZW50c1xyXG4gICAgQFxyXG5cclxuICAjXHJcbiAgIyBJbnNlcnRzIGFuIE9iamVjdCBpbnRvIHRoZSBsaXN0LlxyXG4gICNcclxuICAjIEByZXR1cm4ge0xpc3RNYW5hZ2VyIFR5cGV9IFRoaXMgU3RyaW5nIG9iamVjdC5cclxuICAjXHJcbiAgaW5zZXJ0OiAocG9zaXRpb24sIGNvbnRlbnQpLT5cclxuICAgIGlmIHR5cGVvZiBwb3NpdGlvbiBpc250IFwibnVtYmVyXCJcclxuICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWS5MaXN0Lmluc2VydCBleHBlY3RzIGEgTnVtYmVyIGFzIHRoZSBmaXJzdCBwYXJhbWV0ZXIhXCJcclxuICAgIEBfbW9kZWwuaW5zZXJ0IHBvc2l0aW9uLCBbY29udGVudF1cclxuICAgIEBcclxuXHJcbiAgaW5zZXJ0Q29udGVudHM6IChwb3NpdGlvbiwgY29udGVudHMpLT5cclxuICAgIGlmIHR5cGVvZiBwb3NpdGlvbiBpc250IFwibnVtYmVyXCJcclxuICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWS5MaXN0Lmluc2VydCBleHBlY3RzIGEgTnVtYmVyIGFzIHRoZSBmaXJzdCBwYXJhbWV0ZXIhXCJcclxuICAgIEBfbW9kZWwuaW5zZXJ0IHBvc2l0aW9uLCBjb250ZW50c1xyXG4gICAgQFxyXG5cclxuICBkZWxldGU6IChwb3NpdGlvbiwgbGVuZ3RoKS0+XHJcbiAgICBAX21vZGVsLmRlbGV0ZSBwb3NpdGlvbiwgbGVuZ3RoXHJcbiAgICBAXHJcblxyXG4gIHB1c2g6IChjb250ZW50KS0+XHJcbiAgICBAX21vZGVsLnB1c2ggY29udGVudFxyXG4gICAgQFxyXG5cclxuaWYgd2luZG93P1xyXG4gIGlmIHdpbmRvdy5ZP1xyXG4gICAgd2luZG93LlkuTGlzdCA9IFlMaXN0XHJcbiAgZWxzZVxyXG4gICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3QgZmlyc3QgaW1wb3J0IFkhXCJcclxuXHJcbmlmIG1vZHVsZT9cclxuICBtb2R1bGUuZXhwb3J0cyA9IFlMaXN0XHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG4iLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vbGliL2NoYWknKTtcbiIsIi8qIVxuICogY2hhaVxuICogQ29weXJpZ2h0KGMpIDIwMTEtMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbnZhciB1c2VkID0gW11cbiAgLCBleHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLyohXG4gKiBDaGFpIHZlcnNpb25cbiAqL1xuXG5leHBvcnRzLnZlcnNpb24gPSAnMi4yLjAnO1xuXG4vKiFcbiAqIEFzc2VydGlvbiBFcnJvclxuICovXG5cbmV4cG9ydHMuQXNzZXJ0aW9uRXJyb3IgPSByZXF1aXJlKCdhc3NlcnRpb24tZXJyb3InKTtcblxuLyohXG4gKiBVdGlscyBmb3IgcGx1Z2lucyAobm90IGV4cG9ydGVkKVxuICovXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi9jaGFpL3V0aWxzJyk7XG5cbi8qKlxuICogIyAudXNlKGZ1bmN0aW9uKVxuICpcbiAqIFByb3ZpZGVzIGEgd2F5IHRvIGV4dGVuZCB0aGUgaW50ZXJuYWxzIG9mIENoYWlcbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufVxuICogQHJldHVybnMge3RoaXN9IGZvciBjaGFpbmluZ1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5leHBvcnRzLnVzZSA9IGZ1bmN0aW9uIChmbikge1xuICBpZiAoIX51c2VkLmluZGV4T2YoZm4pKSB7XG4gICAgZm4odGhpcywgdXRpbCk7XG4gICAgdXNlZC5wdXNoKGZuKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuLyohXG4gKiBVdGlsaXR5IEZ1bmN0aW9uc1xuICovXG5cbmV4cG9ydHMudXRpbCA9IHV0aWw7XG5cbi8qIVxuICogQ29uZmlndXJhdGlvblxuICovXG5cbnZhciBjb25maWcgPSByZXF1aXJlKCcuL2NoYWkvY29uZmlnJyk7XG5leHBvcnRzLmNvbmZpZyA9IGNvbmZpZztcblxuLyohXG4gKiBQcmltYXJ5IGBBc3NlcnRpb25gIHByb3RvdHlwZVxuICovXG5cbnZhciBhc3NlcnRpb24gPSByZXF1aXJlKCcuL2NoYWkvYXNzZXJ0aW9uJyk7XG5leHBvcnRzLnVzZShhc3NlcnRpb24pO1xuXG4vKiFcbiAqIENvcmUgQXNzZXJ0aW9uc1xuICovXG5cbnZhciBjb3JlID0gcmVxdWlyZSgnLi9jaGFpL2NvcmUvYXNzZXJ0aW9ucycpO1xuZXhwb3J0cy51c2UoY29yZSk7XG5cbi8qIVxuICogRXhwZWN0IGludGVyZmFjZVxuICovXG5cbnZhciBleHBlY3QgPSByZXF1aXJlKCcuL2NoYWkvaW50ZXJmYWNlL2V4cGVjdCcpO1xuZXhwb3J0cy51c2UoZXhwZWN0KTtcblxuLyohXG4gKiBTaG91bGQgaW50ZXJmYWNlXG4gKi9cblxudmFyIHNob3VsZCA9IHJlcXVpcmUoJy4vY2hhaS9pbnRlcmZhY2Uvc2hvdWxkJyk7XG5leHBvcnRzLnVzZShzaG91bGQpO1xuXG4vKiFcbiAqIEFzc2VydCBpbnRlcmZhY2VcbiAqL1xuXG52YXIgYXNzZXJ0ID0gcmVxdWlyZSgnLi9jaGFpL2ludGVyZmFjZS9hc3NlcnQnKTtcbmV4cG9ydHMudXNlKGFzc2VydCk7XG4iLCIvKiFcbiAqIGNoYWlcbiAqIGh0dHA6Ly9jaGFpanMuY29tXG4gKiBDb3B5cmlnaHQoYykgMjAxMS0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxudmFyIGNvbmZpZyA9IHJlcXVpcmUoJy4vY29uZmlnJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKF9jaGFpLCB1dGlsKSB7XG4gIC8qIVxuICAgKiBNb2R1bGUgZGVwZW5kZW5jaWVzLlxuICAgKi9cblxuICB2YXIgQXNzZXJ0aW9uRXJyb3IgPSBfY2hhaS5Bc3NlcnRpb25FcnJvclxuICAgICwgZmxhZyA9IHV0aWwuZmxhZztcblxuICAvKiFcbiAgICogTW9kdWxlIGV4cG9ydC5cbiAgICovXG5cbiAgX2NoYWkuQXNzZXJ0aW9uID0gQXNzZXJ0aW9uO1xuXG4gIC8qIVxuICAgKiBBc3NlcnRpb24gQ29uc3RydWN0b3JcbiAgICpcbiAgICogQ3JlYXRlcyBvYmplY3QgZm9yIGNoYWluaW5nLlxuICAgKlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICovXG5cbiAgZnVuY3Rpb24gQXNzZXJ0aW9uIChvYmosIG1zZywgc3RhY2spIHtcbiAgICBmbGFnKHRoaXMsICdzc2ZpJywgc3RhY2sgfHwgYXJndW1lbnRzLmNhbGxlZSk7XG4gICAgZmxhZyh0aGlzLCAnb2JqZWN0Jywgb2JqKTtcbiAgICBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgfVxuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBc3NlcnRpb24sICdpbmNsdWRlU3RhY2snLCB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIGNvbnNvbGUud2FybignQXNzZXJ0aW9uLmluY2x1ZGVTdGFjayBpcyBkZXByZWNhdGVkLCB1c2UgY2hhaS5jb25maWcuaW5jbHVkZVN0YWNrIGluc3RlYWQuJyk7XG4gICAgICByZXR1cm4gY29uZmlnLmluY2x1ZGVTdGFjaztcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIGNvbnNvbGUud2FybignQXNzZXJ0aW9uLmluY2x1ZGVTdGFjayBpcyBkZXByZWNhdGVkLCB1c2UgY2hhaS5jb25maWcuaW5jbHVkZVN0YWNrIGluc3RlYWQuJyk7XG4gICAgICBjb25maWcuaW5jbHVkZVN0YWNrID0gdmFsdWU7XG4gICAgfVxuICB9KTtcblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQXNzZXJ0aW9uLCAnc2hvd0RpZmYnLCB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIGNvbnNvbGUud2FybignQXNzZXJ0aW9uLnNob3dEaWZmIGlzIGRlcHJlY2F0ZWQsIHVzZSBjaGFpLmNvbmZpZy5zaG93RGlmZiBpbnN0ZWFkLicpO1xuICAgICAgcmV0dXJuIGNvbmZpZy5zaG93RGlmZjtcbiAgICB9LFxuICAgIHNldDogZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIGNvbnNvbGUud2FybignQXNzZXJ0aW9uLnNob3dEaWZmIGlzIGRlcHJlY2F0ZWQsIHVzZSBjaGFpLmNvbmZpZy5zaG93RGlmZiBpbnN0ZWFkLicpO1xuICAgICAgY29uZmlnLnNob3dEaWZmID0gdmFsdWU7XG4gICAgfVxuICB9KTtcblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkgPSBmdW5jdGlvbiAobmFtZSwgZm4pIHtcbiAgICB1dGlsLmFkZFByb3BlcnR5KHRoaXMucHJvdG90eXBlLCBuYW1lLCBmbik7XG4gIH07XG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCA9IGZ1bmN0aW9uIChuYW1lLCBmbikge1xuICAgIHV0aWwuYWRkTWV0aG9kKHRoaXMucHJvdG90eXBlLCBuYW1lLCBmbik7XG4gIH07XG5cbiAgQXNzZXJ0aW9uLmFkZENoYWluYWJsZU1ldGhvZCA9IGZ1bmN0aW9uIChuYW1lLCBmbiwgY2hhaW5pbmdCZWhhdmlvcikge1xuICAgIHV0aWwuYWRkQ2hhaW5hYmxlTWV0aG9kKHRoaXMucHJvdG90eXBlLCBuYW1lLCBmbiwgY2hhaW5pbmdCZWhhdmlvcik7XG4gIH07XG5cbiAgQXNzZXJ0aW9uLm92ZXJ3cml0ZVByb3BlcnR5ID0gZnVuY3Rpb24gKG5hbWUsIGZuKSB7XG4gICAgdXRpbC5vdmVyd3JpdGVQcm9wZXJ0eSh0aGlzLnByb3RvdHlwZSwgbmFtZSwgZm4pO1xuICB9O1xuXG4gIEFzc2VydGlvbi5vdmVyd3JpdGVNZXRob2QgPSBmdW5jdGlvbiAobmFtZSwgZm4pIHtcbiAgICB1dGlsLm92ZXJ3cml0ZU1ldGhvZCh0aGlzLnByb3RvdHlwZSwgbmFtZSwgZm4pO1xuICB9O1xuXG4gIEFzc2VydGlvbi5vdmVyd3JpdGVDaGFpbmFibGVNZXRob2QgPSBmdW5jdGlvbiAobmFtZSwgZm4sIGNoYWluaW5nQmVoYXZpb3IpIHtcbiAgICB1dGlsLm92ZXJ3cml0ZUNoYWluYWJsZU1ldGhvZCh0aGlzLnByb3RvdHlwZSwgbmFtZSwgZm4sIGNoYWluaW5nQmVoYXZpb3IpO1xuICB9O1xuXG4gIC8qIVxuICAgKiAjIyMgLmFzc2VydChleHByZXNzaW9uLCBtZXNzYWdlLCBuZWdhdGVNZXNzYWdlLCBleHBlY3RlZCwgYWN0dWFsKVxuICAgKlxuICAgKiBFeGVjdXRlcyBhbiBleHByZXNzaW9uIGFuZCBjaGVjayBleHBlY3RhdGlvbnMuIFRocm93cyBBc3NlcnRpb25FcnJvciBmb3IgcmVwb3J0aW5nIGlmIHRlc3QgZG9lc24ndCBwYXNzLlxuICAgKlxuICAgKiBAbmFtZSBhc3NlcnRcbiAgICogQHBhcmFtIHtQaGlsb3NvcGhpY2FsfSBleHByZXNzaW9uIHRvIGJlIHRlc3RlZFxuICAgKiBAcGFyYW0ge1N0cmluZyBvciBGdW5jdGlvbn0gbWVzc2FnZSBvciBmdW5jdGlvbiB0aGF0IHJldHVybnMgbWVzc2FnZSB0byBkaXNwbGF5IGlmIGV4cHJlc3Npb24gZmFpbHNcbiAgICogQHBhcmFtIHtTdHJpbmcgb3IgRnVuY3Rpb259IG5lZ2F0ZWRNZXNzYWdlIG9yIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBuZWdhdGVkTWVzc2FnZSB0byBkaXNwbGF5IGlmIG5lZ2F0ZWQgZXhwcmVzc2lvbiBmYWlsc1xuICAgKiBAcGFyYW0ge01peGVkfSBleHBlY3RlZCB2YWx1ZSAocmVtZW1iZXIgdG8gY2hlY2sgZm9yIG5lZ2F0aW9uKVxuICAgKiBAcGFyYW0ge01peGVkfSBhY3R1YWwgKG9wdGlvbmFsKSB3aWxsIGRlZmF1bHQgdG8gYHRoaXMub2JqYFxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IHNob3dEaWZmIChvcHRpb25hbCkgd2hlbiBzZXQgdG8gYHRydWVgLCBhc3NlcnQgd2lsbCBkaXNwbGF5IGEgZGlmZiBpbiBhZGRpdGlvbiB0byB0aGUgbWVzc2FnZSBpZiBleHByZXNzaW9uIGZhaWxzXG4gICAqIEBhcGkgcHJpdmF0ZVxuICAgKi9cblxuICBBc3NlcnRpb24ucHJvdG90eXBlLmFzc2VydCA9IGZ1bmN0aW9uIChleHByLCBtc2csIG5lZ2F0ZU1zZywgZXhwZWN0ZWQsIF9hY3R1YWwsIHNob3dEaWZmKSB7XG4gICAgdmFyIG9rID0gdXRpbC50ZXN0KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgaWYgKHRydWUgIT09IHNob3dEaWZmKSBzaG93RGlmZiA9IGZhbHNlO1xuICAgIGlmICh0cnVlICE9PSBjb25maWcuc2hvd0RpZmYpIHNob3dEaWZmID0gZmFsc2U7XG5cbiAgICBpZiAoIW9rKSB7XG4gICAgICB2YXIgbXNnID0gdXRpbC5nZXRNZXNzYWdlKHRoaXMsIGFyZ3VtZW50cylcbiAgICAgICAgLCBhY3R1YWwgPSB1dGlsLmdldEFjdHVhbCh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKG1zZywge1xuICAgICAgICAgIGFjdHVhbDogYWN0dWFsXG4gICAgICAgICwgZXhwZWN0ZWQ6IGV4cGVjdGVkXG4gICAgICAgICwgc2hvd0RpZmY6IHNob3dEaWZmXG4gICAgICB9LCAoY29uZmlnLmluY2x1ZGVTdGFjaykgPyB0aGlzLmFzc2VydCA6IGZsYWcodGhpcywgJ3NzZmknKSk7XG4gICAgfVxuICB9O1xuXG4gIC8qIVxuICAgKiAjIyMgLl9vYmpcbiAgICpcbiAgICogUXVpY2sgcmVmZXJlbmNlIHRvIHN0b3JlZCBgYWN0dWFsYCB2YWx1ZSBmb3IgcGx1Z2luIGRldmVsb3BlcnMuXG4gICAqXG4gICAqIEBhcGkgcHJpdmF0ZVxuICAgKi9cblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQXNzZXJ0aW9uLnByb3RvdHlwZSwgJ19vYmonLFxuICAgIHsgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICAgIH1cbiAgICAsIHNldDogZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICBmbGFnKHRoaXMsICdvYmplY3QnLCB2YWwpO1xuICAgICAgfVxuICB9KTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHtcblxuICAvKipcbiAgICogIyMjIGNvbmZpZy5pbmNsdWRlU3RhY2tcbiAgICpcbiAgICogVXNlciBjb25maWd1cmFibGUgcHJvcGVydHksIGluZmx1ZW5jZXMgd2hldGhlciBzdGFjayB0cmFjZVxuICAgKiBpcyBpbmNsdWRlZCBpbiBBc3NlcnRpb24gZXJyb3IgbWVzc2FnZS4gRGVmYXVsdCBvZiBmYWxzZVxuICAgKiBzdXBwcmVzc2VzIHN0YWNrIHRyYWNlIGluIHRoZSBlcnJvciBtZXNzYWdlLlxuICAgKlxuICAgKiAgICAgY2hhaS5jb25maWcuaW5jbHVkZVN0YWNrID0gdHJ1ZTsgIC8vIGVuYWJsZSBzdGFjayBvbiBlcnJvclxuICAgKlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59XG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gICBpbmNsdWRlU3RhY2s6IGZhbHNlLFxuXG4gIC8qKlxuICAgKiAjIyMgY29uZmlnLnNob3dEaWZmXG4gICAqXG4gICAqIFVzZXIgY29uZmlndXJhYmxlIHByb3BlcnR5LCBpbmZsdWVuY2VzIHdoZXRoZXIgb3Igbm90XG4gICAqIHRoZSBgc2hvd0RpZmZgIGZsYWcgc2hvdWxkIGJlIGluY2x1ZGVkIGluIHRoZSB0aHJvd25cbiAgICogQXNzZXJ0aW9uRXJyb3JzLiBgZmFsc2VgIHdpbGwgYWx3YXlzIGJlIGBmYWxzZWA7IGB0cnVlYFxuICAgKiB3aWxsIGJlIHRydWUgd2hlbiB0aGUgYXNzZXJ0aW9uIGhhcyByZXF1ZXN0ZWQgYSBkaWZmXG4gICAqIGJlIHNob3duLlxuICAgKlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59XG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIHNob3dEaWZmOiB0cnVlLFxuXG4gIC8qKlxuICAgKiAjIyMgY29uZmlnLnRydW5jYXRlVGhyZXNob2xkXG4gICAqXG4gICAqIFVzZXIgY29uZmlndXJhYmxlIHByb3BlcnR5LCBzZXRzIGxlbmd0aCB0aHJlc2hvbGQgZm9yIGFjdHVhbCBhbmRcbiAgICogZXhwZWN0ZWQgdmFsdWVzIGluIGFzc2VydGlvbiBlcnJvcnMuIElmIHRoaXMgdGhyZXNob2xkIGlzIGV4Y2VlZGVkLCBmb3JcbiAgICogZXhhbXBsZSBmb3IgbGFyZ2UgZGF0YSBzdHJ1Y3R1cmVzLCB0aGUgdmFsdWUgaXMgcmVwbGFjZWQgd2l0aCBzb21ldGhpbmdcbiAgICogbGlrZSBgWyBBcnJheSgzKSBdYCBvciBgeyBPYmplY3QgKHByb3AxLCBwcm9wMikgfWAuXG4gICAqXG4gICAqIFNldCBpdCB0byB6ZXJvIGlmIHlvdSB3YW50IHRvIGRpc2FibGUgdHJ1bmNhdGluZyBhbHRvZ2V0aGVyLlxuICAgKlxuICAgKiBUaGlzIGlzIGVzcGVjaWFsbHkgdXNlcmZ1bCB3aGVuIGRvaW5nIGFzc2VydGlvbnMgb24gYXJyYXlzOiBoYXZpbmcgdGhpc1xuICAgKiBzZXQgdG8gYSByZWFzb25hYmxlIGxhcmdlIHZhbHVlIG1ha2VzIHRoZSBmYWlsdXJlIG1lc3NhZ2VzIHJlYWRpbHlcbiAgICogaW5zcGVjdGFibGUuXG4gICAqXG4gICAqICAgICBjaGFpLmNvbmZpZy50cnVuY2F0ZVRocmVzaG9sZCA9IDA7ICAvLyBkaXNhYmxlIHRydW5jYXRpbmdcbiAgICpcbiAgICogQHBhcmFtIHtOdW1iZXJ9XG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIHRydW5jYXRlVGhyZXNob2xkOiA0MFxuXG59O1xuIiwiLyohXG4gKiBjaGFpXG4gKiBodHRwOi8vY2hhaWpzLmNvbVxuICogQ29weXJpZ2h0KGMpIDIwMTEtMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGNoYWksIF8pIHtcbiAgdmFyIEFzc2VydGlvbiA9IGNoYWkuQXNzZXJ0aW9uXG4gICAgLCB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdcbiAgICAsIGZsYWcgPSBfLmZsYWc7XG5cbiAgLyoqXG4gICAqICMjIyBMYW5ndWFnZSBDaGFpbnNcbiAgICpcbiAgICogVGhlIGZvbGxvd2luZyBhcmUgcHJvdmlkZWQgYXMgY2hhaW5hYmxlIGdldHRlcnMgdG9cbiAgICogaW1wcm92ZSB0aGUgcmVhZGFiaWxpdHkgb2YgeW91ciBhc3NlcnRpb25zLiBUaGV5XG4gICAqIGRvIG5vdCBwcm92aWRlIHRlc3RpbmcgY2FwYWJpbGl0aWVzIHVubGVzcyB0aGV5XG4gICAqIGhhdmUgYmVlbiBvdmVyd3JpdHRlbiBieSBhIHBsdWdpbi5cbiAgICpcbiAgICogKipDaGFpbnMqKlxuICAgKlxuICAgKiAtIHRvXG4gICAqIC0gYmVcbiAgICogLSBiZWVuXG4gICAqIC0gaXNcbiAgICogLSB0aGF0XG4gICAqIC0gd2hpY2hcbiAgICogLSBhbmRcbiAgICogLSBoYXNcbiAgICogLSBoYXZlXG4gICAqIC0gd2l0aFxuICAgKiAtIGF0XG4gICAqIC0gb2ZcbiAgICogLSBzYW1lXG4gICAqXG4gICAqIEBuYW1lIGxhbmd1YWdlIGNoYWluc1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBbICd0bycsICdiZScsICdiZWVuJ1xuICAsICdpcycsICdhbmQnLCAnaGFzJywgJ2hhdmUnXG4gICwgJ3dpdGgnLCAndGhhdCcsICd3aGljaCcsICdhdCdcbiAgLCAnb2YnLCAnc2FtZScgXS5mb3JFYWNoKGZ1bmN0aW9uIChjaGFpbikge1xuICAgIEFzc2VydGlvbi5hZGRQcm9wZXJ0eShjaGFpbiwgZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdFxuICAgKlxuICAgKiBOZWdhdGVzIGFueSBvZiBhc3NlcnRpb25zIGZvbGxvd2luZyBpbiB0aGUgY2hhaW4uXG4gICAqXG4gICAqICAgICBleHBlY3QoZm9vKS50by5ub3QuZXF1YWwoJ2JhcicpO1xuICAgKiAgICAgZXhwZWN0KGdvb2RGbikudG8ubm90LnRocm93KEVycm9yKTtcbiAgICogICAgIGV4cGVjdCh7IGZvbzogJ2JheicgfSkudG8uaGF2ZS5wcm9wZXJ0eSgnZm9vJylcbiAgICogICAgICAgLmFuZC5ub3QuZXF1YWwoJ2JhcicpO1xuICAgKlxuICAgKiBAbmFtZSBub3RcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdub3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgZmxhZyh0aGlzLCAnbmVnYXRlJywgdHJ1ZSk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLmRlZXBcbiAgICpcbiAgICogU2V0cyB0aGUgYGRlZXBgIGZsYWcsIGxhdGVyIHVzZWQgYnkgdGhlIGBlcXVhbGAgYW5kXG4gICAqIGBwcm9wZXJ0eWAgYXNzZXJ0aW9ucy5cbiAgICpcbiAgICogICAgIGV4cGVjdChmb28pLnRvLmRlZXAuZXF1YWwoeyBiYXI6ICdiYXonIH0pO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiB7IGJhcjogeyBiYXo6ICdxdXV4JyB9IH0gfSlcbiAgICogICAgICAgLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eSgnZm9vLmJhci5iYXonLCAncXV1eCcpO1xuICAgKlxuICAgKiBgLmRlZXAucHJvcGVydHlgIHNwZWNpYWwgY2hhcmFjdGVycyBjYW4gYmUgZXNjYXBlZFxuICAgKiBieSBhZGRpbmcgdHdvIHNsYXNoZXMgYmVmb3JlIHRoZSBgLmAgb3IgYFtdYC5cbiAgICpcbiAgICogICAgIHZhciBkZWVwQ3NzID0geyAnLmxpbmsnOiB7ICdbdGFyZ2V0XSc6IDQyIH19O1xuICAgKiAgICAgZXhwZWN0KGRlZXBDc3MpLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eSgnXFxcXC5saW5rLlxcXFxbdGFyZ2V0XFxcXF0nLCA0Mik7XG4gICAqXG4gICAqIEBuYW1lIGRlZXBcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdkZWVwJywgZnVuY3Rpb24gKCkge1xuICAgIGZsYWcodGhpcywgJ2RlZXAnLCB0cnVlKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAuYW55XG4gICAqXG4gICAqIFNldHMgdGhlIGBhbnlgIGZsYWcsIChvcHBvc2l0ZSBvZiB0aGUgYGFsbGAgZmxhZylcbiAgICogbGF0ZXIgdXNlZCBpbiB0aGUgYGtleXNgIGFzc2VydGlvbi4gXG4gICAqXG4gICAqICAgICBleHBlY3QoZm9vKS50by5oYXZlLmFueS5rZXlzKCdiYXInLCAnYmF6Jyk7XG4gICAqXG4gICAqIEBuYW1lIGFueVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkoJ2FueScsIGZ1bmN0aW9uICgpIHtcbiAgICBmbGFnKHRoaXMsICdhbnknLCB0cnVlKTtcbiAgICBmbGFnKHRoaXMsICdhbGwnLCBmYWxzZSlcbiAgfSk7XG5cblxuICAvKipcbiAgICogIyMjIC5hbGxcbiAgICpcbiAgICogU2V0cyB0aGUgYGFsbGAgZmxhZyAob3Bwb3NpdGUgb2YgdGhlIGBhbnlgIGZsYWcpIFxuICAgKiBsYXRlciB1c2VkIGJ5IHRoZSBga2V5c2AgYXNzZXJ0aW9uLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KGZvbykudG8uaGF2ZS5hbGwua2V5cygnYmFyJywgJ2JheicpO1xuICAgKlxuICAgKiBAbmFtZSBhbGxcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdhbGwnLCBmdW5jdGlvbiAoKSB7XG4gICAgZmxhZyh0aGlzLCAnYWxsJywgdHJ1ZSk7XG4gICAgZmxhZyh0aGlzLCAnYW55JywgZmFsc2UpO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5hKHR5cGUpXG4gICAqXG4gICAqIFRoZSBgYWAgYW5kIGBhbmAgYXNzZXJ0aW9ucyBhcmUgYWxpYXNlcyB0aGF0IGNhbiBiZVxuICAgKiB1c2VkIGVpdGhlciBhcyBsYW5ndWFnZSBjaGFpbnMgb3IgdG8gYXNzZXJ0IGEgdmFsdWUnc1xuICAgKiB0eXBlLlxuICAgKlxuICAgKiAgICAgLy8gdHlwZW9mXG4gICAqICAgICBleHBlY3QoJ3Rlc3QnKS50by5iZS5hKCdzdHJpbmcnKTtcbiAgICogICAgIGV4cGVjdCh7IGZvbzogJ2JhcicgfSkudG8uYmUuYW4oJ29iamVjdCcpO1xuICAgKiAgICAgZXhwZWN0KG51bGwpLnRvLmJlLmEoJ251bGwnKTtcbiAgICogICAgIGV4cGVjdCh1bmRlZmluZWQpLnRvLmJlLmFuKCd1bmRlZmluZWQnKTtcbiAgICpcbiAgICogICAgIC8vIGxhbmd1YWdlIGNoYWluXG4gICAqICAgICBleHBlY3QoZm9vKS50by5iZS5hbi5pbnN0YW5jZW9mKEZvbyk7XG4gICAqXG4gICAqIEBuYW1lIGFcbiAgICogQGFsaWFzIGFuXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gYW4gKHR5cGUsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHR5cGUgPSB0eXBlLnRvTG93ZXJDYXNlKCk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpXG4gICAgICAsIGFydGljbGUgPSB+WyAnYScsICdlJywgJ2knLCAnbycsICd1JyBdLmluZGV4T2YodHlwZS5jaGFyQXQoMCkpID8gJ2FuICcgOiAnYSAnO1xuXG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIHR5cGUgPT09IF8udHlwZShvYmopXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlICcgKyBhcnRpY2xlICsgdHlwZVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSBub3QgdG8gYmUgJyArIGFydGljbGUgKyB0eXBlXG4gICAgKTtcbiAgfVxuXG4gIEFzc2VydGlvbi5hZGRDaGFpbmFibGVNZXRob2QoJ2FuJywgYW4pO1xuICBBc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdhJywgYW4pO1xuXG4gIC8qKlxuICAgKiAjIyMgLmluY2x1ZGUodmFsdWUpXG4gICAqXG4gICAqIFRoZSBgaW5jbHVkZWAgYW5kIGBjb250YWluYCBhc3NlcnRpb25zIGNhbiBiZSB1c2VkIGFzIGVpdGhlciBwcm9wZXJ0eVxuICAgKiBiYXNlZCBsYW5ndWFnZSBjaGFpbnMgb3IgYXMgbWV0aG9kcyB0byBhc3NlcnQgdGhlIGluY2x1c2lvbiBvZiBhbiBvYmplY3RcbiAgICogaW4gYW4gYXJyYXkgb3IgYSBzdWJzdHJpbmcgaW4gYSBzdHJpbmcuIFdoZW4gdXNlZCBhcyBsYW5ndWFnZSBjaGFpbnMsXG4gICAqIHRoZXkgdG9nZ2xlIHRoZSBgY29udGFpbnNgIGZsYWcgZm9yIHRoZSBga2V5c2AgYXNzZXJ0aW9uLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KFsxLDIsM10pLnRvLmluY2x1ZGUoMik7XG4gICAqICAgICBleHBlY3QoJ2Zvb2JhcicpLnRvLmNvbnRhaW4oJ2ZvbycpO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAnYmFyJywgaGVsbG86ICd1bml2ZXJzZScgfSkudG8uaW5jbHVkZS5rZXlzKCdmb28nKTtcbiAgICpcbiAgICogQG5hbWUgaW5jbHVkZVxuICAgKiBAYWxpYXMgY29udGFpblxuICAgKiBAYWxpYXMgaW5jbHVkZXNcbiAgICogQGFsaWFzIGNvbnRhaW5zXG4gICAqIEBwYXJhbSB7T2JqZWN0fFN0cmluZ3xOdW1iZXJ9IG9ialxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGluY2x1ZGVDaGFpbmluZ0JlaGF2aW9yICgpIHtcbiAgICBmbGFnKHRoaXMsICdjb250YWlucycsIHRydWUpO1xuICB9XG5cbiAgZnVuY3Rpb24gaW5jbHVkZSAodmFsLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgdmFyIGV4cGVjdGVkID0gZmFsc2U7XG4gICAgaWYgKF8udHlwZShvYmopID09PSAnYXJyYXknICYmIF8udHlwZSh2YWwpID09PSAnb2JqZWN0Jykge1xuICAgICAgZm9yICh2YXIgaSBpbiBvYmopIHtcbiAgICAgICAgaWYgKF8uZXFsKG9ialtpXSwgdmFsKSkge1xuICAgICAgICAgIGV4cGVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoXy50eXBlKHZhbCkgPT09ICdvYmplY3QnKSB7XG4gICAgICBpZiAoIWZsYWcodGhpcywgJ25lZ2F0ZScpKSB7XG4gICAgICAgIGZvciAodmFyIGsgaW4gdmFsKSBuZXcgQXNzZXJ0aW9uKG9iaikucHJvcGVydHkoaywgdmFsW2tdKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdmFyIHN1YnNldCA9IHt9O1xuICAgICAgZm9yICh2YXIgayBpbiB2YWwpIHN1YnNldFtrXSA9IG9ialtrXTtcbiAgICAgIGV4cGVjdGVkID0gXy5lcWwoc3Vic2V0LCB2YWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICBleHBlY3RlZCA9IG9iaiAmJiB+b2JqLmluZGV4T2YodmFsKTtcbiAgICB9XG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIGV4cGVjdGVkXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGluY2x1ZGUgJyArIF8uaW5zcGVjdCh2YWwpXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBpbmNsdWRlICcgKyBfLmluc3BlY3QodmFsKSk7XG4gIH1cblxuICBBc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdpbmNsdWRlJywgaW5jbHVkZSwgaW5jbHVkZUNoYWluaW5nQmVoYXZpb3IpO1xuICBBc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdjb250YWluJywgaW5jbHVkZSwgaW5jbHVkZUNoYWluaW5nQmVoYXZpb3IpO1xuICBBc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdjb250YWlucycsIGluY2x1ZGUsIGluY2x1ZGVDaGFpbmluZ0JlaGF2aW9yKTtcbiAgQXNzZXJ0aW9uLmFkZENoYWluYWJsZU1ldGhvZCgnaW5jbHVkZXMnLCBpbmNsdWRlLCBpbmNsdWRlQ2hhaW5pbmdCZWhhdmlvcik7XG5cbiAgLyoqXG4gICAqICMjIyAub2tcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgdHJ1dGh5LlxuICAgKlxuICAgKiAgICAgZXhwZWN0KCdldmVydGhpbmcnKS50by5iZS5vaztcbiAgICogICAgIGV4cGVjdCgxKS50by5iZS5vaztcbiAgICogICAgIGV4cGVjdChmYWxzZSkudG8ubm90LmJlLm9rO1xuICAgKiAgICAgZXhwZWN0KHVuZGVmaW5lZCkudG8ubm90LmJlLm9rO1xuICAgKiAgICAgZXhwZWN0KG51bGwpLnRvLm5vdC5iZS5vaztcbiAgICpcbiAgICogQG5hbWUgb2tcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdvaycsIGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgdHJ1dGh5J1xuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBmYWxzeScpO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC50cnVlXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGB0cnVlYC5cbiAgICpcbiAgICogICAgIGV4cGVjdCh0cnVlKS50by5iZS50cnVlO1xuICAgKiAgICAgZXhwZWN0KDEpLnRvLm5vdC5iZS50cnVlO1xuICAgKlxuICAgKiBAbmFtZSB0cnVlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgndHJ1ZScsIGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgdHJ1ZSA9PT0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgdHJ1ZSdcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgZmFsc2UnXG4gICAgICAsIHRoaXMubmVnYXRlID8gZmFsc2UgOiB0cnVlXG4gICAgKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAuZmFsc2VcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgYGZhbHNlYC5cbiAgICpcbiAgICogICAgIGV4cGVjdChmYWxzZSkudG8uYmUuZmFsc2U7XG4gICAqICAgICBleHBlY3QoMCkudG8ubm90LmJlLmZhbHNlO1xuICAgKlxuICAgKiBAbmFtZSBmYWxzZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkoJ2ZhbHNlJywgZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBmYWxzZSA9PT0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgZmFsc2UnXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIHRydWUnXG4gICAgICAsIHRoaXMubmVnYXRlID8gdHJ1ZSA6IGZhbHNlXG4gICAgKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAubnVsbFxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBgbnVsbGAuXG4gICAqXG4gICAqICAgICBleHBlY3QobnVsbCkudG8uYmUubnVsbDtcbiAgICogICAgIGV4cGVjdCh1bmRlZmluZWQpLm5vdC50by5iZS5udWxsO1xuICAgKlxuICAgKiBAbmFtZSBudWxsXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnbnVsbCcsIGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgbnVsbCA9PT0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgbnVsbCdcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gbm90IHRvIGJlIG51bGwnXG4gICAgKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAudW5kZWZpbmVkXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGB1bmRlZmluZWRgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KHVuZGVmaW5lZCkudG8uYmUudW5kZWZpbmVkO1xuICAgKiAgICAgZXhwZWN0KG51bGwpLnRvLm5vdC5iZS51bmRlZmluZWQ7XG4gICAqXG4gICAqIEBuYW1lIHVuZGVmaW5lZFxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkoJ3VuZGVmaW5lZCcsIGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgdW5kZWZpbmVkID09PSBmbGFnKHRoaXMsICdvYmplY3QnKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSB1bmRlZmluZWQnXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IG5vdCB0byBiZSB1bmRlZmluZWQnXG4gICAgKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAuZXhpc3RcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgbmVpdGhlciBgbnVsbGAgbm9yIGB1bmRlZmluZWRgLlxuICAgKlxuICAgKiAgICAgdmFyIGZvbyA9ICdoaSdcbiAgICogICAgICAgLCBiYXIgPSBudWxsXG4gICAqICAgICAgICwgYmF6O1xuICAgKlxuICAgKiAgICAgZXhwZWN0KGZvbykudG8uZXhpc3Q7XG4gICAqICAgICBleHBlY3QoYmFyKS50by5ub3QuZXhpc3Q7XG4gICAqICAgICBleHBlY3QoYmF6KS50by5ub3QuZXhpc3Q7XG4gICAqXG4gICAqIEBuYW1lIGV4aXN0XG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnZXhpc3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIG51bGwgIT0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gZXhpc3QnXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBleGlzdCdcbiAgICApO1xuICB9KTtcblxuXG4gIC8qKlxuICAgKiAjIyMgLmVtcHR5XG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0J3MgbGVuZ3RoIGlzIGAwYC4gRm9yIGFycmF5cyBhbmQgc3RyaW5ncywgaXQgY2hlY2tzXG4gICAqIHRoZSBgbGVuZ3RoYCBwcm9wZXJ0eS4gRm9yIG9iamVjdHMsIGl0IGdldHMgdGhlIGNvdW50IG9mXG4gICAqIGVudW1lcmFibGUga2V5cy5cbiAgICpcbiAgICogICAgIGV4cGVjdChbXSkudG8uYmUuZW1wdHk7XG4gICAqICAgICBleHBlY3QoJycpLnRvLmJlLmVtcHR5O1xuICAgKiAgICAgZXhwZWN0KHt9KS50by5iZS5lbXB0eTtcbiAgICpcbiAgICogQG5hbWUgZW1wdHlcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdlbXB0eScsIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgZXhwZWN0ZWQgPSBvYmo7XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopIHx8ICdzdHJpbmcnID09PSB0eXBlb2Ygb2JqZWN0KSB7XG4gICAgICBleHBlY3RlZCA9IG9iai5sZW5ndGg7XG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygb2JqID09PSAnb2JqZWN0Jykge1xuICAgICAgZXhwZWN0ZWQgPSBPYmplY3Qua2V5cyhvYmopLmxlbmd0aDtcbiAgICB9XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgIWV4cGVjdGVkXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGVtcHR5J1xuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSBub3QgdG8gYmUgZW1wdHknXG4gICAgKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAuYXJndW1lbnRzXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGFuIGFyZ3VtZW50cyBvYmplY3QuXG4gICAqXG4gICAqICAgICBmdW5jdGlvbiB0ZXN0ICgpIHtcbiAgICogICAgICAgZXhwZWN0KGFyZ3VtZW50cykudG8uYmUuYXJndW1lbnRzO1xuICAgKiAgICAgfVxuICAgKlxuICAgKiBAbmFtZSBhcmd1bWVudHNcbiAgICogQGFsaWFzIEFyZ3VtZW50c1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBjaGVja0FyZ3VtZW50cyAoKSB7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpXG4gICAgICAsIHR5cGUgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKTtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgJ1tvYmplY3QgQXJndW1lbnRzXScgPT09IHR5cGVcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYXJndW1lbnRzIGJ1dCBnb3QgJyArIHR5cGVcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGJlIGFyZ3VtZW50cydcbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdhcmd1bWVudHMnLCBjaGVja0FyZ3VtZW50cyk7XG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnQXJndW1lbnRzJywgY2hlY2tBcmd1bWVudHMpO1xuXG4gIC8qKlxuICAgKiAjIyMgLmVxdWFsKHZhbHVlKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBzdHJpY3RseSBlcXVhbCAoYD09PWApIHRvIGB2YWx1ZWAuXG4gICAqIEFsdGVybmF0ZWx5LCBpZiB0aGUgYGRlZXBgIGZsYWcgaXMgc2V0LCBhc3NlcnRzIHRoYXRcbiAgICogdGhlIHRhcmdldCBpcyBkZWVwbHkgZXF1YWwgdG8gYHZhbHVlYC5cbiAgICpcbiAgICogICAgIGV4cGVjdCgnaGVsbG8nKS50by5lcXVhbCgnaGVsbG8nKTtcbiAgICogICAgIGV4cGVjdCg0MikudG8uZXF1YWwoNDIpO1xuICAgKiAgICAgZXhwZWN0KDEpLnRvLm5vdC5lcXVhbCh0cnVlKTtcbiAgICogICAgIGV4cGVjdCh7IGZvbzogJ2JhcicgfSkudG8ubm90LmVxdWFsKHsgZm9vOiAnYmFyJyB9KTtcbiAgICogICAgIGV4cGVjdCh7IGZvbzogJ2JhcicgfSkudG8uZGVlcC5lcXVhbCh7IGZvbzogJ2JhcicgfSk7XG4gICAqXG4gICAqIEBuYW1lIGVxdWFsXG4gICAqIEBhbGlhcyBlcXVhbHNcbiAgICogQGFsaWFzIGVxXG4gICAqIEBhbGlhcyBkZWVwLmVxdWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gYXNzZXJ0RXF1YWwgKHZhbCwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIGlmIChmbGFnKHRoaXMsICdkZWVwJykpIHtcbiAgICAgIHJldHVybiB0aGlzLmVxbCh2YWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICB2YWwgPT09IG9ialxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGVxdWFsICN7ZXhwfSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgZXF1YWwgI3tleHB9J1xuICAgICAgICAsIHZhbFxuICAgICAgICAsIHRoaXMuX29ialxuICAgICAgICAsIHRydWVcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZXF1YWwnLCBhc3NlcnRFcXVhbCk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2VxdWFscycsIGFzc2VydEVxdWFsKTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZXEnLCBhc3NlcnRFcXVhbCk7XG5cbiAgLyoqXG4gICAqICMjIyAuZXFsKHZhbHVlKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBkZWVwbHkgZXF1YWwgdG8gYHZhbHVlYC5cbiAgICpcbiAgICogICAgIGV4cGVjdCh7IGZvbzogJ2JhcicgfSkudG8uZXFsKHsgZm9vOiAnYmFyJyB9KTtcbiAgICogICAgIGV4cGVjdChbIDEsIDIsIDMgXSkudG8uZXFsKFsgMSwgMiwgMyBdKTtcbiAgICpcbiAgICogQG5hbWUgZXFsXG4gICAqIEBhbGlhcyBlcWxzXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gYXNzZXJ0RXFsKG9iaiwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIF8uZXFsKG9iaiwgZmxhZyh0aGlzLCAnb2JqZWN0JykpXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGRlZXBseSBlcXVhbCAje2V4cH0nXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBkZWVwbHkgZXF1YWwgI3tleHB9J1xuICAgICAgLCBvYmpcbiAgICAgICwgdGhpcy5fb2JqXG4gICAgICAsIHRydWVcbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZXFsJywgYXNzZXJ0RXFsKTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZXFscycsIGFzc2VydEVxbCk7XG5cbiAgLyoqXG4gICAqICMjIyAuYWJvdmUodmFsdWUpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGdyZWF0ZXIgdGhhbiBgdmFsdWVgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KDEwKS50by5iZS5hYm92ZSg1KTtcbiAgICpcbiAgICogQ2FuIGFsc28gYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIGBsZW5ndGhgIHRvXG4gICAqIGFzc2VydCBhIG1pbmltdW0gbGVuZ3RoLiBUaGUgYmVuZWZpdCBiZWluZyBhXG4gICAqIG1vcmUgaW5mb3JtYXRpdmUgZXJyb3IgbWVzc2FnZSB0aGFuIGlmIHRoZSBsZW5ndGhcbiAgICogd2FzIHN1cHBsaWVkIGRpcmVjdGx5LlxuICAgKlxuICAgKiAgICAgZXhwZWN0KCdmb28nKS50by5oYXZlLmxlbmd0aC5hYm92ZSgyKTtcbiAgICogICAgIGV4cGVjdChbIDEsIDIsIDMgXSkudG8uaGF2ZS5sZW5ndGguYWJvdmUoMik7XG4gICAqXG4gICAqIEBuYW1lIGFib3ZlXG4gICAqIEBhbGlhcyBndFxuICAgKiBAYWxpYXMgZ3JlYXRlclRoYW5cbiAgICogQHBhcmFtIHtOdW1iZXJ9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gYXNzZXJ0QWJvdmUgKG4sIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICBpZiAoZmxhZyh0aGlzLCAnZG9MZW5ndGgnKSkge1xuICAgICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5wcm9wZXJ0eSgnbGVuZ3RoJyk7XG4gICAgICB2YXIgbGVuID0gb2JqLmxlbmd0aDtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIGxlbiA+IG5cbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBoYXZlIGEgbGVuZ3RoIGFib3ZlICN7ZXhwfSBidXQgZ290ICN7YWN0fSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgaGF2ZSBhIGxlbmd0aCBhYm92ZSAje2V4cH0nXG4gICAgICAgICwgblxuICAgICAgICAsIGxlblxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgb2JqID4gblxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGFib3ZlICcgKyBuXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYXQgbW9zdCAnICsgblxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdhYm92ZScsIGFzc2VydEFib3ZlKTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZ3QnLCBhc3NlcnRBYm92ZSk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2dyZWF0ZXJUaGFuJywgYXNzZXJ0QWJvdmUpO1xuXG4gIC8qKlxuICAgKiAjIyMgLmxlYXN0KHZhbHVlKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYHZhbHVlYC5cbiAgICpcbiAgICogICAgIGV4cGVjdCgxMCkudG8uYmUuYXQubGVhc3QoMTApO1xuICAgKlxuICAgKiBDYW4gYWxzbyBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGggYGxlbmd0aGAgdG9cbiAgICogYXNzZXJ0IGEgbWluaW11bSBsZW5ndGguIFRoZSBiZW5lZml0IGJlaW5nIGFcbiAgICogbW9yZSBpbmZvcm1hdGl2ZSBlcnJvciBtZXNzYWdlIHRoYW4gaWYgdGhlIGxlbmd0aFxuICAgKiB3YXMgc3VwcGxpZWQgZGlyZWN0bHkuXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2ZvbycpLnRvLmhhdmUubGVuZ3RoLm9mLmF0LmxlYXN0KDIpO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5oYXZlLmxlbmd0aC5vZi5hdC5sZWFzdCgzKTtcbiAgICpcbiAgICogQG5hbWUgbGVhc3RcbiAgICogQGFsaWFzIGd0ZVxuICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRMZWFzdCAobiwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIGlmIChmbGFnKHRoaXMsICdkb0xlbmd0aCcpKSB7XG4gICAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5oYXZlLnByb3BlcnR5KCdsZW5ndGgnKTtcbiAgICAgIHZhciBsZW4gPSBvYmoubGVuZ3RoO1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgbGVuID49IG5cbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBoYXZlIGEgbGVuZ3RoIGF0IGxlYXN0ICN7ZXhwfSBidXQgZ290ICN7YWN0fSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBoYXZlIGEgbGVuZ3RoIGJlbG93ICN7ZXhwfSdcbiAgICAgICAgLCBuXG4gICAgICAgICwgbGVuXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICBvYmogPj0gblxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGF0IGxlYXN0ICcgKyBuXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYmVsb3cgJyArIG5cbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnbGVhc3QnLCBhc3NlcnRMZWFzdCk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2d0ZScsIGFzc2VydExlYXN0KTtcblxuICAvKipcbiAgICogIyMjIC5iZWxvdyh2YWx1ZSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgbGVzcyB0aGFuIGB2YWx1ZWAuXG4gICAqXG4gICAqICAgICBleHBlY3QoNSkudG8uYmUuYmVsb3coMTApO1xuICAgKlxuICAgKiBDYW4gYWxzbyBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGggYGxlbmd0aGAgdG9cbiAgICogYXNzZXJ0IGEgbWF4aW11bSBsZW5ndGguIFRoZSBiZW5lZml0IGJlaW5nIGFcbiAgICogbW9yZSBpbmZvcm1hdGl2ZSBlcnJvciBtZXNzYWdlIHRoYW4gaWYgdGhlIGxlbmd0aFxuICAgKiB3YXMgc3VwcGxpZWQgZGlyZWN0bHkuXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2ZvbycpLnRvLmhhdmUubGVuZ3RoLmJlbG93KDQpO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5oYXZlLmxlbmd0aC5iZWxvdyg0KTtcbiAgICpcbiAgICogQG5hbWUgYmVsb3dcbiAgICogQGFsaWFzIGx0XG4gICAqIEBhbGlhcyBsZXNzVGhhblxuICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRCZWxvdyAobiwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIGlmIChmbGFnKHRoaXMsICdkb0xlbmd0aCcpKSB7XG4gICAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5oYXZlLnByb3BlcnR5KCdsZW5ndGgnKTtcbiAgICAgIHZhciBsZW4gPSBvYmoubGVuZ3RoO1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgbGVuIDwgblxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGhhdmUgYSBsZW5ndGggYmVsb3cgI3tleHB9IGJ1dCBnb3QgI3thY3R9J1xuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBoYXZlIGEgbGVuZ3RoIGJlbG93ICN7ZXhwfSdcbiAgICAgICAgLCBuXG4gICAgICAgICwgbGVuXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICBvYmogPCBuXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYmVsb3cgJyArIG5cbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBhdCBsZWFzdCAnICsgblxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdiZWxvdycsIGFzc2VydEJlbG93KTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnbHQnLCBhc3NlcnRCZWxvdyk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2xlc3NUaGFuJywgYXNzZXJ0QmVsb3cpO1xuXG4gIC8qKlxuICAgKiAjIyMgLm1vc3QodmFsdWUpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGxlc3MgdGhhbiBvciBlcXVhbCB0byBgdmFsdWVgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KDUpLnRvLmJlLmF0Lm1vc3QoNSk7XG4gICAqXG4gICAqIENhbiBhbHNvIGJlIHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCBgbGVuZ3RoYCB0b1xuICAgKiBhc3NlcnQgYSBtYXhpbXVtIGxlbmd0aC4gVGhlIGJlbmVmaXQgYmVpbmcgYVxuICAgKiBtb3JlIGluZm9ybWF0aXZlIGVycm9yIG1lc3NhZ2UgdGhhbiBpZiB0aGUgbGVuZ3RoXG4gICAqIHdhcyBzdXBwbGllZCBkaXJlY3RseS5cbiAgICpcbiAgICogICAgIGV4cGVjdCgnZm9vJykudG8uaGF2ZS5sZW5ndGgub2YuYXQubW9zdCg0KTtcbiAgICogICAgIGV4cGVjdChbIDEsIDIsIDMgXSkudG8uaGF2ZS5sZW5ndGgub2YuYXQubW9zdCgzKTtcbiAgICpcbiAgICogQG5hbWUgbW9zdFxuICAgKiBAYWxpYXMgbHRlXG4gICAqIEBwYXJhbSB7TnVtYmVyfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGFzc2VydE1vc3QgKG4sIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICBpZiAoZmxhZyh0aGlzLCAnZG9MZW5ndGgnKSkge1xuICAgICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5wcm9wZXJ0eSgnbGVuZ3RoJyk7XG4gICAgICB2YXIgbGVuID0gb2JqLmxlbmd0aDtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIGxlbiA8PSBuXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBhIGxlbmd0aCBhdCBtb3N0ICN7ZXhwfSBidXQgZ290ICN7YWN0fSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBoYXZlIGEgbGVuZ3RoIGFib3ZlICN7ZXhwfSdcbiAgICAgICAgLCBuXG4gICAgICAgICwgbGVuXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICBvYmogPD0gblxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGF0IG1vc3QgJyArIG5cbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBhYm92ZSAnICsgblxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdtb3N0JywgYXNzZXJ0TW9zdCk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2x0ZScsIGFzc2VydE1vc3QpO1xuXG4gIC8qKlxuICAgKiAjIyMgLndpdGhpbihzdGFydCwgZmluaXNoKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyB3aXRoaW4gYSByYW5nZS5cbiAgICpcbiAgICogICAgIGV4cGVjdCg3KS50by5iZS53aXRoaW4oNSwxMCk7XG4gICAqXG4gICAqIENhbiBhbHNvIGJlIHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCBgbGVuZ3RoYCB0b1xuICAgKiBhc3NlcnQgYSBsZW5ndGggcmFuZ2UuIFRoZSBiZW5lZml0IGJlaW5nIGFcbiAgICogbW9yZSBpbmZvcm1hdGl2ZSBlcnJvciBtZXNzYWdlIHRoYW4gaWYgdGhlIGxlbmd0aFxuICAgKiB3YXMgc3VwcGxpZWQgZGlyZWN0bHkuXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2ZvbycpLnRvLmhhdmUubGVuZ3RoLndpdGhpbigyLDQpO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5oYXZlLmxlbmd0aC53aXRoaW4oMiw0KTtcbiAgICpcbiAgICogQG5hbWUgd2l0aGluXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBzdGFydCBsb3dlcmJvdW5kIGluY2x1c2l2ZVxuICAgKiBAcGFyYW0ge051bWJlcn0gZmluaXNoIHVwcGVyYm91bmQgaW5jbHVzaXZlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnd2l0aGluJywgZnVuY3Rpb24gKHN0YXJ0LCBmaW5pc2gsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKVxuICAgICAgLCByYW5nZSA9IHN0YXJ0ICsgJy4uJyArIGZpbmlzaDtcbiAgICBpZiAoZmxhZyh0aGlzLCAnZG9MZW5ndGgnKSkge1xuICAgICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5wcm9wZXJ0eSgnbGVuZ3RoJyk7XG4gICAgICB2YXIgbGVuID0gb2JqLmxlbmd0aDtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIGxlbiA+PSBzdGFydCAmJiBsZW4gPD0gZmluaXNoXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBhIGxlbmd0aCB3aXRoaW4gJyArIHJhbmdlXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGhhdmUgYSBsZW5ndGggd2l0aGluICcgKyByYW5nZVxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgb2JqID49IHN0YXJ0ICYmIG9iaiA8PSBmaW5pc2hcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSB3aXRoaW4gJyArIHJhbmdlXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGJlIHdpdGhpbiAnICsgcmFuZ2VcbiAgICAgICk7XG4gICAgfVxuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5pbnN0YW5jZW9mKGNvbnN0cnVjdG9yKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBhbiBpbnN0YW5jZSBvZiBgY29uc3RydWN0b3JgLlxuICAgKlxuICAgKiAgICAgdmFyIFRlYSA9IGZ1bmN0aW9uIChuYW1lKSB7IHRoaXMubmFtZSA9IG5hbWU7IH1cbiAgICogICAgICAgLCBDaGFpID0gbmV3IFRlYSgnY2hhaScpO1xuICAgKlxuICAgKiAgICAgZXhwZWN0KENoYWkpLnRvLmJlLmFuLmluc3RhbmNlb2YoVGVhKTtcbiAgICogICAgIGV4cGVjdChbIDEsIDIsIDMgXSkudG8uYmUuaW5zdGFuY2VvZihBcnJheSk7XG4gICAqXG4gICAqIEBuYW1lIGluc3RhbmNlb2ZcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYWxpYXMgaW5zdGFuY2VPZlxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRJbnN0YW5jZU9mIChjb25zdHJ1Y3RvciwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG5hbWUgPSBfLmdldE5hbWUoY29uc3RydWN0b3IpO1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBmbGFnKHRoaXMsICdvYmplY3QnKSBpbnN0YW5jZW9mIGNvbnN0cnVjdG9yXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGFuIGluc3RhbmNlIG9mICcgKyBuYW1lXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBiZSBhbiBpbnN0YW5jZSBvZiAnICsgbmFtZVxuICAgICk7XG4gIH07XG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnaW5zdGFuY2VvZicsIGFzc2VydEluc3RhbmNlT2YpO1xuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdpbnN0YW5jZU9mJywgYXNzZXJ0SW5zdGFuY2VPZik7XG5cbiAgLyoqXG4gICAqICMjIyAucHJvcGVydHkobmFtZSwgW3ZhbHVlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaGFzIGEgcHJvcGVydHkgYG5hbWVgLCBvcHRpb25hbGx5IGFzc2VydGluZyB0aGF0XG4gICAqIHRoZSB2YWx1ZSBvZiB0aGF0IHByb3BlcnR5IGlzIHN0cmljdGx5IGVxdWFsIHRvICBgdmFsdWVgLlxuICAgKiBJZiB0aGUgYGRlZXBgIGZsYWcgaXMgc2V0LCB5b3UgY2FuIHVzZSBkb3QtIGFuZCBicmFja2V0LW5vdGF0aW9uIGZvciBkZWVwXG4gICAqIHJlZmVyZW5jZXMgaW50byBvYmplY3RzIGFuZCBhcnJheXMuXG4gICAqXG4gICAqICAgICAvLyBzaW1wbGUgcmVmZXJlbmNpbmdcbiAgICogICAgIHZhciBvYmogPSB7IGZvbzogJ2JhcicgfTtcbiAgICogICAgIGV4cGVjdChvYmopLnRvLmhhdmUucHJvcGVydHkoJ2ZvbycpO1xuICAgKiAgICAgZXhwZWN0KG9iaikudG8uaGF2ZS5wcm9wZXJ0eSgnZm9vJywgJ2JhcicpO1xuICAgKlxuICAgKiAgICAgLy8gZGVlcCByZWZlcmVuY2luZ1xuICAgKiAgICAgdmFyIGRlZXBPYmogPSB7XG4gICAqICAgICAgICAgZ3JlZW46IHsgdGVhOiAnbWF0Y2hhJyB9XG4gICAqICAgICAgICwgdGVhczogWyAnY2hhaScsICdtYXRjaGEnLCB7IHRlYTogJ2tvbmFjaGEnIH0gXVxuICAgKiAgICAgfTtcbiAgICogXG4gICAqICAgICBleHBlY3QoZGVlcE9iaikudG8uaGF2ZS5kZWVwLnByb3BlcnR5KCdncmVlbi50ZWEnLCAnbWF0Y2hhJyk7XG4gICAqICAgICBleHBlY3QoZGVlcE9iaikudG8uaGF2ZS5kZWVwLnByb3BlcnR5KCd0ZWFzWzFdJywgJ21hdGNoYScpO1xuICAgKiAgICAgZXhwZWN0KGRlZXBPYmopLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eSgndGVhc1syXS50ZWEnLCAna29uYWNoYScpO1xuICAgKlxuICAgKiBZb3UgY2FuIGFsc28gdXNlIGFuIGFycmF5IGFzIHRoZSBzdGFydGluZyBwb2ludCBvZiBhIGBkZWVwLnByb3BlcnR5YFxuICAgKiBhc3NlcnRpb24sIG9yIHRyYXZlcnNlIG5lc3RlZCBhcnJheXMuXG4gICAqXG4gICAqICAgICB2YXIgYXJyID0gW1xuICAgKiAgICAgICAgIFsgJ2NoYWknLCAnbWF0Y2hhJywgJ2tvbmFjaGEnIF1cbiAgICogICAgICAgLCBbIHsgdGVhOiAnY2hhaScgfVxuICAgKiAgICAgICAgICwgeyB0ZWE6ICdtYXRjaGEnIH1cbiAgICogICAgICAgICAsIHsgdGVhOiAna29uYWNoYScgfSBdXG4gICAqICAgICBdO1xuICAgKlxuICAgKiAgICAgZXhwZWN0KGFycikudG8uaGF2ZS5kZWVwLnByb3BlcnR5KCdbMF1bMV0nLCAnbWF0Y2hhJyk7XG4gICAqICAgICBleHBlY3QoYXJyKS50by5oYXZlLmRlZXAucHJvcGVydHkoJ1sxXVsyXS50ZWEnLCAna29uYWNoYScpO1xuICAgKlxuICAgKiBGdXJ0aGVybW9yZSwgYHByb3BlcnR5YCBjaGFuZ2VzIHRoZSBzdWJqZWN0IG9mIHRoZSBhc3NlcnRpb25cbiAgICogdG8gYmUgdGhlIHZhbHVlIG9mIHRoYXQgcHJvcGVydHkgZnJvbSB0aGUgb3JpZ2luYWwgb2JqZWN0LiBUaGlzXG4gICAqIHBlcm1pdHMgZm9yIGZ1cnRoZXIgY2hhaW5hYmxlIGFzc2VydGlvbnMgb24gdGhhdCBwcm9wZXJ0eS5cbiAgICpcbiAgICogICAgIGV4cGVjdChvYmopLnRvLmhhdmUucHJvcGVydHkoJ2ZvbycpXG4gICAqICAgICAgIC50aGF0LmlzLmEoJ3N0cmluZycpO1xuICAgKiAgICAgZXhwZWN0KGRlZXBPYmopLnRvLmhhdmUucHJvcGVydHkoJ2dyZWVuJylcbiAgICogICAgICAgLnRoYXQuaXMuYW4oJ29iamVjdCcpXG4gICAqICAgICAgIC50aGF0LmRlZXAuZXF1YWxzKHsgdGVhOiAnbWF0Y2hhJyB9KTtcbiAgICogICAgIGV4cGVjdChkZWVwT2JqKS50by5oYXZlLnByb3BlcnR5KCd0ZWFzJylcbiAgICogICAgICAgLnRoYXQuaXMuYW4oJ2FycmF5JylcbiAgICogICAgICAgLndpdGguZGVlcC5wcm9wZXJ0eSgnWzJdJylcbiAgICogICAgICAgICAudGhhdC5kZWVwLmVxdWFscyh7IHRlYTogJ2tvbmFjaGEnIH0pO1xuICAgKlxuICAgKiBOb3RlIHRoYXQgZG90cyBhbmQgYnJhY2tldCBpbiBgbmFtZWAgbXVzdCBiZSBiYWNrc2xhc2gtZXNjYXBlZCB3aGVuXG4gICAqIHRoZSBgZGVlcGAgZmxhZyBpcyBzZXQsIHdoaWxlIHRoZXkgbXVzdCBOT1QgYmUgZXNjYXBlZCB3aGVuIHRoZSBgZGVlcGBcbiAgICogZmxhZyBpcyBub3Qgc2V0LlxuICAgKlxuICAgKiAgICAgLy8gc2ltcGxlIHJlZmVyZW5jaW5nXG4gICAqICAgICB2YXIgY3NzID0geyAnLmxpbmtbdGFyZ2V0XSc6IDQyIH07XG4gICAqICAgICBleHBlY3QoY3NzKS50by5oYXZlLnByb3BlcnR5KCcubGlua1t0YXJnZXRdJywgNDIpO1xuICAgKlxuICAgKiAgICAgLy8gZGVlcCByZWZlcmVuY2luZ1xuICAgKiAgICAgdmFyIGRlZXBDc3MgPSB7ICcubGluayc6IHsgJ1t0YXJnZXRdJzogNDIgfX07XG4gICAqICAgICBleHBlY3QoZGVlcENzcykudG8uaGF2ZS5kZWVwLnByb3BlcnR5KCdcXFxcLmxpbmsuXFxcXFt0YXJnZXRcXFxcXScsIDQyKTtcbiAgICpcbiAgICogQG5hbWUgcHJvcGVydHlcbiAgICogQGFsaWFzIGRlZXAucHJvcGVydHlcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWUgKG9wdGlvbmFsKVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEByZXR1cm5zIHZhbHVlIG9mIHByb3BlcnR5IGZvciBjaGFpbmluZ1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdwcm9wZXJ0eScsIGZ1bmN0aW9uIChuYW1lLCB2YWwsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuXG4gICAgdmFyIGlzRGVlcCA9ICEhZmxhZyh0aGlzLCAnZGVlcCcpXG4gICAgICAsIGRlc2NyaXB0b3IgPSBpc0RlZXAgPyAnZGVlcCBwcm9wZXJ0eSAnIDogJ3Byb3BlcnR5ICdcbiAgICAgICwgbmVnYXRlID0gZmxhZyh0aGlzLCAnbmVnYXRlJylcbiAgICAgICwgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgcGF0aEluZm8gPSBpc0RlZXAgPyBfLmdldFBhdGhJbmZvKG5hbWUsIG9iaikgOiBudWxsXG4gICAgICAsIGhhc1Byb3BlcnR5ID0gaXNEZWVwXG4gICAgICAgID8gcGF0aEluZm8uZXhpc3RzXG4gICAgICAgIDogXy5oYXNQcm9wZXJ0eShuYW1lLCBvYmopXG4gICAgICAsIHZhbHVlID0gaXNEZWVwXG4gICAgICAgID8gcGF0aEluZm8udmFsdWVcbiAgICAgICAgOiBvYmpbbmFtZV07XG5cbiAgICBpZiAobmVnYXRlICYmIHVuZGVmaW5lZCAhPT0gdmFsKSB7XG4gICAgICBpZiAodW5kZWZpbmVkID09PSB2YWx1ZSkge1xuICAgICAgICBtc2cgPSAobXNnICE9IG51bGwpID8gbXNnICsgJzogJyA6ICcnO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnICsgXy5pbnNwZWN0KG9iaikgKyAnIGhhcyBubyAnICsgZGVzY3JpcHRvciArIF8uaW5zcGVjdChuYW1lKSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIGhhc1Byb3BlcnR5XG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBhICcgKyBkZXNjcmlwdG9yICsgXy5pbnNwZWN0KG5hbWUpXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGhhdmUgJyArIGRlc2NyaXB0b3IgKyBfLmluc3BlY3QobmFtZSkpO1xuICAgIH1cblxuICAgIGlmICh1bmRlZmluZWQgIT09IHZhbCkge1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgdmFsID09PSB2YWx1ZVxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGhhdmUgYSAnICsgZGVzY3JpcHRvciArIF8uaW5zcGVjdChuYW1lKSArICcgb2YgI3tleHB9LCBidXQgZ290ICN7YWN0fSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgaGF2ZSBhICcgKyBkZXNjcmlwdG9yICsgXy5pbnNwZWN0KG5hbWUpICsgJyBvZiAje2FjdH0nXG4gICAgICAgICwgdmFsXG4gICAgICAgICwgdmFsdWVcbiAgICAgICk7XG4gICAgfVxuXG4gICAgZmxhZyh0aGlzLCAnb2JqZWN0JywgdmFsdWUpO1xuICB9KTtcblxuXG4gIC8qKlxuICAgKiAjIyMgLm93blByb3BlcnR5KG5hbWUpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGhhcyBhbiBvd24gcHJvcGVydHkgYG5hbWVgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KCd0ZXN0JykudG8uaGF2ZS5vd25Qcm9wZXJ0eSgnbGVuZ3RoJyk7XG4gICAqXG4gICAqIEBuYW1lIG93blByb3BlcnR5XG4gICAqIEBhbGlhcyBoYXZlT3duUHJvcGVydHlcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRPd25Qcm9wZXJ0eSAobmFtZSwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBvYmouaGFzT3duUHJvcGVydHkobmFtZSlcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBvd24gcHJvcGVydHkgJyArIF8uaW5zcGVjdChuYW1lKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgaGF2ZSBvd24gcHJvcGVydHkgJyArIF8uaW5zcGVjdChuYW1lKVxuICAgICk7XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdvd25Qcm9wZXJ0eScsIGFzc2VydE93blByb3BlcnR5KTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnaGF2ZU93blByb3BlcnR5JywgYXNzZXJ0T3duUHJvcGVydHkpO1xuXG4gIC8qKlxuICAgKiAjIyMgLmxlbmd0aCh2YWx1ZSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQncyBgbGVuZ3RoYCBwcm9wZXJ0eSBoYXNcbiAgICogdGhlIGV4cGVjdGVkIHZhbHVlLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgM10pLnRvLmhhdmUubGVuZ3RoKDMpO1xuICAgKiAgICAgZXhwZWN0KCdmb29iYXInKS50by5oYXZlLmxlbmd0aCg2KTtcbiAgICpcbiAgICogQ2FuIGFsc28gYmUgdXNlZCBhcyBhIGNoYWluIHByZWN1cnNvciB0byBhIHZhbHVlXG4gICAqIGNvbXBhcmlzb24gZm9yIHRoZSBsZW5ndGggcHJvcGVydHkuXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2ZvbycpLnRvLmhhdmUubGVuZ3RoLmFib3ZlKDIpO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5oYXZlLmxlbmd0aC5hYm92ZSgyKTtcbiAgICogICAgIGV4cGVjdCgnZm9vJykudG8uaGF2ZS5sZW5ndGguYmVsb3coNCk7XG4gICAqICAgICBleHBlY3QoWyAxLCAyLCAzIF0pLnRvLmhhdmUubGVuZ3RoLmJlbG93KDQpO1xuICAgKiAgICAgZXhwZWN0KCdmb28nKS50by5oYXZlLmxlbmd0aC53aXRoaW4oMiw0KTtcbiAgICogICAgIGV4cGVjdChbIDEsIDIsIDMgXSkudG8uaGF2ZS5sZW5ndGgud2l0aGluKDIsNCk7XG4gICAqXG4gICAqIEBuYW1lIGxlbmd0aFxuICAgKiBAYWxpYXMgbGVuZ3RoT2ZcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGxlbmd0aFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGFzc2VydExlbmd0aENoYWluICgpIHtcbiAgICBmbGFnKHRoaXMsICdkb0xlbmd0aCcsIHRydWUpO1xuICB9XG5cbiAgZnVuY3Rpb24gYXNzZXJ0TGVuZ3RoIChuLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5wcm9wZXJ0eSgnbGVuZ3RoJyk7XG4gICAgdmFyIGxlbiA9IG9iai5sZW5ndGg7XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgbGVuID09IG5cbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBhIGxlbmd0aCBvZiAje2V4cH0gYnV0IGdvdCAje2FjdH0nXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBoYXZlIGEgbGVuZ3RoIG9mICN7YWN0fSdcbiAgICAgICwgblxuICAgICAgLCBsZW5cbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZENoYWluYWJsZU1ldGhvZCgnbGVuZ3RoJywgYXNzZXJ0TGVuZ3RoLCBhc3NlcnRMZW5ndGhDaGFpbik7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2xlbmd0aE9mJywgYXNzZXJ0TGVuZ3RoKTtcblxuICAvKipcbiAgICogIyMjIC5tYXRjaChyZWdleHApXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IG1hdGNoZXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2Zvb2JhcicpLnRvLm1hdGNoKC9eZm9vLyk7XG4gICAqXG4gICAqIEBuYW1lIG1hdGNoXG4gICAqIEBwYXJhbSB7UmVnRXhwfSBSZWd1bGFyRXhwcmVzc2lvblxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ21hdGNoJywgZnVuY3Rpb24gKHJlLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIHJlLmV4ZWMob2JqKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBtYXRjaCAnICsgcmVcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gbm90IHRvIG1hdGNoICcgKyByZVxuICAgICk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLnN0cmluZyhzdHJpbmcpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgc3RyaW5nIHRhcmdldCBjb250YWlucyBhbm90aGVyIHN0cmluZy5cbiAgICpcbiAgICogICAgIGV4cGVjdCgnZm9vYmFyJykudG8uaGF2ZS5zdHJpbmcoJ2JhcicpO1xuICAgKlxuICAgKiBAbmFtZSBzdHJpbmdcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0cmluZ1xuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ3N0cmluZycsIGZ1bmN0aW9uIChzdHIsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS5pcy5hKCdzdHJpbmcnKTtcblxuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICB+b2JqLmluZGV4T2Yoc3RyKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBjb250YWluICcgKyBfLmluc3BlY3Qoc3RyKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgY29udGFpbiAnICsgXy5pbnNwZWN0KHN0cilcbiAgICApO1xuICB9KTtcblxuXG4gIC8qKlxuICAgKiAjIyMgLmtleXMoa2V5MSwgW2tleTJdLCBbLi4uXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgY29udGFpbnMgYW55IG9yIGFsbCBvZiB0aGUgcGFzc2VkLWluIGtleXMuXG4gICAqIFVzZSBpbiBjb21iaW5hdGlvbiB3aXRoIGBhbnlgLCBgYWxsYCwgYGNvbnRhaW5zYCwgb3IgYGhhdmVgIHdpbGwgYWZmZWN0IFxuICAgKiB3aGF0IHdpbGwgcGFzcy5cbiAgICogXG4gICAqIFdoZW4gdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIGBhbnlgLCBhdCBsZWFzdCBvbmUga2V5IHRoYXQgaXMgcGFzc2VkIFxuICAgKiBpbiBtdXN0IGV4aXN0IGluIHRoZSB0YXJnZXQgb2JqZWN0LiBUaGlzIGlzIHJlZ2FyZGxlc3Mgd2hldGhlciBvciBub3QgXG4gICAqIHRoZSBgaGF2ZWAgb3IgYGNvbnRhaW5gIHF1YWxpZmllcnMgYXJlIHVzZWQuIE5vdGUsIGVpdGhlciBgYW55YCBvciBgYWxsYFxuICAgKiBzaG91bGQgYmUgdXNlZCBpbiB0aGUgYXNzZXJ0aW9uLiBJZiBuZWl0aGVyIGFyZSB1c2VkLCB0aGUgYXNzZXJ0aW9uIGlzXG4gICAqIGRlZmF1bHRlZCB0byBgYWxsYC5cbiAgICogXG4gICAqIFdoZW4gYm90aCBgYWxsYCBhbmQgYGNvbnRhaW5gIGFyZSB1c2VkLCB0aGUgdGFyZ2V0IG9iamVjdCBtdXN0IGhhdmUgYXQgXG4gICAqIGxlYXN0IGFsbCBvZiB0aGUgcGFzc2VkLWluIGtleXMgYnV0IG1heSBoYXZlIG1vcmUga2V5cyBub3QgbGlzdGVkLlxuICAgKiBcbiAgICogV2hlbiBib3RoIGBhbGxgIGFuZCBgaGF2ZWAgYXJlIHVzZWQsIHRoZSB0YXJnZXQgb2JqZWN0IG11c3QgYm90aCBjb250YWluXG4gICAqIGFsbCBvZiB0aGUgcGFzc2VkLWluIGtleXMgQU5EIHRoZSBudW1iZXIgb2Yga2V5cyBpbiB0aGUgdGFyZ2V0IG9iamVjdCBtdXN0XG4gICAqIG1hdGNoIHRoZSBudW1iZXIgb2Yga2V5cyBwYXNzZWQgaW4gKGluIG90aGVyIHdvcmRzLCBhIHRhcmdldCBvYmplY3QgbXVzdCBcbiAgICogaGF2ZSBhbGwgYW5kIG9ubHkgYWxsIG9mIHRoZSBwYXNzZWQtaW4ga2V5cykuXG4gICAqIFxuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAxLCBiYXI6IDIgfSkudG8uaGF2ZS5hbnkua2V5cygnZm9vJywgJ2JheicpO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAxLCBiYXI6IDIgfSkudG8uaGF2ZS5hbnkua2V5cygnZm9vJyk7XG4gICAqICAgICBleHBlY3QoeyBmb286IDEsIGJhcjogMiB9KS50by5jb250YWluLmFueS5rZXlzKCdiYXInLCAnYmF6Jyk7XG4gICAqICAgICBleHBlY3QoeyBmb286IDEsIGJhcjogMiB9KS50by5jb250YWluLmFueS5rZXlzKFsnZm9vJ10pO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAxLCBiYXI6IDIgfSkudG8uY29udGFpbi5hbnkua2V5cyh7J2Zvbyc6IDZ9KTtcbiAgICogICAgIGV4cGVjdCh7IGZvbzogMSwgYmFyOiAyIH0pLnRvLmhhdmUuYWxsLmtleXMoWydiYXInLCAnZm9vJ10pO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAxLCBiYXI6IDIgfSkudG8uaGF2ZS5hbGwua2V5cyh7J2Jhcic6IDYsICdmb28nLCA3fSk7XG4gICAqICAgICBleHBlY3QoeyBmb286IDEsIGJhcjogMiwgYmF6OiAzIH0pLnRvLmNvbnRhaW4uYWxsLmtleXMoWydiYXInLCAnZm9vJ10pO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAxLCBiYXI6IDIsIGJhejogMyB9KS50by5jb250YWluLmFsbC5rZXlzKFt7J2Jhcic6IDZ9fV0pO1xuICAgKlxuICAgKlxuICAgKiBAbmFtZSBrZXlzXG4gICAqIEBhbGlhcyBrZXlcbiAgICogQHBhcmFtIHtTdHJpbmcuLi58QXJyYXl8T2JqZWN0fSBrZXlzXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGFzc2VydEtleXMgKGtleXMpIHtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgc3RyXG4gICAgICAsIG9rID0gdHJ1ZVxuICAgICAgLCBtaXhlZEFyZ3NNc2cgPSAna2V5cyBtdXN0IGJlIGdpdmVuIHNpbmdsZSBhcmd1bWVudCBvZiBBcnJheXxPYmplY3R8U3RyaW5nLCBvciBtdWx0aXBsZSBTdHJpbmcgYXJndW1lbnRzJztcblxuICAgIHN3aXRjaCAoXy50eXBlKGtleXMpKSB7XG4gICAgICBjYXNlIFwiYXJyYXlcIjpcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB0aHJvdyAobmV3IEVycm9yKG1peGVkQXJnc01zZykpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJvYmplY3RcIjpcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB0aHJvdyAobmV3IEVycm9yKG1peGVkQXJnc01zZykpO1xuICAgICAgICBrZXlzID0gT2JqZWN0LmtleXMoa2V5cyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAga2V5cyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG4gICAgfVxuXG4gICAgaWYgKCFrZXlzLmxlbmd0aCkgdGhyb3cgbmV3IEVycm9yKCdrZXlzIHJlcXVpcmVkJyk7XG5cbiAgICB2YXIgYWN0dWFsID0gT2JqZWN0LmtleXMob2JqKVxuICAgICAgLCBleHBlY3RlZCA9IGtleXNcbiAgICAgICwgbGVuID0ga2V5cy5sZW5ndGhcbiAgICAgICwgYW55ID0gZmxhZyh0aGlzLCAnYW55JylcbiAgICAgICwgYWxsID0gZmxhZyh0aGlzLCAnYWxsJyk7XG5cbiAgICBpZiAoIWFueSAmJiAhYWxsKSB7XG4gICAgICBhbGwgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIEhhcyBhbnlcbiAgICBpZiAoYW55KSB7XG4gICAgICB2YXIgaW50ZXJzZWN0aW9uID0gZXhwZWN0ZWQuZmlsdGVyKGZ1bmN0aW9uKGtleSkge1xuICAgICAgICByZXR1cm4gfmFjdHVhbC5pbmRleE9mKGtleSk7XG4gICAgICB9KTtcbiAgICAgIG9rID0gaW50ZXJzZWN0aW9uLmxlbmd0aCA+IDA7XG4gICAgfVxuXG4gICAgLy8gSGFzIGFsbFxuICAgIGlmIChhbGwpIHtcbiAgICAgIG9rID0ga2V5cy5ldmVyeShmdW5jdGlvbihrZXkpe1xuICAgICAgICByZXR1cm4gfmFjdHVhbC5pbmRleE9mKGtleSk7XG4gICAgICB9KTtcbiAgICAgIGlmICghZmxhZyh0aGlzLCAnbmVnYXRlJykgJiYgIWZsYWcodGhpcywgJ2NvbnRhaW5zJykpIHtcbiAgICAgICAgb2sgPSBvayAmJiBrZXlzLmxlbmd0aCA9PSBhY3R1YWwubGVuZ3RoO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEtleSBzdHJpbmdcbiAgICBpZiAobGVuID4gMSkge1xuICAgICAga2V5cyA9IGtleXMubWFwKGZ1bmN0aW9uKGtleSl7XG4gICAgICAgIHJldHVybiBfLmluc3BlY3Qoa2V5KTtcbiAgICAgIH0pO1xuICAgICAgdmFyIGxhc3QgPSBrZXlzLnBvcCgpO1xuICAgICAgaWYgKGFsbCkge1xuICAgICAgICBzdHIgPSBrZXlzLmpvaW4oJywgJykgKyAnLCBhbmQgJyArIGxhc3Q7XG4gICAgICB9XG4gICAgICBpZiAoYW55KSB7XG4gICAgICAgIHN0ciA9IGtleXMuam9pbignLCAnKSArICcsIG9yICcgKyBsYXN0O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzdHIgPSBfLmluc3BlY3Qoa2V5c1swXSk7XG4gICAgfVxuXG4gICAgLy8gRm9ybVxuICAgIHN0ciA9IChsZW4gPiAxID8gJ2tleXMgJyA6ICdrZXkgJykgKyBzdHI7XG5cbiAgICAvLyBIYXZlIC8gaW5jbHVkZVxuICAgIHN0ciA9IChmbGFnKHRoaXMsICdjb250YWlucycpID8gJ2NvbnRhaW4gJyA6ICdoYXZlICcpICsgc3RyO1xuXG4gICAgLy8gQXNzZXJ0aW9uXG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIG9rXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvICcgKyBzdHJcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90ICcgKyBzdHJcbiAgICAgICwgZXhwZWN0ZWQuc2xpY2UoMCkuc29ydCgpXG4gICAgICAsIGFjdHVhbC5zb3J0KClcbiAgICAgICwgdHJ1ZVxuICAgICk7XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdrZXlzJywgYXNzZXJ0S2V5cyk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2tleScsIGFzc2VydEtleXMpO1xuXG4gIC8qKlxuICAgKiAjIyMgLnRocm93KGNvbnN0cnVjdG9yKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIGZ1bmN0aW9uIHRhcmdldCB3aWxsIHRocm93IGEgc3BlY2lmaWMgZXJyb3IsIG9yIHNwZWNpZmljIHR5cGUgb2YgZXJyb3JcbiAgICogKGFzIGRldGVybWluZWQgdXNpbmcgYGluc3RhbmNlb2ZgKSwgb3B0aW9uYWxseSB3aXRoIGEgUmVnRXhwIG9yIHN0cmluZyBpbmNsdXNpb24gdGVzdFxuICAgKiBmb3IgdGhlIGVycm9yJ3MgbWVzc2FnZS5cbiAgICpcbiAgICogICAgIHZhciBlcnIgPSBuZXcgUmVmZXJlbmNlRXJyb3IoJ1RoaXMgaXMgYSBiYWQgZnVuY3Rpb24uJyk7XG4gICAqICAgICB2YXIgZm4gPSBmdW5jdGlvbiAoKSB7IHRocm93IGVycjsgfVxuICAgKiAgICAgZXhwZWN0KGZuKS50by50aHJvdyhSZWZlcmVuY2VFcnJvcik7XG4gICAqICAgICBleHBlY3QoZm4pLnRvLnRocm93KEVycm9yKTtcbiAgICogICAgIGV4cGVjdChmbikudG8udGhyb3coL2JhZCBmdW5jdGlvbi8pO1xuICAgKiAgICAgZXhwZWN0KGZuKS50by5ub3QudGhyb3coJ2dvb2QgZnVuY3Rpb24nKTtcbiAgICogICAgIGV4cGVjdChmbikudG8udGhyb3coUmVmZXJlbmNlRXJyb3IsIC9iYWQgZnVuY3Rpb24vKTtcbiAgICogICAgIGV4cGVjdChmbikudG8udGhyb3coZXJyKTtcbiAgICogICAgIGV4cGVjdChmbikudG8ubm90LnRocm93KG5ldyBSYW5nZUVycm9yKCdPdXQgb2YgcmFuZ2UuJykpO1xuICAgKlxuICAgKiBQbGVhc2Ugbm90ZSB0aGF0IHdoZW4gYSB0aHJvdyBleHBlY3RhdGlvbiBpcyBuZWdhdGVkLCBpdCB3aWxsIGNoZWNrIGVhY2hcbiAgICogcGFyYW1ldGVyIGluZGVwZW5kZW50bHksIHN0YXJ0aW5nIHdpdGggZXJyb3IgY29uc3RydWN0b3IgdHlwZS4gVGhlIGFwcHJvcHJpYXRlIHdheVxuICAgKiB0byBjaGVjayBmb3IgdGhlIGV4aXN0ZW5jZSBvZiBhIHR5cGUgb2YgZXJyb3IgYnV0IGZvciBhIG1lc3NhZ2UgdGhhdCBkb2VzIG5vdCBtYXRjaFxuICAgKiBpcyB0byB1c2UgYGFuZGAuXG4gICAqXG4gICAqICAgICBleHBlY3QoZm4pLnRvLnRocm93KFJlZmVyZW5jZUVycm9yKVxuICAgKiAgICAgICAgLmFuZC5ub3QudGhyb3coL2dvb2QgZnVuY3Rpb24vKTtcbiAgICpcbiAgICogQG5hbWUgdGhyb3dcbiAgICogQGFsaWFzIHRocm93c1xuICAgKiBAYWxpYXMgVGhyb3dcbiAgICogQHBhcmFtIHtFcnJvckNvbnN0cnVjdG9yfSBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV4cGVjdGVkIGVycm9yIG1lc3NhZ2VcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Vycm9yI0Vycm9yX3R5cGVzXG4gICAqIEByZXR1cm5zIGVycm9yIGZvciBjaGFpbmluZyAobnVsbCBpZiBubyBlcnJvcilcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gYXNzZXJ0VGhyb3dzIChjb25zdHJ1Y3RvciwgZXJyTXNnLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykuaXMuYSgnZnVuY3Rpb24nKTtcblxuICAgIHZhciB0aHJvd24gPSBmYWxzZVxuICAgICAgLCBkZXNpcmVkRXJyb3IgPSBudWxsXG4gICAgICAsIG5hbWUgPSBudWxsXG4gICAgICAsIHRocm93bkVycm9yID0gbnVsbDtcblxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICBlcnJNc2cgPSBudWxsO1xuICAgICAgY29uc3RydWN0b3IgPSBudWxsO1xuICAgIH0gZWxzZSBpZiAoY29uc3RydWN0b3IgJiYgKGNvbnN0cnVjdG9yIGluc3RhbmNlb2YgUmVnRXhwIHx8ICdzdHJpbmcnID09PSB0eXBlb2YgY29uc3RydWN0b3IpKSB7XG4gICAgICBlcnJNc2cgPSBjb25zdHJ1Y3RvcjtcbiAgICAgIGNvbnN0cnVjdG9yID0gbnVsbDtcbiAgICB9IGVsc2UgaWYgKGNvbnN0cnVjdG9yICYmIGNvbnN0cnVjdG9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIGRlc2lyZWRFcnJvciA9IGNvbnN0cnVjdG9yO1xuICAgICAgY29uc3RydWN0b3IgPSBudWxsO1xuICAgICAgZXJyTXNnID0gbnVsbDtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBjb25zdHJ1Y3RvciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgbmFtZSA9IGNvbnN0cnVjdG9yLnByb3RvdHlwZS5uYW1lIHx8IGNvbnN0cnVjdG9yLm5hbWU7XG4gICAgICBpZiAobmFtZSA9PT0gJ0Vycm9yJyAmJiBjb25zdHJ1Y3RvciAhPT0gRXJyb3IpIHtcbiAgICAgICAgbmFtZSA9IChuZXcgY29uc3RydWN0b3IoKSkubmFtZTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3RydWN0b3IgPSBudWxsO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBvYmooKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8vIGZpcnN0LCBjaGVjayBkZXNpcmVkIGVycm9yXG4gICAgICBpZiAoZGVzaXJlZEVycm9yKSB7XG4gICAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgICAgZXJyID09PSBkZXNpcmVkRXJyb3JcbiAgICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIHRocm93ICN7ZXhwfSBidXQgI3thY3R9IHdhcyB0aHJvd24nXG4gICAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgdGhyb3cgI3tleHB9J1xuICAgICAgICAgICwgKGRlc2lyZWRFcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZGVzaXJlZEVycm9yLnRvU3RyaW5nKCkgOiBkZXNpcmVkRXJyb3IpXG4gICAgICAgICAgLCAoZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIudG9TdHJpbmcoKSA6IGVycilcbiAgICAgICAgKTtcblxuICAgICAgICBmbGFnKHRoaXMsICdvYmplY3QnLCBlcnIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgLy8gbmV4dCwgY2hlY2sgY29uc3RydWN0b3JcbiAgICAgIGlmIChjb25zdHJ1Y3Rvcikge1xuICAgICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICAgIGVyciBpbnN0YW5jZW9mIGNvbnN0cnVjdG9yXG4gICAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byB0aHJvdyAje2V4cH0gYnV0ICN7YWN0fSB3YXMgdGhyb3duJ1xuICAgICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IHRocm93ICN7ZXhwfSBidXQgI3thY3R9IHdhcyB0aHJvd24nXG4gICAgICAgICAgLCBuYW1lXG4gICAgICAgICAgLCAoZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIudG9TdHJpbmcoKSA6IGVycilcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoIWVyck1zZykge1xuICAgICAgICAgIGZsYWcodGhpcywgJ29iamVjdCcsIGVycik7XG4gICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gbmV4dCwgY2hlY2sgbWVzc2FnZVxuICAgICAgdmFyIG1lc3NhZ2UgPSAnb2JqZWN0JyA9PT0gXy50eXBlKGVycikgJiYgXCJtZXNzYWdlXCIgaW4gZXJyXG4gICAgICAgID8gZXJyLm1lc3NhZ2VcbiAgICAgICAgOiAnJyArIGVycjtcblxuICAgICAgaWYgKChtZXNzYWdlICE9IG51bGwpICYmIGVyck1zZyAmJiBlcnJNc2cgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgICBlcnJNc2cuZXhlYyhtZXNzYWdlKVxuICAgICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gdGhyb3cgZXJyb3IgbWF0Y2hpbmcgI3tleHB9IGJ1dCBnb3QgI3thY3R9J1xuICAgICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gdGhyb3cgZXJyb3Igbm90IG1hdGNoaW5nICN7ZXhwfSdcbiAgICAgICAgICAsIGVyck1zZ1xuICAgICAgICAgICwgbWVzc2FnZVxuICAgICAgICApO1xuXG4gICAgICAgIGZsYWcodGhpcywgJ29iamVjdCcsIGVycik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfSBlbHNlIGlmICgobWVzc2FnZSAhPSBudWxsKSAmJiBlcnJNc2cgJiYgJ3N0cmluZycgPT09IHR5cGVvZiBlcnJNc2cpIHtcbiAgICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgICB+bWVzc2FnZS5pbmRleE9mKGVyck1zZylcbiAgICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIHRocm93IGVycm9yIGluY2x1ZGluZyAje2V4cH0gYnV0IGdvdCAje2FjdH0nXG4gICAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byB0aHJvdyBlcnJvciBub3QgaW5jbHVkaW5nICN7YWN0fSdcbiAgICAgICAgICAsIGVyck1zZ1xuICAgICAgICAgICwgbWVzc2FnZVxuICAgICAgICApO1xuXG4gICAgICAgIGZsYWcodGhpcywgJ29iamVjdCcsIGVycik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3duID0gdHJ1ZTtcbiAgICAgICAgdGhyb3duRXJyb3IgPSBlcnI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGFjdHVhbGx5R290ID0gJydcbiAgICAgICwgZXhwZWN0ZWRUaHJvd24gPSBuYW1lICE9PSBudWxsXG4gICAgICAgID8gbmFtZVxuICAgICAgICA6IGRlc2lyZWRFcnJvclxuICAgICAgICAgID8gJyN7ZXhwfScgLy9fLmluc3BlY3QoZGVzaXJlZEVycm9yKVxuICAgICAgICAgIDogJ2FuIGVycm9yJztcblxuICAgIGlmICh0aHJvd24pIHtcbiAgICAgIGFjdHVhbGx5R290ID0gJyBidXQgI3thY3R9IHdhcyB0aHJvd24nXG4gICAgfVxuXG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIHRocm93biA9PT0gdHJ1ZVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byB0aHJvdyAnICsgZXhwZWN0ZWRUaHJvd24gKyBhY3R1YWxseUdvdFxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgdGhyb3cgJyArIGV4cGVjdGVkVGhyb3duICsgYWN0dWFsbHlHb3RcbiAgICAgICwgKGRlc2lyZWRFcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZGVzaXJlZEVycm9yLnRvU3RyaW5nKCkgOiBkZXNpcmVkRXJyb3IpXG4gICAgICAsICh0aHJvd25FcnJvciBpbnN0YW5jZW9mIEVycm9yID8gdGhyb3duRXJyb3IudG9TdHJpbmcoKSA6IHRocm93bkVycm9yKVxuICAgICk7XG5cbiAgICBmbGFnKHRoaXMsICdvYmplY3QnLCB0aHJvd25FcnJvcik7XG4gIH07XG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgndGhyb3cnLCBhc3NlcnRUaHJvd3MpO1xuICBBc3NlcnRpb24uYWRkTWV0aG9kKCd0aHJvd3MnLCBhc3NlcnRUaHJvd3MpO1xuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdUaHJvdycsIGFzc2VydFRocm93cyk7XG5cbiAgLyoqXG4gICAqICMjIyAucmVzcG9uZFRvKG1ldGhvZClcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSBvYmplY3Qgb3IgY2xhc3MgdGFyZ2V0IHdpbGwgcmVzcG9uZCB0byBhIG1ldGhvZC5cbiAgICpcbiAgICogICAgIEtsYXNzLnByb3RvdHlwZS5iYXIgPSBmdW5jdGlvbigpe307XG4gICAqICAgICBleHBlY3QoS2xhc3MpLnRvLnJlc3BvbmRUbygnYmFyJyk7XG4gICAqICAgICBleHBlY3Qob2JqKS50by5yZXNwb25kVG8oJ2JhcicpO1xuICAgKlxuICAgKiBUbyBjaGVjayBpZiBhIGNvbnN0cnVjdG9yIHdpbGwgcmVzcG9uZCB0byBhIHN0YXRpYyBmdW5jdGlvbixcbiAgICogc2V0IHRoZSBgaXRzZWxmYCBmbGFnLlxuICAgKlxuICAgKiAgICAgS2xhc3MuYmF6ID0gZnVuY3Rpb24oKXt9O1xuICAgKiAgICAgZXhwZWN0KEtsYXNzKS5pdHNlbGYudG8ucmVzcG9uZFRvKCdiYXonKTtcbiAgICpcbiAgICogQG5hbWUgcmVzcG9uZFRvXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2RcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdyZXNwb25kVG8nLCBmdW5jdGlvbiAobWV0aG9kLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgaXRzZWxmID0gZmxhZyh0aGlzLCAnaXRzZWxmJylcbiAgICAgICwgY29udGV4dCA9ICgnZnVuY3Rpb24nID09PSBfLnR5cGUob2JqKSAmJiAhaXRzZWxmKVxuICAgICAgICA/IG9iai5wcm90b3R5cGVbbWV0aG9kXVxuICAgICAgICA6IG9ialttZXRob2RdO1xuXG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICdmdW5jdGlvbicgPT09IHR5cGVvZiBjb250ZXh0XG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIHJlc3BvbmQgdG8gJyArIF8uaW5zcGVjdChtZXRob2QpXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCByZXNwb25kIHRvICcgKyBfLmluc3BlY3QobWV0aG9kKVxuICAgICk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLml0c2VsZlxuICAgKlxuICAgKiBTZXRzIHRoZSBgaXRzZWxmYCBmbGFnLCBsYXRlciB1c2VkIGJ5IHRoZSBgcmVzcG9uZFRvYCBhc3NlcnRpb24uXG4gICAqXG4gICAqICAgICBmdW5jdGlvbiBGb28oKSB7fVxuICAgKiAgICAgRm9vLmJhciA9IGZ1bmN0aW9uKCkge31cbiAgICogICAgIEZvby5wcm90b3R5cGUuYmF6ID0gZnVuY3Rpb24oKSB7fVxuICAgKlxuICAgKiAgICAgZXhwZWN0KEZvbykuaXRzZWxmLnRvLnJlc3BvbmRUbygnYmFyJyk7XG4gICAqICAgICBleHBlY3QoRm9vKS5pdHNlbGYubm90LnRvLnJlc3BvbmRUbygnYmF6Jyk7XG4gICAqXG4gICAqIEBuYW1lIGl0c2VsZlxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkoJ2l0c2VsZicsIGZ1bmN0aW9uICgpIHtcbiAgICBmbGFnKHRoaXMsICdpdHNlbGYnLCB0cnVlKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAuc2F0aXNmeShtZXRob2QpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IHBhc3NlcyBhIGdpdmVuIHRydXRoIHRlc3QuXG4gICAqXG4gICAqICAgICBleHBlY3QoMSkudG8uc2F0aXNmeShmdW5jdGlvbihudW0pIHsgcmV0dXJuIG51bSA+IDA7IH0pO1xuICAgKlxuICAgKiBAbmFtZSBzYXRpc2Z5XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IG1hdGNoZXJcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdzYXRpc2Z5JywgZnVuY3Rpb24gKG1hdGNoZXIsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICB2YXIgcmVzdWx0ID0gbWF0Y2hlcihvYmopO1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICByZXN1bHRcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gc2F0aXNmeSAnICsgXy5vYmpEaXNwbGF5KG1hdGNoZXIpXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBzYXRpc2Z5JyArIF8ub2JqRGlzcGxheShtYXRjaGVyKVxuICAgICAgLCB0aGlzLm5lZ2F0ZSA/IGZhbHNlIDogdHJ1ZVxuICAgICAgLCByZXN1bHRcbiAgICApO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5jbG9zZVRvKGV4cGVjdGVkLCBkZWx0YSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgZXF1YWwgYGV4cGVjdGVkYCwgdG8gd2l0aGluIGEgKy8tIGBkZWx0YWAgcmFuZ2UuXG4gICAqXG4gICAqICAgICBleHBlY3QoMS41KS50by5iZS5jbG9zZVRvKDEsIDAuNSk7XG4gICAqXG4gICAqIEBuYW1lIGNsb3NlVG9cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkZWx0YVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2Nsb3NlVG8nLCBmdW5jdGlvbiAoZXhwZWN0ZWQsIGRlbHRhLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG5cbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS5pcy5hKCdudW1iZXInKTtcbiAgICBpZiAoXy50eXBlKGV4cGVjdGVkKSAhPT0gJ251bWJlcicgfHwgXy50eXBlKGRlbHRhKSAhPT0gJ251bWJlcicpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndGhlIGFyZ3VtZW50cyB0byBjbG9zZVRvIG11c3QgYmUgbnVtYmVycycpO1xuICAgIH1cblxuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBNYXRoLmFicyhvYmogLSBleHBlY3RlZCkgPD0gZGVsdGFcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgY2xvc2UgdG8gJyArIGV4cGVjdGVkICsgJyArLy0gJyArIGRlbHRhXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IG5vdCB0byBiZSBjbG9zZSB0byAnICsgZXhwZWN0ZWQgKyAnICsvLSAnICsgZGVsdGFcbiAgICApO1xuICB9KTtcblxuICBmdW5jdGlvbiBpc1N1YnNldE9mKHN1YnNldCwgc3VwZXJzZXQsIGNtcCkge1xuICAgIHJldHVybiBzdWJzZXQuZXZlcnkoZnVuY3Rpb24oZWxlbSkge1xuICAgICAgaWYgKCFjbXApIHJldHVybiBzdXBlcnNldC5pbmRleE9mKGVsZW0pICE9PSAtMTtcblxuICAgICAgcmV0dXJuIHN1cGVyc2V0LnNvbWUoZnVuY3Rpb24oZWxlbTIpIHtcbiAgICAgICAgcmV0dXJuIGNtcChlbGVtLCBlbGVtMik7XG4gICAgICB9KTtcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqICMjIyAubWVtYmVycyhzZXQpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGEgc3VwZXJzZXQgb2YgYHNldGAsXG4gICAqIG9yIHRoYXQgdGhlIHRhcmdldCBhbmQgYHNldGAgaGF2ZSB0aGUgc2FtZSBzdHJpY3RseS1lcXVhbCAoPT09KSBtZW1iZXJzLlxuICAgKiBBbHRlcm5hdGVseSwgaWYgdGhlIGBkZWVwYCBmbGFnIGlzIHNldCwgc2V0IG1lbWJlcnMgYXJlIGNvbXBhcmVkIGZvciBkZWVwXG4gICAqIGVxdWFsaXR5LlxuICAgKlxuICAgKiAgICAgZXhwZWN0KFsxLCAyLCAzXSkudG8uaW5jbHVkZS5tZW1iZXJzKFszLCAyXSk7XG4gICAqICAgICBleHBlY3QoWzEsIDIsIDNdKS50by5ub3QuaW5jbHVkZS5tZW1iZXJzKFszLCAyLCA4XSk7XG4gICAqXG4gICAqICAgICBleHBlY3QoWzQsIDJdKS50by5oYXZlLm1lbWJlcnMoWzIsIDRdKTtcbiAgICogICAgIGV4cGVjdChbNSwgMl0pLnRvLm5vdC5oYXZlLm1lbWJlcnMoWzUsIDIsIDFdKTtcbiAgICpcbiAgICogICAgIGV4cGVjdChbeyBpZDogMSB9XSkudG8uZGVlcC5pbmNsdWRlLm1lbWJlcnMoW3sgaWQ6IDEgfV0pO1xuICAgKlxuICAgKiBAbmFtZSBtZW1iZXJzXG4gICAqIEBwYXJhbSB7QXJyYXl9IHNldFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ21lbWJlcnMnLCBmdW5jdGlvbiAoc3Vic2V0LCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG5cbiAgICBuZXcgQXNzZXJ0aW9uKG9iaikudG8uYmUuYW4oJ2FycmF5Jyk7XG4gICAgbmV3IEFzc2VydGlvbihzdWJzZXQpLnRvLmJlLmFuKCdhcnJheScpO1xuXG4gICAgdmFyIGNtcCA9IGZsYWcodGhpcywgJ2RlZXAnKSA/IF8uZXFsIDogdW5kZWZpbmVkO1xuXG4gICAgaWYgKGZsYWcodGhpcywgJ2NvbnRhaW5zJykpIHtcbiAgICAgIHJldHVybiB0aGlzLmFzc2VydChcbiAgICAgICAgICBpc1N1YnNldE9mKHN1YnNldCwgb2JqLCBjbXApXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYSBzdXBlcnNldCBvZiAje2FjdH0nXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGJlIGEgc3VwZXJzZXQgb2YgI3thY3R9J1xuICAgICAgICAsIG9ialxuICAgICAgICAsIHN1YnNldFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgaXNTdWJzZXRPZihvYmosIHN1YnNldCwgY21wKSAmJiBpc1N1YnNldE9mKHN1YnNldCwgb2JqLCBjbXApXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSB0aGUgc2FtZSBtZW1iZXJzIGFzICN7YWN0fSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgaGF2ZSB0aGUgc2FtZSBtZW1iZXJzIGFzICN7YWN0fSdcbiAgICAgICAgLCBvYmpcbiAgICAgICAgLCBzdWJzZXRcbiAgICApO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5jaGFuZ2UoZnVuY3Rpb24pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBhIGZ1bmN0aW9uIGNoYW5nZXMgYW4gb2JqZWN0IHByb3BlcnR5XG4gICAqXG4gICAqICAgICB2YXIgb2JqID0geyB2YWw6IDEwIH07XG4gICAqICAgICB2YXIgZm4gPSBmdW5jdGlvbigpIHsgb2JqLnZhbCArPSAzIH07XG4gICAqICAgICB2YXIgbm9DaGFuZ2VGbiA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gJ2ZvbycgKyAnYmFyJzsgfVxuICAgKiAgICAgZXhwZWN0KGZuKS50by5jaGFuZ2Uob2JqLCAndmFsJyk7XG4gICAqICAgICBleHBlY3Qobm9DaGFuZ0ZuKS50by5ub3QuY2hhbmdlKG9iaiwgJ3ZhbCcpXG4gICAqXG4gICAqIEBuYW1lIGNoYW5nZVxuICAgKiBAYWxpYXMgY2hhbmdlc1xuICAgKiBAYWxpYXMgQ2hhbmdlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRDaGFuZ2VzIChvYmplY3QsIHByb3AsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBmbiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIG5ldyBBc3NlcnRpb24ob2JqZWN0LCBtc2cpLnRvLmhhdmUucHJvcGVydHkocHJvcCk7XG4gICAgbmV3IEFzc2VydGlvbihmbikuaXMuYSgnZnVuY3Rpb24nKTtcblxuICAgIHZhciBpbml0aWFsID0gb2JqZWN0W3Byb3BdO1xuICAgIGZuKCk7XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgIGluaXRpYWwgIT09IG9iamVjdFtwcm9wXVxuICAgICAgLCAnZXhwZWN0ZWQgLicgKyBwcm9wICsgJyB0byBjaGFuZ2UnXG4gICAgICAsICdleHBlY3RlZCAuJyArIHByb3AgKyAnIHRvIG5vdCBjaGFuZ2UnXG4gICAgKTtcbiAgfVxuXG4gIEFzc2VydGlvbi5hZGRDaGFpbmFibGVNZXRob2QoJ2NoYW5nZScsIGFzc2VydENoYW5nZXMpO1xuICBBc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdjaGFuZ2VzJywgYXNzZXJ0Q2hhbmdlcyk7XG5cbiAgLyoqXG4gICAqICMjIyAuaW5jcmVhc2UoZnVuY3Rpb24pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBhIGZ1bmN0aW9uIGluY3JlYXNlcyBhbiBvYmplY3QgcHJvcGVydHlcbiAgICpcbiAgICogICAgIHZhciBvYmogPSB7IHZhbDogMTAgfTtcbiAgICogICAgIHZhciBmbiA9IGZ1bmN0aW9uKCkgeyBvYmoudmFsID0gMTUgfTtcbiAgICogICAgIGV4cGVjdChmbikudG8uaW5jcmVhc2Uob2JqLCAndmFsJyk7XG4gICAqXG4gICAqIEBuYW1lIGluY3JlYXNlXG4gICAqIEBhbGlhcyBpbmNyZWFzZXNcbiAgICogQGFsaWFzIEluY3JlYXNlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRJbmNyZWFzZXMgKG9iamVjdCwgcHJvcCwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIGZuID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgbmV3IEFzc2VydGlvbihvYmplY3QsIG1zZykudG8uaGF2ZS5wcm9wZXJ0eShwcm9wKTtcbiAgICBuZXcgQXNzZXJ0aW9uKGZuKS5pcy5hKCdmdW5jdGlvbicpO1xuXG4gICAgdmFyIGluaXRpYWwgPSBvYmplY3RbcHJvcF07XG4gICAgZm4oKTtcblxuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgb2JqZWN0W3Byb3BdIC0gaW5pdGlhbCA+IDBcbiAgICAgICwgJ2V4cGVjdGVkIC4nICsgcHJvcCArICcgdG8gaW5jcmVhc2UnXG4gICAgICAsICdleHBlY3RlZCAuJyArIHByb3AgKyAnIHRvIG5vdCBpbmNyZWFzZSdcbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZENoYWluYWJsZU1ldGhvZCgnaW5jcmVhc2UnLCBhc3NlcnRJbmNyZWFzZXMpO1xuICBBc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdpbmNyZWFzZXMnLCBhc3NlcnRJbmNyZWFzZXMpO1xuXG4gIC8qKlxuICAgKiAjIyMgLmRlY3JlYXNlKGZ1bmN0aW9uKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYSBmdW5jdGlvbiBkZWNyZWFzZXMgYW4gb2JqZWN0IHByb3BlcnR5XG4gICAqXG4gICAqICAgICB2YXIgb2JqID0geyB2YWw6IDEwIH07XG4gICAqICAgICB2YXIgZm4gPSBmdW5jdGlvbigpIHsgb2JqLnZhbCA9IDUgfTtcbiAgICogICAgIGV4cGVjdChmbikudG8uZGVjcmVhc2Uob2JqLCAndmFsJyk7XG4gICAqXG4gICAqIEBuYW1lIGRlY3JlYXNlXG4gICAqIEBhbGlhcyBkZWNyZWFzZXNcbiAgICogQGFsaWFzIERlY3JlYXNlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnREZWNyZWFzZXMgKG9iamVjdCwgcHJvcCwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIGZuID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgbmV3IEFzc2VydGlvbihvYmplY3QsIG1zZykudG8uaGF2ZS5wcm9wZXJ0eShwcm9wKTtcbiAgICBuZXcgQXNzZXJ0aW9uKGZuKS5pcy5hKCdmdW5jdGlvbicpO1xuXG4gICAgdmFyIGluaXRpYWwgPSBvYmplY3RbcHJvcF07XG4gICAgZm4oKTtcblxuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgb2JqZWN0W3Byb3BdIC0gaW5pdGlhbCA8IDBcbiAgICAgICwgJ2V4cGVjdGVkIC4nICsgcHJvcCArICcgdG8gZGVjcmVhc2UnXG4gICAgICAsICdleHBlY3RlZCAuJyArIHByb3AgKyAnIHRvIG5vdCBkZWNyZWFzZSdcbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZENoYWluYWJsZU1ldGhvZCgnZGVjcmVhc2UnLCBhc3NlcnREZWNyZWFzZXMpO1xuICBBc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdkZWNyZWFzZXMnLCBhc3NlcnREZWNyZWFzZXMpO1xuXG59O1xuIiwiLyohXG4gKiBjaGFpXG4gKiBDb3B5cmlnaHQoYykgMjAxMS0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjaGFpLCB1dGlsKSB7XG5cbiAgLyohXG4gICAqIENoYWkgZGVwZW5kZW5jaWVzLlxuICAgKi9cblxuICB2YXIgQXNzZXJ0aW9uID0gY2hhaS5Bc3NlcnRpb25cbiAgICAsIGZsYWcgPSB1dGlsLmZsYWc7XG5cbiAgLyohXG4gICAqIE1vZHVsZSBleHBvcnQuXG4gICAqL1xuXG4gIC8qKlxuICAgKiAjIyMgYXNzZXJ0KGV4cHJlc3Npb24sIG1lc3NhZ2UpXG4gICAqXG4gICAqIFdyaXRlIHlvdXIgb3duIHRlc3QgZXhwcmVzc2lvbnMuXG4gICAqXG4gICAqICAgICBhc3NlcnQoJ2ZvbycgIT09ICdiYXInLCAnZm9vIGlzIG5vdCBiYXInKTtcbiAgICogICAgIGFzc2VydChBcnJheS5pc0FycmF5KFtdKSwgJ2VtcHR5IGFycmF5cyBhcmUgYXJyYXlzJyk7XG4gICAqXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGV4cHJlc3Npb24gdG8gdGVzdCBmb3IgdHJ1dGhpbmVzc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSB0byBkaXNwbGF5IG9uIGVycm9yXG4gICAqIEBuYW1lIGFzc2VydFxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICB2YXIgYXNzZXJ0ID0gY2hhaS5hc3NlcnQgPSBmdW5jdGlvbiAoZXhwcmVzcywgZXJybXNnKSB7XG4gICAgdmFyIHRlc3QgPSBuZXcgQXNzZXJ0aW9uKG51bGwsIG51bGwsIGNoYWkuYXNzZXJ0KTtcbiAgICB0ZXN0LmFzc2VydChcbiAgICAgICAgZXhwcmVzc1xuICAgICAgLCBlcnJtc2dcbiAgICAgICwgJ1sgbmVnYXRpb24gbWVzc2FnZSB1bmF2YWlsYWJsZSBdJ1xuICAgICk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBbbWVzc2FnZV0sIFtvcGVyYXRvcl0pXG4gICAqXG4gICAqIFRocm93IGEgZmFpbHVyZS4gTm9kZS5qcyBgYXNzZXJ0YCBtb2R1bGUtY29tcGF0aWJsZS5cbiAgICpcbiAgICogQG5hbWUgZmFpbFxuICAgKiBAcGFyYW0ge01peGVkfSBhY3R1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gZXhwZWN0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQHBhcmFtIHtTdHJpbmd9IG9wZXJhdG9yXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5mYWlsID0gZnVuY3Rpb24gKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UsIG9wZXJhdG9yKSB7XG4gICAgbWVzc2FnZSA9IG1lc3NhZ2UgfHwgJ2Fzc2VydC5mYWlsKCknO1xuICAgIHRocm93IG5ldyBjaGFpLkFzc2VydGlvbkVycm9yKG1lc3NhZ2UsIHtcbiAgICAgICAgYWN0dWFsOiBhY3R1YWxcbiAgICAgICwgZXhwZWN0ZWQ6IGV4cGVjdGVkXG4gICAgICAsIG9wZXJhdG9yOiBvcGVyYXRvclxuICAgIH0sIGFzc2VydC5mYWlsKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5vayhvYmplY3QsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBvYmplY3RgIGlzIHRydXRoeS5cbiAgICpcbiAgICogICAgIGFzc2VydC5vaygnZXZlcnl0aGluZycsICdldmVyeXRoaW5nIGlzIG9rJyk7XG4gICAqICAgICBhc3NlcnQub2soZmFsc2UsICd0aGlzIHdpbGwgZmFpbCcpO1xuICAgKlxuICAgKiBAbmFtZSBva1xuICAgKiBAcGFyYW0ge01peGVkfSBvYmplY3QgdG8gdGVzdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQub2sgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS5pcy5vaztcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5ub3RPayhvYmplY3QsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBvYmplY3RgIGlzIGZhbHN5LlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm5vdE9rKCdldmVyeXRoaW5nJywgJ3RoaXMgd2lsbCBmYWlsJyk7XG4gICAqICAgICBhc3NlcnQubm90T2soZmFsc2UsICd0aGlzIHdpbGwgcGFzcycpO1xuICAgKlxuICAgKiBAbmFtZSBub3RPa1xuICAgKiBAcGFyYW0ge01peGVkfSBvYmplY3QgdG8gdGVzdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubm90T2sgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS5pcy5ub3Qub2s7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuZXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIG5vbi1zdHJpY3QgZXF1YWxpdHkgKGA9PWApIG9mIGBhY3R1YWxgIGFuZCBgZXhwZWN0ZWRgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LmVxdWFsKDMsICczJywgJz09IGNvZXJjZXMgdmFsdWVzIHRvIHN0cmluZ3MnKTtcbiAgICpcbiAgICogQG5hbWUgZXF1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gYWN0dWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5lcXVhbCA9IGZ1bmN0aW9uIChhY3QsIGV4cCwgbXNnKSB7XG4gICAgdmFyIHRlc3QgPSBuZXcgQXNzZXJ0aW9uKGFjdCwgbXNnLCBhc3NlcnQuZXF1YWwpO1xuXG4gICAgdGVzdC5hc3NlcnQoXG4gICAgICAgIGV4cCA9PSBmbGFnKHRlc3QsICdvYmplY3QnKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBlcXVhbCAje2V4cH0nXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBlcXVhbCAje2FjdH0nXG4gICAgICAsIGV4cFxuICAgICAgLCBhY3RcbiAgICApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyBub24tc3RyaWN0IGluZXF1YWxpdHkgKGAhPWApIG9mIGBhY3R1YWxgIGFuZCBgZXhwZWN0ZWRgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm5vdEVxdWFsKDMsIDQsICd0aGVzZSBudW1iZXJzIGFyZSBub3QgZXF1YWwnKTtcbiAgICpcbiAgICogQG5hbWUgbm90RXF1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gYWN0dWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5ub3RFcXVhbCA9IGZ1bmN0aW9uIChhY3QsIGV4cCwgbXNnKSB7XG4gICAgdmFyIHRlc3QgPSBuZXcgQXNzZXJ0aW9uKGFjdCwgbXNnLCBhc3NlcnQubm90RXF1YWwpO1xuXG4gICAgdGVzdC5hc3NlcnQoXG4gICAgICAgIGV4cCAhPSBmbGFnKHRlc3QsICdvYmplY3QnKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgZXF1YWwgI3tleHB9J1xuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBlcXVhbCAje2FjdH0nXG4gICAgICAsIGV4cFxuICAgICAgLCBhY3RcbiAgICApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLnN0cmljdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyBzdHJpY3QgZXF1YWxpdHkgKGA9PT1gKSBvZiBgYWN0dWFsYCBhbmQgYGV4cGVjdGVkYC5cbiAgICpcbiAgICogICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0cnVlLCB0cnVlLCAndGhlc2UgYm9vbGVhbnMgYXJlIHN0cmljdGx5IGVxdWFsJyk7XG4gICAqXG4gICAqIEBuYW1lIHN0cmljdEVxdWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGFjdHVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBleHBlY3RlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuc3RyaWN0RXF1YWwgPSBmdW5jdGlvbiAoYWN0LCBleHAsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24oYWN0LCBtc2cpLnRvLmVxdWFsKGV4cCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAubm90U3RyaWN0RXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHN0cmljdCBpbmVxdWFsaXR5IChgIT09YCkgb2YgYGFjdHVhbGAgYW5kIGBleHBlY3RlZGAuXG4gICAqXG4gICAqICAgICBhc3NlcnQubm90U3RyaWN0RXF1YWwoMywgJzMnLCAnbm8gY29lcmNpb24gZm9yIHN0cmljdCBlcXVhbGl0eScpO1xuICAgKlxuICAgKiBAbmFtZSBub3RTdHJpY3RFcXVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBhY3R1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gZXhwZWN0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm5vdFN0cmljdEVxdWFsID0gZnVuY3Rpb24gKGFjdCwgZXhwLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGFjdCwgbXNnKS50by5ub3QuZXF1YWwoZXhwKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5kZWVwRXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYGFjdHVhbGAgaXMgZGVlcGx5IGVxdWFsIHRvIGBleHBlY3RlZGAuXG4gICAqXG4gICAqICAgICBhc3NlcnQuZGVlcEVxdWFsKHsgdGVhOiAnZ3JlZW4nIH0sIHsgdGVhOiAnZ3JlZW4nIH0pO1xuICAgKlxuICAgKiBAbmFtZSBkZWVwRXF1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gYWN0dWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5kZWVwRXF1YWwgPSBmdW5jdGlvbiAoYWN0LCBleHAsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24oYWN0LCBtc2cpLnRvLmVxbChleHApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdERlZXBFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydCB0aGF0IGBhY3R1YWxgIGlzIG5vdCBkZWVwbHkgZXF1YWwgdG8gYGV4cGVjdGVkYC5cbiAgICpcbiAgICogICAgIGFzc2VydC5ub3REZWVwRXF1YWwoeyB0ZWE6ICdncmVlbicgfSwgeyB0ZWE6ICdqYXNtaW5lJyB9KTtcbiAgICpcbiAgICogQG5hbWUgbm90RGVlcEVxdWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGFjdHVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBleHBlY3RlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubm90RGVlcEVxdWFsID0gZnVuY3Rpb24gKGFjdCwgZXhwLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGFjdCwgbXNnKS50by5ub3QuZXFsKGV4cCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNUcnVlKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIHRydWUuXG4gICAqXG4gICAqICAgICB2YXIgdGVhU2VydmVkID0gdHJ1ZTtcbiAgICogICAgIGFzc2VydC5pc1RydWUodGVhU2VydmVkLCAndGhlIHRlYSBoYXMgYmVlbiBzZXJ2ZWQnKTtcbiAgICpcbiAgICogQG5hbWUgaXNUcnVlXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc0Fib3ZlID0gZnVuY3Rpb24gKHZhbCwgYWJ2LCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5iZS5hYm92ZShhYnYpO1xuICB9O1xuXG4gICAvKipcbiAgICogIyMjIC5pc0Fib3ZlKHZhbHVlVG9DaGVjaywgdmFsdWVUb0JlQWJvdmUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyBgdmFsdWVUb0NoZWNrYCBpcyBzdHJpY3RseSBncmVhdGVyIHRoYW4gKD4pIGB2YWx1ZVRvQmVBYm92ZWBcbiAgICpcbiAgICogICAgIGFzc2VydC5pc0Fib3ZlKDUsIDIsICc1IGlzIHN0cmljdGx5IGdyZWF0ZXIgdGhhbiAyJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzQWJvdmVcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVUb0NoZWNrXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlVG9CZUFib3ZlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc0JlbG93ID0gZnVuY3Rpb24gKHZhbCwgYmx3LCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5iZS5iZWxvdyhibHcpO1xuICB9O1xuXG4gICAvKipcbiAgICogIyMjIC5pc0JlbG93KHZhbHVlVG9DaGVjaywgdmFsdWVUb0JlQmVsb3csIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyBgdmFsdWVUb0NoZWNrYCBpcyBzdHJpY3RseSBsZXNzIHRoYW4gKDwpIGB2YWx1ZVRvQmVCZWxvd2BcbiAgICpcbiAgICogICAgIGFzc2VydC5pc0JlbG93KDMsIDYsICczIGlzIHN0cmljdGx5IGxlc3MgdGhhbiA2Jyk7XG4gICAqXG4gICAqIEBuYW1lIGlzQmVsb3dcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVUb0NoZWNrXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlVG9CZUJlbG93XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc1RydWUgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS5pc1sndHJ1ZSddO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzRmFsc2UodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgZmFsc2UuXG4gICAqXG4gICAqICAgICB2YXIgdGVhU2VydmVkID0gZmFsc2U7XG4gICAqICAgICBhc3NlcnQuaXNGYWxzZSh0ZWFTZXJ2ZWQsICdubyB0ZWEgeWV0PyBobW0uLi4nKTtcbiAgICpcbiAgICogQG5hbWUgaXNGYWxzZVxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNGYWxzZSA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLmlzWydmYWxzZSddO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzTnVsbCh2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBudWxsLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LmlzTnVsbChlcnIsICd0aGVyZSB3YXMgbm8gZXJyb3InKTtcbiAgICpcbiAgICogQG5hbWUgaXNOdWxsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc051bGwgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5lcXVhbChudWxsKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc05vdE51bGwodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgbm90IG51bGwuXG4gICAqXG4gICAqICAgICB2YXIgdGVhID0gJ3Rhc3R5IGNoYWknO1xuICAgKiAgICAgYXNzZXJ0LmlzTm90TnVsbCh0ZWEsICdncmVhdCwgdGltZSBmb3IgdGVhIScpO1xuICAgKlxuICAgKiBAbmFtZSBpc05vdE51bGxcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzTm90TnVsbCA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLm5vdC5lcXVhbChudWxsKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc1VuZGVmaW5lZCh2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBgdW5kZWZpbmVkYC5cbiAgICpcbiAgICogICAgIHZhciB0ZWE7XG4gICAqICAgICBhc3NlcnQuaXNVbmRlZmluZWQodGVhLCAnbm8gdGVhIGRlZmluZWQnKTtcbiAgICpcbiAgICogQG5hbWUgaXNVbmRlZmluZWRcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzVW5kZWZpbmVkID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uZXF1YWwodW5kZWZpbmVkKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc0RlZmluZWQodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgbm90IGB1bmRlZmluZWRgLlxuICAgKlxuICAgKiAgICAgdmFyIHRlYSA9ICdjdXAgb2YgY2hhaSc7XG4gICAqICAgICBhc3NlcnQuaXNEZWZpbmVkKHRlYSwgJ3RlYSBoYXMgYmVlbiBkZWZpbmVkJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzRGVmaW5lZFxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNEZWZpbmVkID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8ubm90LmVxdWFsKHVuZGVmaW5lZCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNGdW5jdGlvbih2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBhIGZ1bmN0aW9uLlxuICAgKlxuICAgKiAgICAgZnVuY3Rpb24gc2VydmVUZWEoKSB7IHJldHVybiAnY3VwIG9mIHRlYSc7IH07XG4gICAqICAgICBhc3NlcnQuaXNGdW5jdGlvbihzZXJ2ZVRlYSwgJ2dyZWF0LCB3ZSBjYW4gaGF2ZSB0ZWEgbm93Jyk7XG4gICAqXG4gICAqIEBuYW1lIGlzRnVuY3Rpb25cbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzRnVuY3Rpb24gPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5iZS5hKCdmdW5jdGlvbicpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzTm90RnVuY3Rpb24odmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgX25vdF8gYSBmdW5jdGlvbi5cbiAgICpcbiAgICogICAgIHZhciBzZXJ2ZVRlYSA9IFsgJ2hlYXQnLCAncG91cicsICdzaXAnIF07XG4gICAqICAgICBhc3NlcnQuaXNOb3RGdW5jdGlvbihzZXJ2ZVRlYSwgJ2dyZWF0LCB3ZSBoYXZlIGxpc3RlZCB0aGUgc3RlcHMnKTtcbiAgICpcbiAgICogQG5hbWUgaXNOb3RGdW5jdGlvblxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNOb3RGdW5jdGlvbiA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLm5vdC5iZS5hKCdmdW5jdGlvbicpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzT2JqZWN0KHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIGFuIG9iamVjdCAoYXMgcmV2ZWFsZWQgYnlcbiAgICogYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdgKS5cbiAgICpcbiAgICogICAgIHZhciBzZWxlY3Rpb24gPSB7IG5hbWU6ICdDaGFpJywgc2VydmU6ICd3aXRoIHNwaWNlcycgfTtcbiAgICogICAgIGFzc2VydC5pc09iamVjdChzZWxlY3Rpb24sICd0ZWEgc2VsZWN0aW9uIGlzIGFuIG9iamVjdCcpO1xuICAgKlxuICAgKiBAbmFtZSBpc09iamVjdFxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNPYmplY3QgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5iZS5hKCdvYmplY3QnKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc05vdE9iamVjdCh2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBfbm90XyBhbiBvYmplY3QuXG4gICAqXG4gICAqICAgICB2YXIgc2VsZWN0aW9uID0gJ2NoYWknXG4gICAqICAgICBhc3NlcnQuaXNOb3RPYmplY3Qoc2VsZWN0aW9uLCAndGVhIHNlbGVjdGlvbiBpcyBub3QgYW4gb2JqZWN0Jyk7XG4gICAqICAgICBhc3NlcnQuaXNOb3RPYmplY3QobnVsbCwgJ251bGwgaXMgbm90IGFuIG9iamVjdCcpO1xuICAgKlxuICAgKiBAbmFtZSBpc05vdE9iamVjdFxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNOb3RPYmplY3QgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuYSgnb2JqZWN0Jyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNBcnJheSh2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBhbiBhcnJheS5cbiAgICpcbiAgICogICAgIHZhciBtZW51ID0gWyAnZ3JlZW4nLCAnY2hhaScsICdvb2xvbmcnIF07XG4gICAqICAgICBhc3NlcnQuaXNBcnJheShtZW51LCAnd2hhdCBraW5kIG9mIHRlYSBkbyB3ZSB3YW50PycpO1xuICAgKlxuICAgKiBAbmFtZSBpc0FycmF5XG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc0FycmF5ID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uYmUuYW4oJ2FycmF5Jyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNOb3RBcnJheSh2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBfbm90XyBhbiBhcnJheS5cbiAgICpcbiAgICogICAgIHZhciBtZW51ID0gJ2dyZWVufGNoYWl8b29sb25nJztcbiAgICogICAgIGFzc2VydC5pc05vdEFycmF5KG1lbnUsICd3aGF0IGtpbmQgb2YgdGVhIGRvIHdlIHdhbnQ/Jyk7XG4gICAqXG4gICAqIEBuYW1lIGlzTm90QXJyYXlcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzTm90QXJyYXkgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuYW4oJ2FycmF5Jyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNTdHJpbmcodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgYSBzdHJpbmcuXG4gICAqXG4gICAqICAgICB2YXIgdGVhT3JkZXIgPSAnY2hhaSc7XG4gICAqICAgICBhc3NlcnQuaXNTdHJpbmcodGVhT3JkZXIsICdvcmRlciBwbGFjZWQnKTtcbiAgICpcbiAgICogQG5hbWUgaXNTdHJpbmdcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzU3RyaW5nID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uYmUuYSgnc3RyaW5nJyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNOb3RTdHJpbmcodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgX25vdF8gYSBzdHJpbmcuXG4gICAqXG4gICAqICAgICB2YXIgdGVhT3JkZXIgPSA0O1xuICAgKiAgICAgYXNzZXJ0LmlzTm90U3RyaW5nKHRlYU9yZGVyLCAnb3JkZXIgcGxhY2VkJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzTm90U3RyaW5nXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc05vdFN0cmluZyA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLm5vdC5iZS5hKCdzdHJpbmcnKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc051bWJlcih2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBhIG51bWJlci5cbiAgICpcbiAgICogICAgIHZhciBjdXBzID0gMjtcbiAgICogICAgIGFzc2VydC5pc051bWJlcihjdXBzLCAnaG93IG1hbnkgY3VwcycpO1xuICAgKlxuICAgKiBAbmFtZSBpc051bWJlclxuICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzTnVtYmVyID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uYmUuYSgnbnVtYmVyJyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNOb3ROdW1iZXIodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgX25vdF8gYSBudW1iZXIuXG4gICAqXG4gICAqICAgICB2YXIgY3VwcyA9ICcyIGN1cHMgcGxlYXNlJztcbiAgICogICAgIGFzc2VydC5pc05vdE51bWJlcihjdXBzLCAnaG93IG1hbnkgY3VwcycpO1xuICAgKlxuICAgKiBAbmFtZSBpc05vdE51bWJlclxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNOb3ROdW1iZXIgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuYSgnbnVtYmVyJyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNCb29sZWFuKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIGEgYm9vbGVhbi5cbiAgICpcbiAgICogICAgIHZhciB0ZWFSZWFkeSA9IHRydWVcbiAgICogICAgICAgLCB0ZWFTZXJ2ZWQgPSBmYWxzZTtcbiAgICpcbiAgICogICAgIGFzc2VydC5pc0Jvb2xlYW4odGVhUmVhZHksICdpcyB0aGUgdGVhIHJlYWR5Jyk7XG4gICAqICAgICBhc3NlcnQuaXNCb29sZWFuKHRlYVNlcnZlZCwgJ2hhcyB0ZWEgYmVlbiBzZXJ2ZWQnKTtcbiAgICpcbiAgICogQG5hbWUgaXNCb29sZWFuXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc0Jvb2xlYW4gPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5iZS5hKCdib29sZWFuJyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNOb3RCb29sZWFuKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIF9ub3RfIGEgYm9vbGVhbi5cbiAgICpcbiAgICogICAgIHZhciB0ZWFSZWFkeSA9ICd5ZXAnXG4gICAqICAgICAgICwgdGVhU2VydmVkID0gJ25vcGUnO1xuICAgKlxuICAgKiAgICAgYXNzZXJ0LmlzTm90Qm9vbGVhbih0ZWFSZWFkeSwgJ2lzIHRoZSB0ZWEgcmVhZHknKTtcbiAgICogICAgIGFzc2VydC5pc05vdEJvb2xlYW4odGVhU2VydmVkLCAnaGFzIHRlYSBiZWVuIHNlcnZlZCcpO1xuICAgKlxuICAgKiBAbmFtZSBpc05vdEJvb2xlYW5cbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzTm90Qm9vbGVhbiA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLm5vdC5iZS5hKCdib29sZWFuJyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAudHlwZU9mKHZhbHVlLCBuYW1lLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgJ3MgdHlwZSBpcyBgbmFtZWAsIGFzIGRldGVybWluZWQgYnlcbiAgICogYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LnR5cGVPZih7IHRlYTogJ2NoYWknIH0sICdvYmplY3QnLCAnd2UgaGF2ZSBhbiBvYmplY3QnKTtcbiAgICogICAgIGFzc2VydC50eXBlT2YoWydjaGFpJywgJ2phc21pbmUnXSwgJ2FycmF5JywgJ3dlIGhhdmUgYW4gYXJyYXknKTtcbiAgICogICAgIGFzc2VydC50eXBlT2YoJ3RlYScsICdzdHJpbmcnLCAnd2UgaGF2ZSBhIHN0cmluZycpO1xuICAgKiAgICAgYXNzZXJ0LnR5cGVPZigvdGVhLywgJ3JlZ2V4cCcsICd3ZSBoYXZlIGEgcmVndWxhciBleHByZXNzaW9uJyk7XG4gICAqICAgICBhc3NlcnQudHlwZU9mKG51bGwsICdudWxsJywgJ3dlIGhhdmUgYSBudWxsJyk7XG4gICAqICAgICBhc3NlcnQudHlwZU9mKHVuZGVmaW5lZCwgJ3VuZGVmaW5lZCcsICd3ZSBoYXZlIGFuIHVuZGVmaW5lZCcpO1xuICAgKlxuICAgKiBAbmFtZSB0eXBlT2ZcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LnR5cGVPZiA9IGZ1bmN0aW9uICh2YWwsIHR5cGUsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLmJlLmEodHlwZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAubm90VHlwZU9mKHZhbHVlLCBuYW1lLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgJ3MgdHlwZSBpcyBfbm90XyBgbmFtZWAsIGFzIGRldGVybWluZWQgYnlcbiAgICogYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm5vdFR5cGVPZigndGVhJywgJ251bWJlcicsICdzdHJpbmdzIGFyZSBub3QgbnVtYmVycycpO1xuICAgKlxuICAgKiBAbmFtZSBub3RUeXBlT2ZcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IHR5cGVvZiBuYW1lXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5ub3RUeXBlT2YgPSBmdW5jdGlvbiAodmFsLCB0eXBlLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuYSh0eXBlKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pbnN0YW5jZU9mKG9iamVjdCwgY29uc3RydWN0b3IsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgYW4gaW5zdGFuY2Ugb2YgYGNvbnN0cnVjdG9yYC5cbiAgICpcbiAgICogICAgIHZhciBUZWEgPSBmdW5jdGlvbiAobmFtZSkgeyB0aGlzLm5hbWUgPSBuYW1lOyB9XG4gICAqICAgICAgICwgY2hhaSA9IG5ldyBUZWEoJ2NoYWknKTtcbiAgICpcbiAgICogICAgIGFzc2VydC5pbnN0YW5jZU9mKGNoYWksIFRlYSwgJ2NoYWkgaXMgYW4gaW5zdGFuY2Ugb2YgdGVhJyk7XG4gICAqXG4gICAqIEBuYW1lIGluc3RhbmNlT2ZcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yfSBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaW5zdGFuY2VPZiA9IGZ1bmN0aW9uICh2YWwsIHR5cGUsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLmJlLmluc3RhbmNlT2YodHlwZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAubm90SW5zdGFuY2VPZihvYmplY3QsIGNvbnN0cnVjdG9yLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgYHZhbHVlYCBpcyBub3QgYW4gaW5zdGFuY2Ugb2YgYGNvbnN0cnVjdG9yYC5cbiAgICpcbiAgICogICAgIHZhciBUZWEgPSBmdW5jdGlvbiAobmFtZSkgeyB0aGlzLm5hbWUgPSBuYW1lOyB9XG4gICAqICAgICAgICwgY2hhaSA9IG5ldyBTdHJpbmcoJ2NoYWknKTtcbiAgICpcbiAgICogICAgIGFzc2VydC5ub3RJbnN0YW5jZU9mKGNoYWksIFRlYSwgJ2NoYWkgaXMgbm90IGFuIGluc3RhbmNlIG9mIHRlYScpO1xuICAgKlxuICAgKiBAbmFtZSBub3RJbnN0YW5jZU9mXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm5vdEluc3RhbmNlT2YgPSBmdW5jdGlvbiAodmFsLCB0eXBlLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuaW5zdGFuY2VPZih0eXBlKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pbmNsdWRlKGhheXN0YWNrLCBuZWVkbGUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBoYXlzdGFja2AgaW5jbHVkZXMgYG5lZWRsZWAuIFdvcmtzXG4gICAqIGZvciBzdHJpbmdzIGFuZCBhcnJheXMuXG4gICAqXG4gICAqICAgICBhc3NlcnQuaW5jbHVkZSgnZm9vYmFyJywgJ2JhcicsICdmb29iYXIgY29udGFpbnMgc3RyaW5nIFwiYmFyXCInKTtcbiAgICogICAgIGFzc2VydC5pbmNsdWRlKFsgMSwgMiwgMyBdLCAzLCAnYXJyYXkgY29udGFpbnMgdmFsdWUnKTtcbiAgICpcbiAgICogQG5hbWUgaW5jbHVkZVxuICAgKiBAcGFyYW0ge0FycmF5fFN0cmluZ30gaGF5c3RhY2tcbiAgICogQHBhcmFtIHtNaXhlZH0gbmVlZGxlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pbmNsdWRlID0gZnVuY3Rpb24gKGV4cCwgaW5jLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGV4cCwgbXNnLCBhc3NlcnQuaW5jbHVkZSkuaW5jbHVkZShpbmMpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdEluY2x1ZGUoaGF5c3RhY2ssIG5lZWRsZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYGhheXN0YWNrYCBkb2VzIG5vdCBpbmNsdWRlIGBuZWVkbGVgLiBXb3Jrc1xuICAgKiBmb3Igc3RyaW5ncyBhbmQgYXJyYXlzLlxuICAgKmlcbiAgICogICAgIGFzc2VydC5ub3RJbmNsdWRlKCdmb29iYXInLCAnYmF6JywgJ3N0cmluZyBub3QgaW5jbHVkZSBzdWJzdHJpbmcnKTtcbiAgICogICAgIGFzc2VydC5ub3RJbmNsdWRlKFsgMSwgMiwgMyBdLCA0LCAnYXJyYXkgbm90IGluY2x1ZGUgY29udGFpbiB2YWx1ZScpO1xuICAgKlxuICAgKiBAbmFtZSBub3RJbmNsdWRlXG4gICAqIEBwYXJhbSB7QXJyYXl8U3RyaW5nfSBoYXlzdGFja1xuICAgKiBAcGFyYW0ge01peGVkfSBuZWVkbGVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm5vdEluY2x1ZGUgPSBmdW5jdGlvbiAoZXhwLCBpbmMsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24oZXhwLCBtc2csIGFzc2VydC5ub3RJbmNsdWRlKS5ub3QuaW5jbHVkZShpbmMpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm1hdGNoKHZhbHVlLCByZWdleHAsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgbWF0Y2hlcyB0aGUgcmVndWxhciBleHByZXNzaW9uIGByZWdleHBgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm1hdGNoKCdmb29iYXInLCAvXmZvby8sICdyZWdleHAgbWF0Y2hlcycpO1xuICAgKlxuICAgKiBAbmFtZSBtYXRjaFxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1JlZ0V4cH0gcmVnZXhwXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5tYXRjaCA9IGZ1bmN0aW9uIChleHAsIHJlLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGV4cCwgbXNnKS50by5tYXRjaChyZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAubm90TWF0Y2godmFsdWUsIHJlZ2V4cCwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBkb2VzIG5vdCBtYXRjaCB0aGUgcmVndWxhciBleHByZXNzaW9uIGByZWdleHBgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm5vdE1hdGNoKCdmb29iYXInLCAvXmZvby8sICdyZWdleHAgZG9lcyBub3QgbWF0Y2gnKTtcbiAgICpcbiAgICogQG5hbWUgbm90TWF0Y2hcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtSZWdFeHB9IHJlZ2V4cFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubm90TWF0Y2ggPSBmdW5jdGlvbiAoZXhwLCByZSwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihleHAsIG1zZykudG8ubm90Lm1hdGNoKHJlKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5wcm9wZXJ0eShvYmplY3QsIHByb3BlcnR5LCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgb2JqZWN0YCBoYXMgYSBwcm9wZXJ0eSBuYW1lZCBieSBgcHJvcGVydHlgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LnByb3BlcnR5KHsgdGVhOiB7IGdyZWVuOiAnbWF0Y2hhJyB9fSwgJ3RlYScpO1xuICAgKlxuICAgKiBAbmFtZSBwcm9wZXJ0eVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQucHJvcGVydHkgPSBmdW5jdGlvbiAob2JqLCBwcm9wLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5oYXZlLnByb3BlcnR5KHByb3ApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdFByb3BlcnR5KG9iamVjdCwgcHJvcGVydHksIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBvYmplY3RgIGRvZXMgX25vdF8gaGF2ZSBhIHByb3BlcnR5IG5hbWVkIGJ5IGBwcm9wZXJ0eWAuXG4gICAqXG4gICAqICAgICBhc3NlcnQubm90UHJvcGVydHkoeyB0ZWE6IHsgZ3JlZW46ICdtYXRjaGEnIH19LCAnY29mZmVlJyk7XG4gICAqXG4gICAqIEBuYW1lIG5vdFByb3BlcnR5XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5ub3RQcm9wZXJ0eSA9IGZ1bmN0aW9uIChvYmosIHByb3AsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24ob2JqLCBtc2cpLnRvLm5vdC5oYXZlLnByb3BlcnR5KHByb3ApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmRlZXBQcm9wZXJ0eShvYmplY3QsIHByb3BlcnR5LCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgb2JqZWN0YCBoYXMgYSBwcm9wZXJ0eSBuYW1lZCBieSBgcHJvcGVydHlgLCB3aGljaCBjYW4gYmUgYVxuICAgKiBzdHJpbmcgdXNpbmcgZG90LSBhbmQgYnJhY2tldC1ub3RhdGlvbiBmb3IgZGVlcCByZWZlcmVuY2UuXG4gICAqXG4gICAqICAgICBhc3NlcnQuZGVlcFByb3BlcnR5KHsgdGVhOiB7IGdyZWVuOiAnbWF0Y2hhJyB9fSwgJ3RlYS5ncmVlbicpO1xuICAgKlxuICAgKiBAbmFtZSBkZWVwUHJvcGVydHlcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmRlZXBQcm9wZXJ0eSA9IGZ1bmN0aW9uIChvYmosIHByb3AsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24ob2JqLCBtc2cpLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eShwcm9wKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5ub3REZWVwUHJvcGVydHkob2JqZWN0LCBwcm9wZXJ0eSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYG9iamVjdGAgZG9lcyBfbm90XyBoYXZlIGEgcHJvcGVydHkgbmFtZWQgYnkgYHByb3BlcnR5YCwgd2hpY2hcbiAgICogY2FuIGJlIGEgc3RyaW5nIHVzaW5nIGRvdC0gYW5kIGJyYWNrZXQtbm90YXRpb24gZm9yIGRlZXAgcmVmZXJlbmNlLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm5vdERlZXBQcm9wZXJ0eSh7IHRlYTogeyBncmVlbjogJ21hdGNoYScgfX0sICd0ZWEub29sb25nJyk7XG4gICAqXG4gICAqIEBuYW1lIG5vdERlZXBQcm9wZXJ0eVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubm90RGVlcFByb3BlcnR5ID0gZnVuY3Rpb24gKG9iaiwgcHJvcCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8ubm90LmhhdmUuZGVlcC5wcm9wZXJ0eShwcm9wKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5wcm9wZXJ0eVZhbChvYmplY3QsIHByb3BlcnR5LCB2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYG9iamVjdGAgaGFzIGEgcHJvcGVydHkgbmFtZWQgYnkgYHByb3BlcnR5YCB3aXRoIHZhbHVlIGdpdmVuXG4gICAqIGJ5IGB2YWx1ZWAuXG4gICAqXG4gICAqICAgICBhc3NlcnQucHJvcGVydHlWYWwoeyB0ZWE6ICdpcyBnb29kJyB9LCAndGVhJywgJ2lzIGdvb2QnKTtcbiAgICpcbiAgICogQG5hbWUgcHJvcGVydHlWYWxcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LnByb3BlcnR5VmFsID0gZnVuY3Rpb24gKG9iaiwgcHJvcCwgdmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5oYXZlLnByb3BlcnR5KHByb3AsIHZhbCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAucHJvcGVydHlOb3RWYWwob2JqZWN0LCBwcm9wZXJ0eSwgdmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBvYmplY3RgIGhhcyBhIHByb3BlcnR5IG5hbWVkIGJ5IGBwcm9wZXJ0eWAsIGJ1dCB3aXRoIGEgdmFsdWVcbiAgICogZGlmZmVyZW50IGZyb20gdGhhdCBnaXZlbiBieSBgdmFsdWVgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LnByb3BlcnR5Tm90VmFsKHsgdGVhOiAnaXMgZ29vZCcgfSwgJ3RlYScsICdpcyBiYWQnKTtcbiAgICpcbiAgICogQG5hbWUgcHJvcGVydHlOb3RWYWxcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LnByb3BlcnR5Tm90VmFsID0gZnVuY3Rpb24gKG9iaiwgcHJvcCwgdmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5ub3QuaGF2ZS5wcm9wZXJ0eShwcm9wLCB2YWwpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmRlZXBQcm9wZXJ0eVZhbChvYmplY3QsIHByb3BlcnR5LCB2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYG9iamVjdGAgaGFzIGEgcHJvcGVydHkgbmFtZWQgYnkgYHByb3BlcnR5YCB3aXRoIHZhbHVlIGdpdmVuXG4gICAqIGJ5IGB2YWx1ZWAuIGBwcm9wZXJ0eWAgY2FuIHVzZSBkb3QtIGFuZCBicmFja2V0LW5vdGF0aW9uIGZvciBkZWVwXG4gICAqIHJlZmVyZW5jZS5cbiAgICpcbiAgICogICAgIGFzc2VydC5kZWVwUHJvcGVydHlWYWwoeyB0ZWE6IHsgZ3JlZW46ICdtYXRjaGEnIH19LCAndGVhLmdyZWVuJywgJ21hdGNoYScpO1xuICAgKlxuICAgKiBAbmFtZSBkZWVwUHJvcGVydHlWYWxcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmRlZXBQcm9wZXJ0eVZhbCA9IGZ1bmN0aW9uIChvYmosIHByb3AsIHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5kZWVwLnByb3BlcnR5KHByb3AsIHZhbCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuZGVlcFByb3BlcnR5Tm90VmFsKG9iamVjdCwgcHJvcGVydHksIHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgb2JqZWN0YCBoYXMgYSBwcm9wZXJ0eSBuYW1lZCBieSBgcHJvcGVydHlgLCBidXQgd2l0aCBhIHZhbHVlXG4gICAqIGRpZmZlcmVudCBmcm9tIHRoYXQgZ2l2ZW4gYnkgYHZhbHVlYC4gYHByb3BlcnR5YCBjYW4gdXNlIGRvdC0gYW5kXG4gICAqIGJyYWNrZXQtbm90YXRpb24gZm9yIGRlZXAgcmVmZXJlbmNlLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LmRlZXBQcm9wZXJ0eU5vdFZhbCh7IHRlYTogeyBncmVlbjogJ21hdGNoYScgfX0sICd0ZWEuZ3JlZW4nLCAna29uYWNoYScpO1xuICAgKlxuICAgKiBAbmFtZSBkZWVwUHJvcGVydHlOb3RWYWxcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmRlZXBQcm9wZXJ0eU5vdFZhbCA9IGZ1bmN0aW9uIChvYmosIHByb3AsIHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8ubm90LmhhdmUuZGVlcC5wcm9wZXJ0eShwcm9wLCB2YWwpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmxlbmd0aE9mKG9iamVjdCwgbGVuZ3RoLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgb2JqZWN0YCBoYXMgYSBgbGVuZ3RoYCBwcm9wZXJ0eSB3aXRoIHRoZSBleHBlY3RlZCB2YWx1ZS5cbiAgICpcbiAgICogICAgIGFzc2VydC5sZW5ndGhPZihbMSwyLDNdLCAzLCAnYXJyYXkgaGFzIGxlbmd0aCBvZiAzJyk7XG4gICAqICAgICBhc3NlcnQubGVuZ3RoT2YoJ2Zvb2JhcicsIDUsICdzdHJpbmcgaGFzIGxlbmd0aCBvZiA2Jyk7XG4gICAqXG4gICAqIEBuYW1lIGxlbmd0aE9mXG4gICAqIEBwYXJhbSB7TWl4ZWR9IG9iamVjdFxuICAgKiBAcGFyYW0ge051bWJlcn0gbGVuZ3RoXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5sZW5ndGhPZiA9IGZ1bmN0aW9uIChleHAsIGxlbiwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihleHAsIG1zZykudG8uaGF2ZS5sZW5ndGgobGVuKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC50aHJvd3MoZnVuY3Rpb24sIFtjb25zdHJ1Y3Rvci9zdHJpbmcvcmVnZXhwXSwgW3N0cmluZy9yZWdleHBdLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgZnVuY3Rpb25gIHdpbGwgdGhyb3cgYW4gZXJyb3IgdGhhdCBpcyBhbiBpbnN0YW5jZSBvZlxuICAgKiBgY29uc3RydWN0b3JgLCBvciBhbHRlcm5hdGVseSB0aGF0IGl0IHdpbGwgdGhyb3cgYW4gZXJyb3Igd2l0aCBtZXNzYWdlXG4gICAqIG1hdGNoaW5nIGByZWdleHBgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LnRocm93KGZuLCAnZnVuY3Rpb24gdGhyb3dzIGEgcmVmZXJlbmNlIGVycm9yJyk7XG4gICAqICAgICBhc3NlcnQudGhyb3coZm4sIC9mdW5jdGlvbiB0aHJvd3MgYSByZWZlcmVuY2UgZXJyb3IvKTtcbiAgICogICAgIGFzc2VydC50aHJvdyhmbiwgUmVmZXJlbmNlRXJyb3IpO1xuICAgKiAgICAgYXNzZXJ0LnRocm93KGZuLCBSZWZlcmVuY2VFcnJvciwgJ2Z1bmN0aW9uIHRocm93cyBhIHJlZmVyZW5jZSBlcnJvcicpO1xuICAgKiAgICAgYXNzZXJ0LnRocm93KGZuLCBSZWZlcmVuY2VFcnJvciwgL2Z1bmN0aW9uIHRocm93cyBhIHJlZmVyZW5jZSBlcnJvci8pO1xuICAgKlxuICAgKiBAbmFtZSB0aHJvd3NcbiAgICogQGFsaWFzIHRocm93XG4gICAqIEBhbGlhcyBUaHJvd1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jdGlvblxuICAgKiBAcGFyYW0ge0Vycm9yQ29uc3RydWN0b3J9IGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7UmVnRXhwfSByZWdleHBcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9FcnJvciNFcnJvcl90eXBlc1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuVGhyb3cgPSBmdW5jdGlvbiAoZm4sIGVycnQsIGVycnMsIG1zZykge1xuICAgIGlmICgnc3RyaW5nJyA9PT0gdHlwZW9mIGVycnQgfHwgZXJydCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgZXJycyA9IGVycnQ7XG4gICAgICBlcnJ0ID0gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgYXNzZXJ0RXJyID0gbmV3IEFzc2VydGlvbihmbiwgbXNnKS50by5UaHJvdyhlcnJ0LCBlcnJzKTtcbiAgICByZXR1cm4gZmxhZyhhc3NlcnRFcnIsICdvYmplY3QnKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5kb2VzTm90VGhyb3coZnVuY3Rpb24sIFtjb25zdHJ1Y3Rvci9yZWdleHBdLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgZnVuY3Rpb25gIHdpbGwgX25vdF8gdGhyb3cgYW4gZXJyb3IgdGhhdCBpcyBhbiBpbnN0YW5jZSBvZlxuICAgKiBgY29uc3RydWN0b3JgLCBvciBhbHRlcm5hdGVseSB0aGF0IGl0IHdpbGwgbm90IHRocm93IGFuIGVycm9yIHdpdGggbWVzc2FnZVxuICAgKiBtYXRjaGluZyBgcmVnZXhwYC5cbiAgICpcbiAgICogICAgIGFzc2VydC5kb2VzTm90VGhyb3coZm4sIEVycm9yLCAnZnVuY3Rpb24gZG9lcyBub3QgdGhyb3cnKTtcbiAgICpcbiAgICogQG5hbWUgZG9lc05vdFRocm93XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7RXJyb3JDb25zdHJ1Y3Rvcn0gY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtSZWdFeHB9IHJlZ2V4cFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Vycm9yI0Vycm9yX3R5cGVzXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5kb2VzTm90VGhyb3cgPSBmdW5jdGlvbiAoZm4sIHR5cGUsIG1zZykge1xuICAgIGlmICgnc3RyaW5nJyA9PT0gdHlwZW9mIHR5cGUpIHtcbiAgICAgIG1zZyA9IHR5cGU7XG4gICAgICB0eXBlID0gbnVsbDtcbiAgICB9XG5cbiAgICBuZXcgQXNzZXJ0aW9uKGZuLCBtc2cpLnRvLm5vdC5UaHJvdyh0eXBlKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5vcGVyYXRvcih2YWwxLCBvcGVyYXRvciwgdmFsMiwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBDb21wYXJlcyB0d28gdmFsdWVzIHVzaW5nIGBvcGVyYXRvcmAuXG4gICAqXG4gICAqICAgICBhc3NlcnQub3BlcmF0b3IoMSwgJzwnLCAyLCAnZXZlcnl0aGluZyBpcyBvaycpO1xuICAgKiAgICAgYXNzZXJ0Lm9wZXJhdG9yKDEsICc+JywgMiwgJ3RoaXMgd2lsbCBmYWlsJyk7XG4gICAqXG4gICAqIEBuYW1lIG9wZXJhdG9yXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbDFcbiAgICogQHBhcmFtIHtTdHJpbmd9IG9wZXJhdG9yXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbDJcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm9wZXJhdG9yID0gZnVuY3Rpb24gKHZhbCwgb3BlcmF0b3IsIHZhbDIsIG1zZykge1xuICAgIHZhciBvaztcbiAgICBzd2l0Y2gob3BlcmF0b3IpIHtcbiAgICAgIGNhc2UgJz09JzpcbiAgICAgICAgb2sgPSB2YWwgPT0gdmFsMjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICc9PT0nOlxuICAgICAgICBvayA9IHZhbCA9PT0gdmFsMjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICc+JzpcbiAgICAgICAgb2sgPSB2YWwgPiB2YWwyO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJz49JzpcbiAgICAgICAgb2sgPSB2YWwgPj0gdmFsMjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICc8JzpcbiAgICAgICAgb2sgPSB2YWwgPCB2YWwyO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJzw9JzpcbiAgICAgICAgb2sgPSB2YWwgPD0gdmFsMjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICchPSc6XG4gICAgICAgIG9rID0gdmFsICE9IHZhbDI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnIT09JzpcbiAgICAgICAgb2sgPSB2YWwgIT09IHZhbDI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG9wZXJhdG9yIFwiJyArIG9wZXJhdG9yICsgJ1wiJyk7XG4gICAgfVxuICAgIHZhciB0ZXN0ID0gbmV3IEFzc2VydGlvbihvaywgbXNnKTtcbiAgICB0ZXN0LmFzc2VydChcbiAgICAgICAgdHJ1ZSA9PT0gZmxhZyh0ZXN0LCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICcgKyB1dGlsLmluc3BlY3QodmFsKSArICcgdG8gYmUgJyArIG9wZXJhdG9yICsgJyAnICsgdXRpbC5pbnNwZWN0KHZhbDIpXG4gICAgICAsICdleHBlY3RlZCAnICsgdXRpbC5pbnNwZWN0KHZhbCkgKyAnIHRvIG5vdCBiZSAnICsgb3BlcmF0b3IgKyAnICcgKyB1dGlsLmluc3BlY3QodmFsMikgKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5jbG9zZVRvKGFjdHVhbCwgZXhwZWN0ZWQsIGRlbHRhLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGVxdWFsIGBleHBlY3RlZGAsIHRvIHdpdGhpbiBhICsvLSBgZGVsdGFgIHJhbmdlLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LmNsb3NlVG8oMS41LCAxLCAwLjUsICdudW1iZXJzIGFyZSBjbG9zZScpO1xuICAgKlxuICAgKiBAbmFtZSBjbG9zZVRvXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBhY3R1YWxcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkZWx0YVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuY2xvc2VUbyA9IGZ1bmN0aW9uIChhY3QsIGV4cCwgZGVsdGEsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24oYWN0LCBtc2cpLnRvLmJlLmNsb3NlVG8oZXhwLCBkZWx0YSk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuc2FtZU1lbWJlcnMoc2V0MSwgc2V0MiwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHNldDFgIGFuZCBgc2V0MmAgaGF2ZSB0aGUgc2FtZSBtZW1iZXJzLlxuICAgKiBPcmRlciBpcyBub3QgdGFrZW4gaW50byBhY2NvdW50LlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LnNhbWVNZW1iZXJzKFsgMSwgMiwgMyBdLCBbIDIsIDEsIDMgXSwgJ3NhbWUgbWVtYmVycycpO1xuICAgKlxuICAgKiBAbmFtZSBzYW1lTWVtYmVyc1xuICAgKiBAcGFyYW0ge0FycmF5fSBzZXQxXG4gICAqIEBwYXJhbSB7QXJyYXl9IHNldDJcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LnNhbWVNZW1iZXJzID0gZnVuY3Rpb24gKHNldDEsIHNldDIsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24oc2V0MSwgbXNnKS50by5oYXZlLnNhbWUubWVtYmVycyhzZXQyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiAjIyMgLnNhbWVEZWVwTWVtYmVycyhzZXQxLCBzZXQyLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgc2V0MWAgYW5kIGBzZXQyYCBoYXZlIHRoZSBzYW1lIG1lbWJlcnMgLSB1c2luZyBhIGRlZXAgZXF1YWxpdHkgY2hlY2tpbmcuXG4gICAqIE9yZGVyIGlzIG5vdCB0YWtlbiBpbnRvIGFjY291bnQuXG4gICAqXG4gICAqICAgICBhc3NlcnQuc2FtZURlZXBNZW1iZXJzKFsge2I6IDN9LCB7YTogMn0sIHtjOiA1fSBdLCBbIHtjOiA1fSwge2I6IDN9LCB7YTogMn0gXSwgJ3NhbWUgZGVlcCBtZW1iZXJzJyk7XG4gICAqXG4gICAqIEBuYW1lIHNhbWVEZWVwTWVtYmVyc1xuICAgKiBAcGFyYW0ge0FycmF5fSBzZXQxXG4gICAqIEBwYXJhbSB7QXJyYXl9IHNldDJcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LnNhbWVEZWVwTWVtYmVycyA9IGZ1bmN0aW9uIChzZXQxLCBzZXQyLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHNldDEsIG1zZykudG8uaGF2ZS5zYW1lLmRlZXAubWVtYmVycyhzZXQyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiAjIyMgLmluY2x1ZGVNZW1iZXJzKHN1cGVyc2V0LCBzdWJzZXQsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBzdWJzZXRgIGlzIGluY2x1ZGVkIGluIGBzdXBlcnNldGAuXG4gICAqIE9yZGVyIGlzIG5vdCB0YWtlbiBpbnRvIGFjY291bnQuXG4gICAqXG4gICAqICAgICBhc3NlcnQuaW5jbHVkZU1lbWJlcnMoWyAxLCAyLCAzIF0sIFsgMiwgMSBdLCAnaW5jbHVkZSBtZW1iZXJzJyk7XG4gICAqXG4gICAqIEBuYW1lIGluY2x1ZGVNZW1iZXJzXG4gICAqIEBwYXJhbSB7QXJyYXl9IHN1cGVyc2V0XG4gICAqIEBwYXJhbSB7QXJyYXl9IHN1YnNldFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaW5jbHVkZU1lbWJlcnMgPSBmdW5jdGlvbiAoc3VwZXJzZXQsIHN1YnNldCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihzdXBlcnNldCwgbXNnKS50by5pbmNsdWRlLm1lbWJlcnMoc3Vic2V0KTtcbiAgfVxuXG4gICAvKipcbiAgICogIyMjIC5jaGFuZ2VzKGZ1bmN0aW9uLCBvYmplY3QsIHByb3BlcnR5KVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYSBmdW5jdGlvbiBjaGFuZ2VzIHRoZSB2YWx1ZSBvZiBhIHByb3BlcnR5XG4gICAqXG4gICAqICAgICB2YXIgb2JqID0geyB2YWw6IDEwIH07XG4gICAqICAgICB2YXIgZm4gPSBmdW5jdGlvbigpIHsgb2JqLnZhbCA9IDIyIH07XG4gICAqICAgICBhc3NlcnQuY2hhbmdlcyhmbiwgb2JqLCAndmFsJyk7XG4gICAqXG4gICAqIEBuYW1lIGNoYW5nZXNcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gbW9kaWZpZXIgZnVuY3Rpb25cbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHkgbmFtZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5jaGFuZ2VzID0gZnVuY3Rpb24gKGZuLCBvYmosIHByb3ApIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGZuKS50by5jaGFuZ2Uob2JqLCBwcm9wKTtcbiAgfVxuXG4gICAvKipcbiAgICogIyMjIC5kb2VzTm90Q2hhbmdlKGZ1bmN0aW9uLCBvYmplY3QsIHByb3BlcnR5KVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYSBmdW5jdGlvbiBkb2VzIG5vdCBjaGFuZ2VzIHRoZSB2YWx1ZSBvZiBhIHByb3BlcnR5XG4gICAqXG4gICAqICAgICB2YXIgb2JqID0geyB2YWw6IDEwIH07XG4gICAqICAgICB2YXIgZm4gPSBmdW5jdGlvbigpIHsgY29uc29sZS5sb2coJ2ZvbycpOyB9O1xuICAgKiAgICAgYXNzZXJ0LmRvZXNOb3RDaGFuZ2UoZm4sIG9iaiwgJ3ZhbCcpO1xuICAgKlxuICAgKiBAbmFtZSBkb2VzTm90Q2hhbmdlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IG1vZGlmaWVyIGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuZG9lc05vdENoYW5nZSA9IGZ1bmN0aW9uIChmbiwgb2JqLCBwcm9wKSB7XG4gICAgbmV3IEFzc2VydGlvbihmbikudG8ubm90LmNoYW5nZShvYmosIHByb3ApO1xuICB9XG5cbiAgIC8qKlxuICAgKiAjIyMgLmluY3JlYXNlcyhmdW5jdGlvbiwgb2JqZWN0LCBwcm9wZXJ0eSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGEgZnVuY3Rpb24gaW5jcmVhc2VzIGFuIG9iamVjdCBwcm9wZXJ0eVxuICAgKlxuICAgKiAgICAgdmFyIG9iaiA9IHsgdmFsOiAxMCB9O1xuICAgKiAgICAgdmFyIGZuID0gZnVuY3Rpb24oKSB7IG9iai52YWwgPSAxMyB9O1xuICAgKiAgICAgYXNzZXJ0LmluY3JlYXNlcyhmbiwgb2JqLCAndmFsJyk7XG4gICAqXG4gICAqIEBuYW1lIGluY3JlYXNlc1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBtb2RpZmllciBmdW5jdGlvblxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eSBuYW1lXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmluY3JlYXNlcyA9IGZ1bmN0aW9uIChmbiwgb2JqLCBwcm9wKSB7XG4gICAgbmV3IEFzc2VydGlvbihmbikudG8uaW5jcmVhc2Uob2JqLCBwcm9wKTtcbiAgfVxuXG4gICAvKipcbiAgICogIyMjIC5kb2VzTm90SW5jcmVhc2UoZnVuY3Rpb24sIG9iamVjdCwgcHJvcGVydHkpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBhIGZ1bmN0aW9uIGRvZXMgbm90IGluY3JlYXNlIG9iamVjdCBwcm9wZXJ0eVxuICAgKlxuICAgKiAgICAgdmFyIG9iaiA9IHsgdmFsOiAxMCB9O1xuICAgKiAgICAgdmFyIGZuID0gZnVuY3Rpb24oKSB7IG9iai52YWwgPSA4IH07XG4gICAqICAgICBhc3NlcnQuZG9lc05vdEluY3JlYXNlKGZuLCBvYmosICd2YWwnKTtcbiAgICpcbiAgICogQG5hbWUgZG9lc05vdEluY3JlYXNlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IG1vZGlmaWVyIGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuZG9lc05vdEluY3JlYXNlID0gZnVuY3Rpb24gKGZuLCBvYmosIHByb3ApIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGZuKS50by5ub3QuaW5jcmVhc2Uob2JqLCBwcm9wKTtcbiAgfVxuXG4gICAvKipcbiAgICogIyMjIC5kZWNyZWFzZXMoZnVuY3Rpb24sIG9iamVjdCwgcHJvcGVydHkpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBhIGZ1bmN0aW9uIGRlY3JlYXNlcyBhbiBvYmplY3QgcHJvcGVydHlcbiAgICpcbiAgICogICAgIHZhciBvYmogPSB7IHZhbDogMTAgfTtcbiAgICogICAgIHZhciBmbiA9IGZ1bmN0aW9uKCkgeyBvYmoudmFsID0gNSB9O1xuICAgKiAgICAgYXNzZXJ0LmRlY3JlYXNlcyhmbiwgb2JqLCAndmFsJyk7XG4gICAqXG4gICAqIEBuYW1lIGRlY3JlYXNlc1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBtb2RpZmllciBmdW5jdGlvblxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eSBuYW1lXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmRlY3JlYXNlcyA9IGZ1bmN0aW9uIChmbiwgb2JqLCBwcm9wKSB7XG4gICAgbmV3IEFzc2VydGlvbihmbikudG8uZGVjcmVhc2Uob2JqLCBwcm9wKTtcbiAgfVxuXG4gICAvKipcbiAgICogIyMjIC5kb2VzTm90RGVjcmVhc2UoZnVuY3Rpb24sIG9iamVjdCwgcHJvcGVydHkpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBhIGZ1bmN0aW9uIGRvZXMgbm90IGRlY3JlYXNlcyBhbiBvYmplY3QgcHJvcGVydHlcbiAgICpcbiAgICogICAgIHZhciBvYmogPSB7IHZhbDogMTAgfTtcbiAgICogICAgIHZhciBmbiA9IGZ1bmN0aW9uKCkgeyBvYmoudmFsID0gMTUgfTtcbiAgICogICAgIGFzc2VydC5kb2VzTm90RGVjcmVhc2UoZm4sIG9iaiwgJ3ZhbCcpO1xuICAgKlxuICAgKiBAbmFtZSBkb2VzTm90RGVjcmVhc2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gbW9kaWZpZXIgZnVuY3Rpb25cbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHkgbmFtZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5kb2VzTm90RGVjcmVhc2UgPSBmdW5jdGlvbiAoZm4sIG9iaiwgcHJvcCkge1xuICAgIG5ldyBBc3NlcnRpb24oZm4pLnRvLm5vdC5kZWNyZWFzZShvYmosIHByb3ApO1xuICB9XG5cbiAgLyohXG4gICAqIFVuZG9jdW1lbnRlZCAvIHVudGVzdGVkXG4gICAqL1xuXG4gIGFzc2VydC5pZkVycm9yID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8ubm90LmJlLm9rO1xuICB9O1xuXG4gIC8qIVxuICAgKiBBbGlhc2VzLlxuICAgKi9cblxuICAoZnVuY3Rpb24gYWxpYXMobmFtZSwgYXMpe1xuICAgIGFzc2VydFthc10gPSBhc3NlcnRbbmFtZV07XG4gICAgcmV0dXJuIGFsaWFzO1xuICB9KVxuICAoJ1Rocm93JywgJ3Rocm93JylcbiAgKCdUaHJvdycsICd0aHJvd3MnKTtcbn07XG4iLCIvKiFcbiAqIGNoYWlcbiAqIENvcHlyaWdodChjKSAyMDExLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjaGFpLCB1dGlsKSB7XG4gIGNoYWkuZXhwZWN0ID0gZnVuY3Rpb24gKHZhbCwgbWVzc2FnZSkge1xuICAgIHJldHVybiBuZXcgY2hhaS5Bc3NlcnRpb24odmFsLCBtZXNzYWdlKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5mYWlsKGFjdHVhbCwgZXhwZWN0ZWQsIFttZXNzYWdlXSwgW29wZXJhdG9yXSlcbiAgICpcbiAgICogVGhyb3cgYSBmYWlsdXJlLlxuICAgKlxuICAgKiBAbmFtZSBmYWlsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGFjdHVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBleHBlY3RlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gb3BlcmF0b3JcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgY2hhaS5leHBlY3QuZmFpbCA9IGZ1bmN0aW9uIChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCBvcGVyYXRvcikge1xuICAgIG1lc3NhZ2UgPSBtZXNzYWdlIHx8ICdleHBlY3QuZmFpbCgpJztcbiAgICB0aHJvdyBuZXcgY2hhaS5Bc3NlcnRpb25FcnJvcihtZXNzYWdlLCB7XG4gICAgICAgIGFjdHVhbDogYWN0dWFsXG4gICAgICAsIGV4cGVjdGVkOiBleHBlY3RlZFxuICAgICAgLCBvcGVyYXRvcjogb3BlcmF0b3JcbiAgICB9LCBjaGFpLmV4cGVjdC5mYWlsKTtcbiAgfTtcbn07XG4iLCIvKiFcbiAqIGNoYWlcbiAqIENvcHlyaWdodChjKSAyMDExLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjaGFpLCB1dGlsKSB7XG4gIHZhciBBc3NlcnRpb24gPSBjaGFpLkFzc2VydGlvbjtcblxuICBmdW5jdGlvbiBsb2FkU2hvdWxkICgpIHtcbiAgICAvLyBleHBsaWNpdGx5IGRlZmluZSB0aGlzIG1ldGhvZCBhcyBmdW5jdGlvbiBhcyB0byBoYXZlIGl0J3MgbmFtZSB0byBpbmNsdWRlIGFzIGBzc2ZpYFxuICAgIGZ1bmN0aW9uIHNob3VsZEdldHRlcigpIHtcbiAgICAgIGlmICh0aGlzIGluc3RhbmNlb2YgU3RyaW5nIHx8IHRoaXMgaW5zdGFuY2VvZiBOdW1iZXIgfHwgdGhpcyBpbnN0YW5jZW9mIEJvb2xlYW4gKSB7XG4gICAgICAgIHJldHVybiBuZXcgQXNzZXJ0aW9uKHRoaXMudmFsdWVPZigpLCBudWxsLCBzaG91bGRHZXR0ZXIpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5ldyBBc3NlcnRpb24odGhpcywgbnVsbCwgc2hvdWxkR2V0dGVyKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gc2hvdWxkU2V0dGVyKHZhbHVlKSB7XG4gICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2NoYWlqcy9jaGFpL2lzc3Vlcy84NjogdGhpcyBtYWtlc1xuICAgICAgLy8gYHdoYXRldmVyLnNob3VsZCA9IHNvbWVWYWx1ZWAgYWN0dWFsbHkgc2V0IGBzb21lVmFsdWVgLCB3aGljaCBpc1xuICAgICAgLy8gZXNwZWNpYWxseSB1c2VmdWwgZm9yIGBnbG9iYWwuc2hvdWxkID0gcmVxdWlyZSgnY2hhaScpLnNob3VsZCgpYC5cbiAgICAgIC8vXG4gICAgICAvLyBOb3RlIHRoYXQgd2UgaGF2ZSB0byB1c2UgW1tEZWZpbmVQcm9wZXJ0eV1dIGluc3RlYWQgb2YgW1tQdXRdXVxuICAgICAgLy8gc2luY2Ugb3RoZXJ3aXNlIHdlIHdvdWxkIHRyaWdnZXIgdGhpcyB2ZXJ5IHNldHRlciFcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnc2hvdWxkJywge1xuICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgd3JpdGFibGU6IHRydWVcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBtb2RpZnkgT2JqZWN0LnByb3RvdHlwZSB0byBoYXZlIGBzaG91bGRgXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE9iamVjdC5wcm90b3R5cGUsICdzaG91bGQnLCB7XG4gICAgICBzZXQ6IHNob3VsZFNldHRlclxuICAgICAgLCBnZXQ6IHNob3VsZEdldHRlclxuICAgICAgLCBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcblxuICAgIHZhciBzaG91bGQgPSB7fTtcblxuICAgIC8qKlxuICAgICAqICMjIyAuZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBbbWVzc2FnZV0sIFtvcGVyYXRvcl0pXG4gICAgICpcbiAgICAgKiBUaHJvdyBhIGZhaWx1cmUuXG4gICAgICpcbiAgICAgKiBAbmFtZSBmYWlsXG4gICAgICogQHBhcmFtIHtNaXhlZH0gYWN0dWFsXG4gICAgICogQHBhcmFtIHtNaXhlZH0gZXhwZWN0ZWRcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBvcGVyYXRvclxuICAgICAqIEBhcGkgcHVibGljXG4gICAgICovXG5cbiAgICBzaG91bGQuZmFpbCA9IGZ1bmN0aW9uIChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCBvcGVyYXRvcikge1xuICAgICAgbWVzc2FnZSA9IG1lc3NhZ2UgfHwgJ3Nob3VsZC5mYWlsKCknO1xuICAgICAgdGhyb3cgbmV3IGNoYWkuQXNzZXJ0aW9uRXJyb3IobWVzc2FnZSwge1xuICAgICAgICAgIGFjdHVhbDogYWN0dWFsXG4gICAgICAgICwgZXhwZWN0ZWQ6IGV4cGVjdGVkXG4gICAgICAgICwgb3BlcmF0b3I6IG9wZXJhdG9yXG4gICAgICB9LCBzaG91bGQuZmFpbCk7XG4gICAgfTtcblxuICAgIHNob3VsZC5lcXVhbCA9IGZ1bmN0aW9uICh2YWwxLCB2YWwyLCBtc2cpIHtcbiAgICAgIG5ldyBBc3NlcnRpb24odmFsMSwgbXNnKS50by5lcXVhbCh2YWwyKTtcbiAgICB9O1xuXG4gICAgc2hvdWxkLlRocm93ID0gZnVuY3Rpb24gKGZuLCBlcnJ0LCBlcnJzLCBtc2cpIHtcbiAgICAgIG5ldyBBc3NlcnRpb24oZm4sIG1zZykudG8uVGhyb3coZXJydCwgZXJycyk7XG4gICAgfTtcblxuICAgIHNob3VsZC5leGlzdCA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uZXhpc3Q7XG4gICAgfVxuXG4gICAgLy8gbmVnYXRpb25cbiAgICBzaG91bGQubm90ID0ge31cblxuICAgIHNob3VsZC5ub3QuZXF1YWwgPSBmdW5jdGlvbiAodmFsMSwgdmFsMiwgbXNnKSB7XG4gICAgICBuZXcgQXNzZXJ0aW9uKHZhbDEsIG1zZykudG8ubm90LmVxdWFsKHZhbDIpO1xuICAgIH07XG5cbiAgICBzaG91bGQubm90LlRocm93ID0gZnVuY3Rpb24gKGZuLCBlcnJ0LCBlcnJzLCBtc2cpIHtcbiAgICAgIG5ldyBBc3NlcnRpb24oZm4sIG1zZykudG8ubm90LlRocm93KGVycnQsIGVycnMpO1xuICAgIH07XG5cbiAgICBzaG91bGQubm90LmV4aXN0ID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuZXhpc3Q7XG4gICAgfVxuXG4gICAgc2hvdWxkWyd0aHJvdyddID0gc2hvdWxkWydUaHJvdyddO1xuICAgIHNob3VsZC5ub3RbJ3Rocm93J10gPSBzaG91bGQubm90WydUaHJvdyddO1xuXG4gICAgcmV0dXJuIHNob3VsZDtcbiAgfTtcblxuICBjaGFpLnNob3VsZCA9IGxvYWRTaG91bGQ7XG4gIGNoYWkuU2hvdWxkID0gbG9hZFNob3VsZDtcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBhZGRDaGFpbmluZ01ldGhvZCB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBNb2R1bGUgZGVwZW5kZW5jaWVzXG4gKi9cblxudmFyIHRyYW5zZmVyRmxhZ3MgPSByZXF1aXJlKCcuL3RyYW5zZmVyRmxhZ3MnKTtcbnZhciBmbGFnID0gcmVxdWlyZSgnLi9mbGFnJyk7XG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi4vY29uZmlnJyk7XG5cbi8qIVxuICogTW9kdWxlIHZhcmlhYmxlc1xuICovXG5cbi8vIENoZWNrIHdoZXRoZXIgYF9fcHJvdG9fX2AgaXMgc3VwcG9ydGVkXG52YXIgaGFzUHJvdG9TdXBwb3J0ID0gJ19fcHJvdG9fXycgaW4gT2JqZWN0O1xuXG4vLyBXaXRob3V0IGBfX3Byb3RvX19gIHN1cHBvcnQsIHRoaXMgbW9kdWxlIHdpbGwgbmVlZCB0byBhZGQgcHJvcGVydGllcyB0byBhIGZ1bmN0aW9uLlxuLy8gSG93ZXZlciwgc29tZSBGdW5jdGlvbi5wcm90b3R5cGUgbWV0aG9kcyBjYW5ub3QgYmUgb3ZlcndyaXR0ZW4sXG4vLyBhbmQgdGhlcmUgc2VlbXMgbm8gZWFzeSBjcm9zcy1wbGF0Zm9ybSB3YXkgdG8gZGV0ZWN0IHRoZW0gKEBzZWUgY2hhaWpzL2NoYWkvaXNzdWVzLzY5KS5cbnZhciBleGNsdWRlTmFtZXMgPSAvXig/Omxlbmd0aHxuYW1lfGFyZ3VtZW50c3xjYWxsZXIpJC87XG5cbi8vIENhY2hlIGBGdW5jdGlvbmAgcHJvcGVydGllc1xudmFyIGNhbGwgID0gRnVuY3Rpb24ucHJvdG90eXBlLmNhbGwsXG4gICAgYXBwbHkgPSBGdW5jdGlvbi5wcm90b3R5cGUuYXBwbHk7XG5cbi8qKlxuICogIyMjIGFkZENoYWluYWJsZU1ldGhvZCAoY3R4LCBuYW1lLCBtZXRob2QsIGNoYWluaW5nQmVoYXZpb3IpXG4gKlxuICogQWRkcyBhIG1ldGhvZCB0byBhbiBvYmplY3QsIHN1Y2ggdGhhdCB0aGUgbWV0aG9kIGNhbiBhbHNvIGJlIGNoYWluZWQuXG4gKlxuICogICAgIHV0aWxzLmFkZENoYWluYWJsZU1ldGhvZChjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUsICdmb28nLCBmdW5jdGlvbiAoc3RyKSB7XG4gKiAgICAgICB2YXIgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gKiAgICAgICBuZXcgY2hhaS5Bc3NlcnRpb24ob2JqKS50by5iZS5lcXVhbChzdHIpO1xuICogICAgIH0pO1xuICpcbiAqIENhbiBhbHNvIGJlIGFjY2Vzc2VkIGRpcmVjdGx5IGZyb20gYGNoYWkuQXNzZXJ0aW9uYC5cbiAqXG4gKiAgICAgY2hhaS5Bc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdmb28nLCBmbiwgY2hhaW5pbmdCZWhhdmlvcik7XG4gKlxuICogVGhlIHJlc3VsdCBjYW4gdGhlbiBiZSB1c2VkIGFzIGJvdGggYSBtZXRob2QgYXNzZXJ0aW9uLCBleGVjdXRpbmcgYm90aCBgbWV0aG9kYCBhbmRcbiAqIGBjaGFpbmluZ0JlaGF2aW9yYCwgb3IgYXMgYSBsYW5ndWFnZSBjaGFpbiwgd2hpY2ggb25seSBleGVjdXRlcyBgY2hhaW5pbmdCZWhhdmlvcmAuXG4gKlxuICogICAgIGV4cGVjdChmb29TdHIpLnRvLmJlLmZvbygnYmFyJyk7XG4gKiAgICAgZXhwZWN0KGZvb1N0cikudG8uYmUuZm9vLmVxdWFsKCdmb28nKTtcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY3R4IG9iamVjdCB0byB3aGljaCB0aGUgbWV0aG9kIGlzIGFkZGVkXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiBtZXRob2QgdG8gYWRkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBtZXRob2QgZnVuY3Rpb24gdG8gYmUgdXNlZCBmb3IgYG5hbWVgLCB3aGVuIGNhbGxlZFxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2hhaW5pbmdCZWhhdmlvciBmdW5jdGlvbiB0byBiZSBjYWxsZWQgZXZlcnkgdGltZSB0aGUgcHJvcGVydHkgaXMgYWNjZXNzZWRcbiAqIEBuYW1lIGFkZENoYWluYWJsZU1ldGhvZFxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjdHgsIG5hbWUsIG1ldGhvZCwgY2hhaW5pbmdCZWhhdmlvcikge1xuICBpZiAodHlwZW9mIGNoYWluaW5nQmVoYXZpb3IgIT09ICdmdW5jdGlvbicpIHtcbiAgICBjaGFpbmluZ0JlaGF2aW9yID0gZnVuY3Rpb24gKCkgeyB9O1xuICB9XG5cbiAgdmFyIGNoYWluYWJsZUJlaGF2aW9yID0ge1xuICAgICAgbWV0aG9kOiBtZXRob2RcbiAgICAsIGNoYWluaW5nQmVoYXZpb3I6IGNoYWluaW5nQmVoYXZpb3JcbiAgfTtcblxuICAvLyBzYXZlIHRoZSBtZXRob2RzIHNvIHdlIGNhbiBvdmVyd3JpdGUgdGhlbSBsYXRlciwgaWYgd2UgbmVlZCB0by5cbiAgaWYgKCFjdHguX19tZXRob2RzKSB7XG4gICAgY3R4Ll9fbWV0aG9kcyA9IHt9O1xuICB9XG4gIGN0eC5fX21ldGhvZHNbbmFtZV0gPSBjaGFpbmFibGVCZWhhdmlvcjtcblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoY3R4LCBuYW1lLFxuICAgIHsgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNoYWluYWJsZUJlaGF2aW9yLmNoYWluaW5nQmVoYXZpb3IuY2FsbCh0aGlzKTtcblxuICAgICAgICB2YXIgYXNzZXJ0ID0gZnVuY3Rpb24gYXNzZXJ0KCkge1xuICAgICAgICAgIHZhciBvbGRfc3NmaSA9IGZsYWcodGhpcywgJ3NzZmknKTtcbiAgICAgICAgICBpZiAob2xkX3NzZmkgJiYgY29uZmlnLmluY2x1ZGVTdGFjayA9PT0gZmFsc2UpXG4gICAgICAgICAgICBmbGFnKHRoaXMsICdzc2ZpJywgYXNzZXJ0KTtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gY2hhaW5hYmxlQmVoYXZpb3IubWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gdGhpcyA6IHJlc3VsdDtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBVc2UgYF9fcHJvdG9fX2AgaWYgYXZhaWxhYmxlXG4gICAgICAgIGlmIChoYXNQcm90b1N1cHBvcnQpIHtcbiAgICAgICAgICAvLyBJbmhlcml0IGFsbCBwcm9wZXJ0aWVzIGZyb20gdGhlIG9iamVjdCBieSByZXBsYWNpbmcgdGhlIGBGdW5jdGlvbmAgcHJvdG90eXBlXG4gICAgICAgICAgdmFyIHByb3RvdHlwZSA9IGFzc2VydC5fX3Byb3RvX18gPSBPYmplY3QuY3JlYXRlKHRoaXMpO1xuICAgICAgICAgIC8vIFJlc3RvcmUgdGhlIGBjYWxsYCBhbmQgYGFwcGx5YCBtZXRob2RzIGZyb20gYEZ1bmN0aW9uYFxuICAgICAgICAgIHByb3RvdHlwZS5jYWxsID0gY2FsbDtcbiAgICAgICAgICBwcm90b3R5cGUuYXBwbHkgPSBhcHBseTtcbiAgICAgICAgfVxuICAgICAgICAvLyBPdGhlcndpc2UsIHJlZGVmaW5lIGFsbCBwcm9wZXJ0aWVzIChzbG93ISlcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdmFyIGFzc2VydGVyTmFtZXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhjdHgpO1xuICAgICAgICAgIGFzc2VydGVyTmFtZXMuZm9yRWFjaChmdW5jdGlvbiAoYXNzZXJ0ZXJOYW1lKSB7XG4gICAgICAgICAgICBpZiAoIWV4Y2x1ZGVOYW1lcy50ZXN0KGFzc2VydGVyTmFtZSkpIHtcbiAgICAgICAgICAgICAgdmFyIHBkID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihjdHgsIGFzc2VydGVyTmFtZSk7XG4gICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShhc3NlcnQsIGFzc2VydGVyTmFtZSwgcGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJhbnNmZXJGbGFncyh0aGlzLCBhc3NlcnQpO1xuICAgICAgICByZXR1cm4gYXNzZXJ0O1xuICAgICAgfVxuICAgICwgY29uZmlndXJhYmxlOiB0cnVlXG4gIH0pO1xufTtcbiIsIi8qIVxuICogQ2hhaSAtIGFkZE1ldGhvZCB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxudmFyIGNvbmZpZyA9IHJlcXVpcmUoJy4uL2NvbmZpZycpO1xuXG4vKipcbiAqICMjIyAuYWRkTWV0aG9kIChjdHgsIG5hbWUsIG1ldGhvZClcbiAqXG4gKiBBZGRzIGEgbWV0aG9kIHRvIHRoZSBwcm90b3R5cGUgb2YgYW4gb2JqZWN0LlxuICpcbiAqICAgICB1dGlscy5hZGRNZXRob2QoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCAnZm9vJywgZnVuY3Rpb24gKHN0cikge1xuICogICAgICAgdmFyIG9iaiA9IHV0aWxzLmZsYWcodGhpcywgJ29iamVjdCcpO1xuICogICAgICAgbmV3IGNoYWkuQXNzZXJ0aW9uKG9iaikudG8uYmUuZXF1YWwoc3RyKTtcbiAqICAgICB9KTtcbiAqXG4gKiBDYW4gYWxzbyBiZSBhY2Nlc3NlZCBkaXJlY3RseSBmcm9tIGBjaGFpLkFzc2VydGlvbmAuXG4gKlxuICogICAgIGNoYWkuQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZm9vJywgZm4pO1xuICpcbiAqIFRoZW4gY2FuIGJlIHVzZWQgYXMgYW55IG90aGVyIGFzc2VydGlvbi5cbiAqXG4gKiAgICAgZXhwZWN0KGZvb1N0cikudG8uYmUuZm9vKCdiYXInKTtcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY3R4IG9iamVjdCB0byB3aGljaCB0aGUgbWV0aG9kIGlzIGFkZGVkXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiBtZXRob2QgdG8gYWRkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBtZXRob2QgZnVuY3Rpb24gdG8gYmUgdXNlZCBmb3IgbmFtZVxuICogQG5hbWUgYWRkTWV0aG9kXG4gKiBAYXBpIHB1YmxpY1xuICovXG52YXIgZmxhZyA9IHJlcXVpcmUoJy4vZmxhZycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjdHgsIG5hbWUsIG1ldGhvZCkge1xuICBjdHhbbmFtZV0gPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIG9sZF9zc2ZpID0gZmxhZyh0aGlzLCAnc3NmaScpO1xuICAgIGlmIChvbGRfc3NmaSAmJiBjb25maWcuaW5jbHVkZVN0YWNrID09PSBmYWxzZSlcbiAgICAgIGZsYWcodGhpcywgJ3NzZmknLCBjdHhbbmFtZV0pO1xuICAgIHZhciByZXN1bHQgPSBtZXRob2QuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICByZXR1cm4gcmVzdWx0ID09PSB1bmRlZmluZWQgPyB0aGlzIDogcmVzdWx0O1xuICB9O1xufTtcbiIsIi8qIVxuICogQ2hhaSAtIGFkZFByb3BlcnR5IHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKipcbiAqICMjIyBhZGRQcm9wZXJ0eSAoY3R4LCBuYW1lLCBnZXR0ZXIpXG4gKlxuICogQWRkcyBhIHByb3BlcnR5IHRvIHRoZSBwcm90b3R5cGUgb2YgYW4gb2JqZWN0LlxuICpcbiAqICAgICB1dGlscy5hZGRQcm9wZXJ0eShjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUsICdmb28nLCBmdW5jdGlvbiAoKSB7XG4gKiAgICAgICB2YXIgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gKiAgICAgICBuZXcgY2hhaS5Bc3NlcnRpb24ob2JqKS50by5iZS5pbnN0YW5jZW9mKEZvbyk7XG4gKiAgICAgfSk7XG4gKlxuICogQ2FuIGFsc28gYmUgYWNjZXNzZWQgZGlyZWN0bHkgZnJvbSBgY2hhaS5Bc3NlcnRpb25gLlxuICpcbiAqICAgICBjaGFpLkFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnZm9vJywgZm4pO1xuICpcbiAqIFRoZW4gY2FuIGJlIHVzZWQgYXMgYW55IG90aGVyIGFzc2VydGlvbi5cbiAqXG4gKiAgICAgZXhwZWN0KG15Rm9vKS50by5iZS5mb287XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGN0eCBvYmplY3QgdG8gd2hpY2ggdGhlIHByb3BlcnR5IGlzIGFkZGVkXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiBwcm9wZXJ0eSB0byBhZGRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGdldHRlciBmdW5jdGlvbiB0byBiZSB1c2VkIGZvciBuYW1lXG4gKiBAbmFtZSBhZGRQcm9wZXJ0eVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjdHgsIG5hbWUsIGdldHRlcikge1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoY3R4LCBuYW1lLFxuICAgIHsgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBnZXR0ZXIuY2FsbCh0aGlzKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gdGhpcyA6IHJlc3VsdDtcbiAgICAgIH1cbiAgICAsIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICB9KTtcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBmbGFnIHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKipcbiAqICMjIyBmbGFnKG9iamVjdCwga2V5LCBbdmFsdWVdKVxuICpcbiAqIEdldCBvciBzZXQgYSBmbGFnIHZhbHVlIG9uIGFuIG9iamVjdC4gSWYgYVxuICogdmFsdWUgaXMgcHJvdmlkZWQgaXQgd2lsbCBiZSBzZXQsIGVsc2UgaXQgd2lsbFxuICogcmV0dXJuIHRoZSBjdXJyZW50bHkgc2V0IHZhbHVlIG9yIGB1bmRlZmluZWRgIGlmXG4gKiB0aGUgdmFsdWUgaXMgbm90IHNldC5cbiAqXG4gKiAgICAgdXRpbHMuZmxhZyh0aGlzLCAnZm9vJywgJ2JhcicpOyAvLyBzZXR0ZXJcbiAqICAgICB1dGlscy5mbGFnKHRoaXMsICdmb28nKTsgLy8gZ2V0dGVyLCByZXR1cm5zIGBiYXJgXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBjb25zdHJ1Y3RlZCBBc3NlcnRpb25cbiAqIEBwYXJhbSB7U3RyaW5nfSBrZXlcbiAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlIChvcHRpb25hbClcbiAqIEBuYW1lIGZsYWdcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9iaiwga2V5LCB2YWx1ZSkge1xuICB2YXIgZmxhZ3MgPSBvYmouX19mbGFncyB8fCAob2JqLl9fZmxhZ3MgPSBPYmplY3QuY3JlYXRlKG51bGwpKTtcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpIHtcbiAgICBmbGFnc1trZXldID0gdmFsdWU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGZsYWdzW2tleV07XG4gIH1cbn07XG4iLCIvKiFcbiAqIENoYWkgLSBnZXRBY3R1YWwgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyBnZXRBY3R1YWwob2JqZWN0LCBbYWN0dWFsXSlcbiAqXG4gKiBSZXR1cm5zIHRoZSBgYWN0dWFsYCB2YWx1ZSBmb3IgYW4gQXNzZXJ0aW9uXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCAoY29uc3RydWN0ZWQgQXNzZXJ0aW9uKVxuICogQHBhcmFtIHtBcmd1bWVudHN9IGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZS5hc3NlcnQgYXJndW1lbnRzXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqLCBhcmdzKSB7XG4gIHJldHVybiBhcmdzLmxlbmd0aCA+IDQgPyBhcmdzWzRdIDogb2JqLl9vYmo7XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gZ2V0RW51bWVyYWJsZVByb3BlcnRpZXMgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIC5nZXRFbnVtZXJhYmxlUHJvcGVydGllcyhvYmplY3QpXG4gKlxuICogVGhpcyBhbGxvd3MgdGhlIHJldHJpZXZhbCBvZiBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIG9mIGFuIG9iamVjdCxcbiAqIGluaGVyaXRlZCBvciBub3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICogQHJldHVybnMge0FycmF5fVxuICogQG5hbWUgZ2V0RW51bWVyYWJsZVByb3BlcnRpZXNcbiAqIEBhcGkgcHVibGljXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBnZXRFbnVtZXJhYmxlUHJvcGVydGllcyhvYmplY3QpIHtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuICBmb3IgKHZhciBuYW1lIGluIG9iamVjdCkge1xuICAgIHJlc3VsdC5wdXNoKG5hbWUpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gbWVzc2FnZSBjb21wb3NpdGlvbiB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBNb2R1bGUgZGVwZW5kYW5jaWVzXG4gKi9cblxudmFyIGZsYWcgPSByZXF1aXJlKCcuL2ZsYWcnKVxuICAsIGdldEFjdHVhbCA9IHJlcXVpcmUoJy4vZ2V0QWN0dWFsJylcbiAgLCBpbnNwZWN0ID0gcmVxdWlyZSgnLi9pbnNwZWN0JylcbiAgLCBvYmpEaXNwbGF5ID0gcmVxdWlyZSgnLi9vYmpEaXNwbGF5Jyk7XG5cbi8qKlxuICogIyMjIC5nZXRNZXNzYWdlKG9iamVjdCwgbWVzc2FnZSwgbmVnYXRlTWVzc2FnZSlcbiAqXG4gKiBDb25zdHJ1Y3QgdGhlIGVycm9yIG1lc3NhZ2UgYmFzZWQgb24gZmxhZ3NcbiAqIGFuZCB0ZW1wbGF0ZSB0YWdzLiBUZW1wbGF0ZSB0YWdzIHdpbGwgcmV0dXJuXG4gKiBhIHN0cmluZ2lmaWVkIGluc3BlY3Rpb24gb2YgdGhlIG9iamVjdCByZWZlcmVuY2VkLlxuICpcbiAqIE1lc3NhZ2UgdGVtcGxhdGUgdGFnczpcbiAqIC0gYCN7dGhpc31gIGN1cnJlbnQgYXNzZXJ0ZWQgb2JqZWN0XG4gKiAtIGAje2FjdH1gIGFjdHVhbCB2YWx1ZVxuICogLSBgI3tleHB9YCBleHBlY3RlZCB2YWx1ZVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgKGNvbnN0cnVjdGVkIEFzc2VydGlvbilcbiAqIEBwYXJhbSB7QXJndW1lbnRzfSBjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUuYXNzZXJ0IGFyZ3VtZW50c1xuICogQG5hbWUgZ2V0TWVzc2FnZVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmosIGFyZ3MpIHtcbiAgdmFyIG5lZ2F0ZSA9IGZsYWcob2JqLCAnbmVnYXRlJylcbiAgICAsIHZhbCA9IGZsYWcob2JqLCAnb2JqZWN0JylcbiAgICAsIGV4cGVjdGVkID0gYXJnc1szXVxuICAgICwgYWN0dWFsID0gZ2V0QWN0dWFsKG9iaiwgYXJncylcbiAgICAsIG1zZyA9IG5lZ2F0ZSA/IGFyZ3NbMl0gOiBhcmdzWzFdXG4gICAgLCBmbGFnTXNnID0gZmxhZyhvYmosICdtZXNzYWdlJyk7XG5cbiAgaWYodHlwZW9mIG1zZyA9PT0gXCJmdW5jdGlvblwiKSBtc2cgPSBtc2coKTtcbiAgbXNnID0gbXNnIHx8ICcnO1xuICBtc2cgPSBtc2dcbiAgICAucmVwbGFjZSgvI3t0aGlzfS9nLCBvYmpEaXNwbGF5KHZhbCkpXG4gICAgLnJlcGxhY2UoLyN7YWN0fS9nLCBvYmpEaXNwbGF5KGFjdHVhbCkpXG4gICAgLnJlcGxhY2UoLyN7ZXhwfS9nLCBvYmpEaXNwbGF5KGV4cGVjdGVkKSk7XG5cbiAgcmV0dXJuIGZsYWdNc2cgPyBmbGFnTXNnICsgJzogJyArIG1zZyA6IG1zZztcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBnZXROYW1lIHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKipcbiAqICMgZ2V0TmFtZShmdW5jKVxuICpcbiAqIEdldHMgdGhlIG5hbWUgb2YgYSBmdW5jdGlvbiwgaW4gYSBjcm9zcy1icm93c2VyIHdheS5cbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBhIGZ1bmN0aW9uICh1c3VhbGx5IGEgY29uc3RydWN0b3IpXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZnVuYykge1xuICBpZiAoZnVuYy5uYW1lKSByZXR1cm4gZnVuYy5uYW1lO1xuXG4gIHZhciBtYXRjaCA9IC9eXFxzP2Z1bmN0aW9uIChbXihdKilcXCgvLmV4ZWMoZnVuYyk7XG4gIHJldHVybiBtYXRjaCAmJiBtYXRjaFsxXSA/IG1hdGNoWzFdIDogXCJcIjtcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBnZXRQYXRoSW5mbyB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxudmFyIGhhc1Byb3BlcnR5ID0gcmVxdWlyZSgnLi9oYXNQcm9wZXJ0eScpO1xuXG4vKipcbiAqICMjIyAuZ2V0UGF0aEluZm8ocGF0aCwgb2JqZWN0KVxuICpcbiAqIFRoaXMgYWxsb3dzIHRoZSByZXRyaWV2YWwgb2YgcHJvcGVydHkgaW5mbyBpbiBhblxuICogb2JqZWN0IGdpdmVuIGEgc3RyaW5nIHBhdGguXG4gKlxuICogVGhlIHBhdGggaW5mbyBjb25zaXN0cyBvZiBhbiBvYmplY3Qgd2l0aCB0aGVcbiAqIGZvbGxvd2luZyBwcm9wZXJ0aWVzOlxuICpcbiAqICogcGFyZW50IC0gVGhlIHBhcmVudCBvYmplY3Qgb2YgdGhlIHByb3BlcnR5IHJlZmVyZW5jZWQgYnkgYHBhdGhgXG4gKiAqIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZmluYWwgcHJvcGVydHksIGEgbnVtYmVyIGlmIGl0IHdhcyBhbiBhcnJheSBpbmRleGVyXG4gKiAqIHZhbHVlIC0gVGhlIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSwgaWYgaXQgZXhpc3RzLCBvdGhlcndpc2UgYHVuZGVmaW5lZGBcbiAqICogZXhpc3RzIC0gV2hldGhlciB0aGUgcHJvcGVydHkgZXhpc3RzIG9yIG5vdFxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYXRoXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gKiBAcmV0dXJucyB7T2JqZWN0fSBpbmZvXG4gKiBAbmFtZSBnZXRQYXRoSW5mb1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGdldFBhdGhJbmZvKHBhdGgsIG9iaikge1xuICB2YXIgcGFyc2VkID0gcGFyc2VQYXRoKHBhdGgpLFxuICAgICAgbGFzdCA9IHBhcnNlZFtwYXJzZWQubGVuZ3RoIC0gMV07XG5cbiAgdmFyIGluZm8gPSB7XG4gICAgcGFyZW50OiBwYXJzZWQubGVuZ3RoID4gMSA/IF9nZXRQYXRoVmFsdWUocGFyc2VkLCBvYmosIHBhcnNlZC5sZW5ndGggLSAxKSA6IG9iaixcbiAgICBuYW1lOiBsYXN0LnAgfHwgbGFzdC5pLFxuICAgIHZhbHVlOiBfZ2V0UGF0aFZhbHVlKHBhcnNlZCwgb2JqKSxcbiAgfTtcbiAgaW5mby5leGlzdHMgPSBoYXNQcm9wZXJ0eShpbmZvLm5hbWUsIGluZm8ucGFyZW50KTtcblxuICByZXR1cm4gaW5mbztcbn07XG5cblxuLyohXG4gKiAjIyBwYXJzZVBhdGgocGF0aClcbiAqXG4gKiBIZWxwZXIgZnVuY3Rpb24gdXNlZCB0byBwYXJzZSBzdHJpbmcgb2JqZWN0XG4gKiBwYXRocy4gVXNlIGluIGNvbmp1bmN0aW9uIHdpdGggYF9nZXRQYXRoVmFsdWVgLlxuICpcbiAqICAgICAgdmFyIHBhcnNlZCA9IHBhcnNlUGF0aCgnbXlvYmplY3QucHJvcGVydHkuc3VicHJvcCcpO1xuICpcbiAqICMjIyBQYXRoczpcbiAqXG4gKiAqIENhbiBiZSBhcyBuZWFyIGluZmluaXRlbHkgZGVlcCBhbmQgbmVzdGVkXG4gKiAqIEFycmF5cyBhcmUgYWxzbyB2YWxpZCB1c2luZyB0aGUgZm9ybWFsIGBteW9iamVjdC5kb2N1bWVudFszXS5wcm9wZXJ0eWAuXG4gKiAqIExpdGVyYWwgZG90cyBhbmQgYnJhY2tldHMgKG5vdCBkZWxpbWl0ZXIpIG11c3QgYmUgYmFja3NsYXNoLWVzY2FwZWQuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHBhdGhcbiAqIEByZXR1cm5zIHtPYmplY3R9IHBhcnNlZFxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gcGFyc2VQYXRoIChwYXRoKSB7XG4gIHZhciBzdHIgPSBwYXRoLnJlcGxhY2UoLyhbXlxcXFxdKVxcWy9nLCAnJDEuWycpXG4gICAgLCBwYXJ0cyA9IHN0ci5tYXRjaCgvKFxcXFxcXC58W14uXSs/KSsvZyk7XG4gIHJldHVybiBwYXJ0cy5tYXAoZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgdmFyIHJlID0gL15cXFsoXFxkKylcXF0kL1xuICAgICAgLCBtQXJyID0gcmUuZXhlYyh2YWx1ZSk7XG4gICAgaWYgKG1BcnIpIHJldHVybiB7IGk6IHBhcnNlRmxvYXQobUFyclsxXSkgfTtcbiAgICBlbHNlIHJldHVybiB7IHA6IHZhbHVlLnJlcGxhY2UoL1xcXFwoWy5cXFtcXF1dKS9nLCAnJDEnKSB9O1xuICB9KTtcbn1cblxuXG4vKiFcbiAqICMjIF9nZXRQYXRoVmFsdWUocGFyc2VkLCBvYmopXG4gKlxuICogSGVscGVyIGNvbXBhbmlvbiBmdW5jdGlvbiBmb3IgYC5wYXJzZVBhdGhgIHRoYXQgcmV0dXJuc1xuICogdGhlIHZhbHVlIGxvY2F0ZWQgYXQgdGhlIHBhcnNlZCBhZGRyZXNzLlxuICpcbiAqICAgICAgdmFyIHZhbHVlID0gZ2V0UGF0aFZhbHVlKHBhcnNlZCwgb2JqKTtcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gcGFyc2VkIGRlZmluaXRpb24gZnJvbSBgcGFyc2VQYXRoYC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgdG8gc2VhcmNoIGFnYWluc3RcbiAqIEBwYXJhbSB7TnVtYmVyfSBvYmplY3QgdG8gc2VhcmNoIGFnYWluc3RcbiAqIEByZXR1cm5zIHtPYmplY3R8VW5kZWZpbmVkfSB2YWx1ZVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gX2dldFBhdGhWYWx1ZSAocGFyc2VkLCBvYmosIGluZGV4KSB7XG4gIHZhciB0bXAgPSBvYmpcbiAgICAsIHJlcztcblxuICBpbmRleCA9IChpbmRleCA9PT0gdW5kZWZpbmVkID8gcGFyc2VkLmxlbmd0aCA6IGluZGV4KTtcblxuICBmb3IgKHZhciBpID0gMCwgbCA9IGluZGV4OyBpIDwgbDsgaSsrKSB7XG4gICAgdmFyIHBhcnQgPSBwYXJzZWRbaV07XG4gICAgaWYgKHRtcCkge1xuICAgICAgaWYgKCd1bmRlZmluZWQnICE9PSB0eXBlb2YgcGFydC5wKVxuICAgICAgICB0bXAgPSB0bXBbcGFydC5wXTtcbiAgICAgIGVsc2UgaWYgKCd1bmRlZmluZWQnICE9PSB0eXBlb2YgcGFydC5pKVxuICAgICAgICB0bXAgPSB0bXBbcGFydC5pXTtcbiAgICAgIGlmIChpID09IChsIC0gMSkpIHJlcyA9IHRtcDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzO1xufVxuIiwiLyohXG4gKiBDaGFpIC0gZ2V0UGF0aFZhbHVlIHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBAc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpY2FscGFyYWRveC9maWx0clxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxudmFyIGdldFBhdGhJbmZvID0gcmVxdWlyZSgnLi9nZXRQYXRoSW5mbycpO1xuXG4vKipcbiAqICMjIyAuZ2V0UGF0aFZhbHVlKHBhdGgsIG9iamVjdClcbiAqXG4gKiBUaGlzIGFsbG93cyB0aGUgcmV0cmlldmFsIG9mIHZhbHVlcyBpbiBhblxuICogb2JqZWN0IGdpdmVuIGEgc3RyaW5nIHBhdGguXG4gKlxuICogICAgIHZhciBvYmogPSB7XG4gKiAgICAgICAgIHByb3AxOiB7XG4gKiAgICAgICAgICAgICBhcnI6IFsnYScsICdiJywgJ2MnXVxuICogICAgICAgICAgICwgc3RyOiAnSGVsbG8nXG4gKiAgICAgICAgIH1cbiAqICAgICAgICwgcHJvcDI6IHtcbiAqICAgICAgICAgICAgIGFycjogWyB7IG5lc3RlZDogJ1VuaXZlcnNlJyB9IF1cbiAqICAgICAgICAgICAsIHN0cjogJ0hlbGxvIGFnYWluISdcbiAqICAgICAgICAgfVxuICogICAgIH1cbiAqXG4gKiBUaGUgZm9sbG93aW5nIHdvdWxkIGJlIHRoZSByZXN1bHRzLlxuICpcbiAqICAgICBnZXRQYXRoVmFsdWUoJ3Byb3AxLnN0cicsIG9iaik7IC8vIEhlbGxvXG4gKiAgICAgZ2V0UGF0aFZhbHVlKCdwcm9wMS5hdHRbMl0nLCBvYmopOyAvLyBiXG4gKiAgICAgZ2V0UGF0aFZhbHVlKCdwcm9wMi5hcnJbMF0ubmVzdGVkJywgb2JqKTsgLy8gVW5pdmVyc2VcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gcGF0aFxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICogQHJldHVybnMge09iamVjdH0gdmFsdWUgb3IgYHVuZGVmaW5lZGBcbiAqIEBuYW1lIGdldFBhdGhWYWx1ZVxuICogQGFwaSBwdWJsaWNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihwYXRoLCBvYmopIHtcbiAgdmFyIGluZm8gPSBnZXRQYXRoSW5mbyhwYXRoLCBvYmopO1xuICByZXR1cm4gaW5mby52YWx1ZTtcbn07IFxuIiwiLyohXG4gKiBDaGFpIC0gZ2V0UHJvcGVydGllcyB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyoqXG4gKiAjIyMgLmdldFByb3BlcnRpZXMob2JqZWN0KVxuICpcbiAqIFRoaXMgYWxsb3dzIHRoZSByZXRyaWV2YWwgb2YgcHJvcGVydHkgbmFtZXMgb2YgYW4gb2JqZWN0LCBlbnVtZXJhYmxlIG9yIG5vdCxcbiAqIGluaGVyaXRlZCBvciBub3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICogQHJldHVybnMge0FycmF5fVxuICogQG5hbWUgZ2V0UHJvcGVydGllc1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGdldFByb3BlcnRpZXMob2JqZWN0KSB7XG4gIHZhciByZXN1bHQgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhzdWJqZWN0KTtcblxuICBmdW5jdGlvbiBhZGRQcm9wZXJ0eShwcm9wZXJ0eSkge1xuICAgIGlmIChyZXN1bHQuaW5kZXhPZihwcm9wZXJ0eSkgPT09IC0xKSB7XG4gICAgICByZXN1bHQucHVzaChwcm9wZXJ0eSk7XG4gICAgfVxuICB9XG5cbiAgdmFyIHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHN1YmplY3QpO1xuICB3aGlsZSAocHJvdG8gIT09IG51bGwpIHtcbiAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhwcm90bykuZm9yRWFjaChhZGRQcm9wZXJ0eSk7XG4gICAgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdG8pO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBoYXNQcm9wZXJ0eSB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxudmFyIHR5cGUgPSByZXF1aXJlKCcuL3R5cGUnKTtcblxuLyoqXG4gKiAjIyMgLmhhc1Byb3BlcnR5KG9iamVjdCwgbmFtZSlcbiAqXG4gKiBUaGlzIGFsbG93cyBjaGVja2luZyB3aGV0aGVyIGFuIG9iamVjdCBoYXNcbiAqIG5hbWVkIHByb3BlcnR5IG9yIG51bWVyaWMgYXJyYXkgaW5kZXguXG4gKlxuICogQmFzaWNhbGx5IGRvZXMgdGhlIHNhbWUgdGhpbmcgYXMgdGhlIGBpbmBcbiAqIG9wZXJhdG9yIGJ1dCB3b3JrcyBwcm9wZXJseSB3aXRoIG5hdGl2ZXNcbiAqIGFuZCBudWxsL3VuZGVmaW5lZCB2YWx1ZXMuXG4gKlxuICogICAgIHZhciBvYmogPSB7XG4gKiAgICAgICAgIGFycjogWydhJywgJ2InLCAnYyddXG4gKiAgICAgICAsIHN0cjogJ0hlbGxvJ1xuICogICAgIH1cbiAqXG4gKiBUaGUgZm9sbG93aW5nIHdvdWxkIGJlIHRoZSByZXN1bHRzLlxuICpcbiAqICAgICBoYXNQcm9wZXJ0eSgnc3RyJywgb2JqKTsgIC8vIHRydWVcbiAqICAgICBoYXNQcm9wZXJ0eSgnY29uc3RydWN0b3InLCBvYmopOyAgLy8gdHJ1ZVxuICogICAgIGhhc1Byb3BlcnR5KCdiYXInLCBvYmopOyAgLy8gZmFsc2VcbiAqICAgICBcbiAqICAgICBoYXNQcm9wZXJ0eSgnbGVuZ3RoJywgb2JqLnN0cik7IC8vIHRydWVcbiAqICAgICBoYXNQcm9wZXJ0eSgxLCBvYmouc3RyKTsgIC8vIHRydWVcbiAqICAgICBoYXNQcm9wZXJ0eSg1LCBvYmouc3RyKTsgIC8vIGZhbHNlXG4gKlxuICogICAgIGhhc1Byb3BlcnR5KCdsZW5ndGgnLCBvYmouYXJyKTsgIC8vIHRydWVcbiAqICAgICBoYXNQcm9wZXJ0eSgyLCBvYmouYXJyKTsgIC8vIHRydWVcbiAqICAgICBoYXNQcm9wZXJ0eSgzLCBvYmouYXJyKTsgIC8vIGZhbHNlXG4gKlxuICogQHBhcmFtIHtPYmp1ZWN0fSBvYmplY3RcbiAqIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gbmFtZVxuICogQHJldHVybnMge0Jvb2xlYW59IHdoZXRoZXIgaXQgZXhpc3RzXG4gKiBAbmFtZSBnZXRQYXRoSW5mb1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG52YXIgbGl0ZXJhbHMgPSB7XG4gICAgJ251bWJlcic6IE51bWJlclxuICAsICdzdHJpbmcnOiBTdHJpbmdcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFzUHJvcGVydHkobmFtZSwgb2JqKSB7XG4gIHZhciBvdCA9IHR5cGUob2JqKTtcblxuICAvLyBCYWQgT2JqZWN0LCBvYnZpb3VzbHkgbm8gcHJvcHMgYXQgYWxsXG4gIGlmKG90ID09PSAnbnVsbCcgfHwgb3QgPT09ICd1bmRlZmluZWQnKVxuICAgIHJldHVybiBmYWxzZTtcblxuICAvLyBUaGUgYGluYCBvcGVyYXRvciBkb2VzIG5vdCB3b3JrIHdpdGggY2VydGFpbiBsaXRlcmFsc1xuICAvLyBib3ggdGhlc2UgYmVmb3JlIHRoZSBjaGVja1xuICBpZihsaXRlcmFsc1tvdF0gJiYgdHlwZW9mIG9iaiAhPT0gJ29iamVjdCcpXG4gICAgb2JqID0gbmV3IGxpdGVyYWxzW290XShvYmopO1xuXG4gIHJldHVybiBuYW1lIGluIG9iajtcbn07XG4iLCIvKiFcbiAqIGNoYWlcbiAqIENvcHlyaWdodChjKSAyMDExIEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBNYWluIGV4cG9ydHNcbiAqL1xuXG52YXIgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbi8qIVxuICogdGVzdCB1dGlsaXR5XG4gKi9cblxuZXhwb3J0cy50ZXN0ID0gcmVxdWlyZSgnLi90ZXN0Jyk7XG5cbi8qIVxuICogdHlwZSB1dGlsaXR5XG4gKi9cblxuZXhwb3J0cy50eXBlID0gcmVxdWlyZSgnLi90eXBlJyk7XG5cbi8qIVxuICogbWVzc2FnZSB1dGlsaXR5XG4gKi9cblxuZXhwb3J0cy5nZXRNZXNzYWdlID0gcmVxdWlyZSgnLi9nZXRNZXNzYWdlJyk7XG5cbi8qIVxuICogYWN0dWFsIHV0aWxpdHlcbiAqL1xuXG5leHBvcnRzLmdldEFjdHVhbCA9IHJlcXVpcmUoJy4vZ2V0QWN0dWFsJyk7XG5cbi8qIVxuICogSW5zcGVjdCB1dGlsXG4gKi9cblxuZXhwb3J0cy5pbnNwZWN0ID0gcmVxdWlyZSgnLi9pbnNwZWN0Jyk7XG5cbi8qIVxuICogT2JqZWN0IERpc3BsYXkgdXRpbFxuICovXG5cbmV4cG9ydHMub2JqRGlzcGxheSA9IHJlcXVpcmUoJy4vb2JqRGlzcGxheScpO1xuXG4vKiFcbiAqIEZsYWcgdXRpbGl0eVxuICovXG5cbmV4cG9ydHMuZmxhZyA9IHJlcXVpcmUoJy4vZmxhZycpO1xuXG4vKiFcbiAqIEZsYWcgdHJhbnNmZXJyaW5nIHV0aWxpdHlcbiAqL1xuXG5leHBvcnRzLnRyYW5zZmVyRmxhZ3MgPSByZXF1aXJlKCcuL3RyYW5zZmVyRmxhZ3MnKTtcblxuLyohXG4gKiBEZWVwIGVxdWFsIHV0aWxpdHlcbiAqL1xuXG5leHBvcnRzLmVxbCA9IHJlcXVpcmUoJ2RlZXAtZXFsJyk7XG5cbi8qIVxuICogRGVlcCBwYXRoIHZhbHVlXG4gKi9cblxuZXhwb3J0cy5nZXRQYXRoVmFsdWUgPSByZXF1aXJlKCcuL2dldFBhdGhWYWx1ZScpO1xuXG4vKiFcbiAqIERlZXAgcGF0aCBpbmZvXG4gKi9cblxuZXhwb3J0cy5nZXRQYXRoSW5mbyA9IHJlcXVpcmUoJy4vZ2V0UGF0aEluZm8nKTtcblxuLyohXG4gKiBDaGVjayBpZiBhIHByb3BlcnR5IGV4aXN0c1xuICovXG5cbmV4cG9ydHMuaGFzUHJvcGVydHkgPSByZXF1aXJlKCcuL2hhc1Byb3BlcnR5Jyk7XG5cbi8qIVxuICogRnVuY3Rpb24gbmFtZVxuICovXG5cbmV4cG9ydHMuZ2V0TmFtZSA9IHJlcXVpcmUoJy4vZ2V0TmFtZScpO1xuXG4vKiFcbiAqIGFkZCBQcm9wZXJ0eVxuICovXG5cbmV4cG9ydHMuYWRkUHJvcGVydHkgPSByZXF1aXJlKCcuL2FkZFByb3BlcnR5Jyk7XG5cbi8qIVxuICogYWRkIE1ldGhvZFxuICovXG5cbmV4cG9ydHMuYWRkTWV0aG9kID0gcmVxdWlyZSgnLi9hZGRNZXRob2QnKTtcblxuLyohXG4gKiBvdmVyd3JpdGUgUHJvcGVydHlcbiAqL1xuXG5leHBvcnRzLm92ZXJ3cml0ZVByb3BlcnR5ID0gcmVxdWlyZSgnLi9vdmVyd3JpdGVQcm9wZXJ0eScpO1xuXG4vKiFcbiAqIG92ZXJ3cml0ZSBNZXRob2RcbiAqL1xuXG5leHBvcnRzLm92ZXJ3cml0ZU1ldGhvZCA9IHJlcXVpcmUoJy4vb3ZlcndyaXRlTWV0aG9kJyk7XG5cbi8qIVxuICogQWRkIGEgY2hhaW5hYmxlIG1ldGhvZFxuICovXG5cbmV4cG9ydHMuYWRkQ2hhaW5hYmxlTWV0aG9kID0gcmVxdWlyZSgnLi9hZGRDaGFpbmFibGVNZXRob2QnKTtcblxuLyohXG4gKiBPdmVyd3JpdGUgY2hhaW5hYmxlIG1ldGhvZFxuICovXG5cbmV4cG9ydHMub3ZlcndyaXRlQ2hhaW5hYmxlTWV0aG9kID0gcmVxdWlyZSgnLi9vdmVyd3JpdGVDaGFpbmFibGVNZXRob2QnKTtcblxuIiwiLy8gVGhpcyBpcyAoYWxtb3N0KSBkaXJlY3RseSBmcm9tIE5vZGUuanMgdXRpbHNcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qb3llbnQvbm9kZS9ibG9iL2Y4YzMzNWQwY2FmNDdmMTZkMzE0MTNmODlhYTI4ZWRhMzg3OGUzYWEvbGliL3V0aWwuanNcblxudmFyIGdldE5hbWUgPSByZXF1aXJlKCcuL2dldE5hbWUnKTtcbnZhciBnZXRQcm9wZXJ0aWVzID0gcmVxdWlyZSgnLi9nZXRQcm9wZXJ0aWVzJyk7XG52YXIgZ2V0RW51bWVyYWJsZVByb3BlcnRpZXMgPSByZXF1aXJlKCcuL2dldEVudW1lcmFibGVQcm9wZXJ0aWVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gaW5zcGVjdDtcblxuLyoqXG4gKiBFY2hvcyB0aGUgdmFsdWUgb2YgYSB2YWx1ZS4gVHJ5cyB0byBwcmludCB0aGUgdmFsdWUgb3V0XG4gKiBpbiB0aGUgYmVzdCB3YXkgcG9zc2libGUgZ2l2ZW4gdGhlIGRpZmZlcmVudCB0eXBlcy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqIFRoZSBvYmplY3QgdG8gcHJpbnQgb3V0LlxuICogQHBhcmFtIHtCb29sZWFufSBzaG93SGlkZGVuIEZsYWcgdGhhdCBzaG93cyBoaWRkZW4gKG5vdCBlbnVtZXJhYmxlKVxuICogICAgcHJvcGVydGllcyBvZiBvYmplY3RzLlxuICogQHBhcmFtIHtOdW1iZXJ9IGRlcHRoIERlcHRoIGluIHdoaWNoIHRvIGRlc2NlbmQgaW4gb2JqZWN0LiBEZWZhdWx0IGlzIDIuXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGNvbG9ycyBGbGFnIHRvIHR1cm4gb24gQU5TSSBlc2NhcGUgY29kZXMgdG8gY29sb3IgdGhlXG4gKiAgICBvdXRwdXQuIERlZmF1bHQgaXMgZmFsc2UgKG5vIGNvbG9yaW5nKS5cbiAqL1xuZnVuY3Rpb24gaW5zcGVjdChvYmosIHNob3dIaWRkZW4sIGRlcHRoLCBjb2xvcnMpIHtcbiAgdmFyIGN0eCA9IHtcbiAgICBzaG93SGlkZGVuOiBzaG93SGlkZGVuLFxuICAgIHNlZW46IFtdLFxuICAgIHN0eWxpemU6IGZ1bmN0aW9uIChzdHIpIHsgcmV0dXJuIHN0cjsgfVxuICB9O1xuICByZXR1cm4gZm9ybWF0VmFsdWUoY3R4LCBvYmosICh0eXBlb2YgZGVwdGggPT09ICd1bmRlZmluZWQnID8gMiA6IGRlcHRoKSk7XG59XG5cbi8vIFJldHVybnMgdHJ1ZSBpZiBvYmplY3QgaXMgYSBET00gZWxlbWVudC5cbnZhciBpc0RPTUVsZW1lbnQgPSBmdW5jdGlvbiAob2JqZWN0KSB7XG4gIGlmICh0eXBlb2YgSFRNTEVsZW1lbnQgPT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIG9iamVjdCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50O1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBvYmplY3QgJiZcbiAgICAgIHR5cGVvZiBvYmplY3QgPT09ICdvYmplY3QnICYmXG4gICAgICBvYmplY3Qubm9kZVR5cGUgPT09IDEgJiZcbiAgICAgIHR5cGVvZiBvYmplY3Qubm9kZU5hbWUgPT09ICdzdHJpbmcnO1xuICB9XG59O1xuXG5mdW5jdGlvbiBmb3JtYXRWYWx1ZShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMpIHtcbiAgLy8gUHJvdmlkZSBhIGhvb2sgZm9yIHVzZXItc3BlY2lmaWVkIGluc3BlY3QgZnVuY3Rpb25zLlxuICAvLyBDaGVjayB0aGF0IHZhbHVlIGlzIGFuIG9iamVjdCB3aXRoIGFuIGluc3BlY3QgZnVuY3Rpb24gb24gaXRcbiAgaWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZS5pbnNwZWN0ID09PSAnZnVuY3Rpb24nICYmXG4gICAgICAvLyBGaWx0ZXIgb3V0IHRoZSB1dGlsIG1vZHVsZSwgaXQncyBpbnNwZWN0IGZ1bmN0aW9uIGlzIHNwZWNpYWxcbiAgICAgIHZhbHVlLmluc3BlY3QgIT09IGV4cG9ydHMuaW5zcGVjdCAmJlxuICAgICAgLy8gQWxzbyBmaWx0ZXIgb3V0IGFueSBwcm90b3R5cGUgb2JqZWN0cyB1c2luZyB0aGUgY2lyY3VsYXIgY2hlY2suXG4gICAgICAhKHZhbHVlLmNvbnN0cnVjdG9yICYmIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZSA9PT0gdmFsdWUpKSB7XG4gICAgdmFyIHJldCA9IHZhbHVlLmluc3BlY3QocmVjdXJzZVRpbWVzKTtcbiAgICBpZiAodHlwZW9mIHJldCAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldCA9IGZvcm1hdFZhbHVlKGN0eCwgcmV0LCByZWN1cnNlVGltZXMpO1xuICAgIH1cbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgLy8gUHJpbWl0aXZlIHR5cGVzIGNhbm5vdCBoYXZlIHByb3BlcnRpZXNcbiAgdmFyIHByaW1pdGl2ZSA9IGZvcm1hdFByaW1pdGl2ZShjdHgsIHZhbHVlKTtcbiAgaWYgKHByaW1pdGl2ZSkge1xuICAgIHJldHVybiBwcmltaXRpdmU7XG4gIH1cblxuICAvLyBJZiB0aGlzIGlzIGEgRE9NIGVsZW1lbnQsIHRyeSB0byBnZXQgdGhlIG91dGVyIEhUTUwuXG4gIGlmIChpc0RPTUVsZW1lbnQodmFsdWUpKSB7XG4gICAgaWYgKCdvdXRlckhUTUwnIGluIHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWUub3V0ZXJIVE1MO1xuICAgICAgLy8gVGhpcyB2YWx1ZSBkb2VzIG5vdCBoYXZlIGFuIG91dGVySFRNTCBhdHRyaWJ1dGUsXG4gICAgICAvLyAgIGl0IGNvdWxkIHN0aWxsIGJlIGFuIFhNTCBlbGVtZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0dGVtcHQgdG8gc2VyaWFsaXplIGl0XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoZG9jdW1lbnQueG1sVmVyc2lvbikge1xuICAgICAgICAgIHZhciB4bWxTZXJpYWxpemVyID0gbmV3IFhNTFNlcmlhbGl6ZXIoKTtcbiAgICAgICAgICByZXR1cm4geG1sU2VyaWFsaXplci5zZXJpYWxpemVUb1N0cmluZyh2YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gRmlyZWZveCAxMS0gZG8gbm90IHN1cHBvcnQgb3V0ZXJIVE1MXG4gICAgICAgICAgLy8gICBJdCBkb2VzLCBob3dldmVyLCBzdXBwb3J0IGlubmVySFRNTFxuICAgICAgICAgIC8vICAgVXNlIHRoZSBmb2xsb3dpbmcgdG8gcmVuZGVyIHRoZSBlbGVtZW50XG4gICAgICAgICAgdmFyIG5zID0gXCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sXCI7XG4gICAgICAgICAgdmFyIGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhucywgJ18nKTtcblxuICAgICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZCh2YWx1ZS5jbG9uZU5vZGUoZmFsc2UpKTtcbiAgICAgICAgICBodG1sID0gY29udGFpbmVyLmlubmVySFRNTFxuICAgICAgICAgICAgLnJlcGxhY2UoJz48JywgJz4nICsgdmFsdWUuaW5uZXJIVE1MICsgJzwnKTtcbiAgICAgICAgICBjb250YWluZXIuaW5uZXJIVE1MID0gJyc7XG4gICAgICAgICAgcmV0dXJuIGh0bWw7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAvLyBUaGlzIGNvdWxkIGJlIGEgbm9uLW5hdGl2ZSBET00gaW1wbGVtZW50YXRpb24sXG4gICAgICAgIC8vICAgY29udGludWUgd2l0aCB0aGUgbm9ybWFsIGZsb3c6XG4gICAgICAgIC8vICAgcHJpbnRpbmcgdGhlIGVsZW1lbnQgYXMgaWYgaXQgaXMgYW4gb2JqZWN0LlxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIExvb2sgdXAgdGhlIGtleXMgb2YgdGhlIG9iamVjdC5cbiAgdmFyIHZpc2libGVLZXlzID0gZ2V0RW51bWVyYWJsZVByb3BlcnRpZXModmFsdWUpO1xuICB2YXIga2V5cyA9IGN0eC5zaG93SGlkZGVuID8gZ2V0UHJvcGVydGllcyh2YWx1ZSkgOiB2aXNpYmxlS2V5cztcblxuICAvLyBTb21lIHR5cGUgb2Ygb2JqZWN0IHdpdGhvdXQgcHJvcGVydGllcyBjYW4gYmUgc2hvcnRjdXR0ZWQuXG4gIC8vIEluIElFLCBlcnJvcnMgaGF2ZSBhIHNpbmdsZSBgc3RhY2tgIHByb3BlcnR5LCBvciBpZiB0aGV5IGFyZSB2YW5pbGxhIGBFcnJvcmAsXG4gIC8vIGEgYHN0YWNrYCBwbHVzIGBkZXNjcmlwdGlvbmAgcHJvcGVydHk7IGlnbm9yZSB0aG9zZSBmb3IgY29uc2lzdGVuY3kuXG4gIGlmIChrZXlzLmxlbmd0aCA9PT0gMCB8fCAoaXNFcnJvcih2YWx1ZSkgJiYgKFxuICAgICAgKGtleXMubGVuZ3RoID09PSAxICYmIGtleXNbMF0gPT09ICdzdGFjaycpIHx8XG4gICAgICAoa2V5cy5sZW5ndGggPT09IDIgJiYga2V5c1swXSA9PT0gJ2Rlc2NyaXB0aW9uJyAmJiBrZXlzWzFdID09PSAnc3RhY2snKVxuICAgICApKSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHZhciBuYW1lID0gZ2V0TmFtZSh2YWx1ZSk7XG4gICAgICB2YXIgbmFtZVN1ZmZpeCA9IG5hbWUgPyAnOiAnICsgbmFtZSA6ICcnO1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbRnVuY3Rpb24nICsgbmFtZVN1ZmZpeCArICddJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9XG4gICAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShEYXRlLnByb3RvdHlwZS50b1VUQ1N0cmluZy5jYWxsKHZhbHVlKSwgJ2RhdGUnKTtcbiAgICB9XG4gICAgaWYgKGlzRXJyb3IodmFsdWUpKSB7XG4gICAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBiYXNlID0gJycsIGFycmF5ID0gZmFsc2UsIGJyYWNlcyA9IFsneycsICd9J107XG5cbiAgLy8gTWFrZSBBcnJheSBzYXkgdGhhdCB0aGV5IGFyZSBBcnJheVxuICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBhcnJheSA9IHRydWU7XG4gICAgYnJhY2VzID0gWydbJywgJ10nXTtcbiAgfVxuXG4gIC8vIE1ha2UgZnVuY3Rpb25zIHNheSB0aGF0IHRoZXkgYXJlIGZ1bmN0aW9uc1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgdmFyIG5hbWUgPSBnZXROYW1lKHZhbHVlKTtcbiAgICB2YXIgbmFtZVN1ZmZpeCA9IG5hbWUgPyAnOiAnICsgbmFtZSA6ICcnO1xuICAgIGJhc2UgPSAnIFtGdW5jdGlvbicgKyBuYW1lU3VmZml4ICsgJ10nO1xuICB9XG5cbiAgLy8gTWFrZSBSZWdFeHBzIHNheSB0aGF0IHRoZXkgYXJlIFJlZ0V4cHNcbiAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBkYXRlcyB3aXRoIHByb3BlcnRpZXMgZmlyc3Qgc2F5IHRoZSBkYXRlXG4gIGlmIChpc0RhdGUodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIERhdGUucHJvdG90eXBlLnRvVVRDU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBlcnJvciB3aXRoIG1lc3NhZ2UgZmlyc3Qgc2F5IHRoZSBlcnJvclxuICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICB9XG5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwICYmICghYXJyYXkgfHwgdmFsdWUubGVuZ3RoID09IDApKSB7XG4gICAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyBicmFjZXNbMV07XG4gIH1cblxuICBpZiAocmVjdXJzZVRpbWVzIDwgMCkge1xuICAgIGlmIChpc1JlZ0V4cCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAncmVnZXhwJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgnW09iamVjdF0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuXG4gIGN0eC5zZWVuLnB1c2godmFsdWUpO1xuXG4gIHZhciBvdXRwdXQ7XG4gIGlmIChhcnJheSkge1xuICAgIG91dHB1dCA9IGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpO1xuICB9IGVsc2Uge1xuICAgIG91dHB1dCA9IGtleXMubWFwKGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpO1xuICAgIH0pO1xuICB9XG5cbiAgY3R4LnNlZW4ucG9wKCk7XG5cbiAgcmV0dXJuIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRQcmltaXRpdmUoY3R4LCB2YWx1ZSkge1xuICBzd2l0Y2ggKHR5cGVvZiB2YWx1ZSkge1xuICAgIGNhc2UgJ3VuZGVmaW5lZCc6XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJ3VuZGVmaW5lZCcsICd1bmRlZmluZWQnKTtcblxuICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICB2YXIgc2ltcGxlID0gJ1xcJycgKyBKU09OLnN0cmluZ2lmeSh2YWx1ZSkucmVwbGFjZSgvXlwifFwiJC9nLCAnJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnJlcGxhY2UoLycvZywgXCJcXFxcJ1wiKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxcXFwiL2csICdcIicpICsgJ1xcJyc7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoc2ltcGxlLCAnc3RyaW5nJyk7XG5cbiAgICBjYXNlICdudW1iZXInOlxuICAgICAgaWYgKHZhbHVlID09PSAwICYmICgxL3ZhbHVlKSA9PT0gLUluZmluaXR5KSB7XG4gICAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgnLTAnLCAnbnVtYmVyJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJycgKyB2YWx1ZSwgJ251bWJlcicpO1xuXG4gICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJycgKyB2YWx1ZSwgJ2Jvb2xlYW4nKTtcbiAgfVxuICAvLyBGb3Igc29tZSByZWFzb24gdHlwZW9mIG51bGwgaXMgXCJvYmplY3RcIiwgc28gc3BlY2lhbCBjYXNlIGhlcmUuXG4gIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgIHJldHVybiBjdHguc3R5bGl6ZSgnbnVsbCcsICdudWxsJyk7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRFcnJvcih2YWx1ZSkge1xuICByZXR1cm4gJ1snICsgRXJyb3IucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpICsgJ10nO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpIHtcbiAgdmFyIG91dHB1dCA9IFtdO1xuICBmb3IgKHZhciBpID0gMCwgbCA9IHZhbHVlLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodmFsdWUsIFN0cmluZyhpKSkpIHtcbiAgICAgIG91dHB1dC5wdXNoKGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsXG4gICAgICAgICAgU3RyaW5nKGkpLCB0cnVlKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dHB1dC5wdXNoKCcnKTtcbiAgICB9XG4gIH1cbiAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgIGlmICgha2V5Lm1hdGNoKC9eXFxkKyQvKSkge1xuICAgICAgb3V0cHV0LnB1c2goZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cyxcbiAgICAgICAgICBrZXksIHRydWUpKTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gb3V0cHV0O1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpIHtcbiAgdmFyIG5hbWUsIHN0cjtcbiAgaWYgKHZhbHVlLl9fbG9va3VwR2V0dGVyX18pIHtcbiAgICBpZiAodmFsdWUuX19sb29rdXBHZXR0ZXJfXyhrZXkpKSB7XG4gICAgICBpZiAodmFsdWUuX19sb29rdXBTZXR0ZXJfXyhrZXkpKSB7XG4gICAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbR2V0dGVyL1NldHRlcl0nLCAnc3BlY2lhbCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHZhbHVlLl9fbG9va3VwU2V0dGVyX18oa2V5KSkge1xuICAgICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW1NldHRlcl0nLCAnc3BlY2lhbCcpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBpZiAodmlzaWJsZUtleXMuaW5kZXhPZihrZXkpIDwgMCkge1xuICAgIG5hbWUgPSAnWycgKyBrZXkgKyAnXSc7XG4gIH1cbiAgaWYgKCFzdHIpIHtcbiAgICBpZiAoY3R4LnNlZW4uaW5kZXhPZih2YWx1ZVtrZXldKSA8IDApIHtcbiAgICAgIGlmIChyZWN1cnNlVGltZXMgPT09IG51bGwpIHtcbiAgICAgICAgc3RyID0gZm9ybWF0VmFsdWUoY3R4LCB2YWx1ZVtrZXldLCBudWxsKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0ciA9IGZvcm1hdFZhbHVlKGN0eCwgdmFsdWVba2V5XSwgcmVjdXJzZVRpbWVzIC0gMSk7XG4gICAgICB9XG4gICAgICBpZiAoc3RyLmluZGV4T2YoJ1xcbicpID4gLTEpIHtcbiAgICAgICAgaWYgKGFycmF5KSB7XG4gICAgICAgICAgc3RyID0gc3RyLnNwbGl0KCdcXG4nKS5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgcmV0dXJuICcgICcgKyBsaW5lO1xuICAgICAgICAgIH0pLmpvaW4oJ1xcbicpLnN1YnN0cigyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzdHIgPSAnXFxuJyArIHN0ci5zcGxpdCgnXFxuJykubWFwKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgICAgICAgIHJldHVybiAnICAgJyArIGxpbmU7XG4gICAgICAgICAgfSkuam9pbignXFxuJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tDaXJjdWxhcl0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuICBpZiAodHlwZW9mIG5hbWUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKGFycmF5ICYmIGtleS5tYXRjaCgvXlxcZCskLykpIHtcbiAgICAgIHJldHVybiBzdHI7XG4gICAgfVxuICAgIG5hbWUgPSBKU09OLnN0cmluZ2lmeSgnJyArIGtleSk7XG4gICAgaWYgKG5hbWUubWF0Y2goL15cIihbYS16QS1aX11bYS16QS1aXzAtOV0qKVwiJC8pKSB7XG4gICAgICBuYW1lID0gbmFtZS5zdWJzdHIoMSwgbmFtZS5sZW5ndGggLSAyKTtcbiAgICAgIG5hbWUgPSBjdHguc3R5bGl6ZShuYW1lLCAnbmFtZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuYW1lID0gbmFtZS5yZXBsYWNlKC8nL2csIFwiXFxcXCdcIilcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcXFxcIi9nLCAnXCInKVxuICAgICAgICAgICAgICAgICAucmVwbGFjZSgvKF5cInxcIiQpL2csIFwiJ1wiKTtcbiAgICAgIG5hbWUgPSBjdHguc3R5bGl6ZShuYW1lLCAnc3RyaW5nJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5hbWUgKyAnOiAnICsgc3RyO1xufVxuXG5cbmZ1bmN0aW9uIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKSB7XG4gIHZhciBudW1MaW5lc0VzdCA9IDA7XG4gIHZhciBsZW5ndGggPSBvdXRwdXQucmVkdWNlKGZ1bmN0aW9uKHByZXYsIGN1cikge1xuICAgIG51bUxpbmVzRXN0Kys7XG4gICAgaWYgKGN1ci5pbmRleE9mKCdcXG4nKSA+PSAwKSBudW1MaW5lc0VzdCsrO1xuICAgIHJldHVybiBwcmV2ICsgY3VyLmxlbmd0aCArIDE7XG4gIH0sIDApO1xuXG4gIGlmIChsZW5ndGggPiA2MCkge1xuICAgIHJldHVybiBicmFjZXNbMF0gK1xuICAgICAgICAgICAoYmFzZSA9PT0gJycgPyAnJyA6IGJhc2UgKyAnXFxuICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgb3V0cHV0LmpvaW4oJyxcXG4gICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgYnJhY2VzWzFdO1xuICB9XG5cbiAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyAnICcgKyBvdXRwdXQuam9pbignLCAnKSArICcgJyArIGJyYWNlc1sxXTtcbn1cblxuZnVuY3Rpb24gaXNBcnJheShhcikge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShhcikgfHxcbiAgICAgICAgICh0eXBlb2YgYXIgPT09ICdvYmplY3QnICYmIG9iamVjdFRvU3RyaW5nKGFyKSA9PT0gJ1tvYmplY3QgQXJyYXldJyk7XG59XG5cbmZ1bmN0aW9uIGlzUmVnRXhwKHJlKSB7XG4gIHJldHVybiB0eXBlb2YgcmUgPT09ICdvYmplY3QnICYmIG9iamVjdFRvU3RyaW5nKHJlKSA9PT0gJ1tvYmplY3QgUmVnRXhwXSc7XG59XG5cbmZ1bmN0aW9uIGlzRGF0ZShkKSB7XG4gIHJldHVybiB0eXBlb2YgZCA9PT0gJ29iamVjdCcgJiYgb2JqZWN0VG9TdHJpbmcoZCkgPT09ICdbb2JqZWN0IERhdGVdJztcbn1cblxuZnVuY3Rpb24gaXNFcnJvcihlKSB7XG4gIHJldHVybiB0eXBlb2YgZSA9PT0gJ29iamVjdCcgJiYgb2JqZWN0VG9TdHJpbmcoZSkgPT09ICdbb2JqZWN0IEVycm9yXSc7XG59XG5cbmZ1bmN0aW9uIG9iamVjdFRvU3RyaW5nKG8pIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTtcbn1cbiIsIi8qIVxuICogQ2hhaSAtIGZsYWcgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qIVxuICogTW9kdWxlIGRlcGVuZGFuY2llc1xuICovXG5cbnZhciBpbnNwZWN0ID0gcmVxdWlyZSgnLi9pbnNwZWN0Jyk7XG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi4vY29uZmlnJyk7XG5cbi8qKlxuICogIyMjIC5vYmpEaXNwbGF5IChvYmplY3QpXG4gKlxuICogRGV0ZXJtaW5lcyBpZiBhbiBvYmplY3Qgb3IgYW4gYXJyYXkgbWF0Y2hlc1xuICogY3JpdGVyaWEgdG8gYmUgaW5zcGVjdGVkIGluLWxpbmUgZm9yIGVycm9yXG4gKiBtZXNzYWdlcyBvciBzaG91bGQgYmUgdHJ1bmNhdGVkLlxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IGphdmFzY3JpcHQgb2JqZWN0IHRvIGluc3BlY3RcbiAqIEBuYW1lIG9iakRpc3BsYXlcbiAqIEBhcGkgcHVibGljXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7XG4gIHZhciBzdHIgPSBpbnNwZWN0KG9iailcbiAgICAsIHR5cGUgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKTtcblxuICBpZiAoY29uZmlnLnRydW5jYXRlVGhyZXNob2xkICYmIHN0ci5sZW5ndGggPj0gY29uZmlnLnRydW5jYXRlVGhyZXNob2xkKSB7XG4gICAgaWYgKHR5cGUgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXScpIHtcbiAgICAgIHJldHVybiAhb2JqLm5hbWUgfHwgb2JqLm5hbWUgPT09ICcnXG4gICAgICAgID8gJ1tGdW5jdGlvbl0nXG4gICAgICAgIDogJ1tGdW5jdGlvbjogJyArIG9iai5uYW1lICsgJ10nO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ1tvYmplY3QgQXJyYXldJykge1xuICAgICAgcmV0dXJuICdbIEFycmF5KCcgKyBvYmoubGVuZ3RoICsgJykgXSc7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnW29iamVjdCBPYmplY3RdJykge1xuICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhvYmopXG4gICAgICAgICwga3N0ciA9IGtleXMubGVuZ3RoID4gMlxuICAgICAgICAgID8ga2V5cy5zcGxpY2UoMCwgMikuam9pbignLCAnKSArICcsIC4uLidcbiAgICAgICAgICA6IGtleXMuam9pbignLCAnKTtcbiAgICAgIHJldHVybiAneyBPYmplY3QgKCcgKyBrc3RyICsgJykgfSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBzdHI7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBzdHI7XG4gIH1cbn07XG4iLCIvKiFcbiAqIENoYWkgLSBvdmVyd3JpdGVDaGFpbmFibGVNZXRob2QgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIG92ZXJ3cml0ZUNoYWluYWJsZU1ldGhvZCAoY3R4LCBuYW1lLCBtZXRob2QsIGNoYWluaW5nQmVoYXZpb3IpXG4gKlxuICogT3ZlcndpdGVzIGFuIGFscmVhZHkgZXhpc3RpbmcgY2hhaW5hYmxlIG1ldGhvZFxuICogYW5kIHByb3ZpZGVzIGFjY2VzcyB0byB0aGUgcHJldmlvdXMgZnVuY3Rpb24gb3JcbiAqIHByb3BlcnR5LiAgTXVzdCByZXR1cm4gZnVuY3Rpb25zIHRvIGJlIHVzZWQgZm9yXG4gKiBuYW1lLlxuICpcbiAqICAgICB1dGlscy5vdmVyd3JpdGVDaGFpbmFibGVNZXRob2QoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCAnbGVuZ3RoJyxcbiAqICAgICAgIGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAqICAgICAgIH1cbiAqICAgICAsIGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAqICAgICAgIH1cbiAqICAgICApO1xuICpcbiAqIENhbiBhbHNvIGJlIGFjY2Vzc2VkIGRpcmVjdGx5IGZyb20gYGNoYWkuQXNzZXJ0aW9uYC5cbiAqXG4gKiAgICAgY2hhaS5Bc3NlcnRpb24ub3ZlcndyaXRlQ2hhaW5hYmxlTWV0aG9kKCdmb28nLCBmbiwgZm4pO1xuICpcbiAqIFRoZW4gY2FuIGJlIHVzZWQgYXMgYW55IG90aGVyIGFzc2VydGlvbi5cbiAqXG4gKiAgICAgZXhwZWN0KG15Rm9vKS50by5oYXZlLmxlbmd0aCgzKTtcbiAqICAgICBleHBlY3QobXlGb28pLnRvLmhhdmUubGVuZ3RoLmFib3ZlKDMpO1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjdHggb2JqZWN0IHdob3NlIG1ldGhvZCAvIHByb3BlcnR5IGlzIHRvIGJlIG92ZXJ3cml0dGVuXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiBtZXRob2QgLyBwcm9wZXJ0eSB0byBvdmVyd3JpdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG1ldGhvZCBmdW5jdGlvbiB0aGF0IHJldHVybnMgYSBmdW5jdGlvbiB0byBiZSB1c2VkIGZvciBuYW1lXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjaGFpbmluZ0JlaGF2aW9yIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIGZ1bmN0aW9uIHRvIGJlIHVzZWQgZm9yIHByb3BlcnR5XG4gKiBAbmFtZSBvdmVyd3JpdGVDaGFpbmFibGVNZXRob2RcbiAqIEBhcGkgcHVibGljXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoY3R4LCBuYW1lLCBtZXRob2QsIGNoYWluaW5nQmVoYXZpb3IpIHtcbiAgdmFyIGNoYWluYWJsZUJlaGF2aW9yID0gY3R4Ll9fbWV0aG9kc1tuYW1lXTtcblxuICB2YXIgX2NoYWluaW5nQmVoYXZpb3IgPSBjaGFpbmFibGVCZWhhdmlvci5jaGFpbmluZ0JlaGF2aW9yO1xuICBjaGFpbmFibGVCZWhhdmlvci5jaGFpbmluZ0JlaGF2aW9yID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciByZXN1bHQgPSBjaGFpbmluZ0JlaGF2aW9yKF9jaGFpbmluZ0JlaGF2aW9yKS5jYWxsKHRoaXMpO1xuICAgIHJldHVybiByZXN1bHQgPT09IHVuZGVmaW5lZCA/IHRoaXMgOiByZXN1bHQ7XG4gIH07XG5cbiAgdmFyIF9tZXRob2QgPSBjaGFpbmFibGVCZWhhdmlvci5tZXRob2Q7XG4gIGNoYWluYWJsZUJlaGF2aW9yLm1ldGhvZCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmVzdWx0ID0gbWV0aG9kKF9tZXRob2QpLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gdGhpcyA6IHJlc3VsdDtcbiAgfTtcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBvdmVyd3JpdGVNZXRob2QgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIG92ZXJ3cml0ZU1ldGhvZCAoY3R4LCBuYW1lLCBmbilcbiAqXG4gKiBPdmVyd2l0ZXMgYW4gYWxyZWFkeSBleGlzdGluZyBtZXRob2QgYW5kIHByb3ZpZGVzXG4gKiBhY2Nlc3MgdG8gcHJldmlvdXMgZnVuY3Rpb24uIE11c3QgcmV0dXJuIGZ1bmN0aW9uXG4gKiB0byBiZSB1c2VkIGZvciBuYW1lLlxuICpcbiAqICAgICB1dGlscy5vdmVyd3JpdGVNZXRob2QoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCAnZXF1YWwnLCBmdW5jdGlvbiAoX3N1cGVyKSB7XG4gKiAgICAgICByZXR1cm4gZnVuY3Rpb24gKHN0cikge1xuICogICAgICAgICB2YXIgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gKiAgICAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBGb28pIHtcbiAqICAgICAgICAgICBuZXcgY2hhaS5Bc3NlcnRpb24ob2JqLnZhbHVlKS50by5lcXVhbChzdHIpO1xuICogICAgICAgICB9IGVsc2Uge1xuICogICAgICAgICAgIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICogICAgICAgICB9XG4gKiAgICAgICB9XG4gKiAgICAgfSk7XG4gKlxuICogQ2FuIGFsc28gYmUgYWNjZXNzZWQgZGlyZWN0bHkgZnJvbSBgY2hhaS5Bc3NlcnRpb25gLlxuICpcbiAqICAgICBjaGFpLkFzc2VydGlvbi5vdmVyd3JpdGVNZXRob2QoJ2ZvbycsIGZuKTtcbiAqXG4gKiBUaGVuIGNhbiBiZSB1c2VkIGFzIGFueSBvdGhlciBhc3NlcnRpb24uXG4gKlxuICogICAgIGV4cGVjdChteUZvbykudG8uZXF1YWwoJ2JhcicpO1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjdHggb2JqZWN0IHdob3NlIG1ldGhvZCBpcyB0byBiZSBvdmVyd3JpdHRlblxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgb2YgbWV0aG9kIHRvIG92ZXJ3cml0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gbWV0aG9kIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIGZ1bmN0aW9uIHRvIGJlIHVzZWQgZm9yIG5hbWVcbiAqIEBuYW1lIG92ZXJ3cml0ZU1ldGhvZFxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjdHgsIG5hbWUsIG1ldGhvZCkge1xuICB2YXIgX21ldGhvZCA9IGN0eFtuYW1lXVxuICAgICwgX3N1cGVyID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfTtcblxuICBpZiAoX21ldGhvZCAmJiAnZnVuY3Rpb24nID09PSB0eXBlb2YgX21ldGhvZClcbiAgICBfc3VwZXIgPSBfbWV0aG9kO1xuXG4gIGN0eFtuYW1lXSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmVzdWx0ID0gbWV0aG9kKF9zdXBlcikuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICByZXR1cm4gcmVzdWx0ID09PSB1bmRlZmluZWQgPyB0aGlzIDogcmVzdWx0O1xuICB9XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gb3ZlcndyaXRlUHJvcGVydHkgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIG92ZXJ3cml0ZVByb3BlcnR5IChjdHgsIG5hbWUsIGZuKVxuICpcbiAqIE92ZXJ3aXRlcyBhbiBhbHJlYWR5IGV4aXN0aW5nIHByb3BlcnR5IGdldHRlciBhbmQgcHJvdmlkZXNcbiAqIGFjY2VzcyB0byBwcmV2aW91cyB2YWx1ZS4gTXVzdCByZXR1cm4gZnVuY3Rpb24gdG8gdXNlIGFzIGdldHRlci5cbiAqXG4gKiAgICAgdXRpbHMub3ZlcndyaXRlUHJvcGVydHkoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCAnb2snLCBmdW5jdGlvbiAoX3N1cGVyKSB7XG4gKiAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICogICAgICAgICB2YXIgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gKiAgICAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBGb28pIHtcbiAqICAgICAgICAgICBuZXcgY2hhaS5Bc3NlcnRpb24ob2JqLm5hbWUpLnRvLmVxdWFsKCdiYXInKTtcbiAqICAgICAgICAgfSBlbHNlIHtcbiAqICAgICAgICAgICBfc3VwZXIuY2FsbCh0aGlzKTtcbiAqICAgICAgICAgfVxuICogICAgICAgfVxuICogICAgIH0pO1xuICpcbiAqXG4gKiBDYW4gYWxzbyBiZSBhY2Nlc3NlZCBkaXJlY3RseSBmcm9tIGBjaGFpLkFzc2VydGlvbmAuXG4gKlxuICogICAgIGNoYWkuQXNzZXJ0aW9uLm92ZXJ3cml0ZVByb3BlcnR5KCdmb28nLCBmbik7XG4gKlxuICogVGhlbiBjYW4gYmUgdXNlZCBhcyBhbnkgb3RoZXIgYXNzZXJ0aW9uLlxuICpcbiAqICAgICBleHBlY3QobXlGb28pLnRvLmJlLm9rO1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjdHggb2JqZWN0IHdob3NlIHByb3BlcnR5IGlzIHRvIGJlIG92ZXJ3cml0dGVuXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiBwcm9wZXJ0eSB0byBvdmVyd3JpdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGdldHRlciBmdW5jdGlvbiB0aGF0IHJldHVybnMgYSBnZXR0ZXIgZnVuY3Rpb24gdG8gYmUgdXNlZCBmb3IgbmFtZVxuICogQG5hbWUgb3ZlcndyaXRlUHJvcGVydHlcbiAqIEBhcGkgcHVibGljXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoY3R4LCBuYW1lLCBnZXR0ZXIpIHtcbiAgdmFyIF9nZXQgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGN0eCwgbmFtZSlcbiAgICAsIF9zdXBlciA9IGZ1bmN0aW9uICgpIHt9O1xuXG4gIGlmIChfZ2V0ICYmICdmdW5jdGlvbicgPT09IHR5cGVvZiBfZ2V0LmdldClcbiAgICBfc3VwZXIgPSBfZ2V0LmdldFxuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjdHgsIG5hbWUsXG4gICAgeyBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGdldHRlcihfc3VwZXIpLmNhbGwodGhpcyk7XG4gICAgICAgIHJldHVybiByZXN1bHQgPT09IHVuZGVmaW5lZCA/IHRoaXMgOiByZXN1bHQ7XG4gICAgICB9XG4gICAgLCBjb25maWd1cmFibGU6IHRydWVcbiAgfSk7XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gdGVzdCB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBNb2R1bGUgZGVwZW5kYW5jaWVzXG4gKi9cblxudmFyIGZsYWcgPSByZXF1aXJlKCcuL2ZsYWcnKTtcblxuLyoqXG4gKiAjIHRlc3Qob2JqZWN0LCBleHByZXNzaW9uKVxuICpcbiAqIFRlc3QgYW5kIG9iamVjdCBmb3IgZXhwcmVzc2lvbi5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IChjb25zdHJ1Y3RlZCBBc3NlcnRpb24pXG4gKiBAcGFyYW0ge0FyZ3VtZW50c30gY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLmFzc2VydCBhcmd1bWVudHNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmosIGFyZ3MpIHtcbiAgdmFyIG5lZ2F0ZSA9IGZsYWcob2JqLCAnbmVnYXRlJylcbiAgICAsIGV4cHIgPSBhcmdzWzBdO1xuICByZXR1cm4gbmVnYXRlID8gIWV4cHIgOiBleHByO1xufTtcbiIsIi8qIVxuICogQ2hhaSAtIHRyYW5zZmVyRmxhZ3MgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIHRyYW5zZmVyRmxhZ3MoYXNzZXJ0aW9uLCBvYmplY3QsIGluY2x1ZGVBbGwgPSB0cnVlKVxuICpcbiAqIFRyYW5zZmVyIGFsbCB0aGUgZmxhZ3MgZm9yIGBhc3NlcnRpb25gIHRvIGBvYmplY3RgLiBJZlxuICogYGluY2x1ZGVBbGxgIGlzIHNldCB0byBgZmFsc2VgLCB0aGVuIHRoZSBiYXNlIENoYWlcbiAqIGFzc2VydGlvbiBmbGFncyAobmFtZWx5IGBvYmplY3RgLCBgc3NmaWAsIGFuZCBgbWVzc2FnZWApXG4gKiB3aWxsIG5vdCBiZSB0cmFuc2ZlcnJlZC5cbiAqXG4gKlxuICogICAgIHZhciBuZXdBc3NlcnRpb24gPSBuZXcgQXNzZXJ0aW9uKCk7XG4gKiAgICAgdXRpbHMudHJhbnNmZXJGbGFncyhhc3NlcnRpb24sIG5ld0Fzc2VydGlvbik7XG4gKlxuICogICAgIHZhciBhbm90aGVyQXNzZXJpdG9uID0gbmV3IEFzc2VydGlvbihteU9iaik7XG4gKiAgICAgdXRpbHMudHJhbnNmZXJGbGFncyhhc3NlcnRpb24sIGFub3RoZXJBc3NlcnRpb24sIGZhbHNlKTtcbiAqXG4gKiBAcGFyYW0ge0Fzc2VydGlvbn0gYXNzZXJ0aW9uIHRoZSBhc3NlcnRpb24gdG8gdHJhbnNmZXIgdGhlIGZsYWdzIGZyb21cbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgdGhlIG9iamVjdCB0byB0cmFuc2ZlciB0aGUgZmxhZ3MgdG87IHVzdWFsbHkgYSBuZXcgYXNzZXJ0aW9uXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGluY2x1ZGVBbGxcbiAqIEBuYW1lIHRyYW5zZmVyRmxhZ3NcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFzc2VydGlvbiwgb2JqZWN0LCBpbmNsdWRlQWxsKSB7XG4gIHZhciBmbGFncyA9IGFzc2VydGlvbi5fX2ZsYWdzIHx8IChhc3NlcnRpb24uX19mbGFncyA9IE9iamVjdC5jcmVhdGUobnVsbCkpO1xuXG4gIGlmICghb2JqZWN0Ll9fZmxhZ3MpIHtcbiAgICBvYmplY3QuX19mbGFncyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gIH1cblxuICBpbmNsdWRlQWxsID0gYXJndW1lbnRzLmxlbmd0aCA9PT0gMyA/IGluY2x1ZGVBbGwgOiB0cnVlO1xuXG4gIGZvciAodmFyIGZsYWcgaW4gZmxhZ3MpIHtcbiAgICBpZiAoaW5jbHVkZUFsbCB8fFxuICAgICAgICAoZmxhZyAhPT0gJ29iamVjdCcgJiYgZmxhZyAhPT0gJ3NzZmknICYmIGZsYWcgIT0gJ21lc3NhZ2UnKSkge1xuICAgICAgb2JqZWN0Ll9fZmxhZ3NbZmxhZ10gPSBmbGFnc1tmbGFnXTtcbiAgICB9XG4gIH1cbn07XG4iLCIvKiFcbiAqIENoYWkgLSB0eXBlIHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKiFcbiAqIERldGVjdGFibGUgamF2YXNjcmlwdCBuYXRpdmVzXG4gKi9cblxudmFyIG5hdGl2ZXMgPSB7XG4gICAgJ1tvYmplY3QgQXJndW1lbnRzXSc6ICdhcmd1bWVudHMnXG4gICwgJ1tvYmplY3QgQXJyYXldJzogJ2FycmF5J1xuICAsICdbb2JqZWN0IERhdGVdJzogJ2RhdGUnXG4gICwgJ1tvYmplY3QgRnVuY3Rpb25dJzogJ2Z1bmN0aW9uJ1xuICAsICdbb2JqZWN0IE51bWJlcl0nOiAnbnVtYmVyJ1xuICAsICdbb2JqZWN0IFJlZ0V4cF0nOiAncmVnZXhwJ1xuICAsICdbb2JqZWN0IFN0cmluZ10nOiAnc3RyaW5nJ1xufTtcblxuLyoqXG4gKiAjIyMgdHlwZShvYmplY3QpXG4gKlxuICogQmV0dGVyIGltcGxlbWVudGF0aW9uIG9mIGB0eXBlb2ZgIGRldGVjdGlvbiB0aGF0IGNhblxuICogYmUgdXNlZCBjcm9zcy1icm93c2VyLiBIYW5kbGVzIHRoZSBpbmNvbnNpc3RlbmNpZXMgb2ZcbiAqIEFycmF5LCBgbnVsbGAsIGFuZCBgdW5kZWZpbmVkYCBkZXRlY3Rpb24uXG4gKlxuICogICAgIHV0aWxzLnR5cGUoe30pIC8vICdvYmplY3QnXG4gKiAgICAgdXRpbHMudHlwZShudWxsKSAvLyBgbnVsbCdcbiAqICAgICB1dGlscy50eXBlKHVuZGVmaW5lZCkgLy8gYHVuZGVmaW5lZGBcbiAqICAgICB1dGlscy50eXBlKFtdKSAvLyBgYXJyYXlgXG4gKlxuICogQHBhcmFtIHtNaXhlZH0gb2JqZWN0IHRvIGRldGVjdCB0eXBlIG9mXG4gKiBAbmFtZSB0eXBlXG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmopIHtcbiAgdmFyIHN0ciA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopO1xuICBpZiAobmF0aXZlc1tzdHJdKSByZXR1cm4gbmF0aXZlc1tzdHJdO1xuICBpZiAob2JqID09PSBudWxsKSByZXR1cm4gJ251bGwnO1xuICBpZiAob2JqID09PSB1bmRlZmluZWQpIHJldHVybiAndW5kZWZpbmVkJztcbiAgaWYgKG9iaiA9PT0gT2JqZWN0KG9iaikpIHJldHVybiAnb2JqZWN0JztcbiAgcmV0dXJuIHR5cGVvZiBvYmo7XG59O1xuIiwiLyohXG4gKiBhc3NlcnRpb24tZXJyb3JcbiAqIENvcHlyaWdodChjKSAyMDEzIEpha2UgTHVlciA8amFrZUBxdWFsaWFuY3kuY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBSZXR1cm4gYSBmdW5jdGlvbiB0aGF0IHdpbGwgY29weSBwcm9wZXJ0aWVzIGZyb21cbiAqIG9uZSBvYmplY3QgdG8gYW5vdGhlciBleGNsdWRpbmcgYW55IG9yaWdpbmFsbHlcbiAqIGxpc3RlZC4gUmV0dXJuZWQgZnVuY3Rpb24gd2lsbCBjcmVhdGUgYSBuZXcgYHt9YC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gZXhjbHVkZWQgcHJvcGVydGllcyAuLi5cbiAqIEByZXR1cm4ge0Z1bmN0aW9ufVxuICovXG5cbmZ1bmN0aW9uIGV4Y2x1ZGUgKCkge1xuICB2YXIgZXhjbHVkZXMgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG5cbiAgZnVuY3Rpb24gZXhjbHVkZVByb3BzIChyZXMsIG9iaikge1xuICAgIE9iamVjdC5rZXlzKG9iaikuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICBpZiAoIX5leGNsdWRlcy5pbmRleE9mKGtleSkpIHJlc1trZXldID0gb2JqW2tleV07XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gZXh0ZW5kRXhjbHVkZSAoKSB7XG4gICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cylcbiAgICAgICwgaSA9IDBcbiAgICAgICwgcmVzID0ge307XG5cbiAgICBmb3IgKDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgIGV4Y2x1ZGVQcm9wcyhyZXMsIGFyZ3NbaV0pO1xuICAgIH1cblxuICAgIHJldHVybiByZXM7XG4gIH07XG59O1xuXG4vKiFcbiAqIFByaW1hcnkgRXhwb3J0c1xuICovXG5cbm1vZHVsZS5leHBvcnRzID0gQXNzZXJ0aW9uRXJyb3I7XG5cbi8qKlxuICogIyMjIEFzc2VydGlvbkVycm9yXG4gKlxuICogQW4gZXh0ZW5zaW9uIG9mIHRoZSBKYXZhU2NyaXB0IGBFcnJvcmAgY29uc3RydWN0b3IgZm9yXG4gKiBhc3NlcnRpb24gYW5kIHZhbGlkYXRpb24gc2NlbmFyaW9zLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gKiBAcGFyYW0ge09iamVjdH0gcHJvcGVydGllcyB0byBpbmNsdWRlIChvcHRpb25hbClcbiAqIEBwYXJhbSB7Y2FsbGVlfSBzdGFydCBzdGFjayBmdW5jdGlvbiAob3B0aW9uYWwpXG4gKi9cblxuZnVuY3Rpb24gQXNzZXJ0aW9uRXJyb3IgKG1lc3NhZ2UsIF9wcm9wcywgc3NmKSB7XG4gIHZhciBleHRlbmQgPSBleGNsdWRlKCduYW1lJywgJ21lc3NhZ2UnLCAnc3RhY2snLCAnY29uc3RydWN0b3InLCAndG9KU09OJylcbiAgICAsIHByb3BzID0gZXh0ZW5kKF9wcm9wcyB8fCB7fSk7XG5cbiAgLy8gZGVmYXVsdCB2YWx1ZXNcbiAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZSB8fCAnVW5zcGVjaWZpZWQgQXNzZXJ0aW9uRXJyb3InO1xuICB0aGlzLnNob3dEaWZmID0gZmFsc2U7XG5cbiAgLy8gY29weSBmcm9tIHByb3BlcnRpZXNcbiAgZm9yICh2YXIga2V5IGluIHByb3BzKSB7XG4gICAgdGhpc1trZXldID0gcHJvcHNba2V5XTtcbiAgfVxuXG4gIC8vIGNhcHR1cmUgc3RhY2sgdHJhY2VcbiAgc3NmID0gc3NmIHx8IGFyZ3VtZW50cy5jYWxsZWU7XG4gIGlmIChzc2YgJiYgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UpIHtcbiAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBzc2YpO1xuICB9XG59XG5cbi8qIVxuICogSW5oZXJpdCBmcm9tIEVycm9yLnByb3RvdHlwZVxuICovXG5cbkFzc2VydGlvbkVycm9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXJyb3IucHJvdG90eXBlKTtcblxuLyohXG4gKiBTdGF0aWNhbGx5IHNldCBuYW1lXG4gKi9cblxuQXNzZXJ0aW9uRXJyb3IucHJvdG90eXBlLm5hbWUgPSAnQXNzZXJ0aW9uRXJyb3InO1xuXG4vKiFcbiAqIEVuc3VyZSBjb3JyZWN0IGNvbnN0cnVjdG9yXG4gKi9cblxuQXNzZXJ0aW9uRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gQXNzZXJ0aW9uRXJyb3I7XG5cbi8qKlxuICogQWxsb3cgZXJyb3JzIHRvIGJlIGNvbnZlcnRlZCB0byBKU09OIGZvciBzdGF0aWMgdHJhbnNmZXIuXG4gKlxuICogQHBhcmFtIHtCb29sZWFufSBpbmNsdWRlIHN0YWNrIChkZWZhdWx0OiBgdHJ1ZWApXG4gKiBAcmV0dXJuIHtPYmplY3R9IG9iamVjdCB0aGF0IGNhbiBiZSBgSlNPTi5zdHJpbmdpZnlgXG4gKi9cblxuQXNzZXJ0aW9uRXJyb3IucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIChzdGFjaykge1xuICB2YXIgZXh0ZW5kID0gZXhjbHVkZSgnY29uc3RydWN0b3InLCAndG9KU09OJywgJ3N0YWNrJylcbiAgICAsIHByb3BzID0gZXh0ZW5kKHsgbmFtZTogdGhpcy5uYW1lIH0sIHRoaXMpO1xuXG4gIC8vIGluY2x1ZGUgc3RhY2sgaWYgZXhpc3RzIGFuZCBub3QgdHVybmVkIG9mZlxuICBpZiAoZmFsc2UgIT09IHN0YWNrICYmIHRoaXMuc3RhY2spIHtcbiAgICBwcm9wcy5zdGFjayA9IHRoaXMuc3RhY2s7XG4gIH1cblxuICByZXR1cm4gcHJvcHM7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL2xpYi9lcWwnKTtcbiIsIi8qIVxuICogZGVlcC1lcWxcbiAqIENvcHlyaWdodChjKSAyMDEzIEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBNb2R1bGUgZGVwZW5kZW5jaWVzXG4gKi9cblxudmFyIHR5cGUgPSByZXF1aXJlKCd0eXBlLWRldGVjdCcpO1xuXG4vKiFcbiAqIEJ1ZmZlci5pc0J1ZmZlciBicm93c2VyIHNoaW1cbiAqL1xuXG52YXIgQnVmZmVyO1xudHJ5IHsgQnVmZmVyID0gcmVxdWlyZSgnYnVmZmVyJykuQnVmZmVyOyB9XG5jYXRjaChleCkge1xuICBCdWZmZXIgPSB7fTtcbiAgQnVmZmVyLmlzQnVmZmVyID0gZnVuY3Rpb24oKSB7IHJldHVybiBmYWxzZTsgfVxufVxuXG4vKiFcbiAqIFByaW1hcnkgRXhwb3J0XG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBkZWVwRXF1YWw7XG5cbi8qKlxuICogQXNzZXJ0IHN1cGVyLXN0cmljdCAoZWdhbCkgZXF1YWxpdHkgYmV0d2VlblxuICogdHdvIG9iamVjdHMgb2YgYW55IHR5cGUuXG4gKlxuICogQHBhcmFtIHtNaXhlZH0gYVxuICogQHBhcmFtIHtNaXhlZH0gYlxuICogQHBhcmFtIHtBcnJheX0gbWVtb2lzZWQgKG9wdGlvbmFsKVxuICogQHJldHVybiB7Qm9vbGVhbn0gZXF1YWwgbWF0Y2hcbiAqL1xuXG5mdW5jdGlvbiBkZWVwRXF1YWwoYSwgYiwgbSkge1xuICBpZiAoc2FtZVZhbHVlKGEsIGIpKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSBpZiAoJ2RhdGUnID09PSB0eXBlKGEpKSB7XG4gICAgcmV0dXJuIGRhdGVFcXVhbChhLCBiKTtcbiAgfSBlbHNlIGlmICgncmVnZXhwJyA9PT0gdHlwZShhKSkge1xuICAgIHJldHVybiByZWdleHBFcXVhbChhLCBiKTtcbiAgfSBlbHNlIGlmIChCdWZmZXIuaXNCdWZmZXIoYSkpIHtcbiAgICByZXR1cm4gYnVmZmVyRXF1YWwoYSwgYik7XG4gIH0gZWxzZSBpZiAoJ2FyZ3VtZW50cycgPT09IHR5cGUoYSkpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzRXF1YWwoYSwgYiwgbSk7XG4gIH0gZWxzZSBpZiAoIXR5cGVFcXVhbChhLCBiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfSBlbHNlIGlmICgoJ29iamVjdCcgIT09IHR5cGUoYSkgJiYgJ29iamVjdCcgIT09IHR5cGUoYikpXG4gICYmICgnYXJyYXknICE9PSB0eXBlKGEpICYmICdhcnJheScgIT09IHR5cGUoYikpKSB7XG4gICAgcmV0dXJuIHNhbWVWYWx1ZShhLCBiKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gb2JqZWN0RXF1YWwoYSwgYiwgbSk7XG4gIH1cbn1cblxuLyohXG4gKiBTdHJpY3QgKGVnYWwpIGVxdWFsaXR5IHRlc3QuIEVuc3VyZXMgdGhhdCBOYU4gYWx3YXlzXG4gKiBlcXVhbHMgTmFOIGFuZCBgLTBgIGRvZXMgbm90IGVxdWFsIGArMGAuXG4gKlxuICogQHBhcmFtIHtNaXhlZH0gYVxuICogQHBhcmFtIHtNaXhlZH0gYlxuICogQHJldHVybiB7Qm9vbGVhbn0gZXF1YWwgbWF0Y2hcbiAqL1xuXG5mdW5jdGlvbiBzYW1lVmFsdWUoYSwgYikge1xuICBpZiAoYSA9PT0gYikgcmV0dXJuIGEgIT09IDAgfHwgMSAvIGEgPT09IDEgLyBiO1xuICByZXR1cm4gYSAhPT0gYSAmJiBiICE9PSBiO1xufVxuXG4vKiFcbiAqIENvbXBhcmUgdGhlIHR5cGVzIG9mIHR3byBnaXZlbiBvYmplY3RzIGFuZFxuICogcmV0dXJuIGlmIHRoZXkgYXJlIGVxdWFsLiBOb3RlIHRoYXQgYW4gQXJyYXlcbiAqIGhhcyBhIHR5cGUgb2YgYGFycmF5YCAobm90IGBvYmplY3RgKSBhbmQgYXJndW1lbnRzXG4gKiBoYXZlIGEgdHlwZSBvZiBgYXJndW1lbnRzYCAobm90IGBhcnJheWAvYG9iamVjdGApLlxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IGFcbiAqIEBwYXJhbSB7TWl4ZWR9IGJcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHJlc3VsdFxuICovXG5cbmZ1bmN0aW9uIHR5cGVFcXVhbChhLCBiKSB7XG4gIHJldHVybiB0eXBlKGEpID09PSB0eXBlKGIpO1xufVxuXG4vKiFcbiAqIENvbXBhcmUgdHdvIERhdGUgb2JqZWN0cyBieSBhc3NlcnRpbmcgdGhhdFxuICogdGhlIHRpbWUgdmFsdWVzIGFyZSBlcXVhbCB1c2luZyBgc2F2ZVZhbHVlYC5cbiAqXG4gKiBAcGFyYW0ge0RhdGV9IGFcbiAqIEBwYXJhbSB7RGF0ZX0gYlxuICogQHJldHVybiB7Qm9vbGVhbn0gcmVzdWx0XG4gKi9cblxuZnVuY3Rpb24gZGF0ZUVxdWFsKGEsIGIpIHtcbiAgaWYgKCdkYXRlJyAhPT0gdHlwZShiKSkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gc2FtZVZhbHVlKGEuZ2V0VGltZSgpLCBiLmdldFRpbWUoKSk7XG59XG5cbi8qIVxuICogQ29tcGFyZSB0d28gcmVndWxhciBleHByZXNzaW9ucyBieSBjb252ZXJ0aW5nIHRoZW1cbiAqIHRvIHN0cmluZyBhbmQgY2hlY2tpbmcgZm9yIGBzYW1lVmFsdWVgLlxuICpcbiAqIEBwYXJhbSB7UmVnRXhwfSBhXG4gKiBAcGFyYW0ge1JlZ0V4cH0gYlxuICogQHJldHVybiB7Qm9vbGVhbn0gcmVzdWx0XG4gKi9cblxuZnVuY3Rpb24gcmVnZXhwRXF1YWwoYSwgYikge1xuICBpZiAoJ3JlZ2V4cCcgIT09IHR5cGUoYikpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHNhbWVWYWx1ZShhLnRvU3RyaW5nKCksIGIudG9TdHJpbmcoKSk7XG59XG5cbi8qIVxuICogQXNzZXJ0IGRlZXAgZXF1YWxpdHkgb2YgdHdvIGBhcmd1bWVudHNgIG9iamVjdHMuXG4gKiBVbmZvcnR1bmF0ZWx5LCB0aGVzZSBtdXN0IGJlIHNsaWNlZCB0byBhcnJheXNcbiAqIHByaW9yIHRvIHRlc3QgdG8gZW5zdXJlIG5vIGJhZCBiZWhhdmlvci5cbiAqXG4gKiBAcGFyYW0ge0FyZ3VtZW50c30gYVxuICogQHBhcmFtIHtBcmd1bWVudHN9IGJcbiAqIEBwYXJhbSB7QXJyYXl9IG1lbW9pemUgKG9wdGlvbmFsKVxuICogQHJldHVybiB7Qm9vbGVhbn0gcmVzdWx0XG4gKi9cblxuZnVuY3Rpb24gYXJndW1lbnRzRXF1YWwoYSwgYiwgbSkge1xuICBpZiAoJ2FyZ3VtZW50cycgIT09IHR5cGUoYikpIHJldHVybiBmYWxzZTtcbiAgYSA9IFtdLnNsaWNlLmNhbGwoYSk7XG4gIGIgPSBbXS5zbGljZS5jYWxsKGIpO1xuICByZXR1cm4gZGVlcEVxdWFsKGEsIGIsIG0pO1xufVxuXG4vKiFcbiAqIEdldCBlbnVtZXJhYmxlIHByb3BlcnRpZXMgb2YgYSBnaXZlbiBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGFcbiAqIEByZXR1cm4ge0FycmF5fSBwcm9wZXJ0eSBuYW1lc1xuICovXG5cbmZ1bmN0aW9uIGVudW1lcmFibGUoYSkge1xuICB2YXIgcmVzID0gW107XG4gIGZvciAodmFyIGtleSBpbiBhKSByZXMucHVzaChrZXkpO1xuICByZXR1cm4gcmVzO1xufVxuXG4vKiFcbiAqIFNpbXBsZSBlcXVhbGl0eSBmb3IgZmxhdCBpdGVyYWJsZSBvYmplY3RzXG4gKiBzdWNoIGFzIEFycmF5cyBvciBOb2RlLmpzIGJ1ZmZlcnMuXG4gKlxuICogQHBhcmFtIHtJdGVyYWJsZX0gYVxuICogQHBhcmFtIHtJdGVyYWJsZX0gYlxuICogQHJldHVybiB7Qm9vbGVhbn0gcmVzdWx0XG4gKi9cblxuZnVuY3Rpb24gaXRlcmFibGVFcXVhbChhLCBiKSB7XG4gIGlmIChhLmxlbmd0aCAhPT0gIGIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG5cbiAgdmFyIGkgPSAwO1xuICB2YXIgbWF0Y2ggPSB0cnVlO1xuXG4gIGZvciAoOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgIGlmIChhW2ldICE9PSBiW2ldKSB7XG4gICAgICBtYXRjaCA9IGZhbHNlO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG1hdGNoO1xufVxuXG4vKiFcbiAqIEV4dGVuc2lvbiB0byBgaXRlcmFibGVFcXVhbGAgc3BlY2lmaWNhbGx5XG4gKiBmb3IgTm9kZS5qcyBCdWZmZXJzLlxuICpcbiAqIEBwYXJhbSB7QnVmZmVyfSBhXG4gKiBAcGFyYW0ge01peGVkfSBiXG4gKiBAcmV0dXJuIHtCb29sZWFufSByZXN1bHRcbiAqL1xuXG5mdW5jdGlvbiBidWZmZXJFcXVhbChhLCBiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGIpKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiBpdGVyYWJsZUVxdWFsKGEsIGIpO1xufVxuXG4vKiFcbiAqIEJsb2NrIGZvciBgb2JqZWN0RXF1YWxgIGVuc3VyaW5nIG5vbi1leGlzdGluZ1xuICogdmFsdWVzIGRvbid0IGdldCBpbi5cbiAqXG4gKiBAcGFyYW0ge01peGVkfSBvYmplY3RcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHJlc3VsdFxuICovXG5cbmZ1bmN0aW9uIGlzVmFsdWUoYSkge1xuICByZXR1cm4gYSAhPT0gbnVsbCAmJiBhICE9PSB1bmRlZmluZWQ7XG59XG5cbi8qIVxuICogUmVjdXJzaXZlbHkgY2hlY2sgdGhlIGVxdWFsaXR5IG9mIHR3byBvYmplY3RzLlxuICogT25jZSBiYXNpYyBzYW1lbmVzcyBoYXMgYmVlbiBlc3RhYmxpc2hlZCBpdCB3aWxsXG4gKiBkZWZlciB0byBgZGVlcEVxdWFsYCBmb3IgZWFjaCBlbnVtZXJhYmxlIGtleVxuICogaW4gdGhlIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge01peGVkfSBhXG4gKiBAcGFyYW0ge01peGVkfSBiXG4gKiBAcmV0dXJuIHtCb29sZWFufSByZXN1bHRcbiAqL1xuXG5mdW5jdGlvbiBvYmplY3RFcXVhbChhLCBiLCBtKSB7XG4gIGlmICghaXNWYWx1ZShhKSB8fCAhaXNWYWx1ZShiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChhLnByb3RvdHlwZSAhPT0gYi5wcm90b3R5cGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB2YXIgaTtcbiAgaWYgKG0pIHtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbS5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKChtW2ldWzBdID09PSBhICYmIG1baV1bMV0gPT09IGIpXG4gICAgICB8fCAgKG1baV1bMF0gPT09IGIgJiYgbVtpXVsxXSA9PT0gYSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIG0gPSBbXTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgdmFyIGthID0gZW51bWVyYWJsZShhKTtcbiAgICB2YXIga2IgPSBlbnVtZXJhYmxlKGIpO1xuICB9IGNhdGNoIChleCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGthLnNvcnQoKTtcbiAga2Iuc29ydCgpO1xuXG4gIGlmICghaXRlcmFibGVFcXVhbChrYSwga2IpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbS5wdXNoKFsgYSwgYiBdKTtcblxuICB2YXIga2V5O1xuICBmb3IgKGkgPSBrYS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGtleSA9IGthW2ldO1xuICAgIGlmICghZGVlcEVxdWFsKGFba2V5XSwgYltrZXldLCBtKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL2xpYi90eXBlJyk7XG4iLCIvKiFcbiAqIHR5cGUtZGV0ZWN0XG4gKiBDb3B5cmlnaHQoYykgMjAxMyBqYWtlIGx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qIVxuICogUHJpbWFyeSBFeHBvcnRzXG4gKi9cblxudmFyIGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IGdldFR5cGU7XG5cbi8qIVxuICogRGV0ZWN0YWJsZSBqYXZhc2NyaXB0IG5hdGl2ZXNcbiAqL1xuXG52YXIgbmF0aXZlcyA9IHtcbiAgICAnW29iamVjdCBBcnJheV0nOiAnYXJyYXknXG4gICwgJ1tvYmplY3QgUmVnRXhwXSc6ICdyZWdleHAnXG4gICwgJ1tvYmplY3QgRnVuY3Rpb25dJzogJ2Z1bmN0aW9uJ1xuICAsICdbb2JqZWN0IEFyZ3VtZW50c10nOiAnYXJndW1lbnRzJ1xuICAsICdbb2JqZWN0IERhdGVdJzogJ2RhdGUnXG59O1xuXG4vKipcbiAqICMjIyB0eXBlT2YgKG9iailcbiAqXG4gKiBVc2Ugc2V2ZXJhbCBkaWZmZXJlbnQgdGVjaG5pcXVlcyB0byBkZXRlcm1pbmVcbiAqIHRoZSB0eXBlIG9mIG9iamVjdCBiZWluZyB0ZXN0ZWQuXG4gKlxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IG9iamVjdFxuICogQHJldHVybiB7U3RyaW5nfSBvYmplY3QgdHlwZVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5mdW5jdGlvbiBnZXRUeXBlIChvYmopIHtcbiAgdmFyIHN0ciA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopO1xuICBpZiAobmF0aXZlc1tzdHJdKSByZXR1cm4gbmF0aXZlc1tzdHJdO1xuICBpZiAob2JqID09PSBudWxsKSByZXR1cm4gJ251bGwnO1xuICBpZiAob2JqID09PSB1bmRlZmluZWQpIHJldHVybiAndW5kZWZpbmVkJztcbiAgaWYgKG9iaiA9PT0gT2JqZWN0KG9iaikpIHJldHVybiAnb2JqZWN0JztcbiAgcmV0dXJuIHR5cGVvZiBvYmo7XG59XG5cbmV4cG9ydHMuTGlicmFyeSA9IExpYnJhcnk7XG5cbi8qKlxuICogIyMjIExpYnJhcnlcbiAqXG4gKiBDcmVhdGUgYSByZXBvc2l0b3J5IGZvciBjdXN0b20gdHlwZSBkZXRlY3Rpb24uXG4gKlxuICogYGBganNcbiAqIHZhciBsaWIgPSBuZXcgdHlwZS5MaWJyYXJ5O1xuICogYGBgXG4gKlxuICovXG5cbmZ1bmN0aW9uIExpYnJhcnkgKCkge1xuICB0aGlzLnRlc3RzID0ge307XG59XG5cbi8qKlxuICogIyMjIyAub2YgKG9iailcbiAqXG4gKiBFeHBvc2UgcmVwbGFjZW1lbnQgYHR5cGVvZmAgZGV0ZWN0aW9uIHRvIHRoZSBsaWJyYXJ5LlxuICpcbiAqIGBgYGpzXG4gKiBpZiAoJ3N0cmluZycgPT09IGxpYi5vZignaGVsbG8gd29ybGQnKSkge1xuICogICAvLyAuLi5cbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IG9iamVjdCB0byB0ZXN0XG4gKiBAcmV0dXJuIHtTdHJpbmd9IHR5cGVcbiAqL1xuXG5MaWJyYXJ5LnByb3RvdHlwZS5vZiA9IGdldFR5cGU7XG5cbi8qKlxuICogIyMjIyAuZGVmaW5lICh0eXBlLCB0ZXN0KVxuICpcbiAqIEFkZCBhIHRlc3QgdG8gZm9yIHRoZSBgLnRlc3QoKWAgYXNzZXJ0aW9uLlxuICpcbiAqIENhbiBiZSBkZWZpbmVkIGFzIGEgcmVndWxhciBleHByZXNzaW9uOlxuICpcbiAqIGBgYGpzXG4gKiBsaWIuZGVmaW5lKCdpbnQnLCAvXlswLTldKyQvKTtcbiAqIGBgYFxuICpcbiAqIC4uLiBvciBhcyBhIGZ1bmN0aW9uOlxuICpcbiAqIGBgYGpzXG4gKiBsaWIuZGVmaW5lKCdibG4nLCBmdW5jdGlvbiAob2JqKSB7XG4gKiAgIGlmICgnYm9vbGVhbicgPT09IGxpYi5vZihvYmopKSByZXR1cm4gdHJ1ZTtcbiAqICAgdmFyIGJsbnMgPSBbICd5ZXMnLCAnbm8nLCAndHJ1ZScsICdmYWxzZScsIDEsIDAgXTtcbiAqICAgaWYgKCdzdHJpbmcnID09PSBsaWIub2Yob2JqKSkgb2JqID0gb2JqLnRvTG93ZXJDYXNlKCk7XG4gKiAgIHJldHVybiAhISB+Ymxucy5pbmRleE9mKG9iaik7XG4gKiB9KTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gKiBAcGFyYW0ge1JlZ0V4cHxGdW5jdGlvbn0gdGVzdFxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5MaWJyYXJ5LnByb3RvdHlwZS5kZWZpbmUgPSBmdW5jdGlvbiAodHlwZSwgdGVzdCkge1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgcmV0dXJuIHRoaXMudGVzdHNbdHlwZV07XG4gIHRoaXMudGVzdHNbdHlwZV0gPSB0ZXN0O1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogIyMjIyAudGVzdCAob2JqLCB0ZXN0KVxuICpcbiAqIEFzc2VydCB0aGF0IGFuIG9iamVjdCBpcyBvZiB0eXBlLiBXaWxsIGZpcnN0XG4gKiBjaGVjayBuYXRpdmVzLCBhbmQgaWYgdGhhdCBkb2VzIG5vdCBwYXNzIGl0IHdpbGxcbiAqIHVzZSB0aGUgdXNlciBkZWZpbmVkIGN1c3RvbSB0ZXN0cy5cbiAqXG4gKiBgYGBqc1xuICogYXNzZXJ0KGxpYi50ZXN0KCcxJywgJ2ludCcpKTtcbiAqIGFzc2VydChsaWIudGVzdCgneWVzJywgJ2JsbicpKTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IG9iamVjdFxuICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHJlc3VsdFxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5MaWJyYXJ5LnByb3RvdHlwZS50ZXN0ID0gZnVuY3Rpb24gKG9iaiwgdHlwZSkge1xuICBpZiAodHlwZSA9PT0gZ2V0VHlwZShvYmopKSByZXR1cm4gdHJ1ZTtcbiAgdmFyIHRlc3QgPSB0aGlzLnRlc3RzW3R5cGVdO1xuXG4gIGlmICh0ZXN0ICYmICdyZWdleHAnID09PSBnZXRUeXBlKHRlc3QpKSB7XG4gICAgcmV0dXJuIHRlc3QudGVzdChvYmopO1xuICB9IGVsc2UgaWYgKHRlc3QgJiYgJ2Z1bmN0aW9uJyA9PT0gZ2V0VHlwZSh0ZXN0KSkge1xuICAgIHJldHVybiB0ZXN0KG9iaik7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IFJlZmVyZW5jZUVycm9yKCdUeXBlIHRlc3QgXCInICsgdHlwZSArICdcIiBub3QgZGVmaW5lZCBvciBpbnZhbGlkLicpO1xuICB9XG59O1xuIiwiKGZ1bmN0aW9uIChzaW5vbkNoYWkpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIC8vIE1vZHVsZSBzeXN0ZW1zIG1hZ2ljIGRhbmNlLlxuXG4gICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICBpZiAodHlwZW9mIHJlcXVpcmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZXhwb3J0cyA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIC8vIE5vZGVKU1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHNpbm9uQ2hhaTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIC8vIEFNRFxuICAgICAgICBkZWZpbmUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHNpbm9uQ2hhaTtcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gT3RoZXIgZW52aXJvbm1lbnQgKHVzdWFsbHkgPHNjcmlwdD4gdGFnKTogcGx1ZyBpbiB0byBnbG9iYWwgY2hhaSBpbnN0YW5jZSBkaXJlY3RseS5cbiAgICAgICAgY2hhaS51c2Uoc2lub25DaGFpKTtcbiAgICB9XG59KGZ1bmN0aW9uIHNpbm9uQ2hhaShjaGFpLCB1dGlscykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgdmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xuXG4gICAgZnVuY3Rpb24gaXNTcHkocHV0YXRpdmVTcHkpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBwdXRhdGl2ZVNweSA9PT0gXCJmdW5jdGlvblwiICYmXG4gICAgICAgICAgICAgICB0eXBlb2YgcHV0YXRpdmVTcHkuZ2V0Q2FsbCA9PT0gXCJmdW5jdGlvblwiICYmXG4gICAgICAgICAgICAgICB0eXBlb2YgcHV0YXRpdmVTcHkuY2FsbGVkV2l0aEV4YWN0bHkgPT09IFwiZnVuY3Rpb25cIjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0aW1lc0luV29yZHMoY291bnQpIHtcbiAgICAgICAgcmV0dXJuIGNvdW50ID09PSAxID8gXCJvbmNlXCIgOlxuICAgICAgICAgICAgICAgY291bnQgPT09IDIgPyBcInR3aWNlXCIgOlxuICAgICAgICAgICAgICAgY291bnQgPT09IDMgPyBcInRocmljZVwiIDpcbiAgICAgICAgICAgICAgIChjb3VudCB8fCAwKSArIFwiIHRpbWVzXCI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNDYWxsKHB1dGF0aXZlQ2FsbCkge1xuICAgICAgICByZXR1cm4gcHV0YXRpdmVDYWxsICYmIGlzU3B5KHB1dGF0aXZlQ2FsbC5wcm94eSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXNzZXJ0Q2FuV29ya1dpdGgoYXNzZXJ0aW9uKSB7XG4gICAgICAgIGlmICghaXNTcHkoYXNzZXJ0aW9uLl9vYmopICYmICFpc0NhbGwoYXNzZXJ0aW9uLl9vYmopKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKHV0aWxzLmluc3BlY3QoYXNzZXJ0aW9uLl9vYmopICsgXCIgaXMgbm90IGEgc3B5IG9yIGEgY2FsbCB0byBhIHNweSFcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRNZXNzYWdlcyhzcHksIGFjdGlvbiwgbm9uTmVnYXRlZFN1ZmZpeCwgYWx3YXlzLCBhcmdzKSB7XG4gICAgICAgIHZhciB2ZXJiUGhyYXNlID0gYWx3YXlzID8gXCJhbHdheXMgaGF2ZSBcIiA6IFwiaGF2ZSBcIjtcbiAgICAgICAgbm9uTmVnYXRlZFN1ZmZpeCA9IG5vbk5lZ2F0ZWRTdWZmaXggfHwgXCJcIjtcbiAgICAgICAgaWYgKGlzU3B5KHNweS5wcm94eSkpIHtcbiAgICAgICAgICAgIHNweSA9IHNweS5wcm94eTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHByaW50ZkFycmF5KGFycmF5KSB7XG4gICAgICAgICAgICByZXR1cm4gc3B5LnByaW50Zi5hcHBseShzcHksIGFycmF5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBhZmZpcm1hdGl2ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwcmludGZBcnJheShbXCJleHBlY3RlZCAlbiB0byBcIiArIHZlcmJQaHJhc2UgKyBhY3Rpb24gKyBub25OZWdhdGVkU3VmZml4XS5jb25jYXQoYXJncykpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5lZ2F0aXZlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByaW50ZkFycmF5KFtcImV4cGVjdGVkICVuIHRvIG5vdCBcIiArIHZlcmJQaHJhc2UgKyBhY3Rpb25dLmNvbmNhdChhcmdzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2lub25Qcm9wZXJ0eShuYW1lLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgpIHtcbiAgICAgICAgdXRpbHMuYWRkUHJvcGVydHkoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCBuYW1lLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBhc3NlcnRDYW5Xb3JrV2l0aCh0aGlzKTtcblxuICAgICAgICAgICAgdmFyIG1lc3NhZ2VzID0gZ2V0TWVzc2FnZXModGhpcy5fb2JqLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgsIGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMuYXNzZXJ0KHRoaXMuX29ialtuYW1lXSwgbWVzc2FnZXMuYWZmaXJtYXRpdmUsIG1lc3NhZ2VzLm5lZ2F0aXZlKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2lub25Qcm9wZXJ0eUFzQm9vbGVhbk1ldGhvZChuYW1lLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgpIHtcbiAgICAgICAgdXRpbHMuYWRkTWV0aG9kKGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZSwgbmFtZSwgZnVuY3Rpb24gKGFyZykge1xuICAgICAgICAgICAgYXNzZXJ0Q2FuV29ya1dpdGgodGhpcyk7XG5cbiAgICAgICAgICAgIHZhciBtZXNzYWdlcyA9IGdldE1lc3NhZ2VzKHRoaXMuX29iaiwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4LCBmYWxzZSwgW3RpbWVzSW5Xb3JkcyhhcmcpXSk7XG4gICAgICAgICAgICB0aGlzLmFzc2VydCh0aGlzLl9vYmpbbmFtZV0gPT09IGFyZywgbWVzc2FnZXMuYWZmaXJtYXRpdmUsIG1lc3NhZ2VzLm5lZ2F0aXZlKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlU2lub25NZXRob2RIYW5kbGVyKHNpbm9uTmFtZSwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4KSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBhc3NlcnRDYW5Xb3JrV2l0aCh0aGlzKTtcblxuICAgICAgICAgICAgdmFyIGFsd2F5c1Npbm9uTWV0aG9kID0gXCJhbHdheXNcIiArIHNpbm9uTmFtZVswXS50b1VwcGVyQ2FzZSgpICsgc2lub25OYW1lLnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgIHZhciBzaG91bGRCZUFsd2F5cyA9IHV0aWxzLmZsYWcodGhpcywgXCJhbHdheXNcIikgJiYgdHlwZW9mIHRoaXMuX29ialthbHdheXNTaW5vbk1ldGhvZF0gPT09IFwiZnVuY3Rpb25cIjtcbiAgICAgICAgICAgIHZhciBzaW5vbk1ldGhvZCA9IHNob3VsZEJlQWx3YXlzID8gYWx3YXlzU2lub25NZXRob2QgOiBzaW5vbk5hbWU7XG5cbiAgICAgICAgICAgIHZhciBtZXNzYWdlcyA9IGdldE1lc3NhZ2VzKHRoaXMuX29iaiwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4LCBzaG91bGRCZUFsd2F5cywgc2xpY2UuY2FsbChhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIHRoaXMuYXNzZXJ0KHRoaXMuX29ialtzaW5vbk1ldGhvZF0uYXBwbHkodGhpcy5fb2JqLCBhcmd1bWVudHMpLCBtZXNzYWdlcy5hZmZpcm1hdGl2ZSwgbWVzc2FnZXMubmVnYXRpdmUpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNpbm9uTWV0aG9kQXNQcm9wZXJ0eShuYW1lLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgpIHtcbiAgICAgICAgdmFyIGhhbmRsZXIgPSBjcmVhdGVTaW5vbk1ldGhvZEhhbmRsZXIobmFtZSwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4KTtcbiAgICAgICAgdXRpbHMuYWRkUHJvcGVydHkoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCBuYW1lLCBoYW5kbGVyKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBleGNlcHRpb25hbFNpbm9uTWV0aG9kKGNoYWlOYW1lLCBzaW5vbk5hbWUsIGFjdGlvbiwgbm9uTmVnYXRlZFN1ZmZpeCkge1xuICAgICAgICB2YXIgaGFuZGxlciA9IGNyZWF0ZVNpbm9uTWV0aG9kSGFuZGxlcihzaW5vbk5hbWUsIGFjdGlvbiwgbm9uTmVnYXRlZFN1ZmZpeCk7XG4gICAgICAgIHV0aWxzLmFkZE1ldGhvZChjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUsIGNoYWlOYW1lLCBoYW5kbGVyKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzaW5vbk1ldGhvZChuYW1lLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgpIHtcbiAgICAgICAgZXhjZXB0aW9uYWxTaW5vbk1ldGhvZChuYW1lLCBuYW1lLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgpO1xuICAgIH1cblxuICAgIHV0aWxzLmFkZFByb3BlcnR5KGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZSwgXCJhbHdheXNcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICB1dGlscy5mbGFnKHRoaXMsIFwiYWx3YXlzXCIsIHRydWUpO1xuICAgIH0pO1xuXG4gICAgc2lub25Qcm9wZXJ0eShcImNhbGxlZFwiLCBcImJlZW4gY2FsbGVkXCIsIFwiIGF0IGxlYXN0IG9uY2UsIGJ1dCBpdCB3YXMgbmV2ZXIgY2FsbGVkXCIpO1xuICAgIHNpbm9uUHJvcGVydHlBc0Jvb2xlYW5NZXRob2QoXCJjYWxsQ291bnRcIiwgXCJiZWVuIGNhbGxlZCBleGFjdGx5ICUxXCIsIFwiLCBidXQgaXQgd2FzIGNhbGxlZCAlYyVDXCIpO1xuICAgIHNpbm9uUHJvcGVydHkoXCJjYWxsZWRPbmNlXCIsIFwiYmVlbiBjYWxsZWQgZXhhY3RseSBvbmNlXCIsIFwiLCBidXQgaXQgd2FzIGNhbGxlZCAlYyVDXCIpO1xuICAgIHNpbm9uUHJvcGVydHkoXCJjYWxsZWRUd2ljZVwiLCBcImJlZW4gY2FsbGVkIGV4YWN0bHkgdHdpY2VcIiwgXCIsIGJ1dCBpdCB3YXMgY2FsbGVkICVjJUNcIik7XG4gICAgc2lub25Qcm9wZXJ0eShcImNhbGxlZFRocmljZVwiLCBcImJlZW4gY2FsbGVkIGV4YWN0bHkgdGhyaWNlXCIsIFwiLCBidXQgaXQgd2FzIGNhbGxlZCAlYyVDXCIpO1xuICAgIHNpbm9uTWV0aG9kQXNQcm9wZXJ0eShcImNhbGxlZFdpdGhOZXdcIiwgXCJiZWVuIGNhbGxlZCB3aXRoIG5ld1wiKTtcbiAgICBzaW5vbk1ldGhvZChcImNhbGxlZEJlZm9yZVwiLCBcImJlZW4gY2FsbGVkIGJlZm9yZSAlMVwiKTtcbiAgICBzaW5vbk1ldGhvZChcImNhbGxlZEFmdGVyXCIsIFwiYmVlbiBjYWxsZWQgYWZ0ZXIgJTFcIik7XG4gICAgc2lub25NZXRob2QoXCJjYWxsZWRPblwiLCBcImJlZW4gY2FsbGVkIHdpdGggJTEgYXMgdGhpc1wiLCBcIiwgYnV0IGl0IHdhcyBjYWxsZWQgd2l0aCAldCBpbnN0ZWFkXCIpO1xuICAgIHNpbm9uTWV0aG9kKFwiY2FsbGVkV2l0aFwiLCBcImJlZW4gY2FsbGVkIHdpdGggYXJndW1lbnRzICUqXCIsIFwiJUNcIik7XG4gICAgc2lub25NZXRob2QoXCJjYWxsZWRXaXRoRXhhY3RseVwiLCBcImJlZW4gY2FsbGVkIHdpdGggZXhhY3QgYXJndW1lbnRzICUqXCIsIFwiJUNcIik7XG4gICAgc2lub25NZXRob2QoXCJjYWxsZWRXaXRoTWF0Y2hcIiwgXCJiZWVuIGNhbGxlZCB3aXRoIGFyZ3VtZW50cyBtYXRjaGluZyAlKlwiLCBcIiVDXCIpO1xuICAgIHNpbm9uTWV0aG9kKFwicmV0dXJuZWRcIiwgXCJyZXR1cm5lZCAlMVwiKTtcbiAgICBleGNlcHRpb25hbFNpbm9uTWV0aG9kKFwidGhyb3duXCIsIFwidGhyZXdcIiwgXCJ0aHJvd24gJTFcIik7XG59KSk7XG4iLCIvKipcbiAqIFNpbm9uIGNvcmUgdXRpbGl0aWVzLiBGb3IgaW50ZXJuYWwgdXNlIG9ubHkuXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBzaW5vbiA9IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNpbm9uO1xuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICBzaW5vbiA9IG1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcIi4vc2lub24vdXRpbC9jb3JlXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9zaW5vbi9leHRlbmRcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3Npbm9uL3R5cGVPZlwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vdGltZXNfaW5fd29yZHNcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3Npbm9uL3NweVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vY2FsbFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vYmVoYXZpb3JcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3Npbm9uL3N0dWJcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3Npbm9uL21vY2tcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3Npbm9uL2NvbGxlY3Rpb25cIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3Npbm9uL2Fzc2VydFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vc2FuZGJveFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vdGVzdFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vdGVzdF9jYXNlXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9zaW5vbi9tYXRjaFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vZm9ybWF0XCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9zaW5vbi9sb2dfZXJyb3JcIik7XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgICAgICBzaW5vbiA9IG1vZHVsZS5leHBvcnRzO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHNpbm9uID0ge307XG4gICAgfVxuXG4gICAgcmV0dXJuIHNpbm9uO1xufSgpKTtcbiIsIihmdW5jdGlvbiAoZ2xvYmFsKXtcbi8qKlxuICogQGRlcGVuZCB0aW1lc19pbl93b3Jkcy5qc1xuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqIEBkZXBlbmQgbWF0Y2guanNcbiAqIEBkZXBlbmQgZm9ybWF0LmpzXG4gKi9cbi8qKlxuICogQXNzZXJ0aW9ucyBtYXRjaGluZyB0aGUgdGVzdCBzcHkgcmV0cmlldmFsIGludGVyZmFjZS5cbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbiwgZ2xvYmFsKSB7XG4gICAgdmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xuXG4gICAgZnVuY3Rpb24gbWFrZUFwaShzaW5vbikge1xuICAgICAgICB2YXIgYXNzZXJ0O1xuXG4gICAgICAgIGZ1bmN0aW9uIHZlcmlmeUlzU3R1YigpIHtcbiAgICAgICAgICAgIHZhciBtZXRob2Q7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgICAgIG1ldGhvZCA9IGFyZ3VtZW50c1tpXTtcblxuICAgICAgICAgICAgICAgIGlmICghbWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5mYWlsKFwiZmFrZSBpcyBub3QgYSBzcHlcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG1ldGhvZC5wcm94eSkge1xuICAgICAgICAgICAgICAgICAgICB2ZXJpZnlJc1N0dWIobWV0aG9kLnByb3h5KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1ldGhvZCAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFzc2VydC5mYWlsKG1ldGhvZCArIFwiIGlzIG5vdCBhIGZ1bmN0aW9uXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXRob2QuZ2V0Q2FsbCAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFzc2VydC5mYWlsKG1ldGhvZCArIFwiIGlzIG5vdCBzdHViYmVkXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBmYWlsQXNzZXJ0aW9uKG9iamVjdCwgbXNnKSB7XG4gICAgICAgICAgICBvYmplY3QgPSBvYmplY3QgfHwgZ2xvYmFsO1xuICAgICAgICAgICAgdmFyIGZhaWxNZXRob2QgPSBvYmplY3QuZmFpbCB8fCBhc3NlcnQuZmFpbDtcbiAgICAgICAgICAgIGZhaWxNZXRob2QuY2FsbChvYmplY3QsIG1zZyk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBtaXJyb3JQcm9wQXNBc3NlcnRpb24obmFtZSwgbWV0aG9kLCBtZXNzYWdlKSB7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PSAyKSB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZSA9IG1ldGhvZDtcbiAgICAgICAgICAgICAgICBtZXRob2QgPSBuYW1lO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBhc3NlcnRbbmFtZV0gPSBmdW5jdGlvbiAoZmFrZSkge1xuICAgICAgICAgICAgICAgIHZlcmlmeUlzU3R1YihmYWtlKTtcblxuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgICAgIHZhciBmYWlsZWQgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWV0aG9kID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICBmYWlsZWQgPSAhbWV0aG9kKGZha2UpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZhaWxlZCA9IHR5cGVvZiBmYWtlW21ldGhvZF0gPT0gXCJmdW5jdGlvblwiID9cbiAgICAgICAgICAgICAgICAgICAgICAgICFmYWtlW21ldGhvZF0uYXBwbHkoZmFrZSwgYXJncykgOiAhZmFrZVttZXRob2RdO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChmYWlsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgZmFpbEFzc2VydGlvbih0aGlzLCAoZmFrZS5wcmludGYgfHwgZmFrZS5wcm94eS5wcmludGYpLmFwcGx5KGZha2UsIFttZXNzYWdlXS5jb25jYXQoYXJncykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQucGFzcyhuYW1lKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gZXhwb3NlZE5hbWUocHJlZml4LCBwcm9wKSB7XG4gICAgICAgICAgICByZXR1cm4gIXByZWZpeCB8fCAvXmZhaWwvLnRlc3QocHJvcCkgPyBwcm9wIDpcbiAgICAgICAgICAgICAgICBwcmVmaXggKyBwcm9wLnNsaWNlKDAsIDEpLnRvVXBwZXJDYXNlKCkgKyBwcm9wLnNsaWNlKDEpO1xuICAgICAgICB9XG5cbiAgICAgICAgYXNzZXJ0ID0ge1xuICAgICAgICAgICAgZmFpbEV4Y2VwdGlvbjogXCJBc3NlcnRFcnJvclwiLFxuXG4gICAgICAgICAgICBmYWlsOiBmdW5jdGlvbiBmYWlsKG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgZXJyb3IubmFtZSA9IHRoaXMuZmFpbEV4Y2VwdGlvbiB8fCBhc3NlcnQuZmFpbEV4Y2VwdGlvbjtcblxuICAgICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgcGFzczogZnVuY3Rpb24gcGFzcyhhc3NlcnRpb24pIHt9LFxuXG4gICAgICAgICAgICBjYWxsT3JkZXI6IGZ1bmN0aW9uIGFzc2VydENhbGxPcmRlcigpIHtcbiAgICAgICAgICAgICAgICB2ZXJpZnlJc1N0dWIuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICB2YXIgZXhwZWN0ZWQgPSBcIlwiLCBhY3R1YWwgPSBcIlwiO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFzaW5vbi5jYWxsZWRJbk9yZGVyKGFyZ3VtZW50cykpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4cGVjdGVkID0gW10uam9pbi5jYWxsKGFyZ3VtZW50cywgXCIsIFwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjYWxscyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpID0gY2FsbHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNhbGxzWy0taV0uY2FsbGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBhY3R1YWwgPSBzaW5vbi5vcmRlckJ5Rmlyc3RDYWxsKGNhbGxzKS5qb2luKFwiLCBcIik7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHRoaXMgZmFpbHMsIHdlJ2xsIGp1c3QgZmFsbCBiYWNrIHRvIHRoZSBibGFuayBzdHJpbmdcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGZhaWxBc3NlcnRpb24odGhpcywgXCJleHBlY3RlZCBcIiArIGV4cGVjdGVkICsgXCIgdG8gYmUgXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImNhbGxlZCBpbiBvcmRlciBidXQgd2VyZSBjYWxsZWQgYXMgXCIgKyBhY3R1YWwpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5wYXNzKFwiY2FsbE9yZGVyXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGNhbGxDb3VudDogZnVuY3Rpb24gYXNzZXJ0Q2FsbENvdW50KG1ldGhvZCwgY291bnQpIHtcbiAgICAgICAgICAgICAgICB2ZXJpZnlJc1N0dWIobWV0aG9kKTtcblxuICAgICAgICAgICAgICAgIGlmIChtZXRob2QuY2FsbENvdW50ICE9IGNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtc2cgPSBcImV4cGVjdGVkICVuIHRvIGJlIGNhbGxlZCBcIiArIHNpbm9uLnRpbWVzSW5Xb3Jkcyhjb3VudCkgK1xuICAgICAgICAgICAgICAgICAgICAgICAgXCIgYnV0IHdhcyBjYWxsZWQgJWMlQ1wiO1xuICAgICAgICAgICAgICAgICAgICBmYWlsQXNzZXJ0aW9uKHRoaXMsIG1ldGhvZC5wcmludGYobXNnKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LnBhc3MoXCJjYWxsQ291bnRcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZXhwb3NlOiBmdW5jdGlvbiBleHBvc2UodGFyZ2V0LCBvcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcInRhcmdldCBpcyBudWxsIG9yIHVuZGVmaW5lZFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbyA9IG9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgdmFyIHByZWZpeCA9IHR5cGVvZiBvLnByZWZpeCA9PSBcInVuZGVmaW5lZFwiICYmIFwiYXNzZXJ0XCIgfHwgby5wcmVmaXg7XG4gICAgICAgICAgICAgICAgdmFyIGluY2x1ZGVGYWlsID0gdHlwZW9mIG8uaW5jbHVkZUZhaWwgPT0gXCJ1bmRlZmluZWRcIiB8fCAhIW8uaW5jbHVkZUZhaWw7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBtZXRob2QgaW4gdGhpcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAobWV0aG9kICE9IFwiZXhwb3NlXCIgJiYgKGluY2x1ZGVGYWlsIHx8ICEvXihmYWlsKS8udGVzdChtZXRob2QpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0W2V4cG9zZWROYW1lKHByZWZpeCwgbWV0aG9kKV0gPSB0aGlzW21ldGhvZF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgbWF0Y2g6IGZ1bmN0aW9uIG1hdGNoKGFjdHVhbCwgZXhwZWN0YXRpb24pIHtcbiAgICAgICAgICAgICAgICB2YXIgbWF0Y2hlciA9IHNpbm9uLm1hdGNoKGV4cGVjdGF0aW9uKTtcbiAgICAgICAgICAgICAgICBpZiAobWF0Y2hlci50ZXN0KGFjdHVhbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LnBhc3MoXCJtYXRjaFwiKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZm9ybWF0dGVkID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgXCJleHBlY3RlZCB2YWx1ZSB0byBtYXRjaFwiLFxuICAgICAgICAgICAgICAgICAgICAgICAgXCIgICAgZXhwZWN0ZWQgPSBcIiArIHNpbm9uLmZvcm1hdChleHBlY3RhdGlvbiksXG4gICAgICAgICAgICAgICAgICAgICAgICBcIiAgICBhY3R1YWwgPSBcIiArIHNpbm9uLmZvcm1hdChhY3R1YWwpXG4gICAgICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgICAgICAgZmFpbEFzc2VydGlvbih0aGlzLCBmb3JtYXR0ZWQuam9pbihcIlxcblwiKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZFwiLCBcImV4cGVjdGVkICVuIHRvIGhhdmUgYmVlbiBjYWxsZWQgYXQgbGVhc3Qgb25jZSBidXQgd2FzIG5ldmVyIGNhbGxlZFwiKTtcbiAgICAgICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwibm90Q2FsbGVkXCIsIGZ1bmN0aW9uIChzcHkpIHsgcmV0dXJuICFzcHkuY2FsbGVkOyB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZXhwZWN0ZWQgJW4gdG8gbm90IGhhdmUgYmVlbiBjYWxsZWQgYnV0IHdhcyBjYWxsZWQgJWMlQ1wiKTtcbiAgICAgICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwiY2FsbGVkT25jZVwiLCBcImV4cGVjdGVkICVuIHRvIGJlIGNhbGxlZCBvbmNlIGJ1dCB3YXMgY2FsbGVkICVjJUNcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZFR3aWNlXCIsIFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIHR3aWNlIGJ1dCB3YXMgY2FsbGVkICVjJUNcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZFRocmljZVwiLCBcImV4cGVjdGVkICVuIHRvIGJlIGNhbGxlZCB0aHJpY2UgYnV0IHdhcyBjYWxsZWQgJWMlQ1wiKTtcbiAgICAgICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwiY2FsbGVkT25cIiwgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgd2l0aCAlMSBhcyB0aGlzIGJ1dCB3YXMgY2FsbGVkIHdpdGggJXRcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImFsd2F5c0NhbGxlZE9uXCIsIFwiZXhwZWN0ZWQgJW4gdG8gYWx3YXlzIGJlIGNhbGxlZCB3aXRoICUxIGFzIHRoaXMgYnV0IHdhcyBjYWxsZWQgd2l0aCAldFwiKTtcbiAgICAgICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwiY2FsbGVkV2l0aE5ld1wiLCBcImV4cGVjdGVkICVuIHRvIGJlIGNhbGxlZCB3aXRoIG5ld1wiKTtcbiAgICAgICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwiYWx3YXlzQ2FsbGVkV2l0aE5ld1wiLCBcImV4cGVjdGVkICVuIHRvIGFsd2F5cyBiZSBjYWxsZWQgd2l0aCBuZXdcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZFdpdGhcIiwgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgd2l0aCBhcmd1bWVudHMgJSolQ1wiKTtcbiAgICAgICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwiY2FsbGVkV2l0aE1hdGNoXCIsIFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIHdpdGggbWF0Y2ggJSolQ1wiKTtcbiAgICAgICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwiYWx3YXlzQ2FsbGVkV2l0aFwiLCBcImV4cGVjdGVkICVuIHRvIGFsd2F5cyBiZSBjYWxsZWQgd2l0aCBhcmd1bWVudHMgJSolQ1wiKTtcbiAgICAgICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwiYWx3YXlzQ2FsbGVkV2l0aE1hdGNoXCIsIFwiZXhwZWN0ZWQgJW4gdG8gYWx3YXlzIGJlIGNhbGxlZCB3aXRoIG1hdGNoICUqJUNcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZFdpdGhFeGFjdGx5XCIsIFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIHdpdGggZXhhY3QgYXJndW1lbnRzICUqJUNcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImFsd2F5c0NhbGxlZFdpdGhFeGFjdGx5XCIsIFwiZXhwZWN0ZWQgJW4gdG8gYWx3YXlzIGJlIGNhbGxlZCB3aXRoIGV4YWN0IGFyZ3VtZW50cyAlKiVDXCIpO1xuICAgICAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJuZXZlckNhbGxlZFdpdGhcIiwgXCJleHBlY3RlZCAlbiB0byBuZXZlciBiZSBjYWxsZWQgd2l0aCBhcmd1bWVudHMgJSolQ1wiKTtcbiAgICAgICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwibmV2ZXJDYWxsZWRXaXRoTWF0Y2hcIiwgXCJleHBlY3RlZCAlbiB0byBuZXZlciBiZSBjYWxsZWQgd2l0aCBtYXRjaCAlKiVDXCIpO1xuICAgICAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJ0aHJld1wiLCBcIiVuIGRpZCBub3QgdGhyb3cgZXhjZXB0aW9uJUNcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImFsd2F5c1RocmV3XCIsIFwiJW4gZGlkIG5vdCBhbHdheXMgdGhyb3cgZXhjZXB0aW9uJUNcIik7XG5cbiAgICAgICAgc2lub24uYXNzZXJ0ID0gYXNzZXJ0O1xuICAgICAgICByZXR1cm4gYXNzZXJ0O1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vbWF0Y2hcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2Zvcm1hdFwiKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cblxufSh0eXBlb2Ygc2lub24gPT0gXCJvYmplY3RcIiAmJiBzaW5vbiB8fCBudWxsLCB0eXBlb2Ygd2luZG93ICE9IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiAodHlwZW9mIHNlbGYgIT0gXCJ1bmRlZmluZWRcIikgPyBzZWxmIDogZ2xvYmFsKSk7XG5cbn0pLmNhbGwodGhpcyx0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pIiwiKGZ1bmN0aW9uIChwcm9jZXNzKXtcbi8qKlxuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqIEBkZXBlbmQgZXh0ZW5kLmpzXG4gKi9cbi8qKlxuICogU3R1YiBiZWhhdmlvclxuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGF1dGhvciBUaW0gRmlzY2hiYWNoIChtYWlsQHRpbWZpc2NoYmFjaC5kZSlcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIHZhciBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcbiAgICB2YXIgam9pbiA9IEFycmF5LnByb3RvdHlwZS5qb2luO1xuICAgIHZhciB1c2VMZWZ0TW9zdENhbGxiYWNrID0gLTE7XG4gICAgdmFyIHVzZVJpZ2h0TW9zdENhbGxiYWNrID0gLTI7XG5cbiAgICB2YXIgbmV4dFRpY2sgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodHlwZW9mIHByb2Nlc3MgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIHByb2Nlc3MubmV4dFRpY2sgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3MubmV4dFRpY2s7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHNldEltbWVkaWF0ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICByZXR1cm4gc2V0SW1tZWRpYXRlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoY2FsbGJhY2ssIDApO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH0pKCk7XG5cbiAgICBmdW5jdGlvbiB0aHJvd3NFeGNlcHRpb24oZXJyb3IsIG1lc3NhZ2UpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBlcnJvciA9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICB0aGlzLmV4Y2VwdGlvbiA9IG5ldyBFcnJvcihtZXNzYWdlIHx8IFwiXCIpO1xuICAgICAgICAgICAgdGhpcy5leGNlcHRpb24ubmFtZSA9IGVycm9yO1xuICAgICAgICB9IGVsc2UgaWYgKCFlcnJvcikge1xuICAgICAgICAgICAgdGhpcy5leGNlcHRpb24gPSBuZXcgRXJyb3IoXCJFcnJvclwiKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZXhjZXB0aW9uID0gZXJyb3I7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRDYWxsYmFjayhiZWhhdmlvciwgYXJncykge1xuICAgICAgICB2YXIgY2FsbEFyZ0F0ID0gYmVoYXZpb3IuY2FsbEFyZ0F0O1xuXG4gICAgICAgIGlmIChjYWxsQXJnQXQgPj0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGFyZ3NbY2FsbEFyZ0F0XTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBhcmd1bWVudExpc3Q7XG5cbiAgICAgICAgaWYgKGNhbGxBcmdBdCA9PT0gdXNlTGVmdE1vc3RDYWxsYmFjaykge1xuICAgICAgICAgICAgYXJndW1lbnRMaXN0ID0gYXJncztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjYWxsQXJnQXQgPT09IHVzZVJpZ2h0TW9zdENhbGxiYWNrKSB7XG4gICAgICAgICAgICBhcmd1bWVudExpc3QgPSBzbGljZS5jYWxsKGFyZ3MpLnJldmVyc2UoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBjYWxsQXJnUHJvcCA9IGJlaGF2aW9yLmNhbGxBcmdQcm9wO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gYXJndW1lbnRMaXN0Lmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgaWYgKCFjYWxsQXJnUHJvcCAmJiB0eXBlb2YgYXJndW1lbnRMaXN0W2ldID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhcmd1bWVudExpc3RbaV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjYWxsQXJnUHJvcCAmJiBhcmd1bWVudExpc3RbaV0gJiZcbiAgICAgICAgICAgICAgICB0eXBlb2YgYXJndW1lbnRMaXN0W2ldW2NhbGxBcmdQcm9wXSA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXJndW1lbnRMaXN0W2ldW2NhbGxBcmdQcm9wXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgZnVuY3Rpb24gZ2V0Q2FsbGJhY2tFcnJvcihiZWhhdmlvciwgZnVuYywgYXJncykge1xuICAgICAgICAgICAgaWYgKGJlaGF2aW9yLmNhbGxBcmdBdCA8IDApIHtcbiAgICAgICAgICAgICAgICB2YXIgbXNnO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJlaGF2aW9yLmNhbGxBcmdQcm9wKSB7XG4gICAgICAgICAgICAgICAgICAgIG1zZyA9IHNpbm9uLmZ1bmN0aW9uTmFtZShiZWhhdmlvci5zdHViKSArXG4gICAgICAgICAgICAgICAgICAgICAgICBcIiBleHBlY3RlZCB0byB5aWVsZCB0byAnXCIgKyBiZWhhdmlvci5jYWxsQXJnUHJvcCArXG4gICAgICAgICAgICAgICAgICAgICAgICBcIicsIGJ1dCBubyBvYmplY3Qgd2l0aCBzdWNoIGEgcHJvcGVydHkgd2FzIHBhc3NlZC5cIjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtc2cgPSBzaW5vbi5mdW5jdGlvbk5hbWUoYmVoYXZpb3Iuc3R1YikgK1xuICAgICAgICAgICAgICAgICAgICAgICAgXCIgZXhwZWN0ZWQgdG8geWllbGQsIGJ1dCBubyBjYWxsYmFjayB3YXMgcGFzc2VkLlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcmdzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbXNnICs9IFwiIFJlY2VpdmVkIFtcIiArIGpvaW4uY2FsbChhcmdzLCBcIiwgXCIpICsgXCJdXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG1zZztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIFwiYXJndW1lbnQgYXQgaW5kZXggXCIgKyBiZWhhdmlvci5jYWxsQXJnQXQgKyBcIiBpcyBub3QgYSBmdW5jdGlvbjogXCIgKyBmdW5jO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gY2FsbENhbGxiYWNrKGJlaGF2aW9yLCBhcmdzKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGJlaGF2aW9yLmNhbGxBcmdBdCA9PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmMgPSBnZXRDYWxsYmFjayhiZWhhdmlvciwgYXJncyk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoZ2V0Q2FsbGJhY2tFcnJvcihiZWhhdmlvciwgZnVuYywgYXJncykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChiZWhhdmlvci5jYWxsYmFja0FzeW5jKSB7XG4gICAgICAgICAgICAgICAgICAgIG5leHRUaWNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmMuYXBwbHkoYmVoYXZpb3IuY2FsbGJhY2tDb250ZXh0LCBiZWhhdmlvci5jYWxsYmFja0FyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMuYXBwbHkoYmVoYXZpb3IuY2FsbGJhY2tDb250ZXh0LCBiZWhhdmlvci5jYWxsYmFja0FyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHByb3RvID0ge1xuICAgICAgICAgICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUoc3R1Yikge1xuICAgICAgICAgICAgICAgIHZhciBiZWhhdmlvciA9IHNpbm9uLmV4dGVuZCh7fSwgc2lub24uYmVoYXZpb3IpO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBiZWhhdmlvci5jcmVhdGU7XG4gICAgICAgICAgICAgICAgYmVoYXZpb3Iuc3R1YiA9IHN0dWI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYmVoYXZpb3I7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBpc1ByZXNlbnQ6IGZ1bmN0aW9uIGlzUHJlc2VudCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHR5cGVvZiB0aGlzLmNhbGxBcmdBdCA9PSBcIm51bWJlclwiIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmV4Y2VwdGlvbiB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZW9mIHRoaXMucmV0dXJuQXJnQXQgPT0gXCJudW1iZXJcIiB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXR1cm5UaGlzIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJldHVyblZhbHVlRGVmaW5lZCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBpbnZva2U6IGZ1bmN0aW9uIGludm9rZShjb250ZXh0LCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgY2FsbENhbGxiYWNrKHRoaXMsIGFyZ3MpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IHRoaXMuZXhjZXB0aW9uO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMucmV0dXJuQXJnQXQgPT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXJnc1t0aGlzLnJldHVybkFyZ0F0XTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMucmV0dXJuVGhpcykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29udGV4dDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5yZXR1cm5WYWx1ZTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uQ2FsbDogZnVuY3Rpb24gb25DYWxsKGluZGV4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3R1Yi5vbkNhbGwoaW5kZXgpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb25GaXJzdENhbGw6IGZ1bmN0aW9uIG9uRmlyc3RDYWxsKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnN0dWIub25GaXJzdENhbGwoKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uU2Vjb25kQ2FsbDogZnVuY3Rpb24gb25TZWNvbmRDYWxsKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnN0dWIub25TZWNvbmRDYWxsKCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBvblRoaXJkQ2FsbDogZnVuY3Rpb24gb25UaGlyZENhbGwoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3R1Yi5vblRoaXJkQ2FsbCgpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgd2l0aEFyZ3M6IGZ1bmN0aW9uIHdpdGhBcmdzKC8qIGFyZ3VtZW50cyAqLykge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkRlZmluaW5nIGEgc3R1YiBieSBpbnZva2luZyBcXFwic3R1Yi5vbkNhbGwoLi4uKS53aXRoQXJncyguLi4pXFxcIiBpcyBub3Qgc3VwcG9ydGVkLiBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiVXNlIFxcXCJzdHViLndpdGhBcmdzKC4uLikub25DYWxsKC4uLilcXFwiIHRvIGRlZmluZSBzZXF1ZW50aWFsIGJlaGF2aW9yIGZvciBjYWxscyB3aXRoIGNlcnRhaW4gYXJndW1lbnRzLlwiKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGNhbGxzQXJnOiBmdW5jdGlvbiBjYWxsc0FyZyhwb3MpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHBvcyAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBpbmRleCBpcyBub3QgbnVtYmVyXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ0F0ID0gcG9zO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBcmd1bWVudHMgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQ29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdQcm9wID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsc0FyZ09uOiBmdW5jdGlvbiBjYWxsc0FyZ09uKHBvcywgY29udGV4dCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcG9zICE9IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcImFyZ3VtZW50IGluZGV4IGlzIG5vdCBudW1iZXJcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY29udGV4dCAhPSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBjb250ZXh0IGlzIG5vdCBhbiBvYmplY3RcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsQXJnQXQgPSBwb3M7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FyZ3VtZW50cyA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tDb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdQcm9wID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsc0FyZ1dpdGg6IGZ1bmN0aW9uIGNhbGxzQXJnV2l0aChwb3MpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHBvcyAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBpbmRleCBpcyBub3QgbnVtYmVyXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ0F0ID0gcG9zO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBcmd1bWVudHMgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0NvbnRleHQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsQXJnUHJvcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXN5bmMgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgY2FsbHNBcmdPbldpdGg6IGZ1bmN0aW9uIGNhbGxzQXJnV2l0aChwb3MsIGNvbnRleHQpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHBvcyAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBpbmRleCBpcyBub3QgbnVtYmVyXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNvbnRleHQgIT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgY29udGV4dCBpcyBub3QgYW4gb2JqZWN0XCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ0F0ID0gcG9zO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBcmd1bWVudHMgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0NvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ1Byb3AgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FzeW5jID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHlpZWxkczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ0F0ID0gdXNlTGVmdE1vc3RDYWxsYmFjaztcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXJndW1lbnRzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tDb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ1Byb3AgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FzeW5jID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHlpZWxkc1JpZ2h0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsQXJnQXQgPSB1c2VSaWdodE1vc3RDYWxsYmFjaztcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXJndW1lbnRzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tDb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ1Byb3AgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FzeW5jID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHlpZWxkc09uOiBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY29udGV4dCAhPSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBjb250ZXh0IGlzIG5vdCBhbiBvYmplY3RcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsQXJnQXQgPSB1c2VMZWZ0TW9zdENhbGxiYWNrO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBcmd1bWVudHMgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0NvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ1Byb3AgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FzeW5jID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHlpZWxkc1RvOiBmdW5jdGlvbiAocHJvcCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ0F0ID0gdXNlTGVmdE1vc3RDYWxsYmFjaztcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXJndW1lbnRzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tDb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ1Byb3AgPSBwcm9wO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB5aWVsZHNUb09uOiBmdW5jdGlvbiAocHJvcCwgY29udGV4dCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY29udGV4dCAhPSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBjb250ZXh0IGlzIG5vdCBhbiBvYmplY3RcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsQXJnQXQgPSB1c2VMZWZ0TW9zdENhbGxiYWNrO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBcmd1bWVudHMgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0NvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ1Byb3AgPSBwcm9wO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB0aHJvd3M6IHRocm93c0V4Y2VwdGlvbixcbiAgICAgICAgICAgIHRocm93c0V4Y2VwdGlvbjogdGhyb3dzRXhjZXB0aW9uLFxuXG4gICAgICAgICAgICByZXR1cm5zOiBmdW5jdGlvbiByZXR1cm5zKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXR1cm5WYWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIHRoaXMucmV0dXJuVmFsdWVEZWZpbmVkID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgcmV0dXJuc0FyZzogZnVuY3Rpb24gcmV0dXJuc0FyZyhwb3MpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHBvcyAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBpbmRleCBpcyBub3QgbnVtYmVyXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMucmV0dXJuQXJnQXQgPSBwb3M7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJldHVybnNUaGlzOiBmdW5jdGlvbiByZXR1cm5zVGhpcygpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJldHVyblRoaXMgPSB0cnVlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gY3JlYXRlIGFzeW5jaHJvbm91cyB2ZXJzaW9ucyBvZiBjYWxsc0FyZyogYW5kIHlpZWxkcyogbWV0aG9kc1xuICAgICAgICBmb3IgKHZhciBtZXRob2QgaW4gcHJvdG8pIHtcbiAgICAgICAgICAgIC8vIG5lZWQgdG8gYXZvaWQgY3JlYXRpbmcgYW5vdGhlcmFzeW5jIHZlcnNpb25zIG9mIHRoZSBuZXdseSBhZGRlZCBhc3luYyBtZXRob2RzXG4gICAgICAgICAgICBpZiAocHJvdG8uaGFzT3duUHJvcGVydHkobWV0aG9kKSAmJlxuICAgICAgICAgICAgICAgIG1ldGhvZC5tYXRjaCgvXihjYWxsc0FyZ3x5aWVsZHMpLykgJiZcbiAgICAgICAgICAgICAgICAhbWV0aG9kLm1hdGNoKC9Bc3luYy8pKSB7XG4gICAgICAgICAgICAgICAgcHJvdG9bbWV0aG9kICsgXCJBc3luY1wiXSA9IChmdW5jdGlvbiAoc3luY0ZuTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHRoaXNbc3luY0ZuTmFtZV0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH0pKG1ldGhvZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzaW5vbi5iZWhhdmlvciA9IHByb3RvO1xuICAgICAgICByZXR1cm4gcHJvdG87XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgICAgICAgdmFyIHNpbm9uID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9leHRlbmRcIik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KHR5cGVvZiBzaW5vbiA9PSBcIm9iamVjdFwiICYmIHNpbm9uIHx8IG51bGwpKTtcblxufSkuY2FsbCh0aGlzLHJlcXVpcmUoXCJWQ21Fc3dcIikpIiwiLyoqXG4gICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAgKiBAZGVwZW5kIG1hdGNoLmpzXG4gICogQGRlcGVuZCBmb3JtYXQuanNcbiAgKi9cbi8qKlxuICAqIFNweSBjYWxsc1xuICAqXG4gICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gICogQGF1dGhvciBNYXhpbWlsaWFuIEFudG9uaSAobWFpbEBtYXhhbnRvbmkuZGUpXG4gICogQGxpY2Vuc2UgQlNEXG4gICpcbiAgKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAgKiBDb3B5cmlnaHQgKGMpIDIwMTMgTWF4aW1pbGlhbiBBbnRvbmlcbiAgKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKHNpbm9uKSB7XG4gICAgZnVuY3Rpb24gbWFrZUFwaShzaW5vbikge1xuICAgICAgICBmdW5jdGlvbiB0aHJvd1lpZWxkRXJyb3IocHJveHksIHRleHQsIGFyZ3MpIHtcbiAgICAgICAgICAgIHZhciBtc2cgPSBzaW5vbi5mdW5jdGlvbk5hbWUocHJveHkpICsgdGV4dDtcbiAgICAgICAgICAgIGlmIChhcmdzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG1zZyArPSBcIiBSZWNlaXZlZCBbXCIgKyBzbGljZS5jYWxsKGFyZ3MpLmpvaW4oXCIsIFwiKSArIFwiXVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG5cbiAgICAgICAgdmFyIGNhbGxQcm90byA9IHtcbiAgICAgICAgICAgIGNhbGxlZE9uOiBmdW5jdGlvbiBjYWxsZWRPbih0aGlzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2lub24ubWF0Y2ggJiYgc2lub24ubWF0Y2guaXNNYXRjaGVyKHRoaXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXNWYWx1ZS50ZXN0KHRoaXMudGhpc1ZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudGhpc1ZhbHVlID09PSB0aGlzVmFsdWU7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsZWRXaXRoOiBmdW5jdGlvbiBjYWxsZWRXaXRoKCkge1xuICAgICAgICAgICAgICAgIHZhciBsID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBpZiAobCA+IHRoaXMuYXJncy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbm9uLmRlZXBFcXVhbChhcmd1bWVudHNbaV0sIHRoaXMuYXJnc1tpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgY2FsbGVkV2l0aE1hdGNoOiBmdW5jdGlvbiBjYWxsZWRXaXRoTWF0Y2goKSB7XG4gICAgICAgICAgICAgICAgdmFyIGwgPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGlmIChsID4gdGhpcy5hcmdzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhY3R1YWwgPSB0aGlzLmFyZ3NbaV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBleHBlY3RhdGlvbiA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW5vbi5tYXRjaCB8fCAhc2lub24ubWF0Y2goZXhwZWN0YXRpb24pLnRlc3QoYWN0dWFsKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgY2FsbGVkV2l0aEV4YWN0bHk6IGZ1bmN0aW9uIGNhbGxlZFdpdGhFeGFjdGx5KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID09IHRoaXMuYXJncy5sZW5ndGggJiZcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jYWxsZWRXaXRoLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBub3RDYWxsZWRXaXRoOiBmdW5jdGlvbiBub3RDYWxsZWRXaXRoKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAhdGhpcy5jYWxsZWRXaXRoLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBub3RDYWxsZWRXaXRoTWF0Y2g6IGZ1bmN0aW9uIG5vdENhbGxlZFdpdGhNYXRjaCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gIXRoaXMuY2FsbGVkV2l0aE1hdGNoLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICByZXR1cm5lZDogZnVuY3Rpb24gcmV0dXJuZWQodmFsdWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2lub24uZGVlcEVxdWFsKHZhbHVlLCB0aGlzLnJldHVyblZhbHVlKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHRocmV3OiBmdW5jdGlvbiB0aHJldyhlcnJvcikge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZXJyb3IgPT09IFwidW5kZWZpbmVkXCIgfHwgIXRoaXMuZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAhIXRoaXMuZXhjZXB0aW9uO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmV4Y2VwdGlvbiA9PT0gZXJyb3IgfHwgdGhpcy5leGNlcHRpb24ubmFtZSA9PT0gZXJyb3I7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsZWRXaXRoTmV3OiBmdW5jdGlvbiBjYWxsZWRXaXRoTmV3KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnByb3h5LnByb3RvdHlwZSAmJiB0aGlzLnRoaXNWYWx1ZSBpbnN0YW5jZW9mIHRoaXMucHJveHk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsZWRCZWZvcmU6IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNhbGxJZCA8IG90aGVyLmNhbGxJZDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGNhbGxlZEFmdGVyOiBmdW5jdGlvbiAob3RoZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jYWxsSWQgPiBvdGhlci5jYWxsSWQ7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsQXJnOiBmdW5jdGlvbiAocG9zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hcmdzW3Bvc10oKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGNhbGxBcmdPbjogZnVuY3Rpb24gKHBvcywgdGhpc1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hcmdzW3Bvc10uYXBwbHkodGhpc1ZhbHVlKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGNhbGxBcmdXaXRoOiBmdW5jdGlvbiAocG9zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsQXJnT25XaXRoLmFwcGx5KHRoaXMsIFtwb3MsIG51bGxdLmNvbmNhdChzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGNhbGxBcmdPbldpdGg6IGZ1bmN0aW9uIChwb3MsIHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgICAgICAgICAgICAgIHRoaXMuYXJnc1twb3NdLmFwcGx5KHRoaXNWYWx1ZSwgYXJncyk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB5aWVsZDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRoaXMueWllbGRPbi5hcHBseSh0aGlzLCBbbnVsbF0uY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKSkpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgeWllbGRPbjogZnVuY3Rpb24gKHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gdGhpcy5hcmdzO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gYXJncy5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhcmdzW2ldID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3NbaV0uYXBwbHkodGhpc1ZhbHVlLCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRocm93WWllbGRFcnJvcih0aGlzLnByb3h5LCBcIiBjYW5ub3QgeWllbGQgc2luY2Ugbm8gY2FsbGJhY2sgd2FzIHBhc3NlZC5cIiwgYXJncyk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB5aWVsZFRvOiBmdW5jdGlvbiAocHJvcCkge1xuICAgICAgICAgICAgICAgIHRoaXMueWllbGRUb09uLmFwcGx5KHRoaXMsIFtwcm9wLCBudWxsXS5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB5aWVsZFRvT246IGZ1bmN0aW9uIChwcm9wLCB0aGlzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXJncyA9IHRoaXMuYXJncztcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGFyZ3MubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhcmdzW2ldICYmIHR5cGVvZiBhcmdzW2ldW3Byb3BdID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFyZ3NbaV1bcHJvcF0uYXBwbHkodGhpc1ZhbHVlLCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRocm93WWllbGRFcnJvcih0aGlzLnByb3h5LCBcIiBjYW5ub3QgeWllbGQgdG8gJ1wiICsgcHJvcCArXG4gICAgICAgICAgICAgICAgICAgIFwiJyBzaW5jZSBubyBjYWxsYmFjayB3YXMgcGFzc2VkLlwiLCBhcmdzKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHRvU3RyaW5nOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNhbGxTdHIgPSB0aGlzLnByb3h5LnRvU3RyaW5nKCkgKyBcIihcIjtcbiAgICAgICAgICAgICAgICB2YXIgYXJncyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSB0aGlzLmFyZ3MubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGFyZ3MucHVzaChzaW5vbi5mb3JtYXQodGhpcy5hcmdzW2ldKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgY2FsbFN0ciA9IGNhbGxTdHIgKyBhcmdzLmpvaW4oXCIsIFwiKSArIFwiKVwiO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnJldHVyblZhbHVlICE9IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbFN0ciArPSBcIiA9PiBcIiArIHNpbm9uLmZvcm1hdCh0aGlzLnJldHVyblZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5leGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbFN0ciArPSBcIiAhXCIgKyB0aGlzLmV4Y2VwdGlvbi5uYW1lO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmV4Y2VwdGlvbi5tZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYWxsU3RyICs9IFwiKFwiICsgdGhpcy5leGNlcHRpb24ubWVzc2FnZSArIFwiKVwiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGNhbGxTdHI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgY2FsbFByb3RvLmludm9rZUNhbGxiYWNrID0gY2FsbFByb3RvLnlpZWxkO1xuXG4gICAgICAgIGZ1bmN0aW9uIGNyZWF0ZVNweUNhbGwoc3B5LCB0aGlzVmFsdWUsIGFyZ3MsIHJldHVyblZhbHVlLCBleGNlcHRpb24sIGlkKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGlkICE9PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbGwgaWQgaXMgbm90IGEgbnVtYmVyXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHByb3h5Q2FsbCA9IHNpbm9uLmNyZWF0ZShjYWxsUHJvdG8pO1xuICAgICAgICAgICAgcHJveHlDYWxsLnByb3h5ID0gc3B5O1xuICAgICAgICAgICAgcHJveHlDYWxsLnRoaXNWYWx1ZSA9IHRoaXNWYWx1ZTtcbiAgICAgICAgICAgIHByb3h5Q2FsbC5hcmdzID0gYXJncztcbiAgICAgICAgICAgIHByb3h5Q2FsbC5yZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlO1xuICAgICAgICAgICAgcHJveHlDYWxsLmV4Y2VwdGlvbiA9IGV4Y2VwdGlvbjtcbiAgICAgICAgICAgIHByb3h5Q2FsbC5jYWxsSWQgPSBpZDtcblxuICAgICAgICAgICAgcmV0dXJuIHByb3h5Q2FsbDtcbiAgICAgICAgfVxuICAgICAgICBjcmVhdGVTcHlDYWxsLnRvU3RyaW5nID0gY2FsbFByb3RvLnRvU3RyaW5nOyAvLyB1c2VkIGJ5IG1vY2tzXG5cbiAgICAgICAgc2lub24uc3B5Q2FsbCA9IGNyZWF0ZVNweUNhbGw7XG4gICAgICAgIHJldHVybiBjcmVhdGVTcHlDYWxsO1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vbWF0Y2hcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2Zvcm1hdFwiKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIHV0aWwvY29yZS5qc1xuICogQGRlcGVuZCBzcHkuanNcbiAqIEBkZXBlbmQgc3R1Yi5qc1xuICogQGRlcGVuZCBtb2NrLmpzXG4gKi9cbi8qKlxuICogQ29sbGVjdGlvbnMgb2Ygc3R1YnMsIHNwaWVzIGFuZCBtb2Nrcy5cbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIHZhciBwdXNoID0gW10ucHVzaDtcbiAgICB2YXIgaGFzT3duUHJvcGVydHkgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5O1xuXG4gICAgZnVuY3Rpb24gZ2V0RmFrZXMoZmFrZUNvbGxlY3Rpb24pIHtcbiAgICAgICAgaWYgKCFmYWtlQ29sbGVjdGlvbi5mYWtlcykge1xuICAgICAgICAgICAgZmFrZUNvbGxlY3Rpb24uZmFrZXMgPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmYWtlQ29sbGVjdGlvbi5mYWtlcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlYWNoKGZha2VDb2xsZWN0aW9uLCBtZXRob2QpIHtcbiAgICAgICAgdmFyIGZha2VzID0gZ2V0RmFrZXMoZmFrZUNvbGxlY3Rpb24pO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gZmFrZXMubGVuZ3RoOyBpIDwgbDsgaSArPSAxKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGZha2VzW2ldW21ldGhvZF0gPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgZmFrZXNbaV1bbWV0aG9kXSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcGFjdChmYWtlQ29sbGVjdGlvbikge1xuICAgICAgICB2YXIgZmFrZXMgPSBnZXRGYWtlcyhmYWtlQ29sbGVjdGlvbik7XG4gICAgICAgIHZhciBpID0gMDtcbiAgICAgICAgd2hpbGUgKGkgPCBmYWtlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGZha2VzLnNwbGljZShpLCAxKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgdmFyIGNvbGxlY3Rpb24gPSB7XG4gICAgICAgICAgICB2ZXJpZnk6IGZ1bmN0aW9uIHJlc29sdmUoKSB7XG4gICAgICAgICAgICAgICAgZWFjaCh0aGlzLCBcInZlcmlmeVwiKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlc3RvcmU6IGZ1bmN0aW9uIHJlc3RvcmUoKSB7XG4gICAgICAgICAgICAgICAgZWFjaCh0aGlzLCBcInJlc3RvcmVcIik7XG4gICAgICAgICAgICAgICAgY29tcGFjdCh0aGlzKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlc2V0OiBmdW5jdGlvbiByZXN0b3JlKCkge1xuICAgICAgICAgICAgICAgIGVhY2godGhpcywgXCJyZXNldFwiKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHZlcmlmeUFuZFJlc3RvcmU6IGZ1bmN0aW9uIHZlcmlmeUFuZFJlc3RvcmUoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGV4Y2VwdGlvbjtcblxuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudmVyaWZ5KCk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBleGNlcHRpb24gPSBlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMucmVzdG9yZSgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGV4Y2VwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBleGNlcHRpb247XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgYWRkOiBmdW5jdGlvbiBhZGQoZmFrZSkge1xuICAgICAgICAgICAgICAgIHB1c2guY2FsbChnZXRGYWtlcyh0aGlzKSwgZmFrZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZha2U7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBzcHk6IGZ1bmN0aW9uIHNweSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQoc2lub24uc3B5LmFwcGx5KHNpbm9uLCBhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHN0dWI6IGZ1bmN0aW9uIHN0dWIob2JqZWN0LCBwcm9wZXJ0eSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG9yaWdpbmFsID0gb2JqZWN0W3Byb3BlcnR5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9yaWdpbmFsICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBzdHViIG5vbi1leGlzdGVudCBvd24gcHJvcGVydHkgXCIgKyBwcm9wZXJ0eSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdFtwcm9wZXJ0eV0gPSB2YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRkKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN0b3JlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdFtwcm9wZXJ0eV0gPSBvcmlnaW5hbDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIXByb3BlcnR5ICYmICEhb2JqZWN0ICYmIHR5cGVvZiBvYmplY3QgPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgc3R1YmJlZE9iaiA9IHNpbm9uLnN0dWIuYXBwbHkoc2lub24sIGFyZ3VtZW50cyk7XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiBzdHViYmVkT2JqKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHN0dWJiZWRPYmpbcHJvcF0gPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkKHN0dWJiZWRPYmpbcHJvcF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0dWJiZWRPYmo7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRkKHNpbm9uLnN0dWIuYXBwbHkoc2lub24sIGFyZ3VtZW50cykpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgbW9jazogZnVuY3Rpb24gbW9jaygpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQoc2lub24ubW9jay5hcHBseShzaW5vbiwgYXJndW1lbnRzKSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBpbmplY3Q6IGZ1bmN0aW9uIGluamVjdChvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgY29sID0gdGhpcztcblxuICAgICAgICAgICAgICAgIG9iai5zcHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjb2wuc3B5LmFwcGx5KGNvbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgb2JqLnN0dWIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjb2wuc3R1Yi5hcHBseShjb2wsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIG9iai5tb2NrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29sLm1vY2suYXBwbHkoY29sLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLmNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uO1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL21vY2tcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3NweVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc3R1YlwiKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIHV0aWwvY29yZS5qc1xuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcblxuICAgICAgICAvLyBBZGFwdGVkIGZyb20gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4vZG9jcy9FQ01BU2NyaXB0X0RvbnRFbnVtX2F0dHJpYnV0ZSNKU2NyaXB0X0RvbnRFbnVtX0J1Z1xuICAgICAgICB2YXIgaGFzRG9udEVudW1CdWcgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIG9iaiA9IHtcbiAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCIwXCI7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB0b1N0cmluZzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCIxXCI7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB2YWx1ZU9mOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIjJcIjtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHRvTG9jYWxlU3RyaW5nOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIjNcIjtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHByb3RvdHlwZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCI0XCI7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpc1Byb3RvdHlwZU9mOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIjVcIjtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHByb3BlcnR5SXNFbnVtZXJhYmxlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIjZcIjtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGhhc093blByb3BlcnR5OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIjdcIjtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGxlbmd0aDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCI4XCI7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB1bmlxdWU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiOVwiXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChvYmpbcHJvcF0oKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0LmpvaW4oXCJcIikgIT09IFwiMDEyMzQ1Njc4OVwiO1xuICAgICAgICB9KSgpO1xuXG4gICAgICAgIC8qIFB1YmxpYzogRXh0ZW5kIHRhcmdldCBpbiBwbGFjZSB3aXRoIGFsbCAob3duKSBwcm9wZXJ0aWVzIGZyb20gc291cmNlcyBpbi1vcmRlci4gVGh1cywgbGFzdCBzb3VyY2Ugd2lsbFxuICAgICAgICAgKiAgICAgICAgIG92ZXJyaWRlIHByb3BlcnRpZXMgaW4gcHJldmlvdXMgc291cmNlcy5cbiAgICAgICAgICpcbiAgICAgICAgICogdGFyZ2V0IC0gVGhlIE9iamVjdCB0byBleHRlbmRcbiAgICAgICAgICogc291cmNlcyAtIE9iamVjdHMgdG8gY29weSBwcm9wZXJ0aWVzIGZyb20uXG4gICAgICAgICAqXG4gICAgICAgICAqIFJldHVybnMgdGhlIGV4dGVuZGVkIHRhcmdldFxuICAgICAgICAgKi9cbiAgICAgICAgZnVuY3Rpb24gZXh0ZW5kKHRhcmdldCAvKiwgc291cmNlcyAqLykge1xuICAgICAgICAgICAgdmFyIHNvdXJjZXMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpLFxuICAgICAgICAgICAgICAgIHNvdXJjZSwgaSwgcHJvcDtcblxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHNvdXJjZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBzb3VyY2UgPSBzb3VyY2VzW2ldO1xuXG4gICAgICAgICAgICAgICAgZm9yIChwcm9wIGluIHNvdXJjZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoc291cmNlLmhhc093blByb3BlcnR5KHByb3ApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRbcHJvcF0gPSBzb3VyY2VbcHJvcF07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBNYWtlIHN1cmUgd2UgY29weSAob3duKSB0b1N0cmluZyBtZXRob2QgZXZlbiB3aGVuIGluIEpTY3JpcHQgd2l0aCBEb250RW51bSBidWdcbiAgICAgICAgICAgICAgICAvLyBTZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4vZG9jcy9FQ01BU2NyaXB0X0RvbnRFbnVtX2F0dHJpYnV0ZSNKU2NyaXB0X0RvbnRFbnVtX0J1Z1xuICAgICAgICAgICAgICAgIGlmIChoYXNEb250RW51bUJ1ZyAmJiBzb3VyY2UuaGFzT3duUHJvcGVydHkoXCJ0b1N0cmluZ1wiKSAmJiBzb3VyY2UudG9TdHJpbmcgIT09IHRhcmdldC50b1N0cmluZykge1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXQudG9TdHJpbmcgPSBzb3VyY2UudG9TdHJpbmc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLmV4dGVuZCA9IGV4dGVuZDtcbiAgICAgICAgcmV0dXJuIHNpbm9uLmV4dGVuZDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KHR5cGVvZiBzaW5vbiA9PSBcIm9iamVjdFwiICYmIHNpbm9uIHx8IG51bGwpKTtcbiIsIi8qKlxuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqL1xuLyoqXG4gKiBGb3JtYXQgZnVuY3Rpb25zXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxNCBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiAoc2lub24sIGZvcm1hdGlvKSB7XG4gICAgZnVuY3Rpb24gbWFrZUFwaShzaW5vbikge1xuICAgICAgICBmdW5jdGlvbiB2YWx1ZUZvcm1hdHRlcih2YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIFwiXCIgKyB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGdldEZvcm1hdGlvRm9ybWF0dGVyKCkge1xuICAgICAgICAgICAgdmFyIGZvcm1hdHRlciA9IGZvcm1hdGlvLmNvbmZpZ3VyZSh7XG4gICAgICAgICAgICAgICAgICAgIHF1b3RlU3RyaW5nczogZmFsc2UsXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0Q2hpbGRyZW5Db3VudDogMjUwXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGZvcm1hdCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZm9ybWF0dGVyLmFzY2lpLmFwcGx5KGZvcm1hdHRlciwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHJldHVybiBmb3JtYXQ7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBnZXROb2RlRm9ybWF0dGVyKHZhbHVlKSB7XG4gICAgICAgICAgICBmdW5jdGlvbiBmb3JtYXQodmFsdWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09IFwib2JqZWN0XCIgJiYgdmFsdWUudG9TdHJpbmcgPT09IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcgPyB1dGlsLmluc3BlY3QodmFsdWUpIDogdmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHZhciB1dGlsID0gcmVxdWlyZShcInV0aWxcIik7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgLyogTm9kZSwgYnV0IG5vIHV0aWwgbW9kdWxlIC0gd291bGQgYmUgdmVyeSBvbGQsIGJ1dCBiZXR0ZXIgc2FmZSB0aGFuIHNvcnJ5ICovXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB1dGlsID8gZm9ybWF0IDogdmFsdWVGb3JtYXR0ZXI7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIsXG4gICAgICAgICAgICBmb3JtYXR0ZXI7XG5cbiAgICAgICAgaWYgKGlzTm9kZSkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBmb3JtYXRpbyA9IHJlcXVpcmUoXCJmb3JtYXRpb1wiKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZm9ybWF0aW8pIHtcbiAgICAgICAgICAgIGZvcm1hdHRlciA9IGdldEZvcm1hdGlvRm9ybWF0dGVyKClcbiAgICAgICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgICAgIGZvcm1hdHRlciA9IGdldE5vZGVGb3JtYXR0ZXIoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvcm1hdHRlciA9IHZhbHVlRm9ybWF0dGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgc2lub24uZm9ybWF0ID0gZm9ybWF0dGVyO1xuICAgICAgICByZXR1cm4gc2lub24uZm9ybWF0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZVwiKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0oXG4gICAgKHR5cGVvZiBzaW5vbiA9PSBcIm9iamVjdFwiICYmIHNpbm9uIHx8IG51bGwpLFxuICAgICh0eXBlb2YgZm9ybWF0aW8gPT0gXCJvYmplY3RcIiAmJiBmb3JtYXRpbylcbikpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIHV0aWwvY29yZS5qc1xuICovXG4vKipcbiAqIExvZ3MgZXJyb3JzXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxNCBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiAoc2lub24pIHtcbiAgICAvLyBjYWNoZSBhIHJlZmVyZW5jZSB0byBzZXRUaW1lb3V0LCBzbyB0aGF0IG91ciByZWZlcmVuY2Ugd29uJ3QgYmUgc3R1YmJlZCBvdXRcbiAgICAvLyB3aGVuIHVzaW5nIGZha2UgdGltZXJzIGFuZCBlcnJvcnMgd2lsbCBzdGlsbCBnZXQgbG9nZ2VkXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2Nqb2hhbnNlbi9TaW5vbi5KUy9pc3N1ZXMvMzgxXG4gICAgdmFyIHJlYWxTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcblxuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcblxuICAgICAgICBmdW5jdGlvbiBsb2coKSB7fVxuXG4gICAgICAgIGZ1bmN0aW9uIGxvZ0Vycm9yKGxhYmVsLCBlcnIpIHtcbiAgICAgICAgICAgIHZhciBtc2cgPSBsYWJlbCArIFwiIHRocmV3IGV4Y2VwdGlvbjogXCI7XG5cbiAgICAgICAgICAgIHNpbm9uLmxvZyhtc2cgKyBcIltcIiArIGVyci5uYW1lICsgXCJdIFwiICsgZXJyLm1lc3NhZ2UpO1xuXG4gICAgICAgICAgICBpZiAoZXJyLnN0YWNrKSB7XG4gICAgICAgICAgICAgICAgc2lub24ubG9nKGVyci5zdGFjayk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxvZ0Vycm9yLnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlID0gbXNnICsgZXJyLm1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gd3JhcCByZWFsU2V0VGltZW91dCB3aXRoIHNvbWV0aGluZyB3ZSBjYW4gc3R1YiBpbiB0ZXN0c1xuICAgICAgICBsb2dFcnJvci5zZXRUaW1lb3V0ID0gZnVuY3Rpb24gKGZ1bmMsIHRpbWVvdXQpIHtcbiAgICAgICAgICAgIHJlYWxTZXRUaW1lb3V0KGZ1bmMsIHRpbWVvdXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGV4cG9ydHMgPSB7fTtcbiAgICAgICAgZXhwb3J0cy5sb2cgPSBzaW5vbi5sb2cgPSBsb2c7XG4gICAgICAgIGV4cG9ydHMubG9nRXJyb3IgPSBzaW5vbi5sb2dFcnJvciA9IGxvZ0Vycm9yO1xuXG4gICAgICAgIHJldHVybiBleHBvcnRzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZVwiKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIHV0aWwvY29yZS5qc1xuICogQGRlcGVuZCB0eXBlT2YuanNcbiAqL1xuLypqc2xpbnQgZXFlcWVxOiBmYWxzZSwgb25ldmFyOiBmYWxzZSwgcGx1c3BsdXM6IGZhbHNlKi9cbi8qZ2xvYmFsIG1vZHVsZSwgcmVxdWlyZSwgc2lub24qL1xuLyoqXG4gKiBNYXRjaCBmdW5jdGlvbnNcbiAqXG4gKiBAYXV0aG9yIE1heGltaWxpYW4gQW50b25pIChtYWlsQG1heGFudG9uaS5kZSlcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMiBNYXhpbWlsaWFuIEFudG9uaVxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgZnVuY3Rpb24gYXNzZXJ0VHlwZSh2YWx1ZSwgdHlwZSwgbmFtZSkge1xuICAgICAgICAgICAgdmFyIGFjdHVhbCA9IHNpbm9uLnR5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICBpZiAoYWN0dWFsICE9PSB0eXBlKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkV4cGVjdGVkIHR5cGUgb2YgXCIgKyBuYW1lICsgXCIgdG8gYmUgXCIgK1xuICAgICAgICAgICAgICAgICAgICB0eXBlICsgXCIsIGJ1dCB3YXMgXCIgKyBhY3R1YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG1hdGNoZXIgPSB7XG4gICAgICAgICAgICB0b1N0cmluZzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1lc3NhZ2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgZnVuY3Rpb24gaXNNYXRjaGVyKG9iamVjdCkge1xuICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXIuaXNQcm90b3R5cGVPZihvYmplY3QpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gbWF0Y2hPYmplY3QoZXhwZWN0YXRpb24sIGFjdHVhbCkge1xuICAgICAgICAgICAgaWYgKGFjdHVhbCA9PT0gbnVsbCB8fCBhY3R1YWwgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgICAgIGlmIChleHBlY3RhdGlvbi5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBleHAgPSBleHBlY3RhdGlvbltrZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYWN0ID0gYWN0dWFsW2tleV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5pc01hdGNoZXIoZXhwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFleHAudGVzdChhY3QpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHNpbm9uLnR5cGVPZihleHApID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW1hdGNoT2JqZWN0KGV4cCwgYWN0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghc2lub24uZGVlcEVxdWFsKGV4cCwgYWN0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBtYXRjaGVyLm9yID0gZnVuY3Rpb24gKG0yKSB7XG4gICAgICAgICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWF0Y2hlciBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzTWF0Y2hlcihtMikpIHtcbiAgICAgICAgICAgICAgICBtMiA9IG1hdGNoKG0yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBtMSA9IHRoaXM7XG4gICAgICAgICAgICB2YXIgb3IgPSBzaW5vbi5jcmVhdGUobWF0Y2hlcik7XG4gICAgICAgICAgICBvci50ZXN0ID0gZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBtMS50ZXN0KGFjdHVhbCkgfHwgbTIudGVzdChhY3R1YWwpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIG9yLm1lc3NhZ2UgPSBtMS5tZXNzYWdlICsgXCIub3IoXCIgKyBtMi5tZXNzYWdlICsgXCIpXCI7XG4gICAgICAgICAgICByZXR1cm4gb3I7XG4gICAgICAgIH07XG5cbiAgICAgICAgbWF0Y2hlci5hbmQgPSBmdW5jdGlvbiAobTIpIHtcbiAgICAgICAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJNYXRjaGVyIGV4cGVjdGVkXCIpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghaXNNYXRjaGVyKG0yKSkge1xuICAgICAgICAgICAgICAgIG0yID0gbWF0Y2gobTIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG0xID0gdGhpcztcbiAgICAgICAgICAgIHZhciBhbmQgPSBzaW5vbi5jcmVhdGUobWF0Y2hlcik7XG4gICAgICAgICAgICBhbmQudGVzdCA9IGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbTEudGVzdChhY3R1YWwpICYmIG0yLnRlc3QoYWN0dWFsKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBhbmQubWVzc2FnZSA9IG0xLm1lc3NhZ2UgKyBcIi5hbmQoXCIgKyBtMi5tZXNzYWdlICsgXCIpXCI7XG4gICAgICAgICAgICByZXR1cm4gYW5kO1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBtYXRjaCA9IGZ1bmN0aW9uIChleHBlY3RhdGlvbiwgbWVzc2FnZSkge1xuICAgICAgICAgICAgdmFyIG0gPSBzaW5vbi5jcmVhdGUobWF0Y2hlcik7XG4gICAgICAgICAgICB2YXIgdHlwZSA9IHNpbm9uLnR5cGVPZihleHBlY3RhdGlvbik7XG4gICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgXCJvYmplY3RcIjpcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGV4cGVjdGF0aW9uLnRlc3QgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICBtLnRlc3QgPSBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXhwZWN0YXRpb24udGVzdChhY3R1YWwpID09PSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBtLm1lc3NhZ2UgPSBcIm1hdGNoKFwiICsgc2lub24uZnVuY3Rpb25OYW1lKGV4cGVjdGF0aW9uLnRlc3QpICsgXCIpXCI7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgc3RyID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIGV4cGVjdGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleHBlY3RhdGlvbi5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHIucHVzaChrZXkgKyBcIjogXCIgKyBleHBlY3RhdGlvbltrZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBtLnRlc3QgPSBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXRjaE9iamVjdChleHBlY3RhdGlvbiwgYWN0dWFsKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIG0ubWVzc2FnZSA9IFwibWF0Y2goXCIgKyBzdHIuam9pbihcIiwgXCIpICsgXCIpXCI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwibnVtYmVyXCI6XG4gICAgICAgICAgICAgICAgbS50ZXN0ID0gZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXhwZWN0YXRpb24gPT0gYWN0dWFsO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwic3RyaW5nXCI6XG4gICAgICAgICAgICAgICAgbS50ZXN0ID0gZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGFjdHVhbCAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhY3R1YWwuaW5kZXhPZihleHBlY3RhdGlvbikgIT09IC0xO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgbS5tZXNzYWdlID0gXCJtYXRjaChcXFwiXCIgKyBleHBlY3RhdGlvbiArIFwiXFxcIilcIjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJyZWdleHBcIjpcbiAgICAgICAgICAgICAgICBtLnRlc3QgPSBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYWN0dWFsICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV4cGVjdGF0aW9uLnRlc3QoYWN0dWFsKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcImZ1bmN0aW9uXCI6XG4gICAgICAgICAgICAgICAgbS50ZXN0ID0gZXhwZWN0YXRpb247XG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgbS5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBtLm1lc3NhZ2UgPSBcIm1hdGNoKFwiICsgc2lub24uZnVuY3Rpb25OYW1lKGV4cGVjdGF0aW9uKSArIFwiKVwiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgbS50ZXN0ID0gZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2lub24uZGVlcEVxdWFsKGV4cGVjdGF0aW9uLCBhY3R1YWwpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIW0ubWVzc2FnZSkge1xuICAgICAgICAgICAgICAgIG0ubWVzc2FnZSA9IFwibWF0Y2goXCIgKyBleHBlY3RhdGlvbiArIFwiKVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG07XG4gICAgICAgIH07XG5cbiAgICAgICAgbWF0Y2guaXNNYXRjaGVyID0gaXNNYXRjaGVyO1xuXG4gICAgICAgIG1hdGNoLmFueSA9IG1hdGNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LCBcImFueVwiKTtcblxuICAgICAgICBtYXRjaC5kZWZpbmVkID0gbWF0Y2goZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgcmV0dXJuIGFjdHVhbCAhPT0gbnVsbCAmJiBhY3R1YWwgIT09IHVuZGVmaW5lZDtcbiAgICAgICAgfSwgXCJkZWZpbmVkXCIpO1xuXG4gICAgICAgIG1hdGNoLnRydXRoeSA9IG1hdGNoKGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgIHJldHVybiAhIWFjdHVhbDtcbiAgICAgICAgfSwgXCJ0cnV0aHlcIik7XG5cbiAgICAgICAgbWF0Y2guZmFsc3kgPSBtYXRjaChmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICByZXR1cm4gIWFjdHVhbDtcbiAgICAgICAgfSwgXCJmYWxzeVwiKTtcblxuICAgICAgICBtYXRjaC5zYW1lID0gZnVuY3Rpb24gKGV4cGVjdGF0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2goZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBleHBlY3RhdGlvbiA9PT0gYWN0dWFsO1xuICAgICAgICAgICAgfSwgXCJzYW1lKFwiICsgZXhwZWN0YXRpb24gKyBcIilcIik7XG4gICAgICAgIH07XG5cbiAgICAgICAgbWF0Y2gudHlwZU9mID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgICAgIGFzc2VydFR5cGUodHlwZSwgXCJzdHJpbmdcIiwgXCJ0eXBlXCIpO1xuICAgICAgICAgICAgcmV0dXJuIG1hdGNoKGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2lub24udHlwZU9mKGFjdHVhbCkgPT09IHR5cGU7XG4gICAgICAgICAgICB9LCBcInR5cGVPZihcXFwiXCIgKyB0eXBlICsgXCJcXFwiKVwiKTtcbiAgICAgICAgfTtcblxuICAgICAgICBtYXRjaC5pbnN0YW5jZU9mID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgICAgIGFzc2VydFR5cGUodHlwZSwgXCJmdW5jdGlvblwiLCBcInR5cGVcIik7XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2goZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhY3R1YWwgaW5zdGFuY2VvZiB0eXBlO1xuICAgICAgICAgICAgfSwgXCJpbnN0YW5jZU9mKFwiICsgc2lub24uZnVuY3Rpb25OYW1lKHR5cGUpICsgXCIpXCIpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGZ1bmN0aW9uIGNyZWF0ZVByb3BlcnR5TWF0Y2hlcihwcm9wZXJ0eVRlc3QsIG1lc3NhZ2VQcmVmaXgpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAocHJvcGVydHksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0VHlwZShwcm9wZXJ0eSwgXCJzdHJpbmdcIiwgXCJwcm9wZXJ0eVwiKTtcbiAgICAgICAgICAgICAgICB2YXIgb25seVByb3BlcnR5ID0gYXJndW1lbnRzLmxlbmd0aCA9PT0gMTtcbiAgICAgICAgICAgICAgICB2YXIgbWVzc2FnZSA9IG1lc3NhZ2VQcmVmaXggKyBcIihcXFwiXCIgKyBwcm9wZXJ0eSArIFwiXFxcIlwiO1xuICAgICAgICAgICAgICAgIGlmICghb25seVByb3BlcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgKz0gXCIsIFwiICsgdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1lc3NhZ2UgKz0gXCIpXCI7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoKGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFjdHVhbCA9PT0gdW5kZWZpbmVkIHx8IGFjdHVhbCA9PT0gbnVsbCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICFwcm9wZXJ0eVRlc3QoYWN0dWFsLCBwcm9wZXJ0eSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb25seVByb3BlcnR5IHx8IHNpbm9uLmRlZXBFcXVhbCh2YWx1ZSwgYWN0dWFsW3Byb3BlcnR5XSk7XG4gICAgICAgICAgICAgICAgfSwgbWVzc2FnZSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbWF0Y2guaGFzID0gY3JlYXRlUHJvcGVydHlNYXRjaGVyKGZ1bmN0aW9uIChhY3R1YWwsIHByb3BlcnR5KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGFjdHVhbCA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wZXJ0eSBpbiBhY3R1YWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYWN0dWFsW3Byb3BlcnR5XSAhPT0gdW5kZWZpbmVkO1xuICAgICAgICB9LCBcImhhc1wiKTtcblxuICAgICAgICBtYXRjaC5oYXNPd24gPSBjcmVhdGVQcm9wZXJ0eU1hdGNoZXIoZnVuY3Rpb24gKGFjdHVhbCwgcHJvcGVydHkpIHtcbiAgICAgICAgICAgIHJldHVybiBhY3R1YWwuaGFzT3duUHJvcGVydHkocHJvcGVydHkpO1xuICAgICAgICB9LCBcImhhc093blwiKTtcblxuICAgICAgICBtYXRjaC5ib29sID0gbWF0Y2gudHlwZU9mKFwiYm9vbGVhblwiKTtcbiAgICAgICAgbWF0Y2gubnVtYmVyID0gbWF0Y2gudHlwZU9mKFwibnVtYmVyXCIpO1xuICAgICAgICBtYXRjaC5zdHJpbmcgPSBtYXRjaC50eXBlT2YoXCJzdHJpbmdcIik7XG4gICAgICAgIG1hdGNoLm9iamVjdCA9IG1hdGNoLnR5cGVPZihcIm9iamVjdFwiKTtcbiAgICAgICAgbWF0Y2guZnVuYyA9IG1hdGNoLnR5cGVPZihcImZ1bmN0aW9uXCIpO1xuICAgICAgICBtYXRjaC5hcnJheSA9IG1hdGNoLnR5cGVPZihcImFycmF5XCIpO1xuICAgICAgICBtYXRjaC5yZWdleHAgPSBtYXRjaC50eXBlT2YoXCJyZWdleHBcIik7XG4gICAgICAgIG1hdGNoLmRhdGUgPSBtYXRjaC50eXBlT2YoXCJkYXRlXCIpO1xuXG4gICAgICAgIHNpbm9uLm1hdGNoID0gbWF0Y2g7XG4gICAgICAgIHJldHVybiBtYXRjaDtcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3R5cGVPZlwiKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIHRpbWVzX2luX3dvcmRzLmpzXG4gKiBAZGVwZW5kIHV0aWwvY29yZS5qc1xuICogQGRlcGVuZCBjYWxsLmpzXG4gKiBAZGVwZW5kIGV4dGVuZC5qc1xuICogQGRlcGVuZCBtYXRjaC5qc1xuICogQGRlcGVuZCBzcHkuanNcbiAqIEBkZXBlbmQgc3R1Yi5qc1xuICogQGRlcGVuZCBmb3JtYXQuanNcbiAqL1xuLyoqXG4gKiBNb2NrIGZ1bmN0aW9ucy5cbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgdmFyIHB1c2ggPSBbXS5wdXNoO1xuICAgICAgICB2YXIgbWF0Y2ggPSBzaW5vbi5tYXRjaDtcblxuICAgICAgICBmdW5jdGlvbiBtb2NrKG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKCFvYmplY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2lub24uZXhwZWN0YXRpb24uY3JlYXRlKFwiQW5vbnltb3VzIG1vY2tcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBtb2NrLmNyZWF0ZShvYmplY3QpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gZWFjaChjb2xsZWN0aW9uLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgaWYgKCFjb2xsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGNvbGxlY3Rpb24ubGVuZ3RoOyBpIDwgbDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soY29sbGVjdGlvbltpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzaW5vbi5leHRlbmQobW9jaywge1xuICAgICAgICAgICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUob2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgaWYgKCFvYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIm9iamVjdCBpcyBudWxsXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtb2NrT2JqZWN0ID0gc2lub24uZXh0ZW5kKHt9LCBtb2NrKTtcbiAgICAgICAgICAgICAgICBtb2NrT2JqZWN0Lm9iamVjdCA9IG9iamVjdDtcbiAgICAgICAgICAgICAgICBkZWxldGUgbW9ja09iamVjdC5jcmVhdGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbW9ja09iamVjdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGV4cGVjdHM6IGZ1bmN0aW9uIGV4cGVjdHMobWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFtZXRob2QpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIm1ldGhvZCBpcyBmYWxzeVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuZXhwZWN0YXRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXhwZWN0YXRpb25zID0ge307XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJveGllcyA9IFtdO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5leHBlY3RhdGlvbnNbbWV0aG9kXSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV4cGVjdGF0aW9uc1ttZXRob2RdID0gW107XG4gICAgICAgICAgICAgICAgICAgIHZhciBtb2NrT2JqZWN0ID0gdGhpcztcblxuICAgICAgICAgICAgICAgICAgICBzaW5vbi53cmFwTWV0aG9kKHRoaXMub2JqZWN0LCBtZXRob2QsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtb2NrT2JqZWN0Lmludm9rZU1ldGhvZChtZXRob2QsIHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbCh0aGlzLnByb3hpZXMsIG1ldGhvZCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGV4cGVjdGF0aW9uID0gc2lub24uZXhwZWN0YXRpb24uY3JlYXRlKG1ldGhvZCk7XG4gICAgICAgICAgICAgICAgcHVzaC5jYWxsKHRoaXMuZXhwZWN0YXRpb25zW21ldGhvZF0sIGV4cGVjdGF0aW9uKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBleHBlY3RhdGlvbjtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlc3RvcmU6IGZ1bmN0aW9uIHJlc3RvcmUoKSB7XG4gICAgICAgICAgICAgICAgdmFyIG9iamVjdCA9IHRoaXMub2JqZWN0O1xuXG4gICAgICAgICAgICAgICAgZWFjaCh0aGlzLnByb3hpZXMsIGZ1bmN0aW9uIChwcm94eSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdFtwcm94eV0ucmVzdG9yZSA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdFtwcm94eV0ucmVzdG9yZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB2ZXJpZnk6IGZ1bmN0aW9uIHZlcmlmeSgpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXhwZWN0YXRpb25zID0gdGhpcy5leHBlY3RhdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2VzID0gW10sIG1ldCA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZWFjaCh0aGlzLnByb3hpZXMsIGZ1bmN0aW9uIChwcm94eSkge1xuICAgICAgICAgICAgICAgICAgICBlYWNoKGV4cGVjdGF0aW9uc1twcm94eV0sIGZ1bmN0aW9uIChleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFleHBlY3RhdGlvbi5tZXQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbChtZXNzYWdlcywgZXhwZWN0YXRpb24udG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbChtZXQsIGV4cGVjdGF0aW9uLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHRoaXMucmVzdG9yZSgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbChtZXNzYWdlcy5jb25jYXQobWV0KS5qb2luKFwiXFxuXCIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1ldC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbm9uLmV4cGVjdGF0aW9uLnBhc3MobWVzc2FnZXMuY29uY2F0KG1ldCkuam9pbihcIlxcblwiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBpbnZva2VNZXRob2Q6IGZ1bmN0aW9uIGludm9rZU1ldGhvZChtZXRob2QsIHRoaXNWYWx1ZSwgYXJncykge1xuICAgICAgICAgICAgICAgIHZhciBleHBlY3RhdGlvbnMgPSB0aGlzLmV4cGVjdGF0aW9ucyAmJiB0aGlzLmV4cGVjdGF0aW9uc1ttZXRob2RdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBleHBlY3RhdGlvbnMgJiYgZXhwZWN0YXRpb25zLmxlbmd0aCB8fCAwLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZXhwZWN0YXRpb25zW2ldLm1ldCgpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBleHBlY3RhdGlvbnNbaV0uYWxsb3dzQ2FsbCh0aGlzVmFsdWUsIGFyZ3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXhwZWN0YXRpb25zW2ldLmFwcGx5KHRoaXNWYWx1ZSwgYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbWVzc2FnZXMgPSBbXSwgYXZhaWxhYmxlLCBleGhhdXN0ZWQgPSAwO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleHBlY3RhdGlvbnNbaV0uYWxsb3dzQ2FsbCh0aGlzVmFsdWUsIGFyZ3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhdmFpbGFibGUgPSBhdmFpbGFibGUgfHwgZXhwZWN0YXRpb25zW2ldO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhoYXVzdGVkICs9IDE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcHVzaC5jYWxsKG1lc3NhZ2VzLCBcIiAgICBcIiArIGV4cGVjdGF0aW9uc1tpXS50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoZXhoYXVzdGVkID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhdmFpbGFibGUuYXBwbHkodGhpc1ZhbHVlLCBhcmdzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBtZXNzYWdlcy51bnNoaWZ0KFwiVW5leHBlY3RlZCBjYWxsOiBcIiArIHNpbm9uLnNweUNhbGwudG9TdHJpbmcuY2FsbCh7XG4gICAgICAgICAgICAgICAgICAgIHByb3h5OiBtZXRob2QsXG4gICAgICAgICAgICAgICAgICAgIGFyZ3M6IGFyZ3NcbiAgICAgICAgICAgICAgICB9KSk7XG5cbiAgICAgICAgICAgICAgICBzaW5vbi5leHBlY3RhdGlvbi5mYWlsKG1lc3NhZ2VzLmpvaW4oXCJcXG5cIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgdGltZXMgPSBzaW5vbi50aW1lc0luV29yZHM7XG4gICAgICAgIHZhciBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcblxuICAgICAgICBmdW5jdGlvbiBjYWxsQ291bnRJbldvcmRzKGNhbGxDb3VudCkge1xuICAgICAgICAgICAgaWYgKGNhbGxDb3VudCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwibmV2ZXIgY2FsbGVkXCI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBcImNhbGxlZCBcIiArIHRpbWVzKGNhbGxDb3VudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBleHBlY3RlZENhbGxDb3VudEluV29yZHMoZXhwZWN0YXRpb24pIHtcbiAgICAgICAgICAgIHZhciBtaW4gPSBleHBlY3RhdGlvbi5taW5DYWxscztcbiAgICAgICAgICAgIHZhciBtYXggPSBleHBlY3RhdGlvbi5tYXhDYWxscztcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBtaW4gPT0gXCJudW1iZXJcIiAmJiB0eXBlb2YgbWF4ID09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICB2YXIgc3RyID0gdGltZXMobWluKTtcblxuICAgICAgICAgICAgICAgIGlmIChtaW4gIT0gbWF4KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ciA9IFwiYXQgbGVhc3QgXCIgKyBzdHIgKyBcIiBhbmQgYXQgbW9zdCBcIiArIHRpbWVzKG1heCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBtaW4gPT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgIHJldHVybiBcImF0IGxlYXN0IFwiICsgdGltZXMobWluKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIFwiYXQgbW9zdCBcIiArIHRpbWVzKG1heCk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiByZWNlaXZlZE1pbkNhbGxzKGV4cGVjdGF0aW9uKSB7XG4gICAgICAgICAgICB2YXIgaGFzTWluTGltaXQgPSB0eXBlb2YgZXhwZWN0YXRpb24ubWluQ2FsbHMgPT0gXCJudW1iZXJcIjtcbiAgICAgICAgICAgIHJldHVybiAhaGFzTWluTGltaXQgfHwgZXhwZWN0YXRpb24uY2FsbENvdW50ID49IGV4cGVjdGF0aW9uLm1pbkNhbGxzO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcmVjZWl2ZWRNYXhDYWxscyhleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBleHBlY3RhdGlvbi5tYXhDYWxscyAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZXhwZWN0YXRpb24uY2FsbENvdW50ID09IGV4cGVjdGF0aW9uLm1heENhbGxzO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gdmVyaWZ5TWF0Y2hlcihwb3NzaWJsZU1hdGNoZXIsIGFyZykge1xuICAgICAgICAgICAgaWYgKG1hdGNoICYmIG1hdGNoLmlzTWF0Y2hlcihwb3NzaWJsZU1hdGNoZXIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvc3NpYmxlTWF0Y2hlci50ZXN0KGFyZyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2lub24uZXhwZWN0YXRpb24gPSB7XG4gICAgICAgICAgICBtaW5DYWxsczogMSxcbiAgICAgICAgICAgIG1heENhbGxzOiAxLFxuXG4gICAgICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShtZXRob2ROYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGV4cGVjdGF0aW9uID0gc2lub24uZXh0ZW5kKHNpbm9uLnN0dWIuY3JlYXRlKCksIHNpbm9uLmV4cGVjdGF0aW9uKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgZXhwZWN0YXRpb24uY3JlYXRlO1xuICAgICAgICAgICAgICAgIGV4cGVjdGF0aW9uLm1ldGhvZCA9IG1ldGhvZE5hbWU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXhwZWN0YXRpb247XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBpbnZva2U6IGZ1bmN0aW9uIGludm9rZShmdW5jLCB0aGlzVmFsdWUsIGFyZ3MpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZlcmlmeUNhbGxBbGxvd2VkKHRoaXNWYWx1ZSwgYXJncyk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2lub24uc3B5Lmludm9rZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgYXRMZWFzdDogZnVuY3Rpb24gYXRMZWFzdChudW0pIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG51bSAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInXCIgKyBudW0gKyBcIicgaXMgbm90IG51bWJlclwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMubGltaXRzU2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWF4Q2FsbHMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxpbWl0c1NldCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5taW5DYWxscyA9IG51bTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgYXRNb3N0OiBmdW5jdGlvbiBhdE1vc3QobnVtKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBudW0gIT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiJ1wiICsgbnVtICsgXCInIGlzIG5vdCBudW1iZXJcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmxpbWl0c1NldCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1pbkNhbGxzID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5saW1pdHNTZXQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMubWF4Q2FsbHMgPSBudW07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG5ldmVyOiBmdW5jdGlvbiBuZXZlcigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5leGFjdGx5KDApO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb25jZTogZnVuY3Rpb24gb25jZSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5leGFjdGx5KDEpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgdHdpY2U6IGZ1bmN0aW9uIHR3aWNlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmV4YWN0bHkoMik7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB0aHJpY2U6IGZ1bmN0aW9uIHRocmljZSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5leGFjdGx5KDMpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZXhhY3RseTogZnVuY3Rpb24gZXhhY3RseShudW0pIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG51bSAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInXCIgKyBudW0gKyBcIicgaXMgbm90IGEgbnVtYmVyXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuYXRMZWFzdChudW0pO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmF0TW9zdChudW0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgbWV0OiBmdW5jdGlvbiBtZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICF0aGlzLmZhaWxlZCAmJiByZWNlaXZlZE1pbkNhbGxzKHRoaXMpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgdmVyaWZ5Q2FsbEFsbG93ZWQ6IGZ1bmN0aW9uIHZlcmlmeUNhbGxBbGxvd2VkKHRoaXNWYWx1ZSwgYXJncykge1xuICAgICAgICAgICAgICAgIGlmIChyZWNlaXZlZE1heENhbGxzKHRoaXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbCh0aGlzLm1ldGhvZCArIFwiIGFscmVhZHkgY2FsbGVkIFwiICsgdGltZXModGhpcy5tYXhDYWxscykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChcImV4cGVjdGVkVGhpc1wiIGluIHRoaXMgJiYgdGhpcy5leHBlY3RlZFRoaXMgIT09IHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBzaW5vbi5leHBlY3RhdGlvbi5mYWlsKHRoaXMubWV0aG9kICsgXCIgY2FsbGVkIHdpdGggXCIgKyB0aGlzVmFsdWUgKyBcIiBhcyB0aGlzVmFsdWUsIGV4cGVjdGVkIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZXhwZWN0ZWRUaGlzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShcImV4cGVjdGVkQXJndW1lbnRzXCIgaW4gdGhpcykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghYXJncykge1xuICAgICAgICAgICAgICAgICAgICBzaW5vbi5leHBlY3RhdGlvbi5mYWlsKHRoaXMubWV0aG9kICsgXCIgcmVjZWl2ZWQgbm8gYXJndW1lbnRzLCBleHBlY3RlZCBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBzaW5vbi5mb3JtYXQodGhpcy5leHBlY3RlZEFyZ3VtZW50cykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcmdzLmxlbmd0aCA8IHRoaXMuZXhwZWN0ZWRBcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbm9uLmV4cGVjdGF0aW9uLmZhaWwodGhpcy5tZXRob2QgKyBcIiByZWNlaXZlZCB0b28gZmV3IGFyZ3VtZW50cyAoXCIgKyBzaW5vbi5mb3JtYXQoYXJncykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgXCIpLCBleHBlY3RlZCBcIiArIHNpbm9uLmZvcm1hdCh0aGlzLmV4cGVjdGVkQXJndW1lbnRzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZXhwZWN0c0V4YWN0QXJnQ291bnQgJiZcbiAgICAgICAgICAgICAgICAgICAgYXJncy5sZW5ndGggIT0gdGhpcy5leHBlY3RlZEFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbCh0aGlzLm1ldGhvZCArIFwiIHJlY2VpdmVkIHRvbyBtYW55IGFyZ3VtZW50cyAoXCIgKyBzaW5vbi5mb3JtYXQoYXJncykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgXCIpLCBleHBlY3RlZCBcIiArIHNpbm9uLmZvcm1hdCh0aGlzLmV4cGVjdGVkQXJndW1lbnRzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSB0aGlzLmV4cGVjdGVkQXJndW1lbnRzLmxlbmd0aDsgaSA8IGw7IGkgKz0gMSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdmVyaWZ5TWF0Y2hlcih0aGlzLmV4cGVjdGVkQXJndW1lbnRzW2ldLCBhcmdzW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbCh0aGlzLm1ldGhvZCArIFwiIHJlY2VpdmVkIHdyb25nIGFyZ3VtZW50cyBcIiArIHNpbm9uLmZvcm1hdChhcmdzKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCIsIGRpZG4ndCBtYXRjaCBcIiArIHRoaXMuZXhwZWN0ZWRBcmd1bWVudHMudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbm9uLmRlZXBFcXVhbCh0aGlzLmV4cGVjdGVkQXJndW1lbnRzW2ldLCBhcmdzW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbCh0aGlzLm1ldGhvZCArIFwiIHJlY2VpdmVkIHdyb25nIGFyZ3VtZW50cyBcIiArIHNpbm9uLmZvcm1hdChhcmdzKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCIsIGV4cGVjdGVkIFwiICsgc2lub24uZm9ybWF0KHRoaXMuZXhwZWN0ZWRBcmd1bWVudHMpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGFsbG93c0NhbGw6IGZ1bmN0aW9uIGFsbG93c0NhbGwodGhpc1ZhbHVlLCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWV0KCkgJiYgcmVjZWl2ZWRNYXhDYWxscyh0aGlzKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKFwiZXhwZWN0ZWRUaGlzXCIgaW4gdGhpcyAmJiB0aGlzLmV4cGVjdGVkVGhpcyAhPT0gdGhpc1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShcImV4cGVjdGVkQXJndW1lbnRzXCIgaW4gdGhpcykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgYXJncyA9IGFyZ3MgfHwgW107XG5cbiAgICAgICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPCB0aGlzLmV4cGVjdGVkQXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZXhwZWN0c0V4YWN0QXJnQ291bnQgJiZcbiAgICAgICAgICAgICAgICAgICAgYXJncy5sZW5ndGggIT0gdGhpcy5leHBlY3RlZEFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gdGhpcy5leHBlY3RlZEFyZ3VtZW50cy5sZW5ndGg7IGkgPCBsOyBpICs9IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF2ZXJpZnlNYXRjaGVyKHRoaXMuZXhwZWN0ZWRBcmd1bWVudHNbaV0sIGFyZ3NbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbm9uLmRlZXBFcXVhbCh0aGlzLmV4cGVjdGVkQXJndW1lbnRzW2ldLCBhcmdzW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB3aXRoQXJnczogZnVuY3Rpb24gd2l0aEFyZ3MoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5leHBlY3RlZEFyZ3VtZW50cyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHdpdGhFeGFjdEFyZ3M6IGZ1bmN0aW9uIHdpdGhFeGFjdEFyZ3MoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53aXRoQXJncy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIHRoaXMuZXhwZWN0c0V4YWN0QXJnQ291bnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb246IGZ1bmN0aW9uIG9uKHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZXhwZWN0ZWRUaGlzID0gdGhpc1ZhbHVlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXJncyA9ICh0aGlzLmV4cGVjdGVkQXJndW1lbnRzIHx8IFtdKS5zbGljZSgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmV4cGVjdHNFeGFjdEFyZ0NvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbChhcmdzLCBcIlsuLi5dXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjYWxsU3RyID0gc2lub24uc3B5Q2FsbC50b1N0cmluZy5jYWxsKHtcbiAgICAgICAgICAgICAgICAgICAgcHJveHk6IHRoaXMubWV0aG9kIHx8IFwiYW5vbnltb3VzIG1vY2sgZXhwZWN0YXRpb25cIixcbiAgICAgICAgICAgICAgICAgICAgYXJnczogYXJnc1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBjYWxsU3RyLnJlcGxhY2UoXCIsIFsuLi5cIiwgXCJbLCAuLi5cIikgKyBcIiBcIiArXG4gICAgICAgICAgICAgICAgICAgIGV4cGVjdGVkQ2FsbENvdW50SW5Xb3Jkcyh0aGlzKTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm1ldCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkV4cGVjdGF0aW9uIG1ldDogXCIgKyBtZXNzYWdlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBcIkV4cGVjdGVkIFwiICsgbWVzc2FnZSArIFwiIChcIiArXG4gICAgICAgICAgICAgICAgICAgIGNhbGxDb3VudEluV29yZHModGhpcy5jYWxsQ291bnQpICsgXCIpXCI7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB2ZXJpZnk6IGZ1bmN0aW9uIHZlcmlmeSgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMubWV0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbCh0aGlzLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbm9uLmV4cGVjdGF0aW9uLnBhc3ModGhpcy50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHBhc3M6IGZ1bmN0aW9uIHBhc3MobWVzc2FnZSkge1xuICAgICAgICAgICAgICAgIHNpbm9uLmFzc2VydC5wYXNzKG1lc3NhZ2UpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZmFpbDogZnVuY3Rpb24gZmFpbChtZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGV4Y2VwdGlvbiA9IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgICAgICAgICAgICAgICBleGNlcHRpb24ubmFtZSA9IFwiRXhwZWN0YXRpb25FcnJvclwiO1xuXG4gICAgICAgICAgICAgICAgdGhyb3cgZXhjZXB0aW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLm1vY2sgPSBtb2NrO1xuICAgICAgICByZXR1cm4gbW9jaztcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3RpbWVzX2luX3dvcmRzXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9jYWxsXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9leHRlbmRcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL21hdGNoXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9zcHlcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3N0dWJcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2Zvcm1hdFwiKTtcblxuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG1ha2VBcGkoc2lub24pO1xuICAgIH1cblxuICAgIGlmIChpc0FNRCkge1xuICAgICAgICBkZWZpbmUobG9hZERlcGVuZGVuY2llcyk7XG4gICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBtb2R1bGUuZXhwb3J0cywgbW9kdWxlKTtcbiAgICB9IGVsc2UgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufSh0eXBlb2Ygc2lub24gPT0gXCJvYmplY3RcIiAmJiBzaW5vbiB8fCBudWxsKSk7XG4iLCIvKipcbiAqIEBkZXBlbmQgdXRpbC9jb3JlLmpzXG4gKiBAZGVwZW5kIGV4dGVuZC5qc1xuICogQGRlcGVuZCBjb2xsZWN0aW9uLmpzXG4gKiBAZGVwZW5kIHV0aWwvZmFrZV90aW1lcnMuanNcbiAqIEBkZXBlbmQgdXRpbC9mYWtlX3NlcnZlcl93aXRoX2Nsb2NrLmpzXG4gKi9cbi8qKlxuICogTWFuYWdlcyBmYWtlIGNvbGxlY3Rpb25zIGFzIHdlbGwgYXMgZmFrZSB1dGlsaXRpZXMgc3VjaCBhcyBTaW5vbidzXG4gKiB0aW1lcnMgYW5kIGZha2UgWEhSIGltcGxlbWVudGF0aW9uIGluIG9uZSBjb252ZW5pZW50IG9iamVjdC5cbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBtYWtlQXBpKHNpbm9uKSB7XG4gICAgICAgIHZhciBwdXNoID0gW10ucHVzaDtcblxuICAgICAgICBmdW5jdGlvbiBleHBvc2VWYWx1ZShzYW5kYm94LCBjb25maWcsIGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgIGlmICghdmFsdWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcuaW5qZWN0SW50byAmJiAhKGtleSBpbiBjb25maWcuaW5qZWN0SW50bykpIHtcbiAgICAgICAgICAgICAgICBjb25maWcuaW5qZWN0SW50b1trZXldID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgc2FuZGJveC5pbmplY3RlZEtleXMucHVzaChrZXkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwoc2FuZGJveC5hcmdzLCB2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBwcmVwYXJlU2FuZGJveEZyb21Db25maWcoY29uZmlnKSB7XG4gICAgICAgICAgICB2YXIgc2FuZGJveCA9IHNpbm9uLmNyZWF0ZShzaW5vbi5zYW5kYm94KTtcblxuICAgICAgICAgICAgaWYgKGNvbmZpZy51c2VGYWtlU2VydmVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcudXNlRmFrZVNlcnZlciA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHNhbmRib3guc2VydmVyUHJvdG90eXBlID0gY29uZmlnLnVzZUZha2VTZXJ2ZXI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgc2FuZGJveC51c2VGYWtlU2VydmVyKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcudXNlRmFrZVRpbWVycykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY29uZmlnLnVzZUZha2VUaW1lcnMgPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICBzYW5kYm94LnVzZUZha2VUaW1lcnMuYXBwbHkoc2FuZGJveCwgY29uZmlnLnVzZUZha2VUaW1lcnMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNhbmRib3gudXNlRmFrZVRpbWVycygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgICAgIH1cblxuICAgICAgICBzaW5vbi5zYW5kYm94ID0gc2lub24uZXh0ZW5kKHNpbm9uLmNyZWF0ZShzaW5vbi5jb2xsZWN0aW9uKSwge1xuICAgICAgICAgICAgdXNlRmFrZVRpbWVyczogZnVuY3Rpb24gdXNlRmFrZVRpbWVycygpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsb2NrID0gc2lub24udXNlRmFrZVRpbWVycy5hcHBseShzaW5vbiwgYXJndW1lbnRzKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFkZCh0aGlzLmNsb2NrKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHNlcnZlclByb3RvdHlwZTogc2lub24uZmFrZVNlcnZlcixcblxuICAgICAgICAgICAgdXNlRmFrZVNlcnZlcjogZnVuY3Rpb24gdXNlRmFrZVNlcnZlcigpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJvdG8gPSB0aGlzLnNlcnZlclByb3RvdHlwZSB8fCBzaW5vbi5mYWtlU2VydmVyO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFwcm90byB8fCAhcHJvdG8uY3JlYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuc2VydmVyID0gcHJvdG8uY3JlYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRkKHRoaXMuc2VydmVyKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGluamVjdDogZnVuY3Rpb24gKG9iaikge1xuICAgICAgICAgICAgICAgIHNpbm9uLmNvbGxlY3Rpb24uaW5qZWN0LmNhbGwodGhpcywgb2JqKTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNsb2NrKSB7XG4gICAgICAgICAgICAgICAgICAgIG9iai5jbG9jayA9IHRoaXMuY2xvY2s7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2VydmVyKSB7XG4gICAgICAgICAgICAgICAgICAgIG9iai5zZXJ2ZXIgPSB0aGlzLnNlcnZlcjtcbiAgICAgICAgICAgICAgICAgICAgb2JqLnJlcXVlc3RzID0gdGhpcy5zZXJ2ZXIucmVxdWVzdHM7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgb2JqLm1hdGNoID0gc2lub24ubWF0Y2g7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgcmVzdG9yZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNpbm9uLmNvbGxlY3Rpb24ucmVzdG9yZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVzdG9yZUNvbnRleHQoKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlc3RvcmVDb250ZXh0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5qZWN0ZWRLZXlzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBqID0gdGhpcy5pbmplY3RlZEtleXMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5pbmplY3RJbnRvW3RoaXMuaW5qZWN0ZWRLZXlzW2ldXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLmluamVjdGVkS2V5cyA9IFtdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGNyZWF0ZTogZnVuY3Rpb24gKGNvbmZpZykge1xuICAgICAgICAgICAgICAgIGlmICghY29uZmlnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzaW5vbi5jcmVhdGUoc2lub24uc2FuZGJveCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNhbmRib3ggPSBwcmVwYXJlU2FuZGJveEZyb21Db25maWcoY29uZmlnKTtcbiAgICAgICAgICAgICAgICBzYW5kYm94LmFyZ3MgPSBzYW5kYm94LmFyZ3MgfHwgW107XG4gICAgICAgICAgICAgICAgc2FuZGJveC5pbmplY3RlZEtleXMgPSBbXTtcbiAgICAgICAgICAgICAgICBzYW5kYm94LmluamVjdEludG8gPSBjb25maWcuaW5qZWN0SW50bztcbiAgICAgICAgICAgICAgICB2YXIgcHJvcCwgdmFsdWUsIGV4cG9zZWQgPSBzYW5kYm94LmluamVjdCh7fSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY29uZmlnLnByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBjb25maWcucHJvcGVydGllcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3AgPSBjb25maWcucHJvcGVydGllc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gZXhwb3NlZFtwcm9wXSB8fCBwcm9wID09IFwic2FuZGJveFwiICYmIHNhbmRib3g7XG4gICAgICAgICAgICAgICAgICAgICAgICBleHBvc2VWYWx1ZShzYW5kYm94LCBjb25maWcsIHByb3AsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9zZVZhbHVlKHNhbmRib3gsIGNvbmZpZywgXCJzYW5kYm94XCIsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG1hdGNoOiBzaW5vbi5tYXRjaFxuICAgICAgICB9KTtcblxuICAgICAgICBzaW5vbi5zYW5kYm94LnVzZUZha2VYTUxIdHRwUmVxdWVzdCA9IHNpbm9uLnNhbmRib3gudXNlRmFrZVNlcnZlcjtcblxuICAgICAgICByZXR1cm4gc2lub24uc2FuZGJveDtcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2V4dGVuZFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vdXRpbC9mYWtlX3NlcnZlcl93aXRoX2Nsb2NrXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi91dGlsL2Zha2VfdGltZXJzXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9jb2xsZWN0aW9uXCIpO1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG1ha2VBcGkoc2lub24pO1xuICAgIH1cblxuICAgIGlmIChpc0FNRCkge1xuICAgICAgICBkZWZpbmUobG9hZERlcGVuZGVuY2llcyk7XG4gICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBtb2R1bGUuZXhwb3J0cywgbW9kdWxlKTtcbiAgICB9IGVsc2UgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufSgpKTtcbiIsIi8qKlxuICAqIEBkZXBlbmQgdGltZXNfaW5fd29yZHMuanNcbiAgKiBAZGVwZW5kIHV0aWwvY29yZS5qc1xuICAqIEBkZXBlbmQgZXh0ZW5kLmpzXG4gICogQGRlcGVuZCBjYWxsLmpzXG4gICogQGRlcGVuZCBmb3JtYXQuanNcbiAgKi9cbi8qKlxuICAqIFNweSBmdW5jdGlvbnNcbiAgKlxuICAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICAqIEBsaWNlbnNlIEJTRFxuICAqXG4gICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuXG4gICAgZnVuY3Rpb24gbWFrZUFwaShzaW5vbikge1xuICAgICAgICB2YXIgcHVzaCA9IEFycmF5LnByb3RvdHlwZS5wdXNoO1xuICAgICAgICB2YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG4gICAgICAgIHZhciBjYWxsSWQgPSAwO1xuXG4gICAgICAgIGZ1bmN0aW9uIHNweShvYmplY3QsIHByb3BlcnR5LCB0eXBlcykge1xuICAgICAgICAgICAgaWYgKCFwcm9wZXJ0eSAmJiB0eXBlb2Ygb2JqZWN0ID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIHJldHVybiBzcHkuY3JlYXRlKG9iamVjdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghb2JqZWN0ICYmICFwcm9wZXJ0eSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzcHkuY3JlYXRlKGZ1bmN0aW9uICgpIHsgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlcykge1xuICAgICAgICAgICAgICAgIHZhciBtZXRob2REZXNjID0gc2lub24uZ2V0UHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHlwZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kRGVzY1t0eXBlc1tpXV0gPSBzcHkuY3JlYXRlKG1ldGhvZERlc2NbdHlwZXNbaV1dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNpbm9uLndyYXBNZXRob2Qob2JqZWN0LCBwcm9wZXJ0eSwgbWV0aG9kRGVzYyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBtZXRob2QgPSBvYmplY3RbcHJvcGVydHldO1xuICAgICAgICAgICAgICAgIHJldHVybiBzaW5vbi53cmFwTWV0aG9kKG9iamVjdCwgcHJvcGVydHksIHNweS5jcmVhdGUobWV0aG9kKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBtYXRjaGluZ0Zha2UoZmFrZXMsIGFyZ3MsIHN0cmljdCkge1xuICAgICAgICAgICAgaWYgKCFmYWtlcykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBmYWtlcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoZmFrZXNbaV0ubWF0Y2hlcyhhcmdzLCBzdHJpY3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWtlc1tpXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBpbmNyZW1lbnRDYWxsQ291bnQoKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGxlZCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmNhbGxDb3VudCArPSAxO1xuICAgICAgICAgICAgdGhpcy5ub3RDYWxsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuY2FsbGVkT25jZSA9IHRoaXMuY2FsbENvdW50ID09IDE7XG4gICAgICAgICAgICB0aGlzLmNhbGxlZFR3aWNlID0gdGhpcy5jYWxsQ291bnQgPT0gMjtcbiAgICAgICAgICAgIHRoaXMuY2FsbGVkVGhyaWNlID0gdGhpcy5jYWxsQ291bnQgPT0gMztcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUNhbGxQcm9wZXJ0aWVzKCkge1xuICAgICAgICAgICAgdGhpcy5maXJzdENhbGwgPSB0aGlzLmdldENhbGwoMCk7XG4gICAgICAgICAgICB0aGlzLnNlY29uZENhbGwgPSB0aGlzLmdldENhbGwoMSk7XG4gICAgICAgICAgICB0aGlzLnRoaXJkQ2FsbCA9IHRoaXMuZ2V0Q2FsbCgyKTtcbiAgICAgICAgICAgIHRoaXMubGFzdENhbGwgPSB0aGlzLmdldENhbGwodGhpcy5jYWxsQ291bnQgLSAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB2YXJzID0gXCJhLGIsYyxkLGUsZixnLGgsaSxqLGssbFwiO1xuICAgICAgICBmdW5jdGlvbiBjcmVhdGVQcm94eShmdW5jLCBwcm94eUxlbmd0aCkge1xuICAgICAgICAgICAgLy8gUmV0YWluIHRoZSBmdW5jdGlvbiBsZW5ndGg6XG4gICAgICAgICAgICB2YXIgcDtcbiAgICAgICAgICAgIGlmIChwcm94eUxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGV2YWwoXCJwID0gKGZ1bmN0aW9uIHByb3h5KFwiICsgdmFycy5zdWJzdHJpbmcoMCwgcHJveHlMZW5ndGggKiAyIC0gMSkgK1xuICAgICAgICAgICAgICAgICAgICBcIikgeyByZXR1cm4gcC5pbnZva2UoZnVuYywgdGhpcywgc2xpY2UuY2FsbChhcmd1bWVudHMpKTsgfSk7XCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwID0gZnVuY3Rpb24gcHJveHkoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwLmludm9rZShmdW5jLCB0aGlzLCBzbGljZS5jYWxsKGFyZ3VtZW50cykpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB1dWlkID0gMDtcblxuICAgICAgICAvLyBQdWJsaWMgQVBJXG4gICAgICAgIHZhciBzcHlBcGkgPSB7XG4gICAgICAgICAgICByZXNldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmludm9raW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoXCJDYW5ub3QgcmVzZXQgU2lub24gZnVuY3Rpb24gd2hpbGUgaW52b2tpbmcgaXQuIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIk1vdmUgdGhlIGNhbGwgdG8gLnJlc2V0IG91dHNpZGUgb2YgdGhlIGNhbGxiYWNrLlwiKTtcbiAgICAgICAgICAgICAgICAgICAgZXJyLm5hbWUgPSBcIkludmFsaWRSZXNldEV4Y2VwdGlvblwiO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLm5vdENhbGxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsZWRPbmNlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsZWRUd2ljZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGVkVGhyaWNlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsQ291bnQgPSAwO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RDYWxsID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLnNlY29uZENhbGwgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMudGhpcmRDYWxsID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RDYWxsID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLmFyZ3MgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLnJldHVyblZhbHVlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMudGhpc1ZhbHVlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMuZXhjZXB0aW9ucyA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbElkcyA9IFtdO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmZha2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5mYWtlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mYWtlc1tpXS5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShmdW5jLCBzcHlMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmFtZTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuYyA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuYW1lID0gc2lub24uZnVuY3Rpb25OYW1lKGZ1bmMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghc3B5TGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNweUxlbmd0aCA9IGZ1bmMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwcm94eSA9IGNyZWF0ZVByb3h5KGZ1bmMsIHNweUxlbmd0aCk7XG5cbiAgICAgICAgICAgICAgICBzaW5vbi5leHRlbmQocHJveHksIHNweSk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHByb3h5LmNyZWF0ZTtcbiAgICAgICAgICAgICAgICBzaW5vbi5leHRlbmQocHJveHksIGZ1bmMpO1xuXG4gICAgICAgICAgICAgICAgcHJveHkucmVzZXQoKTtcbiAgICAgICAgICAgICAgICBwcm94eS5wcm90b3R5cGUgPSBmdW5jLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICBwcm94eS5kaXNwbGF5TmFtZSA9IG5hbWUgfHwgXCJzcHlcIjtcbiAgICAgICAgICAgICAgICBwcm94eS50b1N0cmluZyA9IHNpbm9uLmZ1bmN0aW9uVG9TdHJpbmc7XG4gICAgICAgICAgICAgICAgcHJveHkuaW5zdGFudGlhdGVGYWtlID0gc2lub24uc3B5LmNyZWF0ZTtcbiAgICAgICAgICAgICAgICBwcm94eS5pZCA9IFwic3B5I1wiICsgdXVpZCsrO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3h5O1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgaW52b2tlOiBmdW5jdGlvbiBpbnZva2UoZnVuYywgdGhpc1ZhbHVlLCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hdGNoaW5nID0gbWF0Y2hpbmdGYWtlKHRoaXMuZmFrZXMsIGFyZ3MpO1xuICAgICAgICAgICAgICAgIHZhciBleGNlcHRpb24sIHJldHVyblZhbHVlO1xuXG4gICAgICAgICAgICAgICAgaW5jcmVtZW50Q2FsbENvdW50LmNhbGwodGhpcyk7XG4gICAgICAgICAgICAgICAgcHVzaC5jYWxsKHRoaXMudGhpc1ZhbHVlcywgdGhpc1ZhbHVlKTtcbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwodGhpcy5hcmdzLCBhcmdzKTtcbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwodGhpcy5jYWxsSWRzLCBjYWxsSWQrKyk7XG5cbiAgICAgICAgICAgICAgICAvLyBNYWtlIGNhbGwgcHJvcGVydGllcyBhdmFpbGFibGUgZnJvbSB3aXRoaW4gdGhlIHNwaWVkIGZ1bmN0aW9uOlxuICAgICAgICAgICAgICAgIGNyZWF0ZUNhbGxQcm9wZXJ0aWVzLmNhbGwodGhpcyk7XG5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmludm9raW5nID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2hpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVyblZhbHVlID0gbWF0Y2hpbmcuaW52b2tlKGZ1bmMsIHRoaXNWYWx1ZSwgYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm5WYWx1ZSA9ICh0aGlzLmZ1bmMgfHwgZnVuYykuYXBwbHkodGhpc1ZhbHVlLCBhcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB0aGlzQ2FsbCA9IHRoaXMuZ2V0Q2FsbCh0aGlzLmNhbGxDb3VudCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpc0NhbGwuY2FsbGVkV2l0aE5ldygpICYmIHR5cGVvZiByZXR1cm5WYWx1ZSAhPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGV4Y2VwdGlvbiA9IGU7XG4gICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuaW52b2tpbmc7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHVzaC5jYWxsKHRoaXMuZXhjZXB0aW9ucywgZXhjZXB0aW9uKTtcbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwodGhpcy5yZXR1cm5WYWx1ZXMsIHJldHVyblZhbHVlKTtcblxuICAgICAgICAgICAgICAgIC8vIE1ha2UgcmV0dXJuIHZhbHVlIGFuZCBleGNlcHRpb24gYXZhaWxhYmxlIGluIHRoZSBjYWxsczpcbiAgICAgICAgICAgICAgICBjcmVhdGVDYWxsUHJvcGVydGllcy5jYWxsKHRoaXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGV4Y2VwdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IGV4Y2VwdGlvbjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBuYW1lZDogZnVuY3Rpb24gbmFtZWQobmFtZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGlzcGxheU5hbWUgPSBuYW1lO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZ2V0Q2FsbDogZnVuY3Rpb24gZ2V0Q2FsbChpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgPCAwIHx8IGkgPj0gdGhpcy5jYWxsQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNpbm9uLnNweUNhbGwodGhpcywgdGhpcy50aGlzVmFsdWVzW2ldLCB0aGlzLmFyZ3NbaV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXR1cm5WYWx1ZXNbaV0sIHRoaXMuZXhjZXB0aW9uc1tpXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGxJZHNbaV0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZ2V0Q2FsbHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2FsbHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNhbGxDb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxzLnB1c2godGhpcy5nZXRDYWxsKGkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gY2FsbHM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsZWRCZWZvcmU6IGZ1bmN0aW9uIGNhbGxlZEJlZm9yZShzcHlGbikge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5jYWxsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghc3B5Rm4uY2FsbGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNhbGxJZHNbMF0gPCBzcHlGbi5jYWxsSWRzW3NweUZuLmNhbGxJZHMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsZWRBZnRlcjogZnVuY3Rpb24gY2FsbGVkQWZ0ZXIoc3B5Rm4pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY2FsbGVkIHx8ICFzcHlGbi5jYWxsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNhbGxJZHNbdGhpcy5jYWxsQ291bnQgLSAxXSA+IHNweUZuLmNhbGxJZHNbc3B5Rm4uY2FsbENvdW50IC0gMV07XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB3aXRoQXJnczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZmFrZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1hdGNoID0gbWF0Y2hpbmdGYWtlKHRoaXMuZmFrZXMsIGFyZ3MsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mYWtlcyA9IFtdO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBvcmlnaW5hbCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgdmFyIGZha2UgPSB0aGlzLmluc3RhbnRpYXRlRmFrZSgpO1xuICAgICAgICAgICAgICAgIGZha2UubWF0Y2hpbmdBZ3VtZW50cyA9IGFyZ3M7XG4gICAgICAgICAgICAgICAgZmFrZS5wYXJlbnQgPSB0aGlzO1xuICAgICAgICAgICAgICAgIHB1c2guY2FsbCh0aGlzLmZha2VzLCBmYWtlKTtcblxuICAgICAgICAgICAgICAgIGZha2Uud2l0aEFyZ3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbC53aXRoQXJncy5hcHBseShvcmlnaW5hbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZha2UubWF0Y2hlcyh0aGlzLmFyZ3NbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmNyZW1lbnRDYWxsQ291bnQuY2FsbChmYWtlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbChmYWtlLnRoaXNWYWx1ZXMsIHRoaXMudGhpc1ZhbHVlc1tpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdXNoLmNhbGwoZmFrZS5hcmdzLCB0aGlzLmFyZ3NbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVzaC5jYWxsKGZha2UucmV0dXJuVmFsdWVzLCB0aGlzLnJldHVyblZhbHVlc1tpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdXNoLmNhbGwoZmFrZS5leGNlcHRpb25zLCB0aGlzLmV4Y2VwdGlvbnNbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVzaC5jYWxsKGZha2UuY2FsbElkcywgdGhpcy5jYWxsSWRzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjcmVhdGVDYWxsUHJvcGVydGllcy5jYWxsKGZha2UpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZha2U7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBtYXRjaGVzOiBmdW5jdGlvbiAoYXJncywgc3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hcmdzID0gdGhpcy5tYXRjaGluZ0FndW1lbnRzO1xuXG4gICAgICAgICAgICAgICAgaWYgKG1hcmdzLmxlbmd0aCA8PSBhcmdzLmxlbmd0aCAmJlxuICAgICAgICAgICAgICAgICAgICBzaW5vbi5kZWVwRXF1YWwobWFyZ3MsIGFyZ3Muc2xpY2UoMCwgbWFyZ3MubGVuZ3RoKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICFzdHJpY3QgfHwgbWFyZ3MubGVuZ3RoID09IGFyZ3MubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHByaW50ZjogZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICAgICAgICAgIHZhciBzcHkgPSB0aGlzO1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgICAgIHZhciBmb3JtYXR0ZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gKGZvcm1hdCB8fCBcIlwiKS5yZXBsYWNlKC8lKC4pL2csIGZ1bmN0aW9uIChtYXRjaCwgc3BlY2lmeWVyKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcm1hdHRlciA9IHNweUFwaS5mb3JtYXR0ZXJzW3NwZWNpZnllcl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBmb3JtYXR0ZXIgPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZm9ybWF0dGVyLmNhbGwobnVsbCwgc3B5LCBhcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNOYU4ocGFyc2VJbnQoc3BlY2lmeWVyLCAxMCkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2lub24uZm9ybWF0KGFyZ3Nbc3BlY2lmeWVyIC0gMV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiJVwiICsgc3BlY2lmeWVyO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGZ1bmN0aW9uIGRlbGVnYXRlVG9DYWxscyhtZXRob2QsIG1hdGNoQW55LCBhY3R1YWwsIG5vdENhbGxlZCkge1xuICAgICAgICAgICAgc3B5QXBpW21ldGhvZF0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNhbGxlZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobm90Q2FsbGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbm90Q2FsbGVkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50Q2FsbDtcbiAgICAgICAgICAgICAgICB2YXIgbWF0Y2hlcyA9IDA7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRoaXMuY2FsbENvdW50OyBpIDwgbDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRDYWxsID0gdGhpcy5nZXRDYWxsKGkpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50Q2FsbFthY3R1YWwgfHwgbWV0aG9kXS5hcHBseShjdXJyZW50Q2FsbCwgYXJndW1lbnRzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2hBbnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBtYXRjaGVzID09PSB0aGlzLmNhbGxDb3VudDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBkZWxlZ2F0ZVRvQ2FsbHMoXCJjYWxsZWRPblwiLCB0cnVlKTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwiYWx3YXlzQ2FsbGVkT25cIiwgZmFsc2UsIFwiY2FsbGVkT25cIik7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcImNhbGxlZFdpdGhcIiwgdHJ1ZSk7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcImNhbGxlZFdpdGhNYXRjaFwiLCB0cnVlKTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwiYWx3YXlzQ2FsbGVkV2l0aFwiLCBmYWxzZSwgXCJjYWxsZWRXaXRoXCIpO1xuICAgICAgICBkZWxlZ2F0ZVRvQ2FsbHMoXCJhbHdheXNDYWxsZWRXaXRoTWF0Y2hcIiwgZmFsc2UsIFwiY2FsbGVkV2l0aE1hdGNoXCIpO1xuICAgICAgICBkZWxlZ2F0ZVRvQ2FsbHMoXCJjYWxsZWRXaXRoRXhhY3RseVwiLCB0cnVlKTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwiYWx3YXlzQ2FsbGVkV2l0aEV4YWN0bHlcIiwgZmFsc2UsIFwiY2FsbGVkV2l0aEV4YWN0bHlcIik7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcIm5ldmVyQ2FsbGVkV2l0aFwiLCBmYWxzZSwgXCJub3RDYWxsZWRXaXRoXCIsXG4gICAgICAgICAgICBmdW5jdGlvbiAoKSB7IHJldHVybiB0cnVlOyB9KTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwibmV2ZXJDYWxsZWRXaXRoTWF0Y2hcIiwgZmFsc2UsIFwibm90Q2FsbGVkV2l0aE1hdGNoXCIsXG4gICAgICAgICAgICBmdW5jdGlvbiAoKSB7IHJldHVybiB0cnVlOyB9KTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwidGhyZXdcIiwgdHJ1ZSk7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcImFsd2F5c1RocmV3XCIsIGZhbHNlLCBcInRocmV3XCIpO1xuICAgICAgICBkZWxlZ2F0ZVRvQ2FsbHMoXCJyZXR1cm5lZFwiLCB0cnVlKTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwiYWx3YXlzUmV0dXJuZWRcIiwgZmFsc2UsIFwicmV0dXJuZWRcIik7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcImNhbGxlZFdpdGhOZXdcIiwgdHJ1ZSk7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcImFsd2F5c0NhbGxlZFdpdGhOZXdcIiwgZmFsc2UsIFwiY2FsbGVkV2l0aE5ld1wiKTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwiY2FsbEFyZ1wiLCBmYWxzZSwgXCJjYWxsQXJnV2l0aFwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy50b1N0cmluZygpICsgXCIgY2Fubm90IGNhbGwgYXJnIHNpbmNlIGl0IHdhcyBub3QgeWV0IGludm9rZWQuXCIpO1xuICAgICAgICB9KTtcbiAgICAgICAgc3B5QXBpLmNhbGxBcmdXaXRoID0gc3B5QXBpLmNhbGxBcmc7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcImNhbGxBcmdPblwiLCBmYWxzZSwgXCJjYWxsQXJnT25XaXRoXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLnRvU3RyaW5nKCkgKyBcIiBjYW5ub3QgY2FsbCBhcmcgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5cIik7XG4gICAgICAgIH0pO1xuICAgICAgICBzcHlBcGkuY2FsbEFyZ09uV2l0aCA9IHNweUFwaS5jYWxsQXJnT247XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcInlpZWxkXCIsIGZhbHNlLCBcInlpZWxkXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLnRvU3RyaW5nKCkgKyBcIiBjYW5ub3QgeWllbGQgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5cIik7XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBcImludm9rZUNhbGxiYWNrXCIgaXMgYW4gYWxpYXMgZm9yIFwieWllbGRcIiBzaW5jZSBcInlpZWxkXCIgaXMgaW52YWxpZCBpbiBzdHJpY3QgbW9kZS5cbiAgICAgICAgc3B5QXBpLmludm9rZUNhbGxiYWNrID0gc3B5QXBpLnlpZWxkO1xuICAgICAgICBkZWxlZ2F0ZVRvQ2FsbHMoXCJ5aWVsZE9uXCIsIGZhbHNlLCBcInlpZWxkT25cIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHRoaXMudG9TdHJpbmcoKSArIFwiIGNhbm5vdCB5aWVsZCBzaW5jZSBpdCB3YXMgbm90IHlldCBpbnZva2VkLlwiKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcInlpZWxkVG9cIiwgZmFsc2UsIFwieWllbGRUb1wiLCBmdW5jdGlvbiAocHJvcGVydHkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLnRvU3RyaW5nKCkgKyBcIiBjYW5ub3QgeWllbGQgdG8gJ1wiICsgcHJvcGVydHkgK1xuICAgICAgICAgICAgICAgIFwiJyBzaW5jZSBpdCB3YXMgbm90IHlldCBpbnZva2VkLlwiKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcInlpZWxkVG9PblwiLCBmYWxzZSwgXCJ5aWVsZFRvT25cIiwgZnVuY3Rpb24gKHByb3BlcnR5KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy50b1N0cmluZygpICsgXCIgY2Fubm90IHlpZWxkIHRvICdcIiArIHByb3BlcnR5ICtcbiAgICAgICAgICAgICAgICBcIicgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5cIik7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNweUFwaS5mb3JtYXR0ZXJzID0ge1xuICAgICAgICAgICAgYzogZnVuY3Rpb24gKHNweSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzaW5vbi50aW1lc0luV29yZHMoc3B5LmNhbGxDb3VudCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBuOiBmdW5jdGlvbiAoc3B5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNweS50b1N0cmluZygpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgQzogZnVuY3Rpb24gKHNweSkge1xuICAgICAgICAgICAgICAgIHZhciBjYWxscyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBzcHkuY2FsbENvdW50OyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzdHJpbmdpZmllZENhbGwgPSBcIiAgICBcIiArIHNweS5nZXRDYWxsKGkpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICgvXFxuLy50ZXN0KGNhbGxzW2kgLSAxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ2lmaWVkQ2FsbCA9IFwiXFxuXCIgKyBzdHJpbmdpZmllZENhbGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcHVzaC5jYWxsKGNhbGxzLCBzdHJpbmdpZmllZENhbGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBjYWxscy5sZW5ndGggPiAwID8gXCJcXG5cIiArIGNhbGxzLmpvaW4oXCJcXG5cIikgOiBcIlwiO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgdDogZnVuY3Rpb24gKHNweSkge1xuICAgICAgICAgICAgICAgIHZhciBvYmplY3RzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHNweS5jYWxsQ291bnQ7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgcHVzaC5jYWxsKG9iamVjdHMsIHNpbm9uLmZvcm1hdChzcHkudGhpc1ZhbHVlc1tpXSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3RzLmpvaW4oXCIsIFwiKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIFwiKlwiOiBmdW5jdGlvbiAoc3B5LCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZvcm1hdHRlZCA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBhcmdzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBwdXNoLmNhbGwoZm9ybWF0dGVkLCBzaW5vbi5mb3JtYXQoYXJnc1tpXSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmb3JtYXR0ZWQuam9pbihcIiwgXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLmV4dGVuZChzcHksIHNweUFwaSk7XG5cbiAgICAgICAgc3B5LnNweUNhbGwgPSBzaW5vbi5zcHlDYWxsO1xuICAgICAgICBzaW5vbi5zcHkgPSBzcHk7XG5cbiAgICAgICAgcmV0dXJuIHNweTtcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2NhbGxcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2V4dGVuZFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vdGltZXNfaW5fd29yZHNcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2Zvcm1hdFwiKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIHV0aWwvY29yZS5qc1xuICogQGRlcGVuZCBleHRlbmQuanNcbiAqIEBkZXBlbmQgc3B5LmpzXG4gKiBAZGVwZW5kIGJlaGF2aW9yLmpzXG4gKi9cbi8qKlxuICogU3R1YiBmdW5jdGlvbnNcbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgZnVuY3Rpb24gc3R1YihvYmplY3QsIHByb3BlcnR5LCBmdW5jKSB7XG4gICAgICAgICAgICBpZiAoISFmdW5jICYmIHR5cGVvZiBmdW5jICE9IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZnVuYyAhPSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkN1c3RvbSBzdHViIHNob3VsZCBiZSBhIGZ1bmN0aW9uIG9yIGEgcHJvcGVydHkgZGVzY3JpcHRvclwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHdyYXBwZXI7XG5cbiAgICAgICAgICAgIGlmIChmdW5jKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBmdW5jID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICB3cmFwcGVyID0gc2lub24uc3B5ICYmIHNpbm9uLnNweS5jcmVhdGUgPyBzaW5vbi5zcHkuY3JlYXRlKGZ1bmMpIDogZnVuYztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB3cmFwcGVyID0gZnVuYztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNpbm9uLnNweSAmJiBzaW5vbi5zcHkuY3JlYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZXMgPSBzaW5vbi5vYmplY3RLZXlzKHdyYXBwZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0eXBlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyYXBwZXJbdHlwZXNbaV1dID0gc2lub24uc3B5LmNyZWF0ZSh3cmFwcGVyW3R5cGVzW2ldXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBzdHViTGVuZ3RoID0gMDtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdCA9PSBcIm9iamVjdFwiICYmIHR5cGVvZiBvYmplY3RbcHJvcGVydHldID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICBzdHViTGVuZ3RoID0gb2JqZWN0W3Byb3BlcnR5XS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdyYXBwZXIgPSBzdHViLmNyZWF0ZShzdHViTGVuZ3RoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFvYmplY3QgJiYgdHlwZW9mIHByb3BlcnR5ID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNpbm9uLnN0dWIuY3JlYXRlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgcHJvcGVydHkgPT09IFwidW5kZWZpbmVkXCIgJiYgdHlwZW9mIG9iamVjdCA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiBvYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3RbcHJvcF0gPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3R1YihvYmplY3QsIHByb3ApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHNpbm9uLndyYXBNZXRob2Qob2JqZWN0LCBwcm9wZXJ0eSwgd3JhcHBlcik7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBnZXREZWZhdWx0QmVoYXZpb3Ioc3R1Yikge1xuICAgICAgICAgICAgcmV0dXJuIHN0dWIuZGVmYXVsdEJlaGF2aW9yIHx8IGdldFBhcmVudEJlaGF2aW91cihzdHViKSB8fCBzaW5vbi5iZWhhdmlvci5jcmVhdGUoc3R1Yik7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBnZXRQYXJlbnRCZWhhdmlvdXIoc3R1Yikge1xuICAgICAgICAgICAgcmV0dXJuIChzdHViLnBhcmVudCAmJiBnZXRDdXJyZW50QmVoYXZpb3Ioc3R1Yi5wYXJlbnQpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGdldEN1cnJlbnRCZWhhdmlvcihzdHViKSB7XG4gICAgICAgICAgICB2YXIgYmVoYXZpb3IgPSBzdHViLmJlaGF2aW9yc1tzdHViLmNhbGxDb3VudCAtIDFdO1xuICAgICAgICAgICAgcmV0dXJuIGJlaGF2aW9yICYmIGJlaGF2aW9yLmlzUHJlc2VudCgpID8gYmVoYXZpb3IgOiBnZXREZWZhdWx0QmVoYXZpb3Ioc3R1Yik7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdXVpZCA9IDA7XG5cbiAgICAgICAgdmFyIHByb3RvID0ge1xuICAgICAgICAgICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUoc3R1Ykxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHZhciBmdW5jdGlvblN0dWIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBnZXRDdXJyZW50QmVoYXZpb3IoZnVuY3Rpb25TdHViKS5pbnZva2UodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb25TdHViLmlkID0gXCJzdHViI1wiICsgdXVpZCsrO1xuICAgICAgICAgICAgICAgIHZhciBvcmlnID0gZnVuY3Rpb25TdHViO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uU3R1YiA9IHNpbm9uLnNweS5jcmVhdGUoZnVuY3Rpb25TdHViLCBzdHViTGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBmdW5jdGlvblN0dWIuZnVuYyA9IG9yaWc7XG5cbiAgICAgICAgICAgICAgICBzaW5vbi5leHRlbmQoZnVuY3Rpb25TdHViLCBzdHViKTtcbiAgICAgICAgICAgICAgICBmdW5jdGlvblN0dWIuaW5zdGFudGlhdGVGYWtlID0gc2lub24uc3R1Yi5jcmVhdGU7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb25TdHViLmRpc3BsYXlOYW1lID0gXCJzdHViXCI7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb25TdHViLnRvU3RyaW5nID0gc2lub24uZnVuY3Rpb25Ub1N0cmluZztcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uU3R1Yi5kZWZhdWx0QmVoYXZpb3IgPSBudWxsO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uU3R1Yi5iZWhhdmlvcnMgPSBbXTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvblN0dWI7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICByZXNldEJlaGF2aW9yOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmRlZmF1bHRCZWhhdmlvciA9IG51bGw7XG4gICAgICAgICAgICAgICAgdGhpcy5iZWhhdmlvcnMgPSBbXTtcblxuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJldHVyblZhbHVlO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLnJldHVybkFyZ0F0O1xuICAgICAgICAgICAgICAgIHRoaXMucmV0dXJuVGhpcyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZmFrZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRoaXMuZmFrZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmFrZXNbaV0ucmVzZXRCZWhhdmlvcigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb25DYWxsOiBmdW5jdGlvbiBvbkNhbGwoaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuYmVoYXZpb3JzW2luZGV4XSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmJlaGF2aW9yc1tpbmRleF0gPSBzaW5vbi5iZWhhdmlvci5jcmVhdGUodGhpcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmVoYXZpb3JzW2luZGV4XTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uRmlyc3RDYWxsOiBmdW5jdGlvbiBvbkZpcnN0Q2FsbCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5vbkNhbGwoMCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBvblNlY29uZENhbGw6IGZ1bmN0aW9uIG9uU2Vjb25kQ2FsbCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5vbkNhbGwoMSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBvblRoaXJkQ2FsbDogZnVuY3Rpb24gb25UaGlyZENhbGwoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMub25DYWxsKDIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGZvciAodmFyIG1ldGhvZCBpbiBzaW5vbi5iZWhhdmlvcikge1xuICAgICAgICAgICAgaWYgKHNpbm9uLmJlaGF2aW9yLmhhc093blByb3BlcnR5KG1ldGhvZCkgJiZcbiAgICAgICAgICAgICAgICAhcHJvdG8uaGFzT3duUHJvcGVydHkobWV0aG9kKSAmJlxuICAgICAgICAgICAgICAgIG1ldGhvZCAhPSBcImNyZWF0ZVwiICYmXG4gICAgICAgICAgICAgICAgbWV0aG9kICE9IFwid2l0aEFyZ3NcIiAmJlxuICAgICAgICAgICAgICAgIG1ldGhvZCAhPSBcImludm9rZVwiKSB7XG4gICAgICAgICAgICAgICAgcHJvdG9bbWV0aG9kXSA9IChmdW5jdGlvbiAoYmVoYXZpb3JNZXRob2QpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVmYXVsdEJlaGF2aW9yID0gdGhpcy5kZWZhdWx0QmVoYXZpb3IgfHwgc2lub24uYmVoYXZpb3IuY3JlYXRlKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWZhdWx0QmVoYXZpb3JbYmVoYXZpb3JNZXRob2RdLmFwcGx5KHRoaXMuZGVmYXVsdEJlaGF2aW9yLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfShtZXRob2QpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNpbm9uLmV4dGVuZChzdHViLCBwcm90byk7XG4gICAgICAgIHNpbm9uLnN0dWIgPSBzdHViO1xuXG4gICAgICAgIHJldHVybiBzdHViO1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vYmVoYXZpb3JcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3NweVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vZXh0ZW5kXCIpO1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG1ha2VBcGkoc2lub24pO1xuICAgIH1cblxuICAgIGlmIChpc0FNRCkge1xuICAgICAgICBkZWZpbmUobG9hZERlcGVuZGVuY2llcyk7XG4gICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBtb2R1bGUuZXhwb3J0cywgbW9kdWxlKTtcbiAgICB9IGVsc2UgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufSh0eXBlb2Ygc2lub24gPT0gXCJvYmplY3RcIiAmJiBzaW5vbiB8fCBudWxsKSk7XG4iLCIvKipcbiAqIEBkZXBlbmQgdXRpbC9jb3JlLmpzXG4gKiBAZGVwZW5kIHNhbmRib3guanNcbiAqL1xuLyoqXG4gKiBUZXN0IGZ1bmN0aW9uLCBzYW5kYm94ZXMgZmFrZXNcbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgdmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xuXG4gICAgICAgIGZ1bmN0aW9uIHRlc3QoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIHZhciB0eXBlID0gdHlwZW9mIGNhbGxiYWNrO1xuXG4gICAgICAgICAgICBpZiAodHlwZSAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwic2lub24udGVzdCBuZWVkcyB0byB3cmFwIGEgdGVzdCBmdW5jdGlvbiwgZ290IFwiICsgdHlwZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHNpbm9uU2FuZGJveGVkVGVzdCgpIHtcbiAgICAgICAgICAgICAgICB2YXIgY29uZmlnID0gc2lub24uZ2V0Q29uZmlnKHNpbm9uLmNvbmZpZyk7XG4gICAgICAgICAgICAgICAgY29uZmlnLmluamVjdEludG8gPSBjb25maWcuaW5qZWN0SW50b1RoaXMgJiYgdGhpcyB8fCBjb25maWcuaW5qZWN0SW50bztcbiAgICAgICAgICAgICAgICB2YXIgc2FuZGJveCA9IHNpbm9uLnNhbmRib3guY3JlYXRlKGNvbmZpZyk7XG4gICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgdmFyIG9sZERvbmUgPSBhcmdzLmxlbmd0aCAmJiBhcmdzW2FyZ3MubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICAgICAgdmFyIGV4Y2VwdGlvbiwgcmVzdWx0O1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvbGREb25lID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICBhcmdzW2FyZ3MubGVuZ3RoIC0gMV0gPSBmdW5jdGlvbiBzaW5vbkRvbmUocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXhjZXB0aW9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW5kYm94LnZlcmlmeUFuZFJlc3RvcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG9sZERvbmUocmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBjYWxsYmFjay5hcHBseSh0aGlzLCBhcmdzLmNvbmNhdChzYW5kYm94LmFyZ3MpKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGV4Y2VwdGlvbiA9IGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvbGREb25lICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGV4Y2VwdGlvbiAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBleGNlcHRpb247XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzYW5kYm94LnZlcmlmeUFuZFJlc3RvcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjYWxsYmFjay5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gc2lub25Bc3luY1NhbmRib3hlZFRlc3QoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNpbm9uU2FuZGJveGVkVGVzdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBzaW5vblNhbmRib3hlZFRlc3Q7XG4gICAgICAgIH1cblxuICAgICAgICB0ZXN0LmNvbmZpZyA9IHtcbiAgICAgICAgICAgIGluamVjdEludG9UaGlzOiB0cnVlLFxuICAgICAgICAgICAgaW5qZWN0SW50bzogbnVsbCxcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IFtcInNweVwiLCBcInN0dWJcIiwgXCJtb2NrXCIsIFwiY2xvY2tcIiwgXCJzZXJ2ZXJcIiwgXCJyZXF1ZXN0c1wiXSxcbiAgICAgICAgICAgIHVzZUZha2VUaW1lcnM6IHRydWUsXG4gICAgICAgICAgICB1c2VGYWtlU2VydmVyOiB0cnVlXG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24udGVzdCA9IHRlc3Q7XG4gICAgICAgIHJldHVybiB0ZXN0O1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2FuZGJveFwiKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIGlmIChzaW5vbikge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KHR5cGVvZiBzaW5vbiA9PSBcIm9iamVjdFwiICYmIHNpbm9uIHx8IG51bGwpKTtcbiIsIi8qKlxuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqIEBkZXBlbmQgdGVzdC5qc1xuICovXG4vKipcbiAqIFRlc3QgY2FzZSwgc2FuZGJveGVzIGFsbCB0ZXN0IGZ1bmN0aW9uc1xuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKHNpbm9uKSB7XG4gICAgZnVuY3Rpb24gY3JlYXRlVGVzdChwcm9wZXJ0eSwgc2V0VXAsIHRlYXJEb3duKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoc2V0VXApIHtcbiAgICAgICAgICAgICAgICBzZXRVcC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgZXhjZXB0aW9uLCByZXN1bHQ7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gcHJvcGVydHkuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBleGNlcHRpb24gPSBlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGVhckRvd24pIHtcbiAgICAgICAgICAgICAgICB0ZWFyRG93bi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgZXhjZXB0aW9uO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgZnVuY3Rpb24gdGVzdENhc2UodGVzdHMsIHByZWZpeCkge1xuICAgICAgICAgICAgLypqc2w6aWdub3JlKi9cbiAgICAgICAgICAgIGlmICghdGVzdHMgfHwgdHlwZW9mIHRlc3RzICE9IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwic2lub24udGVzdENhc2UgbmVlZHMgYW4gb2JqZWN0IHdpdGggdGVzdCBmdW5jdGlvbnNcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvKmpzbDplbmQqL1xuXG4gICAgICAgICAgICBwcmVmaXggPSBwcmVmaXggfHwgXCJ0ZXN0XCI7XG4gICAgICAgICAgICB2YXIgclByZWZpeCA9IG5ldyBSZWdFeHAoXCJeXCIgKyBwcmVmaXgpO1xuICAgICAgICAgICAgdmFyIG1ldGhvZHMgPSB7fSwgdGVzdE5hbWUsIHByb3BlcnR5LCBtZXRob2Q7XG4gICAgICAgICAgICB2YXIgc2V0VXAgPSB0ZXN0cy5zZXRVcDtcbiAgICAgICAgICAgIHZhciB0ZWFyRG93biA9IHRlc3RzLnRlYXJEb3duO1xuXG4gICAgICAgICAgICBmb3IgKHRlc3ROYW1lIGluIHRlc3RzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRlc3RzLmhhc093blByb3BlcnR5KHRlc3ROYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eSA9IHRlc3RzW3Rlc3ROYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoL14oc2V0VXB8dGVhckRvd24pJC8udGVzdCh0ZXN0TmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwcm9wZXJ0eSA9PSBcImZ1bmN0aW9uXCIgJiYgclByZWZpeC50ZXN0KHRlc3ROYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gcHJvcGVydHk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXRVcCB8fCB0ZWFyRG93bikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9IGNyZWF0ZVRlc3QocHJvcGVydHksIHNldFVwLCB0ZWFyRG93bik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZHNbdGVzdE5hbWVdID0gc2lub24udGVzdChtZXRob2QpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kc1t0ZXN0TmFtZV0gPSB0ZXN0c1t0ZXN0TmFtZV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBtZXRob2RzO1xuICAgICAgICB9XG5cbiAgICAgICAgc2lub24udGVzdENhc2UgPSB0ZXN0Q2FzZTtcbiAgICAgICAgcmV0dXJuIHRlc3RDYXNlO1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vdGVzdFwiKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIHV0aWwvY29yZS5qc1xuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcblxuICAgICAgICBmdW5jdGlvbiB0aW1lc0luV29yZHMoY291bnQpIHtcbiAgICAgICAgICAgIHN3aXRjaCAoY291bnQpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm9uY2VcIjtcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInR3aWNlXCI7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ0aHJpY2VcIjtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKGNvdW50IHx8IDApICsgXCIgdGltZXNcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNpbm9uLnRpbWVzSW5Xb3JkcyA9IHRpbWVzSW5Xb3JkcztcbiAgICAgICAgcmV0dXJuIHNpbm9uLnRpbWVzSW5Xb3JkcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KHR5cGVvZiBzaW5vbiA9PSBcIm9iamVjdFwiICYmIHNpbm9uIHx8IG51bGwpKTtcbiIsIi8qKlxuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqL1xuLyoqXG4gKiBGb3JtYXQgZnVuY3Rpb25zXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxNCBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiAoc2lub24sIGZvcm1hdGlvKSB7XG4gICAgZnVuY3Rpb24gbWFrZUFwaShzaW5vbikge1xuICAgICAgICBmdW5jdGlvbiB0eXBlT2YodmFsdWUpIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBcIm51bGxcIjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBcInVuZGVmaW5lZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHN0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnN1YnN0cmluZyg4LCBzdHJpbmcubGVuZ3RoIC0gMSkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi50eXBlT2YgPSB0eXBlT2Y7XG4gICAgICAgIHJldHVybiBzaW5vbi50eXBlT2Y7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgICAgICAgdmFyIHNpbm9uID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlXCIpO1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG1ha2VBcGkoc2lub24pO1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGlmIChpc0FNRCkge1xuICAgICAgICBkZWZpbmUobG9hZERlcGVuZGVuY2llcyk7XG4gICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBtb2R1bGUuZXhwb3J0cywgbW9kdWxlKTtcbiAgICB9IGVsc2UgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufShcbiAgICAodHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCksXG4gICAgKHR5cGVvZiBmb3JtYXRpbyA9PSBcIm9iamVjdFwiICYmIGZvcm1hdGlvKVxuKSk7XG4iLCIvKipcbiAqIEBkZXBlbmQgLi4vLi4vc2lub24uanNcbiAqL1xuLyoqXG4gKiBTaW5vbiBjb3JlIHV0aWxpdGllcy4gRm9yIGludGVybmFsIHVzZSBvbmx5LlxuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKHNpbm9uKSB7XG4gICAgdmFyIGRpdiA9IHR5cGVvZiBkb2N1bWVudCAhPSBcInVuZGVmaW5lZFwiICYmIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgdmFyIGhhc093biA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG5cbiAgICBmdW5jdGlvbiBpc0RPTU5vZGUob2JqKSB7XG4gICAgICAgIHZhciBzdWNjZXNzID0gZmFsc2U7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG9iai5hcHBlbmRDaGlsZChkaXYpO1xuICAgICAgICAgICAgc3VjY2VzcyA9IGRpdi5wYXJlbnROb2RlID09IG9iajtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBvYmoucmVtb3ZlQ2hpbGQoZGl2KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgZmFpbGVkLCBub3QgbXVjaCB3ZSBjYW4gZG8gYWJvdXQgdGhhdFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHN1Y2Nlc3M7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNFbGVtZW50KG9iaikge1xuICAgICAgICByZXR1cm4gZGl2ICYmIG9iaiAmJiBvYmoubm9kZVR5cGUgPT09IDEgJiYgaXNET01Ob2RlKG9iaik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNGdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmogPT09IFwiZnVuY3Rpb25cIiB8fCAhIShvYmogJiYgb2JqLmNvbnN0cnVjdG9yICYmIG9iai5jYWxsICYmIG9iai5hcHBseSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNSZWFsbHlOYU4odmFsKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsID09PSBcIm51bWJlclwiICYmIGlzTmFOKHZhbCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWlycm9yUHJvcGVydGllcyh0YXJnZXQsIHNvdXJjZSkge1xuICAgICAgICBmb3IgKHZhciBwcm9wIGluIHNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKCFoYXNPd24uY2FsbCh0YXJnZXQsIHByb3ApKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0W3Byb3BdID0gc291cmNlW3Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNSZXN0b3JhYmxlKG9iaikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBvYmoucmVzdG9yZSA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5yZXN0b3JlLnNpbm9uO1xuICAgIH1cblxuICAgIC8vIENoZWFwIHdheSB0byBkZXRlY3QgaWYgd2UgaGF2ZSBFUzUgc3VwcG9ydC5cbiAgICB2YXIgaGFzRVM1U3VwcG9ydCA9IFwia2V5c1wiIGluIE9iamVjdDtcblxuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgc2lub24ud3JhcE1ldGhvZCA9IGZ1bmN0aW9uIHdyYXBNZXRob2Qob2JqZWN0LCBwcm9wZXJ0eSwgbWV0aG9kKSB7XG4gICAgICAgICAgICBpZiAoIW9iamVjdCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTaG91bGQgd3JhcCBwcm9wZXJ0eSBvZiBvYmplY3RcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWV0aG9kICE9IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgbWV0aG9kICE9IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWV0aG9kIHdyYXBwZXIgc2hvdWxkIGJlIGEgZnVuY3Rpb24gb3IgYSBwcm9wZXJ0eSBkZXNjcmlwdG9yXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjaGVja1dyYXBwZWRNZXRob2Qod3JhcHBlZE1ldGhvZCkge1xuICAgICAgICAgICAgICAgIGlmICghaXNGdW5jdGlvbih3cmFwcGVkTWV0aG9kKSkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvciA9IG5ldyBUeXBlRXJyb3IoXCJBdHRlbXB0ZWQgdG8gd3JhcCBcIiArICh0eXBlb2Ygd3JhcHBlZE1ldGhvZCkgKyBcIiBwcm9wZXJ0eSBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydHkgKyBcIiBhcyBmdW5jdGlvblwiKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHdyYXBwZWRNZXRob2QucmVzdG9yZSAmJiB3cmFwcGVkTWV0aG9kLnJlc3RvcmUuc2lub24pIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBuZXcgVHlwZUVycm9yKFwiQXR0ZW1wdGVkIHRvIHdyYXAgXCIgKyBwcm9wZXJ0eSArIFwiIHdoaWNoIGlzIGFscmVhZHkgd3JhcHBlZFwiKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHdyYXBwZWRNZXRob2QuY2FsbGVkQmVmb3JlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2ZXJiID0gISF3cmFwcGVkTWV0aG9kLnJldHVybnMgPyBcInN0dWJiZWRcIiA6IFwic3BpZWQgb25cIjtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBuZXcgVHlwZUVycm9yKFwiQXR0ZW1wdGVkIHRvIHdyYXAgXCIgKyBwcm9wZXJ0eSArIFwiIHdoaWNoIGlzIGFscmVhZHkgXCIgKyB2ZXJiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdyYXBwZWRNZXRob2QgJiYgd3JhcHBlZE1ldGhvZC5zdGFja1RyYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5zdGFjayArPSBcIlxcbi0tLS0tLS0tLS0tLS0tXFxuXCIgKyB3cmFwcGVkTWV0aG9kLnN0YWNrVHJhY2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgZXJyb3IsIHdyYXBwZWRNZXRob2Q7XG5cbiAgICAgICAgICAgIC8vIElFIDggZG9lcyBub3Qgc3VwcG9ydCBoYXNPd25Qcm9wZXJ0eSBvbiB0aGUgd2luZG93IG9iamVjdCBhbmQgRmlyZWZveCBoYXMgYSBwcm9ibGVtXG4gICAgICAgICAgICAvLyB3aGVuIHVzaW5nIGhhc093bi5jYWxsIG9uIG9iamVjdHMgZnJvbSBvdGhlciBmcmFtZXMuXG4gICAgICAgICAgICB2YXIgb3duZWQgPSBvYmplY3QuaGFzT3duUHJvcGVydHkgPyBvYmplY3QuaGFzT3duUHJvcGVydHkocHJvcGVydHkpIDogaGFzT3duLmNhbGwob2JqZWN0LCBwcm9wZXJ0eSk7XG5cbiAgICAgICAgICAgIGlmIChoYXNFUzVTdXBwb3J0KSB7XG4gICAgICAgICAgICAgICAgdmFyIG1ldGhvZERlc2MgPSAodHlwZW9mIG1ldGhvZCA9PSBcImZ1bmN0aW9uXCIpID8ge3ZhbHVlOiBtZXRob2R9IDogbWV0aG9kLFxuICAgICAgICAgICAgICAgICAgICB3cmFwcGVkTWV0aG9kRGVzYyA9IHNpbm9uLmdldFByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KSxcbiAgICAgICAgICAgICAgICAgICAgaTtcblxuICAgICAgICAgICAgICAgIGlmICghd3JhcHBlZE1ldGhvZERlc2MpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBuZXcgVHlwZUVycm9yKFwiQXR0ZW1wdGVkIHRvIHdyYXAgXCIgKyAodHlwZW9mIHdyYXBwZWRNZXRob2QpICsgXCIgcHJvcGVydHkgXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnR5ICsgXCIgYXMgZnVuY3Rpb25cIik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh3cmFwcGVkTWV0aG9kRGVzYy5yZXN0b3JlICYmIHdyYXBwZWRNZXRob2REZXNjLnJlc3RvcmUuc2lub24pIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBuZXcgVHlwZUVycm9yKFwiQXR0ZW1wdGVkIHRvIHdyYXAgXCIgKyBwcm9wZXJ0eSArIFwiIHdoaWNoIGlzIGFscmVhZHkgd3JhcHBlZFwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3cmFwcGVkTWV0aG9kRGVzYyAmJiB3cmFwcGVkTWV0aG9kRGVzYy5zdGFja1RyYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5zdGFjayArPSBcIlxcbi0tLS0tLS0tLS0tLS0tXFxuXCIgKyB3cmFwcGVkTWV0aG9kRGVzYy5zdGFja1RyYWNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciB0eXBlcyA9IHNpbm9uLm9iamVjdEtleXMobWV0aG9kRGVzYyk7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHR5cGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHdyYXBwZWRNZXRob2QgPSB3cmFwcGVkTWV0aG9kRGVzY1t0eXBlc1tpXV07XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrV3JhcHBlZE1ldGhvZCh3cmFwcGVkTWV0aG9kKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBtaXJyb3JQcm9wZXJ0aWVzKG1ldGhvZERlc2MsIHdyYXBwZWRNZXRob2REZXNjKTtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdHlwZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbWlycm9yUHJvcGVydGllcyhtZXRob2REZXNjW3R5cGVzW2ldXSwgd3JhcHBlZE1ldGhvZERlc2NbdHlwZXNbaV1dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcGVydHksIG1ldGhvZERlc2MpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB3cmFwcGVkTWV0aG9kID0gb2JqZWN0W3Byb3BlcnR5XTtcbiAgICAgICAgICAgICAgICBjaGVja1dyYXBwZWRNZXRob2Qod3JhcHBlZE1ldGhvZCk7XG4gICAgICAgICAgICAgICAgb2JqZWN0W3Byb3BlcnR5XSA9IG1ldGhvZDtcbiAgICAgICAgICAgICAgICBtZXRob2QuZGlzcGxheU5hbWUgPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbWV0aG9kLmRpc3BsYXlOYW1lID0gcHJvcGVydHk7XG5cbiAgICAgICAgICAgIC8vIFNldCB1cCBhIHN0YWNrIHRyYWNlIHdoaWNoIGNhbiBiZSB1c2VkIGxhdGVyIHRvIGZpbmQgd2hhdCBsaW5lIG9mXG4gICAgICAgICAgICAvLyBjb2RlIHRoZSBvcmlnaW5hbCBtZXRob2Qgd2FzIGNyZWF0ZWQgb24uXG4gICAgICAgICAgICBtZXRob2Quc3RhY2tUcmFjZSA9IChuZXcgRXJyb3IoXCJTdGFjayBUcmFjZSBmb3Igb3JpZ2luYWxcIikpLnN0YWNrO1xuXG4gICAgICAgICAgICBtZXRob2QucmVzdG9yZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAvLyBGb3IgcHJvdG90eXBlIHByb3BlcnRpZXMgdHJ5IHRvIHJlc2V0IGJ5IGRlbGV0ZSBmaXJzdC5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGlzIGZhaWxzIChleDogbG9jYWxTdG9yYWdlIG9uIG1vYmlsZSBzYWZhcmkpIHRoZW4gZm9yY2UgYSByZXNldFxuICAgICAgICAgICAgICAgIC8vIHZpYSBkaXJlY3QgYXNzaWdubWVudC5cbiAgICAgICAgICAgICAgICBpZiAoIW93bmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgb2JqZWN0W3Byb3BlcnR5XTtcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgICAgICAgICAgICAgLy8gRm9yIG5hdGl2ZSBjb2RlIGZ1bmN0aW9ucyBgZGVsZXRlYCBmYWlscyB3aXRob3V0IHRocm93aW5nIGFuIGVycm9yXG4gICAgICAgICAgICAgICAgICAgIC8vIG9uIENocm9tZSA8IDQzLCBQaGFudG9tSlMsIGV0Yy5cbiAgICAgICAgICAgICAgICAgICAgLy8gVXNlIHN0cmljdCBlcXVhbGl0eSBjb21wYXJpc29uIHRvIGNoZWNrIGZhaWx1cmVzIHRoZW4gZm9yY2UgYSByZXNldFxuICAgICAgICAgICAgICAgICAgICAvLyB2aWEgZGlyZWN0IGFzc2lnbm1lbnQuXG4gICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3RbcHJvcGVydHldID09PSBtZXRob2QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdFtwcm9wZXJ0eV0gPSB3cmFwcGVkTWV0aG9kO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChoYXNFUzVTdXBwb3J0KSB7XG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmplY3QsIHByb3BlcnR5LCB3cmFwcGVkTWV0aG9kRGVzYyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNFUzVTdXBwb3J0ICYmIG9iamVjdFtwcm9wZXJ0eV0gPT09IG1ldGhvZCkge1xuICAgICAgICAgICAgICAgICAgICBvYmplY3RbcHJvcGVydHldID0gd3JhcHBlZE1ldGhvZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBtZXRob2QucmVzdG9yZS5zaW5vbiA9IHRydWU7XG5cbiAgICAgICAgICAgIGlmICghaGFzRVM1U3VwcG9ydCkge1xuICAgICAgICAgICAgICAgIG1pcnJvclByb3BlcnRpZXMobWV0aG9kLCB3cmFwcGVkTWV0aG9kKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIG1ldGhvZDtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5jcmVhdGUgPSBmdW5jdGlvbiBjcmVhdGUocHJvdG8pIHtcbiAgICAgICAgICAgIHZhciBGID0gZnVuY3Rpb24gKCkge307XG4gICAgICAgICAgICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBGKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uZGVlcEVxdWFsID0gZnVuY3Rpb24gZGVlcEVxdWFsKGEsIGIpIHtcbiAgICAgICAgICAgIGlmIChzaW5vbi5tYXRjaCAmJiBzaW5vbi5tYXRjaC5pc01hdGNoZXIoYSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYS50ZXN0KGIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZW9mIGEgIT0gXCJvYmplY3RcIiB8fCB0eXBlb2YgYiAhPSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzUmVhbGx5TmFOKGEpICYmIGlzUmVhbGx5TmFOKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhID09PSBiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGlzRWxlbWVudChhKSB8fCBpc0VsZW1lbnQoYikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA9PT0gYjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKChhID09PSBudWxsICYmIGIgIT09IG51bGwpIHx8IChhICE9PSBudWxsICYmIGIgPT09IG51bGwpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoYSBpbnN0YW5jZW9mIFJlZ0V4cCAmJiBiIGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChhLnNvdXJjZSA9PT0gYi5zb3VyY2UpICYmIChhLmdsb2JhbCA9PT0gYi5nbG9iYWwpICYmXG4gICAgICAgICAgICAgICAgICAgIChhLmlnbm9yZUNhc2UgPT09IGIuaWdub3JlQ2FzZSkgJiYgKGEubXVsdGlsaW5lID09PSBiLm11bHRpbGluZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBhU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGEpO1xuICAgICAgICAgICAgaWYgKGFTdHJpbmcgIT0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoYVN0cmluZyA9PSBcIltvYmplY3QgRGF0ZV1cIikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhLnZhbHVlT2YoKSA9PT0gYi52YWx1ZU9mKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBwcm9wLCBhTGVuZ3RoID0gMCwgYkxlbmd0aCA9IDA7XG5cbiAgICAgICAgICAgIGlmIChhU3RyaW5nID09IFwiW29iamVjdCBBcnJheV1cIiAmJiBhLmxlbmd0aCAhPT0gYi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAocHJvcCBpbiBhKSB7XG4gICAgICAgICAgICAgICAgYUxlbmd0aCArPSAxO1xuXG4gICAgICAgICAgICAgICAgaWYgKCEocHJvcCBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFkZWVwRXF1YWwoYVtwcm9wXSwgYltwcm9wXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChwcm9wIGluIGIpIHtcbiAgICAgICAgICAgICAgICBiTGVuZ3RoICs9IDE7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBhTGVuZ3RoID09IGJMZW5ndGg7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uZnVuY3Rpb25OYW1lID0gZnVuY3Rpb24gZnVuY3Rpb25OYW1lKGZ1bmMpIHtcbiAgICAgICAgICAgIHZhciBuYW1lID0gZnVuYy5kaXNwbGF5TmFtZSB8fCBmdW5jLm5hbWU7XG5cbiAgICAgICAgICAgIC8vIFVzZSBmdW5jdGlvbiBkZWNvbXBvc2l0aW9uIGFzIGEgbGFzdCByZXNvcnQgdG8gZ2V0IGZ1bmN0aW9uXG4gICAgICAgICAgICAvLyBuYW1lLiBEb2VzIG5vdCByZWx5IG9uIGZ1bmN0aW9uIGRlY29tcG9zaXRpb24gdG8gd29yayAtIGlmIGl0XG4gICAgICAgICAgICAvLyBkb2Vzbid0IGRlYnVnZ2luZyB3aWxsIGJlIHNsaWdodGx5IGxlc3MgaW5mb3JtYXRpdmVcbiAgICAgICAgICAgIC8vIChpLmUuIHRvU3RyaW5nIHdpbGwgc2F5ICdzcHknIHJhdGhlciB0aGFuICdteUZ1bmMnKS5cbiAgICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBtYXRjaGVzID0gZnVuYy50b1N0cmluZygpLm1hdGNoKC9mdW5jdGlvbiAoW15cXHNcXChdKykvKTtcbiAgICAgICAgICAgICAgICBuYW1lID0gbWF0Y2hlcyAmJiBtYXRjaGVzWzFdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gbmFtZTtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5mdW5jdGlvblRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5nZXRDYWxsICYmIHRoaXMuY2FsbENvdW50KSB7XG4gICAgICAgICAgICAgICAgdmFyIHRoaXNWYWx1ZSwgcHJvcCwgaSA9IHRoaXMuY2FsbENvdW50O1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKGktLSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzVmFsdWUgPSB0aGlzLmdldENhbGwoaSkudGhpc1ZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIGZvciAocHJvcCBpbiB0aGlzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzVmFsdWVbcHJvcF0gPT09IHRoaXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJvcDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGlzcGxheU5hbWUgfHwgXCJzaW5vbiBmYWtlXCI7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24ub2JqZWN0S2V5cyA9IGZ1bmN0aW9uIG9iamVjdEtleXMob2JqKSB7XG4gICAgICAgICAgICBpZiAob2JqICE9PSBPYmplY3Qob2JqKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJzaW5vbi5vYmplY3RLZXlzIGNhbGxlZCBvbiBhIG5vbi1vYmplY3RcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBrZXlzID0gW107XG4gICAgICAgICAgICB2YXIga2V5O1xuICAgICAgICAgICAgZm9yIChrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhc093bi5jYWxsKG9iaiwga2V5KSkge1xuICAgICAgICAgICAgICAgICAgICBrZXlzLnB1c2goa2V5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBrZXlzO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLmdldFByb3BlcnR5RGVzY3JpcHRvciA9IGZ1bmN0aW9uIGdldFByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KSB7XG4gICAgICAgICAgICB2YXIgcHJvdG8gPSBvYmplY3QsIGRlc2NyaXB0b3I7XG4gICAgICAgICAgICB3aGlsZSAocHJvdG8gJiYgIShkZXNjcmlwdG9yID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihwcm90bywgcHJvcGVydHkpKSkge1xuICAgICAgICAgICAgICAgIHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHByb3RvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBkZXNjcmlwdG9yO1xuICAgICAgICB9XG5cbiAgICAgICAgc2lub24uZ2V0Q29uZmlnID0gZnVuY3Rpb24gKGN1c3RvbSkge1xuICAgICAgICAgICAgdmFyIGNvbmZpZyA9IHt9O1xuICAgICAgICAgICAgY3VzdG9tID0gY3VzdG9tIHx8IHt9O1xuICAgICAgICAgICAgdmFyIGRlZmF1bHRzID0gc2lub24uZGVmYXVsdENvbmZpZztcblxuICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiBkZWZhdWx0cykge1xuICAgICAgICAgICAgICAgIGlmIChkZWZhdWx0cy5oYXNPd25Qcm9wZXJ0eShwcm9wKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25maWdbcHJvcF0gPSBjdXN0b20uaGFzT3duUHJvcGVydHkocHJvcCkgPyBjdXN0b21bcHJvcF0gOiBkZWZhdWx0c1twcm9wXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBjb25maWc7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uZGVmYXVsdENvbmZpZyA9IHtcbiAgICAgICAgICAgIGluamVjdEludG9UaGlzOiB0cnVlLFxuICAgICAgICAgICAgaW5qZWN0SW50bzogbnVsbCxcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IFtcInNweVwiLCBcInN0dWJcIiwgXCJtb2NrXCIsIFwiY2xvY2tcIiwgXCJzZXJ2ZXJcIiwgXCJyZXF1ZXN0c1wiXSxcbiAgICAgICAgICAgIHVzZUZha2VUaW1lcnM6IHRydWUsXG4gICAgICAgICAgICB1c2VGYWtlU2VydmVyOiB0cnVlXG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24udGltZXNJbldvcmRzID0gZnVuY3Rpb24gdGltZXNJbldvcmRzKGNvdW50KSB7XG4gICAgICAgICAgICByZXR1cm4gY291bnQgPT0gMSAmJiBcIm9uY2VcIiB8fFxuICAgICAgICAgICAgICAgIGNvdW50ID09IDIgJiYgXCJ0d2ljZVwiIHx8XG4gICAgICAgICAgICAgICAgY291bnQgPT0gMyAmJiBcInRocmljZVwiIHx8XG4gICAgICAgICAgICAgICAgKGNvdW50IHx8IDApICsgXCIgdGltZXNcIjtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5jYWxsZWRJbk9yZGVyID0gZnVuY3Rpb24gKHNwaWVzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMSwgbCA9IHNwaWVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICghc3BpZXNbaSAtIDFdLmNhbGxlZEJlZm9yZShzcGllc1tpXSkgfHwgIXNwaWVzW2ldLmNhbGxlZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5vcmRlckJ5Rmlyc3RDYWxsID0gZnVuY3Rpb24gKHNwaWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gc3BpZXMuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgICAgIC8vIHV1aWQsIHdvbid0IGV2ZXIgYmUgZXF1YWxcbiAgICAgICAgICAgICAgICB2YXIgYUNhbGwgPSBhLmdldENhbGwoMCk7XG4gICAgICAgICAgICAgICAgdmFyIGJDYWxsID0gYi5nZXRDYWxsKDApO1xuICAgICAgICAgICAgICAgIHZhciBhSWQgPSBhQ2FsbCAmJiBhQ2FsbC5jYWxsSWQgfHwgLTE7XG4gICAgICAgICAgICAgICAgdmFyIGJJZCA9IGJDYWxsICYmIGJDYWxsLmNhbGxJZCB8fCAtMTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBhSWQgPCBiSWQgPyAtMSA6IDE7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5jcmVhdGVTdHViSW5zdGFuY2UgPSBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY29uc3RydWN0b3IgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJUaGUgY29uc3RydWN0b3Igc2hvdWxkIGJlIGEgZnVuY3Rpb24uXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHNpbm9uLnN0dWIoc2lub24uY3JlYXRlKGNvbnN0cnVjdG9yLnByb3RvdHlwZSkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLnJlc3RvcmUgPSBmdW5jdGlvbiAob2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAob2JqZWN0ICE9PSBudWxsICYmIHR5cGVvZiBvYmplY3QgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wIGluIG9iamVjdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNSZXN0b3JhYmxlKG9iamVjdFtwcm9wXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdFtwcm9wXS5yZXN0b3JlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzUmVzdG9yYWJsZShvYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LnJlc3RvcmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICByZXR1cm4gc2lub247XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBleHBvcnRzKSB7XG4gICAgICAgIG1ha2VBcGkoZXhwb3J0cyk7XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzKTtcbiAgICB9IGVsc2UgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufSh0eXBlb2Ygc2lub24gPT0gXCJvYmplY3RcIiAmJiBzaW5vbiB8fCBudWxsKSk7XG4iLCIvKipcbiAqIE1pbmltYWwgRXZlbnQgaW50ZXJmYWNlIGltcGxlbWVudGF0aW9uXG4gKlxuICogT3JpZ2luYWwgaW1wbGVtZW50YXRpb24gYnkgU3ZlbiBGdWNoczogaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vOTk1MDI4XG4gKiBNb2RpZmljYXRpb25zIGFuZCB0ZXN0cyBieSBDaHJpc3RpYW4gSm9oYW5zZW4uXG4gKlxuICogQGF1dGhvciBTdmVuIEZ1Y2hzIChzdmVuZnVjaHNAYXJ0d2ViLWRlc2lnbi5kZSlcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDExIFN2ZW4gRnVjaHMsIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuaWYgKHR5cGVvZiBzaW5vbiA9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgdGhpcy5zaW5vbiA9IHt9O1xufVxuXG4oZnVuY3Rpb24gKCkge1xuICAgIHZhciBwdXNoID0gW10ucHVzaDtcblxuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgc2lub24uRXZlbnQgPSBmdW5jdGlvbiBFdmVudCh0eXBlLCBidWJibGVzLCBjYW5jZWxhYmxlLCB0YXJnZXQpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdEV2ZW50KHR5cGUsIGJ1YmJsZXMsIGNhbmNlbGFibGUsIHRhcmdldCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uRXZlbnQucHJvdG90eXBlID0ge1xuICAgICAgICAgICAgaW5pdEV2ZW50OiBmdW5jdGlvbiAodHlwZSwgYnViYmxlcywgY2FuY2VsYWJsZSwgdGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICAgICAgICAgICAgICB0aGlzLmJ1YmJsZXMgPSBidWJibGVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FuY2VsYWJsZSA9IGNhbmNlbGFibGU7XG4gICAgICAgICAgICAgICAgdGhpcy50YXJnZXQgPSB0YXJnZXQ7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBzdG9wUHJvcGFnYXRpb246IGZ1bmN0aW9uICgpIHt9LFxuXG4gICAgICAgICAgICBwcmV2ZW50RGVmYXVsdDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGVmYXVsdFByZXZlbnRlZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uUHJvZ3Jlc3NFdmVudCA9IGZ1bmN0aW9uIFByb2dyZXNzRXZlbnQodHlwZSwgcHJvZ3Jlc3NFdmVudFJhdywgdGFyZ2V0KSB7XG4gICAgICAgICAgICB0aGlzLmluaXRFdmVudCh0eXBlLCBmYWxzZSwgZmFsc2UsIHRhcmdldCk7XG4gICAgICAgICAgICB0aGlzLmxvYWRlZCA9IHByb2dyZXNzRXZlbnRSYXcubG9hZGVkIHx8IG51bGw7XG4gICAgICAgICAgICB0aGlzLnRvdGFsID0gcHJvZ3Jlc3NFdmVudFJhdy50b3RhbCB8fCBudWxsO1xuICAgICAgICAgICAgdGhpcy5sZW5ndGhDb21wdXRhYmxlID0gISFwcm9ncmVzc0V2ZW50UmF3LnRvdGFsO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLlByb2dyZXNzRXZlbnQucHJvdG90eXBlID0gbmV3IHNpbm9uLkV2ZW50KCk7XG5cbiAgICAgICAgc2lub24uUHJvZ3Jlc3NFdmVudC5wcm90b3R5cGUuY29uc3RydWN0b3IgPSAgc2lub24uUHJvZ3Jlc3NFdmVudDtcblxuICAgICAgICBzaW5vbi5DdXN0b21FdmVudCA9IGZ1bmN0aW9uIEN1c3RvbUV2ZW50KHR5cGUsIGN1c3RvbURhdGEsIHRhcmdldCkge1xuICAgICAgICAgICAgdGhpcy5pbml0RXZlbnQodHlwZSwgZmFsc2UsIGZhbHNlLCB0YXJnZXQpO1xuICAgICAgICAgICAgdGhpcy5kZXRhaWwgPSBjdXN0b21EYXRhLmRldGFpbCB8fCBudWxsO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLkN1c3RvbUV2ZW50LnByb3RvdHlwZSA9IG5ldyBzaW5vbi5FdmVudCgpO1xuXG4gICAgICAgIHNpbm9uLkN1c3RvbUV2ZW50LnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9ICBzaW5vbi5DdXN0b21FdmVudDtcblxuICAgICAgICBzaW5vbi5FdmVudFRhcmdldCA9IHtcbiAgICAgICAgICAgIGFkZEV2ZW50TGlzdGVuZXI6IGZ1bmN0aW9uIGFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudExpc3RlbmVycyA9IHRoaXMuZXZlbnRMaXN0ZW5lcnMgfHwge307XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudExpc3RlbmVyc1tldmVudF0gPSB0aGlzLmV2ZW50TGlzdGVuZXJzW2V2ZW50XSB8fCBbXTtcbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwodGhpcy5ldmVudExpc3RlbmVyc1tldmVudF0sIGxpc3RlbmVyKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlbW92ZUV2ZW50TGlzdGVuZXI6IGZ1bmN0aW9uIHJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZXZlbnRMaXN0ZW5lcnMgJiYgdGhpcy5ldmVudExpc3RlbmVyc1tldmVudF0gfHwgW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyc1tpXSA9PSBsaXN0ZW5lcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGxpc3RlbmVycy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBkaXNwYXRjaEV2ZW50OiBmdW5jdGlvbiBkaXNwYXRjaEV2ZW50KGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSBldmVudC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmV2ZW50TGlzdGVuZXJzICYmIHRoaXMuZXZlbnRMaXN0ZW5lcnNbdHlwZV0gfHwgW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxpc3RlbmVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGxpc3RlbmVyc1tpXSA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5jYWxsKHRoaXMsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxpc3RlbmVyc1tpXS5oYW5kbGVFdmVudChldmVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gISFldmVudC5kZWZhdWx0UHJldmVudGVkO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi9jb3JlXCIpO1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufSgpKTtcbiIsIi8qKlxuICogQGRlcGVuZCBmYWtlX3hkb21haW5fcmVxdWVzdC5qc1xuICogQGRlcGVuZCBmYWtlX3htbF9odHRwX3JlcXVlc3QuanNcbiAqIEBkZXBlbmQgLi4vZm9ybWF0LmpzXG4gKiBAZGVwZW5kIC4uL2xvZ19lcnJvci5qc1xuICovXG4vKipcbiAqIFRoZSBTaW5vbiBcInNlcnZlclwiIG1pbWljcyBhIHdlYiBzZXJ2ZXIgdGhhdCByZWNlaXZlcyByZXF1ZXN0cyBmcm9tXG4gKiBzaW5vbi5GYWtlWE1MSHR0cFJlcXVlc3QgYW5kIHByb3ZpZGVzIGFuIEFQSSB0byByZXNwb25kIHRvIHRob3NlIHJlcXVlc3RzLFxuICogYm90aCBzeW5jaHJvbm91c2x5IGFuZCBhc3luY2hyb25vdXNseS4gVG8gcmVzcG9uZCBzeW5jaHJvbnVvdXNseSwgY2FubmVkXG4gKiBhbnN3ZXJzIGhhdmUgdG8gYmUgcHJvdmlkZWQgdXBmcm9udC5cbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuaWYgKHR5cGVvZiBzaW5vbiA9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgdmFyIHNpbm9uID0ge307XG59XG5cbihmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHB1c2ggPSBbXS5wdXNoO1xuICAgIGZ1bmN0aW9uIEYoKSB7fVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlKHByb3RvKSB7XG4gICAgICAgIEYucHJvdG90eXBlID0gcHJvdG87XG4gICAgICAgIHJldHVybiBuZXcgRigpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlc3BvbnNlQXJyYXkoaGFuZGxlcikge1xuICAgICAgICB2YXIgcmVzcG9uc2UgPSBoYW5kbGVyO1xuXG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaGFuZGxlcikgIT0gXCJbb2JqZWN0IEFycmF5XVwiKSB7XG4gICAgICAgICAgICByZXNwb25zZSA9IFsyMDAsIHt9LCBoYW5kbGVyXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgcmVzcG9uc2VbMl0gIT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkZha2Ugc2VydmVyIHJlc3BvbnNlIGJvZHkgc2hvdWxkIGJlIHN0cmluZywgYnV0IHdhcyBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVvZiByZXNwb25zZVsyXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzcG9uc2U7XG4gICAgfVxuXG4gICAgdmFyIHdsb2MgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93LmxvY2F0aW9uIDoge307XG4gICAgdmFyIHJDdXJyTG9jID0gbmV3IFJlZ0V4cChcIl5cIiArIHdsb2MucHJvdG9jb2wgKyBcIi8vXCIgKyB3bG9jLmhvc3QpO1xuXG4gICAgZnVuY3Rpb24gbWF0Y2hPbmUocmVzcG9uc2UsIHJlcU1ldGhvZCwgcmVxVXJsKSB7XG4gICAgICAgIHZhciBybWV0aCA9IHJlc3BvbnNlLm1ldGhvZDtcbiAgICAgICAgdmFyIG1hdGNoTWV0aG9kID0gIXJtZXRoIHx8IHJtZXRoLnRvTG93ZXJDYXNlKCkgPT0gcmVxTWV0aG9kLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIHZhciB1cmwgPSByZXNwb25zZS51cmw7XG4gICAgICAgIHZhciBtYXRjaFVybCA9ICF1cmwgfHwgdXJsID09IHJlcVVybCB8fCAodHlwZW9mIHVybC50ZXN0ID09IFwiZnVuY3Rpb25cIiAmJiB1cmwudGVzdChyZXFVcmwpKTtcblxuICAgICAgICByZXR1cm4gbWF0Y2hNZXRob2QgJiYgbWF0Y2hVcmw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWF0Y2gocmVzcG9uc2UsIHJlcXVlc3QpIHtcbiAgICAgICAgdmFyIHJlcXVlc3RVcmwgPSByZXF1ZXN0LnVybDtcblxuICAgICAgICBpZiAoIS9eaHR0cHM/OlxcL1xcLy8udGVzdChyZXF1ZXN0VXJsKSB8fCByQ3VyckxvYy50ZXN0KHJlcXVlc3RVcmwpKSB7XG4gICAgICAgICAgICByZXF1ZXN0VXJsID0gcmVxdWVzdFVybC5yZXBsYWNlKHJDdXJyTG9jLCBcIlwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChtYXRjaE9uZShyZXNwb25zZSwgdGhpcy5nZXRIVFRQTWV0aG9kKHJlcXVlc3QpLCByZXF1ZXN0VXJsKSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiByZXNwb25zZS5yZXNwb25zZSA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcnUgPSByZXNwb25zZS51cmw7XG4gICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBbcmVxdWVzdF0uY29uY2F0KHJ1ICYmIHR5cGVvZiBydS5leGVjID09IFwiZnVuY3Rpb25cIiA/IHJ1LmV4ZWMocmVxdWVzdFVybCkuc2xpY2UoMSkgOiBbXSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLnJlc3BvbnNlLmFwcGx5KHJlc3BvbnNlLCBhcmdzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFrZUFwaShzaW5vbikge1xuICAgICAgICBzaW5vbi5mYWtlU2VydmVyID0ge1xuICAgICAgICAgICAgY3JlYXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlcnZlciA9IGNyZWF0ZSh0aGlzKTtcbiAgICAgICAgICAgICAgICBpZiAoIXNpbm9uLnhoci5zdXBwb3J0c0NPUlMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy54aHIgPSBzaW5vbi51c2VGYWtlWERvbWFpblJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnhociA9IHNpbm9uLnVzZUZha2VYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzZXJ2ZXIucmVxdWVzdHMgPSBbXTtcblxuICAgICAgICAgICAgICAgIHRoaXMueGhyLm9uQ3JlYXRlID0gZnVuY3Rpb24gKHhock9iaikge1xuICAgICAgICAgICAgICAgICAgICBzZXJ2ZXIuYWRkUmVxdWVzdCh4aHJPYmopO1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2VydmVyO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgYWRkUmVxdWVzdDogZnVuY3Rpb24gYWRkUmVxdWVzdCh4aHJPYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgc2VydmVyID0gdGhpcztcbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwodGhpcy5yZXF1ZXN0cywgeGhyT2JqKTtcblxuICAgICAgICAgICAgICAgIHhock9iai5vblNlbmQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNlcnZlci5oYW5kbGVSZXF1ZXN0KHRoaXMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChzZXJ2ZXIucmVzcG9uZEltbWVkaWF0ZWx5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXJ2ZXIucmVzcG9uZCgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHNlcnZlci5hdXRvUmVzcG9uZCAmJiAhc2VydmVyLnJlc3BvbmRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcnZlci5yZXNwb25kaW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VydmVyLnJlc3BvbmQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sIHNlcnZlci5hdXRvUmVzcG9uZEFmdGVyIHx8IDEwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgc2VydmVyLnJlc3BvbmRpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGdldEhUVFBNZXRob2Q6IGZ1bmN0aW9uIGdldEhUVFBNZXRob2QocmVxdWVzdCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmZha2VIVFRQTWV0aG9kcyAmJiAvcG9zdC9pLnRlc3QocmVxdWVzdC5tZXRob2QpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBtYXRjaGVzID0gKHJlcXVlc3QucmVxdWVzdEJvZHkgfHwgXCJcIikubWF0Y2goL19tZXRob2Q9KFteXFxiO10rKS8pO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gISFtYXRjaGVzID8gbWF0Y2hlc1sxXSA6IHJlcXVlc3QubWV0aG9kO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXF1ZXN0Lm1ldGhvZDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGhhbmRsZVJlcXVlc3Q6IGZ1bmN0aW9uIGhhbmRsZVJlcXVlc3QoeGhyKSB7XG4gICAgICAgICAgICAgICAgaWYgKHhoci5hc3luYykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMucXVldWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucXVldWUgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbCh0aGlzLnF1ZXVlLCB4aHIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc1JlcXVlc3QoeGhyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBsb2c6IGZ1bmN0aW9uIGxvZyhyZXNwb25zZSwgcmVxdWVzdCkge1xuICAgICAgICAgICAgICAgIHZhciBzdHI7XG5cbiAgICAgICAgICAgICAgICBzdHIgPSAgXCJSZXF1ZXN0OlxcblwiICArIHNpbm9uLmZvcm1hdChyZXF1ZXN0KSAgKyBcIlxcblxcblwiO1xuICAgICAgICAgICAgICAgIHN0ciArPSBcIlJlc3BvbnNlOlxcblwiICsgc2lub24uZm9ybWF0KHJlc3BvbnNlKSArIFwiXFxuXFxuXCI7XG5cbiAgICAgICAgICAgICAgICBzaW5vbi5sb2coc3RyKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlc3BvbmRXaXRoOiBmdW5jdGlvbiByZXNwb25kV2l0aChtZXRob2QsIHVybCwgYm9keSkge1xuICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09IDEgJiYgdHlwZW9mIG1ldGhvZCAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZSA9IHJlc3BvbnNlQXJyYXkobWV0aG9kKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5yZXNwb25zZXMpIHsgdGhpcy5yZXNwb25zZXMgPSBbXTsgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT0gMSkge1xuICAgICAgICAgICAgICAgICAgICBib2R5ID0gbWV0aG9kO1xuICAgICAgICAgICAgICAgICAgICB1cmwgPSBtZXRob2QgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgYm9keSA9IHVybDtcbiAgICAgICAgICAgICAgICAgICAgdXJsID0gbWV0aG9kO1xuICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHB1c2guY2FsbCh0aGlzLnJlc3BvbnNlcywge1xuICAgICAgICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlOiB0eXBlb2YgYm9keSA9PSBcImZ1bmN0aW9uXCIgPyBib2R5IDogcmVzcG9uc2VBcnJheShib2R5KVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgcmVzcG9uZDogZnVuY3Rpb24gcmVzcG9uZCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNwb25kV2l0aC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBxdWV1ZSA9IHRoaXMucXVldWUgfHwgW107XG4gICAgICAgICAgICAgICAgdmFyIHJlcXVlc3RzID0gcXVldWUuc3BsaWNlKDAsIHF1ZXVlLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgdmFyIHJlcXVlc3Q7XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAocmVxdWVzdCA9IHJlcXVlc3RzLnNoaWZ0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzUmVxdWVzdChyZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBwcm9jZXNzUmVxdWVzdDogZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QocmVxdWVzdCkge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXF1ZXN0LmFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciByZXNwb25zZSA9IHRoaXMucmVzcG9uc2UgfHwgWzQwNCwge30sIFwiXCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlc3BvbnNlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbCA9IHRoaXMucmVzcG9uc2VzLmxlbmd0aCwgaSA9IGwgLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5jYWxsKHRoaXMsIHRoaXMucmVzcG9uc2VzW2ldLCByZXF1ZXN0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IHRoaXMucmVzcG9uc2VzW2ldLnJlc3BvbnNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAocmVxdWVzdC5yZWFkeVN0YXRlICE9IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nKHJlc3BvbnNlLCByZXF1ZXN0KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdC5yZXNwb25kKHJlc3BvbnNlWzBdLCByZXNwb25zZVsxXSwgcmVzcG9uc2VbMl0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBzaW5vbi5sb2dFcnJvcihcIkZha2Ugc2VydmVyIHJlcXVlc3QgcHJvY2Vzc2luZ1wiLCBlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICByZXN0b3JlOiBmdW5jdGlvbiByZXN0b3JlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnhoci5yZXN0b3JlICYmIHRoaXMueGhyLnJlc3RvcmUuYXBwbHkodGhpcy54aHIsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgICAgICAgdmFyIHNpbm9uID0gcmVxdWlyZShcIi4vY29yZVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vZmFrZV94ZG9tYWluX3JlcXVlc3RcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2Zha2VfeG1sX2h0dHBfcmVxdWVzdFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4uL2Zvcm1hdFwiKTtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gc2lub247XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0oKSk7XG4iLCIvKipcbiAqIEBkZXBlbmQgZmFrZV9zZXJ2ZXIuanNcbiAqIEBkZXBlbmQgZmFrZV90aW1lcnMuanNcbiAqL1xuLyoqXG4gKiBBZGQtb24gZm9yIHNpbm9uLmZha2VTZXJ2ZXIgdGhhdCBhdXRvbWF0aWNhbGx5IGhhbmRsZXMgYSBmYWtlIHRpbWVyIGFsb25nIHdpdGhcbiAqIHRoZSBGYWtlWE1MSHR0cFJlcXVlc3QuIFRoZSBkaXJlY3QgaW5zcGlyYXRpb24gZm9yIHRoaXMgYWRkLW9uIGlzIGpRdWVyeVxuICogMS4zLngsIHdoaWNoIGRvZXMgbm90IHVzZSB4aHIgb2JqZWN0J3Mgb25yZWFkeXN0YXRlaGFuZGxlciBhdCBhbGwgLSBpbnN0ZWFkLFxuICogaXQgcG9sbHMgdGhlIG9iamVjdCBmb3IgY29tcGxldGlvbiB3aXRoIHNldEludGVydmFsLiBEaXNwaXRlIHRoZSBkaXJlY3RcbiAqIG1vdGl2YXRpb24sIHRoZXJlIGlzIG5vdGhpbmcgalF1ZXJ5LXNwZWNpZmljIGluIHRoaXMgZmlsZSwgc28gaXQgY2FuIGJlIHVzZWRcbiAqIGluIGFueSBlbnZpcm9ubWVudCB3aGVyZSB0aGUgYWpheCBpbXBsZW1lbnRhdGlvbiBkZXBlbmRzIG9uIHNldEludGVydmFsIG9yXG4gKiBzZXRUaW1lb3V0LlxuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgZnVuY3Rpb24gU2VydmVyKCkge31cbiAgICAgICAgU2VydmVyLnByb3RvdHlwZSA9IHNpbm9uLmZha2VTZXJ2ZXI7XG5cbiAgICAgICAgc2lub24uZmFrZVNlcnZlcldpdGhDbG9jayA9IG5ldyBTZXJ2ZXIoKTtcblxuICAgICAgICBzaW5vbi5mYWtlU2VydmVyV2l0aENsb2NrLmFkZFJlcXVlc3QgPSBmdW5jdGlvbiBhZGRSZXF1ZXN0KHhocikge1xuICAgICAgICAgICAgaWYgKHhoci5hc3luYykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc2V0VGltZW91dC5jbG9jayA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2xvY2sgPSBzZXRUaW1lb3V0LmNsb2NrO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2xvY2sgPSBzaW5vbi51c2VGYWtlVGltZXJzKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVzZXRDbG9jayA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmxvbmdlc3RUaW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjbG9ja1NldFRpbWVvdXQgPSB0aGlzLmNsb2NrLnNldFRpbWVvdXQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjbG9ja1NldEludGVydmFsID0gdGhpcy5jbG9jay5zZXRJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNlcnZlciA9IHRoaXM7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jbG9jay5zZXRUaW1lb3V0ID0gZnVuY3Rpb24gKGZuLCB0aW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXJ2ZXIubG9uZ2VzdFRpbWVvdXQgPSBNYXRoLm1heCh0aW1lb3V0LCBzZXJ2ZXIubG9uZ2VzdFRpbWVvdXQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjbG9ja1NldFRpbWVvdXQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNsb2NrLnNldEludGVydmFsID0gZnVuY3Rpb24gKGZuLCB0aW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXJ2ZXIubG9uZ2VzdFRpbWVvdXQgPSBNYXRoLm1heCh0aW1lb3V0LCBzZXJ2ZXIubG9uZ2VzdFRpbWVvdXQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjbG9ja1NldEludGVydmFsLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gc2lub24uZmFrZVNlcnZlci5hZGRSZXF1ZXN0LmNhbGwodGhpcywgeGhyKTtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5mYWtlU2VydmVyV2l0aENsb2NrLnJlc3BvbmQgPSBmdW5jdGlvbiByZXNwb25kKCkge1xuICAgICAgICAgICAgdmFyIHJldHVyblZhbCA9IHNpbm9uLmZha2VTZXJ2ZXIucmVzcG9uZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5jbG9jaykge1xuICAgICAgICAgICAgICAgIHRoaXMuY2xvY2sudGljayh0aGlzLmxvbmdlc3RUaW1lb3V0IHx8IDApO1xuICAgICAgICAgICAgICAgIHRoaXMubG9uZ2VzdFRpbWVvdXQgPSAwO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucmVzZXRDbG9jaykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNsb2NrLnJlc3RvcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNldENsb2NrID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmV0dXJuVmFsO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLmZha2VTZXJ2ZXJXaXRoQ2xvY2sucmVzdG9yZSA9IGZ1bmN0aW9uIHJlc3RvcmUoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jbG9jaykge1xuICAgICAgICAgICAgICAgIHRoaXMuY2xvY2sucmVzdG9yZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gc2lub24uZmFrZVNlcnZlci5yZXN0b3JlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2Zha2Vfc2VydmVyXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9mYWtlX3RpbWVyc1wiKTtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0oKSk7XG4iLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG4vKmdsb2JhbCBsb2xleCAqL1xuXG4vKipcbiAqIEZha2UgdGltZXIgQVBJXG4gKiBzZXRUaW1lb3V0XG4gKiBzZXRJbnRlcnZhbFxuICogY2xlYXJUaW1lb3V0XG4gKiBjbGVhckludGVydmFsXG4gKiB0aWNrXG4gKiByZXNldFxuICogRGF0ZVxuICpcbiAqIEluc3BpcmVkIGJ5IGpzVW5pdE1vY2tUaW1lT3V0IGZyb20gSnNVbml0XG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbmlmICh0eXBlb2Ygc2lub24gPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHZhciBzaW5vbiA9IHt9O1xufVxuXG4oZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24sIGxvbCkge1xuICAgICAgICB2YXIgbGx4ID0gdHlwZW9mIGxvbGV4ICE9PSBcInVuZGVmaW5lZFwiID8gbG9sZXggOiBsb2w7XG5cbiAgICAgICAgc2lub24udXNlRmFrZVRpbWVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBub3csIG1ldGhvZHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG1ldGhvZHNbMF0gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBub3cgPSAwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBub3cgPSBtZXRob2RzLnNoaWZ0KCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBjbG9jayA9IGxseC5pbnN0YWxsKG5vdyB8fCAwLCBtZXRob2RzKTtcbiAgICAgICAgICAgIGNsb2NrLnJlc3RvcmUgPSBjbG9jay51bmluc3RhbGw7XG4gICAgICAgICAgICByZXR1cm4gY2xvY2s7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uY2xvY2sgPSB7XG4gICAgICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uIChub3cpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGx4LmNyZWF0ZUNsb2NrKG5vdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24udGltZXJzID0ge1xuICAgICAgICAgICAgc2V0VGltZW91dDogc2V0VGltZW91dCxcbiAgICAgICAgICAgIGNsZWFyVGltZW91dDogY2xlYXJUaW1lb3V0LFxuICAgICAgICAgICAgc2V0SW1tZWRpYXRlOiAodHlwZW9mIHNldEltbWVkaWF0ZSAhPT0gXCJ1bmRlZmluZWRcIiA/IHNldEltbWVkaWF0ZSA6IHVuZGVmaW5lZCksXG4gICAgICAgICAgICBjbGVhckltbWVkaWF0ZTogKHR5cGVvZiBjbGVhckltbWVkaWF0ZSAhPT0gXCJ1bmRlZmluZWRcIiA/IGNsZWFySW1tZWRpYXRlIDogdW5kZWZpbmVkKSxcbiAgICAgICAgICAgIHNldEludGVydmFsOiBzZXRJbnRlcnZhbCxcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWw6IGNsZWFySW50ZXJ2YWwsXG4gICAgICAgICAgICBEYXRlOiBEYXRlXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBlcHhvcnRzLCBtb2R1bGUsIGxvbGV4KSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL2NvcmVcIik7XG4gICAgICAgIG1ha2VBcGkoc2lub24sIGxvbGV4KTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBzaW5vbjtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgcmVxdWlyZShcImxvbGV4XCIpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KHR5cGVvZiBnbG9iYWwgIT0gXCJ1bmRlZmluZWRcIiAmJiB0eXBlb2YgZ2xvYmFsICE9PSBcImZ1bmN0aW9uXCIgPyBnbG9iYWwgOiB0aGlzKSk7XG5cbn0pLmNhbGwodGhpcyx0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pIiwiLyoqXG4gKiBAZGVwZW5kIGNvcmUuanNcbiAqIEBkZXBlbmQgLi4vZXh0ZW5kLmpzXG4gKiBAZGVwZW5kIGV2ZW50LmpzXG4gKiBAZGVwZW5kIC4uL2xvZ19lcnJvci5qc1xuICovXG4vKipcbiAqIEZha2UgWERvbWFpblJlcXVlc3Qgb2JqZWN0XG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG5pZiAodHlwZW9mIHNpbm9uID09IFwidW5kZWZpbmVkXCIpIHtcbiAgICB0aGlzLnNpbm9uID0ge307XG59XG5cbi8vIHdyYXBwZXIgZm9yIGdsb2JhbFxuKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICB2YXIgeGRyID0geyBYRG9tYWluUmVxdWVzdDogZ2xvYmFsLlhEb21haW5SZXF1ZXN0IH07XG4gICAgeGRyLkdsb2JhbFhEb21haW5SZXF1ZXN0ID0gZ2xvYmFsLlhEb21haW5SZXF1ZXN0O1xuICAgIHhkci5zdXBwb3J0c1hEUiA9IHR5cGVvZiB4ZHIuR2xvYmFsWERvbWFpblJlcXVlc3QgIT0gXCJ1bmRlZmluZWRcIjtcbiAgICB4ZHIud29ya2luZ1hEUiA9IHhkci5zdXBwb3J0c1hEUiA/IHhkci5HbG9iYWxYRG9tYWluUmVxdWVzdCA6ICBmYWxzZTtcblxuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgc2lub24ueGRyID0geGRyO1xuXG4gICAgICAgIGZ1bmN0aW9uIEZha2VYRG9tYWluUmVxdWVzdCgpIHtcbiAgICAgICAgICAgIHRoaXMucmVhZHlTdGF0ZSA9IEZha2VYRG9tYWluUmVxdWVzdC5VTlNFTlQ7XG4gICAgICAgICAgICB0aGlzLnJlcXVlc3RCb2R5ID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMucmVxdWVzdEhlYWRlcnMgPSB7fTtcbiAgICAgICAgICAgIHRoaXMuc3RhdHVzID0gMDtcbiAgICAgICAgICAgIHRoaXMudGltZW91dCA9IG51bGw7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgRmFrZVhEb21haW5SZXF1ZXN0Lm9uQ3JlYXRlID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIEZha2VYRG9tYWluUmVxdWVzdC5vbkNyZWF0ZSh0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHZlcmlmeVN0YXRlKHhkcikge1xuICAgICAgICAgICAgaWYgKHhkci5yZWFkeVN0YXRlICE9PSBGYWtlWERvbWFpblJlcXVlc3QuT1BFTkVEKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSU5WQUxJRF9TVEFURV9FUlJcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh4ZHIuc2VuZEZsYWcpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJTlZBTElEX1NUQVRFX0VSUlwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHZlcmlmeVJlcXVlc3RTZW50KHhkcikge1xuICAgICAgICAgICAgaWYgKHhkci5yZWFkeVN0YXRlID09IEZha2VYRG9tYWluUmVxdWVzdC5VTlNFTlQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZXF1ZXN0IG5vdCBzZW50XCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHhkci5yZWFkeVN0YXRlID09IEZha2VYRG9tYWluUmVxdWVzdC5ET05FKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVxdWVzdCBkb25lXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gdmVyaWZ5UmVzcG9uc2VCb2R5VHlwZShib2R5KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGJvZHkgIT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgIHZhciBlcnJvciA9IG5ldyBFcnJvcihcIkF0dGVtcHRlZCB0byByZXNwb25kIHRvIGZha2UgWERvbWFpblJlcXVlc3Qgd2l0aCBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib2R5ICsgXCIsIHdoaWNoIGlzIG5vdCBhIHN0cmluZy5cIik7XG4gICAgICAgICAgICAgICAgZXJyb3IubmFtZSA9IFwiSW52YWxpZEJvZHlFeGNlcHRpb25cIjtcbiAgICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNpbm9uLmV4dGVuZChGYWtlWERvbWFpblJlcXVlc3QucHJvdG90eXBlLCBzaW5vbi5FdmVudFRhcmdldCwge1xuICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gb3BlbihtZXRob2QsIHVybCkge1xuICAgICAgICAgICAgICAgIHRoaXMubWV0aG9kID0gbWV0aG9kO1xuICAgICAgICAgICAgICAgIHRoaXMudXJsID0gdXJsO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZVRleHQgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMuc2VuZEZsYWcgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIHRoaXMucmVhZHlTdGF0ZUNoYW5nZShGYWtlWERvbWFpblJlcXVlc3QuT1BFTkVEKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlYWR5U3RhdGVDaGFuZ2U6IGZ1bmN0aW9uIHJlYWR5U3RhdGVDaGFuZ2Uoc3RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGUgPSBzdGF0ZTtcbiAgICAgICAgICAgICAgICB2YXIgZXZlbnROYW1lID0gXCJcIjtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMucmVhZHlTdGF0ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgRmFrZVhEb21haW5SZXF1ZXN0LlVOU0VOVDpcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBGYWtlWERvbWFpblJlcXVlc3QuT1BFTkVEOlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEZha2VYRG9tYWluUmVxdWVzdC5MT0FESU5HOlxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZW5kRmxhZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy9yYWlzZSB0aGUgcHJvZ3Jlc3MgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TmFtZSA9IFwib25wcm9ncmVzc1wiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgRmFrZVhEb21haW5SZXF1ZXN0LkRPTkU6XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzVGltZW91dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnROYW1lID0gXCJvbnRpbWVvdXRcIlxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZXJyb3JGbGFnIHx8ICh0aGlzLnN0YXR1cyA8IDIwMCB8fCB0aGlzLnN0YXR1cyA+IDI5OSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TmFtZSA9IFwib25lcnJvclwiO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnROYW1lID0gXCJvbmxvYWRcIlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJhaXNpbmcgZXZlbnQgKGlmIGRlZmluZWQpXG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50TmFtZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaXNbZXZlbnROYW1lXSA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1tldmVudE5hbWVdKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2lub24ubG9nRXJyb3IoXCJGYWtlIFhIUiBcIiArIGV2ZW50TmFtZSArIFwiIGhhbmRsZXJcIiwgZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBzZW5kOiBmdW5jdGlvbiBzZW5kKGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2ZXJpZnlTdGF0ZSh0aGlzKTtcblxuICAgICAgICAgICAgICAgIGlmICghL14oZ2V0fGhlYWQpJC9pLnRlc3QodGhpcy5tZXRob2QpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVxdWVzdEJvZHkgPSBkYXRhO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlcXVlc3RIZWFkZXJzW1wiQ29udGVudC1UeXBlXCJdID0gXCJ0ZXh0L3BsYWluO2NoYXJzZXQ9dXRmLThcIjtcblxuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JGbGFnID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kRmxhZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkeVN0YXRlQ2hhbmdlKEZha2VYRG9tYWluUmVxdWVzdC5PUEVORUQpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm9uU2VuZCA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblNlbmQodGhpcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgYWJvcnQ6IGZ1bmN0aW9uIGFib3J0KCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWJvcnRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZVRleHQgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JGbGFnID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlYWR5U3RhdGUgPiBzaW5vbi5GYWtlWERvbWFpblJlcXVlc3QuVU5TRU5UICYmIHRoaXMuc2VuZEZsYWcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWFkeVN0YXRlQ2hhbmdlKHNpbm9uLkZha2VYRG9tYWluUmVxdWVzdC5ET05FKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZW5kRmxhZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHNldFJlc3BvbnNlQm9keTogZnVuY3Rpb24gc2V0UmVzcG9uc2VCb2R5KGJvZHkpIHtcbiAgICAgICAgICAgICAgICB2ZXJpZnlSZXF1ZXN0U2VudCh0aGlzKTtcbiAgICAgICAgICAgICAgICB2ZXJpZnlSZXNwb25zZUJvZHlUeXBlKGJvZHkpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNodW5rU2l6ZSA9IHRoaXMuY2h1bmtTaXplIHx8IDEwO1xuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZVRleHQgPSBcIlwiO1xuXG4gICAgICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGVDaGFuZ2UoRmFrZVhEb21haW5SZXF1ZXN0LkxPQURJTkcpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlVGV4dCArPSBib2R5LnN1YnN0cmluZyhpbmRleCwgaW5kZXggKyBjaHVua1NpemUpO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaHVua1NpemU7XG4gICAgICAgICAgICAgICAgfSB3aGlsZSAoaW5kZXggPCBib2R5Lmxlbmd0aCk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGVDaGFuZ2UoRmFrZVhEb21haW5SZXF1ZXN0LkRPTkUpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgcmVzcG9uZDogZnVuY3Rpb24gcmVzcG9uZChzdGF0dXMsIGNvbnRlbnRUeXBlLCBib2R5KSB7XG4gICAgICAgICAgICAgICAgLy8gY29udGVudC10eXBlIGlnbm9yZWQsIHNpbmNlIFhEb21haW5SZXF1ZXN0IGRvZXMgbm90IGNhcnJ5IHRoaXNcbiAgICAgICAgICAgICAgICAvLyB3ZSBrZWVwIHRoZSBzYW1lIHN5bnRheCBmb3IgcmVzcG9uZCguLi4pIGFzIGZvciBGYWtlWE1MSHR0cFJlcXVlc3QgdG8gZWFzZVxuICAgICAgICAgICAgICAgIC8vIHRlc3QgaW50ZWdyYXRpb24gYWNyb3NzIGJyb3dzZXJzXG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0dXMgPSB0eXBlb2Ygc3RhdHVzID09IFwibnVtYmVyXCIgPyBzdGF0dXMgOiAyMDA7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRSZXNwb25zZUJvZHkoYm9keSB8fCBcIlwiKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHNpbXVsYXRldGltZW91dDogZnVuY3Rpb24gc2ltdWxhdGV0aW1lb3V0KCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzID0gMDtcbiAgICAgICAgICAgICAgICB0aGlzLmlzVGltZW91dCA9IHRydWU7XG4gICAgICAgICAgICAgICAgLy8gQWNjZXNzIHRvIHRoaXMgc2hvdWxkIGFjdHVhbGx5IHRocm93IGFuIGVycm9yXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZVRleHQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkeVN0YXRlQ2hhbmdlKEZha2VYRG9tYWluUmVxdWVzdC5ET05FKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2lub24uZXh0ZW5kKEZha2VYRG9tYWluUmVxdWVzdCwge1xuICAgICAgICAgICAgVU5TRU5UOiAwLFxuICAgICAgICAgICAgT1BFTkVEOiAxLFxuICAgICAgICAgICAgTE9BRElORzogMyxcbiAgICAgICAgICAgIERPTkU6IDRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2lub24udXNlRmFrZVhEb21haW5SZXF1ZXN0ID0gZnVuY3Rpb24gdXNlRmFrZVhEb21haW5SZXF1ZXN0KCkge1xuICAgICAgICAgICAgc2lub24uRmFrZVhEb21haW5SZXF1ZXN0LnJlc3RvcmUgPSBmdW5jdGlvbiByZXN0b3JlKGtlZXBPbkNyZWF0ZSkge1xuICAgICAgICAgICAgICAgIGlmICh4ZHIuc3VwcG9ydHNYRFIpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2xvYmFsLlhEb21haW5SZXF1ZXN0ID0geGRyLkdsb2JhbFhEb21haW5SZXF1ZXN0O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlbGV0ZSBzaW5vbi5GYWtlWERvbWFpblJlcXVlc3QucmVzdG9yZTtcblxuICAgICAgICAgICAgICAgIGlmIChrZWVwT25DcmVhdGUgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHNpbm9uLkZha2VYRG9tYWluUmVxdWVzdC5vbkNyZWF0ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKHhkci5zdXBwb3J0c1hEUikge1xuICAgICAgICAgICAgICAgIGdsb2JhbC5YRG9tYWluUmVxdWVzdCA9IHNpbm9uLkZha2VYRG9tYWluUmVxdWVzdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzaW5vbi5GYWtlWERvbWFpblJlcXVlc3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uRmFrZVhEb21haW5SZXF1ZXN0ID0gRmFrZVhEb21haW5SZXF1ZXN0O1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuLi9leHRlbmRcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2V2ZW50XCIpO1xuICAgICAgICByZXF1aXJlKFwiLi4vbG9nX2Vycm9yXCIpO1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBzaW5vbjtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufSkodGhpcyk7XG4iLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG4vKipcbiAqIEBkZXBlbmQgY29yZS5qc1xuICogQGRlcGVuZCAuLi9leHRlbmQuanNcbiAqIEBkZXBlbmQgZXZlbnQuanNcbiAqIEBkZXBlbmQgLi4vbG9nX2Vycm9yLmpzXG4gKi9cbi8qKlxuICogRmFrZSBYTUxIdHRwUmVxdWVzdCBvYmplY3RcbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChnbG9iYWwpIHtcblxuICAgIHZhciBzdXBwb3J0c1Byb2dyZXNzID0gdHlwZW9mIFByb2dyZXNzRXZlbnQgIT09IFwidW5kZWZpbmVkXCI7XG4gICAgdmFyIHN1cHBvcnRzQ3VzdG9tRXZlbnQgPSB0eXBlb2YgQ3VzdG9tRXZlbnQgIT09IFwidW5kZWZpbmVkXCI7XG4gICAgdmFyIHNpbm9uWGhyID0geyBYTUxIdHRwUmVxdWVzdDogZ2xvYmFsLlhNTEh0dHBSZXF1ZXN0IH07XG4gICAgc2lub25YaHIuR2xvYmFsWE1MSHR0cFJlcXVlc3QgPSBnbG9iYWwuWE1MSHR0cFJlcXVlc3Q7XG4gICAgc2lub25YaHIuR2xvYmFsQWN0aXZlWE9iamVjdCA9IGdsb2JhbC5BY3RpdmVYT2JqZWN0O1xuICAgIHNpbm9uWGhyLnN1cHBvcnRzQWN0aXZlWCA9IHR5cGVvZiBzaW5vblhoci5HbG9iYWxBY3RpdmVYT2JqZWN0ICE9IFwidW5kZWZpbmVkXCI7XG4gICAgc2lub25YaHIuc3VwcG9ydHNYSFIgPSB0eXBlb2Ygc2lub25YaHIuR2xvYmFsWE1MSHR0cFJlcXVlc3QgIT0gXCJ1bmRlZmluZWRcIjtcbiAgICBzaW5vblhoci53b3JraW5nWEhSID0gc2lub25YaHIuc3VwcG9ydHNYSFIgPyBzaW5vblhoci5HbG9iYWxYTUxIdHRwUmVxdWVzdCA6IHNpbm9uWGhyLnN1cHBvcnRzQWN0aXZlWFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gZnVuY3Rpb24gKCkgeyByZXR1cm4gbmV3IHNpbm9uWGhyLkdsb2JhbEFjdGl2ZVhPYmplY3QoXCJNU1hNTDIuWE1MSFRUUC4zLjBcIikgfSA6IGZhbHNlO1xuICAgIHNpbm9uWGhyLnN1cHBvcnRzQ09SUyA9IHNpbm9uWGhyLnN1cHBvcnRzWEhSICYmIFwid2l0aENyZWRlbnRpYWxzXCIgaW4gKG5ldyBzaW5vblhoci5HbG9iYWxYTUxIdHRwUmVxdWVzdCgpKTtcblxuICAgIC8qanNsOmlnbm9yZSovXG4gICAgdmFyIHVuc2FmZUhlYWRlcnMgPSB7XG4gICAgICAgIFwiQWNjZXB0LUNoYXJzZXRcIjogdHJ1ZSxcbiAgICAgICAgXCJBY2NlcHQtRW5jb2RpbmdcIjogdHJ1ZSxcbiAgICAgICAgQ29ubmVjdGlvbjogdHJ1ZSxcbiAgICAgICAgXCJDb250ZW50LUxlbmd0aFwiOiB0cnVlLFxuICAgICAgICBDb29raWU6IHRydWUsXG4gICAgICAgIENvb2tpZTI6IHRydWUsXG4gICAgICAgIFwiQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZ1wiOiB0cnVlLFxuICAgICAgICBEYXRlOiB0cnVlLFxuICAgICAgICBFeHBlY3Q6IHRydWUsXG4gICAgICAgIEhvc3Q6IHRydWUsXG4gICAgICAgIFwiS2VlcC1BbGl2ZVwiOiB0cnVlLFxuICAgICAgICBSZWZlcmVyOiB0cnVlLFxuICAgICAgICBURTogdHJ1ZSxcbiAgICAgICAgVHJhaWxlcjogdHJ1ZSxcbiAgICAgICAgXCJUcmFuc2Zlci1FbmNvZGluZ1wiOiB0cnVlLFxuICAgICAgICBVcGdyYWRlOiB0cnVlLFxuICAgICAgICBcIlVzZXItQWdlbnRcIjogdHJ1ZSxcbiAgICAgICAgVmlhOiB0cnVlXG4gICAgfTtcbiAgICAvKmpzbDplbmQqL1xuXG4gICAgZnVuY3Rpb24gRmFrZVhNTEh0dHBSZXF1ZXN0KCkge1xuICAgICAgICB0aGlzLnJlYWR5U3RhdGUgPSBGYWtlWE1MSHR0cFJlcXVlc3QuVU5TRU5UO1xuICAgICAgICB0aGlzLnJlcXVlc3RIZWFkZXJzID0ge307XG4gICAgICAgIHRoaXMucmVxdWVzdEJvZHkgPSBudWxsO1xuICAgICAgICB0aGlzLnN0YXR1cyA9IDA7XG4gICAgICAgIHRoaXMuc3RhdHVzVGV4dCA9IFwiXCI7XG4gICAgICAgIHRoaXMudXBsb2FkID0gbmV3IFVwbG9hZFByb2dyZXNzKCk7XG4gICAgICAgIGlmIChzaW5vblhoci5zdXBwb3J0c0NPUlMpIHtcbiAgICAgICAgICAgIHRoaXMud2l0aENyZWRlbnRpYWxzID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgeGhyID0gdGhpcztcbiAgICAgICAgdmFyIGV2ZW50cyA9IFtcImxvYWRzdGFydFwiLCBcImxvYWRcIiwgXCJhYm9ydFwiLCBcImxvYWRlbmRcIl07XG5cbiAgICAgICAgZnVuY3Rpb24gYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWUpIHtcbiAgICAgICAgICAgIHhoci5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdmFyIGxpc3RlbmVyID0geGhyW1wib25cIiArIGV2ZW50TmFtZV07XG5cbiAgICAgICAgICAgICAgICBpZiAobGlzdGVuZXIgJiYgdHlwZW9mIGxpc3RlbmVyID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lci5jYWxsKHRoaXMsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGkgPSBldmVudHMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgICAgIGFkZEV2ZW50TGlzdGVuZXIoZXZlbnRzW2ldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgRmFrZVhNTEh0dHBSZXF1ZXN0Lm9uQ3JlYXRlID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgRmFrZVhNTEh0dHBSZXF1ZXN0Lm9uQ3JlYXRlKHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQW4gdXBsb2FkIG9iamVjdCBpcyBjcmVhdGVkIGZvciBlYWNoXG4gICAgLy8gRmFrZVhNTEh0dHBSZXF1ZXN0IGFuZCBhbGxvd3MgdXBsb2FkXG4gICAgLy8gZXZlbnRzIHRvIGJlIHNpbXVsYXRlZCB1c2luZyB1cGxvYWRQcm9ncmVzc1xuICAgIC8vIGFuZCB1cGxvYWRFcnJvci5cbiAgICBmdW5jdGlvbiBVcGxvYWRQcm9ncmVzcygpIHtcbiAgICAgICAgdGhpcy5ldmVudExpc3RlbmVycyA9IHtcbiAgICAgICAgICAgIHByb2dyZXNzOiBbXSxcbiAgICAgICAgICAgIGxvYWQ6IFtdLFxuICAgICAgICAgICAgYWJvcnQ6IFtdLFxuICAgICAgICAgICAgZXJyb3I6IFtdXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBVcGxvYWRQcm9ncmVzcy5wcm90b3R5cGUuYWRkRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIGFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHRoaXMuZXZlbnRMaXN0ZW5lcnNbZXZlbnRdLnB1c2gobGlzdGVuZXIpO1xuICAgIH07XG5cbiAgICBVcGxvYWRQcm9ncmVzcy5wcm90b3R5cGUucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIGxpc3RlbmVyKSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmV2ZW50TGlzdGVuZXJzW2V2ZW50XSB8fCBbXTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGxpc3RlbmVycy5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0gPT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGlzdGVuZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBVcGxvYWRQcm9ncmVzcy5wcm90b3R5cGUuZGlzcGF0Y2hFdmVudCA9IGZ1bmN0aW9uIGRpc3BhdGNoRXZlbnQoZXZlbnQpIHtcbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuZXZlbnRMaXN0ZW5lcnNbZXZlbnQudHlwZV0gfHwgW107XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxpc3RlbmVyOyAobGlzdGVuZXIgPSBsaXN0ZW5lcnNbaV0pICE9IG51bGw7IGkrKykge1xuICAgICAgICAgICAgbGlzdGVuZXIoZXZlbnQpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIHZlcmlmeVN0YXRlKHhocikge1xuICAgICAgICBpZiAoeGhyLnJlYWR5U3RhdGUgIT09IEZha2VYTUxIdHRwUmVxdWVzdC5PUEVORUQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIklOVkFMSURfU1RBVEVfRVJSXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHhoci5zZW5kRmxhZykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSU5WQUxJRF9TVEFURV9FUlJcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRIZWFkZXIoaGVhZGVycywgaGVhZGVyKSB7XG4gICAgICAgIGhlYWRlciA9IGhlYWRlci50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICAgIGZvciAodmFyIGggaW4gaGVhZGVycykge1xuICAgICAgICAgICAgaWYgKGgudG9Mb3dlckNhc2UoKSA9PSBoZWFkZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIC8vIGZpbHRlcmluZyB0byBlbmFibGUgYSB3aGl0ZS1saXN0IHZlcnNpb24gb2YgU2lub24gRmFrZVhocixcbiAgICAvLyB3aGVyZSB3aGl0ZWxpc3RlZCByZXF1ZXN0cyBhcmUgcGFzc2VkIHRocm91Z2ggdG8gcmVhbCBYSFJcbiAgICBmdW5jdGlvbiBlYWNoKGNvbGxlY3Rpb24sIGNhbGxiYWNrKSB7XG4gICAgICAgIGlmICghY29sbGVjdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBjb2xsZWN0aW9uLmxlbmd0aDsgaSA8IGw7IGkgKz0gMSkge1xuICAgICAgICAgICAgY2FsbGJhY2soY29sbGVjdGlvbltpXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZnVuY3Rpb24gc29tZShjb2xsZWN0aW9uLCBjYWxsYmFjaykge1xuICAgICAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgY29sbGVjdGlvbi5sZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgICAgIGlmIChjYWxsYmFjayhjb2xsZWN0aW9uW2luZGV4XSkgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIC8vIGxhcmdlc3QgYXJpdHkgaW4gWEhSIGlzIDUgLSBYSFIjb3BlblxuICAgIHZhciBhcHBseSA9IGZ1bmN0aW9uIChvYmosIG1ldGhvZCwgYXJncykge1xuICAgICAgICBzd2l0Y2ggKGFyZ3MubGVuZ3RoKSB7XG4gICAgICAgIGNhc2UgMDogcmV0dXJuIG9ialttZXRob2RdKCk7XG4gICAgICAgIGNhc2UgMTogcmV0dXJuIG9ialttZXRob2RdKGFyZ3NbMF0pO1xuICAgICAgICBjYXNlIDI6IHJldHVybiBvYmpbbWV0aG9kXShhcmdzWzBdLCBhcmdzWzFdKTtcbiAgICAgICAgY2FzZSAzOiByZXR1cm4gb2JqW21ldGhvZF0oYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSk7XG4gICAgICAgIGNhc2UgNDogcmV0dXJuIG9ialttZXRob2RdKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10pO1xuICAgICAgICBjYXNlIDU6IHJldHVybiBvYmpbbWV0aG9kXShhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdLCBhcmdzWzNdLCBhcmdzWzRdKTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBGYWtlWE1MSHR0cFJlcXVlc3QuZmlsdGVycyA9IFtdO1xuICAgIEZha2VYTUxIdHRwUmVxdWVzdC5hZGRGaWx0ZXIgPSBmdW5jdGlvbiBhZGRGaWx0ZXIoZm4pIHtcbiAgICAgICAgdGhpcy5maWx0ZXJzLnB1c2goZm4pXG4gICAgfTtcbiAgICB2YXIgSUU2UmUgPSAvTVNJRSA2LztcbiAgICBGYWtlWE1MSHR0cFJlcXVlc3QuZGVmYWtlID0gZnVuY3Rpb24gZGVmYWtlKGZha2VYaHIsIHhockFyZ3MpIHtcbiAgICAgICAgdmFyIHhociA9IG5ldyBzaW5vblhoci53b3JraW5nWEhSKCk7XG4gICAgICAgIGVhY2goW1xuICAgICAgICAgICAgXCJvcGVuXCIsXG4gICAgICAgICAgICBcInNldFJlcXVlc3RIZWFkZXJcIixcbiAgICAgICAgICAgIFwic2VuZFwiLFxuICAgICAgICAgICAgXCJhYm9ydFwiLFxuICAgICAgICAgICAgXCJnZXRSZXNwb25zZUhlYWRlclwiLFxuICAgICAgICAgICAgXCJnZXRBbGxSZXNwb25zZUhlYWRlcnNcIixcbiAgICAgICAgICAgIFwiYWRkRXZlbnRMaXN0ZW5lclwiLFxuICAgICAgICAgICAgXCJvdmVycmlkZU1pbWVUeXBlXCIsXG4gICAgICAgICAgICBcInJlbW92ZUV2ZW50TGlzdGVuZXJcIlxuICAgICAgICBdLCBmdW5jdGlvbiAobWV0aG9kKSB7XG4gICAgICAgICAgICBmYWtlWGhyW21ldGhvZF0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5KHhociwgbWV0aG9kLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdmFyIGNvcHlBdHRycyA9IGZ1bmN0aW9uIChhcmdzKSB7XG4gICAgICAgICAgICBlYWNoKGFyZ3MsIGZ1bmN0aW9uIChhdHRyKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgZmFrZVhoclthdHRyXSA9IHhoclthdHRyXVxuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFJRTZSZS50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIHN0YXRlQ2hhbmdlID0gZnVuY3Rpb24gc3RhdGVDaGFuZ2UoKSB7XG4gICAgICAgICAgICBmYWtlWGhyLnJlYWR5U3RhdGUgPSB4aHIucmVhZHlTdGF0ZTtcbiAgICAgICAgICAgIGlmICh4aHIucmVhZHlTdGF0ZSA+PSBGYWtlWE1MSHR0cFJlcXVlc3QuSEVBREVSU19SRUNFSVZFRCkge1xuICAgICAgICAgICAgICAgIGNvcHlBdHRycyhbXCJzdGF0dXNcIiwgXCJzdGF0dXNUZXh0XCJdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh4aHIucmVhZHlTdGF0ZSA+PSBGYWtlWE1MSHR0cFJlcXVlc3QuTE9BRElORykge1xuICAgICAgICAgICAgICAgIGNvcHlBdHRycyhbXCJyZXNwb25zZVRleHRcIiwgXCJyZXNwb25zZVwiXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoeGhyLnJlYWR5U3RhdGUgPT09IEZha2VYTUxIdHRwUmVxdWVzdC5ET05FKSB7XG4gICAgICAgICAgICAgICAgY29weUF0dHJzKFtcInJlc3BvbnNlWE1MXCJdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChmYWtlWGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSkge1xuICAgICAgICAgICAgICAgIGZha2VYaHIub25yZWFkeXN0YXRlY2hhbmdlLmNhbGwoZmFrZVhociwgeyB0YXJnZXQ6IGZha2VYaHIgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKHhoci5hZGRFdmVudExpc3RlbmVyKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBldmVudCBpbiBmYWtlWGhyLmV2ZW50TGlzdGVuZXJzKSB7XG4gICAgICAgICAgICAgICAgaWYgKGZha2VYaHIuZXZlbnRMaXN0ZW5lcnMuaGFzT3duUHJvcGVydHkoZXZlbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGVhY2goZmFrZVhoci5ldmVudExpc3RlbmVyc1tldmVudF0sIGZ1bmN0aW9uIChoYW5kbGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB4aHIuYWRkRXZlbnRMaXN0ZW5lcihldmVudCwgaGFuZGxlcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHhoci5hZGRFdmVudExpc3RlbmVyKFwicmVhZHlzdGF0ZWNoYW5nZVwiLCBzdGF0ZUNoYW5nZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB4aHIub25yZWFkeXN0YXRlY2hhbmdlID0gc3RhdGVDaGFuZ2U7XG4gICAgICAgIH1cbiAgICAgICAgYXBwbHkoeGhyLCBcIm9wZW5cIiwgeGhyQXJncyk7XG4gICAgfTtcbiAgICBGYWtlWE1MSHR0cFJlcXVlc3QudXNlRmlsdGVycyA9IGZhbHNlO1xuXG4gICAgZnVuY3Rpb24gdmVyaWZ5UmVxdWVzdE9wZW5lZCh4aHIpIHtcbiAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlICE9IEZha2VYTUxIdHRwUmVxdWVzdC5PUEVORUQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIklOVkFMSURfU1RBVEVfRVJSIC0gXCIgKyB4aHIucmVhZHlTdGF0ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB2ZXJpZnlSZXF1ZXN0U2VudCh4aHIpIHtcbiAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlID09IEZha2VYTUxIdHRwUmVxdWVzdC5ET05FKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZXF1ZXN0IGRvbmVcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB2ZXJpZnlIZWFkZXJzUmVjZWl2ZWQoeGhyKSB7XG4gICAgICAgIGlmICh4aHIuYXN5bmMgJiYgeGhyLnJlYWR5U3RhdGUgIT0gRmFrZVhNTEh0dHBSZXF1ZXN0LkhFQURFUlNfUkVDRUlWRUQpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGhlYWRlcnMgcmVjZWl2ZWRcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB2ZXJpZnlSZXNwb25zZUJvZHlUeXBlKGJvZHkpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBib2R5ICE9IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIHZhciBlcnJvciA9IG5ldyBFcnJvcihcIkF0dGVtcHRlZCB0byByZXNwb25kIHRvIGZha2UgWE1MSHR0cFJlcXVlc3Qgd2l0aCBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib2R5ICsgXCIsIHdoaWNoIGlzIG5vdCBhIHN0cmluZy5cIik7XG4gICAgICAgICAgICBlcnJvci5uYW1lID0gXCJJbnZhbGlkQm9keUV4Y2VwdGlvblwiO1xuICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBGYWtlWE1MSHR0cFJlcXVlc3QucGFyc2VYTUwgPSBmdW5jdGlvbiBwYXJzZVhNTCh0ZXh0KSB7XG4gICAgICAgIHZhciB4bWxEb2M7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBET01QYXJzZXIgIT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgdmFyIHBhcnNlciA9IG5ldyBET01QYXJzZXIoKTtcbiAgICAgICAgICAgIHhtbERvYyA9IHBhcnNlci5wYXJzZUZyb21TdHJpbmcodGV4dCwgXCJ0ZXh0L3htbFwiKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHhtbERvYyA9IG5ldyBBY3RpdmVYT2JqZWN0KFwiTWljcm9zb2Z0LlhNTERPTVwiKTtcbiAgICAgICAgICAgIHhtbERvYy5hc3luYyA9IFwiZmFsc2VcIjtcbiAgICAgICAgICAgIHhtbERvYy5sb2FkWE1MKHRleHQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHhtbERvYztcbiAgICB9O1xuXG4gICAgRmFrZVhNTEh0dHBSZXF1ZXN0LnN0YXR1c0NvZGVzID0ge1xuICAgICAgICAxMDA6IFwiQ29udGludWVcIixcbiAgICAgICAgMTAxOiBcIlN3aXRjaGluZyBQcm90b2NvbHNcIixcbiAgICAgICAgMjAwOiBcIk9LXCIsXG4gICAgICAgIDIwMTogXCJDcmVhdGVkXCIsXG4gICAgICAgIDIwMjogXCJBY2NlcHRlZFwiLFxuICAgICAgICAyMDM6IFwiTm9uLUF1dGhvcml0YXRpdmUgSW5mb3JtYXRpb25cIixcbiAgICAgICAgMjA0OiBcIk5vIENvbnRlbnRcIixcbiAgICAgICAgMjA1OiBcIlJlc2V0IENvbnRlbnRcIixcbiAgICAgICAgMjA2OiBcIlBhcnRpYWwgQ29udGVudFwiLFxuICAgICAgICAyMDc6IFwiTXVsdGktU3RhdHVzXCIsXG4gICAgICAgIDMwMDogXCJNdWx0aXBsZSBDaG9pY2VcIixcbiAgICAgICAgMzAxOiBcIk1vdmVkIFBlcm1hbmVudGx5XCIsXG4gICAgICAgIDMwMjogXCJGb3VuZFwiLFxuICAgICAgICAzMDM6IFwiU2VlIE90aGVyXCIsXG4gICAgICAgIDMwNDogXCJOb3QgTW9kaWZpZWRcIixcbiAgICAgICAgMzA1OiBcIlVzZSBQcm94eVwiLFxuICAgICAgICAzMDc6IFwiVGVtcG9yYXJ5IFJlZGlyZWN0XCIsXG4gICAgICAgIDQwMDogXCJCYWQgUmVxdWVzdFwiLFxuICAgICAgICA0MDE6IFwiVW5hdXRob3JpemVkXCIsXG4gICAgICAgIDQwMjogXCJQYXltZW50IFJlcXVpcmVkXCIsXG4gICAgICAgIDQwMzogXCJGb3JiaWRkZW5cIixcbiAgICAgICAgNDA0OiBcIk5vdCBGb3VuZFwiLFxuICAgICAgICA0MDU6IFwiTWV0aG9kIE5vdCBBbGxvd2VkXCIsXG4gICAgICAgIDQwNjogXCJOb3QgQWNjZXB0YWJsZVwiLFxuICAgICAgICA0MDc6IFwiUHJveHkgQXV0aGVudGljYXRpb24gUmVxdWlyZWRcIixcbiAgICAgICAgNDA4OiBcIlJlcXVlc3QgVGltZW91dFwiLFxuICAgICAgICA0MDk6IFwiQ29uZmxpY3RcIixcbiAgICAgICAgNDEwOiBcIkdvbmVcIixcbiAgICAgICAgNDExOiBcIkxlbmd0aCBSZXF1aXJlZFwiLFxuICAgICAgICA0MTI6IFwiUHJlY29uZGl0aW9uIEZhaWxlZFwiLFxuICAgICAgICA0MTM6IFwiUmVxdWVzdCBFbnRpdHkgVG9vIExhcmdlXCIsXG4gICAgICAgIDQxNDogXCJSZXF1ZXN0LVVSSSBUb28gTG9uZ1wiLFxuICAgICAgICA0MTU6IFwiVW5zdXBwb3J0ZWQgTWVkaWEgVHlwZVwiLFxuICAgICAgICA0MTY6IFwiUmVxdWVzdGVkIFJhbmdlIE5vdCBTYXRpc2ZpYWJsZVwiLFxuICAgICAgICA0MTc6IFwiRXhwZWN0YXRpb24gRmFpbGVkXCIsXG4gICAgICAgIDQyMjogXCJVbnByb2Nlc3NhYmxlIEVudGl0eVwiLFxuICAgICAgICA1MDA6IFwiSW50ZXJuYWwgU2VydmVyIEVycm9yXCIsXG4gICAgICAgIDUwMTogXCJOb3QgSW1wbGVtZW50ZWRcIixcbiAgICAgICAgNTAyOiBcIkJhZCBHYXRld2F5XCIsXG4gICAgICAgIDUwMzogXCJTZXJ2aWNlIFVuYXZhaWxhYmxlXCIsXG4gICAgICAgIDUwNDogXCJHYXRld2F5IFRpbWVvdXRcIixcbiAgICAgICAgNTA1OiBcIkhUVFAgVmVyc2lvbiBOb3QgU3VwcG9ydGVkXCJcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbWFrZUFwaShzaW5vbikge1xuICAgICAgICBzaW5vbi54aHIgPSBzaW5vblhocjtcblxuICAgICAgICBzaW5vbi5leHRlbmQoRmFrZVhNTEh0dHBSZXF1ZXN0LnByb3RvdHlwZSwgc2lub24uRXZlbnRUYXJnZXQsIHtcbiAgICAgICAgICAgIGFzeW5jOiB0cnVlLFxuXG4gICAgICAgICAgICBvcGVuOiBmdW5jdGlvbiBvcGVuKG1ldGhvZCwgdXJsLCBhc3luYywgdXNlcm5hbWUsIHBhc3N3b3JkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tZXRob2QgPSBtZXRob2Q7XG4gICAgICAgICAgICAgICAgdGhpcy51cmwgPSB1cmw7XG4gICAgICAgICAgICAgICAgdGhpcy5hc3luYyA9IHR5cGVvZiBhc3luYyA9PSBcImJvb2xlYW5cIiA/IGFzeW5jIDogdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnVzZXJuYW1lID0gdXNlcm5hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXNzd29yZCA9IHBhc3N3b3JkO1xuICAgICAgICAgICAgICAgIHRoaXMucmVzcG9uc2VUZXh0ID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlWE1MID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLnJlcXVlc3RIZWFkZXJzID0ge307XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kRmxhZyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKEZha2VYTUxIdHRwUmVxdWVzdC51c2VGaWx0ZXJzID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB4aHJBcmdzID0gYXJndW1lbnRzO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZGVmYWtlID0gc29tZShGYWtlWE1MSHR0cFJlcXVlc3QuZmlsdGVycywgZnVuY3Rpb24gKGZpbHRlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZpbHRlci5hcHBseSh0aGlzLCB4aHJBcmdzKVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRlZmFrZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEZha2VYTUxIdHRwUmVxdWVzdC5kZWZha2UodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGVDaGFuZ2UoRmFrZVhNTEh0dHBSZXF1ZXN0Lk9QRU5FRCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICByZWFkeVN0YXRlQ2hhbmdlOiBmdW5jdGlvbiByZWFkeVN0YXRlQ2hhbmdlKHN0YXRlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkeVN0YXRlID0gc3RhdGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMub25yZWFkeXN0YXRlY2hhbmdlID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5vbnJlYWR5c3RhdGVjaGFuZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2lub24ubG9nRXJyb3IoXCJGYWtlIFhIUiBvbnJlYWR5c3RhdGVjaGFuZ2UgaGFuZGxlclwiLCBlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgc2lub24uRXZlbnQoXCJyZWFkeXN0YXRlY2hhbmdlXCIpKTtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5yZWFkeVN0YXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgRmFrZVhNTEh0dHBSZXF1ZXN0LkRPTkU6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IHNpbm9uLkV2ZW50KFwibG9hZFwiLCBmYWxzZSwgZmFsc2UsIHRoaXMpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgc2lub24uRXZlbnQoXCJsb2FkZW5kXCIsIGZhbHNlLCBmYWxzZSwgdGhpcykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51cGxvYWQuZGlzcGF0Y2hFdmVudChuZXcgc2lub24uRXZlbnQoXCJsb2FkXCIsIGZhbHNlLCBmYWxzZSwgdGhpcykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN1cHBvcnRzUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnVwbG9hZC5kaXNwYXRjaEV2ZW50KG5ldyBzaW5vbi5Qcm9ncmVzc0V2ZW50KFwicHJvZ3Jlc3NcIiwge2xvYWRlZDogMTAwLCB0b3RhbDogMTAwfSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgc2lub24uUHJvZ3Jlc3NFdmVudChcInByb2dyZXNzXCIsIHtsb2FkZWQ6IDEwMCwgdG90YWw6IDEwMH0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHNldFJlcXVlc3RIZWFkZXI6IGZ1bmN0aW9uIHNldFJlcXVlc3RIZWFkZXIoaGVhZGVyLCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHZlcmlmeVN0YXRlKHRoaXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHVuc2FmZUhlYWRlcnNbaGVhZGVyXSB8fCAvXihTZWMtfFByb3h5LSkvLnRlc3QoaGVhZGVyKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZWZ1c2VkIHRvIHNldCB1bnNhZmUgaGVhZGVyIFxcXCJcIiArIGhlYWRlciArIFwiXFxcIlwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yZXF1ZXN0SGVhZGVyc1toZWFkZXJdKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVxdWVzdEhlYWRlcnNbaGVhZGVyXSArPSBcIixcIiArIHZhbHVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVxdWVzdEhlYWRlcnNbaGVhZGVyXSA9IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8vIEhlbHBzIHRlc3RpbmdcbiAgICAgICAgICAgIHNldFJlc3BvbnNlSGVhZGVyczogZnVuY3Rpb24gc2V0UmVzcG9uc2VIZWFkZXJzKGhlYWRlcnMpIHtcbiAgICAgICAgICAgICAgICB2ZXJpZnlSZXF1ZXN0T3BlbmVkKHRoaXMpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVzcG9uc2VIZWFkZXJzID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBoZWFkZXIgaW4gaGVhZGVycykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaGVhZGVycy5oYXNPd25Qcm9wZXJ0eShoZWFkZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlSGVhZGVyc1toZWFkZXJdID0gaGVhZGVyc1toZWFkZXJdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuYXN5bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWFkeVN0YXRlQ2hhbmdlKEZha2VYTUxIdHRwUmVxdWVzdC5IRUFERVJTX1JFQ0VJVkVEKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGUgPSBGYWtlWE1MSHR0cFJlcXVlc3QuSEVBREVSU19SRUNFSVZFRDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvLyBDdXJyZW50bHkgdHJlYXRzIEFMTCBkYXRhIGFzIGEgRE9NU3RyaW5nIChpLmUuIG5vIERvY3VtZW50KVxuICAgICAgICAgICAgc2VuZDogZnVuY3Rpb24gc2VuZChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmVyaWZ5U3RhdGUodGhpcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoIS9eKGdldHxoZWFkKSQvaS50ZXN0KHRoaXMubWV0aG9kKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY29udGVudFR5cGUgPSBnZXRIZWFkZXIodGhpcy5yZXF1ZXN0SGVhZGVycywgXCJDb250ZW50LVR5cGVcIik7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlcXVlc3RIZWFkZXJzW2NvbnRlbnRUeXBlXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gdGhpcy5yZXF1ZXN0SGVhZGVyc1tjb250ZW50VHlwZV0uc3BsaXQoXCI7XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXF1ZXN0SGVhZGVyc1tjb250ZW50VHlwZV0gPSB2YWx1ZVswXSArIFwiO2NoYXJzZXQ9dXRmLThcIjtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghKGRhdGEgaW5zdGFuY2VvZiBGb3JtRGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVxdWVzdEhlYWRlcnNbXCJDb250ZW50LVR5cGVcIl0gPSBcInRleHQvcGxhaW47Y2hhcnNldD11dGYtOFwiO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXF1ZXN0Qm9keSA9IGRhdGE7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5lcnJvckZsYWcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRGbGFnID0gdGhpcy5hc3luYztcbiAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGVDaGFuZ2UoRmFrZVhNTEh0dHBSZXF1ZXN0Lk9QRU5FRCk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMub25TZW5kID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uU2VuZCh0aGlzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IHNpbm9uLkV2ZW50KFwibG9hZHN0YXJ0XCIsIGZhbHNlLCBmYWxzZSwgdGhpcykpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgYWJvcnQ6IGZ1bmN0aW9uIGFib3J0KCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWJvcnRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZVRleHQgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JGbGFnID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlcXVlc3RIZWFkZXJzID0ge307XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yZWFkeVN0YXRlID4gRmFrZVhNTEh0dHBSZXF1ZXN0LlVOU0VOVCAmJiB0aGlzLnNlbmRGbGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVhZHlTdGF0ZUNoYW5nZShGYWtlWE1MSHR0cFJlcXVlc3QuRE9ORSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2VuZEZsYWcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGUgPSBGYWtlWE1MSHR0cFJlcXVlc3QuVU5TRU5UO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBzaW5vbi5FdmVudChcImFib3J0XCIsIGZhbHNlLCBmYWxzZSwgdGhpcykpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy51cGxvYWQuZGlzcGF0Y2hFdmVudChuZXcgc2lub24uRXZlbnQoXCJhYm9ydFwiLCBmYWxzZSwgZmFsc2UsIHRoaXMpKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5vbmVycm9yID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vbmVycm9yKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZ2V0UmVzcG9uc2VIZWFkZXI6IGZ1bmN0aW9uIGdldFJlc3BvbnNlSGVhZGVyKGhlYWRlcikge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlYWR5U3RhdGUgPCBGYWtlWE1MSHR0cFJlcXVlc3QuSEVBREVSU19SRUNFSVZFRCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoL15TZXQtQ29va2llMj8kL2kudGVzdChoZWFkZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGhlYWRlciA9IGdldEhlYWRlcih0aGlzLnJlc3BvbnNlSGVhZGVycywgaGVhZGVyKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnJlc3BvbnNlSGVhZGVyc1toZWFkZXJdIHx8IG51bGw7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBnZXRBbGxSZXNwb25zZUhlYWRlcnM6IGZ1bmN0aW9uIGdldEFsbFJlc3BvbnNlSGVhZGVycygpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yZWFkeVN0YXRlIDwgRmFrZVhNTEh0dHBSZXF1ZXN0LkhFQURFUlNfUkVDRUlWRUQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGhlYWRlcnMgPSBcIlwiO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaGVhZGVyIGluIHRoaXMucmVzcG9uc2VIZWFkZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlc3BvbnNlSGVhZGVycy5oYXNPd25Qcm9wZXJ0eShoZWFkZXIpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAhL15TZXQtQ29va2llMj8kL2kudGVzdChoZWFkZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXJzICs9IGhlYWRlciArIFwiOiBcIiArIHRoaXMucmVzcG9uc2VIZWFkZXJzW2hlYWRlcl0gKyBcIlxcclxcblwiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhlYWRlcnM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBzZXRSZXNwb25zZUJvZHk6IGZ1bmN0aW9uIHNldFJlc3BvbnNlQm9keShib2R5KSB7XG4gICAgICAgICAgICAgICAgdmVyaWZ5UmVxdWVzdFNlbnQodGhpcyk7XG4gICAgICAgICAgICAgICAgdmVyaWZ5SGVhZGVyc1JlY2VpdmVkKHRoaXMpO1xuICAgICAgICAgICAgICAgIHZlcmlmeVJlc3BvbnNlQm9keVR5cGUoYm9keSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY2h1bmtTaXplID0gdGhpcy5jaHVua1NpemUgfHwgMTA7XG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlVGV4dCA9IFwiXCI7XG5cbiAgICAgICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmFzeW5jKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGVDaGFuZ2UoRmFrZVhNTEh0dHBSZXF1ZXN0LkxPQURJTkcpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZVRleHQgKz0gYm9keS5zdWJzdHJpbmcoaW5kZXgsIGluZGV4ICsgY2h1bmtTaXplKTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2h1bmtTaXplO1xuICAgICAgICAgICAgICAgIH0gd2hpbGUgKGluZGV4IDwgYm9keS5sZW5ndGgpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSB0aGlzLmdldFJlc3BvbnNlSGVhZGVyKFwiQ29udGVudC1UeXBlXCIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucmVzcG9uc2VUZXh0ICYmXG4gICAgICAgICAgICAgICAgICAgICghdHlwZSB8fCAvKHRleHRcXC94bWwpfChhcHBsaWNhdGlvblxcL3htbCl8KFxcK3htbCkvLnRlc3QodHlwZSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlWE1MID0gRmFrZVhNTEh0dHBSZXF1ZXN0LnBhcnNlWE1MKHRoaXMucmVzcG9uc2VUZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVW5hYmxlIHRvIHBhcnNlIFhNTCAtIG5vIGJpZ2dpZVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkeVN0YXRlQ2hhbmdlKEZha2VYTUxIdHRwUmVxdWVzdC5ET05FKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlc3BvbmQ6IGZ1bmN0aW9uIHJlc3BvbmQoc3RhdHVzLCBoZWFkZXJzLCBib2R5KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0dXMgPSB0eXBlb2Ygc3RhdHVzID09IFwibnVtYmVyXCIgPyBzdGF0dXMgOiAyMDA7XG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0dXNUZXh0ID0gRmFrZVhNTEh0dHBSZXF1ZXN0LnN0YXR1c0NvZGVzW3RoaXMuc3RhdHVzXTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFJlc3BvbnNlSGVhZGVycyhoZWFkZXJzIHx8IHt9KTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFJlc3BvbnNlQm9keShib2R5IHx8IFwiXCIpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgdXBsb2FkUHJvZ3Jlc3M6IGZ1bmN0aW9uIHVwbG9hZFByb2dyZXNzKHByb2dyZXNzRXZlbnRSYXcpIHtcbiAgICAgICAgICAgICAgICBpZiAoc3VwcG9ydHNQcm9ncmVzcykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVwbG9hZC5kaXNwYXRjaEV2ZW50KG5ldyBzaW5vbi5Qcm9ncmVzc0V2ZW50KFwicHJvZ3Jlc3NcIiwgcHJvZ3Jlc3NFdmVudFJhdykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGRvd25sb2FkUHJvZ3Jlc3M6IGZ1bmN0aW9uIGRvd25sb2FkUHJvZ3Jlc3MocHJvZ3Jlc3NFdmVudFJhdykge1xuICAgICAgICAgICAgICAgIGlmIChzdXBwb3J0c1Byb2dyZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgc2lub24uUHJvZ3Jlc3NFdmVudChcInByb2dyZXNzXCIsIHByb2dyZXNzRXZlbnRSYXcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB1cGxvYWRFcnJvcjogZnVuY3Rpb24gdXBsb2FkRXJyb3IoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBpZiAoc3VwcG9ydHNDdXN0b21FdmVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnVwbG9hZC5kaXNwYXRjaEV2ZW50KG5ldyBzaW5vbi5DdXN0b21FdmVudChcImVycm9yXCIsIHtkZXRhaWw6IGVycm9yfSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2lub24uZXh0ZW5kKEZha2VYTUxIdHRwUmVxdWVzdCwge1xuICAgICAgICAgICAgVU5TRU5UOiAwLFxuICAgICAgICAgICAgT1BFTkVEOiAxLFxuICAgICAgICAgICAgSEVBREVSU19SRUNFSVZFRDogMixcbiAgICAgICAgICAgIExPQURJTkc6IDMsXG4gICAgICAgICAgICBET05FOiA0XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNpbm9uLnVzZUZha2VYTUxIdHRwUmVxdWVzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIEZha2VYTUxIdHRwUmVxdWVzdC5yZXN0b3JlID0gZnVuY3Rpb24gcmVzdG9yZShrZWVwT25DcmVhdGUpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2lub25YaHIuc3VwcG9ydHNYSFIpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2xvYmFsLlhNTEh0dHBSZXF1ZXN0ID0gc2lub25YaHIuR2xvYmFsWE1MSHR0cFJlcXVlc3Q7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHNpbm9uWGhyLnN1cHBvcnRzQWN0aXZlWCkge1xuICAgICAgICAgICAgICAgICAgICBnbG9iYWwuQWN0aXZlWE9iamVjdCA9IHNpbm9uWGhyLkdsb2JhbEFjdGl2ZVhPYmplY3Q7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVsZXRlIEZha2VYTUxIdHRwUmVxdWVzdC5yZXN0b3JlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGtlZXBPbkNyZWF0ZSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgRmFrZVhNTEh0dHBSZXF1ZXN0Lm9uQ3JlYXRlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoc2lub25YaHIuc3VwcG9ydHNYSFIpIHtcbiAgICAgICAgICAgICAgICBnbG9iYWwuWE1MSHR0cFJlcXVlc3QgPSBGYWtlWE1MSHR0cFJlcXVlc3Q7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzaW5vblhoci5zdXBwb3J0c0FjdGl2ZVgpIHtcbiAgICAgICAgICAgICAgICBnbG9iYWwuQWN0aXZlWE9iamVjdCA9IGZ1bmN0aW9uIEFjdGl2ZVhPYmplY3Qob2JqSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9iaklkID09IFwiTWljcm9zb2Z0LlhNTEhUVFBcIiB8fCAvXk1zeG1sMlxcLlhNTEhUVFAvaS50ZXN0KG9iaklkKSkge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEZha2VYTUxIdHRwUmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBzaW5vblhoci5HbG9iYWxBY3RpdmVYT2JqZWN0KG9iaklkKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gRmFrZVhNTEh0dHBSZXF1ZXN0O1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLkZha2VYTUxIdHRwUmVxdWVzdCA9IEZha2VYTUxIdHRwUmVxdWVzdDtcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi9jb3JlXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi4vZXh0ZW5kXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9ldmVudFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4uL2xvZ19lcnJvclwiKTtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gc2lub247XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHNpbm9uID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbn0pKHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0aGlzKTtcblxufSkuY2FsbCh0aGlzLHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSkiLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG4oKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kICYmIGZ1bmN0aW9uIChtKSB7XG4gICAgZGVmaW5lKFwiZm9ybWF0aW9cIiwgW1wic2Ftc2FtXCJdLCBtKTtcbn0pIHx8ICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIGZ1bmN0aW9uIChtKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBtKHJlcXVpcmUoXCJzYW1zYW1cIikpO1xufSkgfHwgZnVuY3Rpb24gKG0pIHsgdGhpcy5mb3JtYXRpbyA9IG0odGhpcy5zYW1zYW0pOyB9XG4pKGZ1bmN0aW9uIChzYW1zYW0pIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIHZhciBmb3JtYXRpbyA9IHtcbiAgICAgICAgZXhjbHVkZUNvbnN0cnVjdG9yczogW1wiT2JqZWN0XCIsIC9eLiQvXSxcbiAgICAgICAgcXVvdGVTdHJpbmdzOiB0cnVlLFxuICAgICAgICBsaW1pdENoaWxkcmVuQ291bnQ6IDBcbiAgICB9O1xuXG4gICAgdmFyIGhhc093biA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG5cbiAgICB2YXIgc3BlY2lhbE9iamVjdHMgPSBbXTtcbiAgICBpZiAodHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICBzcGVjaWFsT2JqZWN0cy5wdXNoKHsgb2JqZWN0OiBnbG9iYWwsIHZhbHVlOiBcIltvYmplY3QgZ2xvYmFsXVwiIH0pO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIHNwZWNpYWxPYmplY3RzLnB1c2goe1xuICAgICAgICAgICAgb2JqZWN0OiBkb2N1bWVudCxcbiAgICAgICAgICAgIHZhbHVlOiBcIltvYmplY3QgSFRNTERvY3VtZW50XVwiXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICBzcGVjaWFsT2JqZWN0cy5wdXNoKHsgb2JqZWN0OiB3aW5kb3csIHZhbHVlOiBcIltvYmplY3QgV2luZG93XVwiIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZ1bmN0aW9uTmFtZShmdW5jKSB7XG4gICAgICAgIGlmICghZnVuYykgeyByZXR1cm4gXCJcIjsgfVxuICAgICAgICBpZiAoZnVuYy5kaXNwbGF5TmFtZSkgeyByZXR1cm4gZnVuYy5kaXNwbGF5TmFtZTsgfVxuICAgICAgICBpZiAoZnVuYy5uYW1lKSB7IHJldHVybiBmdW5jLm5hbWU7IH1cbiAgICAgICAgdmFyIG1hdGNoZXMgPSBmdW5jLnRvU3RyaW5nKCkubWF0Y2goL2Z1bmN0aW9uXFxzKyhbXlxcKF0rKS9tKTtcbiAgICAgICAgcmV0dXJuIChtYXRjaGVzICYmIG1hdGNoZXNbMV0pIHx8IFwiXCI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29uc3RydWN0b3JOYW1lKGYsIG9iamVjdCkge1xuICAgICAgICB2YXIgbmFtZSA9IGZ1bmN0aW9uTmFtZShvYmplY3QgJiYgb2JqZWN0LmNvbnN0cnVjdG9yKTtcbiAgICAgICAgdmFyIGV4Y2x1ZGVzID0gZi5leGNsdWRlQ29uc3RydWN0b3JzIHx8XG4gICAgICAgICAgICAgICAgZm9ybWF0aW8uZXhjbHVkZUNvbnN0cnVjdG9ycyB8fCBbXTtcblxuICAgICAgICB2YXIgaSwgbDtcbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGV4Y2x1ZGVzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBleGNsdWRlc1tpXSA9PT0gXCJzdHJpbmdcIiAmJiBleGNsdWRlc1tpXSA9PT0gbmFtZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBcIlwiO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChleGNsdWRlc1tpXS50ZXN0ICYmIGV4Y2x1ZGVzW2ldLnRlc3QobmFtZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuYW1lO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzQ2lyY3VsYXIob2JqZWN0LCBvYmplY3RzKSB7XG4gICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0ICE9PSBcIm9iamVjdFwiKSB7IHJldHVybiBmYWxzZTsgfVxuICAgICAgICB2YXIgaSwgbDtcbiAgICAgICAgZm9yIChpID0gMCwgbCA9IG9iamVjdHMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICBpZiAob2JqZWN0c1tpXSA9PT0gb2JqZWN0KSB7IHJldHVybiB0cnVlOyB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFzY2lpKGYsIG9iamVjdCwgcHJvY2Vzc2VkLCBpbmRlbnQpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIHZhciBxcyA9IGYucXVvdGVTdHJpbmdzO1xuICAgICAgICAgICAgdmFyIHF1b3RlID0gdHlwZW9mIHFzICE9PSBcImJvb2xlYW5cIiB8fCBxcztcbiAgICAgICAgICAgIHJldHVybiBwcm9jZXNzZWQgfHwgcXVvdGUgPyAnXCInICsgb2JqZWN0ICsgJ1wiJyA6IG9iamVjdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0ID09PSBcImZ1bmN0aW9uXCIgJiYgIShvYmplY3QgaW5zdGFuY2VvZiBSZWdFeHApKSB7XG4gICAgICAgICAgICByZXR1cm4gYXNjaWkuZnVuYyhvYmplY3QpO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkIHx8IFtdO1xuXG4gICAgICAgIGlmIChpc0NpcmN1bGFyKG9iamVjdCwgcHJvY2Vzc2VkKSkgeyByZXR1cm4gXCJbQ2lyY3VsYXJdXCI7IH1cblxuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iamVjdCkgPT09IFwiW29iamVjdCBBcnJheV1cIikge1xuICAgICAgICAgICAgcmV0dXJuIGFzY2lpLmFycmF5LmNhbGwoZiwgb2JqZWN0LCBwcm9jZXNzZWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFvYmplY3QpIHsgcmV0dXJuIFN0cmluZygoMS9vYmplY3QpID09PSAtSW5maW5pdHkgPyBcIi0wXCIgOiBvYmplY3QpOyB9XG4gICAgICAgIGlmIChzYW1zYW0uaXNFbGVtZW50KG9iamVjdCkpIHsgcmV0dXJuIGFzY2lpLmVsZW1lbnQob2JqZWN0KTsgfVxuXG4gICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LnRvU3RyaW5nID09PSBcImZ1bmN0aW9uXCIgJiZcbiAgICAgICAgICAgICAgICBvYmplY3QudG9TdHJpbmcgIT09IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmplY3QudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBpLCBsO1xuICAgICAgICBmb3IgKGkgPSAwLCBsID0gc3BlY2lhbE9iamVjdHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAob2JqZWN0ID09PSBzcGVjaWFsT2JqZWN0c1tpXS5vYmplY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3BlY2lhbE9iamVjdHNbaV0udmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXNjaWkub2JqZWN0LmNhbGwoZiwgb2JqZWN0LCBwcm9jZXNzZWQsIGluZGVudCk7XG4gICAgfVxuXG4gICAgYXNjaWkuZnVuYyA9IGZ1bmN0aW9uIChmdW5jKSB7XG4gICAgICAgIHJldHVybiBcImZ1bmN0aW9uIFwiICsgZnVuY3Rpb25OYW1lKGZ1bmMpICsgXCIoKSB7fVwiO1xuICAgIH07XG5cbiAgICBhc2NpaS5hcnJheSA9IGZ1bmN0aW9uIChhcnJheSwgcHJvY2Vzc2VkKSB7XG4gICAgICAgIHByb2Nlc3NlZCA9IHByb2Nlc3NlZCB8fCBbXTtcbiAgICAgICAgcHJvY2Vzc2VkLnB1c2goYXJyYXkpO1xuICAgICAgICB2YXIgcGllY2VzID0gW107XG4gICAgICAgIHZhciBpLCBsO1xuICAgICAgICBsID0gKHRoaXMubGltaXRDaGlsZHJlbkNvdW50ID4gMCkgPyBcbiAgICAgICAgICAgIE1hdGgubWluKHRoaXMubGltaXRDaGlsZHJlbkNvdW50LCBhcnJheS5sZW5ndGgpIDogYXJyYXkubGVuZ3RoO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgIHBpZWNlcy5wdXNoKGFzY2lpKHRoaXMsIGFycmF5W2ldLCBwcm9jZXNzZWQpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKGwgPCBhcnJheS5sZW5ndGgpXG4gICAgICAgICAgICBwaWVjZXMucHVzaChcIlsuLi4gXCIgKyAoYXJyYXkubGVuZ3RoIC0gbCkgKyBcIiBtb3JlIGVsZW1lbnRzXVwiKTtcblxuICAgICAgICByZXR1cm4gXCJbXCIgKyBwaWVjZXMuam9pbihcIiwgXCIpICsgXCJdXCI7XG4gICAgfTtcblxuICAgIGFzY2lpLm9iamVjdCA9IGZ1bmN0aW9uIChvYmplY3QsIHByb2Nlc3NlZCwgaW5kZW50KSB7XG4gICAgICAgIHByb2Nlc3NlZCA9IHByb2Nlc3NlZCB8fCBbXTtcbiAgICAgICAgcHJvY2Vzc2VkLnB1c2gob2JqZWN0KTtcbiAgICAgICAgaW5kZW50ID0gaW5kZW50IHx8IDA7XG4gICAgICAgIHZhciBwaWVjZXMgPSBbXSwgcHJvcGVydGllcyA9IHNhbXNhbS5rZXlzKG9iamVjdCkuc29ydCgpO1xuICAgICAgICB2YXIgbGVuZ3RoID0gMztcbiAgICAgICAgdmFyIHByb3AsIHN0ciwgb2JqLCBpLCBrLCBsO1xuICAgICAgICBsID0gKHRoaXMubGltaXRDaGlsZHJlbkNvdW50ID4gMCkgPyBcbiAgICAgICAgICAgIE1hdGgubWluKHRoaXMubGltaXRDaGlsZHJlbkNvdW50LCBwcm9wZXJ0aWVzLmxlbmd0aCkgOiBwcm9wZXJ0aWVzLmxlbmd0aDtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICBwcm9wID0gcHJvcGVydGllc1tpXTtcbiAgICAgICAgICAgIG9iaiA9IG9iamVjdFtwcm9wXTtcblxuICAgICAgICAgICAgaWYgKGlzQ2lyY3VsYXIob2JqLCBwcm9jZXNzZWQpKSB7XG4gICAgICAgICAgICAgICAgc3RyID0gXCJbQ2lyY3VsYXJdXCI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHN0ciA9IGFzY2lpKHRoaXMsIG9iaiwgcHJvY2Vzc2VkLCBpbmRlbnQgKyAyKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3RyID0gKC9cXHMvLnRlc3QocHJvcCkgPyAnXCInICsgcHJvcCArICdcIicgOiBwcm9wKSArIFwiOiBcIiArIHN0cjtcbiAgICAgICAgICAgIGxlbmd0aCArPSBzdHIubGVuZ3RoO1xuICAgICAgICAgICAgcGllY2VzLnB1c2goc3RyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBjb25zID0gY29uc3RydWN0b3JOYW1lKHRoaXMsIG9iamVjdCk7XG4gICAgICAgIHZhciBwcmVmaXggPSBjb25zID8gXCJbXCIgKyBjb25zICsgXCJdIFwiIDogXCJcIjtcbiAgICAgICAgdmFyIGlzID0gXCJcIjtcbiAgICAgICAgZm9yIChpID0gMCwgayA9IGluZGVudDsgaSA8IGs7ICsraSkgeyBpcyArPSBcIiBcIjsgfVxuXG4gICAgICAgIGlmKGwgPCBwcm9wZXJ0aWVzLmxlbmd0aClcbiAgICAgICAgICAgIHBpZWNlcy5wdXNoKFwiWy4uLiBcIiArIChwcm9wZXJ0aWVzLmxlbmd0aCAtIGwpICsgXCIgbW9yZSBlbGVtZW50c11cIik7XG5cbiAgICAgICAgaWYgKGxlbmd0aCArIGluZGVudCA+IDgwKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJlZml4ICsgXCJ7XFxuICBcIiArIGlzICsgcGllY2VzLmpvaW4oXCIsXFxuICBcIiArIGlzKSArIFwiXFxuXCIgK1xuICAgICAgICAgICAgICAgIGlzICsgXCJ9XCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHByZWZpeCArIFwieyBcIiArIHBpZWNlcy5qb2luKFwiLCBcIikgKyBcIiB9XCI7XG4gICAgfTtcblxuICAgIGFzY2lpLmVsZW1lbnQgPSBmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICB2YXIgdGFnTmFtZSA9IGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICB2YXIgYXR0cnMgPSBlbGVtZW50LmF0dHJpYnV0ZXMsIGF0dHIsIHBhaXJzID0gW10sIGF0dHJOYW1lLCBpLCBsLCB2YWw7XG5cbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGF0dHJzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgYXR0ciA9IGF0dHJzLml0ZW0oaSk7XG4gICAgICAgICAgICBhdHRyTmFtZSA9IGF0dHIubm9kZU5hbWUudG9Mb3dlckNhc2UoKS5yZXBsYWNlKFwiaHRtbDpcIiwgXCJcIik7XG4gICAgICAgICAgICB2YWwgPSBhdHRyLm5vZGVWYWx1ZTtcbiAgICAgICAgICAgIGlmIChhdHRyTmFtZSAhPT0gXCJjb250ZW50ZWRpdGFibGVcIiB8fCB2YWwgIT09IFwiaW5oZXJpdFwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEhdmFsKSB7IHBhaXJzLnB1c2goYXR0ck5hbWUgKyBcIj1cXFwiXCIgKyB2YWwgKyBcIlxcXCJcIik7IH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBmb3JtYXR0ZWQgPSBcIjxcIiArIHRhZ05hbWUgKyAocGFpcnMubGVuZ3RoID4gMCA/IFwiIFwiIDogXCJcIik7XG4gICAgICAgIHZhciBjb250ZW50ID0gZWxlbWVudC5pbm5lckhUTUw7XG5cbiAgICAgICAgaWYgKGNvbnRlbnQubGVuZ3RoID4gMjApIHtcbiAgICAgICAgICAgIGNvbnRlbnQgPSBjb250ZW50LnN1YnN0cigwLCAyMCkgKyBcIlsuLi5dXCI7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVzID0gZm9ybWF0dGVkICsgcGFpcnMuam9pbihcIiBcIikgKyBcIj5cIiArIGNvbnRlbnQgK1xuICAgICAgICAgICAgICAgIFwiPC9cIiArIHRhZ05hbWUgKyBcIj5cIjtcblxuICAgICAgICByZXR1cm4gcmVzLnJlcGxhY2UoLyBjb250ZW50RWRpdGFibGU9XCJpbmhlcml0XCIvLCBcIlwiKTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gRm9ybWF0aW8ob3B0aW9ucykge1xuICAgICAgICBmb3IgKHZhciBvcHQgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgdGhpc1tvcHRdID0gb3B0aW9uc1tvcHRdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgRm9ybWF0aW8ucHJvdG90eXBlID0ge1xuICAgICAgICBmdW5jdGlvbk5hbWU6IGZ1bmN0aW9uTmFtZSxcblxuICAgICAgICBjb25maWd1cmU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEZvcm1hdGlvKG9wdGlvbnMpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGNvbnN0cnVjdG9yTmFtZTogZnVuY3Rpb24gKG9iamVjdCkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbnN0cnVjdG9yTmFtZSh0aGlzLCBvYmplY3QpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGFzY2lpOiBmdW5jdGlvbiAob2JqZWN0LCBwcm9jZXNzZWQsIGluZGVudCkge1xuICAgICAgICAgICAgcmV0dXJuIGFzY2lpKHRoaXMsIG9iamVjdCwgcHJvY2Vzc2VkLCBpbmRlbnQpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBGb3JtYXRpby5wcm90b3R5cGU7XG59KTtcblxufSkuY2FsbCh0aGlzLHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSkiLCIoKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kICYmIGZ1bmN0aW9uIChtKSB7IGRlZmluZShcInNhbXNhbVwiLCBtKTsgfSkgfHxcbiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJlxuICAgICAgZnVuY3Rpb24gKG0pIHsgbW9kdWxlLmV4cG9ydHMgPSBtKCk7IH0pIHx8IC8vIE5vZGVcbiBmdW5jdGlvbiAobSkgeyB0aGlzLnNhbXNhbSA9IG0oKTsgfSAvLyBCcm93c2VyIGdsb2JhbHNcbikoZnVuY3Rpb24gKCkge1xuICAgIHZhciBvID0gT2JqZWN0LnByb3RvdHlwZTtcbiAgICB2YXIgZGl2ID0gdHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiICYmIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG5cbiAgICBmdW5jdGlvbiBpc05hTih2YWx1ZSkge1xuICAgICAgICAvLyBVbmxpa2UgZ2xvYmFsIGlzTmFOLCB0aGlzIGF2b2lkcyB0eXBlIGNvZXJjaW9uXG4gICAgICAgIC8vIHR5cGVvZiBjaGVjayBhdm9pZHMgSUUgaG9zdCBvYmplY3QgaXNzdWVzLCBoYXQgdGlwIHRvXG4gICAgICAgIC8vIGxvZGFzaFxuICAgICAgICB2YXIgdmFsID0gdmFsdWU7IC8vIEpzTGludCB0aGlua3MgdmFsdWUgIT09IHZhbHVlIGlzIFwid2VpcmRcIlxuICAgICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiICYmIHZhbHVlICE9PSB2YWw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Q2xhc3ModmFsdWUpIHtcbiAgICAgICAgLy8gUmV0dXJucyB0aGUgaW50ZXJuYWwgW1tDbGFzc11dIGJ5IGNhbGxpbmcgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ1xuICAgICAgICAvLyB3aXRoIHRoZSBwcm92aWRlZCB2YWx1ZSBhcyB0aGlzLiBSZXR1cm4gdmFsdWUgaXMgYSBzdHJpbmcsIG5hbWluZyB0aGVcbiAgICAgICAgLy8gaW50ZXJuYWwgY2xhc3MsIGUuZy4gXCJBcnJheVwiXG4gICAgICAgIHJldHVybiBvLnRvU3RyaW5nLmNhbGwodmFsdWUpLnNwbGl0KC9bIFxcXV0vKVsxXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAbmFtZSBzYW1zYW0uaXNBcmd1bWVudHNcbiAgICAgKiBAcGFyYW0gT2JqZWN0IG9iamVjdFxuICAgICAqXG4gICAgICogUmV0dXJucyBgYHRydWVgYCBpZiBgYG9iamVjdGBgIGlzIGFuIGBgYXJndW1lbnRzYGAgb2JqZWN0LFxuICAgICAqIGBgZmFsc2VgYCBvdGhlcndpc2UuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNBcmd1bWVudHMob2JqZWN0KSB7XG4gICAgICAgIGlmIChnZXRDbGFzcyhvYmplY3QpID09PSAnQXJndW1lbnRzJykgeyByZXR1cm4gdHJ1ZTsgfVxuICAgICAgICBpZiAodHlwZW9mIG9iamVjdCAhPT0gXCJvYmplY3RcIiB8fCB0eXBlb2Ygb2JqZWN0Lmxlbmd0aCAhPT0gXCJudW1iZXJcIiB8fFxuICAgICAgICAgICAgICAgIGdldENsYXNzKG9iamVjdCkgPT09IFwiQXJyYXlcIikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LmNhbGxlZSA9PSBcImZ1bmN0aW9uXCIpIHsgcmV0dXJuIHRydWU7IH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG9iamVjdFtvYmplY3QubGVuZ3RoXSA9IDY7XG4gICAgICAgICAgICBkZWxldGUgb2JqZWN0W29iamVjdC5sZW5ndGhdO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQG5hbWUgc2Ftc2FtLmlzRWxlbWVudFxuICAgICAqIEBwYXJhbSBPYmplY3Qgb2JqZWN0XG4gICAgICpcbiAgICAgKiBSZXR1cm5zIGBgdHJ1ZWBgIGlmIGBgb2JqZWN0YGAgaXMgYSBET00gZWxlbWVudCBub2RlLiBVbmxpa2VcbiAgICAgKiBVbmRlcnNjb3JlLmpzL2xvZGFzaCwgdGhpcyBmdW5jdGlvbiB3aWxsIHJldHVybiBgYGZhbHNlYGAgaWYgYGBvYmplY3RgYFxuICAgICAqIGlzIGFuICplbGVtZW50LWxpa2UqIG9iamVjdCwgaS5lLiBhIHJlZ3VsYXIgb2JqZWN0IHdpdGggYSBgYG5vZGVUeXBlYGBcbiAgICAgKiBwcm9wZXJ0eSB0aGF0IGhvbGRzIHRoZSB2YWx1ZSBgYDFgYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0VsZW1lbnQob2JqZWN0KSB7XG4gICAgICAgIGlmICghb2JqZWN0IHx8IG9iamVjdC5ub2RlVHlwZSAhPT0gMSB8fCAhZGl2KSB7IHJldHVybiBmYWxzZTsgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgb2JqZWN0LmFwcGVuZENoaWxkKGRpdik7XG4gICAgICAgICAgICBvYmplY3QucmVtb3ZlQ2hpbGQoZGl2KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBuYW1lIHNhbXNhbS5rZXlzXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmplY3RcbiAgICAgKlxuICAgICAqIFJldHVybiBhbiBhcnJheSBvZiBvd24gcHJvcGVydHkgbmFtZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24ga2V5cyhvYmplY3QpIHtcbiAgICAgICAgdmFyIGtzID0gW10sIHByb3A7XG4gICAgICAgIGZvciAocHJvcCBpbiBvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wKSkgeyBrcy5wdXNoKHByb3ApOyB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGtzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBuYW1lIHNhbXNhbS5pc0RhdGVcbiAgICAgKiBAcGFyYW0gT2JqZWN0IHZhbHVlXG4gICAgICpcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIG9iamVjdCBpcyBhIGBgRGF0ZWBgLCBvciAqZGF0ZS1saWtlKi4gRHVjayB0eXBpbmdcbiAgICAgKiBvZiBkYXRlIG9iamVjdHMgd29yayBieSBjaGVja2luZyB0aGF0IHRoZSBvYmplY3QgaGFzIGEgYGBnZXRUaW1lYGBcbiAgICAgKiBmdW5jdGlvbiB3aG9zZSByZXR1cm4gdmFsdWUgZXF1YWxzIHRoZSByZXR1cm4gdmFsdWUgZnJvbSB0aGUgb2JqZWN0J3NcbiAgICAgKiBgYHZhbHVlT2ZgYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0RhdGUodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZS5nZXRUaW1lID09IFwiZnVuY3Rpb25cIiAmJlxuICAgICAgICAgICAgdmFsdWUuZ2V0VGltZSgpID09IHZhbHVlLnZhbHVlT2YoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAbmFtZSBzYW1zYW0uaXNOZWdaZXJvXG4gICAgICogQHBhcmFtIE9iamVjdCB2YWx1ZVxuICAgICAqXG4gICAgICogUmV0dXJucyBgYHRydWVgYCBpZiBgYHZhbHVlYGAgaXMgYGAtMGBgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTmVnWmVybyh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlID09PSAtSW5maW5pdHk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQG5hbWUgc2Ftc2FtLmVxdWFsXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmoxXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmoyXG4gICAgICpcbiAgICAgKiBSZXR1cm5zIGBgdHJ1ZWBgIGlmIHR3byBvYmplY3RzIGFyZSBzdHJpY3RseSBlcXVhbC4gQ29tcGFyZWQgdG9cbiAgICAgKiBgYD09PWBgIHRoZXJlIGFyZSB0d28gZXhjZXB0aW9uczpcbiAgICAgKlxuICAgICAqICAgLSBOYU4gaXMgY29uc2lkZXJlZCBlcXVhbCB0byBOYU5cbiAgICAgKiAgIC0gLTAgYW5kICswIGFyZSBub3QgY29uc2lkZXJlZCBlcXVhbFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlkZW50aWNhbChvYmoxLCBvYmoyKSB7XG4gICAgICAgIGlmIChvYmoxID09PSBvYmoyIHx8IChpc05hTihvYmoxKSAmJiBpc05hTihvYmoyKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmoxICE9PSAwIHx8IGlzTmVnWmVybyhvYmoxKSA9PT0gaXNOZWdaZXJvKG9iajIpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBAbmFtZSBzYW1zYW0uZGVlcEVxdWFsXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmoxXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmoyXG4gICAgICpcbiAgICAgKiBEZWVwIGVxdWFsIGNvbXBhcmlzb24uIFR3byB2YWx1ZXMgYXJlIFwiZGVlcCBlcXVhbFwiIGlmOlxuICAgICAqXG4gICAgICogICAtIFRoZXkgYXJlIGVxdWFsLCBhY2NvcmRpbmcgdG8gc2Ftc2FtLmlkZW50aWNhbFxuICAgICAqICAgLSBUaGV5IGFyZSBib3RoIGRhdGUgb2JqZWN0cyByZXByZXNlbnRpbmcgdGhlIHNhbWUgdGltZVxuICAgICAqICAgLSBUaGV5IGFyZSBib3RoIGFycmF5cyBjb250YWluaW5nIGVsZW1lbnRzIHRoYXQgYXJlIGFsbCBkZWVwRXF1YWxcbiAgICAgKiAgIC0gVGhleSBhcmUgb2JqZWN0cyB3aXRoIHRoZSBzYW1lIHNldCBvZiBwcm9wZXJ0aWVzLCBhbmQgZWFjaCBwcm9wZXJ0eVxuICAgICAqICAgICBpbiBgYG9iajFgYCBpcyBkZWVwRXF1YWwgdG8gdGhlIGNvcnJlc3BvbmRpbmcgcHJvcGVydHkgaW4gYGBvYmoyYGBcbiAgICAgKlxuICAgICAqIFN1cHBvcnRzIGN5Y2xpYyBvYmplY3RzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRlZXBFcXVhbEN5Y2xpYyhvYmoxLCBvYmoyKSB7XG5cbiAgICAgICAgLy8gdXNlZCBmb3IgY3ljbGljIGNvbXBhcmlzb25cbiAgICAgICAgLy8gY29udGFpbiBhbHJlYWR5IHZpc2l0ZWQgb2JqZWN0c1xuICAgICAgICB2YXIgb2JqZWN0czEgPSBbXSxcbiAgICAgICAgICAgIG9iamVjdHMyID0gW10sXG4gICAgICAgIC8vIGNvbnRhaW4gcGF0aGVzIChwb3NpdGlvbiBpbiB0aGUgb2JqZWN0IHN0cnVjdHVyZSlcbiAgICAgICAgLy8gb2YgdGhlIGFscmVhZHkgdmlzaXRlZCBvYmplY3RzXG4gICAgICAgIC8vIGluZGV4ZXMgc2FtZSBhcyBpbiBvYmplY3RzIGFycmF5c1xuICAgICAgICAgICAgcGF0aHMxID0gW10sXG4gICAgICAgICAgICBwYXRoczIgPSBbXSxcbiAgICAgICAgLy8gY29udGFpbnMgY29tYmluYXRpb25zIG9mIGFscmVhZHkgY29tcGFyZWQgb2JqZWN0c1xuICAgICAgICAvLyBpbiB0aGUgbWFubmVyOiB7IFwiJDFbJ3JlZiddJDJbJ3JlZiddXCI6IHRydWUgfVxuICAgICAgICAgICAgY29tcGFyZWQgPSB7fTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogdXNlZCB0byBjaGVjaywgaWYgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkgaXMgYW4gb2JqZWN0XG4gICAgICAgICAqIChjeWNsaWMgbG9naWMgaXMgb25seSBuZWVkZWQgZm9yIG9iamVjdHMpXG4gICAgICAgICAqIG9ubHkgbmVlZGVkIGZvciBjeWNsaWMgbG9naWNcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIGlzT2JqZWN0KHZhbHVlKSB7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBCb29sZWFuKSAmJlxuICAgICAgICAgICAgICAgICAgICAhKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkgICAgJiZcbiAgICAgICAgICAgICAgICAgICAgISh2YWx1ZSBpbnN0YW5jZW9mIE51bWJlcikgICYmXG4gICAgICAgICAgICAgICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBSZWdFeHApICAmJlxuICAgICAgICAgICAgICAgICAgICAhKHZhbHVlIGluc3RhbmNlb2YgU3RyaW5nKSkge1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiByZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgZ2l2ZW4gb2JqZWN0IGluIHRoZVxuICAgICAgICAgKiBnaXZlbiBvYmplY3RzIGFycmF5LCAtMSBpZiBub3QgY29udGFpbmVkXG4gICAgICAgICAqIG9ubHkgbmVlZGVkIGZvciBjeWNsaWMgbG9naWNcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIGdldEluZGV4KG9iamVjdHMsIG9iaikge1xuXG4gICAgICAgICAgICB2YXIgaTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBvYmplY3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9iamVjdHNbaV0gPT09IG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGRvZXMgdGhlIHJlY3Vyc2lvbiBmb3IgdGhlIGRlZXAgZXF1YWwgY2hlY2tcbiAgICAgICAgcmV0dXJuIChmdW5jdGlvbiBkZWVwRXF1YWwob2JqMSwgb2JqMiwgcGF0aDEsIHBhdGgyKSB7XG4gICAgICAgICAgICB2YXIgdHlwZTEgPSB0eXBlb2Ygb2JqMTtcbiAgICAgICAgICAgIHZhciB0eXBlMiA9IHR5cGVvZiBvYmoyO1xuXG4gICAgICAgICAgICAvLyA9PSBudWxsIGFsc28gbWF0Y2hlcyB1bmRlZmluZWRcbiAgICAgICAgICAgIGlmIChvYmoxID09PSBvYmoyIHx8XG4gICAgICAgICAgICAgICAgICAgIGlzTmFOKG9iajEpIHx8IGlzTmFOKG9iajIpIHx8XG4gICAgICAgICAgICAgICAgICAgIG9iajEgPT0gbnVsbCB8fCBvYmoyID09IG51bGwgfHxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTEgIT09IFwib2JqZWN0XCIgfHwgdHlwZTIgIT09IFwib2JqZWN0XCIpIHtcblxuICAgICAgICAgICAgICAgIHJldHVybiBpZGVudGljYWwob2JqMSwgb2JqMik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEVsZW1lbnRzIGFyZSBvbmx5IGVxdWFsIGlmIGlkZW50aWNhbChleHBlY3RlZCwgYWN0dWFsKVxuICAgICAgICAgICAgaWYgKGlzRWxlbWVudChvYmoxKSB8fCBpc0VsZW1lbnQob2JqMikpIHsgcmV0dXJuIGZhbHNlOyB9XG5cbiAgICAgICAgICAgIHZhciBpc0RhdGUxID0gaXNEYXRlKG9iajEpLCBpc0RhdGUyID0gaXNEYXRlKG9iajIpO1xuICAgICAgICAgICAgaWYgKGlzRGF0ZTEgfHwgaXNEYXRlMikge1xuICAgICAgICAgICAgICAgIGlmICghaXNEYXRlMSB8fCAhaXNEYXRlMiB8fCBvYmoxLmdldFRpbWUoKSAhPT0gb2JqMi5nZXRUaW1lKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9iajEgaW5zdGFuY2VvZiBSZWdFeHAgJiYgb2JqMiBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgICAgIGlmIChvYmoxLnRvU3RyaW5nKCkgIT09IG9iajIudG9TdHJpbmcoKSkgeyByZXR1cm4gZmFsc2U7IH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGNsYXNzMSA9IGdldENsYXNzKG9iajEpO1xuICAgICAgICAgICAgdmFyIGNsYXNzMiA9IGdldENsYXNzKG9iajIpO1xuICAgICAgICAgICAgdmFyIGtleXMxID0ga2V5cyhvYmoxKTtcbiAgICAgICAgICAgIHZhciBrZXlzMiA9IGtleXMob2JqMik7XG5cbiAgICAgICAgICAgIGlmIChpc0FyZ3VtZW50cyhvYmoxKSB8fCBpc0FyZ3VtZW50cyhvYmoyKSkge1xuICAgICAgICAgICAgICAgIGlmIChvYmoxLmxlbmd0aCAhPT0gb2JqMi5sZW5ndGgpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlMSAhPT0gdHlwZTIgfHwgY2xhc3MxICE9PSBjbGFzczIgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXMxLmxlbmd0aCAhPT0ga2V5czIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBrZXksIGksIGwsXG4gICAgICAgICAgICAgICAgLy8gZm9sbG93aW5nIHZhcnMgYXJlIHVzZWQgZm9yIHRoZSBjeWNsaWMgbG9naWNcbiAgICAgICAgICAgICAgICB2YWx1ZTEsIHZhbHVlMixcbiAgICAgICAgICAgICAgICBpc09iamVjdDEsIGlzT2JqZWN0MixcbiAgICAgICAgICAgICAgICBpbmRleDEsIGluZGV4MixcbiAgICAgICAgICAgICAgICBuZXdQYXRoMSwgbmV3UGF0aDI7XG5cbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGwgPSBrZXlzMS5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICBrZXkgPSBrZXlzMVtpXTtcbiAgICAgICAgICAgICAgICBpZiAoIW8uaGFzT3duUHJvcGVydHkuY2FsbChvYmoyLCBrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBTdGFydCBvZiB0aGUgY3ljbGljIGxvZ2ljXG5cbiAgICAgICAgICAgICAgICB2YWx1ZTEgPSBvYmoxW2tleV07XG4gICAgICAgICAgICAgICAgdmFsdWUyID0gb2JqMltrZXldO1xuXG4gICAgICAgICAgICAgICAgaXNPYmplY3QxID0gaXNPYmplY3QodmFsdWUxKTtcbiAgICAgICAgICAgICAgICBpc09iamVjdDIgPSBpc09iamVjdCh2YWx1ZTIpO1xuXG4gICAgICAgICAgICAgICAgLy8gZGV0ZXJtaW5lLCBpZiB0aGUgb2JqZWN0cyB3ZXJlIGFscmVhZHkgdmlzaXRlZFxuICAgICAgICAgICAgICAgIC8vIChpdCdzIGZhc3RlciB0byBjaGVjayBmb3IgaXNPYmplY3QgZmlyc3QsIHRoYW4gdG9cbiAgICAgICAgICAgICAgICAvLyBnZXQgLTEgZnJvbSBnZXRJbmRleCBmb3Igbm9uIG9iamVjdHMpXG4gICAgICAgICAgICAgICAgaW5kZXgxID0gaXNPYmplY3QxID8gZ2V0SW5kZXgob2JqZWN0czEsIHZhbHVlMSkgOiAtMTtcbiAgICAgICAgICAgICAgICBpbmRleDIgPSBpc09iamVjdDIgPyBnZXRJbmRleChvYmplY3RzMiwgdmFsdWUyKSA6IC0xO1xuXG4gICAgICAgICAgICAgICAgLy8gZGV0ZXJtaW5lIHRoZSBuZXcgcGF0aGVzIG9mIHRoZSBvYmplY3RzXG4gICAgICAgICAgICAgICAgLy8gLSBmb3Igbm9uIGN5Y2xpYyBvYmplY3RzIHRoZSBjdXJyZW50IHBhdGggd2lsbCBiZSBleHRlbmRlZFxuICAgICAgICAgICAgICAgIC8vICAgYnkgY3VycmVudCBwcm9wZXJ0eSBuYW1lXG4gICAgICAgICAgICAgICAgLy8gLSBmb3IgY3ljbGljIG9iamVjdHMgdGhlIHN0b3JlZCBwYXRoIGlzIHRha2VuXG4gICAgICAgICAgICAgICAgbmV3UGF0aDEgPSBpbmRleDEgIT09IC0xXG4gICAgICAgICAgICAgICAgICAgID8gcGF0aHMxW2luZGV4MV1cbiAgICAgICAgICAgICAgICAgICAgOiBwYXRoMSArICdbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXSc7XG4gICAgICAgICAgICAgICAgbmV3UGF0aDIgPSBpbmRleDIgIT09IC0xXG4gICAgICAgICAgICAgICAgICAgID8gcGF0aHMyW2luZGV4Ml1cbiAgICAgICAgICAgICAgICAgICAgOiBwYXRoMiArICdbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXSc7XG5cbiAgICAgICAgICAgICAgICAvLyBzdG9wIHJlY3Vyc2lvbiBpZiBjdXJyZW50IG9iamVjdHMgYXJlIGFscmVhZHkgY29tcGFyZWRcbiAgICAgICAgICAgICAgICBpZiAoY29tcGFyZWRbbmV3UGF0aDEgKyBuZXdQYXRoMl0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtZW1iZXIgdGhlIGN1cnJlbnQgb2JqZWN0cyBhbmQgdGhlaXIgcGF0aGVzXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4MSA9PT0gLTEgJiYgaXNPYmplY3QxKSB7XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdHMxLnB1c2godmFsdWUxKTtcbiAgICAgICAgICAgICAgICAgICAgcGF0aHMxLnB1c2gobmV3UGF0aDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXgyID09PSAtMSAmJiBpc09iamVjdDIpIHtcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0czIucHVzaCh2YWx1ZTIpO1xuICAgICAgICAgICAgICAgICAgICBwYXRoczIucHVzaChuZXdQYXRoMik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtZW1iZXIgdGhhdCB0aGUgY3VycmVudCBvYmplY3RzIGFyZSBhbHJlYWR5IGNvbXBhcmVkXG4gICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0MSAmJiBpc09iamVjdDIpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGFyZWRbbmV3UGF0aDEgKyBuZXdQYXRoMl0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEVuZCBvZiBjeWNsaWMgbG9naWNcblxuICAgICAgICAgICAgICAgIC8vIG5laXRoZXIgdmFsdWUxIG5vciB2YWx1ZTIgaXMgYSBjeWNsZVxuICAgICAgICAgICAgICAgIC8vIGNvbnRpbnVlIHdpdGggbmV4dCBsZXZlbFxuICAgICAgICAgICAgICAgIGlmICghZGVlcEVxdWFsKHZhbHVlMSwgdmFsdWUyLCBuZXdQYXRoMSwgbmV3UGF0aDIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuXG4gICAgICAgIH0ob2JqMSwgb2JqMiwgJyQxJywgJyQyJykpO1xuICAgIH1cblxuICAgIHZhciBtYXRjaDtcblxuICAgIGZ1bmN0aW9uIGFycmF5Q29udGFpbnMoYXJyYXksIHN1YnNldCkge1xuICAgICAgICBpZiAoc3Vic2V0Lmxlbmd0aCA9PT0gMCkgeyByZXR1cm4gdHJ1ZTsgfVxuICAgICAgICB2YXIgaSwgbCwgaiwgaztcbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGFycmF5Lmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgaWYgKG1hdGNoKGFycmF5W2ldLCBzdWJzZXRbMF0pKSB7XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMCwgayA9IHN1YnNldC5sZW5ndGg7IGogPCBrOyArK2opIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFtYXRjaChhcnJheVtpICsgal0sIHN1YnNldFtqXSkpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAbmFtZSBzYW1zYW0ubWF0Y2hcbiAgICAgKiBAcGFyYW0gT2JqZWN0IG9iamVjdFxuICAgICAqIEBwYXJhbSBPYmplY3QgbWF0Y2hlclxuICAgICAqXG4gICAgICogQ29tcGFyZSBhcmJpdHJhcnkgdmFsdWUgYGBvYmplY3RgYCB3aXRoIG1hdGNoZXIuXG4gICAgICovXG4gICAgbWF0Y2ggPSBmdW5jdGlvbiBtYXRjaChvYmplY3QsIG1hdGNoZXIpIHtcbiAgICAgICAgaWYgKG1hdGNoZXIgJiYgdHlwZW9mIG1hdGNoZXIudGVzdCA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hlci50ZXN0KG9iamVjdCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIG1hdGNoZXIgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXIob2JqZWN0KSA9PT0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbWF0Y2hlciA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgbWF0Y2hlciA9IG1hdGNoZXIudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgIHZhciBub3ROdWxsID0gdHlwZW9mIG9iamVjdCA9PT0gXCJzdHJpbmdcIiB8fCAhIW9iamVjdDtcbiAgICAgICAgICAgIHJldHVybiBub3ROdWxsICYmXG4gICAgICAgICAgICAgICAgKFN0cmluZyhvYmplY3QpKS50b0xvd2VyQ2FzZSgpLmluZGV4T2YobWF0Y2hlcikgPj0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbWF0Y2hlciA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXIgPT09IG9iamVjdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbWF0Y2hlciA9PT0gXCJib29sZWFuXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBtYXRjaGVyID09PSBvYmplY3Q7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mKG1hdGNoZXIpID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICByZXR1cm4gdHlwZW9mKG9iamVjdCkgPT09IFwidW5kZWZpbmVkXCI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWF0Y2hlciA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdCA9PT0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChnZXRDbGFzcyhvYmplY3QpID09PSBcIkFycmF5XCIgJiYgZ2V0Q2xhc3MobWF0Y2hlcikgPT09IFwiQXJyYXlcIikge1xuICAgICAgICAgICAgcmV0dXJuIGFycmF5Q29udGFpbnMob2JqZWN0LCBtYXRjaGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChtYXRjaGVyICYmIHR5cGVvZiBtYXRjaGVyID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBpZiAobWF0Y2hlciA9PT0gb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcHJvcDtcbiAgICAgICAgICAgIGZvciAocHJvcCBpbiBtYXRjaGVyKSB7XG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gb2JqZWN0W3Byb3BdO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwidW5kZWZpbmVkXCIgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVvZiBvYmplY3QuZ2V0QXR0cmlidXRlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBvYmplY3QuZ2V0QXR0cmlidXRlKHByb3ApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWF0Y2hlcltwcm9wXSA9PT0gbnVsbCB8fCB0eXBlb2YgbWF0Y2hlcltwcm9wXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlICE9PSBtYXRjaGVyW3Byb3BdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiAgdmFsdWUgPT09IFwidW5kZWZpbmVkXCIgfHwgIW1hdGNoKHZhbHVlLCBtYXRjaGVyW3Byb3BdKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJNYXRjaGVyIHdhcyBub3QgYSBzdHJpbmcsIGEgbnVtYmVyLCBhIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiZnVuY3Rpb24sIGEgYm9vbGVhbiBvciBhbiBvYmplY3RcIik7XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGlzQXJndW1lbnRzOiBpc0FyZ3VtZW50cyxcbiAgICAgICAgaXNFbGVtZW50OiBpc0VsZW1lbnQsXG4gICAgICAgIGlzRGF0ZTogaXNEYXRlLFxuICAgICAgICBpc05lZ1plcm86IGlzTmVnWmVybyxcbiAgICAgICAgaWRlbnRpY2FsOiBpZGVudGljYWwsXG4gICAgICAgIGRlZXBFcXVhbDogZGVlcEVxdWFsQ3ljbGljLFxuICAgICAgICBtYXRjaDogbWF0Y2gsXG4gICAgICAgIGtleXM6IGtleXNcbiAgICB9O1xufSk7XG4iLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG4vKmpzbGludCBlcWVxZXE6IGZhbHNlLCBwbHVzcGx1czogZmFsc2UsIGV2aWw6IHRydWUsIG9uZXZhcjogZmFsc2UsIGJyb3dzZXI6IHRydWUsIGZvcmluOiBmYWxzZSovXG4vKmdsb2JhbCBnbG9iYWwqL1xuLyoqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubykgYW5kIGNvbnRyaWJ1dG9yc1xuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTQgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4vLyBub2RlIGV4cGVjdHMgc2V0VGltZW91dC9zZXRJbnRlcnZhbCB0byByZXR1cm4gYSBmbiBvYmplY3Qgdy8gLnJlZigpLy51bnJlZigpXG4vLyBicm93c2VycywgYSBudW1iZXIuXG4vLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2Nqb2hhbnNlbi9TaW5vbi5KUy9wdWxsLzQzNlxudmFyIHRpbWVvdXRSZXN1bHQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge30sIDApO1xudmFyIGFkZFRpbWVyUmV0dXJuc09iamVjdCA9IHR5cGVvZiB0aW1lb3V0UmVzdWx0ID09PSBcIm9iamVjdFwiO1xuY2xlYXJUaW1lb3V0KHRpbWVvdXRSZXN1bHQpO1xuXG52YXIgTmF0aXZlRGF0ZSA9IERhdGU7XG52YXIgaWQgPSAxO1xuXG4vKipcbiAqIFBhcnNlIHN0cmluZ3MgbGlrZSBcIjAxOjEwOjAwXCIgKG1lYW5pbmcgMSBob3VyLCAxMCBtaW51dGVzLCAwIHNlY29uZHMpIGludG9cbiAqIG51bWJlciBvZiBtaWxsaXNlY29uZHMuIFRoaXMgaXMgdXNlZCB0byBzdXBwb3J0IGh1bWFuLXJlYWRhYmxlIHN0cmluZ3MgcGFzc2VkXG4gKiB0byBjbG9jay50aWNrKClcbiAqL1xuZnVuY3Rpb24gcGFyc2VUaW1lKHN0cikge1xuICAgIGlmICghc3RyKSB7XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIHZhciBzdHJpbmdzID0gc3RyLnNwbGl0KFwiOlwiKTtcbiAgICB2YXIgbCA9IHN0cmluZ3MubGVuZ3RoLCBpID0gbDtcbiAgICB2YXIgbXMgPSAwLCBwYXJzZWQ7XG5cbiAgICBpZiAobCA+IDMgfHwgIS9eKFxcZFxcZDopezAsMn1cXGRcXGQ/JC8udGVzdChzdHIpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcInRpY2sgb25seSB1bmRlcnN0YW5kcyBudW1iZXJzIGFuZCAnaDptOnMnXCIpO1xuICAgIH1cblxuICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgcGFyc2VkID0gcGFyc2VJbnQoc3RyaW5nc1tpXSwgMTApO1xuXG4gICAgICAgIGlmIChwYXJzZWQgPj0gNjApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgdGltZSBcIiArIHN0cik7XG4gICAgICAgIH1cblxuICAgICAgICBtcyArPSBwYXJzZWQgKiBNYXRoLnBvdyg2MCwgKGwgLSBpIC0gMSkpO1xuICAgIH1cblxuICAgIHJldHVybiBtcyAqIDEwMDA7XG59XG5cbi8qKlxuICogVXNlZCB0byBncm9rIHRoZSBgbm93YCBwYXJhbWV0ZXIgdG8gY3JlYXRlQ2xvY2suXG4gKi9cbmZ1bmN0aW9uIGdldEVwb2NoKGVwb2NoKSB7XG4gICAgaWYgKCFlcG9jaCkgeyByZXR1cm4gMDsgfVxuICAgIGlmICh0eXBlb2YgZXBvY2guZ2V0VGltZSA9PT0gXCJmdW5jdGlvblwiKSB7IHJldHVybiBlcG9jaC5nZXRUaW1lKCk7IH1cbiAgICBpZiAodHlwZW9mIGVwb2NoID09PSBcIm51bWJlclwiKSB7IHJldHVybiBlcG9jaDsgfVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJub3cgc2hvdWxkIGJlIG1pbGxpc2Vjb25kcyBzaW5jZSBVTklYIGVwb2NoXCIpO1xufVxuXG5mdW5jdGlvbiBpblJhbmdlKGZyb20sIHRvLCB0aW1lcikge1xuICAgIHJldHVybiB0aW1lciAmJiB0aW1lci5jYWxsQXQgPj0gZnJvbSAmJiB0aW1lci5jYWxsQXQgPD0gdG87XG59XG5cbmZ1bmN0aW9uIG1pcnJvckRhdGVQcm9wZXJ0aWVzKHRhcmdldCwgc291cmNlKSB7XG4gICAgaWYgKHNvdXJjZS5ub3cpIHtcbiAgICAgICAgdGFyZ2V0Lm5vdyA9IGZ1bmN0aW9uIG5vdygpIHtcbiAgICAgICAgICAgIHJldHVybiB0YXJnZXQuY2xvY2subm93O1xuICAgICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGRlbGV0ZSB0YXJnZXQubm93O1xuICAgIH1cblxuICAgIGlmIChzb3VyY2UudG9Tb3VyY2UpIHtcbiAgICAgICAgdGFyZ2V0LnRvU291cmNlID0gZnVuY3Rpb24gdG9Tb3VyY2UoKSB7XG4gICAgICAgICAgICByZXR1cm4gc291cmNlLnRvU291cmNlKCk7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZGVsZXRlIHRhcmdldC50b1NvdXJjZTtcbiAgICB9XG5cbiAgICB0YXJnZXQudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIHNvdXJjZS50b1N0cmluZygpO1xuICAgIH07XG5cbiAgICB0YXJnZXQucHJvdG90eXBlID0gc291cmNlLnByb3RvdHlwZTtcbiAgICB0YXJnZXQucGFyc2UgPSBzb3VyY2UucGFyc2U7XG4gICAgdGFyZ2V0LlVUQyA9IHNvdXJjZS5VVEM7XG4gICAgdGFyZ2V0LnByb3RvdHlwZS50b1VUQ1N0cmluZyA9IHNvdXJjZS5wcm90b3R5cGUudG9VVENTdHJpbmc7XG5cbiAgICBmb3IgKHZhciBwcm9wIGluIHNvdXJjZSkge1xuICAgICAgICBpZiAoc291cmNlLmhhc093blByb3BlcnR5KHByb3ApKSB7XG4gICAgICAgICAgICB0YXJnZXRbcHJvcF0gPSBzb3VyY2VbcHJvcF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGFyZ2V0O1xufVxuXG5mdW5jdGlvbiBjcmVhdGVEYXRlKCkge1xuICAgIGZ1bmN0aW9uIENsb2NrRGF0ZSh5ZWFyLCBtb250aCwgZGF0ZSwgaG91ciwgbWludXRlLCBzZWNvbmQsIG1zKSB7XG4gICAgICAgIC8vIERlZmVuc2l2ZSBhbmQgdmVyYm9zZSB0byBhdm9pZCBwb3RlbnRpYWwgaGFybSBpbiBwYXNzaW5nXG4gICAgICAgIC8vIGV4cGxpY2l0IHVuZGVmaW5lZCB3aGVuIHVzZXIgZG9lcyBub3QgcGFzcyBhcmd1bWVudFxuICAgICAgICBzd2l0Y2ggKGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKENsb2NrRGF0ZS5jbG9jay5ub3cpO1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICByZXR1cm4gbmV3IE5hdGl2ZURhdGUoeWVhcik7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgIHJldHVybiBuZXcgTmF0aXZlRGF0ZSh5ZWFyLCBtb250aCk7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgIHJldHVybiBuZXcgTmF0aXZlRGF0ZSh5ZWFyLCBtb250aCwgZGF0ZSk7XG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgIHJldHVybiBuZXcgTmF0aXZlRGF0ZSh5ZWFyLCBtb250aCwgZGF0ZSwgaG91cik7XG4gICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgIHJldHVybiBuZXcgTmF0aXZlRGF0ZSh5ZWFyLCBtb250aCwgZGF0ZSwgaG91ciwgbWludXRlKTtcbiAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKHllYXIsIG1vbnRoLCBkYXRlLCBob3VyLCBtaW51dGUsIHNlY29uZCk7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gbmV3IE5hdGl2ZURhdGUoeWVhciwgbW9udGgsIGRhdGUsIGhvdXIsIG1pbnV0ZSwgc2Vjb25kLCBtcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbWlycm9yRGF0ZVByb3BlcnRpZXMoQ2xvY2tEYXRlLCBOYXRpdmVEYXRlKTtcbn1cblxuZnVuY3Rpb24gYWRkVGltZXIoY2xvY2ssIHRpbWVyKSB7XG4gICAgaWYgKHR5cGVvZiB0aW1lci5mdW5jID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbGxiYWNrIG11c3QgYmUgcHJvdmlkZWQgdG8gdGltZXIgY2FsbHNcIik7XG4gICAgfVxuXG4gICAgaWYgKCFjbG9jay50aW1lcnMpIHtcbiAgICAgICAgY2xvY2sudGltZXJzID0ge307XG4gICAgfVxuXG4gICAgdGltZXIuaWQgPSBpZCsrO1xuICAgIHRpbWVyLmNyZWF0ZWRBdCA9IGNsb2NrLm5vdztcbiAgICB0aW1lci5jYWxsQXQgPSBjbG9jay5ub3cgKyAodGltZXIuZGVsYXkgfHwgMCk7XG5cbiAgICBjbG9jay50aW1lcnNbdGltZXIuaWRdID0gdGltZXI7XG5cbiAgICBpZiAoYWRkVGltZXJSZXR1cm5zT2JqZWN0KSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBpZDogdGltZXIuaWQsXG4gICAgICAgICAgICByZWY6IGZ1bmN0aW9uKCkge30sXG4gICAgICAgICAgICB1bnJlZjogZnVuY3Rpb24oKSB7fVxuICAgICAgICB9O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRpbWVyLmlkO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZmlyc3RUaW1lckluUmFuZ2UoY2xvY2ssIGZyb20sIHRvKSB7XG4gICAgdmFyIHRpbWVycyA9IGNsb2NrLnRpbWVycywgdGltZXIgPSBudWxsO1xuXG4gICAgZm9yICh2YXIgaWQgaW4gdGltZXJzKSB7XG4gICAgICAgIGlmICghaW5SYW5nZShmcm9tLCB0bywgdGltZXJzW2lkXSkpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aW1lciB8fCB+Y29tcGFyZVRpbWVycyh0aW1lciwgdGltZXJzW2lkXSkpIHtcbiAgICAgICAgICAgIHRpbWVyID0gdGltZXJzW2lkXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0aW1lcjtcbn1cblxuZnVuY3Rpb24gY29tcGFyZVRpbWVycyhhLCBiKSB7XG4gICAgLy8gU29ydCBmaXJzdCBieSBhYnNvbHV0ZSB0aW1pbmdcbiAgICBpZiAoYS5jYWxsQXQgPCBiLmNhbGxBdCkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuICAgIGlmIChhLmNhbGxBdCA+IGIuY2FsbEF0KSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH1cblxuICAgIC8vIFNvcnQgbmV4dCBieSBpbW1lZGlhdGUsIGltbWVkaWF0ZSB0aW1lcnMgdGFrZSBwcmVjZWRlbmNlXG4gICAgaWYgKGEuaW1tZWRpYXRlICYmICFiLmltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuICAgIGlmICghYS5pbW1lZGlhdGUgJiYgYi5pbW1lZGlhdGUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuXG4gICAgLy8gU29ydCBuZXh0IGJ5IGNyZWF0aW9uIHRpbWUsIGVhcmxpZXItY3JlYXRlZCB0aW1lcnMgdGFrZSBwcmVjZWRlbmNlXG4gICAgaWYgKGEuY3JlYXRlZEF0IDwgYi5jcmVhdGVkQXQpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cbiAgICBpZiAoYS5jcmVhdGVkQXQgPiBiLmNyZWF0ZWRBdCkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICB9XG5cbiAgICAvLyBTb3J0IG5leHQgYnkgaWQsIGxvd2VyLWlkIHRpbWVycyB0YWtlIHByZWNlZGVuY2VcbiAgICBpZiAoYS5pZCA8IGIuaWQpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgIH1cbiAgICBpZiAoYS5pZCA+IGIuaWQpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuXG4gICAgLy8gQXMgdGltZXIgaWRzIGFyZSB1bmlxdWUsIG5vIGZhbGxiYWNrIGAwYCBpcyBuZWNlc3Nhcnlcbn1cblxuZnVuY3Rpb24gY2FsbFRpbWVyKGNsb2NrLCB0aW1lcikge1xuICAgIGlmICh0eXBlb2YgdGltZXIuaW50ZXJ2YWwgPT0gXCJudW1iZXJcIikge1xuICAgICAgICBjbG9jay50aW1lcnNbdGltZXIuaWRdLmNhbGxBdCArPSB0aW1lci5pbnRlcnZhbDtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkZWxldGUgY2xvY2sudGltZXJzW3RpbWVyLmlkXTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIHRpbWVyLmZ1bmMgPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICB0aW1lci5mdW5jLmFwcGx5KG51bGwsIHRpbWVyLmFyZ3MpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXZhbCh0aW1lci5mdW5jKTtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgdmFyIGV4Y2VwdGlvbiA9IGU7XG4gICAgfVxuXG4gICAgaWYgKCFjbG9jay50aW1lcnNbdGltZXIuaWRdKSB7XG4gICAgICAgIGlmIChleGNlcHRpb24pIHtcbiAgICAgICAgICAgIHRocm93IGV4Y2VwdGlvbjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGV4Y2VwdGlvbikge1xuICAgICAgICB0aHJvdyBleGNlcHRpb247XG4gICAgfVxufVxuXG5mdW5jdGlvbiB1bmluc3RhbGwoY2xvY2ssIHRhcmdldCkge1xuICAgIHZhciBtZXRob2Q7XG5cbiAgICBmb3IgKHZhciBpID0gMCwgbCA9IGNsb2NrLm1ldGhvZHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgIG1ldGhvZCA9IGNsb2NrLm1ldGhvZHNbaV07XG5cbiAgICAgICAgaWYgKHRhcmdldFttZXRob2RdLmhhZE93blByb3BlcnR5KSB7XG4gICAgICAgICAgICB0YXJnZXRbbWV0aG9kXSA9IGNsb2NrW1wiX1wiICsgbWV0aG9kXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRhcmdldFttZXRob2RdO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIFByZXZlbnQgbXVsdGlwbGUgZXhlY3V0aW9ucyB3aGljaCB3aWxsIGNvbXBsZXRlbHkgcmVtb3ZlIHRoZXNlIHByb3BzXG4gICAgY2xvY2subWV0aG9kcyA9IFtdO1xufVxuXG5mdW5jdGlvbiBoaWphY2tNZXRob2QodGFyZ2V0LCBtZXRob2QsIGNsb2NrKSB7XG4gICAgY2xvY2tbbWV0aG9kXS5oYWRPd25Qcm9wZXJ0eSA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCh0YXJnZXQsIG1ldGhvZCk7XG4gICAgY2xvY2tbXCJfXCIgKyBtZXRob2RdID0gdGFyZ2V0W21ldGhvZF07XG5cbiAgICBpZiAobWV0aG9kID09IFwiRGF0ZVwiKSB7XG4gICAgICAgIHZhciBkYXRlID0gbWlycm9yRGF0ZVByb3BlcnRpZXMoY2xvY2tbbWV0aG9kXSwgdGFyZ2V0W21ldGhvZF0pO1xuICAgICAgICB0YXJnZXRbbWV0aG9kXSA9IGRhdGU7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGFyZ2V0W21ldGhvZF0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gY2xvY2tbbWV0aG9kXS5hcHBseShjbG9jaywgYXJndW1lbnRzKTtcbiAgICAgICAgfTtcblxuICAgICAgICBmb3IgKHZhciBwcm9wIGluIGNsb2NrW21ldGhvZF0pIHtcbiAgICAgICAgICAgIGlmIChjbG9ja1ttZXRob2RdLmhhc093blByb3BlcnR5KHByb3ApKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0W21ldGhvZF1bcHJvcF0gPSBjbG9ja1ttZXRob2RdW3Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGFyZ2V0W21ldGhvZF0uY2xvY2sgPSBjbG9jaztcbn1cblxudmFyIHRpbWVycyA9IHtcbiAgICBzZXRUaW1lb3V0OiBzZXRUaW1lb3V0LFxuICAgIGNsZWFyVGltZW91dDogY2xlYXJUaW1lb3V0LFxuICAgIHNldEltbWVkaWF0ZTogKHR5cGVvZiBzZXRJbW1lZGlhdGUgIT09IFwidW5kZWZpbmVkXCIgPyBzZXRJbW1lZGlhdGUgOiB1bmRlZmluZWQpLFxuICAgIGNsZWFySW1tZWRpYXRlOiAodHlwZW9mIGNsZWFySW1tZWRpYXRlICE9PSBcInVuZGVmaW5lZFwiID8gY2xlYXJJbW1lZGlhdGU6IHVuZGVmaW5lZCksXG4gICAgc2V0SW50ZXJ2YWw6IHNldEludGVydmFsLFxuICAgIGNsZWFySW50ZXJ2YWw6IGNsZWFySW50ZXJ2YWwsXG4gICAgRGF0ZTogRGF0ZVxufTtcblxudmFyIGtleXMgPSBPYmplY3Qua2V5cyB8fCBmdW5jdGlvbiAob2JqKSB7XG4gICAgdmFyIGtzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICBrcy5wdXNoKGtleSk7XG4gICAgfVxuICAgIHJldHVybiBrcztcbn07XG5cbmV4cG9ydHMudGltZXJzID0gdGltZXJzO1xuXG52YXIgY3JlYXRlQ2xvY2sgPSBleHBvcnRzLmNyZWF0ZUNsb2NrID0gZnVuY3Rpb24gKG5vdykge1xuICAgIHZhciBjbG9jayA9IHtcbiAgICAgICAgbm93OiBnZXRFcG9jaChub3cpLFxuICAgICAgICB0aW1lb3V0czoge30sXG4gICAgICAgIERhdGU6IGNyZWF0ZURhdGUoKVxuICAgIH07XG5cbiAgICBjbG9jay5EYXRlLmNsb2NrID0gY2xvY2s7XG5cbiAgICBjbG9jay5zZXRUaW1lb3V0ID0gZnVuY3Rpb24gc2V0VGltZW91dChmdW5jLCB0aW1lb3V0KSB7XG4gICAgICAgIHJldHVybiBhZGRUaW1lcihjbG9jaywge1xuICAgICAgICAgICAgZnVuYzogZnVuYyxcbiAgICAgICAgICAgIGFyZ3M6IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMiksXG4gICAgICAgICAgICBkZWxheTogdGltZW91dFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgY2xvY2suY2xlYXJUaW1lb3V0ID0gZnVuY3Rpb24gY2xlYXJUaW1lb3V0KHRpbWVySWQpIHtcbiAgICAgICAgaWYgKCF0aW1lcklkKSB7XG4gICAgICAgICAgICAvLyBudWxsIGFwcGVhcnMgdG8gYmUgYWxsb3dlZCBpbiBtb3N0IGJyb3dzZXJzLCBhbmQgYXBwZWFycyB0byBiZVxuICAgICAgICAgICAgLy8gcmVsaWVkIHVwb24gYnkgc29tZSBsaWJyYXJpZXMsIGxpa2UgQm9vdHN0cmFwIGNhcm91c2VsXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFjbG9jay50aW1lcnMpIHtcbiAgICAgICAgICAgIGNsb2NrLnRpbWVycyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIC8vIGluIE5vZGUsIHRpbWVySWQgaXMgYW4gb2JqZWN0IHdpdGggLnJlZigpLy51bnJlZigpLCBhbmRcbiAgICAgICAgLy8gaXRzIC5pZCBmaWVsZCBpcyB0aGUgYWN0dWFsIHRpbWVyIGlkLlxuICAgICAgICBpZiAodHlwZW9mIHRpbWVySWQgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgIHRpbWVySWQgPSB0aW1lcklkLmlkXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRpbWVySWQgaW4gY2xvY2sudGltZXJzKSB7XG4gICAgICAgICAgICBkZWxldGUgY2xvY2sudGltZXJzW3RpbWVySWRdO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIGNsb2NrLnNldEludGVydmFsID0gZnVuY3Rpb24gc2V0SW50ZXJ2YWwoZnVuYywgdGltZW91dCkge1xuICAgICAgICByZXR1cm4gYWRkVGltZXIoY2xvY2ssIHtcbiAgICAgICAgICAgIGZ1bmM6IGZ1bmMsXG4gICAgICAgICAgICBhcmdzOiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpLFxuICAgICAgICAgICAgZGVsYXk6IHRpbWVvdXQsXG4gICAgICAgICAgICBpbnRlcnZhbDogdGltZW91dFxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgY2xvY2suY2xlYXJJbnRlcnZhbCA9IGZ1bmN0aW9uIGNsZWFySW50ZXJ2YWwodGltZXJJZCkge1xuICAgICAgICBjbG9jay5jbGVhclRpbWVvdXQodGltZXJJZCk7XG4gICAgfTtcblxuICAgIGNsb2NrLnNldEltbWVkaWF0ZSA9IGZ1bmN0aW9uIHNldEltbWVkaWF0ZShmdW5jKSB7XG4gICAgICAgIHJldHVybiBhZGRUaW1lcihjbG9jaywge1xuICAgICAgICAgICAgZnVuYzogZnVuYyxcbiAgICAgICAgICAgIGFyZ3M6IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSksXG4gICAgICAgICAgICBpbW1lZGlhdGU6IHRydWVcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIGNsb2NrLmNsZWFySW1tZWRpYXRlID0gZnVuY3Rpb24gY2xlYXJJbW1lZGlhdGUodGltZXJJZCkge1xuICAgICAgICBjbG9jay5jbGVhclRpbWVvdXQodGltZXJJZCk7XG4gICAgfTtcblxuICAgIGNsb2NrLnRpY2sgPSBmdW5jdGlvbiB0aWNrKG1zKSB7XG4gICAgICAgIG1zID0gdHlwZW9mIG1zID09IFwibnVtYmVyXCIgPyBtcyA6IHBhcnNlVGltZShtcyk7XG4gICAgICAgIHZhciB0aWNrRnJvbSA9IGNsb2NrLm5vdywgdGlja1RvID0gY2xvY2subm93ICsgbXMsIHByZXZpb3VzID0gY2xvY2subm93O1xuICAgICAgICB2YXIgdGltZXIgPSBmaXJzdFRpbWVySW5SYW5nZShjbG9jaywgdGlja0Zyb20sIHRpY2tUbyk7XG5cbiAgICAgICAgdmFyIGZpcnN0RXhjZXB0aW9uO1xuICAgICAgICB3aGlsZSAodGltZXIgJiYgdGlja0Zyb20gPD0gdGlja1RvKSB7XG4gICAgICAgICAgICBpZiAoY2xvY2sudGltZXJzW3RpbWVyLmlkXSkge1xuICAgICAgICAgICAgICAgIHRpY2tGcm9tID0gY2xvY2subm93ID0gdGltZXIuY2FsbEF0O1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxUaW1lcihjbG9jaywgdGltZXIpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgZmlyc3RFeGNlcHRpb24gPSBmaXJzdEV4Y2VwdGlvbiB8fCBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGltZXIgPSBmaXJzdFRpbWVySW5SYW5nZShjbG9jaywgcHJldmlvdXMsIHRpY2tUbyk7XG4gICAgICAgICAgICBwcmV2aW91cyA9IHRpY2tGcm9tO1xuICAgICAgICB9XG5cbiAgICAgICAgY2xvY2subm93ID0gdGlja1RvO1xuXG4gICAgICAgIGlmIChmaXJzdEV4Y2VwdGlvbikge1xuICAgICAgICAgICAgdGhyb3cgZmlyc3RFeGNlcHRpb247XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY2xvY2subm93O1xuICAgIH07XG5cbiAgICBjbG9jay5yZXNldCA9IGZ1bmN0aW9uIHJlc2V0KCkge1xuICAgICAgICBjbG9jay50aW1lcnMgPSB7fTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGNsb2NrO1xufTtcblxuZXhwb3J0cy5pbnN0YWxsID0gZnVuY3Rpb24gaW5zdGFsbCh0YXJnZXQsIG5vdywgdG9GYWtlKSB7XG4gICAgaWYgKHR5cGVvZiB0YXJnZXQgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgdG9GYWtlID0gbm93O1xuICAgICAgICBub3cgPSB0YXJnZXQ7XG4gICAgICAgIHRhcmdldCA9IG51bGw7XG4gICAgfVxuXG4gICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgICAgdGFyZ2V0ID0gZ2xvYmFsO1xuICAgIH1cblxuICAgIHZhciBjbG9jayA9IGNyZWF0ZUNsb2NrKG5vdyk7XG5cbiAgICBjbG9jay51bmluc3RhbGwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHVuaW5zdGFsbChjbG9jaywgdGFyZ2V0KTtcbiAgICB9O1xuXG4gICAgY2xvY2subWV0aG9kcyA9IHRvRmFrZSB8fCBbXTtcblxuICAgIGlmIChjbG9jay5tZXRob2RzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBjbG9jay5tZXRob2RzID0ga2V5cyh0aW1lcnMpO1xuICAgIH1cblxuICAgIGZvciAodmFyIGkgPSAwLCBsID0gY2xvY2subWV0aG9kcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgaGlqYWNrTWV0aG9kKHRhcmdldCwgY2xvY2subWV0aG9kc1tpXSwgY2xvY2spO1xuICAgIH1cblxuICAgIHJldHVybiBjbG9jaztcbn07XG5cbn0pLmNhbGwodGhpcyx0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pIiwiLy8gICAgIFVuZGVyc2NvcmUuanMgMS44LjNcbi8vICAgICBodHRwOi8vdW5kZXJzY29yZWpzLm9yZ1xuLy8gICAgIChjKSAyMDA5LTIwMTUgSmVyZW15IEFzaGtlbmFzLCBEb2N1bWVudENsb3VkIGFuZCBJbnZlc3RpZ2F0aXZlIFJlcG9ydGVycyAmIEVkaXRvcnNcbi8vICAgICBVbmRlcnNjb3JlIG1heSBiZSBmcmVlbHkgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlLlxuXG4oZnVuY3Rpb24oKSB7XG5cbiAgLy8gQmFzZWxpbmUgc2V0dXBcbiAgLy8gLS0tLS0tLS0tLS0tLS1cblxuICAvLyBFc3RhYmxpc2ggdGhlIHJvb3Qgb2JqZWN0LCBgd2luZG93YCBpbiB0aGUgYnJvd3Nlciwgb3IgYGV4cG9ydHNgIG9uIHRoZSBzZXJ2ZXIuXG4gIHZhciByb290ID0gdGhpcztcblxuICAvLyBTYXZlIHRoZSBwcmV2aW91cyB2YWx1ZSBvZiB0aGUgYF9gIHZhcmlhYmxlLlxuICB2YXIgcHJldmlvdXNVbmRlcnNjb3JlID0gcm9vdC5fO1xuXG4gIC8vIFNhdmUgYnl0ZXMgaW4gdGhlIG1pbmlmaWVkIChidXQgbm90IGd6aXBwZWQpIHZlcnNpb246XG4gIHZhciBBcnJheVByb3RvID0gQXJyYXkucHJvdG90eXBlLCBPYmpQcm90byA9IE9iamVjdC5wcm90b3R5cGUsIEZ1bmNQcm90byA9IEZ1bmN0aW9uLnByb3RvdHlwZTtcblxuICAvLyBDcmVhdGUgcXVpY2sgcmVmZXJlbmNlIHZhcmlhYmxlcyBmb3Igc3BlZWQgYWNjZXNzIHRvIGNvcmUgcHJvdG90eXBlcy5cbiAgdmFyXG4gICAgcHVzaCAgICAgICAgICAgICA9IEFycmF5UHJvdG8ucHVzaCxcbiAgICBzbGljZSAgICAgICAgICAgID0gQXJyYXlQcm90by5zbGljZSxcbiAgICB0b1N0cmluZyAgICAgICAgID0gT2JqUHJvdG8udG9TdHJpbmcsXG4gICAgaGFzT3duUHJvcGVydHkgICA9IE9ialByb3RvLmhhc093blByb3BlcnR5O1xuXG4gIC8vIEFsbCAqKkVDTUFTY3JpcHQgNSoqIG5hdGl2ZSBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvbnMgdGhhdCB3ZSBob3BlIHRvIHVzZVxuICAvLyBhcmUgZGVjbGFyZWQgaGVyZS5cbiAgdmFyXG4gICAgbmF0aXZlSXNBcnJheSAgICAgID0gQXJyYXkuaXNBcnJheSxcbiAgICBuYXRpdmVLZXlzICAgICAgICAgPSBPYmplY3Qua2V5cyxcbiAgICBuYXRpdmVCaW5kICAgICAgICAgPSBGdW5jUHJvdG8uYmluZCxcbiAgICBuYXRpdmVDcmVhdGUgICAgICAgPSBPYmplY3QuY3JlYXRlO1xuXG4gIC8vIE5ha2VkIGZ1bmN0aW9uIHJlZmVyZW5jZSBmb3Igc3Vycm9nYXRlLXByb3RvdHlwZS1zd2FwcGluZy5cbiAgdmFyIEN0b3IgPSBmdW5jdGlvbigpe307XG5cbiAgLy8gQ3JlYXRlIGEgc2FmZSByZWZlcmVuY2UgdG8gdGhlIFVuZGVyc2NvcmUgb2JqZWN0IGZvciB1c2UgYmVsb3cuXG4gIHZhciBfID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYgKG9iaiBpbnN0YW5jZW9mIF8pIHJldHVybiBvYmo7XG4gICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIF8pKSByZXR1cm4gbmV3IF8ob2JqKTtcbiAgICB0aGlzLl93cmFwcGVkID0gb2JqO1xuICB9O1xuXG4gIC8vIEV4cG9ydCB0aGUgVW5kZXJzY29yZSBvYmplY3QgZm9yICoqTm9kZS5qcyoqLCB3aXRoXG4gIC8vIGJhY2t3YXJkcy1jb21wYXRpYmlsaXR5IGZvciB0aGUgb2xkIGByZXF1aXJlKClgIEFQSS4gSWYgd2UncmUgaW5cbiAgLy8gdGhlIGJyb3dzZXIsIGFkZCBgX2AgYXMgYSBnbG9iYWwgb2JqZWN0LlxuICBpZiAodHlwZW9mIGV4cG9ydHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgICBleHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSBfO1xuICAgIH1cbiAgICBleHBvcnRzLl8gPSBfO1xuICB9IGVsc2Uge1xuICAgIHJvb3QuXyA9IF87XG4gIH1cblxuICAvLyBDdXJyZW50IHZlcnNpb24uXG4gIF8uVkVSU0lPTiA9ICcxLjguMyc7XG5cbiAgLy8gSW50ZXJuYWwgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGFuIGVmZmljaWVudCAoZm9yIGN1cnJlbnQgZW5naW5lcykgdmVyc2lvblxuICAvLyBvZiB0aGUgcGFzc2VkLWluIGNhbGxiYWNrLCB0byBiZSByZXBlYXRlZGx5IGFwcGxpZWQgaW4gb3RoZXIgVW5kZXJzY29yZVxuICAvLyBmdW5jdGlvbnMuXG4gIHZhciBvcHRpbWl6ZUNiID0gZnVuY3Rpb24oZnVuYywgY29udGV4dCwgYXJnQ291bnQpIHtcbiAgICBpZiAoY29udGV4dCA9PT0gdm9pZCAwKSByZXR1cm4gZnVuYztcbiAgICBzd2l0Y2ggKGFyZ0NvdW50ID09IG51bGwgPyAzIDogYXJnQ291bnQpIHtcbiAgICAgIGNhc2UgMTogcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBmdW5jLmNhbGwoY29udGV4dCwgdmFsdWUpO1xuICAgICAgfTtcbiAgICAgIGNhc2UgMjogcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBvdGhlcikge1xuICAgICAgICByZXR1cm4gZnVuYy5jYWxsKGNvbnRleHQsIHZhbHVlLCBvdGhlcik7XG4gICAgICB9O1xuICAgICAgY2FzZSAzOiByZXR1cm4gZnVuY3Rpb24odmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHJldHVybiBmdW5jLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKTtcbiAgICAgIH07XG4gICAgICBjYXNlIDQ6IHJldHVybiBmdW5jdGlvbihhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKSB7XG4gICAgICAgIHJldHVybiBmdW5jLmNhbGwoY29udGV4dCwgYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbik7XG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZnVuYy5hcHBseShjb250ZXh0LCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH07XG5cbiAgLy8gQSBtb3N0bHktaW50ZXJuYWwgZnVuY3Rpb24gdG8gZ2VuZXJhdGUgY2FsbGJhY2tzIHRoYXQgY2FuIGJlIGFwcGxpZWRcbiAgLy8gdG8gZWFjaCBlbGVtZW50IGluIGEgY29sbGVjdGlvbiwgcmV0dXJuaW5nIHRoZSBkZXNpcmVkIHJlc3VsdCDigJQgZWl0aGVyXG4gIC8vIGlkZW50aXR5LCBhbiBhcmJpdHJhcnkgY2FsbGJhY2ssIGEgcHJvcGVydHkgbWF0Y2hlciwgb3IgYSBwcm9wZXJ0eSBhY2Nlc3Nvci5cbiAgdmFyIGNiID0gZnVuY3Rpb24odmFsdWUsIGNvbnRleHQsIGFyZ0NvdW50KSB7XG4gICAgaWYgKHZhbHVlID09IG51bGwpIHJldHVybiBfLmlkZW50aXR5O1xuICAgIGlmIChfLmlzRnVuY3Rpb24odmFsdWUpKSByZXR1cm4gb3B0aW1pemVDYih2YWx1ZSwgY29udGV4dCwgYXJnQ291bnQpO1xuICAgIGlmIChfLmlzT2JqZWN0KHZhbHVlKSkgcmV0dXJuIF8ubWF0Y2hlcih2YWx1ZSk7XG4gICAgcmV0dXJuIF8ucHJvcGVydHkodmFsdWUpO1xuICB9O1xuICBfLml0ZXJhdGVlID0gZnVuY3Rpb24odmFsdWUsIGNvbnRleHQpIHtcbiAgICByZXR1cm4gY2IodmFsdWUsIGNvbnRleHQsIEluZmluaXR5KTtcbiAgfTtcblxuICAvLyBBbiBpbnRlcm5hbCBmdW5jdGlvbiBmb3IgY3JlYXRpbmcgYXNzaWduZXIgZnVuY3Rpb25zLlxuICB2YXIgY3JlYXRlQXNzaWduZXIgPSBmdW5jdGlvbihrZXlzRnVuYywgdW5kZWZpbmVkT25seSkge1xuICAgIHJldHVybiBmdW5jdGlvbihvYmopIHtcbiAgICAgIHZhciBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgICAgaWYgKGxlbmd0aCA8IDIgfHwgb2JqID09IG51bGwpIHJldHVybiBvYmo7XG4gICAgICBmb3IgKHZhciBpbmRleCA9IDE7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICAgIHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaW5kZXhdLFxuICAgICAgICAgICAga2V5cyA9IGtleXNGdW5jKHNvdXJjZSksXG4gICAgICAgICAgICBsID0ga2V5cy5sZW5ndGg7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgdmFyIGtleSA9IGtleXNbaV07XG4gICAgICAgICAgaWYgKCF1bmRlZmluZWRPbmx5IHx8IG9ialtrZXldID09PSB2b2lkIDApIG9ialtrZXldID0gc291cmNlW2tleV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBvYmo7XG4gICAgfTtcbiAgfTtcblxuICAvLyBBbiBpbnRlcm5hbCBmdW5jdGlvbiBmb3IgY3JlYXRpbmcgYSBuZXcgb2JqZWN0IHRoYXQgaW5oZXJpdHMgZnJvbSBhbm90aGVyLlxuICB2YXIgYmFzZUNyZWF0ZSA9IGZ1bmN0aW9uKHByb3RvdHlwZSkge1xuICAgIGlmICghXy5pc09iamVjdChwcm90b3R5cGUpKSByZXR1cm4ge307XG4gICAgaWYgKG5hdGl2ZUNyZWF0ZSkgcmV0dXJuIG5hdGl2ZUNyZWF0ZShwcm90b3R5cGUpO1xuICAgIEN0b3IucHJvdG90eXBlID0gcHJvdG90eXBlO1xuICAgIHZhciByZXN1bHQgPSBuZXcgQ3RvcjtcbiAgICBDdG9yLnByb3RvdHlwZSA9IG51bGw7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICB2YXIgcHJvcGVydHkgPSBmdW5jdGlvbihrZXkpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gb2JqID09IG51bGwgPyB2b2lkIDAgOiBvYmpba2V5XTtcbiAgICB9O1xuICB9O1xuXG4gIC8vIEhlbHBlciBmb3IgY29sbGVjdGlvbiBtZXRob2RzIHRvIGRldGVybWluZSB3aGV0aGVyIGEgY29sbGVjdGlvblxuICAvLyBzaG91bGQgYmUgaXRlcmF0ZWQgYXMgYW4gYXJyYXkgb3IgYXMgYW4gb2JqZWN0XG4gIC8vIFJlbGF0ZWQ6IGh0dHA6Ly9wZW9wbGUubW96aWxsYS5vcmcvfmpvcmVuZG9yZmYvZXM2LWRyYWZ0Lmh0bWwjc2VjLXRvbGVuZ3RoXG4gIC8vIEF2b2lkcyBhIHZlcnkgbmFzdHkgaU9TIDggSklUIGJ1ZyBvbiBBUk0tNjQuICMyMDk0XG4gIHZhciBNQVhfQVJSQVlfSU5ERVggPSBNYXRoLnBvdygyLCA1MykgLSAxO1xuICB2YXIgZ2V0TGVuZ3RoID0gcHJvcGVydHkoJ2xlbmd0aCcpO1xuICB2YXIgaXNBcnJheUxpa2UgPSBmdW5jdGlvbihjb2xsZWN0aW9uKSB7XG4gICAgdmFyIGxlbmd0aCA9IGdldExlbmd0aChjb2xsZWN0aW9uKTtcbiAgICByZXR1cm4gdHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyAmJiBsZW5ndGggPj0gMCAmJiBsZW5ndGggPD0gTUFYX0FSUkFZX0lOREVYO1xuICB9O1xuXG4gIC8vIENvbGxlY3Rpb24gRnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLy8gVGhlIGNvcm5lcnN0b25lLCBhbiBgZWFjaGAgaW1wbGVtZW50YXRpb24sIGFrYSBgZm9yRWFjaGAuXG4gIC8vIEhhbmRsZXMgcmF3IG9iamVjdHMgaW4gYWRkaXRpb24gdG8gYXJyYXktbGlrZXMuIFRyZWF0cyBhbGxcbiAgLy8gc3BhcnNlIGFycmF5LWxpa2VzIGFzIGlmIHRoZXkgd2VyZSBkZW5zZS5cbiAgXy5lYWNoID0gXy5mb3JFYWNoID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgY29udGV4dCkge1xuICAgIGl0ZXJhdGVlID0gb3B0aW1pemVDYihpdGVyYXRlZSwgY29udGV4dCk7XG4gICAgdmFyIGksIGxlbmd0aDtcbiAgICBpZiAoaXNBcnJheUxpa2Uob2JqKSkge1xuICAgICAgZm9yIChpID0gMCwgbGVuZ3RoID0gb2JqLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGl0ZXJhdGVlKG9ialtpXSwgaSwgb2JqKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGtleXMgPSBfLmtleXMob2JqKTtcbiAgICAgIGZvciAoaSA9IDAsIGxlbmd0aCA9IGtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaXRlcmF0ZWUob2JqW2tleXNbaV1dLCBrZXlzW2ldLCBvYmopO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gb2JqO1xuICB9O1xuXG4gIC8vIFJldHVybiB0aGUgcmVzdWx0cyBvZiBhcHBseWluZyB0aGUgaXRlcmF0ZWUgdG8gZWFjaCBlbGVtZW50LlxuICBfLm1hcCA9IF8uY29sbGVjdCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpIHtcbiAgICBpdGVyYXRlZSA9IGNiKGl0ZXJhdGVlLCBjb250ZXh0KTtcbiAgICB2YXIga2V5cyA9ICFpc0FycmF5TGlrZShvYmopICYmIF8ua2V5cyhvYmopLFxuICAgICAgICBsZW5ndGggPSAoa2V5cyB8fCBvYmopLmxlbmd0aCxcbiAgICAgICAgcmVzdWx0cyA9IEFycmF5KGxlbmd0aCk7XG4gICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgdmFyIGN1cnJlbnRLZXkgPSBrZXlzID8ga2V5c1tpbmRleF0gOiBpbmRleDtcbiAgICAgIHJlc3VsdHNbaW5kZXhdID0gaXRlcmF0ZWUob2JqW2N1cnJlbnRLZXldLCBjdXJyZW50S2V5LCBvYmopO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfTtcblxuICAvLyBDcmVhdGUgYSByZWR1Y2luZyBmdW5jdGlvbiBpdGVyYXRpbmcgbGVmdCBvciByaWdodC5cbiAgZnVuY3Rpb24gY3JlYXRlUmVkdWNlKGRpcikge1xuICAgIC8vIE9wdGltaXplZCBpdGVyYXRvciBmdW5jdGlvbiBhcyB1c2luZyBhcmd1bWVudHMubGVuZ3RoXG4gICAgLy8gaW4gdGhlIG1haW4gZnVuY3Rpb24gd2lsbCBkZW9wdGltaXplIHRoZSwgc2VlICMxOTkxLlxuICAgIGZ1bmN0aW9uIGl0ZXJhdG9yKG9iaiwgaXRlcmF0ZWUsIG1lbW8sIGtleXMsIGluZGV4LCBsZW5ndGgpIHtcbiAgICAgIGZvciAoOyBpbmRleCA+PSAwICYmIGluZGV4IDwgbGVuZ3RoOyBpbmRleCArPSBkaXIpIHtcbiAgICAgICAgdmFyIGN1cnJlbnRLZXkgPSBrZXlzID8ga2V5c1tpbmRleF0gOiBpbmRleDtcbiAgICAgICAgbWVtbyA9IGl0ZXJhdGVlKG1lbW8sIG9ialtjdXJyZW50S2V5XSwgY3VycmVudEtleSwgb2JqKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBtZW1vO1xuICAgIH1cblxuICAgIHJldHVybiBmdW5jdGlvbihvYmosIGl0ZXJhdGVlLCBtZW1vLCBjb250ZXh0KSB7XG4gICAgICBpdGVyYXRlZSA9IG9wdGltaXplQ2IoaXRlcmF0ZWUsIGNvbnRleHQsIDQpO1xuICAgICAgdmFyIGtleXMgPSAhaXNBcnJheUxpa2Uob2JqKSAmJiBfLmtleXMob2JqKSxcbiAgICAgICAgICBsZW5ndGggPSAoa2V5cyB8fCBvYmopLmxlbmd0aCxcbiAgICAgICAgICBpbmRleCA9IGRpciA+IDAgPyAwIDogbGVuZ3RoIC0gMTtcbiAgICAgIC8vIERldGVybWluZSB0aGUgaW5pdGlhbCB2YWx1ZSBpZiBub25lIGlzIHByb3ZpZGVkLlxuICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPCAzKSB7XG4gICAgICAgIG1lbW8gPSBvYmpba2V5cyA/IGtleXNbaW5kZXhdIDogaW5kZXhdO1xuICAgICAgICBpbmRleCArPSBkaXI7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXRlcmF0b3Iob2JqLCBpdGVyYXRlZSwgbWVtbywga2V5cywgaW5kZXgsIGxlbmd0aCk7XG4gICAgfTtcbiAgfVxuXG4gIC8vICoqUmVkdWNlKiogYnVpbGRzIHVwIGEgc2luZ2xlIHJlc3VsdCBmcm9tIGEgbGlzdCBvZiB2YWx1ZXMsIGFrYSBgaW5qZWN0YCxcbiAgLy8gb3IgYGZvbGRsYC5cbiAgXy5yZWR1Y2UgPSBfLmZvbGRsID0gXy5pbmplY3QgPSBjcmVhdGVSZWR1Y2UoMSk7XG5cbiAgLy8gVGhlIHJpZ2h0LWFzc29jaWF0aXZlIHZlcnNpb24gb2YgcmVkdWNlLCBhbHNvIGtub3duIGFzIGBmb2xkcmAuXG4gIF8ucmVkdWNlUmlnaHQgPSBfLmZvbGRyID0gY3JlYXRlUmVkdWNlKC0xKTtcblxuICAvLyBSZXR1cm4gdGhlIGZpcnN0IHZhbHVlIHdoaWNoIHBhc3NlcyBhIHRydXRoIHRlc3QuIEFsaWFzZWQgYXMgYGRldGVjdGAuXG4gIF8uZmluZCA9IF8uZGV0ZWN0ID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcbiAgICB2YXIga2V5O1xuICAgIGlmIChpc0FycmF5TGlrZShvYmopKSB7XG4gICAgICBrZXkgPSBfLmZpbmRJbmRleChvYmosIHByZWRpY2F0ZSwgY29udGV4dCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGtleSA9IF8uZmluZEtleShvYmosIHByZWRpY2F0ZSwgY29udGV4dCk7XG4gICAgfVxuICAgIGlmIChrZXkgIT09IHZvaWQgMCAmJiBrZXkgIT09IC0xKSByZXR1cm4gb2JqW2tleV07XG4gIH07XG5cbiAgLy8gUmV0dXJuIGFsbCB0aGUgZWxlbWVudHMgdGhhdCBwYXNzIGEgdHJ1dGggdGVzdC5cbiAgLy8gQWxpYXNlZCBhcyBgc2VsZWN0YC5cbiAgXy5maWx0ZXIgPSBfLnNlbGVjdCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICBwcmVkaWNhdGUgPSBjYihwcmVkaWNhdGUsIGNvbnRleHQpO1xuICAgIF8uZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwgaW5kZXgsIGxpc3QpKSByZXN1bHRzLnB1c2godmFsdWUpO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9O1xuXG4gIC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIGZvciB3aGljaCBhIHRydXRoIHRlc3QgZmFpbHMuXG4gIF8ucmVqZWN0ID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcbiAgICByZXR1cm4gXy5maWx0ZXIob2JqLCBfLm5lZ2F0ZShjYihwcmVkaWNhdGUpKSwgY29udGV4dCk7XG4gIH07XG5cbiAgLy8gRGV0ZXJtaW5lIHdoZXRoZXIgYWxsIG9mIHRoZSBlbGVtZW50cyBtYXRjaCBhIHRydXRoIHRlc3QuXG4gIC8vIEFsaWFzZWQgYXMgYGFsbGAuXG4gIF8uZXZlcnkgPSBfLmFsbCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgcHJlZGljYXRlID0gY2IocHJlZGljYXRlLCBjb250ZXh0KTtcbiAgICB2YXIga2V5cyA9ICFpc0FycmF5TGlrZShvYmopICYmIF8ua2V5cyhvYmopLFxuICAgICAgICBsZW5ndGggPSAoa2V5cyB8fCBvYmopLmxlbmd0aDtcbiAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICB2YXIgY3VycmVudEtleSA9IGtleXMgPyBrZXlzW2luZGV4XSA6IGluZGV4O1xuICAgICAgaWYgKCFwcmVkaWNhdGUob2JqW2N1cnJlbnRLZXldLCBjdXJyZW50S2V5LCBvYmopKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9O1xuXG4gIC8vIERldGVybWluZSBpZiBhdCBsZWFzdCBvbmUgZWxlbWVudCBpbiB0aGUgb2JqZWN0IG1hdGNoZXMgYSB0cnV0aCB0ZXN0LlxuICAvLyBBbGlhc2VkIGFzIGBhbnlgLlxuICBfLnNvbWUgPSBfLmFueSA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgcHJlZGljYXRlID0gY2IocHJlZGljYXRlLCBjb250ZXh0KTtcbiAgICB2YXIga2V5cyA9ICFpc0FycmF5TGlrZShvYmopICYmIF8ua2V5cyhvYmopLFxuICAgICAgICBsZW5ndGggPSAoa2V5cyB8fCBvYmopLmxlbmd0aDtcbiAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICB2YXIgY3VycmVudEtleSA9IGtleXMgPyBrZXlzW2luZGV4XSA6IGluZGV4O1xuICAgICAgaWYgKHByZWRpY2F0ZShvYmpbY3VycmVudEtleV0sIGN1cnJlbnRLZXksIG9iaikpIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG5cbiAgLy8gRGV0ZXJtaW5lIGlmIHRoZSBhcnJheSBvciBvYmplY3QgY29udGFpbnMgYSBnaXZlbiBpdGVtICh1c2luZyBgPT09YCkuXG4gIC8vIEFsaWFzZWQgYXMgYGluY2x1ZGVzYCBhbmQgYGluY2x1ZGVgLlxuICBfLmNvbnRhaW5zID0gXy5pbmNsdWRlcyA9IF8uaW5jbHVkZSA9IGZ1bmN0aW9uKG9iaiwgaXRlbSwgZnJvbUluZGV4LCBndWFyZCkge1xuICAgIGlmICghaXNBcnJheUxpa2Uob2JqKSkgb2JqID0gXy52YWx1ZXMob2JqKTtcbiAgICBpZiAodHlwZW9mIGZyb21JbmRleCAhPSAnbnVtYmVyJyB8fCBndWFyZCkgZnJvbUluZGV4ID0gMDtcbiAgICByZXR1cm4gXy5pbmRleE9mKG9iaiwgaXRlbSwgZnJvbUluZGV4KSA+PSAwO1xuICB9O1xuXG4gIC8vIEludm9rZSBhIG1ldGhvZCAod2l0aCBhcmd1bWVudHMpIG9uIGV2ZXJ5IGl0ZW0gaW4gYSBjb2xsZWN0aW9uLlxuICBfLmludm9rZSA9IGZ1bmN0aW9uKG9iaiwgbWV0aG9kKSB7XG4gICAgdmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgdmFyIGlzRnVuYyA9IF8uaXNGdW5jdGlvbihtZXRob2QpO1xuICAgIHJldHVybiBfLm1hcChvYmosIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICB2YXIgZnVuYyA9IGlzRnVuYyA/IG1ldGhvZCA6IHZhbHVlW21ldGhvZF07XG4gICAgICByZXR1cm4gZnVuYyA9PSBudWxsID8gZnVuYyA6IGZ1bmMuYXBwbHkodmFsdWUsIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIENvbnZlbmllbmNlIHZlcnNpb24gb2YgYSBjb21tb24gdXNlIGNhc2Ugb2YgYG1hcGA6IGZldGNoaW5nIGEgcHJvcGVydHkuXG4gIF8ucGx1Y2sgPSBmdW5jdGlvbihvYmosIGtleSkge1xuICAgIHJldHVybiBfLm1hcChvYmosIF8ucHJvcGVydHkoa2V5KSk7XG4gIH07XG5cbiAgLy8gQ29udmVuaWVuY2UgdmVyc2lvbiBvZiBhIGNvbW1vbiB1c2UgY2FzZSBvZiBgZmlsdGVyYDogc2VsZWN0aW5nIG9ubHkgb2JqZWN0c1xuICAvLyBjb250YWluaW5nIHNwZWNpZmljIGBrZXk6dmFsdWVgIHBhaXJzLlxuICBfLndoZXJlID0gZnVuY3Rpb24ob2JqLCBhdHRycykge1xuICAgIHJldHVybiBfLmZpbHRlcihvYmosIF8ubWF0Y2hlcihhdHRycykpO1xuICB9O1xuXG4gIC8vIENvbnZlbmllbmNlIHZlcnNpb24gb2YgYSBjb21tb24gdXNlIGNhc2Ugb2YgYGZpbmRgOiBnZXR0aW5nIHRoZSBmaXJzdCBvYmplY3RcbiAgLy8gY29udGFpbmluZyBzcGVjaWZpYyBga2V5OnZhbHVlYCBwYWlycy5cbiAgXy5maW5kV2hlcmUgPSBmdW5jdGlvbihvYmosIGF0dHJzKSB7XG4gICAgcmV0dXJuIF8uZmluZChvYmosIF8ubWF0Y2hlcihhdHRycykpO1xuICB9O1xuXG4gIC8vIFJldHVybiB0aGUgbWF4aW11bSBlbGVtZW50IChvciBlbGVtZW50LWJhc2VkIGNvbXB1dGF0aW9uKS5cbiAgXy5tYXggPSBmdW5jdGlvbihvYmosIGl0ZXJhdGVlLCBjb250ZXh0KSB7XG4gICAgdmFyIHJlc3VsdCA9IC1JbmZpbml0eSwgbGFzdENvbXB1dGVkID0gLUluZmluaXR5LFxuICAgICAgICB2YWx1ZSwgY29tcHV0ZWQ7XG4gICAgaWYgKGl0ZXJhdGVlID09IG51bGwgJiYgb2JqICE9IG51bGwpIHtcbiAgICAgIG9iaiA9IGlzQXJyYXlMaWtlKG9iaikgPyBvYmogOiBfLnZhbHVlcyhvYmopO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IG9iai5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICB2YWx1ZSA9IG9ialtpXTtcbiAgICAgICAgaWYgKHZhbHVlID4gcmVzdWx0KSB7XG4gICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaXRlcmF0ZWUgPSBjYihpdGVyYXRlZSwgY29udGV4dCk7XG4gICAgICBfLmVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSh2YWx1ZSwgaW5kZXgsIGxpc3QpO1xuICAgICAgICBpZiAoY29tcHV0ZWQgPiBsYXN0Q29tcHV0ZWQgfHwgY29tcHV0ZWQgPT09IC1JbmZpbml0eSAmJiByZXN1bHQgPT09IC1JbmZpbml0eSkge1xuICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICAgIGxhc3RDb21wdXRlZCA9IGNvbXB1dGVkO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBSZXR1cm4gdGhlIG1pbmltdW0gZWxlbWVudCAob3IgZWxlbWVudC1iYXNlZCBjb21wdXRhdGlvbikuXG4gIF8ubWluID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgY29udGV4dCkge1xuICAgIHZhciByZXN1bHQgPSBJbmZpbml0eSwgbGFzdENvbXB1dGVkID0gSW5maW5pdHksXG4gICAgICAgIHZhbHVlLCBjb21wdXRlZDtcbiAgICBpZiAoaXRlcmF0ZWUgPT0gbnVsbCAmJiBvYmogIT0gbnVsbCkge1xuICAgICAgb2JqID0gaXNBcnJheUxpa2Uob2JqKSA/IG9iaiA6IF8udmFsdWVzKG9iaik7XG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gb2JqLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhbHVlID0gb2JqW2ldO1xuICAgICAgICBpZiAodmFsdWUgPCByZXN1bHQpIHtcbiAgICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpdGVyYXRlZSA9IGNiKGl0ZXJhdGVlLCBjb250ZXh0KTtcbiAgICAgIF8uZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlKHZhbHVlLCBpbmRleCwgbGlzdCk7XG4gICAgICAgIGlmIChjb21wdXRlZCA8IGxhc3RDb21wdXRlZCB8fCBjb21wdXRlZCA9PT0gSW5maW5pdHkgJiYgcmVzdWx0ID09PSBJbmZpbml0eSkge1xuICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICAgIGxhc3RDb21wdXRlZCA9IGNvbXB1dGVkO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBTaHVmZmxlIGEgY29sbGVjdGlvbiwgdXNpbmcgdGhlIG1vZGVybiB2ZXJzaW9uIG9mIHRoZVxuICAvLyBbRmlzaGVyLVlhdGVzIHNodWZmbGVdKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRmlzaGVy4oCTWWF0ZXNfc2h1ZmZsZSkuXG4gIF8uc2h1ZmZsZSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBzZXQgPSBpc0FycmF5TGlrZShvYmopID8gb2JqIDogXy52YWx1ZXMob2JqKTtcbiAgICB2YXIgbGVuZ3RoID0gc2V0Lmxlbmd0aDtcbiAgICB2YXIgc2h1ZmZsZWQgPSBBcnJheShsZW5ndGgpO1xuICAgIGZvciAodmFyIGluZGV4ID0gMCwgcmFuZDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgIHJhbmQgPSBfLnJhbmRvbSgwLCBpbmRleCk7XG4gICAgICBpZiAocmFuZCAhPT0gaW5kZXgpIHNodWZmbGVkW2luZGV4XSA9IHNodWZmbGVkW3JhbmRdO1xuICAgICAgc2h1ZmZsZWRbcmFuZF0gPSBzZXRbaW5kZXhdO1xuICAgIH1cbiAgICByZXR1cm4gc2h1ZmZsZWQ7XG4gIH07XG5cbiAgLy8gU2FtcGxlICoqbioqIHJhbmRvbSB2YWx1ZXMgZnJvbSBhIGNvbGxlY3Rpb24uXG4gIC8vIElmICoqbioqIGlzIG5vdCBzcGVjaWZpZWQsIHJldHVybnMgYSBzaW5nbGUgcmFuZG9tIGVsZW1lbnQuXG4gIC8vIFRoZSBpbnRlcm5hbCBgZ3VhcmRgIGFyZ3VtZW50IGFsbG93cyBpdCB0byB3b3JrIHdpdGggYG1hcGAuXG4gIF8uc2FtcGxlID0gZnVuY3Rpb24ob2JqLCBuLCBndWFyZCkge1xuICAgIGlmIChuID09IG51bGwgfHwgZ3VhcmQpIHtcbiAgICAgIGlmICghaXNBcnJheUxpa2Uob2JqKSkgb2JqID0gXy52YWx1ZXMob2JqKTtcbiAgICAgIHJldHVybiBvYmpbXy5yYW5kb20ob2JqLmxlbmd0aCAtIDEpXTtcbiAgICB9XG4gICAgcmV0dXJuIF8uc2h1ZmZsZShvYmopLnNsaWNlKDAsIE1hdGgubWF4KDAsIG4pKTtcbiAgfTtcblxuICAvLyBTb3J0IHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24gcHJvZHVjZWQgYnkgYW4gaXRlcmF0ZWUuXG4gIF8uc29ydEJ5ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgY29udGV4dCkge1xuICAgIGl0ZXJhdGVlID0gY2IoaXRlcmF0ZWUsIGNvbnRleHQpO1xuICAgIHJldHVybiBfLnBsdWNrKF8ubWFwKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgIGluZGV4OiBpbmRleCxcbiAgICAgICAgY3JpdGVyaWE6IGl0ZXJhdGVlKHZhbHVlLCBpbmRleCwgbGlzdClcbiAgICAgIH07XG4gICAgfSkuc29ydChmdW5jdGlvbihsZWZ0LCByaWdodCkge1xuICAgICAgdmFyIGEgPSBsZWZ0LmNyaXRlcmlhO1xuICAgICAgdmFyIGIgPSByaWdodC5jcml0ZXJpYTtcbiAgICAgIGlmIChhICE9PSBiKSB7XG4gICAgICAgIGlmIChhID4gYiB8fCBhID09PSB2b2lkIDApIHJldHVybiAxO1xuICAgICAgICBpZiAoYSA8IGIgfHwgYiA9PT0gdm9pZCAwKSByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICByZXR1cm4gbGVmdC5pbmRleCAtIHJpZ2h0LmluZGV4O1xuICAgIH0pLCAndmFsdWUnKTtcbiAgfTtcblxuICAvLyBBbiBpbnRlcm5hbCBmdW5jdGlvbiB1c2VkIGZvciBhZ2dyZWdhdGUgXCJncm91cCBieVwiIG9wZXJhdGlvbnMuXG4gIHZhciBncm91cCA9IGZ1bmN0aW9uKGJlaGF2aW9yKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpIHtcbiAgICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICAgIGl0ZXJhdGVlID0gY2IoaXRlcmF0ZWUsIGNvbnRleHQpO1xuICAgICAgXy5lYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICAgIHZhciBrZXkgPSBpdGVyYXRlZSh2YWx1ZSwgaW5kZXgsIG9iaik7XG4gICAgICAgIGJlaGF2aW9yKHJlc3VsdCwgdmFsdWUsIGtleSk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgfTtcblxuICAvLyBHcm91cHMgdGhlIG9iamVjdCdzIHZhbHVlcyBieSBhIGNyaXRlcmlvbi4gUGFzcyBlaXRoZXIgYSBzdHJpbmcgYXR0cmlidXRlXG4gIC8vIHRvIGdyb3VwIGJ5LCBvciBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgY3JpdGVyaW9uLlxuICBfLmdyb3VwQnkgPSBncm91cChmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICBpZiAoXy5oYXMocmVzdWx0LCBrZXkpKSByZXN1bHRba2V5XS5wdXNoKHZhbHVlKTsgZWxzZSByZXN1bHRba2V5XSA9IFt2YWx1ZV07XG4gIH0pO1xuXG4gIC8vIEluZGV4ZXMgdGhlIG9iamVjdCdzIHZhbHVlcyBieSBhIGNyaXRlcmlvbiwgc2ltaWxhciB0byBgZ3JvdXBCeWAsIGJ1dCBmb3JcbiAgLy8gd2hlbiB5b3Uga25vdyB0aGF0IHlvdXIgaW5kZXggdmFsdWVzIHdpbGwgYmUgdW5pcXVlLlxuICBfLmluZGV4QnkgPSBncm91cChmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICByZXN1bHRba2V5XSA9IHZhbHVlO1xuICB9KTtcblxuICAvLyBDb3VudHMgaW5zdGFuY2VzIG9mIGFuIG9iamVjdCB0aGF0IGdyb3VwIGJ5IGEgY2VydGFpbiBjcml0ZXJpb24uIFBhc3NcbiAgLy8gZWl0aGVyIGEgc3RyaW5nIGF0dHJpYnV0ZSB0byBjb3VudCBieSwgb3IgYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgdGhlXG4gIC8vIGNyaXRlcmlvbi5cbiAgXy5jb3VudEJ5ID0gZ3JvdXAoZnVuY3Rpb24ocmVzdWx0LCB2YWx1ZSwga2V5KSB7XG4gICAgaWYgKF8uaGFzKHJlc3VsdCwga2V5KSkgcmVzdWx0W2tleV0rKzsgZWxzZSByZXN1bHRba2V5XSA9IDE7XG4gIH0pO1xuXG4gIC8vIFNhZmVseSBjcmVhdGUgYSByZWFsLCBsaXZlIGFycmF5IGZyb20gYW55dGhpbmcgaXRlcmFibGUuXG4gIF8udG9BcnJheSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmICghb2JqKSByZXR1cm4gW107XG4gICAgaWYgKF8uaXNBcnJheShvYmopKSByZXR1cm4gc2xpY2UuY2FsbChvYmopO1xuICAgIGlmIChpc0FycmF5TGlrZShvYmopKSByZXR1cm4gXy5tYXAob2JqLCBfLmlkZW50aXR5KTtcbiAgICByZXR1cm4gXy52YWx1ZXMob2JqKTtcbiAgfTtcblxuICAvLyBSZXR1cm4gdGhlIG51bWJlciBvZiBlbGVtZW50cyBpbiBhbiBvYmplY3QuXG4gIF8uc2l6ZSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIDA7XG4gICAgcmV0dXJuIGlzQXJyYXlMaWtlKG9iaikgPyBvYmoubGVuZ3RoIDogXy5rZXlzKG9iaikubGVuZ3RoO1xuICB9O1xuXG4gIC8vIFNwbGl0IGEgY29sbGVjdGlvbiBpbnRvIHR3byBhcnJheXM6IG9uZSB3aG9zZSBlbGVtZW50cyBhbGwgc2F0aXNmeSB0aGUgZ2l2ZW5cbiAgLy8gcHJlZGljYXRlLCBhbmQgb25lIHdob3NlIGVsZW1lbnRzIGFsbCBkbyBub3Qgc2F0aXNmeSB0aGUgcHJlZGljYXRlLlxuICBfLnBhcnRpdGlvbiA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgcHJlZGljYXRlID0gY2IocHJlZGljYXRlLCBjb250ZXh0KTtcbiAgICB2YXIgcGFzcyA9IFtdLCBmYWlsID0gW107XG4gICAgXy5lYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGtleSwgb2JqKSB7XG4gICAgICAocHJlZGljYXRlKHZhbHVlLCBrZXksIG9iaikgPyBwYXNzIDogZmFpbCkucHVzaCh2YWx1ZSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIFtwYXNzLCBmYWlsXTtcbiAgfTtcblxuICAvLyBBcnJheSBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tXG5cbiAgLy8gR2V0IHRoZSBmaXJzdCBlbGVtZW50IG9mIGFuIGFycmF5LiBQYXNzaW5nICoqbioqIHdpbGwgcmV0dXJuIHRoZSBmaXJzdCBOXG4gIC8vIHZhbHVlcyBpbiB0aGUgYXJyYXkuIEFsaWFzZWQgYXMgYGhlYWRgIGFuZCBgdGFrZWAuIFRoZSAqKmd1YXJkKiogY2hlY2tcbiAgLy8gYWxsb3dzIGl0IHRvIHdvcmsgd2l0aCBgXy5tYXBgLlxuICBfLmZpcnN0ID0gXy5oZWFkID0gXy50YWtlID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgaWYgKGFycmF5ID09IG51bGwpIHJldHVybiB2b2lkIDA7XG4gICAgaWYgKG4gPT0gbnVsbCB8fCBndWFyZCkgcmV0dXJuIGFycmF5WzBdO1xuICAgIHJldHVybiBfLmluaXRpYWwoYXJyYXksIGFycmF5Lmxlbmd0aCAtIG4pO1xuICB9O1xuXG4gIC8vIFJldHVybnMgZXZlcnl0aGluZyBidXQgdGhlIGxhc3QgZW50cnkgb2YgdGhlIGFycmF5LiBFc3BlY2lhbGx5IHVzZWZ1bCBvblxuICAvLyB0aGUgYXJndW1lbnRzIG9iamVjdC4gUGFzc2luZyAqKm4qKiB3aWxsIHJldHVybiBhbGwgdGhlIHZhbHVlcyBpblxuICAvLyB0aGUgYXJyYXksIGV4Y2x1ZGluZyB0aGUgbGFzdCBOLlxuICBfLmluaXRpYWwgPSBmdW5jdGlvbihhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICByZXR1cm4gc2xpY2UuY2FsbChhcnJheSwgMCwgTWF0aC5tYXgoMCwgYXJyYXkubGVuZ3RoIC0gKG4gPT0gbnVsbCB8fCBndWFyZCA/IDEgOiBuKSkpO1xuICB9O1xuXG4gIC8vIEdldCB0aGUgbGFzdCBlbGVtZW50IG9mIGFuIGFycmF5LiBQYXNzaW5nICoqbioqIHdpbGwgcmV0dXJuIHRoZSBsYXN0IE5cbiAgLy8gdmFsdWVzIGluIHRoZSBhcnJheS5cbiAgXy5sYXN0ID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgaWYgKGFycmF5ID09IG51bGwpIHJldHVybiB2b2lkIDA7XG4gICAgaWYgKG4gPT0gbnVsbCB8fCBndWFyZCkgcmV0dXJuIGFycmF5W2FycmF5Lmxlbmd0aCAtIDFdO1xuICAgIHJldHVybiBfLnJlc3QoYXJyYXksIE1hdGgubWF4KDAsIGFycmF5Lmxlbmd0aCAtIG4pKTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGV2ZXJ5dGhpbmcgYnV0IHRoZSBmaXJzdCBlbnRyeSBvZiB0aGUgYXJyYXkuIEFsaWFzZWQgYXMgYHRhaWxgIGFuZCBgZHJvcGAuXG4gIC8vIEVzcGVjaWFsbHkgdXNlZnVsIG9uIHRoZSBhcmd1bWVudHMgb2JqZWN0LiBQYXNzaW5nIGFuICoqbioqIHdpbGwgcmV0dXJuXG4gIC8vIHRoZSByZXN0IE4gdmFsdWVzIGluIHRoZSBhcnJheS5cbiAgXy5yZXN0ID0gXy50YWlsID0gXy5kcm9wID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgcmV0dXJuIHNsaWNlLmNhbGwoYXJyYXksIG4gPT0gbnVsbCB8fCBndWFyZCA/IDEgOiBuKTtcbiAgfTtcblxuICAvLyBUcmltIG91dCBhbGwgZmFsc3kgdmFsdWVzIGZyb20gYW4gYXJyYXkuXG4gIF8uY29tcGFjdCA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgcmV0dXJuIF8uZmlsdGVyKGFycmF5LCBfLmlkZW50aXR5KTtcbiAgfTtcblxuICAvLyBJbnRlcm5hbCBpbXBsZW1lbnRhdGlvbiBvZiBhIHJlY3Vyc2l2ZSBgZmxhdHRlbmAgZnVuY3Rpb24uXG4gIHZhciBmbGF0dGVuID0gZnVuY3Rpb24oaW5wdXQsIHNoYWxsb3csIHN0cmljdCwgc3RhcnRJbmRleCkge1xuICAgIHZhciBvdXRwdXQgPSBbXSwgaWR4ID0gMDtcbiAgICBmb3IgKHZhciBpID0gc3RhcnRJbmRleCB8fCAwLCBsZW5ndGggPSBnZXRMZW5ndGgoaW5wdXQpOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciB2YWx1ZSA9IGlucHV0W2ldO1xuICAgICAgaWYgKGlzQXJyYXlMaWtlKHZhbHVlKSAmJiAoXy5pc0FycmF5KHZhbHVlKSB8fCBfLmlzQXJndW1lbnRzKHZhbHVlKSkpIHtcbiAgICAgICAgLy9mbGF0dGVuIGN1cnJlbnQgbGV2ZWwgb2YgYXJyYXkgb3IgYXJndW1lbnRzIG9iamVjdFxuICAgICAgICBpZiAoIXNoYWxsb3cpIHZhbHVlID0gZmxhdHRlbih2YWx1ZSwgc2hhbGxvdywgc3RyaWN0KTtcbiAgICAgICAgdmFyIGogPSAwLCBsZW4gPSB2YWx1ZS5sZW5ndGg7XG4gICAgICAgIG91dHB1dC5sZW5ndGggKz0gbGVuO1xuICAgICAgICB3aGlsZSAoaiA8IGxlbikge1xuICAgICAgICAgIG91dHB1dFtpZHgrK10gPSB2YWx1ZVtqKytdO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKCFzdHJpY3QpIHtcbiAgICAgICAgb3V0cHV0W2lkeCsrXSA9IHZhbHVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gb3V0cHV0O1xuICB9O1xuXG4gIC8vIEZsYXR0ZW4gb3V0IGFuIGFycmF5LCBlaXRoZXIgcmVjdXJzaXZlbHkgKGJ5IGRlZmF1bHQpLCBvciBqdXN0IG9uZSBsZXZlbC5cbiAgXy5mbGF0dGVuID0gZnVuY3Rpb24oYXJyYXksIHNoYWxsb3cpIHtcbiAgICByZXR1cm4gZmxhdHRlbihhcnJheSwgc2hhbGxvdywgZmFsc2UpO1xuICB9O1xuXG4gIC8vIFJldHVybiBhIHZlcnNpb24gb2YgdGhlIGFycmF5IHRoYXQgZG9lcyBub3QgY29udGFpbiB0aGUgc3BlY2lmaWVkIHZhbHVlKHMpLlxuICBfLndpdGhvdXQgPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHJldHVybiBfLmRpZmZlcmVuY2UoYXJyYXksIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gIH07XG5cbiAgLy8gUHJvZHVjZSBhIGR1cGxpY2F0ZS1mcmVlIHZlcnNpb24gb2YgdGhlIGFycmF5LiBJZiB0aGUgYXJyYXkgaGFzIGFscmVhZHlcbiAgLy8gYmVlbiBzb3J0ZWQsIHlvdSBoYXZlIHRoZSBvcHRpb24gb2YgdXNpbmcgYSBmYXN0ZXIgYWxnb3JpdGhtLlxuICAvLyBBbGlhc2VkIGFzIGB1bmlxdWVgLlxuICBfLnVuaXEgPSBfLnVuaXF1ZSA9IGZ1bmN0aW9uKGFycmF5LCBpc1NvcnRlZCwgaXRlcmF0ZWUsIGNvbnRleHQpIHtcbiAgICBpZiAoIV8uaXNCb29sZWFuKGlzU29ydGVkKSkge1xuICAgICAgY29udGV4dCA9IGl0ZXJhdGVlO1xuICAgICAgaXRlcmF0ZWUgPSBpc1NvcnRlZDtcbiAgICAgIGlzU29ydGVkID0gZmFsc2U7XG4gICAgfVxuICAgIGlmIChpdGVyYXRlZSAhPSBudWxsKSBpdGVyYXRlZSA9IGNiKGl0ZXJhdGVlLCBjb250ZXh0KTtcbiAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgdmFyIHNlZW4gPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gZ2V0TGVuZ3RoKGFycmF5KTsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgdmFsdWUgPSBhcnJheVtpXSxcbiAgICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlID8gaXRlcmF0ZWUodmFsdWUsIGksIGFycmF5KSA6IHZhbHVlO1xuICAgICAgaWYgKGlzU29ydGVkKSB7XG4gICAgICAgIGlmICghaSB8fCBzZWVuICE9PSBjb21wdXRlZCkgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICBzZWVuID0gY29tcHV0ZWQ7XG4gICAgICB9IGVsc2UgaWYgKGl0ZXJhdGVlKSB7XG4gICAgICAgIGlmICghXy5jb250YWlucyhzZWVuLCBjb21wdXRlZCkpIHtcbiAgICAgICAgICBzZWVuLnB1c2goY29tcHV0ZWQpO1xuICAgICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICghXy5jb250YWlucyhyZXN1bHQsIHZhbHVlKSkge1xuICAgICAgICByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gUHJvZHVjZSBhbiBhcnJheSB0aGF0IGNvbnRhaW5zIHRoZSB1bmlvbjogZWFjaCBkaXN0aW5jdCBlbGVtZW50IGZyb20gYWxsIG9mXG4gIC8vIHRoZSBwYXNzZWQtaW4gYXJyYXlzLlxuICBfLnVuaW9uID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIF8udW5pcShmbGF0dGVuKGFyZ3VtZW50cywgdHJ1ZSwgdHJ1ZSkpO1xuICB9O1xuXG4gIC8vIFByb2R1Y2UgYW4gYXJyYXkgdGhhdCBjb250YWlucyBldmVyeSBpdGVtIHNoYXJlZCBiZXR3ZWVuIGFsbCB0aGVcbiAgLy8gcGFzc2VkLWluIGFycmF5cy5cbiAgXy5pbnRlcnNlY3Rpb24gPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICB2YXIgYXJnc0xlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGdldExlbmd0aChhcnJheSk7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGl0ZW0gPSBhcnJheVtpXTtcbiAgICAgIGlmIChfLmNvbnRhaW5zKHJlc3VsdCwgaXRlbSkpIGNvbnRpbnVlO1xuICAgICAgZm9yICh2YXIgaiA9IDE7IGogPCBhcmdzTGVuZ3RoOyBqKyspIHtcbiAgICAgICAgaWYgKCFfLmNvbnRhaW5zKGFyZ3VtZW50c1tqXSwgaXRlbSkpIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKGogPT09IGFyZ3NMZW5ndGgpIHJlc3VsdC5wdXNoKGl0ZW0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFRha2UgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBvbmUgYXJyYXkgYW5kIGEgbnVtYmVyIG9mIG90aGVyIGFycmF5cy5cbiAgLy8gT25seSB0aGUgZWxlbWVudHMgcHJlc2VudCBpbiBqdXN0IHRoZSBmaXJzdCBhcnJheSB3aWxsIHJlbWFpbi5cbiAgXy5kaWZmZXJlbmNlID0gZnVuY3Rpb24oYXJyYXkpIHtcbiAgICB2YXIgcmVzdCA9IGZsYXR0ZW4oYXJndW1lbnRzLCB0cnVlLCB0cnVlLCAxKTtcbiAgICByZXR1cm4gXy5maWx0ZXIoYXJyYXksIGZ1bmN0aW9uKHZhbHVlKXtcbiAgICAgIHJldHVybiAhXy5jb250YWlucyhyZXN0LCB2YWx1ZSk7XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gWmlwIHRvZ2V0aGVyIG11bHRpcGxlIGxpc3RzIGludG8gYSBzaW5nbGUgYXJyYXkgLS0gZWxlbWVudHMgdGhhdCBzaGFyZVxuICAvLyBhbiBpbmRleCBnbyB0b2dldGhlci5cbiAgXy56aXAgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gXy51bnppcChhcmd1bWVudHMpO1xuICB9O1xuXG4gIC8vIENvbXBsZW1lbnQgb2YgXy56aXAuIFVuemlwIGFjY2VwdHMgYW4gYXJyYXkgb2YgYXJyYXlzIGFuZCBncm91cHNcbiAgLy8gZWFjaCBhcnJheSdzIGVsZW1lbnRzIG9uIHNoYXJlZCBpbmRpY2VzXG4gIF8udW56aXAgPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHZhciBsZW5ndGggPSBhcnJheSAmJiBfLm1heChhcnJheSwgZ2V0TGVuZ3RoKS5sZW5ndGggfHwgMDtcbiAgICB2YXIgcmVzdWx0ID0gQXJyYXkobGVuZ3RoKTtcblxuICAgIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgIHJlc3VsdFtpbmRleF0gPSBfLnBsdWNrKGFycmF5LCBpbmRleCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gQ29udmVydHMgbGlzdHMgaW50byBvYmplY3RzLiBQYXNzIGVpdGhlciBhIHNpbmdsZSBhcnJheSBvZiBgW2tleSwgdmFsdWVdYFxuICAvLyBwYWlycywgb3IgdHdvIHBhcmFsbGVsIGFycmF5cyBvZiB0aGUgc2FtZSBsZW5ndGggLS0gb25lIG9mIGtleXMsIGFuZCBvbmUgb2ZcbiAgLy8gdGhlIGNvcnJlc3BvbmRpbmcgdmFsdWVzLlxuICBfLm9iamVjdCA9IGZ1bmN0aW9uKGxpc3QsIHZhbHVlcykge1xuICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gZ2V0TGVuZ3RoKGxpc3QpOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICh2YWx1ZXMpIHtcbiAgICAgICAgcmVzdWx0W2xpc3RbaV1dID0gdmFsdWVzW2ldO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzdWx0W2xpc3RbaV1bMF1dID0gbGlzdFtpXVsxXTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBHZW5lcmF0b3IgZnVuY3Rpb24gdG8gY3JlYXRlIHRoZSBmaW5kSW5kZXggYW5kIGZpbmRMYXN0SW5kZXggZnVuY3Rpb25zXG4gIGZ1bmN0aW9uIGNyZWF0ZVByZWRpY2F0ZUluZGV4RmluZGVyKGRpcikge1xuICAgIHJldHVybiBmdW5jdGlvbihhcnJheSwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgICBwcmVkaWNhdGUgPSBjYihwcmVkaWNhdGUsIGNvbnRleHQpO1xuICAgICAgdmFyIGxlbmd0aCA9IGdldExlbmd0aChhcnJheSk7XG4gICAgICB2YXIgaW5kZXggPSBkaXIgPiAwID8gMCA6IGxlbmd0aCAtIDE7XG4gICAgICBmb3IgKDsgaW5kZXggPj0gMCAmJiBpbmRleCA8IGxlbmd0aDsgaW5kZXggKz0gZGlyKSB7XG4gICAgICAgIGlmIChwcmVkaWNhdGUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpKSByZXR1cm4gaW5kZXg7XG4gICAgICB9XG4gICAgICByZXR1cm4gLTE7XG4gICAgfTtcbiAgfVxuXG4gIC8vIFJldHVybnMgdGhlIGZpcnN0IGluZGV4IG9uIGFuIGFycmF5LWxpa2UgdGhhdCBwYXNzZXMgYSBwcmVkaWNhdGUgdGVzdFxuICBfLmZpbmRJbmRleCA9IGNyZWF0ZVByZWRpY2F0ZUluZGV4RmluZGVyKDEpO1xuICBfLmZpbmRMYXN0SW5kZXggPSBjcmVhdGVQcmVkaWNhdGVJbmRleEZpbmRlcigtMSk7XG5cbiAgLy8gVXNlIGEgY29tcGFyYXRvciBmdW5jdGlvbiB0byBmaWd1cmUgb3V0IHRoZSBzbWFsbGVzdCBpbmRleCBhdCB3aGljaFxuICAvLyBhbiBvYmplY3Qgc2hvdWxkIGJlIGluc2VydGVkIHNvIGFzIHRvIG1haW50YWluIG9yZGVyLiBVc2VzIGJpbmFyeSBzZWFyY2guXG4gIF8uc29ydGVkSW5kZXggPSBmdW5jdGlvbihhcnJheSwgb2JqLCBpdGVyYXRlZSwgY29udGV4dCkge1xuICAgIGl0ZXJhdGVlID0gY2IoaXRlcmF0ZWUsIGNvbnRleHQsIDEpO1xuICAgIHZhciB2YWx1ZSA9IGl0ZXJhdGVlKG9iaik7XG4gICAgdmFyIGxvdyA9IDAsIGhpZ2ggPSBnZXRMZW5ndGgoYXJyYXkpO1xuICAgIHdoaWxlIChsb3cgPCBoaWdoKSB7XG4gICAgICB2YXIgbWlkID0gTWF0aC5mbG9vcigobG93ICsgaGlnaCkgLyAyKTtcbiAgICAgIGlmIChpdGVyYXRlZShhcnJheVttaWRdKSA8IHZhbHVlKSBsb3cgPSBtaWQgKyAxOyBlbHNlIGhpZ2ggPSBtaWQ7XG4gICAgfVxuICAgIHJldHVybiBsb3c7XG4gIH07XG5cbiAgLy8gR2VuZXJhdG9yIGZ1bmN0aW9uIHRvIGNyZWF0ZSB0aGUgaW5kZXhPZiBhbmQgbGFzdEluZGV4T2YgZnVuY3Rpb25zXG4gIGZ1bmN0aW9uIGNyZWF0ZUluZGV4RmluZGVyKGRpciwgcHJlZGljYXRlRmluZCwgc29ydGVkSW5kZXgpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oYXJyYXksIGl0ZW0sIGlkeCkge1xuICAgICAgdmFyIGkgPSAwLCBsZW5ndGggPSBnZXRMZW5ndGgoYXJyYXkpO1xuICAgICAgaWYgKHR5cGVvZiBpZHggPT0gJ251bWJlcicpIHtcbiAgICAgICAgaWYgKGRpciA+IDApIHtcbiAgICAgICAgICAgIGkgPSBpZHggPj0gMCA/IGlkeCA6IE1hdGgubWF4KGlkeCArIGxlbmd0aCwgaSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsZW5ndGggPSBpZHggPj0gMCA/IE1hdGgubWluKGlkeCArIDEsIGxlbmd0aCkgOiBpZHggKyBsZW5ndGggKyAxO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHNvcnRlZEluZGV4ICYmIGlkeCAmJiBsZW5ndGgpIHtcbiAgICAgICAgaWR4ID0gc29ydGVkSW5kZXgoYXJyYXksIGl0ZW0pO1xuICAgICAgICByZXR1cm4gYXJyYXlbaWR4XSA9PT0gaXRlbSA/IGlkeCA6IC0xO1xuICAgICAgfVxuICAgICAgaWYgKGl0ZW0gIT09IGl0ZW0pIHtcbiAgICAgICAgaWR4ID0gcHJlZGljYXRlRmluZChzbGljZS5jYWxsKGFycmF5LCBpLCBsZW5ndGgpLCBfLmlzTmFOKTtcbiAgICAgICAgcmV0dXJuIGlkeCA+PSAwID8gaWR4ICsgaSA6IC0xO1xuICAgICAgfVxuICAgICAgZm9yIChpZHggPSBkaXIgPiAwID8gaSA6IGxlbmd0aCAtIDE7IGlkeCA+PSAwICYmIGlkeCA8IGxlbmd0aDsgaWR4ICs9IGRpcikge1xuICAgICAgICBpZiAoYXJyYXlbaWR4XSA9PT0gaXRlbSkgcmV0dXJuIGlkeDtcbiAgICAgIH1cbiAgICAgIHJldHVybiAtMTtcbiAgICB9O1xuICB9XG5cbiAgLy8gUmV0dXJuIHRoZSBwb3NpdGlvbiBvZiB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBhbiBpdGVtIGluIGFuIGFycmF5LFxuICAvLyBvciAtMSBpZiB0aGUgaXRlbSBpcyBub3QgaW5jbHVkZWQgaW4gdGhlIGFycmF5LlxuICAvLyBJZiB0aGUgYXJyYXkgaXMgbGFyZ2UgYW5kIGFscmVhZHkgaW4gc29ydCBvcmRlciwgcGFzcyBgdHJ1ZWBcbiAgLy8gZm9yICoqaXNTb3J0ZWQqKiB0byB1c2UgYmluYXJ5IHNlYXJjaC5cbiAgXy5pbmRleE9mID0gY3JlYXRlSW5kZXhGaW5kZXIoMSwgXy5maW5kSW5kZXgsIF8uc29ydGVkSW5kZXgpO1xuICBfLmxhc3RJbmRleE9mID0gY3JlYXRlSW5kZXhGaW5kZXIoLTEsIF8uZmluZExhc3RJbmRleCk7XG5cbiAgLy8gR2VuZXJhdGUgYW4gaW50ZWdlciBBcnJheSBjb250YWluaW5nIGFuIGFyaXRobWV0aWMgcHJvZ3Jlc3Npb24uIEEgcG9ydCBvZlxuICAvLyB0aGUgbmF0aXZlIFB5dGhvbiBgcmFuZ2UoKWAgZnVuY3Rpb24uIFNlZVxuICAvLyBbdGhlIFB5dGhvbiBkb2N1bWVudGF0aW9uXShodHRwOi8vZG9jcy5weXRob24ub3JnL2xpYnJhcnkvZnVuY3Rpb25zLmh0bWwjcmFuZ2UpLlxuICBfLnJhbmdlID0gZnVuY3Rpb24oc3RhcnQsIHN0b3AsIHN0ZXApIHtcbiAgICBpZiAoc3RvcCA9PSBudWxsKSB7XG4gICAgICBzdG9wID0gc3RhcnQgfHwgMDtcbiAgICAgIHN0YXJ0ID0gMDtcbiAgICB9XG4gICAgc3RlcCA9IHN0ZXAgfHwgMTtcblxuICAgIHZhciBsZW5ndGggPSBNYXRoLm1heChNYXRoLmNlaWwoKHN0b3AgLSBzdGFydCkgLyBzdGVwKSwgMCk7XG4gICAgdmFyIHJhbmdlID0gQXJyYXkobGVuZ3RoKTtcblxuICAgIGZvciAodmFyIGlkeCA9IDA7IGlkeCA8IGxlbmd0aDsgaWR4KyssIHN0YXJ0ICs9IHN0ZXApIHtcbiAgICAgIHJhbmdlW2lkeF0gPSBzdGFydDtcbiAgICB9XG5cbiAgICByZXR1cm4gcmFuZ2U7XG4gIH07XG5cbiAgLy8gRnVuY3Rpb24gKGFoZW0pIEZ1bmN0aW9uc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBEZXRlcm1pbmVzIHdoZXRoZXIgdG8gZXhlY3V0ZSBhIGZ1bmN0aW9uIGFzIGEgY29uc3RydWN0b3JcbiAgLy8gb3IgYSBub3JtYWwgZnVuY3Rpb24gd2l0aCB0aGUgcHJvdmlkZWQgYXJndW1lbnRzXG4gIHZhciBleGVjdXRlQm91bmQgPSBmdW5jdGlvbihzb3VyY2VGdW5jLCBib3VuZEZ1bmMsIGNvbnRleHQsIGNhbGxpbmdDb250ZXh0LCBhcmdzKSB7XG4gICAgaWYgKCEoY2FsbGluZ0NvbnRleHQgaW5zdGFuY2VvZiBib3VuZEZ1bmMpKSByZXR1cm4gc291cmNlRnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICB2YXIgc2VsZiA9IGJhc2VDcmVhdGUoc291cmNlRnVuYy5wcm90b3R5cGUpO1xuICAgIHZhciByZXN1bHQgPSBzb3VyY2VGdW5jLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICAgIGlmIChfLmlzT2JqZWN0KHJlc3VsdCkpIHJldHVybiByZXN1bHQ7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH07XG5cbiAgLy8gQ3JlYXRlIGEgZnVuY3Rpb24gYm91bmQgdG8gYSBnaXZlbiBvYmplY3QgKGFzc2lnbmluZyBgdGhpc2AsIGFuZCBhcmd1bWVudHMsXG4gIC8vIG9wdGlvbmFsbHkpLiBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgRnVuY3Rpb24uYmluZGAgaWZcbiAgLy8gYXZhaWxhYmxlLlxuICBfLmJpbmQgPSBmdW5jdGlvbihmdW5jLCBjb250ZXh0KSB7XG4gICAgaWYgKG5hdGl2ZUJpbmQgJiYgZnVuYy5iaW5kID09PSBuYXRpdmVCaW5kKSByZXR1cm4gbmF0aXZlQmluZC5hcHBseShmdW5jLCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICAgIGlmICghXy5pc0Z1bmN0aW9uKGZ1bmMpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdCaW5kIG11c3QgYmUgY2FsbGVkIG9uIGEgZnVuY3Rpb24nKTtcbiAgICB2YXIgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICB2YXIgYm91bmQgPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBleGVjdXRlQm91bmQoZnVuYywgYm91bmQsIGNvbnRleHQsIHRoaXMsIGFyZ3MuY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzKSkpO1xuICAgIH07XG4gICAgcmV0dXJuIGJvdW5kO1xuICB9O1xuXG4gIC8vIFBhcnRpYWxseSBhcHBseSBhIGZ1bmN0aW9uIGJ5IGNyZWF0aW5nIGEgdmVyc2lvbiB0aGF0IGhhcyBoYWQgc29tZSBvZiBpdHNcbiAgLy8gYXJndW1lbnRzIHByZS1maWxsZWQsIHdpdGhvdXQgY2hhbmdpbmcgaXRzIGR5bmFtaWMgYHRoaXNgIGNvbnRleHQuIF8gYWN0c1xuICAvLyBhcyBhIHBsYWNlaG9sZGVyLCBhbGxvd2luZyBhbnkgY29tYmluYXRpb24gb2YgYXJndW1lbnRzIHRvIGJlIHByZS1maWxsZWQuXG4gIF8ucGFydGlhbCA9IGZ1bmN0aW9uKGZ1bmMpIHtcbiAgICB2YXIgYm91bmRBcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgIHZhciBib3VuZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIHBvc2l0aW9uID0gMCwgbGVuZ3RoID0gYm91bmRBcmdzLmxlbmd0aDtcbiAgICAgIHZhciBhcmdzID0gQXJyYXkobGVuZ3RoKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgYXJnc1tpXSA9IGJvdW5kQXJnc1tpXSA9PT0gXyA/IGFyZ3VtZW50c1twb3NpdGlvbisrXSA6IGJvdW5kQXJnc1tpXTtcbiAgICAgIH1cbiAgICAgIHdoaWxlIChwb3NpdGlvbiA8IGFyZ3VtZW50cy5sZW5ndGgpIGFyZ3MucHVzaChhcmd1bWVudHNbcG9zaXRpb24rK10pO1xuICAgICAgcmV0dXJuIGV4ZWN1dGVCb3VuZChmdW5jLCBib3VuZCwgdGhpcywgdGhpcywgYXJncyk7XG4gICAgfTtcbiAgICByZXR1cm4gYm91bmQ7XG4gIH07XG5cbiAgLy8gQmluZCBhIG51bWJlciBvZiBhbiBvYmplY3QncyBtZXRob2RzIHRvIHRoYXQgb2JqZWN0LiBSZW1haW5pbmcgYXJndW1lbnRzXG4gIC8vIGFyZSB0aGUgbWV0aG9kIG5hbWVzIHRvIGJlIGJvdW5kLiBVc2VmdWwgZm9yIGVuc3VyaW5nIHRoYXQgYWxsIGNhbGxiYWNrc1xuICAvLyBkZWZpbmVkIG9uIGFuIG9iamVjdCBiZWxvbmcgdG8gaXQuXG4gIF8uYmluZEFsbCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBpLCBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoLCBrZXk7XG4gICAgaWYgKGxlbmd0aCA8PSAxKSB0aHJvdyBuZXcgRXJyb3IoJ2JpbmRBbGwgbXVzdCBiZSBwYXNzZWQgZnVuY3Rpb24gbmFtZXMnKTtcbiAgICBmb3IgKGkgPSAxOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIGtleSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgIG9ialtrZXldID0gXy5iaW5kKG9ialtrZXldLCBvYmopO1xuICAgIH1cbiAgICByZXR1cm4gb2JqO1xuICB9O1xuXG4gIC8vIE1lbW9pemUgYW4gZXhwZW5zaXZlIGZ1bmN0aW9uIGJ5IHN0b3JpbmcgaXRzIHJlc3VsdHMuXG4gIF8ubWVtb2l6ZSA9IGZ1bmN0aW9uKGZ1bmMsIGhhc2hlcikge1xuICAgIHZhciBtZW1vaXplID0gZnVuY3Rpb24oa2V5KSB7XG4gICAgICB2YXIgY2FjaGUgPSBtZW1vaXplLmNhY2hlO1xuICAgICAgdmFyIGFkZHJlc3MgPSAnJyArIChoYXNoZXIgPyBoYXNoZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSA6IGtleSk7XG4gICAgICBpZiAoIV8uaGFzKGNhY2hlLCBhZGRyZXNzKSkgY2FjaGVbYWRkcmVzc10gPSBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICByZXR1cm4gY2FjaGVbYWRkcmVzc107XG4gICAgfTtcbiAgICBtZW1vaXplLmNhY2hlID0ge307XG4gICAgcmV0dXJuIG1lbW9pemU7XG4gIH07XG5cbiAgLy8gRGVsYXlzIGEgZnVuY3Rpb24gZm9yIHRoZSBnaXZlbiBudW1iZXIgb2YgbWlsbGlzZWNvbmRzLCBhbmQgdGhlbiBjYWxsc1xuICAvLyBpdCB3aXRoIHRoZSBhcmd1bWVudHMgc3VwcGxpZWQuXG4gIF8uZGVsYXkgPSBmdW5jdGlvbihmdW5jLCB3YWl0KSB7XG4gICAgdmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcbiAgICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGFyZ3MpO1xuICAgIH0sIHdhaXQpO1xuICB9O1xuXG4gIC8vIERlZmVycyBhIGZ1bmN0aW9uLCBzY2hlZHVsaW5nIGl0IHRvIHJ1biBhZnRlciB0aGUgY3VycmVudCBjYWxsIHN0YWNrIGhhc1xuICAvLyBjbGVhcmVkLlxuICBfLmRlZmVyID0gXy5wYXJ0aWFsKF8uZGVsYXksIF8sIDEpO1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiwgdGhhdCwgd2hlbiBpbnZva2VkLCB3aWxsIG9ubHkgYmUgdHJpZ2dlcmVkIGF0IG1vc3Qgb25jZVxuICAvLyBkdXJpbmcgYSBnaXZlbiB3aW5kb3cgb2YgdGltZS4gTm9ybWFsbHksIHRoZSB0aHJvdHRsZWQgZnVuY3Rpb24gd2lsbCBydW5cbiAgLy8gYXMgbXVjaCBhcyBpdCBjYW4sIHdpdGhvdXQgZXZlciBnb2luZyBtb3JlIHRoYW4gb25jZSBwZXIgYHdhaXRgIGR1cmF0aW9uO1xuICAvLyBidXQgaWYgeW91J2QgbGlrZSB0byBkaXNhYmxlIHRoZSBleGVjdXRpb24gb24gdGhlIGxlYWRpbmcgZWRnZSwgcGFzc1xuICAvLyBge2xlYWRpbmc6IGZhbHNlfWAuIFRvIGRpc2FibGUgZXhlY3V0aW9uIG9uIHRoZSB0cmFpbGluZyBlZGdlLCBkaXR0by5cbiAgXy50aHJvdHRsZSA9IGZ1bmN0aW9uKGZ1bmMsIHdhaXQsIG9wdGlvbnMpIHtcbiAgICB2YXIgY29udGV4dCwgYXJncywgcmVzdWx0O1xuICAgIHZhciB0aW1lb3V0ID0gbnVsbDtcbiAgICB2YXIgcHJldmlvdXMgPSAwO1xuICAgIGlmICghb3B0aW9ucykgb3B0aW9ucyA9IHt9O1xuICAgIHZhciBsYXRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgcHJldmlvdXMgPSBvcHRpb25zLmxlYWRpbmcgPT09IGZhbHNlID8gMCA6IF8ubm93KCk7XG4gICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICBpZiAoIXRpbWVvdXQpIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBub3cgPSBfLm5vdygpO1xuICAgICAgaWYgKCFwcmV2aW91cyAmJiBvcHRpb25zLmxlYWRpbmcgPT09IGZhbHNlKSBwcmV2aW91cyA9IG5vdztcbiAgICAgIHZhciByZW1haW5pbmcgPSB3YWl0IC0gKG5vdyAtIHByZXZpb3VzKTtcbiAgICAgIGNvbnRleHQgPSB0aGlzO1xuICAgICAgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIGlmIChyZW1haW5pbmcgPD0gMCB8fCByZW1haW5pbmcgPiB3YWl0KSB7XG4gICAgICAgIGlmICh0aW1lb3V0KSB7XG4gICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHByZXZpb3VzID0gbm93O1xuICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICBpZiAoIXRpbWVvdXQpIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcbiAgICAgIH0gZWxzZSBpZiAoIXRpbWVvdXQgJiYgb3B0aW9ucy50cmFpbGluZyAhPT0gZmFsc2UpIHtcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHJlbWFpbmluZyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uLCB0aGF0LCBhcyBsb25nIGFzIGl0IGNvbnRpbnVlcyB0byBiZSBpbnZva2VkLCB3aWxsIG5vdFxuICAvLyBiZSB0cmlnZ2VyZWQuIFRoZSBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBhZnRlciBpdCBzdG9wcyBiZWluZyBjYWxsZWQgZm9yXG4gIC8vIE4gbWlsbGlzZWNvbmRzLiBJZiBgaW1tZWRpYXRlYCBpcyBwYXNzZWQsIHRyaWdnZXIgdGhlIGZ1bmN0aW9uIG9uIHRoZVxuICAvLyBsZWFkaW5nIGVkZ2UsIGluc3RlYWQgb2YgdGhlIHRyYWlsaW5nLlxuICBfLmRlYm91bmNlID0gZnVuY3Rpb24oZnVuYywgd2FpdCwgaW1tZWRpYXRlKSB7XG4gICAgdmFyIHRpbWVvdXQsIGFyZ3MsIGNvbnRleHQsIHRpbWVzdGFtcCwgcmVzdWx0O1xuXG4gICAgdmFyIGxhdGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbGFzdCA9IF8ubm93KCkgLSB0aW1lc3RhbXA7XG5cbiAgICAgIGlmIChsYXN0IDwgd2FpdCAmJiBsYXN0ID49IDApIHtcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQgLSBsYXN0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICBpZiAoIWltbWVkaWF0ZSkge1xuICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgICAgaWYgKCF0aW1lb3V0KSBjb250ZXh0ID0gYXJncyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgY29udGV4dCA9IHRoaXM7XG4gICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgdGltZXN0YW1wID0gXy5ub3coKTtcbiAgICAgIHZhciBjYWxsTm93ID0gaW1tZWRpYXRlICYmICF0aW1lb3V0O1xuICAgICAgaWYgKCF0aW1lb3V0KSB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgd2FpdCk7XG4gICAgICBpZiAoY2FsbE5vdykge1xuICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICBjb250ZXh0ID0gYXJncyA9IG51bGw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIHRoZSBmaXJzdCBmdW5jdGlvbiBwYXNzZWQgYXMgYW4gYXJndW1lbnQgdG8gdGhlIHNlY29uZCxcbiAgLy8gYWxsb3dpbmcgeW91IHRvIGFkanVzdCBhcmd1bWVudHMsIHJ1biBjb2RlIGJlZm9yZSBhbmQgYWZ0ZXIsIGFuZFxuICAvLyBjb25kaXRpb25hbGx5IGV4ZWN1dGUgdGhlIG9yaWdpbmFsIGZ1bmN0aW9uLlxuICBfLndyYXAgPSBmdW5jdGlvbihmdW5jLCB3cmFwcGVyKSB7XG4gICAgcmV0dXJuIF8ucGFydGlhbCh3cmFwcGVyLCBmdW5jKTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgbmVnYXRlZCB2ZXJzaW9uIG9mIHRoZSBwYXNzZWQtaW4gcHJlZGljYXRlLlxuICBfLm5lZ2F0ZSA9IGZ1bmN0aW9uKHByZWRpY2F0ZSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiAhcHJlZGljYXRlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBpcyB0aGUgY29tcG9zaXRpb24gb2YgYSBsaXN0IG9mIGZ1bmN0aW9ucywgZWFjaFxuICAvLyBjb25zdW1pbmcgdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgZnVuY3Rpb24gdGhhdCBmb2xsb3dzLlxuICBfLmNvbXBvc2UgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICB2YXIgc3RhcnQgPSBhcmdzLmxlbmd0aCAtIDE7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGkgPSBzdGFydDtcbiAgICAgIHZhciByZXN1bHQgPSBhcmdzW3N0YXJ0XS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgd2hpbGUgKGktLSkgcmVzdWx0ID0gYXJnc1tpXS5jYWxsKHRoaXMsIHJlc3VsdCk7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBvbmx5IGJlIGV4ZWN1dGVkIG9uIGFuZCBhZnRlciB0aGUgTnRoIGNhbGwuXG4gIF8uYWZ0ZXIgPSBmdW5jdGlvbih0aW1lcywgZnVuYykge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICgtLXRpbWVzIDwgMSkge1xuICAgICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgfVxuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBvbmx5IGJlIGV4ZWN1dGVkIHVwIHRvIChidXQgbm90IGluY2x1ZGluZykgdGhlIE50aCBjYWxsLlxuICBfLmJlZm9yZSA9IGZ1bmN0aW9uKHRpbWVzLCBmdW5jKSB7XG4gICAgdmFyIG1lbW87XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKC0tdGltZXMgPiAwKSB7XG4gICAgICAgIG1lbW8gPSBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB9XG4gICAgICBpZiAodGltZXMgPD0gMSkgZnVuYyA9IG51bGw7XG4gICAgICByZXR1cm4gbWVtbztcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiB0aGF0IHdpbGwgYmUgZXhlY3V0ZWQgYXQgbW9zdCBvbmUgdGltZSwgbm8gbWF0dGVyIGhvd1xuICAvLyBvZnRlbiB5b3UgY2FsbCBpdC4gVXNlZnVsIGZvciBsYXp5IGluaXRpYWxpemF0aW9uLlxuICBfLm9uY2UgPSBfLnBhcnRpYWwoXy5iZWZvcmUsIDIpO1xuXG4gIC8vIE9iamVjdCBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIEtleXMgaW4gSUUgPCA5IHRoYXQgd29uJ3QgYmUgaXRlcmF0ZWQgYnkgYGZvciBrZXkgaW4gLi4uYCBhbmQgdGh1cyBtaXNzZWQuXG4gIHZhciBoYXNFbnVtQnVnID0gIXt0b1N0cmluZzogbnVsbH0ucHJvcGVydHlJc0VudW1lcmFibGUoJ3RvU3RyaW5nJyk7XG4gIHZhciBub25FbnVtZXJhYmxlUHJvcHMgPSBbJ3ZhbHVlT2YnLCAnaXNQcm90b3R5cGVPZicsICd0b1N0cmluZycsXG4gICAgICAgICAgICAgICAgICAgICAgJ3Byb3BlcnR5SXNFbnVtZXJhYmxlJywgJ2hhc093blByb3BlcnR5JywgJ3RvTG9jYWxlU3RyaW5nJ107XG5cbiAgZnVuY3Rpb24gY29sbGVjdE5vbkVudW1Qcm9wcyhvYmosIGtleXMpIHtcbiAgICB2YXIgbm9uRW51bUlkeCA9IG5vbkVudW1lcmFibGVQcm9wcy5sZW5ndGg7XG4gICAgdmFyIGNvbnN0cnVjdG9yID0gb2JqLmNvbnN0cnVjdG9yO1xuICAgIHZhciBwcm90byA9IChfLmlzRnVuY3Rpb24oY29uc3RydWN0b3IpICYmIGNvbnN0cnVjdG9yLnByb3RvdHlwZSkgfHwgT2JqUHJvdG87XG5cbiAgICAvLyBDb25zdHJ1Y3RvciBpcyBhIHNwZWNpYWwgY2FzZS5cbiAgICB2YXIgcHJvcCA9ICdjb25zdHJ1Y3Rvcic7XG4gICAgaWYgKF8uaGFzKG9iaiwgcHJvcCkgJiYgIV8uY29udGFpbnMoa2V5cywgcHJvcCkpIGtleXMucHVzaChwcm9wKTtcblxuICAgIHdoaWxlIChub25FbnVtSWR4LS0pIHtcbiAgICAgIHByb3AgPSBub25FbnVtZXJhYmxlUHJvcHNbbm9uRW51bUlkeF07XG4gICAgICBpZiAocHJvcCBpbiBvYmogJiYgb2JqW3Byb3BdICE9PSBwcm90b1twcm9wXSAmJiAhXy5jb250YWlucyhrZXlzLCBwcm9wKSkge1xuICAgICAgICBrZXlzLnB1c2gocHJvcCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gUmV0cmlldmUgdGhlIG5hbWVzIG9mIGFuIG9iamVjdCdzIG93biBwcm9wZXJ0aWVzLlxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgT2JqZWN0LmtleXNgXG4gIF8ua2V5cyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmICghXy5pc09iamVjdChvYmopKSByZXR1cm4gW107XG4gICAgaWYgKG5hdGl2ZUtleXMpIHJldHVybiBuYXRpdmVLZXlzKG9iaik7XG4gICAgdmFyIGtleXMgPSBbXTtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSBpZiAoXy5oYXMob2JqLCBrZXkpKSBrZXlzLnB1c2goa2V5KTtcbiAgICAvLyBBaGVtLCBJRSA8IDkuXG4gICAgaWYgKGhhc0VudW1CdWcpIGNvbGxlY3ROb25FbnVtUHJvcHMob2JqLCBrZXlzKTtcbiAgICByZXR1cm4ga2V5cztcbiAgfTtcblxuICAvLyBSZXRyaWV2ZSBhbGwgdGhlIHByb3BlcnR5IG5hbWVzIG9mIGFuIG9iamVjdC5cbiAgXy5hbGxLZXlzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYgKCFfLmlzT2JqZWN0KG9iaikpIHJldHVybiBbXTtcbiAgICB2YXIga2V5cyA9IFtdO1xuICAgIGZvciAodmFyIGtleSBpbiBvYmopIGtleXMucHVzaChrZXkpO1xuICAgIC8vIEFoZW0sIElFIDwgOS5cbiAgICBpZiAoaGFzRW51bUJ1ZykgY29sbGVjdE5vbkVudW1Qcm9wcyhvYmosIGtleXMpO1xuICAgIHJldHVybiBrZXlzO1xuICB9O1xuXG4gIC8vIFJldHJpZXZlIHRoZSB2YWx1ZXMgb2YgYW4gb2JqZWN0J3MgcHJvcGVydGllcy5cbiAgXy52YWx1ZXMgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xuICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgICB2YXIgdmFsdWVzID0gQXJyYXkobGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB2YWx1ZXNbaV0gPSBvYmpba2V5c1tpXV07XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZXM7XG4gIH07XG5cbiAgLy8gUmV0dXJucyB0aGUgcmVzdWx0cyBvZiBhcHBseWluZyB0aGUgaXRlcmF0ZWUgdG8gZWFjaCBlbGVtZW50IG9mIHRoZSBvYmplY3RcbiAgLy8gSW4gY29udHJhc3QgdG8gXy5tYXAgaXQgcmV0dXJucyBhbiBvYmplY3RcbiAgXy5tYXBPYmplY3QgPSBmdW5jdGlvbihvYmosIGl0ZXJhdGVlLCBjb250ZXh0KSB7XG4gICAgaXRlcmF0ZWUgPSBjYihpdGVyYXRlZSwgY29udGV4dCk7XG4gICAgdmFyIGtleXMgPSAgXy5rZXlzKG9iaiksXG4gICAgICAgICAgbGVuZ3RoID0ga2V5cy5sZW5ndGgsXG4gICAgICAgICAgcmVzdWx0cyA9IHt9LFxuICAgICAgICAgIGN1cnJlbnRLZXk7XG4gICAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICAgIGN1cnJlbnRLZXkgPSBrZXlzW2luZGV4XTtcbiAgICAgICAgcmVzdWx0c1tjdXJyZW50S2V5XSA9IGl0ZXJhdGVlKG9ialtjdXJyZW50S2V5XSwgY3VycmVudEtleSwgb2JqKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHRzO1xuICB9O1xuXG4gIC8vIENvbnZlcnQgYW4gb2JqZWN0IGludG8gYSBsaXN0IG9mIGBba2V5LCB2YWx1ZV1gIHBhaXJzLlxuICBfLnBhaXJzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIGtleXMgPSBfLmtleXMob2JqKTtcbiAgICB2YXIgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XG4gICAgdmFyIHBhaXJzID0gQXJyYXkobGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBwYWlyc1tpXSA9IFtrZXlzW2ldLCBvYmpba2V5c1tpXV1dO1xuICAgIH1cbiAgICByZXR1cm4gcGFpcnM7XG4gIH07XG5cbiAgLy8gSW52ZXJ0IHRoZSBrZXlzIGFuZCB2YWx1ZXMgb2YgYW4gb2JqZWN0LiBUaGUgdmFsdWVzIG11c3QgYmUgc2VyaWFsaXphYmxlLlxuICBfLmludmVydCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBrZXlzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICByZXN1bHRbb2JqW2tleXNbaV1dXSA9IGtleXNbaV07XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gUmV0dXJuIGEgc29ydGVkIGxpc3Qgb2YgdGhlIGZ1bmN0aW9uIG5hbWVzIGF2YWlsYWJsZSBvbiB0aGUgb2JqZWN0LlxuICAvLyBBbGlhc2VkIGFzIGBtZXRob2RzYFxuICBfLmZ1bmN0aW9ucyA9IF8ubWV0aG9kcyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBuYW1lcyA9IFtdO1xuICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgIGlmIChfLmlzRnVuY3Rpb24ob2JqW2tleV0pKSBuYW1lcy5wdXNoKGtleSk7XG4gICAgfVxuICAgIHJldHVybiBuYW1lcy5zb3J0KCk7XG4gIH07XG5cbiAgLy8gRXh0ZW5kIGEgZ2l2ZW4gb2JqZWN0IHdpdGggYWxsIHRoZSBwcm9wZXJ0aWVzIGluIHBhc3NlZC1pbiBvYmplY3QocykuXG4gIF8uZXh0ZW5kID0gY3JlYXRlQXNzaWduZXIoXy5hbGxLZXlzKTtcblxuICAvLyBBc3NpZ25zIGEgZ2l2ZW4gb2JqZWN0IHdpdGggYWxsIHRoZSBvd24gcHJvcGVydGllcyBpbiB0aGUgcGFzc2VkLWluIG9iamVjdChzKVxuICAvLyAoaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvT2JqZWN0L2Fzc2lnbilcbiAgXy5leHRlbmRPd24gPSBfLmFzc2lnbiA9IGNyZWF0ZUFzc2lnbmVyKF8ua2V5cyk7XG5cbiAgLy8gUmV0dXJucyB0aGUgZmlyc3Qga2V5IG9uIGFuIG9iamVjdCB0aGF0IHBhc3NlcyBhIHByZWRpY2F0ZSB0ZXN0XG4gIF8uZmluZEtleSA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgcHJlZGljYXRlID0gY2IocHJlZGljYXRlLCBjb250ZXh0KTtcbiAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopLCBrZXk7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIGtleSA9IGtleXNbaV07XG4gICAgICBpZiAocHJlZGljYXRlKG9ialtrZXldLCBrZXksIG9iaikpIHJldHVybiBrZXk7XG4gICAgfVxuICB9O1xuXG4gIC8vIFJldHVybiBhIGNvcHkgb2YgdGhlIG9iamVjdCBvbmx5IGNvbnRhaW5pbmcgdGhlIHdoaXRlbGlzdGVkIHByb3BlcnRpZXMuXG4gIF8ucGljayA9IGZ1bmN0aW9uKG9iamVjdCwgb2l0ZXJhdGVlLCBjb250ZXh0KSB7XG4gICAgdmFyIHJlc3VsdCA9IHt9LCBvYmogPSBvYmplY3QsIGl0ZXJhdGVlLCBrZXlzO1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIHJlc3VsdDtcbiAgICBpZiAoXy5pc0Z1bmN0aW9uKG9pdGVyYXRlZSkpIHtcbiAgICAgIGtleXMgPSBfLmFsbEtleXMob2JqKTtcbiAgICAgIGl0ZXJhdGVlID0gb3B0aW1pemVDYihvaXRlcmF0ZWUsIGNvbnRleHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBrZXlzID0gZmxhdHRlbihhcmd1bWVudHMsIGZhbHNlLCBmYWxzZSwgMSk7XG4gICAgICBpdGVyYXRlZSA9IGZ1bmN0aW9uKHZhbHVlLCBrZXksIG9iaikgeyByZXR1cm4ga2V5IGluIG9iajsgfTtcbiAgICAgIG9iaiA9IE9iamVjdChvYmopO1xuICAgIH1cbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0ga2V5cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGtleSA9IGtleXNbaV07XG4gICAgICB2YXIgdmFsdWUgPSBvYmpba2V5XTtcbiAgICAgIGlmIChpdGVyYXRlZSh2YWx1ZSwga2V5LCBvYmopKSByZXN1bHRba2V5XSA9IHZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gICAvLyBSZXR1cm4gYSBjb3B5IG9mIHRoZSBvYmplY3Qgd2l0aG91dCB0aGUgYmxhY2tsaXN0ZWQgcHJvcGVydGllcy5cbiAgXy5vbWl0ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgY29udGV4dCkge1xuICAgIGlmIChfLmlzRnVuY3Rpb24oaXRlcmF0ZWUpKSB7XG4gICAgICBpdGVyYXRlZSA9IF8ubmVnYXRlKGl0ZXJhdGVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGtleXMgPSBfLm1hcChmbGF0dGVuKGFyZ3VtZW50cywgZmFsc2UsIGZhbHNlLCAxKSwgU3RyaW5nKTtcbiAgICAgIGl0ZXJhdGVlID0gZnVuY3Rpb24odmFsdWUsIGtleSkge1xuICAgICAgICByZXR1cm4gIV8uY29udGFpbnMoa2V5cywga2V5KTtcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiBfLnBpY2sob2JqLCBpdGVyYXRlZSwgY29udGV4dCk7XG4gIH07XG5cbiAgLy8gRmlsbCBpbiBhIGdpdmVuIG9iamVjdCB3aXRoIGRlZmF1bHQgcHJvcGVydGllcy5cbiAgXy5kZWZhdWx0cyA9IGNyZWF0ZUFzc2lnbmVyKF8uYWxsS2V5cywgdHJ1ZSk7XG5cbiAgLy8gQ3JlYXRlcyBhbiBvYmplY3QgdGhhdCBpbmhlcml0cyBmcm9tIHRoZSBnaXZlbiBwcm90b3R5cGUgb2JqZWN0LlxuICAvLyBJZiBhZGRpdGlvbmFsIHByb3BlcnRpZXMgYXJlIHByb3ZpZGVkIHRoZW4gdGhleSB3aWxsIGJlIGFkZGVkIHRvIHRoZVxuICAvLyBjcmVhdGVkIG9iamVjdC5cbiAgXy5jcmVhdGUgPSBmdW5jdGlvbihwcm90b3R5cGUsIHByb3BzKSB7XG4gICAgdmFyIHJlc3VsdCA9IGJhc2VDcmVhdGUocHJvdG90eXBlKTtcbiAgICBpZiAocHJvcHMpIF8uZXh0ZW5kT3duKHJlc3VsdCwgcHJvcHMpO1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gQ3JlYXRlIGEgKHNoYWxsb3ctY2xvbmVkKSBkdXBsaWNhdGUgb2YgYW4gb2JqZWN0LlxuICBfLmNsb25lID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYgKCFfLmlzT2JqZWN0KG9iaikpIHJldHVybiBvYmo7XG4gICAgcmV0dXJuIF8uaXNBcnJheShvYmopID8gb2JqLnNsaWNlKCkgOiBfLmV4dGVuZCh7fSwgb2JqKTtcbiAgfTtcblxuICAvLyBJbnZva2VzIGludGVyY2VwdG9yIHdpdGggdGhlIG9iaiwgYW5kIHRoZW4gcmV0dXJucyBvYmouXG4gIC8vIFRoZSBwcmltYXJ5IHB1cnBvc2Ugb2YgdGhpcyBtZXRob2QgaXMgdG8gXCJ0YXAgaW50b1wiIGEgbWV0aG9kIGNoYWluLCBpblxuICAvLyBvcmRlciB0byBwZXJmb3JtIG9wZXJhdGlvbnMgb24gaW50ZXJtZWRpYXRlIHJlc3VsdHMgd2l0aGluIHRoZSBjaGFpbi5cbiAgXy50YXAgPSBmdW5jdGlvbihvYmosIGludGVyY2VwdG9yKSB7XG4gICAgaW50ZXJjZXB0b3Iob2JqKTtcbiAgICByZXR1cm4gb2JqO1xuICB9O1xuXG4gIC8vIFJldHVybnMgd2hldGhlciBhbiBvYmplY3QgaGFzIGEgZ2l2ZW4gc2V0IG9mIGBrZXk6dmFsdWVgIHBhaXJzLlxuICBfLmlzTWF0Y2ggPSBmdW5jdGlvbihvYmplY3QsIGF0dHJzKSB7XG4gICAgdmFyIGtleXMgPSBfLmtleXMoYXR0cnMpLCBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgICBpZiAob2JqZWN0ID09IG51bGwpIHJldHVybiAhbGVuZ3RoO1xuICAgIHZhciBvYmogPSBPYmplY3Qob2JqZWN0KTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIga2V5ID0ga2V5c1tpXTtcbiAgICAgIGlmIChhdHRyc1trZXldICE9PSBvYmpba2V5XSB8fCAhKGtleSBpbiBvYmopKSByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9O1xuXG5cbiAgLy8gSW50ZXJuYWwgcmVjdXJzaXZlIGNvbXBhcmlzb24gZnVuY3Rpb24gZm9yIGBpc0VxdWFsYC5cbiAgdmFyIGVxID0gZnVuY3Rpb24oYSwgYiwgYVN0YWNrLCBiU3RhY2spIHtcbiAgICAvLyBJZGVudGljYWwgb2JqZWN0cyBhcmUgZXF1YWwuIGAwID09PSAtMGAsIGJ1dCB0aGV5IGFyZW4ndCBpZGVudGljYWwuXG4gICAgLy8gU2VlIHRoZSBbSGFybW9ueSBgZWdhbGAgcHJvcG9zYWxdKGh0dHA6Ly93aWtpLmVjbWFzY3JpcHQub3JnL2Rva3UucGhwP2lkPWhhcm1vbnk6ZWdhbCkuXG4gICAgaWYgKGEgPT09IGIpIHJldHVybiBhICE9PSAwIHx8IDEgLyBhID09PSAxIC8gYjtcbiAgICAvLyBBIHN0cmljdCBjb21wYXJpc29uIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIGBudWxsID09IHVuZGVmaW5lZGAuXG4gICAgaWYgKGEgPT0gbnVsbCB8fCBiID09IG51bGwpIHJldHVybiBhID09PSBiO1xuICAgIC8vIFVud3JhcCBhbnkgd3JhcHBlZCBvYmplY3RzLlxuICAgIGlmIChhIGluc3RhbmNlb2YgXykgYSA9IGEuX3dyYXBwZWQ7XG4gICAgaWYgKGIgaW5zdGFuY2VvZiBfKSBiID0gYi5fd3JhcHBlZDtcbiAgICAvLyBDb21wYXJlIGBbW0NsYXNzXV1gIG5hbWVzLlxuICAgIHZhciBjbGFzc05hbWUgPSB0b1N0cmluZy5jYWxsKGEpO1xuICAgIGlmIChjbGFzc05hbWUgIT09IHRvU3RyaW5nLmNhbGwoYikpIHJldHVybiBmYWxzZTtcbiAgICBzd2l0Y2ggKGNsYXNzTmFtZSkge1xuICAgICAgLy8gU3RyaW5ncywgbnVtYmVycywgcmVndWxhciBleHByZXNzaW9ucywgZGF0ZXMsIGFuZCBib29sZWFucyBhcmUgY29tcGFyZWQgYnkgdmFsdWUuXG4gICAgICBjYXNlICdbb2JqZWN0IFJlZ0V4cF0nOlxuICAgICAgLy8gUmVnRXhwcyBhcmUgY29lcmNlZCB0byBzdHJpbmdzIGZvciBjb21wYXJpc29uIChOb3RlOiAnJyArIC9hL2kgPT09ICcvYS9pJylcbiAgICAgIGNhc2UgJ1tvYmplY3QgU3RyaW5nXSc6XG4gICAgICAgIC8vIFByaW1pdGl2ZXMgYW5kIHRoZWlyIGNvcnJlc3BvbmRpbmcgb2JqZWN0IHdyYXBwZXJzIGFyZSBlcXVpdmFsZW50OyB0aHVzLCBgXCI1XCJgIGlzXG4gICAgICAgIC8vIGVxdWl2YWxlbnQgdG8gYG5ldyBTdHJpbmcoXCI1XCIpYC5cbiAgICAgICAgcmV0dXJuICcnICsgYSA9PT0gJycgKyBiO1xuICAgICAgY2FzZSAnW29iamVjdCBOdW1iZXJdJzpcbiAgICAgICAgLy8gYE5hTmBzIGFyZSBlcXVpdmFsZW50LCBidXQgbm9uLXJlZmxleGl2ZS5cbiAgICAgICAgLy8gT2JqZWN0KE5hTikgaXMgZXF1aXZhbGVudCB0byBOYU5cbiAgICAgICAgaWYgKCthICE9PSArYSkgcmV0dXJuICtiICE9PSArYjtcbiAgICAgICAgLy8gQW4gYGVnYWxgIGNvbXBhcmlzb24gaXMgcGVyZm9ybWVkIGZvciBvdGhlciBudW1lcmljIHZhbHVlcy5cbiAgICAgICAgcmV0dXJuICthID09PSAwID8gMSAvICthID09PSAxIC8gYiA6ICthID09PSArYjtcbiAgICAgIGNhc2UgJ1tvYmplY3QgRGF0ZV0nOlxuICAgICAgY2FzZSAnW29iamVjdCBCb29sZWFuXSc6XG4gICAgICAgIC8vIENvZXJjZSBkYXRlcyBhbmQgYm9vbGVhbnMgdG8gbnVtZXJpYyBwcmltaXRpdmUgdmFsdWVzLiBEYXRlcyBhcmUgY29tcGFyZWQgYnkgdGhlaXJcbiAgICAgICAgLy8gbWlsbGlzZWNvbmQgcmVwcmVzZW50YXRpb25zLiBOb3RlIHRoYXQgaW52YWxpZCBkYXRlcyB3aXRoIG1pbGxpc2Vjb25kIHJlcHJlc2VudGF0aW9uc1xuICAgICAgICAvLyBvZiBgTmFOYCBhcmUgbm90IGVxdWl2YWxlbnQuXG4gICAgICAgIHJldHVybiArYSA9PT0gK2I7XG4gICAgfVxuXG4gICAgdmFyIGFyZUFycmF5cyA9IGNsYXNzTmFtZSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbiAgICBpZiAoIWFyZUFycmF5cykge1xuICAgICAgaWYgKHR5cGVvZiBhICE9ICdvYmplY3QnIHx8IHR5cGVvZiBiICE9ICdvYmplY3QnKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIC8vIE9iamVjdHMgd2l0aCBkaWZmZXJlbnQgY29uc3RydWN0b3JzIGFyZSBub3QgZXF1aXZhbGVudCwgYnV0IGBPYmplY3RgcyBvciBgQXJyYXlgc1xuICAgICAgLy8gZnJvbSBkaWZmZXJlbnQgZnJhbWVzIGFyZS5cbiAgICAgIHZhciBhQ3RvciA9IGEuY29uc3RydWN0b3IsIGJDdG9yID0gYi5jb25zdHJ1Y3RvcjtcbiAgICAgIGlmIChhQ3RvciAhPT0gYkN0b3IgJiYgIShfLmlzRnVuY3Rpb24oYUN0b3IpICYmIGFDdG9yIGluc3RhbmNlb2YgYUN0b3IgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfLmlzRnVuY3Rpb24oYkN0b3IpICYmIGJDdG9yIGluc3RhbmNlb2YgYkN0b3IpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICYmICgnY29uc3RydWN0b3InIGluIGEgJiYgJ2NvbnN0cnVjdG9yJyBpbiBiKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEFzc3VtZSBlcXVhbGl0eSBmb3IgY3ljbGljIHN0cnVjdHVyZXMuIFRoZSBhbGdvcml0aG0gZm9yIGRldGVjdGluZyBjeWNsaWNcbiAgICAvLyBzdHJ1Y3R1cmVzIGlzIGFkYXB0ZWQgZnJvbSBFUyA1LjEgc2VjdGlvbiAxNS4xMi4zLCBhYnN0cmFjdCBvcGVyYXRpb24gYEpPYC5cblxuICAgIC8vIEluaXRpYWxpemluZyBzdGFjayBvZiB0cmF2ZXJzZWQgb2JqZWN0cy5cbiAgICAvLyBJdCdzIGRvbmUgaGVyZSBzaW5jZSB3ZSBvbmx5IG5lZWQgdGhlbSBmb3Igb2JqZWN0cyBhbmQgYXJyYXlzIGNvbXBhcmlzb24uXG4gICAgYVN0YWNrID0gYVN0YWNrIHx8IFtdO1xuICAgIGJTdGFjayA9IGJTdGFjayB8fCBbXTtcbiAgICB2YXIgbGVuZ3RoID0gYVN0YWNrLmxlbmd0aDtcbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIC8vIExpbmVhciBzZWFyY2guIFBlcmZvcm1hbmNlIGlzIGludmVyc2VseSBwcm9wb3J0aW9uYWwgdG8gdGhlIG51bWJlciBvZlxuICAgICAgLy8gdW5pcXVlIG5lc3RlZCBzdHJ1Y3R1cmVzLlxuICAgICAgaWYgKGFTdGFja1tsZW5ndGhdID09PSBhKSByZXR1cm4gYlN0YWNrW2xlbmd0aF0gPT09IGI7XG4gICAgfVxuXG4gICAgLy8gQWRkIHRoZSBmaXJzdCBvYmplY3QgdG8gdGhlIHN0YWNrIG9mIHRyYXZlcnNlZCBvYmplY3RzLlxuICAgIGFTdGFjay5wdXNoKGEpO1xuICAgIGJTdGFjay5wdXNoKGIpO1xuXG4gICAgLy8gUmVjdXJzaXZlbHkgY29tcGFyZSBvYmplY3RzIGFuZCBhcnJheXMuXG4gICAgaWYgKGFyZUFycmF5cykge1xuICAgICAgLy8gQ29tcGFyZSBhcnJheSBsZW5ndGhzIHRvIGRldGVybWluZSBpZiBhIGRlZXAgY29tcGFyaXNvbiBpcyBuZWNlc3NhcnkuXG4gICAgICBsZW5ndGggPSBhLmxlbmd0aDtcbiAgICAgIGlmIChsZW5ndGggIT09IGIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gICAgICAvLyBEZWVwIGNvbXBhcmUgdGhlIGNvbnRlbnRzLCBpZ25vcmluZyBub24tbnVtZXJpYyBwcm9wZXJ0aWVzLlxuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIGlmICghZXEoYVtsZW5ndGhdLCBiW2xlbmd0aF0sIGFTdGFjaywgYlN0YWNrKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBEZWVwIGNvbXBhcmUgb2JqZWN0cy5cbiAgICAgIHZhciBrZXlzID0gXy5rZXlzKGEpLCBrZXk7XG4gICAgICBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgICAgIC8vIEVuc3VyZSB0aGF0IGJvdGggb2JqZWN0cyBjb250YWluIHRoZSBzYW1lIG51bWJlciBvZiBwcm9wZXJ0aWVzIGJlZm9yZSBjb21wYXJpbmcgZGVlcCBlcXVhbGl0eS5cbiAgICAgIGlmIChfLmtleXMoYikubGVuZ3RoICE9PSBsZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgICAvLyBEZWVwIGNvbXBhcmUgZWFjaCBtZW1iZXJcbiAgICAgICAga2V5ID0ga2V5c1tsZW5ndGhdO1xuICAgICAgICBpZiAoIShfLmhhcyhiLCBrZXkpICYmIGVxKGFba2V5XSwgYltrZXldLCBhU3RhY2ssIGJTdGFjaykpKSByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFJlbW92ZSB0aGUgZmlyc3Qgb2JqZWN0IGZyb20gdGhlIHN0YWNrIG9mIHRyYXZlcnNlZCBvYmplY3RzLlxuICAgIGFTdGFjay5wb3AoKTtcbiAgICBiU3RhY2sucG9wKCk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG5cbiAgLy8gUGVyZm9ybSBhIGRlZXAgY29tcGFyaXNvbiB0byBjaGVjayBpZiB0d28gb2JqZWN0cyBhcmUgZXF1YWwuXG4gIF8uaXNFcXVhbCA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgICByZXR1cm4gZXEoYSwgYik7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiBhcnJheSwgc3RyaW5nLCBvciBvYmplY3QgZW1wdHk/XG4gIC8vIEFuIFwiZW1wdHlcIiBvYmplY3QgaGFzIG5vIGVudW1lcmFibGUgb3duLXByb3BlcnRpZXMuXG4gIF8uaXNFbXB0eSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIHRydWU7XG4gICAgaWYgKGlzQXJyYXlMaWtlKG9iaikgJiYgKF8uaXNBcnJheShvYmopIHx8IF8uaXNTdHJpbmcob2JqKSB8fCBfLmlzQXJndW1lbnRzKG9iaikpKSByZXR1cm4gb2JqLmxlbmd0aCA9PT0gMDtcbiAgICByZXR1cm4gXy5rZXlzKG9iaikubGVuZ3RoID09PSAwO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFsdWUgYSBET00gZWxlbWVudD9cbiAgXy5pc0VsZW1lbnQgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gISEob2JqICYmIG9iai5ub2RlVHlwZSA9PT0gMSk7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YWx1ZSBhbiBhcnJheT9cbiAgLy8gRGVsZWdhdGVzIHRvIEVDTUE1J3MgbmF0aXZlIEFycmF5LmlzQXJyYXlcbiAgXy5pc0FycmF5ID0gbmF0aXZlSXNBcnJheSB8fCBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCBBcnJheV0nO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFyaWFibGUgYW4gb2JqZWN0P1xuICBfLmlzT2JqZWN0ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIHR5cGUgPSB0eXBlb2Ygb2JqO1xuICAgIHJldHVybiB0eXBlID09PSAnZnVuY3Rpb24nIHx8IHR5cGUgPT09ICdvYmplY3QnICYmICEhb2JqO1xuICB9O1xuXG4gIC8vIEFkZCBzb21lIGlzVHlwZSBtZXRob2RzOiBpc0FyZ3VtZW50cywgaXNGdW5jdGlvbiwgaXNTdHJpbmcsIGlzTnVtYmVyLCBpc0RhdGUsIGlzUmVnRXhwLCBpc0Vycm9yLlxuICBfLmVhY2goWydBcmd1bWVudHMnLCAnRnVuY3Rpb24nLCAnU3RyaW5nJywgJ051bWJlcicsICdEYXRlJywgJ1JlZ0V4cCcsICdFcnJvciddLCBmdW5jdGlvbihuYW1lKSB7XG4gICAgX1snaXMnICsgbmFtZV0gPSBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0ICcgKyBuYW1lICsgJ10nO1xuICAgIH07XG4gIH0pO1xuXG4gIC8vIERlZmluZSBhIGZhbGxiYWNrIHZlcnNpb24gb2YgdGhlIG1ldGhvZCBpbiBicm93c2VycyAoYWhlbSwgSUUgPCA5KSwgd2hlcmVcbiAgLy8gdGhlcmUgaXNuJ3QgYW55IGluc3BlY3RhYmxlIFwiQXJndW1lbnRzXCIgdHlwZS5cbiAgaWYgKCFfLmlzQXJndW1lbnRzKGFyZ3VtZW50cykpIHtcbiAgICBfLmlzQXJndW1lbnRzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gXy5oYXMob2JqLCAnY2FsbGVlJyk7XG4gICAgfTtcbiAgfVxuXG4gIC8vIE9wdGltaXplIGBpc0Z1bmN0aW9uYCBpZiBhcHByb3ByaWF0ZS4gV29yayBhcm91bmQgc29tZSB0eXBlb2YgYnVncyBpbiBvbGQgdjgsXG4gIC8vIElFIDExICgjMTYyMSksIGFuZCBpbiBTYWZhcmkgOCAoIzE5MjkpLlxuICBpZiAodHlwZW9mIC8uLyAhPSAnZnVuY3Rpb24nICYmIHR5cGVvZiBJbnQ4QXJyYXkgIT0gJ29iamVjdCcpIHtcbiAgICBfLmlzRnVuY3Rpb24gPSBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiB0eXBlb2Ygb2JqID09ICdmdW5jdGlvbicgfHwgZmFsc2U7XG4gICAgfTtcbiAgfVxuXG4gIC8vIElzIGEgZ2l2ZW4gb2JqZWN0IGEgZmluaXRlIG51bWJlcj9cbiAgXy5pc0Zpbml0ZSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBpc0Zpbml0ZShvYmopICYmICFpc05hTihwYXJzZUZsb2F0KG9iaikpO1xuICB9O1xuXG4gIC8vIElzIHRoZSBnaXZlbiB2YWx1ZSBgTmFOYD8gKE5hTiBpcyB0aGUgb25seSBudW1iZXIgd2hpY2ggZG9lcyBub3QgZXF1YWwgaXRzZWxmKS5cbiAgXy5pc05hTiA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBfLmlzTnVtYmVyKG9iaikgJiYgb2JqICE9PSArb2JqO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFsdWUgYSBib29sZWFuP1xuICBfLmlzQm9vbGVhbiA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBvYmogPT09IHRydWUgfHwgb2JqID09PSBmYWxzZSB8fCB0b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IEJvb2xlYW5dJztcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhbHVlIGVxdWFsIHRvIG51bGw/XG4gIF8uaXNOdWxsID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIG9iaiA9PT0gbnVsbDtcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhcmlhYmxlIHVuZGVmaW5lZD9cbiAgXy5pc1VuZGVmaW5lZCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBvYmogPT09IHZvaWQgMDtcbiAgfTtcblxuICAvLyBTaG9ydGN1dCBmdW5jdGlvbiBmb3IgY2hlY2tpbmcgaWYgYW4gb2JqZWN0IGhhcyBhIGdpdmVuIHByb3BlcnR5IGRpcmVjdGx5XG4gIC8vIG9uIGl0c2VsZiAoaW4gb3RoZXIgd29yZHMsIG5vdCBvbiBhIHByb3RvdHlwZSkuXG4gIF8uaGFzID0gZnVuY3Rpb24ob2JqLCBrZXkpIHtcbiAgICByZXR1cm4gb2JqICE9IG51bGwgJiYgaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGtleSk7XG4gIH07XG5cbiAgLy8gVXRpbGl0eSBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBSdW4gVW5kZXJzY29yZS5qcyBpbiAqbm9Db25mbGljdCogbW9kZSwgcmV0dXJuaW5nIHRoZSBgX2AgdmFyaWFibGUgdG8gaXRzXG4gIC8vIHByZXZpb3VzIG93bmVyLiBSZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoZSBVbmRlcnNjb3JlIG9iamVjdC5cbiAgXy5ub0NvbmZsaWN0ID0gZnVuY3Rpb24oKSB7XG4gICAgcm9vdC5fID0gcHJldmlvdXNVbmRlcnNjb3JlO1xuICAgIHJldHVybiB0aGlzO1xuICB9O1xuXG4gIC8vIEtlZXAgdGhlIGlkZW50aXR5IGZ1bmN0aW9uIGFyb3VuZCBmb3IgZGVmYXVsdCBpdGVyYXRlZXMuXG4gIF8uaWRlbnRpdHkgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfTtcblxuICAvLyBQcmVkaWNhdGUtZ2VuZXJhdGluZyBmdW5jdGlvbnMuIE9mdGVuIHVzZWZ1bCBvdXRzaWRlIG9mIFVuZGVyc2NvcmUuXG4gIF8uY29uc3RhbnQgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9O1xuICB9O1xuXG4gIF8ubm9vcCA9IGZ1bmN0aW9uKCl7fTtcblxuICBfLnByb3BlcnR5ID0gcHJvcGVydHk7XG5cbiAgLy8gR2VuZXJhdGVzIGEgZnVuY3Rpb24gZm9yIGEgZ2l2ZW4gb2JqZWN0IHRoYXQgcmV0dXJucyBhIGdpdmVuIHByb3BlcnR5LlxuICBfLnByb3BlcnR5T2YgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gb2JqID09IG51bGwgPyBmdW5jdGlvbigpe30gOiBmdW5jdGlvbihrZXkpIHtcbiAgICAgIHJldHVybiBvYmpba2V5XTtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBwcmVkaWNhdGUgZm9yIGNoZWNraW5nIHdoZXRoZXIgYW4gb2JqZWN0IGhhcyBhIGdpdmVuIHNldCBvZlxuICAvLyBga2V5OnZhbHVlYCBwYWlycy5cbiAgXy5tYXRjaGVyID0gXy5tYXRjaGVzID0gZnVuY3Rpb24oYXR0cnMpIHtcbiAgICBhdHRycyA9IF8uZXh0ZW5kT3duKHt9LCBhdHRycyk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKG9iaikge1xuICAgICAgcmV0dXJuIF8uaXNNYXRjaChvYmosIGF0dHJzKTtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJ1biBhIGZ1bmN0aW9uICoqbioqIHRpbWVzLlxuICBfLnRpbWVzID0gZnVuY3Rpb24obiwgaXRlcmF0ZWUsIGNvbnRleHQpIHtcbiAgICB2YXIgYWNjdW0gPSBBcnJheShNYXRoLm1heCgwLCBuKSk7XG4gICAgaXRlcmF0ZWUgPSBvcHRpbWl6ZUNiKGl0ZXJhdGVlLCBjb250ZXh0LCAxKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykgYWNjdW1baV0gPSBpdGVyYXRlZShpKTtcbiAgICByZXR1cm4gYWNjdW07XG4gIH07XG5cbiAgLy8gUmV0dXJuIGEgcmFuZG9tIGludGVnZXIgYmV0d2VlbiBtaW4gYW5kIG1heCAoaW5jbHVzaXZlKS5cbiAgXy5yYW5kb20gPSBmdW5jdGlvbihtaW4sIG1heCkge1xuICAgIGlmIChtYXggPT0gbnVsbCkge1xuICAgICAgbWF4ID0gbWluO1xuICAgICAgbWluID0gMDtcbiAgICB9XG4gICAgcmV0dXJuIG1pbiArIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIChtYXggLSBtaW4gKyAxKSk7XG4gIH07XG5cbiAgLy8gQSAocG9zc2libHkgZmFzdGVyKSB3YXkgdG8gZ2V0IHRoZSBjdXJyZW50IHRpbWVzdGFtcCBhcyBhbiBpbnRlZ2VyLlxuICBfLm5vdyA9IERhdGUubm93IHx8IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgfTtcblxuICAgLy8gTGlzdCBvZiBIVE1MIGVudGl0aWVzIGZvciBlc2NhcGluZy5cbiAgdmFyIGVzY2FwZU1hcCA9IHtcbiAgICAnJic6ICcmYW1wOycsXG4gICAgJzwnOiAnJmx0OycsXG4gICAgJz4nOiAnJmd0OycsXG4gICAgJ1wiJzogJyZxdW90OycsXG4gICAgXCInXCI6ICcmI3gyNzsnLFxuICAgICdgJzogJyYjeDYwOydcbiAgfTtcbiAgdmFyIHVuZXNjYXBlTWFwID0gXy5pbnZlcnQoZXNjYXBlTWFwKTtcblxuICAvLyBGdW5jdGlvbnMgZm9yIGVzY2FwaW5nIGFuZCB1bmVzY2FwaW5nIHN0cmluZ3MgdG8vZnJvbSBIVE1MIGludGVycG9sYXRpb24uXG4gIHZhciBjcmVhdGVFc2NhcGVyID0gZnVuY3Rpb24obWFwKSB7XG4gICAgdmFyIGVzY2FwZXIgPSBmdW5jdGlvbihtYXRjaCkge1xuICAgICAgcmV0dXJuIG1hcFttYXRjaF07XG4gICAgfTtcbiAgICAvLyBSZWdleGVzIGZvciBpZGVudGlmeWluZyBhIGtleSB0aGF0IG5lZWRzIHRvIGJlIGVzY2FwZWRcbiAgICB2YXIgc291cmNlID0gJyg/OicgKyBfLmtleXMobWFwKS5qb2luKCd8JykgKyAnKSc7XG4gICAgdmFyIHRlc3RSZWdleHAgPSBSZWdFeHAoc291cmNlKTtcbiAgICB2YXIgcmVwbGFjZVJlZ2V4cCA9IFJlZ0V4cChzb3VyY2UsICdnJyk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgc3RyaW5nID0gc3RyaW5nID09IG51bGwgPyAnJyA6ICcnICsgc3RyaW5nO1xuICAgICAgcmV0dXJuIHRlc3RSZWdleHAudGVzdChzdHJpbmcpID8gc3RyaW5nLnJlcGxhY2UocmVwbGFjZVJlZ2V4cCwgZXNjYXBlcikgOiBzdHJpbmc7XG4gICAgfTtcbiAgfTtcbiAgXy5lc2NhcGUgPSBjcmVhdGVFc2NhcGVyKGVzY2FwZU1hcCk7XG4gIF8udW5lc2NhcGUgPSBjcmVhdGVFc2NhcGVyKHVuZXNjYXBlTWFwKTtcblxuICAvLyBJZiB0aGUgdmFsdWUgb2YgdGhlIG5hbWVkIGBwcm9wZXJ0eWAgaXMgYSBmdW5jdGlvbiB0aGVuIGludm9rZSBpdCB3aXRoIHRoZVxuICAvLyBgb2JqZWN0YCBhcyBjb250ZXh0OyBvdGhlcndpc2UsIHJldHVybiBpdC5cbiAgXy5yZXN1bHQgPSBmdW5jdGlvbihvYmplY3QsIHByb3BlcnR5LCBmYWxsYmFjaykge1xuICAgIHZhciB2YWx1ZSA9IG9iamVjdCA9PSBudWxsID8gdm9pZCAwIDogb2JqZWN0W3Byb3BlcnR5XTtcbiAgICBpZiAodmFsdWUgPT09IHZvaWQgMCkge1xuICAgICAgdmFsdWUgPSBmYWxsYmFjaztcbiAgICB9XG4gICAgcmV0dXJuIF8uaXNGdW5jdGlvbih2YWx1ZSkgPyB2YWx1ZS5jYWxsKG9iamVjdCkgOiB2YWx1ZTtcbiAgfTtcblxuICAvLyBHZW5lcmF0ZSBhIHVuaXF1ZSBpbnRlZ2VyIGlkICh1bmlxdWUgd2l0aGluIHRoZSBlbnRpcmUgY2xpZW50IHNlc3Npb24pLlxuICAvLyBVc2VmdWwgZm9yIHRlbXBvcmFyeSBET00gaWRzLlxuICB2YXIgaWRDb3VudGVyID0gMDtcbiAgXy51bmlxdWVJZCA9IGZ1bmN0aW9uKHByZWZpeCkge1xuICAgIHZhciBpZCA9ICsraWRDb3VudGVyICsgJyc7XG4gICAgcmV0dXJuIHByZWZpeCA/IHByZWZpeCArIGlkIDogaWQ7XG4gIH07XG5cbiAgLy8gQnkgZGVmYXVsdCwgVW5kZXJzY29yZSB1c2VzIEVSQi1zdHlsZSB0ZW1wbGF0ZSBkZWxpbWl0ZXJzLCBjaGFuZ2UgdGhlXG4gIC8vIGZvbGxvd2luZyB0ZW1wbGF0ZSBzZXR0aW5ncyB0byB1c2UgYWx0ZXJuYXRpdmUgZGVsaW1pdGVycy5cbiAgXy50ZW1wbGF0ZVNldHRpbmdzID0ge1xuICAgIGV2YWx1YXRlICAgIDogLzwlKFtcXHNcXFNdKz8pJT4vZyxcbiAgICBpbnRlcnBvbGF0ZSA6IC88JT0oW1xcc1xcU10rPyklPi9nLFxuICAgIGVzY2FwZSAgICAgIDogLzwlLShbXFxzXFxTXSs/KSU+L2dcbiAgfTtcblxuICAvLyBXaGVuIGN1c3RvbWl6aW5nIGB0ZW1wbGF0ZVNldHRpbmdzYCwgaWYgeW91IGRvbid0IHdhbnQgdG8gZGVmaW5lIGFuXG4gIC8vIGludGVycG9sYXRpb24sIGV2YWx1YXRpb24gb3IgZXNjYXBpbmcgcmVnZXgsIHdlIG5lZWQgb25lIHRoYXQgaXNcbiAgLy8gZ3VhcmFudGVlZCBub3QgdG8gbWF0Y2guXG4gIHZhciBub01hdGNoID0gLyguKV4vO1xuXG4gIC8vIENlcnRhaW4gY2hhcmFjdGVycyBuZWVkIHRvIGJlIGVzY2FwZWQgc28gdGhhdCB0aGV5IGNhbiBiZSBwdXQgaW50byBhXG4gIC8vIHN0cmluZyBsaXRlcmFsLlxuICB2YXIgZXNjYXBlcyA9IHtcbiAgICBcIidcIjogICAgICBcIidcIixcbiAgICAnXFxcXCc6ICAgICAnXFxcXCcsXG4gICAgJ1xccic6ICAgICAncicsXG4gICAgJ1xcbic6ICAgICAnbicsXG4gICAgJ1xcdTIwMjgnOiAndTIwMjgnLFxuICAgICdcXHUyMDI5JzogJ3UyMDI5J1xuICB9O1xuXG4gIHZhciBlc2NhcGVyID0gL1xcXFx8J3xcXHJ8XFxufFxcdTIwMjh8XFx1MjAyOS9nO1xuXG4gIHZhciBlc2NhcGVDaGFyID0gZnVuY3Rpb24obWF0Y2gpIHtcbiAgICByZXR1cm4gJ1xcXFwnICsgZXNjYXBlc1ttYXRjaF07XG4gIH07XG5cbiAgLy8gSmF2YVNjcmlwdCBtaWNyby10ZW1wbGF0aW5nLCBzaW1pbGFyIHRvIEpvaG4gUmVzaWcncyBpbXBsZW1lbnRhdGlvbi5cbiAgLy8gVW5kZXJzY29yZSB0ZW1wbGF0aW5nIGhhbmRsZXMgYXJiaXRyYXJ5IGRlbGltaXRlcnMsIHByZXNlcnZlcyB3aGl0ZXNwYWNlLFxuICAvLyBhbmQgY29ycmVjdGx5IGVzY2FwZXMgcXVvdGVzIHdpdGhpbiBpbnRlcnBvbGF0ZWQgY29kZS5cbiAgLy8gTkI6IGBvbGRTZXR0aW5nc2Agb25seSBleGlzdHMgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LlxuICBfLnRlbXBsYXRlID0gZnVuY3Rpb24odGV4dCwgc2V0dGluZ3MsIG9sZFNldHRpbmdzKSB7XG4gICAgaWYgKCFzZXR0aW5ncyAmJiBvbGRTZXR0aW5ncykgc2V0dGluZ3MgPSBvbGRTZXR0aW5ncztcbiAgICBzZXR0aW5ncyA9IF8uZGVmYXVsdHMoe30sIHNldHRpbmdzLCBfLnRlbXBsYXRlU2V0dGluZ3MpO1xuXG4gICAgLy8gQ29tYmluZSBkZWxpbWl0ZXJzIGludG8gb25lIHJlZ3VsYXIgZXhwcmVzc2lvbiB2aWEgYWx0ZXJuYXRpb24uXG4gICAgdmFyIG1hdGNoZXIgPSBSZWdFeHAoW1xuICAgICAgKHNldHRpbmdzLmVzY2FwZSB8fCBub01hdGNoKS5zb3VyY2UsXG4gICAgICAoc2V0dGluZ3MuaW50ZXJwb2xhdGUgfHwgbm9NYXRjaCkuc291cmNlLFxuICAgICAgKHNldHRpbmdzLmV2YWx1YXRlIHx8IG5vTWF0Y2gpLnNvdXJjZVxuICAgIF0uam9pbignfCcpICsgJ3wkJywgJ2cnKTtcblxuICAgIC8vIENvbXBpbGUgdGhlIHRlbXBsYXRlIHNvdXJjZSwgZXNjYXBpbmcgc3RyaW5nIGxpdGVyYWxzIGFwcHJvcHJpYXRlbHkuXG4gICAgdmFyIGluZGV4ID0gMDtcbiAgICB2YXIgc291cmNlID0gXCJfX3ArPSdcIjtcbiAgICB0ZXh0LnJlcGxhY2UobWF0Y2hlciwgZnVuY3Rpb24obWF0Y2gsIGVzY2FwZSwgaW50ZXJwb2xhdGUsIGV2YWx1YXRlLCBvZmZzZXQpIHtcbiAgICAgIHNvdXJjZSArPSB0ZXh0LnNsaWNlKGluZGV4LCBvZmZzZXQpLnJlcGxhY2UoZXNjYXBlciwgZXNjYXBlQ2hhcik7XG4gICAgICBpbmRleCA9IG9mZnNldCArIG1hdGNoLmxlbmd0aDtcblxuICAgICAgaWYgKGVzY2FwZSkge1xuICAgICAgICBzb3VyY2UgKz0gXCInK1xcbigoX190PShcIiArIGVzY2FwZSArIFwiKSk9PW51bGw/Jyc6Xy5lc2NhcGUoX190KSkrXFxuJ1wiO1xuICAgICAgfSBlbHNlIGlmIChpbnRlcnBvbGF0ZSkge1xuICAgICAgICBzb3VyY2UgKz0gXCInK1xcbigoX190PShcIiArIGludGVycG9sYXRlICsgXCIpKT09bnVsbD8nJzpfX3QpK1xcbidcIjtcbiAgICAgIH0gZWxzZSBpZiAoZXZhbHVhdGUpIHtcbiAgICAgICAgc291cmNlICs9IFwiJztcXG5cIiArIGV2YWx1YXRlICsgXCJcXG5fX3ArPSdcIjtcbiAgICAgIH1cblxuICAgICAgLy8gQWRvYmUgVk1zIG5lZWQgdGhlIG1hdGNoIHJldHVybmVkIHRvIHByb2R1Y2UgdGhlIGNvcnJlY3Qgb2ZmZXN0LlxuICAgICAgcmV0dXJuIG1hdGNoO1xuICAgIH0pO1xuICAgIHNvdXJjZSArPSBcIic7XFxuXCI7XG5cbiAgICAvLyBJZiBhIHZhcmlhYmxlIGlzIG5vdCBzcGVjaWZpZWQsIHBsYWNlIGRhdGEgdmFsdWVzIGluIGxvY2FsIHNjb3BlLlxuICAgIGlmICghc2V0dGluZ3MudmFyaWFibGUpIHNvdXJjZSA9ICd3aXRoKG9ianx8e30pe1xcbicgKyBzb3VyY2UgKyAnfVxcbic7XG5cbiAgICBzb3VyY2UgPSBcInZhciBfX3QsX19wPScnLF9faj1BcnJheS5wcm90b3R5cGUuam9pbixcIiArXG4gICAgICBcInByaW50PWZ1bmN0aW9uKCl7X19wKz1fX2ouY2FsbChhcmd1bWVudHMsJycpO307XFxuXCIgK1xuICAgICAgc291cmNlICsgJ3JldHVybiBfX3A7XFxuJztcblxuICAgIHRyeSB7XG4gICAgICB2YXIgcmVuZGVyID0gbmV3IEZ1bmN0aW9uKHNldHRpbmdzLnZhcmlhYmxlIHx8ICdvYmonLCAnXycsIHNvdXJjZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZS5zb3VyY2UgPSBzb3VyY2U7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIHZhciB0ZW1wbGF0ZSA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgIHJldHVybiByZW5kZXIuY2FsbCh0aGlzLCBkYXRhLCBfKTtcbiAgICB9O1xuXG4gICAgLy8gUHJvdmlkZSB0aGUgY29tcGlsZWQgc291cmNlIGFzIGEgY29udmVuaWVuY2UgZm9yIHByZWNvbXBpbGF0aW9uLlxuICAgIHZhciBhcmd1bWVudCA9IHNldHRpbmdzLnZhcmlhYmxlIHx8ICdvYmonO1xuICAgIHRlbXBsYXRlLnNvdXJjZSA9ICdmdW5jdGlvbignICsgYXJndW1lbnQgKyAnKXtcXG4nICsgc291cmNlICsgJ30nO1xuXG4gICAgcmV0dXJuIHRlbXBsYXRlO1xuICB9O1xuXG4gIC8vIEFkZCBhIFwiY2hhaW5cIiBmdW5jdGlvbi4gU3RhcnQgY2hhaW5pbmcgYSB3cmFwcGVkIFVuZGVyc2NvcmUgb2JqZWN0LlxuICBfLmNoYWluID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIGluc3RhbmNlID0gXyhvYmopO1xuICAgIGluc3RhbmNlLl9jaGFpbiA9IHRydWU7XG4gICAgcmV0dXJuIGluc3RhbmNlO1xuICB9O1xuXG4gIC8vIE9PUFxuICAvLyAtLS0tLS0tLS0tLS0tLS1cbiAgLy8gSWYgVW5kZXJzY29yZSBpcyBjYWxsZWQgYXMgYSBmdW5jdGlvbiwgaXQgcmV0dXJucyBhIHdyYXBwZWQgb2JqZWN0IHRoYXRcbiAgLy8gY2FuIGJlIHVzZWQgT08tc3R5bGUuIFRoaXMgd3JhcHBlciBob2xkcyBhbHRlcmVkIHZlcnNpb25zIG9mIGFsbCB0aGVcbiAgLy8gdW5kZXJzY29yZSBmdW5jdGlvbnMuIFdyYXBwZWQgb2JqZWN0cyBtYXkgYmUgY2hhaW5lZC5cblxuICAvLyBIZWxwZXIgZnVuY3Rpb24gdG8gY29udGludWUgY2hhaW5pbmcgaW50ZXJtZWRpYXRlIHJlc3VsdHMuXG4gIHZhciByZXN1bHQgPSBmdW5jdGlvbihpbnN0YW5jZSwgb2JqKSB7XG4gICAgcmV0dXJuIGluc3RhbmNlLl9jaGFpbiA/IF8ob2JqKS5jaGFpbigpIDogb2JqO1xuICB9O1xuXG4gIC8vIEFkZCB5b3VyIG93biBjdXN0b20gZnVuY3Rpb25zIHRvIHRoZSBVbmRlcnNjb3JlIG9iamVjdC5cbiAgXy5taXhpbiA9IGZ1bmN0aW9uKG9iaikge1xuICAgIF8uZWFjaChfLmZ1bmN0aW9ucyhvYmopLCBmdW5jdGlvbihuYW1lKSB7XG4gICAgICB2YXIgZnVuYyA9IF9bbmFtZV0gPSBvYmpbbmFtZV07XG4gICAgICBfLnByb3RvdHlwZVtuYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgYXJncyA9IFt0aGlzLl93cmFwcGVkXTtcbiAgICAgICAgcHVzaC5hcHBseShhcmdzLCBhcmd1bWVudHMpO1xuICAgICAgICByZXR1cm4gcmVzdWx0KHRoaXMsIGZ1bmMuYXBwbHkoXywgYXJncykpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgfTtcblxuICAvLyBBZGQgYWxsIG9mIHRoZSBVbmRlcnNjb3JlIGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlciBvYmplY3QuXG4gIF8ubWl4aW4oXyk7XG5cbiAgLy8gQWRkIGFsbCBtdXRhdG9yIEFycmF5IGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlci5cbiAgXy5lYWNoKFsncG9wJywgJ3B1c2gnLCAncmV2ZXJzZScsICdzaGlmdCcsICdzb3J0JywgJ3NwbGljZScsICd1bnNoaWZ0J10sIGZ1bmN0aW9uKG5hbWUpIHtcbiAgICB2YXIgbWV0aG9kID0gQXJyYXlQcm90b1tuYW1lXTtcbiAgICBfLnByb3RvdHlwZVtuYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIG9iaiA9IHRoaXMuX3dyYXBwZWQ7XG4gICAgICBtZXRob2QuYXBwbHkob2JqLCBhcmd1bWVudHMpO1xuICAgICAgaWYgKChuYW1lID09PSAnc2hpZnQnIHx8IG5hbWUgPT09ICdzcGxpY2UnKSAmJiBvYmoubGVuZ3RoID09PSAwKSBkZWxldGUgb2JqWzBdO1xuICAgICAgcmV0dXJuIHJlc3VsdCh0aGlzLCBvYmopO1xuICAgIH07XG4gIH0pO1xuXG4gIC8vIEFkZCBhbGwgYWNjZXNzb3IgQXJyYXkgZnVuY3Rpb25zIHRvIHRoZSB3cmFwcGVyLlxuICBfLmVhY2goWydjb25jYXQnLCAnam9pbicsICdzbGljZSddLCBmdW5jdGlvbihuYW1lKSB7XG4gICAgdmFyIG1ldGhvZCA9IEFycmF5UHJvdG9bbmFtZV07XG4gICAgXy5wcm90b3R5cGVbbmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiByZXN1bHQodGhpcywgbWV0aG9kLmFwcGx5KHRoaXMuX3dyYXBwZWQsIGFyZ3VtZW50cykpO1xuICAgIH07XG4gIH0pO1xuXG4gIC8vIEV4dHJhY3RzIHRoZSByZXN1bHQgZnJvbSBhIHdyYXBwZWQgYW5kIGNoYWluZWQgb2JqZWN0LlxuICBfLnByb3RvdHlwZS52YWx1ZSA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLl93cmFwcGVkO1xuICB9O1xuXG4gIC8vIFByb3ZpZGUgdW53cmFwcGluZyBwcm94eSBmb3Igc29tZSBtZXRob2RzIHVzZWQgaW4gZW5naW5lIG9wZXJhdGlvbnNcbiAgLy8gc3VjaCBhcyBhcml0aG1ldGljIGFuZCBKU09OIHN0cmluZ2lmaWNhdGlvbi5cbiAgXy5wcm90b3R5cGUudmFsdWVPZiA9IF8ucHJvdG90eXBlLnRvSlNPTiA9IF8ucHJvdG90eXBlLnZhbHVlO1xuXG4gIF8ucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuICcnICsgdGhpcy5fd3JhcHBlZDtcbiAgfTtcblxuICAvLyBBTUQgcmVnaXN0cmF0aW9uIGhhcHBlbnMgYXQgdGhlIGVuZCBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIEFNRCBsb2FkZXJzXG4gIC8vIHRoYXQgbWF5IG5vdCBlbmZvcmNlIG5leHQtdHVybiBzZW1hbnRpY3Mgb24gbW9kdWxlcy4gRXZlbiB0aG91Z2ggZ2VuZXJhbFxuICAvLyBwcmFjdGljZSBmb3IgQU1EIHJlZ2lzdHJhdGlvbiBpcyB0byBiZSBhbm9ueW1vdXMsIHVuZGVyc2NvcmUgcmVnaXN0ZXJzXG4gIC8vIGFzIGEgbmFtZWQgbW9kdWxlIGJlY2F1c2UsIGxpa2UgalF1ZXJ5LCBpdCBpcyBhIGJhc2UgbGlicmFyeSB0aGF0IGlzXG4gIC8vIHBvcHVsYXIgZW5vdWdoIHRvIGJlIGJ1bmRsZWQgaW4gYSB0aGlyZCBwYXJ0eSBsaWIsIGJ1dCBub3QgYmUgcGFydCBvZlxuICAvLyBhbiBBTUQgbG9hZCByZXF1ZXN0LiBUaG9zZSBjYXNlcyBjb3VsZCBnZW5lcmF0ZSBhbiBlcnJvciB3aGVuIGFuXG4gIC8vIGFub255bW91cyBkZWZpbmUoKSBpcyBjYWxsZWQgb3V0c2lkZSBvZiBhIGxvYWRlciByZXF1ZXN0LlxuICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgZGVmaW5lKCd1bmRlcnNjb3JlJywgW10sIGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIF87XG4gICAgfSk7XG4gIH1cbn0uY2FsbCh0aGlzKSk7XG4iLCJjaGFpICAgICAgPSByZXF1aXJlKCdjaGFpJylcclxuZXhwZWN0ICAgID0gY2hhaS5leHBlY3Rcclxuc2hvdWxkICAgID0gY2hhaS5zaG91bGQoKVxyXG5zaW5vbiAgICAgPSByZXF1aXJlKCdzaW5vbicpXHJcbnNpbm9uQ2hhaSA9IHJlcXVpcmUoJ3Npbm9uLWNoYWknKVxyXG5fICAgICAgICAgPSByZXF1aXJlKFwidW5kZXJzY29yZVwiKVxyXG5cclxuY2hhaS51c2Uoc2lub25DaGFpKVxyXG5cclxuWSA9IHJlcXVpcmUgXCIuLi8uLi95anMvbGliL3lcIlxyXG5ZLkxpc3QgPSByZXF1aXJlIFwiLi4vbGliL3ktbGlzdFwiXHJcblxyXG5Db25uZWN0b3IgPSByZXF1aXJlIFwiLi4vLi4veS10ZXN0L2xpYi95LXRlc3QuY29mZmVlXCJcclxuXHJcblRlc3RTdWl0ZSA9IHJlcXVpcmUgXCIuLi8uLi95anMvdGVzdC9vYmplY3QtdGVzdFwiXHJcblxyXG5jbGFzcyBMaXN0VGVzdCBleHRlbmRzIFRlc3RTdWl0ZVxyXG5cclxuICBjb25zdHJ1Y3RvcjogKHN1ZmZpeCktPlxyXG4gICAgc3VwZXIgc3VmZml4LCBZXHJcblxyXG4gIHR5cGU6IFwiTGlzdFRlc3RcIlxyXG5cclxuICBtYWtlTmV3VXNlcjogKHVzZXJJZCktPlxyXG4gICAgY29ubiA9IG5ldyBDb25uZWN0b3IgdXNlcklkXHJcbiAgICBuZXcgWSBjb25uXHJcblxyXG4gIGluaXRVc2VyczogKHUpLT5cclxuICAgIHUudmFsKFwiTGlzdFRlc3RcIixuZXcgWS5MaXN0KCkpXHJcblxyXG4gIGdldFJhbmRvbVJvb3Q6ICh1c2VyX251bSktPlxyXG4gICAgQHVzZXJzW3VzZXJfbnVtXS52YWwoXCJMaXN0VGVzdFwiKVxyXG5cclxuICBnZXRDb250ZW50OiAodXNlcl9udW0pLT5cclxuICAgIEB1c2Vyc1t1c2VyX251bV0udmFsKFwiTGlzdFRlc3RcIikudmFsKClcclxuXHJcbmRlc2NyaWJlIFwiTGlzdCBUZXN0XCIsIC0+XHJcbiAgQHRpbWVvdXQgNTAwMDAwXHJcblxyXG4gIGJlZm9yZUVhY2ggKGRvbmUpLT5cclxuICAgIEB5VGVzdCA9IG5ldyBMaXN0VGVzdCgpXHJcbiAgICBkb25lKClcclxuXHJcbiAgaXQgXCJjYW4gaGFuZGxlIG1hbnkgZW5naW5lcywgbWFueSBvcGVyYXRpb25zLCBjb25jdXJyZW50bHkgKHJhbmRvbSlcIiwgLT5cclxuICAgIGNvbnNvbGUubG9nIFwiXCIgIyBUT0RPXHJcbiAgICBAeVRlc3QucnVuKClcclxuXHJcbiAgaXQgXCJzaW1wbGUgbXVsdGktY2hhciBpbnNlcnRcIiwgLT5cclxuICAgIHUgPSBAeVRlc3QudXNlcnNbMF0udmFsKFwiTGlzdFRlc3RcIilcclxuICAgIHUuaW5zZXJ0Q29udGVudHMgMCwgWydhJywnYicsJ2MnXVxyXG4gICAgdSA9IEB5VGVzdC51c2Vyc1sxXS52YWwoXCJMaXN0VGVzdFwiKVxyXG4gICAgdS5pbnNlcnQgMCwgJ3gnXHJcbiAgICB1Lmluc2VydENvbnRlbnRzIDEsIFsneScsICd6J11cclxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcclxuICAgIHUuZGVsZXRlIDAsIDFcclxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcclxuICAgIGV4cGVjdCh1LnZhbCgpLmpvaW4oXCJcIikpLnRvLmVxdWFsKFwiYmN4eXpcIilcclxuXHJcbiAgaXQgXCJPYnNlcnZlcnMgd29yayBvbiBzaGFyZWQgTGlzdCAoaW5zZXJ0IHR5cGUgb2JzZXJ2ZXJzLCBsb2NhbCBhbmQgZm9yZWlnbilcIiwgLT5cclxuICAgIHUgPSBAeVRlc3QudXNlcnNbMF0udmFsKFwiTGlzdFRlc3RcIixuZXcgWS5MaXN0KFwibXkgYXdlc29tZSBMaXN0XCIuc3BsaXQoXCJcIikpKS52YWwoXCJMaXN0VGVzdFwiKVxyXG4gICAgQHlUZXN0LmZsdXNoQWxsKClcclxuICAgIGxhc3RfdGFzayA9IG51bGxcclxuICAgIG9ic2VydmVyMSA9IChjaGFuZ2VzKS0+XHJcbiAgICAgIGV4cGVjdChjaGFuZ2VzLmxlbmd0aCkudG8uZXF1YWwoMSlcclxuICAgICAgY2hhbmdlID0gY2hhbmdlc1swXVxyXG4gICAgICBleHBlY3QoY2hhbmdlLnR5cGUpLnRvLmVxdWFsKFwiaW5zZXJ0XCIpXHJcbiAgICAgIGV4cGVjdChjaGFuZ2Uub2JqZWN0KS50by5lcXVhbCh1KVxyXG4gICAgICBleHBlY3QoY2hhbmdlLnZhbHVlKS50by5lcXVhbChcImFcIilcclxuICAgICAgZXhwZWN0KGNoYW5nZS5wb3NpdGlvbikudG8uZXF1YWwoMSlcclxuICAgICAgZXhwZWN0KGNoYW5nZS5jaGFuZ2VkQnkpLnRvLmVxdWFsKCcwJylcclxuICAgICAgbGFzdF90YXNrID0gXCJvYnNlcnZlcjFcIlxyXG4gICAgdS5vYnNlcnZlIG9ic2VydmVyMVxyXG4gICAgdS5pbnNlcnQgMSwgXCJhXCJcclxuICAgIGV4cGVjdChsYXN0X3Rhc2spLnRvLmVxdWFsKFwib2JzZXJ2ZXIxXCIpXHJcbiAgICB1LnVub2JzZXJ2ZSBvYnNlcnZlcjFcclxuXHJcbiAgICBvYnNlcnZlcjIgPSAoY2hhbmdlcyktPlxyXG4gICAgICBleHBlY3QoY2hhbmdlcy5sZW5ndGgpLnRvLmVxdWFsKDEpXHJcbiAgICAgIGNoYW5nZSA9IGNoYW5nZXNbMF1cclxuICAgICAgZXhwZWN0KGNoYW5nZS50eXBlKS50by5lcXVhbChcImluc2VydFwiKVxyXG4gICAgICBleHBlY3QoY2hhbmdlLm9iamVjdCkudG8uZXF1YWwodSlcclxuICAgICAgZXhwZWN0KGNoYW5nZS52YWx1ZSkudG8uZXF1YWwoXCJ4XCIpXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UucG9zaXRpb24pLnRvLmVxdWFsKDApXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UuY2hhbmdlZEJ5KS50by5lcXVhbCgnMScpXHJcbiAgICAgIGxhc3RfdGFzayA9IFwib2JzZXJ2ZXIyXCJcclxuICAgIHUub2JzZXJ2ZSBvYnNlcnZlcjJcclxuICAgIHYgPSBAeVRlc3QudXNlcnNbMV0udmFsKFwiTGlzdFRlc3RcIilcclxuICAgIHYuaW5zZXJ0IDAsIFwieFwiXHJcbiAgICBAeVRlc3QuZmx1c2hBbGwoKVxyXG4gICAgZXhwZWN0KGxhc3RfdGFzaykudG8uZXF1YWwoXCJvYnNlcnZlcjJcIilcclxuICAgIHUudW5vYnNlcnZlIG9ic2VydmVyMlxyXG5cclxuICBpdCBcIk9ic2VydmVycyB3b3JrIG9uIHNoYXJlZCBMaXN0IChkZWxldGUgdHlwZSBvYnNlcnZlcnMsIGxvY2FsIGFuZCBmb3JlaWduKVwiLCAtPlxyXG4gICAgdSA9IEB5VGVzdC51c2Vyc1swXS52YWwoXCJMaXN0VGVzdFwiLG5ldyBZLkxpc3QoXCJteSBhd2Vzb21lIExpc3RcIi5zcGxpdChcIlwiKSkpLnZhbChcIkxpc3RUZXN0XCIpXHJcbiAgICBAeVRlc3QuZmx1c2hBbGwoKVxyXG4gICAgbGFzdF90YXNrID0gbnVsbFxyXG4gICAgb2JzZXJ2ZXIxID0gKGNoYW5nZXMpLT5cclxuICAgICAgZXhwZWN0KGNoYW5nZXMubGVuZ3RoKS50by5lcXVhbCgxKVxyXG4gICAgICBjaGFuZ2UgPSBjaGFuZ2VzWzBdXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UudHlwZSkudG8uZXF1YWwoXCJkZWxldGVcIilcclxuICAgICAgZXhwZWN0KGNoYW5nZS5vYmplY3QpLnRvLmVxdWFsKHUpXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UucG9zaXRpb24pLnRvLmVxdWFsKDEpXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UubGVuZ3RoKS50by5lcXVhbCgxKVxyXG4gICAgICBleHBlY3QoY2hhbmdlLmNoYW5nZWRCeSkudG8uZXF1YWwoJzAnKVxyXG4gICAgICBsYXN0X3Rhc2sgPSBcIm9ic2VydmVyMVwiXHJcbiAgICB1Lm9ic2VydmUgb2JzZXJ2ZXIxXHJcbiAgICB1LmRlbGV0ZSAxLCAxXHJcbiAgICBleHBlY3QobGFzdF90YXNrKS50by5lcXVhbChcIm9ic2VydmVyMVwiKVxyXG4gICAgdS51bm9ic2VydmUgb2JzZXJ2ZXIxXHJcblxyXG4gICAgb2JzZXJ2ZXIyID0gKGNoYW5nZXMpLT5cclxuICAgICAgZXhwZWN0KGNoYW5nZXMubGVuZ3RoKS50by5lcXVhbCgxKVxyXG4gICAgICBjaGFuZ2UgPSBjaGFuZ2VzWzBdXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UudHlwZSkudG8uZXF1YWwoXCJkZWxldGVcIilcclxuICAgICAgZXhwZWN0KGNoYW5nZS5vYmplY3QpLnRvLmVxdWFsKHUpXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UucG9zaXRpb24pLnRvLmVxdWFsKDApXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UubGVuZ3RoKS50by5lcXVhbCgxKVxyXG4gICAgICBleHBlY3QoY2hhbmdlLmNoYW5nZWRCeSkudG8uZXF1YWwoJzEnKVxyXG4gICAgICBsYXN0X3Rhc2sgPSBcIm9ic2VydmVyMlwiXHJcbiAgICB1Lm9ic2VydmUgb2JzZXJ2ZXIyXHJcbiAgICB2ID0gQHlUZXN0LnVzZXJzWzFdLnZhbChcIkxpc3RUZXN0XCIpXHJcbiAgICB2LmRlbGV0ZSAwLCAxXHJcbiAgICBAeVRlc3QuZmx1c2hBbGwoKVxyXG4gICAgZXhwZWN0KGxhc3RfdGFzaykudG8uZXF1YWwoXCJvYnNlcnZlcjJcIilcclxuICAgIHUudW5vYnNlcnZlIG9ic2VydmVyMlxyXG5cclxuICBpdCBcImNhbiBoYW5kbGUgbWFueSBlbmdpbmVzLCBtYW55IG9wZXJhdGlvbnMsIGNvbmN1cnJlbnRseSAocmFuZG9tKVwiLCAtPlxyXG4gICAgY29uc29sZS5sb2coXCJ0ZXN0aXkgZGVsZXRlZCB0aGlzIFRPRE86ZHRyblwiKVxyXG4gICAgQHlUZXN0LnJ1bigpXHJcblxyXG4gIGl0IFwiaGFuZGxlcyBkb3VibGUtbGF0ZS1qb2luXCIsIC0+XHJcbiAgICB0ZXN0ID0gbmV3IExpc3RUZXN0KFwiZG91YmxlXCIpXHJcbiAgICB0ZXN0LnJ1bigpXHJcbiAgICBAeVRlc3QucnVuKClcclxuICAgIHUxID0gdGVzdC51c2Vyc1swXVxyXG4gICAgdTIgPSBAeVRlc3QudXNlcnNbMV1cclxuICAgIG9wczEgPSB1MS5fbW9kZWwuSEIuX2VuY29kZSgpXHJcbiAgICBvcHMyID0gdTIuX21vZGVsLkhCLl9lbmNvZGUoKVxyXG4gICAgdTEuX21vZGVsLmVuZ2luZS5hcHBseU9wIG9wczIsIHRydWVcclxuICAgIHUyLl9tb2RlbC5lbmdpbmUuYXBwbHlPcCBvcHMxLCB0cnVlXHJcbiAgICBAeVRlc3QuY29tcGFyZSB1MSwgdTJcclxuXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IExpc3RUZXN0XHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG4iLCJcclxuI1xyXG4jIEEgdHJpdmlhbCBDb25uZWN0b3IgdGhhdCBzaW11bGF0ZXMgbmV0d29yayBkZWxheS5cclxuI1xyXG5jbGFzcyBUZXN0Q29ubmVjdG9yXHJcblxyXG4gICNcclxuICAjIEBwYXJhbSBpZCB7U3RyaW5nfSBTb21lIHVuaXF1ZSBpZFxyXG4gICNcclxuICBjb25zdHJ1Y3RvcjogKEBpZCktPlxyXG4gICAgb3B0aW9ucyA9XHJcbiAgICAgIHN5bmNNZXRob2Q6IFwic3luY0FsbFwiXHJcbiAgICAgIHJvbGU6IFwic2xhdmVcIlxyXG4gICAgICB1c2VyX2lkOiBAaWQgIyBUT0RPOiBmb3Igbm93LCB3ZSBzYXZlIHRoZSB1c2VyX2lkIHVuZGVyIEBpZCBBTkQgQHVzZXJfaWQsIGJ1dCBjaGFuZ2UgdGhpcyBsYXRlci4uXHJcbiAgICAgIHBlcmZvcm1fc2VuZF9hZ2FpbjogZmFsc2VcclxuXHJcbiAgICBAb25fYm91bmRfdG9feSA9ICgpPT5cclxuICAgICAgQGluaXQgb3B0aW9uc1xyXG5cclxuICAgICAgIyBJZiB5b3UgdGhpbmsgb2Ygb3BlcmF0aW9ucywgdGhpcyB3aWxsIG1pcnJvciB0aGVcclxuICAgICAgIyBleGVjaXRvbiBvcmRlciBvZiBvcGVyYXRpb25zICh3aGVuIGEgbWVzc2FnZSBpcyBzZW5kLCBvciByZWNlaXZlZCBpdCBpcyBwdXQgaW50byB0aGlzKVxyXG4gICAgICBAZXhlY3V0aW9uX29yZGVyID0gW11cclxuICAgICAgIyBUaGUgbWVzc2FnZXMgYXJlIGJ1ZmZlcmVkIHVuZGVyIHRoZSBuYW1lIG9mIHRlaCBzZW5kaW5nIHVzZXIuXHJcbiAgICAgIEByZWNlaXZlX2J1ZmZlciA9IHt9XHJcblxyXG4gICAgICBAcmVjZWl2ZV9oYW5kbGVycy5wdXNoICh1c2VyLCBtZXNzYWdlKT0+XHJcbiAgICAgICAgQGV4ZWN1dGlvbl9vcmRlci5wdXNoIG1lc3NhZ2VcclxuXHJcbiAgIyBqb2luIGFub3RoZXIgdXNlciBjb25uZWN0b3JcclxuICBqb2luOiAoY29ubiktPlxyXG4gICAgaWYgbm90IEBjb25uZWN0aW9uc1tjb25uLmlkXT9cclxuICAgICAgQGNvbm5lY3Rpb25zW2Nvbm4uaWRdID0ge2Nvbm4gOiBjb25ufVxyXG4gICAgICBAdXNlckpvaW5lZCBjb25uLmlkLCBcInNsYXZlXCJcclxuICAgICAgY29ubi5qb2luIEBcclxuICAgICAgQGZsdXNoQWxsKClcclxuICAgICAgY29ubi5mbHVzaEFsbCgpXHJcbiAgICAgIEBmbHVzaEFsbCgpXHJcbiAgICAgIGNvbm4uZmx1c2hBbGwoKVxyXG4gICAgICBmb3IgY2lkLGMgb2YgY29ubi5jb25uZWN0aW9uc1xyXG4gICAgICAgIGlmIG5vdCBAY29ubmVjdGlvbnNbY2lkXT9cclxuICAgICAgICAgIEBqb2luIGMuY29ublxyXG5cclxuXHJcblxyXG4gICNcclxuICAjIEdldCB0aGUgb3BzIGluIHRoZSBleGVjdXRpb24gb3JkZXIuXHJcbiAgI1xyXG4gIGdldE9wc0luRXhlY3V0aW9uT3JkZXI6ICgpLT5cclxuICAgIEBleGVjdXRpb25fb3JkZXJcclxuXHJcbiAgI1xyXG4gICMgU2VuZCBhIG1lc3NhZ2UgdG8gYW5vdGhlciBwZWVyXHJcbiAgIyBAcGFyYW0ge09wZXJhdGlvbn0gbyBUaGUgb3BlcmF0aW9uIHRoYXQgd2FzIGV4ZWN1dGVkLlxyXG4gICNcclxuICBzZW5kOiAodWlkLCBtZXNzYWdlKS0+XHJcbiAgICBpZiBtZXNzYWdlLnN5bmNfc3RlcD8gYW5kIGZhbHNlICMgVE9ETzogZmFsc2VcclxuICAgICAgQHJlY2VpdmVNZXNzYWdlIHVpZCwgbWVzc2FnZVxyXG4gICAgZWxzZVxyXG4gICAgICByYiA9IEBjb25uZWN0aW9uc1t1aWRdLmNvbm4ucmVjZWl2ZV9idWZmZXJcclxuICAgICAgcmJbQGlkXSA/PSBbXVxyXG4gICAgICByYltAaWRdLnB1c2ggbWVzc2FnZVxyXG5cclxuICBicm9hZGNhc3Q6IChtZXNzYWdlKS0+XHJcbiAgICBmb3IgbmFtZSwgYyBvZiBAY29ubmVjdGlvbnNcclxuICAgICAgQHNlbmQgbmFtZSwgbWVzc2FnZVxyXG5cclxuICAjXHJcbiAgIyBGbHVzaCBvbmUgb3BlcmF0aW9uIGZyb20gdGhlIGxpbmUgb2YgYSBzcGVjaWZpYyB1c2VyLlxyXG4gICNcclxuICBmbHVzaE9uZTogKHVpZCktPlxyXG4gICAgaWYgQHJlY2VpdmVfYnVmZmVyW3VpZF0/Lmxlbmd0aCA+IDBcclxuICAgICAgbWVzc2FnZSA9IEByZWNlaXZlX2J1ZmZlclt1aWRdLnNoaWZ0KClcclxuICAgICAgQHJlY2VpdmVNZXNzYWdlKHVpZCwgbWVzc2FnZSlcclxuXHJcblxyXG4gICNcclxuICAjIEZsdXNoIG9uZSBvcGVyYXRpb24gb24gYSByYW5kb20gbGluZS5cclxuICAjXHJcbiAgZmx1c2hPbmVSYW5kb206ICgpLT5cclxuICAgIGNvbm5saXN0ID0gZm9yIGNpZCxjIG9mIEByZWNlaXZlX2J1ZmZlclxyXG4gICAgICBjaWRcclxuICAgIGkgPSBNYXRoLmNlaWwoTWF0aC5yYW5kb20oKSpjb25ubGlzdC5sZW5ndGgtMC41KVxyXG4gICAgQGZsdXNoT25lIGNvbm5saXN0W2ldXHJcblxyXG4gICNcclxuICAjIEZsdXNoIGFsbCBvcGVyYXRpb25zIG9uIGV2ZXJ5IGxpbmUuXHJcbiAgI1xyXG4gIGZsdXNoQWxsOiAoKS0+XHJcbiAgICBmb3IgbixtZXNzYWdlcyBvZiBAcmVjZWl2ZV9idWZmZXJcclxuICAgICAgZm9yIG1lc3NhZ2UgaW4gbWVzc2FnZXNcclxuICAgICAgICBAcmVjZWl2ZU1lc3NhZ2UobiwgbWVzc2FnZSlcclxuXHJcbiAgICBAcmVjZWl2ZV9idWZmZXIgPSB7fVxyXG5cclxuXHJcbmlmIHdpbmRvdz9cclxuICBpZiBub3QgWT9cclxuICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBtdXN0IGltcG9ydCBZIGZpcnN0IVwiXHJcbiAgZWxzZVxyXG4gICAgd2luZG93LlkuVGVzdENvbm5lY3RvciA9IFRlc3RDb25uZWN0b3JcclxuXHJcbmlmIG1vZHVsZT9cclxuICBtb2R1bGUuZXhwb3J0cyA9IFRlc3RDb25uZWN0b3JcclxuIiwiXHJcblxyXG4jXHJcbiMgSGFuZGxlcyBhIFN0cmluZy1saWtlIGRhdGEgc3RydWN0dXJlcyB3aXRoIHN1cHBvcnQgZm9yIGluc2VydC9kZWxldGUgYXQgYSB3b3JkLXBvc2l0aW9uLlxyXG4jXHJcbmNsYXNzIFlUZXh0XHJcblxyXG4gICNcclxuICAjIEBwcml2YXRlXHJcbiAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXHJcbiAgI1xyXG4gIGNvbnN0cnVjdG9yOiAodGV4dCktPlxyXG4gICAgQHRleHRmaWVsZHMgPSBbXVxyXG4gICAgaWYgbm90IHRleHQ/XHJcbiAgICAgIEBfdGV4dCA9IFwiXCJcclxuICAgIGVsc2UgaWYgdGV4dC5jb25zdHJ1Y3RvciBpcyBTdHJpbmdcclxuICAgICAgQF90ZXh0ID0gdGV4dFxyXG4gICAgZWxzZVxyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZLlRleHQgZXhwZWN0cyBhIFN0cmluZyBhcyBhIGNvbnN0cnVjdG9yXCJcclxuXHJcbiAgX25hbWU6IFwiVGV4dFwiXHJcblxyXG4gIF9nZXRNb2RlbDogKHR5cGVzLCBvcHMpLT5cclxuICAgIGlmIG5vdCBAX21vZGVsP1xyXG4gICAgICBAX21vZGVsID0gbmV3IG9wcy5MaXN0TWFuYWdlcihAKS5leGVjdXRlKClcclxuICAgICAgQGluc2VydCAwLCBAX3RleHRcclxuICAgIGRlbGV0ZSBAX3RleHRcclxuICAgIEBfbW9kZWxcclxuXHJcbiAgX3NldE1vZGVsOiAoQF9tb2RlbCktPlxyXG4gICAgZGVsZXRlIEBfdGV4dFxyXG5cclxuICAjXHJcbiAgIyBHZXQgdGhlIFN0cmluZy1yZXByZXNlbnRhdGlvbiBvZiB0aGlzIHdvcmQuXHJcbiAgIyBAcmV0dXJuIHtTdHJpbmd9IFRoZSBTdHJpbmctcmVwcmVzZW50YXRpb24gb2YgdGhpcyBvYmplY3QuXHJcbiAgI1xyXG4gIHZhbDogKCktPlxyXG4gICAgQF9tb2RlbC5mb2xkIFwiXCIsIChsZWZ0LCBvKS0+XHJcbiAgICAgIGxlZnQgKyBvLnZhbCgpXHJcblxyXG4gIG9ic2VydmU6ICgpLT5cclxuICAgIEBfbW9kZWwub2JzZXJ2ZS5hcHBseSBAX21vZGVsLCBhcmd1bWVudHNcclxuXHJcbiAgdW5vYnNlcnZlOiAoKS0+XHJcbiAgICBAX21vZGVsLnVub2JzZXJ2ZS5hcHBseSBAX21vZGVsLCBhcmd1bWVudHNcclxuXHJcbiAgI1xyXG4gICMgU2FtZSBhcyBTdHJpbmcudmFsXHJcbiAgIyBAc2VlIFN0cmluZy52YWxcclxuICAjXHJcbiAgdG9TdHJpbmc6ICgpLT5cclxuICAgIEB2YWwoKVxyXG5cclxuICAjXHJcbiAgIyBJbnNlcnRzIGEgc3RyaW5nIGludG8gdGhlIHdvcmQuXHJcbiAgI1xyXG4gICMgQHJldHVybiB7TGlzdE1hbmFnZXIgVHlwZX0gVGhpcyBTdHJpbmcgb2JqZWN0LlxyXG4gICNcclxuICBpbnNlcnQ6IChwb3NpdGlvbiwgY29udGVudCktPlxyXG4gICAgaWYgY29udGVudC5jb25zdHJ1Y3RvciBpc250IFN0cmluZ1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZLlN0cmluZy5pbnNlcnQgZXhwZWN0cyBhIFN0cmluZyBhcyB0aGUgc2Vjb25kIHBhcmFtZXRlciFcIlxyXG4gICAgaWYgdHlwZW9mIHBvc2l0aW9uIGlzbnQgXCJudW1iZXJcIlxyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZLlN0cmluZy5pbnNlcnQgZXhwZWN0cyBhIE51bWJlciBhcyB0aGUgZmlyc3QgcGFyYW1ldGVyIVwiXHJcbiAgICBpZiBjb250ZW50Lmxlbmd0aCA+IDBcclxuICAgICAgaXRoID0gQF9tb2RlbC5nZXRPcGVyYXRpb25CeVBvc2l0aW9uIHBvc2l0aW9uXHJcbiAgICAgICMgdGhlIChpLTEpdGggY2hhcmFjdGVyLiBlLmcuIFwiYWJjXCIgdGhlIDF0aCBjaGFyYWN0ZXIgaXMgXCJhXCJcclxuICAgICAgIyB0aGUgMHRoIGNoYXJhY3RlciBpcyB0aGUgbGVmdCBEZWxpbWl0ZXJcclxuICAgICAgQF9tb2RlbC5pbnNlcnRBZnRlciBpdGgsIGNvbnRlbnRcclxuXHJcbiAgZGVsZXRlOiAocG9zaXRpb24sIGxlbmd0aCktPlxyXG4gICAgQF9tb2RlbC5kZWxldGUgcG9zaXRpb24sIGxlbmd0aFxyXG5cclxuICAjXHJcbiAgIyBCaW5kIHRoaXMgU3RyaW5nIHRvIGEgdGV4dGZpZWxkIG9yIGlucHV0IGZpZWxkLlxyXG4gICNcclxuICAjIEBleGFtcGxlXHJcbiAgIyAgIHZhciB0ZXh0Ym94ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJ0ZXh0ZmllbGRcIik7XHJcbiAgIyAgIHkuYmluZCh0ZXh0Ym94KTtcclxuICAjXHJcbiAgYmluZDogKHRleHRmaWVsZCwgZG9tX3Jvb3QpLT5cclxuICAgIGRvbV9yb290ID89IHdpbmRvd1xyXG4gICAgaWYgKG5vdCBkb21fcm9vdC5nZXRTZWxlY3Rpb24/KVxyXG4gICAgICBkb21fcm9vdCA9IHdpbmRvd1xyXG5cclxuICAgICMgZG9uJ3QgZHVwbGljYXRlIVxyXG4gICAgZm9yIHQgaW4gQHRleHRmaWVsZHNcclxuICAgICAgaWYgdCBpcyB0ZXh0ZmllbGRcclxuICAgICAgICByZXR1cm5cclxuICAgIGNyZWF0b3JfdG9rZW4gPSBmYWxzZTtcclxuXHJcbiAgICB3b3JkID0gQFxyXG4gICAgdGV4dGZpZWxkLnZhbHVlID0gQHZhbCgpXHJcbiAgICBAdGV4dGZpZWxkcy5wdXNoIHRleHRmaWVsZFxyXG5cclxuICAgIGlmIHRleHRmaWVsZC5zZWxlY3Rpb25TdGFydD8gYW5kIHRleHRmaWVsZC5zZXRTZWxlY3Rpb25SYW5nZT9cclxuICAgICAgY3JlYXRlUmFuZ2UgPSAoZml4KS0+XHJcbiAgICAgICAgbGVmdCA9IHRleHRmaWVsZC5zZWxlY3Rpb25TdGFydFxyXG4gICAgICAgIHJpZ2h0ID0gdGV4dGZpZWxkLnNlbGVjdGlvbkVuZFxyXG4gICAgICAgIGlmIGZpeD9cclxuICAgICAgICAgIGxlZnQgPSBmaXggbGVmdFxyXG4gICAgICAgICAgcmlnaHQgPSBmaXggcmlnaHRcclxuICAgICAgICB7XHJcbiAgICAgICAgICBsZWZ0OiBsZWZ0XHJcbiAgICAgICAgICByaWdodDogcmlnaHRcclxuICAgICAgICB9XHJcblxyXG4gICAgICB3cml0ZVJhbmdlID0gKHJhbmdlKS0+XHJcbiAgICAgICAgd3JpdGVDb250ZW50IHdvcmQudmFsKClcclxuICAgICAgICB0ZXh0ZmllbGQuc2V0U2VsZWN0aW9uUmFuZ2UgcmFuZ2UubGVmdCwgcmFuZ2UucmlnaHRcclxuXHJcbiAgICAgIHdyaXRlQ29udGVudCA9IChjb250ZW50KS0+XHJcbiAgICAgICAgdGV4dGZpZWxkLnZhbHVlID0gY29udGVudFxyXG4gICAgZWxzZVxyXG4gICAgICBjcmVhdGVSYW5nZSA9IChmaXgpLT5cclxuICAgICAgICByYW5nZSA9IHt9XHJcbiAgICAgICAgcyA9IGRvbV9yb290LmdldFNlbGVjdGlvbigpXHJcbiAgICAgICAgY2xlbmd0aCA9IHRleHRmaWVsZC50ZXh0Q29udGVudC5sZW5ndGhcclxuICAgICAgICByYW5nZS5sZWZ0ID0gTWF0aC5taW4gcy5hbmNob3JPZmZzZXQsIGNsZW5ndGhcclxuICAgICAgICByYW5nZS5yaWdodCA9IE1hdGgubWluIHMuZm9jdXNPZmZzZXQsIGNsZW5ndGhcclxuICAgICAgICBpZiBmaXg/XHJcbiAgICAgICAgICByYW5nZS5sZWZ0ID0gZml4IHJhbmdlLmxlZnRcclxuICAgICAgICAgIHJhbmdlLnJpZ2h0ID0gZml4IHJhbmdlLnJpZ2h0XHJcblxyXG4gICAgICAgIGVkaXRlZF9lbGVtZW50ID0gcy5mb2N1c05vZGVcclxuICAgICAgICBpZiBlZGl0ZWRfZWxlbWVudCBpcyB0ZXh0ZmllbGQgb3IgZWRpdGVkX2VsZW1lbnQgaXMgdGV4dGZpZWxkLmNoaWxkTm9kZXNbMF1cclxuICAgICAgICAgIHJhbmdlLmlzUmVhbCA9IHRydWVcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICByYW5nZS5pc1JlYWwgPSBmYWxzZVxyXG4gICAgICAgIHJhbmdlXHJcblxyXG4gICAgICB3cml0ZVJhbmdlID0gKHJhbmdlKS0+XHJcbiAgICAgICAgd3JpdGVDb250ZW50IHdvcmQudmFsKClcclxuICAgICAgICB0ZXh0bm9kZSA9IHRleHRmaWVsZC5jaGlsZE5vZGVzWzBdXHJcbiAgICAgICAgaWYgcmFuZ2UuaXNSZWFsIGFuZCB0ZXh0bm9kZT9cclxuICAgICAgICAgIGlmIHJhbmdlLmxlZnQgPCAwXHJcbiAgICAgICAgICAgIHJhbmdlLmxlZnQgPSAwXHJcbiAgICAgICAgICByYW5nZS5yaWdodCA9IE1hdGgubWF4IHJhbmdlLmxlZnQsIHJhbmdlLnJpZ2h0XHJcbiAgICAgICAgICBpZiByYW5nZS5yaWdodCA+IHRleHRub2RlLmxlbmd0aFxyXG4gICAgICAgICAgICByYW5nZS5yaWdodCA9IHRleHRub2RlLmxlbmd0aFxyXG4gICAgICAgICAgcmFuZ2UubGVmdCA9IE1hdGgubWluIHJhbmdlLmxlZnQsIHJhbmdlLnJpZ2h0XHJcbiAgICAgICAgICByID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKVxyXG4gICAgICAgICAgci5zZXRTdGFydCh0ZXh0bm9kZSwgcmFuZ2UubGVmdClcclxuICAgICAgICAgIHIuc2V0RW5kKHRleHRub2RlLCByYW5nZS5yaWdodClcclxuICAgICAgICAgIHMgPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKClcclxuICAgICAgICAgIHMucmVtb3ZlQWxsUmFuZ2VzKClcclxuICAgICAgICAgIHMuYWRkUmFuZ2UocilcclxuICAgICAgd3JpdGVDb250ZW50ID0gKGNvbnRlbnQpLT5cclxuICAgICAgICBjb250ZW50X2FycmF5ID0gY29udGVudC5yZXBsYWNlKG5ldyBSZWdFeHAoXCJcXG5cIiwnZycpLFwiIFwiKS5zcGxpdChcIiBcIilcclxuICAgICAgICB0ZXh0ZmllbGQuaW5uZXJUZXh0ID0gXCJcIlxyXG4gICAgICAgIGZvciBjLCBpIGluIGNvbnRlbnRfYXJyYXlcclxuICAgICAgICAgIHRleHRmaWVsZC5pbm5lclRleHQgKz0gY1xyXG4gICAgICAgICAgaWYgaSBpc250IGNvbnRlbnRfYXJyYXkubGVuZ3RoLTFcclxuICAgICAgICAgICAgdGV4dGZpZWxkLmlubmVySFRNTCArPSAnJm5ic3A7J1xyXG5cclxuICAgIHdyaXRlQ29udGVudCB0aGlzLnZhbCgpXHJcblxyXG4gICAgQG9ic2VydmUgKGV2ZW50cyktPlxyXG4gICAgICBmb3IgZXZlbnQgaW4gZXZlbnRzXHJcbiAgICAgICAgaWYgbm90IGNyZWF0b3JfdG9rZW5cclxuICAgICAgICAgIGlmIGV2ZW50LnR5cGUgaXMgXCJpbnNlcnRcIlxyXG4gICAgICAgICAgICBvX3BvcyA9IGV2ZW50LnBvc2l0aW9uXHJcbiAgICAgICAgICAgIGZpeCA9IChjdXJzb3IpLT5cclxuICAgICAgICAgICAgICBpZiBjdXJzb3IgPD0gb19wb3NcclxuICAgICAgICAgICAgICAgIGN1cnNvclxyXG4gICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgIGN1cnNvciArPSAxXHJcbiAgICAgICAgICAgICAgICBjdXJzb3JcclxuICAgICAgICAgICAgciA9IGNyZWF0ZVJhbmdlIGZpeFxyXG4gICAgICAgICAgICB3cml0ZVJhbmdlIHJcclxuXHJcbiAgICAgICAgICBlbHNlIGlmIGV2ZW50LnR5cGUgaXMgXCJkZWxldGVcIlxyXG4gICAgICAgICAgICBvX3BvcyA9IGV2ZW50LnBvc2l0aW9uXHJcbiAgICAgICAgICAgIGZpeCA9IChjdXJzb3IpLT5cclxuICAgICAgICAgICAgICBpZiBjdXJzb3IgPCBvX3Bvc1xyXG4gICAgICAgICAgICAgICAgY3Vyc29yXHJcbiAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgY3Vyc29yIC09IDFcclxuICAgICAgICAgICAgICAgIGN1cnNvclxyXG4gICAgICAgICAgICByID0gY3JlYXRlUmFuZ2UgZml4XHJcbiAgICAgICAgICAgIHdyaXRlUmFuZ2UgclxyXG5cclxuICAgICMgY29uc3VtZSBhbGwgdGV4dC1pbnNlcnQgY2hhbmdlcy5cclxuICAgIHRleHRmaWVsZC5vbmtleXByZXNzID0gKGV2ZW50KS0+XHJcbiAgICAgIGlmIHdvcmQuaXNfZGVsZXRlZFxyXG4gICAgICAgICMgaWYgd29yZCBpcyBkZWxldGVkLCBkbyBub3QgZG8gYW55dGhpbmcgZXZlciBhZ2FpblxyXG4gICAgICAgIHRleHRmaWVsZC5vbmtleXByZXNzID0gbnVsbFxyXG4gICAgICAgIHJldHVybiB0cnVlXHJcbiAgICAgIGNyZWF0b3JfdG9rZW4gPSB0cnVlXHJcbiAgICAgIGNoYXIgPSBudWxsXHJcbiAgICAgIGlmIGV2ZW50LmtleUNvZGUgaXMgMTNcclxuICAgICAgICBjaGFyID0gJ1xcbidcclxuICAgICAgZWxzZSBpZiBldmVudC5rZXk/XHJcbiAgICAgICAgaWYgZXZlbnQuY2hhckNvZGUgaXMgMzJcclxuICAgICAgICAgIGNoYXIgPSBcIiBcIlxyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgIGNoYXIgPSBldmVudC5rZXlcclxuICAgICAgZWxzZVxyXG4gICAgICAgIGNoYXIgPSB3aW5kb3cuU3RyaW5nLmZyb21DaGFyQ29kZSBldmVudC5rZXlDb2RlXHJcbiAgICAgIGlmIGNoYXIubGVuZ3RoID4gMVxyXG4gICAgICAgIHJldHVybiB0cnVlXHJcbiAgICAgIGVsc2UgaWYgY2hhci5sZW5ndGggPiAwXHJcbiAgICAgICAgciA9IGNyZWF0ZVJhbmdlKClcclxuICAgICAgICBwb3MgPSBNYXRoLm1pbiByLmxlZnQsIHIucmlnaHRcclxuICAgICAgICBkaWZmID0gTWF0aC5hYnMoci5yaWdodCAtIHIubGVmdClcclxuICAgICAgICB3b3JkLmRlbGV0ZSBwb3MsIGRpZmZcclxuICAgICAgICB3b3JkLmluc2VydCBwb3MsIGNoYXJcclxuICAgICAgICByLmxlZnQgPSBwb3MgKyBjaGFyLmxlbmd0aFxyXG4gICAgICAgIHIucmlnaHQgPSByLmxlZnRcclxuICAgICAgICB3cml0ZVJhbmdlIHJcclxuXHJcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KClcclxuICAgICAgY3JlYXRvcl90b2tlbiA9IGZhbHNlXHJcbiAgICAgIGZhbHNlXHJcblxyXG4gICAgdGV4dGZpZWxkLm9ucGFzdGUgPSAoZXZlbnQpLT5cclxuICAgICAgaWYgd29yZC5pc19kZWxldGVkXHJcbiAgICAgICAgIyBpZiB3b3JkIGlzIGRlbGV0ZWQsIGRvIG5vdCBkbyBhbnl0aGluZyBldmVyIGFnYWluXHJcbiAgICAgICAgdGV4dGZpZWxkLm9ucGFzdGUgPSBudWxsXHJcbiAgICAgICAgcmV0dXJuIHRydWVcclxuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKVxyXG4gICAgdGV4dGZpZWxkLm9uY3V0ID0gKGV2ZW50KS0+XHJcbiAgICAgIGlmIHdvcmQuaXNfZGVsZXRlZFxyXG4gICAgICAgICMgaWYgd29yZCBpcyBkZWxldGVkLCBkbyBub3QgZG8gYW55dGhpbmcgZXZlciBhZ2FpblxyXG4gICAgICAgIHRleHRmaWVsZC5vbmN1dCA9IG51bGxcclxuICAgICAgICByZXR1cm4gdHJ1ZVxyXG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpXHJcblxyXG4gICAgI1xyXG4gICAgIyBjb25zdW1lIGRlbGV0ZXMuIE5vdGUgdGhhdFxyXG4gICAgIyAgIGNocm9tZTogd29uJ3QgY29uc3VtZSBkZWxldGlvbnMgb24ga2V5cHJlc3MgZXZlbnQuXHJcbiAgICAjICAga2V5Q29kZSBpcyBkZXByZWNhdGVkLiBCVVQ6IEkgZG9uJ3Qgc2VlIGFub3RoZXIgd2F5LlxyXG4gICAgIyAgICAgc2luY2UgZXZlbnQua2V5IGlzIG5vdCBpbXBsZW1lbnRlZCBpbiB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIGNocm9tZS5cclxuICAgICMgICAgIEV2ZXJ5IGJyb3dzZXIgc3VwcG9ydHMga2V5Q29kZS4gTGV0J3Mgc3RpY2sgd2l0aCBpdCBmb3Igbm93Li5cclxuICAgICNcclxuICAgIHRleHRmaWVsZC5vbmtleWRvd24gPSAoZXZlbnQpLT5cclxuICAgICAgY3JlYXRvcl90b2tlbiA9IHRydWVcclxuICAgICAgaWYgd29yZC5pc19kZWxldGVkXHJcbiAgICAgICAgIyBpZiB3b3JkIGlzIGRlbGV0ZWQsIGRvIG5vdCBkbyBhbnl0aGluZyBldmVyIGFnYWluXHJcbiAgICAgICAgdGV4dGZpZWxkLm9ua2V5ZG93biA9IG51bGxcclxuICAgICAgICByZXR1cm4gdHJ1ZVxyXG4gICAgICByID0gY3JlYXRlUmFuZ2UoKVxyXG4gICAgICBwb3MgPSBNYXRoLm1pbihyLmxlZnQsIHIucmlnaHQsIHdvcmQudmFsKCkubGVuZ3RoKVxyXG4gICAgICBkaWZmID0gTWF0aC5hYnMoci5sZWZ0IC0gci5yaWdodClcclxuICAgICAgaWYgZXZlbnQua2V5Q29kZT8gYW5kIGV2ZW50LmtleUNvZGUgaXMgOCAjIEJhY2tzcGFjZVxyXG4gICAgICAgIGlmIGRpZmYgPiAwXHJcbiAgICAgICAgICB3b3JkLmRlbGV0ZSBwb3MsIGRpZmZcclxuICAgICAgICAgIHIubGVmdCA9IHBvc1xyXG4gICAgICAgICAgci5yaWdodCA9IHBvc1xyXG4gICAgICAgICAgd3JpdGVSYW5nZSByXHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgaWYgZXZlbnQuY3RybEtleT8gYW5kIGV2ZW50LmN0cmxLZXlcclxuICAgICAgICAgICAgdmFsID0gd29yZC52YWwoKVxyXG4gICAgICAgICAgICBuZXdfcG9zID0gcG9zXHJcbiAgICAgICAgICAgIGRlbF9sZW5ndGggPSAwXHJcbiAgICAgICAgICAgIGlmIHBvcyA+IDBcclxuICAgICAgICAgICAgICBuZXdfcG9zLS1cclxuICAgICAgICAgICAgICBkZWxfbGVuZ3RoKytcclxuICAgICAgICAgICAgd2hpbGUgbmV3X3BvcyA+IDAgYW5kIHZhbFtuZXdfcG9zXSBpc250IFwiIFwiIGFuZCB2YWxbbmV3X3Bvc10gaXNudCAnXFxuJ1xyXG4gICAgICAgICAgICAgIG5ld19wb3MtLVxyXG4gICAgICAgICAgICAgIGRlbF9sZW5ndGgrK1xyXG4gICAgICAgICAgICB3b3JkLmRlbGV0ZSBuZXdfcG9zLCAocG9zLW5ld19wb3MpXHJcbiAgICAgICAgICAgIHIubGVmdCA9IG5ld19wb3NcclxuICAgICAgICAgICAgci5yaWdodCA9IG5ld19wb3NcclxuICAgICAgICAgICAgd3JpdGVSYW5nZSByXHJcbiAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIGlmIHBvcyA+IDBcclxuICAgICAgICAgICAgICB3b3JkLmRlbGV0ZSAocG9zLTEpLCAxXHJcbiAgICAgICAgICAgICAgci5sZWZ0ID0gcG9zLTFcclxuICAgICAgICAgICAgICByLnJpZ2h0ID0gcG9zLTFcclxuICAgICAgICAgICAgICB3cml0ZVJhbmdlIHJcclxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpXHJcbiAgICAgICAgY3JlYXRvcl90b2tlbiA9IGZhbHNlXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlXHJcbiAgICAgIGVsc2UgaWYgZXZlbnQua2V5Q29kZT8gYW5kIGV2ZW50LmtleUNvZGUgaXMgNDYgIyBEZWxldGVcclxuICAgICAgICBpZiBkaWZmID4gMFxyXG4gICAgICAgICAgd29yZC5kZWxldGUgcG9zLCBkaWZmXHJcbiAgICAgICAgICByLmxlZnQgPSBwb3NcclxuICAgICAgICAgIHIucmlnaHQgPSBwb3NcclxuICAgICAgICAgIHdyaXRlUmFuZ2UgclxyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgIHdvcmQuZGVsZXRlIHBvcywgMVxyXG4gICAgICAgICAgci5sZWZ0ID0gcG9zXHJcbiAgICAgICAgICByLnJpZ2h0ID0gcG9zXHJcbiAgICAgICAgICB3cml0ZVJhbmdlIHJcclxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpXHJcbiAgICAgICAgY3JlYXRvcl90b2tlbiA9IGZhbHNlXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlXHJcbiAgICAgIGVsc2VcclxuICAgICAgICBjcmVhdG9yX3Rva2VuID0gZmFsc2VcclxuICAgICAgICB0cnVlXHJcblxyXG5cclxuaWYgd2luZG93P1xyXG4gIGlmIHdpbmRvdy5ZP1xyXG4gICAgd2luZG93LlkuVGV4dCA9IFlUZXh0XHJcbiAgZWxzZVxyXG4gICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3QgZmlyc3QgaW1wb3J0IFkhXCJcclxuXHJcbmlmIG1vZHVsZT9cclxuICBtb2R1bGUuZXhwb3J0cyA9IFlUZXh0XHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG4iLCJcclxuQ29ubmVjdG9yQ2xhc3MgPSByZXF1aXJlIFwiLi9Db25uZWN0b3JDbGFzc1wiXHJcbiNcclxuIyBAcGFyYW0ge0VuZ2luZX0gZW5naW5lIFRoZSB0cmFuc2Zvcm1hdGlvbiBlbmdpbmVcclxuIyBAcGFyYW0ge0hpc3RvcnlCdWZmZXJ9IEhCXHJcbiMgQHBhcmFtIHtBcnJheTxGdW5jdGlvbj59IGV4ZWN1dGlvbl9saXN0ZW5lciBZb3UgbXVzdCBlbnN1cmUgdGhhdCB3aGVuZXZlciBhbiBvcGVyYXRpb24gaXMgZXhlY3V0ZWQsIGV2ZXJ5IGZ1bmN0aW9uIGluIHRoaXMgQXJyYXkgaXMgY2FsbGVkLlxyXG4jXHJcbmFkYXB0Q29ubmVjdG9yID0gKGNvbm5lY3RvciwgZW5naW5lLCBIQiwgZXhlY3V0aW9uX2xpc3RlbmVyKS0+XHJcblxyXG4gIGZvciBuYW1lLCBmIG9mIENvbm5lY3RvckNsYXNzXHJcbiAgICBjb25uZWN0b3JbbmFtZV0gPSBmXHJcblxyXG4gIGNvbm5lY3Rvci5zZXRJc0JvdW5kVG9ZKClcclxuXHJcbiAgc2VuZF8gPSAobyktPlxyXG4gICAgaWYgKG8udWlkLmNyZWF0b3IgaXMgSEIuZ2V0VXNlcklkKCkpIGFuZFxyXG4gICAgICAgICh0eXBlb2Ygby51aWQub3BfbnVtYmVyIGlzbnQgXCJzdHJpbmdcIikgYW5kICMgVE9ETzogaSBkb24ndCB0aGluayB0aGF0IHdlIG5lZWQgdGhpcyBhbnltb3JlLi5cclxuICAgICAgICAoSEIuZ2V0VXNlcklkKCkgaXNudCBcIl90ZW1wXCIpXHJcbiAgICAgIGNvbm5lY3Rvci5icm9hZGNhc3Qgb1xyXG5cclxuICBpZiBjb25uZWN0b3IuaW52b2tlU3luYz9cclxuICAgIEhCLnNldEludm9rZVN5bmNIYW5kbGVyIGNvbm5lY3Rvci5pbnZva2VTeW5jXHJcblxyXG4gIGV4ZWN1dGlvbl9saXN0ZW5lci5wdXNoIHNlbmRfXHJcbiAgIyBGb3IgdGhlIFhNUFBDb25uZWN0b3I6IGxldHMgc2VuZCBpdCBhcyBhbiBhcnJheVxyXG4gICMgdGhlcmVmb3JlLCB3ZSBoYXZlIHRvIHJlc3RydWN0dXJlIGl0IGxhdGVyXHJcbiAgZW5jb2RlX3N0YXRlX3ZlY3RvciA9ICh2KS0+XHJcbiAgICBmb3IgbmFtZSx2YWx1ZSBvZiB2XHJcbiAgICAgIHVzZXI6IG5hbWVcclxuICAgICAgc3RhdGU6IHZhbHVlXHJcbiAgcGFyc2Vfc3RhdGVfdmVjdG9yID0gKHYpLT5cclxuICAgIHN0YXRlX3ZlY3RvciA9IHt9XHJcbiAgICBmb3IgcyBpbiB2XHJcbiAgICAgIHN0YXRlX3ZlY3RvcltzLnVzZXJdID0gcy5zdGF0ZVxyXG4gICAgc3RhdGVfdmVjdG9yXHJcblxyXG4gIGdldFN0YXRlVmVjdG9yID0gKCktPlxyXG4gICAgZW5jb2RlX3N0YXRlX3ZlY3RvciBIQi5nZXRPcGVyYXRpb25Db3VudGVyKClcclxuXHJcbiAgZ2V0SEIgPSAodiktPlxyXG4gICAgc3RhdGVfdmVjdG9yID0gcGFyc2Vfc3RhdGVfdmVjdG9yIHZcclxuICAgIGhiID0gSEIuX2VuY29kZSBzdGF0ZV92ZWN0b3JcclxuICAgIGpzb24gPVxyXG4gICAgICBoYjogaGJcclxuICAgICAgc3RhdGVfdmVjdG9yOiBlbmNvZGVfc3RhdGVfdmVjdG9yIEhCLmdldE9wZXJhdGlvbkNvdW50ZXIoKVxyXG4gICAganNvblxyXG5cclxuICBhcHBseUhCID0gKGhiLCBmcm9tSEIpLT5cclxuICAgIGVuZ2luZS5hcHBseU9wIGhiLCBmcm9tSEJcclxuXHJcbiAgY29ubmVjdG9yLmdldFN0YXRlVmVjdG9yID0gZ2V0U3RhdGVWZWN0b3JcclxuICBjb25uZWN0b3IuZ2V0SEIgPSBnZXRIQlxyXG4gIGNvbm5lY3Rvci5hcHBseUhCID0gYXBwbHlIQlxyXG5cclxuICBjb25uZWN0b3IucmVjZWl2ZV9oYW5kbGVycyA/PSBbXVxyXG4gIGNvbm5lY3Rvci5yZWNlaXZlX2hhbmRsZXJzLnB1c2ggKHNlbmRlciwgb3ApLT5cclxuICAgIGlmIG9wLnVpZC5jcmVhdG9yIGlzbnQgSEIuZ2V0VXNlcklkKClcclxuICAgICAgZW5naW5lLmFwcGx5T3Agb3BcclxuXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IGFkYXB0Q29ubmVjdG9yXHJcbiIsIlxyXG5tb2R1bGUuZXhwb3J0cyA9XHJcbiAgI1xyXG4gICMgQHBhcmFtcyBuZXcgQ29ubmVjdG9yKG9wdGlvbnMpXHJcbiAgIyAgIEBwYXJhbSBvcHRpb25zLnN5bmNNZXRob2Qge1N0cmluZ30gIGlzIGVpdGhlciBcInN5bmNBbGxcIiBvciBcIm1hc3Rlci1zbGF2ZVwiLlxyXG4gICMgICBAcGFyYW0gb3B0aW9ucy5yb2xlIHtTdHJpbmd9IFRoZSByb2xlIG9mIHRoaXMgY2xpZW50XHJcbiAgIyAgICAgICAgICAgIChzbGF2ZSBvciBtYXN0ZXIgKG9ubHkgdXNlZCB3aGVuIHN5bmNNZXRob2QgaXMgbWFzdGVyLXNsYXZlKSlcclxuICAjICAgQHBhcmFtIG9wdGlvbnMucGVyZm9ybV9zZW5kX2FnYWluIHtCb29sZWFufSBXaGV0ZWhyIHRvIHdoZXRoZXIgdG8gcmVzZW5kIHRoZSBIQiBhZnRlciBzb21lIHRpbWUgcGVyaW9kLiBUaGlzIHJlZHVjZXMgc3luYyBlcnJvcnMsIGJ1dCBoYXMgc29tZSBvdmVyaGVhZCAob3B0aW9uYWwpXHJcbiAgI1xyXG4gIGluaXQ6IChvcHRpb25zKS0+XHJcbiAgICByZXEgPSAobmFtZSwgY2hvaWNlcyk9PlxyXG4gICAgICBpZiBvcHRpb25zW25hbWVdP1xyXG4gICAgICAgIGlmIChub3QgY2hvaWNlcz8pIG9yIGNob2ljZXMuc29tZSgoYyktPmMgaXMgb3B0aW9uc1tuYW1lXSlcclxuICAgICAgICAgIEBbbmFtZV0gPSBvcHRpb25zW25hbWVdXHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IGNhbiBzZXQgdGhlICdcIituYW1lK1wiJyBvcHRpb24gdG8gb25lIG9mIHRoZSBmb2xsb3dpbmcgY2hvaWNlczogXCIrSlNPTi5lbmNvZGUoY2hvaWNlcylcclxuICAgICAgZWxzZVxyXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBtdXN0IHNwZWNpZnkgXCIrbmFtZStcIiwgd2hlbiBpbml0aWFsaXppbmcgdGhlIENvbm5lY3RvciFcIlxyXG5cclxuICAgIHJlcSBcInN5bmNNZXRob2RcIiwgW1wic3luY0FsbFwiLCBcIm1hc3Rlci1zbGF2ZVwiXVxyXG4gICAgcmVxIFwicm9sZVwiLCBbXCJtYXN0ZXJcIiwgXCJzbGF2ZVwiXVxyXG4gICAgcmVxIFwidXNlcl9pZFwiXHJcbiAgICBAb25fdXNlcl9pZF9zZXQ/KEB1c2VyX2lkKVxyXG5cclxuICAgICMgd2hldGhlciB0byByZXNlbmQgdGhlIEhCIGFmdGVyIHNvbWUgdGltZSBwZXJpb2QuIFRoaXMgcmVkdWNlcyBzeW5jIGVycm9ycy5cclxuICAgICMgQnV0IHRoaXMgaXMgbm90IG5lY2Vzc2FyeSBpbiB0aGUgdGVzdC1jb25uZWN0b3JcclxuICAgIGlmIG9wdGlvbnMucGVyZm9ybV9zZW5kX2FnYWluP1xyXG4gICAgICBAcGVyZm9ybV9zZW5kX2FnYWluID0gb3B0aW9ucy5wZXJmb3JtX3NlbmRfYWdhaW5cclxuICAgIGVsc2VcclxuICAgICAgQHBlcmZvcm1fc2VuZF9hZ2FpbiA9IHRydWVcclxuXHJcbiAgICAjIEEgTWFzdGVyIHNob3VsZCBzeW5jIHdpdGggZXZlcnlvbmUhIFRPRE86IHJlYWxseT8gLSBmb3Igbm93IGl0cyBzYWZlciB0aGlzIHdheSFcclxuICAgIGlmIEByb2xlIGlzIFwibWFzdGVyXCJcclxuICAgICAgQHN5bmNNZXRob2QgPSBcInN5bmNBbGxcIlxyXG5cclxuICAgICMgaXMgc2V0IHRvIHRydWUgd2hlbiB0aGlzIGlzIHN5bmNlZCB3aXRoIGFsbCBvdGhlciBjb25uZWN0aW9uc1xyXG4gICAgQGlzX3N5bmNlZCA9IGZhbHNlXHJcbiAgICAjIFBlZXJqcyBDb25uZWN0aW9uczoga2V5OiBjb25uLWlkLCB2YWx1ZTogb2JqZWN0XHJcbiAgICBAY29ubmVjdGlvbnMgPSB7fVxyXG4gICAgIyBMaXN0IG9mIGZ1bmN0aW9ucyB0aGF0IHNoYWxsIHByb2Nlc3MgaW5jb21pbmcgZGF0YVxyXG4gICAgQHJlY2VpdmVfaGFuZGxlcnMgPz0gW11cclxuXHJcbiAgICAjIHdoZXRoZXIgdGhpcyBpbnN0YW5jZSBpcyBib3VuZCB0byBhbnkgeSBpbnN0YW5jZVxyXG4gICAgQGNvbm5lY3Rpb25zID0ge31cclxuICAgIEBjdXJyZW50X3N5bmNfdGFyZ2V0ID0gbnVsbFxyXG4gICAgQHNlbnRfaGJfdG9fYWxsX3VzZXJzID0gZmFsc2VcclxuICAgIEBpc19pbml0aWFsaXplZCA9IHRydWVcclxuXHJcbiAgaXNSb2xlTWFzdGVyOiAtPlxyXG4gICAgQHJvbGUgaXMgXCJtYXN0ZXJcIlxyXG5cclxuICBpc1JvbGVTbGF2ZTogLT5cclxuICAgIEByb2xlIGlzIFwic2xhdmVcIlxyXG5cclxuICBmaW5kTmV3U3luY1RhcmdldDogKCktPlxyXG4gICAgQGN1cnJlbnRfc3luY190YXJnZXQgPSBudWxsXHJcbiAgICBpZiBAc3luY01ldGhvZCBpcyBcInN5bmNBbGxcIlxyXG4gICAgICBmb3IgdXNlciwgYyBvZiBAY29ubmVjdGlvbnNcclxuICAgICAgICBpZiBub3QgYy5pc19zeW5jZWRcclxuICAgICAgICAgIEBwZXJmb3JtU3luYyB1c2VyXHJcbiAgICAgICAgICBicmVha1xyXG4gICAgaWYgbm90IEBjdXJyZW50X3N5bmNfdGFyZ2V0P1xyXG4gICAgICBAc2V0U3RhdGVTeW5jZWQoKVxyXG4gICAgbnVsbFxyXG5cclxuICB1c2VyTGVmdDogKHVzZXIpLT5cclxuICAgIGRlbGV0ZSBAY29ubmVjdGlvbnNbdXNlcl1cclxuICAgIEBmaW5kTmV3U3luY1RhcmdldCgpXHJcblxyXG4gIHVzZXJKb2luZWQ6ICh1c2VyLCByb2xlKS0+XHJcbiAgICBpZiBub3Qgcm9sZT9cclxuICAgICAgdGhyb3cgbmV3IEVycm9yIFwiSW50ZXJuYWw6IFlvdSBtdXN0IHNwZWNpZnkgdGhlIHJvbGUgb2YgdGhlIGpvaW5lZCB1c2VyISBFLmcuIHVzZXJKb2luZWQoJ3VpZDozOTM5Jywnc2xhdmUnKVwiXHJcbiAgICAjIGEgdXNlciBqb2luZWQgdGhlIHJvb21cclxuICAgIEBjb25uZWN0aW9uc1t1c2VyXSA/PSB7fVxyXG4gICAgQGNvbm5lY3Rpb25zW3VzZXJdLmlzX3N5bmNlZCA9IGZhbHNlXHJcblxyXG4gICAgaWYgKG5vdCBAaXNfc3luY2VkKSBvciBAc3luY01ldGhvZCBpcyBcInN5bmNBbGxcIlxyXG4gICAgICBpZiBAc3luY01ldGhvZCBpcyBcInN5bmNBbGxcIlxyXG4gICAgICAgIEBwZXJmb3JtU3luYyB1c2VyXHJcbiAgICAgIGVsc2UgaWYgcm9sZSBpcyBcIm1hc3RlclwiXHJcbiAgICAgICAgIyBUT0RPOiBXaGF0IGlmIHRoZXJlIGFyZSB0d28gbWFzdGVycz8gUHJldmVudCBzZW5kaW5nIGV2ZXJ5dGhpbmcgdHdvIHRpbWVzIVxyXG4gICAgICAgIEBwZXJmb3JtU3luY1dpdGhNYXN0ZXIgdXNlclxyXG5cclxuXHJcbiAgI1xyXG4gICMgRXhlY3V0ZSBhIGZ1bmN0aW9uIF93aGVuXyB3ZSBhcmUgY29ubmVjdGVkLiBJZiBub3QgY29ubmVjdGVkLCB3YWl0IHVudGlsIGNvbm5lY3RlZC5cclxuICAjIEBwYXJhbSBmIHtGdW5jdGlvbn0gV2lsbCBiZSBleGVjdXRlZCBvbiB0aGUgUGVlckpzLUNvbm5lY3RvciBjb250ZXh0LlxyXG4gICNcclxuICB3aGVuU3luY2VkOiAoYXJncyktPlxyXG4gICAgaWYgYXJncy5jb25zdHJ1Y3RvcmUgaXMgRnVuY3Rpb25cclxuICAgICAgYXJncyA9IFthcmdzXVxyXG4gICAgaWYgQGlzX3N5bmNlZFxyXG4gICAgICBhcmdzWzBdLmFwcGx5IHRoaXMsIGFyZ3NbMS4uXVxyXG4gICAgZWxzZVxyXG4gICAgICBAY29tcHV0ZV93aGVuX3N5bmNlZCA/PSBbXVxyXG4gICAgICBAY29tcHV0ZV93aGVuX3N5bmNlZC5wdXNoIGFyZ3NcclxuXHJcbiAgI1xyXG4gICMgRXhlY3V0ZSBhbiBmdW5jdGlvbiB3aGVuIGEgbWVzc2FnZSBpcyByZWNlaXZlZC5cclxuICAjIEBwYXJhbSBmIHtGdW5jdGlvbn0gV2lsbCBiZSBleGVjdXRlZCBvbiB0aGUgUGVlckpzLUNvbm5lY3RvciBjb250ZXh0LiBmIHdpbGwgYmUgY2FsbGVkIHdpdGggKHNlbmRlcl9pZCwgYnJvYWRjYXN0IHt0cnVlfGZhbHNlfSwgbWVzc2FnZSkuXHJcbiAgI1xyXG4gIG9uUmVjZWl2ZTogKGYpLT5cclxuICAgIEByZWNlaXZlX2hhbmRsZXJzLnB1c2ggZlxyXG5cclxuICAjIyNcclxuICAjIEJyb2FkY2FzdCBhIG1lc3NhZ2UgdG8gYWxsIGNvbm5lY3RlZCBwZWVycy5cclxuICAjIEBwYXJhbSBtZXNzYWdlIHtPYmplY3R9IFRoZSBtZXNzYWdlIHRvIGJyb2FkY2FzdC5cclxuICAjXHJcbiAgYnJvYWRjYXN0OiAobWVzc2FnZSktPlxyXG4gICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3QgaW1wbGVtZW50IGJyb2FkY2FzdCFcIlxyXG5cclxuICAjXHJcbiAgIyBTZW5kIGEgbWVzc2FnZSB0byBhIHBlZXIsIG9yIHNldCBvZiBwZWVyc1xyXG4gICNcclxuICBzZW5kOiAocGVlcl9zLCBtZXNzYWdlKS0+XHJcbiAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBpbXBsZW1lbnQgc2VuZCFcIlxyXG4gICMjI1xyXG5cclxuICAjXHJcbiAgIyBwZXJmb3JtIGEgc3luYyB3aXRoIGEgc3BlY2lmaWMgdXNlci5cclxuICAjXHJcbiAgcGVyZm9ybVN5bmM6ICh1c2VyKS0+XHJcbiAgICBpZiBub3QgQGN1cnJlbnRfc3luY190YXJnZXQ/XHJcbiAgICAgIEBjdXJyZW50X3N5bmNfdGFyZ2V0ID0gdXNlclxyXG4gICAgICBAc2VuZCB1c2VyLFxyXG4gICAgICAgIHN5bmNfc3RlcDogXCJnZXRIQlwiXHJcbiAgICAgICAgc2VuZF9hZ2FpbjogXCJ0cnVlXCJcclxuICAgICAgICBkYXRhOiBbXSAjIEBnZXRTdGF0ZVZlY3RvcigpXHJcbiAgICAgIGlmIG5vdCBAc2VudF9oYl90b19hbGxfdXNlcnNcclxuICAgICAgICBAc2VudF9oYl90b19hbGxfdXNlcnMgPSB0cnVlXHJcblxyXG4gICAgICAgIGhiID0gQGdldEhCKFtdKS5oYlxyXG4gICAgICAgIF9oYiA9IFtdXHJcbiAgICAgICAgZm9yIG8gaW4gaGJcclxuICAgICAgICAgIF9oYi5wdXNoIG9cclxuICAgICAgICAgIGlmIF9oYi5sZW5ndGggPiAxMFxyXG4gICAgICAgICAgICBAYnJvYWRjYXN0XHJcbiAgICAgICAgICAgICAgc3luY19zdGVwOiBcImFwcGx5SEJfXCJcclxuICAgICAgICAgICAgICBkYXRhOiBfaGJcclxuICAgICAgICAgICAgX2hiID0gW11cclxuICAgICAgICBAYnJvYWRjYXN0XHJcbiAgICAgICAgICBzeW5jX3N0ZXA6IFwiYXBwbHlIQlwiXHJcbiAgICAgICAgICBkYXRhOiBfaGJcclxuXHJcblxyXG5cclxuICAjXHJcbiAgIyBXaGVuIGEgbWFzdGVyIG5vZGUgam9pbmVkIHRoZSByb29tLCBwZXJmb3JtIHRoaXMgc3luYyB3aXRoIGhpbS4gSXQgd2lsbCBhc2sgdGhlIG1hc3RlciBmb3IgdGhlIEhCLFxyXG4gICMgYW5kIHdpbGwgYnJvYWRjYXN0IGhpcyBvd24gSEJcclxuICAjXHJcbiAgcGVyZm9ybVN5bmNXaXRoTWFzdGVyOiAodXNlciktPlxyXG4gICAgQGN1cnJlbnRfc3luY190YXJnZXQgPSB1c2VyXHJcbiAgICBAc2VuZCB1c2VyLFxyXG4gICAgICBzeW5jX3N0ZXA6IFwiZ2V0SEJcIlxyXG4gICAgICBzZW5kX2FnYWluOiBcInRydWVcIlxyXG4gICAgICBkYXRhOiBbXVxyXG4gICAgaGIgPSBAZ2V0SEIoW10pLmhiXHJcbiAgICBfaGIgPSBbXVxyXG4gICAgZm9yIG8gaW4gaGJcclxuICAgICAgX2hiLnB1c2ggb1xyXG4gICAgICBpZiBfaGIubGVuZ3RoID4gMTBcclxuICAgICAgICBAYnJvYWRjYXN0XHJcbiAgICAgICAgICBzeW5jX3N0ZXA6IFwiYXBwbHlIQl9cIlxyXG4gICAgICAgICAgZGF0YTogX2hiXHJcbiAgICAgICAgX2hiID0gW11cclxuICAgIEBicm9hZGNhc3RcclxuICAgICAgc3luY19zdGVwOiBcImFwcGx5SEJcIlxyXG4gICAgICBkYXRhOiBfaGJcclxuXHJcbiAgI1xyXG4gICMgWW91IGFyZSBzdXJlIHRoYXQgYWxsIGNsaWVudHMgYXJlIHN5bmNlZCwgY2FsbCB0aGlzIGZ1bmN0aW9uLlxyXG4gICNcclxuICBzZXRTdGF0ZVN5bmNlZDogKCktPlxyXG4gICAgaWYgbm90IEBpc19zeW5jZWRcclxuICAgICAgQGlzX3N5bmNlZCA9IHRydWVcclxuICAgICAgaWYgQGNvbXB1dGVfd2hlbl9zeW5jZWQ/XHJcbiAgICAgICAgZm9yIGYgaW4gQGNvbXB1dGVfd2hlbl9zeW5jZWRcclxuICAgICAgICAgIGYoKVxyXG4gICAgICAgIGRlbGV0ZSBAY29tcHV0ZV93aGVuX3N5bmNlZFxyXG4gICAgICBudWxsXHJcblxyXG4gICNcclxuICAjIFlvdSByZWNlaXZlZCBhIHJhdyBtZXNzYWdlLCBhbmQgeW91IGtub3cgdGhhdCBpdCBpcyBpbnRlbmRlZCBmb3IgdG8gWWpzLiBUaGVuIGNhbGwgdGhpcyBmdW5jdGlvbi5cclxuICAjXHJcbiAgcmVjZWl2ZU1lc3NhZ2U6IChzZW5kZXIsIHJlcyktPlxyXG4gICAgaWYgbm90IHJlcy5zeW5jX3N0ZXA/XHJcbiAgICAgIGZvciBmIGluIEByZWNlaXZlX2hhbmRsZXJzXHJcbiAgICAgICAgZiBzZW5kZXIsIHJlc1xyXG4gICAgZWxzZVxyXG4gICAgICBpZiBzZW5kZXIgaXMgQHVzZXJfaWRcclxuICAgICAgICByZXR1cm5cclxuICAgICAgaWYgcmVzLnN5bmNfc3RlcCBpcyBcImdldEhCXCJcclxuICAgICAgICBkYXRhID0gQGdldEhCKHJlcy5kYXRhKVxyXG4gICAgICAgIGhiID0gZGF0YS5oYlxyXG4gICAgICAgIF9oYiA9IFtdXHJcbiAgICAgICAgIyBhbHdheXMgYnJvYWRjYXN0LCB3aGVuIG5vdCBzeW5jZWQuXHJcbiAgICAgICAgIyBUaGlzIHJlZHVjZXMgZXJyb3JzLCB3aGVuIHRoZSBjbGllbnRzIGdvZXMgb2ZmbGluZSBwcmVtYXR1cmVseS5cclxuICAgICAgICAjIFdoZW4gdGhpcyBjbGllbnQgb25seSBzeW5jcyB0byBvbmUgb3RoZXIgY2xpZW50cywgYnV0IGxvb3NlcyBjb25uZWN0b3JzLFxyXG4gICAgICAgICMgYmVmb3JlIHN5bmNpbmcgdG8gdGhlIG90aGVyIGNsaWVudHMsIHRoZSBvbmxpbmUgY2xpZW50cyBoYXZlIGRpZmZlcmVudCBzdGF0ZXMuXHJcbiAgICAgICAgIyBTaW5jZSB3ZSBkbyBub3Qgd2FudCB0byBwZXJmb3JtIHJlZ3VsYXIgc3luY3MsIHRoaXMgaXMgYSBnb29kIGFsdGVybmF0aXZlXHJcbiAgICAgICAgaWYgQGlzX3N5bmNlZFxyXG4gICAgICAgICAgc2VuZEFwcGx5SEIgPSAobSk9PlxyXG4gICAgICAgICAgICBAc2VuZCBzZW5kZXIsIG1cclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICBzZW5kQXBwbHlIQiA9IChtKT0+XHJcbiAgICAgICAgICAgIEBicm9hZGNhc3QgbVxyXG5cclxuICAgICAgICBmb3IgbyBpbiBoYlxyXG4gICAgICAgICAgX2hiLnB1c2ggb1xyXG4gICAgICAgICAgaWYgX2hiLmxlbmd0aCA+IDEwXHJcbiAgICAgICAgICAgIHNlbmRBcHBseUhCXHJcbiAgICAgICAgICAgICAgc3luY19zdGVwOiBcImFwcGx5SEJfXCJcclxuICAgICAgICAgICAgICBkYXRhOiBfaGJcclxuICAgICAgICAgICAgX2hiID0gW11cclxuXHJcbiAgICAgICAgc2VuZEFwcGx5SEJcclxuICAgICAgICAgIHN5bmNfc3RlcCA6IFwiYXBwbHlIQlwiXHJcbiAgICAgICAgICBkYXRhOiBfaGJcclxuXHJcbiAgICAgICAgaWYgcmVzLnNlbmRfYWdhaW4/IGFuZCBAcGVyZm9ybV9zZW5kX2FnYWluXHJcbiAgICAgICAgICBzZW5kX2FnYWluID0gZG8gKHN2ID0gZGF0YS5zdGF0ZV92ZWN0b3IpPT5cclxuICAgICAgICAgICAgKCk9PlxyXG4gICAgICAgICAgICAgIGhiID0gQGdldEhCKHN2KS5oYlxyXG4gICAgICAgICAgICAgIEBzZW5kIHNlbmRlcixcclxuICAgICAgICAgICAgICAgIHN5bmNfc3RlcDogXCJhcHBseUhCXCIsXHJcbiAgICAgICAgICAgICAgICBkYXRhOiBoYlxyXG4gICAgICAgICAgICAgICAgc2VudF9hZ2FpbjogXCJ0cnVlXCJcclxuICAgICAgICAgIHNldFRpbWVvdXQgc2VuZF9hZ2FpbiwgMzAwMFxyXG4gICAgICBlbHNlIGlmIHJlcy5zeW5jX3N0ZXAgaXMgXCJhcHBseUhCXCJcclxuICAgICAgICBAYXBwbHlIQihyZXMuZGF0YSwgc2VuZGVyIGlzIEBjdXJyZW50X3N5bmNfdGFyZ2V0KVxyXG5cclxuICAgICAgICBpZiAoQHN5bmNNZXRob2QgaXMgXCJzeW5jQWxsXCIgb3IgcmVzLnNlbnRfYWdhaW4/KSBhbmQgKG5vdCBAaXNfc3luY2VkKSBhbmQgKChAY3VycmVudF9zeW5jX3RhcmdldCBpcyBzZW5kZXIpIG9yIChub3QgQGN1cnJlbnRfc3luY190YXJnZXQ/KSlcclxuICAgICAgICAgIEBjb25uZWN0aW9uc1tzZW5kZXJdLmlzX3N5bmNlZCA9IHRydWVcclxuICAgICAgICAgIEBmaW5kTmV3U3luY1RhcmdldCgpXHJcblxyXG4gICAgICBlbHNlIGlmIHJlcy5zeW5jX3N0ZXAgaXMgXCJhcHBseUhCX1wiXHJcbiAgICAgICAgQGFwcGx5SEIocmVzLmRhdGEsIHNlbmRlciBpcyBAY3VycmVudF9zeW5jX3RhcmdldClcclxuXHJcblxyXG4gICMgQ3VycmVudGx5LCB0aGUgSEIgZW5jb2RlcyBvcGVyYXRpb25zIGFzIEpTT04uIEZvciB0aGUgbW9tZW50IEkgd2FudCB0byBrZWVwIGl0XHJcbiAgIyB0aGF0IHdheS4gTWF5YmUgd2Ugc3VwcG9ydCBlbmNvZGluZyBpbiB0aGUgSEIgYXMgWE1MIGluIHRoZSBmdXR1cmUsIGJ1dCBmb3Igbm93IEkgZG9uJ3Qgd2FudFxyXG4gICMgdG9vIG11Y2ggb3ZlcmhlYWQuIFkgaXMgdmVyeSBsaWtlbHkgdG8gZ2V0IGNoYW5nZWQgYSBsb3QgaW4gdGhlIGZ1dHVyZVxyXG4gICNcclxuICAjIEJlY2F1c2Ugd2UgZG9uJ3Qgd2FudCB0byBlbmNvZGUgSlNPTiBhcyBzdHJpbmcgKHdpdGggY2hhcmFjdGVyIGVzY2FwaW5nLCB3aWNoIG1ha2VzIGl0IHByZXR0eSBtdWNoIHVucmVhZGFibGUpXHJcbiAgIyB3ZSBlbmNvZGUgdGhlIEpTT04gYXMgWE1MLlxyXG4gICNcclxuICAjIFdoZW4gdGhlIEhCIHN1cHBvcnQgZW5jb2RpbmcgYXMgWE1MLCB0aGUgZm9ybWF0IHNob3VsZCBsb29rIHByZXR0eSBtdWNoIGxpa2UgdGhpcy5cclxuXHJcbiAgIyBkb2VzIG5vdCBzdXBwb3J0IHByaW1pdGl2ZSB2YWx1ZXMgYXMgYXJyYXkgZWxlbWVudHNcclxuICAjIGV4cGVjdHMgYW4gbHR4IChsZXNzIHRoYW4geG1sKSBvYmplY3RcclxuICBwYXJzZU1lc3NhZ2VGcm9tWG1sOiAobSktPlxyXG4gICAgcGFyc2VfYXJyYXkgPSAobm9kZSktPlxyXG4gICAgICBmb3IgbiBpbiBub2RlLmNoaWxkcmVuXHJcbiAgICAgICAgaWYgbi5nZXRBdHRyaWJ1dGUoXCJpc0FycmF5XCIpIGlzIFwidHJ1ZVwiXHJcbiAgICAgICAgICBwYXJzZV9hcnJheSBuXHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgcGFyc2Vfb2JqZWN0IG5cclxuXHJcbiAgICBwYXJzZV9vYmplY3QgPSAobm9kZSktPlxyXG4gICAgICBqc29uID0ge31cclxuICAgICAgZm9yIG5hbWUsIHZhbHVlICBvZiBub2RlLmF0dHJzXHJcbiAgICAgICAgaW50ID0gcGFyc2VJbnQodmFsdWUpXHJcbiAgICAgICAgaWYgaXNOYU4oaW50KSBvciAoXCJcIitpbnQpIGlzbnQgdmFsdWVcclxuICAgICAgICAgIGpzb25bbmFtZV0gPSB2YWx1ZVxyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgIGpzb25bbmFtZV0gPSBpbnRcclxuICAgICAgZm9yIG4gaW4gbm9kZS5jaGlsZHJlblxyXG4gICAgICAgIG5hbWUgPSBuLm5hbWVcclxuICAgICAgICBpZiBuLmdldEF0dHJpYnV0ZShcImlzQXJyYXlcIikgaXMgXCJ0cnVlXCJcclxuICAgICAgICAgIGpzb25bbmFtZV0gPSBwYXJzZV9hcnJheSBuXHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAganNvbltuYW1lXSA9IHBhcnNlX29iamVjdCBuXHJcbiAgICAgIGpzb25cclxuICAgIHBhcnNlX29iamVjdCBtXHJcblxyXG4gICMgZW5jb2RlIG1lc3NhZ2UgaW4geG1sXHJcbiAgIyB3ZSB1c2Ugc3RyaW5nIGJlY2F1c2UgU3Ryb3BoZSBvbmx5IGFjY2VwdHMgYW4gXCJ4bWwtc3RyaW5nXCIuLlxyXG4gICMgU28ge2E6NCxiOntjOjV9fSB3aWxsIGxvb2sgbGlrZVxyXG4gICMgPHkgYT1cIjRcIj5cclxuICAjICAgPGIgYz1cIjVcIj48L2I+XHJcbiAgIyA8L3k+XHJcbiAgIyBtIC0gbHR4IGVsZW1lbnRcclxuICAjIGpzb24gLSBndWVzcyBpdCA7KVxyXG4gICNcclxuICBlbmNvZGVNZXNzYWdlVG9YbWw6IChtLCBqc29uKS0+XHJcbiAgICAjIGF0dHJpYnV0ZXMgaXMgb3B0aW9uYWxcclxuICAgIGVuY29kZV9vYmplY3QgPSAobSwganNvbiktPlxyXG4gICAgICBmb3IgbmFtZSx2YWx1ZSBvZiBqc29uXHJcbiAgICAgICAgaWYgbm90IHZhbHVlP1xyXG4gICAgICAgICAgIyBub3BcclxuICAgICAgICBlbHNlIGlmIHZhbHVlLmNvbnN0cnVjdG9yIGlzIE9iamVjdFxyXG4gICAgICAgICAgZW5jb2RlX29iamVjdCBtLmMobmFtZSksIHZhbHVlXHJcbiAgICAgICAgZWxzZSBpZiB2YWx1ZS5jb25zdHJ1Y3RvciBpcyBBcnJheVxyXG4gICAgICAgICAgZW5jb2RlX2FycmF5IG0uYyhuYW1lKSwgdmFsdWVcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICBtLnNldEF0dHJpYnV0ZShuYW1lLHZhbHVlKVxyXG4gICAgICBtXHJcbiAgICBlbmNvZGVfYXJyYXkgPSAobSwgYXJyYXkpLT5cclxuICAgICAgbS5zZXRBdHRyaWJ1dGUoXCJpc0FycmF5XCIsXCJ0cnVlXCIpXHJcbiAgICAgIGZvciBlIGluIGFycmF5XHJcbiAgICAgICAgaWYgZS5jb25zdHJ1Y3RvciBpcyBPYmplY3RcclxuICAgICAgICAgIGVuY29kZV9vYmplY3QgbS5jKFwiYXJyYXktZWxlbWVudFwiKSwgZVxyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgIGVuY29kZV9hcnJheSBtLmMoXCJhcnJheS1lbGVtZW50XCIpLCBlXHJcbiAgICAgIG1cclxuICAgIGlmIGpzb24uY29uc3RydWN0b3IgaXMgT2JqZWN0XHJcbiAgICAgIGVuY29kZV9vYmplY3QgbS5jKFwieVwiLHt4bWxuczpcImh0dHA6Ly95Lm5pbmphL2Nvbm5lY3Rvci1zdGFuemFcIn0pLCBqc29uXHJcbiAgICBlbHNlIGlmIGpzb24uY29uc3RydWN0b3IgaXMgQXJyYXlcclxuICAgICAgZW5jb2RlX2FycmF5IG0uYyhcInlcIix7eG1sbnM6XCJodHRwOi8veS5uaW5qYS9jb25uZWN0b3Itc3RhbnphXCJ9KSwganNvblxyXG4gICAgZWxzZVxyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJJIGNhbid0IGVuY29kZSB0aGlzIGpzb24hXCJcclxuXHJcbiAgc2V0SXNCb3VuZFRvWTogKCktPlxyXG4gICAgQG9uX2JvdW5kX3RvX3k/KClcclxuICAgIGRlbGV0ZSBAd2hlbl9ib3VuZF90b195XHJcbiAgICBAaXNfYm91bmRfdG9feSA9IHRydWVcclxuIiwiXHJcbndpbmRvdz8udW5wcm9jZXNzZWRfY291bnRlciA9IDAgIyBkZWwgdGhpc1xyXG53aW5kb3c/LnVucHJvY2Vzc2VkX2V4ZWNfY291bnRlciA9IDAgIyBUT0RPXHJcbndpbmRvdz8udW5wcm9jZXNzZWRfdHlwZXMgPSBbXVxyXG5cclxuI1xyXG4jIEBub2RvY1xyXG4jIFRoZSBFbmdpbmUgaGFuZGxlcyBob3cgYW5kIGluIHdoaWNoIG9yZGVyIHRvIGV4ZWN1dGUgb3BlcmF0aW9ucyBhbmQgYWRkIG9wZXJhdGlvbnMgdG8gdGhlIEhpc3RvcnlCdWZmZXIuXHJcbiNcclxuY2xhc3MgRW5naW5lXHJcblxyXG4gICNcclxuICAjIEBwYXJhbSB7SGlzdG9yeUJ1ZmZlcn0gSEJcclxuICAjIEBwYXJhbSB7T2JqZWN0fSB0eXBlcyBsaXN0IG9mIGF2YWlsYWJsZSB0eXBlc1xyXG4gICNcclxuICBjb25zdHJ1Y3RvcjogKEBIQiwgQHR5cGVzKS0+XHJcbiAgICBAdW5wcm9jZXNzZWRfb3BzID0gW11cclxuXHJcbiAgI1xyXG4gICMgUGFyc2VzIGFuIG9wZXJhdGlvIGZyb20gdGhlIGpzb24gZm9ybWF0LiBJdCB1c2VzIHRoZSBzcGVjaWZpZWQgcGFyc2VyIGluIHlvdXIgT3BlcmF0aW9uVHlwZSBtb2R1bGUuXHJcbiAgI1xyXG4gIHBhcnNlT3BlcmF0aW9uOiAoanNvbiktPlxyXG4gICAgdHlwZSA9IEB0eXBlc1tqc29uLnR5cGVdXHJcbiAgICBpZiB0eXBlPy5wYXJzZT9cclxuICAgICAgdHlwZS5wYXJzZSBqc29uXHJcbiAgICBlbHNlXHJcbiAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBmb3Jnb3QgdG8gc3BlY2lmeSBhIHBhcnNlciBmb3IgdHlwZSAje2pzb24udHlwZX0uIFRoZSBtZXNzYWdlIGlzICN7SlNPTi5zdHJpbmdpZnkganNvbn0uXCJcclxuXHJcblxyXG4gICNcclxuICAjIEFwcGx5IGEgc2V0IG9mIG9wZXJhdGlvbnMuIEUuZy4gdGhlIG9wZXJhdGlvbnMgeW91IHJlY2VpdmVkIGZyb20gYW5vdGhlciB1c2VycyBIQi5fZW5jb2RlKCkuXHJcbiAgIyBAbm90ZSBZb3UgbXVzdCBub3QgdXNlIHRoaXMgbWV0aG9kIHdoZW4geW91IGFscmVhZHkgaGF2ZSBvcHMgaW4geW91ciBIQiFcclxuICAjIyNcclxuICBhcHBseU9wc0J1bmRsZTogKG9wc19qc29uKS0+XHJcbiAgICBvcHMgPSBbXVxyXG4gICAgZm9yIG8gaW4gb3BzX2pzb25cclxuICAgICAgb3BzLnB1c2ggQHBhcnNlT3BlcmF0aW9uIG9cclxuICAgIGZvciBvIGluIG9wc1xyXG4gICAgICBpZiBub3Qgby5leGVjdXRlKClcclxuICAgICAgICBAdW5wcm9jZXNzZWRfb3BzLnB1c2ggb1xyXG4gICAgQHRyeVVucHJvY2Vzc2VkKClcclxuICAjIyNcclxuXHJcbiAgI1xyXG4gICMgU2FtZSBhcyBhcHBseU9wcyBidXQgb3BlcmF0aW9ucyB0aGF0IGFyZSBhbHJlYWR5IGluIHRoZSBIQiBhcmUgbm90IGFwcGxpZWQuXHJcbiAgIyBAc2VlIEVuZ2luZS5hcHBseU9wc1xyXG4gICNcclxuICBhcHBseU9wc0NoZWNrRG91YmxlOiAob3BzX2pzb24pLT5cclxuICAgIGZvciBvIGluIG9wc19qc29uXHJcbiAgICAgIGlmIG5vdCBASEIuZ2V0T3BlcmF0aW9uKG8udWlkKT9cclxuICAgICAgICBAYXBwbHlPcCBvXHJcblxyXG4gICNcclxuICAjIEFwcGx5IGEgc2V0IG9mIG9wZXJhdGlvbnMuIChIZWxwZXIgZm9yIHVzaW5nIGFwcGx5T3Agb24gQXJyYXlzKVxyXG4gICMgQHNlZSBFbmdpbmUuYXBwbHlPcFxyXG4gIGFwcGx5T3BzOiAob3BzX2pzb24pLT5cclxuICAgIEBhcHBseU9wIG9wc19qc29uXHJcblxyXG4gICNcclxuICAjIEFwcGx5IGFuIG9wZXJhdGlvbiB0aGF0IHlvdSByZWNlaXZlZCBmcm9tIGFub3RoZXIgcGVlci5cclxuICAjIFRPRE86IG1ha2UgdGhpcyBtb3JlIGVmZmljaWVudCEhXHJcbiAgIyAtIG9wZXJhdGlvbnMgbWF5IG9ubHkgZXhlY3V0ZWQgaW4gb3JkZXIgYnkgY3JlYXRvciwgb3JkZXIgdGhlbSBpbiBvYmplY3Qgb2YgYXJyYXlzIChrZXkgYnkgY3JlYXRvcilcclxuICAjIC0geW91IGNhbiBwcm9iYWJseSBtYWtlIHNvbWV0aGluZyBsaWtlIGRlcGVuZGVuY2llcyAoY3JlYXRvcjEgd2FpdHMgZm9yIGNyZWF0b3IyKVxyXG4gIGFwcGx5T3A6IChvcF9qc29uX2FycmF5LCBmcm9tSEIgPSBmYWxzZSktPlxyXG4gICAgaWYgb3BfanNvbl9hcnJheS5jb25zdHJ1Y3RvciBpc250IEFycmF5XHJcbiAgICAgIG9wX2pzb25fYXJyYXkgPSBbb3BfanNvbl9hcnJheV1cclxuICAgIGZvciBvcF9qc29uIGluIG9wX2pzb25fYXJyYXlcclxuICAgICAgaWYgZnJvbUhCXHJcbiAgICAgICAgb3BfanNvbi5mcm9tSEIgPSBcInRydWVcIiAjIGV4ZWN1dGUgaW1tZWRpYXRlbHksIGlmXHJcbiAgICAgICMgJHBhcnNlX2FuZF9leGVjdXRlIHdpbGwgcmV0dXJuIGZhbHNlIGlmICRvX2pzb24gd2FzIHBhcnNlZCBhbmQgZXhlY3V0ZWQsIG90aGVyd2lzZSB0aGUgcGFyc2VkIG9wZXJhZGlvblxyXG4gICAgICBvID0gQHBhcnNlT3BlcmF0aW9uIG9wX2pzb25cclxuICAgICAgby5wYXJzZWRfZnJvbV9qc29uID0gb3BfanNvblxyXG4gICAgICBpZiBvcF9qc29uLmZyb21IQj9cclxuICAgICAgICBvLmZyb21IQiA9IG9wX2pzb24uZnJvbUhCXHJcbiAgICAgICMgQEhCLmFkZE9wZXJhdGlvbiBvXHJcbiAgICAgIGlmIEBIQi5nZXRPcGVyYXRpb24obyk/XHJcbiAgICAgICAgIyBub3BcclxuICAgICAgZWxzZSBpZiAoKG5vdCBASEIuaXNFeHBlY3RlZE9wZXJhdGlvbihvKSkgYW5kIChub3Qgby5mcm9tSEI/KSkgb3IgKG5vdCBvLmV4ZWN1dGUoKSlcclxuICAgICAgICBAdW5wcm9jZXNzZWRfb3BzLnB1c2ggb1xyXG4gICAgICAgIHdpbmRvdz8udW5wcm9jZXNzZWRfdHlwZXMucHVzaCBvLnR5cGUgIyBUT0RPOiBkZWxldGUgdGhpc1xyXG4gICAgQHRyeVVucHJvY2Vzc2VkKClcclxuXHJcbiAgI1xyXG4gICMgQ2FsbCB0aGlzIG1ldGhvZCB3aGVuIHlvdSBhcHBsaWVkIGEgbmV3IG9wZXJhdGlvbi5cclxuICAjIEl0IGNoZWNrcyBpZiBvcGVyYXRpb25zIHRoYXQgd2VyZSBwcmV2aW91c2x5IG5vdCBleGVjdXRhYmxlIGFyZSBub3cgZXhlY3V0YWJsZS5cclxuICAjXHJcbiAgdHJ5VW5wcm9jZXNzZWQ6ICgpLT5cclxuICAgIHdoaWxlIHRydWVcclxuICAgICAgb2xkX2xlbmd0aCA9IEB1bnByb2Nlc3NlZF9vcHMubGVuZ3RoXHJcbiAgICAgIHVucHJvY2Vzc2VkID0gW11cclxuICAgICAgZm9yIG9wIGluIEB1bnByb2Nlc3NlZF9vcHNcclxuICAgICAgICBpZiBASEIuZ2V0T3BlcmF0aW9uKG9wKT9cclxuICAgICAgICAgICMgbm9wXHJcbiAgICAgICAgZWxzZSBpZiAobm90IEBIQi5pc0V4cGVjdGVkT3BlcmF0aW9uKG9wKSBhbmQgKG5vdCBvcC5mcm9tSEI/KSkgb3IgKG5vdCBvcC5leGVjdXRlKCkpXHJcbiAgICAgICAgICB1bnByb2Nlc3NlZC5wdXNoIG9wXHJcbiAgICAgIEB1bnByb2Nlc3NlZF9vcHMgPSB1bnByb2Nlc3NlZFxyXG4gICAgICBpZiBAdW5wcm9jZXNzZWRfb3BzLmxlbmd0aCBpcyBvbGRfbGVuZ3RoXHJcbiAgICAgICAgYnJlYWtcclxuICAgIGlmIEB1bnByb2Nlc3NlZF9vcHMubGVuZ3RoIGlzbnQgMFxyXG4gICAgICBASEIuaW52b2tlU3luYygpXHJcblxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBFbmdpbmVcclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuIiwiXHJcbiNcclxuIyBAbm9kb2NcclxuIyBBbiBvYmplY3QgdGhhdCBob2xkcyBhbGwgYXBwbGllZCBvcGVyYXRpb25zLlxyXG4jXHJcbiMgQG5vdGUgVGhlIEhpc3RvcnlCdWZmZXIgaXMgY29tbW9ubHkgYWJicmV2aWF0ZWQgdG8gSEIuXHJcbiNcclxuY2xhc3MgSGlzdG9yeUJ1ZmZlclxyXG5cclxuICAjXHJcbiAgIyBDcmVhdGVzIGFuIGVtcHR5IEhCLlxyXG4gICMgQHBhcmFtIHtPYmplY3R9IHVzZXJfaWQgQ3JlYXRvciBvZiB0aGUgSEIuXHJcbiAgI1xyXG4gIGNvbnN0cnVjdG9yOiAoQHVzZXJfaWQpLT5cclxuICAgIEBvcGVyYXRpb25fY291bnRlciA9IHt9XHJcbiAgICBAYnVmZmVyID0ge31cclxuICAgIEBjaGFuZ2VfbGlzdGVuZXJzID0gW11cclxuICAgIEBnYXJiYWdlID0gW10gIyBXaWxsIGJlIGNsZWFuZWQgb24gbmV4dCBjYWxsIG9mIGdhcmJhZ2VDb2xsZWN0b3JcclxuICAgIEB0cmFzaCA9IFtdICMgSXMgZGVsZXRlZC4gV2FpdCB1bnRpbCBpdCBpcyBub3QgdXNlZCBhbnltb3JlLlxyXG4gICAgQHBlcmZvcm1HYXJiYWdlQ29sbGVjdGlvbiA9IHRydWVcclxuICAgIEBnYXJiYWdlQ29sbGVjdFRpbWVvdXQgPSAzMDAwMFxyXG4gICAgQHJlc2VydmVkX2lkZW50aWZpZXJfY291bnRlciA9IDBcclxuICAgIHNldFRpbWVvdXQgQGVtcHR5R2FyYmFnZSwgQGdhcmJhZ2VDb2xsZWN0VGltZW91dFxyXG5cclxuICByZXNldFVzZXJJZDogKGlkKS0+XHJcbiAgICBvd24gPSBAYnVmZmVyW0B1c2VyX2lkXVxyXG4gICAgaWYgb3duP1xyXG4gICAgICBmb3Igb19uYW1lLG8gb2Ygb3duXHJcbiAgICAgICAgaWYgby51aWQuY3JlYXRvcj9cclxuICAgICAgICAgIG8udWlkLmNyZWF0b3IgPSBpZFxyXG4gICAgICAgIGlmIG8udWlkLmFsdD9cclxuICAgICAgICAgIG8udWlkLmFsdC5jcmVhdG9yID0gaWRcclxuICAgICAgaWYgQGJ1ZmZlcltpZF0/XHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IGFyZSByZS1hc3NpZ25pbmcgYW4gb2xkIHVzZXIgaWQgLSB0aGlzIGlzIG5vdCAoeWV0KSBwb3NzaWJsZSFcIlxyXG4gICAgICBAYnVmZmVyW2lkXSA9IG93blxyXG4gICAgICBkZWxldGUgQGJ1ZmZlcltAdXNlcl9pZF1cclxuICAgIGlmIEBvcGVyYXRpb25fY291bnRlcltAdXNlcl9pZF0/XHJcbiAgICAgIEBvcGVyYXRpb25fY291bnRlcltpZF0gPSBAb3BlcmF0aW9uX2NvdW50ZXJbQHVzZXJfaWRdXHJcbiAgICAgIGRlbGV0ZSBAb3BlcmF0aW9uX2NvdW50ZXJbQHVzZXJfaWRdXHJcbiAgICBAdXNlcl9pZCA9IGlkXHJcblxyXG4gIGVtcHR5R2FyYmFnZTogKCk9PlxyXG4gICAgZm9yIG8gaW4gQGdhcmJhZ2VcclxuICAgICAgI2lmIEBnZXRPcGVyYXRpb25Db3VudGVyKG8udWlkLmNyZWF0b3IpID4gby51aWQub3BfbnVtYmVyXHJcbiAgICAgIG8uY2xlYW51cD8oKVxyXG5cclxuICAgIEBnYXJiYWdlID0gQHRyYXNoXHJcbiAgICBAdHJhc2ggPSBbXVxyXG4gICAgaWYgQGdhcmJhZ2VDb2xsZWN0VGltZW91dCBpc250IC0xXHJcbiAgICAgIEBnYXJiYWdlQ29sbGVjdFRpbWVvdXRJZCA9IHNldFRpbWVvdXQgQGVtcHR5R2FyYmFnZSwgQGdhcmJhZ2VDb2xsZWN0VGltZW91dFxyXG4gICAgdW5kZWZpbmVkXHJcblxyXG4gICNcclxuICAjIEdldCB0aGUgdXNlciBpZCB3aXRoIHdpY2ggdGhlIEhpc3RvcnkgQnVmZmVyIHdhcyBpbml0aWFsaXplZC5cclxuICAjXHJcbiAgZ2V0VXNlcklkOiAoKS0+XHJcbiAgICBAdXNlcl9pZFxyXG5cclxuICBhZGRUb0dhcmJhZ2VDb2xsZWN0b3I6ICgpLT5cclxuICAgIGlmIEBwZXJmb3JtR2FyYmFnZUNvbGxlY3Rpb25cclxuICAgICAgZm9yIG8gaW4gYXJndW1lbnRzXHJcbiAgICAgICAgaWYgbz9cclxuICAgICAgICAgIEBnYXJiYWdlLnB1c2ggb1xyXG5cclxuICBzdG9wR2FyYmFnZUNvbGxlY3Rpb246ICgpLT5cclxuICAgIEBwZXJmb3JtR2FyYmFnZUNvbGxlY3Rpb24gPSBmYWxzZVxyXG4gICAgQHNldE1hbnVhbEdhcmJhZ2VDb2xsZWN0KClcclxuICAgIEBnYXJiYWdlID0gW11cclxuICAgIEB0cmFzaCA9IFtdXHJcblxyXG4gIHNldE1hbnVhbEdhcmJhZ2VDb2xsZWN0OiAoKS0+XHJcbiAgICBAZ2FyYmFnZUNvbGxlY3RUaW1lb3V0ID0gLTFcclxuICAgIGNsZWFyVGltZW91dCBAZ2FyYmFnZUNvbGxlY3RUaW1lb3V0SWRcclxuICAgIEBnYXJiYWdlQ29sbGVjdFRpbWVvdXRJZCA9IHVuZGVmaW5lZFxyXG5cclxuICBzZXRHYXJiYWdlQ29sbGVjdFRpbWVvdXQ6IChAZ2FyYmFnZUNvbGxlY3RUaW1lb3V0KS0+XHJcblxyXG4gICNcclxuICAjIEkgcHJvcG9zZSB0byB1c2UgaXQgaW4geW91ciBGcmFtZXdvcmssIHRvIGNyZWF0ZSBzb21ldGhpbmcgbGlrZSBhIHJvb3QgZWxlbWVudC5cclxuICAjIEFuIG9wZXJhdGlvbiB3aXRoIHRoaXMgaWRlbnRpZmllciBpcyBub3QgcHJvcGFnYXRlZCB0byBvdGhlciBjbGllbnRzLlxyXG4gICMgVGhpcyBpcyB3aHkgZXZlcnlib2RlIG11c3QgY3JlYXRlIHRoZSBzYW1lIG9wZXJhdGlvbiB3aXRoIHRoaXMgdWlkLlxyXG4gICNcclxuICBnZXRSZXNlcnZlZFVuaXF1ZUlkZW50aWZpZXI6ICgpLT5cclxuICAgIHtcclxuICAgICAgY3JlYXRvciA6ICdfJ1xyXG4gICAgICBvcF9udW1iZXIgOiBcIl8je0ByZXNlcnZlZF9pZGVudGlmaWVyX2NvdW50ZXIrK31cIlxyXG4gICAgfVxyXG5cclxuICAjXHJcbiAgIyBHZXQgdGhlIG9wZXJhdGlvbiBjb3VudGVyIHRoYXQgZGVzY3JpYmVzIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBkb2N1bWVudC5cclxuICAjXHJcbiAgZ2V0T3BlcmF0aW9uQ291bnRlcjogKHVzZXJfaWQpLT5cclxuICAgIGlmIG5vdCB1c2VyX2lkP1xyXG4gICAgICByZXMgPSB7fVxyXG4gICAgICBmb3IgdXNlcixjdG4gb2YgQG9wZXJhdGlvbl9jb3VudGVyXHJcbiAgICAgICAgcmVzW3VzZXJdID0gY3RuXHJcbiAgICAgIHJlc1xyXG4gICAgZWxzZVxyXG4gICAgICBAb3BlcmF0aW9uX2NvdW50ZXJbdXNlcl9pZF1cclxuXHJcbiAgaXNFeHBlY3RlZE9wZXJhdGlvbjogKG8pLT5cclxuICAgIEBvcGVyYXRpb25fY291bnRlcltvLnVpZC5jcmVhdG9yXSA/PSAwXHJcbiAgICBvLnVpZC5vcF9udW1iZXIgPD0gQG9wZXJhdGlvbl9jb3VudGVyW28udWlkLmNyZWF0b3JdXHJcbiAgICB0cnVlICNUT0RPOiAhISB0aGlzIGNvdWxkIGJyZWFrIHN0dWZmLiBCdXQgSSBkdW5ubyB3aHlcclxuXHJcbiAgI1xyXG4gICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cclxuICAjIFRPRE86IE1ha2UgdGhpcyBtb3JlIGVmZmljaWVudCFcclxuICBfZW5jb2RlOiAoc3RhdGVfdmVjdG9yPXt9KS0+XHJcbiAgICBqc29uID0gW11cclxuICAgIHVua25vd24gPSAodXNlciwgb19udW1iZXIpLT5cclxuICAgICAgaWYgKG5vdCB1c2VyPykgb3IgKG5vdCBvX251bWJlcj8pXHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiZGFoIVwiXHJcbiAgICAgIG5vdCBzdGF0ZV92ZWN0b3JbdXNlcl0/IG9yIHN0YXRlX3ZlY3Rvclt1c2VyXSA8PSBvX251bWJlclxyXG5cclxuICAgIGZvciB1X25hbWUsdXNlciBvZiBAYnVmZmVyXHJcbiAgICAgICMgVE9ETyBuZXh0LCBpZiBAc3RhdGVfdmVjdG9yW3VzZXJdIDw9IHN0YXRlX3ZlY3Rvclt1c2VyXVxyXG4gICAgICBpZiB1X25hbWUgaXMgXCJfXCJcclxuICAgICAgICBjb250aW51ZVxyXG4gICAgICBmb3Igb19udW1iZXIsbyBvZiB1c2VyXHJcbiAgICAgICAgaWYgKG5vdCBvLnVpZC5ub09wZXJhdGlvbj8pIGFuZCB1bmtub3duKHVfbmFtZSwgb19udW1iZXIpXHJcbiAgICAgICAgICAjIGl0cyBuZWNlc3NhcnkgdG8gc2VuZCBpdCwgYW5kIG5vdCBrbm93biBpbiBzdGF0ZV92ZWN0b3JcclxuICAgICAgICAgIG9fanNvbiA9IG8uX2VuY29kZSgpXHJcbiAgICAgICAgICBpZiBvLm5leHRfY2w/ICMgYXBwbGllcyBmb3IgYWxsIG9wcyBidXQgdGhlIG1vc3QgcmlnaHQgZGVsaW1pdGVyIVxyXG4gICAgICAgICAgICAjIHNlYXJjaCBmb3IgdGhlIG5leHQgX2tub3duXyBvcGVyYXRpb24uIChXaGVuIHN0YXRlX3ZlY3RvciBpcyB7fSB0aGVuIHRoaXMgaXMgdGhlIERlbGltaXRlcilcclxuICAgICAgICAgICAgb19uZXh0ID0gby5uZXh0X2NsXHJcbiAgICAgICAgICAgIHdoaWxlIG9fbmV4dC5uZXh0X2NsPyBhbmQgdW5rbm93bihvX25leHQudWlkLmNyZWF0b3IsIG9fbmV4dC51aWQub3BfbnVtYmVyKVxyXG4gICAgICAgICAgICAgIG9fbmV4dCA9IG9fbmV4dC5uZXh0X2NsXHJcbiAgICAgICAgICAgIG9fanNvbi5uZXh0ID0gb19uZXh0LmdldFVpZCgpXHJcbiAgICAgICAgICBlbHNlIGlmIG8ucHJldl9jbD8gIyBtb3N0IHJpZ2h0IGRlbGltaXRlciBvbmx5IVxyXG4gICAgICAgICAgICAjIHNhbWUgYXMgdGhlIGFib3ZlIHdpdGggcHJldi5cclxuICAgICAgICAgICAgb19wcmV2ID0gby5wcmV2X2NsXHJcbiAgICAgICAgICAgIHdoaWxlIG9fcHJldi5wcmV2X2NsPyBhbmQgdW5rbm93bihvX3ByZXYudWlkLmNyZWF0b3IsIG9fcHJldi51aWQub3BfbnVtYmVyKVxyXG4gICAgICAgICAgICAgIG9fcHJldiA9IG9fcHJldi5wcmV2X2NsXHJcbiAgICAgICAgICAgIG9fanNvbi5wcmV2ID0gb19wcmV2LmdldFVpZCgpXHJcbiAgICAgICAgICBqc29uLnB1c2ggb19qc29uXHJcblxyXG4gICAganNvblxyXG5cclxuICAjXHJcbiAgIyBHZXQgdGhlIG51bWJlciBvZiBvcGVyYXRpb25zIHRoYXQgd2VyZSBjcmVhdGVkIGJ5IGEgdXNlci5cclxuICAjIEFjY29yZGluZ2x5IHlvdSB3aWxsIGdldCB0aGUgbmV4dCBvcGVyYXRpb24gbnVtYmVyIHRoYXQgaXMgZXhwZWN0ZWQgZnJvbSB0aGF0IHVzZXIuXHJcbiAgIyBUaGlzIHdpbGwgaW5jcmVtZW50IHRoZSBvcGVyYXRpb24gY291bnRlci5cclxuICAjXHJcbiAgZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXI6ICh1c2VyX2lkKS0+XHJcbiAgICBpZiBub3QgdXNlcl9pZD9cclxuICAgICAgdXNlcl9pZCA9IEB1c2VyX2lkXHJcbiAgICBpZiBub3QgQG9wZXJhdGlvbl9jb3VudGVyW3VzZXJfaWRdP1xyXG4gICAgICBAb3BlcmF0aW9uX2NvdW50ZXJbdXNlcl9pZF0gPSAwXHJcbiAgICB1aWQgPVxyXG4gICAgICAnY3JlYXRvcicgOiB1c2VyX2lkXHJcbiAgICAgICdvcF9udW1iZXInIDogQG9wZXJhdGlvbl9jb3VudGVyW3VzZXJfaWRdXHJcbiAgICBAb3BlcmF0aW9uX2NvdW50ZXJbdXNlcl9pZF0rK1xyXG4gICAgdWlkXHJcblxyXG4gICNcclxuICAjIFJldHJpZXZlIGFuIG9wZXJhdGlvbiBmcm9tIGEgdW5pcXVlIGlkLlxyXG4gICNcclxuICAjIHdoZW4gdWlkIGhhcyBhIFwic3ViXCIgcHJvcGVydHksIHRoZSB2YWx1ZSBvZiBpdCB3aWxsIGJlIGFwcGxpZWRcclxuICAjIG9uIHRoZSBvcGVyYXRpb25zIHJldHJpZXZlU3ViIG1ldGhvZCAod2hpY2ggbXVzdCEgYmUgZGVmaW5lZClcclxuICAjXHJcbiAgZ2V0T3BlcmF0aW9uOiAodWlkKS0+XHJcbiAgICBpZiB1aWQudWlkP1xyXG4gICAgICB1aWQgPSB1aWQudWlkXHJcbiAgICBvID0gQGJ1ZmZlclt1aWQuY3JlYXRvcl0/W3VpZC5vcF9udW1iZXJdXHJcbiAgICBpZiB1aWQuc3ViPyBhbmQgbz9cclxuICAgICAgby5yZXRyaWV2ZVN1YiB1aWQuc3ViXHJcbiAgICBlbHNlXHJcbiAgICAgIG9cclxuXHJcbiAgI1xyXG4gICMgQWRkIGFuIG9wZXJhdGlvbiB0byB0aGUgSEIuIE5vdGUgdGhhdCB0aGlzIHdpbGwgbm90IGxpbmsgaXQgYWdhaW5zdFxyXG4gICMgb3RoZXIgb3BlcmF0aW9ucyAoaXQgd29udCBleGVjdXRlZClcclxuICAjXHJcbiAgYWRkT3BlcmF0aW9uOiAobyktPlxyXG4gICAgaWYgbm90IEBidWZmZXJbby51aWQuY3JlYXRvcl0/XHJcbiAgICAgIEBidWZmZXJbby51aWQuY3JlYXRvcl0gPSB7fVxyXG4gICAgaWYgQGJ1ZmZlcltvLnVpZC5jcmVhdG9yXVtvLnVpZC5vcF9udW1iZXJdP1xyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBub3Qgb3ZlcndyaXRlIG9wZXJhdGlvbnMhXCJcclxuICAgIGlmIChvLnVpZC5vcF9udW1iZXIuY29uc3RydWN0b3IgaXNudCBTdHJpbmcpIGFuZCAobm90IEBpc0V4cGVjdGVkT3BlcmF0aW9uKG8pKSBhbmQgKG5vdCBvLmZyb21IQj8pICMgeW91IGFscmVhZHkgZG8gdGhpcyBpbiB0aGUgZW5naW5lLCBzbyBkZWxldGUgaXQgaGVyZSFcclxuICAgICAgdGhyb3cgbmV3IEVycm9yIFwidGhpcyBvcGVyYXRpb24gd2FzIG5vdCBleHBlY3RlZCFcIlxyXG4gICAgQGFkZFRvQ291bnRlcihvKVxyXG4gICAgQGJ1ZmZlcltvLnVpZC5jcmVhdG9yXVtvLnVpZC5vcF9udW1iZXJdID0gb1xyXG4gICAgb1xyXG5cclxuICByZW1vdmVPcGVyYXRpb246IChvKS0+XHJcbiAgICBkZWxldGUgQGJ1ZmZlcltvLnVpZC5jcmVhdG9yXT9bby51aWQub3BfbnVtYmVyXVxyXG5cclxuICAjIFdoZW4gdGhlIEhCIGRldGVybWluZXMgaW5jb25zaXN0ZW5jaWVzLCB0aGVuIHRoZSBpbnZva2VTeW5jXHJcbiAgIyBoYW5kbGVyIHdpbCBiZSBjYWxsZWQsIHdoaWNoIHNob3VsZCBzb21laG93IGludm9rZSB0aGUgc3luYyB3aXRoIGFub3RoZXIgY29sbGFib3JhdG9yLlxyXG4gICMgVGhlIHBhcmFtZXRlciBvZiB0aGUgc3luYyBoYW5kbGVyIGlzIHRoZSB1c2VyX2lkIHdpdGggd2ljaCBhbiBpbmNvbnNpc3RlbmN5IHdhcyBkZXRlcm1pbmVkXHJcbiAgc2V0SW52b2tlU3luY0hhbmRsZXI6IChmKS0+XHJcbiAgICBAaW52b2tlU3luYyA9IGZcclxuXHJcbiAgIyBlbXB0eSBwZXIgZGVmYXVsdCAjIFRPRE86IGRvIGkgbmVlZCB0aGlzP1xyXG4gIGludm9rZVN5bmM6ICgpLT5cclxuXHJcbiAgIyBhZnRlciB5b3UgcmVjZWl2ZWQgdGhlIEhCIG9mIGFub3RoZXIgdXNlciAoaW4gdGhlIHN5bmMgcHJvY2VzcyksXHJcbiAgIyB5b3UgcmVuZXcgeW91ciBvd24gc3RhdGVfdmVjdG9yIHRvIHRoZSBzdGF0ZV92ZWN0b3Igb2YgdGhlIG90aGVyIHVzZXJcclxuICByZW5ld1N0YXRlVmVjdG9yOiAoc3RhdGVfdmVjdG9yKS0+XHJcbiAgICBmb3IgdXNlcixzdGF0ZSBvZiBzdGF0ZV92ZWN0b3JcclxuICAgICAgaWYgKChub3QgQG9wZXJhdGlvbl9jb3VudGVyW3VzZXJdPykgb3IgKEBvcGVyYXRpb25fY291bnRlclt1c2VyXSA8IHN0YXRlX3ZlY3Rvclt1c2VyXSkpIGFuZCBzdGF0ZV92ZWN0b3JbdXNlcl0/XHJcbiAgICAgICAgQG9wZXJhdGlvbl9jb3VudGVyW3VzZXJdID0gc3RhdGVfdmVjdG9yW3VzZXJdXHJcblxyXG4gICNcclxuICAjIEluY3JlbWVudCB0aGUgb3BlcmF0aW9uX2NvdW50ZXIgdGhhdCBkZWZpbmVzIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBFbmdpbmUuXHJcbiAgI1xyXG4gIGFkZFRvQ291bnRlcjogKG8pLT5cclxuICAgIEBvcGVyYXRpb25fY291bnRlcltvLnVpZC5jcmVhdG9yXSA/PSAwXHJcbiAgICBpZiBvLnVpZC5jcmVhdG9yIGlzbnQgQGdldFVzZXJJZCgpXHJcbiAgICAgICMgVE9ETzogY2hlY2sgaWYgb3BlcmF0aW9ucyBhcmUgc2VuZCBpbiBvcmRlclxyXG4gICAgICBpZiBvLnVpZC5vcF9udW1iZXIgaXMgQG9wZXJhdGlvbl9jb3VudGVyW28udWlkLmNyZWF0b3JdXHJcbiAgICAgICAgQG9wZXJhdGlvbl9jb3VudGVyW28udWlkLmNyZWF0b3JdKytcclxuICAgICAgd2hpbGUgQGJ1ZmZlcltvLnVpZC5jcmVhdG9yXVtAb3BlcmF0aW9uX2NvdW50ZXJbby51aWQuY3JlYXRvcl1dP1xyXG4gICAgICAgIEBvcGVyYXRpb25fY291bnRlcltvLnVpZC5jcmVhdG9yXSsrXHJcbiAgICAgIHVuZGVmaW5lZFxyXG5cclxuICAgICNpZiBAb3BlcmF0aW9uX2NvdW50ZXJbby51aWQuY3JlYXRvcl0gaXNudCAoby51aWQub3BfbnVtYmVyICsgMSlcclxuICAgICAgI2NvbnNvbGUubG9nIChAb3BlcmF0aW9uX2NvdW50ZXJbby51aWQuY3JlYXRvcl0gLSAoby51aWQub3BfbnVtYmVyICsgMSkpXHJcbiAgICAgICNjb25zb2xlLmxvZyBvXHJcbiAgICAgICN0aHJvdyBuZXcgRXJyb3IgXCJZb3UgZG9uJ3QgcmVjZWl2ZSBvcGVyYXRpb25zIGluIHRoZSBwcm9wZXIgb3JkZXIuIFRyeSBjb3VudGluZyBsaWtlIHRoaXMgMCwxLDIsMyw0LC4uIDspXCJcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gSGlzdG9yeUJ1ZmZlclxyXG4iLCJcclxuY2xhc3MgWU9iamVjdFxyXG5cclxuICBjb25zdHJ1Y3RvcjogKEBfb2JqZWN0ID0ge30pLT5cclxuICAgIGlmIEBfb2JqZWN0LmNvbnN0cnVjdG9yIGlzIE9iamVjdFxyXG4gICAgICBmb3IgbmFtZSwgdmFsIG9mIEBfb2JqZWN0XHJcbiAgICAgICAgaWYgdmFsLmNvbnN0cnVjdG9yIGlzIE9iamVjdFxyXG4gICAgICAgICAgQF9vYmplY3RbbmFtZV0gPSBuZXcgWU9iamVjdCh2YWwpXHJcbiAgICBlbHNlXHJcbiAgICAgIHRocm93IG5ldyBFcnJvciBcIlkuT2JqZWN0IGFjY2VwdHMgSnNvbiBPYmplY3RzIG9ubHlcIlxyXG5cclxuICBfbmFtZTogXCJPYmplY3RcIlxyXG5cclxuICBfZ2V0TW9kZWw6ICh0eXBlcywgb3BzKS0+XHJcbiAgICBpZiBub3QgQF9tb2RlbD9cclxuICAgICAgQF9tb2RlbCA9IG5ldyBvcHMuTWFwTWFuYWdlcihAKS5leGVjdXRlKClcclxuICAgICAgZm9yIG4sbyBvZiBAX29iamVjdFxyXG4gICAgICAgIEBfbW9kZWwudmFsIG4sIG9cclxuICAgIGRlbGV0ZSBAX29iamVjdFxyXG4gICAgQF9tb2RlbFxyXG5cclxuICBfc2V0TW9kZWw6IChAX21vZGVsKS0+XHJcbiAgICBkZWxldGUgQF9vYmplY3RcclxuXHJcbiAgb2JzZXJ2ZTogKGYpLT5cclxuICAgIEBfbW9kZWwub2JzZXJ2ZSBmXHJcbiAgICBAXHJcblxyXG4gIHVub2JzZXJ2ZTogKGYpLT5cclxuICAgIEBfbW9kZWwudW5vYnNlcnZlIGZcclxuICAgIEBcclxuXHJcbiAgI1xyXG4gICMgQG92ZXJsb2FkIHZhbCgpXHJcbiAgIyAgIEdldCB0aGlzIGFzIGEgSnNvbiBvYmplY3QuXHJcbiAgIyAgIEByZXR1cm4gW0pzb25dXHJcbiAgI1xyXG4gICMgQG92ZXJsb2FkIHZhbChuYW1lKVxyXG4gICMgICBHZXQgdmFsdWUgb2YgYSBwcm9wZXJ0eS5cclxuICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgb2JqZWN0IHByb3BlcnR5LlxyXG4gICMgICBAcmV0dXJuIFtPYmplY3QgVHlwZXx8U3RyaW5nfE9iamVjdF0gRGVwZW5kaW5nIG9uIHRoZSB2YWx1ZSBvZiB0aGUgcHJvcGVydHkuIElmIG11dGFibGUgaXQgd2lsbCByZXR1cm4gYSBPcGVyYXRpb24tdHlwZSBvYmplY3QsIGlmIGltbXV0YWJsZSBpdCB3aWxsIHJldHVybiBTdHJpbmcvT2JqZWN0LlxyXG4gICNcclxuICAjIEBvdmVybG9hZCB2YWwobmFtZSwgY29udGVudClcclxuICAjICAgU2V0IGEgbmV3IHByb3BlcnR5LlxyXG4gICMgICBAcGFyYW0ge1N0cmluZ30gbmFtZSBOYW1lIG9mIHRoZSBvYmplY3QgcHJvcGVydHkuXHJcbiAgIyAgIEBwYXJhbSB7T2JqZWN0fFN0cmluZ30gY29udGVudCBDb250ZW50IG9mIHRoZSBvYmplY3QgcHJvcGVydHkuXHJcbiAgIyAgIEByZXR1cm4gW09iamVjdCBUeXBlXSBUaGlzIG9iamVjdC4gKHN1cHBvcnRzIGNoYWluaW5nKVxyXG4gICNcclxuICB2YWw6IChuYW1lLCBjb250ZW50KS0+XHJcbiAgICBpZiBAX21vZGVsP1xyXG4gICAgICBAX21vZGVsLnZhbC5hcHBseSBAX21vZGVsLCBhcmd1bWVudHNcclxuICAgIGVsc2VcclxuICAgICAgaWYgY29udGVudD9cclxuICAgICAgICBAX29iamVjdFtuYW1lXSA9IGNvbnRlbnRcclxuICAgICAgZWxzZSBpZiBuYW1lP1xyXG4gICAgICAgIEBfb2JqZWN0W25hbWVdXHJcbiAgICAgIGVsc2VcclxuICAgICAgICByZXMgPSB7fVxyXG4gICAgICAgIGZvciBuLHYgb2YgQF9vYmplY3RcclxuICAgICAgICAgIHJlc1tuXSA9IHZcclxuICAgICAgICByZXNcclxuXHJcbiAgZGVsZXRlOiAobmFtZSktPlxyXG4gICAgQF9tb2RlbC5kZWxldGUobmFtZSlcclxuICAgIEBcclxuXHJcbmlmIHdpbmRvdz9cclxuICBpZiB3aW5kb3cuWT9cclxuICAgIHdpbmRvdy5ZLk9iamVjdCA9IFlPYmplY3RcclxuICBlbHNlXHJcbiAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBmaXJzdCBpbXBvcnQgWSFcIlxyXG5cclxuaWYgbW9kdWxlP1xyXG4gIG1vZHVsZS5leHBvcnRzID0gWU9iamVjdFxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcbiIsIm1vZHVsZS5leHBvcnRzID0gKCktPlxyXG4gICMgQHNlZSBFbmdpbmUucGFyc2VcclxuICBvcHMgPSB7fVxyXG4gIGV4ZWN1dGlvbl9saXN0ZW5lciA9IFtdXHJcblxyXG4gICNcclxuICAjIEBwcml2YXRlXHJcbiAgIyBAYWJzdHJhY3RcclxuICAjIEBub2RvY1xyXG4gICMgQSBnZW5lcmljIGludGVyZmFjZSB0byBvcHMuXHJcbiAgI1xyXG4gICMgQW4gb3BlcmF0aW9uIGhhcyB0aGUgZm9sbG93aW5nIG1ldGhvZHM6XHJcbiAgIyAqIF9lbmNvZGU6IGVuY29kZXMgYW4gb3BlcmF0aW9uIChuZWVkZWQgb25seSBpZiBpbnN0YW5jZSBvZiB0aGlzIG9wZXJhdGlvbiBpcyBzZW50KS5cclxuICAjICogZXhlY3V0ZTogZXhlY3V0ZSB0aGUgZWZmZWN0cyBvZiB0aGlzIG9wZXJhdGlvbnMuIEdvb2QgZXhhbXBsZXMgYXJlIEluc2VydC10eXBlIGFuZCBBZGROYW1lLXR5cGVcclxuICAjICogdmFsOiBpbiB0aGUgY2FzZSB0aGF0IHRoZSBvcGVyYXRpb24gaG9sZHMgYSB2YWx1ZVxyXG4gICNcclxuICAjIEZ1cnRoZXJtb3JlIGFuIGVuY29kYWJsZSBvcGVyYXRpb24gaGFzIGEgcGFyc2VyLiBXZSBleHRlbmQgdGhlIHBhcnNlciBvYmplY3QgaW4gb3JkZXIgdG8gcGFyc2UgZW5jb2RlZCBvcGVyYXRpb25zLlxyXG4gICNcclxuICBjbGFzcyBvcHMuT3BlcmF0aW9uXHJcblxyXG4gICAgI1xyXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuXHJcbiAgICAjIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQgYmVmb3JlIGF0IHRoZSBlbmQgb2YgdGhlIGV4ZWN1dGlvbiBzZXF1ZW5jZVxyXG4gICAgI1xyXG4gICAgY29uc3RydWN0b3I6IChjdXN0b21fdHlwZSwgdWlkLCBjb250ZW50LCBjb250ZW50X29wZXJhdGlvbnMpLT5cclxuICAgICAgaWYgY3VzdG9tX3R5cGU/XHJcbiAgICAgICAgQGN1c3RvbV90eXBlID0gY3VzdG9tX3R5cGVcclxuICAgICAgQGlzX2RlbGV0ZWQgPSBmYWxzZVxyXG4gICAgICBAZ2FyYmFnZV9jb2xsZWN0ZWQgPSBmYWxzZVxyXG4gICAgICBAZXZlbnRfbGlzdGVuZXJzID0gW10gIyBUT0RPOiByZW5hbWUgdG8gb2JzZXJ2ZXJzIG9yIHN0aCBsaWtlIHRoYXRcclxuICAgICAgaWYgdWlkP1xyXG4gICAgICAgIEB1aWQgPSB1aWRcclxuXHJcbiAgICAgICMgc2VlIGVuY29kZSB0byBzZWUsIHdoeSB3ZSBhcmUgZG9pbmcgaXQgdGhpcyB3YXlcclxuICAgICAgaWYgY29udGVudCBpcyB1bmRlZmluZWRcclxuICAgICAgICAjIG5vcFxyXG4gICAgICBlbHNlIGlmIGNvbnRlbnQ/IGFuZCBjb250ZW50LmNyZWF0b3I/XHJcbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ2NvbnRlbnQnLCBjb250ZW50XHJcbiAgICAgIGVsc2VcclxuICAgICAgICBAY29udGVudCA9IGNvbnRlbnRcclxuICAgICAgaWYgY29udGVudF9vcGVyYXRpb25zP1xyXG4gICAgICAgIEBjb250ZW50X29wZXJhdGlvbnMgPSB7fVxyXG4gICAgICAgIGZvciBuYW1lLCBvcCBvZiBjb250ZW50X29wZXJhdGlvbnNcclxuICAgICAgICAgIEBzYXZlT3BlcmF0aW9uIG5hbWUsIG9wLCAnY29udGVudF9vcGVyYXRpb25zJ1xyXG5cclxuICAgIHR5cGU6IFwiT3BlcmF0aW9uXCJcclxuXHJcbiAgICBnZXRDb250ZW50OiAobmFtZSktPlxyXG4gICAgICBpZiBAY29udGVudD9cclxuICAgICAgICBpZiBAY29udGVudC5nZXRDdXN0b21UeXBlP1xyXG4gICAgICAgICAgQGNvbnRlbnQuZ2V0Q3VzdG9tVHlwZSgpXHJcbiAgICAgICAgZWxzZSBpZiBAY29udGVudC5jb25zdHJ1Y3RvciBpcyBPYmplY3RcclxuICAgICAgICAgIGlmIG5hbWU/XHJcbiAgICAgICAgICAgIGlmIEBjb250ZW50W25hbWVdP1xyXG4gICAgICAgICAgICAgIEBjb250ZW50W25hbWVdXHJcbiAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICBAY29udGVudF9vcGVyYXRpb25zW25hbWVdLmdldEN1c3RvbVR5cGUoKVxyXG4gICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICBjb250ZW50ID0ge31cclxuICAgICAgICAgICAgZm9yIG4sdiBvZiBAY29udGVudFxyXG4gICAgICAgICAgICAgIGNvbnRlbnRbbl0gPSB2XHJcbiAgICAgICAgICAgIGlmIEBjb250ZW50X29wZXJhdGlvbnM/XHJcbiAgICAgICAgICAgICAgZm9yIG4sdiBvZiBAY29udGVudF9vcGVyYXRpb25zXHJcbiAgICAgICAgICAgICAgICB2ID0gdi5nZXRDdXN0b21UeXBlKClcclxuICAgICAgICAgICAgICAgIGNvbnRlbnRbbl0gPSB2XHJcbiAgICAgICAgICAgIGNvbnRlbnRcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICBAY29udGVudFxyXG4gICAgICBlbHNlXHJcbiAgICAgICAgQGNvbnRlbnRcclxuXHJcbiAgICByZXRyaWV2ZVN1YjogKCktPlxyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJzdWIgcHJvcGVydGllcyBhcmUgbm90IGVuYWJsZSBvbiB0aGlzIG9wZXJhdGlvbiB0eXBlIVwiXHJcblxyXG4gICAgI1xyXG4gICAgIyBBZGQgYW4gZXZlbnQgbGlzdGVuZXIuIEl0IGRlcGVuZHMgb24gdGhlIG9wZXJhdGlvbiB3aGljaCBldmVudHMgYXJlIHN1cHBvcnRlZC5cclxuICAgICMgQHBhcmFtIHtGdW5jdGlvbn0gZiBmIGlzIGV4ZWN1dGVkIGluIGNhc2UgdGhlIGV2ZW50IGZpcmVzLlxyXG4gICAgI1xyXG4gICAgb2JzZXJ2ZTogKGYpLT5cclxuICAgICAgQGV2ZW50X2xpc3RlbmVycy5wdXNoIGZcclxuXHJcbiAgICAjXHJcbiAgICAjIERlbGV0ZXMgZnVuY3Rpb24gZnJvbSB0aGUgb2JzZXJ2ZXIgbGlzdFxyXG4gICAgIyBAc2VlIE9wZXJhdGlvbi5vYnNlcnZlXHJcbiAgICAjXHJcbiAgICAjIEBvdmVybG9hZCB1bm9ic2VydmUoZXZlbnQsIGYpXHJcbiAgICAjICAgQHBhcmFtIGYgICAgIHtGdW5jdGlvbn0gVGhlIGZ1bmN0aW9uIHRoYXQgeW91IHdhbnQgdG8gZGVsZXRlXHJcbiAgICB1bm9ic2VydmU6IChmKS0+XHJcbiAgICAgIEBldmVudF9saXN0ZW5lcnMgPSBAZXZlbnRfbGlzdGVuZXJzLmZpbHRlciAoZyktPlxyXG4gICAgICAgIGYgaXNudCBnXHJcblxyXG4gICAgI1xyXG4gICAgIyBEZWxldGVzIGFsbCBzdWJzY3JpYmVkIGV2ZW50IGxpc3RlbmVycy5cclxuICAgICMgVGhpcyBzaG91bGQgYmUgY2FsbGVkLCBlLmcuIGFmdGVyIHRoaXMgaGFzIGJlZW4gcmVwbGFjZWQuXHJcbiAgICAjIChUaGVuIG9ubHkgb25lIHJlcGxhY2UgZXZlbnQgc2hvdWxkIGZpcmUuIClcclxuICAgICMgVGhpcyBpcyBhbHNvIGNhbGxlZCBpbiB0aGUgY2xlYW51cCBtZXRob2QuXHJcbiAgICBkZWxldGVBbGxPYnNlcnZlcnM6ICgpLT5cclxuICAgICAgQGV2ZW50X2xpc3RlbmVycyA9IFtdXHJcblxyXG4gICAgZGVsZXRlOiAoKS0+XHJcbiAgICAgIChuZXcgb3BzLkRlbGV0ZSB1bmRlZmluZWQsIEApLmV4ZWN1dGUoKVxyXG4gICAgICBudWxsXHJcblxyXG4gICAgI1xyXG4gICAgIyBGaXJlIGFuIGV2ZW50LlxyXG4gICAgIyBUT0RPOiBEbyBzb21ldGhpbmcgd2l0aCB0aW1lb3V0cy4gWW91IGRvbid0IHdhbnQgdGhpcyB0byBmaXJlIGZvciBldmVyeSBvcGVyYXRpb24gKGUuZy4gaW5zZXJ0KS5cclxuICAgICMgVE9ETzogZG8geW91IG5lZWQgY2FsbEV2ZW50K2ZvcndhcmRFdmVudD8gT25seSBvbmUgc3VmZmljZXMgcHJvYmFibHlcclxuICAgIGNhbGxFdmVudDogKCktPlxyXG4gICAgICBpZiBAY3VzdG9tX3R5cGU/XHJcbiAgICAgICAgY2FsbG9uID0gQGdldEN1c3RvbVR5cGUoKVxyXG4gICAgICBlbHNlXHJcbiAgICAgICAgY2FsbG9uID0gQFxyXG4gICAgICBAZm9yd2FyZEV2ZW50IGNhbGxvbiwgYXJndW1lbnRzLi4uXHJcblxyXG4gICAgI1xyXG4gICAgIyBGaXJlIGFuIGV2ZW50IGFuZCBzcGVjaWZ5IGluIHdoaWNoIGNvbnRleHQgdGhlIGxpc3RlbmVyIGlzIGNhbGxlZCAoc2V0ICd0aGlzJykuXHJcbiAgICAjIFRPRE86IGRvIHlvdSBuZWVkIHRoaXMgP1xyXG4gICAgZm9yd2FyZEV2ZW50OiAob3AsIGFyZ3MuLi4pLT5cclxuICAgICAgZm9yIGYgaW4gQGV2ZW50X2xpc3RlbmVyc1xyXG4gICAgICAgIGYuY2FsbCBvcCwgYXJncy4uLlxyXG5cclxuICAgIGlzRGVsZXRlZDogKCktPlxyXG4gICAgICBAaXNfZGVsZXRlZFxyXG5cclxuICAgIGFwcGx5RGVsZXRlOiAoZ2FyYmFnZWNvbGxlY3QgPSB0cnVlKS0+XHJcbiAgICAgIGlmIG5vdCBAZ2FyYmFnZV9jb2xsZWN0ZWRcclxuICAgICAgICAjY29uc29sZS5sb2cgXCJhcHBseURlbGV0ZTogI3tAdHlwZX1cIlxyXG4gICAgICAgIEBpc19kZWxldGVkID0gdHJ1ZVxyXG4gICAgICAgIGlmIGdhcmJhZ2Vjb2xsZWN0XHJcbiAgICAgICAgICBAZ2FyYmFnZV9jb2xsZWN0ZWQgPSB0cnVlXHJcbiAgICAgICAgICBASEIuYWRkVG9HYXJiYWdlQ29sbGVjdG9yIEBcclxuXHJcbiAgICBjbGVhbnVwOiAoKS0+XHJcbiAgICAgICNjb25zb2xlLmxvZyBcImNsZWFudXA6ICN7QHR5cGV9XCJcclxuICAgICAgQEhCLnJlbW92ZU9wZXJhdGlvbiBAXHJcbiAgICAgIEBkZWxldGVBbGxPYnNlcnZlcnMoKVxyXG5cclxuICAgICNcclxuICAgICMgU2V0IHRoZSBwYXJlbnQgb2YgdGhpcyBvcGVyYXRpb24uXHJcbiAgICAjXHJcbiAgICBzZXRQYXJlbnQ6IChAcGFyZW50KS0+XHJcblxyXG4gICAgI1xyXG4gICAgIyBHZXQgdGhlIHBhcmVudCBvZiB0aGlzIG9wZXJhdGlvbi5cclxuICAgICNcclxuICAgIGdldFBhcmVudDogKCktPlxyXG4gICAgICBAcGFyZW50XHJcblxyXG4gICAgI1xyXG4gICAgIyBDb21wdXRlcyBhIHVuaXF1ZSBpZGVudGlmaWVyICh1aWQpIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi5cclxuICAgICNcclxuICAgIGdldFVpZDogKCktPlxyXG4gICAgICBpZiBub3QgQHVpZC5ub09wZXJhdGlvbj9cclxuICAgICAgICBAdWlkXHJcbiAgICAgIGVsc2VcclxuICAgICAgICBpZiBAdWlkLmFsdD8gIyBjb3VsZCBiZSAoc2FmZWx5KSB1bmRlZmluZWRcclxuICAgICAgICAgIG1hcF91aWQgPSBAdWlkLmFsdC5jbG9uZVVpZCgpXHJcbiAgICAgICAgICBtYXBfdWlkLnN1YiA9IEB1aWQuc3ViXHJcbiAgICAgICAgICBtYXBfdWlkXHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgdW5kZWZpbmVkXHJcblxyXG4gICAgY2xvbmVVaWQ6ICgpLT5cclxuICAgICAgdWlkID0ge31cclxuICAgICAgZm9yIG4sdiBvZiBAZ2V0VWlkKClcclxuICAgICAgICB1aWRbbl0gPSB2XHJcbiAgICAgIHVpZFxyXG5cclxuICAgICNcclxuICAgICMgQHByaXZhdGVcclxuICAgICMgSWYgbm90IGFscmVhZHkgZG9uZSwgc2V0IHRoZSB1aWRcclxuICAgICMgQWRkIHRoaXMgdG8gdGhlIEhCXHJcbiAgICAjIE5vdGlmeSB0aGUgYWxsIHRoZSBsaXN0ZW5lcnMuXHJcbiAgICAjXHJcbiAgICBleGVjdXRlOiAoKS0+XHJcbiAgICAgIGlmIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXHJcbiAgICAgICAgQGlzX2V4ZWN1dGVkID0gdHJ1ZVxyXG4gICAgICAgIGlmIG5vdCBAdWlkP1xyXG4gICAgICAgICAgIyBXaGVuIHRoaXMgb3BlcmF0aW9uIHdhcyBjcmVhdGVkIHdpdGhvdXQgYSB1aWQsIHRoZW4gc2V0IGl0IGhlcmUuXHJcbiAgICAgICAgICAjIFRoZXJlIGlzIG9ubHkgb25lIG90aGVyIHBsYWNlLCB3aGVyZSB0aGlzIGNhbiBiZSBkb25lIC0gYmVmb3JlIGFuIEluc2VydGlvblxyXG4gICAgICAgICAgIyBpcyBleGVjdXRlZCAoYmVjYXVzZSB3ZSBuZWVkIHRoZSBjcmVhdG9yX2lkKVxyXG4gICAgICAgICAgQHVpZCA9IEBIQi5nZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllcigpXHJcbiAgICAgICAgaWYgbm90IEB1aWQubm9PcGVyYXRpb24/XHJcbiAgICAgICAgICBASEIuYWRkT3BlcmF0aW9uIEBcclxuICAgICAgICAgIGZvciBsIGluIGV4ZWN1dGlvbl9saXN0ZW5lclxyXG4gICAgICAgICAgICBsIEBfZW5jb2RlKClcclxuICAgICAgICBAXHJcbiAgICAgIGVsc2VcclxuICAgICAgICBmYWxzZVxyXG5cclxuICAgICNcclxuICAgICMgQHByaXZhdGVcclxuICAgICMgT3BlcmF0aW9ucyBtYXkgZGVwZW5kIG9uIG90aGVyIG9wZXJhdGlvbnMgKGxpbmtlZCBsaXN0cywgZXRjLikuXHJcbiAgICAjIFRoZSBzYXZlT3BlcmF0aW9uIGFuZCB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucyBtZXRob2RzIHByb3ZpZGVcclxuICAgICMgYW4gZWFzeSB3YXkgdG8gcmVmZXIgdG8gdGhlc2Ugb3BlcmF0aW9ucyB2aWEgYW4gdWlkIG9yIG9iamVjdCByZWZlcmVuY2UuXHJcbiAgICAjXHJcbiAgICAjIEZvciBleGFtcGxlOiBXZSBjYW4gY3JlYXRlIGEgbmV3IERlbGV0ZSBvcGVyYXRpb24gdGhhdCBkZWxldGVzIHRoZSBvcGVyYXRpb24gJG8gbGlrZSB0aGlzXHJcbiAgICAjICAgICAtIHZhciBkID0gbmV3IERlbGV0ZSh1aWQsICRvKTsgICBvclxyXG4gICAgIyAgICAgLSB2YXIgZCA9IG5ldyBEZWxldGUodWlkLCAkby5nZXRVaWQoKSk7XHJcbiAgICAjIEVpdGhlciB3YXkgd2Ugd2FudCB0byBhY2Nlc3MgJG8gdmlhIGQuZGVsZXRlcy4gSW4gdGhlIHNlY29uZCBjYXNlIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zIG11c3QgYmUgY2FsbGVkIGZpcnN0LlxyXG4gICAgI1xyXG4gICAgIyBAb3ZlcmxvYWQgc2F2ZU9wZXJhdGlvbihuYW1lLCBvcF91aWQpXHJcbiAgICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGlvbi4gQWZ0ZXIgdmFsaWRhdGluZyAod2l0aCB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucykgdGhlIGluc3RhbnRpYXRlZCBvcGVyYXRpb24gd2lsbCBiZSBhY2Nlc3NpYmxlIHZpYSB0aGlzW25hbWVdLlxyXG4gICAgIyAgIEBwYXJhbSB7T2JqZWN0fSBvcF91aWQgQSB1aWQgdGhhdCByZWZlcnMgdG8gYW4gb3BlcmF0aW9uXHJcbiAgICAjIEBvdmVybG9hZCBzYXZlT3BlcmF0aW9uKG5hbWUsIG9wKVxyXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpb24uIEFmdGVyIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiBvcCBpcyBhY2Nlc3NpYmxlIHZpYSB0aGlzW25hbWVdLlxyXG4gICAgIyAgIEBwYXJhbSB7T3BlcmF0aW9ufSBvcCBBbiBPcGVyYXRpb24gb2JqZWN0XHJcbiAgICAjXHJcbiAgICBzYXZlT3BlcmF0aW9uOiAobmFtZSwgb3AsIGJhc2UgPSBcInRoaXNcIiktPlxyXG4gICAgICBpZiBvcD8gYW5kIG9wLl9nZXRNb2RlbD9cclxuICAgICAgICBvcCA9IG9wLl9nZXRNb2RlbChAY3VzdG9tX3R5cGVzLCBAb3BlcmF0aW9ucylcclxuICAgICAgI1xyXG4gICAgICAjIEV2ZXJ5IGluc3RhbmNlIG9mICRPcGVyYXRpb24gbXVzdCBoYXZlIGFuICRleGVjdXRlIGZ1bmN0aW9uLlxyXG4gICAgICAjIFdlIHVzZSBkdWNrLXR5cGluZyB0byBjaGVjayBpZiBvcCBpcyBpbnN0YW50aWF0ZWQgc2luY2UgdGhlcmVcclxuICAgICAgIyBjb3VsZCBleGlzdCBtdWx0aXBsZSBjbGFzc2VzIG9mICRPcGVyYXRpb25cclxuICAgICAgI1xyXG4gICAgICBpZiBub3Qgb3A/XHJcbiAgICAgICAgIyBub3BcclxuICAgICAgZWxzZSBpZiBvcC5leGVjdXRlPyBvciBub3QgKG9wLm9wX251bWJlcj8gYW5kIG9wLmNyZWF0b3I/KVxyXG4gICAgICAgICMgaXMgaW5zdGFudGlhdGVkLCBvciBvcCBpcyBzdHJpbmcuIEN1cnJlbnRseSBcIkRlbGltaXRlclwiIGlzIHNhdmVkIGFzIHN0cmluZ1xyXG4gICAgICAgICMgKGluIGNvbWJpbmF0aW9uIHdpdGggQHBhcmVudCB5b3UgY2FuIHJldHJpZXZlIHRoZSBkZWxpbWl0ZXIuLilcclxuICAgICAgICBpZiBiYXNlIGlzIFwidGhpc1wiXHJcbiAgICAgICAgICBAW25hbWVdID0gb3BcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICBkZXN0ID0gQFtiYXNlXVxyXG4gICAgICAgICAgcGF0aHMgPSBuYW1lLnNwbGl0KFwiL1wiKVxyXG4gICAgICAgICAgbGFzdF9wYXRoID0gcGF0aHMucG9wKClcclxuICAgICAgICAgIGZvciBwYXRoIGluIHBhdGhzXHJcbiAgICAgICAgICAgIGRlc3QgPSBkZXN0W3BhdGhdXHJcbiAgICAgICAgICBkZXN0W2xhc3RfcGF0aF0gPSBvcFxyXG4gICAgICBlbHNlXHJcbiAgICAgICAgIyBub3QgaW5pdGlhbGl6ZWQuIERvIGl0IHdoZW4gY2FsbGluZyAkdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxyXG4gICAgICAgIEB1bmNoZWNrZWQgPz0ge31cclxuICAgICAgICBAdW5jaGVja2VkW2Jhc2VdID89IHt9XHJcbiAgICAgICAgQHVuY2hlY2tlZFtiYXNlXVtuYW1lXSA9IG9wXHJcblxyXG4gICAgI1xyXG4gICAgIyBAcHJpdmF0ZVxyXG4gICAgIyBBZnRlciBjYWxsaW5nIHRoaXMgZnVuY3Rpb24gYWxsIG5vdCBpbnN0YW50aWF0ZWQgb3BlcmF0aW9ucyB3aWxsIGJlIGFjY2Vzc2libGUuXHJcbiAgICAjIEBzZWUgT3BlcmF0aW9uLnNhdmVPcGVyYXRpb25cclxuICAgICNcclxuICAgICMgQHJldHVybiBbQm9vbGVhbl0gV2hldGhlciBpdCB3YXMgcG9zc2libGUgdG8gaW5zdGFudGlhdGUgYWxsIG9wZXJhdGlvbnMuXHJcbiAgICAjXHJcbiAgICB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9uczogKCktPlxyXG4gICAgICB1bmluc3RhbnRpYXRlZCA9IHt9XHJcbiAgICAgIHN1Y2Nlc3MgPSB0cnVlXHJcbiAgICAgIGZvciBiYXNlX25hbWUsIGJhc2Ugb2YgQHVuY2hlY2tlZFxyXG4gICAgICAgIGZvciBuYW1lLCBvcF91aWQgb2YgYmFzZVxyXG4gICAgICAgICAgb3AgPSBASEIuZ2V0T3BlcmF0aW9uIG9wX3VpZFxyXG4gICAgICAgICAgaWYgb3BcclxuICAgICAgICAgICAgaWYgYmFzZV9uYW1lIGlzIFwidGhpc1wiXHJcbiAgICAgICAgICAgICAgQFtuYW1lXSA9IG9wXHJcbiAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICBkZXN0ID0gQFtiYXNlX25hbWVdXHJcbiAgICAgICAgICAgICAgcGF0aHMgPSBuYW1lLnNwbGl0KFwiL1wiKVxyXG4gICAgICAgICAgICAgIGxhc3RfcGF0aCA9IHBhdGhzLnBvcCgpXHJcbiAgICAgICAgICAgICAgZm9yIHBhdGggaW4gcGF0aHNcclxuICAgICAgICAgICAgICAgIGRlc3QgPSBkZXN0W3BhdGhdXHJcbiAgICAgICAgICAgICAgZGVzdFtsYXN0X3BhdGhdID0gb3BcclxuICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgdW5pbnN0YW50aWF0ZWRbYmFzZV9uYW1lXSA/PSB7fVxyXG4gICAgICAgICAgICB1bmluc3RhbnRpYXRlZFtiYXNlX25hbWVdW25hbWVdID0gb3BfdWlkXHJcbiAgICAgICAgICAgIHN1Y2Nlc3MgPSBmYWxzZVxyXG4gICAgICBpZiBub3Qgc3VjY2Vzc1xyXG4gICAgICAgIEB1bmNoZWNrZWQgPSB1bmluc3RhbnRpYXRlZFxyXG4gICAgICAgIHJldHVybiBmYWxzZVxyXG4gICAgICBlbHNlXHJcbiAgICAgICAgZGVsZXRlIEB1bmNoZWNrZWRcclxuICAgICAgICByZXR1cm4gQFxyXG5cclxuICAgIGdldEN1c3RvbVR5cGU6ICgpLT5cclxuICAgICAgaWYgbm90IEBjdXN0b21fdHlwZT9cclxuICAgICAgICAjIHRocm93IG5ldyBFcnJvciBcIlRoaXMgb3BlcmF0aW9uIHdhcyBub3QgaW5pdGlhbGl6ZWQgd2l0aCBhIGN1c3RvbSB0eXBlXCJcclxuICAgICAgICBAXHJcbiAgICAgIGVsc2VcclxuICAgICAgICBpZiBAY3VzdG9tX3R5cGUuY29uc3RydWN0b3IgaXMgU3RyaW5nXHJcbiAgICAgICAgICAjIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZCB5ZXQgKG9ubHkgdGhlIG5hbWUgaXMgc3BlY2lmaWVkKVxyXG4gICAgICAgICAgVHlwZSA9IEBjdXN0b21fdHlwZXNcclxuICAgICAgICAgIGZvciB0IGluIEBjdXN0b21fdHlwZS5zcGxpdChcIi5cIilcclxuICAgICAgICAgICAgVHlwZSA9IFR5cGVbdF1cclxuICAgICAgICAgIEBjdXN0b21fdHlwZSA9IG5ldyBUeXBlKClcclxuICAgICAgICAgIEBjdXN0b21fdHlwZS5fc2V0TW9kZWwgQFxyXG4gICAgICAgIEBjdXN0b21fdHlwZVxyXG5cclxuICAgICNcclxuICAgICMgQHByaXZhdGVcclxuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cclxuICAgICNcclxuICAgIF9lbmNvZGU6IChqc29uID0ge30pLT5cclxuICAgICAganNvbi50eXBlID0gQHR5cGVcclxuICAgICAganNvbi51aWQgPSBAZ2V0VWlkKClcclxuICAgICAgaWYgQGN1c3RvbV90eXBlP1xyXG4gICAgICAgIGlmIEBjdXN0b21fdHlwZS5jb25zdHJ1Y3RvciBpcyBTdHJpbmdcclxuICAgICAgICAgIGpzb24uY3VzdG9tX3R5cGUgPSBAY3VzdG9tX3R5cGVcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICBqc29uLmN1c3RvbV90eXBlID0gQGN1c3RvbV90eXBlLl9uYW1lXHJcblxyXG4gICAgICBpZiBAY29udGVudD8uZ2V0VWlkP1xyXG4gICAgICAgIGpzb24uY29udGVudCA9IEBjb250ZW50LmdldFVpZCgpXHJcbiAgICAgIGVsc2VcclxuICAgICAgICBqc29uLmNvbnRlbnQgPSBAY29udGVudFxyXG4gICAgICBpZiBAY29udGVudF9vcGVyYXRpb25zP1xyXG4gICAgICAgIG9wZXJhdGlvbnMgPSB7fVxyXG4gICAgICAgIGZvciBuLG8gb2YgQGNvbnRlbnRfb3BlcmF0aW9uc1xyXG4gICAgICAgICAgaWYgby5fZ2V0TW9kZWw/XHJcbiAgICAgICAgICAgIG8gPSBvLl9nZXRNb2RlbChAY3VzdG9tX3R5cGVzLCBAb3BlcmF0aW9ucylcclxuICAgICAgICAgIG9wZXJhdGlvbnNbbl0gPSBvLmdldFVpZCgpXHJcbiAgICAgICAganNvbi5jb250ZW50X29wZXJhdGlvbnMgPSBvcGVyYXRpb25zXHJcbiAgICAgIGpzb25cclxuXHJcbiAgI1xyXG4gICMgQG5vZG9jXHJcbiAgIyBBIHNpbXBsZSBEZWxldGUtdHlwZSBvcGVyYXRpb24gdGhhdCBkZWxldGVzIGFuIG9wZXJhdGlvbi5cclxuICAjXHJcbiAgY2xhc3Mgb3BzLkRlbGV0ZSBleHRlbmRzIG9wcy5PcGVyYXRpb25cclxuXHJcbiAgICAjXHJcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cclxuICAgICMgQHBhcmFtIHtPYmplY3R9IGRlbGV0ZXMgVUlEIG9yIHJlZmVyZW5jZSBvZiB0aGUgb3BlcmF0aW9uIHRoYXQgdGhpcyB0byBiZSBkZWxldGVkLlxyXG4gICAgI1xyXG4gICAgY29uc3RydWN0b3I6IChjdXN0b21fdHlwZSwgdWlkLCBkZWxldGVzKS0+XHJcbiAgICAgIEBzYXZlT3BlcmF0aW9uICdkZWxldGVzJywgZGVsZXRlc1xyXG4gICAgICBzdXBlciBjdXN0b21fdHlwZSwgdWlkXHJcblxyXG4gICAgdHlwZTogXCJEZWxldGVcIlxyXG5cclxuICAgICNcclxuICAgICMgQHByaXZhdGVcclxuICAgICMgQ29udmVydCBhbGwgcmVsZXZhbnQgaW5mb3JtYXRpb24gb2YgdGhpcyBvcGVyYXRpb24gdG8gdGhlIGpzb24tZm9ybWF0LlxyXG4gICAgIyBUaGlzIHJlc3VsdCBjYW4gYmUgc2VudCB0byBvdGhlciBjbGllbnRzLlxyXG4gICAgI1xyXG4gICAgX2VuY29kZTogKCktPlxyXG4gICAgICB7XHJcbiAgICAgICAgJ3R5cGUnOiBcIkRlbGV0ZVwiXHJcbiAgICAgICAgJ3VpZCc6IEBnZXRVaWQoKVxyXG4gICAgICAgICdkZWxldGVzJzogQGRlbGV0ZXMuZ2V0VWlkKClcclxuICAgICAgfVxyXG5cclxuICAgICNcclxuICAgICMgQHByaXZhdGVcclxuICAgICMgQXBwbHkgdGhlIGRlbGV0aW9uLlxyXG4gICAgI1xyXG4gICAgZXhlY3V0ZTogKCktPlxyXG4gICAgICBpZiBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxyXG4gICAgICAgIHJlcyA9IHN1cGVyXHJcbiAgICAgICAgaWYgcmVzXHJcbiAgICAgICAgICBAZGVsZXRlcy5hcHBseURlbGV0ZSBAXHJcbiAgICAgICAgcmVzXHJcbiAgICAgIGVsc2VcclxuICAgICAgICBmYWxzZVxyXG5cclxuICAjXHJcbiAgIyBEZWZpbmUgaG93IHRvIHBhcnNlIERlbGV0ZSBvcGVyYXRpb25zLlxyXG4gICNcclxuICBvcHMuRGVsZXRlLnBhcnNlID0gKG8pLT5cclxuICAgIHtcclxuICAgICAgJ3VpZCcgOiB1aWRcclxuICAgICAgJ2RlbGV0ZXMnOiBkZWxldGVzX3VpZFxyXG4gICAgfSA9IG9cclxuICAgIG5ldyB0aGlzKG51bGwsIHVpZCwgZGVsZXRlc191aWQpXHJcblxyXG4gICNcclxuICAjIEBub2RvY1xyXG4gICMgQSBzaW1wbGUgaW5zZXJ0LXR5cGUgb3BlcmF0aW9uLlxyXG4gICNcclxuICAjIEFuIGluc2VydCBvcGVyYXRpb24gaXMgYWx3YXlzIHBvc2l0aW9uZWQgYmV0d2VlbiB0d28gb3RoZXIgaW5zZXJ0IG9wZXJhdGlvbnMuXHJcbiAgIyBJbnRlcm5hbGx5IHRoaXMgaXMgcmVhbGl6ZWQgYXMgYXNzb2NpYXRpdmUgbGlzdHMsIHdoZXJlYnkgZWFjaCBpbnNlcnQgb3BlcmF0aW9uIGhhcyBhIHByZWRlY2Vzc29yIGFuZCBhIHN1Y2Nlc3Nvci5cclxuICAjIEZvciB0aGUgc2FrZSBvZiBlZmZpY2llbmN5IHdlIG1haW50YWluIHR3byBsaXN0czpcclxuICAjICAgLSBUaGUgc2hvcnQtbGlzdCAoYWJicmV2LiBzbCkgbWFpbnRhaW5zIG9ubHkgdGhlIG9wZXJhdGlvbnMgdGhhdCBhcmUgbm90IGRlbGV0ZWQgKHVuaW1wbGVtZW50ZWQsIGdvb2QgaWRlYT8pXHJcbiAgIyAgIC0gVGhlIGNvbXBsZXRlLWxpc3QgKGFiYnJldi4gY2wpIG1haW50YWlucyBhbGwgb3BlcmF0aW9uc1xyXG4gICNcclxuICBjbGFzcyBvcHMuSW5zZXJ0IGV4dGVuZHMgb3BzLk9wZXJhdGlvblxyXG5cclxuICAgICNcclxuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxyXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gcHJldl9jbCBUaGUgcHJlZGVjZXNzb3Igb2YgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGNvbXBsZXRlLWxpc3QgKGNsKVxyXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gbmV4dF9jbCBUaGUgc3VjY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcclxuICAgICNcclxuICAgIGNvbnN0cnVjdG9yOiAoY3VzdG9tX3R5cGUsIGNvbnRlbnQsIGNvbnRlbnRfb3BlcmF0aW9ucywgcGFyZW50LCB1aWQsIHByZXZfY2wsIG5leHRfY2wsIG9yaWdpbiktPlxyXG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncGFyZW50JywgcGFyZW50XHJcbiAgICAgIEBzYXZlT3BlcmF0aW9uICdwcmV2X2NsJywgcHJldl9jbFxyXG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnbmV4dF9jbCcsIG5leHRfY2xcclxuICAgICAgaWYgb3JpZ2luP1xyXG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBvcmlnaW5cclxuICAgICAgZWxzZVxyXG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBwcmV2X2NsXHJcbiAgICAgIHN1cGVyIGN1c3RvbV90eXBlLCB1aWQsIGNvbnRlbnQsIGNvbnRlbnRfb3BlcmF0aW9uc1xyXG5cclxuICAgIHR5cGU6IFwiSW5zZXJ0XCJcclxuXHJcbiAgICB2YWw6ICgpLT5cclxuICAgICAgQGdldENvbnRlbnQoKVxyXG5cclxuICAgIGdldE5leHQ6IChpPTEpLT5cclxuICAgICAgbiA9IEBcclxuICAgICAgd2hpbGUgaSA+IDAgYW5kIG4uaXNfZGVsZXRlZCBhbmQgbi5uZXh0X2NsP1xyXG4gICAgICAgIG4gPSBuLm5leHRfY2xcclxuICAgICAgICBpZiBub3Qgbi5pc19kZWxldGVkXHJcbiAgICAgICAgICBpLS1cclxuICAgICAgblxyXG5cclxuICAgIGdldFByZXY6IChpPTEpLT5cclxuICAgICAgbiA9IEBcclxuICAgICAgd2hpbGUgaSA+IDAgYW5kIG4uaXNfZGVsZXRlZCBhbmQgbi5wcmV2X2NsP1xyXG4gICAgICAgIG4gPSBuLnByZXZfY2xcclxuICAgICAgICBpZiBub3Qgbi5pc19kZWxldGVkXHJcbiAgICAgICAgICBpLS1cclxuICAgICAgblxyXG5cclxuICAgICNcclxuICAgICMgc2V0IGNvbnRlbnQgdG8gbnVsbCBhbmQgb3RoZXIgc3R1ZmZcclxuICAgICMgQHByaXZhdGVcclxuICAgICNcclxuICAgIGFwcGx5RGVsZXRlOiAobyktPlxyXG4gICAgICBAZGVsZXRlZF9ieSA/PSBbXVxyXG4gICAgICBjYWxsTGF0ZXIgPSBmYWxzZVxyXG4gICAgICBpZiBAcGFyZW50PyBhbmQgbm90IEBpc19kZWxldGVkIGFuZCBvPyAjIG8/IDogaWYgbm90IG8/LCB0aGVuIHRoZSBkZWxpbWl0ZXIgZGVsZXRlZCB0aGlzIEluc2VydGlvbi4gRnVydGhlcm1vcmUsIGl0IHdvdWxkIGJlIHdyb25nIHRvIGNhbGwgaXQuIFRPRE86IG1ha2UgdGhpcyBtb3JlIGV4cHJlc3NpdmUgYW5kIHNhdmVcclxuICAgICAgICAjIGNhbGwgaWZmIHdhc24ndCBkZWxldGVkIGVhcmx5ZXJcclxuICAgICAgICBjYWxsTGF0ZXIgPSB0cnVlXHJcbiAgICAgIGlmIG8/XHJcbiAgICAgICAgQGRlbGV0ZWRfYnkucHVzaCBvXHJcbiAgICAgIGdhcmJhZ2Vjb2xsZWN0ID0gZmFsc2VcclxuICAgICAgaWYgQG5leHRfY2wuaXNEZWxldGVkKClcclxuICAgICAgICBnYXJiYWdlY29sbGVjdCA9IHRydWVcclxuICAgICAgc3VwZXIgZ2FyYmFnZWNvbGxlY3RcclxuICAgICAgaWYgY2FsbExhdGVyXHJcbiAgICAgICAgQHBhcmVudC5jYWxsT3BlcmF0aW9uU3BlY2lmaWNEZWxldGVFdmVudHModGhpcywgbylcclxuICAgICAgaWYgQHByZXZfY2w/IGFuZCBAcHJldl9jbC5pc0RlbGV0ZWQoKVxyXG4gICAgICAgICMgZ2FyYmFnZSBjb2xsZWN0IHByZXZfY2xcclxuICAgICAgICBAcHJldl9jbC5hcHBseURlbGV0ZSgpXHJcblxyXG4gICAgY2xlYW51cDogKCktPlxyXG4gICAgICBpZiBAbmV4dF9jbC5pc0RlbGV0ZWQoKVxyXG4gICAgICAgICMgZGVsZXRlIGFsbCBvcHMgdGhhdCBkZWxldGUgdGhpcyBpbnNlcnRpb25cclxuICAgICAgICBmb3IgZCBpbiBAZGVsZXRlZF9ieVxyXG4gICAgICAgICAgZC5jbGVhbnVwKClcclxuXHJcbiAgICAgICAgIyB0aHJvdyBuZXcgRXJyb3IgXCJyaWdodCBpcyBub3QgZGVsZXRlZC4gaW5jb25zaXN0ZW5jeSEsIHdyYXJhcmFyXCJcclxuICAgICAgICAjIGNoYW5nZSBvcmlnaW4gcmVmZXJlbmNlcyB0byB0aGUgcmlnaHRcclxuICAgICAgICBvID0gQG5leHRfY2xcclxuICAgICAgICB3aGlsZSBvLnR5cGUgaXNudCBcIkRlbGltaXRlclwiXHJcbiAgICAgICAgICBpZiBvLm9yaWdpbiBpcyBAXHJcbiAgICAgICAgICAgIG8ub3JpZ2luID0gQHByZXZfY2xcclxuICAgICAgICAgIG8gPSBvLm5leHRfY2xcclxuICAgICAgICAjIHJlY29ubmVjdCBsZWZ0L3JpZ2h0XHJcbiAgICAgICAgQHByZXZfY2wubmV4dF9jbCA9IEBuZXh0X2NsXHJcbiAgICAgICAgQG5leHRfY2wucHJldl9jbCA9IEBwcmV2X2NsXHJcblxyXG4gICAgICAgICMgZGVsZXRlIGNvbnRlbnRcclxuICAgICAgICAjIC0gd2UgbXVzdCBub3QgZG8gdGhpcyBpbiBhcHBseURlbGV0ZSwgYmVjYXVzZSB0aGlzIHdvdWxkIGxlYWQgdG8gaW5jb25zaXN0ZW5jaWVzXHJcbiAgICAgICAgIyAoZS5nLiB0aGUgZm9sbG93aW5nIG9wZXJhdGlvbiBvcmRlciBtdXN0IGJlIGludmVydGlibGUgOlxyXG4gICAgICAgICMgICBJbnNlcnQgcmVmZXJzIHRvIGNvbnRlbnQsIHRoZW4gdGhlIGNvbnRlbnQgaXMgZGVsZXRlZClcclxuICAgICAgICAjIFRoZXJlZm9yZSwgd2UgaGF2ZSB0byBkbyB0aGlzIGluIHRoZSBjbGVhbnVwXHJcbiAgICAgICAgIyAqIE5PREU6IFdlIG5ldmVyIGRlbGV0ZSBJbnNlcnRpb25zIVxyXG4gICAgICAgIGlmIEBjb250ZW50IGluc3RhbmNlb2Ygb3BzLk9wZXJhdGlvbiBhbmQgbm90IChAY29udGVudCBpbnN0YW5jZW9mIG9wcy5JbnNlcnQpXHJcbiAgICAgICAgICBAY29udGVudC5yZWZlcmVuY2VkX2J5LS1cclxuICAgICAgICAgIGlmIEBjb250ZW50LnJlZmVyZW5jZWRfYnkgPD0gMCBhbmQgbm90IEBjb250ZW50LmlzX2RlbGV0ZWRcclxuICAgICAgICAgICAgQGNvbnRlbnQuYXBwbHlEZWxldGUoKVxyXG4gICAgICAgIGRlbGV0ZSBAY29udGVudFxyXG4gICAgICAgIHN1cGVyXHJcbiAgICAgICMgZWxzZVxyXG4gICAgICAjICAgU29tZW9uZSBpbnNlcnRlZCBzb21ldGhpbmcgaW4gdGhlIG1lYW50aW1lLlxyXG4gICAgICAjICAgUmVtZW1iZXI6IHRoaXMgY2FuIG9ubHkgYmUgZ2FyYmFnZSBjb2xsZWN0ZWQgd2hlbiBuZXh0X2NsIGlzIGRlbGV0ZWRcclxuXHJcbiAgICAjXHJcbiAgICAjIEBwcml2YXRlXHJcbiAgICAjIFRoZSBhbW91bnQgb2YgcG9zaXRpb25zIHRoYXQgJHRoaXMgb3BlcmF0aW9uIHdhcyBtb3ZlZCB0byB0aGUgcmlnaHQuXHJcbiAgICAjXHJcbiAgICBnZXREaXN0YW5jZVRvT3JpZ2luOiAoKS0+XHJcbiAgICAgIGQgPSAwXHJcbiAgICAgIG8gPSBAcHJldl9jbFxyXG4gICAgICB3aGlsZSB0cnVlXHJcbiAgICAgICAgaWYgQG9yaWdpbiBpcyBvXHJcbiAgICAgICAgICBicmVha1xyXG4gICAgICAgIGQrK1xyXG4gICAgICAgIG8gPSBvLnByZXZfY2xcclxuICAgICAgZFxyXG5cclxuICAgICNcclxuICAgICMgQHByaXZhdGVcclxuICAgICMgSW5jbHVkZSB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgYXNzb2NpYXRpdmUgbGlzdHMuXHJcbiAgICBleGVjdXRlOiAoKS0+XHJcbiAgICAgIGlmIG5vdCBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxyXG4gICAgICAgIHJldHVybiBmYWxzZVxyXG4gICAgICBlbHNlXHJcbiAgICAgICAgaWYgQGNvbnRlbnQgaW5zdGFuY2VvZiBvcHMuT3BlcmF0aW9uXHJcbiAgICAgICAgICBAY29udGVudC5pbnNlcnRfcGFyZW50ID0gQCAjIFRPRE86IHRoaXMgaXMgcHJvYmFibHkgbm90IG5lY2Vzc2FyeSBhbmQgb25seSBuaWNlIGZvciBkZWJ1Z2dpbmdcclxuICAgICAgICAgIEBjb250ZW50LnJlZmVyZW5jZWRfYnkgPz0gMFxyXG4gICAgICAgICAgQGNvbnRlbnQucmVmZXJlbmNlZF9ieSsrXHJcbiAgICAgICAgaWYgQHBhcmVudD9cclxuICAgICAgICAgIGlmIG5vdCBAcHJldl9jbD9cclxuICAgICAgICAgICAgQHByZXZfY2wgPSBAcGFyZW50LmJlZ2lubmluZ1xyXG4gICAgICAgICAgaWYgbm90IEBvcmlnaW4/XHJcbiAgICAgICAgICAgIEBvcmlnaW4gPSBAcHJldl9jbFxyXG4gICAgICAgICAgZWxzZSBpZiBAb3JpZ2luIGlzIFwiRGVsaW1pdGVyXCJcclxuICAgICAgICAgICAgQG9yaWdpbiA9IEBwYXJlbnQuYmVnaW5uaW5nXHJcbiAgICAgICAgICBpZiBub3QgQG5leHRfY2w/XHJcbiAgICAgICAgICAgIEBuZXh0X2NsID0gQHBhcmVudC5lbmRcclxuICAgICAgICBpZiBAcHJldl9jbD9cclxuICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IEBnZXREaXN0YW5jZVRvT3JpZ2luKCkgIyBtb3N0IGNhc2VzOiAwXHJcbiAgICAgICAgICBvID0gQHByZXZfY2wubmV4dF9jbFxyXG4gICAgICAgICAgaSA9IGRpc3RhbmNlX3RvX29yaWdpbiAjIGxvb3AgY291bnRlclxyXG5cclxuICAgICAgICAgICMgJHRoaXMgaGFzIHRvIGZpbmQgYSB1bmlxdWUgcG9zaXRpb24gYmV0d2VlbiBvcmlnaW4gYW5kIHRoZSBuZXh0IGtub3duIGNoYXJhY3RlclxyXG4gICAgICAgICAgIyBjYXNlIDE6ICRvcmlnaW4gZXF1YWxzICRvLm9yaWdpbjogdGhlICRjcmVhdG9yIHBhcmFtZXRlciBkZWNpZGVzIGlmIGxlZnQgb3IgcmlnaHRcclxuICAgICAgICAgICMgICAgICAgICBsZXQgJE9MPSBbbzEsbzIsbzMsbzRdLCB3aGVyZWJ5ICR0aGlzIGlzIHRvIGJlIGluc2VydGVkIGJldHdlZW4gbzEgYW5kIG80XHJcbiAgICAgICAgICAjICAgICAgICAgbzIsbzMgYW5kIG80IG9yaWdpbiBpcyAxICh0aGUgcG9zaXRpb24gb2YgbzIpXHJcbiAgICAgICAgICAjICAgICAgICAgdGhlcmUgaXMgdGhlIGNhc2UgdGhhdCAkdGhpcy5jcmVhdG9yIDwgbzIuY3JlYXRvciwgYnV0IG8zLmNyZWF0b3IgPCAkdGhpcy5jcmVhdG9yXHJcbiAgICAgICAgICAjICAgICAgICAgdGhlbiBvMiBrbm93cyBvMy4gU2luY2Ugb24gYW5vdGhlciBjbGllbnQgJE9MIGNvdWxkIGJlIFtvMSxvMyxvNF0gdGhlIHByb2JsZW0gaXMgY29tcGxleFxyXG4gICAgICAgICAgIyAgICAgICAgIHRoZXJlZm9yZSAkdGhpcyB3b3VsZCBiZSBhbHdheXMgdG8gdGhlIHJpZ2h0IG9mIG8zXHJcbiAgICAgICAgICAjIGNhc2UgMjogJG9yaWdpbiA8ICRvLm9yaWdpblxyXG4gICAgICAgICAgIyAgICAgICAgIGlmIGN1cnJlbnQgJHRoaXMgaW5zZXJ0X3Bvc2l0aW9uID4gJG8gb3JpZ2luOiAkdGhpcyBpbnNcclxuICAgICAgICAgICMgICAgICAgICBlbHNlICRpbnNlcnRfcG9zaXRpb24gd2lsbCBub3QgY2hhbmdlXHJcbiAgICAgICAgICAjICAgICAgICAgKG1heWJlIHdlIGVuY291bnRlciBjYXNlIDEgbGF0ZXIsIHRoZW4gdGhpcyB3aWxsIGJlIHRvIHRoZSByaWdodCBvZiAkbylcclxuICAgICAgICAgICMgY2FzZSAzOiAkb3JpZ2luID4gJG8ub3JpZ2luXHJcbiAgICAgICAgICAjICAgICAgICAgJHRoaXMgaW5zZXJ0X3Bvc2l0aW9uIGlzIHRvIHRoZSBsZWZ0IG9mICRvIChmb3JldmVyISlcclxuICAgICAgICAgIHdoaWxlIHRydWVcclxuICAgICAgICAgICAgaWYgbyBpc250IEBuZXh0X2NsXHJcbiAgICAgICAgICAgICAgIyAkbyBoYXBwZW5lZCBjb25jdXJyZW50bHlcclxuICAgICAgICAgICAgICBpZiBvLmdldERpc3RhbmNlVG9PcmlnaW4oKSBpcyBpXHJcbiAgICAgICAgICAgICAgICAjIGNhc2UgMVxyXG4gICAgICAgICAgICAgICAgaWYgby51aWQuY3JlYXRvciA8IEB1aWQuY3JlYXRvclxyXG4gICAgICAgICAgICAgICAgICBAcHJldl9jbCA9IG9cclxuICAgICAgICAgICAgICAgICAgZGlzdGFuY2VfdG9fb3JpZ2luID0gaSArIDFcclxuICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgIyBub3BcclxuICAgICAgICAgICAgICBlbHNlIGlmIG8uZ2V0RGlzdGFuY2VUb09yaWdpbigpIDwgaVxyXG4gICAgICAgICAgICAgICAgIyBjYXNlIDJcclxuICAgICAgICAgICAgICAgIGlmIGkgLSBkaXN0YW5jZV90b19vcmlnaW4gPD0gby5nZXREaXN0YW5jZVRvT3JpZ2luKClcclxuICAgICAgICAgICAgICAgICAgQHByZXZfY2wgPSBvXHJcbiAgICAgICAgICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IGkgKyAxXHJcbiAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICNub3BcclxuICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAjIGNhc2UgM1xyXG4gICAgICAgICAgICAgICAgYnJlYWtcclxuICAgICAgICAgICAgICBpKytcclxuICAgICAgICAgICAgICBvID0gby5uZXh0X2NsXHJcbiAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAjICR0aGlzIGtub3dzIHRoYXQgJG8gZXhpc3RzLFxyXG4gICAgICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgICAjIG5vdyByZWNvbm5lY3QgZXZlcnl0aGluZ1xyXG4gICAgICAgICAgQG5leHRfY2wgPSBAcHJldl9jbC5uZXh0X2NsXHJcbiAgICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxyXG4gICAgICAgICAgQG5leHRfY2wucHJldl9jbCA9IEBcclxuXHJcbiAgICAgICAgQHNldFBhcmVudCBAcHJldl9jbC5nZXRQYXJlbnQoKSAjIGRvIEluc2VydGlvbnMgYWx3YXlzIGhhdmUgYSBwYXJlbnQ/XHJcbiAgICAgICAgc3VwZXIgIyBub3RpZnkgdGhlIGV4ZWN1dGlvbl9saXN0ZW5lcnNcclxuICAgICAgICBAcGFyZW50LmNhbGxPcGVyYXRpb25TcGVjaWZpY0luc2VydEV2ZW50cyh0aGlzKVxyXG4gICAgICAgIEBcclxuXHJcbiAgICAjXHJcbiAgICAjIENvbXB1dGUgdGhlIHBvc2l0aW9uIG9mIHRoaXMgb3BlcmF0aW9uLlxyXG4gICAgI1xyXG4gICAgZ2V0UG9zaXRpb246ICgpLT5cclxuICAgICAgcG9zaXRpb24gPSAwXHJcbiAgICAgIHByZXYgPSBAcHJldl9jbFxyXG4gICAgICB3aGlsZSB0cnVlXHJcbiAgICAgICAgaWYgcHJldiBpbnN0YW5jZW9mIG9wcy5EZWxpbWl0ZXJcclxuICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgaWYgbm90IHByZXYuaXNEZWxldGVkKClcclxuICAgICAgICAgIHBvc2l0aW9uKytcclxuICAgICAgICBwcmV2ID0gcHJldi5wcmV2X2NsXHJcbiAgICAgIHBvc2l0aW9uXHJcblxyXG4gICAgI1xyXG4gICAgIyBDb252ZXJ0IGFsbCByZWxldmFudCBpbmZvcm1hdGlvbiBvZiB0aGlzIG9wZXJhdGlvbiB0byB0aGUganNvbi1mb3JtYXQuXHJcbiAgICAjIFRoaXMgcmVzdWx0IGNhbiBiZSBzZW5kIHRvIG90aGVyIGNsaWVudHMuXHJcbiAgICAjXHJcbiAgICBfZW5jb2RlOiAoanNvbiA9IHt9KS0+XHJcbiAgICAgIGpzb24ucHJldiA9IEBwcmV2X2NsLmdldFVpZCgpXHJcbiAgICAgIGpzb24ubmV4dCA9IEBuZXh0X2NsLmdldFVpZCgpXHJcblxyXG4gICAgICBpZiBAb3JpZ2luLnR5cGUgaXMgXCJEZWxpbWl0ZXJcIlxyXG4gICAgICAgIGpzb24ub3JpZ2luID0gXCJEZWxpbWl0ZXJcIlxyXG4gICAgICBlbHNlIGlmIEBvcmlnaW4gaXNudCBAcHJldl9jbFxyXG4gICAgICAgIGpzb24ub3JpZ2luID0gQG9yaWdpbi5nZXRVaWQoKVxyXG5cclxuICAgICAgIyBpZiBub3QgKGpzb24ucHJldj8gYW5kIGpzb24ubmV4dD8pXHJcbiAgICAgIGpzb24ucGFyZW50ID0gQHBhcmVudC5nZXRVaWQoKVxyXG5cclxuICAgICAgc3VwZXIganNvblxyXG5cclxuICBvcHMuSW5zZXJ0LnBhcnNlID0gKGpzb24pLT5cclxuICAgIHtcclxuICAgICAgJ2NvbnRlbnQnIDogY29udGVudFxyXG4gICAgICAnY29udGVudF9vcGVyYXRpb25zJyA6IGNvbnRlbnRfb3BlcmF0aW9uc1xyXG4gICAgICAndWlkJyA6IHVpZFxyXG4gICAgICAncHJldic6IHByZXZcclxuICAgICAgJ25leHQnOiBuZXh0XHJcbiAgICAgICdvcmlnaW4nIDogb3JpZ2luXHJcbiAgICAgICdwYXJlbnQnIDogcGFyZW50XHJcbiAgICB9ID0ganNvblxyXG4gICAgbmV3IHRoaXMgbnVsbCwgY29udGVudCwgY29udGVudF9vcGVyYXRpb25zLCBwYXJlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXHJcblxyXG4gICNcclxuICAjIEBub2RvY1xyXG4gICMgQSBkZWxpbWl0ZXIgaXMgcGxhY2VkIGF0IHRoZSBlbmQgYW5kIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFzc29jaWF0aXZlIGxpc3RzLlxyXG4gICMgVGhpcyBpcyBuZWNlc3NhcnkgaW4gb3JkZXIgdG8gaGF2ZSBhIGJlZ2lubmluZyBhbmQgYW4gZW5kIGV2ZW4gaWYgdGhlIGNvbnRlbnRcclxuICAjIG9mIHRoZSBFbmdpbmUgaXMgZW1wdHkuXHJcbiAgI1xyXG4gIGNsYXNzIG9wcy5EZWxpbWl0ZXIgZXh0ZW5kcyBvcHMuT3BlcmF0aW9uXHJcbiAgICAjXHJcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cclxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IHByZXZfY2wgVGhlIHByZWRlY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcclxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG5leHRfY2wgVGhlIHN1Y2Nlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXHJcbiAgICAjXHJcbiAgICBjb25zdHJ1Y3RvcjogKHByZXZfY2wsIG5leHRfY2wsIG9yaWdpbiktPlxyXG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncHJldl9jbCcsIHByZXZfY2xcclxuICAgICAgQHNhdmVPcGVyYXRpb24gJ25leHRfY2wnLCBuZXh0X2NsXHJcbiAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBwcmV2X2NsXHJcbiAgICAgIHN1cGVyIG51bGwsIHtub09wZXJhdGlvbjogdHJ1ZX1cclxuXHJcbiAgICB0eXBlOiBcIkRlbGltaXRlclwiXHJcblxyXG4gICAgYXBwbHlEZWxldGU6ICgpLT5cclxuICAgICAgc3VwZXIoKVxyXG4gICAgICBvID0gQHByZXZfY2xcclxuICAgICAgd2hpbGUgbz9cclxuICAgICAgICBvLmFwcGx5RGVsZXRlKClcclxuICAgICAgICBvID0gby5wcmV2X2NsXHJcbiAgICAgIHVuZGVmaW5lZFxyXG5cclxuICAgIGNsZWFudXA6ICgpLT5cclxuICAgICAgc3VwZXIoKVxyXG5cclxuICAgICNcclxuICAgICMgQHByaXZhdGVcclxuICAgICNcclxuICAgIGV4ZWN1dGU6ICgpLT5cclxuICAgICAgaWYgQHVuY2hlY2tlZD9bJ25leHRfY2wnXT9cclxuICAgICAgICBzdXBlclxyXG4gICAgICBlbHNlIGlmIEB1bmNoZWNrZWQ/WydwcmV2X2NsJ11cclxuICAgICAgICBpZiBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxyXG4gICAgICAgICAgaWYgQHByZXZfY2wubmV4dF9jbD9cclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiUHJvYmFibHkgZHVwbGljYXRlZCBvcGVyYXRpb25zXCJcclxuICAgICAgICAgIEBwcmV2X2NsLm5leHRfY2wgPSBAXHJcbiAgICAgICAgICBzdXBlclxyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgIGZhbHNlXHJcbiAgICAgIGVsc2UgaWYgQHByZXZfY2w/IGFuZCBub3QgQHByZXZfY2wubmV4dF9jbD9cclxuICAgICAgICBkZWxldGUgQHByZXZfY2wudW5jaGVja2VkLm5leHRfY2xcclxuICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxyXG4gICAgICAgIHN1cGVyXHJcbiAgICAgIGVsc2UgaWYgQHByZXZfY2w/IG9yIEBuZXh0X2NsPyBvciB0cnVlICMgVE9ETzogYXJlIHlvdSBzdXJlPyBUaGlzIGNhbiBoYXBwZW4gcmlnaHQ/XHJcbiAgICAgICAgc3VwZXJcclxuICAgICAgI2Vsc2VcclxuICAgICAgIyAgdGhyb3cgbmV3IEVycm9yIFwiRGVsaW1pdGVyIGlzIHVuc3VmZmljaWVudCBkZWZpbmVkIVwiXHJcblxyXG4gICAgI1xyXG4gICAgIyBAcHJpdmF0ZVxyXG4gICAgI1xyXG4gICAgX2VuY29kZTogKCktPlxyXG4gICAgICB7XHJcbiAgICAgICAgJ3R5cGUnIDogQHR5cGVcclxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxyXG4gICAgICAgICdwcmV2JyA6IEBwcmV2X2NsPy5nZXRVaWQoKVxyXG4gICAgICAgICduZXh0JyA6IEBuZXh0X2NsPy5nZXRVaWQoKVxyXG4gICAgICB9XHJcblxyXG4gIG9wcy5EZWxpbWl0ZXIucGFyc2UgPSAoanNvbiktPlxyXG4gICAge1xyXG4gICAgJ3VpZCcgOiB1aWRcclxuICAgICdwcmV2JyA6IHByZXZcclxuICAgICduZXh0JyA6IG5leHRcclxuICAgIH0gPSBqc29uXHJcbiAgICBuZXcgdGhpcyh1aWQsIHByZXYsIG5leHQpXHJcblxyXG4gICMgVGhpcyBpcyB3aGF0IHRoaXMgbW9kdWxlIGV4cG9ydHMgYWZ0ZXIgaW5pdGlhbGl6aW5nIGl0IHdpdGggdGhlIEhpc3RvcnlCdWZmZXJcclxuICB7XHJcbiAgICAnb3BlcmF0aW9ucycgOiBvcHNcclxuICAgICdleGVjdXRpb25fbGlzdGVuZXInIDogZXhlY3V0aW9uX2xpc3RlbmVyXHJcbiAgfVxyXG4iLCJiYXNpY19vcHNfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuL0Jhc2ljXCJcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gKCktPlxyXG4gIGJhc2ljX29wcyA9IGJhc2ljX29wc191bmluaXRpYWxpemVkKClcclxuICBvcHMgPSBiYXNpY19vcHMub3BlcmF0aW9uc1xyXG5cclxuICAjXHJcbiAgIyBAbm9kb2NcclxuICAjIE1hbmFnZXMgbWFwIGxpa2Ugb2JqZWN0cy4gRS5nLiBKc29uLVR5cGUgYW5kIFhNTCBhdHRyaWJ1dGVzLlxyXG4gICNcclxuICBjbGFzcyBvcHMuTWFwTWFuYWdlciBleHRlbmRzIG9wcy5PcGVyYXRpb25cclxuXHJcbiAgICAjXHJcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cclxuICAgICNcclxuICAgIGNvbnN0cnVjdG9yOiAoY3VzdG9tX3R5cGUsIHVpZCwgY29udGVudCwgY29udGVudF9vcGVyYXRpb25zKS0+XHJcbiAgICAgIEBfbWFwID0ge31cclxuICAgICAgc3VwZXIgY3VzdG9tX3R5cGUsIHVpZCwgY29udGVudCwgY29udGVudF9vcGVyYXRpb25zXHJcblxyXG4gICAgdHlwZTogXCJNYXBNYW5hZ2VyXCJcclxuXHJcbiAgICBhcHBseURlbGV0ZTogKCktPlxyXG4gICAgICBmb3IgbmFtZSxwIG9mIEBfbWFwXHJcbiAgICAgICAgcC5hcHBseURlbGV0ZSgpXHJcbiAgICAgIHN1cGVyKClcclxuXHJcbiAgICBjbGVhbnVwOiAoKS0+XHJcbiAgICAgIHN1cGVyKClcclxuXHJcbiAgICBtYXA6IChmKS0+XHJcbiAgICAgIGZvciBuLHYgb2YgQF9tYXBcclxuICAgICAgICBmKG4sdilcclxuICAgICAgdW5kZWZpbmVkXHJcblxyXG4gICAgI1xyXG4gICAgIyBAc2VlIEpzb25PcGVyYXRpb25zLnZhbFxyXG4gICAgI1xyXG4gICAgdmFsOiAobmFtZSwgY29udGVudCktPlxyXG4gICAgICBpZiBhcmd1bWVudHMubGVuZ3RoID4gMVxyXG4gICAgICAgIGlmIGNvbnRlbnQ/IGFuZCBjb250ZW50Ll9nZXRNb2RlbD9cclxuICAgICAgICAgIHJlcCA9IGNvbnRlbnQuX2dldE1vZGVsKEBjdXN0b21fdHlwZXMsIEBvcGVyYXRpb25zKVxyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgIHJlcCA9IGNvbnRlbnRcclxuICAgICAgICBAcmV0cmlldmVTdWIobmFtZSkucmVwbGFjZSByZXBcclxuICAgICAgICBAZ2V0Q3VzdG9tVHlwZSgpXHJcbiAgICAgIGVsc2UgaWYgbmFtZT9cclxuICAgICAgICBwcm9wID0gQF9tYXBbbmFtZV1cclxuICAgICAgICBpZiBwcm9wPyBhbmQgbm90IHByb3AuaXNDb250ZW50RGVsZXRlZCgpXHJcbiAgICAgICAgICByZXMgPSBwcm9wLnZhbCgpXHJcbiAgICAgICAgICBpZiByZXMgaW5zdGFuY2VvZiBvcHMuT3BlcmF0aW9uXHJcbiAgICAgICAgICAgIHJlcy5nZXRDdXN0b21UeXBlKClcclxuICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgcmVzXHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgdW5kZWZpbmVkXHJcbiAgICAgIGVsc2VcclxuICAgICAgICByZXN1bHQgPSB7fVxyXG4gICAgICAgIGZvciBuYW1lLG8gb2YgQF9tYXBcclxuICAgICAgICAgIGlmIG5vdCBvLmlzQ29udGVudERlbGV0ZWQoKVxyXG4gICAgICAgICAgICByZXN1bHRbbmFtZV0gPSBvLnZhbCgpXHJcbiAgICAgICAgcmVzdWx0XHJcblxyXG4gICAgZGVsZXRlOiAobmFtZSktPlxyXG4gICAgICBAX21hcFtuYW1lXT8uZGVsZXRlQ29udGVudCgpXHJcbiAgICAgIEBcclxuXHJcbiAgICByZXRyaWV2ZVN1YjogKHByb3BlcnR5X25hbWUpLT5cclxuICAgICAgaWYgbm90IEBfbWFwW3Byb3BlcnR5X25hbWVdP1xyXG4gICAgICAgIGV2ZW50X3Byb3BlcnRpZXMgPVxyXG4gICAgICAgICAgbmFtZTogcHJvcGVydHlfbmFtZVxyXG4gICAgICAgIGV2ZW50X3RoaXMgPSBAXHJcbiAgICAgICAgcm1fdWlkID1cclxuICAgICAgICAgIG5vT3BlcmF0aW9uOiB0cnVlXHJcbiAgICAgICAgICBzdWI6IHByb3BlcnR5X25hbWVcclxuICAgICAgICAgIGFsdDogQFxyXG4gICAgICAgIHJtID0gbmV3IG9wcy5SZXBsYWNlTWFuYWdlciBudWxsLCBldmVudF9wcm9wZXJ0aWVzLCBldmVudF90aGlzLCBybV91aWQgIyB0aGlzIG9wZXJhdGlvbiBzaGFsbCBub3QgYmUgc2F2ZWQgaW4gdGhlIEhCXHJcbiAgICAgICAgQF9tYXBbcHJvcGVydHlfbmFtZV0gPSBybVxyXG4gICAgICAgIHJtLnNldFBhcmVudCBALCBwcm9wZXJ0eV9uYW1lXHJcbiAgICAgICAgcm0uZXhlY3V0ZSgpXHJcbiAgICAgIEBfbWFwW3Byb3BlcnR5X25hbWVdXHJcblxyXG4gIG9wcy5NYXBNYW5hZ2VyLnBhcnNlID0gKGpzb24pLT5cclxuICAgIHtcclxuICAgICAgJ3VpZCcgOiB1aWRcclxuICAgICAgJ2N1c3RvbV90eXBlJyA6IGN1c3RvbV90eXBlXHJcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcclxuICAgICAgJ2NvbnRlbnRfb3BlcmF0aW9ucycgOiBjb250ZW50X29wZXJhdGlvbnNcclxuICAgIH0gPSBqc29uXHJcbiAgICBuZXcgdGhpcyhjdXN0b21fdHlwZSwgdWlkLCBjb250ZW50LCBjb250ZW50X29wZXJhdGlvbnMpXHJcblxyXG5cclxuXHJcbiAgI1xyXG4gICMgQG5vZG9jXHJcbiAgIyBNYW5hZ2VzIGEgbGlzdCBvZiBJbnNlcnQtdHlwZSBvcGVyYXRpb25zLlxyXG4gICNcclxuICBjbGFzcyBvcHMuTGlzdE1hbmFnZXIgZXh0ZW5kcyBvcHMuT3BlcmF0aW9uXHJcblxyXG4gICAgI1xyXG4gICAgIyBBIExpc3RNYW5hZ2VyIG1haW50YWlucyBhIG5vbi1lbXB0eSBsaXN0IHRoYXQgaGFzIGEgYmVnaW5uaW5nIGFuZCBhbiBlbmQgKGJvdGggRGVsaW1pdGVycyEpXHJcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cclxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGJlZ2lubmluZyBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxyXG4gICAgIyBAcGFyYW0ge0RlbGltaXRlcn0gZW5kIFJlZmVyZW5jZSBvciBPYmplY3QuXHJcbiAgICBjb25zdHJ1Y3RvcjogKGN1c3RvbV90eXBlLCB1aWQsIGNvbnRlbnQsIGNvbnRlbnRfb3BlcmF0aW9ucyktPlxyXG4gICAgICBAYmVnaW5uaW5nID0gbmV3IG9wcy5EZWxpbWl0ZXIgdW5kZWZpbmVkLCB1bmRlZmluZWRcclxuICAgICAgQGVuZCA9ICAgICAgIG5ldyBvcHMuRGVsaW1pdGVyIEBiZWdpbm5pbmcsIHVuZGVmaW5lZFxyXG4gICAgICBAYmVnaW5uaW5nLm5leHRfY2wgPSBAZW5kXHJcbiAgICAgIEBiZWdpbm5pbmcuZXhlY3V0ZSgpXHJcbiAgICAgIEBlbmQuZXhlY3V0ZSgpXHJcbiAgICAgIHN1cGVyIGN1c3RvbV90eXBlLCB1aWQsIGNvbnRlbnQsIGNvbnRlbnRfb3BlcmF0aW9uc1xyXG5cclxuICAgIHR5cGU6IFwiTGlzdE1hbmFnZXJcIlxyXG5cclxuXHJcbiAgICBhcHBseURlbGV0ZTogKCktPlxyXG4gICAgICBvID0gQGJlZ2lubmluZ1xyXG4gICAgICB3aGlsZSBvP1xyXG4gICAgICAgIG8uYXBwbHlEZWxldGUoKVxyXG4gICAgICAgIG8gPSBvLm5leHRfY2xcclxuICAgICAgc3VwZXIoKVxyXG5cclxuICAgIGNsZWFudXA6ICgpLT5cclxuICAgICAgc3VwZXIoKVxyXG5cclxuXHJcbiAgICB0b0pzb246ICh0cmFuc2Zvcm1fdG9fdmFsdWUgPSBmYWxzZSktPlxyXG4gICAgICB2YWwgPSBAdmFsKClcclxuICAgICAgZm9yIGksIG8gaW4gdmFsXHJcbiAgICAgICAgaWYgbyBpbnN0YW5jZW9mIG9wcy5PYmplY3RcclxuICAgICAgICAgIG8udG9Kc29uKHRyYW5zZm9ybV90b192YWx1ZSlcclxuICAgICAgICBlbHNlIGlmIG8gaW5zdGFuY2VvZiBvcHMuTGlzdE1hbmFnZXJcclxuICAgICAgICAgIG8udG9Kc29uKHRyYW5zZm9ybV90b192YWx1ZSlcclxuICAgICAgICBlbHNlIGlmIHRyYW5zZm9ybV90b192YWx1ZSBhbmQgbyBpbnN0YW5jZW9mIG9wcy5PcGVyYXRpb25cclxuICAgICAgICAgIG8udmFsKClcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICBvXHJcblxyXG4gICAgI1xyXG4gICAgIyBAcHJpdmF0ZVxyXG4gICAgIyBAc2VlIE9wZXJhdGlvbi5leGVjdXRlXHJcbiAgICAjXHJcbiAgICBleGVjdXRlOiAoKS0+XHJcbiAgICAgIGlmIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXHJcbiAgICAgICAgQGJlZ2lubmluZy5zZXRQYXJlbnQgQFxyXG4gICAgICAgIEBlbmQuc2V0UGFyZW50IEBcclxuICAgICAgICBzdXBlclxyXG4gICAgICBlbHNlXHJcbiAgICAgICAgZmFsc2VcclxuXHJcbiAgICAjIEdldCB0aGUgZWxlbWVudCBwcmV2aW91cyB0byB0aGUgZGVsZW1pdGVyIGF0IHRoZSBlbmRcclxuICAgIGdldExhc3RPcGVyYXRpb246ICgpLT5cclxuICAgICAgQGVuZC5wcmV2X2NsXHJcblxyXG4gICAgIyBzaW1pbGFyIHRvIHRoZSBhYm92ZVxyXG4gICAgZ2V0Rmlyc3RPcGVyYXRpb246ICgpLT5cclxuICAgICAgQGJlZ2lubmluZy5uZXh0X2NsXHJcblxyXG4gICAgIyBUcmFuc2Zvcm1zIHRoZSB0aGUgbGlzdCB0byBhbiBhcnJheVxyXG4gICAgIyBEb2Vzbid0IHJldHVybiBsZWZ0LXJpZ2h0IGRlbGltaXRlci5cclxuICAgIHRvQXJyYXk6ICgpLT5cclxuICAgICAgbyA9IEBiZWdpbm5pbmcubmV4dF9jbFxyXG4gICAgICByZXN1bHQgPSBbXVxyXG4gICAgICB3aGlsZSBvIGlzbnQgQGVuZFxyXG4gICAgICAgIGlmIG5vdCBvLmlzX2RlbGV0ZWRcclxuICAgICAgICAgIHJlc3VsdC5wdXNoIG8udmFsKClcclxuICAgICAgICBvID0gby5uZXh0X2NsXHJcbiAgICAgIHJlc3VsdFxyXG5cclxuICAgIG1hcDogKGYpLT5cclxuICAgICAgbyA9IEBiZWdpbm5pbmcubmV4dF9jbFxyXG4gICAgICByZXN1bHQgPSBbXVxyXG4gICAgICB3aGlsZSBvIGlzbnQgQGVuZFxyXG4gICAgICAgIGlmIG5vdCBvLmlzX2RlbGV0ZWRcclxuICAgICAgICAgIHJlc3VsdC5wdXNoIGYobylcclxuICAgICAgICBvID0gby5uZXh0X2NsXHJcbiAgICAgIHJlc3VsdFxyXG5cclxuICAgIGZvbGQ6IChpbml0LCBmKS0+XHJcbiAgICAgIG8gPSBAYmVnaW5uaW5nLm5leHRfY2xcclxuICAgICAgd2hpbGUgbyBpc250IEBlbmRcclxuICAgICAgICBpZiBub3Qgby5pc19kZWxldGVkXHJcbiAgICAgICAgICBpbml0ID0gZihpbml0LCBvKVxyXG4gICAgICAgIG8gPSBvLm5leHRfY2xcclxuICAgICAgaW5pdFxyXG5cclxuICAgIHZhbDogKHBvcyktPlxyXG4gICAgICBpZiBwb3M/XHJcbiAgICAgICAgbyA9IEBnZXRPcGVyYXRpb25CeVBvc2l0aW9uKHBvcysxKVxyXG4gICAgICAgIGlmIG5vdCAobyBpbnN0YW5jZW9mIG9wcy5EZWxpbWl0ZXIpXHJcbiAgICAgICAgICBvLnZhbCgpXHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwidGhpcyBwb3NpdGlvbiBkb2VzIG5vdCBleGlzdFwiXHJcbiAgICAgIGVsc2VcclxuICAgICAgICBAdG9BcnJheSgpXHJcblxyXG4gICAgcmVmOiAocG9zKS0+XHJcbiAgICAgIGlmIHBvcz9cclxuICAgICAgICBvID0gQGdldE9wZXJhdGlvbkJ5UG9zaXRpb24ocG9zKzEpXHJcbiAgICAgICAgaWYgbm90IChvIGluc3RhbmNlb2Ygb3BzLkRlbGltaXRlcilcclxuICAgICAgICAgIG9cclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICBudWxsXHJcbiAgICAgICAgICAjIHRocm93IG5ldyBFcnJvciBcInRoaXMgcG9zaXRpb24gZG9lcyBub3QgZXhpc3RcIlxyXG4gICAgICBlbHNlXHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwieW91IG11c3Qgc3BlY2lmeSBhIHBvc2l0aW9uIHBhcmFtZXRlclwiXHJcblxyXG4gICAgI1xyXG4gICAgIyBSZXRyaWV2ZXMgdGhlIHgtdGggbm90IGRlbGV0ZWQgZWxlbWVudC5cclxuICAgICMgZS5nLiBcImFiY1wiIDogdGhlIDF0aCBjaGFyYWN0ZXIgaXMgXCJhXCJcclxuICAgICMgdGhlIDB0aCBjaGFyYWN0ZXIgaXMgdGhlIGxlZnQgRGVsaW1pdGVyXHJcbiAgICAjXHJcbiAgICBnZXRPcGVyYXRpb25CeVBvc2l0aW9uOiAocG9zaXRpb24pLT5cclxuICAgICAgbyA9IEBiZWdpbm5pbmdcclxuICAgICAgd2hpbGUgdHJ1ZVxyXG4gICAgICAgICMgZmluZCB0aGUgaS10aCBvcFxyXG4gICAgICAgIGlmIG8gaW5zdGFuY2VvZiBvcHMuRGVsaW1pdGVyIGFuZCBvLnByZXZfY2w/XHJcbiAgICAgICAgICAjIHRoZSB1c2VyIG9yIHlvdSBnYXZlIGEgcG9zaXRpb24gcGFyYW1ldGVyIHRoYXQgaXMgdG8gYmlnXHJcbiAgICAgICAgICAjIGZvciB0aGUgY3VycmVudCBhcnJheS4gVGhlcmVmb3JlIHdlIHJlYWNoIGEgRGVsaW1pdGVyLlxyXG4gICAgICAgICAgIyBUaGVuLCB3ZSdsbCBqdXN0IHJldHVybiB0aGUgbGFzdCBjaGFyYWN0ZXIuXHJcbiAgICAgICAgICBvID0gby5wcmV2X2NsXHJcbiAgICAgICAgICB3aGlsZSBvLmlzRGVsZXRlZCgpIGFuZCBvLnByZXZfY2w/XHJcbiAgICAgICAgICAgIG8gPSBvLnByZXZfY2xcclxuICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgaWYgcG9zaXRpb24gPD0gMCBhbmQgbm90IG8uaXNEZWxldGVkKClcclxuICAgICAgICAgIGJyZWFrXHJcblxyXG4gICAgICAgIG8gPSBvLm5leHRfY2xcclxuICAgICAgICBpZiBub3Qgby5pc0RlbGV0ZWQoKVxyXG4gICAgICAgICAgcG9zaXRpb24gLT0gMVxyXG4gICAgICBvXHJcblxyXG4gICAgcHVzaDogKGNvbnRlbnQpLT5cclxuICAgICAgQGluc2VydEFmdGVyIEBlbmQucHJldl9jbCwgW2NvbnRlbnRdXHJcblxyXG4gICAgaW5zZXJ0QWZ0ZXI6IChsZWZ0LCBjb250ZW50cyktPlxyXG4gICAgICByaWdodCA9IGxlZnQubmV4dF9jbFxyXG4gICAgICB3aGlsZSByaWdodC5pc0RlbGV0ZWQoKVxyXG4gICAgICAgIHJpZ2h0ID0gcmlnaHQubmV4dF9jbCAjIGZpbmQgdGhlIGZpcnN0IGNoYXJhY3RlciB0byB0aGUgcmlnaHQsIHRoYXQgaXMgbm90IGRlbGV0ZWQuIEluIHRoZSBjYXNlIHRoYXQgcG9zaXRpb24gaXMgMCwgaXRzIHRoZSBEZWxpbWl0ZXIuXHJcbiAgICAgIGxlZnQgPSByaWdodC5wcmV2X2NsXHJcblxyXG4gICAgICAjIFRPRE86IGFsd2F5cyBleHBlY3QgYW4gYXJyYXkgYXMgY29udGVudC4gVGhlbiB5b3UgY2FuIGNvbWJpbmUgdGhpcyB3aXRoIHRoZSBvdGhlciBvcHRpb24gKGVsc2UpXHJcbiAgICAgIGlmIGNvbnRlbnRzIGluc3RhbmNlb2Ygb3BzLk9wZXJhdGlvblxyXG4gICAgICAgIChuZXcgb3BzLkluc2VydCBudWxsLCBjb250ZW50LCBudWxsLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgbGVmdCwgcmlnaHQpLmV4ZWN1dGUoKVxyXG4gICAgICBlbHNlXHJcbiAgICAgICAgZm9yIGMgaW4gY29udGVudHNcclxuICAgICAgICAgIGlmIGM/IGFuZCBjLl9uYW1lPyBhbmQgYy5fZ2V0TW9kZWw/XHJcbiAgICAgICAgICAgIGMgPSBjLl9nZXRNb2RlbChAY3VzdG9tX3R5cGVzLCBAb3BlcmF0aW9ucylcclxuICAgICAgICAgIHRtcCA9IChuZXcgb3BzLkluc2VydCBudWxsLCBjLCBudWxsLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgbGVmdCwgcmlnaHQpLmV4ZWN1dGUoKVxyXG4gICAgICAgICAgbGVmdCA9IHRtcFxyXG4gICAgICBAXHJcblxyXG4gICAgI1xyXG4gICAgIyBJbnNlcnRzIGFuIGFycmF5IG9mIGNvbnRlbnQgaW50byB0aGlzIGxpc3QuXHJcbiAgICAjIEBOb3RlOiBUaGlzIGV4cGVjdHMgYW4gYXJyYXkgYXMgY29udGVudCFcclxuICAgICNcclxuICAgICMgQHJldHVybiB7TGlzdE1hbmFnZXIgVHlwZX0gVGhpcyBTdHJpbmcgb2JqZWN0LlxyXG4gICAgI1xyXG4gICAgaW5zZXJ0OiAocG9zaXRpb24sIGNvbnRlbnRzKS0+XHJcbiAgICAgIGl0aCA9IEBnZXRPcGVyYXRpb25CeVBvc2l0aW9uIHBvc2l0aW9uXHJcbiAgICAgICMgdGhlIChpLTEpdGggY2hhcmFjdGVyLiBlLmcuIFwiYWJjXCIgdGhlIDF0aCBjaGFyYWN0ZXIgaXMgXCJhXCJcclxuICAgICAgIyB0aGUgMHRoIGNoYXJhY3RlciBpcyB0aGUgbGVmdCBEZWxpbWl0ZXJcclxuICAgICAgQGluc2VydEFmdGVyIGl0aCwgY29udGVudHNcclxuXHJcbiAgICAjXHJcbiAgICAjIERlbGV0ZXMgYSBwYXJ0IG9mIHRoZSB3b3JkLlxyXG4gICAgI1xyXG4gICAgIyBAcmV0dXJuIHtMaXN0TWFuYWdlciBUeXBlfSBUaGlzIFN0cmluZyBvYmplY3RcclxuICAgICNcclxuICAgIGRlbGV0ZTogKHBvc2l0aW9uLCBsZW5ndGggPSAxKS0+XHJcbiAgICAgIG8gPSBAZ2V0T3BlcmF0aW9uQnlQb3NpdGlvbihwb3NpdGlvbisxKSAjIHBvc2l0aW9uIDAgaW4gdGhpcyBjYXNlIGlzIHRoZSBkZWxldGlvbiBvZiB0aGUgZmlyc3QgY2hhcmFjdGVyXHJcblxyXG4gICAgICBkZWxldGVfb3BzID0gW11cclxuICAgICAgZm9yIGkgaW4gWzAuLi5sZW5ndGhdXHJcbiAgICAgICAgaWYgbyBpbnN0YW5jZW9mIG9wcy5EZWxpbWl0ZXJcclxuICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgZCA9IChuZXcgb3BzLkRlbGV0ZSBudWxsLCB1bmRlZmluZWQsIG8pLmV4ZWN1dGUoKVxyXG4gICAgICAgIG8gPSBvLm5leHRfY2xcclxuICAgICAgICB3aGlsZSAobm90IChvIGluc3RhbmNlb2Ygb3BzLkRlbGltaXRlcikpIGFuZCBvLmlzRGVsZXRlZCgpXHJcbiAgICAgICAgICBvID0gby5uZXh0X2NsXHJcbiAgICAgICAgZGVsZXRlX29wcy5wdXNoIGQuX2VuY29kZSgpXHJcbiAgICAgIEBcclxuXHJcblxyXG4gICAgY2FsbE9wZXJhdGlvblNwZWNpZmljSW5zZXJ0RXZlbnRzOiAob3ApLT5cclxuICAgICAgZ2V0Q29udGVudFR5cGUgPSAoY29udGVudCktPlxyXG4gICAgICAgIGlmIGNvbnRlbnQgaW5zdGFuY2VvZiBvcHMuT3BlcmF0aW9uXHJcbiAgICAgICAgICBjb250ZW50LmdldEN1c3RvbVR5cGUoKVxyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgIGNvbnRlbnRcclxuICAgICAgQGNhbGxFdmVudCBbXHJcbiAgICAgICAgdHlwZTogXCJpbnNlcnRcIlxyXG4gICAgICAgIHJlZmVyZW5jZTogb3BcclxuICAgICAgICBwb3NpdGlvbjogb3AuZ2V0UG9zaXRpb24oKVxyXG4gICAgICAgIG9iamVjdDogQGdldEN1c3RvbVR5cGUoKVxyXG4gICAgICAgIGNoYW5nZWRCeTogb3AudWlkLmNyZWF0b3JcclxuICAgICAgICB2YWx1ZTogZ2V0Q29udGVudFR5cGUgb3AudmFsKClcclxuICAgICAgXVxyXG5cclxuICAgIGNhbGxPcGVyYXRpb25TcGVjaWZpY0RlbGV0ZUV2ZW50czogKG9wLCBkZWxfb3ApLT5cclxuICAgICAgQGNhbGxFdmVudCBbXHJcbiAgICAgICAgdHlwZTogXCJkZWxldGVcIlxyXG4gICAgICAgIHJlZmVyZW5jZTogb3BcclxuICAgICAgICBwb3NpdGlvbjogb3AuZ2V0UG9zaXRpb24oKVxyXG4gICAgICAgIG9iamVjdDogQGdldEN1c3RvbVR5cGUoKSAjIFRPRE86IFlvdSBjYW4gY29tYmluZSBnZXRQb3NpdGlvbiArIGdldFBhcmVudCBpbiBhIG1vcmUgZWZmaWNpZW50IG1hbm5lciEgKG9ubHkgbGVmdCBEZWxpbWl0ZXIgd2lsbCBob2xkIEBwYXJlbnQpXHJcbiAgICAgICAgbGVuZ3RoOiAxXHJcbiAgICAgICAgY2hhbmdlZEJ5OiBkZWxfb3AudWlkLmNyZWF0b3JcclxuICAgICAgICBvbGRWYWx1ZTogb3AudmFsKClcclxuICAgICAgXVxyXG5cclxuICBvcHMuTGlzdE1hbmFnZXIucGFyc2UgPSAoanNvbiktPlxyXG4gICAge1xyXG4gICAgICAndWlkJyA6IHVpZFxyXG4gICAgICAnY3VzdG9tX3R5cGUnOiBjdXN0b21fdHlwZVxyXG4gICAgICAnY29udGVudCcgOiBjb250ZW50XHJcbiAgICAgICdjb250ZW50X29wZXJhdGlvbnMnIDogY29udGVudF9vcGVyYXRpb25zXHJcbiAgICB9ID0ganNvblxyXG4gICAgbmV3IHRoaXMoY3VzdG9tX3R5cGUsIHVpZCwgY29udGVudCwgY29udGVudF9vcGVyYXRpb25zKVxyXG5cclxuICBjbGFzcyBvcHMuQ29tcG9zaXRpb24gZXh0ZW5kcyBvcHMuTGlzdE1hbmFnZXJcclxuXHJcbiAgICBjb25zdHJ1Y3RvcjogKGN1c3RvbV90eXBlLCBAX2NvbXBvc2l0aW9uX3ZhbHVlLCBjb21wb3NpdGlvbl92YWx1ZV9vcGVyYXRpb25zLCB1aWQsIHRtcF9jb21wb3NpdGlvbl9yZWYpLT5cclxuICAgICAgIyB3ZSBjYW4ndCB1c2UgQHNldmVPcGVyYXRpb24gJ2NvbXBvc2l0aW9uX3JlZicsIHRtcF9jb21wb3NpdGlvbl9yZWYgaGVyZSxcclxuICAgICAgIyBiZWNhdXNlIHRoZW4gdGhlcmUgaXMgYSBcImxvb3BcIiAoaW5zZXJ0aW9uIHJlZmVycyB0byBwYXJlbnQsIHJlZmVycyB0byBpbnNlcnRpb24uLilcclxuICAgICAgIyBUaGlzIGlzIHdoeSB3ZSBoYXZlIHRvIGNoZWNrIGluIEBjYWxsT3BlcmF0aW9uU3BlY2lmaWNJbnNlcnRFdmVudHMgdW50aWwgd2UgZmluZCBpdFxyXG4gICAgICBzdXBlciBjdXN0b21fdHlwZSwgdWlkXHJcbiAgICAgIGlmIHRtcF9jb21wb3NpdGlvbl9yZWY/XHJcbiAgICAgICAgQHRtcF9jb21wb3NpdGlvbl9yZWYgPSB0bXBfY29tcG9zaXRpb25fcmVmXHJcbiAgICAgIGVsc2VcclxuICAgICAgICBAY29tcG9zaXRpb25fcmVmID0gQGVuZC5wcmV2X2NsXHJcbiAgICAgIGlmIGNvbXBvc2l0aW9uX3ZhbHVlX29wZXJhdGlvbnM/XHJcbiAgICAgICAgQGNvbXBvc2l0aW9uX3ZhbHVlX29wZXJhdGlvbnMgPSB7fVxyXG4gICAgICAgIGZvciBuLG8gb2YgY29tcG9zaXRpb25fdmFsdWVfb3BlcmF0aW9uc1xyXG4gICAgICAgICAgQHNhdmVPcGVyYXRpb24gbiwgbywgJ19jb21wb3NpdGlvbl92YWx1ZSdcclxuXHJcbiAgICB0eXBlOiBcIkNvbXBvc2l0aW9uXCJcclxuXHJcbiAgICAjXHJcbiAgICAjIEBwcml2YXRlXHJcbiAgICAjIEBzZWUgT3BlcmF0aW9uLmV4ZWN1dGVcclxuICAgICNcclxuICAgIGV4ZWN1dGU6ICgpLT5cclxuICAgICAgaWYgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcclxuICAgICAgICBAZ2V0Q3VzdG9tVHlwZSgpLl9zZXRDb21wb3NpdGlvblZhbHVlIEBfY29tcG9zaXRpb25fdmFsdWVcclxuICAgICAgICBkZWxldGUgQF9jb21wb3NpdGlvbl92YWx1ZVxyXG4gICAgICAgIHN1cGVyXHJcbiAgICAgIGVsc2VcclxuICAgICAgICBmYWxzZVxyXG5cclxuICAgICNcclxuICAgICMgVGhpcyBpcyBjYWxsZWQsIHdoZW4gdGhlIEluc2VydC1vcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWxseSBleGVjdXRlZC5cclxuICAgICNcclxuICAgIGNhbGxPcGVyYXRpb25TcGVjaWZpY0luc2VydEV2ZW50czogKG9wKS0+XHJcbiAgICAgIGlmIEB0bXBfY29tcG9zaXRpb25fcmVmP1xyXG4gICAgICAgIGlmIG9wLnVpZC5jcmVhdG9yIGlzIEB0bXBfY29tcG9zaXRpb25fcmVmLmNyZWF0b3IgYW5kIG9wLnVpZC5vcF9udW1iZXIgaXMgQHRtcF9jb21wb3NpdGlvbl9yZWYub3BfbnVtYmVyXHJcbiAgICAgICAgICBAY29tcG9zaXRpb25fcmVmID0gb3BcclxuICAgICAgICAgIGRlbGV0ZSBAdG1wX2NvbXBvc2l0aW9uX3JlZlxyXG4gICAgICAgICAgbyA9IG9wLm5leHRfY2xcclxuICAgICAgICAgIHdoaWxlIG8ubmV4dF9jbD9cclxuICAgICAgICAgICAgaWYgbm90IG8uaXNEZWxldGVkKClcclxuICAgICAgICAgICAgICBAY2FsbE9wZXJhdGlvblNwZWNpZmljSW5zZXJ0RXZlbnRzIG9cclxuICAgICAgICAgICAgbyA9IG8ubmV4dF9jbFxyXG4gICAgICAgIHJldHVyblxyXG5cclxuICAgICAgaWYgQGNvbXBvc2l0aW9uX3JlZi5uZXh0X2NsIGlzIG9wXHJcbiAgICAgICAgb3AudW5kb19kZWx0YSA9IEBnZXRDdXN0b21UeXBlKCkuX2FwcGx5IG9wLnZhbCgpXHJcbiAgICAgIGVsc2VcclxuICAgICAgICBvID0gQGVuZC5wcmV2X2NsXHJcbiAgICAgICAgd2hpbGUgbyBpc250IG9wXHJcbiAgICAgICAgICBAZ2V0Q3VzdG9tVHlwZSgpLl91bmFwcGx5IG8udW5kb19kZWx0YVxyXG4gICAgICAgICAgbyA9IG8ucHJldl9jbFxyXG4gICAgICAgIHdoaWxlIG8gaXNudCBAZW5kXHJcbiAgICAgICAgICBvLnVuZG9fZGVsdGEgPSBAZ2V0Q3VzdG9tVHlwZSgpLl9hcHBseSBvLnZhbCgpXHJcbiAgICAgICAgICBvID0gby5uZXh0X2NsXHJcbiAgICAgIEBjb21wb3NpdGlvbl9yZWYgPSBAZW5kLnByZXZfY2xcclxuXHJcbiAgICAgIEBjYWxsRXZlbnQgW1xyXG4gICAgICAgIHR5cGU6IFwidXBkYXRlXCJcclxuICAgICAgICBjaGFuZ2VkQnk6IG9wLnVpZC5jcmVhdG9yXHJcbiAgICAgICAgbmV3VmFsdWU6IEB2YWwoKVxyXG4gICAgICBdXHJcblxyXG4gICAgY2FsbE9wZXJhdGlvblNwZWNpZmljRGVsZXRlRXZlbnRzOiAob3AsIGRlbF9vcCktPlxyXG4gICAgICByZXR1cm5cclxuXHJcbiAgICAjXHJcbiAgICAjIENyZWF0ZSBhIG5ldyBEZWx0YVxyXG4gICAgIyAtIGluc2VydHMgbmV3IENvbnRlbnQgYXQgdGhlIGVuZCBvZiB0aGUgbGlzdFxyXG4gICAgIyAtIHVwZGF0ZXMgdGhlIGNvbXBvc2l0aW9uX3ZhbHVlXHJcbiAgICAjIC0gdXBkYXRlcyB0aGUgY29tcG9zaXRpb25fcmVmXHJcbiAgICAjXHJcbiAgICAjIEBwYXJhbSBkZWx0YSBUaGUgZGVsdGEgdGhhdCBpcyBhcHBsaWVkIHRvIHRoZSBjb21wb3NpdGlvbl92YWx1ZVxyXG4gICAgI1xyXG4gICAgYXBwbHlEZWx0YTogKGRlbHRhLCBvcGVyYXRpb25zKS0+XHJcbiAgICAgIChuZXcgb3BzLkluc2VydCBudWxsLCBkZWx0YSwgb3BlcmF0aW9ucywgQCwgbnVsbCwgQGVuZC5wcmV2X2NsLCBAZW5kKS5leGVjdXRlKClcclxuICAgICAgdW5kZWZpbmVkXHJcblxyXG4gICAgI1xyXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxyXG4gICAgI1xyXG4gICAgX2VuY29kZTogKGpzb24gPSB7fSktPlxyXG4gICAgICBjdXN0b20gPSBAZ2V0Q3VzdG9tVHlwZSgpLl9nZXRDb21wb3NpdGlvblZhbHVlKClcclxuICAgICAganNvbi5jb21wb3NpdGlvbl92YWx1ZSA9IGN1c3RvbS5jb21wb3NpdGlvbl92YWx1ZVxyXG4gICAgICBpZiBjdXN0b20uY29tcG9zaXRpb25fdmFsdWVfb3BlcmF0aW9ucz9cclxuICAgICAgICBqc29uLmNvbXBvc2l0aW9uX3ZhbHVlX29wZXJhdGlvbnMgPSB7fVxyXG4gICAgICAgIGZvciBuLG8gb2YgY3VzdG9tLmNvbXBvc2l0aW9uX3ZhbHVlX29wZXJhdGlvbnNcclxuICAgICAgICAgIGpzb24uY29tcG9zaXRpb25fdmFsdWVfb3BlcmF0aW9uc1tuXSA9IG8uZ2V0VWlkKClcclxuICAgICAgaWYgQGNvbXBvc2l0aW9uX3JlZj9cclxuICAgICAgICBqc29uLmNvbXBvc2l0aW9uX3JlZiA9IEBjb21wb3NpdGlvbl9yZWYuZ2V0VWlkKClcclxuICAgICAgZWxzZVxyXG4gICAgICAgIGpzb24uY29tcG9zaXRpb25fcmVmID0gQHRtcF9jb21wb3NpdGlvbl9yZWZcclxuICAgICAgc3VwZXIganNvblxyXG5cclxuICBvcHMuQ29tcG9zaXRpb24ucGFyc2UgPSAoanNvbiktPlxyXG4gICAge1xyXG4gICAgICAndWlkJyA6IHVpZFxyXG4gICAgICAnY3VzdG9tX3R5cGUnOiBjdXN0b21fdHlwZVxyXG4gICAgICAnY29tcG9zaXRpb25fdmFsdWUnIDogY29tcG9zaXRpb25fdmFsdWVcclxuICAgICAgJ2NvbXBvc2l0aW9uX3ZhbHVlX29wZXJhdGlvbnMnIDogY29tcG9zaXRpb25fdmFsdWVfb3BlcmF0aW9uc1xyXG4gICAgICAnY29tcG9zaXRpb25fcmVmJyA6IGNvbXBvc2l0aW9uX3JlZlxyXG4gICAgfSA9IGpzb25cclxuICAgIG5ldyB0aGlzKGN1c3RvbV90eXBlLCBjb21wb3NpdGlvbl92YWx1ZSwgY29tcG9zaXRpb25fdmFsdWVfb3BlcmF0aW9ucywgdWlkLCBjb21wb3NpdGlvbl9yZWYpXHJcblxyXG5cclxuICAjXHJcbiAgIyBAbm9kb2NcclxuICAjIEFkZHMgc3VwcG9ydCBmb3IgcmVwbGFjZS4gVGhlIFJlcGxhY2VNYW5hZ2VyIG1hbmFnZXMgUmVwbGFjZWFibGUgb3BlcmF0aW9ucy5cclxuICAjIEVhY2ggUmVwbGFjZWFibGUgaG9sZHMgYSB2YWx1ZSB0aGF0IGlzIG5vdyByZXBsYWNlYWJsZS5cclxuICAjXHJcbiAgIyBUaGUgVGV4dFR5cGUtdHlwZSBoYXMgaW1wbGVtZW50ZWQgc3VwcG9ydCBmb3IgcmVwbGFjZVxyXG4gICMgQHNlZSBUZXh0VHlwZVxyXG4gICNcclxuICBjbGFzcyBvcHMuUmVwbGFjZU1hbmFnZXIgZXh0ZW5kcyBvcHMuTGlzdE1hbmFnZXJcclxuICAgICNcclxuICAgICMgQHBhcmFtIHtPYmplY3R9IGV2ZW50X3Byb3BlcnRpZXMgRGVjb3JhdGVzIHRoZSBldmVudCB0aGF0IGlzIHRocm93biBieSB0aGUgUk1cclxuICAgICMgQHBhcmFtIHtPYmplY3R9IGV2ZW50X3RoaXMgVGhlIG9iamVjdCBvbiB3aGljaCB0aGUgZXZlbnQgc2hhbGwgYmUgZXhlY3V0ZWRcclxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IGluaXRpYWxfY29udGVudCBJbml0aWFsaXplIHRoaXMgd2l0aCBhIFJlcGxhY2VhYmxlIHRoYXQgaG9sZHMgdGhlIGluaXRpYWxfY29udGVudC5cclxuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxyXG4gICAgIyBAcGFyYW0ge0RlbGltaXRlcn0gYmVnaW5uaW5nIFJlZmVyZW5jZSBvciBPYmplY3QuXHJcbiAgICAjIEBwYXJhbSB7RGVsaW1pdGVyfSBlbmQgUmVmZXJlbmNlIG9yIE9iamVjdC5cclxuICAgIGNvbnN0cnVjdG9yOiAoY3VzdG9tX3R5cGUsIEBldmVudF9wcm9wZXJ0aWVzLCBAZXZlbnRfdGhpcywgdWlkKS0+XHJcbiAgICAgIGlmIG5vdCBAZXZlbnRfcHJvcGVydGllc1snb2JqZWN0J10/XHJcbiAgICAgICAgQGV2ZW50X3Byb3BlcnRpZXNbJ29iamVjdCddID0gQGV2ZW50X3RoaXMuZ2V0Q3VzdG9tVHlwZSgpXHJcbiAgICAgIHN1cGVyIGN1c3RvbV90eXBlLCB1aWRcclxuXHJcbiAgICB0eXBlOiBcIlJlcGxhY2VNYW5hZ2VyXCJcclxuXHJcbiAgICAjXHJcbiAgICAjIFRoaXMgZG9lc24ndCB0aHJvdyB0aGUgc2FtZSBldmVudHMgYXMgdGhlIExpc3RNYW5hZ2VyLiBUaGVyZWZvcmUsIHRoZVxyXG4gICAgIyBSZXBsYWNlYWJsZXMgYWxzbyBub3QgdGhyb3cgdGhlIHNhbWUgZXZlbnRzLlxyXG4gICAgIyBTbywgUmVwbGFjZU1hbmFnZXIgYW5kIExpc3RNYW5hZ2VyIGJvdGggaW1wbGVtZW50XHJcbiAgICAjIHRoZXNlIGZ1bmN0aW9ucyB0aGF0IGFyZSBjYWxsZWQgd2hlbiBhbiBJbnNlcnRpb24gaXMgZXhlY3V0ZWQgKGF0IHRoZSBlbmQpLlxyXG4gICAgI1xyXG4gICAgI1xyXG4gICAgY2FsbEV2ZW50RGVjb3JhdG9yOiAoZXZlbnRzKS0+XHJcbiAgICAgIGlmIG5vdCBAaXNEZWxldGVkKClcclxuICAgICAgICBmb3IgZXZlbnQgaW4gZXZlbnRzXHJcbiAgICAgICAgICBmb3IgbmFtZSxwcm9wIG9mIEBldmVudF9wcm9wZXJ0aWVzXHJcbiAgICAgICAgICAgIGV2ZW50W25hbWVdID0gcHJvcFxyXG4gICAgICAgIEBldmVudF90aGlzLmNhbGxFdmVudCBldmVudHNcclxuICAgICAgdW5kZWZpbmVkXHJcblxyXG4gICAgI1xyXG4gICAgIyBUaGlzIGlzIGNhbGxlZCwgd2hlbiB0aGUgSW5zZXJ0LXR5cGUgd2FzIHN1Y2Nlc3NmdWxseSBleGVjdXRlZC5cclxuICAgICMgVE9ETzogY29uc2lkZXIgZG9pbmcgdGhpcyBpbiBhIG1vcmUgY29uc2lzdGVudCBtYW5uZXIuIFRoaXMgY291bGQgYWxzbyBiZVxyXG4gICAgIyBkb25lIHdpdGggZXhlY3V0ZS4gQnV0IGN1cnJlbnRseSwgdGhlcmUgYXJlIG5vIHNwZWNpdGFsIEluc2VydC1vcHMgZm9yIExpc3RNYW5hZ2VyLlxyXG4gICAgI1xyXG4gICAgY2FsbE9wZXJhdGlvblNwZWNpZmljSW5zZXJ0RXZlbnRzOiAob3ApLT5cclxuICAgICAgaWYgb3AubmV4dF9jbC50eXBlIGlzIFwiRGVsaW1pdGVyXCIgYW5kIG9wLnByZXZfY2wudHlwZSBpc250IFwiRGVsaW1pdGVyXCJcclxuICAgICAgICAjIHRoaXMgcmVwbGFjZXMgYW5vdGhlciBSZXBsYWNlYWJsZVxyXG4gICAgICAgIGlmIG5vdCBvcC5pc19kZWxldGVkICMgV2hlbiB0aGlzIGlzIHJlY2VpdmVkIGZyb20gdGhlIEhCLCB0aGlzIGNvdWxkIGFscmVhZHkgYmUgZGVsZXRlZCFcclxuICAgICAgICAgIG9sZF92YWx1ZSA9IG9wLnByZXZfY2wudmFsKClcclxuICAgICAgICAgIEBjYWxsRXZlbnREZWNvcmF0b3IgW1xyXG4gICAgICAgICAgICB0eXBlOiBcInVwZGF0ZVwiXHJcbiAgICAgICAgICAgIGNoYW5nZWRCeTogb3AudWlkLmNyZWF0b3JcclxuICAgICAgICAgICAgb2xkVmFsdWU6IG9sZF92YWx1ZVxyXG4gICAgICAgICAgXVxyXG4gICAgICAgIG9wLnByZXZfY2wuYXBwbHlEZWxldGUoKVxyXG4gICAgICBlbHNlIGlmIG9wLm5leHRfY2wudHlwZSBpc250IFwiRGVsaW1pdGVyXCJcclxuICAgICAgICAjIFRoaXMgd29uJ3QgYmUgcmVjb2duaXplZCBieSB0aGUgdXNlciwgYmVjYXVzZSBhbm90aGVyXHJcbiAgICAgICAgIyBjb25jdXJyZW50IG9wZXJhdGlvbiBpcyBzZXQgYXMgdGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIFJNXHJcbiAgICAgICAgb3AuYXBwbHlEZWxldGUoKVxyXG4gICAgICBlbHNlICMgcHJldiBfYW5kXyBuZXh0IGFyZSBEZWxpbWl0ZXJzLiBUaGlzIGlzIHRoZSBmaXJzdCBjcmVhdGVkIFJlcGxhY2VhYmxlIGluIHRoZSBSTVxyXG4gICAgICAgIEBjYWxsRXZlbnREZWNvcmF0b3IgW1xyXG4gICAgICAgICAgdHlwZTogXCJhZGRcIlxyXG4gICAgICAgICAgY2hhbmdlZEJ5OiBvcC51aWQuY3JlYXRvclxyXG4gICAgICAgIF1cclxuICAgICAgdW5kZWZpbmVkXHJcblxyXG4gICAgY2FsbE9wZXJhdGlvblNwZWNpZmljRGVsZXRlRXZlbnRzOiAob3AsIGRlbF9vcCktPlxyXG4gICAgICBpZiBvcC5uZXh0X2NsLnR5cGUgaXMgXCJEZWxpbWl0ZXJcIlxyXG4gICAgICAgIEBjYWxsRXZlbnREZWNvcmF0b3IgW1xyXG4gICAgICAgICAgdHlwZTogXCJkZWxldGVcIlxyXG4gICAgICAgICAgY2hhbmdlZEJ5OiBkZWxfb3AudWlkLmNyZWF0b3JcclxuICAgICAgICAgIG9sZFZhbHVlOiBvcC52YWwoKVxyXG4gICAgICAgIF1cclxuXHJcblxyXG4gICAgI1xyXG4gICAgIyBSZXBsYWNlIHRoZSBleGlzdGluZyB3b3JkIHdpdGggYSBuZXcgd29yZC5cclxuICAgICNcclxuICAgICMgQHBhcmFtIGNvbnRlbnQge09wZXJhdGlvbn0gVGhlIG5ldyB2YWx1ZSBvZiB0aGlzIFJlcGxhY2VNYW5hZ2VyLlxyXG4gICAgIyBAcGFyYW0gcmVwbGFjZWFibGVfdWlkIHtVSUR9IE9wdGlvbmFsOiBVbmlxdWUgaWQgb2YgdGhlIFJlcGxhY2VhYmxlIHRoYXQgaXMgY3JlYXRlZFxyXG4gICAgI1xyXG4gICAgcmVwbGFjZTogKGNvbnRlbnQsIHJlcGxhY2VhYmxlX3VpZCktPlxyXG4gICAgICBvID0gQGdldExhc3RPcGVyYXRpb24oKVxyXG4gICAgICByZWxwID0gKG5ldyBvcHMuSW5zZXJ0IG51bGwsIGNvbnRlbnQsIG51bGwsIEAsIHJlcGxhY2VhYmxlX3VpZCwgbywgby5uZXh0X2NsKS5leGVjdXRlKClcclxuICAgICAgIyBUT0RPOiBkZWxldGUgcmVwbCAoZm9yIGRlYnVnZ2luZylcclxuICAgICAgdW5kZWZpbmVkXHJcblxyXG4gICAgaXNDb250ZW50RGVsZXRlZDogKCktPlxyXG4gICAgICBAZ2V0TGFzdE9wZXJhdGlvbigpLmlzRGVsZXRlZCgpXHJcblxyXG4gICAgZGVsZXRlQ29udGVudDogKCktPlxyXG4gICAgICAobmV3IG9wcy5EZWxldGUgbnVsbCwgdW5kZWZpbmVkLCBAZ2V0TGFzdE9wZXJhdGlvbigpLnVpZCkuZXhlY3V0ZSgpXHJcbiAgICAgIHVuZGVmaW5lZFxyXG5cclxuICAgICNcclxuICAgICMgR2V0IHRoZSB2YWx1ZSBvZiB0aGlzXHJcbiAgICAjIEByZXR1cm4ge1N0cmluZ31cclxuICAgICNcclxuICAgIHZhbDogKCktPlxyXG4gICAgICBvID0gQGdldExhc3RPcGVyYXRpb24oKVxyXG4gICAgICAjaWYgbyBpbnN0YW5jZW9mIG9wcy5EZWxpbWl0ZXJcclxuICAgICAgICAjIHRocm93IG5ldyBFcnJvciBcIlJlcGxhY2UgTWFuYWdlciBkb2Vzbid0IGNvbnRhaW4gYW55dGhpbmcuXCJcclxuICAgICAgby52YWw/KCkgIyA/IC0gZm9yIHRoZSBjYXNlIHRoYXQgKGN1cnJlbnRseSkgdGhlIFJNIGRvZXMgbm90IGNvbnRhaW4gYW55dGhpbmcgKHRoZW4gbyBpcyBhIERlbGltaXRlcilcclxuXHJcblxyXG5cclxuICBiYXNpY19vcHNcclxuIiwiXHJcbnN0cnVjdHVyZWRfb3BzX3VuaW5pdGlhbGl6ZWQgPSByZXF1aXJlIFwiLi9PcGVyYXRpb25zL1N0cnVjdHVyZWRcIlxyXG5cclxuSGlzdG9yeUJ1ZmZlciA9IHJlcXVpcmUgXCIuL0hpc3RvcnlCdWZmZXJcIlxyXG5FbmdpbmUgPSByZXF1aXJlIFwiLi9FbmdpbmVcIlxyXG5hZGFwdENvbm5lY3RvciA9IHJlcXVpcmUgXCIuL0Nvbm5lY3RvckFkYXB0ZXJcIlxyXG5cclxuY3JlYXRlWSA9IChjb25uZWN0b3IpLT5cclxuICB1c2VyX2lkID0gbnVsbFxyXG4gIGlmIGNvbm5lY3Rvci51c2VyX2lkP1xyXG4gICAgdXNlcl9pZCA9IGNvbm5lY3Rvci51c2VyX2lkICMgVE9ETzogY2hhbmdlIHRvIGdldFVuaXF1ZUlkKClcclxuICBlbHNlXHJcbiAgICB1c2VyX2lkID0gXCJfdGVtcFwiXHJcbiAgICBjb25uZWN0b3Iub25fdXNlcl9pZF9zZXQgPSAoaWQpLT5cclxuICAgICAgdXNlcl9pZCA9IGlkXHJcbiAgICAgIEhCLnJlc2V0VXNlcklkIGlkXHJcbiAgSEIgPSBuZXcgSGlzdG9yeUJ1ZmZlciB1c2VyX2lkXHJcbiAgb3BzX21hbmFnZXIgPSBzdHJ1Y3R1cmVkX29wc191bmluaXRpYWxpemVkIEhCLCB0aGlzLmNvbnN0cnVjdG9yXHJcbiAgb3BzID0gb3BzX21hbmFnZXIub3BlcmF0aW9uc1xyXG5cclxuICBlbmdpbmUgPSBuZXcgRW5naW5lIEhCLCBvcHNcclxuICBhZGFwdENvbm5lY3RvciBjb25uZWN0b3IsIGVuZ2luZSwgSEIsIG9wc19tYW5hZ2VyLmV4ZWN1dGlvbl9saXN0ZW5lclxyXG5cclxuICBvcHMuT3BlcmF0aW9uLnByb3RvdHlwZS5IQiA9IEhCXHJcbiAgb3BzLk9wZXJhdGlvbi5wcm90b3R5cGUub3BlcmF0aW9ucyA9IG9wc1xyXG4gIG9wcy5PcGVyYXRpb24ucHJvdG90eXBlLmVuZ2luZSA9IGVuZ2luZVxyXG4gIG9wcy5PcGVyYXRpb24ucHJvdG90eXBlLmNvbm5lY3RvciA9IGNvbm5lY3RvclxyXG4gIG9wcy5PcGVyYXRpb24ucHJvdG90eXBlLmN1c3RvbV90eXBlcyA9IHRoaXMuY29uc3RydWN0b3JcclxuXHJcbiAgY3QgPSBuZXcgY3JlYXRlWS5PYmplY3QoKVxyXG4gIG1vZGVsID0gbmV3IG9wcy5NYXBNYW5hZ2VyKGN0LCBIQi5nZXRSZXNlcnZlZFVuaXF1ZUlkZW50aWZpZXIoKSkuZXhlY3V0ZSgpXHJcbiAgY3QuX3NldE1vZGVsIG1vZGVsXHJcbiAgY3RcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlWVxyXG5pZiB3aW5kb3c/XHJcbiAgd2luZG93LlkgPSBjcmVhdGVZXHJcblxyXG5jcmVhdGVZLk9iamVjdCA9IHJlcXVpcmUgXCIuL09iamVjdFR5cGVcIlxyXG4iLCIvKiFcbiAqIFRoZSBidWZmZXIgbW9kdWxlIGZyb20gbm9kZS5qcywgZm9yIHRoZSBicm93c2VyLlxuICpcbiAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxmZXJvc3NAZmVyb3NzLm9yZz4gPGh0dHA6Ly9mZXJvc3Mub3JnPlxuICogQGxpY2Vuc2UgIE1JVFxuICovXG5cbnZhciBiYXNlNjQgPSByZXF1aXJlKCdiYXNlNjQtanMnKVxudmFyIGllZWU3NTQgPSByZXF1aXJlKCdpZWVlNzU0JylcblxuZXhwb3J0cy5CdWZmZXIgPSBCdWZmZXJcbmV4cG9ydHMuU2xvd0J1ZmZlciA9IEJ1ZmZlclxuZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFUyA9IDUwXG5CdWZmZXIucG9vbFNpemUgPSA4MTkyXG5cbi8qKlxuICogSWYgYEJ1ZmZlci5fdXNlVHlwZWRBcnJheXNgOlxuICogICA9PT0gdHJ1ZSAgICBVc2UgVWludDhBcnJheSBpbXBsZW1lbnRhdGlvbiAoZmFzdGVzdClcbiAqICAgPT09IGZhbHNlICAgVXNlIE9iamVjdCBpbXBsZW1lbnRhdGlvbiAoY29tcGF0aWJsZSBkb3duIHRvIElFNilcbiAqL1xuQnVmZmVyLl91c2VUeXBlZEFycmF5cyA9IChmdW5jdGlvbiAoKSB7XG4gIC8vIERldGVjdCBpZiBicm93c2VyIHN1cHBvcnRzIFR5cGVkIEFycmF5cy4gU3VwcG9ydGVkIGJyb3dzZXJzIGFyZSBJRSAxMCssIEZpcmVmb3ggNCssXG4gIC8vIENocm9tZSA3KywgU2FmYXJpIDUuMSssIE9wZXJhIDExLjYrLCBpT1MgNC4yKy4gSWYgdGhlIGJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBhZGRpbmdcbiAgLy8gcHJvcGVydGllcyB0byBgVWludDhBcnJheWAgaW5zdGFuY2VzLCB0aGVuIHRoYXQncyB0aGUgc2FtZSBhcyBubyBgVWludDhBcnJheWAgc3VwcG9ydFxuICAvLyBiZWNhdXNlIHdlIG5lZWQgdG8gYmUgYWJsZSB0byBhZGQgYWxsIHRoZSBub2RlIEJ1ZmZlciBBUEkgbWV0aG9kcy4gVGhpcyBpcyBhbiBpc3N1ZVxuICAvLyBpbiBGaXJlZm94IDQtMjkuIE5vdyBmaXhlZDogaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9Njk1NDM4XG4gIHRyeSB7XG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcigwKVxuICAgIHZhciBhcnIgPSBuZXcgVWludDhBcnJheShidWYpXG4gICAgYXJyLmZvbyA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIDQyIH1cbiAgICByZXR1cm4gNDIgPT09IGFyci5mb28oKSAmJlxuICAgICAgICB0eXBlb2YgYXJyLnN1YmFycmF5ID09PSAnZnVuY3Rpb24nIC8vIENocm9tZSA5LTEwIGxhY2sgYHN1YmFycmF5YFxuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbn0pKClcblxuLyoqXG4gKiBDbGFzczogQnVmZmVyXG4gKiA9PT09PT09PT09PT09XG4gKlxuICogVGhlIEJ1ZmZlciBjb25zdHJ1Y3RvciByZXR1cm5zIGluc3RhbmNlcyBvZiBgVWludDhBcnJheWAgdGhhdCBhcmUgYXVnbWVudGVkXG4gKiB3aXRoIGZ1bmN0aW9uIHByb3BlcnRpZXMgZm9yIGFsbCB0aGUgbm9kZSBgQnVmZmVyYCBBUEkgZnVuY3Rpb25zLiBXZSB1c2VcbiAqIGBVaW50OEFycmF5YCBzbyB0aGF0IHNxdWFyZSBicmFja2V0IG5vdGF0aW9uIHdvcmtzIGFzIGV4cGVjdGVkIC0tIGl0IHJldHVybnNcbiAqIGEgc2luZ2xlIG9jdGV0LlxuICpcbiAqIEJ5IGF1Z21lbnRpbmcgdGhlIGluc3RhbmNlcywgd2UgY2FuIGF2b2lkIG1vZGlmeWluZyB0aGUgYFVpbnQ4QXJyYXlgXG4gKiBwcm90b3R5cGUuXG4gKi9cbmZ1bmN0aW9uIEJ1ZmZlciAoc3ViamVjdCwgZW5jb2RpbmcsIG5vWmVybykge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgQnVmZmVyKSlcbiAgICByZXR1cm4gbmV3IEJ1ZmZlcihzdWJqZWN0LCBlbmNvZGluZywgbm9aZXJvKVxuXG4gIHZhciB0eXBlID0gdHlwZW9mIHN1YmplY3RcblxuICAvLyBXb3JrYXJvdW5kOiBub2RlJ3MgYmFzZTY0IGltcGxlbWVudGF0aW9uIGFsbG93cyBmb3Igbm9uLXBhZGRlZCBzdHJpbmdzXG4gIC8vIHdoaWxlIGJhc2U2NC1qcyBkb2VzIG5vdC5cbiAgaWYgKGVuY29kaW5nID09PSAnYmFzZTY0JyAmJiB0eXBlID09PSAnc3RyaW5nJykge1xuICAgIHN1YmplY3QgPSBzdHJpbmd0cmltKHN1YmplY3QpXG4gICAgd2hpbGUgKHN1YmplY3QubGVuZ3RoICUgNCAhPT0gMCkge1xuICAgICAgc3ViamVjdCA9IHN1YmplY3QgKyAnPSdcbiAgICB9XG4gIH1cblxuICAvLyBGaW5kIHRoZSBsZW5ndGhcbiAgdmFyIGxlbmd0aFxuICBpZiAodHlwZSA9PT0gJ251bWJlcicpXG4gICAgbGVuZ3RoID0gY29lcmNlKHN1YmplY3QpXG4gIGVsc2UgaWYgKHR5cGUgPT09ICdzdHJpbmcnKVxuICAgIGxlbmd0aCA9IEJ1ZmZlci5ieXRlTGVuZ3RoKHN1YmplY3QsIGVuY29kaW5nKVxuICBlbHNlIGlmICh0eXBlID09PSAnb2JqZWN0JylcbiAgICBsZW5ndGggPSBjb2VyY2Uoc3ViamVjdC5sZW5ndGgpIC8vIGFzc3VtZSB0aGF0IG9iamVjdCBpcyBhcnJheS1saWtlXG4gIGVsc2VcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ZpcnN0IGFyZ3VtZW50IG5lZWRzIHRvIGJlIGEgbnVtYmVyLCBhcnJheSBvciBzdHJpbmcuJylcblxuICB2YXIgYnVmXG4gIGlmIChCdWZmZXIuX3VzZVR5cGVkQXJyYXlzKSB7XG4gICAgLy8gUHJlZmVycmVkOiBSZXR1cm4gYW4gYXVnbWVudGVkIGBVaW50OEFycmF5YCBpbnN0YW5jZSBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIGJ1ZiA9IEJ1ZmZlci5fYXVnbWVudChuZXcgVWludDhBcnJheShsZW5ndGgpKVxuICB9IGVsc2Uge1xuICAgIC8vIEZhbGxiYWNrOiBSZXR1cm4gVEhJUyBpbnN0YW5jZSBvZiBCdWZmZXIgKGNyZWF0ZWQgYnkgYG5ld2ApXG4gICAgYnVmID0gdGhpc1xuICAgIGJ1Zi5sZW5ndGggPSBsZW5ndGhcbiAgICBidWYuX2lzQnVmZmVyID0gdHJ1ZVxuICB9XG5cbiAgdmFyIGlcbiAgaWYgKEJ1ZmZlci5fdXNlVHlwZWRBcnJheXMgJiYgdHlwZW9mIHN1YmplY3QuYnl0ZUxlbmd0aCA9PT0gJ251bWJlcicpIHtcbiAgICAvLyBTcGVlZCBvcHRpbWl6YXRpb24gLS0gdXNlIHNldCBpZiB3ZSdyZSBjb3B5aW5nIGZyb20gYSB0eXBlZCBhcnJheVxuICAgIGJ1Zi5fc2V0KHN1YmplY3QpXG4gIH0gZWxzZSBpZiAoaXNBcnJheWlzaChzdWJqZWN0KSkge1xuICAgIC8vIFRyZWF0IGFycmF5LWlzaCBvYmplY3RzIGFzIGEgYnl0ZSBhcnJheVxuICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihzdWJqZWN0KSlcbiAgICAgICAgYnVmW2ldID0gc3ViamVjdC5yZWFkVUludDgoaSlcbiAgICAgIGVsc2VcbiAgICAgICAgYnVmW2ldID0gc3ViamVjdFtpXVxuICAgIH1cbiAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgIGJ1Zi53cml0ZShzdWJqZWN0LCAwLCBlbmNvZGluZylcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnbnVtYmVyJyAmJiAhQnVmZmVyLl91c2VUeXBlZEFycmF5cyAmJiAhbm9aZXJvKSB7XG4gICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBidWZbaV0gPSAwXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ1ZlxufVxuXG4vLyBTVEFUSUMgTUVUSE9EU1xuLy8gPT09PT09PT09PT09PT1cblxuQnVmZmVyLmlzRW5jb2RpbmcgPSBmdW5jdGlvbiAoZW5jb2RpbmcpIHtcbiAgc3dpdGNoIChTdHJpbmcoZW5jb2RpbmcpLnRvTG93ZXJDYXNlKCkpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgIGNhc2UgJ3Jhdyc6XG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldHVybiB0cnVlXG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBmYWxzZVxuICB9XG59XG5cbkJ1ZmZlci5pc0J1ZmZlciA9IGZ1bmN0aW9uIChiKSB7XG4gIHJldHVybiAhIShiICE9PSBudWxsICYmIGIgIT09IHVuZGVmaW5lZCAmJiBiLl9pc0J1ZmZlcilcbn1cblxuQnVmZmVyLmJ5dGVMZW5ndGggPSBmdW5jdGlvbiAoc3RyLCBlbmNvZGluZykge1xuICB2YXIgcmV0XG4gIHN0ciA9IHN0ciArICcnXG4gIHN3aXRjaCAoZW5jb2RpbmcgfHwgJ3V0ZjgnKSB7XG4gICAgY2FzZSAnaGV4JzpcbiAgICAgIHJldCA9IHN0ci5sZW5ndGggLyAyXG4gICAgICBicmVha1xuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgIHJldCA9IHV0ZjhUb0J5dGVzKHN0cikubGVuZ3RoXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2FzY2lpJzpcbiAgICBjYXNlICdiaW5hcnknOlxuICAgIGNhc2UgJ3Jhdyc6XG4gICAgICByZXQgPSBzdHIubGVuZ3RoXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICByZXQgPSBiYXNlNjRUb0J5dGVzKHN0cikubGVuZ3RoXG4gICAgICBicmVha1xuICAgIGNhc2UgJ3VjczInOlxuICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICBjYXNlICd1dGYxNmxlJzpcbiAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICByZXQgPSBzdHIubGVuZ3RoICogMlxuICAgICAgYnJlYWtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGVuY29kaW5nJylcbiAgfVxuICByZXR1cm4gcmV0XG59XG5cbkJ1ZmZlci5jb25jYXQgPSBmdW5jdGlvbiAobGlzdCwgdG90YWxMZW5ndGgpIHtcbiAgYXNzZXJ0KGlzQXJyYXkobGlzdCksICdVc2FnZTogQnVmZmVyLmNvbmNhdChsaXN0LCBbdG90YWxMZW5ndGhdKVxcbicgK1xuICAgICAgJ2xpc3Qgc2hvdWxkIGJlIGFuIEFycmF5LicpXG5cbiAgaWYgKGxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIG5ldyBCdWZmZXIoMClcbiAgfSBlbHNlIGlmIChsaXN0Lmxlbmd0aCA9PT0gMSkge1xuICAgIHJldHVybiBsaXN0WzBdXG4gIH1cblxuICB2YXIgaVxuICBpZiAodHlwZW9mIHRvdGFsTGVuZ3RoICE9PSAnbnVtYmVyJykge1xuICAgIHRvdGFsTGVuZ3RoID0gMFxuICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICB0b3RhbExlbmd0aCArPSBsaXN0W2ldLmxlbmd0aFxuICAgIH1cbiAgfVxuXG4gIHZhciBidWYgPSBuZXcgQnVmZmVyKHRvdGFsTGVuZ3RoKVxuICB2YXIgcG9zID0gMFxuICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIHZhciBpdGVtID0gbGlzdFtpXVxuICAgIGl0ZW0uY29weShidWYsIHBvcylcbiAgICBwb3MgKz0gaXRlbS5sZW5ndGhcbiAgfVxuICByZXR1cm4gYnVmXG59XG5cbi8vIEJVRkZFUiBJTlNUQU5DRSBNRVRIT0RTXG4vLyA9PT09PT09PT09PT09PT09PT09PT09PVxuXG5mdW5jdGlvbiBfaGV4V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICBvZmZzZXQgPSBOdW1iZXIob2Zmc2V0KSB8fCAwXG4gIHZhciByZW1haW5pbmcgPSBidWYubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmICghbGVuZ3RoKSB7XG4gICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gIH0gZWxzZSB7XG4gICAgbGVuZ3RoID0gTnVtYmVyKGxlbmd0aClcbiAgICBpZiAobGVuZ3RoID4gcmVtYWluaW5nKSB7XG4gICAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgICB9XG4gIH1cblxuICAvLyBtdXN0IGJlIGFuIGV2ZW4gbnVtYmVyIG9mIGRpZ2l0c1xuICB2YXIgc3RyTGVuID0gc3RyaW5nLmxlbmd0aFxuICBhc3NlcnQoc3RyTGVuICUgMiA9PT0gMCwgJ0ludmFsaWQgaGV4IHN0cmluZycpXG5cbiAgaWYgKGxlbmd0aCA+IHN0ckxlbiAvIDIpIHtcbiAgICBsZW5ndGggPSBzdHJMZW4gLyAyXG4gIH1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgIHZhciBieXRlID0gcGFyc2VJbnQoc3RyaW5nLnN1YnN0cihpICogMiwgMiksIDE2KVxuICAgIGFzc2VydCghaXNOYU4oYnl0ZSksICdJbnZhbGlkIGhleCBzdHJpbmcnKVxuICAgIGJ1ZltvZmZzZXQgKyBpXSA9IGJ5dGVcbiAgfVxuICBCdWZmZXIuX2NoYXJzV3JpdHRlbiA9IGkgKiAyXG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIF91dGY4V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICB2YXIgY2hhcnNXcml0dGVuID0gQnVmZmVyLl9jaGFyc1dyaXR0ZW4gPVxuICAgIGJsaXRCdWZmZXIodXRmOFRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbiAgcmV0dXJuIGNoYXJzV3JpdHRlblxufVxuXG5mdW5jdGlvbiBfYXNjaWlXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHZhciBjaGFyc1dyaXR0ZW4gPSBCdWZmZXIuX2NoYXJzV3JpdHRlbiA9XG4gICAgYmxpdEJ1ZmZlcihhc2NpaVRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbiAgcmV0dXJuIGNoYXJzV3JpdHRlblxufVxuXG5mdW5jdGlvbiBfYmluYXJ5V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gX2FzY2lpV3JpdGUoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBfYmFzZTY0V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICB2YXIgY2hhcnNXcml0dGVuID0gQnVmZmVyLl9jaGFyc1dyaXR0ZW4gPVxuICAgIGJsaXRCdWZmZXIoYmFzZTY0VG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxuICByZXR1cm4gY2hhcnNXcml0dGVuXG59XG5cbmZ1bmN0aW9uIF91dGYxNmxlV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICB2YXIgY2hhcnNXcml0dGVuID0gQnVmZmVyLl9jaGFyc1dyaXR0ZW4gPVxuICAgIGJsaXRCdWZmZXIodXRmMTZsZVRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbiAgcmV0dXJuIGNoYXJzV3JpdHRlblxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlID0gZnVuY3Rpb24gKHN0cmluZywgb2Zmc2V0LCBsZW5ndGgsIGVuY29kaW5nKSB7XG4gIC8vIFN1cHBvcnQgYm90aCAoc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCwgZW5jb2RpbmcpXG4gIC8vIGFuZCB0aGUgbGVnYWN5IChzdHJpbmcsIGVuY29kaW5nLCBvZmZzZXQsIGxlbmd0aClcbiAgaWYgKGlzRmluaXRlKG9mZnNldCkpIHtcbiAgICBpZiAoIWlzRmluaXRlKGxlbmd0aCkpIHtcbiAgICAgIGVuY29kaW5nID0gbGVuZ3RoXG4gICAgICBsZW5ndGggPSB1bmRlZmluZWRcbiAgICB9XG4gIH0gZWxzZSB7ICAvLyBsZWdhY3lcbiAgICB2YXIgc3dhcCA9IGVuY29kaW5nXG4gICAgZW5jb2RpbmcgPSBvZmZzZXRcbiAgICBvZmZzZXQgPSBsZW5ndGhcbiAgICBsZW5ndGggPSBzd2FwXG4gIH1cblxuICBvZmZzZXQgPSBOdW1iZXIob2Zmc2V0KSB8fCAwXG4gIHZhciByZW1haW5pbmcgPSB0aGlzLmxlbmd0aCAtIG9mZnNldFxuICBpZiAoIWxlbmd0aCkge1xuICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICB9IGVsc2Uge1xuICAgIGxlbmd0aCA9IE51bWJlcihsZW5ndGgpXG4gICAgaWYgKGxlbmd0aCA+IHJlbWFpbmluZykge1xuICAgICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gICAgfVxuICB9XG4gIGVuY29kaW5nID0gU3RyaW5nKGVuY29kaW5nIHx8ICd1dGY4JykudG9Mb3dlckNhc2UoKVxuXG4gIHZhciByZXRcbiAgc3dpdGNoIChlbmNvZGluZykge1xuICAgIGNhc2UgJ2hleCc6XG4gICAgICByZXQgPSBfaGV4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAndXRmOCc6XG4gICAgY2FzZSAndXRmLTgnOlxuICAgICAgcmV0ID0gX3V0ZjhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgICByZXQgPSBfYXNjaWlXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdiaW5hcnknOlxuICAgICAgcmV0ID0gX2JpbmFyeVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICByZXQgPSBfYmFzZTY0V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldCA9IF91dGYxNmxlV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbiAgICAgIGJyZWFrXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5rbm93biBlbmNvZGluZycpXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gKGVuY29kaW5nLCBzdGFydCwgZW5kKSB7XG4gIHZhciBzZWxmID0gdGhpc1xuXG4gIGVuY29kaW5nID0gU3RyaW5nKGVuY29kaW5nIHx8ICd1dGY4JykudG9Mb3dlckNhc2UoKVxuICBzdGFydCA9IE51bWJlcihzdGFydCkgfHwgMFxuICBlbmQgPSAoZW5kICE9PSB1bmRlZmluZWQpXG4gICAgPyBOdW1iZXIoZW5kKVxuICAgIDogZW5kID0gc2VsZi5sZW5ndGhcblxuICAvLyBGYXN0cGF0aCBlbXB0eSBzdHJpbmdzXG4gIGlmIChlbmQgPT09IHN0YXJ0KVxuICAgIHJldHVybiAnJ1xuXG4gIHZhciByZXRcbiAgc3dpdGNoIChlbmNvZGluZykge1xuICAgIGNhc2UgJ2hleCc6XG4gICAgICByZXQgPSBfaGV4U2xpY2Uoc2VsZiwgc3RhcnQsIGVuZClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAndXRmOCc6XG4gICAgY2FzZSAndXRmLTgnOlxuICAgICAgcmV0ID0gX3V0ZjhTbGljZShzZWxmLCBzdGFydCwgZW5kKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgICByZXQgPSBfYXNjaWlTbGljZShzZWxmLCBzdGFydCwgZW5kKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdiaW5hcnknOlxuICAgICAgcmV0ID0gX2JpbmFyeVNsaWNlKHNlbGYsIHN0YXJ0LCBlbmQpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICByZXQgPSBfYmFzZTY0U2xpY2Uoc2VsZiwgc3RhcnQsIGVuZClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldCA9IF91dGYxNmxlU2xpY2Uoc2VsZiwgc3RhcnQsIGVuZClcbiAgICAgIGJyZWFrXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5rbm93biBlbmNvZGluZycpXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnQnVmZmVyJyxcbiAgICBkYXRhOiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh0aGlzLl9hcnIgfHwgdGhpcywgMClcbiAgfVxufVxuXG4vLyBjb3B5KHRhcmdldEJ1ZmZlciwgdGFyZ2V0U3RhcnQ9MCwgc291cmNlU3RhcnQ9MCwgc291cmNlRW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiAodGFyZ2V0LCB0YXJnZXRfc3RhcnQsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHNvdXJjZSA9IHRoaXNcblxuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgJiYgZW5kICE9PSAwKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAoIXRhcmdldF9zdGFydCkgdGFyZ2V0X3N0YXJ0ID0gMFxuXG4gIC8vIENvcHkgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuXG4gIGlmICh0YXJnZXQubGVuZ3RoID09PSAwIHx8IHNvdXJjZS5sZW5ndGggPT09IDApIHJldHVyblxuXG4gIC8vIEZhdGFsIGVycm9yIGNvbmRpdGlvbnNcbiAgYXNzZXJ0KGVuZCA+PSBzdGFydCwgJ3NvdXJjZUVuZCA8IHNvdXJjZVN0YXJ0JylcbiAgYXNzZXJ0KHRhcmdldF9zdGFydCA+PSAwICYmIHRhcmdldF9zdGFydCA8IHRhcmdldC5sZW5ndGgsXG4gICAgICAndGFyZ2V0U3RhcnQgb3V0IG9mIGJvdW5kcycpXG4gIGFzc2VydChzdGFydCA+PSAwICYmIHN0YXJ0IDwgc291cmNlLmxlbmd0aCwgJ3NvdXJjZVN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICBhc3NlcnQoZW5kID49IDAgJiYgZW5kIDw9IHNvdXJjZS5sZW5ndGgsICdzb3VyY2VFbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgLy8gQXJlIHdlIG9vYj9cbiAgaWYgKGVuZCA+IHRoaXMubGVuZ3RoKVxuICAgIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0X3N0YXJ0IDwgZW5kIC0gc3RhcnQpXG4gICAgZW5kID0gdGFyZ2V0Lmxlbmd0aCAtIHRhcmdldF9zdGFydCArIHN0YXJ0XG5cbiAgdmFyIGxlbiA9IGVuZCAtIHN0YXJ0XG5cbiAgaWYgKGxlbiA8IDEwMCB8fCAhQnVmZmVyLl91c2VUeXBlZEFycmF5cykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspXG4gICAgICB0YXJnZXRbaSArIHRhcmdldF9zdGFydF0gPSB0aGlzW2kgKyBzdGFydF1cbiAgfSBlbHNlIHtcbiAgICB0YXJnZXQuX3NldCh0aGlzLnN1YmFycmF5KHN0YXJ0LCBzdGFydCArIGxlbiksIHRhcmdldF9zdGFydClcbiAgfVxufVxuXG5mdW5jdGlvbiBfYmFzZTY0U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBpZiAoc3RhcnQgPT09IDAgJiYgZW5kID09PSBidWYubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1ZilcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmLnNsaWNlKHN0YXJ0LCBlbmQpKVxuICB9XG59XG5cbmZ1bmN0aW9uIF91dGY4U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgcmVzID0gJydcbiAgdmFyIHRtcCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgIGlmIChidWZbaV0gPD0gMHg3Rikge1xuICAgICAgcmVzICs9IGRlY29kZVV0ZjhDaGFyKHRtcCkgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSlcbiAgICAgIHRtcCA9ICcnXG4gICAgfSBlbHNlIHtcbiAgICAgIHRtcCArPSAnJScgKyBidWZbaV0udG9TdHJpbmcoMTYpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlcyArIGRlY29kZVV0ZjhDaGFyKHRtcClcbn1cblxuZnVuY3Rpb24gX2FzY2lpU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgcmV0ID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKVxuICAgIHJldCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSlcbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBfYmluYXJ5U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICByZXR1cm4gX2FzY2lpU2xpY2UoYnVmLCBzdGFydCwgZW5kKVxufVxuXG5mdW5jdGlvbiBfaGV4U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuXG4gIGlmICghc3RhcnQgfHwgc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgfHwgZW5kIDwgMCB8fCBlbmQgPiBsZW4pIGVuZCA9IGxlblxuXG4gIHZhciBvdXQgPSAnJ1xuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgIG91dCArPSB0b0hleChidWZbaV0pXG4gIH1cbiAgcmV0dXJuIG91dFxufVxuXG5mdW5jdGlvbiBfdXRmMTZsZVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGJ5dGVzID0gYnVmLnNsaWNlKHN0YXJ0LCBlbmQpXG4gIHZhciByZXMgPSAnJ1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGJ5dGVzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgcmVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnl0ZXNbaV0gKyBieXRlc1tpKzFdICogMjU2KVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zbGljZSA9IGZ1bmN0aW9uIChzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBzdGFydCA9IGNsYW1wKHN0YXJ0LCBsZW4sIDApXG4gIGVuZCA9IGNsYW1wKGVuZCwgbGVuLCBsZW4pXG5cbiAgaWYgKEJ1ZmZlci5fdXNlVHlwZWRBcnJheXMpIHtcbiAgICByZXR1cm4gQnVmZmVyLl9hdWdtZW50KHRoaXMuc3ViYXJyYXkoc3RhcnQsIGVuZCkpXG4gIH0gZWxzZSB7XG4gICAgdmFyIHNsaWNlTGVuID0gZW5kIC0gc3RhcnRcbiAgICB2YXIgbmV3QnVmID0gbmV3IEJ1ZmZlcihzbGljZUxlbiwgdW5kZWZpbmVkLCB0cnVlKVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2xpY2VMZW47IGkrKykge1xuICAgICAgbmV3QnVmW2ldID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICAgIHJldHVybiBuZXdCdWZcbiAgfVxufVxuXG4vLyBgZ2V0YCB3aWxsIGJlIHJlbW92ZWQgaW4gTm9kZSAwLjEzK1xuQnVmZmVyLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiAob2Zmc2V0KSB7XG4gIGNvbnNvbGUubG9nKCcuZ2V0KCkgaXMgZGVwcmVjYXRlZC4gQWNjZXNzIHVzaW5nIGFycmF5IGluZGV4ZXMgaW5zdGVhZC4nKVxuICByZXR1cm4gdGhpcy5yZWFkVUludDgob2Zmc2V0KVxufVxuXG4vLyBgc2V0YCB3aWxsIGJlIHJlbW92ZWQgaW4gTm9kZSAwLjEzK1xuQnVmZmVyLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiAodiwgb2Zmc2V0KSB7XG4gIGNvbnNvbGUubG9nKCcuc2V0KCkgaXMgZGVwcmVjYXRlZC4gQWNjZXNzIHVzaW5nIGFycmF5IGluZGV4ZXMgaW5zdGVhZC4nKVxuICByZXR1cm4gdGhpcy53cml0ZVVJbnQ4KHYsIG9mZnNldClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDggPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0IDwgdGhpcy5sZW5ndGgsICdUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gIH1cblxuICBpZiAob2Zmc2V0ID49IHRoaXMubGVuZ3RoKVxuICAgIHJldHVyblxuXG4gIHJldHVybiB0aGlzW29mZnNldF1cbn1cblxuZnVuY3Rpb24gX3JlYWRVSW50MTYgKGJ1Ziwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0ICsgMSA8IGJ1Zi5sZW5ndGgsICdUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICB2YXIgdmFsXG4gIGlmIChsaXR0bGVFbmRpYW4pIHtcbiAgICB2YWwgPSBidWZbb2Zmc2V0XVxuICAgIGlmIChvZmZzZXQgKyAxIDwgbGVuKVxuICAgICAgdmFsIHw9IGJ1ZltvZmZzZXQgKyAxXSA8PCA4XG4gIH0gZWxzZSB7XG4gICAgdmFsID0gYnVmW29mZnNldF0gPDwgOFxuICAgIGlmIChvZmZzZXQgKyAxIDwgbGVuKVxuICAgICAgdmFsIHw9IGJ1ZltvZmZzZXQgKyAxXVxuICB9XG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDE2TEUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gX3JlYWRVSW50MTYodGhpcywgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDE2QkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gX3JlYWRVSW50MTYodGhpcywgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIF9yZWFkVUludDMyIChidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDMgPCBidWYubGVuZ3RoLCAnVHJ5aW5nIHRvIHJlYWQgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICB9XG5cbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcbiAgaWYgKG9mZnNldCA+PSBsZW4pXG4gICAgcmV0dXJuXG5cbiAgdmFyIHZhbFxuICBpZiAobGl0dGxlRW5kaWFuKSB7XG4gICAgaWYgKG9mZnNldCArIDIgPCBsZW4pXG4gICAgICB2YWwgPSBidWZbb2Zmc2V0ICsgMl0gPDwgMTZcbiAgICBpZiAob2Zmc2V0ICsgMSA8IGxlbilcbiAgICAgIHZhbCB8PSBidWZbb2Zmc2V0ICsgMV0gPDwgOFxuICAgIHZhbCB8PSBidWZbb2Zmc2V0XVxuICAgIGlmIChvZmZzZXQgKyAzIDwgbGVuKVxuICAgICAgdmFsID0gdmFsICsgKGJ1ZltvZmZzZXQgKyAzXSA8PCAyNCA+Pj4gMClcbiAgfSBlbHNlIHtcbiAgICBpZiAob2Zmc2V0ICsgMSA8IGxlbilcbiAgICAgIHZhbCA9IGJ1ZltvZmZzZXQgKyAxXSA8PCAxNlxuICAgIGlmIChvZmZzZXQgKyAyIDwgbGVuKVxuICAgICAgdmFsIHw9IGJ1ZltvZmZzZXQgKyAyXSA8PCA4XG4gICAgaWYgKG9mZnNldCArIDMgPCBsZW4pXG4gICAgICB2YWwgfD0gYnVmW29mZnNldCArIDNdXG4gICAgdmFsID0gdmFsICsgKGJ1ZltvZmZzZXRdIDw8IDI0ID4+PiAwKVxuICB9XG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyTEUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gX3JlYWRVSW50MzIodGhpcywgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyQkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gX3JlYWRVSW50MzIodGhpcywgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDggPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCxcbiAgICAgICAgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0IDwgdGhpcy5sZW5ndGgsICdUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gIH1cblxuICBpZiAob2Zmc2V0ID49IHRoaXMubGVuZ3RoKVxuICAgIHJldHVyblxuXG4gIHZhciBuZWcgPSB0aGlzW29mZnNldF0gJiAweDgwXG4gIGlmIChuZWcpXG4gICAgcmV0dXJuICgweGZmIC0gdGhpc1tvZmZzZXRdICsgMSkgKiAtMVxuICBlbHNlXG4gICAgcmV0dXJuIHRoaXNbb2Zmc2V0XVxufVxuXG5mdW5jdGlvbiBfcmVhZEludDE2IChidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDEgPCBidWYubGVuZ3RoLCAnVHJ5aW5nIHRvIHJlYWQgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICB9XG5cbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcbiAgaWYgKG9mZnNldCA+PSBsZW4pXG4gICAgcmV0dXJuXG5cbiAgdmFyIHZhbCA9IF9yZWFkVUludDE2KGJ1Ziwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIHRydWUpXG4gIHZhciBuZWcgPSB2YWwgJiAweDgwMDBcbiAgaWYgKG5lZylcbiAgICByZXR1cm4gKDB4ZmZmZiAtIHZhbCArIDEpICogLTFcbiAgZWxzZVxuICAgIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiBfcmVhZEludDE2KHRoaXMsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2QkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gX3JlYWRJbnQxNih0aGlzLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gX3JlYWRJbnQzMiAoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAzIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIHZhciB2YWwgPSBfcmVhZFVJbnQzMihidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCB0cnVlKVxuICB2YXIgbmVnID0gdmFsICYgMHg4MDAwMDAwMFxuICBpZiAobmVnKVxuICAgIHJldHVybiAoMHhmZmZmZmZmZiAtIHZhbCArIDEpICogLTFcbiAgZWxzZVxuICAgIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiBfcmVhZEludDMyKHRoaXMsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyQkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gX3JlYWRJbnQzMih0aGlzLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gX3JlYWRGbG9hdCAoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICsgMyA8IGJ1Zi5sZW5ndGgsICdUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gIH1cblxuICByZXR1cm4gaWVlZTc1NC5yZWFkKGJ1Ziwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDIzLCA0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdExFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIF9yZWFkRmxvYXQodGhpcywgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiBfcmVhZEZsb2F0KHRoaXMsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiBfcmVhZERvdWJsZSAoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICsgNyA8IGJ1Zi5sZW5ndGgsICdUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gIH1cblxuICByZXR1cm4gaWVlZTc1NC5yZWFkKGJ1Ziwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDUyLCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiBfcmVhZERvdWJsZSh0aGlzLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiBfcmVhZERvdWJsZSh0aGlzLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQ4ID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCwgJ21pc3NpbmcgdmFsdWUnKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCA8IHRoaXMubGVuZ3RoLCAndHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgICB2ZXJpZnVpbnQodmFsdWUsIDB4ZmYpXG4gIH1cblxuICBpZiAob2Zmc2V0ID49IHRoaXMubGVuZ3RoKSByZXR1cm5cblxuICB0aGlzW29mZnNldF0gPSB2YWx1ZVxufVxuXG5mdW5jdGlvbiBfd3JpdGVVSW50MTYgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwsICdtaXNzaW5nIHZhbHVlJylcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0ICsgMSA8IGJ1Zi5sZW5ndGgsICd0cnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICAgIHZlcmlmdWludCh2YWx1ZSwgMHhmZmZmKVxuICB9XG5cbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcbiAgaWYgKG9mZnNldCA+PSBsZW4pXG4gICAgcmV0dXJuXG5cbiAgZm9yICh2YXIgaSA9IDAsIGogPSBNYXRoLm1pbihsZW4gLSBvZmZzZXQsIDIpOyBpIDwgajsgaSsrKSB7XG4gICAgYnVmW29mZnNldCArIGldID1cbiAgICAgICAgKHZhbHVlICYgKDB4ZmYgPDwgKDggKiAobGl0dGxlRW5kaWFuID8gaSA6IDEgLSBpKSkpKSA+Pj5cbiAgICAgICAgICAgIChsaXR0bGVFbmRpYW4gPyBpIDogMSAtIGkpICogOFxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZMRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBfd3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZCRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBfd3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiBfd3JpdGVVSW50MzIgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwsICdtaXNzaW5nIHZhbHVlJylcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0ICsgMyA8IGJ1Zi5sZW5ndGgsICd0cnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICAgIHZlcmlmdWludCh2YWx1ZSwgMHhmZmZmZmZmZilcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIGZvciAodmFyIGkgPSAwLCBqID0gTWF0aC5taW4obGVuIC0gb2Zmc2V0LCA0KTsgaSA8IGo7IGkrKykge1xuICAgIGJ1ZltvZmZzZXQgKyBpXSA9XG4gICAgICAgICh2YWx1ZSA+Pj4gKGxpdHRsZUVuZGlhbiA/IGkgOiAzIC0gaSkgKiA4KSAmIDB4ZmZcbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDMyTEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgX3dyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDMyQkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgX3dyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsLCAnbWlzc2luZyB2YWx1ZScpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0IDwgdGhpcy5sZW5ndGgsICdUcnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICAgIHZlcmlmc2ludCh2YWx1ZSwgMHg3ZiwgLTB4ODApXG4gIH1cblxuICBpZiAob2Zmc2V0ID49IHRoaXMubGVuZ3RoKVxuICAgIHJldHVyblxuXG4gIGlmICh2YWx1ZSA+PSAwKVxuICAgIHRoaXMud3JpdGVVSW50OCh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydClcbiAgZWxzZVxuICAgIHRoaXMud3JpdGVVSW50OCgweGZmICsgdmFsdWUgKyAxLCBvZmZzZXQsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiBfd3JpdGVJbnQxNiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCwgJ21pc3NpbmcgdmFsdWUnKVxuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAxIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gICAgdmVyaWZzaW50KHZhbHVlLCAweDdmZmYsIC0weDgwMDApXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICBpZiAodmFsdWUgPj0gMClcbiAgICBfd3JpdGVVSW50MTYoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KVxuICBlbHNlXG4gICAgX3dyaXRlVUludDE2KGJ1ZiwgMHhmZmZmICsgdmFsdWUgKyAxLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkxFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIF93cml0ZUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZCRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBfd3JpdGVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIF93cml0ZUludDMyIChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsLCAnbWlzc2luZyB2YWx1ZScpXG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDMgPCBidWYubGVuZ3RoLCAnVHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgICB2ZXJpZnNpbnQodmFsdWUsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICB9XG5cbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcbiAgaWYgKG9mZnNldCA+PSBsZW4pXG4gICAgcmV0dXJuXG5cbiAgaWYgKHZhbHVlID49IDApXG4gICAgX3dyaXRlVUludDMyKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydClcbiAgZWxzZVxuICAgIF93cml0ZVVJbnQzMihidWYsIDB4ZmZmZmZmZmYgKyB2YWx1ZSArIDEsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyTEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgX3dyaXRlSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIF93cml0ZUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gX3dyaXRlRmxvYXQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwsICdtaXNzaW5nIHZhbHVlJylcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0ICsgMyA8IGJ1Zi5sZW5ndGgsICdUcnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICAgIHZlcmlmSUVFRTc1NCh2YWx1ZSwgMy40MDI4MjM0NjYzODUyODg2ZSszOCwgLTMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgpXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0TEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgX3dyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdEJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIF93cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gX3dyaXRlRG91YmxlIChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsLCAnbWlzc2luZyB2YWx1ZScpXG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDcgPCBidWYubGVuZ3RoLFxuICAgICAgICAnVHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgICB2ZXJpZklFRUU3NTQodmFsdWUsIDEuNzk3NjkzMTM0ODYyMzE1N0UrMzA4LCAtMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgpXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCA1MiwgOClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUxFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIF93cml0ZURvdWJsZSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIF93cml0ZURvdWJsZSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbi8vIGZpbGwodmFsdWUsIHN0YXJ0PTAsIGVuZD1idWZmZXIubGVuZ3RoKVxuQnVmZmVyLnByb3RvdHlwZS5maWxsID0gZnVuY3Rpb24gKHZhbHVlLCBzdGFydCwgZW5kKSB7XG4gIGlmICghdmFsdWUpIHZhbHVlID0gMFxuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQpIGVuZCA9IHRoaXMubGVuZ3RoXG5cbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICB2YWx1ZSA9IHZhbHVlLmNoYXJDb2RlQXQoMClcbiAgfVxuXG4gIGFzc2VydCh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInICYmICFpc05hTih2YWx1ZSksICd2YWx1ZSBpcyBub3QgYSBudW1iZXInKVxuICBhc3NlcnQoZW5kID49IHN0YXJ0LCAnZW5kIDwgc3RhcnQnKVxuXG4gIC8vIEZpbGwgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuXG4gIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuXG5cbiAgYXNzZXJ0KHN0YXJ0ID49IDAgJiYgc3RhcnQgPCB0aGlzLmxlbmd0aCwgJ3N0YXJ0IG91dCBvZiBib3VuZHMnKVxuICBhc3NlcnQoZW5kID49IDAgJiYgZW5kIDw9IHRoaXMubGVuZ3RoLCAnZW5kIG91dCBvZiBib3VuZHMnKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgdGhpc1tpXSA9IHZhbHVlXG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5pbnNwZWN0ID0gZnVuY3Rpb24gKCkge1xuICB2YXIgb3V0ID0gW11cbiAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICBvdXRbaV0gPSB0b0hleCh0aGlzW2ldKVxuICAgIGlmIChpID09PSBleHBvcnRzLklOU1BFQ1RfTUFYX0JZVEVTKSB7XG4gICAgICBvdXRbaSArIDFdID0gJy4uLidcbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG4gIHJldHVybiAnPEJ1ZmZlciAnICsgb3V0LmpvaW4oJyAnKSArICc+J1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgYEFycmF5QnVmZmVyYCB3aXRoIHRoZSAqY29waWVkKiBtZW1vcnkgb2YgdGhlIGJ1ZmZlciBpbnN0YW5jZS5cbiAqIEFkZGVkIGluIE5vZGUgMC4xMi4gT25seSBhdmFpbGFibGUgaW4gYnJvd3NlcnMgdGhhdCBzdXBwb3J0IEFycmF5QnVmZmVyLlxuICovXG5CdWZmZXIucHJvdG90eXBlLnRvQXJyYXlCdWZmZXIgPSBmdW5jdGlvbiAoKSB7XG4gIGlmICh0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAoQnVmZmVyLl91c2VUeXBlZEFycmF5cykge1xuICAgICAgcmV0dXJuIChuZXcgQnVmZmVyKHRoaXMpKS5idWZmZXJcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGJ1ZiA9IG5ldyBVaW50OEFycmF5KHRoaXMubGVuZ3RoKVxuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGJ1Zi5sZW5ndGg7IGkgPCBsZW47IGkgKz0gMSlcbiAgICAgICAgYnVmW2ldID0gdGhpc1tpXVxuICAgICAgcmV0dXJuIGJ1Zi5idWZmZXJcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdCdWZmZXIudG9BcnJheUJ1ZmZlciBub3Qgc3VwcG9ydGVkIGluIHRoaXMgYnJvd3NlcicpXG4gIH1cbn1cblxuLy8gSEVMUEVSIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PVxuXG5mdW5jdGlvbiBzdHJpbmd0cmltIChzdHIpIHtcbiAgaWYgKHN0ci50cmltKSByZXR1cm4gc3RyLnRyaW0oKVxuICByZXR1cm4gc3RyLnJlcGxhY2UoL15cXHMrfFxccyskL2csICcnKVxufVxuXG52YXIgQlAgPSBCdWZmZXIucHJvdG90eXBlXG5cbi8qKlxuICogQXVnbWVudCBhIFVpbnQ4QXJyYXkgKmluc3RhbmNlKiAobm90IHRoZSBVaW50OEFycmF5IGNsYXNzISkgd2l0aCBCdWZmZXIgbWV0aG9kc1xuICovXG5CdWZmZXIuX2F1Z21lbnQgPSBmdW5jdGlvbiAoYXJyKSB7XG4gIGFyci5faXNCdWZmZXIgPSB0cnVlXG5cbiAgLy8gc2F2ZSByZWZlcmVuY2UgdG8gb3JpZ2luYWwgVWludDhBcnJheSBnZXQvc2V0IG1ldGhvZHMgYmVmb3JlIG92ZXJ3cml0aW5nXG4gIGFyci5fZ2V0ID0gYXJyLmdldFxuICBhcnIuX3NldCA9IGFyci5zZXRcblxuICAvLyBkZXByZWNhdGVkLCB3aWxsIGJlIHJlbW92ZWQgaW4gbm9kZSAwLjEzK1xuICBhcnIuZ2V0ID0gQlAuZ2V0XG4gIGFyci5zZXQgPSBCUC5zZXRcblxuICBhcnIud3JpdGUgPSBCUC53cml0ZVxuICBhcnIudG9TdHJpbmcgPSBCUC50b1N0cmluZ1xuICBhcnIudG9Mb2NhbGVTdHJpbmcgPSBCUC50b1N0cmluZ1xuICBhcnIudG9KU09OID0gQlAudG9KU09OXG4gIGFyci5jb3B5ID0gQlAuY29weVxuICBhcnIuc2xpY2UgPSBCUC5zbGljZVxuICBhcnIucmVhZFVJbnQ4ID0gQlAucmVhZFVJbnQ4XG4gIGFyci5yZWFkVUludDE2TEUgPSBCUC5yZWFkVUludDE2TEVcbiAgYXJyLnJlYWRVSW50MTZCRSA9IEJQLnJlYWRVSW50MTZCRVxuICBhcnIucmVhZFVJbnQzMkxFID0gQlAucmVhZFVJbnQzMkxFXG4gIGFyci5yZWFkVUludDMyQkUgPSBCUC5yZWFkVUludDMyQkVcbiAgYXJyLnJlYWRJbnQ4ID0gQlAucmVhZEludDhcbiAgYXJyLnJlYWRJbnQxNkxFID0gQlAucmVhZEludDE2TEVcbiAgYXJyLnJlYWRJbnQxNkJFID0gQlAucmVhZEludDE2QkVcbiAgYXJyLnJlYWRJbnQzMkxFID0gQlAucmVhZEludDMyTEVcbiAgYXJyLnJlYWRJbnQzMkJFID0gQlAucmVhZEludDMyQkVcbiAgYXJyLnJlYWRGbG9hdExFID0gQlAucmVhZEZsb2F0TEVcbiAgYXJyLnJlYWRGbG9hdEJFID0gQlAucmVhZEZsb2F0QkVcbiAgYXJyLnJlYWREb3VibGVMRSA9IEJQLnJlYWREb3VibGVMRVxuICBhcnIucmVhZERvdWJsZUJFID0gQlAucmVhZERvdWJsZUJFXG4gIGFyci53cml0ZVVJbnQ4ID0gQlAud3JpdGVVSW50OFxuICBhcnIud3JpdGVVSW50MTZMRSA9IEJQLndyaXRlVUludDE2TEVcbiAgYXJyLndyaXRlVUludDE2QkUgPSBCUC53cml0ZVVJbnQxNkJFXG4gIGFyci53cml0ZVVJbnQzMkxFID0gQlAud3JpdGVVSW50MzJMRVxuICBhcnIud3JpdGVVSW50MzJCRSA9IEJQLndyaXRlVUludDMyQkVcbiAgYXJyLndyaXRlSW50OCA9IEJQLndyaXRlSW50OFxuICBhcnIud3JpdGVJbnQxNkxFID0gQlAud3JpdGVJbnQxNkxFXG4gIGFyci53cml0ZUludDE2QkUgPSBCUC53cml0ZUludDE2QkVcbiAgYXJyLndyaXRlSW50MzJMRSA9IEJQLndyaXRlSW50MzJMRVxuICBhcnIud3JpdGVJbnQzMkJFID0gQlAud3JpdGVJbnQzMkJFXG4gIGFyci53cml0ZUZsb2F0TEUgPSBCUC53cml0ZUZsb2F0TEVcbiAgYXJyLndyaXRlRmxvYXRCRSA9IEJQLndyaXRlRmxvYXRCRVxuICBhcnIud3JpdGVEb3VibGVMRSA9IEJQLndyaXRlRG91YmxlTEVcbiAgYXJyLndyaXRlRG91YmxlQkUgPSBCUC53cml0ZURvdWJsZUJFXG4gIGFyci5maWxsID0gQlAuZmlsbFxuICBhcnIuaW5zcGVjdCA9IEJQLmluc3BlY3RcbiAgYXJyLnRvQXJyYXlCdWZmZXIgPSBCUC50b0FycmF5QnVmZmVyXG5cbiAgcmV0dXJuIGFyclxufVxuXG4vLyBzbGljZShzdGFydCwgZW5kKVxuZnVuY3Rpb24gY2xhbXAgKGluZGV4LCBsZW4sIGRlZmF1bHRWYWx1ZSkge1xuICBpZiAodHlwZW9mIGluZGV4ICE9PSAnbnVtYmVyJykgcmV0dXJuIGRlZmF1bHRWYWx1ZVxuICBpbmRleCA9IH5+aW5kZXg7ICAvLyBDb2VyY2UgdG8gaW50ZWdlci5cbiAgaWYgKGluZGV4ID49IGxlbikgcmV0dXJuIGxlblxuICBpZiAoaW5kZXggPj0gMCkgcmV0dXJuIGluZGV4XG4gIGluZGV4ICs9IGxlblxuICBpZiAoaW5kZXggPj0gMCkgcmV0dXJuIGluZGV4XG4gIHJldHVybiAwXG59XG5cbmZ1bmN0aW9uIGNvZXJjZSAobGVuZ3RoKSB7XG4gIC8vIENvZXJjZSBsZW5ndGggdG8gYSBudW1iZXIgKHBvc3NpYmx5IE5hTiksIHJvdW5kIHVwXG4gIC8vIGluIGNhc2UgaXQncyBmcmFjdGlvbmFsIChlLmcuIDEyMy40NTYpIHRoZW4gZG8gYVxuICAvLyBkb3VibGUgbmVnYXRlIHRvIGNvZXJjZSBhIE5hTiB0byAwLiBFYXN5LCByaWdodD9cbiAgbGVuZ3RoID0gfn5NYXRoLmNlaWwoK2xlbmd0aClcbiAgcmV0dXJuIGxlbmd0aCA8IDAgPyAwIDogbGVuZ3RoXG59XG5cbmZ1bmN0aW9uIGlzQXJyYXkgKHN1YmplY3QpIHtcbiAgcmV0dXJuIChBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uIChzdWJqZWN0KSB7XG4gICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzdWJqZWN0KSA9PT0gJ1tvYmplY3QgQXJyYXldJ1xuICB9KShzdWJqZWN0KVxufVxuXG5mdW5jdGlvbiBpc0FycmF5aXNoIChzdWJqZWN0KSB7XG4gIHJldHVybiBpc0FycmF5KHN1YmplY3QpIHx8IEJ1ZmZlci5pc0J1ZmZlcihzdWJqZWN0KSB8fFxuICAgICAgc3ViamVjdCAmJiB0eXBlb2Ygc3ViamVjdCA9PT0gJ29iamVjdCcgJiZcbiAgICAgIHR5cGVvZiBzdWJqZWN0Lmxlbmd0aCA9PT0gJ251bWJlcidcbn1cblxuZnVuY3Rpb24gdG9IZXggKG4pIHtcbiAgaWYgKG4gPCAxNikgcmV0dXJuICcwJyArIG4udG9TdHJpbmcoMTYpXG4gIHJldHVybiBuLnRvU3RyaW5nKDE2KVxufVxuXG5mdW5jdGlvbiB1dGY4VG9CeXRlcyAoc3RyKSB7XG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIHZhciBiID0gc3RyLmNoYXJDb2RlQXQoaSlcbiAgICBpZiAoYiA8PSAweDdGKVxuICAgICAgYnl0ZUFycmF5LnB1c2goc3RyLmNoYXJDb2RlQXQoaSkpXG4gICAgZWxzZSB7XG4gICAgICB2YXIgc3RhcnQgPSBpXG4gICAgICBpZiAoYiA+PSAweEQ4MDAgJiYgYiA8PSAweERGRkYpIGkrK1xuICAgICAgdmFyIGggPSBlbmNvZGVVUklDb21wb25lbnQoc3RyLnNsaWNlKHN0YXJ0LCBpKzEpKS5zdWJzdHIoMSkuc3BsaXQoJyUnKVxuICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBoLmxlbmd0aDsgaisrKVxuICAgICAgICBieXRlQXJyYXkucHVzaChwYXJzZUludChoW2pdLCAxNikpXG4gICAgfVxuICB9XG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gYXNjaWlUb0J5dGVzIChzdHIpIHtcbiAgdmFyIGJ5dGVBcnJheSA9IFtdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgLy8gTm9kZSdzIGNvZGUgc2VlbXMgdG8gYmUgZG9pbmcgdGhpcyBhbmQgbm90ICYgMHg3Ri4uXG4gICAgYnl0ZUFycmF5LnB1c2goc3RyLmNoYXJDb2RlQXQoaSkgJiAweEZGKVxuICB9XG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gdXRmMTZsZVRvQnl0ZXMgKHN0cikge1xuICB2YXIgYywgaGksIGxvXG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIGMgPSBzdHIuY2hhckNvZGVBdChpKVxuICAgIGhpID0gYyA+PiA4XG4gICAgbG8gPSBjICUgMjU2XG4gICAgYnl0ZUFycmF5LnB1c2gobG8pXG4gICAgYnl0ZUFycmF5LnB1c2goaGkpXG4gIH1cblxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIGJhc2U2NFRvQnl0ZXMgKHN0cikge1xuICByZXR1cm4gYmFzZTY0LnRvQnl0ZUFycmF5KHN0cilcbn1cblxuZnVuY3Rpb24gYmxpdEJ1ZmZlciAoc3JjLCBkc3QsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHZhciBwb3NcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgIGlmICgoaSArIG9mZnNldCA+PSBkc3QubGVuZ3RoKSB8fCAoaSA+PSBzcmMubGVuZ3RoKSlcbiAgICAgIGJyZWFrXG4gICAgZHN0W2kgKyBvZmZzZXRdID0gc3JjW2ldXG4gIH1cbiAgcmV0dXJuIGlcbn1cblxuZnVuY3Rpb24gZGVjb2RlVXRmOENoYXIgKHN0cikge1xuICB0cnkge1xuICAgIHJldHVybiBkZWNvZGVVUklDb21wb25lbnQoc3RyKVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgweEZGRkQpIC8vIFVURiA4IGludmFsaWQgY2hhclxuICB9XG59XG5cbi8qXG4gKiBXZSBoYXZlIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSB2YWx1ZSBpcyBhIHZhbGlkIGludGVnZXIuIFRoaXMgbWVhbnMgdGhhdCBpdFxuICogaXMgbm9uLW5lZ2F0aXZlLiBJdCBoYXMgbm8gZnJhY3Rpb25hbCBjb21wb25lbnQgYW5kIHRoYXQgaXQgZG9lcyBub3RcbiAqIGV4Y2VlZCB0aGUgbWF4aW11bSBhbGxvd2VkIHZhbHVlLlxuICovXG5mdW5jdGlvbiB2ZXJpZnVpbnQgKHZhbHVlLCBtYXgpIHtcbiAgYXNzZXJ0KHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicsICdjYW5ub3Qgd3JpdGUgYSBub24tbnVtYmVyIGFzIGEgbnVtYmVyJylcbiAgYXNzZXJ0KHZhbHVlID49IDAsICdzcGVjaWZpZWQgYSBuZWdhdGl2ZSB2YWx1ZSBmb3Igd3JpdGluZyBhbiB1bnNpZ25lZCB2YWx1ZScpXG4gIGFzc2VydCh2YWx1ZSA8PSBtYXgsICd2YWx1ZSBpcyBsYXJnZXIgdGhhbiBtYXhpbXVtIHZhbHVlIGZvciB0eXBlJylcbiAgYXNzZXJ0KE1hdGguZmxvb3IodmFsdWUpID09PSB2YWx1ZSwgJ3ZhbHVlIGhhcyBhIGZyYWN0aW9uYWwgY29tcG9uZW50Jylcbn1cblxuZnVuY3Rpb24gdmVyaWZzaW50ICh2YWx1ZSwgbWF4LCBtaW4pIHtcbiAgYXNzZXJ0KHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicsICdjYW5ub3Qgd3JpdGUgYSBub24tbnVtYmVyIGFzIGEgbnVtYmVyJylcbiAgYXNzZXJ0KHZhbHVlIDw9IG1heCwgJ3ZhbHVlIGxhcmdlciB0aGFuIG1heGltdW0gYWxsb3dlZCB2YWx1ZScpXG4gIGFzc2VydCh2YWx1ZSA+PSBtaW4sICd2YWx1ZSBzbWFsbGVyIHRoYW4gbWluaW11bSBhbGxvd2VkIHZhbHVlJylcbiAgYXNzZXJ0KE1hdGguZmxvb3IodmFsdWUpID09PSB2YWx1ZSwgJ3ZhbHVlIGhhcyBhIGZyYWN0aW9uYWwgY29tcG9uZW50Jylcbn1cblxuZnVuY3Rpb24gdmVyaWZJRUVFNzU0ICh2YWx1ZSwgbWF4LCBtaW4pIHtcbiAgYXNzZXJ0KHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicsICdjYW5ub3Qgd3JpdGUgYSBub24tbnVtYmVyIGFzIGEgbnVtYmVyJylcbiAgYXNzZXJ0KHZhbHVlIDw9IG1heCwgJ3ZhbHVlIGxhcmdlciB0aGFuIG1heGltdW0gYWxsb3dlZCB2YWx1ZScpXG4gIGFzc2VydCh2YWx1ZSA+PSBtaW4sICd2YWx1ZSBzbWFsbGVyIHRoYW4gbWluaW11bSBhbGxvd2VkIHZhbHVlJylcbn1cblxuZnVuY3Rpb24gYXNzZXJ0ICh0ZXN0LCBtZXNzYWdlKSB7XG4gIGlmICghdGVzdCkgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2UgfHwgJ0ZhaWxlZCBhc3NlcnRpb24nKVxufVxuIiwidmFyIGxvb2t1cCA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvJztcblxuOyhmdW5jdGlvbiAoZXhwb3J0cykge1xuXHQndXNlIHN0cmljdCc7XG5cbiAgdmFyIEFyciA9ICh0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcpXG4gICAgPyBVaW50OEFycmF5XG4gICAgOiBBcnJheVxuXG5cdHZhciBQTFVTICAgPSAnKycuY2hhckNvZGVBdCgwKVxuXHR2YXIgU0xBU0ggID0gJy8nLmNoYXJDb2RlQXQoMClcblx0dmFyIE5VTUJFUiA9ICcwJy5jaGFyQ29kZUF0KDApXG5cdHZhciBMT1dFUiAgPSAnYScuY2hhckNvZGVBdCgwKVxuXHR2YXIgVVBQRVIgID0gJ0EnLmNoYXJDb2RlQXQoMClcblx0dmFyIFBMVVNfVVJMX1NBRkUgPSAnLScuY2hhckNvZGVBdCgwKVxuXHR2YXIgU0xBU0hfVVJMX1NBRkUgPSAnXycuY2hhckNvZGVBdCgwKVxuXG5cdGZ1bmN0aW9uIGRlY29kZSAoZWx0KSB7XG5cdFx0dmFyIGNvZGUgPSBlbHQuY2hhckNvZGVBdCgwKVxuXHRcdGlmIChjb2RlID09PSBQTFVTIHx8XG5cdFx0ICAgIGNvZGUgPT09IFBMVVNfVVJMX1NBRkUpXG5cdFx0XHRyZXR1cm4gNjIgLy8gJysnXG5cdFx0aWYgKGNvZGUgPT09IFNMQVNIIHx8XG5cdFx0ICAgIGNvZGUgPT09IFNMQVNIX1VSTF9TQUZFKVxuXHRcdFx0cmV0dXJuIDYzIC8vICcvJ1xuXHRcdGlmIChjb2RlIDwgTlVNQkVSKVxuXHRcdFx0cmV0dXJuIC0xIC8vbm8gbWF0Y2hcblx0XHRpZiAoY29kZSA8IE5VTUJFUiArIDEwKVxuXHRcdFx0cmV0dXJuIGNvZGUgLSBOVU1CRVIgKyAyNiArIDI2XG5cdFx0aWYgKGNvZGUgPCBVUFBFUiArIDI2KVxuXHRcdFx0cmV0dXJuIGNvZGUgLSBVUFBFUlxuXHRcdGlmIChjb2RlIDwgTE9XRVIgKyAyNilcblx0XHRcdHJldHVybiBjb2RlIC0gTE9XRVIgKyAyNlxuXHR9XG5cblx0ZnVuY3Rpb24gYjY0VG9CeXRlQXJyYXkgKGI2NCkge1xuXHRcdHZhciBpLCBqLCBsLCB0bXAsIHBsYWNlSG9sZGVycywgYXJyXG5cblx0XHRpZiAoYjY0Lmxlbmd0aCAlIDQgPiAwKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3RyaW5nLiBMZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDQnKVxuXHRcdH1cblxuXHRcdC8vIHRoZSBudW1iZXIgb2YgZXF1YWwgc2lnbnMgKHBsYWNlIGhvbGRlcnMpXG5cdFx0Ly8gaWYgdGhlcmUgYXJlIHR3byBwbGFjZWhvbGRlcnMsIHRoYW4gdGhlIHR3byBjaGFyYWN0ZXJzIGJlZm9yZSBpdFxuXHRcdC8vIHJlcHJlc2VudCBvbmUgYnl0ZVxuXHRcdC8vIGlmIHRoZXJlIGlzIG9ubHkgb25lLCB0aGVuIHRoZSB0aHJlZSBjaGFyYWN0ZXJzIGJlZm9yZSBpdCByZXByZXNlbnQgMiBieXRlc1xuXHRcdC8vIHRoaXMgaXMganVzdCBhIGNoZWFwIGhhY2sgdG8gbm90IGRvIGluZGV4T2YgdHdpY2Vcblx0XHR2YXIgbGVuID0gYjY0Lmxlbmd0aFxuXHRcdHBsYWNlSG9sZGVycyA9ICc9JyA9PT0gYjY0LmNoYXJBdChsZW4gLSAyKSA/IDIgOiAnPScgPT09IGI2NC5jaGFyQXQobGVuIC0gMSkgPyAxIDogMFxuXG5cdFx0Ly8gYmFzZTY0IGlzIDQvMyArIHVwIHRvIHR3byBjaGFyYWN0ZXJzIG9mIHRoZSBvcmlnaW5hbCBkYXRhXG5cdFx0YXJyID0gbmV3IEFycihiNjQubGVuZ3RoICogMyAvIDQgLSBwbGFjZUhvbGRlcnMpXG5cblx0XHQvLyBpZiB0aGVyZSBhcmUgcGxhY2Vob2xkZXJzLCBvbmx5IGdldCB1cCB0byB0aGUgbGFzdCBjb21wbGV0ZSA0IGNoYXJzXG5cdFx0bCA9IHBsYWNlSG9sZGVycyA+IDAgPyBiNjQubGVuZ3RoIC0gNCA6IGI2NC5sZW5ndGhcblxuXHRcdHZhciBMID0gMFxuXG5cdFx0ZnVuY3Rpb24gcHVzaCAodikge1xuXHRcdFx0YXJyW0wrK10gPSB2XG5cdFx0fVxuXG5cdFx0Zm9yIChpID0gMCwgaiA9IDA7IGkgPCBsOyBpICs9IDQsIGogKz0gMykge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAxOCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDEpKSA8PCAxMikgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDIpKSA8PCA2KSB8IGRlY29kZShiNjQuY2hhckF0KGkgKyAzKSlcblx0XHRcdHB1c2goKHRtcCAmIDB4RkYwMDAwKSA+PiAxNilcblx0XHRcdHB1c2goKHRtcCAmIDB4RkYwMCkgPj4gOClcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9XG5cblx0XHRpZiAocGxhY2VIb2xkZXJzID09PSAyKSB7XG5cdFx0XHR0bXAgPSAoZGVjb2RlKGI2NC5jaGFyQXQoaSkpIDw8IDIpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPj4gNClcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9IGVsc2UgaWYgKHBsYWNlSG9sZGVycyA9PT0gMSkge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAxMCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDEpKSA8PCA0KSB8IChkZWNvZGUoYjY0LmNoYXJBdChpICsgMikpID4+IDIpXG5cdFx0XHRwdXNoKCh0bXAgPj4gOCkgJiAweEZGKVxuXHRcdFx0cHVzaCh0bXAgJiAweEZGKVxuXHRcdH1cblxuXHRcdHJldHVybiBhcnJcblx0fVxuXG5cdGZ1bmN0aW9uIHVpbnQ4VG9CYXNlNjQgKHVpbnQ4KSB7XG5cdFx0dmFyIGksXG5cdFx0XHRleHRyYUJ5dGVzID0gdWludDgubGVuZ3RoICUgMywgLy8gaWYgd2UgaGF2ZSAxIGJ5dGUgbGVmdCwgcGFkIDIgYnl0ZXNcblx0XHRcdG91dHB1dCA9IFwiXCIsXG5cdFx0XHR0ZW1wLCBsZW5ndGhcblxuXHRcdGZ1bmN0aW9uIGVuY29kZSAobnVtKSB7XG5cdFx0XHRyZXR1cm4gbG9va3VwLmNoYXJBdChudW0pXG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gdHJpcGxldFRvQmFzZTY0IChudW0pIHtcblx0XHRcdHJldHVybiBlbmNvZGUobnVtID4+IDE4ICYgMHgzRikgKyBlbmNvZGUobnVtID4+IDEyICYgMHgzRikgKyBlbmNvZGUobnVtID4+IDYgJiAweDNGKSArIGVuY29kZShudW0gJiAweDNGKVxuXHRcdH1cblxuXHRcdC8vIGdvIHRocm91Z2ggdGhlIGFycmF5IGV2ZXJ5IHRocmVlIGJ5dGVzLCB3ZSdsbCBkZWFsIHdpdGggdHJhaWxpbmcgc3R1ZmYgbGF0ZXJcblx0XHRmb3IgKGkgPSAwLCBsZW5ndGggPSB1aW50OC5sZW5ndGggLSBleHRyYUJ5dGVzOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHtcblx0XHRcdHRlbXAgPSAodWludDhbaV0gPDwgMTYpICsgKHVpbnQ4W2kgKyAxXSA8PCA4KSArICh1aW50OFtpICsgMl0pXG5cdFx0XHRvdXRwdXQgKz0gdHJpcGxldFRvQmFzZTY0KHRlbXApXG5cdFx0fVxuXG5cdFx0Ly8gcGFkIHRoZSBlbmQgd2l0aCB6ZXJvcywgYnV0IG1ha2Ugc3VyZSB0byBub3QgZm9yZ2V0IHRoZSBleHRyYSBieXRlc1xuXHRcdHN3aXRjaCAoZXh0cmFCeXRlcykge1xuXHRcdFx0Y2FzZSAxOlxuXHRcdFx0XHR0ZW1wID0gdWludDhbdWludDgubGVuZ3RoIC0gMV1cblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSh0ZW1wID4+IDIpXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUoKHRlbXAgPDwgNCkgJiAweDNGKVxuXHRcdFx0XHRvdXRwdXQgKz0gJz09J1xuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAyOlxuXHRcdFx0XHR0ZW1wID0gKHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDJdIDw8IDgpICsgKHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDFdKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKHRlbXAgPj4gMTApXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUoKHRlbXAgPj4gNCkgJiAweDNGKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wIDw8IDIpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9ICc9J1xuXHRcdFx0XHRicmVha1xuXHRcdH1cblxuXHRcdHJldHVybiBvdXRwdXRcblx0fVxuXG5cdGV4cG9ydHMudG9CeXRlQXJyYXkgPSBiNjRUb0J5dGVBcnJheVxuXHRleHBvcnRzLmZyb21CeXRlQXJyYXkgPSB1aW50OFRvQmFzZTY0XG59KHR5cGVvZiBleHBvcnRzID09PSAndW5kZWZpbmVkJyA/ICh0aGlzLmJhc2U2NGpzID0ge30pIDogZXhwb3J0cykpXG4iLCJleHBvcnRzLnJlYWQgPSBmdW5jdGlvbihidWZmZXIsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLFxuICAgICAgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMSxcbiAgICAgIGVNYXggPSAoMSA8PCBlTGVuKSAtIDEsXG4gICAgICBlQmlhcyA9IGVNYXggPj4gMSxcbiAgICAgIG5CaXRzID0gLTcsXG4gICAgICBpID0gaXNMRSA/IChuQnl0ZXMgLSAxKSA6IDAsXG4gICAgICBkID0gaXNMRSA/IC0xIDogMSxcbiAgICAgIHMgPSBidWZmZXJbb2Zmc2V0ICsgaV07XG5cbiAgaSArPSBkO1xuXG4gIGUgPSBzICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpO1xuICBzID4+PSAoLW5CaXRzKTtcbiAgbkJpdHMgKz0gZUxlbjtcbiAgZm9yICg7IG5CaXRzID4gMDsgZSA9IGUgKiAyNTYgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCk7XG5cbiAgbSA9IGUgJiAoKDEgPDwgKC1uQml0cykpIC0gMSk7XG4gIGUgPj49ICgtbkJpdHMpO1xuICBuQml0cyArPSBtTGVuO1xuICBmb3IgKDsgbkJpdHMgPiAwOyBtID0gbSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KTtcblxuICBpZiAoZSA9PT0gMCkge1xuICAgIGUgPSAxIC0gZUJpYXM7XG4gIH0gZWxzZSBpZiAoZSA9PT0gZU1heCkge1xuICAgIHJldHVybiBtID8gTmFOIDogKChzID8gLTEgOiAxKSAqIEluZmluaXR5KTtcbiAgfSBlbHNlIHtcbiAgICBtID0gbSArIE1hdGgucG93KDIsIG1MZW4pO1xuICAgIGUgPSBlIC0gZUJpYXM7XG4gIH1cbiAgcmV0dXJuIChzID8gLTEgOiAxKSAqIG0gKiBNYXRoLnBvdygyLCBlIC0gbUxlbik7XG59O1xuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24oYnVmZmVyLCB2YWx1ZSwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG0sIGMsXG4gICAgICBlTGVuID0gbkJ5dGVzICogOCAtIG1MZW4gLSAxLFxuICAgICAgZU1heCA9ICgxIDw8IGVMZW4pIC0gMSxcbiAgICAgIGVCaWFzID0gZU1heCA+PiAxLFxuICAgICAgcnQgPSAobUxlbiA9PT0gMjMgPyBNYXRoLnBvdygyLCAtMjQpIC0gTWF0aC5wb3coMiwgLTc3KSA6IDApLFxuICAgICAgaSA9IGlzTEUgPyAwIDogKG5CeXRlcyAtIDEpLFxuICAgICAgZCA9IGlzTEUgPyAxIDogLTEsXG4gICAgICBzID0gdmFsdWUgPCAwIHx8ICh2YWx1ZSA9PT0gMCAmJiAxIC8gdmFsdWUgPCAwKSA/IDEgOiAwO1xuXG4gIHZhbHVlID0gTWF0aC5hYnModmFsdWUpO1xuXG4gIGlmIChpc05hTih2YWx1ZSkgfHwgdmFsdWUgPT09IEluZmluaXR5KSB7XG4gICAgbSA9IGlzTmFOKHZhbHVlKSA/IDEgOiAwO1xuICAgIGUgPSBlTWF4O1xuICB9IGVsc2Uge1xuICAgIGUgPSBNYXRoLmZsb29yKE1hdGgubG9nKHZhbHVlKSAvIE1hdGguTE4yKTtcbiAgICBpZiAodmFsdWUgKiAoYyA9IE1hdGgucG93KDIsIC1lKSkgPCAxKSB7XG4gICAgICBlLS07XG4gICAgICBjICo9IDI7XG4gICAgfVxuICAgIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgdmFsdWUgKz0gcnQgLyBjO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx1ZSArPSBydCAqIE1hdGgucG93KDIsIDEgLSBlQmlhcyk7XG4gICAgfVxuICAgIGlmICh2YWx1ZSAqIGMgPj0gMikge1xuICAgICAgZSsrO1xuICAgICAgYyAvPSAyO1xuICAgIH1cblxuICAgIGlmIChlICsgZUJpYXMgPj0gZU1heCkge1xuICAgICAgbSA9IDA7XG4gICAgICBlID0gZU1heDtcbiAgICB9IGVsc2UgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICBtID0gKHZhbHVlICogYyAtIDEpICogTWF0aC5wb3coMiwgbUxlbik7XG4gICAgICBlID0gZSArIGVCaWFzO1xuICAgIH0gZWxzZSB7XG4gICAgICBtID0gdmFsdWUgKiBNYXRoLnBvdygyLCBlQmlhcyAtIDEpICogTWF0aC5wb3coMiwgbUxlbik7XG4gICAgICBlID0gMDtcbiAgICB9XG4gIH1cblxuICBmb3IgKDsgbUxlbiA+PSA4OyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBtICYgMHhmZiwgaSArPSBkLCBtIC89IDI1NiwgbUxlbiAtPSA4KTtcblxuICBlID0gKGUgPDwgbUxlbikgfCBtO1xuICBlTGVuICs9IG1MZW47XG4gIGZvciAoOyBlTGVuID4gMDsgYnVmZmVyW29mZnNldCArIGldID0gZSAmIDB4ZmYsIGkgKz0gZCwgZSAvPSAyNTYsIGVMZW4gLT0gOCk7XG5cbiAgYnVmZmVyW29mZnNldCArIGkgLSBkXSB8PSBzICogMTI4O1xufTtcbiIsImlmICh0eXBlb2YgT2JqZWN0LmNyZWF0ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAvLyBpbXBsZW1lbnRhdGlvbiBmcm9tIHN0YW5kYXJkIG5vZGUuanMgJ3V0aWwnIG1vZHVsZVxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgY3Rvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ3Rvci5wcm90b3R5cGUsIHtcbiAgICAgIGNvbnN0cnVjdG9yOiB7XG4gICAgICAgIHZhbHVlOiBjdG9yLFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgfVxuICAgIH0pO1xuICB9O1xufSBlbHNlIHtcbiAgLy8gb2xkIHNjaG9vbCBzaGltIGZvciBvbGQgYnJvd3NlcnNcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIHZhciBUZW1wQ3RvciA9IGZ1bmN0aW9uICgpIHt9XG4gICAgVGVtcEN0b3IucHJvdG90eXBlID0gc3VwZXJDdG9yLnByb3RvdHlwZVxuICAgIGN0b3IucHJvdG90eXBlID0gbmV3IFRlbXBDdG9yKClcbiAgICBjdG9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IGN0b3JcbiAgfVxufVxuIiwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG5cbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxucHJvY2Vzcy5uZXh0VGljayA9IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNhblNldEltbWVkaWF0ZSA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnNldEltbWVkaWF0ZTtcbiAgICB2YXIgY2FuUG9zdCA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnBvc3RNZXNzYWdlICYmIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyXG4gICAgO1xuXG4gICAgaWYgKGNhblNldEltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGYpIHsgcmV0dXJuIHdpbmRvdy5zZXRJbW1lZGlhdGUoZikgfTtcbiAgICB9XG5cbiAgICBpZiAoY2FuUG9zdCkge1xuICAgICAgICB2YXIgcXVldWUgPSBbXTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBzb3VyY2UgPSBldi5zb3VyY2U7XG4gICAgICAgICAgICBpZiAoKHNvdXJjZSA9PT0gd2luZG93IHx8IHNvdXJjZSA9PT0gbnVsbCkgJiYgZXYuZGF0YSA9PT0gJ3Byb2Nlc3MtdGljaycpIHtcbiAgICAgICAgICAgICAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICBpZiAocXVldWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZm4gPSBxdWV1ZS5zaGlmdCgpO1xuICAgICAgICAgICAgICAgICAgICBmbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgdHJ1ZSk7XG5cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIG5leHRUaWNrKGZuKSB7XG4gICAgICAgICAgICBxdWV1ZS5wdXNoKGZuKTtcbiAgICAgICAgICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgncHJvY2Vzcy10aWNrJywgJyonKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gbmV4dFRpY2soZm4pIHtcbiAgICAgICAgc2V0VGltZW91dChmbiwgMCk7XG4gICAgfTtcbn0pKCk7XG5cbnByb2Nlc3MudGl0bGUgPSAnYnJvd3Nlcic7XG5wcm9jZXNzLmJyb3dzZXIgPSB0cnVlO1xucHJvY2Vzcy5lbnYgPSB7fTtcbnByb2Nlc3MuYXJndiA9IFtdO1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufVxuXG4vLyBUT0RPKHNodHlsbWFuKVxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzQnVmZmVyKGFyZykge1xuICByZXR1cm4gYXJnICYmIHR5cGVvZiBhcmcgPT09ICdvYmplY3QnXG4gICAgJiYgdHlwZW9mIGFyZy5jb3B5ID09PSAnZnVuY3Rpb24nXG4gICAgJiYgdHlwZW9mIGFyZy5maWxsID09PSAnZnVuY3Rpb24nXG4gICAgJiYgdHlwZW9mIGFyZy5yZWFkVUludDggPT09ICdmdW5jdGlvbic7XG59IiwiKGZ1bmN0aW9uIChwcm9jZXNzLGdsb2JhbCl7XG4vLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIGZvcm1hdFJlZ0V4cCA9IC8lW3NkaiVdL2c7XG5leHBvcnRzLmZvcm1hdCA9IGZ1bmN0aW9uKGYpIHtcbiAgaWYgKCFpc1N0cmluZyhmKSkge1xuICAgIHZhciBvYmplY3RzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIG9iamVjdHMucHVzaChpbnNwZWN0KGFyZ3VtZW50c1tpXSkpO1xuICAgIH1cbiAgICByZXR1cm4gb2JqZWN0cy5qb2luKCcgJyk7XG4gIH1cblxuICB2YXIgaSA9IDE7XG4gIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICB2YXIgbGVuID0gYXJncy5sZW5ndGg7XG4gIHZhciBzdHIgPSBTdHJpbmcoZikucmVwbGFjZShmb3JtYXRSZWdFeHAsIGZ1bmN0aW9uKHgpIHtcbiAgICBpZiAoeCA9PT0gJyUlJykgcmV0dXJuICclJztcbiAgICBpZiAoaSA+PSBsZW4pIHJldHVybiB4O1xuICAgIHN3aXRjaCAoeCkge1xuICAgICAgY2FzZSAnJXMnOiByZXR1cm4gU3RyaW5nKGFyZ3NbaSsrXSk7XG4gICAgICBjYXNlICclZCc6IHJldHVybiBOdW1iZXIoYXJnc1tpKytdKTtcbiAgICAgIGNhc2UgJyVqJzpcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoYXJnc1tpKytdKTtcbiAgICAgICAgfSBjYXRjaCAoXykge1xuICAgICAgICAgIHJldHVybiAnW0NpcmN1bGFyXSc7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiB4O1xuICAgIH1cbiAgfSk7XG4gIGZvciAodmFyIHggPSBhcmdzW2ldOyBpIDwgbGVuOyB4ID0gYXJnc1srK2ldKSB7XG4gICAgaWYgKGlzTnVsbCh4KSB8fCAhaXNPYmplY3QoeCkpIHtcbiAgICAgIHN0ciArPSAnICcgKyB4O1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHIgKz0gJyAnICsgaW5zcGVjdCh4KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHN0cjtcbn07XG5cblxuLy8gTWFyayB0aGF0IGEgbWV0aG9kIHNob3VsZCBub3QgYmUgdXNlZC5cbi8vIFJldHVybnMgYSBtb2RpZmllZCBmdW5jdGlvbiB3aGljaCB3YXJucyBvbmNlIGJ5IGRlZmF1bHQuXG4vLyBJZiAtLW5vLWRlcHJlY2F0aW9uIGlzIHNldCwgdGhlbiBpdCBpcyBhIG5vLW9wLlxuZXhwb3J0cy5kZXByZWNhdGUgPSBmdW5jdGlvbihmbiwgbXNnKSB7XG4gIC8vIEFsbG93IGZvciBkZXByZWNhdGluZyB0aGluZ3MgaW4gdGhlIHByb2Nlc3Mgb2Ygc3RhcnRpbmcgdXAuXG4gIGlmIChpc1VuZGVmaW5lZChnbG9iYWwucHJvY2VzcykpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gZXhwb3J0cy5kZXByZWNhdGUoZm4sIG1zZykuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9XG5cbiAgaWYgKHByb2Nlc3Mubm9EZXByZWNhdGlvbiA9PT0gdHJ1ZSkge1xuICAgIHJldHVybiBmbjtcbiAgfVxuXG4gIHZhciB3YXJuZWQgPSBmYWxzZTtcbiAgZnVuY3Rpb24gZGVwcmVjYXRlZCgpIHtcbiAgICBpZiAoIXdhcm5lZCkge1xuICAgICAgaWYgKHByb2Nlc3MudGhyb3dEZXByZWNhdGlvbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcbiAgICAgIH0gZWxzZSBpZiAocHJvY2Vzcy50cmFjZURlcHJlY2F0aW9uKSB7XG4gICAgICAgIGNvbnNvbGUudHJhY2UobXNnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IobXNnKTtcbiAgICAgIH1cbiAgICAgIHdhcm5lZCA9IHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICB9XG5cbiAgcmV0dXJuIGRlcHJlY2F0ZWQ7XG59O1xuXG5cbnZhciBkZWJ1Z3MgPSB7fTtcbnZhciBkZWJ1Z0Vudmlyb247XG5leHBvcnRzLmRlYnVnbG9nID0gZnVuY3Rpb24oc2V0KSB7XG4gIGlmIChpc1VuZGVmaW5lZChkZWJ1Z0Vudmlyb24pKVxuICAgIGRlYnVnRW52aXJvbiA9IHByb2Nlc3MuZW52Lk5PREVfREVCVUcgfHwgJyc7XG4gIHNldCA9IHNldC50b1VwcGVyQ2FzZSgpO1xuICBpZiAoIWRlYnVnc1tzZXRdKSB7XG4gICAgaWYgKG5ldyBSZWdFeHAoJ1xcXFxiJyArIHNldCArICdcXFxcYicsICdpJykudGVzdChkZWJ1Z0Vudmlyb24pKSB7XG4gICAgICB2YXIgcGlkID0gcHJvY2Vzcy5waWQ7XG4gICAgICBkZWJ1Z3Nbc2V0XSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgbXNnID0gZXhwb3J0cy5mb3JtYXQuYXBwbHkoZXhwb3J0cywgYXJndW1lbnRzKTtcbiAgICAgICAgY29uc29sZS5lcnJvcignJXMgJWQ6ICVzJywgc2V0LCBwaWQsIG1zZyk7XG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWJ1Z3Nbc2V0XSA9IGZ1bmN0aW9uKCkge307XG4gICAgfVxuICB9XG4gIHJldHVybiBkZWJ1Z3Nbc2V0XTtcbn07XG5cblxuLyoqXG4gKiBFY2hvcyB0aGUgdmFsdWUgb2YgYSB2YWx1ZS4gVHJ5cyB0byBwcmludCB0aGUgdmFsdWUgb3V0XG4gKiBpbiB0aGUgYmVzdCB3YXkgcG9zc2libGUgZ2l2ZW4gdGhlIGRpZmZlcmVudCB0eXBlcy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqIFRoZSBvYmplY3QgdG8gcHJpbnQgb3V0LlxuICogQHBhcmFtIHtPYmplY3R9IG9wdHMgT3B0aW9uYWwgb3B0aW9ucyBvYmplY3QgdGhhdCBhbHRlcnMgdGhlIG91dHB1dC5cbiAqL1xuLyogbGVnYWN5OiBvYmosIHNob3dIaWRkZW4sIGRlcHRoLCBjb2xvcnMqL1xuZnVuY3Rpb24gaW5zcGVjdChvYmosIG9wdHMpIHtcbiAgLy8gZGVmYXVsdCBvcHRpb25zXG4gIHZhciBjdHggPSB7XG4gICAgc2VlbjogW10sXG4gICAgc3R5bGl6ZTogc3R5bGl6ZU5vQ29sb3JcbiAgfTtcbiAgLy8gbGVnYWN5Li4uXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID49IDMpIGN0eC5kZXB0aCA9IGFyZ3VtZW50c1syXTtcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPj0gNCkgY3R4LmNvbG9ycyA9IGFyZ3VtZW50c1szXTtcbiAgaWYgKGlzQm9vbGVhbihvcHRzKSkge1xuICAgIC8vIGxlZ2FjeS4uLlxuICAgIGN0eC5zaG93SGlkZGVuID0gb3B0cztcbiAgfSBlbHNlIGlmIChvcHRzKSB7XG4gICAgLy8gZ290IGFuIFwib3B0aW9uc1wiIG9iamVjdFxuICAgIGV4cG9ydHMuX2V4dGVuZChjdHgsIG9wdHMpO1xuICB9XG4gIC8vIHNldCBkZWZhdWx0IG9wdGlvbnNcbiAgaWYgKGlzVW5kZWZpbmVkKGN0eC5zaG93SGlkZGVuKSkgY3R4LnNob3dIaWRkZW4gPSBmYWxzZTtcbiAgaWYgKGlzVW5kZWZpbmVkKGN0eC5kZXB0aCkpIGN0eC5kZXB0aCA9IDI7XG4gIGlmIChpc1VuZGVmaW5lZChjdHguY29sb3JzKSkgY3R4LmNvbG9ycyA9IGZhbHNlO1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LmN1c3RvbUluc3BlY3QpKSBjdHguY3VzdG9tSW5zcGVjdCA9IHRydWU7XG4gIGlmIChjdHguY29sb3JzKSBjdHguc3R5bGl6ZSA9IHN0eWxpemVXaXRoQ29sb3I7XG4gIHJldHVybiBmb3JtYXRWYWx1ZShjdHgsIG9iaiwgY3R4LmRlcHRoKTtcbn1cbmV4cG9ydHMuaW5zcGVjdCA9IGluc3BlY3Q7XG5cblxuLy8gaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9BTlNJX2VzY2FwZV9jb2RlI2dyYXBoaWNzXG5pbnNwZWN0LmNvbG9ycyA9IHtcbiAgJ2JvbGQnIDogWzEsIDIyXSxcbiAgJ2l0YWxpYycgOiBbMywgMjNdLFxuICAndW5kZXJsaW5lJyA6IFs0LCAyNF0sXG4gICdpbnZlcnNlJyA6IFs3LCAyN10sXG4gICd3aGl0ZScgOiBbMzcsIDM5XSxcbiAgJ2dyZXknIDogWzkwLCAzOV0sXG4gICdibGFjaycgOiBbMzAsIDM5XSxcbiAgJ2JsdWUnIDogWzM0LCAzOV0sXG4gICdjeWFuJyA6IFszNiwgMzldLFxuICAnZ3JlZW4nIDogWzMyLCAzOV0sXG4gICdtYWdlbnRhJyA6IFszNSwgMzldLFxuICAncmVkJyA6IFszMSwgMzldLFxuICAneWVsbG93JyA6IFszMywgMzldXG59O1xuXG4vLyBEb24ndCB1c2UgJ2JsdWUnIG5vdCB2aXNpYmxlIG9uIGNtZC5leGVcbmluc3BlY3Quc3R5bGVzID0ge1xuICAnc3BlY2lhbCc6ICdjeWFuJyxcbiAgJ251bWJlcic6ICd5ZWxsb3cnLFxuICAnYm9vbGVhbic6ICd5ZWxsb3cnLFxuICAndW5kZWZpbmVkJzogJ2dyZXknLFxuICAnbnVsbCc6ICdib2xkJyxcbiAgJ3N0cmluZyc6ICdncmVlbicsXG4gICdkYXRlJzogJ21hZ2VudGEnLFxuICAvLyBcIm5hbWVcIjogaW50ZW50aW9uYWxseSBub3Qgc3R5bGluZ1xuICAncmVnZXhwJzogJ3JlZCdcbn07XG5cblxuZnVuY3Rpb24gc3R5bGl6ZVdpdGhDb2xvcihzdHIsIHN0eWxlVHlwZSkge1xuICB2YXIgc3R5bGUgPSBpbnNwZWN0LnN0eWxlc1tzdHlsZVR5cGVdO1xuXG4gIGlmIChzdHlsZSkge1xuICAgIHJldHVybiAnXFx1MDAxYlsnICsgaW5zcGVjdC5jb2xvcnNbc3R5bGVdWzBdICsgJ20nICsgc3RyICtcbiAgICAgICAgICAgJ1xcdTAwMWJbJyArIGluc3BlY3QuY29sb3JzW3N0eWxlXVsxXSArICdtJztcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gc3RyO1xuICB9XG59XG5cblxuZnVuY3Rpb24gc3R5bGl6ZU5vQ29sb3Ioc3RyLCBzdHlsZVR5cGUpIHtcbiAgcmV0dXJuIHN0cjtcbn1cblxuXG5mdW5jdGlvbiBhcnJheVRvSGFzaChhcnJheSkge1xuICB2YXIgaGFzaCA9IHt9O1xuXG4gIGFycmF5LmZvckVhY2goZnVuY3Rpb24odmFsLCBpZHgpIHtcbiAgICBoYXNoW3ZhbF0gPSB0cnVlO1xuICB9KTtcblxuICByZXR1cm4gaGFzaDtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRWYWx1ZShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMpIHtcbiAgLy8gUHJvdmlkZSBhIGhvb2sgZm9yIHVzZXItc3BlY2lmaWVkIGluc3BlY3QgZnVuY3Rpb25zLlxuICAvLyBDaGVjayB0aGF0IHZhbHVlIGlzIGFuIG9iamVjdCB3aXRoIGFuIGluc3BlY3QgZnVuY3Rpb24gb24gaXRcbiAgaWYgKGN0eC5jdXN0b21JbnNwZWN0ICYmXG4gICAgICB2YWx1ZSAmJlxuICAgICAgaXNGdW5jdGlvbih2YWx1ZS5pbnNwZWN0KSAmJlxuICAgICAgLy8gRmlsdGVyIG91dCB0aGUgdXRpbCBtb2R1bGUsIGl0J3MgaW5zcGVjdCBmdW5jdGlvbiBpcyBzcGVjaWFsXG4gICAgICB2YWx1ZS5pbnNwZWN0ICE9PSBleHBvcnRzLmluc3BlY3QgJiZcbiAgICAgIC8vIEFsc28gZmlsdGVyIG91dCBhbnkgcHJvdG90eXBlIG9iamVjdHMgdXNpbmcgdGhlIGNpcmN1bGFyIGNoZWNrLlxuICAgICAgISh2YWx1ZS5jb25zdHJ1Y3RvciAmJiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGUgPT09IHZhbHVlKSkge1xuICAgIHZhciByZXQgPSB2YWx1ZS5pbnNwZWN0KHJlY3Vyc2VUaW1lcywgY3R4KTtcbiAgICBpZiAoIWlzU3RyaW5nKHJldCkpIHtcbiAgICAgIHJldCA9IGZvcm1hdFZhbHVlKGN0eCwgcmV0LCByZWN1cnNlVGltZXMpO1xuICAgIH1cbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgLy8gUHJpbWl0aXZlIHR5cGVzIGNhbm5vdCBoYXZlIHByb3BlcnRpZXNcbiAgdmFyIHByaW1pdGl2ZSA9IGZvcm1hdFByaW1pdGl2ZShjdHgsIHZhbHVlKTtcbiAgaWYgKHByaW1pdGl2ZSkge1xuICAgIHJldHVybiBwcmltaXRpdmU7XG4gIH1cblxuICAvLyBMb29rIHVwIHRoZSBrZXlzIG9mIHRoZSBvYmplY3QuXG4gIHZhciBrZXlzID0gT2JqZWN0LmtleXModmFsdWUpO1xuICB2YXIgdmlzaWJsZUtleXMgPSBhcnJheVRvSGFzaChrZXlzKTtcblxuICBpZiAoY3R4LnNob3dIaWRkZW4pIHtcbiAgICBrZXlzID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXModmFsdWUpO1xuICB9XG5cbiAgLy8gSUUgZG9lc24ndCBtYWtlIGVycm9yIGZpZWxkcyBub24tZW51bWVyYWJsZVxuICAvLyBodHRwOi8vbXNkbi5taWNyb3NvZnQuY29tL2VuLXVzL2xpYnJhcnkvaWUvZHd3NTJzYnQodj12cy45NCkuYXNweFxuICBpZiAoaXNFcnJvcih2YWx1ZSlcbiAgICAgICYmIChrZXlzLmluZGV4T2YoJ21lc3NhZ2UnKSA+PSAwIHx8IGtleXMuaW5kZXhPZignZGVzY3JpcHRpb24nKSA+PSAwKSkge1xuICAgIHJldHVybiBmb3JtYXRFcnJvcih2YWx1ZSk7XG4gIH1cblxuICAvLyBTb21lIHR5cGUgb2Ygb2JqZWN0IHdpdGhvdXQgcHJvcGVydGllcyBjYW4gYmUgc2hvcnRjdXR0ZWQuXG4gIGlmIChrZXlzLmxlbmd0aCA9PT0gMCkge1xuICAgIGlmIChpc0Z1bmN0aW9uKHZhbHVlKSkge1xuICAgICAgdmFyIG5hbWUgPSB2YWx1ZS5uYW1lID8gJzogJyArIHZhbHVlLm5hbWUgOiAnJztcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgnW0Z1bmN0aW9uJyArIG5hbWUgKyAnXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICAgIGlmIChpc1JlZ0V4cCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAncmVnZXhwJyk7XG4gICAgfVxuICAgIGlmIChpc0RhdGUodmFsdWUpKSB7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoRGF0ZS5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdkYXRlJyk7XG4gICAgfVxuICAgIGlmIChpc0Vycm9yKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGZvcm1hdEVycm9yKHZhbHVlKTtcbiAgICB9XG4gIH1cblxuICB2YXIgYmFzZSA9ICcnLCBhcnJheSA9IGZhbHNlLCBicmFjZXMgPSBbJ3snLCAnfSddO1xuXG4gIC8vIE1ha2UgQXJyYXkgc2F5IHRoYXQgdGhleSBhcmUgQXJyYXlcbiAgaWYgKGlzQXJyYXkodmFsdWUpKSB7XG4gICAgYXJyYXkgPSB0cnVlO1xuICAgIGJyYWNlcyA9IFsnWycsICddJ107XG4gIH1cblxuICAvLyBNYWtlIGZ1bmN0aW9ucyBzYXkgdGhhdCB0aGV5IGFyZSBmdW5jdGlvbnNcbiAgaWYgKGlzRnVuY3Rpb24odmFsdWUpKSB7XG4gICAgdmFyIG4gPSB2YWx1ZS5uYW1lID8gJzogJyArIHZhbHVlLm5hbWUgOiAnJztcbiAgICBiYXNlID0gJyBbRnVuY3Rpb24nICsgbiArICddJztcbiAgfVxuXG4gIC8vIE1ha2UgUmVnRXhwcyBzYXkgdGhhdCB0aGV5IGFyZSBSZWdFeHBzXG4gIGlmIChpc1JlZ0V4cCh2YWx1ZSkpIHtcbiAgICBiYXNlID0gJyAnICsgUmVnRXhwLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKTtcbiAgfVxuXG4gIC8vIE1ha2UgZGF0ZXMgd2l0aCBwcm9wZXJ0aWVzIGZpcnN0IHNheSB0aGUgZGF0ZVxuICBpZiAoaXNEYXRlKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBEYXRlLnByb3RvdHlwZS50b1VUQ1N0cmluZy5jYWxsKHZhbHVlKTtcbiAgfVxuXG4gIC8vIE1ha2UgZXJyb3Igd2l0aCBtZXNzYWdlIGZpcnN0IHNheSB0aGUgZXJyb3JcbiAgaWYgKGlzRXJyb3IodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIGZvcm1hdEVycm9yKHZhbHVlKTtcbiAgfVxuXG4gIGlmIChrZXlzLmxlbmd0aCA9PT0gMCAmJiAoIWFycmF5IHx8IHZhbHVlLmxlbmd0aCA9PSAwKSkge1xuICAgIHJldHVybiBicmFjZXNbMF0gKyBiYXNlICsgYnJhY2VzWzFdO1xuICB9XG5cbiAgaWYgKHJlY3Vyc2VUaW1lcyA8IDApIHtcbiAgICBpZiAoaXNSZWdFeHAodmFsdWUpKSB7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoUmVnRXhwLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSwgJ3JlZ2V4cCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJ1tPYmplY3RdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH1cblxuICBjdHguc2Vlbi5wdXNoKHZhbHVlKTtcblxuICB2YXIgb3V0cHV0O1xuICBpZiAoYXJyYXkpIHtcbiAgICBvdXRwdXQgPSBmb3JtYXRBcnJheShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLCBrZXlzKTtcbiAgfSBlbHNlIHtcbiAgICBvdXRwdXQgPSBrZXlzLm1hcChmdW5jdGlvbihrZXkpIHtcbiAgICAgIHJldHVybiBmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLCBrZXksIGFycmF5KTtcbiAgICB9KTtcbiAgfVxuXG4gIGN0eC5zZWVuLnBvcCgpO1xuXG4gIHJldHVybiByZWR1Y2VUb1NpbmdsZVN0cmluZyhvdXRwdXQsIGJhc2UsIGJyYWNlcyk7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0UHJpbWl0aXZlKGN0eCwgdmFsdWUpIHtcbiAgaWYgKGlzVW5kZWZpbmVkKHZhbHVlKSlcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoJ3VuZGVmaW5lZCcsICd1bmRlZmluZWQnKTtcbiAgaWYgKGlzU3RyaW5nKHZhbHVlKSkge1xuICAgIHZhciBzaW1wbGUgPSAnXFwnJyArIEpTT04uc3RyaW5naWZ5KHZhbHVlKS5yZXBsYWNlKC9eXCJ8XCIkL2csICcnKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnJlcGxhY2UoLycvZywgXCJcXFxcJ1wiKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcXFxcIi9nLCAnXCInKSArICdcXCcnO1xuICAgIHJldHVybiBjdHguc3R5bGl6ZShzaW1wbGUsICdzdHJpbmcnKTtcbiAgfVxuICBpZiAoaXNOdW1iZXIodmFsdWUpKVxuICAgIHJldHVybiBjdHguc3R5bGl6ZSgnJyArIHZhbHVlLCAnbnVtYmVyJyk7XG4gIGlmIChpc0Jvb2xlYW4odmFsdWUpKVxuICAgIHJldHVybiBjdHguc3R5bGl6ZSgnJyArIHZhbHVlLCAnYm9vbGVhbicpO1xuICAvLyBGb3Igc29tZSByZWFzb24gdHlwZW9mIG51bGwgaXMgXCJvYmplY3RcIiwgc28gc3BlY2lhbCBjYXNlIGhlcmUuXG4gIGlmIChpc051bGwodmFsdWUpKVxuICAgIHJldHVybiBjdHguc3R5bGl6ZSgnbnVsbCcsICdudWxsJyk7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0RXJyb3IodmFsdWUpIHtcbiAgcmV0dXJuICdbJyArIEVycm9yLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSArICddJztcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRBcnJheShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLCBrZXlzKSB7XG4gIHZhciBvdXRwdXQgPSBbXTtcbiAgZm9yICh2YXIgaSA9IDAsIGwgPSB2YWx1ZS5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICBpZiAoaGFzT3duUHJvcGVydHkodmFsdWUsIFN0cmluZyhpKSkpIHtcbiAgICAgIG91dHB1dC5wdXNoKGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsXG4gICAgICAgICAgU3RyaW5nKGkpLCB0cnVlKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dHB1dC5wdXNoKCcnKTtcbiAgICB9XG4gIH1cbiAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgIGlmICgha2V5Lm1hdGNoKC9eXFxkKyQvKSkge1xuICAgICAgb3V0cHV0LnB1c2goZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cyxcbiAgICAgICAgICBrZXksIHRydWUpKTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gb3V0cHV0O1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpIHtcbiAgdmFyIG5hbWUsIHN0ciwgZGVzYztcbiAgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IodmFsdWUsIGtleSkgfHwgeyB2YWx1ZTogdmFsdWVba2V5XSB9O1xuICBpZiAoZGVzYy5nZXQpIHtcbiAgICBpZiAoZGVzYy5zZXQpIHtcbiAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbR2V0dGVyL1NldHRlcl0nLCAnc3BlY2lhbCcpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW0dldHRlcl0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAoZGVzYy5zZXQpIHtcbiAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbU2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9XG4gIGlmICghaGFzT3duUHJvcGVydHkodmlzaWJsZUtleXMsIGtleSkpIHtcbiAgICBuYW1lID0gJ1snICsga2V5ICsgJ10nO1xuICB9XG4gIGlmICghc3RyKSB7XG4gICAgaWYgKGN0eC5zZWVuLmluZGV4T2YoZGVzYy52YWx1ZSkgPCAwKSB7XG4gICAgICBpZiAoaXNOdWxsKHJlY3Vyc2VUaW1lcykpIHtcbiAgICAgICAgc3RyID0gZm9ybWF0VmFsdWUoY3R4LCBkZXNjLnZhbHVlLCBudWxsKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0ciA9IGZvcm1hdFZhbHVlKGN0eCwgZGVzYy52YWx1ZSwgcmVjdXJzZVRpbWVzIC0gMSk7XG4gICAgICB9XG4gICAgICBpZiAoc3RyLmluZGV4T2YoJ1xcbicpID4gLTEpIHtcbiAgICAgICAgaWYgKGFycmF5KSB7XG4gICAgICAgICAgc3RyID0gc3RyLnNwbGl0KCdcXG4nKS5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgcmV0dXJuICcgICcgKyBsaW5lO1xuICAgICAgICAgIH0pLmpvaW4oJ1xcbicpLnN1YnN0cigyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzdHIgPSAnXFxuJyArIHN0ci5zcGxpdCgnXFxuJykubWFwKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgICAgICAgIHJldHVybiAnICAgJyArIGxpbmU7XG4gICAgICAgICAgfSkuam9pbignXFxuJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tDaXJjdWxhcl0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuICBpZiAoaXNVbmRlZmluZWQobmFtZSkpIHtcbiAgICBpZiAoYXJyYXkgJiYga2V5Lm1hdGNoKC9eXFxkKyQvKSkge1xuICAgICAgcmV0dXJuIHN0cjtcbiAgICB9XG4gICAgbmFtZSA9IEpTT04uc3RyaW5naWZ5KCcnICsga2V5KTtcbiAgICBpZiAobmFtZS5tYXRjaCgvXlwiKFthLXpBLVpfXVthLXpBLVpfMC05XSopXCIkLykpIHtcbiAgICAgIG5hbWUgPSBuYW1lLnN1YnN0cigxLCBuYW1lLmxlbmd0aCAtIDIpO1xuICAgICAgbmFtZSA9IGN0eC5zdHlsaXplKG5hbWUsICduYW1lJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5hbWUgPSBuYW1lLnJlcGxhY2UoLycvZywgXCJcXFxcJ1wiKVxuICAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxcXFwiL2csICdcIicpXG4gICAgICAgICAgICAgICAgIC5yZXBsYWNlKC8oXlwifFwiJCkvZywgXCInXCIpO1xuICAgICAgbmFtZSA9IGN0eC5zdHlsaXplKG5hbWUsICdzdHJpbmcnKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmFtZSArICc6ICcgKyBzdHI7XG59XG5cblxuZnVuY3Rpb24gcmVkdWNlVG9TaW5nbGVTdHJpbmcob3V0cHV0LCBiYXNlLCBicmFjZXMpIHtcbiAgdmFyIG51bUxpbmVzRXN0ID0gMDtcbiAgdmFyIGxlbmd0aCA9IG91dHB1dC5yZWR1Y2UoZnVuY3Rpb24ocHJldiwgY3VyKSB7XG4gICAgbnVtTGluZXNFc3QrKztcbiAgICBpZiAoY3VyLmluZGV4T2YoJ1xcbicpID49IDApIG51bUxpbmVzRXN0Kys7XG4gICAgcmV0dXJuIHByZXYgKyBjdXIucmVwbGFjZSgvXFx1MDAxYlxcW1xcZFxcZD9tL2csICcnKS5sZW5ndGggKyAxO1xuICB9LCAwKTtcblxuICBpZiAobGVuZ3RoID4gNjApIHtcbiAgICByZXR1cm4gYnJhY2VzWzBdICtcbiAgICAgICAgICAgKGJhc2UgPT09ICcnID8gJycgOiBiYXNlICsgJ1xcbiAnKSArXG4gICAgICAgICAgICcgJyArXG4gICAgICAgICAgIG91dHB1dC5qb2luKCcsXFxuICAnKSArXG4gICAgICAgICAgICcgJyArXG4gICAgICAgICAgIGJyYWNlc1sxXTtcbiAgfVxuXG4gIHJldHVybiBicmFjZXNbMF0gKyBiYXNlICsgJyAnICsgb3V0cHV0LmpvaW4oJywgJykgKyAnICcgKyBicmFjZXNbMV07XG59XG5cblxuLy8gTk9URTogVGhlc2UgdHlwZSBjaGVja2luZyBmdW5jdGlvbnMgaW50ZW50aW9uYWxseSBkb24ndCB1c2UgYGluc3RhbmNlb2ZgXG4vLyBiZWNhdXNlIGl0IGlzIGZyYWdpbGUgYW5kIGNhbiBiZSBlYXNpbHkgZmFrZWQgd2l0aCBgT2JqZWN0LmNyZWF0ZSgpYC5cbmZ1bmN0aW9uIGlzQXJyYXkoYXIpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoYXIpO1xufVxuZXhwb3J0cy5pc0FycmF5ID0gaXNBcnJheTtcblxuZnVuY3Rpb24gaXNCb29sZWFuKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ2Jvb2xlYW4nO1xufVxuZXhwb3J0cy5pc0Jvb2xlYW4gPSBpc0Jvb2xlYW47XG5cbmZ1bmN0aW9uIGlzTnVsbChhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gbnVsbDtcbn1cbmV4cG9ydHMuaXNOdWxsID0gaXNOdWxsO1xuXG5mdW5jdGlvbiBpc051bGxPclVuZGVmaW5lZChhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PSBudWxsO1xufVxuZXhwb3J0cy5pc051bGxPclVuZGVmaW5lZCA9IGlzTnVsbE9yVW5kZWZpbmVkO1xuXG5mdW5jdGlvbiBpc051bWJlcihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdudW1iZXInO1xufVxuZXhwb3J0cy5pc051bWJlciA9IGlzTnVtYmVyO1xuXG5mdW5jdGlvbiBpc1N0cmluZyhhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdzdHJpbmcnO1xufVxuZXhwb3J0cy5pc1N0cmluZyA9IGlzU3RyaW5nO1xuXG5mdW5jdGlvbiBpc1N5bWJvbChhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnO1xufVxuZXhwb3J0cy5pc1N5bWJvbCA9IGlzU3ltYm9sO1xuXG5mdW5jdGlvbiBpc1VuZGVmaW5lZChhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gdm9pZCAwO1xufVxuZXhwb3J0cy5pc1VuZGVmaW5lZCA9IGlzVW5kZWZpbmVkO1xuXG5mdW5jdGlvbiBpc1JlZ0V4cChyZSkge1xuICByZXR1cm4gaXNPYmplY3QocmUpICYmIG9iamVjdFRvU3RyaW5nKHJlKSA9PT0gJ1tvYmplY3QgUmVnRXhwXSc7XG59XG5leHBvcnRzLmlzUmVnRXhwID0gaXNSZWdFeHA7XG5cbmZ1bmN0aW9uIGlzT2JqZWN0KGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ29iamVjdCcgJiYgYXJnICE9PSBudWxsO1xufVxuZXhwb3J0cy5pc09iamVjdCA9IGlzT2JqZWN0O1xuXG5mdW5jdGlvbiBpc0RhdGUoZCkge1xuICByZXR1cm4gaXNPYmplY3QoZCkgJiYgb2JqZWN0VG9TdHJpbmcoZCkgPT09ICdbb2JqZWN0IERhdGVdJztcbn1cbmV4cG9ydHMuaXNEYXRlID0gaXNEYXRlO1xuXG5mdW5jdGlvbiBpc0Vycm9yKGUpIHtcbiAgcmV0dXJuIGlzT2JqZWN0KGUpICYmXG4gICAgICAob2JqZWN0VG9TdHJpbmcoZSkgPT09ICdbb2JqZWN0IEVycm9yXScgfHwgZSBpbnN0YW5jZW9mIEVycm9yKTtcbn1cbmV4cG9ydHMuaXNFcnJvciA9IGlzRXJyb3I7XG5cbmZ1bmN0aW9uIGlzRnVuY3Rpb24oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnZnVuY3Rpb24nO1xufVxuZXhwb3J0cy5pc0Z1bmN0aW9uID0gaXNGdW5jdGlvbjtcblxuZnVuY3Rpb24gaXNQcmltaXRpdmUoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IG51bGwgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdib29sZWFuJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ251bWJlcicgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdzdHJpbmcnIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnc3ltYm9sJyB8fCAgLy8gRVM2IHN5bWJvbFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3VuZGVmaW5lZCc7XG59XG5leHBvcnRzLmlzUHJpbWl0aXZlID0gaXNQcmltaXRpdmU7XG5cbmV4cG9ydHMuaXNCdWZmZXIgPSByZXF1aXJlKCcuL3N1cHBvcnQvaXNCdWZmZXInKTtcblxuZnVuY3Rpb24gb2JqZWN0VG9TdHJpbmcobykge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG8pO1xufVxuXG5cbmZ1bmN0aW9uIHBhZChuKSB7XG4gIHJldHVybiBuIDwgMTAgPyAnMCcgKyBuLnRvU3RyaW5nKDEwKSA6IG4udG9TdHJpbmcoMTApO1xufVxuXG5cbnZhciBtb250aHMgPSBbJ0phbicsICdGZWInLCAnTWFyJywgJ0FwcicsICdNYXknLCAnSnVuJywgJ0p1bCcsICdBdWcnLCAnU2VwJyxcbiAgICAgICAgICAgICAgJ09jdCcsICdOb3YnLCAnRGVjJ107XG5cbi8vIDI2IEZlYiAxNjoxOTozNFxuZnVuY3Rpb24gdGltZXN0YW1wKCkge1xuICB2YXIgZCA9IG5ldyBEYXRlKCk7XG4gIHZhciB0aW1lID0gW3BhZChkLmdldEhvdXJzKCkpLFxuICAgICAgICAgICAgICBwYWQoZC5nZXRNaW51dGVzKCkpLFxuICAgICAgICAgICAgICBwYWQoZC5nZXRTZWNvbmRzKCkpXS5qb2luKCc6Jyk7XG4gIHJldHVybiBbZC5nZXREYXRlKCksIG1vbnRoc1tkLmdldE1vbnRoKCldLCB0aW1lXS5qb2luKCcgJyk7XG59XG5cblxuLy8gbG9nIGlzIGp1c3QgYSB0aGluIHdyYXBwZXIgdG8gY29uc29sZS5sb2cgdGhhdCBwcmVwZW5kcyBhIHRpbWVzdGFtcFxuZXhwb3J0cy5sb2cgPSBmdW5jdGlvbigpIHtcbiAgY29uc29sZS5sb2coJyVzIC0gJXMnLCB0aW1lc3RhbXAoKSwgZXhwb3J0cy5mb3JtYXQuYXBwbHkoZXhwb3J0cywgYXJndW1lbnRzKSk7XG59O1xuXG5cbi8qKlxuICogSW5oZXJpdCB0aGUgcHJvdG90eXBlIG1ldGhvZHMgZnJvbSBvbmUgY29uc3RydWN0b3IgaW50byBhbm90aGVyLlxuICpcbiAqIFRoZSBGdW5jdGlvbi5wcm90b3R5cGUuaW5oZXJpdHMgZnJvbSBsYW5nLmpzIHJld3JpdHRlbiBhcyBhIHN0YW5kYWxvbmVcbiAqIGZ1bmN0aW9uIChub3Qgb24gRnVuY3Rpb24ucHJvdG90eXBlKS4gTk9URTogSWYgdGhpcyBmaWxlIGlzIHRvIGJlIGxvYWRlZFxuICogZHVyaW5nIGJvb3RzdHJhcHBpbmcgdGhpcyBmdW5jdGlvbiBuZWVkcyB0byBiZSByZXdyaXR0ZW4gdXNpbmcgc29tZSBuYXRpdmVcbiAqIGZ1bmN0aW9ucyBhcyBwcm90b3R5cGUgc2V0dXAgdXNpbmcgbm9ybWFsIEphdmFTY3JpcHQgZG9lcyBub3Qgd29yayBhc1xuICogZXhwZWN0ZWQgZHVyaW5nIGJvb3RzdHJhcHBpbmcgKHNlZSBtaXJyb3IuanMgaW4gcjExNDkwMykuXG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbn0gY3RvciBDb25zdHJ1Y3RvciBmdW5jdGlvbiB3aGljaCBuZWVkcyB0byBpbmhlcml0IHRoZVxuICogICAgIHByb3RvdHlwZS5cbiAqIEBwYXJhbSB7ZnVuY3Rpb259IHN1cGVyQ3RvciBDb25zdHJ1Y3RvciBmdW5jdGlvbiB0byBpbmhlcml0IHByb3RvdHlwZSBmcm9tLlxuICovXG5leHBvcnRzLmluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKTtcblxuZXhwb3J0cy5fZXh0ZW5kID0gZnVuY3Rpb24ob3JpZ2luLCBhZGQpIHtcbiAgLy8gRG9uJ3QgZG8gYW55dGhpbmcgaWYgYWRkIGlzbid0IGFuIG9iamVjdFxuICBpZiAoIWFkZCB8fCAhaXNPYmplY3QoYWRkKSkgcmV0dXJuIG9yaWdpbjtcblxuICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGFkZCk7XG4gIHZhciBpID0ga2V5cy5sZW5ndGg7XG4gIHdoaWxlIChpLS0pIHtcbiAgICBvcmlnaW5ba2V5c1tpXV0gPSBhZGRba2V5c1tpXV07XG4gIH1cbiAgcmV0dXJuIG9yaWdpbjtcbn07XG5cbmZ1bmN0aW9uIGhhc093blByb3BlcnR5KG9iaiwgcHJvcCkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCk7XG59XG5cbn0pLmNhbGwodGhpcyxyZXF1aXJlKFwiVkNtRXN3XCIpLHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSkiLCJjaGFpICAgICAgPSByZXF1aXJlKCdjaGFpJylcclxuZXhwZWN0ICAgID0gY2hhaS5leHBlY3Rcclxuc2lub24gICAgID0gcmVxdWlyZSgnc2lub24nKVxyXG5zaW5vbkNoYWkgPSByZXF1aXJlKCdzaW5vbi1jaGFpJylcclxuXyAgICAgICAgID0gcmVxdWlyZShcInVuZGVyc2NvcmVcIilcclxuXHJcbmNoYWkudXNlKHNpbm9uQ2hhaSlcclxuXHJcbkNvbm5lY3RvciA9IHJlcXVpcmUgXCIuLi8uLi95LXRlc3QvbGliL3ktdGVzdC5jb2ZmZWVcIlxyXG5ZID0gbnVsbCAjIG5lZWQgZ2xvYmFsIHJlZmVyZW5jZSFcclxuXHJcbm1vZHVsZS5leHBvcnRzID0gY2xhc3MgVGVzdFxyXG4gIGNvbnN0cnVjdG9yOiAoQG5hbWVfc3VmZml4ID0gXCJcIiwgWWpzKS0+XHJcbiAgICBZID0gWWpzXHJcbiAgICBAbnVtYmVyX29mX3Rlc3RfY2FzZXNfbXVsdGlwbGllciA9IDFcclxuICAgIEByZXBlYXRfdGhpcyA9IDEgKiBAbnVtYmVyX29mX3Rlc3RfY2FzZXNfbXVsdGlwbGllclxyXG4gICAgQGRvU29tZXRoaW5nX2Ftb3VudCA9IDEyMyAqIEBudW1iZXJfb2ZfdGVzdF9jYXNlc19tdWx0aXBsaWVyXHJcbiAgICBAbnVtYmVyX29mX2VuZ2luZXMgPSA1ICsgQG51bWJlcl9vZl90ZXN0X2Nhc2VzX211bHRpcGxpZXIgLSAxXHJcblxyXG4gICAgQHRpbWUgPSAwICMgZGVub3RlcyB0byB0aGUgdGltZSB3aGVuIHJ1biB3YXMgc3RhcnRlZFxyXG4gICAgQG9wcyA9IDAgIyBudW1iZXIgb2Ygb3BlcmF0aW9ucyAodXNlZCB3aXRoIEB0aW1lKVxyXG4gICAgQHRpbWVfbm93ID0gMCAjIGN1cnJlbnQgdGltZVxyXG4gICAgQG1heF9kZXB0aCA9IDNcclxuXHJcbiAgICBAZGVidWcgPSBmYWxzZVxyXG5cclxuICAgIEByZWluaXRpYWxpemUoKVxyXG4gICAgZm9yIGdmIGluIEBnZXRHZW5lcmF0aW5nRnVuY3Rpb25zKDApXHJcbiAgICAgIGlmIG5vdCAoZ2YudHlwZXM/IGFuZCBnZi5mPylcclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJHZW5lcmF0aW5nIEZ1bmN0aW9ucyBhcmUgbm90IGluaXRpYWxpemVkIHByb3Blcmx5IVwiXHJcbiAgICAgIGZvciB0IGluIGdmLnR5cGVzXHJcbiAgICAgICAgaWYgbm90IHQ/XHJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgaGF2ZW50IGluY2x1ZGVkdCB0aGlzIHR5cGUgaW4gWSAoZG8gcmVxdWlyZSAneS13aGF0ZXZlcicpXCJcclxuXHJcbiAgcmVpbml0aWFsaXplOiAoKS0+XHJcbiAgICBAdXNlcnMgPSBbXVxyXG4gICAgZm9yIGkgaW4gWzAuLi5AbnVtYmVyX29mX2VuZ2luZXNdXHJcbiAgICAgIHUgPSBAbWFrZU5ld1VzZXIgKGkrQG5hbWVfc3VmZml4KVxyXG4gICAgICBmb3IgdXNlciBpbiBAdXNlcnNcclxuICAgICAgICB1Ll9tb2RlbC5jb25uZWN0b3Iuam9pbih1c2VyLl9tb2RlbC5jb25uZWN0b3IpICMgVE9ETzogY2hhbmdlIHRoZSB0ZXN0LWNvbm5lY3RvciB0byBtYWtlIHRoaXMgbW9yZSBjb252ZW5pZW50XHJcbiAgICAgIEB1c2Vycy5wdXNoIHVcclxuICAgIEBpbml0VXNlcnM/KEB1c2Vyc1swXSlcclxuICAgIEBmbHVzaEFsbCgpXHJcblxyXG4gICMgaXMgY2FsbGVkIGJ5IGltcGxlbWVudGluZyBjbGFzc1xyXG4gIG1ha2VOZXdVc2VyOiAodXNlciktPlxyXG4gICAgdXNlci5fbW9kZWwuSEIuc3RvcEdhcmJhZ2VDb2xsZWN0aW9uKClcclxuICAgIHVzZXJcclxuXHJcbiAgZ2V0U29tZVVzZXI6ICgpLT5cclxuICAgIGkgPSBfLnJhbmRvbSAwLCAoQHVzZXJzLmxlbmd0aC0xKVxyXG4gICAgQHVzZXJzW2ldXHJcblxyXG4gIGdldFJhbmRvbVRleHQ6IChjaGFycywgbWluX2xlbmd0aCA9IDApLT5cclxuICAgIGNoYXJzID89IFwiYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpcIlxyXG4gICAgbGVuZ3RoID0gXy5yYW5kb20gbWluX2xlbmd0aCwgMTBcclxuICAgICNsZW5ndGggPSAxXHJcbiAgICBuZXh0Y2hhciA9IGNoYXJzWyhfLnJhbmRvbSAwLCAoY2hhcnMubGVuZ3RoLTEpKV1cclxuICAgIHRleHQgPSBcIlwiXHJcbiAgICBfKGxlbmd0aCkudGltZXMgKCktPiB0ZXh0ICs9IG5leHRjaGFyXHJcbiAgICB0ZXh0XHJcblxyXG4gIGdldFJhbmRvbU9iamVjdDogKCktPlxyXG4gICAgcmVzdWx0ID0ge31cclxuICAgIGtleTEgPSBAZ2V0UmFuZG9tS2V5KClcclxuICAgIGtleTIgPSBAZ2V0UmFuZG9tS2V5KClcclxuICAgIHZhbDEgPSBAZ2V0UmFuZG9tVGV4dCgpXHJcbiAgICB2YWwyID0gbnVsbFxyXG4gICAgaWYgXy5yYW5kb20oMCwxKSBpcyAxXHJcbiAgICAgIHZhbDIgPSBAZ2V0UmFuZG9tT2JqZWN0KClcclxuICAgIGVsc2VcclxuICAgICAgdmFsMiA9IEBnZXRSYW5kb21UZXh0KClcclxuICAgIHJlc3VsdFtrZXkxXSA9IHZhbDFcclxuICAgIHJlc3VsdFtrZXkyXSA9IHZhbDJcclxuICAgIHJlc3VsdFxyXG5cclxuICBnZXRSYW5kb21LZXk6ICgpLT5cclxuICAgIEBnZXRSYW5kb21UZXh0IFsxLDIsJ3gnLCd5J10sIDEgIyBvbmx5IDQga2V5c1xyXG5cclxuICBnZXRHZW5lcmF0aW5nRnVuY3Rpb25zOiAodXNlcl9udW0pPT5cclxuICAgIHR5cGVzID0gQHVzZXJzW3VzZXJfbnVtXS5fbW9kZWwub3BlcmF0aW9uc1xyXG4gICAgW11cclxuICBnZXRSYW5kb21Sb290OiAodXNlcl9udW0pLT5cclxuICAgIHRocm93IG5ldyBFcnJvciBcImltcGxlbWVudCBtZSFcIlxyXG5cclxuICBjb21wYXJlOiAobzEsIG8yLCBkZXB0aCA9IChAbWF4X2RlcHRoKzEpKS0+XHJcbiAgICBpZiBvMSBpcyBvMiBvciBkZXB0aCA8PSAwXHJcbiAgICAgIHRydWVcclxuICAgIGVsc2UgaWYgbzEuX25hbWU/IGFuZCBvMS5fbmFtZSBpc250IG8yLl9uYW1lXHJcbiAgICAgIHRocm93IG5ldyBFcnJvciBcImRpZmZlcmVudCB0eXBlc1wiXHJcbiAgICBlbHNlIGlmIG8xLl9tb2RlbD9cclxuICAgICAgQGNvbXBhcmUgbzEuX21vZGVsLCBvMi5fbW9kZWwsIGRlcHRoXHJcbiAgICBlbHNlIGlmIG8xLnR5cGUgaXMgXCJNYXBNYW5hZ2VyXCJcclxuICAgICAgZm9yIG5hbWUsIHZhbCBvZiBvMS52YWwoKVxyXG4gICAgICAgIEBjb21wYXJlKHZhbCwgbzIudmFsKG5hbWUpLCBkZXB0aC0xKVxyXG4gICAgZWxzZSBpZiBvMS50eXBlIGlzIFwiTGlzdE1hbmFnZXJcIlxyXG4gICAgICBmb3IgdmFsLGkgaW4gbzEudmFsKClcclxuICAgICAgICBAY29tcGFyZSh2YWwsIG8yLnZhbChpKSwgZGVwdGgtMSlcclxuICAgIGVsc2UgaWYgbzEuY29uc3RydWN0b3IgaXMgQXJyYXkgYW5kIG8yLmNvbnN0cnVjdG9yIGlzIEFycmF5XHJcbiAgICAgIGlmIG8xLmxlbmd0aCBpc250IG8yLmxlbmd0aFxyXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcIlRoZSBBcnJheXMgZG8gbm90IGhhdmUgdGhlIHNhbWUgc2l6ZSFcIlxyXG4gICAgICBmb3IgbyxpIGluIG8xXHJcbiAgICAgICAgQGNvbXBhcmUgbywgbzJbaV0sIChkZXB0aC0xKVxyXG4gICAgZWxzZSBpZiBvMSBpc250IG8yXHJcbiAgICAgIHRocm93IG5ldyBFcnJvciBcImRpZmZlcmVudCB2YWx1ZXNcIlxyXG4gICAgZWxzZVxyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJJIGRvbid0IGtub3cgd2hhdCB0byBkbyAuLiBcIlxyXG5cclxuICBnZW5lcmF0ZVJhbmRvbU9wOiAodXNlcl9udW0pPT5cclxuICAgIHkgPSBAZ2V0UmFuZG9tUm9vdCh1c2VyX251bSlcclxuICAgIGNob2ljZXMgPSBAZ2V0R2VuZXJhdGluZ0Z1bmN0aW9ucyh1c2VyX251bSkuZmlsdGVyIChnZiktPlxyXG4gICAgICBfLnNvbWUgZ2YudHlwZXMsICh0eXBlKS0+XHJcbiAgICAgICAgeSBpbnN0YW5jZW9mIHR5cGVcclxuXHJcbiAgICBpZiBjaG9pY2VzLmxlbmd0aCBpcyAwXHJcbiAgICAgIGNvbnNvbGUuZGlyKHkpXHJcbiAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBmb3Jnb3QgdG8gc3BlY2lmeSBhIHRlc3QgZ2VuZXJhdGlvbiBtZXRob3QgZm9yIHRoaXMgT3BlcmF0aW9uISAoI3t5LnR5cGV9KVwiXHJcbiAgICBpID0gXy5yYW5kb20gMCwgKGNob2ljZXMubGVuZ3RoLTEpXHJcbiAgICBjaG9pY2VzW2ldLmYgeVxyXG5cclxuICBhcHBseVJhbmRvbU9wOiAodXNlcl9udW0pPT5cclxuICAgIHVzZXIgPSBAdXNlcnNbdXNlcl9udW1dXHJcbiAgICB1c2VyLl9tb2RlbC5jb25uZWN0b3IuZmx1c2hPbmVSYW5kb20oKVxyXG5cclxuICBkb1NvbWV0aGluZzogKCktPlxyXG4gICAgdXNlcl9udW0gPSBfLnJhbmRvbSAoQG51bWJlcl9vZl9lbmdpbmVzLTEpXHJcbiAgICBjaG9pY2VzID0gW0BhcHBseVJhbmRvbU9wLCBAZ2VuZXJhdGVSYW5kb21PcF1cclxuICAgIGNob2ljZSA9IF8ucmFuZG9tIChjaG9pY2VzLmxlbmd0aC0xKVxyXG4gICAgY2hvaWNlc1tjaG9pY2VdKHVzZXJfbnVtKVxyXG5cclxuICBmbHVzaEFsbDogKGZpbmFsKS0+XHJcbiAgICAjIFRPRE86ISFcclxuICAgIGZpbmFsID0gZmFsc2VcclxuICAgIGlmIEB1c2Vycy5sZW5ndGggPD0gMSBvciBub3QgZmluYWxcclxuICAgICAgZm9yIHVzZXIsdXNlcl9udW1iZXIgaW4gQHVzZXJzXHJcbiAgICAgICAgdXNlci5fbW9kZWwuY29ubmVjdG9yLmZsdXNoQWxsKClcclxuICAgIGVsc2VcclxuICAgICAgZm9yIHVzZXIsdXNlcl9udW1iZXIgaW4gQHVzZXJzWzEuLl1cclxuICAgICAgICB1c2VyLl9tb2RlbC5jb25uZWN0b3IuZmx1c2hBbGwoKVxyXG4gICAgICBvcHMgPSBAdXNlcnNbMV0uZ2V0SGlzdG9yeUJ1ZmZlcigpLl9lbmNvZGUgQHVzZXJzWzBdLkhCLmdldE9wZXJhdGlvbkNvdW50ZXIoKVxyXG4gICAgICBAdXNlcnNbMF0uZW5naW5lLmFwcGx5T3BzQ2hlY2tEb3VibGUgb3BzXHJcblxyXG5cclxuICBjb21wYXJlQWxsOiAodGVzdF9udW1iZXIpLT5cclxuICAgIEBmbHVzaEFsbCh0cnVlKVxyXG5cclxuICAgIEB0aW1lICs9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCkgLSBAdGltZV9ub3dcclxuXHJcbiAgICBudW1iZXJfb2ZfY3JlYXRlZF9vcGVyYXRpb25zID0gMFxyXG4gICAgZm9yIGkgaW4gWzAuLi4oQHVzZXJzLmxlbmd0aCldXHJcbiAgICAgIG51bWJlcl9vZl9jcmVhdGVkX29wZXJhdGlvbnMgKz0gQHVzZXJzW2ldLl9tb2RlbC5jb25uZWN0b3IuZ2V0T3BzSW5FeGVjdXRpb25PcmRlcigpLmxlbmd0aFxyXG4gICAgQG9wcyArPSBudW1iZXJfb2ZfY3JlYXRlZF9vcGVyYXRpb25zKkB1c2Vycy5sZW5ndGhcclxuXHJcbiAgICBvcHNfcGVyX21zZWsgPSBNYXRoLmZsb29yKEBvcHMvQHRpbWUpXHJcbiAgICBpZiB0ZXN0X251bWJlcj8gIyBhbmQgQGRlYnVnXHJcbiAgICAgIGNvbnNvbGUubG9nIFwiI3t0ZXN0X251bWJlcn0vI3tAcmVwZWF0X3RoaXN9OiAje251bWJlcl9vZl9jcmVhdGVkX29wZXJhdGlvbnN9IHdlcmUgY3JlYXRlZCBhbmQgYXBwbGllZCBvbiAoI3tAdXNlcnMubGVuZ3RofSkgdXNlcnMgb3BzIGluIGEgZGlmZmVyZW50IG9yZGVyLlwiICsgXCIgT3ZlciBhbGwgd2UgY29uc3VtZWQgI3tAb3BzfSBvcGVyYXRpb25zIGluICN7QHRpbWUvMTAwMH0gc2Vjb25kcyAoI3tvcHNfcGVyX21zZWt9IG9wcy9tc2VrKS5cIlxyXG5cclxuICAgIGZvciBpIGluIFswLi4uKEB1c2Vycy5sZW5ndGgtMSldXHJcbiAgICAgIGlmIEBkZWJ1Z1xyXG4gICAgICAgIGlmIG5vdCBfLmlzRXF1YWwgQGdldENvbnRlbnQoaSksIEBnZXRDb250ZW50KGkrMSlcclxuICAgICAgICAgIHByaW50T3BzSW5FeGVjdXRpb25PcmRlciA9IChvdG51bWJlciwgb3RoZXJvdG51bWJlcik9PlxyXG4gICAgICAgICAgICBvcHMgPSBfLmZpbHRlciBAdXNlcnNbb3RudW1iZXJdLl9tb2RlbC5jb25uZWN0b3IuZ2V0T3BzSW5FeGVjdXRpb25PcmRlcigpLCAobyktPlxyXG4gICAgICAgICAgICAgIHR5cGVvZiBvLnVpZC5vcF9uYW1lIGlzbnQgJ3N0cmluZycgYW5kIG8udWlkLmNyZWF0b3IgaXNudCAnXydcclxuICAgICAgICAgICAgZm9yIHMsaiBpbiBvcHNcclxuICAgICAgICAgICAgICBjb25zb2xlLmxvZyBcIm9wI3tqfSA9IFwiICsgKEpTT04uc3RyaW5naWZ5IHMpXHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nIFwiXCJcclxuICAgICAgICAgICAgcyA9IFwib3BzID0gW1wiXHJcbiAgICAgICAgICAgIGZvciBvLGogaW4gb3BzXHJcbiAgICAgICAgICAgICAgaWYgaiBpc250IDBcclxuICAgICAgICAgICAgICAgIHMgKz0gXCIsIFwiXHJcbiAgICAgICAgICAgICAgcyArPSBcIm9wI3tqfVwiXHJcbiAgICAgICAgICAgIHMgKz0gXCJdXCJcclxuICAgICAgICAgICAgY29uc29sZS5sb2cgc1xyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyBcIkB0ZXN0X3VzZXIuZW5naW5lLmFwcGx5T3BzIG9wc1wiXHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nIFwiZXhwZWN0KEB0ZXN0X3VzZXIudmFsKCduYW1lJykudmFsKCkpLnRvLmVxdWFsKFxcXCIje0B1c2Vyc1tvdGhlcm90bnVtYmVyXS52YWwoJ25hbWUnKS52YWwoKX1cXFwiKVwiXHJcbiAgICAgICAgICAgIG9wc1xyXG4gICAgICAgICAgY29uc29sZS5sb2cgXCJcIlxyXG4gICAgICAgICAgY29uc29sZS5sb2cgXCJGb3VuZCBhbiBPVCBQdXp6bGUhXCJcclxuICAgICAgICAgIGNvbnNvbGUubG9nIFwiT1Qgc3RhdGVzOlwiXHJcbiAgICAgICAgICBmb3IgdSxqIGluIEB1c2Vyc1xyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyBcIk9UI3tqfTogXCIrdS52YWwoJ25hbWUnKS52YWwoKVxyXG4gICAgICAgICAgY29uc29sZS5sb2cgXCJcXG5PVCBleGVjdXRpb24gb3JkZXIgKCN7aX0sI3tpKzF9KTpcIlxyXG4gICAgICAgICAgcHJpbnRPcHNJbkV4ZWN1dGlvbk9yZGVyIGksIGkrMVxyXG4gICAgICAgICAgY29uc29sZS5sb2cgXCJcIlxyXG4gICAgICAgICAgb3BzID0gcHJpbnRPcHNJbkV4ZWN1dGlvbk9yZGVyIGkrMSwgaVxyXG5cclxuICAgICAgICAgIGNvbnNvbGUubG9nIFwiXCJcclxuICAgICAgZXhwZWN0KEBjb21wYXJlKEB1c2Vyc1tpXSwgQHVzZXJzW2krMV0pKS50by5ub3QuYmUudW5kZWZpbmVkXHJcblxyXG4gIHJ1bjogKCktPlxyXG4gICAgaWYgQGRlYnVnXHJcbiAgICAgIGNvbnNvbGUubG9nICcnXHJcbiAgICBmb3IgdGltZXMgaW4gWzEuLkByZXBlYXRfdGhpc11cclxuICAgICAgQHRpbWVfbm93ID0gKG5ldyBEYXRlKS5nZXRUaW1lKClcclxuICAgICAgZm9yIGkgaW4gWzEuLk1hdGguZmxvb3IoQGRvU29tZXRoaW5nX2Ftb3VudC8yKV1cclxuICAgICAgICBAZG9Tb21ldGhpbmcoKVxyXG4gICAgICBAZmx1c2hBbGwoZmFsc2UpXHJcbiAgICAgIGZvciB1IGluIEB1c2Vyc1xyXG4gICAgICAgIHUuX21vZGVsLkhCLmVtcHR5R2FyYmFnZSgpXHJcbiAgICAgIGZvciBpIGluIFsxLi5NYXRoLmZsb29yKEBkb1NvbWV0aGluZ19hbW91bnQvMildXHJcbiAgICAgICAgQGRvU29tZXRoaW5nKClcclxuXHJcbiAgICAgIEBjb21wYXJlQWxsKHRpbWVzKVxyXG4gICAgICBAdGVzdEhCZW5jb2RpbmcoKVxyXG4gICAgICBpZiB0aW1lcyBpc250IEByZXBlYXRfdGhpc1xyXG4gICAgICAgIEByZWluaXRpYWxpemUoKVxyXG5cclxuICB0ZXN0SEJlbmNvZGluZzogKCktPlxyXG4gICAgIyBpbiBjYXNlIG9mIEpzb25GcmFtZXdvcmssIGV2ZXJ5IHVzZXIgd2lsbCBjcmVhdGUgaXRzIEpTT04gZmlyc3QhIHRoZXJlZm9yZSwgdGhlIHRlc3R1c2VycyBpZCBtdXN0IGJlIHNtYWxsIHRoYW4gYWxsIHRoZSBvdGhlcnMgKHNlZSBJbnNlcnRUeXBlKVxyXG4gICAgQHVzZXJzW0B1c2Vycy5sZW5ndGhdID0gQG1ha2VOZXdVc2VyICgtMSkgIyB0aGlzIGRvZXMgbm90IHdhbnQgdG8gam9pbiB3aXRoIGFueW1vZHlcclxuXHJcbiAgICBAdXNlcnNbQHVzZXJzLmxlbmd0aC0xXS5fbW9kZWwuSEIucmVuZXdTdGF0ZVZlY3RvciBAdXNlcnNbMF0uX21vZGVsLkhCLmdldE9wZXJhdGlvbkNvdW50ZXIoKVxyXG4gICAgQHVzZXJzW0B1c2Vycy5sZW5ndGgtMV0uX21vZGVsLmVuZ2luZS5hcHBseU9wcyBAdXNlcnNbMF0uX21vZGVsLkhCLl9lbmNvZGUoKVxyXG5cclxuICAgICNpZiBAZ2V0Q29udGVudChAdXNlcnMubGVuZ3RoLTEpIGlzbnQgQGdldENvbnRlbnQoMClcclxuICAgICMgIGNvbnNvbGUubG9nIFwidGVzdEhCZW5jb2Rpbmc6XCJcclxuICAgICMgIGNvbnNvbGUubG9nIFwiVW5wcm9jZXNzZWQgb3BzIGZpcnN0OiAje0B1c2Vyc1swXS5lbmdpbmUudW5wcm9jZXNzZWRfb3BzLmxlbmd0aH1cIlxyXG4gICAgIyAgY29uc29sZS5sb2cgXCJVbnByb2Nlc3NlZCBvcHMgbGFzdDogI3tAdXNlcnNbQHVzZXJzLmxlbmd0aC0xXS5lbmdpbmUudW5wcm9jZXNzZWRfb3BzLmxlbmd0aH1cIlxyXG4gICAgZXhwZWN0KEBjb21wYXJlKEB1c2Vyc1tAdXNlcnMubGVuZ3RoLTFdLCBAdXNlcnNbMF0pKS50by5ub3QuYmUudW5kZWZpbmVkXHJcbiIsImNoYWkgICAgICA9IHJlcXVpcmUoJ2NoYWknKVxyXG5leHBlY3QgICAgPSBjaGFpLmV4cGVjdFxyXG5zaG91bGQgICAgPSBjaGFpLnNob3VsZCgpXHJcbnNpbm9uICAgICA9IHJlcXVpcmUoJ3Npbm9uJylcclxuc2lub25DaGFpID0gcmVxdWlyZSgnc2lub24tY2hhaScpXHJcbl8gICAgICAgICA9IHJlcXVpcmUoXCJ1bmRlcnNjb3JlXCIpXHJcblxyXG5jaGFpLnVzZShzaW5vbkNoYWkpXHJcblxyXG5ZID0gcmVxdWlyZSBcIi4uL2xpYi95LmNvZmZlZVwiXHJcblkuVGVzdCA9IHJlcXVpcmUgXCIuLi8uLi95LXRlc3QvbGliL3ktdGVzdC5jb2ZmZWVcIlxyXG5ZLlRleHQgPSByZXF1aXJlIFwiLi4vLi4veS10ZXh0L2xpYi95LXRleHRcIlxyXG5ZLkxpc3QgPSByZXF1aXJlIFwiLi4vLi4veS1saXN0L2xpYi95LWxpc3RcIlxyXG5cclxuVGVzdFN1aXRlID0gcmVxdWlyZSBcIi4vVGVzdFN1aXRlXCJcclxuY2xhc3MgT2JqZWN0VGVzdCBleHRlbmRzIFRlc3RTdWl0ZVxyXG5cclxuICBjb25zdHJ1Y3RvcjogKHN1ZmZpeCktPlxyXG4gICAgc3VwZXIgc3VmZml4LCBZXHJcblxyXG4gIG1ha2VOZXdVc2VyOiAodXNlcklkKS0+XHJcbiAgICBjb25uID0gbmV3IFkuVGVzdCB1c2VySWRcclxuICAgIHN1cGVyIG5ldyBZIGNvbm5cclxuXHJcbiAgdHlwZTogXCJPYmplY3RUZXN0XCJcclxuXHJcbiAgZ2V0UmFuZG9tUm9vdDogKHVzZXJfbnVtLCByb290LCBkZXB0aCA9IEBtYXhfZGVwdGgpLT5cclxuICAgIHJvb3QgPz0gQHVzZXJzW3VzZXJfbnVtXVxyXG4gICAgaWYgZGVwdGggaXMgMCBvciBfLnJhbmRvbSgwLDEpIGlzIDEgIyB0YWtlIHJvb3RcclxuICAgICAgcm9vdFxyXG4gICAgZWxzZSAjIHRha2UgY2hpbGRcclxuICAgICAgZGVwdGgtLVxyXG4gICAgICBlbGVtcyA9IG51bGxcclxuICAgICAgaWYgcm9vdC5fbmFtZSBpcyBcIk9iamVjdFwiXHJcbiAgICAgICAgZWxlbXMgPVxyXG4gICAgICAgICAgZm9yIG9uYW1lLHZhbCBvZiByb290LnZhbCgpXHJcbiAgICAgICAgICAgIHZhbFxyXG4gICAgICBlbHNlIGlmIHJvb3QuX25hbWUgaXMgXCJBcnJheVwiXHJcbiAgICAgICAgZWxlbXMgPSByb290LnZhbCgpXHJcbiAgICAgIGVsc2VcclxuICAgICAgICByZXR1cm4gcm9vdFxyXG5cclxuICAgICAgZWxlbXMgPSBlbGVtcy5maWx0ZXIgKGVsZW0pLT5cclxuICAgICAgICBlbGVtPyBhbmQgKChlbGVtLl9uYW1lIGlzIFwiQXJyYXlcIikgb3IgKGVsZW0uX25hbWUgaXMgXCJPYmplY3RcIikpXHJcbiAgICAgIGlmIGVsZW1zLmxlbmd0aCBpcyAwXHJcbiAgICAgICAgcm9vdFxyXG4gICAgICBlbHNlXHJcbiAgICAgICAgcCA9IGVsZW1zW18ucmFuZG9tKDAsIGVsZW1zLmxlbmd0aC0xKV1cclxuICAgICAgICBAZ2V0UmFuZG9tUm9vdCB1c2VyX251bSwgcCwgZGVwdGhcclxuXHJcbiAgZ2V0R2VuZXJhdGluZ0Z1bmN0aW9uczogKHVzZXJfbnVtKS0+XHJcbiAgICBzdXBlcih1c2VyX251bSkuY29uY2F0IFtcclxuICAgICAgICBmIDogKHkpPT4gIyBEZWxldGUgT2JqZWN0IFByb3BlcnR5XHJcbiAgICAgICAgICBsaXN0ID0gZm9yIG5hbWUsIG8gb2YgeS52YWwoKVxyXG4gICAgICAgICAgICBuYW1lXHJcbiAgICAgICAgICBpZiBsaXN0Lmxlbmd0aCA+IDBcclxuICAgICAgICAgICAga2V5ID0gbGlzdFtfLnJhbmRvbSgwLGxpc3QubGVuZ3RoLTEpXVxyXG4gICAgICAgICAgICB5LmRlbGV0ZShrZXkpXHJcbiAgICAgICAgdHlwZXM6IFtZLk9iamVjdF1cclxuICAgICAgLFxyXG4gICAgICAgIGYgOiAoeSk9PiAjIFNFVCBPYmplY3QgUHJvcGVydHlcclxuICAgICAgICAgIHkudmFsKEBnZXRSYW5kb21LZXkoKSwgbmV3IFkuT2JqZWN0KEBnZXRSYW5kb21PYmplY3QoKSkpXHJcbiAgICAgICAgdHlwZXM6IFtZLk9iamVjdF1cclxuICAgICAgLFxyXG4gICAgICAgIGYgOiAoeSk9PiAjIFNFVCBQUk9QRVJUWSBURVhUXHJcbiAgICAgICAgICB5LnZhbChAZ2V0UmFuZG9tS2V5KCksIG5ldyBZLlRleHQoQGdldFJhbmRvbVRleHQoKSkpXHJcbiAgICAgICAgdHlwZXM6IFtZLk9iamVjdF1cclxuICAgICAgLFxyXG4gICAgICAgIGYgOiAoeSk9PiAjIFNFVCBQUk9QRVJUWSBMaXN0XHJcbiAgICAgICAgICB5LnZhbChAZ2V0UmFuZG9tS2V5KCksIG5ldyBZLkxpc3QoQGdldFJhbmRvbVRleHQoKS5zcGxpdChcIlwiKSkpXHJcbiAgICAgICAgdHlwZXM6IFtZLk9iamVjdF1cclxuICAgICAgLFxyXG4gICAgICAgIGYgOiAoeSk9PiAjIERlbGV0ZSBBcnJheSBFbGVtZW50XHJcbiAgICAgICAgICBsaXN0ID0geS52YWwoKVxyXG4gICAgICAgICAgaWYgbGlzdC5sZW5ndGggPiAwXHJcbiAgICAgICAgICAgIGkgPSBfLnJhbmRvbSgwLGxpc3QubGVuZ3RoLTEpXHJcbiAgICAgICAgICAgIHkuZGVsZXRlKGkpXHJcbiAgICAgICAgdHlwZXM6IFtZLkxpc3RdXHJcbiAgICAgICxcclxuICAgICAgICBmIDogKHkpPT4gIyBpbnNlcnQgT2JqZWN0IG11dGFibGVcclxuICAgICAgICAgIGwgPSB5LnZhbCgpLmxlbmd0aFxyXG4gICAgICAgICAgeS5pbnNlcnQoXy5yYW5kb20oMCwgbC0xKSwgbmV3IFkuT2JqZWN0KEBnZXRSYW5kb21PYmplY3QoKSkpXHJcbiAgICAgICAgdHlwZXM6IFtZLkxpc3RdXHJcbiAgICAgICxcclxuICAgICAgICBmIDogKHkpPT4gIyBpbnNlcnQgVGV4dCBtdXRhYmxlXHJcbiAgICAgICAgICBsID0geS52YWwoKS5sZW5ndGhcclxuICAgICAgICAgIHkuaW5zZXJ0KF8ucmFuZG9tKDAsIGwtMSksIG5ldyBZLlRleHQoQGdldFJhbmRvbVRleHQoKSkpXHJcbiAgICAgICAgdHlwZXMgOiBbWS5MaXN0XVxyXG4gICAgICAsXHJcbiAgICAgICAgZiA6ICh5KT0+ICMgaW5zZXJ0IExpc3QgbXV0YWJsZVxyXG4gICAgICAgICAgbCA9IHkudmFsKCkubGVuZ3RoXHJcbiAgICAgICAgICB5Lmluc2VydChfLnJhbmRvbSgwLCBsLTEpLCBuZXcgWS5MaXN0KEBnZXRSYW5kb21UZXh0KCkuc3BsaXQoXCJcIikpKVxyXG4gICAgICAgIHR5cGVzIDogW1kuTGlzdF1cclxuICAgICAgLFxyXG4gICAgICAgIGYgOiAoeSk9PiAjIGluc2VydCBOdW1iZXIgKHByaW1pdGl2ZSBvYmplY3QpXHJcbiAgICAgICAgICBsID0geS52YWwoKS5sZW5ndGhcclxuICAgICAgICAgIHkuaW5zZXJ0KF8ucmFuZG9tKDAsbC0xKSwgXy5yYW5kb20oMCw0MikpXHJcbiAgICAgICAgdHlwZXMgOiBbWS5MaXN0XVxyXG4gICAgICAsXHJcbiAgICAgICAgZiA6ICh5KT0+ICMgU0VUIE9iamVjdCBQcm9wZXJ0eSAoY2lyY3VsYXIpXHJcbiAgICAgICAgICB5LnZhbChAZ2V0UmFuZG9tS2V5KCksIEBnZXRSYW5kb21Sb290IHVzZXJfbnVtKVxyXG4gICAgICAgIHR5cGVzOiBbWS5PYmplY3RdXHJcbiAgICAgICxcclxuICAgICAgICBmIDogKHkpPT4gIyBpbnNlcnQgT2JqZWN0IG11dGFibGUgKGNpcmN1bGFyKVxyXG4gICAgICAgICAgbCA9IHkudmFsKCkubGVuZ3RoXHJcbiAgICAgICAgICB5Lmluc2VydChfLnJhbmRvbSgwLCBsLTEpLCBAZ2V0UmFuZG9tUm9vdCB1c2VyX251bSlcclxuICAgICAgICB0eXBlczogW1kuTGlzdF1cclxuICAgICAgLFxyXG4gICAgICAgIGYgOiAoeSk9PiAjIElOU0VSVCBURVhUXHJcbiAgICAgICAgICB5XHJcbiAgICAgICAgICBwb3MgPSBfLnJhbmRvbSAwLCAoeS52YWwoKS5sZW5ndGgtMSlcclxuICAgICAgICAgIHkuaW5zZXJ0IHBvcywgQGdldFJhbmRvbVRleHQoKVxyXG4gICAgICAgICAgbnVsbFxyXG4gICAgICAgIHR5cGVzOiBbWS5UZXh0XVxyXG4gICAgICAsXHJcbiAgICAgICAgZiA6ICh5KS0+ICMgREVMRVRFIFRFWFRcclxuICAgICAgICAgIGlmIHkudmFsKCkubGVuZ3RoID4gMFxyXG4gICAgICAgICAgICBwb3MgPSBfLnJhbmRvbSAwLCAoeS52YWwoKS5sZW5ndGgtMSkgIyBUT0RPOiBwdXQgaGVyZSBhbHNvIGFyYml0cmFyeSBudW1iZXIgKHRlc3QgYmVoYXZpb3VyIGluIGVycm9yIGNhc2VzKVxyXG4gICAgICAgICAgICBsZW5ndGggPSBfLnJhbmRvbSAwLCAoeS52YWwoKS5sZW5ndGggLSBwb3MpXHJcbiAgICAgICAgICAgIG9wczEgPSB5LmRlbGV0ZSBwb3MsIGxlbmd0aFxyXG4gICAgICAgICAgdW5kZWZpbmVkXHJcbiAgICAgICAgdHlwZXMgOiBbWS5UZXh0XVxyXG4gICAgICBdXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdFRlc3RcclxuXHJcbmRlc2NyaWJlIFwiT2JqZWN0IFRlc3RcIiwgLT5cclxuICBAdGltZW91dCA1MDAwMDBcclxuXHJcbiAgYmVmb3JlRWFjaCAoZG9uZSktPlxyXG4gICAgQHlUZXN0ID0gbmV3IE9iamVjdFRlc3QoKVxyXG4gICAgQHVzZXJzID0gQHlUZXN0LnVzZXJzXHJcblxyXG4gICAgQHRlc3RfdXNlciA9IEB5VGVzdC5tYWtlTmV3VXNlciBcInRlc3RfdXNlclwiXHJcbiAgICBkb25lKClcclxuXHJcbiAgaXQgXCJjYW4gaGFuZGxlIG1hbnkgZW5naW5lcywgbWFueSBvcGVyYXRpb25zLCBjb25jdXJyZW50bHkgKHJhbmRvbSlcIiwgLT5cclxuICAgIGNvbnNvbGUubG9nIFwiXCIgIyBUT0RPXHJcbiAgICBAeVRlc3QucnVuKClcclxuXHJcbiAgaXQgXCJoYXMgYSB3b3JraW5nIHRlc3Qgc3VpdGVcIiwgLT5cclxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcclxuXHJcbiAgaXQgXCJoYW5kbGVzIGRvdWJsZS1sYXRlLWpvaW5cIiwgLT5cclxuICAgIHRlc3QgPSBuZXcgT2JqZWN0VGVzdChcImRvdWJsZVwiKVxyXG4gICAgdGVzdC5ydW4oKVxyXG4gICAgQHlUZXN0LnJ1bigpXHJcbiAgICB1MSA9IHRlc3QudXNlcnNbMF1cclxuICAgIHUyID0gQHlUZXN0LnVzZXJzWzFdXHJcbiAgICBvcHMxID0gdTEuX21vZGVsLkhCLl9lbmNvZGUoKVxyXG4gICAgb3BzMiA9IHUyLl9tb2RlbC5IQi5fZW5jb2RlKClcclxuICAgIHUxLl9tb2RlbC5lbmdpbmUuYXBwbHlPcCBvcHMyLCB0cnVlXHJcbiAgICB1Mi5fbW9kZWwuZW5naW5lLmFwcGx5T3Agb3BzMSwgdHJ1ZVxyXG5cclxuICAgIGV4cGVjdChAeVRlc3QuY29tcGFyZSh1MSwgdTIpKS50by5ub3QuYmUudW5kZWZpbmVkXHJcblxyXG4gIGl0IFwiY2FuIGhhbmRsZSBjcmVhdG9uIG9mIGNvbXBsZXgganNvbiAoMSlcIiwgLT5cclxuICAgIEB5VGVzdC51c2Vyc1swXS52YWwoJ2EnLCBuZXcgWS5UZXh0KCdxJykpXHJcbiAgICBAeVRlc3QudXNlcnNbMV0udmFsKCdhJywgbmV3IFkuVGV4dCgndCcpKVxyXG4gICAgQHlUZXN0LmNvbXBhcmVBbGwoKVxyXG4gICAgcSA9IEB5VGVzdC51c2Vyc1syXS52YWwoJ2EnKVxyXG4gICAgcS5pbnNlcnQoMCwnQScpXHJcbiAgICBAeVRlc3QuY29tcGFyZUFsbCgpXHJcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKFwiYVwiKS52YWwoKSkudG8uZXF1YWwoXCJBdFwiKVxyXG5cclxuICBpdCBcImNhbiBoYW5kbGUgY3JlYXRvbiBvZiBjb21wbGV4IGpzb24gKDIpXCIsIC0+XHJcbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ3gnLCBuZXcgWS5PYmplY3QoeydhJzonYid9KSlcclxuICAgIEB5VGVzdC5nZXRTb21lVXNlcigpLnZhbCgnYScsIG5ldyBZLk9iamVjdCh7J2EnOntxOiBuZXcgWS5UZXh0KFwiZHRybmR0cnRkcm50ZHJucnRkbnJ0ZG5ydGRucnRkbnJkbnJkdFwiKX19KSlcclxuICAgIEB5VGVzdC5nZXRTb21lVXNlcigpLnZhbCgnYicsIG5ldyBZLk9iamVjdCh7J2EnOnt9fSkpXHJcbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ2MnLCBuZXcgWS5PYmplY3QoeydhJzonYyd9KSlcclxuICAgIEB5VGVzdC5nZXRTb21lVXNlcigpLnZhbCgnYycsIG5ldyBZLk9iamVjdCh7J2EnOidiJ30pKVxyXG4gICAgQHlUZXN0LmNvbXBhcmVBbGwoKVxyXG4gICAgcSA9IEB5VGVzdC5nZXRTb21lVXNlcigpLnZhbChcImFcIikudmFsKFwiYVwiKS52YWwoXCJxXCIpXHJcbiAgICBxLmluc2VydCgwLCdBJylcclxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcclxuICAgIGV4cGVjdChAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoXCJhXCIpLnZhbChcImFcIikudmFsKFwicVwiKS52YWwoKSkudG8uZXF1YWwoXCJBZHRybmR0cnRkcm50ZHJucnRkbnJ0ZG5ydGRucnRkbnJkbnJkdFwiKVxyXG5cclxuICBpdCBcImNhbiBoYW5kbGUgY3JlYXRvbiBvZiBjb21wbGV4IGpzb24gKDMpXCIsIC0+XHJcbiAgICBAeVRlc3QudXNlcnNbMF0udmFsKCdsJywgbmV3IFkuTGlzdChbMSwyLDNdKSlcclxuICAgIEB5VGVzdC51c2Vyc1sxXS52YWwoJ2wnLCBuZXcgWS5MaXN0KFs0LDUsNl0pKVxyXG4gICAgQHlUZXN0LmNvbXBhcmVBbGwoKVxyXG4gICAgQHlUZXN0LnVzZXJzWzJdLnZhbCgnbCcpLmluc2VydCgwLCdBJylcclxuICAgIHcgPSBAeVRlc3QudXNlcnNbMV0udmFsKCdsJykuaW5zZXJ0KDAsbmV3IFkuVGV4dCgnQicpKS52YWwoMClcclxuICAgIHcuaW5zZXJ0IDEsIFwiQ1wiXHJcbiAgICBleHBlY3Qody52YWwoKSkudG8uZXF1YWwoXCJCQ1wiKVxyXG4gICAgQHlUZXN0LmNvbXBhcmVBbGwoKVxyXG5cclxuICBpdCBcImhhbmRsZXMgaW1tdXRhYmxlcyBhbmQgcHJpbWl0aXZlIGRhdGEgdHlwZXNcIiwgLT5cclxuICAgIEB5VGVzdC5nZXRTb21lVXNlcigpLnZhbCgnc3RyaW5nJywgXCJ0ZXh0XCIpXHJcbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ251bWJlcicsIDQpXHJcbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ29iamVjdCcsIG5ldyBZLk9iamVjdCh7cTpcInJyXCJ9KSlcclxuICAgIEB5VGVzdC5nZXRTb21lVXNlcigpLnZhbCgnbnVsbCcsIG51bGwpXHJcbiAgICBAeVRlc3QuY29tcGFyZUFsbCgpXHJcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdzdHJpbmcnKSkudG8uZXF1YWwgXCJ0ZXh0XCJcclxuICAgIGV4cGVjdChAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ251bWJlcicpKS50by5lcXVhbCA0XHJcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdvYmplY3QnKS52YWwoJ3EnKSkudG8uZXF1YWwgXCJyclwiXHJcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdudWxsJykgaXMgbnVsbCkudG8uYmUub2tcclxuXHJcbiAgaXQgXCJoYW5kbGVzIGltbXV0YWJsZXMgYW5kIHByaW1pdGl2ZSBkYXRhIHR5cGVzICgyKVwiLCAtPlxyXG4gICAgQHlUZXN0LnVzZXJzWzBdLnZhbCgnc3RyaW5nJywgXCJ0ZXh0XCIpXHJcbiAgICBAeVRlc3QudXNlcnNbMV0udmFsKCdudW1iZXInLCA0KVxyXG4gICAgQHlUZXN0LnVzZXJzWzJdLnZhbCgnb2JqZWN0JywgbmV3IFkuT2JqZWN0KHtxOlwicnJcIn0pKVxyXG4gICAgQHlUZXN0LnVzZXJzWzBdLnZhbCgnbnVsbCcsIG51bGwpXHJcbiAgICBAeVRlc3QuY29tcGFyZUFsbCgpXHJcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdzdHJpbmcnKSkudG8uZXF1YWwgXCJ0ZXh0XCJcclxuICAgIGV4cGVjdChAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ251bWJlcicpKS50by5lcXVhbCA0XHJcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdvYmplY3QnKS52YWwoJ3EnKSkudG8uZXF1YWwgXCJyclwiXHJcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdudWxsJykgaXMgbnVsbCkudG8uYmUub2tcclxuXHJcbiAgaXQgXCJPYnNlcnZlcnMgd29yayBvbiBKU09OIFR5cGVzfyAoYWRkIHR5cGUgb2JzZXJ2ZXJzLCBsb2NhbCBhbmQgZm9yZWlnbilcIiwgLT5cclxuICAgIHUgPSBAeVRlc3QudXNlcnNbMF1cclxuICAgIEB5VGVzdC5mbHVzaEFsbCgpXHJcbiAgICBsYXN0X3Rhc2sgPSBudWxsXHJcbiAgICBvYnNlcnZlcjEgPSAoY2hhbmdlcyktPlxyXG4gICAgICBleHBlY3QoY2hhbmdlcy5sZW5ndGgpLnRvLmVxdWFsKDEpXHJcbiAgICAgIGNoYW5nZSA9IGNoYW5nZXNbMF1cclxuICAgICAgZXhwZWN0KGNoYW5nZS50eXBlKS50by5lcXVhbChcImFkZFwiKVxyXG4gICAgICBleHBlY3QoY2hhbmdlLm9iamVjdCkudG8uZXF1YWwodSlcclxuICAgICAgZXhwZWN0KGNoYW5nZS5jaGFuZ2VkQnkpLnRvLmVxdWFsKCcwJylcclxuICAgICAgZXhwZWN0KGNoYW5nZS5uYW1lKS50by5lcXVhbChcIm5ld1N0dWZmXCIpXHJcbiAgICAgIGxhc3RfdGFzayA9IFwib2JzZXJ2ZXIxXCJcclxuICAgIHUub2JzZXJ2ZSBvYnNlcnZlcjFcclxuICAgIHUudmFsKFwibmV3U3R1ZmZcIixuZXcgWS5UZXh0KFwic29tZVN0dWZmXCIpKVxyXG4gICAgZXhwZWN0KGxhc3RfdGFzaykudG8uZXF1YWwoXCJvYnNlcnZlcjFcIilcclxuICAgIHUudW5vYnNlcnZlIG9ic2VydmVyMVxyXG5cclxuICAgIG9ic2VydmVyMiA9IChjaGFuZ2VzKS0+XHJcbiAgICAgIGV4cGVjdChjaGFuZ2VzLmxlbmd0aCkudG8uZXF1YWwoMSlcclxuICAgICAgY2hhbmdlID0gY2hhbmdlc1swXVxyXG4gICAgICBleHBlY3QoY2hhbmdlLnR5cGUpLnRvLmVxdWFsKFwiYWRkXCIpXHJcbiAgICAgIGV4cGVjdChjaGFuZ2Uub2JqZWN0KS50by5lcXVhbCh1KVxyXG4gICAgICBleHBlY3QoY2hhbmdlLmNoYW5nZWRCeSkudG8uZXF1YWwoJzEnKVxyXG4gICAgICBleHBlY3QoY2hhbmdlLm5hbWUpLnRvLmVxdWFsKFwibW9yZVN0dWZmXCIpXHJcbiAgICAgIGxhc3RfdGFzayA9IFwib2JzZXJ2ZXIyXCJcclxuICAgIHUub2JzZXJ2ZSBvYnNlcnZlcjJcclxuICAgIHYgPSBAeVRlc3QudXNlcnNbMV1cclxuICAgIHYudmFsKFwibW9yZVN0dWZmXCIsXCJzb21lTW9yZVN0dWZmXCIpXHJcbiAgICBAeVRlc3QuZmx1c2hBbGwoKVxyXG4gICAgZXhwZWN0KGxhc3RfdGFzaykudG8uZXF1YWwoXCJvYnNlcnZlcjJcIilcclxuICAgIHUudW5vYnNlcnZlIG9ic2VydmVyMlxyXG5cclxuICBpdCBcIk9ic2VydmVycyB3b3JrIG9uIEpTT04gVHlwZXN/ICh1cGRhdGUgdHlwZSBvYnNlcnZlcnMsIGxvY2FsIGFuZCBmb3JlaWduKVwiLCAtPlxyXG4gICAgdSA9IEB5VGVzdC51c2Vyc1swXS52YWwoXCJuZXdTdHVmZlwiLCBuZXcgWS5UZXh0KFwib2xkU3R1ZmZcIikpLnZhbChcIm1vcmVTdHVmZlwiLG5ldyBZLlRleHQoXCJtb3JlT2xkU3R1ZmZcIikpXHJcbiAgICBAeVRlc3QuZmx1c2hBbGwoKVxyXG4gICAgbGFzdF90YXNrID0gbnVsbFxyXG4gICAgb2JzZXJ2ZXIxID0gKGNoYW5nZXMpLT5cclxuICAgICAgZXhwZWN0KGNoYW5nZXMubGVuZ3RoKS50by5lcXVhbCgxKVxyXG4gICAgICBjaGFuZ2UgPSBjaGFuZ2VzWzBdXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UudHlwZSkudG8uZXF1YWwoXCJ1cGRhdGVcIilcclxuICAgICAgZXhwZWN0KGNoYW5nZS5vYmplY3QpLnRvLmVxdWFsKHUpXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UuY2hhbmdlZEJ5KS50by5lcXVhbCgnMCcpXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UubmFtZSkudG8uZXF1YWwoXCJuZXdTdHVmZlwiKVxyXG4gICAgICBleHBlY3QoY2hhbmdlLm9sZFZhbHVlLnZhbCgpKS50by5lcXVhbChcIm9sZFN0dWZmXCIpXHJcbiAgICAgIGxhc3RfdGFzayA9IFwib2JzZXJ2ZXIxXCJcclxuICAgIHUub2JzZXJ2ZSBvYnNlcnZlcjFcclxuICAgIHUudmFsKFwibmV3U3R1ZmZcIixcInNvbWVTdHVmZlwiKVxyXG4gICAgZXhwZWN0KGxhc3RfdGFzaykudG8uZXF1YWwoXCJvYnNlcnZlcjFcIilcclxuICAgIHUudW5vYnNlcnZlIG9ic2VydmVyMVxyXG5cclxuICAgIG9ic2VydmVyMiA9IChjaGFuZ2VzKS0+XHJcbiAgICAgIGV4cGVjdChjaGFuZ2VzLmxlbmd0aCkudG8uZXF1YWwoMSlcclxuICAgICAgY2hhbmdlID0gY2hhbmdlc1swXVxyXG4gICAgICBleHBlY3QoY2hhbmdlLnR5cGUpLnRvLmVxdWFsKFwidXBkYXRlXCIpXHJcbiAgICAgIGV4cGVjdChjaGFuZ2Uub2JqZWN0KS50by5lcXVhbCh1KVxyXG4gICAgICBleHBlY3QoY2hhbmdlLmNoYW5nZWRCeSkudG8uZXF1YWwoJzEnKVxyXG4gICAgICBleHBlY3QoY2hhbmdlLm5hbWUpLnRvLmVxdWFsKFwibW9yZVN0dWZmXCIpXHJcbiAgICAgIGV4cGVjdChjaGFuZ2Uub2xkVmFsdWUudmFsKCkpLnRvLmVxdWFsKFwibW9yZU9sZFN0dWZmXCIpXHJcbiAgICAgIGxhc3RfdGFzayA9IFwib2JzZXJ2ZXIyXCJcclxuICAgIHUub2JzZXJ2ZSBvYnNlcnZlcjJcclxuICAgIHYgPSBAeVRlc3QudXNlcnNbMV1cclxuICAgIHYudmFsKFwibW9yZVN0dWZmXCIsXCJzb21lTW9yZVN0dWZmXCIpXHJcbiAgICBAeVRlc3QuZmx1c2hBbGwoKVxyXG4gICAgZXhwZWN0KGxhc3RfdGFzaykudG8uZXF1YWwoXCJvYnNlcnZlcjJcIilcclxuICAgIHUudW5vYnNlcnZlIG9ic2VydmVyMlxyXG5cclxuXHJcbiAgaXQgXCJPYnNlcnZlcnMgd29yayBvbiBKU09OIFR5cGVzfyAoZGVsZXRlIHR5cGUgb2JzZXJ2ZXJzLCBsb2NhbCBhbmQgZm9yZWlnbilcIiwgLT5cclxuICAgIHUgPSBAeVRlc3QudXNlcnNbMF0udmFsKFwibmV3U3R1ZmZcIixuZXcgWS5UZXh0KFwib2xkU3R1ZmZcIikpLnZhbChcIm1vcmVTdHVmZlwiLG5ldyBZLlRleHQoXCJtb3JlT2xkU3R1ZmZcIikpXHJcbiAgICBAeVRlc3QuZmx1c2hBbGwoKVxyXG4gICAgbGFzdF90YXNrID0gbnVsbFxyXG4gICAgb2JzZXJ2ZXIxID0gKGNoYW5nZXMpLT5cclxuICAgICAgZXhwZWN0KGNoYW5nZXMubGVuZ3RoKS50by5lcXVhbCgxKVxyXG4gICAgICBjaGFuZ2UgPSBjaGFuZ2VzWzBdXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UudHlwZSkudG8uZXF1YWwoXCJkZWxldGVcIilcclxuICAgICAgZXhwZWN0KGNoYW5nZS5vYmplY3QpLnRvLmVxdWFsKHUpXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UuY2hhbmdlZEJ5KS50by5lcXVhbCgnMCcpXHJcbiAgICAgIGV4cGVjdChjaGFuZ2UubmFtZSkudG8uZXF1YWwoXCJuZXdTdHVmZlwiKVxyXG4gICAgICBleHBlY3QoY2hhbmdlLm9sZFZhbHVlLnZhbCgpKS50by5lcXVhbChcIm9sZFN0dWZmXCIpXHJcbiAgICAgIGxhc3RfdGFzayA9IFwib2JzZXJ2ZXIxXCJcclxuICAgIHUub2JzZXJ2ZSBvYnNlcnZlcjFcclxuICAgIHUuZGVsZXRlKFwibmV3U3R1ZmZcIilcclxuICAgIGV4cGVjdChsYXN0X3Rhc2spLnRvLmVxdWFsKFwib2JzZXJ2ZXIxXCIpXHJcbiAgICB1LnVub2JzZXJ2ZSBvYnNlcnZlcjFcclxuXHJcbiAgICBvYnNlcnZlcjIgPSAoY2hhbmdlcyktPlxyXG4gICAgICBleHBlY3QoY2hhbmdlcy5sZW5ndGgpLnRvLmVxdWFsKDEpXHJcbiAgICAgIGNoYW5nZSA9IGNoYW5nZXNbMF1cclxuICAgICAgZXhwZWN0KGNoYW5nZS50eXBlKS50by5lcXVhbChcImRlbGV0ZVwiKVxyXG4gICAgICBleHBlY3QoY2hhbmdlLm9iamVjdCkudG8uZXF1YWwodSlcclxuICAgICAgZXhwZWN0KGNoYW5nZS5jaGFuZ2VkQnkpLnRvLmVxdWFsKCcxJylcclxuICAgICAgZXhwZWN0KGNoYW5nZS5uYW1lKS50by5lcXVhbChcIm1vcmVTdHVmZlwiKVxyXG4gICAgICBleHBlY3QoY2hhbmdlLm9sZFZhbHVlLnZhbCgpKS50by5lcXVhbChcIm1vcmVPbGRTdHVmZlwiKVxyXG4gICAgICBsYXN0X3Rhc2sgPSBcIm9ic2VydmVyMlwiXHJcbiAgICB1Lm9ic2VydmUgb2JzZXJ2ZXIyXHJcbiAgICB2ID0gQHlUZXN0LnVzZXJzWzFdXHJcbiAgICB2LmRlbGV0ZShcIm1vcmVTdHVmZlwiKVxyXG4gICAgQHlUZXN0LmZsdXNoQWxsKClcclxuICAgIGV4cGVjdChsYXN0X3Rhc2spLnRvLmVxdWFsKFwib2JzZXJ2ZXIyXCIpXHJcbiAgICB1LnVub2JzZXJ2ZSBvYnNlcnZlcjJcclxuXHJcbiAgaXQgXCJjYW4gaGFuZGxlIGNpcmN1bGFyIEpTT05cIiwgLT5cclxuICAgIHUgPSBAeVRlc3QudXNlcnNbMF1cclxuICAgIHUudmFsKFwibWVcIiwgdSlcclxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcclxuICAgIHUudmFsKFwic3R1ZmZcIiwgbmV3IFkuT2JqZWN0KHt4OiB0cnVlfSkpXHJcbiAgICB1LnZhbChcInNhbWVfc3R1ZmZcIiwgdS52YWwoXCJzdHVmZlwiKSlcclxuICAgIHUudmFsKFwic2FtZV9zdHVmZlwiKS52YWwoXCJ4XCIsIDUpXHJcbiAgICBleHBlY3QodS52YWwoXCJzYW1lX3N0dWZmXCIpLnZhbChcInhcIikpLnRvLmVxdWFsKDUpXHJcbiAgICBAeVRlc3QuY29tcGFyZUFsbCgpXHJcbiAgICB1LnZhbChcInN0dWZmXCIpLnZhbChcInlcIiwgdS52YWwoXCJzdHVmZlwiKSlcclxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcclxuXHJcblxyXG5cclxuIl19
|