13899 lines
1.1 MiB
13899 lines
1.1 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 _;
|
||
|
||
_ = require("underscore");
|
||
|
||
module.exports = function(user_list) {
|
||
var TestConnector;
|
||
return TestConnector = (function() {
|
||
function TestConnector(engine, HB, execution_listener) {
|
||
var appliedOperationsListener, send_;
|
||
this.engine = engine;
|
||
this.HB = HB;
|
||
this.execution_listener = execution_listener;
|
||
send_ = (function(_this) {
|
||
return function(o) {
|
||
return _this.send(o);
|
||
};
|
||
})(this);
|
||
this.execution_listener.push(send_);
|
||
this.applied_operations = [];
|
||
appliedOperationsListener = (function(_this) {
|
||
return function(o) {
|
||
return _this.applied_operations.push(o);
|
||
};
|
||
})(this);
|
||
this.execution_listener.push(appliedOperationsListener);
|
||
if (!((user_list != null ? user_list.length : void 0) === 0)) {
|
||
this.engine.applyOps(user_list[0].getHistoryBuffer()._encode());
|
||
}
|
||
this.unexecuted = {};
|
||
}
|
||
|
||
TestConnector.prototype.getOpsInExecutionOrder = function() {
|
||
return this.applied_operations;
|
||
};
|
||
|
||
TestConnector.prototype.send = function(o) {
|
||
var user, _i, _len, _results;
|
||
if ((o.uid.creator === this.HB.getUserId()) && (typeof o.uid.op_number !== "string")) {
|
||
_results = [];
|
||
for (_i = 0, _len = user_list.length; _i < _len; _i++) {
|
||
user = user_list[_i];
|
||
if (user.getUserId() !== this.HB.getUserId()) {
|
||
_results.push(user.getConnector().receive(o));
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
}
|
||
};
|
||
|
||
TestConnector.prototype.receive = function(o) {
|
||
var _base, _name;
|
||
if ((_base = this.unexecuted)[_name = o.uid.creator] == null) {
|
||
_base[_name] = [];
|
||
}
|
||
return this.unexecuted[o.uid.creator].push(o);
|
||
};
|
||
|
||
TestConnector.prototype.flushOne = function(user) {
|
||
var _ref;
|
||
if (((_ref = this.unexecuted[user]) != null ? _ref.length : void 0) > 0) {
|
||
return this.engine.applyOp(this.unexecuted[user].shift());
|
||
}
|
||
};
|
||
|
||
TestConnector.prototype.flushOneRandom = function() {
|
||
return this.flushOne(_.random(0, user_list.length - 1));
|
||
};
|
||
|
||
TestConnector.prototype.flushAll = function() {
|
||
var n, ops, _ref;
|
||
_ref = this.unexecuted;
|
||
for (n in _ref) {
|
||
ops = _ref[n];
|
||
this.engine.applyOps(ops);
|
||
}
|
||
return this.unexecuted = {};
|
||
};
|
||
|
||
return TestConnector;
|
||
|
||
})();
|
||
};
|
||
|
||
|
||
},{"underscore":64}],2:[function(require,module,exports){
|
||
var Engine;
|
||
|
||
Engine = (function() {
|
||
function Engine(HB, parser) {
|
||
this.HB = HB;
|
||
this.parser = parser;
|
||
this.unprocessed_ops = [];
|
||
}
|
||
|
||
Engine.prototype.parseOperation = function(json) {
|
||
var typeParser;
|
||
typeParser = this.parser[json.type];
|
||
if (typeParser != null) {
|
||
return typeParser(json);
|
||
} else {
|
||
throw new Error("You forgot to specify a parser for type " + json.type + ". The message is " + (JSON.stringify(json)) + ".");
|
||
}
|
||
};
|
||
|
||
Engine.prototype.applyOpsBundle = function(ops_json) {
|
||
var o, ops, _i, _j, _k, _len, _len1, _len2;
|
||
ops = [];
|
||
for (_i = 0, _len = ops_json.length; _i < _len; _i++) {
|
||
o = ops_json[_i];
|
||
ops.push(this.parseOperation(o));
|
||
}
|
||
for (_j = 0, _len1 = ops.length; _j < _len1; _j++) {
|
||
o = ops[_j];
|
||
this.HB.addOperation(o);
|
||
}
|
||
for (_k = 0, _len2 = ops.length; _k < _len2; _k++) {
|
||
o = ops[_k];
|
||
if (!o.execute()) {
|
||
this.unprocessed_ops.push(o);
|
||
}
|
||
}
|
||
return this.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) {
|
||
var o, _i, _len, _results;
|
||
_results = [];
|
||
for (_i = 0, _len = ops_json.length; _i < _len; _i++) {
|
||
o = ops_json[_i];
|
||
_results.push(this.applyOp(o));
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
Engine.prototype.applyOp = function(op_json) {
|
||
var o;
|
||
o = this.parseOperation(op_json);
|
||
this.HB.addToCounter(o);
|
||
if (!o.execute()) {
|
||
this.unprocessed_ops.push(o);
|
||
} else {
|
||
this.HB.addOperation(o);
|
||
}
|
||
return this.tryUnprocessed();
|
||
};
|
||
|
||
Engine.prototype.tryUnprocessed = function() {
|
||
var old_length, op, unprocessed, _i, _len, _ref, _results;
|
||
_results = [];
|
||
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 (!op.execute()) {
|
||
unprocessed.push(op);
|
||
} else {
|
||
this.HB.addOperation(op);
|
||
}
|
||
}
|
||
this.unprocessed_ops = unprocessed;
|
||
if (this.unprocessed_ops.length === old_length) {
|
||
break;
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
return Engine;
|
||
|
||
})();
|
||
|
||
module.exports = Engine;
|
||
|
||
|
||
},{}],3:[function(require,module,exports){
|
||
var Engine, HistoryBuffer, JsonYatta, json_types_uninitialized;
|
||
|
||
json_types_uninitialized = require("../Types/JsonTypes");
|
||
|
||
HistoryBuffer = require("../HistoryBuffer");
|
||
|
||
Engine = require("../Engine");
|
||
|
||
JsonYatta = (function() {
|
||
function JsonYatta(user_id, Connector) {
|
||
var first_word, json_types;
|
||
this.HB = new HistoryBuffer(user_id);
|
||
json_types = json_types_uninitialized(this.HB);
|
||
this.engine = new Engine(this.HB, json_types.parser);
|
||
this.connector = new Connector(this.engine, this.HB, json_types.execution_listener, this);
|
||
first_word = new json_types.types.JsonType(this.HB.getReservedUniqueIdentifier());
|
||
this.HB.addOperation(first_word).execute();
|
||
this.root_element = first_word;
|
||
}
|
||
|
||
JsonYatta.prototype.getRootElement = function() {
|
||
return this.root_element;
|
||
};
|
||
|
||
JsonYatta.prototype.getEngine = function() {
|
||
return this.engine;
|
||
};
|
||
|
||
JsonYatta.prototype.getConnector = function() {
|
||
return this.connector;
|
||
};
|
||
|
||
JsonYatta.prototype.getHistoryBuffer = function() {
|
||
return this.HB;
|
||
};
|
||
|
||
JsonYatta.prototype.setMutableDefault = function(mutable) {
|
||
return this.root_element.setMutableDefault(mutable);
|
||
};
|
||
|
||
JsonYatta.prototype.getUserId = function() {
|
||
return this.HB.getUserId();
|
||
};
|
||
|
||
JsonYatta.prototype.val = function(name, content, mutable) {
|
||
return this.root_element.val(name, content, mutable);
|
||
};
|
||
|
||
Object.defineProperty(JsonYatta.prototype, 'value', {
|
||
get: function() {
|
||
return this.root_element.value;
|
||
},
|
||
set: function(o) {
|
||
var o_name, o_obj, _results;
|
||
if (o.constructor === {}.constructor) {
|
||
_results = [];
|
||
for (o_name in o) {
|
||
o_obj = o[o_name];
|
||
_results.push(this.val(o_name, o_obj, 'immutable'));
|
||
}
|
||
return _results;
|
||
} else {
|
||
throw new Error("You must only set Object values!");
|
||
}
|
||
}
|
||
});
|
||
|
||
return JsonYatta;
|
||
|
||
})();
|
||
|
||
module.exports = JsonYatta;
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
if (window.Y == null) {
|
||
window.Y = {};
|
||
}
|
||
window.Y.JsonYatta = JsonYatta;
|
||
}
|
||
|
||
|
||
},{"../Engine":2,"../HistoryBuffer":4,"../Types/JsonTypes":6}],4:[function(require,module,exports){
|
||
var HistoryBuffer;
|
||
|
||
HistoryBuffer = (function() {
|
||
function HistoryBuffer(user_id) {
|
||
this.user_id = user_id;
|
||
this.operation_counter = {};
|
||
this.buffer = {};
|
||
this.change_listeners = [];
|
||
}
|
||
|
||
HistoryBuffer.prototype.getUserId = function() {
|
||
return this.user_id;
|
||
};
|
||
|
||
HistoryBuffer.prototype.getReservedUniqueIdentifier = function() {
|
||
return {
|
||
creator: '_',
|
||
op_number: '_'
|
||
};
|
||
};
|
||
|
||
HistoryBuffer.prototype.getOperationCounter = function() {
|
||
var ctn, res, user, _ref;
|
||
res = {};
|
||
_ref = this.operation_counter;
|
||
for (user in _ref) {
|
||
ctn = _ref[user];
|
||
res[user] = ctn;
|
||
}
|
||
return res;
|
||
};
|
||
|
||
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];
|
||
for (o_number in user) {
|
||
o = user[o_number];
|
||
if ((!isNaN(parseInt(o_number))) && 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.creator, o_next.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_next.creator, o_next.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 _ref;
|
||
if (uid instanceof Object) {
|
||
return (_ref = this.buffer[uid.creator]) != null ? _ref[uid.op_number] : void 0;
|
||
} else if (uid == null) {
|
||
|
||
} else {
|
||
throw new Error("This type of uid is not defined!");
|
||
}
|
||
};
|
||
|
||
HistoryBuffer.prototype.addOperation = function(o) {
|
||
if (this.buffer[o.creator] == null) {
|
||
this.buffer[o.creator] = {};
|
||
}
|
||
if (this.buffer[o.creator][o.op_number] != null) {
|
||
throw new Error("You must not overwrite operations!");
|
||
}
|
||
this.buffer[o.creator][o.op_number] = o;
|
||
return o;
|
||
};
|
||
|
||
HistoryBuffer.prototype.addToCounter = function(o) {
|
||
if (this.operation_counter[o.creator] == null) {
|
||
this.operation_counter[o.creator] = 0;
|
||
}
|
||
if (typeof o.op_number === 'number' && o.creator !== this.getUserId()) {
|
||
return this.operation_counter[o.creator]++;
|
||
}
|
||
};
|
||
|
||
return HistoryBuffer;
|
||
|
||
})();
|
||
|
||
module.exports = HistoryBuffer;
|
||
|
||
|
||
},{}],5:[function(require,module,exports){
|
||
var __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(HB) {
|
||
var Delete, Delimiter, ImmutableObject, Insert, Operation, execution_listener, parser;
|
||
parser = {};
|
||
execution_listener = [];
|
||
Operation = (function() {
|
||
function Operation(uid) {
|
||
if (uid == null) {
|
||
uid = HB.getNextOperationIdentifier();
|
||
}
|
||
this.creator = uid['creator'], this.op_number = uid['op_number'];
|
||
}
|
||
|
||
Operation.prototype.on = function(event, f) {
|
||
var _base;
|
||
if (this.event_listeners == null) {
|
||
this.event_listeners = {};
|
||
}
|
||
if ((_base = this.event_listeners)[event] == null) {
|
||
_base[event] = [];
|
||
}
|
||
return this.event_listeners[event].push(f);
|
||
};
|
||
|
||
Operation.prototype.callEvent = function(event, args) {
|
||
var f, _i, _len, _ref, _ref1, _results;
|
||
if (((_ref = this.event_listeners) != null ? _ref[event] : void 0) != null) {
|
||
_ref1 = this.event_listeners[event];
|
||
_results = [];
|
||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||
f = _ref1[_i];
|
||
_results.push(f.call(this, event, args));
|
||
}
|
||
return _results;
|
||
}
|
||
};
|
||
|
||
Operation.prototype.setParent = function(o) {
|
||
return this.parent = o;
|
||
};
|
||
|
||
Operation.prototype.getParent = function() {
|
||
return this.parent;
|
||
};
|
||
|
||
Operation.prototype.getUid = function() {
|
||
return {
|
||
'creator': this.creator,
|
||
'op_number': this.op_number
|
||
};
|
||
};
|
||
|
||
Operation.prototype.execute = function() {
|
||
var l, _i, _len;
|
||
this.is_executed = true;
|
||
for (_i = 0, _len = execution_listener.length; _i < _len; _i++) {
|
||
l = execution_listener[_i];
|
||
l(this._encode());
|
||
}
|
||
return this;
|
||
};
|
||
|
||
Operation.prototype.saveOperation = function(name, op) {
|
||
if ((op != null ? op.execute : void 0) != null) {
|
||
return this[name] = op;
|
||
} else if (op != null) {
|
||
if (this.unchecked == null) {
|
||
this.unchecked = {};
|
||
}
|
||
return this.unchecked[name] = op;
|
||
}
|
||
};
|
||
|
||
Operation.prototype.validateSavedOperations = function() {
|
||
var name, op, op_uid, success, uninstantiated, _ref;
|
||
uninstantiated = {};
|
||
success = this;
|
||
_ref = this.unchecked;
|
||
for (name in _ref) {
|
||
op_uid = _ref[name];
|
||
op = HB.getOperation(op_uid);
|
||
if (op) {
|
||
this[name] = op;
|
||
} else {
|
||
uninstantiated[name] = op_uid;
|
||
success = false;
|
||
}
|
||
}
|
||
delete this.unchecked;
|
||
if (!success) {
|
||
this.unchecked = uninstantiated;
|
||
}
|
||
return success;
|
||
};
|
||
|
||
return Operation;
|
||
|
||
})();
|
||
Delete = (function(_super) {
|
||
__extends(Delete, _super);
|
||
|
||
function Delete(uid, deletes) {
|
||
this.saveOperation('deletes', deletes);
|
||
Delete.__super__.constructor.call(this, uid);
|
||
}
|
||
|
||
Delete.prototype._encode = function() {
|
||
return {
|
||
'type': "Delete",
|
||
'uid': this.getUid(),
|
||
'deletes': this.deletes.getUid()
|
||
};
|
||
};
|
||
|
||
Delete.prototype.execute = function() {
|
||
if (this.validateSavedOperations()) {
|
||
this.deletes.applyDelete(this);
|
||
return Delete.__super__.execute.apply(this, arguments);
|
||
} else {
|
||
return false;
|
||
}
|
||
};
|
||
|
||
return Delete;
|
||
|
||
})(Operation);
|
||
parser['Delete'] = function(o) {
|
||
var deletes_uid, uid;
|
||
uid = o['uid'], deletes_uid = o['deletes'];
|
||
return new Delete(uid, deletes_uid);
|
||
};
|
||
Insert = (function(_super) {
|
||
__extends(Insert, _super);
|
||
|
||
function Insert(uid, prev_cl, next_cl, origin) {
|
||
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, uid);
|
||
}
|
||
|
||
Insert.prototype.applyDelete = function(o) {
|
||
if (this.deleted_by == null) {
|
||
this.deleted_by = [];
|
||
}
|
||
this.deleted_by.push(o);
|
||
if ((this.parent != null) && this.deleted_by.length === 1) {
|
||
return this.parent.callEvent("delete", this);
|
||
}
|
||
};
|
||
|
||
Insert.prototype.isDeleted = function() {
|
||
var _ref;
|
||
return ((_ref = this.deleted_by) != null ? _ref.length : void 0) > 0;
|
||
};
|
||
|
||
Insert.prototype.getDistanceToOrigin = function() {
|
||
var d, o;
|
||
d = 0;
|
||
o = this.prev_cl;
|
||
while (true) {
|
||
if (this.origin === o) {
|
||
break;
|
||
}
|
||
d++;
|
||
if (this === this.prev_cl) {
|
||
throw new Error("this should not happen ;) ");
|
||
}
|
||
o = o.prev_cl;
|
||
}
|
||
return d;
|
||
};
|
||
|
||
Insert.prototype.update_sl = function() {
|
||
var o;
|
||
o = this.prev_cl;
|
||
({
|
||
update: function(dest_cl, dest_sl) {
|
||
var _results;
|
||
_results = [];
|
||
while (true) {
|
||
if (o.isDeleted()) {
|
||
_results.push(o = o[dest_cl]);
|
||
} else {
|
||
this[dest_sl] = o;
|
||
break;
|
||
}
|
||
}
|
||
return _results;
|
||
}
|
||
});
|
||
update("prev_cl", "prev_sl");
|
||
return update("next_cl", "prev_sl");
|
||
};
|
||
|
||
Insert.prototype.execute = function() {
|
||
var distance_to_origin, i, o, parent, _ref, _ref1, _ref2;
|
||
if (this.is_executed != null) {
|
||
return this;
|
||
}
|
||
if (!this.validateSavedOperations()) {
|
||
return false;
|
||
} else {
|
||
if (((_ref = this.prev_cl) != null ? _ref.validateSavedOperations() : void 0) && ((_ref1 = this.next_cl) != null ? _ref1.validateSavedOperations() : void 0) && this.prev_cl.next_cl !== this) {
|
||
distance_to_origin = 0;
|
||
o = this.prev_cl.next_cl;
|
||
i = 0;
|
||
while (true) {
|
||
if (o == null) {
|
||
console.log(JSON.stringify(this.prev_cl.getUid()));
|
||
console.log(JSON.stringify(this.next_cl.getUid()));
|
||
}
|
||
if (o !== this.next_cl) {
|
||
if (o.getDistanceToOrigin() === i) {
|
||
if (o.creator < this.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;
|
||
}
|
||
parent = (_ref2 = this.prev_cl) != null ? _ref2.getParent() : void 0;
|
||
if (parent != null) {
|
||
this.setParent(parent);
|
||
this.parent.callEvent("insert", this);
|
||
}
|
||
return Insert.__super__.execute.apply(this, arguments);
|
||
}
|
||
};
|
||
|
||
Insert.prototype.getPosition = function() {
|
||
var position, prev;
|
||
position = 0;
|
||
prev = this.prev_cl;
|
||
while (true) {
|
||
if (prev instanceof Delimiter) {
|
||
break;
|
||
}
|
||
if ((prev.isDeleted != null) && !prev.isDeleted()) {
|
||
position++;
|
||
}
|
||
prev = prev.prev_cl;
|
||
}
|
||
return position;
|
||
};
|
||
|
||
return Insert;
|
||
|
||
})(Operation);
|
||
ImmutableObject = (function(_super) {
|
||
__extends(ImmutableObject, _super);
|
||
|
||
function ImmutableObject(uid, content, prev, next, origin) {
|
||
this.content = content;
|
||
ImmutableObject.__super__.constructor.call(this, uid, prev, next, origin);
|
||
}
|
||
|
||
ImmutableObject.prototype.val = function() {
|
||
return this.content;
|
||
};
|
||
|
||
ImmutableObject.prototype._encode = function() {
|
||
var json;
|
||
json = {
|
||
'type': "ImmutableObject",
|
||
'uid': this.getUid(),
|
||
'content': this.content
|
||
};
|
||
if (this.prev_cl != null) {
|
||
json['prev'] = this.prev_cl.getUid();
|
||
}
|
||
if (this.next_cl != null) {
|
||
json['next'] = this.next_cl.getUid();
|
||
}
|
||
if ((this.origin != null) && this.origin !== this.prev_cl) {
|
||
json["origin"] = this.origin.getUid();
|
||
}
|
||
return json;
|
||
};
|
||
|
||
return ImmutableObject;
|
||
|
||
})(Insert);
|
||
parser['ImmutableObject'] = function(json) {
|
||
var content, next, origin, prev, uid;
|
||
uid = json['uid'], content = json['content'], prev = json['prev'], next = json['next'], origin = json['origin'];
|
||
return new ImmutableObject(uid, content, prev, next, origin);
|
||
};
|
||
Delimiter = (function(_super) {
|
||
__extends(Delimiter, _super);
|
||
|
||
function Delimiter(uid, 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, uid);
|
||
}
|
||
|
||
Delimiter.prototype.isDeleted = function() {
|
||
return false;
|
||
};
|
||
|
||
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;
|
||
delete this.prev_cl.unchecked.next_cl;
|
||
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;
|
||
return this.prev_cl.next_cl = this;
|
||
} else if ((this.prev_cl != null) || (this.next_cl != null)) {
|
||
return Delimiter.__super__.execute.apply(this, arguments);
|
||
} else {
|
||
throw new Error("Delimiter is unsufficient defined!");
|
||
}
|
||
};
|
||
|
||
Delimiter.prototype._encode = function() {
|
||
var _ref, _ref1;
|
||
return {
|
||
'type': "Delimiter",
|
||
'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;
|
||
|
||
})(Operation);
|
||
parser['Delimiter'] = function(json) {
|
||
var next, prev, uid;
|
||
uid = json['uid'], prev = json['prev'], next = json['next'];
|
||
return new Delimiter(uid, prev, next);
|
||
};
|
||
return {
|
||
'types': {
|
||
'Delete': Delete,
|
||
'Insert': Insert,
|
||
'Delimiter': Delimiter,
|
||
'Operation': Operation,
|
||
'ImmutableObject': ImmutableObject
|
||
},
|
||
'parser': parser,
|
||
'execution_listener': execution_listener
|
||
};
|
||
};
|
||
|
||
|
||
},{}],6:[function(require,module,exports){
|
||
var text_types_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; };
|
||
|
||
text_types_uninitialized = require("./TextTypes");
|
||
|
||
module.exports = function(HB) {
|
||
var JsonType, createJsonWrapper, parser, text_types, types;
|
||
text_types = text_types_uninitialized(HB);
|
||
types = text_types.types;
|
||
parser = text_types.parser;
|
||
createJsonWrapper = function(_jsonType) {
|
||
var JsonWrapper;
|
||
JsonWrapper = (function() {
|
||
function JsonWrapper(jsonType) {
|
||
var name, obj, _fn, _ref;
|
||
_ref = jsonType.map;
|
||
_fn = function(name, obj) {
|
||
return Object.defineProperty(JsonWrapper.prototype, name, {
|
||
get: function() {
|
||
var x;
|
||
x = obj.val();
|
||
if (x instanceof JsonType) {
|
||
return createJsonWrapper(x);
|
||
} else if (x instanceof types.ImmutableObject) {
|
||
return x.val();
|
||
} else {
|
||
return x;
|
||
}
|
||
},
|
||
set: function(o) {
|
||
var o_name, o_obj, overwrite, _results;
|
||
if (o.constructor === {}.constructor) {
|
||
overwrite = jsonType.val(name);
|
||
_results = [];
|
||
for (o_name in o) {
|
||
o_obj = o[o_name];
|
||
_results.push(overwrite.val(o_name, o_obj, 'immutable'));
|
||
}
|
||
return _results;
|
||
} else {
|
||
return jsonType.val(name, o, 'immutable');
|
||
}
|
||
},
|
||
enumerable: true,
|
||
configurable: false
|
||
});
|
||
};
|
||
for (name in _ref) {
|
||
obj = _ref[name];
|
||
_fn(name, obj);
|
||
}
|
||
}
|
||
|
||
return JsonWrapper;
|
||
|
||
})();
|
||
return new JsonWrapper(_jsonType);
|
||
};
|
||
JsonType = (function(_super) {
|
||
__extends(JsonType, _super);
|
||
|
||
function JsonType(uid, initial_value, mutable) {
|
||
var name, o;
|
||
JsonType.__super__.constructor.call(this, uid);
|
||
if (initial_value != null) {
|
||
if (typeof initial_value !== "object") {
|
||
throw new Error("The initial value of JsonTypes must be of type Object! (current type: " + (typeof initial_value) + ")");
|
||
}
|
||
for (name in initial_value) {
|
||
o = initial_value[name];
|
||
this.val(name, o, mutable);
|
||
}
|
||
}
|
||
}
|
||
|
||
JsonType.prototype.mutable_default = true;
|
||
|
||
JsonType.prototype.setMutableDefault = function(mutable) {
|
||
if (mutable === true || mutable === 'mutable') {
|
||
JsonType.prototype.mutable_default = true;
|
||
} else if (mutable === false || mutable === 'immutable') {
|
||
JsonType.prototype.mutable_default = false;
|
||
} else {
|
||
throw new Error('Set mutable either "mutable" or "immutable"!');
|
||
}
|
||
return 'OK';
|
||
};
|
||
|
||
JsonType.prototype.val = function(name, content, mutable) {
|
||
var json, o, o_name, obj, word;
|
||
if (typeof name === 'object') {
|
||
for (o_name in name) {
|
||
o = name[o_name];
|
||
this.val(o_name, o, content);
|
||
}
|
||
return this;
|
||
} else if ((name != null) && (content != null)) {
|
||
if (mutable != null) {
|
||
if (mutable === true || mutable === 'mutable') {
|
||
mutable = true;
|
||
} else {
|
||
mutable = false;
|
||
}
|
||
} else {
|
||
mutable = this.mutable_default;
|
||
}
|
||
if (typeof content === 'function') {
|
||
return this;
|
||
} else if (((!mutable) || typeof content === 'number') && content.constructor !== Object) {
|
||
obj = HB.addOperation(new types.ImmutableObject(void 0, content)).execute();
|
||
return JsonType.__super__.val.call(this, name, obj);
|
||
} else {
|
||
if (typeof content === 'string') {
|
||
word = HB.addOperation(new types.Word(void 0)).execute();
|
||
word.insertText(0, content);
|
||
return JsonType.__super__.val.call(this, name, word);
|
||
} else if (content.constructor === Object) {
|
||
json = HB.addOperation(new JsonType(void 0, content, mutable)).execute();
|
||
return JsonType.__super__.val.call(this, name, json);
|
||
} else {
|
||
throw new Error("You must not set " + (typeof content) + "-types in collaborative Json-objects!");
|
||
}
|
||
}
|
||
} else {
|
||
return JsonType.__super__.val.call(this, name, content);
|
||
}
|
||
};
|
||
|
||
Object.defineProperty(JsonType.prototype, 'value', {
|
||
get: function() {
|
||
return createJsonWrapper(this);
|
||
},
|
||
set: function(o) {
|
||
var o_name, o_obj, _results;
|
||
if (o.constructor === {}.constructor) {
|
||
_results = [];
|
||
for (o_name in o) {
|
||
o_obj = o[o_name];
|
||
_results.push(this.val(o_name, o_obj, 'immutable'));
|
||
}
|
||
return _results;
|
||
} else {
|
||
throw new Error("You must only set Object values!");
|
||
}
|
||
}
|
||
});
|
||
|
||
JsonType.prototype._encode = function() {
|
||
return {
|
||
'type': "JsonType",
|
||
'uid': this.getUid()
|
||
};
|
||
};
|
||
|
||
return JsonType;
|
||
|
||
})(types.MapManager);
|
||
parser['JsonType'] = function(json) {
|
||
var uid;
|
||
uid = json['uid'];
|
||
return new JsonType(uid);
|
||
};
|
||
types['JsonType'] = JsonType;
|
||
return text_types;
|
||
};
|
||
|
||
|
||
},{"./TextTypes":8}],7:[function(require,module,exports){
|
||
var basic_types_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_types_uninitialized = require("./BasicTypes");
|
||
|
||
module.exports = function(HB) {
|
||
var AddName, ListManager, MapManager, ReplaceManager, Replaceable, basic_types, parser, types;
|
||
basic_types = basic_types_uninitialized(HB);
|
||
types = basic_types.types;
|
||
parser = basic_types.parser;
|
||
MapManager = (function(_super) {
|
||
__extends(MapManager, _super);
|
||
|
||
function MapManager(uid) {
|
||
this.map = {};
|
||
MapManager.__super__.constructor.call(this, uid);
|
||
}
|
||
|
||
MapManager.prototype.val = function(name, content) {
|
||
var o, obj, result, _ref, _ref1;
|
||
if (content != null) {
|
||
if (this.map[name] == null) {
|
||
HB.addOperation(new AddName(void 0, this, name)).execute();
|
||
}
|
||
this.map[name].replace(content);
|
||
return this;
|
||
} else if (name != null) {
|
||
obj = (_ref = this.map[name]) != null ? _ref.val() : void 0;
|
||
if (obj instanceof types.ImmutableObject) {
|
||
return obj.val();
|
||
} else {
|
||
return obj;
|
||
}
|
||
} else {
|
||
result = {};
|
||
_ref1 = this.map;
|
||
for (name in _ref1) {
|
||
o = _ref1[name];
|
||
obj = o.val();
|
||
if (obj instanceof types.ImmutableObject || obj instanceof MapManager) {
|
||
obj = obj.val();
|
||
}
|
||
result[name] = obj;
|
||
}
|
||
return result;
|
||
}
|
||
};
|
||
|
||
return MapManager;
|
||
|
||
})(types.Operation);
|
||
AddName = (function(_super) {
|
||
__extends(AddName, _super);
|
||
|
||
function AddName(uid, map_manager, name) {
|
||
this.name = name;
|
||
this.saveOperation('map_manager', map_manager);
|
||
AddName.__super__.constructor.call(this, uid);
|
||
}
|
||
|
||
AddName.prototype.execute = function() {
|
||
var beg, end, uid_beg, uid_end, uid_r;
|
||
if (!this.validateSavedOperations()) {
|
||
return false;
|
||
} else {
|
||
uid_r = this.map_manager.getUid();
|
||
uid_r.op_number = "_" + uid_r.op_number + "_RM_" + this.name;
|
||
if (HB.getOperation(uid_r) == null) {
|
||
uid_beg = this.map_manager.getUid();
|
||
uid_beg.op_number = "_" + uid_beg.op_number + "_RM_" + this.name + "_beginning";
|
||
uid_end = this.map_manager.getUid();
|
||
uid_end.op_number = "_" + uid_end.op_number + "_RM_" + this.name + "_end";
|
||
beg = HB.addOperation(new types.Delimiter(uid_beg, void 0, uid_end)).execute();
|
||
end = HB.addOperation(new types.Delimiter(uid_end, beg, void 0)).execute();
|
||
this.map_manager.map[this.name] = HB.addOperation(new ReplaceManager(void 0, uid_r, beg, end)).execute();
|
||
}
|
||
return AddName.__super__.execute.apply(this, arguments);
|
||
}
|
||
};
|
||
|
||
AddName.prototype._encode = function() {
|
||
return {
|
||
'type': "AddName",
|
||
'uid': this.getUid(),
|
||
'map_manager': this.map_manager.getUid(),
|
||
'name': this.name
|
||
};
|
||
};
|
||
|
||
return AddName;
|
||
|
||
})(types.Operation);
|
||
parser['AddName'] = function(json) {
|
||
var map_manager, name, uid;
|
||
map_manager = json['map_manager'], uid = json['uid'], name = json['name'];
|
||
return new AddName(uid, map_manager, name);
|
||
};
|
||
ListManager = (function(_super) {
|
||
__extends(ListManager, _super);
|
||
|
||
function ListManager(uid, beginning, end, prev, next, origin) {
|
||
if ((beginning != null) && (end != null)) {
|
||
this.saveOperation('beginning', beginning);
|
||
this.saveOperation('end', end);
|
||
} else {
|
||
this.beginning = HB.addOperation(new types.Delimiter(void 0, void 0, void 0));
|
||
this.end = HB.addOperation(new types.Delimiter(void 0, this.beginning, void 0));
|
||
this.beginning.next_cl = this.end;
|
||
this.beginning.execute();
|
||
this.end.execute();
|
||
}
|
||
ListManager.__super__.constructor.call(this, uid, prev, next, origin);
|
||
}
|
||
|
||
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) {
|
||
result.push(o);
|
||
o = o.next_cl;
|
||
}
|
||
return result;
|
||
};
|
||
|
||
ListManager.prototype.getOperationByPosition = function(position) {
|
||
var o;
|
||
o = this.beginning.next_cl;
|
||
if ((position > 0 || o.isDeleted()) && !(o instanceof types.Delimiter)) {
|
||
while (o.isDeleted() && !(o instanceof types.Delimiter)) {
|
||
o = o.next_cl;
|
||
}
|
||
while (true) {
|
||
if (o instanceof types.Delimiter) {
|
||
break;
|
||
}
|
||
if (position <= 0 && !o.isDeleted()) {
|
||
break;
|
||
}
|
||
o = o.next_cl;
|
||
if (!o.isDeleted()) {
|
||
position -= 1;
|
||
}
|
||
}
|
||
}
|
||
return o;
|
||
};
|
||
|
||
return ListManager;
|
||
|
||
})(types.Insert);
|
||
ReplaceManager = (function(_super) {
|
||
__extends(ReplaceManager, _super);
|
||
|
||
function ReplaceManager(initial_content, uid, beginning, end, prev, next, origin) {
|
||
ReplaceManager.__super__.constructor.call(this, uid, beginning, end, prev, next, origin);
|
||
if (initial_content != null) {
|
||
this.replace(initial_content);
|
||
}
|
||
}
|
||
|
||
ReplaceManager.prototype.replace = function(content) {
|
||
var o, op;
|
||
o = this.getLastOperation();
|
||
op = new Replaceable(content, this, void 0, o, o.next_cl);
|
||
return HB.addOperation(op).execute();
|
||
};
|
||
|
||
ReplaceManager.prototype.val = function() {
|
||
var o;
|
||
o = this.getLastOperation();
|
||
if (o instanceof types.Delimiter) {
|
||
throw new Error("dtrn");
|
||
}
|
||
return o.val();
|
||
};
|
||
|
||
ReplaceManager.prototype._encode = function() {
|
||
var json;
|
||
json = {
|
||
'type': "ReplaceManager",
|
||
'uid': this.getUid(),
|
||
'beginning': this.beginning.getUid(),
|
||
'end': this.end.getUid()
|
||
};
|
||
if ((this.prev_cl != null) && (this.next_cl != null)) {
|
||
json['prev'] = this.prev_cl.getUid();
|
||
json['next'] = this.next_cl.getUid();
|
||
}
|
||
if ((this.origin != null) && this.origin !== this.prev_cl) {
|
||
json["origin"] = this.origin.getUid();
|
||
}
|
||
return json;
|
||
};
|
||
|
||
return ReplaceManager;
|
||
|
||
})(ListManager);
|
||
parser["ReplaceManager"] = function(json) {
|
||
var beginning, content, end, next, origin, prev, uid;
|
||
content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], beginning = json['beginning'], end = json['end'];
|
||
return new ReplaceManager(content, uid, beginning, end, prev, next, origin);
|
||
};
|
||
Replaceable = (function(_super) {
|
||
__extends(Replaceable, _super);
|
||
|
||
function Replaceable(content, parent, uid, prev, next, origin) {
|
||
this.saveOperation('content', content);
|
||
this.saveOperation('parent', parent);
|
||
if (!((prev != null) && (next != null) && (content != null))) {
|
||
throw new Error("You must define content, prev, and next for Replaceable-types!");
|
||
}
|
||
Replaceable.__super__.constructor.call(this, uid, prev, next, origin);
|
||
}
|
||
|
||
Replaceable.prototype.val = function() {
|
||
return this.content;
|
||
};
|
||
|
||
Replaceable.prototype.replace = function(content) {
|
||
return this.parent.replace(content);
|
||
};
|
||
|
||
Replaceable.prototype.execute = function() {
|
||
var _base;
|
||
if (!this.validateSavedOperations()) {
|
||
return false;
|
||
} else {
|
||
if (typeof (_base = this.content).setReplaceManager === "function") {
|
||
_base.setReplaceManager(this.parent);
|
||
}
|
||
return Replaceable.__super__.execute.apply(this, arguments);
|
||
}
|
||
};
|
||
|
||
Replaceable.prototype._encode = function() {
|
||
var json;
|
||
json = {
|
||
'type': "Replaceable",
|
||
'content': this.content.getUid(),
|
||
'ReplaceManager': this.parent.getUid(),
|
||
'prev': this.prev_cl.getUid(),
|
||
'next': this.next_cl.getUid(),
|
||
'uid': this.getUid()
|
||
};
|
||
if ((this.origin != null) && this.origin !== this.prev_cl) {
|
||
json["origin"] = this.origin.getUid();
|
||
}
|
||
return json;
|
||
};
|
||
|
||
return Replaceable;
|
||
|
||
})(types.Insert);
|
||
parser["Replaceable"] = function(json) {
|
||
var content, next, origin, parent, prev, uid;
|
||
content = json['content'], parent = json['ReplaceManager'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'];
|
||
return new Replaceable(content, parent, uid, prev, next, origin);
|
||
};
|
||
types['ListManager'] = ListManager;
|
||
types['MapManager'] = MapManager;
|
||
types['ReplaceManager'] = ReplaceManager;
|
||
types['Replaceable'] = Replaceable;
|
||
return basic_types;
|
||
};
|
||
|
||
|
||
},{"./BasicTypes":5}],8:[function(require,module,exports){
|
||
var structured_types_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; };
|
||
|
||
structured_types_uninitialized = require("./StructuredTypes");
|
||
|
||
module.exports = function(HB) {
|
||
var TextDelete, TextInsert, Word, parser, structured_types, types;
|
||
structured_types = structured_types_uninitialized(HB);
|
||
types = structured_types.types;
|
||
parser = structured_types.parser;
|
||
TextDelete = (function(_super) {
|
||
__extends(TextDelete, _super);
|
||
|
||
function TextDelete() {
|
||
return TextDelete.__super__.constructor.apply(this, arguments);
|
||
}
|
||
|
||
return TextDelete;
|
||
|
||
})(types.Delete);
|
||
parser["TextDelete"] = parser["Delete"];
|
||
TextInsert = (function(_super) {
|
||
__extends(TextInsert, _super);
|
||
|
||
function TextInsert(content, uid, prev, next, origin) {
|
||
this.content = content;
|
||
if (!((prev != null) && (next != null))) {
|
||
throw new Error("You must define prev, and next for TextInsert-types!");
|
||
}
|
||
TextInsert.__super__.constructor.call(this, uid, prev, next, origin);
|
||
}
|
||
|
||
TextInsert.prototype.getLength = function() {
|
||
if (this.isDeleted()) {
|
||
return 0;
|
||
} else {
|
||
return this.content.length;
|
||
}
|
||
};
|
||
|
||
TextInsert.prototype.val = function(current_position) {
|
||
if (this.isDeleted()) {
|
||
return "";
|
||
} else {
|
||
return this.content;
|
||
}
|
||
};
|
||
|
||
TextInsert.prototype._encode = function() {
|
||
var json;
|
||
json = {
|
||
'type': "TextInsert",
|
||
'content': this.content,
|
||
'uid': this.getUid(),
|
||
'prev': this.prev_cl.getUid(),
|
||
'next': this.next_cl.getUid()
|
||
};
|
||
if ((this.origin != null) && this.origin !== this.prev_cl) {
|
||
json["origin"] = this.origin.getUid();
|
||
}
|
||
return json;
|
||
};
|
||
|
||
return TextInsert;
|
||
|
||
})(types.Insert);
|
||
parser["TextInsert"] = function(json) {
|
||
var content, next, origin, prev, uid;
|
||
content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'];
|
||
return new TextInsert(content, uid, prev, next, origin);
|
||
};
|
||
Word = (function(_super) {
|
||
__extends(Word, _super);
|
||
|
||
function Word(uid, beginning, end, prev, next, origin) {
|
||
Word.__super__.constructor.call(this, uid, beginning, end, prev, next, origin);
|
||
}
|
||
|
||
Word.prototype.insertText = function(position, content) {
|
||
var c, o, op, _i, _len, _results;
|
||
o = this.getOperationByPosition(position);
|
||
_results = [];
|
||
for (_i = 0, _len = content.length; _i < _len; _i++) {
|
||
c = content[_i];
|
||
op = new TextInsert(c, void 0, o.prev_cl, o);
|
||
_results.push(HB.addOperation(op).execute());
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
Word.prototype.deleteText = function(position, length) {
|
||
var d, delete_ops, i, o, _i;
|
||
o = this.getOperationByPosition(position);
|
||
delete_ops = [];
|
||
for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) {
|
||
if (o instanceof types.Delimiter) {
|
||
break;
|
||
}
|
||
d = HB.addOperation(new TextDelete(void 0, o)).execute();
|
||
o = o.next_cl;
|
||
while (!(o instanceof types.Delimiter) && o.isDeleted()) {
|
||
o = o.next_cl;
|
||
}
|
||
delete_ops.push(d._encode());
|
||
}
|
||
return delete_ops;
|
||
};
|
||
|
||
Word.prototype.replaceText = function(text) {
|
||
var word;
|
||
if (this.replace_manager != null) {
|
||
word = HB.addOperation(new Word(void 0)).execute();
|
||
word.insertText(0, text);
|
||
return this.replace_manager.replace(word);
|
||
} else {
|
||
throw new Error("This type is currently not maintained by a ReplaceManager!");
|
||
}
|
||
};
|
||
|
||
Word.prototype.val = function() {
|
||
var c, o;
|
||
c = (function() {
|
||
var _i, _len, _ref, _results;
|
||
_ref = this.toArray();
|
||
_results = [];
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
o = _ref[_i];
|
||
if (o.val != null) {
|
||
_results.push(o.val());
|
||
} else {
|
||
_results.push("");
|
||
}
|
||
}
|
||
return _results;
|
||
}).call(this);
|
||
return c.join('');
|
||
};
|
||
|
||
Word.prototype.setReplaceManager = function(op) {
|
||
this.saveOperation('replace_manager', op);
|
||
return this.validateSavedOperations;
|
||
};
|
||
|
||
Word.prototype.bind = function(textfield) {
|
||
var word;
|
||
word = this;
|
||
textfield.value = this.val();
|
||
this.on("insert", function(event, op) {
|
||
var fix, left, o_pos, right;
|
||
o_pos = op.getPosition();
|
||
fix = function(cursor) {
|
||
if (cursor <= o_pos) {
|
||
return cursor;
|
||
} else {
|
||
cursor += 1;
|
||
return cursor;
|
||
}
|
||
};
|
||
left = fix(textfield.selectionStart);
|
||
right = fix(textfield.selectionEnd);
|
||
textfield.value = word.val();
|
||
return textfield.setSelectionRange(left, right);
|
||
});
|
||
this.on("delete", function(event, op) {
|
||
var fix, left, o_pos, right;
|
||
o_pos = op.getPosition();
|
||
fix = function(cursor) {
|
||
if (cursor < o_pos) {
|
||
return cursor;
|
||
} else {
|
||
cursor -= 1;
|
||
return cursor;
|
||
}
|
||
};
|
||
left = fix(textfield.selectionStart);
|
||
right = fix(textfield.selectionEnd);
|
||
textfield.value = word.val();
|
||
return textfield.setSelectionRange(left, right);
|
||
});
|
||
textfield.onkeypress = function(event) {
|
||
var char, diff, new_pos, pos;
|
||
char = null;
|
||
if (event.key != null) {
|
||
if (event.charCode === 32) {
|
||
char = " ";
|
||
} else if (event.keyCode === 13) {
|
||
char = '\n';
|
||
} else {
|
||
char = event.key;
|
||
}
|
||
} else {
|
||
char = String.fromCharCode(event.keyCode);
|
||
}
|
||
if (char.length > 0) {
|
||
pos = Math.min(textfield.selectionStart, textfield.selectionEnd);
|
||
diff = Math.abs(textfield.selectionEnd - textfield.selectionStart);
|
||
word.deleteText(pos, diff);
|
||
word.insertText(pos, char);
|
||
new_pos = pos + char.length;
|
||
textfield.setSelectionRange(new_pos, new_pos);
|
||
return event.preventDefault();
|
||
} else {
|
||
return event.preventDefault();
|
||
}
|
||
};
|
||
textfield.onpaste = function(event) {
|
||
return event.preventDefault();
|
||
};
|
||
textfield.oncut = function(event) {
|
||
return event.preventDefault();
|
||
};
|
||
return textfield.onkeydown = function(event) {
|
||
var del_length, diff, new_pos, pos, val;
|
||
pos = Math.min(textfield.selectionStart, textfield.selectionEnd);
|
||
diff = Math.abs(textfield.selectionEnd - textfield.selectionStart);
|
||
if ((event.keyCode != null) && event.keyCode === 8) {
|
||
if (diff > 0) {
|
||
word.deleteText(pos, diff);
|
||
textfield.setSelectionRange(pos, pos);
|
||
} else {
|
||
if ((event.ctrlKey != null) && event.ctrlKey) {
|
||
val = textfield.value;
|
||
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.deleteText(new_pos, pos - new_pos);
|
||
textfield.setSelectionRange(new_pos, new_pos);
|
||
} else {
|
||
word.deleteText(pos - 1, 1);
|
||
}
|
||
}
|
||
return event.preventDefault();
|
||
} else if ((event.keyCode != null) && event.keyCode === 46) {
|
||
if (diff > 0) {
|
||
word.deleteText(pos, diff);
|
||
textfield.setSelectionRange(pos, pos);
|
||
} else {
|
||
word.deleteText(pos, 1);
|
||
textfield.setSelectionRange(pos, pos);
|
||
}
|
||
return event.preventDefault();
|
||
}
|
||
};
|
||
};
|
||
|
||
Word.prototype._encode = function() {
|
||
var json;
|
||
json = {
|
||
'type': "Word",
|
||
'uid': this.getUid(),
|
||
'beginning': this.beginning.getUid(),
|
||
'end': this.end.getUid()
|
||
};
|
||
if (this.prev_cl != null) {
|
||
json['prev'] = this.prev_cl.getUid();
|
||
}
|
||
if (this.next_cl != null) {
|
||
json['next'] = this.next_cl.getUid();
|
||
}
|
||
if ((this.origin != null) && this.origin !== this.prev_cl) {
|
||
json["origin"] = this.origin.getUid();
|
||
}
|
||
return json;
|
||
};
|
||
|
||
return Word;
|
||
|
||
})(types.ListManager);
|
||
parser['Word'] = function(json) {
|
||
var beginning, end, next, origin, prev, uid;
|
||
uid = json['uid'], beginning = json['beginning'], end = json['end'], prev = json['prev'], next = json['next'], origin = json['origin'];
|
||
return new Word(uid, beginning, end, prev, next, origin);
|
||
};
|
||
types['TextInsert'] = TextInsert;
|
||
types['TextDelete'] = TextDelete;
|
||
types['Word'] = Word;
|
||
return structured_types;
|
||
};
|
||
|
||
|
||
},{"./StructuredTypes":7}],9:[function(require,module,exports){
|
||
module.exports = require('./lib/chai');
|
||
|
||
},{"./lib/chai":10}],10:[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 = '1.9.1';
|
||
|
||
/*!
|
||
* 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;
|
||
};
|
||
|
||
/*!
|
||
* 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":11,"./chai/config":12,"./chai/core/assertions":13,"./chai/interface/assert":14,"./chai/interface/expect":15,"./chai/interface/should":16,"./chai/utils":27,"assertion-error":36}],11:[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} message to display if fails
|
||
* @param {String} 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`
|
||
* @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":12}],12:[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,
|
||
* the value is truncated.
|
||
*
|
||
* Set it to zero if you want to disable truncating altogether.
|
||
*
|
||
* chai.config.truncateThreshold = 0; // disable truncating
|
||
*
|
||
* @param {Number}
|
||
* @api public
|
||
*/
|
||
|
||
truncateThreshold: 40
|
||
|
||
};
|
||
|
||
},{}],13:[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
|
||
* - and
|
||
* - has
|
||
* - have
|
||
* - with
|
||
* - at
|
||
* - of
|
||
* - same
|
||
*
|
||
* @name language chains
|
||
* @api public
|
||
*/
|
||
|
||
[ 'to', 'be', 'been'
|
||
, 'is', 'and', 'has', 'have'
|
||
, 'with', 'that', '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');
|
||
*
|
||
* @name deep
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('deep', function () {
|
||
flag(this, 'deep', true);
|
||
});
|
||
|
||
/**
|
||
* ### .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 `contain` 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
|
||
* @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);
|
||
|
||
/**
|
||
* ### .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, 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' });
|
||
*
|
||
* @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 descriptor = flag(this, 'deep') ? 'deep property ' : 'property '
|
||
, negate = flag(this, 'negate')
|
||
, obj = flag(this, 'object')
|
||
, value = flag(this, 'deep')
|
||
? _.getPathValue(name, obj)
|
||
: 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(
|
||
undefined !== value
|
||
, '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, assertLengthChain);
|
||
|
||
/**
|
||
* ### .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 has exactly the given keys, or
|
||
* asserts the inclusion of some keys when using the
|
||
* `include` or `contain` modifiers.
|
||
*
|
||
* expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']);
|
||
* expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar');
|
||
*
|
||
* @name keys
|
||
* @alias key
|
||
* @param {String...|Array} keys
|
||
* @api public
|
||
*/
|
||
|
||
function assertKeys (keys) {
|
||
var obj = flag(this, 'object')
|
||
, str
|
||
, ok = true;
|
||
|
||
keys = keys instanceof Array
|
||
? keys
|
||
: Array.prototype.slice.call(arguments);
|
||
|
||
if (!keys.length) throw new Error('keys required');
|
||
|
||
var actual = Object.keys(obj)
|
||
, len = keys.length;
|
||
|
||
// Inclusion
|
||
ok = keys.every(function(key){
|
||
return ~actual.indexOf(key);
|
||
});
|
||
|
||
// Strict
|
||
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();
|
||
str = keys.join(', ') + ', and ' + 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
|
||
);
|
||
}
|
||
|
||
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');
|
||
this.assert(
|
||
matcher(obj)
|
||
, 'expected #{this} to satisfy ' + _.objDisplay(matcher)
|
||
, 'expected #{this} to not satisfy' + _.objDisplay(matcher)
|
||
, this.negate ? false : true
|
||
, matcher(obj)
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .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');
|
||
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
|
||
);
|
||
});
|
||
};
|
||
|
||
},{}],14:[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.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) {
|
||
if (!~['==', '===', '>', '>=', '<', '<=', '!=', '!=='].indexOf(operator)) {
|
||
throw new Error('Invalid operator "' + operator + '"');
|
||
}
|
||
var test = new Assertion(eval(val + operator + val2), 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} superset
|
||
* @param {Array} subset
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.sameMembers = function (set1, set2, msg) {
|
||
new Assertion(set1, msg).to.have.same.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);
|
||
}
|
||
|
||
/*!
|
||
* 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');
|
||
};
|
||
|
||
},{}],15:[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);
|
||
};
|
||
};
|
||
|
||
|
||
},{}],16:[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) {
|
||
return new Assertion(this.constructor(this), null, shouldGetter);
|
||
} else if (this instanceof Boolean) {
|
||
return new Assertion(this == true, 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 = {};
|
||
|
||
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;
|
||
};
|
||
|
||
},{}],17:[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":12,"./flag":20,"./transferFlags":34}],18:[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":12,"./flag":20}],19:[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
|
||
});
|
||
};
|
||
|
||
},{}],20:[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];
|
||
}
|
||
};
|
||
|
||
},{}],21:[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;
|
||
};
|
||
|
||
},{}],22:[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;
|
||
};
|
||
|
||
},{}],23:[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');
|
||
|
||
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":20,"./getActual":21,"./inspect":28,"./objDisplay":29}],24:[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] : "";
|
||
};
|
||
|
||
},{}],25:[function(require,module,exports){
|
||
/*!
|
||
* Chai - getPathValue utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* @see https://github.com/logicalparadox/filtr
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* ### .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
|
||
*/
|
||
|
||
var getPathValue = module.exports = function (path, obj) {
|
||
var parsed = parsePath(path);
|
||
return _getPathValue(parsed, obj);
|
||
};
|
||
|
||
/*!
|
||
* ## 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`.
|
||
*
|
||
* @param {String} path
|
||
* @returns {Object} parsed
|
||
* @api private
|
||
*/
|
||
|
||
function parsePath (path) {
|
||
var str = path.replace(/\[/g, '.[')
|
||
, 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 };
|
||
});
|
||
};
|
||
|
||
/*!
|
||
* ## _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
|
||
* @returns {Object|Undefined} value
|
||
* @api private
|
||
*/
|
||
|
||
function _getPathValue (parsed, obj) {
|
||
var tmp = obj
|
||
, res;
|
||
for (var i = 0, l = parsed.length; 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;
|
||
};
|
||
|
||
},{}],26:[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;
|
||
};
|
||
|
||
},{}],27:[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');
|
||
|
||
/*!
|
||
* 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":17,"./addMethod":18,"./addProperty":19,"./flag":20,"./getActual":21,"./getMessage":23,"./getName":24,"./getPathValue":25,"./inspect":28,"./objDisplay":29,"./overwriteChainableMethod":30,"./overwriteMethod":31,"./overwriteProperty":32,"./test":33,"./transferFlags":34,"./type":35,"deep-eql":37}],28:[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));
|
||
}
|
||
|
||
// https://gist.github.com/1044128/
|
||
var getOuterHTML = function(element) {
|
||
if ('outerHTML' in element) return element.outerHTML;
|
||
var ns = "http://www.w3.org/1999/xhtml";
|
||
var container = document.createElementNS(ns, '_');
|
||
var elemProto = (window.HTMLElement || window.Element).prototype;
|
||
var xmlSerializer = new XMLSerializer();
|
||
var html;
|
||
if (document.xmlVersion) {
|
||
return xmlSerializer.serializeToString(element);
|
||
} else {
|
||
container.appendChild(element.cloneNode(false));
|
||
html = container.innerHTML.replace('><', '>' + element.innerHTML + '<');
|
||
container.innerHTML = '';
|
||
return html;
|
||
}
|
||
};
|
||
|
||
// 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 it's DOM elem, get outer HTML.
|
||
if (isDOMElement(value)) {
|
||
return getOuterHTML(value);
|
||
}
|
||
|
||
// 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':
|
||
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":22,"./getName":24,"./getProperties":26}],29:[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":12,"./inspect":28}],30:[function(require,module,exports){
|
||
/*!
|
||
* Chai - overwriteChainableMethod utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* ### overwriteChainableMethod (ctx, name, fn)
|
||
*
|
||
* 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;
|
||
};
|
||
};
|
||
|
||
},{}],31:[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;
|
||
}
|
||
};
|
||
|
||
},{}],32:[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
|
||
});
|
||
};
|
||
|
||
},{}],33:[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":20}],34:[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 too; usually a new assertion
|
||
* @param {Boolean} includeAll
|
||
* @name getAllFlags
|
||
* @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];
|
||
}
|
||
}
|
||
};
|
||
|
||
},{}],35:[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;
|
||
};
|
||
|
||
},{}],36:[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;
|
||
};
|
||
|
||
},{}],37:[function(require,module,exports){
|
||
module.exports = require('./lib/eql');
|
||
|
||
},{"./lib/eql":38}],38:[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":41,"type-detect":39}],39:[function(require,module,exports){
|
||
module.exports = require('./lib/type');
|
||
|
||
},{"./lib/type":40}],40:[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.');
|
||
}
|
||
};
|
||
|
||
},{}],41:[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":42,"ieee754":43}],42:[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)
|
||
|
||
function decode (elt) {
|
||
var code = elt.charCodeAt(0)
|
||
if (code === PLUS)
|
||
return 62 // '+'
|
||
if (code === SLASH)
|
||
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))
|
||
|
||
},{}],43:[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;
|
||
};
|
||
|
||
},{}],44:[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
|
||
}
|
||
}
|
||
|
||
},{}],45:[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');
|
||
};
|
||
|
||
},{}],46:[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';
|
||
}
|
||
},{}],47:[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("1YiZ5S"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"./support/isBuffer":46,"1YiZ5S":45,"inherits":44}],48:[function(require,module,exports){
|
||
(function (sinonChai) {
|
||
"use strict";
|
||
|
||
// Module systems magic dance.
|
||
|
||
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: printfArray(["expected %n to " + verbPhrase + action + nonNegatedSuffix].concat(args)),
|
||
negative: 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");
|
||
}));
|
||
|
||
},{}],49:[function(require,module,exports){
|
||
/*jslint eqeqeq: false, onevar: false, forin: true, nomen: false, regexp: false, plusplus: false*/
|
||
/*global module, require, __dirname, document*/
|
||
/**
|
||
* 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 (formatio) {
|
||
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;
|
||
}
|
||
|
||
var sinon = {
|
||
wrapMethod: function wrapMethod(object, property, method) {
|
||
if (!object) {
|
||
throw new TypeError("Should wrap property of object");
|
||
}
|
||
|
||
if (typeof method != "function") {
|
||
throw new TypeError("Method wrapper should be function");
|
||
}
|
||
|
||
var wrappedMethod = object[property],
|
||
error;
|
||
|
||
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._stack) {
|
||
error.stack += '\n--------------\n' + wrappedMethod._stack;
|
||
}
|
||
throw error;
|
||
}
|
||
|
||
// 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);
|
||
object[property] = method;
|
||
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._stack = (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) {
|
||
delete object[property];
|
||
}
|
||
if (object[property] === method) {
|
||
object[property] = wrappedMethod;
|
||
}
|
||
};
|
||
|
||
method.restore.sinon = true;
|
||
mirrorProperties(method, wrappedMethod);
|
||
|
||
return method;
|
||
},
|
||
|
||
extend: function extend(target) {
|
||
for (var i = 1, l = arguments.length; i < l; i += 1) {
|
||
for (var prop in arguments[i]) {
|
||
if (arguments[i].hasOwnProperty(prop)) {
|
||
target[prop] = arguments[i][prop];
|
||
}
|
||
|
||
// DONT ENUM bug, only care about toString
|
||
if (arguments[i].hasOwnProperty("toString") &&
|
||
arguments[i].toString != target.toString) {
|
||
target.toString = arguments[i].toString;
|
||
}
|
||
}
|
||
}
|
||
|
||
return target;
|
||
},
|
||
|
||
create: function create(proto) {
|
||
var F = function () {};
|
||
F.prototype = proto;
|
||
return new F();
|
||
},
|
||
|
||
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;
|
||
},
|
||
|
||
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;
|
||
},
|
||
|
||
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";
|
||
},
|
||
|
||
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;
|
||
},
|
||
|
||
format: function (val) {
|
||
return "" + val;
|
||
},
|
||
|
||
defaultConfig: {
|
||
injectIntoThis: true,
|
||
injectInto: null,
|
||
properties: ["spy", "stub", "mock", "clock", "server", "requests"],
|
||
useFakeTimers: true,
|
||
useFakeServer: true
|
||
},
|
||
|
||
timesInWords: function timesInWords(count) {
|
||
return count == 1 && "once" ||
|
||
count == 2 && "twice" ||
|
||
count == 3 && "thrice" ||
|
||
(count || 0) + " times";
|
||
},
|
||
|
||
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;
|
||
},
|
||
|
||
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;
|
||
});
|
||
},
|
||
|
||
log: function () {},
|
||
|
||
logError: function (label, err) {
|
||
var msg = label + " threw exception: ";
|
||
sinon.log(msg + "[" + err.name + "] " + err.message);
|
||
if (err.stack) { sinon.log(err.stack); }
|
||
|
||
setTimeout(function () {
|
||
err.message = msg + err.message;
|
||
throw err;
|
||
}, 0);
|
||
},
|
||
|
||
typeOf: function (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();
|
||
},
|
||
|
||
createStubInstance: function (constructor) {
|
||
if (typeof constructor !== "function") {
|
||
throw new TypeError("The constructor should be a function.");
|
||
}
|
||
return sinon.stub(sinon.create(constructor.prototype));
|
||
},
|
||
|
||
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();
|
||
}
|
||
}
|
||
};
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === 'function' && typeof define.amd === 'object' && define.amd;
|
||
|
||
function makePublicAPI(require, exports, module) {
|
||
module.exports = sinon;
|
||
sinon.spy = require("./sinon/spy");
|
||
sinon.spyCall = require("./sinon/call");
|
||
sinon.behavior = require("./sinon/behavior");
|
||
sinon.stub = require("./sinon/stub");
|
||
sinon.mock = require("./sinon/mock");
|
||
sinon.collection = require("./sinon/collection");
|
||
sinon.assert = require("./sinon/assert");
|
||
sinon.sandbox = require("./sinon/sandbox");
|
||
sinon.test = require("./sinon/test");
|
||
sinon.testCase = require("./sinon/test_case");
|
||
sinon.match = require("./sinon/match");
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(makePublicAPI);
|
||
} else if (isNode) {
|
||
try {
|
||
formatio = require("formatio");
|
||
} catch (e) {}
|
||
makePublicAPI(require, exports, module);
|
||
}
|
||
|
||
if (formatio) {
|
||
var formatter = formatio.configure({ quoteStrings: false });
|
||
sinon.format = function () {
|
||
return formatter.ascii.apply(formatter, arguments);
|
||
};
|
||
} else if (isNode) {
|
||
try {
|
||
var util = require("util");
|
||
sinon.format = function (value) {
|
||
return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
|
||
};
|
||
} catch (e) {
|
||
/* Node, but no util module - would be very old, but better safe than
|
||
sorry */
|
||
}
|
||
}
|
||
|
||
return sinon;
|
||
}(typeof formatio == "object" && formatio));
|
||
|
||
},{"./sinon/assert":50,"./sinon/behavior":51,"./sinon/call":52,"./sinon/collection":53,"./sinon/match":54,"./sinon/mock":55,"./sinon/sandbox":56,"./sinon/spy":57,"./sinon/stub":58,"./sinon/test":59,"./sinon/test_case":60,"formatio":62,"util":47}],50:[function(require,module,exports){
|
||
(function (global){
|
||
/**
|
||
* @depend ../sinon.js
|
||
* @depend stub.js
|
||
*/
|
||
/*jslint eqeqeq: false, onevar: false, nomen: false, plusplus: false*/
|
||
/*global module, require, sinon*/
|
||
/**
|
||
* 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 commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var slice = Array.prototype.slice;
|
||
var assert;
|
||
|
||
if (!sinon && commonJSModule) {
|
||
sinon = require("../sinon");
|
||
}
|
||
|
||
if (!sinon) {
|
||
return;
|
||
}
|
||
|
||
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 (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.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 != "export" && (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;
|
||
|
||
if (typeof define === "function" && define.amd) {
|
||
define(["module"], function(module) { module.exports = assert; });
|
||
} else if (commonJSModule) {
|
||
module.exports = assert;
|
||
}
|
||
}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"../sinon":49}],51:[function(require,module,exports){
|
||
(function (process){
|
||
/**
|
||
* @depend ../sinon.js
|
||
*/
|
||
/*jslint eqeqeq: false, onevar: false*/
|
||
/*global module, require, sinon, process, setImmediate, setTimeout*/
|
||
/**
|
||
* 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 commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
|
||
if (!sinon && commonJSModule) {
|
||
sinon = require("../sinon");
|
||
}
|
||
|
||
if (!sinon) {
|
||
return;
|
||
}
|
||
|
||
var slice = Array.prototype.slice;
|
||
var join = Array.prototype.join;
|
||
var proto;
|
||
|
||
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) {
|
||
var callArgProp = behavior.callArgProp;
|
||
|
||
for (var i = 0, l = args.length; i < l; ++i) {
|
||
if (!callArgProp && typeof args[i] == "function") {
|
||
return args[i];
|
||
}
|
||
|
||
if (callArgProp && args[i] &&
|
||
typeof args[i][callArgProp] == "function") {
|
||
return args[i][callArgProp];
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
return args[callArgAt];
|
||
}
|
||
|
||
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);
|
||
}
|
||
}
|
||
}
|
||
|
||
proto = {
|
||
create: function(stub) {
|
||
var behavior = sinon.extend({}, sinon.behavior);
|
||
delete behavior.create;
|
||
behavior.stub = stub;
|
||
|
||
return behavior;
|
||
},
|
||
|
||
isPresent: function() {
|
||
return (typeof this.callArgAt == 'number' ||
|
||
this.exception ||
|
||
typeof this.returnArgAt == 'number' ||
|
||
this.returnThis ||
|
||
this.returnValueDefined);
|
||
},
|
||
|
||
invoke: function(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(index) {
|
||
return this.stub.onCall(index);
|
||
},
|
||
|
||
onFirstCall: function() {
|
||
return this.stub.onFirstCall();
|
||
},
|
||
|
||
onSecondCall: function() {
|
||
return this.stub.onSecondCall();
|
||
},
|
||
|
||
onThirdCall: function() {
|
||
return this.stub.onThirdCall();
|
||
},
|
||
|
||
withArgs: function(/* 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 = -1;
|
||
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 = -1;
|
||
this.callbackArguments = slice.call(arguments, 1);
|
||
this.callbackContext = context;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
yieldsTo: function (prop) {
|
||
this.callArgAt = -1;
|
||
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 = -1;
|
||
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;
|
||
|
||
if (typeof define === "function" && define.amd) {
|
||
define(["module"], function(module) { module.exports = proto; });
|
||
} else if (commonJSModule) {
|
||
module.exports = proto;
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
}).call(this,require("1YiZ5S"))
|
||
},{"../sinon":49,"1YiZ5S":45}],52:[function(require,module,exports){
|
||
/**
|
||
* @depend ../sinon.js
|
||
* @depend match.js
|
||
*/
|
||
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
|
||
/*global module, require, sinon*/
|
||
/**
|
||
* 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) {
|
||
var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
if (!sinon && commonJSModule) {
|
||
sinon = require("../sinon");
|
||
}
|
||
|
||
if (!sinon) {
|
||
return;
|
||
}
|
||
|
||
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() {
|
||
for (var i = 0, l = arguments.length; i < l; i += 1) {
|
||
if (!sinon.deepEqual(arguments[i], this.args[i])) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
},
|
||
|
||
calledWithMatch: function calledWithMatch() {
|
||
for (var i = 0, l = arguments.length; 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;
|
||
|
||
if (typeof define === "function" && define.amd) {
|
||
define(["module"], function(module) { module.exports = createSpyCall; });
|
||
} else if (commonJSModule) {
|
||
module.exports = createSpyCall;
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
|
||
},{"../sinon":49}],53:[function(require,module,exports){
|
||
/**
|
||
* @depend ../sinon.js
|
||
* @depend stub.js
|
||
* @depend mock.js
|
||
*/
|
||
/*jslint eqeqeq: false, onevar: false, forin: true*/
|
||
/*global module, require, sinon*/
|
||
/**
|
||
* 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 commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var push = [].push;
|
||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||
|
||
if (!sinon && commonJSModule) {
|
||
sinon = require("../sinon");
|
||
}
|
||
|
||
if (!sinon) {
|
||
return;
|
||
}
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
var collection = {
|
||
verify: function resolve() {
|
||
each(this, "verify");
|
||
},
|
||
|
||
restore: function restore() {
|
||
each(this, "restore");
|
||
compact(this);
|
||
},
|
||
|
||
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;
|
||
|
||
if (typeof define === "function" && define.amd) {
|
||
define(["module"], function(module) { module.exports = collection; });
|
||
} else if (commonJSModule) {
|
||
module.exports = collection;
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"../sinon":49}],54:[function(require,module,exports){
|
||
/* @depend ../sinon.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) {
|
||
var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
|
||
if (!sinon && commonJSModule) {
|
||
sinon = require("../sinon");
|
||
}
|
||
|
||
if (!sinon) {
|
||
return;
|
||
}
|
||
|
||
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;
|
||
|
||
if (typeof define === "function" && define.amd) {
|
||
define(["module"], function(module) { module.exports = match; });
|
||
} else if (commonJSModule) {
|
||
module.exports = match;
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"../sinon":49}],55:[function(require,module,exports){
|
||
/**
|
||
* @depend ../sinon.js
|
||
* @depend stub.js
|
||
*/
|
||
/*jslint eqeqeq: false, onevar: false, nomen: false*/
|
||
/*global module, require, sinon*/
|
||
/**
|
||
* Mock functions.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var push = [].push;
|
||
var match;
|
||
|
||
if (!sinon && commonJSModule) {
|
||
sinon = require("../sinon");
|
||
}
|
||
|
||
if (!sinon) {
|
||
return;
|
||
}
|
||
|
||
match = sinon.match;
|
||
|
||
if (!match && commonJSModule) {
|
||
match = require("./match");
|
||
}
|
||
|
||
function mock(object) {
|
||
if (!object) {
|
||
return sinon.expectation.create("Anonymous mock");
|
||
}
|
||
|
||
return mock.create(object);
|
||
}
|
||
|
||
sinon.mock = mock;
|
||
|
||
sinon.extend(mock, (function () {
|
||
function each(collection, callback) {
|
||
if (!collection) {
|
||
return;
|
||
}
|
||
|
||
for (var i = 0, l = collection.length; i < l; i += 1) {
|
||
callback(collection[i]);
|
||
}
|
||
}
|
||
|
||
return {
|
||
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 {
|
||
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;
|
||
|
||
sinon.expectation = (function () {
|
||
var slice = Array.prototype.slice;
|
||
var _invoke = sinon.spy.invoke;
|
||
|
||
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;
|
||
}
|
||
}
|
||
|
||
return {
|
||
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 _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(message) {
|
||
sinon.assert.pass(message);
|
||
},
|
||
fail: function (message) {
|
||
var exception = new Error(message);
|
||
exception.name = "ExpectationError";
|
||
|
||
throw exception;
|
||
}
|
||
};
|
||
}());
|
||
|
||
sinon.mock = mock;
|
||
|
||
if (typeof define === "function" && define.amd) {
|
||
define(["module"], function(module) { module.exports = mock; });
|
||
} else if (commonJSModule) {
|
||
module.exports = mock;
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"../sinon":49,"./match":54}],56:[function(require,module,exports){
|
||
/**
|
||
* @depend ../sinon.js
|
||
* @depend collection.js
|
||
* @depend util/fake_timers.js
|
||
* @depend util/fake_server_with_clock.js
|
||
*/
|
||
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
|
||
/*global require, module*/
|
||
/**
|
||
* 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";
|
||
|
||
if (typeof module !== "undefined" && module.exports && typeof require == "function") {
|
||
var sinon = require("../sinon");
|
||
sinon.extend(sinon, require("./util/fake_timers"));
|
||
}
|
||
|
||
(function () {
|
||
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;
|
||
}
|
||
|
||
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;
|
||
}
|
||
});
|
||
|
||
sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
|
||
|
||
if (typeof define === "function" && define.amd) {
|
||
define(["module"], function(module) { module.exports = sinon.sandbox; });
|
||
} else if (typeof module !== 'undefined' && module.exports) {
|
||
module.exports = sinon.sandbox;
|
||
}
|
||
}());
|
||
|
||
},{"../sinon":49,"./util/fake_timers":61}],57:[function(require,module,exports){
|
||
/**
|
||
* @depend ../sinon.js
|
||
* @depend call.js
|
||
*/
|
||
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
|
||
/*global module, require, sinon*/
|
||
/**
|
||
* Spy functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var push = Array.prototype.push;
|
||
var slice = Array.prototype.slice;
|
||
var callId = 0;
|
||
|
||
if (!sinon && commonJSModule) {
|
||
sinon = require("../sinon");
|
||
}
|
||
|
||
if (!sinon) {
|
||
return;
|
||
}
|
||
|
||
function spy(object, property) {
|
||
if (!property && typeof object == "function") {
|
||
return spy.create(object);
|
||
}
|
||
|
||
if (!object && !property) {
|
||
return spy.create(function () { });
|
||
}
|
||
|
||
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) {
|
||
// Retain the function length:
|
||
var p;
|
||
if (func.length) {
|
||
eval("p = (function proxy(" + vars.substring(0, func.length * 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 () {
|
||
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();
|
||
}
|
||
}
|
||
},
|
||
|
||
create: function create(func) {
|
||
var name;
|
||
|
||
if (typeof func != "function") {
|
||
func = function () { };
|
||
} else {
|
||
name = sinon.functionName(func);
|
||
}
|
||
|
||
var proxy = createProxy(func);
|
||
|
||
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._create = 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 {
|
||
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;
|
||
}
|
||
|
||
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._create();
|
||
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;
|
||
|
||
if (typeof define === "function" && define.amd) {
|
||
define(["module"], function(module) { module.exports = spy; });
|
||
} else if (commonJSModule) {
|
||
module.exports = spy;
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"../sinon":49}],58:[function(require,module,exports){
|
||
/**
|
||
* @depend ../sinon.js
|
||
* @depend spy.js
|
||
* @depend behavior.js
|
||
*/
|
||
/*jslint eqeqeq: false, onevar: false*/
|
||
/*global module, require, sinon*/
|
||
/**
|
||
* Stub functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
|
||
if (!sinon && commonJSModule) {
|
||
sinon = require("../sinon");
|
||
}
|
||
|
||
if (!sinon) {
|
||
return;
|
||
}
|
||
|
||
function stub(object, property, func) {
|
||
if (!!func && typeof func != "function") {
|
||
throw new TypeError("Custom stub should be function");
|
||
}
|
||
|
||
var wrapper;
|
||
|
||
if (func) {
|
||
wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
|
||
} else {
|
||
wrapper = stub.create();
|
||
}
|
||
|
||
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;
|
||
|
||
sinon.extend(stub, (function () {
|
||
var proto = {
|
||
create: function create() {
|
||
var functionStub = function () {
|
||
return getCurrentBehavior(functionStub).invoke(this, arguments);
|
||
};
|
||
|
||
functionStub.id = "stub#" + uuid++;
|
||
var orig = functionStub;
|
||
functionStub = sinon.spy.create(functionStub);
|
||
functionStub.func = orig;
|
||
|
||
sinon.extend(functionStub, stub);
|
||
functionStub._create = 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(index) {
|
||
if (!this.behaviors[index]) {
|
||
this.behaviors[index] = sinon.behavior.create(this);
|
||
}
|
||
|
||
return this.behaviors[index];
|
||
},
|
||
|
||
onFirstCall: function() {
|
||
return this.onCall(0);
|
||
},
|
||
|
||
onSecondCall: function() {
|
||
return this.onCall(1);
|
||
},
|
||
|
||
onThirdCall: function() {
|
||
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));
|
||
}
|
||
}
|
||
|
||
return proto;
|
||
}()));
|
||
|
||
sinon.stub = stub;
|
||
|
||
if (typeof define === "function" && define.amd) {
|
||
define(["module"], function(module) { module.exports = stub; });
|
||
} else if (commonJSModule) {
|
||
module.exports = stub;
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"../sinon":49}],59:[function(require,module,exports){
|
||
/**
|
||
* @depend ../sinon.js
|
||
* @depend stub.js
|
||
* @depend mock.js
|
||
* @depend sandbox.js
|
||
*/
|
||
/*jslint eqeqeq: false, onevar: false, forin: true, plusplus: false*/
|
||
/*global module, require, sinon*/
|
||
/**
|
||
* Test function, sandboxes fakes
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
|
||
if (!sinon && commonJSModule) {
|
||
sinon = require("../sinon");
|
||
}
|
||
|
||
if (!sinon) {
|
||
return;
|
||
}
|
||
|
||
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 exception, result;
|
||
var args = Array.prototype.slice.call(arguments).concat(sandbox.args);
|
||
|
||
try {
|
||
result = callback.apply(this, args);
|
||
} catch (e) {
|
||
exception = e;
|
||
}
|
||
|
||
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;
|
||
|
||
if (typeof define === "function" && define.amd) {
|
||
define(["module"], function(module) { module.exports = test; });
|
||
} else if (commonJSModule) {
|
||
module.exports = test;
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"../sinon":49}],60:[function(require,module,exports){
|
||
/**
|
||
* @depend ../sinon.js
|
||
* @depend test.js
|
||
*/
|
||
/*jslint eqeqeq: false, onevar: false, eqeqeq: false*/
|
||
/*global module, require, sinon*/
|
||
/**
|
||
* Test case, sandboxes all test functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
var commonJSModule = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
|
||
if (!sinon && commonJSModule) {
|
||
sinon = require("../sinon");
|
||
}
|
||
|
||
if (!sinon || !Object.prototype.hasOwnProperty) {
|
||
return;
|
||
}
|
||
|
||
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 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;
|
||
|
||
if (typeof define === "function" && define.amd) {
|
||
define(["module"], function(module) { module.exports = testCase; });
|
||
} else if (commonJSModule) {
|
||
module.exports = testCase;
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"../sinon":49}],61:[function(require,module,exports){
|
||
(function (global){
|
||
/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
|
||
/*global module, require, window*/
|
||
/**
|
||
* 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) {
|
||
// 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 id = 1;
|
||
|
||
function addTimer(args, recurring) {
|
||
if (args.length === 0) {
|
||
throw new Error("Function requires at least 1 parameter");
|
||
}
|
||
|
||
if (typeof args[0] === "undefined") {
|
||
throw new Error("Callback must be provided to timer calls");
|
||
}
|
||
|
||
var toId = id++;
|
||
var delay = args[1] || 0;
|
||
|
||
if (!this.timeouts) {
|
||
this.timeouts = {};
|
||
}
|
||
|
||
this.timeouts[toId] = {
|
||
id: toId,
|
||
func: args[0],
|
||
callAt: this.now + delay,
|
||
invokeArgs: Array.prototype.slice.call(args, 2)
|
||
};
|
||
|
||
if (recurring === true) {
|
||
this.timeouts[toId].interval = delay;
|
||
}
|
||
|
||
if (addTimerReturnsObject) {
|
||
return {
|
||
id: toId,
|
||
ref: function() {},
|
||
unref: function() {}
|
||
};
|
||
}
|
||
else {
|
||
return toId;
|
||
}
|
||
}
|
||
|
||
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;
|
||
}
|
||
|
||
function createObject(object) {
|
||
var newObject;
|
||
|
||
if (Object.create) {
|
||
newObject = Object.create(object);
|
||
} else {
|
||
var F = function () {};
|
||
F.prototype = object;
|
||
newObject = new F();
|
||
}
|
||
|
||
newObject.Date.clock = newObject;
|
||
return newObject;
|
||
}
|
||
|
||
sinon.clock = {
|
||
now: 0,
|
||
|
||
create: function create(now) {
|
||
var clock = createObject(this);
|
||
|
||
if (typeof now == "number") {
|
||
clock.now = now;
|
||
}
|
||
|
||
if (!!now && typeof now == "object") {
|
||
throw new TypeError("now should be milliseconds since UNIX epoch");
|
||
}
|
||
|
||
return clock;
|
||
},
|
||
|
||
setTimeout: function setTimeout(callback, timeout) {
|
||
return addTimer.call(this, arguments, false);
|
||
},
|
||
|
||
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 (!this.timeouts) {
|
||
this.timeouts = [];
|
||
}
|
||
// 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 this.timeouts) {
|
||
delete this.timeouts[timerId];
|
||
}
|
||
},
|
||
|
||
setInterval: function setInterval(callback, timeout) {
|
||
return addTimer.call(this, arguments, true);
|
||
},
|
||
|
||
clearInterval: function clearInterval(timerId) {
|
||
this.clearTimeout(timerId);
|
||
},
|
||
|
||
setImmediate: function setImmediate(callback) {
|
||
var passThruArgs = Array.prototype.slice.call(arguments, 1);
|
||
|
||
return addTimer.call(this, [callback, 0].concat(passThruArgs), false);
|
||
},
|
||
|
||
clearImmediate: function clearImmediate(timerId) {
|
||
this.clearTimeout(timerId);
|
||
},
|
||
|
||
tick: function tick(ms) {
|
||
ms = typeof ms == "number" ? ms : parseTime(ms);
|
||
var tickFrom = this.now, tickTo = this.now + ms, previous = this.now;
|
||
var timer = this.firstTimerInRange(tickFrom, tickTo);
|
||
|
||
var firstException;
|
||
while (timer && tickFrom <= tickTo) {
|
||
if (this.timeouts[timer.id]) {
|
||
tickFrom = this.now = timer.callAt;
|
||
try {
|
||
this.callTimer(timer);
|
||
} catch (e) {
|
||
firstException = firstException || e;
|
||
}
|
||
}
|
||
|
||
timer = this.firstTimerInRange(previous, tickTo);
|
||
previous = tickFrom;
|
||
}
|
||
|
||
this.now = tickTo;
|
||
|
||
if (firstException) {
|
||
throw firstException;
|
||
}
|
||
|
||
return this.now;
|
||
},
|
||
|
||
firstTimerInRange: function (from, to) {
|
||
var timer, smallest = null, originalTimer;
|
||
|
||
for (var id in this.timeouts) {
|
||
if (this.timeouts.hasOwnProperty(id)) {
|
||
if (this.timeouts[id].callAt < from || this.timeouts[id].callAt > to) {
|
||
continue;
|
||
}
|
||
|
||
if (smallest === null || this.timeouts[id].callAt < smallest) {
|
||
originalTimer = this.timeouts[id];
|
||
smallest = this.timeouts[id].callAt;
|
||
|
||
timer = {
|
||
func: this.timeouts[id].func,
|
||
callAt: this.timeouts[id].callAt,
|
||
interval: this.timeouts[id].interval,
|
||
id: this.timeouts[id].id,
|
||
invokeArgs: this.timeouts[id].invokeArgs
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|
||
return timer || null;
|
||
},
|
||
|
||
callTimer: function (timer) {
|
||
if (typeof timer.interval == "number") {
|
||
this.timeouts[timer.id].callAt += timer.interval;
|
||
} else {
|
||
delete this.timeouts[timer.id];
|
||
}
|
||
|
||
try {
|
||
if (typeof timer.func == "function") {
|
||
timer.func.apply(null, timer.invokeArgs);
|
||
} else {
|
||
eval(timer.func);
|
||
}
|
||
} catch (e) {
|
||
var exception = e;
|
||
}
|
||
|
||
if (!this.timeouts[timer.id]) {
|
||
if (exception) {
|
||
throw exception;
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (exception) {
|
||
throw exception;
|
||
}
|
||
},
|
||
|
||
reset: function reset() {
|
||
this.timeouts = {};
|
||
},
|
||
|
||
Date: (function () {
|
||
var NativeDate = Date;
|
||
|
||
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 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;
|
||
}
|
||
|
||
var methods = ["Date", "setTimeout", "setInterval",
|
||
"clearTimeout", "clearInterval"];
|
||
|
||
if (typeof global.setImmediate !== "undefined") {
|
||
methods.push("setImmediate");
|
||
}
|
||
|
||
if (typeof global.clearImmediate !== "undefined") {
|
||
methods.push("clearImmediate");
|
||
}
|
||
|
||
function restore() {
|
||
var method;
|
||
|
||
for (var i = 0, l = this.methods.length; i < l; i++) {
|
||
method = this.methods[i];
|
||
|
||
if (global[method].hadOwnProperty) {
|
||
global[method] = this["_" + method];
|
||
} else {
|
||
try {
|
||
delete global[method];
|
||
} catch (e) {}
|
||
}
|
||
}
|
||
|
||
// Prevent multiple executions which will completely remove these props
|
||
this.methods = [];
|
||
}
|
||
|
||
function stubGlobal(method, clock) {
|
||
clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(global, method);
|
||
clock["_" + method] = global[method];
|
||
|
||
if (method == "Date") {
|
||
var date = mirrorDateProperties(clock[method], global[method]);
|
||
global[method] = date;
|
||
} else {
|
||
global[method] = function () {
|
||
return clock[method].apply(clock, arguments);
|
||
};
|
||
|
||
for (var prop in clock[method]) {
|
||
if (clock[method].hasOwnProperty(prop)) {
|
||
global[method][prop] = clock[method][prop];
|
||
}
|
||
}
|
||
}
|
||
|
||
global[method].clock = clock;
|
||
}
|
||
|
||
sinon.useFakeTimers = function useFakeTimers(now) {
|
||
var clock = sinon.clock.create(now);
|
||
clock.restore = restore;
|
||
clock.methods = Array.prototype.slice.call(arguments,
|
||
typeof now == "number" ? 1 : 0);
|
||
|
||
if (clock.methods.length === 0) {
|
||
clock.methods = methods;
|
||
}
|
||
|
||
for (var i = 0, l = clock.methods.length; i < l; i++) {
|
||
stubGlobal(clock.methods[i], clock);
|
||
}
|
||
|
||
return clock;
|
||
};
|
||
}(typeof global != "undefined" && typeof global !== "function" ? global : this));
|
||
|
||
sinon.timers = {
|
||
setTimeout: setTimeout,
|
||
clearTimeout: clearTimeout,
|
||
setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
|
||
clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
|
||
setInterval: setInterval,
|
||
clearInterval: clearInterval,
|
||
Date: Date
|
||
};
|
||
|
||
if (typeof module !== 'undefined' && module.exports) {
|
||
module.exports = sinon;
|
||
}
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{}],62:[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
|
||
};
|
||
|
||
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 i, l, pieces = [];
|
||
for (i = 0, l = array.length; i < l; ++i) {
|
||
pieces.push(ascii(this, array[i], processed));
|
||
}
|
||
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, l;
|
||
|
||
for (i = 0, l = properties.length; 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, l = indent; i < l; ++i) { is += " "; }
|
||
|
||
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":63}],63:[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 (getClass(object) === "Array" && getClass(matcher) === "Array") {
|
||
return arrayContains(object, matcher);
|
||
}
|
||
|
||
if (matcher && typeof matcher === "object") {
|
||
var prop;
|
||
for (prop in matcher) {
|
||
var value = object[prop];
|
||
if (typeof value === "undefined" &&
|
||
typeof object.getAttribute === "function") {
|
||
value = object.getAttribute(prop);
|
||
}
|
||
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
|
||
};
|
||
});
|
||
|
||
},{}],64:[function(require,module,exports){
|
||
// Underscore.js 1.6.0
|
||
// http://underscorejs.org
|
||
// (c) 2009-2014 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._;
|
||
|
||
// Establish the object that gets returned to break out of a loop iteration.
|
||
var breaker = {};
|
||
|
||
// 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,
|
||
concat = ArrayProto.concat,
|
||
toString = ObjProto.toString,
|
||
hasOwnProperty = ObjProto.hasOwnProperty;
|
||
|
||
// All **ECMAScript 5** native function implementations that we hope to use
|
||
// are declared here.
|
||
var
|
||
nativeForEach = ArrayProto.forEach,
|
||
nativeMap = ArrayProto.map,
|
||
nativeReduce = ArrayProto.reduce,
|
||
nativeReduceRight = ArrayProto.reduceRight,
|
||
nativeFilter = ArrayProto.filter,
|
||
nativeEvery = ArrayProto.every,
|
||
nativeSome = ArrayProto.some,
|
||
nativeIndexOf = ArrayProto.indexOf,
|
||
nativeLastIndexOf = ArrayProto.lastIndexOf,
|
||
nativeIsArray = Array.isArray,
|
||
nativeKeys = Object.keys,
|
||
nativeBind = FuncProto.bind;
|
||
|
||
// 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 via a string identifier,
|
||
// for Closure Compiler "advanced" mode.
|
||
if (typeof exports !== 'undefined') {
|
||
if (typeof module !== 'undefined' && module.exports) {
|
||
exports = module.exports = _;
|
||
}
|
||
exports._ = _;
|
||
} else {
|
||
root._ = _;
|
||
}
|
||
|
||
// Current version.
|
||
_.VERSION = '1.6.0';
|
||
|
||
// Collection Functions
|
||
// --------------------
|
||
|
||
// The cornerstone, an `each` implementation, aka `forEach`.
|
||
// Handles objects with the built-in `forEach`, arrays, and raw objects.
|
||
// Delegates to **ECMAScript 5**'s native `forEach` if available.
|
||
var each = _.each = _.forEach = function(obj, iterator, context) {
|
||
if (obj == null) return obj;
|
||
if (nativeForEach && obj.forEach === nativeForEach) {
|
||
obj.forEach(iterator, context);
|
||
} else if (obj.length === +obj.length) {
|
||
for (var i = 0, length = obj.length; i < length; i++) {
|
||
if (iterator.call(context, obj[i], i, obj) === breaker) return;
|
||
}
|
||
} else {
|
||
var keys = _.keys(obj);
|
||
for (var i = 0, length = keys.length; i < length; i++) {
|
||
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
|
||
}
|
||
}
|
||
return obj;
|
||
};
|
||
|
||
// Return the results of applying the iterator to each element.
|
||
// Delegates to **ECMAScript 5**'s native `map` if available.
|
||
_.map = _.collect = function(obj, iterator, context) {
|
||
var results = [];
|
||
if (obj == null) return results;
|
||
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
|
||
each(obj, function(value, index, list) {
|
||
results.push(iterator.call(context, value, index, list));
|
||
});
|
||
return results;
|
||
};
|
||
|
||
var reduceError = 'Reduce of empty array with no initial value';
|
||
|
||
// **Reduce** builds up a single result from a list of values, aka `inject`,
|
||
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
|
||
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
|
||
var initial = arguments.length > 2;
|
||
if (obj == null) obj = [];
|
||
if (nativeReduce && obj.reduce === nativeReduce) {
|
||
if (context) iterator = _.bind(iterator, context);
|
||
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
|
||
}
|
||
each(obj, function(value, index, list) {
|
||
if (!initial) {
|
||
memo = value;
|
||
initial = true;
|
||
} else {
|
||
memo = iterator.call(context, memo, value, index, list);
|
||
}
|
||
});
|
||
if (!initial) throw new TypeError(reduceError);
|
||
return memo;
|
||
};
|
||
|
||
// The right-associative version of reduce, also known as `foldr`.
|
||
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
|
||
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
|
||
var initial = arguments.length > 2;
|
||
if (obj == null) obj = [];
|
||
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
|
||
if (context) iterator = _.bind(iterator, context);
|
||
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
|
||
}
|
||
var length = obj.length;
|
||
if (length !== +length) {
|
||
var keys = _.keys(obj);
|
||
length = keys.length;
|
||
}
|
||
each(obj, function(value, index, list) {
|
||
index = keys ? keys[--length] : --length;
|
||
if (!initial) {
|
||
memo = obj[index];
|
||
initial = true;
|
||
} else {
|
||
memo = iterator.call(context, memo, obj[index], index, list);
|
||
}
|
||
});
|
||
if (!initial) throw new TypeError(reduceError);
|
||
return memo;
|
||
};
|
||
|
||
// Return the first value which passes a truth test. Aliased as `detect`.
|
||
_.find = _.detect = function(obj, predicate, context) {
|
||
var result;
|
||
any(obj, function(value, index, list) {
|
||
if (predicate.call(context, value, index, list)) {
|
||
result = value;
|
||
return true;
|
||
}
|
||
});
|
||
return result;
|
||
};
|
||
|
||
// Return all the elements that pass a truth test.
|
||
// Delegates to **ECMAScript 5**'s native `filter` if available.
|
||
// Aliased as `select`.
|
||
_.filter = _.select = function(obj, predicate, context) {
|
||
var results = [];
|
||
if (obj == null) return results;
|
||
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context);
|
||
each(obj, function(value, index, list) {
|
||
if (predicate.call(context, 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, function(value, index, list) {
|
||
return !predicate.call(context, value, index, list);
|
||
}, context);
|
||
};
|
||
|
||
// Determine whether all of the elements match a truth test.
|
||
// Delegates to **ECMAScript 5**'s native `every` if available.
|
||
// Aliased as `all`.
|
||
_.every = _.all = function(obj, predicate, context) {
|
||
predicate || (predicate = _.identity);
|
||
var result = true;
|
||
if (obj == null) return result;
|
||
if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context);
|
||
each(obj, function(value, index, list) {
|
||
if (!(result = result && predicate.call(context, value, index, list))) return breaker;
|
||
});
|
||
return !!result;
|
||
};
|
||
|
||
// Determine if at least one element in the object matches a truth test.
|
||
// Delegates to **ECMAScript 5**'s native `some` if available.
|
||
// Aliased as `any`.
|
||
var any = _.some = _.any = function(obj, predicate, context) {
|
||
predicate || (predicate = _.identity);
|
||
var result = false;
|
||
if (obj == null) return result;
|
||
if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context);
|
||
each(obj, function(value, index, list) {
|
||
if (result || (result = predicate.call(context, value, index, list))) return breaker;
|
||
});
|
||
return !!result;
|
||
};
|
||
|
||
// Determine if the array or object contains a given value (using `===`).
|
||
// Aliased as `include`.
|
||
_.contains = _.include = function(obj, target) {
|
||
if (obj == null) return false;
|
||
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
|
||
return any(obj, function(value) {
|
||
return value === target;
|
||
});
|
||
};
|
||
|
||
// 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) {
|
||
return (isFunc ? method : value[method]).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, _.matches(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, _.matches(attrs));
|
||
};
|
||
|
||
// Return the maximum element or (element-based computation).
|
||
// Can't optimize arrays of integers longer than 65,535 elements.
|
||
// See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797)
|
||
_.max = function(obj, iterator, context) {
|
||
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
|
||
return Math.max.apply(Math, obj);
|
||
}
|
||
var result = -Infinity, lastComputed = -Infinity;
|
||
each(obj, function(value, index, list) {
|
||
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||
if (computed > lastComputed) {
|
||
result = value;
|
||
lastComputed = computed;
|
||
}
|
||
});
|
||
return result;
|
||
};
|
||
|
||
// Return the minimum element (or element-based computation).
|
||
_.min = function(obj, iterator, context) {
|
||
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
|
||
return Math.min.apply(Math, obj);
|
||
}
|
||
var result = Infinity, lastComputed = Infinity;
|
||
each(obj, function(value, index, list) {
|
||
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||
if (computed < lastComputed) {
|
||
result = value;
|
||
lastComputed = computed;
|
||
}
|
||
});
|
||
return result;
|
||
};
|
||
|
||
// Shuffle an array, using the modern version of the
|
||
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
|
||
_.shuffle = function(obj) {
|
||
var rand;
|
||
var index = 0;
|
||
var shuffled = [];
|
||
each(obj, function(value) {
|
||
rand = _.random(index++);
|
||
shuffled[index - 1] = shuffled[rand];
|
||
shuffled[rand] = value;
|
||
});
|
||
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 (obj.length !== +obj.length) obj = _.values(obj);
|
||
return obj[_.random(obj.length - 1)];
|
||
}
|
||
return _.shuffle(obj).slice(0, Math.max(0, n));
|
||
};
|
||
|
||
// An internal function to generate lookup iterators.
|
||
var lookupIterator = function(value) {
|
||
if (value == null) return _.identity;
|
||
if (_.isFunction(value)) return value;
|
||
return _.property(value);
|
||
};
|
||
|
||
// Sort the object's values by a criterion produced by an iterator.
|
||
_.sortBy = function(obj, iterator, context) {
|
||
iterator = lookupIterator(iterator);
|
||
return _.pluck(_.map(obj, function(value, index, list) {
|
||
return {
|
||
value: value,
|
||
index: index,
|
||
criteria: iterator.call(context, 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, iterator, context) {
|
||
var result = {};
|
||
iterator = lookupIterator(iterator);
|
||
each(obj, function(value, index) {
|
||
var key = iterator.call(context, value, index, obj);
|
||
behavior(result, key, value);
|
||
});
|
||
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, key, value) {
|
||
_.has(result, key) ? result[key].push(value) : 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, key, value) {
|
||
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, key) {
|
||
_.has(result, key) ? result[key]++ : result[key] = 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, iterator, context) {
|
||
iterator = lookupIterator(iterator);
|
||
var value = iterator.call(context, obj);
|
||
var low = 0, high = array.length;
|
||
while (low < high) {
|
||
var mid = (low + high) >>> 1;
|
||
iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
|
||
}
|
||
return low;
|
||
};
|
||
|
||
// Safely create a real, live array from anything iterable.
|
||
_.toArray = function(obj) {
|
||
if (!obj) return [];
|
||
if (_.isArray(obj)) return slice.call(obj);
|
||
if (obj.length === +obj.length) return _.map(obj, _.identity);
|
||
return _.values(obj);
|
||
};
|
||
|
||
// Return the number of elements in an object.
|
||
_.size = function(obj) {
|
||
if (obj == null) return 0;
|
||
return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
|
||
};
|
||
|
||
// 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];
|
||
if (n < 0) return [];
|
||
return slice.call(array, 0, 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. The **guard** check allows it to work with
|
||
// `_.map`.
|
||
_.initial = function(array, n, guard) {
|
||
return slice.call(array, 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. The **guard** check allows it to work with `_.map`.
|
||
_.last = function(array, n, guard) {
|
||
if (array == null) return void 0;
|
||
if ((n == null) || guard) return array[array.length - 1];
|
||
return slice.call(array, Math.max(array.length - n, 0));
|
||
};
|
||
|
||
// 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. The **guard**
|
||
// check allows it to work with `_.map`.
|
||
_.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, output) {
|
||
if (shallow && _.every(input, _.isArray)) {
|
||
return concat.apply(output, input);
|
||
}
|
||
each(input, function(value) {
|
||
if (_.isArray(value) || _.isArguments(value)) {
|
||
shallow ? push.apply(output, value) : flatten(value, shallow, output);
|
||
} else {
|
||
output.push(value);
|
||
}
|
||
});
|
||
return output;
|
||
};
|
||
|
||
// Flatten out an array, either recursively (by default), or just one level.
|
||
_.flatten = function(array, shallow) {
|
||
return flatten(array, shallow, []);
|
||
};
|
||
|
||
// Return a version of the array that does not contain the specified value(s).
|
||
_.without = function(array) {
|
||
return _.difference(array, slice.call(arguments, 1));
|
||
};
|
||
|
||
// Split an array into two arrays: one whose elements all satisfy the given
|
||
// predicate, and one whose elements all do not satisfy the predicate.
|
||
_.partition = function(array, predicate) {
|
||
var pass = [], fail = [];
|
||
each(array, function(elem) {
|
||
(predicate(elem) ? pass : fail).push(elem);
|
||
});
|
||
return [pass, fail];
|
||
};
|
||
|
||
// 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, iterator, context) {
|
||
if (_.isFunction(isSorted)) {
|
||
context = iterator;
|
||
iterator = isSorted;
|
||
isSorted = false;
|
||
}
|
||
var initial = iterator ? _.map(array, iterator, context) : array;
|
||
var results = [];
|
||
var seen = [];
|
||
each(initial, function(value, index) {
|
||
if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
|
||
seen.push(value);
|
||
results.push(array[index]);
|
||
}
|
||
});
|
||
return results;
|
||
};
|
||
|
||
// Produce an array that contains the union: each distinct element from all of
|
||
// the passed-in arrays.
|
||
_.union = function() {
|
||
return _.uniq(_.flatten(arguments, true));
|
||
};
|
||
|
||
// Produce an array that contains every item shared between all the
|
||
// passed-in arrays.
|
||
_.intersection = function(array) {
|
||
var rest = slice.call(arguments, 1);
|
||
return _.filter(_.uniq(array), function(item) {
|
||
return _.every(rest, function(other) {
|
||
return _.contains(other, item);
|
||
});
|
||
});
|
||
};
|
||
|
||
// 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 = concat.apply(ArrayProto, slice.call(arguments, 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() {
|
||
var length = _.max(_.pluck(arguments, 'length').concat(0));
|
||
var results = new Array(length);
|
||
for (var i = 0; i < length; i++) {
|
||
results[i] = _.pluck(arguments, '' + i);
|
||
}
|
||
return results;
|
||
};
|
||
|
||
// 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) {
|
||
if (list == null) return {};
|
||
var result = {};
|
||
for (var i = 0, length = list.length; i < length; i++) {
|
||
if (values) {
|
||
result[list[i]] = values[i];
|
||
} else {
|
||
result[list[i][0]] = list[i][1];
|
||
}
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
|
||
// we need this function. Return the position of the first occurrence of an
|
||
// item in an array, or -1 if the item is not included in the array.
|
||
// Delegates to **ECMAScript 5**'s native `indexOf` if available.
|
||
// If the array is large and already in sort order, pass `true`
|
||
// for **isSorted** to use binary search.
|
||
_.indexOf = function(array, item, isSorted) {
|
||
if (array == null) return -1;
|
||
var i = 0, length = array.length;
|
||
if (isSorted) {
|
||
if (typeof isSorted == 'number') {
|
||
i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted);
|
||
} else {
|
||
i = _.sortedIndex(array, item);
|
||
return array[i] === item ? i : -1;
|
||
}
|
||
}
|
||
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
|
||
for (; i < length; i++) if (array[i] === item) return i;
|
||
return -1;
|
||
};
|
||
|
||
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
|
||
_.lastIndexOf = function(array, item, from) {
|
||
if (array == null) return -1;
|
||
var hasIndex = from != null;
|
||
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) {
|
||
return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item);
|
||
}
|
||
var i = (hasIndex ? from : array.length);
|
||
while (i--) if (array[i] === item) return i;
|
||
return -1;
|
||
};
|
||
|
||
// 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 (arguments.length <= 1) {
|
||
stop = start || 0;
|
||
start = 0;
|
||
}
|
||
step = arguments[2] || 1;
|
||
|
||
var length = Math.max(Math.ceil((stop - start) / step), 0);
|
||
var idx = 0;
|
||
var range = new Array(length);
|
||
|
||
while(idx < length) {
|
||
range[idx++] = start;
|
||
start += step;
|
||
}
|
||
|
||
return range;
|
||
};
|
||
|
||
// Function (ahem) Functions
|
||
// ------------------
|
||
|
||
// Reusable constructor function for prototype setting.
|
||
var ctor = function(){};
|
||
|
||
// 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) {
|
||
var args, bound;
|
||
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
|
||
if (!_.isFunction(func)) throw new TypeError;
|
||
args = slice.call(arguments, 2);
|
||
return bound = function() {
|
||
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments)));
|
||
ctor.prototype = func.prototype;
|
||
var self = new ctor;
|
||
ctor.prototype = null;
|
||
var result = func.apply(self, args.concat(slice.call(arguments)));
|
||
if (Object(result) === result) return result;
|
||
return self;
|
||
};
|
||
};
|
||
|
||
// 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);
|
||
return function() {
|
||
var position = 0;
|
||
var args = boundArgs.slice();
|
||
for (var i = 0, length = args.length; i < length; i++) {
|
||
if (args[i] === _) args[i] = arguments[position++];
|
||
}
|
||
while (position < arguments.length) args.push(arguments[position++]);
|
||
return func.apply(this, args);
|
||
};
|
||
};
|
||
|
||
// 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 funcs = slice.call(arguments, 1);
|
||
if (funcs.length === 0) throw new Error('bindAll must be passed function names');
|
||
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
|
||
return obj;
|
||
};
|
||
|
||
// Memoize an expensive function by storing its results.
|
||
_.memoize = function(func, hasher) {
|
||
var memo = {};
|
||
hasher || (hasher = _.identity);
|
||
return function() {
|
||
var key = hasher.apply(this, arguments);
|
||
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
|
||
};
|
||
};
|
||
|
||
// 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 = function(func) {
|
||
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 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;
|
||
options || (options = {});
|
||
var later = function() {
|
||
previous = options.leading === false ? 0 : _.now();
|
||
timeout = null;
|
||
result = func.apply(context, args);
|
||
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) {
|
||
clearTimeout(timeout);
|
||
timeout = null;
|
||
previous = now;
|
||
result = func.apply(context, args);
|
||
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) {
|
||
timeout = setTimeout(later, wait - last);
|
||
} else {
|
||
timeout = null;
|
||
if (!immediate) {
|
||
result = func.apply(context, args);
|
||
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 a function that will be executed at most one time, no matter how
|
||
// often you call it. Useful for lazy initialization.
|
||
_.once = function(func) {
|
||
var ran = false, memo;
|
||
return function() {
|
||
if (ran) return memo;
|
||
ran = true;
|
||
memo = func.apply(this, arguments);
|
||
func = null;
|
||
return memo;
|
||
};
|
||
};
|
||
|
||
// 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 function that is the composition of a list of functions, each
|
||
// consuming the return value of the function that follows.
|
||
_.compose = function() {
|
||
var funcs = arguments;
|
||
return function() {
|
||
var args = arguments;
|
||
for (var i = funcs.length - 1; i >= 0; i--) {
|
||
args = [funcs[i].apply(this, args)];
|
||
}
|
||
return args[0];
|
||
};
|
||
};
|
||
|
||
// Returns a function that will only be executed after being called N times.
|
||
_.after = function(times, func) {
|
||
return function() {
|
||
if (--times < 1) {
|
||
return func.apply(this, arguments);
|
||
}
|
||
};
|
||
};
|
||
|
||
// Object Functions
|
||
// ----------------
|
||
|
||
// Retrieve the names of an object's 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);
|
||
return keys;
|
||
};
|
||
|
||
// Retrieve the values of an object's properties.
|
||
_.values = function(obj) {
|
||
var keys = _.keys(obj);
|
||
var length = keys.length;
|
||
var values = new Array(length);
|
||
for (var i = 0; i < length; i++) {
|
||
values[i] = obj[keys[i]];
|
||
}
|
||
return values;
|
||
};
|
||
|
||
// Convert an object into a list of `[key, value]` pairs.
|
||
_.pairs = function(obj) {
|
||
var keys = _.keys(obj);
|
||
var length = keys.length;
|
||
var pairs = new 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 = function(obj) {
|
||
each(slice.call(arguments, 1), function(source) {
|
||
if (source) {
|
||
for (var prop in source) {
|
||
obj[prop] = source[prop];
|
||
}
|
||
}
|
||
});
|
||
return obj;
|
||
};
|
||
|
||
// Return a copy of the object only containing the whitelisted properties.
|
||
_.pick = function(obj) {
|
||
var copy = {};
|
||
var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
|
||
each(keys, function(key) {
|
||
if (key in obj) copy[key] = obj[key];
|
||
});
|
||
return copy;
|
||
};
|
||
|
||
// Return a copy of the object without the blacklisted properties.
|
||
_.omit = function(obj) {
|
||
var copy = {};
|
||
var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
|
||
for (var key in obj) {
|
||
if (!_.contains(keys, key)) copy[key] = obj[key];
|
||
}
|
||
return copy;
|
||
};
|
||
|
||
// Fill in a given object with default properties.
|
||
_.defaults = function(obj) {
|
||
each(slice.call(arguments, 1), function(source) {
|
||
if (source) {
|
||
for (var prop in source) {
|
||
if (obj[prop] === void 0) obj[prop] = source[prop];
|
||
}
|
||
}
|
||
});
|
||
return obj;
|
||
};
|
||
|
||
// 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;
|
||
};
|
||
|
||
// 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, dates, and booleans are compared by value.
|
||
case '[object String]':
|
||
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
|
||
// equivalent to `new String("5")`.
|
||
return a == String(b);
|
||
case '[object Number]':
|
||
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
|
||
// other numeric values.
|
||
return a != +a ? b != +b : (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;
|
||
// RegExps are compared by their source patterns and flags.
|
||
case '[object RegExp]':
|
||
return a.source == b.source &&
|
||
a.global == b.global &&
|
||
a.multiline == b.multiline &&
|
||
a.ignoreCase == b.ignoreCase;
|
||
}
|
||
if (typeof a != 'object' || typeof b != 'object') 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`.
|
||
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;
|
||
}
|
||
// Objects with different constructors are not equivalent, but `Object`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;
|
||
}
|
||
// Add the first object to the stack of traversed objects.
|
||
aStack.push(a);
|
||
bStack.push(b);
|
||
var size = 0, result = true;
|
||
// Recursively compare objects and arrays.
|
||
if (className == '[object Array]') {
|
||
// Compare array lengths to determine if a deep comparison is necessary.
|
||
size = a.length;
|
||
result = size == b.length;
|
||
if (result) {
|
||
// Deep compare the contents, ignoring non-numeric properties.
|
||
while (size--) {
|
||
if (!(result = eq(a[size], b[size], aStack, bStack))) break;
|
||
}
|
||
}
|
||
} else {
|
||
// Deep compare objects.
|
||
for (var key in a) {
|
||
if (_.has(a, key)) {
|
||
// Count the expected number of properties.
|
||
size++;
|
||
// Deep compare each member.
|
||
if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
|
||
}
|
||
}
|
||
// Ensure that both objects contain the same number of properties.
|
||
if (result) {
|
||
for (key in b) {
|
||
if (_.has(b, key) && !(size--)) break;
|
||
}
|
||
result = !size;
|
||
}
|
||
}
|
||
// Remove the first object from the stack of traversed objects.
|
||
aStack.pop();
|
||
bStack.pop();
|
||
return result;
|
||
};
|
||
|
||
// 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 (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
|
||
for (var key in obj) if (_.has(obj, key)) return false;
|
||
return true;
|
||
};
|
||
|
||
// 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) {
|
||
return obj === Object(obj);
|
||
};
|
||
|
||
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
|
||
each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
|
||
_['is' + name] = function(obj) {
|
||
return toString.call(obj) == '[object ' + name + ']';
|
||
};
|
||
});
|
||
|
||
// Define a fallback version of the method in browsers (ahem, IE), where
|
||
// there isn't any inspectable "Arguments" type.
|
||
if (!_.isArguments(arguments)) {
|
||
_.isArguments = function(obj) {
|
||
return !!(obj && _.has(obj, 'callee'));
|
||
};
|
||
}
|
||
|
||
// Optimize `isFunction` if appropriate.
|
||
if (typeof (/./) !== 'function') {
|
||
_.isFunction = function(obj) {
|
||
return typeof obj === 'function';
|
||
};
|
||
}
|
||
|
||
// 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 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 iterators.
|
||
_.identity = function(value) {
|
||
return value;
|
||
};
|
||
|
||
_.constant = function(value) {
|
||
return function () {
|
||
return value;
|
||
};
|
||
};
|
||
|
||
_.property = function(key) {
|
||
return function(obj) {
|
||
return obj[key];
|
||
};
|
||
};
|
||
|
||
// Returns a predicate for checking whether an object has a given set of `key:value` pairs.
|
||
_.matches = function(attrs) {
|
||
return function(obj) {
|
||
if (obj === attrs) return true; //avoid comparing an object to itself.
|
||
for (var key in attrs) {
|
||
if (attrs[key] !== obj[key])
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
};
|
||
|
||
// Run a function **n** times.
|
||
_.times = function(n, iterator, context) {
|
||
var accum = Array(Math.max(0, n));
|
||
for (var i = 0; i < n; i++) accum[i] = iterator.call(context, 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 entityMap = {
|
||
escape: {
|
||
'&': '&',
|
||
'<': '<',
|
||
'>': '>',
|
||
'"': '"',
|
||
"'": '''
|
||
}
|
||
};
|
||
entityMap.unescape = _.invert(entityMap.escape);
|
||
|
||
// Regexes containing the keys and values listed immediately above.
|
||
var entityRegexes = {
|
||
escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
|
||
unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
|
||
};
|
||
|
||
// Functions for escaping and unescaping strings to/from HTML interpolation.
|
||
_.each(['escape', 'unescape'], function(method) {
|
||
_[method] = function(string) {
|
||
if (string == null) return '';
|
||
return ('' + string).replace(entityRegexes[method], function(match) {
|
||
return entityMap[method][match];
|
||
});
|
||
};
|
||
});
|
||
|
||
// 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) {
|
||
if (object == null) return void 0;
|
||
var value = object[property];
|
||
return _.isFunction(value) ? value.call(object) : value;
|
||
};
|
||
|
||
// 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.call(this, func.apply(_, args));
|
||
};
|
||
});
|
||
};
|
||
|
||
// 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',
|
||
'\t': 't',
|
||
'\u2028': 'u2028',
|
||
'\u2029': 'u2029'
|
||
};
|
||
|
||
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
|
||
|
||
// JavaScript micro-templating, similar to John Resig's implementation.
|
||
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
||
// and correctly escapes quotes within interpolated code.
|
||
_.template = function(text, data, settings) {
|
||
var render;
|
||
settings = _.defaults({}, settings, _.templateSettings);
|
||
|
||
// Combine delimiters into one regular expression via alternation.
|
||
var matcher = new 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, function(match) { return '\\' + escapes[match]; });
|
||
|
||
if (escape) {
|
||
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
|
||
}
|
||
if (interpolate) {
|
||
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
|
||
}
|
||
if (evaluate) {
|
||
source += "';\n" + evaluate + "\n__p+='";
|
||
}
|
||
index = offset + match.length;
|
||
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 {
|
||
render = new Function(settings.variable || 'obj', '_', source);
|
||
} catch (e) {
|
||
e.source = source;
|
||
throw e;
|
||
}
|
||
|
||
if (data) return render(data, _);
|
||
var template = function(data) {
|
||
return render.call(this, data, _);
|
||
};
|
||
|
||
// Provide the compiled function source as a convenience for precompilation.
|
||
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
|
||
|
||
return template;
|
||
};
|
||
|
||
// Add a "chain" function, which will delegate to the wrapper.
|
||
_.chain = function(obj) {
|
||
return _(obj).chain();
|
||
};
|
||
|
||
// 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(obj) {
|
||
return this._chain ? _(obj).chain() : obj;
|
||
};
|
||
|
||
// 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.call(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.call(this, method.apply(this._wrapped, arguments));
|
||
};
|
||
});
|
||
|
||
_.extend(_.prototype, {
|
||
|
||
// Start chaining a wrapped Underscore object.
|
||
chain: function() {
|
||
this._chain = true;
|
||
return this;
|
||
},
|
||
|
||
// Extracts the result from a wrapped and chained object.
|
||
value: 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_uninitialized, Test, Yatta, chai, expect, should, sinon, sinonChai, _,
|
||
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||
|
||
chai = require('chai');
|
||
|
||
expect = chai.expect;
|
||
|
||
should = chai.should();
|
||
|
||
sinon = require('sinon');
|
||
|
||
sinonChai = require('sinon-chai');
|
||
|
||
_ = require("underscore");
|
||
|
||
chai.use(sinonChai);
|
||
|
||
Yatta = require("../lib/Frameworks/JsonYatta");
|
||
|
||
Connector_uninitialized = require("../lib/Connectors/TestConnector");
|
||
|
||
Test = (function() {
|
||
function Test(name_suffix) {
|
||
this.name_suffix = name_suffix != null ? name_suffix : "";
|
||
this.applyRandomOp = __bind(this.applyRandomOp, this);
|
||
this.generateRandomOp = __bind(this.generateRandomOp, this);
|
||
this.generateDeleteOp = __bind(this.generateDeleteOp, this);
|
||
this.generateReplaceOp = __bind(this.generateReplaceOp, this);
|
||
this.generateInsertOp = __bind(this.generateInsertOp, this);
|
||
this.number_of_test_cases_multiplier = 1;
|
||
this.repeat_this = 1 * this.number_of_test_cases_multiplier;
|
||
this.doSomething_amount = 1000 * this.number_of_test_cases_multiplier;
|
||
this.number_of_engines = 2 + this.number_of_test_cases_multiplier - 1;
|
||
this.time = 0;
|
||
this.ops = 0;
|
||
this.time_now = 0;
|
||
this.debug = true;
|
||
this.reinitialize();
|
||
}
|
||
|
||
Test.prototype.reinitialize = function() {
|
||
var i, _i, _ref;
|
||
this.users = [];
|
||
this.Connector = Connector_uninitialized(this.users);
|
||
for (i = _i = 0, _ref = this.number_of_engines; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
|
||
this.users.push(new Yatta(i + this.name_suffix, this.Connector));
|
||
}
|
||
this.users[0].val('name', "i");
|
||
return this.flushAll();
|
||
};
|
||
|
||
Test.prototype.getSomeUser = function() {
|
||
var i;
|
||
i = _.random(0, this.users.length - 1);
|
||
return this.users[i];
|
||
};
|
||
|
||
Test.prototype.getRandomText = function() {
|
||
var chars, length, nextchar, text;
|
||
chars = "abcdefghijklmnopqrstuvwxyz";
|
||
length = _.random(0, 10);
|
||
nextchar = chars[_.random(0, chars.length - 1)];
|
||
text = "";
|
||
_(length).times(function() {
|
||
return text += nextchar;
|
||
});
|
||
return text;
|
||
};
|
||
|
||
Test.prototype.generateInsertOp = function(user_num) {
|
||
var pos;
|
||
pos = _.random(0, this.users[user_num].val('name').val().length - 1);
|
||
this.users[user_num].val('name').insertText(pos, this.getRandomText());
|
||
return null;
|
||
};
|
||
|
||
Test.prototype.generateReplaceOp = function(user_num) {
|
||
this.users[user_num].val('name').replaceText(this.getRandomText());
|
||
return null;
|
||
};
|
||
|
||
Test.prototype.generateDeleteOp = function(user_num) {
|
||
var length, ops1, pos;
|
||
if (this.users[user_num].val('name').val().length > 0) {
|
||
pos = _.random(0, this.users[user_num].val('name').val().length - 1);
|
||
length = _.random(0, this.users[user_num].val('name').val().length - pos);
|
||
ops1 = this.users[user_num].val('name').deleteText(pos, length);
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
Test.prototype.generateRandomOp = function(user_num) {
|
||
var i, op, op_gen;
|
||
op_gen = [this.generateInsertOp, this.generateDeleteOp, this.generateReplaceOp];
|
||
i = _.random(op_gen.length - 1);
|
||
return op = op_gen[i](user_num);
|
||
};
|
||
|
||
Test.prototype.applyRandomOp = function(user_num) {
|
||
var user;
|
||
user = this.users[user_num];
|
||
return user.getConnector().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() {
|
||
var user, user_number, _i, _len, _ref, _results;
|
||
_ref = this.users;
|
||
_results = [];
|
||
for (user_number = _i = 0, _len = _ref.length; _i < _len; user_number = ++_i) {
|
||
user = _ref[user_number];
|
||
_results.push(user.getConnector().flushAll());
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
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();
|
||
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].getConnector().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 + ": Every collaborator (" + this.users.length + ") applied " + number_of_created_operations + " 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 (this.users[i].val('name').val() !== this.users[i + 1].val('name').val()) {
|
||
printOpsInExecutionOrder = (function(_this) {
|
||
return function(otnumber, otherotnumber) {
|
||
var j, o, ops, s, _k, _l, _len, _len1;
|
||
ops = _.filter(_this.users[otnumber].getConnector().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("");
|
||
}
|
||
}
|
||
if (this.users[i].val('name').val() !== this.users[i + 1].val('name').val()) {
|
||
console.log("found error");
|
||
}
|
||
_results.push(expect(this.users[i].val('name').val()).to.equal(this.users[i + 1].val('name').val()));
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
Test.prototype.run = function() {
|
||
var i, times, _i, _j, _ref, _ref1, _results;
|
||
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 = this.doSomething_amount; 1 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 1 <= _ref1 ? ++_j : --_j) {
|
||
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() {
|
||
var user;
|
||
user = new Yatta('testuser', Connector_uninitialized([]));
|
||
user.engine.applyOps(this.users[0].HB._encode());
|
||
return expect(user.value.name.val()).to.equal(this.users[0].value.name.val());
|
||
};
|
||
|
||
return Test;
|
||
|
||
})();
|
||
|
||
describe("JsonYatta", function() {
|
||
beforeEach(function(done) {
|
||
this.timeout(50000);
|
||
this.yTest = new Test();
|
||
this.users = this.yTest.users;
|
||
this.test_user = new Yatta(0, Connector_uninitialized([]));
|
||
return done();
|
||
});
|
||
it("has a JsonWrapper", function() {
|
||
var w, y;
|
||
y = this.yTest.getSomeUser().root_element;
|
||
y.val('x', "dtrn", 'immutable');
|
||
y.val('set', {
|
||
x: "x"
|
||
}, 'immutable');
|
||
w = y.value;
|
||
w.x;
|
||
w.set = {
|
||
y: ""
|
||
};
|
||
w.x;
|
||
w.set;
|
||
w.set.x;
|
||
expect(w.x).to.equal("dtrn");
|
||
return expect(w.set.x).to.equal("x");
|
||
});
|
||
it("handles double-late-join", function() {
|
||
var ops1, ops2, test, u1, u2;
|
||
test = new Test("double");
|
||
test.run();
|
||
this.yTest.run();
|
||
u1 = test.users[0];
|
||
u2 = this.yTest.users[1];
|
||
ops1 = u1.HB._encode();
|
||
ops2 = u2.HB._encode();
|
||
u1.engine.applyOps(ops2);
|
||
u2.engine.applyOps(ops1);
|
||
return expect(u2.value.name.val()).to.equal(u2.value.name.val());
|
||
});
|
||
it("can handle creaton of complex json", function() {
|
||
this.yTest.getSomeUser().val('x', {
|
||
'a': 'b'
|
||
});
|
||
this.yTest.getSomeUser().val('a', {
|
||
'a': {
|
||
q: "dtrndtrtdrntdrnrtdnrtdnrtdnrtdnrdnrdt"
|
||
}
|
||
});
|
||
this.yTest.getSomeUser().val('b', {
|
||
'a': {}
|
||
});
|
||
this.yTest.getSomeUser().val('c', {
|
||
'a': 'c'
|
||
});
|
||
this.yTest.getSomeUser().val('c', {
|
||
'a': 'b'
|
||
});
|
||
this.yTest.compareAll();
|
||
this.yTest.getSomeUser().value.a.a.q.insertText(0, 'AAA');
|
||
this.yTest.compareAll();
|
||
return expect(this.yTest.getSomeUser().value.a.a.q.val()).to.equal("AAAdtrndtrtdrntdrnrtdnrtdnrtdnrtdnrdnrdt");
|
||
});
|
||
it("handles some immutable tests", function() {
|
||
this.yTest.getSomeUser().val('string', "text", "immutable");
|
||
this.yTest.getSomeUser().val('number', 4, "immutable");
|
||
this.yTest.getSomeUser().val('object', {
|
||
q: "rr"
|
||
}, "immutable");
|
||
this.yTest.compareAll();
|
||
expect(this.yTest.getSomeUser().val('string')).to.equal("text");
|
||
expect(this.yTest.getSomeUser().val('number')).to.equal(4);
|
||
return expect(this.yTest.getSomeUser().val('object').val('q')).to.equal("rr");
|
||
});
|
||
it("can handle many engines, many operations, concurrently (random)", function() {
|
||
return this.yTest.run();
|
||
});
|
||
return it("converges t1", function() {
|
||
var op0, op1, op2, op3, op4, op5, op6, op7, op8, ops;
|
||
op0 = {
|
||
"type": "Delimiter",
|
||
"uid": {
|
||
"creator": 0,
|
||
"op_number": 0
|
||
},
|
||
"next": {
|
||
"creator": 0,
|
||
"op_number": 1
|
||
}
|
||
};
|
||
op1 = {
|
||
"type": "Delimiter",
|
||
"uid": {
|
||
"creator": 0,
|
||
"op_number": 1
|
||
},
|
||
"prev": {
|
||
"creator": 0,
|
||
"op_number": 0
|
||
}
|
||
};
|
||
op2 = {
|
||
"type": "Word",
|
||
"uid": {
|
||
"creator": 0,
|
||
"op_number": 2
|
||
},
|
||
"beginning": {
|
||
"creator": 0,
|
||
"op_number": 0
|
||
},
|
||
"end": {
|
||
"creator": 0,
|
||
"op_number": 1
|
||
}
|
||
};
|
||
op3 = {
|
||
"type": "AddName",
|
||
"uid": {
|
||
"creator": 0,
|
||
"op_number": 3
|
||
},
|
||
"map_manager": {
|
||
"creator": "_",
|
||
"op_number": "_"
|
||
},
|
||
"name": "name"
|
||
};
|
||
op4 = {
|
||
"type": "Replaceable",
|
||
"content": {
|
||
"creator": 0,
|
||
"op_number": 2
|
||
},
|
||
"ReplaceManager": {
|
||
"creator": "_",
|
||
"op_number": "___RM_name"
|
||
},
|
||
"prev": {
|
||
"creator": "_",
|
||
"op_number": "___RM_name_beginning"
|
||
},
|
||
"next": {
|
||
"creator": "_",
|
||
"op_number": "___RM_name_end"
|
||
},
|
||
"uid": {
|
||
"creator": 0,
|
||
"op_number": 4
|
||
}
|
||
};
|
||
op5 = {
|
||
"type": "TextInsert",
|
||
"content": "u",
|
||
"uid": {
|
||
"creator": 1,
|
||
"op_number": 2
|
||
},
|
||
"prev": {
|
||
"creator": 1,
|
||
"op_number": 0
|
||
},
|
||
"next": {
|
||
"creator": 1,
|
||
"op_number": 1
|
||
}
|
||
};
|
||
op6 = {
|
||
"type": "TextInsert",
|
||
"content": "w",
|
||
"uid": {
|
||
"creator": 2,
|
||
"op_number": 0
|
||
},
|
||
"prev": {
|
||
"creator": 0,
|
||
"op_number": 0
|
||
},
|
||
"next": {
|
||
"creator": 0,
|
||
"op_number": 1
|
||
}
|
||
};
|
||
op7 = {
|
||
"type": "TextInsert",
|
||
"content": "d",
|
||
"uid": {
|
||
"creator": 1,
|
||
"op_number": 0
|
||
},
|
||
"prev": {
|
||
"creator": 0,
|
||
"op_number": 0
|
||
},
|
||
"next": {
|
||
"creator": 2,
|
||
"op_number": 0
|
||
}
|
||
};
|
||
op8 = {
|
||
"type": "TextInsert",
|
||
"content": "a",
|
||
"uid": {
|
||
"creator": 1,
|
||
"op_number": 1
|
||
},
|
||
"prev": {
|
||
"creator": 1,
|
||
"op_number": 0
|
||
},
|
||
"next": {
|
||
"creator": 2,
|
||
"op_number": 0
|
||
}
|
||
};
|
||
ops = [op0, op1, op2, op3, op4, op5, op6, op7, op8];
|
||
this.test_user.engine.applyOps(ops);
|
||
return expect(this.test_user.val('name').val()).to.equal("duaw");
|
||
});
|
||
});
|
||
|
||
|
||
},{"../lib/Connectors/TestConnector":1,"../lib/Frameworks/JsonYatta":3,"chai":9,"sinon":49,"sinon-chai":48,"underscore":64}]},{},[65])
|
||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL0Nvbm5lY3RvcnMvVGVzdENvbm5lY3Rvci5jb2ZmZWUiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL0VuZ2luZS5jb2ZmZWUiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL0ZyYW1ld29ya3MvSnNvbllhdHRhLmNvZmZlZSIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9saWIvSGlzdG9yeUJ1ZmZlci5jb2ZmZWUiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL1R5cGVzL0Jhc2ljVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9Kc29uVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9TdHJ1Y3R1cmVkVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9UZXh0VHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL2luZGV4LmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpLmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL2Fzc2VydGlvbi5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS9jb25maWcuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvY29yZS9hc3NlcnRpb25zLmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL2ludGVyZmFjZS9hc3NlcnQuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvaW50ZXJmYWNlL2V4cGVjdC5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS9pbnRlcmZhY2Uvc2hvdWxkLmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2FkZENoYWluYWJsZU1ldGhvZC5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9hZGRNZXRob2QuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvYWRkUHJvcGVydHkuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvZmxhZy5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9nZXRBY3R1YWwuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvZ2V0RW51bWVyYWJsZVByb3BlcnRpZXMuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvZ2V0TWVzc2FnZS5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9nZXROYW1lLmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2dldFBhdGhWYWx1ZS5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9nZXRQcm9wZXJ0aWVzLmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2luZGV4LmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2luc3BlY3QuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvb2JqRGlzcGxheS5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9vdmVyd3JpdGVDaGFpbmFibGVNZXRob2QuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvb3ZlcndyaXRlTWV0aG9kLmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL292ZXJ3cml0ZVByb3BlcnR5LmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL3Rlc3QuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvdHJhbnNmZXJGbGFncy5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy90eXBlLmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL25vZGVfbW9kdWxlcy9hc3NlcnRpb24tZXJyb3IvaW5kZXguanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2NoYWkvbm9kZV9tb2R1bGVzL2RlZXAtZXFsL2luZGV4LmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL25vZGVfbW9kdWxlcy9kZWVwLWVxbC9saWIvZXFsLmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9jaGFpL25vZGVfbW9kdWxlcy9kZWVwLWVxbC9ub2RlX21vZHVsZXMvdHlwZS1kZXRlY3QvaW5kZXguanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2NoYWkvbm9kZV9tb2R1bGVzL2RlZXAtZXFsL25vZGVfbW9kdWxlcy90eXBlLWRldGVjdC9saWIvdHlwZS5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9idWZmZXIvaW5kZXguanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnVmZmVyL25vZGVfbW9kdWxlcy9iYXNlNjQtanMvbGliL2I2NC5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9idWZmZXIvbm9kZV9tb2R1bGVzL2llZWU3NTQvaW5kZXguanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvaW5oZXJpdHMvaW5oZXJpdHNfYnJvd3Nlci5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvdXRpbC9zdXBwb3J0L2lzQnVmZmVyQnJvd3Nlci5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3V0aWwuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL3Npbm9uLWNoYWkvbGliL3Npbm9uLWNoYWkuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL2Fzc2VydC5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL2JlaGF2aW9yLmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vY2FsbC5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL2NvbGxlY3Rpb24uanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi9tYXRjaC5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL21vY2suanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi9zYW5kYm94LmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vc3B5LmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vc3R1Yi5qcyIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL3Rlc3QuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi90ZXN0X2Nhc2UuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi91dGlsL2Zha2VfdGltZXJzLmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9zaW5vbi9ub2RlX21vZHVsZXMvZm9ybWF0aW8vbGliL2Zvcm1hdGlvLmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy9zaW5vbi9ub2RlX21vZHVsZXMvZm9ybWF0aW8vbm9kZV9tb2R1bGVzL3NhbXNhbS9saWIvc2Ftc2FtLmpzIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy91bmRlcnNjb3JlL3VuZGVyc2NvcmUuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvdGVzdC9ZYXR0YV90ZXN0LmNvZmZlZSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0NBLElBQUEsQ0FBQTs7QUFBQSxDQUFBLEdBQUksT0FBQSxDQUFRLFlBQVIsQ0FBSixDQUFBOztBQUFBLE1BRU0sQ0FBQyxPQUFQLEdBQWlCLFNBQUMsU0FBRCxHQUFBO0FBS2YsTUFBQSxhQUFB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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNseUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hpQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9HQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3REQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5R0E7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDalFBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEhBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNWtCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9YQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN01BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25jQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDamFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNaQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaFlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvekNBLElBQUEsK0VBQUE7RUFBQSxrRkFBQTs7QUFBQSxJQUFBLEdBQVksT0FBQSxDQUFRLE1BQVIsQ0FBWixDQUFBOztBQUFBLE1BQ0EsR0FBWSxJQUFJLENBQUMsTUFEakIsQ0FBQTs7QUFBQSxNQUVBLEdBQVksSUFBSSxDQUFDLE1BQUwsQ0FBQSxDQUZaLENBQUE7O0FBQUEsS0FHQSxHQUFZLE9BQUEsQ0FBUSxPQUFSLENBSFosQ0FBQTs7QUFBQSxTQUlBLEdBQVksT0FBQSxDQUFRLFlBQVIsQ0FKWixDQUFBOztBQUFBLENBS0EsR0FBWSxPQUFBLENBQVEsWUFBUixDQUxaLENBQUE7O0FBQUEsSUFPSSxDQUFDLEdB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YSxXQUFBLEVBQVksQ0FBekI7T0FBL0c7S0FQTixDQUFBO0FBQUEsSUFRQSxHQUFBLEdBQU07QUFBQSxNQUFDLE1BQUEsRUFBTyxZQUFSO0FBQUEsTUFBcUIsU0FBQSxFQUFVLEdBQS9CO0FBQUEsTUFBbUMsS0FBQSxFQUFNO0FBQUEsUUFBQyxTQUFBLEVBQVUsQ0FBWDtBQUFBLFFBQWEsV0FBQSxFQUFZLENBQXpCO09BQXpDO0FBQUEsTUFBcUUsTUFBQSxFQUFPO0FBQUEsUUFBQyxTQUFBLEVBQVUsQ0FBWDtBQUFBLFFBQWEsV0FBQSxFQUFZLENBQXpCO09BQTVFO0FBQUEsTUFBd0csTUFBQSxFQUFPO0FBQUEsUUFBQyxTQUFBLEVBQVUsQ0FBWDtBQUFBLFFBQWEsV0FBQSxFQUFZLENBQXpCO09BQS9HO0tBUk4sQ0FBQTtBQUFBLElBVUEsR0FBQSxHQUFNLENBQUMsR0FBRCxFQUFNLEdBQU4sRUFBVyxHQUFYLEVBQWdCLEdBQWhCLEVBQXFCLEdBQXJCLEVBQTBCLEdBQTFCLEVBQStCLEdBQS9CLEVBQW9DLEdBQXBDLEVBQXlDLEdBQXpDLENBVk4sQ0FBQTtBQUFBLElBV0EsSUFBQyxDQUFBLFNBQVMsQ0FBQyxNQUFNLENBQUMsUUFBbEIsQ0FBMkIsR0FBM0IsQ0FYQSxDQUFBO1dBWUEsTUFBQSxDQUFPLElBQUMsQ0FBQSxTQUFTLENBQUMsR0FBWCxDQUFlLE1BQWYsQ0FBc0IsQ0FBQyxHQUF2QixDQUFBLENBQVAsQ0FBb0MsQ0FBQyxFQUFFLENBQUMsS0FBeEMsQ0FBOEMsTUFBOUMsRUFiaUI7RUFBQSxDQUFuQixFQTVEb0I7QUFBQSxDQUF0QixDQXBKQSxDQUFBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3Rocm93IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIil9dmFyIGY9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGYuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sZixmLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIlxuXyA9IHJlcXVpcmUgXCJ1bmRlcnNjb3JlXCJcblxubW9kdWxlLmV4cG9ydHMgPSAodXNlcl9saXN0KS0+XG5cbiAgI1xuICAjIEEgdHJpdmlhbCBDb25uZWN0b3IgdGhhdCBzaW11bGF0ZXMgbmV0d29yayBkZWxheS5cbiAgI1xuICBjbGFzcyBUZXN0Q29ubmVjdG9yXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge0VuZ2luZX0gZW5naW5lIFRoZSB0cmFuc2Zvcm1hdGlvbiBlbmdpbmVcbiAgICAjIEBwYXJhbSB7SGlzdG9yeUJ1ZmZlcn0gSEJcbiAgICAjIEBwYXJhbSB7QXJyYXk8RnVuY3Rpb24+fSBleGVjdXRpb25fbGlzdGVuZXIgWW91IG11c3QgZW5zdXJlIHRoYXQgd2hlbmV2ZXIgYW4gb3BlcmF0aW9uIGlzIGV4ZWN1dGVkLCBldmVyeSBmdW5jdGlvbiBpbiB0aGlzIEFycmF5IGlzIGNhbGxlZC5cbiAgICAjIEBwYXJhbSB7WWF0dGF9IHlhdHRhIFRoZSBZYXR0YSBmcmFtZXdvcmsuXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAoQGVuZ2luZSwgQEhCLCBAZXhlY3V0aW9uX2xpc3RlbmVyKS0+XG4gICAgICBzZW5kXyA9IChvKT0+XG4gICAgICAgIEBzZW5kIG9cbiAgICAgIEBleGVjdXRpb25fbGlzdGVuZXIucHVzaCBzZW5kX1xuXG4gICAgICBAYXBwbGllZF9vcGVyYXRpb25zID0gW11cbiAgICAgIGFwcGxpZWRPcGVyYXRpb25zTGlzdGVuZXIgPSAobyk9PlxuICAgICAgICBAYXBwbGllZF9vcGVyYXRpb25zLnB1c2ggb1xuICAgICAgQGV4ZWN1dGlvbl9saXN0ZW5lci5wdXNoIGFwcGxpZWRPcGVyYXRpb25zTGlzdGVuZXJcbiAgICAgIGlmIG5vdCAodXNlcl9saXN0Py5sZW5ndGggaXMgMClcbiAgICAgICAgQGVuZ2luZS5hcHBseU9wcyB1c2VyX2xpc3RbMF0uZ2V0SGlzdG9yeUJ1ZmZlcigpLl9lbmNvZGUoKVxuXG4gICAgICBAdW5leGVjdXRlZCA9IHt9XG5cbiAgICAjXG4gICAgIyBUaGlzIGVuZ2luZSBhcHBsaWVkIG9wZXJhdGlvbnMgaW4gYSBzcGVjaWZpYyBvcmRlci5cbiAgICAjIEdldCB0aGUgb3BzIGluIHRoZSByaWdodCBvcmRlci5cbiAgICAjXG4gICAgZ2V0T3BzSW5FeGVjdXRpb25PcmRlcjogKCktPlxuICAgICAgQGFwcGxpZWRfb3BlcmF0aW9uc1xuXG4gICAgI1xuICAgICMgVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2hlbmV2ZXIgYW4gb3BlcmF0aW9uIHdhcyBleGVjdXRlZC5cbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBvIFRoZSBvcGVyYXRpb24gdGhhdCB3YXMgZXhlY3V0ZWQuXG4gICAgI1xuICAgIHNlbmQ6IChvKS0+XG4gICAgICBpZiAoby51aWQuY3JlYXRvciBpcyBASEIuZ2V0VXNlcklkKCkpIGFuZCAodHlwZW9mIG8udWlkLm9wX251bWJlciBpc250IFwic3RyaW5nXCIpXG4gICAgICAgIGZvciB1c2VyIGluIHVzZXJfbGlzdFxuICAgICAgICAgIGlmIHVzZXIuZ2V0VXNlcklkKCkgaXNudCBASEIuZ2V0VXNlcklkKClcbiAgICAgICAgICAgIHVzZXIuZ2V0Q29ubmVjdG9yKCkucmVjZWl2ZShvKVxuXG4gICAgI1xuICAgICMgVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2hlbmV2ZXIgYW4gb3BlcmF0aW9uIHdhcyByZWNlaXZlZCBmcm9tIGFub3RoZXIgcGVlci5cbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBvIFRoZSBvcGVyYXRpb24gdGhhdCB3YXMgcmVjZWl2ZWQuXG4gICAgI1xuICAgIHJlY2VpdmU6IChvKS0+XG4gICAgICBAdW5leGVjdXRlZFtvLnVpZC5jcmVhdG9yXSA/PSBbXVxuICAgICAgQHVuZXhlY3V0ZWRbby51aWQuY3JlYXRvcl0ucHVzaCBvXG5cbiAgICAjXG4gICAgIyBGbHVzaCBvbmUgb3BlcmF0aW9uIGZyb20gdGhlIGxpbmUgb2YgYSBzcGVjaWZpYyB1c2VyLlxuICAgICNcbiAgICBmbHVzaE9uZTogKHVzZXIpLT5cbiAgICAgIGlmIEB1bmV4ZWN1dGVkW3VzZXJdPy5sZW5ndGggPiAwXG4gICAgICAgIEBlbmdpbmUuYXBwbHlPcCBAdW5leGVjdXRlZFt1c2VyXS5zaGlmdCgpXG5cbiAgICAjXG4gICAgIyBGbHVzaCBvbmUgb3BlcmF0aW9uIG9uIGEgcmFuZG9tIGxpbmUuXG4gICAgI1xuICAgIGZsdXNoT25lUmFuZG9tOiAoKS0+XG4gICAgICBAZmx1c2hPbmUgKF8ucmFuZG9tIDAsICh1c2VyX2xpc3QubGVuZ3RoLTEpKVxuXG4gICAgI1xuICAgICMgRmx1c2ggYWxsIG9wZXJhdGlvbnMgb24gZXZlcnkgbGluZS5cbiAgICAjXG4gICAgZmx1c2hBbGw6ICgpLT5cbiAgICAgIGZvciBuLG9wcyBvZiBAdW5leGVjdXRlZFxuICAgICAgICBAZW5naW5lLmFwcGx5T3BzIG9wc1xuICAgICAgQHVuZXhlY3V0ZWQgPSB7fVxuXG4iLCJcclxuI1xyXG4jIFRoZSBFbmdpbmUgaGFuZGxlcyBob3cgYW5kIGluIHdoaWNoIG9yZGVyIHRvIGV4ZWN1dGUgb3BlcmF0aW9ucyBhbmQgYWRkIG9wZXJhdGlvbnMgdG8gdGhlIEhpc3RvcnlCdWZmZXIuXHJcbiNcclxuY2xhc3MgRW5naW5lXHJcblxyXG4gICNcclxuICAjIEBwYXJhbSB7SGlzdG9yeUJ1ZmZlcn0gSEJcclxuICAjIEBwYXJhbSB7QXJyYXl9IHBhcnNlciBEZWZpbmVzIGhvdyB0byBwYXJzZSBlbmNvZGVkIG1lc3NhZ2VzLlxyXG4gICNcclxuICBjb25zdHJ1Y3RvcjogKEBIQiwgQHBhcnNlciktPlxyXG4gICAgQHVucHJvY2Vzc2VkX29wcyA9IFtdXHJcblxyXG4gICNcclxuICAjIFBhcnNlcyBhbiBvcGVyYXRpbyBmcm9tIHRoZSBqc29uIGZvcm1hdC4gSXQgdXNlcyB0aGUgc3BlY2lmaWVkIHBhcnNlciBpbiB5b3VyIE9wZXJhdGlvblR5cGUgbW9kdWxlLlxyXG4gICNcclxuICBwYXJzZU9wZXJhdGlvbjogKGpzb24pLT5cclxuICAgIHR5cGVQYXJzZXIgPSBAcGFyc2VyW2pzb24udHlwZV1cclxuICAgIGlmIHR5cGVQYXJzZXI/XHJcbiAgICAgIHR5cGVQYXJzZXIganNvblxyXG4gICAgZWxzZVxyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgZm9yZ290IHRvIHNwZWNpZnkgYSBwYXJzZXIgZm9yIHR5cGUgI3tqc29uLnR5cGV9LiBUaGUgbWVzc2FnZSBpcyAje0pTT04uc3RyaW5naWZ5IGpzb259LlwiXHJcblxyXG4gICNcclxuICAjIEFwcGx5IGEgc2V0IG9mIG9wZXJhdGlvbnMuIEUuZy4gdGhlIG9wZXJhdGlvbnMgeW91IHJlY2VpdmVkIGZyb20gYW5vdGhlciB1c2VycyBIQi50b0pzb24oKS5cclxuICAjIEBub3RlIFlvdSBtdXN0IG5vdCB1c2UgdGhpcyBtZXRob2Qgd2hlbiB5b3UgYWxyZWFkeSBoYXZlIG9wcyBpbiB5b3VyIEhCIVxyXG4gICNcclxuICBhcHBseU9wc0J1bmRsZTogKG9wc19qc29uKS0+XHJcbiAgICBvcHMgPSBbXVxyXG4gICAgZm9yIG8gaW4gb3BzX2pzb25cclxuICAgICAgb3BzLnB1c2ggQHBhcnNlT3BlcmF0aW9uIG9cclxuICAgIGZvciBvIGluIG9wc1xyXG4gICAgICBASEIuYWRkT3BlcmF0aW9uIG9cclxuICAgIGZvciBvIGluIG9wc1xyXG4gICAgICBpZiBub3Qgby5leGVjdXRlKClcclxuICAgICAgICBAdW5wcm9jZXNzZWRfb3BzLnB1c2ggb1xyXG4gICAgQHRyeVVucHJvY2Vzc2VkKClcclxuXHJcbiAgI1xyXG4gICMgU2FtZSBhcyBhcHBseU9wcyBidXQgb3BlcmF0aW9ucyB0aGF0IGFyZSBhbHJlYWR5IGluIHRoZSBIQiBhcmUgbm90IGFwcGxpZWQuXHJcbiAgIyBAc2VlIEVuZ2luZS5hcHBseU9wc1xyXG4gICNcclxuICBhcHBseU9wc0NoZWNrRG91YmxlOiAob3BzX2pzb24pLT5cclxuICAgIGZvciBvIGluIG9wc19qc29uXHJcbiAgICAgIGlmIG5vdCBASEIuZ2V0T3BlcmF0aW9uKG8udWlkKT9cclxuICAgICAgICBAYXBwbHlPcCBvXHJcblxyXG4gICNcclxuICAjIEFwcGx5IGEgc2V0IG9mIG9wZXJhdGlvbnMuIChIZWxwZXIgZm9yIHVzaW5nIGFwcGx5T3Agb24gQXJyYXlzKVxyXG4gICMgQHNlZSBFbmdpbmUuYXBwbHlPcFxyXG4gIGFwcGx5T3BzOiAob3BzX2pzb24pLT5cclxuICAgIGZvciBvIGluIG9wc19qc29uXHJcbiAgICAgIEBhcHBseU9wIG9cclxuXHJcbiAgI1xyXG4gICMgQXBwbHkgYW4gb3BlcmF0aW9uIHRoYXQgeW91IHJlY2VpdmVkIGZyb20gYW5vdGhlciBwZWVyLlxyXG4gICNcclxuICBhcHBseU9wOiAob3BfanNvbiktPlxyXG4gICAgIyAkcGFyc2VfYW5kX2V4ZWN1dGUgd2lsbCByZXR1cm4gZmFsc2UgaWYgJG9fanNvbiB3YXMgcGFyc2VkIGFuZCBleGVjdXRlZCwgb3RoZXJ3aXNlIHRoZSBwYXJzZWQgb3BlcmFkaW9uXHJcbiAgICBvID0gQHBhcnNlT3BlcmF0aW9uIG9wX2pzb25cclxuICAgIEBIQi5hZGRUb0NvdW50ZXIgb1xyXG4gICAgIyBASEIuYWRkT3BlcmF0aW9uIG9cclxuICAgIGlmIG5vdCBvLmV4ZWN1dGUoKVxyXG4gICAgICBAdW5wcm9jZXNzZWRfb3BzLnB1c2ggb1xyXG4gICAgZWxzZVxyXG4gICAgICBASEIuYWRkT3BlcmF0aW9uIG9cclxuICAgIEB0cnlVbnByb2Nlc3NlZCgpXHJcblxyXG4gICNcclxuICAjIENhbGwgdGhpcyBtZXRob2Qgd2hlbiB5b3UgYXBwbGllZCBhIG5ldyBvcGVyYXRpb24uXHJcbiAgIyBJdCBjaGVja3MgaWYgb3BlcmF0aW9ucyB0aGF0IHdlcmUgcHJldmlvdXNseSBub3QgZXhlY3V0YWJsZSBhcmUgbm93IGV4ZWN1dGFibGUuXHJcbiAgI1xyXG4gIHRyeVVucHJvY2Vzc2VkOiAoKS0+XHJcbiAgICB3aGlsZSB0cnVlXHJcbiAgICAgIG9sZF9sZW5ndGggPSBAdW5wcm9jZXNzZWRfb3BzLmxlbmd0aFxyXG4gICAgICB1bnByb2Nlc3NlZCA9IFtdXHJcbiAgICAgIGZvciBvcCBpbiBAdW5wcm9jZXNzZWRfb3BzXHJcbiAgICAgICAgaWYgbm90IG9wLmV4ZWN1dGUoKVxyXG4gICAgICAgICAgdW5wcm9jZXNzZWQucHVzaCBvcFxyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgIEBIQi5hZGRPcGVyYXRpb24gb3BcclxuICAgICAgQHVucHJvY2Vzc2VkX29wcyA9IHVucHJvY2Vzc2VkXHJcbiAgICAgIGlmIEB1bnByb2Nlc3NlZF9vcHMubGVuZ3RoIGlzIG9sZF9sZW5ndGhcclxuICAgICAgICBicmVha1xyXG5cclxuXHJcblxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBFbmdpbmVcclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuIiwiXG5qc29uX3R5cGVzX3VuaW5pdGlhbGl6ZWQgPSByZXF1aXJlIFwiLi4vVHlwZXMvSnNvblR5cGVzXCJcbkhpc3RvcnlCdWZmZXIgPSByZXF1aXJlIFwiLi4vSGlzdG9yeUJ1ZmZlclwiXG5FbmdpbmUgPSByZXF1aXJlIFwiLi4vRW5naW5lXCJcblxuI1xuIyBGcmFtZXdvcmsgZm9yIEpzb24gZGF0YS1zdHJ1Y3R1cmVzLlxuIyBLbm93biB2YWx1ZXMgdGhhdCBhcmUgc3VwcG9ydGVkOlxuIyAqIFN0cmluZ1xuIyAqIEludGVnZXJcbiMgKiBBcnJheVxuI1xuY2xhc3MgSnNvbllhdHRhXG5cbiAgI1xuICAjIEBwYXJhbSB7U3RyaW5nfSB1c2VyX2lkIFVuaXF1ZSBpZCBvZiB0aGUgcGVlci5cbiAgIyBAcGFyYW0ge0Nvbm5lY3Rvcn0gQ29ubmVjdG9yIHRoZSBjb25uZWN0b3IgY2xhc3MuXG4gICNcbiAgY29uc3RydWN0b3I6ICh1c2VyX2lkLCBDb25uZWN0b3IpLT5cbiAgICBASEIgPSBuZXcgSGlzdG9yeUJ1ZmZlciB1c2VyX2lkXG4gICAganNvbl90eXBlcyA9IGpzb25fdHlwZXNfdW5pbml0aWFsaXplZCBASEJcbiAgICBAZW5naW5lID0gbmV3IEVuZ2luZSBASEIsIGpzb25fdHlwZXMucGFyc2VyXG4gICAgQGNvbm5lY3RvciA9IG5ldyBDb25uZWN0b3IgQGVuZ2luZSwgQEhCLCBqc29uX3R5cGVzLmV4ZWN1dGlvbl9saXN0ZW5lciwgQFxuXG4gICAgZmlyc3Rfd29yZCA9IG5ldyBqc29uX3R5cGVzLnR5cGVzLkpzb25UeXBlIEBIQi5nZXRSZXNlcnZlZFVuaXF1ZUlkZW50aWZpZXIoKVxuICAgIEBIQi5hZGRPcGVyYXRpb24oZmlyc3Rfd29yZCkuZXhlY3V0ZSgpXG4gICAgQHJvb3RfZWxlbWVudCA9IGZpcnN0X3dvcmRcblxuICAjXG4gICMgQHJlc3VsdCBKc29uVHlwZVxuICAjXG4gIGdldFJvb3RFbGVtZW50OiAoKS0+XG4gICAgQHJvb3RfZWxlbWVudFxuXG4gICNcbiAgIyBAc2VlIEVuZ2luZVxuICAjXG4gIGdldEVuZ2luZTogKCktPlxuICAgIEBlbmdpbmVcblxuICAjXG4gICMgR2V0IHRoZSBpbml0aWFsaXplZCBjb25uZWN0b3IuXG4gICNcbiAgZ2V0Q29ubmVjdG9yOiAoKS0+XG4gICAgQGNvbm5lY3RvclxuXG4gICNcbiAgIyBAc2VlIEhpc3RvcnlCdWZmZXJcbiAgI1xuICBnZXRIaXN0b3J5QnVmZmVyOiAoKS0+XG4gICAgQEhCXG5cbiAgI1xuICAjIEBzZWUgSnNvblR5cGUuc2V0TXV0YWJsZURlZmF1bHRcbiAgI1xuICBzZXRNdXRhYmxlRGVmYXVsdDogKG11dGFibGUpLT5cbiAgICBAcm9vdF9lbGVtZW50LnNldE11dGFibGVEZWZhdWx0KG11dGFibGUpXG5cbiAgI1xuICAjIEdldCB0aGUgVXNlcklkIGZyb20gdGhlIEhpc3RvcnlCdWZmZXIgb2JqZWN0LlxuICAjIEluIG1vc3QgY2FzZXMgdGhpcyB3aWxsIGJlIHRoZSBzYW1lIGFzIHRoZSB1c2VyX2lkIHZhbHVlIHdpdGggd2hpY2hcbiAgIyBKc29uWWF0dGEgd2FzIGluaXRpYWxpemVkIChEZXBlbmRpbmcgb24gdGhlIEhpc3RvcnlCdWZmZXIgaW1wbGVtZW50YXRpb24pLlxuICAjXG4gIGdldFVzZXJJZDogKCktPlxuICAgIEBIQi5nZXRVc2VySWQoKVxuXG4gICNcbiAgIyBAc2VlIEpzb25UeXBlLnZhbFxuICAjXG4gIHZhbCA6IChuYW1lLCBjb250ZW50LCBtdXRhYmxlKS0+XG4gICAgQHJvb3RfZWxlbWVudC52YWwobmFtZSwgY29udGVudCwgbXV0YWJsZSlcblxuICAjXG4gICMgQHNlZSBKc29uVHlwZS52YWx1ZVxuICAjXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSBKc29uWWF0dGEucHJvdG90eXBlLCAndmFsdWUnLFxuICAgIGdldCA6IC0+IEByb290X2VsZW1lbnQudmFsdWVcbiAgICBzZXQgOiAobyktPlxuICAgICAgaWYgby5jb25zdHJ1Y3RvciBpcyB7fS5jb25zdHJ1Y3RvclxuICAgICAgICBmb3Igb19uYW1lLG9fb2JqIG9mIG9cbiAgICAgICAgICBAdmFsKG9fbmFtZSwgb19vYmosICdpbW11dGFibGUnKVxuICAgICAgZWxzZVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBvbmx5IHNldCBPYmplY3QgdmFsdWVzIVwiXG5cbm1vZHVsZS5leHBvcnRzID0gSnNvbllhdHRhXG5pZiB3aW5kb3c/XG4gIGlmIG5vdCB3aW5kb3cuWT9cbiAgICB3aW5kb3cuWSA9IHt9XG4gIHdpbmRvdy5ZLkpzb25ZYXR0YSA9IEpzb25ZYXR0YVxuIiwiXG4jXG4jIEFuIG9iamVjdCB0aGF0IGhvbGRzIGFsbCBhcHBsaWVkIG9wZXJhdGlvbnMuXG4jXG4jIEBub3RlIFRoZSBIaXN0b3J5QnVmZmVyIGlzIGNvbW1vbmx5IGFiYnJldmlhdGVkIHRvIEhCLlxuI1xuY2xhc3MgSGlzdG9yeUJ1ZmZlclxuXG4gICNcbiAgIyBDcmVhdGVzIGFuIGVtcHR5IEhCLlxuICAjIEBwYXJhbSB7T2JqZWN0fSB1c2VyX2lkIENyZWF0b3Igb2YgdGhlIEhCLlxuICAjXG4gIGNvbnN0cnVjdG9yOiAoQHVzZXJfaWQpLT5cbiAgICBAb3BlcmF0aW9uX2NvdW50ZXIgPSB7fVxuICAgIEBidWZmZXIgPSB7fVxuICAgIEBjaGFuZ2VfbGlzdGVuZXJzID0gW11cblxuICAjXG4gICMgR2V0IHRoZSB1c2VyIGlkIHdpdGggd2ljaCB0aGUgSGlzdG9yeSBCdWZmZXIgd2FzIGluaXRpYWxpemVkLlxuICAjXG4gIGdldFVzZXJJZDogKCktPlxuICAgIEB1c2VyX2lkXG5cbiAgI1xuICAjIFRoZXJlIGlzIG9ubHkgb25lIHJlc2VydmVkIHVuaXF1ZSBpZGVudGlmaWVyICh1aWQpLCBzbyB1c2UgaXQgd2lzZWx5LlxuICAjIEkgcHJvcG9zZSB0byB1c2UgaXQgaW4geW91ciBGcmFtZXdvcmssIHRvIGNyZWF0ZSBzb21ldGhpbmcgbGlrZSBhIHJvb3QgZWxlbWVudC5cbiAgIyBBbiBvcGVyYXRpb24gd2l0aCB0aGlzIGlkZW50aWZpZXIgaXMgbm90IHByb3BhZ2F0ZWQgdG8gb3RoZXIgY2xpZW50cy5cbiAgIyBUaGlzIGlzIHdoeSBldmVyeWJvZGUgbXVzdCBjcmVhdGUgdGhlIHNhbWUgb3BlcmF0aW9uIHdpdGggdGhpcyB1aWQuXG4gICNcbiAgZ2V0UmVzZXJ2ZWRVbmlxdWVJZGVudGlmaWVyOiAoKS0+XG4gICAge1xuICAgICAgY3JlYXRvciA6ICdfJ1xuICAgICAgb3BfbnVtYmVyIDogJ18nXG4gICAgfVxuXG4gICNcbiAgIyBHZXQgdGhlIG9wZXJhdGlvbiBjb3VudGVyIHRoYXQgZGVzY3JpYmVzIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBkb2N1bWVudC5cbiAgI1xuICBnZXRPcGVyYXRpb25Db3VudGVyOiAoKS0+XG4gICAgcmVzID0ge31cbiAgICBmb3IgdXNlcixjdG4gb2YgQG9wZXJhdGlvbl9jb3VudGVyXG4gICAgICByZXNbdXNlcl0gPSBjdG5cbiAgICByZXNcblxuICAjXG4gICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgI1xuICBfZW5jb2RlOiAoc3RhdGVfdmVjdG9yPXt9KS0+XG4gICAganNvbiA9IFtdXG4gICAgdW5rbm93biA9ICh1c2VyLCBvX251bWJlciktPlxuICAgICAgaWYgKG5vdCB1c2VyPykgb3IgKG5vdCBvX251bWJlcj8pXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcImRhaCFcIlxuICAgICAgbm90IHN0YXRlX3ZlY3Rvclt1c2VyXT8gb3Igc3RhdGVfdmVjdG9yW3VzZXJdIDw9IG9fbnVtYmVyXG5cbiAgICBmb3IgdV9uYW1lLHVzZXIgb2YgQGJ1ZmZlclxuICAgICAgZm9yIG9fbnVtYmVyLG8gb2YgdXNlclxuICAgICAgICBpZiAobm90IGlzTmFOKHBhcnNlSW50KG9fbnVtYmVyKSkpIGFuZCB1bmtub3duKHVfbmFtZSwgb19udW1iZXIpXG4gICAgICAgICAgb19qc29uID0gby5fZW5jb2RlKClcbiAgICAgICAgICBpZiBvLm5leHRfY2w/XG4gICAgICAgICAgICBvX25leHQgPSBvLm5leHRfY2xcbiAgICAgICAgICAgIHdoaWxlIG9fbmV4dC5uZXh0X2NsPyBhbmQgdW5rbm93bihvX25leHQuY3JlYXRvciwgb19uZXh0Lm9wX251bWJlcilcbiAgICAgICAgICAgICAgb19uZXh0ID0gb19uZXh0Lm5leHRfY2xcbiAgICAgICAgICAgIG9fanNvbi5uZXh0ID0gb19uZXh0LmdldFVpZCgpXG4gICAgICAgICAgZWxzZSBpZiBvLnByZXZfY2w/XG4gICAgICAgICAgICBvX3ByZXYgPSBvLnByZXZfY2xcbiAgICAgICAgICAgIHdoaWxlIG9fcHJldi5wcmV2X2NsPyBhbmQgdW5rbm93bihvX25leHQuY3JlYXRvciwgb19uZXh0Lm9wX251bWJlcilcbiAgICAgICAgICAgICAgb19wcmV2ID0gb19wcmV2LnByZXZfY2xcbiAgICAgICAgICAgIG9fanNvbi5wcmV2ID0gb19wcmV2LmdldFVpZCgpXG4gICAgICAgICAganNvbi5wdXNoIG9fanNvblxuXG4gICAganNvblxuXG4gICNcbiAgIyBHZXQgdGhlIG51bWJlciBvZiBvcGVyYXRpb25zIHRoYXQgd2VyZSBjcmVhdGVkIGJ5IGEgdXNlci5cbiAgIyBBY2NvcmRpbmdseSB5b3Ugd2lsbCBnZXQgdGhlIG5leHQgb3BlcmF0aW9uIG51bWJlciB0aGF0IGlzIGV4cGVjdGVkIGZyb20gdGhhdCB1c2VyLlxuICAjIFRoaXMgd2lsbCBpbmNyZW1lbnQgdGhlIG9wZXJhdGlvbiBjb3VudGVyLlxuICAjXG4gIGdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyOiAodXNlcl9pZCktPlxuICAgIGlmIG5vdCB1c2VyX2lkP1xuICAgICAgdXNlcl9pZCA9IEB1c2VyX2lkXG4gICAgaWYgbm90IEBvcGVyYXRpb25fY291bnRlclt1c2VyX2lkXT9cbiAgICAgIEBvcGVyYXRpb25fY291bnRlclt1c2VyX2lkXSA9IDBcbiAgICB1aWQgPVxuICAgICAgJ2NyZWF0b3InIDogdXNlcl9pZFxuICAgICAgJ29wX251bWJlcicgOiBAb3BlcmF0aW9uX2NvdW50ZXJbdXNlcl9pZF1cbiAgICBAb3BlcmF0aW9uX2NvdW50ZXJbdXNlcl9pZF0rK1xuICAgIHVpZFxuXG4gICNcbiAgIyBSZXRyaWV2ZSBhbiBvcGVyYXRpb24gZnJvbSBhIHVuaXF1ZSBpZC5cbiAgI1xuICBnZXRPcGVyYXRpb246ICh1aWQpLT5cbiAgICBpZiB1aWQgaW5zdGFuY2VvZiBPYmplY3RcbiAgICAgIEBidWZmZXJbdWlkLmNyZWF0b3JdP1t1aWQub3BfbnVtYmVyXVxuICAgIGVsc2UgaWYgbm90IHVpZD9cbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJUaGlzIHR5cGUgb2YgdWlkIGlzIG5vdCBkZWZpbmVkIVwiXG4gICNcbiAgIyBBZGQgYW4gb3BlcmF0aW9uIHRvIHRoZSBIQi4gTm90ZSB0aGF0IHRoaXMgd2lsbCBub3QgbGluayBpdCBhZ2FpbnN0XG4gICMgb3RoZXIgb3BlcmF0aW9ucyAoaXQgd29udCBleGVjdXRlZClcbiAgI1xuICBhZGRPcGVyYXRpb246IChvKS0+XG4gICAgaWYgbm90IEBidWZmZXJbby5jcmVhdG9yXT9cbiAgICAgIEBidWZmZXJbby5jcmVhdG9yXSA9IHt9XG4gICAgaWYgQGJ1ZmZlcltvLmNyZWF0b3JdW28ub3BfbnVtYmVyXT9cbiAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBtdXN0IG5vdCBvdmVyd3JpdGUgb3BlcmF0aW9ucyFcIlxuICAgIEBidWZmZXJbby5jcmVhdG9yXVtvLm9wX251bWJlcl0gPSBvXG4gICAgb1xuXG4gICNcbiAgIyBJbmNyZW1lbnQgdGhlIG9wZXJhdGlvbl9jb3VudGVyIHRoYXQgZGVmaW5lcyB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgRW5naW5lLlxuICAjXG4gIGFkZFRvQ291bnRlcjogKG8pLT5cbiAgICBpZiBub3QgQG9wZXJhdGlvbl9jb3VudGVyW28uY3JlYXRvcl0/XG4gICAgICBAb3BlcmF0aW9uX2NvdW50ZXJbby5jcmVhdG9yXSA9IDBcbiAgICBpZiB0eXBlb2Ygby5vcF9udW1iZXIgaXMgJ251bWJlcicgYW5kIG8uY3JlYXRvciBpc250IEBnZXRVc2VySWQoKVxuICAgICAgQG9wZXJhdGlvbl9jb3VudGVyW28uY3JlYXRvcl0rK1xuICAgICNpZiBAb3BlcmF0aW9uX2NvdW50ZXJbby5jcmVhdG9yXSBpc250IChvLm9wX251bWJlciArIDEpXG4gICAgICAjY29uc29sZS5sb2cgKEBvcGVyYXRpb25fY291bnRlcltvLmNyZWF0b3JdIC0gKG8ub3BfbnVtYmVyICsgMSkpXG4gICAgICAjY29uc29sZS5sb2cgb1xuICAgICAgI3Rocm93IG5ldyBFcnJvciBcIllvdSBkb24ndCByZWNlaXZlIG9wZXJhdGlvbnMgaW4gdGhlIHByb3BlciBvcmRlci4gVHJ5IGNvdW50aW5nIGxpa2UgdGhpcyAwLDEsMiwzLDQsLi4gOylcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IEhpc3RvcnlCdWZmZXJcbiIsIm1vZHVsZS5leHBvcnRzID0gKEhCKS0+XG4gICMgQHNlZSBFbmdpbmUucGFyc2VcbiAgcGFyc2VyID0ge31cbiAgZXhlY3V0aW9uX2xpc3RlbmVyID0gW11cblxuICAjXG4gICMgQSBnZW5lcmljIGludGVyZmFjZSB0byBvcGVyYXRpb25zLlxuICAjXG4gICMgQW4gb3BlcmF0aW9uIGhhcyB0aGUgZm9sbG93aW5nIG1ldGhvZHM6XG4gICMgX2VuY29kZTogZW5jb2RlcyBhbiBvcGVyYXRpb24gKG5lZWRlZCBvbmx5IGlmIGluc3RhbmNlIG9mIHRoaXMgb3BlcmF0aW9uIGlzIHNlbnQpLlxuICAjIGV4ZWN1dGU6IGV4ZWN1dGUgdGhlIGVmZmVjdHMgb2YgdGhpcyBvcGVyYXRpb25zLiBHb29kIGV4YW1wbGVzIGFyZSBJbnNlcnQtdHlwZSBhbmQgQWRkTmFtZS10eXBlXG4gICMgdmFsOiBpbiB0aGUgY2FzZSB0aGF0IHRoZSBvcGVyYXRpb24gaG9sZHMgYSB2YWx1ZVxuICAjXG4gICMgRnVydGhlcm1vcmUgYW4gZW5jb2RhYmxlIG9wZXJhdGlvbiBoYXMgYSBwYXJzZXIuXG4gICNcbiAgY2xhc3MgT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAc2VlIEhpc3RvcnlCdWZmZXIuZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXJcbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQpLT5cbiAgICAgIGlmIG5vdCB1aWQ/XG4gICAgICAgIHVpZCA9IEhCLmdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyKClcbiAgICAgIHtcbiAgICAgICAgJ2NyZWF0b3InOiBAY3JlYXRvclxuICAgICAgICAnb3BfbnVtYmVyJyA6IEBvcF9udW1iZXJcbiAgICAgIH0gPSB1aWRcblxuICAgICNcbiAgICAjIEFkZCBhbiBldmVudCBsaXN0ZW5lci4gSXQgZGVwZW5kcyBvbiB0aGUgb3BlcmF0aW9uIHdoaWNoIGV2ZW50cyBhcmUgc3VwcG9ydGVkLlxuICAgICMgQHBhcmFtIHtTdHJpbmd9IGV2ZW50IE5hbWUgb2YgdGhlIGV2ZW50LlxuICAgICMgQHBhcmFtIHtGdW5jdGlvbn0gZiBmIGlzIGV4ZWN1dGVkIGluIGNhc2UgdGhlIGV2ZW50IGZpcmVzLlxuICAgICNcbiAgICBvbjogKGV2ZW50LCBmKS0+XG4gICAgICBAZXZlbnRfbGlzdGVuZXJzID89IHt9XG4gICAgICBAZXZlbnRfbGlzdGVuZXJzW2V2ZW50XSA/PSBbXVxuICAgICAgQGV2ZW50X2xpc3RlbmVyc1tldmVudF0ucHVzaCBmXG5cbiAgICAjXG4gICAgIyBGaXJlIGFuIGV2ZW50LlxuICAgICMgVE9ETzogRG8gc29tZXRoaW5nIHdpdGggdGltZW91dHMuIFlvdSBkb24ndCB3YW50IHRoaXMgdG8gZmlyZSBmb3IgZXZlcnkgb3BlcmF0aW9uIChlLmcuIGluc2VydCkuXG4gICAgI1xuICAgIGNhbGxFdmVudDogKGV2ZW50LCBhcmdzKS0+XG4gICAgICBpZiBAZXZlbnRfbGlzdGVuZXJzP1tldmVudF0/XG4gICAgICAgIGZvciBmIGluIEBldmVudF9saXN0ZW5lcnNbZXZlbnRdXG4gICAgICAgICAgZi5jYWxsIEAsIGV2ZW50LCBhcmdzXG5cbiAgICAjXG4gICAgIyBTZXQgdGhlIHBhcmVudCBvZiB0aGlzIG9wZXJhdGlvbi5cbiAgICAjXG4gICAgc2V0UGFyZW50OiAobyktPlxuICAgICAgQHBhcmVudCA9IG9cblxuICAgICNcbiAgICAjIEdldCB0aGUgcGFyZW50IG9mIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICBnZXRQYXJlbnQ6ICgpLT5cbiAgICAgIEBwYXJlbnRcblxuICAgICNcbiAgICAjIENvbXB1dGVzIGEgdW5pcXVlIGlkZW50aWZpZXIgKHVpZCkgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICBnZXRVaWQ6ICgpLT5cbiAgICAgIHsgJ2NyZWF0b3InOiBAY3JlYXRvciwgJ29wX251bWJlcic6IEBvcF9udW1iZXIgfVxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIE5vdGlmeSB0aGUgYWxsIHRoZSBsaXN0ZW5lcnMuXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIEBpc19leGVjdXRlZCA9IHRydWVcbiAgICAgIGZvciBsIGluIGV4ZWN1dGlvbl9saXN0ZW5lclxuICAgICAgICBsIEBfZW5jb2RlKClcbiAgICAgIEBcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBPcGVyYXRpb25zIG1heSBkZXBlbmQgb24gb3RoZXIgb3BlcmF0aW9ucyAobGlua2VkIGxpc3RzLCBldGMuKS5cbiAgICAjIFRoZSBzYXZlT3BlcmF0aW9uIGFuZCB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucyBtZXRob2RzIHByb3ZpZGVcbiAgICAjIGFuIGVhc3kgd2F5IHRvIHJlZmVyIHRvIHRoZXNlIG9wZXJhdGlvbnMgdmlhIGFuIHVpZCBvciBvYmplY3QgcmVmZXJlbmNlLlxuICAgICNcbiAgICAjIEZvciBleGFtcGxlOiBXZSBjYW4gY3JlYXRlIGEgbmV3IERlbGV0ZSBvcGVyYXRpb24gdGhhdCBkZWxldGVzIHRoZSBvcGVyYXRpb24gJG8gbGlrZSB0aGlzXG4gICAgIyAgICAgLSB2YXIgZCA9IG5ldyBEZWxldGUodWlkLCAkbyk7ICAgb3JcbiAgICAjICAgICAtIHZhciBkID0gbmV3IERlbGV0ZSh1aWQsICRvLmdldFVpZCgpKTtcbiAgICAjIEVpdGhlciB3YXkgd2Ugd2FudCB0byBhY2Nlc3MgJG8gdmlhIGQuZGVsZXRlcy4gSW4gdGhlIHNlY29uZCBjYXNlIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zIG11c3QgYmUgY2FsbGVkIGZpcnN0LlxuICAgICNcbiAgICAjIEBvdmVybG9hZCBzYXZlT3BlcmF0aW9uKG5hbWUsIG9wX3VpZClcbiAgICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGlvbi4gQWZ0ZXIgdmFsaWRhdGluZyAod2l0aCB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucykgdGhlIGluc3RhbnRpYXRlZCBvcGVyYXRpb24gd2lsbCBiZSBhY2Nlc3NpYmxlIHZpYSB0aGlzW25hbWVdLlxuICAgICMgICBAcGFyYW0ge09iamVjdH0gb3BfdWlkIEEgdWlkIHRoYXQgcmVmZXJzIHRvIGFuIG9wZXJhdGlvblxuICAgICMgQG92ZXJsb2FkIHNhdmVPcGVyYXRpb24obmFtZSwgb3ApXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpb24uIEFmdGVyIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiBvcCBpcyBhY2Nlc3NpYmxlIHZpYSB0aGlzW25hbWVdLlxuICAgICMgICBAcGFyYW0ge09wZXJhdGlvbn0gb3AgQW4gT3BlcmF0aW9uIG9iamVjdFxuICAgICNcbiAgICBzYXZlT3BlcmF0aW9uOiAobmFtZSwgb3ApLT5cblxuICAgICAgI1xuICAgICAgIyBFdmVyeSBpbnN0YW5jZSBvZiAkT3BlcmF0aW9uIG11c3QgaGF2ZSBhbiAkZXhlY3V0ZSBmdW5jdGlvbi5cbiAgICAgICMgV2UgdXNlIGR1Y2stdHlwaW5nIHRvIGNoZWNrIGlmIG9wIGlzIGluc3RhbnRpYXRlZCBzaW5jZSB0aGVyZVxuICAgICAgIyBjb3VsZCBleGlzdCBtdWx0aXBsZSBjbGFzc2VzIG9mICRPcGVyYXRpb25cbiAgICAgICNcbiAgICAgIGlmIG9wPy5leGVjdXRlP1xuICAgICAgICAjIGlzIGluc3RhbnRpYXRlZFxuICAgICAgICBAW25hbWVdID0gb3BcbiAgICAgIGVsc2UgaWYgb3A/XG4gICAgICAgICMgbm90IGluaXRpYWxpemVkLiBEbyBpdCB3aGVuIGNhbGxpbmcgJHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgQHVuY2hlY2tlZCA/PSB7fVxuICAgICAgICBAdW5jaGVja2VkW25hbWVdID0gb3BcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBBZnRlciBjYWxsaW5nIHRoaXMgZnVuY3Rpb24gYWxsIG5vdCBpbnN0YW50aWF0ZWQgb3BlcmF0aW9ucyB3aWxsIGJlIGFjY2Vzc2libGUuXG4gICAgIyBAc2VlIE9wZXJhdGlvbi5zYXZlT3BlcmF0aW9uXG4gICAgI1xuICAgICMgQHJldHVybiBbQm9vbGVhbl0gV2hldGhlciBpdCB3YXMgcG9zc2libGUgdG8gaW5zdGFudGlhdGUgYWxsIG9wZXJhdGlvbnMuXG4gICAgI1xuICAgIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zOiAoKS0+XG4gICAgICB1bmluc3RhbnRpYXRlZCA9IHt9XG4gICAgICBzdWNjZXNzID0gQFxuICAgICAgZm9yIG5hbWUsIG9wX3VpZCBvZiBAdW5jaGVja2VkXG4gICAgICAgIG9wID0gSEIuZ2V0T3BlcmF0aW9uIG9wX3VpZFxuICAgICAgICBpZiBvcFxuICAgICAgICAgIEBbbmFtZV0gPSBvcFxuICAgICAgICBlbHNlXG4gICAgICAgICAgdW5pbnN0YW50aWF0ZWRbbmFtZV0gPSBvcF91aWRcbiAgICAgICAgICBzdWNjZXNzID0gZmFsc2VcbiAgICAgIGRlbGV0ZSBAdW5jaGVja2VkXG4gICAgICBpZiBub3Qgc3VjY2Vzc1xuICAgICAgICBAdW5jaGVja2VkID0gdW5pbnN0YW50aWF0ZWRcbiAgICAgIHN1Y2Nlc3NcblxuXG5cbiAgI1xuICAjIEEgc2ltcGxlIERlbGV0ZS10eXBlIG9wZXJhdGlvbiB0aGF0IGRlbGV0ZXMgYW4gSW5zZXJ0LXR5cGUgb3BlcmF0aW9uLlxuICAjXG4gIGNsYXNzIERlbGV0ZSBleHRlbmRzIE9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IGRlbGV0ZXMgVUlEIG9yIHJlZmVyZW5jZSBvZiB0aGUgb3BlcmF0aW9uIHRoYXQgdGhpcyB0byBiZSBkZWxldGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgZGVsZXRlcyktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ2RlbGV0ZXMnLCBkZWxldGVzXG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBDb252ZXJ0IGFsbCByZWxldmFudCBpbmZvcm1hdGlvbiBvZiB0aGlzIG9wZXJhdGlvbiB0byB0aGUganNvbi1mb3JtYXQuXG4gICAgIyBUaGlzIHJlc3VsdCBjYW4gYmUgc2VudCB0byBvdGhlciBjbGllbnRzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICB7XG4gICAgICAgICd0eXBlJzogXCJEZWxldGVcIlxuICAgICAgICAndWlkJzogQGdldFVpZCgpXG4gICAgICAgICdkZWxldGVzJzogQGRlbGV0ZXMuZ2V0VWlkKClcbiAgICAgIH1cblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBBcHBseSB0aGUgZGVsZXRpb24uXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIEBkZWxldGVzLmFwcGx5RGVsZXRlIEBcbiAgICAgICAgc3VwZXJcbiAgICAgIGVsc2VcbiAgICAgICAgZmFsc2VcblxuICAjXG4gICMgRGVmaW5lIGhvdyB0byBwYXJzZSBEZWxldGUgb3BlcmF0aW9ucy5cbiAgI1xuICBwYXJzZXJbJ0RlbGV0ZSddID0gKG8pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ2RlbGV0ZXMnOiBkZWxldGVzX3VpZFxuICAgIH0gPSBvXG4gICAgbmV3IERlbGV0ZSB1aWQsIGRlbGV0ZXNfdWlkXG5cbiAgI1xuICAjIEEgc2ltcGxlIGluc2VydC10eXBlIG9wZXJhdGlvbi5cbiAgI1xuICAjIEFuIGluc2VydCBvcGVyYXRpb24gaXMgYWx3YXlzIHBvc2l0aW9uZWQgYmV0d2VlbiB0d28gb3RoZXIgaW5zZXJ0IG9wZXJhdGlvbnMuXG4gICMgSW50ZXJuYWxseSB0aGlzIGlzIHJlYWxpemVkIGFzIGFzc29jaWF0aXZlIGxpc3RzLCB3aGVyZWJ5IGVhY2ggaW5zZXJ0IG9wZXJhdGlvbiBoYXMgYSBwcmVkZWNlc3NvciBhbmQgYSBzdWNjZXNzb3IuXG4gICMgRm9yIHRoZSBzYWtlIG9mIGVmZmljaWVuY3kgd2UgbWFpbnRhaW4gdHdvIGxpc3RzOlxuICAjICAgLSBUaGUgc2hvcnQtbGlzdCAoYWJicmV2LiBzbCkgbWFpbnRhaW5zIG9ubHkgdGhlIG9wZXJhdGlvbnMgdGhhdCBhcmUgbm90IGRlbGV0ZWRcbiAgIyAgIC0gVGhlIGNvbXBsZXRlLWxpc3QgKGFiYnJldi4gY2wpIG1haW50YWlucyBhbGwgb3BlcmF0aW9uc1xuICAjXG4gIGNsYXNzIEluc2VydCBleHRlbmRzIE9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IHByZXZfY2wgVGhlIHByZWRlY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBuZXh0X2NsIFRoZSBzdWNjZXNzb3Igb2YgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGNvbXBsZXRlLWxpc3QgKGNsKVxuICAgICNcbiAgICAjIEBzZWUgSGlzdG9yeUJ1ZmZlci5nZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllclxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgcHJldl9jbCwgbmV4dF9jbCwgb3JpZ2luKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncHJldl9jbCcsIHByZXZfY2xcbiAgICAgIEBzYXZlT3BlcmF0aW9uICduZXh0X2NsJywgbmV4dF9jbFxuICAgICAgaWYgb3JpZ2luP1xuICAgICAgICBAc2F2ZU9wZXJhdGlvbiAnb3JpZ2luJywgb3JpZ2luXG4gICAgICBlbHNlXG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBwcmV2X2NsXG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgI1xuICAgIGFwcGx5RGVsZXRlOiAobyktPlxuICAgICAgQGRlbGV0ZWRfYnkgPz0gW11cbiAgICAgIEBkZWxldGVkX2J5LnB1c2ggb1xuICAgICAgaWYgQHBhcmVudD8gYW5kIEBkZWxldGVkX2J5Lmxlbmd0aCBpcyAxXG4gICAgICAgICMgY2FsbCBpZmYgd2Fzbid0IGRlbGV0ZWQgZWFybHllclxuICAgICAgICBAcGFyZW50LmNhbGxFdmVudCBcImRlbGV0ZVwiLCBAXG5cbiAgICAjXG4gICAgIyBJZiBpc0RlbGV0ZWQoKSBpcyB0cnVlIHRoaXMgb3BlcmF0aW9uIHdvbid0IGJlIG1haW50YWluZWQgaW4gdGhlIHNsXG4gICAgI1xuICAgIGlzRGVsZXRlZDogKCktPlxuICAgICAgQGRlbGV0ZWRfYnk/Lmxlbmd0aCA+IDBcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBUaGUgYW1vdW50IG9mIHBvc2l0aW9ucyB0aGF0ICR0aGlzIG9wZXJhdGlvbiB3YXMgbW92ZWQgdG8gdGhlIHJpZ2h0LlxuICAgICNcbiAgICBnZXREaXN0YW5jZVRvT3JpZ2luOiAoKS0+XG4gICAgICBkID0gMFxuICAgICAgbyA9IEBwcmV2X2NsXG4gICAgICB3aGlsZSB0cnVlXG4gICAgICAgIGlmIEBvcmlnaW4gaXMgb1xuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGQrK1xuICAgICAgICAjVE9ETzogZGVsZXRlIHRoaXNcbiAgICAgICAgaWYgQCBpcyBAcHJldl9jbFxuICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcInRoaXMgc2hvdWxkIG5vdCBoYXBwZW4gOykgXCJcbiAgICAgICAgbyA9IG8ucHJldl9jbFxuICAgICAgZFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIFVwZGF0ZSB0aGUgc2hvcnQgbGlzdFxuICAgICMgVE9ETyAoVW51c2VkKVxuICAgIHVwZGF0ZV9zbDogKCktPlxuICAgICAgbyA9IEBwcmV2X2NsXG4gICAgICB1cGRhdGU6IChkZXN0X2NsLGRlc3Rfc2wpLT5cbiAgICAgICAgd2hpbGUgdHJ1ZVxuICAgICAgICAgIGlmIG8uaXNEZWxldGVkKClcbiAgICAgICAgICAgIG8gPSBvW2Rlc3RfY2xdXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgQFtkZXN0X3NsXSA9IG9cblxuICAgICAgICAgICAgYnJlYWtcbiAgICAgIHVwZGF0ZSBcInByZXZfY2xcIiwgXCJwcmV2X3NsXCJcbiAgICAgIHVwZGF0ZSBcIm5leHRfY2xcIiwgXCJwcmV2X3NsXCJcblxuXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgSW5jbHVkZSB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgYXNzb2NpYXRpdmUgbGlzdHMuXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEBpc19leGVjdXRlZD9cbiAgICAgICAgcmV0dXJuIEBcbiAgICAgIGlmIG5vdCBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIGVsc2VcbiAgICAgICAgaWYgQHByZXZfY2w/LnZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKCkgYW5kIEBuZXh0X2NsPy52YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpIGFuZCBAcHJldl9jbC5uZXh0X2NsIGlzbnQgQFxuICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IDBcbiAgICAgICAgICBvID0gQHByZXZfY2wubmV4dF9jbFxuICAgICAgICAgIGkgPSAwXG4gICAgICAgICAgIyAkdGhpcyBoYXMgdG8gZmluZCBhIHVuaXF1ZSBwb3NpdGlvbiBiZXR3ZWVuIG9yaWdpbiBhbmQgdGhlIG5leHQga25vd24gY2hhcmFjdGVyXG4gICAgICAgICAgIyBjYXNlIDE6ICRvcmlnaW4gZXF1YWxzICRvLm9yaWdpbjogdGhlICRjcmVhdG9yIHBhcmFtZXRlciBkZWNpZGVzIGlmIGxlZnQgb3IgcmlnaHRcbiAgICAgICAgICAjICAgICAgICAgbGV0ICRPTD0gW28xLG8yLG8zLG80XSwgd2hlcmVieSAkdGhpcyBpcyB0byBiZSBpbnNlcnRlZCBiZXR3ZWVuIG8xIGFuZCBvNFxuICAgICAgICAgICMgICAgICAgICBvMixvMyBhbmQgbzQgb3JpZ2luIGlzIDEgKHRoZSBwb3NpdGlvbiBvZiBvMilcbiAgICAgICAgICAjICAgICAgICAgdGhlcmUgaXMgdGhlIGNhc2UgdGhhdCAkdGhpcy5jcmVhdG9yIDwgbzIuY3JlYXRvciwgYnV0IG8zLmNyZWF0b3IgPCAkdGhpcy5jcmVhdG9yXG4gICAgICAgICAgIyAgICAgICAgIHRoZW4gbzIga25vd3MgbzMuIFNpbmNlIG9uIGFub3RoZXIgY2xpZW50ICRPTCBjb3VsZCBiZSBbbzEsbzMsbzRdIHRoZSBwcm9ibGVtIGlzIGNvbXBsZXhcbiAgICAgICAgICAjICAgICAgICAgdGhlcmVmb3JlICR0aGlzIHdvdWxkIGJlIGFsd2F5cyB0byB0aGUgcmlnaHQgb2YgbzNcbiAgICAgICAgICAjIGNhc2UgMjogJG9yaWdpbiA8ICRvLm9yaWdpblxuICAgICAgICAgICMgICAgICAgICBpZiBjdXJyZW50ICR0aGlzIGluc2VydF9wb3NpdGlvbiA+ICRvIG9yaWdpbjogJHRoaXMgaW5zXG4gICAgICAgICAgIyAgICAgICAgIGVsc2UgJGluc2VydF9wb3NpdGlvbiB3aWxsIG5vdCBjaGFuZ2UgKG1heWJlIHdlIGVuY291bnRlciBjYXNlIDEgbGF0ZXIsIHRoZW4gdGhpcyB3aWxsIGJlIHRvIHRoZSByaWdodCBvZiAkbylcbiAgICAgICAgICAjIGNhc2UgMzogJG9yaWdpbiA+ICRvLm9yaWdpblxuICAgICAgICAgICMgICAgICAgICAkdGhpcyBpbnNlcnRfcG9zaXRpb24gaXMgdG8gdGhlIGxlZnQgb2YgJG8gKGZvcmV2ZXIhKVxuICAgICAgICAgIHdoaWxlIHRydWVcbiAgICAgICAgICAgIGlmIG5vdCBvP1xuICAgICAgICAgICAgICAjIFRPRE86IERlYnVnZ2luZ1xuICAgICAgICAgICAgICBjb25zb2xlLmxvZyBKU09OLnN0cmluZ2lmeSBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICAgICAgICBjb25zb2xlLmxvZyBKU09OLnN0cmluZ2lmeSBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgICAgICAgaWYgbyBpc250IEBuZXh0X2NsXG4gICAgICAgICAgICAgICMgJG8gaGFwcGVuZWQgY29uY3VycmVudGx5XG4gICAgICAgICAgICAgIGlmIG8uZ2V0RGlzdGFuY2VUb09yaWdpbigpIGlzIGlcbiAgICAgICAgICAgICAgICAjIGNhc2UgMVxuICAgICAgICAgICAgICAgIGlmIG8uY3JlYXRvciA8IEBjcmVhdG9yXG4gICAgICAgICAgICAgICAgICBAcHJldl9jbCA9IG9cbiAgICAgICAgICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IGkgKyAxXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgIyBub3BcbiAgICAgICAgICAgICAgZWxzZSBpZiBvLmdldERpc3RhbmNlVG9PcmlnaW4oKSA8IGlcbiAgICAgICAgICAgICAgICAjIGNhc2UgMlxuICAgICAgICAgICAgICAgIGlmIGkgLSBkaXN0YW5jZV90b19vcmlnaW4gPD0gby5nZXREaXN0YW5jZVRvT3JpZ2luKClcbiAgICAgICAgICAgICAgICAgIEBwcmV2X2NsID0gb1xuICAgICAgICAgICAgICAgICAgZGlzdGFuY2VfdG9fb3JpZ2luID0gaSArIDFcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAjbm9wXG4gICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAjIGNhc2UgM1xuICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgIGkrK1xuICAgICAgICAgICAgICBvID0gby5uZXh0X2NsXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICMgJHRoaXMga25vd3MgdGhhdCAkbyBleGlzdHMsXG4gICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgIyBub3cgcmVjb25uZWN0IGV2ZXJ5dGhpbmdcbiAgICAgICAgICBAbmV4dF9jbCA9IEBwcmV2X2NsLm5leHRfY2xcbiAgICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxuICAgICAgICAgIEBuZXh0X2NsLnByZXZfY2wgPSBAXG4gICAgICAgIHBhcmVudCA9IEBwcmV2X2NsPy5nZXRQYXJlbnQoKVxuICAgICAgICBpZiBwYXJlbnQ/XG4gICAgICAgICAgQHNldFBhcmVudCBwYXJlbnRcbiAgICAgICAgICBAcGFyZW50LmNhbGxFdmVudCBcImluc2VydFwiLCBAXG4gICAgICAgIHN1cGVyICMgbm90aWZ5IHRoZSBleGVjdXRpb25fbGlzdGVuZXJzXG5cbiAgICAjXG4gICAgIyBDb21wdXRlIHRoZSBwb3NpdGlvbiBvZiB0aGlzIG9wZXJhdGlvbi5cbiAgICAjXG4gICAgZ2V0UG9zaXRpb246ICgpLT5cbiAgICAgIHBvc2l0aW9uID0gMFxuICAgICAgcHJldiA9IEBwcmV2X2NsXG4gICAgICB3aGlsZSB0cnVlXG4gICAgICAgIGlmIHByZXYgaW5zdGFuY2VvZiBEZWxpbWl0ZXJcbiAgICAgICAgICBicmVha1xuICAgICAgICBpZiBwcmV2LmlzRGVsZXRlZD8gYW5kIG5vdCBwcmV2LmlzRGVsZXRlZCgpXG4gICAgICAgICAgcG9zaXRpb24rK1xuICAgICAgICBwcmV2ID0gcHJldi5wcmV2X2NsXG4gICAgICBwb3NpdGlvblxuICAjXG4gICMgRGVmaW5lcyBhbiBvYmplY3QgdGhhdCBpcyBjYW5ub3QgYmUgY2hhbmdlZC4gWW91IGNhbiB1c2UgdGhpcyB0byBzZXQgYW4gaW1tdXRhYmxlIHN0cmluZywgb3IgYSBudW1iZXIuXG4gICNcbiAgY2xhc3MgSW1tdXRhYmxlT2JqZWN0IGV4dGVuZHMgSW5zZXJ0XG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gY29udGVudFxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgQGNvbnRlbnQsIHByZXYsIG5leHQsIG9yaWdpbiktPlxuICAgICAgc3VwZXIgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICAgICNcbiAgICAjIEByZXR1cm4gW1N0cmluZ10gVGhlIGNvbnRlbnQgb2YgdGhpcyBvcGVyYXRpb24uXG4gICAgI1xuICAgIHZhbCA6ICgpLT5cbiAgICAgIEBjb250ZW50XG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID0ge1xuICAgICAgICAndHlwZSc6IFwiSW1tdXRhYmxlT2JqZWN0XCJcbiAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgJ2NvbnRlbnQnIDogQGNvbnRlbnRcbiAgICAgIH1cbiAgICAgIGlmIEBwcmV2X2NsP1xuICAgICAgICBqc29uWydwcmV2J10gPSBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgaWYgQG5leHRfY2w/XG4gICAgICAgIGpzb25bJ25leHQnXSA9IEBuZXh0X2NsLmdldFVpZCgpXG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyWydJbW11dGFibGVPYmplY3QnXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICdwcmV2JzogcHJldlxuICAgICAgJ25leHQnOiBuZXh0XG4gICAgICAnb3JpZ2luJyA6IG9yaWdpblxuICAgIH0gPSBqc29uXG4gICAgbmV3IEltbXV0YWJsZU9iamVjdCB1aWQsIGNvbnRlbnQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICNcbiAgIyBBIGRlbGltaXRlciBpcyBwbGFjZWQgYXQgdGhlIGVuZCBhbmQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgYXNzb2NpYXRpdmUgbGlzdHMuXG4gICMgVGhpcyBpcyBuZWNlc3NhcnkgaW4gb3JkZXIgdG8gaGF2ZSBhIGJlZ2lubmluZyBhbmQgYW4gZW5kIGV2ZW4gaWYgdGhlIGNvbnRlbnRcbiAgIyBvZiB0aGUgRW5naW5lIGlzIGVtcHR5LlxuICAjXG4gIGNsYXNzIERlbGltaXRlciBleHRlbmRzIE9wZXJhdGlvblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBwcmV2X2NsIFRoZSBwcmVkZWNlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gbmV4dF9jbCBUaGUgc3VjY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcbiAgICAjXG4gICAgIyBAc2VlIEhpc3RvcnlCdWZmZXIuZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXJcbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIHByZXZfY2wsIG5leHRfY2wsIG9yaWdpbiktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ3ByZXZfY2wnLCBwcmV2X2NsXG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnbmV4dF9jbCcsIG5leHRfY2xcbiAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBwcmV2X2NsXG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIElmIGlzRGVsZXRlZCgpIGlzIHRydWUgdGhpcyBvcGVyYXRpb24gd29uJ3QgYmUgbWFpbnRhaW5lZCBpbiB0aGUgc2xcbiAgICAjXG4gICAgaXNEZWxldGVkOiAoKS0+XG4gICAgICBmYWxzZVxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgQHVuY2hlY2tlZD9bJ25leHRfY2wnXT9cbiAgICAgICAgc3VwZXJcbiAgICAgIGVsc2UgaWYgQHVuY2hlY2tlZD9bJ3ByZXZfY2wnXVxuICAgICAgICBpZiBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICAgIGlmIEBwcmV2X2NsLm5leHRfY2w/XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJQcm9iYWJseSBkdXBsaWNhdGVkIG9wZXJhdGlvbnNcIlxuICAgICAgICAgIEBwcmV2X2NsLm5leHRfY2wgPSBAXG4gICAgICAgICAgZGVsZXRlIEBwcmV2X2NsLnVuY2hlY2tlZC5uZXh0X2NsXG4gICAgICAgICAgc3VwZXJcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGZhbHNlXG4gICAgICBlbHNlIGlmIEBwcmV2X2NsPyBhbmQgbm90IEBwcmV2X2NsLm5leHRfY2w/XG4gICAgICAgIGRlbGV0ZSBAcHJldl9jbC51bmNoZWNrZWQubmV4dF9jbFxuICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxuICAgICAgZWxzZSBpZiBAcHJldl9jbD8gb3IgQG5leHRfY2w/XG4gICAgICAgIHN1cGVyXG4gICAgICBlbHNlXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcIkRlbGltaXRlciBpcyB1bnN1ZmZpY2llbnQgZGVmaW5lZCFcIlxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAge1xuICAgICAgICAndHlwZScgOiBcIkRlbGltaXRlclwiXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICdwcmV2JyA6IEBwcmV2X2NsPy5nZXRVaWQoKVxuICAgICAgICAnbmV4dCcgOiBAbmV4dF9jbD8uZ2V0VWlkKClcbiAgICAgIH1cblxuICBwYXJzZXJbJ0RlbGltaXRlciddID0gKGpzb24pLT5cbiAgICB7XG4gICAgJ3VpZCcgOiB1aWRcbiAgICAncHJldicgOiBwcmV2XG4gICAgJ25leHQnIDogbmV4dFxuICAgIH0gPSBqc29uXG4gICAgbmV3IERlbGltaXRlciB1aWQsIHByZXYsIG5leHRcblxuICAjIFRoaXMgaXMgd2hhdCB0aGlzIG1vZHVsZSBleHBvcnRzIGFmdGVyIGluaXRpYWxpemluZyBpdCB3aXRoIHRoZSBIaXN0b3J5QnVmZmVyXG4gIHtcbiAgICAndHlwZXMnIDpcbiAgICAgICdEZWxldGUnIDogRGVsZXRlXG4gICAgICAnSW5zZXJ0JyA6IEluc2VydFxuICAgICAgJ0RlbGltaXRlcic6IERlbGltaXRlclxuICAgICAgJ09wZXJhdGlvbic6IE9wZXJhdGlvblxuICAgICAgJ0ltbXV0YWJsZU9iamVjdCcgOiBJbW11dGFibGVPYmplY3RcbiAgICAncGFyc2VyJyA6IHBhcnNlclxuICAgICdleGVjdXRpb25fbGlzdGVuZXInIDogZXhlY3V0aW9uX2xpc3RlbmVyXG4gIH1cblxuXG5cblxuIiwidGV4dF90eXBlc191bmluaXRpYWxpemVkID0gcmVxdWlyZSBcIi4vVGV4dFR5cGVzXCJcblxubW9kdWxlLmV4cG9ydHMgPSAoSEIpLT5cbiAgdGV4dF90eXBlcyA9IHRleHRfdHlwZXNfdW5pbml0aWFsaXplZCBIQlxuICB0eXBlcyA9IHRleHRfdHlwZXMudHlwZXNcbiAgcGFyc2VyID0gdGV4dF90eXBlcy5wYXJzZXJcblxuICBjcmVhdGVKc29uV3JhcHBlciA9IChfanNvblR5cGUpLT5cblxuICAgICNcbiAgICAjIEEgSnNvbldyYXBwZXIgd2FzIGludGVuZGVkIHRvIGJlIGEgY29udmVuaWVudCB3cmFwcGVyIGZvciB0aGUgSnNvblR5cGUuXG4gICAgIyBCdXQgaXQgY2FuIG1ha2UgdGhpbmdzIG1vcmUgZGlmZmljdWx0IHRoYW4gdGhleSBhcmUuXG4gICAgIyBAc2VlIEpzb25UeXBlXG4gICAgI1xuICAgICMgQGV4YW1wbGUgY3JlYXRlIGEgSnNvbldyYXBwZXJcbiAgICAjICAgIyBZb3UgZ2V0IGEgSnNvbldyYXBwZXIgZnJvbSBhIEpzb25UeXBlIGJ5IGNhbGxpbmdcbiAgICAjICAgdyA9IHlhdHRhLnZhbHVlXG4gICAgI1xuICAgICMgSXQgY3JlYXRlcyBKYXZhc2NyaXB0cyAtZ2V0dGVyIGFuZCAtc2V0dGVyIG1ldGhvZHMgZm9yIGVhY2ggcHJvcGVydHkgdGhhdCBKc29uVHlwZSBtYWludGFpbnMuXG4gICAgIyBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL09iamVjdC9kZWZpbmVQcm9wZXJ0eVxuICAgICNcbiAgICAjIEBleGFtcGxlIEdldHRlciBFeGFtcGxlXG4gICAgIyAgICMgeW91IGNhbiBhY2Nlc3MgdGhlIHggcHJvcGVydHkgb2YgeWF0dGEgYnkgY2FsbGluZ1xuICAgICMgICB3LnhcbiAgICAjICAgIyBpbnN0ZWFkIG9mXG4gICAgIyAgIHlhdHRhLnZhbCgneCcpXG4gICAgI1xuICAgICMgQG5vdGUgWW91IGNhbiBvbmx5IG92ZXJ3cml0ZSBleGlzdGluZyB2YWx1ZXMhIFNldHRpbmcgYSBuZXcgcHJvcGVydHkgd29uJ3QgaGF2ZSBhbnkgZWZmZWN0IVxuICAgICNcbiAgICAjIEBleGFtcGxlIFNldHRlciBFeGFtcGxlXG4gICAgIyAgICMgeW91IGNhbiBzZXQgYW4gZXhpc3RpbmcgeCBwcm9wZXJ0eSBvZiB5YXR0YSBieSBjYWxsaW5nXG4gICAgIyAgIHcueCA9IFwidGV4dFwiXG4gICAgIyAgICMgaW5zdGVhZCBvZlxuICAgICMgICB5YXR0YS52YWwoJ3gnLCBcInRleHRcIilcbiAgICAjXG4gICAgIyBJbiBvcmRlciB0byBzZXQgYSBuZXcgcHJvcGVydHkgeW91IGhhdmUgdG8gb3ZlcndyaXRlIGFuIGV4aXN0aW5nIHByb3BlcnR5LlxuICAgICMgVGhlcmVmb3JlIHRoZSBKc29uV3JhcHBlciBzdXBwb3J0cyBhIHNwZWNpYWwgZmVhdHVyZSB0aGF0IHNob3VsZCBtYWtlIHRoaW5ncyBtb3JlIGNvbnZlbmllbnRcbiAgICAjICh3ZSBjYW4gYXJndWUgYWJvdXQgdGhhdCwgdXNlIHRoZSBKc29uVHlwZSBpZiB5b3UgZG9uJ3QgbGlrZSBpdCA7KS5cbiAgICAjIElmIHlvdSBvdmVyd3JpdGUgYW4gb2JqZWN0IHByb3BlcnR5IG9mIHRoZSBKc29uV3JhcHBlciB3aXRoIGEgbmV3IG9iamVjdCwgaXQgd2lsbCByZXN1bHQgaW4gYSBtZXJnZWQgdmVyc2lvbiBvZiB0aGUgb2JqZWN0cy5cbiAgICAjIExldCB3LnAgdGhlIHByb3BlcnR5IHRoYXQgaXMgdG8gYmUgb3ZlcndyaXR0ZW4gYW5kIG8gdGhlIG5ldyB2YWx1ZS4gRS5nLiB3LnAgPSBvXG4gICAgIyAqIFRoZSByZXN1bHQgaGFzIGFsbCBwcm9wZXJ0aWVzIG9mIG9cbiAgICAjICogVGhlIHJlc3VsdCBoYXMgYWxsIHByb3BlcnRpZXMgb2Ygdy5wIGlmIHRoZXkgZG9uJ3Qgb2NjdXIgdW5kZXIgdGhlIHNhbWUgcHJvcGVydHktbmFtZSBpbiBvLlxuICAgICNcbiAgICAjIEBleGFtcGxlIENvbmZsaWN0IEV4YW1wbGVcbiAgICAjICAgeWF0dGEudmFsdWUgPSB7YSA6IFwic3RyaW5nXCJ9XG4gICAgIyAgIHcgPSB5YXR0YS52YWx1ZVxuICAgICMgICBjb25zb2xlLmxvZyh3KSAjIHthIDogXCJzdHJpbmdcIn1cbiAgICAjICAgdy5hID0ge2EgOiB7YiA6IFwic3RyaW5nXCJ9fVxuICAgICMgICBjb25zb2xlLmxvZyh3KSAjIHthIDoge2IgOiBcIlN0cmluZ1wifX1cbiAgICAjICAgdy5hID0ge2EgOiB7YyA6IDR9fVxuICAgICMgICBjb25zb2xlLmxvZyh3KSAjIHthIDoge2IgOiBcIlN0cmluZ1wiLCBjIDogNH19XG4gICAgI1xuICAgICMgQGV4YW1wbGUgQ29tbW9uIFBpdGZhbGxzXG4gICAgIyAgIHcgPSB5YXR0YS52YWx1ZVxuICAgICMgICAjIFNldHRpbmcgYSBuZXcgcHJvcGVydHlcbiAgICAjICAgdy5uZXdQcm9wZXJ0eSA9IFwiQXdlc29tZVwiXG4gICAgIyAgIGNvbnNvbGUubG9nKHcubmV3UHJvcGVydHkgPT0gXCJBd2Vzb21lXCIpICMgZmFsc2UsIHcubmV3UHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgIyAgICMgb3ZlcndyaXRlIHRoZSB3IG9iamVjdFxuICAgICMgICB3ID0ge25ld1Byb3BlcnR5IDogXCJBd2Vzb21lXCJ9XG4gICAgIyAgIGNvbnNvbGUubG9nKHcubmV3UHJvcGVydHkgPT0gXCJBd2Vzb21lXCIpICMgdHJ1ZSEsIGJ1dCAuLlxuICAgICMgICBjb25zb2xlLmxvZyh5YXR0YS52YWx1ZS5uZXdQcm9wZXJ0eSA9PSBcIkF3ZXNvbWVcIikgIyBmYWxzZSwgeW91IGFyZSBvbmx5IGFsbG93ZWQgdG8gc2V0IHByb3BlcnRpZXMhXG4gICAgIyAgICMgVGhlIHNvbHV0aW9uXG4gICAgIyAgIHlhdHRhLnZhbHVlID0ge25ld1Byb3BlcnR5IDogXCJBd2Vzb21lXCJ9XG4gICAgIyAgIGNvbnNvbGUubG9nKHcubmV3UHJvcGVydHkgPT0gXCJBd2Vzb21lXCIpICMgdHJ1ZSFcbiAgICAjXG4gICAgY2xhc3MgSnNvbldyYXBwZXJcblxuICAgICAgI1xuICAgICAgIyBAcGFyYW0ge0pzb25UeXBlfSBqc29uVHlwZSBJbnN0YW5jZSBvZiB0aGUgSnNvblR5cGUgdGhhdCB0aGlzIGNsYXNzIHdyYXBwZXMuXG4gICAgICAjXG4gICAgICBjb25zdHJ1Y3RvcjogKGpzb25UeXBlKS0+XG4gICAgICAgIGZvciBuYW1lLCBvYmogb2YganNvblR5cGUubWFwXG4gICAgICAgICAgZG8gKG5hbWUsIG9iaiktPlxuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5IEpzb25XcmFwcGVyLnByb3RvdHlwZSwgbmFtZSxcbiAgICAgICAgICAgICAgZ2V0IDogLT5cbiAgICAgICAgICAgICAgICB4ID0gb2JqLnZhbCgpXG4gICAgICAgICAgICAgICAgaWYgeCBpbnN0YW5jZW9mIEpzb25UeXBlXG4gICAgICAgICAgICAgICAgICBjcmVhdGVKc29uV3JhcHBlciB4XG4gICAgICAgICAgICAgICAgZWxzZSBpZiB4IGluc3RhbmNlb2YgdHlwZXMuSW1tdXRhYmxlT2JqZWN0XG4gICAgICAgICAgICAgICAgICB4LnZhbCgpXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgeFxuICAgICAgICAgICAgICBzZXQgOiAobyktPlxuICAgICAgICAgICAgICAgIGlmIG8uY29uc3RydWN0b3IgaXMge30uY29uc3RydWN0b3JcbiAgICAgICAgICAgICAgICAgIG92ZXJ3cml0ZSA9IGpzb25UeXBlLnZhbChuYW1lKVxuICAgICAgICAgICAgICAgICAgZm9yIG9fbmFtZSxvX29iaiBvZiBvXG4gICAgICAgICAgICAgICAgICAgIG92ZXJ3cml0ZS52YWwob19uYW1lLCBvX29iaiwgJ2ltbXV0YWJsZScpXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAganNvblR5cGUudmFsKG5hbWUsIG8sICdpbW11dGFibGUnKVxuICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2VcbiAgICBuZXcgSnNvbldyYXBwZXIgX2pzb25UeXBlXG5cbiAgI1xuICAjIE1hbmFnZXMgT2JqZWN0LWxpa2UgdmFsdWVzLlxuICAjXG4gIGNsYXNzIEpzb25UeXBlIGV4dGVuZHMgdHlwZXMuTWFwTWFuYWdlclxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IGluaXRpYWxfdmFsdWUgQ3JlYXRlIHRoaXMgb3BlcmF0aW9uIHdpdGggYW4gaW5pdGlhbCB2YWx1ZS5cbiAgICAjIEBwYXJhbSB7U3RyaW5nfEJvb2xlYW59IFdoZXRoZXIgdGhlIGluaXRpYWxfdmFsdWUgc2hvdWxkIGJlIGNyZWF0ZWQgYXMgbXV0YWJsZS4gKE9wdGlvbmFsIC0gc2VlIHNldE11dGFibGVEZWZhdWx0KVxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgaW5pdGlhbF92YWx1ZSwgbXV0YWJsZSktPlxuICAgICAgc3VwZXIgdWlkXG4gICAgICBpZiBpbml0aWFsX3ZhbHVlP1xuICAgICAgICBpZiB0eXBlb2YgaW5pdGlhbF92YWx1ZSBpc250IFwib2JqZWN0XCJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJUaGUgaW5pdGlhbCB2YWx1ZSBvZiBKc29uVHlwZXMgbXVzdCBiZSBvZiB0eXBlIE9iamVjdCEgKGN1cnJlbnQgdHlwZTogI3t0eXBlb2YgaW5pdGlhbF92YWx1ZX0pXCJcbiAgICAgICAgZm9yIG5hbWUsbyBvZiBpbml0aWFsX3ZhbHVlXG4gICAgICAgICAgQHZhbCBuYW1lLCBvLCBtdXRhYmxlXG5cbiAgICAjXG4gICAgIyBXaGV0aGVyIHRoZSBkZWZhdWx0IGlzICdtdXRhYmxlJyAodHJ1ZSkgb3IgJ2ltbXV0YWJsZScgKGZhbHNlKVxuICAgICNcbiAgICBtdXRhYmxlX2RlZmF1bHQ6XG4gICAgICB0cnVlXG5cbiAgICAjXG4gICAgIyBTZXQgaWYgdGhlIGRlZmF1bHQgaXMgJ211dGFibGUnIG9yICdpbW11dGFibGUnXG4gICAgIyBAcGFyYW0ge1N0cmluZ3xCb29sZWFufSBtdXRhYmxlIFNldCBlaXRoZXIgJ211dGFibGUnIC8gdHJ1ZSBvciAnaW1tdXRhYmxlJyAvIGZhbHNlXG4gICAgc2V0TXV0YWJsZURlZmF1bHQ6IChtdXRhYmxlKS0+XG4gICAgICBpZiBtdXRhYmxlIGlzIHRydWUgb3IgbXV0YWJsZSBpcyAnbXV0YWJsZSdcbiAgICAgICAgSnNvblR5cGUucHJvdG90eXBlLm11dGFibGVfZGVmYXVsdCA9IHRydWVcbiAgICAgIGVsc2UgaWYgbXV0YWJsZSBpcyBmYWxzZSBvciBtdXRhYmxlIGlzICdpbW11dGFibGUnXG4gICAgICAgIEpzb25UeXBlLnByb3RvdHlwZS5tdXRhYmxlX2RlZmF1bHQgPSBmYWxzZVxuICAgICAgZWxzZVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgJ1NldCBtdXRhYmxlIGVpdGhlciBcIm11dGFibGVcIiBvciBcImltbXV0YWJsZVwiISdcbiAgICAgICdPSydcblxuICAgICNcbiAgICAjIEBvdmVybG9hZCB2YWwoKVxuICAgICMgICBHZXQgdGhpcyBhcyBhIEpzb24gb2JqZWN0LlxuICAgICMgICBAcmV0dXJuIFtKc29uXVxuICAgICNcbiAgICAjIEBvdmVybG9hZCB2YWwobmFtZSlcbiAgICAjICAgR2V0IHZhbHVlIG9mIGEgcHJvcGVydHkuXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIG9iamVjdCBwcm9wZXJ0eS5cbiAgICAjICAgQHJldHVybiBbSnNvblR5cGV8V29yZHxTdHJpbmd8T2JqZWN0XSBEZXBlbmRpbmcgb24gdGhlIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eS4gSWYgbXV0YWJsZSBpdCB3aWxsIHJldHVybiBhIE9wZXJhdGlvbi10eXBlIG9iamVjdCwgaWYgaW1tdXRhYmxlIGl0IHdpbGwgcmV0dXJuIFN0cmluZy9PYmplY3QuXG4gICAgI1xuICAgICMgQG92ZXJsb2FkIHZhbChuYW1lLCBjb250ZW50KVxuICAgICMgICBTZXQgYSBuZXcgcHJvcGVydHkuXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIG9iamVjdCBwcm9wZXJ0eS5cbiAgICAjICAgQHBhcmFtIHtPYmplY3R8U3RyaW5nfSBjb250ZW50IENvbnRlbnQgb2YgdGhlIG9iamVjdCBwcm9wZXJ0eS5cbiAgICAjICAgQHJldHVybiBbSnNvblR5cGVdIFRoaXMgb2JqZWN0LiAoc3VwcG9ydHMgY2hhaW5pbmcpXG4gICAgI1xuICAgIHZhbDogKG5hbWUsIGNvbnRlbnQsIG11dGFibGUpLT5cbiAgICAgIGlmIHR5cGVvZiBuYW1lIGlzICdvYmplY3QnXG4gICAgICAgICMgU3BlY2lhbCBjYXNlLiBGaXJzdCBhcmd1bWVudCBpcyBhbiBvYmplY3QuIFRoZW4gdGhlIHNlY29uZCBhcmcgaXMgbXV0YWJsZS5cbiAgICAgICAgIyBLZWVwIHRoYXQgaW4gbWluZCB3aGVuIHJlYWRpbmcgdGhlIGZvbGxvd2luZy4uXG4gICAgICAgIGZvciBvX25hbWUsbyBvZiBuYW1lXG4gICAgICAgICAgQHZhbChvX25hbWUsbyxjb250ZW50KVxuICAgICAgICBAXG4gICAgICBlbHNlIGlmIG5hbWU/IGFuZCBjb250ZW50P1xuICAgICAgICBpZiBtdXRhYmxlP1xuICAgICAgICAgIGlmIG11dGFibGUgaXMgdHJ1ZSBvciBtdXRhYmxlIGlzICdtdXRhYmxlJ1xuICAgICAgICAgICAgbXV0YWJsZSA9IHRydWVcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBtdXRhYmxlID0gZmFsc2VcbiAgICAgICAgZWxzZVxuICAgICAgICAgIG11dGFibGUgPSBAbXV0YWJsZV9kZWZhdWx0XG4gICAgICAgIGlmIHR5cGVvZiBjb250ZW50IGlzICdmdW5jdGlvbidcbiAgICAgICAgICBAICMgSnVzdCBkbyBub3RoaW5nXG4gICAgICAgIGVsc2UgaWYgKChub3QgbXV0YWJsZSkgb3IgdHlwZW9mIGNvbnRlbnQgaXMgJ251bWJlcicpIGFuZCBjb250ZW50LmNvbnN0cnVjdG9yIGlzbnQgT2JqZWN0XG4gICAgICAgICAgb2JqID0gSEIuYWRkT3BlcmF0aW9uKG5ldyB0eXBlcy5JbW11dGFibGVPYmplY3QgdW5kZWZpbmVkLCBjb250ZW50KS5leGVjdXRlKClcbiAgICAgICAgICBzdXBlciBuYW1lLCBvYmpcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGlmIHR5cGVvZiBjb250ZW50IGlzICdzdHJpbmcnXG4gICAgICAgICAgICB3b3JkID0gSEIuYWRkT3BlcmF0aW9uKG5ldyB0eXBlcy5Xb3JkIHVuZGVmaW5lZCkuZXhlY3V0ZSgpXG4gICAgICAgICAgICB3b3JkLmluc2VydFRleHQgMCwgY29udGVudFxuICAgICAgICAgICAgc3VwZXIgbmFtZSwgd29yZFxuICAgICAgICAgIGVsc2UgaWYgY29udGVudC5jb25zdHJ1Y3RvciBpcyBPYmplY3RcbiAgICAgICAgICAgIGpzb24gPSBIQi5hZGRPcGVyYXRpb24obmV3IEpzb25UeXBlIHVuZGVmaW5lZCwgY29udGVudCwgbXV0YWJsZSkuZXhlY3V0ZSgpXG4gICAgICAgICAgICBzdXBlciBuYW1lLCBqc29uXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3Qgbm90IHNldCAje3R5cGVvZiBjb250ZW50fS10eXBlcyBpbiBjb2xsYWJvcmF0aXZlIEpzb24tb2JqZWN0cyFcIlxuICAgICAgZWxzZVxuICAgICAgICBzdXBlciBuYW1lLCBjb250ZW50XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkgSnNvblR5cGUucHJvdG90eXBlLCAndmFsdWUnLFxuICAgICAgZ2V0IDogLT4gY3JlYXRlSnNvbldyYXBwZXIgQFxuICAgICAgc2V0IDogKG8pLT5cbiAgICAgICAgaWYgby5jb25zdHJ1Y3RvciBpcyB7fS5jb25zdHJ1Y3RvclxuICAgICAgICAgIGZvciBvX25hbWUsb19vYmogb2Ygb1xuICAgICAgICAgICAgQHZhbChvX25hbWUsIG9fb2JqLCAnaW1tdXRhYmxlJylcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBtdXN0IG9ubHkgc2V0IE9iamVjdCB2YWx1ZXMhXCJcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIHtcbiAgICAgICAgJ3R5cGUnIDogXCJKc29uVHlwZVwiXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICB9XG5cbiAgcGFyc2VyWydKc29uVHlwZSddID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgIH0gPSBqc29uXG4gICAgbmV3IEpzb25UeXBlIHVpZFxuXG5cblxuXG4gIHR5cGVzWydKc29uVHlwZSddID0gSnNvblR5cGVcblxuICB0ZXh0X3R5cGVzXG5cblxuIiwiYmFzaWNfdHlwZXNfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuL0Jhc2ljVHlwZXNcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IChIQiktPlxuICBiYXNpY190eXBlcyA9IGJhc2ljX3R5cGVzX3VuaW5pdGlhbGl6ZWQgSEJcbiAgdHlwZXMgPSBiYXNpY190eXBlcy50eXBlc1xuICBwYXJzZXIgPSBiYXNpY190eXBlcy5wYXJzZXJcblxuICAjXG4gICMgTWFuYWdlcyBtYXAgbGlrZSBvYmplY3RzLiBFLmcuIEpzb24tVHlwZSBhbmQgWE1MIGF0dHJpYnV0ZXMuXG4gICNcbiAgY2xhc3MgTWFwTWFuYWdlciBleHRlbmRzIHR5cGVzLk9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCktPlxuICAgICAgQG1hcCA9IHt9XG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIEBzZWUgSnNvblR5cGVzLnZhbFxuICAgICNcbiAgICB2YWw6IChuYW1lLCBjb250ZW50KS0+XG4gICAgICBpZiBjb250ZW50P1xuICAgICAgICBpZiBub3QgQG1hcFtuYW1lXT9cbiAgICAgICAgICBIQi5hZGRPcGVyYXRpb24obmV3IEFkZE5hbWUgdW5kZWZpbmVkLCBALCBuYW1lKS5leGVjdXRlKClcbiAgICAgICAgQG1hcFtuYW1lXS5yZXBsYWNlIGNvbnRlbnRcbiAgICAgICAgQFxuICAgICAgZWxzZSBpZiBuYW1lP1xuICAgICAgICBvYmogPSBAbWFwW25hbWVdPy52YWwoKVxuICAgICAgICBpZiBvYmogaW5zdGFuY2VvZiB0eXBlcy5JbW11dGFibGVPYmplY3RcbiAgICAgICAgICBvYmoudmFsKClcbiAgICAgICAgZWxzZVxuICAgICAgICAgIG9ialxuICAgICAgZWxzZVxuICAgICAgICByZXN1bHQgPSB7fVxuICAgICAgICBmb3IgbmFtZSxvIG9mIEBtYXBcbiAgICAgICAgICBvYmogPSBvLnZhbCgpXG4gICAgICAgICAgaWYgb2JqIGluc3RhbmNlb2YgdHlwZXMuSW1tdXRhYmxlT2JqZWN0IG9yIG9iaiBpbnN0YW5jZW9mIE1hcE1hbmFnZXJcbiAgICAgICAgICAgIG9iaiA9IG9iai52YWwoKVxuICAgICAgICAgIHJlc3VsdFtuYW1lXSA9IG9ialxuICAgICAgICByZXN1bHRcblxuICAjXG4gICMgV2hlbiBhIG5ldyBwcm9wZXJ0eSBpbiBhIG1hcCBtYW5hZ2VyIGlzIGNyZWF0ZWQsIHRoZW4gdGhlIHVpZHMgb2YgdGhlIGluc2VydGVkIE9wZXJhdGlvbnNcbiAgIyBtdXN0IGJlIHVuaXF1ZSAodGhpbmsgYWJvdXQgY29uY3VycmVudCBvcGVyYXRpb25zKS4gVGhlcmVmb3JlIG9ubHkgYW4gQWRkTmFtZSBvcGVyYXRpb24gaXMgYWxsb3dlZCB0b1xuICAjIGFkZCBhIHByb3BlcnR5IGluIGEgTWFwTWFuYWdlci4gSWYgdHdvIEFkZE5hbWUgb3BlcmF0aW9ucyBvbiB0aGUgc2FtZSBNYXBNYW5hZ2VyIG5hbWUgaGFwcGVuIGNvbmN1cnJlbnRseVxuICAjIG9ubHkgb25lIHdpbGwgQWRkTmFtZSBvcGVyYXRpb24gd2lsbCBiZSBleGVjdXRlZC5cbiAgI1xuICBjbGFzcyBBZGROYW1lIGV4dGVuZHMgdHlwZXMuT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gbWFwX21hbmFnZXIgVWlkIG9yIHJlZmVyZW5jZSB0byB0aGUgTWFwTWFuYWdlci5cbiAgICAjIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIHByb3BlcnR5IHRoYXQgd2lsbCBiZSBhZGRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIG1hcF9tYW5hZ2VyLCBAbmFtZSktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ21hcF9tYW5hZ2VyJywgbWFwX21hbmFnZXJcbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgSWYgbWFwX21hbmFnZXIgZG9lc24ndCBoYXZlIHRoZSBwcm9wZXJ0eSBuYW1lLCB0aGVuIGFkZCBpdC5cbiAgICAjIFRoZSBSZXBsYWNlTWFuYWdlciB0aGF0IGlzIGJlaW5nIHdyaXR0ZW4gb24gdGhlIHByb3BlcnR5IGlzIHVuaXF1ZVxuICAgICMgaW4gc3VjaCBhIHdheSB0aGF0IGlmIEFkZE5hbWUgaXMgZXhlY3V0ZWQgKGZyb20gYW5vdGhlciBwZWVyKSBpdCB3aWxsXG4gICAgIyBhbHdheXMgaGF2ZSB0aGUgc2FtZSByZXN1bHQgKFJlcGxhY2VNYW5hZ2VyLCBhbmQgaXRzIGJlZ2lubmluZyBhbmQgZW5kIGFyZSB0aGUgc2FtZSlcbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgbm90IEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgZWxzZVxuICAgICAgICB1aWRfciA9IEBtYXBfbWFuYWdlci5nZXRVaWQoKVxuICAgICAgICB1aWRfci5vcF9udW1iZXIgPSBcIl8je3VpZF9yLm9wX251bWJlcn1fUk1fI3tAbmFtZX1cIlxuICAgICAgICBpZiBub3QgSEIuZ2V0T3BlcmF0aW9uKHVpZF9yKT9cbiAgICAgICAgICB1aWRfYmVnID0gQG1hcF9tYW5hZ2VyLmdldFVpZCgpXG4gICAgICAgICAgdWlkX2JlZy5vcF9udW1iZXIgPSBcIl8je3VpZF9iZWcub3BfbnVtYmVyfV9STV8je0BuYW1lfV9iZWdpbm5pbmdcIlxuICAgICAgICAgIHVpZF9lbmQgPSBAbWFwX21hbmFnZXIuZ2V0VWlkKClcbiAgICAgICAgICB1aWRfZW5kLm9wX251bWJlciA9IFwiXyN7dWlkX2VuZC5vcF9udW1iZXJ9X1JNXyN7QG5hbWV9X2VuZFwiXG4gICAgICAgICAgYmVnID0gSEIuYWRkT3BlcmF0aW9uKG5ldyB0eXBlcy5EZWxpbWl0ZXIgdWlkX2JlZywgdW5kZWZpbmVkLCB1aWRfZW5kKS5leGVjdXRlKClcbiAgICAgICAgICBlbmQgPSBIQi5hZGRPcGVyYXRpb24obmV3IHR5cGVzLkRlbGltaXRlciB1aWRfZW5kLCBiZWcsIHVuZGVmaW5lZCkuZXhlY3V0ZSgpXG4gICAgICAgICAgI2JlZy5leGVjdXRlKClcbiAgICAgICAgICBAbWFwX21hbmFnZXIubWFwW0BuYW1lXSA9IEhCLmFkZE9wZXJhdGlvbihuZXcgUmVwbGFjZU1hbmFnZXIgdW5kZWZpbmVkLCB1aWRfciwgYmVnLCBlbmQpLmV4ZWN1dGUoKVxuICAgICAgICBzdXBlclxuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAge1xuICAgICAgICAndHlwZScgOiBcIkFkZE5hbWVcIlxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAnbWFwX21hbmFnZXInIDogQG1hcF9tYW5hZ2VyLmdldFVpZCgpXG4gICAgICAgICduYW1lJyA6IEBuYW1lXG4gICAgICB9XG5cbiAgcGFyc2VyWydBZGROYW1lJ10gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdtYXBfbWFuYWdlcicgOiBtYXBfbWFuYWdlclxuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICduYW1lJyA6IG5hbWVcbiAgICB9ID0ganNvblxuICAgIG5ldyBBZGROYW1lIHVpZCwgbWFwX21hbmFnZXIsIG5hbWVcblxuICAjXG4gICMgTWFuYWdlcyBhIGxpc3Qgb2YgSW5zZXJ0LXR5cGUgb3BlcmF0aW9ucy5cbiAgI1xuICBjbGFzcyBMaXN0TWFuYWdlciBleHRlbmRzIHR5cGVzLkluc2VydFxuXG4gICAgI1xuICAgICMgQSBMaXN0TWFuYWdlciBtYWludGFpbnMgYSBub24tZW1wdHkgbGlzdCB0aGF0IGhhcyBhIGJlZ2lubmluZyBhbmQgYW4gZW5kIChib3RoIERlbGltaXRlcnMhKVxuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGJlZ2lubmluZyBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGVuZCBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBpZiBiZWdpbm5pbmc/IGFuZCBlbmQ/XG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdiZWdpbm5pbmcnLCBiZWdpbm5pbmdcbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ2VuZCcsIGVuZFxuICAgICAgZWxzZVxuICAgICAgICBAYmVnaW5uaW5nID0gSEIuYWRkT3BlcmF0aW9uIG5ldyB0eXBlcy5EZWxpbWl0ZXIgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZFxuICAgICAgICBAZW5kID0gICAgICAgSEIuYWRkT3BlcmF0aW9uIG5ldyB0eXBlcy5EZWxpbWl0ZXIgdW5kZWZpbmVkLCBAYmVnaW5uaW5nLCB1bmRlZmluZWRcbiAgICAgICAgQGJlZ2lubmluZy5uZXh0X2NsID0gQGVuZFxuICAgICAgICBAYmVnaW5uaW5nLmV4ZWN1dGUoKVxuICAgICAgICBAZW5kLmV4ZWN1dGUoKVxuICAgICAgc3VwZXIgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIEBiZWdpbm5pbmcuc2V0UGFyZW50IEBcbiAgICAgICAgQGVuZC5zZXRQYXJlbnQgQFxuICAgICAgICBzdXBlclxuICAgICAgZWxzZVxuICAgICAgICBmYWxzZVxuXG4gICAgIyBHZXQgdGhlIGVsZW1lbnQgcHJldmlvdXMgdG8gdGhlIGRlbGVtaXRlciBhdCB0aGUgZW5kXG4gICAgZ2V0TGFzdE9wZXJhdGlvbjogKCktPlxuICAgICAgQGVuZC5wcmV2X2NsXG5cbiAgICAjIHNpbWlsYXIgdG8gdGhlIGFib3ZlXG4gICAgZ2V0Rmlyc3RPcGVyYXRpb246ICgpLT5cbiAgICAgIEBiZWdpbm5pbmcubmV4dF9jbFxuXG4gICAgIyBUcmFuc2Zvcm1zIHRoZSB0aGUgbGlzdCB0byBhbiBhcnJheVxuICAgICMgRG9lc24ndCByZXR1cm4gbGVmdC1yaWdodCBkZWxpbWl0ZXIuXG4gICAgdG9BcnJheTogKCktPlxuICAgICAgbyA9IEBiZWdpbm5pbmcubmV4dF9jbFxuICAgICAgcmVzdWx0ID0gW11cbiAgICAgIHdoaWxlIG8gaXNudCBAZW5kXG4gICAgICAgIHJlc3VsdC5wdXNoIG9cbiAgICAgICAgbyA9IG8ubmV4dF9jbFxuICAgICAgcmVzdWx0XG5cbiAgICAjXG4gICAgIyBSZXRyaWV2ZXMgdGhlIHgtdGggbm90IGRlbGV0ZWQgZWxlbWVudC5cbiAgICAjXG4gICAgZ2V0T3BlcmF0aW9uQnlQb3NpdGlvbjogKHBvc2l0aW9uKS0+XG4gICAgICBvID0gQGJlZ2lubmluZy5uZXh0X2NsXG4gICAgICBpZiAocG9zaXRpb24gPiAwIG9yIG8uaXNEZWxldGVkKCkpIGFuZCBub3QgKG8gaW5zdGFuY2VvZiB0eXBlcy5EZWxpbWl0ZXIpXG4gICAgICAgIHdoaWxlIG8uaXNEZWxldGVkKCkgYW5kIG5vdCAobyBpbnN0YW5jZW9mIHR5cGVzLkRlbGltaXRlcilcbiAgICAgICAgICAjIGZpbmQgZmlyc3Qgbm9uIGRlbGV0ZWQgb3BcbiAgICAgICAgICBvID0gby5uZXh0X2NsXG4gICAgICAgIHdoaWxlIHRydWVcbiAgICAgICAgICAjIGZpbmQgdGhlIGktdGggb3BcbiAgICAgICAgICBpZiBvIGluc3RhbmNlb2YgdHlwZXMuRGVsaW1pdGVyXG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIGlmIHBvc2l0aW9uIDw9IDAgYW5kIG5vdCBvLmlzRGVsZXRlZCgpXG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgICBpZiBub3Qgby5pc0RlbGV0ZWQoKVxuICAgICAgICAgICAgcG9zaXRpb24gLT0gMVxuXG5cbiAgICAgIG9cblxuICAjXG4gICMgQWRkcyBzdXBwb3J0IGZvciByZXBsYWNlLiBUaGUgUmVwbGFjZU1hbmFnZXIgbWFuYWdlcyBSZXBsYWNlYWJsZSBvcGVyYXRpb25zLlxuICAjIEVhY2ggUmVwbGFjZWFibGUgaG9sZHMgYSB2YWx1ZSB0aGF0IGlzIG5vdyByZXBsYWNlYWJsZS5cbiAgI1xuICAjIFRoZSBXb3JkLXR5cGUgaGFzIGltcGxlbWVudGVkIHN1cHBvcnQgZm9yIHJlcGxhY2VcbiAgIyBAc2VlIFdvcmRcbiAgI1xuICBjbGFzcyBSZXBsYWNlTWFuYWdlciBleHRlbmRzIExpc3RNYW5hZ2VyXG4gICAgI1xuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IGluaXRpYWxfY29udGVudCBJbml0aWFsaXplIHRoaXMgd2l0aCBhIFJlcGxhY2VhYmxlIHRoYXQgaG9sZHMgdGhlIGluaXRpYWxfY29udGVudC5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7RGVsaW1pdGVyfSBiZWdpbm5pbmcgUmVmZXJlbmNlIG9yIE9iamVjdC5cbiAgICAjIEBwYXJhbSB7RGVsaW1pdGVyfSBlbmQgUmVmZXJlbmNlIG9yIE9iamVjdC5cbiAgICBjb25zdHJ1Y3RvcjogKGluaXRpYWxfY29udGVudCwgdWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBzdXBlciB1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW5cbiAgICAgIGlmIGluaXRpYWxfY29udGVudD9cbiAgICAgICAgQHJlcGxhY2UgaW5pdGlhbF9jb250ZW50XG5cbiAgICAjXG4gICAgIyBSZXBsYWNlIHRoZSBleGlzdGluZyB3b3JkIHdpdGggYSBuZXcgd29yZC5cbiAgICAjXG4gICAgcmVwbGFjZTogKGNvbnRlbnQpLT5cbiAgICAgIG8gPSBAZ2V0TGFzdE9wZXJhdGlvbigpXG4gICAgICBvcCA9IG5ldyBSZXBsYWNlYWJsZSBjb250ZW50LCBALCB1bmRlZmluZWQsIG8sIG8ubmV4dF9jbFxuICAgICAgSEIuYWRkT3BlcmF0aW9uKG9wKS5leGVjdXRlKClcblxuICAgICNcbiAgICAjIEdldCB0aGUgdmFsdWUgb2YgdGhpcyBXb3JkXG4gICAgIyBAcmV0dXJuIHtTdHJpbmd9XG4gICAgI1xuICAgIHZhbDogKCktPlxuICAgICAgbyA9IEBnZXRMYXN0T3BlcmF0aW9uKClcbiAgICAgIGlmIG8gaW5zdGFuY2VvZiB0eXBlcy5EZWxpbWl0ZXJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiZHRyblwiXG4gICAgICBvLnZhbCgpXG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID1cbiAgICAgICAge1xuICAgICAgICAgICd0eXBlJzogXCJSZXBsYWNlTWFuYWdlclwiXG4gICAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgICAnYmVnaW5uaW5nJyA6IEBiZWdpbm5pbmcuZ2V0VWlkKClcbiAgICAgICAgICAnZW5kJyA6IEBlbmQuZ2V0VWlkKClcbiAgICAgICAgfVxuICAgICAgaWYgQHByZXZfY2w/IGFuZCBAbmV4dF9jbD9cbiAgICAgICAganNvblsncHJldiddID0gQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgICAganNvblsnbmV4dCddID0gQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgIGlmIEBvcmlnaW4/IGFuZCBAb3JpZ2luIGlzbnQgQHByZXZfY2xcbiAgICAgICAganNvbltcIm9yaWdpblwiXSA9IEBvcmlnaW4uZ2V0VWlkKClcbiAgICAgIGpzb25cblxuICBwYXJzZXJbXCJSZXBsYWNlTWFuYWdlclwiXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ2NvbnRlbnQnIDogY29udGVudFxuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdwcmV2JzogcHJldlxuICAgICAgJ25leHQnOiBuZXh0XG4gICAgICAnb3JpZ2luJyA6IG9yaWdpblxuICAgICAgJ2JlZ2lubmluZycgOiBiZWdpbm5pbmdcbiAgICAgICdlbmQnIDogZW5kXG4gICAgfSA9IGpzb25cbiAgICBuZXcgUmVwbGFjZU1hbmFnZXIgY29udGVudCwgdWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cblxuICAjXG4gICMgVGhlIFJlcGxhY2VNYW5hZ2VyIG1hbmFnZXMgUmVwbGFjZWFibGVzLlxuICAjIEBzZWUgUmVwbGFjZU1hbmFnZXJcbiAgI1xuICBjbGFzcyBSZXBsYWNlYWJsZSBleHRlbmRzIHR5cGVzLkluc2VydFxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IGNvbnRlbnQgVGhlIHZhbHVlIHRoYXQgdGhpcyBSZXBsYWNlYWJsZSBob2xkcy5cbiAgICAjIEBwYXJhbSB7UmVwbGFjZU1hbmFnZXJ9IHBhcmVudCBVc2VkIHRvIHJlcGxhY2UgdGhpcyBSZXBsYWNlYWJsZSB3aXRoIGFub3RoZXIgb25lLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKGNvbnRlbnQsIHBhcmVudCwgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIEBzYXZlT3BlcmF0aW9uICdjb250ZW50JywgY29udGVudFxuICAgICAgQHNhdmVPcGVyYXRpb24gJ3BhcmVudCcsIHBhcmVudFxuICAgICAgaWYgbm90IChwcmV2PyBhbmQgbmV4dD8gYW5kIGNvbnRlbnQ/KVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBkZWZpbmUgY29udGVudCwgcHJldiwgYW5kIG5leHQgZm9yIFJlcGxhY2VhYmxlLXR5cGVzIVwiXG4gICAgICBzdXBlciB1aWQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICAgI1xuICAgICMgUmV0dXJuIHRoZSBjb250ZW50IHRoYXQgdGhpcyBvcGVyYXRpb24gaG9sZHMuXG4gICAgI1xuICAgIHZhbDogKCktPlxuICAgICAgQGNvbnRlbnRcblxuICAgICNcbiAgICAjIFJlcGxhY2UgdGhlIGNvbnRlbnQgb2YgdGhpcyByZXBsYWNlYWJsZSB3aXRoIG5ldyBjb250ZW50LlxuICAgICNcbiAgICByZXBsYWNlOiAoY29udGVudCktPlxuICAgICAgQHBhcmVudC5yZXBsYWNlIGNvbnRlbnRcblxuICAgICNcbiAgICAjIElmIHBvc3NpYmxlIHNldCB0aGUgcmVwbGFjZSBtYW5hZ2VyIGluIHRoZSBjb250ZW50LlxuICAgICMgQHNlZSBXb3JkLnNldFJlcGxhY2VNYW5hZ2VyXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIG5vdCBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIGVsc2VcbiAgICAgICAgQGNvbnRlbnQuc2V0UmVwbGFjZU1hbmFnZXI/KEBwYXJlbnQpXG4gICAgICAgIHN1cGVyXG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID1cbiAgICAgICAge1xuICAgICAgICAgICd0eXBlJzogXCJSZXBsYWNlYWJsZVwiXG4gICAgICAgICAgJ2NvbnRlbnQnOiBAY29udGVudC5nZXRVaWQoKVxuICAgICAgICAgICdSZXBsYWNlTWFuYWdlcicgOiBAcGFyZW50LmdldFVpZCgpXG4gICAgICAgICAgJ3ByZXYnOiBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICAgICduZXh0JzogQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICB9XG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyW1wiUmVwbGFjZWFibGVcIl0gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICdSZXBsYWNlTWFuYWdlcicgOiBwYXJlbnRcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBSZXBsYWNlYWJsZSBjb250ZW50LCBwYXJlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cblxuXG4gIHR5cGVzWydMaXN0TWFuYWdlciddID0gTGlzdE1hbmFnZXJcbiAgdHlwZXNbJ01hcE1hbmFnZXInXSA9IE1hcE1hbmFnZXJcbiAgdHlwZXNbJ1JlcGxhY2VNYW5hZ2VyJ10gPSBSZXBsYWNlTWFuYWdlclxuICB0eXBlc1snUmVwbGFjZWFibGUnXSA9IFJlcGxhY2VhYmxlXG5cbiAgYmFzaWNfdHlwZXNcblxuXG5cblxuXG5cbiIsInN0cnVjdHVyZWRfdHlwZXNfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuL1N0cnVjdHVyZWRUeXBlc1wiXG5cbm1vZHVsZS5leHBvcnRzID0gKEhCKS0+XG4gIHN0cnVjdHVyZWRfdHlwZXMgPSBzdHJ1Y3R1cmVkX3R5cGVzX3VuaW5pdGlhbGl6ZWQgSEJcbiAgdHlwZXMgPSBzdHJ1Y3R1cmVkX3R5cGVzLnR5cGVzXG4gIHBhcnNlciA9IHN0cnVjdHVyZWRfdHlwZXMucGFyc2VyXG5cbiAgI1xuICAjIEF0IHRoZSBtb21lbnQgVGV4dERlbGV0ZSB0eXBlIGVxdWFscyB0aGUgRGVsZXRlIHR5cGUgaW4gQmFzaWNUeXBlcy5cbiAgIyBAc2VlIEJhc2ljVHlwZXMuRGVsZXRlXG4gICNcbiAgY2xhc3MgVGV4dERlbGV0ZSBleHRlbmRzIHR5cGVzLkRlbGV0ZVxuICBwYXJzZXJbXCJUZXh0RGVsZXRlXCJdID0gcGFyc2VyW1wiRGVsZXRlXCJdXG5cbiAgI1xuICAjICBFeHRlbmRzIHRoZSBiYXNpYyBJbnNlcnQgdHlwZSB0byBhbiBvcGVyYXRpb24gdGhhdCBob2xkcyBhIHRleHQgdmFsdWVcbiAgI1xuICBjbGFzcyBUZXh0SW5zZXJ0IGV4dGVuZHMgdHlwZXMuSW5zZXJ0XG4gICAgI1xuICAgICMgQHBhcmFtIHtTdHJpbmd9IGNvbnRlbnQgVGhlIGNvbnRlbnQgb2YgdGhpcyBJbnNlcnQtdHlwZSBPcGVyYXRpb24uIFVzdWFsbHkgeW91IHJlc3RyaWN0IHRoZSBsZW5ndGggb2YgY29udGVudCB0byBzaXplIDFcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6IChAY29udGVudCwgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIGlmIG5vdCAocHJldj8gYW5kIG5leHQ/KVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBkZWZpbmUgcHJldiwgYW5kIG5leHQgZm9yIFRleHRJbnNlcnQtdHlwZXMhXCJcbiAgICAgIHN1cGVyIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG4gICAgI1xuICAgICMgUmV0cmlldmUgdGhlIGVmZmVjdGl2ZSBsZW5ndGggb2YgdGhlICRjb250ZW50IG9mIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICBnZXRMZW5ndGg6ICgpLT5cbiAgICAgIGlmIEBpc0RlbGV0ZWQoKVxuICAgICAgICAwXG4gICAgICBlbHNlXG4gICAgICAgIEBjb250ZW50Lmxlbmd0aFxuXG4gICAgI1xuICAgICMgVGhlIHJlc3VsdCB3aWxsIGJlIGNvbmNhdGVuYXRlZCB3aXRoIHRoZSByZXN1bHRzIGZyb20gdGhlIG90aGVyIGluc2VydCBvcGVyYXRpb25zXG4gICAgIyBpbiBvcmRlciB0byByZXRyaWV2ZSB0aGUgY29udGVudCBvZiB0aGUgZW5naW5lLlxuICAgICMgQHNlZSBIaXN0b3J5QnVmZmVyLnRvRXhlY3V0ZWRBcnJheVxuICAgICNcbiAgICB2YWw6IChjdXJyZW50X3Bvc2l0aW9uKS0+XG4gICAgICBpZiBAaXNEZWxldGVkKClcbiAgICAgICAgXCJcIlxuICAgICAgZWxzZVxuICAgICAgICBAY29udGVudFxuXG4gICAgI1xuICAgICMgQ29udmVydCBhbGwgcmVsZXZhbnQgaW5mb3JtYXRpb24gb2YgdGhpcyBvcGVyYXRpb24gdG8gdGhlIGpzb24tZm9ybWF0LlxuICAgICMgVGhpcyByZXN1bHQgY2FuIGJlIHNlbmQgdG8gb3RoZXIgY2xpZW50cy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9XG4gICAgICAgIHtcbiAgICAgICAgICAndHlwZSc6IFwiVGV4dEluc2VydFwiXG4gICAgICAgICAgJ2NvbnRlbnQnOiBAY29udGVudFxuICAgICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICAgJ3ByZXYnOiBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICAgICduZXh0JzogQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgICAgfVxuICAgICAgaWYgQG9yaWdpbj8gYW5kIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uW1wib3JpZ2luXCJdID0gQG9yaWdpbi5nZXRVaWQoKVxuICAgICAganNvblxuXG4gIHBhcnNlcltcIlRleHRJbnNlcnRcIl0gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBUZXh0SW5zZXJ0IGNvbnRlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cbiAgI1xuICAjIEhhbmRsZXMgYSBUZXh0LWxpa2UgZGF0YSBzdHJ1Y3R1cmVzIHdpdGggc3VwcG9ydCBmb3IgaW5zZXJ0VGV4dC9kZWxldGVUZXh0IGF0IGEgd29yZC1wb3NpdGlvbi5cbiAgI1xuICBjbGFzcyBXb3JkIGV4dGVuZHMgdHlwZXMuTGlzdE1hbmFnZXJcblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIHN1cGVyIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICAgI1xuICAgICMgSW5zZXJ0cyBhIHN0cmluZyBpbnRvIHRoZSB3b3JkXG4gICAgI1xuICAgIGluc2VydFRleHQ6IChwb3NpdGlvbiwgY29udGVudCktPlxuICAgICAgbyA9IEBnZXRPcGVyYXRpb25CeVBvc2l0aW9uIHBvc2l0aW9uXG4gICAgICBmb3IgYyBpbiBjb250ZW50XG4gICAgICAgIG9wID0gbmV3IFRleHRJbnNlcnQgYywgdW5kZWZpbmVkLCBvLnByZXZfY2wsIG9cbiAgICAgICAgSEIuYWRkT3BlcmF0aW9uKG9wKS5leGVjdXRlKClcblxuICAgICNcbiAgICAjIERlbGV0ZXMgYSBwYXJ0IG9mIHRoZSB3b3JkLlxuICAgICNcbiAgICBkZWxldGVUZXh0OiAocG9zaXRpb24sIGxlbmd0aCktPlxuICAgICAgbyA9IEBnZXRPcGVyYXRpb25CeVBvc2l0aW9uIHBvc2l0aW9uXG5cbiAgICAgIGRlbGV0ZV9vcHMgPSBbXVxuICAgICAgZm9yIGkgaW4gWzAuLi5sZW5ndGhdXG4gICAgICAgIGlmIG8gaW5zdGFuY2VvZiB0eXBlcy5EZWxpbWl0ZXJcbiAgICAgICAgICBicmVha1xuICAgICAgICBkID0gSEIuYWRkT3BlcmF0aW9uKG5ldyBUZXh0RGVsZXRlIHVuZGVmaW5lZCwgbykuZXhlY3V0ZSgpXG4gICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgd2hpbGUgbm90IChvIGluc3RhbmNlb2YgdHlwZXMuRGVsaW1pdGVyKSBhbmQgby5pc0RlbGV0ZWQoKVxuICAgICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgZGVsZXRlX29wcy5wdXNoIGQuX2VuY29kZSgpXG4gICAgICBkZWxldGVfb3BzXG5cbiAgICAjXG4gICAgIyBSZXBsYWNlIHRoZSBjb250ZW50IG9mIHRoaXMgd29yZCB3aXRoIGFub3RoZXIgb25lLiBDb25jdXJyZW50IHJlcGxhY2VtZW50cyBhcmUgbm90IG1lcmdlZCFcbiAgICAjIE9ubHkgb25lIG9mIHRoZSByZXBsYWNlbWVudHMgd2lsbCBiZSB1c2VkLlxuICAgICNcbiAgICAjIENhbiBvbmx5IGJlIHVzZWQgaWYgdGhlIFJlcGxhY2VNYW5hZ2VyIHdhcyBzZXQhXG4gICAgIyBAc2VlIFdvcmQuc2V0UmVwbGFjZU1hbmFnZXJcbiAgICAjXG4gICAgcmVwbGFjZVRleHQ6ICh0ZXh0KS0+XG4gICAgICBpZiBAcmVwbGFjZV9tYW5hZ2VyP1xuICAgICAgICB3b3JkID0gSEIuYWRkT3BlcmF0aW9uKG5ldyBXb3JkIHVuZGVmaW5lZCkuZXhlY3V0ZSgpXG4gICAgICAgIHdvcmQuaW5zZXJ0VGV4dCAwLCB0ZXh0XG4gICAgICAgIEByZXBsYWNlX21hbmFnZXIucmVwbGFjZSh3b3JkKVxuICAgICAgZWxzZVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJUaGlzIHR5cGUgaXMgY3VycmVudGx5IG5vdCBtYWludGFpbmVkIGJ5IGEgUmVwbGFjZU1hbmFnZXIhXCJcblxuICAgICNcbiAgICAjIEByZXR1cm5zIFtKc29uXSBBIEpzb24gb2JqZWN0LlxuICAgICNcbiAgICB2YWw6ICgpLT5cbiAgICAgIGMgPSBmb3IgbyBpbiBAdG9BcnJheSgpXG4gICAgICAgIGlmIG8udmFsP1xuICAgICAgICAgIG8udmFsKClcbiAgICAgICAgZWxzZVxuICAgICAgICAgIFwiXCJcbiAgICAgIGMuam9pbignJylcblxuICAgICNcbiAgICAjIEluIG1vc3QgY2FzZXMgeW91IHdvdWxkIGVtYmVkIGEgV29yZCBpbiBhIFJlcGxhY2VhYmxlLCB3aWNoIGlzIGhhbmRsZWQgYnkgdGhlIFJlcGxhY2VNYW5hZ2VyIGluIG9yZGVyXG4gICAgIyB0byBwcm92aWRlIHJlcGxhY2UgZnVuY3Rpb25hbGl0eS5cbiAgICAjXG4gICAgc2V0UmVwbGFjZU1hbmFnZXI6IChvcCktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ3JlcGxhY2VfbWFuYWdlcicsIG9wXG4gICAgICBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnNcblxuICAgICNcbiAgICAjIEJpbmQgdGhpcyBXb3JkIHRvIGEgdGV4dGZpZWxkLlxuICAgICNcbiAgICBiaW5kOiAodGV4dGZpZWxkKS0+XG4gICAgICB3b3JkID0gQFxuICAgICAgdGV4dGZpZWxkLnZhbHVlID0gQHZhbCgpXG5cbiAgICAgIEBvbiBcImluc2VydFwiLCAoZXZlbnQsIG9wKS0+XG4gICAgICAgIG9fcG9zID0gb3AuZ2V0UG9zaXRpb24oKVxuICAgICAgICBmaXggPSAoY3Vyc29yKS0+XG4gICAgICAgICAgaWYgY3Vyc29yIDw9IG9fcG9zXG4gICAgICAgICAgICBjdXJzb3JcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBjdXJzb3IgKz0gMVxuICAgICAgICAgICAgY3Vyc29yXG4gICAgICAgIGxlZnQgPSBmaXggdGV4dGZpZWxkLnNlbGVjdGlvblN0YXJ0XG4gICAgICAgIHJpZ2h0ID0gZml4IHRleHRmaWVsZC5zZWxlY3Rpb25FbmRcblxuICAgICAgICB0ZXh0ZmllbGQudmFsdWUgPSB3b3JkLnZhbCgpXG4gICAgICAgIHRleHRmaWVsZC5zZXRTZWxlY3Rpb25SYW5nZSBsZWZ0LCByaWdodFxuXG5cbiAgICAgIEBvbiBcImRlbGV0ZVwiLCAoZXZlbnQsIG9wKS0+XG4gICAgICAgIG9fcG9zID0gb3AuZ2V0UG9zaXRpb24oKVxuICAgICAgICBmaXggPSAoY3Vyc29yKS0+XG4gICAgICAgICAgaWYgY3Vyc29yIDwgb19wb3NcbiAgICAgICAgICAgIGN1cnNvclxuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGN1cnNvciAtPSAxXG4gICAgICAgICAgICBjdXJzb3JcbiAgICAgICAgbGVmdCA9IGZpeCB0ZXh0ZmllbGQuc2VsZWN0aW9uU3RhcnRcbiAgICAgICAgcmlnaHQgPSBmaXggdGV4dGZpZWxkLnNlbGVjdGlvbkVuZFxuXG4gICAgICAgIHRleHRmaWVsZC52YWx1ZSA9IHdvcmQudmFsKClcbiAgICAgICAgdGV4dGZpZWxkLnNldFNlbGVjdGlvblJhbmdlIGxlZnQsIHJpZ2h0XG5cbiAgICAgICMgY29uc3VtZSBhbGwgdGV4dC1pbnNlcnQgY2hhbmdlcy5cbiAgICAgIHRleHRmaWVsZC5vbmtleXByZXNzID0gKGV2ZW50KS0+XG4gICAgICAgIGNoYXIgPSBudWxsXG4gICAgICAgIGlmIGV2ZW50LmtleT9cbiAgICAgICAgICBpZiBldmVudC5jaGFyQ29kZSBpcyAzMlxuICAgICAgICAgICAgY2hhciA9IFwiIFwiXG4gICAgICAgICAgZWxzZSBpZiBldmVudC5rZXlDb2RlIGlzIDEzXG4gICAgICAgICAgICBjaGFyID0gJ1xcbidcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBjaGFyID0gZXZlbnQua2V5XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBjaGFyID0gU3RyaW5nLmZyb21DaGFyQ29kZSBldmVudC5rZXlDb2RlXG4gICAgICAgIGlmIGNoYXIubGVuZ3RoID4gMFxuICAgICAgICAgIHBvcyA9IE1hdGgubWluIHRleHRmaWVsZC5zZWxlY3Rpb25TdGFydCwgdGV4dGZpZWxkLnNlbGVjdGlvbkVuZFxuICAgICAgICAgIGRpZmYgPSBNYXRoLmFicyh0ZXh0ZmllbGQuc2VsZWN0aW9uRW5kIC0gdGV4dGZpZWxkLnNlbGVjdGlvblN0YXJ0KVxuICAgICAgICAgIHdvcmQuZGVsZXRlVGV4dCAocG9zKSwgZGlmZlxuICAgICAgICAgIHdvcmQuaW5zZXJ0VGV4dCBwb3MsIGNoYXJcbiAgICAgICAgICBuZXdfcG9zID0gcG9zICsgY2hhci5sZW5ndGhcbiAgICAgICAgICB0ZXh0ZmllbGQuc2V0U2VsZWN0aW9uUmFuZ2UgbmV3X3BvcywgbmV3X3Bvc1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KClcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KClcblxuICAgICAgdGV4dGZpZWxkLm9ucGFzdGUgPSAoZXZlbnQpLT5cbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKVxuICAgICAgdGV4dGZpZWxkLm9uY3V0ID0gKGV2ZW50KS0+XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KClcblxuICAgICAgI1xuICAgICAgIyBjb25zdW1lIGRlbGV0ZXMuIE5vdGUgdGhhdFxuICAgICAgIyAgIGNocm9tZTogd29uJ3QgY29uc3VtZSBkZWxldGlvbnMgb24ga2V5cHJlc3MgZXZlbnQuXG4gICAgICAjICAga2V5Q29kZSBpcyBkZXByZWNhdGVkLiBCVVQ6IEkgZG9uJ3Qgc2VlIGFub3RoZXIgd2F5LlxuICAgICAgIyAgICAgc2luY2UgZXZlbnQua2V5IGlzIG5vdCBpbXBsZW1lbnRlZCBpbiB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIGNocm9tZS5cbiAgICAgICMgICAgIEV2ZXJ5IGJyb3dzZXIgc3VwcG9ydHMga2V5Q29kZS4gTGV0J3Mgc3RpY2sgd2l0aCBpdCBmb3Igbm93Li5cbiAgICAgICNcbiAgICAgIHRleHRmaWVsZC5vbmtleWRvd24gPSAoZXZlbnQpLT5cbiAgICAgICAgcG9zID0gTWF0aC5taW4gdGV4dGZpZWxkLnNlbGVjdGlvblN0YXJ0LCB0ZXh0ZmllbGQuc2VsZWN0aW9uRW5kXG4gICAgICAgIGRpZmYgPSBNYXRoLmFicyh0ZXh0ZmllbGQuc2VsZWN0aW9uRW5kIC0gdGV4dGZpZWxkLnNlbGVjdGlvblN0YXJ0KVxuICAgICAgICBpZiBldmVudC5rZXlDb2RlPyBhbmQgZXZlbnQua2V5Q29kZSBpcyA4ICMgQmFja3NwYWNlXG4gICAgICAgICAgaWYgZGlmZiA+IDBcbiAgICAgICAgICAgIHdvcmQuZGVsZXRlVGV4dCBwb3MsIGRpZmZcbiAgICAgICAgICAgIHRleHRmaWVsZC5zZXRTZWxlY3Rpb25SYW5nZSBwb3MsIHBvc1xuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIGlmIGV2ZW50LmN0cmxLZXk/IGFuZCBldmVudC5jdHJsS2V5XG4gICAgICAgICAgICAgIHZhbCA9IHRleHRmaWVsZC52YWx1ZVxuICAgICAgICAgICAgICBuZXdfcG9zID0gcG9zXG4gICAgICAgICAgICAgIGRlbF9sZW5ndGggPSAwXG4gICAgICAgICAgICAgIGlmIHBvcyA+IDBcbiAgICAgICAgICAgICAgICBuZXdfcG9zLS1cbiAgICAgICAgICAgICAgICBkZWxfbGVuZ3RoKytcbiAgICAgICAgICAgICAgd2hpbGUgbmV3X3BvcyA+IDAgYW5kIHZhbFtuZXdfcG9zXSBpc250IFwiIFwiIGFuZCB2YWxbbmV3X3Bvc10gaXNudCAnXFxuJ1xuICAgICAgICAgICAgICAgIG5ld19wb3MtLVxuICAgICAgICAgICAgICAgIGRlbF9sZW5ndGgrK1xuICAgICAgICAgICAgICB3b3JkLmRlbGV0ZVRleHQgbmV3X3BvcywgKHBvcy1uZXdfcG9zKVxuICAgICAgICAgICAgICB0ZXh0ZmllbGQuc2V0U2VsZWN0aW9uUmFuZ2UgbmV3X3BvcywgbmV3X3Bvc1xuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICB3b3JkLmRlbGV0ZVRleHQgKHBvcy0xKSwgMVxuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KClcbiAgICAgICAgZWxzZSBpZiBldmVudC5rZXlDb2RlPyBhbmQgZXZlbnQua2V5Q29kZSBpcyA0NiAjIERlbGV0ZVxuICAgICAgICAgIGlmIGRpZmYgPiAwXG4gICAgICAgICAgICB3b3JkLmRlbGV0ZVRleHQgcG9zLCBkaWZmXG4gICAgICAgICAgICB0ZXh0ZmllbGQuc2V0U2VsZWN0aW9uUmFuZ2UgcG9zLCBwb3NcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICB3b3JkLmRlbGV0ZVRleHQgcG9zLCAxXG4gICAgICAgICAgICB0ZXh0ZmllbGQuc2V0U2VsZWN0aW9uUmFuZ2UgcG9zLCBwb3NcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpXG5cblxuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9IHtcbiAgICAgICAgJ3R5cGUnOiBcIldvcmRcIlxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAnYmVnaW5uaW5nJyA6IEBiZWdpbm5pbmcuZ2V0VWlkKClcbiAgICAgICAgJ2VuZCcgOiBAZW5kLmdldFVpZCgpXG4gICAgICB9XG4gICAgICBpZiBAcHJldl9jbD9cbiAgICAgICAganNvblsncHJldiddID0gQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgIGlmIEBuZXh0X2NsP1xuICAgICAgICBqc29uWyduZXh0J10gPSBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgaWYgQG9yaWdpbj8gYW5kIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uW1wib3JpZ2luXCJdID0gQG9yaWdpbi5nZXRVaWQoKVxuICAgICAganNvblxuXG4gIHBhcnNlclsnV29yZCddID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ2JlZ2lubmluZycgOiBiZWdpbm5pbmdcbiAgICAgICdlbmQnIDogZW5kXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBXb3JkIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gIHR5cGVzWydUZXh0SW5zZXJ0J10gPSBUZXh0SW5zZXJ0XG4gIHR5cGVzWydUZXh0RGVsZXRlJ10gPSBUZXh0RGVsZXRlXG4gIHR5cGVzWydXb3JkJ10gPSBXb3JkXG4gIHN0cnVjdHVyZWRfdHlwZXNcblxuXG4iLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vbGliL2NoYWknKTtcbiIsIi8qIVxuICogY2hhaVxuICogQ29weXJpZ2h0KGMpIDIwMTEtMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbnZhciB1c2VkID0gW11cbiAgLCBleHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLyohXG4gKiBDaGFpIHZlcnNpb25cbiAqL1xuXG5leHBvcnRzLnZlcnNpb24gPSAnMS45LjEnO1xuXG4vKiFcbiAqIEFzc2VydGlvbiBFcnJvclxuICovXG5cbmV4cG9ydHMuQXNzZXJ0aW9uRXJyb3IgPSByZXF1aXJlKCdhc3NlcnRpb24tZXJyb3InKTtcblxuLyohXG4gKiBVdGlscyBmb3IgcGx1Z2lucyAobm90IGV4cG9ydGVkKVxuICovXG5cbnZhciB1dGlsID0gcmVxdWlyZSgnLi9jaGFpL3V0aWxzJyk7XG5cbi8qKlxuICogIyAudXNlKGZ1bmN0aW9uKVxuICpcbiAqIFByb3ZpZGVzIGEgd2F5IHRvIGV4dGVuZCB0aGUgaW50ZXJuYWxzIG9mIENoYWlcbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufVxuICogQHJldHVybnMge3RoaXN9IGZvciBjaGFpbmluZ1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5leHBvcnRzLnVzZSA9IGZ1bmN0aW9uIChmbikge1xuICBpZiAoIX51c2VkLmluZGV4T2YoZm4pKSB7XG4gICAgZm4odGhpcywgdXRpbCk7XG4gICAgdXNlZC5wdXNoKGZuKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuLyohXG4gKiBDb25maWd1cmF0aW9uXG4gKi9cblxudmFyIGNvbmZpZyA9IHJlcXVpcmUoJy4vY2hhaS9jb25maWcnKTtcbmV4cG9ydHMuY29uZmlnID0gY29uZmlnO1xuXG4vKiFcbiAqIFByaW1hcnkgYEFzc2VydGlvbmAgcHJvdG90eXBlXG4gKi9cblxudmFyIGFzc2VydGlvbiA9IHJlcXVpcmUoJy4vY2hhaS9hc3NlcnRpb24nKTtcbmV4cG9ydHMudXNlKGFzc2VydGlvbik7XG5cbi8qIVxuICogQ29yZSBBc3NlcnRpb25zXG4gKi9cblxudmFyIGNvcmUgPSByZXF1aXJlKCcuL2NoYWkvY29yZS9hc3NlcnRpb25zJyk7XG5leHBvcnRzLnVzZShjb3JlKTtcblxuLyohXG4gKiBFeHBlY3QgaW50ZXJmYWNlXG4gKi9cblxudmFyIGV4cGVjdCA9IHJlcXVpcmUoJy4vY2hhaS9pbnRlcmZhY2UvZXhwZWN0Jyk7XG5leHBvcnRzLnVzZShleHBlY3QpO1xuXG4vKiFcbiAqIFNob3VsZCBpbnRlcmZhY2VcbiAqL1xuXG52YXIgc2hvdWxkID0gcmVxdWlyZSgnLi9jaGFpL2ludGVyZmFjZS9zaG91bGQnKTtcbmV4cG9ydHMudXNlKHNob3VsZCk7XG5cbi8qIVxuICogQXNzZXJ0IGludGVyZmFjZVxuICovXG5cbnZhciBhc3NlcnQgPSByZXF1aXJlKCcuL2NoYWkvaW50ZXJmYWNlL2Fzc2VydCcpO1xuZXhwb3J0cy51c2UoYXNzZXJ0KTtcbiIsIi8qIVxuICogY2hhaVxuICogaHR0cDovL2NoYWlqcy5jb21cbiAqIENvcHlyaWdodChjKSAyMDExLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi9jb25maWcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoX2NoYWksIHV0aWwpIHtcbiAgLyohXG4gICAqIE1vZHVsZSBkZXBlbmRlbmNpZXMuXG4gICAqL1xuXG4gIHZhciBBc3NlcnRpb25FcnJvciA9IF9jaGFpLkFzc2VydGlvbkVycm9yXG4gICAgLCBmbGFnID0gdXRpbC5mbGFnO1xuXG4gIC8qIVxuICAgKiBNb2R1bGUgZXhwb3J0LlxuICAgKi9cblxuICBfY2hhaS5Bc3NlcnRpb24gPSBBc3NlcnRpb247XG5cbiAgLyohXG4gICAqIEFzc2VydGlvbiBDb25zdHJ1Y3RvclxuICAgKlxuICAgKiBDcmVhdGVzIG9iamVjdCBmb3IgY2hhaW5pbmcuXG4gICAqXG4gICAqIEBhcGkgcHJpdmF0ZVxuICAgKi9cblxuICBmdW5jdGlvbiBBc3NlcnRpb24gKG9iaiwgbXNnLCBzdGFjaykge1xuICAgIGZsYWcodGhpcywgJ3NzZmknLCBzdGFjayB8fCBhcmd1bWVudHMuY2FsbGVlKTtcbiAgICBmbGFnKHRoaXMsICdvYmplY3QnLCBvYmopO1xuICAgIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICB9XG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFzc2VydGlvbiwgJ2luY2x1ZGVTdGFjaycsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgY29uc29sZS53YXJuKCdBc3NlcnRpb24uaW5jbHVkZVN0YWNrIGlzIGRlcHJlY2F0ZWQsIHVzZSBjaGFpLmNvbmZpZy5pbmNsdWRlU3RhY2sgaW5zdGVhZC4nKTtcbiAgICAgIHJldHVybiBjb25maWcuaW5jbHVkZVN0YWNrO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgY29uc29sZS53YXJuKCdBc3NlcnRpb24uaW5jbHVkZVN0YWNrIGlzIGRlcHJlY2F0ZWQsIHVzZSBjaGFpLmNvbmZpZy5pbmNsdWRlU3RhY2sgaW5zdGVhZC4nKTtcbiAgICAgIGNvbmZpZy5pbmNsdWRlU3RhY2sgPSB2YWx1ZTtcbiAgICB9XG4gIH0pO1xuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShBc3NlcnRpb24sICdzaG93RGlmZicsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgY29uc29sZS53YXJuKCdBc3NlcnRpb24uc2hvd0RpZmYgaXMgZGVwcmVjYXRlZCwgdXNlIGNoYWkuY29uZmlnLnNob3dEaWZmIGluc3RlYWQuJyk7XG4gICAgICByZXR1cm4gY29uZmlnLnNob3dEaWZmO1xuICAgIH0sXG4gICAgc2V0OiBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgY29uc29sZS53YXJuKCdBc3NlcnRpb24uc2hvd0RpZmYgaXMgZGVwcmVjYXRlZCwgdXNlIGNoYWkuY29uZmlnLnNob3dEaWZmIGluc3RlYWQuJyk7XG4gICAgICBjb25maWcuc2hvd0RpZmYgPSB2YWx1ZTtcbiAgICB9XG4gIH0pO1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSA9IGZ1bmN0aW9uIChuYW1lLCBmbikge1xuICAgIHV0aWwuYWRkUHJvcGVydHkodGhpcy5wcm90b3R5cGUsIG5hbWUsIGZuKTtcbiAgfTtcblxuICBBc3NlcnRpb24uYWRkTWV0aG9kID0gZnVuY3Rpb24gKG5hbWUsIGZuKSB7XG4gICAgdXRpbC5hZGRNZXRob2QodGhpcy5wcm90b3R5cGUsIG5hbWUsIGZuKTtcbiAgfTtcblxuICBBc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kID0gZnVuY3Rpb24gKG5hbWUsIGZuLCBjaGFpbmluZ0JlaGF2aW9yKSB7XG4gICAgdXRpbC5hZGRDaGFpbmFibGVNZXRob2QodGhpcy5wcm90b3R5cGUsIG5hbWUsIGZuLCBjaGFpbmluZ0JlaGF2aW9yKTtcbiAgfTtcblxuICBBc3NlcnRpb24ub3ZlcndyaXRlUHJvcGVydHkgPSBmdW5jdGlvbiAobmFtZSwgZm4pIHtcbiAgICB1dGlsLm92ZXJ3cml0ZVByb3BlcnR5KHRoaXMucHJvdG90eXBlLCBuYW1lLCBmbik7XG4gIH07XG5cbiAgQXNzZXJ0aW9uLm92ZXJ3cml0ZU1ldGhvZCA9IGZ1bmN0aW9uIChuYW1lLCBmbikge1xuICAgIHV0aWwub3ZlcndyaXRlTWV0aG9kKHRoaXMucHJvdG90eXBlLCBuYW1lLCBmbik7XG4gIH07XG5cbiAgQXNzZXJ0aW9uLm92ZXJ3cml0ZUNoYWluYWJsZU1ldGhvZCA9IGZ1bmN0aW9uIChuYW1lLCBmbiwgY2hhaW5pbmdCZWhhdmlvcikge1xuICAgIHV0aWwub3ZlcndyaXRlQ2hhaW5hYmxlTWV0aG9kKHRoaXMucHJvdG90eXBlLCBuYW1lLCBmbiwgY2hhaW5pbmdCZWhhdmlvcik7XG4gIH07XG5cbiAgLyohXG4gICAqICMjIyAuYXNzZXJ0KGV4cHJlc3Npb24sIG1lc3NhZ2UsIG5lZ2F0ZU1lc3NhZ2UsIGV4cGVjdGVkLCBhY3R1YWwpXG4gICAqXG4gICAqIEV4ZWN1dGVzIGFuIGV4cHJlc3Npb24gYW5kIGNoZWNrIGV4cGVjdGF0aW9ucy4gVGhyb3dzIEFzc2VydGlvbkVycm9yIGZvciByZXBvcnRpbmcgaWYgdGVzdCBkb2Vzbid0IHBhc3MuXG4gICAqXG4gICAqIEBuYW1lIGFzc2VydFxuICAgKiBAcGFyYW0ge1BoaWxvc29waGljYWx9IGV4cHJlc3Npb24gdG8gYmUgdGVzdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIHRvIGRpc3BsYXkgaWYgZmFpbHNcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5lZ2F0ZWRNZXNzYWdlIHRvIGRpc3BsYXkgaWYgbmVnYXRlZCBleHByZXNzaW9uIGZhaWxzXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGV4cGVjdGVkIHZhbHVlIChyZW1lbWJlciB0byBjaGVjayBmb3IgbmVnYXRpb24pXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGFjdHVhbCAob3B0aW9uYWwpIHdpbGwgZGVmYXVsdCB0byBgdGhpcy5vYmpgXG4gICAqIEBhcGkgcHJpdmF0ZVxuICAgKi9cblxuICBBc3NlcnRpb24ucHJvdG90eXBlLmFzc2VydCA9IGZ1bmN0aW9uIChleHByLCBtc2csIG5lZ2F0ZU1zZywgZXhwZWN0ZWQsIF9hY3R1YWwsIHNob3dEaWZmKSB7XG4gICAgdmFyIG9rID0gdXRpbC50ZXN0KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgaWYgKHRydWUgIT09IHNob3dEaWZmKSBzaG93RGlmZiA9IGZhbHNlO1xuICAgIGlmICh0cnVlICE9PSBjb25maWcuc2hvd0RpZmYpIHNob3dEaWZmID0gZmFsc2U7XG5cbiAgICBpZiAoIW9rKSB7XG4gICAgICB2YXIgbXNnID0gdXRpbC5nZXRNZXNzYWdlKHRoaXMsIGFyZ3VtZW50cylcbiAgICAgICAgLCBhY3R1YWwgPSB1dGlsLmdldEFjdHVhbCh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgdGhyb3cgbmV3IEFzc2VydGlvbkVycm9yKG1zZywge1xuICAgICAgICAgIGFjdHVhbDogYWN0dWFsXG4gICAgICAgICwgZXhwZWN0ZWQ6IGV4cGVjdGVkXG4gICAgICAgICwgc2hvd0RpZmY6IHNob3dEaWZmXG4gICAgICB9LCAoY29uZmlnLmluY2x1ZGVTdGFjaykgPyB0aGlzLmFzc2VydCA6IGZsYWcodGhpcywgJ3NzZmknKSk7XG4gICAgfVxuICB9O1xuXG4gIC8qIVxuICAgKiAjIyMgLl9vYmpcbiAgICpcbiAgICogUXVpY2sgcmVmZXJlbmNlIHRvIHN0b3JlZCBgYWN0dWFsYCB2YWx1ZSBmb3IgcGx1Z2luIGRldmVsb3BlcnMuXG4gICAqXG4gICAqIEBhcGkgcHJpdmF0ZVxuICAgKi9cblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQXNzZXJ0aW9uLnByb3RvdHlwZSwgJ19vYmonLFxuICAgIHsgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICAgIH1cbiAgICAsIHNldDogZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICBmbGFnKHRoaXMsICdvYmplY3QnLCB2YWwpO1xuICAgICAgfVxuICB9KTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHtcblxuICAvKipcbiAgICogIyMjIGNvbmZpZy5pbmNsdWRlU3RhY2tcbiAgICpcbiAgICogVXNlciBjb25maWd1cmFibGUgcHJvcGVydHksIGluZmx1ZW5jZXMgd2hldGhlciBzdGFjayB0cmFjZVxuICAgKiBpcyBpbmNsdWRlZCBpbiBBc3NlcnRpb24gZXJyb3IgbWVzc2FnZS4gRGVmYXVsdCBvZiBmYWxzZVxuICAgKiBzdXBwcmVzc2VzIHN0YWNrIHRyYWNlIGluIHRoZSBlcnJvciBtZXNzYWdlLlxuICAgKlxuICAgKiAgICAgY2hhaS5jb25maWcuaW5jbHVkZVN0YWNrID0gdHJ1ZTsgIC8vIGVuYWJsZSBzdGFjayBvbiBlcnJvclxuICAgKlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59XG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gICBpbmNsdWRlU3RhY2s6IGZhbHNlLFxuXG4gIC8qKlxuICAgKiAjIyMgY29uZmlnLnNob3dEaWZmXG4gICAqXG4gICAqIFVzZXIgY29uZmlndXJhYmxlIHByb3BlcnR5LCBpbmZsdWVuY2VzIHdoZXRoZXIgb3Igbm90XG4gICAqIHRoZSBgc2hvd0RpZmZgIGZsYWcgc2hvdWxkIGJlIGluY2x1ZGVkIGluIHRoZSB0aHJvd25cbiAgICogQXNzZXJ0aW9uRXJyb3JzLiBgZmFsc2VgIHdpbGwgYWx3YXlzIGJlIGBmYWxzZWA7IGB0cnVlYFxuICAgKiB3aWxsIGJlIHRydWUgd2hlbiB0aGUgYXNzZXJ0aW9uIGhhcyByZXF1ZXN0ZWQgYSBkaWZmXG4gICAqIGJlIHNob3duLlxuICAgKlxuICAgKiBAcGFyYW0ge0Jvb2xlYW59XG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIHNob3dEaWZmOiB0cnVlLFxuXG4gIC8qKlxuICAgKiAjIyMgY29uZmlnLnRydW5jYXRlVGhyZXNob2xkXG4gICAqXG4gICAqIFVzZXIgY29uZmlndXJhYmxlIHByb3BlcnR5LCBzZXRzIGxlbmd0aCB0aHJlc2hvbGQgZm9yIGFjdHVhbCBhbmRcbiAgICogZXhwZWN0ZWQgdmFsdWVzIGluIGFzc2VydGlvbiBlcnJvcnMuIElmIHRoaXMgdGhyZXNob2xkIGlzIGV4Y2VlZGVkLFxuICAgKiB0aGUgdmFsdWUgaXMgdHJ1bmNhdGVkLlxuICAgKlxuICAgKiBTZXQgaXQgdG8gemVybyBpZiB5b3Ugd2FudCB0byBkaXNhYmxlIHRydW5jYXRpbmcgYWx0b2dldGhlci5cbiAgICpcbiAgICogICAgIGNoYWkuY29uZmlnLnRydW5jYXRlVGhyZXNob2xkID0gMDsgIC8vIGRpc2FibGUgdHJ1bmNhdGluZ1xuICAgKlxuICAgKiBAcGFyYW0ge051bWJlcn1cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgdHJ1bmNhdGVUaHJlc2hvbGQ6IDQwXG5cbn07XG4iLCIvKiFcbiAqIGNoYWlcbiAqIGh0dHA6Ly9jaGFpanMuY29tXG4gKiBDb3B5cmlnaHQoYykgMjAxMS0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoY2hhaSwgXykge1xuICB2YXIgQXNzZXJ0aW9uID0gY2hhaS5Bc3NlcnRpb25cbiAgICAsIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ1xuICAgICwgZmxhZyA9IF8uZmxhZztcblxuICAvKipcbiAgICogIyMjIExhbmd1YWdlIENoYWluc1xuICAgKlxuICAgKiBUaGUgZm9sbG93aW5nIGFyZSBwcm92aWRlZCBhcyBjaGFpbmFibGUgZ2V0dGVycyB0b1xuICAgKiBpbXByb3ZlIHRoZSByZWFkYWJpbGl0eSBvZiB5b3VyIGFzc2VydGlvbnMuIFRoZXlcbiAgICogZG8gbm90IHByb3ZpZGUgdGVzdGluZyBjYXBhYmlsaXRpZXMgdW5sZXNzIHRoZXlcbiAgICogaGF2ZSBiZWVuIG92ZXJ3cml0dGVuIGJ5IGEgcGx1Z2luLlxuICAgKlxuICAgKiAqKkNoYWlucyoqXG4gICAqXG4gICAqIC0gdG9cbiAgICogLSBiZVxuICAgKiAtIGJlZW5cbiAgICogLSBpc1xuICAgKiAtIHRoYXRcbiAgICogLSBhbmRcbiAgICogLSBoYXNcbiAgICogLSBoYXZlXG4gICAqIC0gd2l0aFxuICAgKiAtIGF0XG4gICAqIC0gb2ZcbiAgICogLSBzYW1lXG4gICAqXG4gICAqIEBuYW1lIGxhbmd1YWdlIGNoYWluc1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBbICd0bycsICdiZScsICdiZWVuJ1xuICAsICdpcycsICdhbmQnLCAnaGFzJywgJ2hhdmUnXG4gICwgJ3dpdGgnLCAndGhhdCcsICdhdCdcbiAgLCAnb2YnLCAnc2FtZScgXS5mb3JFYWNoKGZ1bmN0aW9uIChjaGFpbikge1xuICAgIEFzc2VydGlvbi5hZGRQcm9wZXJ0eShjaGFpbiwgZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdFxuICAgKlxuICAgKiBOZWdhdGVzIGFueSBvZiBhc3NlcnRpb25zIGZvbGxvd2luZyBpbiB0aGUgY2hhaW4uXG4gICAqXG4gICAqICAgICBleHBlY3QoZm9vKS50by5ub3QuZXF1YWwoJ2JhcicpO1xuICAgKiAgICAgZXhwZWN0KGdvb2RGbikudG8ubm90LnRocm93KEVycm9yKTtcbiAgICogICAgIGV4cGVjdCh7IGZvbzogJ2JheicgfSkudG8uaGF2ZS5wcm9wZXJ0eSgnZm9vJylcbiAgICogICAgICAgLmFuZC5ub3QuZXF1YWwoJ2JhcicpO1xuICAgKlxuICAgKiBAbmFtZSBub3RcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdub3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgZmxhZyh0aGlzLCAnbmVnYXRlJywgdHJ1ZSk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLmRlZXBcbiAgICpcbiAgICogU2V0cyB0aGUgYGRlZXBgIGZsYWcsIGxhdGVyIHVzZWQgYnkgdGhlIGBlcXVhbGAgYW5kXG4gICAqIGBwcm9wZXJ0eWAgYXNzZXJ0aW9ucy5cbiAgICpcbiAgICogICAgIGV4cGVjdChmb28pLnRvLmRlZXAuZXF1YWwoeyBiYXI6ICdiYXonIH0pO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiB7IGJhcjogeyBiYXo6ICdxdXV4JyB9IH0gfSlcbiAgICogICAgICAgLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eSgnZm9vLmJhci5iYXonLCAncXV1eCcpO1xuICAgKlxuICAgKiBAbmFtZSBkZWVwXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnZGVlcCcsIGZ1bmN0aW9uICgpIHtcbiAgICBmbGFnKHRoaXMsICdkZWVwJywgdHJ1ZSk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLmEodHlwZSlcbiAgICpcbiAgICogVGhlIGBhYCBhbmQgYGFuYCBhc3NlcnRpb25zIGFyZSBhbGlhc2VzIHRoYXQgY2FuIGJlXG4gICAqIHVzZWQgZWl0aGVyIGFzIGxhbmd1YWdlIGNoYWlucyBvciB0byBhc3NlcnQgYSB2YWx1ZSdzXG4gICAqIHR5cGUuXG4gICAqXG4gICAqICAgICAvLyB0eXBlb2ZcbiAgICogICAgIGV4cGVjdCgndGVzdCcpLnRvLmJlLmEoJ3N0cmluZycpO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAnYmFyJyB9KS50by5iZS5hbignb2JqZWN0Jyk7XG4gICAqICAgICBleHBlY3QobnVsbCkudG8uYmUuYSgnbnVsbCcpO1xuICAgKiAgICAgZXhwZWN0KHVuZGVmaW5lZCkudG8uYmUuYW4oJ3VuZGVmaW5lZCcpO1xuICAgKlxuICAgKiAgICAgLy8gbGFuZ3VhZ2UgY2hhaW5cbiAgICogICAgIGV4cGVjdChmb28pLnRvLmJlLmFuLmluc3RhbmNlb2YoRm9vKTtcbiAgICpcbiAgICogQG5hbWUgYVxuICAgKiBAYWxpYXMgYW5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhbiAodHlwZSwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdHlwZSA9IHR5cGUudG9Mb3dlckNhc2UoKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgYXJ0aWNsZSA9IH5bICdhJywgJ2UnLCAnaScsICdvJywgJ3UnIF0uaW5kZXhPZih0eXBlLmNoYXJBdCgwKSkgPyAnYW4gJyA6ICdhICc7XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgdHlwZSA9PT0gXy50eXBlKG9iailcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgJyArIGFydGljbGUgKyB0eXBlXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IG5vdCB0byBiZSAnICsgYXJ0aWNsZSArIHR5cGVcbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZENoYWluYWJsZU1ldGhvZCgnYW4nLCBhbik7XG4gIEFzc2VydGlvbi5hZGRDaGFpbmFibGVNZXRob2QoJ2EnLCBhbik7XG5cbiAgLyoqXG4gICAqICMjIyAuaW5jbHVkZSh2YWx1ZSlcbiAgICpcbiAgICogVGhlIGBpbmNsdWRlYCBhbmQgYGNvbnRhaW5gIGFzc2VydGlvbnMgY2FuIGJlIHVzZWQgYXMgZWl0aGVyIHByb3BlcnR5XG4gICAqIGJhc2VkIGxhbmd1YWdlIGNoYWlucyBvciBhcyBtZXRob2RzIHRvIGFzc2VydCB0aGUgaW5jbHVzaW9uIG9mIGFuIG9iamVjdFxuICAgKiBpbiBhbiBhcnJheSBvciBhIHN1YnN0cmluZyBpbiBhIHN0cmluZy4gV2hlbiB1c2VkIGFzIGxhbmd1YWdlIGNoYWlucyxcbiAgICogdGhleSB0b2dnbGUgdGhlIGBjb250YWluYCBmbGFnIGZvciB0aGUgYGtleXNgIGFzc2VydGlvbi5cbiAgICpcbiAgICogICAgIGV4cGVjdChbMSwyLDNdKS50by5pbmNsdWRlKDIpO1xuICAgKiAgICAgZXhwZWN0KCdmb29iYXInKS50by5jb250YWluKCdmb28nKTtcbiAgICogICAgIGV4cGVjdCh7IGZvbzogJ2JhcicsIGhlbGxvOiAndW5pdmVyc2UnIH0pLnRvLmluY2x1ZGUua2V5cygnZm9vJyk7XG4gICAqXG4gICAqIEBuYW1lIGluY2x1ZGVcbiAgICogQGFsaWFzIGNvbnRhaW5cbiAgICogQHBhcmFtIHtPYmplY3R8U3RyaW5nfE51bWJlcn0gb2JqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gaW5jbHVkZUNoYWluaW5nQmVoYXZpb3IgKCkge1xuICAgIGZsYWcodGhpcywgJ2NvbnRhaW5zJywgdHJ1ZSk7XG4gIH1cblxuICBmdW5jdGlvbiBpbmNsdWRlICh2YWwsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICB2YXIgZXhwZWN0ZWQgPSBmYWxzZTtcbiAgICBpZiAoXy50eXBlKG9iaikgPT09ICdhcnJheScgJiYgXy50eXBlKHZhbCkgPT09ICdvYmplY3QnKSB7XG4gICAgICBmb3IgKHZhciBpIGluIG9iaikge1xuICAgICAgICBpZiAoXy5lcWwob2JqW2ldLCB2YWwpKSB7XG4gICAgICAgICAgZXhwZWN0ZWQgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChfLnR5cGUodmFsKSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmICghZmxhZyh0aGlzLCAnbmVnYXRlJykpIHtcbiAgICAgICAgZm9yICh2YXIgayBpbiB2YWwpIG5ldyBBc3NlcnRpb24ob2JqKS5wcm9wZXJ0eShrLCB2YWxba10pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2YXIgc3Vic2V0ID0ge31cbiAgICAgIGZvciAodmFyIGsgaW4gdmFsKSBzdWJzZXRba10gPSBvYmpba11cbiAgICAgIGV4cGVjdGVkID0gXy5lcWwoc3Vic2V0LCB2YWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICBleHBlY3RlZCA9IG9iaiAmJiB+b2JqLmluZGV4T2YodmFsKVxuICAgIH1cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgZXhwZWN0ZWRcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaW5jbHVkZSAnICsgXy5pbnNwZWN0KHZhbClcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGluY2x1ZGUgJyArIF8uaW5zcGVjdCh2YWwpKTtcbiAgfVxuXG4gIEFzc2VydGlvbi5hZGRDaGFpbmFibGVNZXRob2QoJ2luY2x1ZGUnLCBpbmNsdWRlLCBpbmNsdWRlQ2hhaW5pbmdCZWhhdmlvcik7XG4gIEFzc2VydGlvbi5hZGRDaGFpbmFibGVNZXRob2QoJ2NvbnRhaW4nLCBpbmNsdWRlLCBpbmNsdWRlQ2hhaW5pbmdCZWhhdmlvcik7XG5cbiAgLyoqXG4gICAqICMjIyAub2tcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgdHJ1dGh5LlxuICAgKlxuICAgKiAgICAgZXhwZWN0KCdldmVydGhpbmcnKS50by5iZS5vaztcbiAgICogICAgIGV4cGVjdCgxKS50by5iZS5vaztcbiAgICogICAgIGV4cGVjdChmYWxzZSkudG8ubm90LmJlLm9rO1xuICAgKiAgICAgZXhwZWN0KHVuZGVmaW5lZCkudG8ubm90LmJlLm9rO1xuICAgKiAgICAgZXhwZWN0KG51bGwpLnRvLm5vdC5iZS5vaztcbiAgICpcbiAgICogQG5hbWUgb2tcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdvaycsIGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgdHJ1dGh5J1xuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBmYWxzeScpO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC50cnVlXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGB0cnVlYC5cbiAgICpcbiAgICogICAgIGV4cGVjdCh0cnVlKS50by5iZS50cnVlO1xuICAgKiAgICAgZXhwZWN0KDEpLnRvLm5vdC5iZS50cnVlO1xuICAgKlxuICAgKiBAbmFtZSB0cnVlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgndHJ1ZScsIGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgdHJ1ZSA9PT0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgdHJ1ZSdcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgZmFsc2UnXG4gICAgICAsIHRoaXMubmVnYXRlID8gZmFsc2UgOiB0cnVlXG4gICAgKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAuZmFsc2VcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgYGZhbHNlYC5cbiAgICpcbiAgICogICAgIGV4cGVjdChmYWxzZSkudG8uYmUuZmFsc2U7XG4gICAqICAgICBleHBlY3QoMCkudG8ubm90LmJlLmZhbHNlO1xuICAgKlxuICAgKiBAbmFtZSBmYWxzZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkoJ2ZhbHNlJywgZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBmYWxzZSA9PT0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgZmFsc2UnXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIHRydWUnXG4gICAgICAsIHRoaXMubmVnYXRlID8gdHJ1ZSA6IGZhbHNlXG4gICAgKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAubnVsbFxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBgbnVsbGAuXG4gICAqXG4gICAqICAgICBleHBlY3QobnVsbCkudG8uYmUubnVsbDtcbiAgICogICAgIGV4cGVjdCh1bmRlZmluZWQpLm5vdC50by5iZS5udWxsO1xuICAgKlxuICAgKiBAbmFtZSBudWxsXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnbnVsbCcsIGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgbnVsbCA9PT0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgbnVsbCdcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gbm90IHRvIGJlIG51bGwnXG4gICAgKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAudW5kZWZpbmVkXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGB1bmRlZmluZWRgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KHVuZGVmaW5lZCkudG8uYmUudW5kZWZpbmVkO1xuICAgKiAgICAgZXhwZWN0KG51bGwpLnRvLm5vdC5iZS51bmRlZmluZWQ7XG4gICAqXG4gICAqIEBuYW1lIHVuZGVmaW5lZFxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkoJ3VuZGVmaW5lZCcsIGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgdW5kZWZpbmVkID09PSBmbGFnKHRoaXMsICdvYmplY3QnKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSB1bmRlZmluZWQnXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IG5vdCB0byBiZSB1bmRlZmluZWQnXG4gICAgKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAuZXhpc3RcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgbmVpdGhlciBgbnVsbGAgbm9yIGB1bmRlZmluZWRgLlxuICAgKlxuICAgKiAgICAgdmFyIGZvbyA9ICdoaSdcbiAgICogICAgICAgLCBiYXIgPSBudWxsXG4gICAqICAgICAgICwgYmF6O1xuICAgKlxuICAgKiAgICAgZXhwZWN0KGZvbykudG8uZXhpc3Q7XG4gICAqICAgICBleHBlY3QoYmFyKS50by5ub3QuZXhpc3Q7XG4gICAqICAgICBleHBlY3QoYmF6KS50by5ub3QuZXhpc3Q7XG4gICAqXG4gICAqIEBuYW1lIGV4aXN0XG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnZXhpc3QnLCBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIG51bGwgIT0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gZXhpc3QnXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBleGlzdCdcbiAgICApO1xuICB9KTtcblxuXG4gIC8qKlxuICAgKiAjIyMgLmVtcHR5XG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0J3MgbGVuZ3RoIGlzIGAwYC4gRm9yIGFycmF5cywgaXQgY2hlY2tzXG4gICAqIHRoZSBgbGVuZ3RoYCBwcm9wZXJ0eS4gRm9yIG9iamVjdHMsIGl0IGdldHMgdGhlIGNvdW50IG9mXG4gICAqIGVudW1lcmFibGUga2V5cy5cbiAgICpcbiAgICogICAgIGV4cGVjdChbXSkudG8uYmUuZW1wdHk7XG4gICAqICAgICBleHBlY3QoJycpLnRvLmJlLmVtcHR5O1xuICAgKiAgICAgZXhwZWN0KHt9KS50by5iZS5lbXB0eTtcbiAgICpcbiAgICogQG5hbWUgZW1wdHlcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdlbXB0eScsIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgZXhwZWN0ZWQgPSBvYmo7XG5cbiAgICBpZiAoQXJyYXkuaXNBcnJheShvYmopIHx8ICdzdHJpbmcnID09PSB0eXBlb2Ygb2JqZWN0KSB7XG4gICAgICBleHBlY3RlZCA9IG9iai5sZW5ndGg7XG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygb2JqID09PSAnb2JqZWN0Jykge1xuICAgICAgZXhwZWN0ZWQgPSBPYmplY3Qua2V5cyhvYmopLmxlbmd0aDtcbiAgICB9XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgIWV4cGVjdGVkXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGVtcHR5J1xuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSBub3QgdG8gYmUgZW1wdHknXG4gICAgKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAuYXJndW1lbnRzXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGFuIGFyZ3VtZW50cyBvYmplY3QuXG4gICAqXG4gICAqICAgICBmdW5jdGlvbiB0ZXN0ICgpIHtcbiAgICogICAgICAgZXhwZWN0KGFyZ3VtZW50cykudG8uYmUuYXJndW1lbnRzO1xuICAgKiAgICAgfVxuICAgKlxuICAgKiBAbmFtZSBhcmd1bWVudHNcbiAgICogQGFsaWFzIEFyZ3VtZW50c1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBjaGVja0FyZ3VtZW50cyAoKSB7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpXG4gICAgICAsIHR5cGUgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKTtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgJ1tvYmplY3QgQXJndW1lbnRzXScgPT09IHR5cGVcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYXJndW1lbnRzIGJ1dCBnb3QgJyArIHR5cGVcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGJlIGFyZ3VtZW50cydcbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdhcmd1bWVudHMnLCBjaGVja0FyZ3VtZW50cyk7XG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnQXJndW1lbnRzJywgY2hlY2tBcmd1bWVudHMpO1xuXG4gIC8qKlxuICAgKiAjIyMgLmVxdWFsKHZhbHVlKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBzdHJpY3RseSBlcXVhbCAoYD09PWApIHRvIGB2YWx1ZWAuXG4gICAqIEFsdGVybmF0ZWx5LCBpZiB0aGUgYGRlZXBgIGZsYWcgaXMgc2V0LCBhc3NlcnRzIHRoYXRcbiAgICogdGhlIHRhcmdldCBpcyBkZWVwbHkgZXF1YWwgdG8gYHZhbHVlYC5cbiAgICpcbiAgICogICAgIGV4cGVjdCgnaGVsbG8nKS50by5lcXVhbCgnaGVsbG8nKTtcbiAgICogICAgIGV4cGVjdCg0MikudG8uZXF1YWwoNDIpO1xuICAgKiAgICAgZXhwZWN0KDEpLnRvLm5vdC5lcXVhbCh0cnVlKTtcbiAgICogICAgIGV4cGVjdCh7IGZvbzogJ2JhcicgfSkudG8ubm90LmVxdWFsKHsgZm9vOiAnYmFyJyB9KTtcbiAgICogICAgIGV4cGVjdCh7IGZvbzogJ2JhcicgfSkudG8uZGVlcC5lcXVhbCh7IGZvbzogJ2JhcicgfSk7XG4gICAqXG4gICAqIEBuYW1lIGVxdWFsXG4gICAqIEBhbGlhcyBlcXVhbHNcbiAgICogQGFsaWFzIGVxXG4gICAqIEBhbGlhcyBkZWVwLmVxdWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gYXNzZXJ0RXF1YWwgKHZhbCwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIGlmIChmbGFnKHRoaXMsICdkZWVwJykpIHtcbiAgICAgIHJldHVybiB0aGlzLmVxbCh2YWwpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICB2YWwgPT09IG9ialxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGVxdWFsICN7ZXhwfSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgZXF1YWwgI3tleHB9J1xuICAgICAgICAsIHZhbFxuICAgICAgICAsIHRoaXMuX29ialxuICAgICAgICAsIHRydWVcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZXF1YWwnLCBhc3NlcnRFcXVhbCk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2VxdWFscycsIGFzc2VydEVxdWFsKTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZXEnLCBhc3NlcnRFcXVhbCk7XG5cbiAgLyoqXG4gICAqICMjIyAuZXFsKHZhbHVlKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBkZWVwbHkgZXF1YWwgdG8gYHZhbHVlYC5cbiAgICpcbiAgICogICAgIGV4cGVjdCh7IGZvbzogJ2JhcicgfSkudG8uZXFsKHsgZm9vOiAnYmFyJyB9KTtcbiAgICogICAgIGV4cGVjdChbIDEsIDIsIDMgXSkudG8uZXFsKFsgMSwgMiwgMyBdKTtcbiAgICpcbiAgICogQG5hbWUgZXFsXG4gICAqIEBhbGlhcyBlcWxzXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gYXNzZXJ0RXFsKG9iaiwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIF8uZXFsKG9iaiwgZmxhZyh0aGlzLCAnb2JqZWN0JykpXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGRlZXBseSBlcXVhbCAje2V4cH0nXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBkZWVwbHkgZXF1YWwgI3tleHB9J1xuICAgICAgLCBvYmpcbiAgICAgICwgdGhpcy5fb2JqXG4gICAgICAsIHRydWVcbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZXFsJywgYXNzZXJ0RXFsKTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZXFscycsIGFzc2VydEVxbCk7XG5cbiAgLyoqXG4gICAqICMjIyAuYWJvdmUodmFsdWUpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGdyZWF0ZXIgdGhhbiBgdmFsdWVgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KDEwKS50by5iZS5hYm92ZSg1KTtcbiAgICpcbiAgICogQ2FuIGFsc28gYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIGBsZW5ndGhgIHRvXG4gICAqIGFzc2VydCBhIG1pbmltdW0gbGVuZ3RoLiBUaGUgYmVuZWZpdCBiZWluZyBhXG4gICAqIG1vcmUgaW5mb3JtYXRpdmUgZXJyb3IgbWVzc2FnZSB0aGFuIGlmIHRoZSBsZW5ndGhcbiAgICogd2FzIHN1cHBsaWVkIGRpcmVjdGx5LlxuICAgKlxuICAgKiAgICAgZXhwZWN0KCdmb28nKS50by5oYXZlLmxlbmd0aC5hYm92ZSgyKTtcbiAgICogICAgIGV4cGVjdChbIDEsIDIsIDMgXSkudG8uaGF2ZS5sZW5ndGguYWJvdmUoMik7XG4gICAqXG4gICAqIEBuYW1lIGFib3ZlXG4gICAqIEBhbGlhcyBndFxuICAgKiBAYWxpYXMgZ3JlYXRlclRoYW5cbiAgICogQHBhcmFtIHtOdW1iZXJ9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gYXNzZXJ0QWJvdmUgKG4sIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICBpZiAoZmxhZyh0aGlzLCAnZG9MZW5ndGgnKSkge1xuICAgICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5wcm9wZXJ0eSgnbGVuZ3RoJyk7XG4gICAgICB2YXIgbGVuID0gb2JqLmxlbmd0aDtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIGxlbiA+IG5cbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBoYXZlIGEgbGVuZ3RoIGFib3ZlICN7ZXhwfSBidXQgZ290ICN7YWN0fSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgaGF2ZSBhIGxlbmd0aCBhYm92ZSAje2V4cH0nXG4gICAgICAgICwgblxuICAgICAgICAsIGxlblxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgb2JqID4gblxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGFib3ZlICcgKyBuXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYXQgbW9zdCAnICsgblxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdhYm92ZScsIGFzc2VydEFib3ZlKTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZ3QnLCBhc3NlcnRBYm92ZSk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2dyZWF0ZXJUaGFuJywgYXNzZXJ0QWJvdmUpO1xuXG4gIC8qKlxuICAgKiAjIyMgLmxlYXN0KHZhbHVlKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gYHZhbHVlYC5cbiAgICpcbiAgICogICAgIGV4cGVjdCgxMCkudG8uYmUuYXQubGVhc3QoMTApO1xuICAgKlxuICAgKiBDYW4gYWxzbyBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGggYGxlbmd0aGAgdG9cbiAgICogYXNzZXJ0IGEgbWluaW11bSBsZW5ndGguIFRoZSBiZW5lZml0IGJlaW5nIGFcbiAgICogbW9yZSBpbmZvcm1hdGl2ZSBlcnJvciBtZXNzYWdlIHRoYW4gaWYgdGhlIGxlbmd0aFxuICAgKiB3YXMgc3VwcGxpZWQgZGlyZWN0bHkuXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2ZvbycpLnRvLmhhdmUubGVuZ3RoLm9mLmF0LmxlYXN0KDIpO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5oYXZlLmxlbmd0aC5vZi5hdC5sZWFzdCgzKTtcbiAgICpcbiAgICogQG5hbWUgbGVhc3RcbiAgICogQGFsaWFzIGd0ZVxuICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRMZWFzdCAobiwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIGlmIChmbGFnKHRoaXMsICdkb0xlbmd0aCcpKSB7XG4gICAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5oYXZlLnByb3BlcnR5KCdsZW5ndGgnKTtcbiAgICAgIHZhciBsZW4gPSBvYmoubGVuZ3RoO1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgbGVuID49IG5cbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBoYXZlIGEgbGVuZ3RoIGF0IGxlYXN0ICN7ZXhwfSBidXQgZ290ICN7YWN0fSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBoYXZlIGEgbGVuZ3RoIGJlbG93ICN7ZXhwfSdcbiAgICAgICAgLCBuXG4gICAgICAgICwgbGVuXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICBvYmogPj0gblxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGF0IGxlYXN0ICcgKyBuXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYmVsb3cgJyArIG5cbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnbGVhc3QnLCBhc3NlcnRMZWFzdCk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2d0ZScsIGFzc2VydExlYXN0KTtcblxuICAvKipcbiAgICogIyMjIC5iZWxvdyh2YWx1ZSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgbGVzcyB0aGFuIGB2YWx1ZWAuXG4gICAqXG4gICAqICAgICBleHBlY3QoNSkudG8uYmUuYmVsb3coMTApO1xuICAgKlxuICAgKiBDYW4gYWxzbyBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGggYGxlbmd0aGAgdG9cbiAgICogYXNzZXJ0IGEgbWF4aW11bSBsZW5ndGguIFRoZSBiZW5lZml0IGJlaW5nIGFcbiAgICogbW9yZSBpbmZvcm1hdGl2ZSBlcnJvciBtZXNzYWdlIHRoYW4gaWYgdGhlIGxlbmd0aFxuICAgKiB3YXMgc3VwcGxpZWQgZGlyZWN0bHkuXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2ZvbycpLnRvLmhhdmUubGVuZ3RoLmJlbG93KDQpO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5oYXZlLmxlbmd0aC5iZWxvdyg0KTtcbiAgICpcbiAgICogQG5hbWUgYmVsb3dcbiAgICogQGFsaWFzIGx0XG4gICAqIEBhbGlhcyBsZXNzVGhhblxuICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRCZWxvdyAobiwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIGlmIChmbGFnKHRoaXMsICdkb0xlbmd0aCcpKSB7XG4gICAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5oYXZlLnByb3BlcnR5KCdsZW5ndGgnKTtcbiAgICAgIHZhciBsZW4gPSBvYmoubGVuZ3RoO1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgbGVuIDwgblxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGhhdmUgYSBsZW5ndGggYmVsb3cgI3tleHB9IGJ1dCBnb3QgI3thY3R9J1xuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBoYXZlIGEgbGVuZ3RoIGJlbG93ICN7ZXhwfSdcbiAgICAgICAgLCBuXG4gICAgICAgICwgbGVuXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICBvYmogPCBuXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYmVsb3cgJyArIG5cbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBhdCBsZWFzdCAnICsgblxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdiZWxvdycsIGFzc2VydEJlbG93KTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnbHQnLCBhc3NlcnRCZWxvdyk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2xlc3NUaGFuJywgYXNzZXJ0QmVsb3cpO1xuXG4gIC8qKlxuICAgKiAjIyMgLm1vc3QodmFsdWUpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGxlc3MgdGhhbiBvciBlcXVhbCB0byBgdmFsdWVgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KDUpLnRvLmJlLmF0Lm1vc3QoNSk7XG4gICAqXG4gICAqIENhbiBhbHNvIGJlIHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCBgbGVuZ3RoYCB0b1xuICAgKiBhc3NlcnQgYSBtYXhpbXVtIGxlbmd0aC4gVGhlIGJlbmVmaXQgYmVpbmcgYVxuICAgKiBtb3JlIGluZm9ybWF0aXZlIGVycm9yIG1lc3NhZ2UgdGhhbiBpZiB0aGUgbGVuZ3RoXG4gICAqIHdhcyBzdXBwbGllZCBkaXJlY3RseS5cbiAgICpcbiAgICogICAgIGV4cGVjdCgnZm9vJykudG8uaGF2ZS5sZW5ndGgub2YuYXQubW9zdCg0KTtcbiAgICogICAgIGV4cGVjdChbIDEsIDIsIDMgXSkudG8uaGF2ZS5sZW5ndGgub2YuYXQubW9zdCgzKTtcbiAgICpcbiAgICogQG5hbWUgbW9zdFxuICAgKiBAYWxpYXMgbHRlXG4gICAqIEBwYXJhbSB7TnVtYmVyfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGFzc2VydE1vc3QgKG4sIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICBpZiAoZmxhZyh0aGlzLCAnZG9MZW5ndGgnKSkge1xuICAgICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5wcm9wZXJ0eSgnbGVuZ3RoJyk7XG4gICAgICB2YXIgbGVuID0gb2JqLmxlbmd0aDtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIGxlbiA8PSBuXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBhIGxlbmd0aCBhdCBtb3N0ICN7ZXhwfSBidXQgZ290ICN7YWN0fSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBoYXZlIGEgbGVuZ3RoIGFib3ZlICN7ZXhwfSdcbiAgICAgICAgLCBuXG4gICAgICAgICwgbGVuXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICBvYmogPD0gblxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGF0IG1vc3QgJyArIG5cbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBhYm92ZSAnICsgblxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdtb3N0JywgYXNzZXJ0TW9zdCk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2x0ZScsIGFzc2VydE1vc3QpO1xuXG4gIC8qKlxuICAgKiAjIyMgLndpdGhpbihzdGFydCwgZmluaXNoKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyB3aXRoaW4gYSByYW5nZS5cbiAgICpcbiAgICogICAgIGV4cGVjdCg3KS50by5iZS53aXRoaW4oNSwxMCk7XG4gICAqXG4gICAqIENhbiBhbHNvIGJlIHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCBgbGVuZ3RoYCB0b1xuICAgKiBhc3NlcnQgYSBsZW5ndGggcmFuZ2UuIFRoZSBiZW5lZml0IGJlaW5nIGFcbiAgICogbW9yZSBpbmZvcm1hdGl2ZSBlcnJvciBtZXNzYWdlIHRoYW4gaWYgdGhlIGxlbmd0aFxuICAgKiB3YXMgc3VwcGxpZWQgZGlyZWN0bHkuXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2ZvbycpLnRvLmhhdmUubGVuZ3RoLndpdGhpbigyLDQpO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5oYXZlLmxlbmd0aC53aXRoaW4oMiw0KTtcbiAgICpcbiAgICogQG5hbWUgd2l0aGluXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBzdGFydCBsb3dlcmJvdW5kIGluY2x1c2l2ZVxuICAgKiBAcGFyYW0ge051bWJlcn0gZmluaXNoIHVwcGVyYm91bmQgaW5jbHVzaXZlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnd2l0aGluJywgZnVuY3Rpb24gKHN0YXJ0LCBmaW5pc2gsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKVxuICAgICAgLCByYW5nZSA9IHN0YXJ0ICsgJy4uJyArIGZpbmlzaDtcbiAgICBpZiAoZmxhZyh0aGlzLCAnZG9MZW5ndGgnKSkge1xuICAgICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5wcm9wZXJ0eSgnbGVuZ3RoJyk7XG4gICAgICB2YXIgbGVuID0gb2JqLmxlbmd0aDtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIGxlbiA+PSBzdGFydCAmJiBsZW4gPD0gZmluaXNoXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBhIGxlbmd0aCB3aXRoaW4gJyArIHJhbmdlXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGhhdmUgYSBsZW5ndGggd2l0aGluICcgKyByYW5nZVxuICAgICAgKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgb2JqID49IHN0YXJ0ICYmIG9iaiA8PSBmaW5pc2hcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSB3aXRoaW4gJyArIHJhbmdlXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGJlIHdpdGhpbiAnICsgcmFuZ2VcbiAgICAgICk7XG4gICAgfVxuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5pbnN0YW5jZW9mKGNvbnN0cnVjdG9yKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBhbiBpbnN0YW5jZSBvZiBgY29uc3RydWN0b3JgLlxuICAgKlxuICAgKiAgICAgdmFyIFRlYSA9IGZ1bmN0aW9uIChuYW1lKSB7IHRoaXMubmFtZSA9IG5hbWU7IH1cbiAgICogICAgICAgLCBDaGFpID0gbmV3IFRlYSgnY2hhaScpO1xuICAgKlxuICAgKiAgICAgZXhwZWN0KENoYWkpLnRvLmJlLmFuLmluc3RhbmNlb2YoVGVhKTtcbiAgICogICAgIGV4cGVjdChbIDEsIDIsIDMgXSkudG8uYmUuaW5zdGFuY2VvZihBcnJheSk7XG4gICAqXG4gICAqIEBuYW1lIGluc3RhbmNlb2ZcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYWxpYXMgaW5zdGFuY2VPZlxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRJbnN0YW5jZU9mIChjb25zdHJ1Y3RvciwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG5hbWUgPSBfLmdldE5hbWUoY29uc3RydWN0b3IpO1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBmbGFnKHRoaXMsICdvYmplY3QnKSBpbnN0YW5jZW9mIGNvbnN0cnVjdG9yXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGFuIGluc3RhbmNlIG9mICcgKyBuYW1lXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBiZSBhbiBpbnN0YW5jZSBvZiAnICsgbmFtZVxuICAgICk7XG4gIH07XG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnaW5zdGFuY2VvZicsIGFzc2VydEluc3RhbmNlT2YpO1xuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdpbnN0YW5jZU9mJywgYXNzZXJ0SW5zdGFuY2VPZik7XG5cbiAgLyoqXG4gICAqICMjIyAucHJvcGVydHkobmFtZSwgW3ZhbHVlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaGFzIGEgcHJvcGVydHkgYG5hbWVgLCBvcHRpb25hbGx5IGFzc2VydGluZyB0aGF0XG4gICAqIHRoZSB2YWx1ZSBvZiB0aGF0IHByb3BlcnR5IGlzIHN0cmljdGx5IGVxdWFsIHRvICBgdmFsdWVgLlxuICAgKiBJZiB0aGUgYGRlZXBgIGZsYWcgaXMgc2V0LCB5b3UgY2FuIHVzZSBkb3QtIGFuZCBicmFja2V0LW5vdGF0aW9uIGZvciBkZWVwXG4gICAqIHJlZmVyZW5jZXMgaW50byBvYmplY3RzIGFuZCBhcnJheXMuXG4gICAqXG4gICAqICAgICAvLyBzaW1wbGUgcmVmZXJlbmNpbmdcbiAgICogICAgIHZhciBvYmogPSB7IGZvbzogJ2JhcicgfTtcbiAgICogICAgIGV4cGVjdChvYmopLnRvLmhhdmUucHJvcGVydHkoJ2ZvbycpO1xuICAgKiAgICAgZXhwZWN0KG9iaikudG8uaGF2ZS5wcm9wZXJ0eSgnZm9vJywgJ2JhcicpO1xuICAgKlxuICAgKiAgICAgLy8gZGVlcCByZWZlcmVuY2luZ1xuICAgKiAgICAgdmFyIGRlZXBPYmogPSB7XG4gICAqICAgICAgICAgZ3JlZW46IHsgdGVhOiAnbWF0Y2hhJyB9XG4gICAqICAgICAgICwgdGVhczogWyAnY2hhaScsICdtYXRjaGEnLCB7IHRlYTogJ2tvbmFjaGEnIH0gXVxuICAgKiAgICAgfTtcblxuICAgKiAgICAgZXhwZWN0KGRlZXBPYmopLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eSgnZ3JlZW4udGVhJywgJ21hdGNoYScpO1xuICAgKiAgICAgZXhwZWN0KGRlZXBPYmopLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eSgndGVhc1sxXScsICdtYXRjaGEnKTtcbiAgICogICAgIGV4cGVjdChkZWVwT2JqKS50by5oYXZlLmRlZXAucHJvcGVydHkoJ3RlYXNbMl0udGVhJywgJ2tvbmFjaGEnKTtcbiAgICpcbiAgICogWW91IGNhbiBhbHNvIHVzZSBhbiBhcnJheSBhcyB0aGUgc3RhcnRpbmcgcG9pbnQgb2YgYSBgZGVlcC5wcm9wZXJ0eWBcbiAgICogYXNzZXJ0aW9uLCBvciB0cmF2ZXJzZSBuZXN0ZWQgYXJyYXlzLlxuICAgKlxuICAgKiAgICAgdmFyIGFyciA9IFtcbiAgICogICAgICAgICBbICdjaGFpJywgJ21hdGNoYScsICdrb25hY2hhJyBdXG4gICAqICAgICAgICwgWyB7IHRlYTogJ2NoYWknIH1cbiAgICogICAgICAgICAsIHsgdGVhOiAnbWF0Y2hhJyB9XG4gICAqICAgICAgICAgLCB7IHRlYTogJ2tvbmFjaGEnIH0gXVxuICAgKiAgICAgXTtcbiAgICpcbiAgICogICAgIGV4cGVjdChhcnIpLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eSgnWzBdWzFdJywgJ21hdGNoYScpO1xuICAgKiAgICAgZXhwZWN0KGFycikudG8uaGF2ZS5kZWVwLnByb3BlcnR5KCdbMV1bMl0udGVhJywgJ2tvbmFjaGEnKTtcbiAgICpcbiAgICogRnVydGhlcm1vcmUsIGBwcm9wZXJ0eWAgY2hhbmdlcyB0aGUgc3ViamVjdCBvZiB0aGUgYXNzZXJ0aW9uXG4gICAqIHRvIGJlIHRoZSB2YWx1ZSBvZiB0aGF0IHByb3BlcnR5IGZyb20gdGhlIG9yaWdpbmFsIG9iamVjdC4gVGhpc1xuICAgKiBwZXJtaXRzIGZvciBmdXJ0aGVyIGNoYWluYWJsZSBhc3NlcnRpb25zIG9uIHRoYXQgcHJvcGVydHkuXG4gICAqXG4gICAqICAgICBleHBlY3Qob2JqKS50by5oYXZlLnByb3BlcnR5KCdmb28nKVxuICAgKiAgICAgICAudGhhdC5pcy5hKCdzdHJpbmcnKTtcbiAgICogICAgIGV4cGVjdChkZWVwT2JqKS50by5oYXZlLnByb3BlcnR5KCdncmVlbicpXG4gICAqICAgICAgIC50aGF0LmlzLmFuKCdvYmplY3QnKVxuICAgKiAgICAgICAudGhhdC5kZWVwLmVxdWFscyh7IHRlYTogJ21hdGNoYScgfSk7XG4gICAqICAgICBleHBlY3QoZGVlcE9iaikudG8uaGF2ZS5wcm9wZXJ0eSgndGVhcycpXG4gICAqICAgICAgIC50aGF0LmlzLmFuKCdhcnJheScpXG4gICAqICAgICAgIC53aXRoLmRlZXAucHJvcGVydHkoJ1syXScpXG4gICAqICAgICAgICAgLnRoYXQuZGVlcC5lcXVhbHMoeyB0ZWE6ICdrb25hY2hhJyB9KTtcbiAgICpcbiAgICogQG5hbWUgcHJvcGVydHlcbiAgICogQGFsaWFzIGRlZXAucHJvcGVydHlcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWUgKG9wdGlvbmFsKVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEByZXR1cm5zIHZhbHVlIG9mIHByb3BlcnR5IGZvciBjaGFpbmluZ1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdwcm9wZXJ0eScsIGZ1bmN0aW9uIChuYW1lLCB2YWwsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuXG4gICAgdmFyIGRlc2NyaXB0b3IgPSBmbGFnKHRoaXMsICdkZWVwJykgPyAnZGVlcCBwcm9wZXJ0eSAnIDogJ3Byb3BlcnR5ICdcbiAgICAgICwgbmVnYXRlID0gZmxhZyh0aGlzLCAnbmVnYXRlJylcbiAgICAgICwgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgdmFsdWUgPSBmbGFnKHRoaXMsICdkZWVwJylcbiAgICAgICAgPyBfLmdldFBhdGhWYWx1ZShuYW1lLCBvYmopXG4gICAgICAgIDogb2JqW25hbWVdO1xuXG4gICAgaWYgKG5lZ2F0ZSAmJiB1bmRlZmluZWQgIT09IHZhbCkge1xuICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gdmFsdWUpIHtcbiAgICAgICAgbXNnID0gKG1zZyAhPSBudWxsKSA/IG1zZyArICc6ICcgOiAnJztcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyArIF8uaW5zcGVjdChvYmopICsgJyBoYXMgbm8gJyArIGRlc2NyaXB0b3IgKyBfLmluc3BlY3QobmFtZSkpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICB1bmRlZmluZWQgIT09IHZhbHVlXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBhICcgKyBkZXNjcmlwdG9yICsgXy5pbnNwZWN0KG5hbWUpXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGhhdmUgJyArIGRlc2NyaXB0b3IgKyBfLmluc3BlY3QobmFtZSkpO1xuICAgIH1cblxuICAgIGlmICh1bmRlZmluZWQgIT09IHZhbCkge1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgdmFsID09PSB2YWx1ZVxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGhhdmUgYSAnICsgZGVzY3JpcHRvciArIF8uaW5zcGVjdChuYW1lKSArICcgb2YgI3tleHB9LCBidXQgZ290ICN7YWN0fSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgaGF2ZSBhICcgKyBkZXNjcmlwdG9yICsgXy5pbnNwZWN0KG5hbWUpICsgJyBvZiAje2FjdH0nXG4gICAgICAgICwgdmFsXG4gICAgICAgICwgdmFsdWVcbiAgICAgICk7XG4gICAgfVxuXG4gICAgZmxhZyh0aGlzLCAnb2JqZWN0JywgdmFsdWUpO1xuICB9KTtcblxuXG4gIC8qKlxuICAgKiAjIyMgLm93blByb3BlcnR5KG5hbWUpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGhhcyBhbiBvd24gcHJvcGVydHkgYG5hbWVgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KCd0ZXN0JykudG8uaGF2ZS5vd25Qcm9wZXJ0eSgnbGVuZ3RoJyk7XG4gICAqXG4gICAqIEBuYW1lIG93blByb3BlcnR5XG4gICAqIEBhbGlhcyBoYXZlT3duUHJvcGVydHlcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRPd25Qcm9wZXJ0eSAobmFtZSwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBvYmouaGFzT3duUHJvcGVydHkobmFtZSlcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBvd24gcHJvcGVydHkgJyArIF8uaW5zcGVjdChuYW1lKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgaGF2ZSBvd24gcHJvcGVydHkgJyArIF8uaW5zcGVjdChuYW1lKVxuICAgICk7XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdvd25Qcm9wZXJ0eScsIGFzc2VydE93blByb3BlcnR5KTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnaGF2ZU93blByb3BlcnR5JywgYXNzZXJ0T3duUHJvcGVydHkpO1xuXG4gIC8qKlxuICAgKiAjIyMgLmxlbmd0aCh2YWx1ZSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQncyBgbGVuZ3RoYCBwcm9wZXJ0eSBoYXNcbiAgICogdGhlIGV4cGVjdGVkIHZhbHVlLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgM10pLnRvLmhhdmUubGVuZ3RoKDMpO1xuICAgKiAgICAgZXhwZWN0KCdmb29iYXInKS50by5oYXZlLmxlbmd0aCg2KTtcbiAgICpcbiAgICogQ2FuIGFsc28gYmUgdXNlZCBhcyBhIGNoYWluIHByZWN1cnNvciB0byBhIHZhbHVlXG4gICAqIGNvbXBhcmlzb24gZm9yIHRoZSBsZW5ndGggcHJvcGVydHkuXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2ZvbycpLnRvLmhhdmUubGVuZ3RoLmFib3ZlKDIpO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5oYXZlLmxlbmd0aC5hYm92ZSgyKTtcbiAgICogICAgIGV4cGVjdCgnZm9vJykudG8uaGF2ZS5sZW5ndGguYmVsb3coNCk7XG4gICAqICAgICBleHBlY3QoWyAxLCAyLCAzIF0pLnRvLmhhdmUubGVuZ3RoLmJlbG93KDQpO1xuICAgKiAgICAgZXhwZWN0KCdmb28nKS50by5oYXZlLmxlbmd0aC53aXRoaW4oMiw0KTtcbiAgICogICAgIGV4cGVjdChbIDEsIDIsIDMgXSkudG8uaGF2ZS5sZW5ndGgud2l0aGluKDIsNCk7XG4gICAqXG4gICAqIEBuYW1lIGxlbmd0aFxuICAgKiBAYWxpYXMgbGVuZ3RoT2ZcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGxlbmd0aFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGFzc2VydExlbmd0aENoYWluICgpIHtcbiAgICBmbGFnKHRoaXMsICdkb0xlbmd0aCcsIHRydWUpO1xuICB9XG5cbiAgZnVuY3Rpb24gYXNzZXJ0TGVuZ3RoIChuLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5wcm9wZXJ0eSgnbGVuZ3RoJyk7XG4gICAgdmFyIGxlbiA9IG9iai5sZW5ndGg7XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgbGVuID09IG5cbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBhIGxlbmd0aCBvZiAje2V4cH0gYnV0IGdvdCAje2FjdH0nXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBoYXZlIGEgbGVuZ3RoIG9mICN7YWN0fSdcbiAgICAgICwgblxuICAgICAgLCBsZW5cbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZENoYWluYWJsZU1ldGhvZCgnbGVuZ3RoJywgYXNzZXJ0TGVuZ3RoLCBhc3NlcnRMZW5ndGhDaGFpbik7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2xlbmd0aE9mJywgYXNzZXJ0TGVuZ3RoLCBhc3NlcnRMZW5ndGhDaGFpbik7XG5cbiAgLyoqXG4gICAqICMjIyAubWF0Y2gocmVnZXhwKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBtYXRjaGVzIGEgcmVndWxhciBleHByZXNzaW9uLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KCdmb29iYXInKS50by5tYXRjaCgvXmZvby8pO1xuICAgKlxuICAgKiBAbmFtZSBtYXRjaFxuICAgKiBAcGFyYW0ge1JlZ0V4cH0gUmVndWxhckV4cHJlc3Npb25cbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdtYXRjaCcsIGZ1bmN0aW9uIChyZSwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICByZS5leGVjKG9iailcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbWF0Y2ggJyArIHJlXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IG5vdCB0byBtYXRjaCAnICsgcmVcbiAgICApO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5zdHJpbmcoc3RyaW5nKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHN0cmluZyB0YXJnZXQgY29udGFpbnMgYW5vdGhlciBzdHJpbmcuXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2Zvb2JhcicpLnRvLmhhdmUuc3RyaW5nKCdiYXInKTtcbiAgICpcbiAgICogQG5hbWUgc3RyaW5nXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzdHJpbmdcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdzdHJpbmcnLCBmdW5jdGlvbiAoc3RyLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykuaXMuYSgnc3RyaW5nJyk7XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgfm9iai5pbmRleE9mKHN0cilcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gY29udGFpbiAnICsgXy5pbnNwZWN0KHN0cilcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGNvbnRhaW4gJyArIF8uaW5zcGVjdChzdHIpXG4gICAgKTtcbiAgfSk7XG5cblxuICAvKipcbiAgICogIyMjIC5rZXlzKGtleTEsIFtrZXkyXSwgWy4uLl0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGhhcyBleGFjdGx5IHRoZSBnaXZlbiBrZXlzLCBvclxuICAgKiBhc3NlcnRzIHRoZSBpbmNsdXNpb24gb2Ygc29tZSBrZXlzIHdoZW4gdXNpbmcgdGhlXG4gICAqIGBpbmNsdWRlYCBvciBgY29udGFpbmAgbW9kaWZpZXJzLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAxLCBiYXI6IDIgfSkudG8uaGF2ZS5rZXlzKFsnZm9vJywgJ2JhciddKTtcbiAgICogICAgIGV4cGVjdCh7IGZvbzogMSwgYmFyOiAyLCBiYXo6IDMgfSkudG8uY29udGFpbi5rZXlzKCdmb28nLCAnYmFyJyk7XG4gICAqXG4gICAqIEBuYW1lIGtleXNcbiAgICogQGFsaWFzIGtleVxuICAgKiBAcGFyYW0ge1N0cmluZy4uLnxBcnJheX0ga2V5c1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRLZXlzIChrZXlzKSB7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpXG4gICAgICAsIHN0clxuICAgICAgLCBvayA9IHRydWU7XG5cbiAgICBrZXlzID0ga2V5cyBpbnN0YW5jZW9mIEFycmF5XG4gICAgICA/IGtleXNcbiAgICAgIDogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcblxuICAgIGlmICgha2V5cy5sZW5ndGgpIHRocm93IG5ldyBFcnJvcigna2V5cyByZXF1aXJlZCcpO1xuXG4gICAgdmFyIGFjdHVhbCA9IE9iamVjdC5rZXlzKG9iailcbiAgICAgICwgbGVuID0ga2V5cy5sZW5ndGg7XG5cbiAgICAvLyBJbmNsdXNpb25cbiAgICBvayA9IGtleXMuZXZlcnkoZnVuY3Rpb24oa2V5KXtcbiAgICAgIHJldHVybiB+YWN0dWFsLmluZGV4T2Yoa2V5KTtcbiAgICB9KTtcblxuICAgIC8vIFN0cmljdFxuICAgIGlmICghZmxhZyh0aGlzLCAnbmVnYXRlJykgJiYgIWZsYWcodGhpcywgJ2NvbnRhaW5zJykpIHtcbiAgICAgIG9rID0gb2sgJiYga2V5cy5sZW5ndGggPT0gYWN0dWFsLmxlbmd0aDtcbiAgICB9XG5cbiAgICAvLyBLZXkgc3RyaW5nXG4gICAgaWYgKGxlbiA+IDEpIHtcbiAgICAgIGtleXMgPSBrZXlzLm1hcChmdW5jdGlvbihrZXkpe1xuICAgICAgICByZXR1cm4gXy5pbnNwZWN0KGtleSk7XG4gICAgICB9KTtcbiAgICAgIHZhciBsYXN0ID0ga2V5cy5wb3AoKTtcbiAgICAgIHN0ciA9IGtleXMuam9pbignLCAnKSArICcsIGFuZCAnICsgbGFzdDtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyID0gXy5pbnNwZWN0KGtleXNbMF0pO1xuICAgIH1cblxuICAgIC8vIEZvcm1cbiAgICBzdHIgPSAobGVuID4gMSA/ICdrZXlzICcgOiAna2V5ICcpICsgc3RyO1xuXG4gICAgLy8gSGF2ZSAvIGluY2x1ZGVcbiAgICBzdHIgPSAoZmxhZyh0aGlzLCAnY29udGFpbnMnKSA/ICdjb250YWluICcgOiAnaGF2ZSAnKSArIHN0cjtcblxuICAgIC8vIEFzc2VydGlvblxuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBva1xuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byAnICsgc3RyXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCAnICsgc3RyXG4gICAgKTtcbiAgfVxuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2tleXMnLCBhc3NlcnRLZXlzKTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgna2V5JywgYXNzZXJ0S2V5cyk7XG5cbiAgLyoqXG4gICAqICMjIyAudGhyb3coY29uc3RydWN0b3IpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgZnVuY3Rpb24gdGFyZ2V0IHdpbGwgdGhyb3cgYSBzcGVjaWZpYyBlcnJvciwgb3Igc3BlY2lmaWMgdHlwZSBvZiBlcnJvclxuICAgKiAoYXMgZGV0ZXJtaW5lZCB1c2luZyBgaW5zdGFuY2VvZmApLCBvcHRpb25hbGx5IHdpdGggYSBSZWdFeHAgb3Igc3RyaW5nIGluY2x1c2lvbiB0ZXN0XG4gICAqIGZvciB0aGUgZXJyb3IncyBtZXNzYWdlLlxuICAgKlxuICAgKiAgICAgdmFyIGVyciA9IG5ldyBSZWZlcmVuY2VFcnJvcignVGhpcyBpcyBhIGJhZCBmdW5jdGlvbi4nKTtcbiAgICogICAgIHZhciBmbiA9IGZ1bmN0aW9uICgpIHsgdGhyb3cgZXJyOyB9XG4gICAqICAgICBleHBlY3QoZm4pLnRvLnRocm93KFJlZmVyZW5jZUVycm9yKTtcbiAgICogICAgIGV4cGVjdChmbikudG8udGhyb3coRXJyb3IpO1xuICAgKiAgICAgZXhwZWN0KGZuKS50by50aHJvdygvYmFkIGZ1bmN0aW9uLyk7XG4gICAqICAgICBleHBlY3QoZm4pLnRvLm5vdC50aHJvdygnZ29vZCBmdW5jdGlvbicpO1xuICAgKiAgICAgZXhwZWN0KGZuKS50by50aHJvdyhSZWZlcmVuY2VFcnJvciwgL2JhZCBmdW5jdGlvbi8pO1xuICAgKiAgICAgZXhwZWN0KGZuKS50by50aHJvdyhlcnIpO1xuICAgKiAgICAgZXhwZWN0KGZuKS50by5ub3QudGhyb3cobmV3IFJhbmdlRXJyb3IoJ091dCBvZiByYW5nZS4nKSk7XG4gICAqXG4gICAqIFBsZWFzZSBub3RlIHRoYXQgd2hlbiBhIHRocm93IGV4cGVjdGF0aW9uIGlzIG5lZ2F0ZWQsIGl0IHdpbGwgY2hlY2sgZWFjaFxuICAgKiBwYXJhbWV0ZXIgaW5kZXBlbmRlbnRseSwgc3RhcnRpbmcgd2l0aCBlcnJvciBjb25zdHJ1Y3RvciB0eXBlLiBUaGUgYXBwcm9wcmlhdGUgd2F5XG4gICAqIHRvIGNoZWNrIGZvciB0aGUgZXhpc3RlbmNlIG9mIGEgdHlwZSBvZiBlcnJvciBidXQgZm9yIGEgbWVzc2FnZSB0aGF0IGRvZXMgbm90IG1hdGNoXG4gICAqIGlzIHRvIHVzZSBgYW5kYC5cbiAgICpcbiAgICogICAgIGV4cGVjdChmbikudG8udGhyb3coUmVmZXJlbmNlRXJyb3IpXG4gICAqICAgICAgICAuYW5kLm5vdC50aHJvdygvZ29vZCBmdW5jdGlvbi8pO1xuICAgKlxuICAgKiBAbmFtZSB0aHJvd1xuICAgKiBAYWxpYXMgdGhyb3dzXG4gICAqIEBhbGlhcyBUaHJvd1xuICAgKiBAcGFyYW0ge0Vycm9yQ29uc3RydWN0b3J9IGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7U3RyaW5nfFJlZ0V4cH0gZXhwZWN0ZWQgZXJyb3IgbWVzc2FnZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4vSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRXJyb3IjRXJyb3JfdHlwZXNcbiAgICogQHJldHVybnMgZXJyb3IgZm9yIGNoYWluaW5nIChudWxsIGlmIG5vIGVycm9yKVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRUaHJvd3MgKGNvbnN0cnVjdG9yLCBlcnJNc2csIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS5pcy5hKCdmdW5jdGlvbicpO1xuXG4gICAgdmFyIHRocm93biA9IGZhbHNlXG4gICAgICAsIGRlc2lyZWRFcnJvciA9IG51bGxcbiAgICAgICwgbmFtZSA9IG51bGxcbiAgICAgICwgdGhyb3duRXJyb3IgPSBudWxsO1xuXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgIGVyck1zZyA9IG51bGw7XG4gICAgICBjb25zdHJ1Y3RvciA9IG51bGw7XG4gICAgfSBlbHNlIGlmIChjb25zdHJ1Y3RvciAmJiAoY29uc3RydWN0b3IgaW5zdGFuY2VvZiBSZWdFeHAgfHwgJ3N0cmluZycgPT09IHR5cGVvZiBjb25zdHJ1Y3RvcikpIHtcbiAgICAgIGVyck1zZyA9IGNvbnN0cnVjdG9yO1xuICAgICAgY29uc3RydWN0b3IgPSBudWxsO1xuICAgIH0gZWxzZSBpZiAoY29uc3RydWN0b3IgJiYgY29uc3RydWN0b3IgaW5zdGFuY2VvZiBFcnJvcikge1xuICAgICAgZGVzaXJlZEVycm9yID0gY29uc3RydWN0b3I7XG4gICAgICBjb25zdHJ1Y3RvciA9IG51bGw7XG4gICAgICBlcnJNc2cgPSBudWxsO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGNvbnN0cnVjdG9yID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBuYW1lID0gY29uc3RydWN0b3IucHJvdG90eXBlLm5hbWUgfHwgY29uc3RydWN0b3IubmFtZTtcbiAgICAgIGlmIChuYW1lID09PSAnRXJyb3InICYmIGNvbnN0cnVjdG9yICE9PSBFcnJvcikge1xuICAgICAgICBuYW1lID0gKG5ldyBjb25zdHJ1Y3RvcigpKS5uYW1lO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdHJ1Y3RvciA9IG51bGw7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIG9iaigpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgLy8gZmlyc3QsIGNoZWNrIGRlc2lyZWQgZXJyb3JcbiAgICAgIGlmIChkZXNpcmVkRXJyb3IpIHtcbiAgICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgICBlcnIgPT09IGRlc2lyZWRFcnJvclxuICAgICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gdGhyb3cgI3tleHB9IGJ1dCAje2FjdH0gd2FzIHRocm93bidcbiAgICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCB0aHJvdyAje2V4cH0nXG4gICAgICAgICAgLCAoZGVzaXJlZEVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBkZXNpcmVkRXJyb3IudG9TdHJpbmcoKSA6IGRlc2lyZWRFcnJvcilcbiAgICAgICAgICAsIChlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci50b1N0cmluZygpIDogZXJyKVxuICAgICAgICApO1xuXG4gICAgICAgIGZsYWcodGhpcywgJ29iamVjdCcsIGVycik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfVxuXG4gICAgICAvLyBuZXh0LCBjaGVjayBjb25zdHJ1Y3RvclxuICAgICAgaWYgKGNvbnN0cnVjdG9yKSB7XG4gICAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgICAgZXJyIGluc3RhbmNlb2YgY29uc3RydWN0b3JcbiAgICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIHRocm93ICN7ZXhwfSBidXQgI3thY3R9IHdhcyB0aHJvd24nXG4gICAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgdGhyb3cgI3tleHB9IGJ1dCAje2FjdH0gd2FzIHRocm93bidcbiAgICAgICAgICAsIG5hbWVcbiAgICAgICAgICAsIChlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci50b1N0cmluZygpIDogZXJyKVxuICAgICAgICApO1xuXG4gICAgICAgIGlmICghZXJyTXNnKSB7XG4gICAgICAgICAgZmxhZyh0aGlzLCAnb2JqZWN0JywgZXJyKTtcbiAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBuZXh0LCBjaGVjayBtZXNzYWdlXG4gICAgICB2YXIgbWVzc2FnZSA9ICdvYmplY3QnID09PSBfLnR5cGUoZXJyKSAmJiBcIm1lc3NhZ2VcIiBpbiBlcnJcbiAgICAgICAgPyBlcnIubWVzc2FnZVxuICAgICAgICA6ICcnICsgZXJyO1xuXG4gICAgICBpZiAoKG1lc3NhZ2UgIT0gbnVsbCkgJiYgZXJyTXNnICYmIGVyck1zZyBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICAgIGVyck1zZy5leGVjKG1lc3NhZ2UpXG4gICAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byB0aHJvdyBlcnJvciBtYXRjaGluZyAje2V4cH0gYnV0IGdvdCAje2FjdH0nXG4gICAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byB0aHJvdyBlcnJvciBub3QgbWF0Y2hpbmcgI3tleHB9J1xuICAgICAgICAgICwgZXJyTXNnXG4gICAgICAgICAgLCBtZXNzYWdlXG4gICAgICAgICk7XG5cbiAgICAgICAgZmxhZyh0aGlzLCAnb2JqZWN0JywgZXJyKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9IGVsc2UgaWYgKChtZXNzYWdlICE9IG51bGwpICYmIGVyck1zZyAmJiAnc3RyaW5nJyA9PT0gdHlwZW9mIGVyck1zZykge1xuICAgICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICAgIH5tZXNzYWdlLmluZGV4T2YoZXJyTXNnKVxuICAgICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gdGhyb3cgZXJyb3IgaW5jbHVkaW5nICN7ZXhwfSBidXQgZ290ICN7YWN0fSdcbiAgICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIHRocm93IGVycm9yIG5vdCBpbmNsdWRpbmcgI3thY3R9J1xuICAgICAgICAgICwgZXJyTXNnXG4gICAgICAgICAgLCBtZXNzYWdlXG4gICAgICAgICk7XG5cbiAgICAgICAgZmxhZyh0aGlzLCAnb2JqZWN0JywgZXJyKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvd24gPSB0cnVlO1xuICAgICAgICB0aHJvd25FcnJvciA9IGVycjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgYWN0dWFsbHlHb3QgPSAnJ1xuICAgICAgLCBleHBlY3RlZFRocm93biA9IG5hbWUgIT09IG51bGxcbiAgICAgICAgPyBuYW1lXG4gICAgICAgIDogZGVzaXJlZEVycm9yXG4gICAgICAgICAgPyAnI3tleHB9JyAvL18uaW5zcGVjdChkZXNpcmVkRXJyb3IpXG4gICAgICAgICAgOiAnYW4gZXJyb3InO1xuXG4gICAgaWYgKHRocm93bikge1xuICAgICAgYWN0dWFsbHlHb3QgPSAnIGJ1dCAje2FjdH0gd2FzIHRocm93bidcbiAgICB9XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgdGhyb3duID09PSB0cnVlXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIHRocm93ICcgKyBleHBlY3RlZFRocm93biArIGFjdHVhbGx5R290XG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCB0aHJvdyAnICsgZXhwZWN0ZWRUaHJvd24gKyBhY3R1YWxseUdvdFxuICAgICAgLCAoZGVzaXJlZEVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyBkZXNpcmVkRXJyb3IudG9TdHJpbmcoKSA6IGRlc2lyZWRFcnJvcilcbiAgICAgICwgKHRocm93bkVycm9yIGluc3RhbmNlb2YgRXJyb3IgPyB0aHJvd25FcnJvci50b1N0cmluZygpIDogdGhyb3duRXJyb3IpXG4gICAgKTtcblxuICAgIGZsYWcodGhpcywgJ29iamVjdCcsIHRocm93bkVycm9yKTtcbiAgfTtcblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCd0aHJvdycsIGFzc2VydFRocm93cyk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ3Rocm93cycsIGFzc2VydFRocm93cyk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ1Rocm93JywgYXNzZXJ0VGhyb3dzKTtcblxuICAvKipcbiAgICogIyMjIC5yZXNwb25kVG8obWV0aG9kKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIG9iamVjdCBvciBjbGFzcyB0YXJnZXQgd2lsbCByZXNwb25kIHRvIGEgbWV0aG9kLlxuICAgKlxuICAgKiAgICAgS2xhc3MucHJvdG90eXBlLmJhciA9IGZ1bmN0aW9uKCl7fTtcbiAgICogICAgIGV4cGVjdChLbGFzcykudG8ucmVzcG9uZFRvKCdiYXInKTtcbiAgICogICAgIGV4cGVjdChvYmopLnRvLnJlc3BvbmRUbygnYmFyJyk7XG4gICAqXG4gICAqIFRvIGNoZWNrIGlmIGEgY29uc3RydWN0b3Igd2lsbCByZXNwb25kIHRvIGEgc3RhdGljIGZ1bmN0aW9uLFxuICAgKiBzZXQgdGhlIGBpdHNlbGZgIGZsYWcuXG4gICAqXG4gICAqICAgICBLbGFzcy5iYXogPSBmdW5jdGlvbigpe307XG4gICAqICAgICBleHBlY3QoS2xhc3MpLml0c2VsZi50by5yZXNwb25kVG8oJ2JheicpO1xuICAgKlxuICAgKiBAbmFtZSByZXNwb25kVG9cbiAgICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ3Jlc3BvbmRUbycsIGZ1bmN0aW9uIChtZXRob2QsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKVxuICAgICAgLCBpdHNlbGYgPSBmbGFnKHRoaXMsICdpdHNlbGYnKVxuICAgICAgLCBjb250ZXh0ID0gKCdmdW5jdGlvbicgPT09IF8udHlwZShvYmopICYmICFpdHNlbGYpXG4gICAgICAgID8gb2JqLnByb3RvdHlwZVttZXRob2RdXG4gICAgICAgIDogb2JqW21ldGhvZF07XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgJ2Z1bmN0aW9uJyA9PT0gdHlwZW9mIGNvbnRleHRcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gcmVzcG9uZCB0byAnICsgXy5pbnNwZWN0KG1ldGhvZClcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IHJlc3BvbmQgdG8gJyArIF8uaW5zcGVjdChtZXRob2QpXG4gICAgKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAuaXRzZWxmXG4gICAqXG4gICAqIFNldHMgdGhlIGBpdHNlbGZgIGZsYWcsIGxhdGVyIHVzZWQgYnkgdGhlIGByZXNwb25kVG9gIGFzc2VydGlvbi5cbiAgICpcbiAgICogICAgIGZ1bmN0aW9uIEZvbygpIHt9XG4gICAqICAgICBGb28uYmFyID0gZnVuY3Rpb24oKSB7fVxuICAgKiAgICAgRm9vLnByb3RvdHlwZS5iYXogPSBmdW5jdGlvbigpIHt9XG4gICAqXG4gICAqICAgICBleHBlY3QoRm9vKS5pdHNlbGYudG8ucmVzcG9uZFRvKCdiYXInKTtcbiAgICogICAgIGV4cGVjdChGb28pLml0c2VsZi5ub3QudG8ucmVzcG9uZFRvKCdiYXonKTtcbiAgICpcbiAgICogQG5hbWUgaXRzZWxmXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnaXRzZWxmJywgZnVuY3Rpb24gKCkge1xuICAgIGZsYWcodGhpcywgJ2l0c2VsZicsIHRydWUpO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5zYXRpc2Z5KG1ldGhvZClcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgcGFzc2VzIGEgZ2l2ZW4gdHJ1dGggdGVzdC5cbiAgICpcbiAgICogICAgIGV4cGVjdCgxKS50by5zYXRpc2Z5KGZ1bmN0aW9uKG51bSkgeyByZXR1cm4gbnVtID4gMDsgfSk7XG4gICAqXG4gICAqIEBuYW1lIHNhdGlzZnlcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gbWF0Y2hlclxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ3NhdGlzZnknLCBmdW5jdGlvbiAobWF0Y2hlciwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBtYXRjaGVyKG9iailcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gc2F0aXNmeSAnICsgXy5vYmpEaXNwbGF5KG1hdGNoZXIpXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBzYXRpc2Z5JyArIF8ub2JqRGlzcGxheShtYXRjaGVyKVxuICAgICAgLCB0aGlzLm5lZ2F0ZSA/IGZhbHNlIDogdHJ1ZVxuICAgICAgLCBtYXRjaGVyKG9iailcbiAgICApO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5jbG9zZVRvKGV4cGVjdGVkLCBkZWx0YSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgZXF1YWwgYGV4cGVjdGVkYCwgdG8gd2l0aGluIGEgKy8tIGBkZWx0YWAgcmFuZ2UuXG4gICAqXG4gICAqICAgICBleHBlY3QoMS41KS50by5iZS5jbG9zZVRvKDEsIDAuNSk7XG4gICAqXG4gICAqIEBuYW1lIGNsb3NlVG9cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkZWx0YVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2Nsb3NlVG8nLCBmdW5jdGlvbiAoZXhwZWN0ZWQsIGRlbHRhLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIE1hdGguYWJzKG9iaiAtIGV4cGVjdGVkKSA8PSBkZWx0YVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBjbG9zZSB0byAnICsgZXhwZWN0ZWQgKyAnICsvLSAnICsgZGVsdGFcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gbm90IHRvIGJlIGNsb3NlIHRvICcgKyBleHBlY3RlZCArICcgKy8tICcgKyBkZWx0YVxuICAgICk7XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGlzU3Vic2V0T2Yoc3Vic2V0LCBzdXBlcnNldCwgY21wKSB7XG4gICAgcmV0dXJuIHN1YnNldC5ldmVyeShmdW5jdGlvbihlbGVtKSB7XG4gICAgICBpZiAoIWNtcCkgcmV0dXJuIHN1cGVyc2V0LmluZGV4T2YoZWxlbSkgIT09IC0xO1xuXG4gICAgICByZXR1cm4gc3VwZXJzZXQuc29tZShmdW5jdGlvbihlbGVtMikge1xuICAgICAgICByZXR1cm4gY21wKGVsZW0sIGVsZW0yKTtcbiAgICAgIH0pO1xuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogIyMjIC5tZW1iZXJzKHNldClcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgYSBzdXBlcnNldCBvZiBgc2V0YCxcbiAgICogb3IgdGhhdCB0aGUgdGFyZ2V0IGFuZCBgc2V0YCBoYXZlIHRoZSBzYW1lIHN0cmljdGx5LWVxdWFsICg9PT0pIG1lbWJlcnMuXG4gICAqIEFsdGVybmF0ZWx5LCBpZiB0aGUgYGRlZXBgIGZsYWcgaXMgc2V0LCBzZXQgbWVtYmVycyBhcmUgY29tcGFyZWQgZm9yIGRlZXBcbiAgICogZXF1YWxpdHkuXG4gICAqXG4gICAqICAgICBleHBlY3QoWzEsIDIsIDNdKS50by5pbmNsdWRlLm1lbWJlcnMoWzMsIDJdKTtcbiAgICogICAgIGV4cGVjdChbMSwgMiwgM10pLnRvLm5vdC5pbmNsdWRlLm1lbWJlcnMoWzMsIDIsIDhdKTtcbiAgICpcbiAgICogICAgIGV4cGVjdChbNCwgMl0pLnRvLmhhdmUubWVtYmVycyhbMiwgNF0pO1xuICAgKiAgICAgZXhwZWN0KFs1LCAyXSkudG8ubm90LmhhdmUubWVtYmVycyhbNSwgMiwgMV0pO1xuICAgKlxuICAgKiAgICAgZXhwZWN0KFt7IGlkOiAxIH1dKS50by5kZWVwLmluY2x1ZGUubWVtYmVycyhbeyBpZDogMSB9XSk7XG4gICAqXG4gICAqIEBuYW1lIG1lbWJlcnNcbiAgICogQHBhcmFtIHtBcnJheX0gc2V0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnbWVtYmVycycsIGZ1bmN0aW9uIChzdWJzZXQsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcblxuICAgIG5ldyBBc3NlcnRpb24ob2JqKS50by5iZS5hbignYXJyYXknKTtcbiAgICBuZXcgQXNzZXJ0aW9uKHN1YnNldCkudG8uYmUuYW4oJ2FycmF5Jyk7XG5cbiAgICB2YXIgY21wID0gZmxhZyh0aGlzLCAnZGVlcCcpID8gXy5lcWwgOiB1bmRlZmluZWQ7XG5cbiAgICBpZiAoZmxhZyh0aGlzLCAnY29udGFpbnMnKSkge1xuICAgICAgcmV0dXJuIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIGlzU3Vic2V0T2Yoc3Vic2V0LCBvYmosIGNtcClcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBhIHN1cGVyc2V0IG9mICN7YWN0fSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgYmUgYSBzdXBlcnNldCBvZiAje2FjdH0nXG4gICAgICAgICwgb2JqXG4gICAgICAgICwgc3Vic2V0XG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBpc1N1YnNldE9mKG9iaiwgc3Vic2V0LCBjbXApICYmIGlzU3Vic2V0T2Yoc3Vic2V0LCBvYmosIGNtcClcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBoYXZlIHRoZSBzYW1lIG1lbWJlcnMgYXMgI3thY3R9J1xuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBoYXZlIHRoZSBzYW1lIG1lbWJlcnMgYXMgI3thY3R9J1xuICAgICAgICAsIG9ialxuICAgICAgICAsIHN1YnNldFxuICAgICk7XG4gIH0pO1xufTtcbiIsIi8qIVxuICogY2hhaVxuICogQ29weXJpZ2h0KGMpIDIwMTEtMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoY2hhaSwgdXRpbCkge1xuXG4gIC8qIVxuICAgKiBDaGFpIGRlcGVuZGVuY2llcy5cbiAgICovXG5cbiAgdmFyIEFzc2VydGlvbiA9IGNoYWkuQXNzZXJ0aW9uXG4gICAgLCBmbGFnID0gdXRpbC5mbGFnO1xuXG4gIC8qIVxuICAgKiBNb2R1bGUgZXhwb3J0LlxuICAgKi9cblxuICAvKipcbiAgICogIyMjIGFzc2VydChleHByZXNzaW9uLCBtZXNzYWdlKVxuICAgKlxuICAgKiBXcml0ZSB5b3VyIG93biB0ZXN0IGV4cHJlc3Npb25zLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0KCdmb28nICE9PSAnYmFyJywgJ2ZvbyBpcyBub3QgYmFyJyk7XG4gICAqICAgICBhc3NlcnQoQXJyYXkuaXNBcnJheShbXSksICdlbXB0eSBhcnJheXMgYXJlIGFycmF5cycpO1xuICAgKlxuICAgKiBAcGFyYW0ge01peGVkfSBleHByZXNzaW9uIHRvIHRlc3QgZm9yIHRydXRoaW5lc3NcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgdG8gZGlzcGxheSBvbiBlcnJvclxuICAgKiBAbmFtZSBhc3NlcnRcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgdmFyIGFzc2VydCA9IGNoYWkuYXNzZXJ0ID0gZnVuY3Rpb24gKGV4cHJlc3MsIGVycm1zZykge1xuICAgIHZhciB0ZXN0ID0gbmV3IEFzc2VydGlvbihudWxsLCBudWxsLCBjaGFpLmFzc2VydCk7XG4gICAgdGVzdC5hc3NlcnQoXG4gICAgICAgIGV4cHJlc3NcbiAgICAgICwgZXJybXNnXG4gICAgICAsICdbIG5lZ2F0aW9uIG1lc3NhZ2UgdW5hdmFpbGFibGUgXSdcbiAgICApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmZhaWwoYWN0dWFsLCBleHBlY3RlZCwgW21lc3NhZ2VdLCBbb3BlcmF0b3JdKVxuICAgKlxuICAgKiBUaHJvdyBhIGZhaWx1cmUuIE5vZGUuanMgYGFzc2VydGAgbW9kdWxlLWNvbXBhdGlibGUuXG4gICAqXG4gICAqIEBuYW1lIGZhaWxcbiAgICogQHBhcmFtIHtNaXhlZH0gYWN0dWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvcGVyYXRvclxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuZmFpbCA9IGZ1bmN0aW9uIChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCBvcGVyYXRvcikge1xuICAgIG1lc3NhZ2UgPSBtZXNzYWdlIHx8ICdhc3NlcnQuZmFpbCgpJztcbiAgICB0aHJvdyBuZXcgY2hhaS5Bc3NlcnRpb25FcnJvcihtZXNzYWdlLCB7XG4gICAgICAgIGFjdHVhbDogYWN0dWFsXG4gICAgICAsIGV4cGVjdGVkOiBleHBlY3RlZFxuICAgICAgLCBvcGVyYXRvcjogb3BlcmF0b3JcbiAgICB9LCBhc3NlcnQuZmFpbCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAub2sob2JqZWN0LCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgb2JqZWN0YCBpcyB0cnV0aHkuXG4gICAqXG4gICAqICAgICBhc3NlcnQub2soJ2V2ZXJ5dGhpbmcnLCAnZXZlcnl0aGluZyBpcyBvaycpO1xuICAgKiAgICAgYXNzZXJ0Lm9rKGZhbHNlLCAndGhpcyB3aWxsIGZhaWwnKTtcbiAgICpcbiAgICogQG5hbWUgb2tcbiAgICogQHBhcmFtIHtNaXhlZH0gb2JqZWN0IHRvIHRlc3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm9rID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykuaXMub2s7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAubm90T2sob2JqZWN0LCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgb2JqZWN0YCBpcyBmYWxzeS5cbiAgICpcbiAgICogICAgIGFzc2VydC5ub3RPaygnZXZlcnl0aGluZycsICd0aGlzIHdpbGwgZmFpbCcpO1xuICAgKiAgICAgYXNzZXJ0Lm5vdE9rKGZhbHNlLCAndGhpcyB3aWxsIHBhc3MnKTtcbiAgICpcbiAgICogQG5hbWUgbm90T2tcbiAgICogQHBhcmFtIHtNaXhlZH0gb2JqZWN0IHRvIHRlc3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm5vdE9rID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykuaXMubm90Lm9rO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyBub24tc3RyaWN0IGVxdWFsaXR5IChgPT1gKSBvZiBgYWN0dWFsYCBhbmQgYGV4cGVjdGVkYC5cbiAgICpcbiAgICogICAgIGFzc2VydC5lcXVhbCgzLCAnMycsICc9PSBjb2VyY2VzIHZhbHVlcyB0byBzdHJpbmdzJyk7XG4gICAqXG4gICAqIEBuYW1lIGVxdWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGFjdHVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBleHBlY3RlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuZXF1YWwgPSBmdW5jdGlvbiAoYWN0LCBleHAsIG1zZykge1xuICAgIHZhciB0ZXN0ID0gbmV3IEFzc2VydGlvbihhY3QsIG1zZywgYXNzZXJ0LmVxdWFsKTtcblxuICAgIHRlc3QuYXNzZXJ0KFxuICAgICAgICBleHAgPT0gZmxhZyh0ZXN0LCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gZXF1YWwgI3tleHB9J1xuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgZXF1YWwgI3thY3R9J1xuICAgICAgLCBleHBcbiAgICAgICwgYWN0XG4gICAgKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5ub3RFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgbm9uLXN0cmljdCBpbmVxdWFsaXR5IChgIT1gKSBvZiBgYWN0dWFsYCBhbmQgYGV4cGVjdGVkYC5cbiAgICpcbiAgICogICAgIGFzc2VydC5ub3RFcXVhbCgzLCA0LCAndGhlc2UgbnVtYmVycyBhcmUgbm90IGVxdWFsJyk7XG4gICAqXG4gICAqIEBuYW1lIG5vdEVxdWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGFjdHVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBleHBlY3RlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubm90RXF1YWwgPSBmdW5jdGlvbiAoYWN0LCBleHAsIG1zZykge1xuICAgIHZhciB0ZXN0ID0gbmV3IEFzc2VydGlvbihhY3QsIG1zZywgYXNzZXJ0Lm5vdEVxdWFsKTtcblxuICAgIHRlc3QuYXNzZXJ0KFxuICAgICAgICBleHAgIT0gZmxhZyh0ZXN0LCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGVxdWFsICN7ZXhwfSdcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gZXF1YWwgI3thY3R9J1xuICAgICAgLCBleHBcbiAgICAgICwgYWN0XG4gICAgKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5zdHJpY3RFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgc3RyaWN0IGVxdWFsaXR5IChgPT09YCkgb2YgYGFjdHVhbGAgYW5kIGBleHBlY3RlZGAuXG4gICAqXG4gICAqICAgICBhc3NlcnQuc3RyaWN0RXF1YWwodHJ1ZSwgdHJ1ZSwgJ3RoZXNlIGJvb2xlYW5zIGFyZSBzdHJpY3RseSBlcXVhbCcpO1xuICAgKlxuICAgKiBAbmFtZSBzdHJpY3RFcXVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBhY3R1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gZXhwZWN0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LnN0cmljdEVxdWFsID0gZnVuY3Rpb24gKGFjdCwgZXhwLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGFjdCwgbXNnKS50by5lcXVhbChleHApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdFN0cmljdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyBzdHJpY3QgaW5lcXVhbGl0eSAoYCE9PWApIG9mIGBhY3R1YWxgIGFuZCBgZXhwZWN0ZWRgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm5vdFN0cmljdEVxdWFsKDMsICczJywgJ25vIGNvZXJjaW9uIGZvciBzdHJpY3QgZXF1YWxpdHknKTtcbiAgICpcbiAgICogQG5hbWUgbm90U3RyaWN0RXF1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gYWN0dWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5ub3RTdHJpY3RFcXVhbCA9IGZ1bmN0aW9uIChhY3QsIGV4cCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihhY3QsIG1zZykudG8ubm90LmVxdWFsKGV4cCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuZGVlcEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBhY3R1YWxgIGlzIGRlZXBseSBlcXVhbCB0byBgZXhwZWN0ZWRgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LmRlZXBFcXVhbCh7IHRlYTogJ2dyZWVuJyB9LCB7IHRlYTogJ2dyZWVuJyB9KTtcbiAgICpcbiAgICogQG5hbWUgZGVlcEVxdWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGFjdHVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBleHBlY3RlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuZGVlcEVxdWFsID0gZnVuY3Rpb24gKGFjdCwgZXhwLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGFjdCwgbXNnKS50by5lcWwoZXhwKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5ub3REZWVwRXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnQgdGhhdCBgYWN0dWFsYCBpcyBub3QgZGVlcGx5IGVxdWFsIHRvIGBleHBlY3RlZGAuXG4gICAqXG4gICAqICAgICBhc3NlcnQubm90RGVlcEVxdWFsKHsgdGVhOiAnZ3JlZW4nIH0sIHsgdGVhOiAnamFzbWluZScgfSk7XG4gICAqXG4gICAqIEBuYW1lIG5vdERlZXBFcXVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBhY3R1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gZXhwZWN0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm5vdERlZXBFcXVhbCA9IGZ1bmN0aW9uIChhY3QsIGV4cCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihhY3QsIG1zZykudG8ubm90LmVxbChleHApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzVHJ1ZSh2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyB0cnVlLlxuICAgKlxuICAgKiAgICAgdmFyIHRlYVNlcnZlZCA9IHRydWU7XG4gICAqICAgICBhc3NlcnQuaXNUcnVlKHRlYVNlcnZlZCwgJ3RoZSB0ZWEgaGFzIGJlZW4gc2VydmVkJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzVHJ1ZVxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNUcnVlID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykuaXNbJ3RydWUnXTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc0ZhbHNlKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIGZhbHNlLlxuICAgKlxuICAgKiAgICAgdmFyIHRlYVNlcnZlZCA9IGZhbHNlO1xuICAgKiAgICAgYXNzZXJ0LmlzRmFsc2UodGVhU2VydmVkLCAnbm8gdGVhIHlldD8gaG1tLi4uJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzRmFsc2VcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzRmFsc2UgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS5pc1snZmFsc2UnXTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc051bGwodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgbnVsbC5cbiAgICpcbiAgICogICAgIGFzc2VydC5pc051bGwoZXJyLCAndGhlcmUgd2FzIG5vIGVycm9yJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzTnVsbFxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNOdWxsID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uZXF1YWwobnVsbCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNOb3ROdWxsKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIG5vdCBudWxsLlxuICAgKlxuICAgKiAgICAgdmFyIHRlYSA9ICd0YXN0eSBjaGFpJztcbiAgICogICAgIGFzc2VydC5pc05vdE51bGwodGVhLCAnZ3JlYXQsIHRpbWUgZm9yIHRlYSEnKTtcbiAgICpcbiAgICogQG5hbWUgaXNOb3ROdWxsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc05vdE51bGwgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuZXF1YWwobnVsbCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNVbmRlZmluZWQodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgYHVuZGVmaW5lZGAuXG4gICAqXG4gICAqICAgICB2YXIgdGVhO1xuICAgKiAgICAgYXNzZXJ0LmlzVW5kZWZpbmVkKHRlYSwgJ25vIHRlYSBkZWZpbmVkJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzVW5kZWZpbmVkXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc1VuZGVmaW5lZCA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLmVxdWFsKHVuZGVmaW5lZCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNEZWZpbmVkKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIG5vdCBgdW5kZWZpbmVkYC5cbiAgICpcbiAgICogICAgIHZhciB0ZWEgPSAnY3VwIG9mIGNoYWknO1xuICAgKiAgICAgYXNzZXJ0LmlzRGVmaW5lZCh0ZWEsICd0ZWEgaGFzIGJlZW4gZGVmaW5lZCcpO1xuICAgKlxuICAgKiBAbmFtZSBpc0RlZmluZWRcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzRGVmaW5lZCA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLm5vdC5lcXVhbCh1bmRlZmluZWQpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzRnVuY3Rpb24odmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgYSBmdW5jdGlvbi5cbiAgICpcbiAgICogICAgIGZ1bmN0aW9uIHNlcnZlVGVhKCkgeyByZXR1cm4gJ2N1cCBvZiB0ZWEnOyB9O1xuICAgKiAgICAgYXNzZXJ0LmlzRnVuY3Rpb24oc2VydmVUZWEsICdncmVhdCwgd2UgY2FuIGhhdmUgdGVhIG5vdycpO1xuICAgKlxuICAgKiBAbmFtZSBpc0Z1bmN0aW9uXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc0Z1bmN0aW9uID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uYmUuYSgnZnVuY3Rpb24nKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc05vdEZ1bmN0aW9uKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIF9ub3RfIGEgZnVuY3Rpb24uXG4gICAqXG4gICAqICAgICB2YXIgc2VydmVUZWEgPSBbICdoZWF0JywgJ3BvdXInLCAnc2lwJyBdO1xuICAgKiAgICAgYXNzZXJ0LmlzTm90RnVuY3Rpb24oc2VydmVUZWEsICdncmVhdCwgd2UgaGF2ZSBsaXN0ZWQgdGhlIHN0ZXBzJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzTm90RnVuY3Rpb25cbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzTm90RnVuY3Rpb24gPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuYSgnZnVuY3Rpb24nKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc09iamVjdCh2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBhbiBvYmplY3QgKGFzIHJldmVhbGVkIGJ5XG4gICAqIGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nYCkuXG4gICAqXG4gICAqICAgICB2YXIgc2VsZWN0aW9uID0geyBuYW1lOiAnQ2hhaScsIHNlcnZlOiAnd2l0aCBzcGljZXMnIH07XG4gICAqICAgICBhc3NlcnQuaXNPYmplY3Qoc2VsZWN0aW9uLCAndGVhIHNlbGVjdGlvbiBpcyBhbiBvYmplY3QnKTtcbiAgICpcbiAgICogQG5hbWUgaXNPYmplY3RcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzT2JqZWN0ID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uYmUuYSgnb2JqZWN0Jyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNOb3RPYmplY3QodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgX25vdF8gYW4gb2JqZWN0LlxuICAgKlxuICAgKiAgICAgdmFyIHNlbGVjdGlvbiA9ICdjaGFpJ1xuICAgKiAgICAgYXNzZXJ0LmlzTm90T2JqZWN0KHNlbGVjdGlvbiwgJ3RlYSBzZWxlY3Rpb24gaXMgbm90IGFuIG9iamVjdCcpO1xuICAgKiAgICAgYXNzZXJ0LmlzTm90T2JqZWN0KG51bGwsICdudWxsIGlzIG5vdCBhbiBvYmplY3QnKTtcbiAgICpcbiAgICogQG5hbWUgaXNOb3RPYmplY3RcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzTm90T2JqZWN0ID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8ubm90LmJlLmEoJ29iamVjdCcpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzQXJyYXkodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgYW4gYXJyYXkuXG4gICAqXG4gICAqICAgICB2YXIgbWVudSA9IFsgJ2dyZWVuJywgJ2NoYWknLCAnb29sb25nJyBdO1xuICAgKiAgICAgYXNzZXJ0LmlzQXJyYXkobWVudSwgJ3doYXQga2luZCBvZiB0ZWEgZG8gd2Ugd2FudD8nKTtcbiAgICpcbiAgICogQG5hbWUgaXNBcnJheVxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNBcnJheSA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLmJlLmFuKCdhcnJheScpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzTm90QXJyYXkodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgX25vdF8gYW4gYXJyYXkuXG4gICAqXG4gICAqICAgICB2YXIgbWVudSA9ICdncmVlbnxjaGFpfG9vbG9uZyc7XG4gICAqICAgICBhc3NlcnQuaXNOb3RBcnJheShtZW51LCAnd2hhdCBraW5kIG9mIHRlYSBkbyB3ZSB3YW50PycpO1xuICAgKlxuICAgKiBAbmFtZSBpc05vdEFycmF5XG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc05vdEFycmF5ID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8ubm90LmJlLmFuKCdhcnJheScpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzU3RyaW5nKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIGEgc3RyaW5nLlxuICAgKlxuICAgKiAgICAgdmFyIHRlYU9yZGVyID0gJ2NoYWknO1xuICAgKiAgICAgYXNzZXJ0LmlzU3RyaW5nKHRlYU9yZGVyLCAnb3JkZXIgcGxhY2VkJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzU3RyaW5nXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc1N0cmluZyA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLmJlLmEoJ3N0cmluZycpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzTm90U3RyaW5nKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIF9ub3RfIGEgc3RyaW5nLlxuICAgKlxuICAgKiAgICAgdmFyIHRlYU9yZGVyID0gNDtcbiAgICogICAgIGFzc2VydC5pc05vdFN0cmluZyh0ZWFPcmRlciwgJ29yZGVyIHBsYWNlZCcpO1xuICAgKlxuICAgKiBAbmFtZSBpc05vdFN0cmluZ1xuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNOb3RTdHJpbmcgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuYSgnc3RyaW5nJyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNOdW1iZXIodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgYSBudW1iZXIuXG4gICAqXG4gICAqICAgICB2YXIgY3VwcyA9IDI7XG4gICAqICAgICBhc3NlcnQuaXNOdW1iZXIoY3VwcywgJ2hvdyBtYW55IGN1cHMnKTtcbiAgICpcbiAgICogQG5hbWUgaXNOdW1iZXJcbiAgICogQHBhcmFtIHtOdW1iZXJ9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc051bWJlciA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLmJlLmEoJ251bWJlcicpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzTm90TnVtYmVyKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIF9ub3RfIGEgbnVtYmVyLlxuICAgKlxuICAgKiAgICAgdmFyIGN1cHMgPSAnMiBjdXBzIHBsZWFzZSc7XG4gICAqICAgICBhc3NlcnQuaXNOb3ROdW1iZXIoY3VwcywgJ2hvdyBtYW55IGN1cHMnKTtcbiAgICpcbiAgICogQG5hbWUgaXNOb3ROdW1iZXJcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzTm90TnVtYmVyID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8ubm90LmJlLmEoJ251bWJlcicpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzQm9vbGVhbih2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBhIGJvb2xlYW4uXG4gICAqXG4gICAqICAgICB2YXIgdGVhUmVhZHkgPSB0cnVlXG4gICAqICAgICAgICwgdGVhU2VydmVkID0gZmFsc2U7XG4gICAqXG4gICAqICAgICBhc3NlcnQuaXNCb29sZWFuKHRlYVJlYWR5LCAnaXMgdGhlIHRlYSByZWFkeScpO1xuICAgKiAgICAgYXNzZXJ0LmlzQm9vbGVhbih0ZWFTZXJ2ZWQsICdoYXMgdGVhIGJlZW4gc2VydmVkJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzQm9vbGVhblxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNCb29sZWFuID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uYmUuYSgnYm9vbGVhbicpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzTm90Qm9vbGVhbih2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBfbm90XyBhIGJvb2xlYW4uXG4gICAqXG4gICAqICAgICB2YXIgdGVhUmVhZHkgPSAneWVwJ1xuICAgKiAgICAgICAsIHRlYVNlcnZlZCA9ICdub3BlJztcbiAgICpcbiAgICogICAgIGFzc2VydC5pc05vdEJvb2xlYW4odGVhUmVhZHksICdpcyB0aGUgdGVhIHJlYWR5Jyk7XG4gICAqICAgICBhc3NlcnQuaXNOb3RCb29sZWFuKHRlYVNlcnZlZCwgJ2hhcyB0ZWEgYmVlbiBzZXJ2ZWQnKTtcbiAgICpcbiAgICogQG5hbWUgaXNOb3RCb29sZWFuXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc05vdEJvb2xlYW4gPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuYSgnYm9vbGVhbicpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLnR5cGVPZih2YWx1ZSwgbmFtZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCdzIHR5cGUgaXMgYG5hbWVgLCBhcyBkZXRlcm1pbmVkIGJ5XG4gICAqIGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nYC5cbiAgICpcbiAgICogICAgIGFzc2VydC50eXBlT2YoeyB0ZWE6ICdjaGFpJyB9LCAnb2JqZWN0JywgJ3dlIGhhdmUgYW4gb2JqZWN0Jyk7XG4gICAqICAgICBhc3NlcnQudHlwZU9mKFsnY2hhaScsICdqYXNtaW5lJ10sICdhcnJheScsICd3ZSBoYXZlIGFuIGFycmF5Jyk7XG4gICAqICAgICBhc3NlcnQudHlwZU9mKCd0ZWEnLCAnc3RyaW5nJywgJ3dlIGhhdmUgYSBzdHJpbmcnKTtcbiAgICogICAgIGFzc2VydC50eXBlT2YoL3RlYS8sICdyZWdleHAnLCAnd2UgaGF2ZSBhIHJlZ3VsYXIgZXhwcmVzc2lvbicpO1xuICAgKiAgICAgYXNzZXJ0LnR5cGVPZihudWxsLCAnbnVsbCcsICd3ZSBoYXZlIGEgbnVsbCcpO1xuICAgKiAgICAgYXNzZXJ0LnR5cGVPZih1bmRlZmluZWQsICd1bmRlZmluZWQnLCAnd2UgaGF2ZSBhbiB1bmRlZmluZWQnKTtcbiAgICpcbiAgICogQG5hbWUgdHlwZU9mXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC50eXBlT2YgPSBmdW5jdGlvbiAodmFsLCB0eXBlLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5iZS5hKHR5cGUpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdFR5cGVPZih2YWx1ZSwgbmFtZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCdzIHR5cGUgaXMgX25vdF8gYG5hbWVgLCBhcyBkZXRlcm1pbmVkIGJ5XG4gICAqIGBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nYC5cbiAgICpcbiAgICogICAgIGFzc2VydC5ub3RUeXBlT2YoJ3RlYScsICdudW1iZXInLCAnc3RyaW5ncyBhcmUgbm90IG51bWJlcnMnKTtcbiAgICpcbiAgICogQG5hbWUgbm90VHlwZU9mXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlb2YgbmFtZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubm90VHlwZU9mID0gZnVuY3Rpb24gKHZhbCwgdHlwZSwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8ubm90LmJlLmEodHlwZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaW5zdGFuY2VPZihvYmplY3QsIGNvbnN0cnVjdG9yLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIGFuIGluc3RhbmNlIG9mIGBjb25zdHJ1Y3RvcmAuXG4gICAqXG4gICAqICAgICB2YXIgVGVhID0gZnVuY3Rpb24gKG5hbWUpIHsgdGhpcy5uYW1lID0gbmFtZTsgfVxuICAgKiAgICAgICAsIGNoYWkgPSBuZXcgVGVhKCdjaGFpJyk7XG4gICAqXG4gICAqICAgICBhc3NlcnQuaW5zdGFuY2VPZihjaGFpLCBUZWEsICdjaGFpIGlzIGFuIGluc3RhbmNlIG9mIHRlYScpO1xuICAgKlxuICAgKiBAbmFtZSBpbnN0YW5jZU9mXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lmluc3RhbmNlT2YgPSBmdW5jdGlvbiAodmFsLCB0eXBlLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5iZS5pbnN0YW5jZU9mKHR5cGUpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdEluc3RhbmNlT2Yob2JqZWN0LCBjb25zdHJ1Y3RvciwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIGB2YWx1ZWAgaXMgbm90IGFuIGluc3RhbmNlIG9mIGBjb25zdHJ1Y3RvcmAuXG4gICAqXG4gICAqICAgICB2YXIgVGVhID0gZnVuY3Rpb24gKG5hbWUpIHsgdGhpcy5uYW1lID0gbmFtZTsgfVxuICAgKiAgICAgICAsIGNoYWkgPSBuZXcgU3RyaW5nKCdjaGFpJyk7XG4gICAqXG4gICAqICAgICBhc3NlcnQubm90SW5zdGFuY2VPZihjaGFpLCBUZWEsICdjaGFpIGlzIG5vdCBhbiBpbnN0YW5jZSBvZiB0ZWEnKTtcbiAgICpcbiAgICogQG5hbWUgbm90SW5zdGFuY2VPZlxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gICAqIEBwYXJhbSB7Q29uc3RydWN0b3J9IGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5ub3RJbnN0YW5jZU9mID0gZnVuY3Rpb24gKHZhbCwgdHlwZSwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8ubm90LmJlLmluc3RhbmNlT2YodHlwZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaW5jbHVkZShoYXlzdGFjaywgbmVlZGxlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgaGF5c3RhY2tgIGluY2x1ZGVzIGBuZWVkbGVgLiBXb3Jrc1xuICAgKiBmb3Igc3RyaW5ncyBhbmQgYXJyYXlzLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LmluY2x1ZGUoJ2Zvb2JhcicsICdiYXInLCAnZm9vYmFyIGNvbnRhaW5zIHN0cmluZyBcImJhclwiJyk7XG4gICAqICAgICBhc3NlcnQuaW5jbHVkZShbIDEsIDIsIDMgXSwgMywgJ2FycmF5IGNvbnRhaW5zIHZhbHVlJyk7XG4gICAqXG4gICAqIEBuYW1lIGluY2x1ZGVcbiAgICogQHBhcmFtIHtBcnJheXxTdHJpbmd9IGhheXN0YWNrXG4gICAqIEBwYXJhbSB7TWl4ZWR9IG5lZWRsZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaW5jbHVkZSA9IGZ1bmN0aW9uIChleHAsIGluYywgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihleHAsIG1zZywgYXNzZXJ0LmluY2x1ZGUpLmluY2x1ZGUoaW5jKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5ub3RJbmNsdWRlKGhheXN0YWNrLCBuZWVkbGUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBoYXlzdGFja2AgZG9lcyBub3QgaW5jbHVkZSBgbmVlZGxlYC4gV29ya3NcbiAgICogZm9yIHN0cmluZ3MgYW5kIGFycmF5cy5cbiAgICppXG4gICAqICAgICBhc3NlcnQubm90SW5jbHVkZSgnZm9vYmFyJywgJ2JheicsICdzdHJpbmcgbm90IGluY2x1ZGUgc3Vic3RyaW5nJyk7XG4gICAqICAgICBhc3NlcnQubm90SW5jbHVkZShbIDEsIDIsIDMgXSwgNCwgJ2FycmF5IG5vdCBpbmNsdWRlIGNvbnRhaW4gdmFsdWUnKTtcbiAgICpcbiAgICogQG5hbWUgbm90SW5jbHVkZVxuICAgKiBAcGFyYW0ge0FycmF5fFN0cmluZ30gaGF5c3RhY2tcbiAgICogQHBhcmFtIHtNaXhlZH0gbmVlZGxlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5ub3RJbmNsdWRlID0gZnVuY3Rpb24gKGV4cCwgaW5jLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGV4cCwgbXNnLCBhc3NlcnQubm90SW5jbHVkZSkubm90LmluY2x1ZGUoaW5jKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5tYXRjaCh2YWx1ZSwgcmVnZXhwLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIG1hdGNoZXMgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbiBgcmVnZXhwYC5cbiAgICpcbiAgICogICAgIGFzc2VydC5tYXRjaCgnZm9vYmFyJywgL15mb28vLCAncmVnZXhwIG1hdGNoZXMnKTtcbiAgICpcbiAgICogQG5hbWUgbWF0Y2hcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtSZWdFeHB9IHJlZ2V4cFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubWF0Y2ggPSBmdW5jdGlvbiAoZXhwLCByZSwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihleHAsIG1zZykudG8ubWF0Y2gocmUpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdE1hdGNoKHZhbHVlLCByZWdleHAsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgZG9lcyBub3QgbWF0Y2ggdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbiBgcmVnZXhwYC5cbiAgICpcbiAgICogICAgIGFzc2VydC5ub3RNYXRjaCgnZm9vYmFyJywgL15mb28vLCAncmVnZXhwIGRvZXMgbm90IG1hdGNoJyk7XG4gICAqXG4gICAqIEBuYW1lIG5vdE1hdGNoXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7UmVnRXhwfSByZWdleHBcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm5vdE1hdGNoID0gZnVuY3Rpb24gKGV4cCwgcmUsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24oZXhwLCBtc2cpLnRvLm5vdC5tYXRjaChyZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAucHJvcGVydHkob2JqZWN0LCBwcm9wZXJ0eSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYG9iamVjdGAgaGFzIGEgcHJvcGVydHkgbmFtZWQgYnkgYHByb3BlcnR5YC5cbiAgICpcbiAgICogICAgIGFzc2VydC5wcm9wZXJ0eSh7IHRlYTogeyBncmVlbjogJ21hdGNoYScgfX0sICd0ZWEnKTtcbiAgICpcbiAgICogQG5hbWUgcHJvcGVydHlcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LnByb3BlcnR5ID0gZnVuY3Rpb24gKG9iaiwgcHJvcCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5wcm9wZXJ0eShwcm9wKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5ub3RQcm9wZXJ0eShvYmplY3QsIHByb3BlcnR5LCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgb2JqZWN0YCBkb2VzIF9ub3RfIGhhdmUgYSBwcm9wZXJ0eSBuYW1lZCBieSBgcHJvcGVydHlgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm5vdFByb3BlcnR5KHsgdGVhOiB7IGdyZWVuOiAnbWF0Y2hhJyB9fSwgJ2NvZmZlZScpO1xuICAgKlxuICAgKiBAbmFtZSBub3RQcm9wZXJ0eVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubm90UHJvcGVydHkgPSBmdW5jdGlvbiAob2JqLCBwcm9wLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5ub3QuaGF2ZS5wcm9wZXJ0eShwcm9wKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5kZWVwUHJvcGVydHkob2JqZWN0LCBwcm9wZXJ0eSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYG9iamVjdGAgaGFzIGEgcHJvcGVydHkgbmFtZWQgYnkgYHByb3BlcnR5YCwgd2hpY2ggY2FuIGJlIGFcbiAgICogc3RyaW5nIHVzaW5nIGRvdC0gYW5kIGJyYWNrZXQtbm90YXRpb24gZm9yIGRlZXAgcmVmZXJlbmNlLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LmRlZXBQcm9wZXJ0eSh7IHRlYTogeyBncmVlbjogJ21hdGNoYScgfX0sICd0ZWEuZ3JlZW4nKTtcbiAgICpcbiAgICogQG5hbWUgZGVlcFByb3BlcnR5XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5kZWVwUHJvcGVydHkgPSBmdW5jdGlvbiAob2JqLCBwcm9wLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5oYXZlLmRlZXAucHJvcGVydHkocHJvcCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAubm90RGVlcFByb3BlcnR5KG9iamVjdCwgcHJvcGVydHksIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBvYmplY3RgIGRvZXMgX25vdF8gaGF2ZSBhIHByb3BlcnR5IG5hbWVkIGJ5IGBwcm9wZXJ0eWAsIHdoaWNoXG4gICAqIGNhbiBiZSBhIHN0cmluZyB1c2luZyBkb3QtIGFuZCBicmFja2V0LW5vdGF0aW9uIGZvciBkZWVwIHJlZmVyZW5jZS5cbiAgICpcbiAgICogICAgIGFzc2VydC5ub3REZWVwUHJvcGVydHkoeyB0ZWE6IHsgZ3JlZW46ICdtYXRjaGEnIH19LCAndGVhLm9vbG9uZycpO1xuICAgKlxuICAgKiBAbmFtZSBub3REZWVwUHJvcGVydHlcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm5vdERlZXBQcm9wZXJ0eSA9IGZ1bmN0aW9uIChvYmosIHByb3AsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24ob2JqLCBtc2cpLnRvLm5vdC5oYXZlLmRlZXAucHJvcGVydHkocHJvcCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAucHJvcGVydHlWYWwob2JqZWN0LCBwcm9wZXJ0eSwgdmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBvYmplY3RgIGhhcyBhIHByb3BlcnR5IG5hbWVkIGJ5IGBwcm9wZXJ0eWAgd2l0aCB2YWx1ZSBnaXZlblxuICAgKiBieSBgdmFsdWVgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LnByb3BlcnR5VmFsKHsgdGVhOiAnaXMgZ29vZCcgfSwgJ3RlYScsICdpcyBnb29kJyk7XG4gICAqXG4gICAqIEBuYW1lIHByb3BlcnR5VmFsXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5XG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5wcm9wZXJ0eVZhbCA9IGZ1bmN0aW9uIChvYmosIHByb3AsIHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5wcm9wZXJ0eShwcm9wLCB2YWwpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLnByb3BlcnR5Tm90VmFsKG9iamVjdCwgcHJvcGVydHksIHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgb2JqZWN0YCBoYXMgYSBwcm9wZXJ0eSBuYW1lZCBieSBgcHJvcGVydHlgLCBidXQgd2l0aCBhIHZhbHVlXG4gICAqIGRpZmZlcmVudCBmcm9tIHRoYXQgZ2l2ZW4gYnkgYHZhbHVlYC5cbiAgICpcbiAgICogICAgIGFzc2VydC5wcm9wZXJ0eU5vdFZhbCh7IHRlYTogJ2lzIGdvb2QnIH0sICd0ZWEnLCAnaXMgYmFkJyk7XG4gICAqXG4gICAqIEBuYW1lIHByb3BlcnR5Tm90VmFsXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5XG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5wcm9wZXJ0eU5vdFZhbCA9IGZ1bmN0aW9uIChvYmosIHByb3AsIHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8ubm90LmhhdmUucHJvcGVydHkocHJvcCwgdmFsKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5kZWVwUHJvcGVydHlWYWwob2JqZWN0LCBwcm9wZXJ0eSwgdmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBvYmplY3RgIGhhcyBhIHByb3BlcnR5IG5hbWVkIGJ5IGBwcm9wZXJ0eWAgd2l0aCB2YWx1ZSBnaXZlblxuICAgKiBieSBgdmFsdWVgLiBgcHJvcGVydHlgIGNhbiB1c2UgZG90LSBhbmQgYnJhY2tldC1ub3RhdGlvbiBmb3IgZGVlcFxuICAgKiByZWZlcmVuY2UuXG4gICAqXG4gICAqICAgICBhc3NlcnQuZGVlcFByb3BlcnR5VmFsKHsgdGVhOiB7IGdyZWVuOiAnbWF0Y2hhJyB9fSwgJ3RlYS5ncmVlbicsICdtYXRjaGEnKTtcbiAgICpcbiAgICogQG5hbWUgZGVlcFByb3BlcnR5VmFsXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5XG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5kZWVwUHJvcGVydHlWYWwgPSBmdW5jdGlvbiAob2JqLCBwcm9wLCB2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24ob2JqLCBtc2cpLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eShwcm9wLCB2YWwpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmRlZXBQcm9wZXJ0eU5vdFZhbChvYmplY3QsIHByb3BlcnR5LCB2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYG9iamVjdGAgaGFzIGEgcHJvcGVydHkgbmFtZWQgYnkgYHByb3BlcnR5YCwgYnV0IHdpdGggYSB2YWx1ZVxuICAgKiBkaWZmZXJlbnQgZnJvbSB0aGF0IGdpdmVuIGJ5IGB2YWx1ZWAuIGBwcm9wZXJ0eWAgY2FuIHVzZSBkb3QtIGFuZFxuICAgKiBicmFja2V0LW5vdGF0aW9uIGZvciBkZWVwIHJlZmVyZW5jZS5cbiAgICpcbiAgICogICAgIGFzc2VydC5kZWVwUHJvcGVydHlOb3RWYWwoeyB0ZWE6IHsgZ3JlZW46ICdtYXRjaGEnIH19LCAndGVhLmdyZWVuJywgJ2tvbmFjaGEnKTtcbiAgICpcbiAgICogQG5hbWUgZGVlcFByb3BlcnR5Tm90VmFsXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5XG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5kZWVwUHJvcGVydHlOb3RWYWwgPSBmdW5jdGlvbiAob2JqLCBwcm9wLCB2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24ob2JqLCBtc2cpLnRvLm5vdC5oYXZlLmRlZXAucHJvcGVydHkocHJvcCwgdmFsKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5sZW5ndGhPZihvYmplY3QsIGxlbmd0aCwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYG9iamVjdGAgaGFzIGEgYGxlbmd0aGAgcHJvcGVydHkgd2l0aCB0aGUgZXhwZWN0ZWQgdmFsdWUuXG4gICAqXG4gICAqICAgICBhc3NlcnQubGVuZ3RoT2YoWzEsMiwzXSwgMywgJ2FycmF5IGhhcyBsZW5ndGggb2YgMycpO1xuICAgKiAgICAgYXNzZXJ0Lmxlbmd0aE9mKCdmb29iYXInLCA1LCAnc3RyaW5nIGhhcyBsZW5ndGggb2YgNicpO1xuICAgKlxuICAgKiBAbmFtZSBsZW5ndGhPZlxuICAgKiBAcGFyYW0ge01peGVkfSBvYmplY3RcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGxlbmd0aFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubGVuZ3RoT2YgPSBmdW5jdGlvbiAoZXhwLCBsZW4sIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24oZXhwLCBtc2cpLnRvLmhhdmUubGVuZ3RoKGxlbik7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAudGhyb3dzKGZ1bmN0aW9uLCBbY29uc3RydWN0b3Ivc3RyaW5nL3JlZ2V4cF0sIFtzdHJpbmcvcmVnZXhwXSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYGZ1bmN0aW9uYCB3aWxsIHRocm93IGFuIGVycm9yIHRoYXQgaXMgYW4gaW5zdGFuY2Ugb2ZcbiAgICogYGNvbnN0cnVjdG9yYCwgb3IgYWx0ZXJuYXRlbHkgdGhhdCBpdCB3aWxsIHRocm93IGFuIGVycm9yIHdpdGggbWVzc2FnZVxuICAgKiBtYXRjaGluZyBgcmVnZXhwYC5cbiAgICpcbiAgICogICAgIGFzc2VydC50aHJvdyhmbiwgJ2Z1bmN0aW9uIHRocm93cyBhIHJlZmVyZW5jZSBlcnJvcicpO1xuICAgKiAgICAgYXNzZXJ0LnRocm93KGZuLCAvZnVuY3Rpb24gdGhyb3dzIGEgcmVmZXJlbmNlIGVycm9yLyk7XG4gICAqICAgICBhc3NlcnQudGhyb3coZm4sIFJlZmVyZW5jZUVycm9yKTtcbiAgICogICAgIGFzc2VydC50aHJvdyhmbiwgUmVmZXJlbmNlRXJyb3IsICdmdW5jdGlvbiB0aHJvd3MgYSByZWZlcmVuY2UgZXJyb3InKTtcbiAgICogICAgIGFzc2VydC50aHJvdyhmbiwgUmVmZXJlbmNlRXJyb3IsIC9mdW5jdGlvbiB0aHJvd3MgYSByZWZlcmVuY2UgZXJyb3IvKTtcbiAgICpcbiAgICogQG5hbWUgdGhyb3dzXG4gICAqIEBhbGlhcyB0aHJvd1xuICAgKiBAYWxpYXMgVGhyb3dcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuY3Rpb25cbiAgICogQHBhcmFtIHtFcnJvckNvbnN0cnVjdG9yfSBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge1JlZ0V4cH0gcmVnZXhwXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4vSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRXJyb3IjRXJyb3JfdHlwZXNcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LlRocm93ID0gZnVuY3Rpb24gKGZuLCBlcnJ0LCBlcnJzLCBtc2cpIHtcbiAgICBpZiAoJ3N0cmluZycgPT09IHR5cGVvZiBlcnJ0IHx8IGVycnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgIGVycnMgPSBlcnJ0O1xuICAgICAgZXJydCA9IG51bGw7XG4gICAgfVxuXG4gICAgdmFyIGFzc2VydEVyciA9IG5ldyBBc3NlcnRpb24oZm4sIG1zZykudG8uVGhyb3coZXJydCwgZXJycyk7XG4gICAgcmV0dXJuIGZsYWcoYXNzZXJ0RXJyLCAnb2JqZWN0Jyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuZG9lc05vdFRocm93KGZ1bmN0aW9uLCBbY29uc3RydWN0b3IvcmVnZXhwXSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYGZ1bmN0aW9uYCB3aWxsIF9ub3RfIHRocm93IGFuIGVycm9yIHRoYXQgaXMgYW4gaW5zdGFuY2Ugb2ZcbiAgICogYGNvbnN0cnVjdG9yYCwgb3IgYWx0ZXJuYXRlbHkgdGhhdCBpdCB3aWxsIG5vdCB0aHJvdyBhbiBlcnJvciB3aXRoIG1lc3NhZ2VcbiAgICogbWF0Y2hpbmcgYHJlZ2V4cGAuXG4gICAqXG4gICAqICAgICBhc3NlcnQuZG9lc05vdFRocm93KGZuLCBFcnJvciwgJ2Z1bmN0aW9uIGRvZXMgbm90IHRocm93Jyk7XG4gICAqXG4gICAqIEBuYW1lIGRvZXNOb3RUaHJvd1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jdGlvblxuICAgKiBAcGFyYW0ge0Vycm9yQ29uc3RydWN0b3J9IGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7UmVnRXhwfSByZWdleHBcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9FcnJvciNFcnJvcl90eXBlc1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuZG9lc05vdFRocm93ID0gZnVuY3Rpb24gKGZuLCB0eXBlLCBtc2cpIHtcbiAgICBpZiAoJ3N0cmluZycgPT09IHR5cGVvZiB0eXBlKSB7XG4gICAgICBtc2cgPSB0eXBlO1xuICAgICAgdHlwZSA9IG51bGw7XG4gICAgfVxuXG4gICAgbmV3IEFzc2VydGlvbihmbiwgbXNnKS50by5ub3QuVGhyb3codHlwZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAub3BlcmF0b3IodmFsMSwgb3BlcmF0b3IsIHZhbDIsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQ29tcGFyZXMgdHdvIHZhbHVlcyB1c2luZyBgb3BlcmF0b3JgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm9wZXJhdG9yKDEsICc8JywgMiwgJ2V2ZXJ5dGhpbmcgaXMgb2snKTtcbiAgICogICAgIGFzc2VydC5vcGVyYXRvcigxLCAnPicsIDIsICd0aGlzIHdpbGwgZmFpbCcpO1xuICAgKlxuICAgKiBAbmFtZSBvcGVyYXRvclxuICAgKiBAcGFyYW0ge01peGVkfSB2YWwxXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvcGVyYXRvclxuICAgKiBAcGFyYW0ge01peGVkfSB2YWwyXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5vcGVyYXRvciA9IGZ1bmN0aW9uICh2YWwsIG9wZXJhdG9yLCB2YWwyLCBtc2cpIHtcbiAgICBpZiAoIX5bJz09JywgJz09PScsICc+JywgJz49JywgJzwnLCAnPD0nLCAnIT0nLCAnIT09J10uaW5kZXhPZihvcGVyYXRvcikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBvcGVyYXRvciBcIicgKyBvcGVyYXRvciArICdcIicpO1xuICAgIH1cbiAgICB2YXIgdGVzdCA9IG5ldyBBc3NlcnRpb24oZXZhbCh2YWwgKyBvcGVyYXRvciArIHZhbDIpLCBtc2cpO1xuICAgIHRlc3QuYXNzZXJ0KFxuICAgICAgICB0cnVlID09PSBmbGFnKHRlc3QsICdvYmplY3QnKVxuICAgICAgLCAnZXhwZWN0ZWQgJyArIHV0aWwuaW5zcGVjdCh2YWwpICsgJyB0byBiZSAnICsgb3BlcmF0b3IgKyAnICcgKyB1dGlsLmluc3BlY3QodmFsMilcbiAgICAgICwgJ2V4cGVjdGVkICcgKyB1dGlsLmluc3BlY3QodmFsKSArICcgdG8gbm90IGJlICcgKyBvcGVyYXRvciArICcgJyArIHV0aWwuaW5zcGVjdCh2YWwyKSApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmNsb3NlVG8oYWN0dWFsLCBleHBlY3RlZCwgZGVsdGEsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgZXF1YWwgYGV4cGVjdGVkYCwgdG8gd2l0aGluIGEgKy8tIGBkZWx0YWAgcmFuZ2UuXG4gICAqXG4gICAqICAgICBhc3NlcnQuY2xvc2VUbygxLjUsIDEsIDAuNSwgJ251bWJlcnMgYXJlIGNsb3NlJyk7XG4gICAqXG4gICAqIEBuYW1lIGNsb3NlVG9cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGFjdHVhbFxuICAgKiBAcGFyYW0ge051bWJlcn0gZXhwZWN0ZWRcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGRlbHRhXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5jbG9zZVRvID0gZnVuY3Rpb24gKGFjdCwgZXhwLCBkZWx0YSwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihhY3QsIG1zZykudG8uYmUuY2xvc2VUbyhleHAsIGRlbHRhKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5zYW1lTWVtYmVycyhzZXQxLCBzZXQyLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgc2V0MWAgYW5kIGBzZXQyYCBoYXZlIHRoZSBzYW1lIG1lbWJlcnMuXG4gICAqIE9yZGVyIGlzIG5vdCB0YWtlbiBpbnRvIGFjY291bnQuXG4gICAqXG4gICAqICAgICBhc3NlcnQuc2FtZU1lbWJlcnMoWyAxLCAyLCAzIF0sIFsgMiwgMSwgMyBdLCAnc2FtZSBtZW1iZXJzJyk7XG4gICAqXG4gICAqIEBuYW1lIHNhbWVNZW1iZXJzXG4gICAqIEBwYXJhbSB7QXJyYXl9IHN1cGVyc2V0XG4gICAqIEBwYXJhbSB7QXJyYXl9IHN1YnNldFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuc2FtZU1lbWJlcnMgPSBmdW5jdGlvbiAoc2V0MSwgc2V0MiwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihzZXQxLCBtc2cpLnRvLmhhdmUuc2FtZS5tZW1iZXJzKHNldDIpO1xuICB9XG5cbiAgLyoqXG4gICAqICMjIyAuaW5jbHVkZU1lbWJlcnMoc3VwZXJzZXQsIHN1YnNldCwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHN1YnNldGAgaXMgaW5jbHVkZWQgaW4gYHN1cGVyc2V0YC5cbiAgICogT3JkZXIgaXMgbm90IHRha2VuIGludG8gYWNjb3VudC5cbiAgICpcbiAgICogICAgIGFzc2VydC5pbmNsdWRlTWVtYmVycyhbIDEsIDIsIDMgXSwgWyAyLCAxIF0sICdpbmNsdWRlIG1lbWJlcnMnKTtcbiAgICpcbiAgICogQG5hbWUgaW5jbHVkZU1lbWJlcnNcbiAgICogQHBhcmFtIHtBcnJheX0gc3VwZXJzZXRcbiAgICogQHBhcmFtIHtBcnJheX0gc3Vic2V0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pbmNsdWRlTWVtYmVycyA9IGZ1bmN0aW9uIChzdXBlcnNldCwgc3Vic2V0LCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHN1cGVyc2V0LCBtc2cpLnRvLmluY2x1ZGUubWVtYmVycyhzdWJzZXQpO1xuICB9XG5cbiAgLyohXG4gICAqIFVuZG9jdW1lbnRlZCAvIHVudGVzdGVkXG4gICAqL1xuXG4gIGFzc2VydC5pZkVycm9yID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8ubm90LmJlLm9rO1xuICB9O1xuXG4gIC8qIVxuICAgKiBBbGlhc2VzLlxuICAgKi9cblxuICAoZnVuY3Rpb24gYWxpYXMobmFtZSwgYXMpe1xuICAgIGFzc2VydFthc10gPSBhc3NlcnRbbmFtZV07XG4gICAgcmV0dXJuIGFsaWFzO1xuICB9KVxuICAoJ1Rocm93JywgJ3Rocm93JylcbiAgKCdUaHJvdycsICd0aHJvd3MnKTtcbn07XG4iLCIvKiFcbiAqIGNoYWlcbiAqIENvcHlyaWdodChjKSAyMDExLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjaGFpLCB1dGlsKSB7XG4gIGNoYWkuZXhwZWN0ID0gZnVuY3Rpb24gKHZhbCwgbWVzc2FnZSkge1xuICAgIHJldHVybiBuZXcgY2hhaS5Bc3NlcnRpb24odmFsLCBtZXNzYWdlKTtcbiAgfTtcbn07XG5cbiIsIi8qIVxuICogY2hhaVxuICogQ29weXJpZ2h0KGMpIDIwMTEtMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGNoYWksIHV0aWwpIHtcbiAgdmFyIEFzc2VydGlvbiA9IGNoYWkuQXNzZXJ0aW9uO1xuXG4gIGZ1bmN0aW9uIGxvYWRTaG91bGQgKCkge1xuICAgIC8vIGV4cGxpY2l0bHkgZGVmaW5lIHRoaXMgbWV0aG9kIGFzIGZ1bmN0aW9uIGFzIHRvIGhhdmUgaXQncyBuYW1lIHRvIGluY2x1ZGUgYXMgYHNzZmlgXG4gICAgZnVuY3Rpb24gc2hvdWxkR2V0dGVyKCkge1xuICAgICAgaWYgKHRoaXMgaW5zdGFuY2VvZiBTdHJpbmcgfHwgdGhpcyBpbnN0YW5jZW9mIE51bWJlcikge1xuICAgICAgICByZXR1cm4gbmV3IEFzc2VydGlvbih0aGlzLmNvbnN0cnVjdG9yKHRoaXMpLCBudWxsLCBzaG91bGRHZXR0ZXIpO1xuICAgICAgfSBlbHNlIGlmICh0aGlzIGluc3RhbmNlb2YgQm9vbGVhbikge1xuICAgICAgICByZXR1cm4gbmV3IEFzc2VydGlvbih0aGlzID09IHRydWUsIG51bGwsIHNob3VsZEdldHRlcik7XG4gICAgICB9XG4gICAgICByZXR1cm4gbmV3IEFzc2VydGlvbih0aGlzLCBudWxsLCBzaG91bGRHZXR0ZXIpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBzaG91bGRTZXR0ZXIodmFsdWUpIHtcbiAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vY2hhaWpzL2NoYWkvaXNzdWVzLzg2OiB0aGlzIG1ha2VzXG4gICAgICAvLyBgd2hhdGV2ZXIuc2hvdWxkID0gc29tZVZhbHVlYCBhY3R1YWxseSBzZXQgYHNvbWVWYWx1ZWAsIHdoaWNoIGlzXG4gICAgICAvLyBlc3BlY2lhbGx5IHVzZWZ1bCBmb3IgYGdsb2JhbC5zaG91bGQgPSByZXF1aXJlKCdjaGFpJykuc2hvdWxkKClgLlxuICAgICAgLy9cbiAgICAgIC8vIE5vdGUgdGhhdCB3ZSBoYXZlIHRvIHVzZSBbW0RlZmluZVByb3BlcnR5XV0gaW5zdGVhZCBvZiBbW1B1dF1dXG4gICAgICAvLyBzaW5jZSBvdGhlcndpc2Ugd2Ugd291bGQgdHJpZ2dlciB0aGlzIHZlcnkgc2V0dGVyIVxuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsICdzaG91bGQnLCB7XG4gICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICB3cml0YWJsZTogdHJ1ZVxuICAgICAgfSk7XG4gICAgfVxuICAgIC8vIG1vZGlmeSBPYmplY3QucHJvdG90eXBlIHRvIGhhdmUgYHNob3VsZGBcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoT2JqZWN0LnByb3RvdHlwZSwgJ3Nob3VsZCcsIHtcbiAgICAgIHNldDogc2hvdWxkU2V0dGVyXG4gICAgICAsIGdldDogc2hvdWxkR2V0dGVyXG4gICAgICAsIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pO1xuXG4gICAgdmFyIHNob3VsZCA9IHt9O1xuXG4gICAgc2hvdWxkLmVxdWFsID0gZnVuY3Rpb24gKHZhbDEsIHZhbDIsIG1zZykge1xuICAgICAgbmV3IEFzc2VydGlvbih2YWwxLCBtc2cpLnRvLmVxdWFsKHZhbDIpO1xuICAgIH07XG5cbiAgICBzaG91bGQuVGhyb3cgPSBmdW5jdGlvbiAoZm4sIGVycnQsIGVycnMsIG1zZykge1xuICAgICAgbmV3IEFzc2VydGlvbihmbiwgbXNnKS50by5UaHJvdyhlcnJ0LCBlcnJzKTtcbiAgICB9O1xuXG4gICAgc2hvdWxkLmV4aXN0ID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5leGlzdDtcbiAgICB9XG5cbiAgICAvLyBuZWdhdGlvblxuICAgIHNob3VsZC5ub3QgPSB7fVxuXG4gICAgc2hvdWxkLm5vdC5lcXVhbCA9IGZ1bmN0aW9uICh2YWwxLCB2YWwyLCBtc2cpIHtcbiAgICAgIG5ldyBBc3NlcnRpb24odmFsMSwgbXNnKS50by5ub3QuZXF1YWwodmFsMik7XG4gICAgfTtcblxuICAgIHNob3VsZC5ub3QuVGhyb3cgPSBmdW5jdGlvbiAoZm4sIGVycnQsIGVycnMsIG1zZykge1xuICAgICAgbmV3IEFzc2VydGlvbihmbiwgbXNnKS50by5ub3QuVGhyb3coZXJydCwgZXJycyk7XG4gICAgfTtcblxuICAgIHNob3VsZC5ub3QuZXhpc3QgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLm5vdC5leGlzdDtcbiAgICB9XG5cbiAgICBzaG91bGRbJ3Rocm93J10gPSBzaG91bGRbJ1Rocm93J107XG4gICAgc2hvdWxkLm5vdFsndGhyb3cnXSA9IHNob3VsZC5ub3RbJ1Rocm93J107XG5cbiAgICByZXR1cm4gc2hvdWxkO1xuICB9O1xuXG4gIGNoYWkuc2hvdWxkID0gbG9hZFNob3VsZDtcbiAgY2hhaS5TaG91bGQgPSBsb2FkU2hvdWxkO1xufTtcbiIsIi8qIVxuICogQ2hhaSAtIGFkZENoYWluaW5nTWV0aG9kIHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKiFcbiAqIE1vZHVsZSBkZXBlbmRlbmNpZXNcbiAqL1xuXG52YXIgdHJhbnNmZXJGbGFncyA9IHJlcXVpcmUoJy4vdHJhbnNmZXJGbGFncycpO1xudmFyIGZsYWcgPSByZXF1aXJlKCcuL2ZsYWcnKTtcbnZhciBjb25maWcgPSByZXF1aXJlKCcuLi9jb25maWcnKTtcblxuLyohXG4gKiBNb2R1bGUgdmFyaWFibGVzXG4gKi9cblxuLy8gQ2hlY2sgd2hldGhlciBgX19wcm90b19fYCBpcyBzdXBwb3J0ZWRcbnZhciBoYXNQcm90b1N1cHBvcnQgPSAnX19wcm90b19fJyBpbiBPYmplY3Q7XG5cbi8vIFdpdGhvdXQgYF9fcHJvdG9fX2Agc3VwcG9ydCwgdGhpcyBtb2R1bGUgd2lsbCBuZWVkIHRvIGFkZCBwcm9wZXJ0aWVzIHRvIGEgZnVuY3Rpb24uXG4vLyBIb3dldmVyLCBzb21lIEZ1bmN0aW9uLnByb3RvdHlwZSBtZXRob2RzIGNhbm5vdCBiZSBvdmVyd3JpdHRlbixcbi8vIGFuZCB0aGVyZSBzZWVtcyBubyBlYXN5IGNyb3NzLXBsYXRmb3JtIHdheSB0byBkZXRlY3QgdGhlbSAoQHNlZSBjaGFpanMvY2hhaS9pc3N1ZXMvNjkpLlxudmFyIGV4Y2x1ZGVOYW1lcyA9IC9eKD86bGVuZ3RofG5hbWV8YXJndW1lbnRzfGNhbGxlcikkLztcblxuLy8gQ2FjaGUgYEZ1bmN0aW9uYCBwcm9wZXJ0aWVzXG52YXIgY2FsbCAgPSBGdW5jdGlvbi5wcm90b3R5cGUuY2FsbCxcbiAgICBhcHBseSA9IEZ1bmN0aW9uLnByb3RvdHlwZS5hcHBseTtcblxuLyoqXG4gKiAjIyMgYWRkQ2hhaW5hYmxlTWV0aG9kIChjdHgsIG5hbWUsIG1ldGhvZCwgY2hhaW5pbmdCZWhhdmlvcilcbiAqXG4gKiBBZGRzIGEgbWV0aG9kIHRvIGFuIG9iamVjdCwgc3VjaCB0aGF0IHRoZSBtZXRob2QgY2FuIGFsc28gYmUgY2hhaW5lZC5cbiAqXG4gKiAgICAgdXRpbHMuYWRkQ2hhaW5hYmxlTWV0aG9kKGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZSwgJ2ZvbycsIGZ1bmN0aW9uIChzdHIpIHtcbiAqICAgICAgIHZhciBvYmogPSB1dGlscy5mbGFnKHRoaXMsICdvYmplY3QnKTtcbiAqICAgICAgIG5ldyBjaGFpLkFzc2VydGlvbihvYmopLnRvLmJlLmVxdWFsKHN0cik7XG4gKiAgICAgfSk7XG4gKlxuICogQ2FuIGFsc28gYmUgYWNjZXNzZWQgZGlyZWN0bHkgZnJvbSBgY2hhaS5Bc3NlcnRpb25gLlxuICpcbiAqICAgICBjaGFpLkFzc2VydGlvbi5hZGRDaGFpbmFibGVNZXRob2QoJ2ZvbycsIGZuLCBjaGFpbmluZ0JlaGF2aW9yKTtcbiAqXG4gKiBUaGUgcmVzdWx0IGNhbiB0aGVuIGJlIHVzZWQgYXMgYm90aCBhIG1ldGhvZCBhc3NlcnRpb24sIGV4ZWN1dGluZyBib3RoIGBtZXRob2RgIGFuZFxuICogYGNoYWluaW5nQmVoYXZpb3JgLCBvciBhcyBhIGxhbmd1YWdlIGNoYWluLCB3aGljaCBvbmx5IGV4ZWN1dGVzIGBjaGFpbmluZ0JlaGF2aW9yYC5cbiAqXG4gKiAgICAgZXhwZWN0KGZvb1N0cikudG8uYmUuZm9vKCdiYXInKTtcbiAqICAgICBleHBlY3QoZm9vU3RyKS50by5iZS5mb28uZXF1YWwoJ2ZvbycpO1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjdHggb2JqZWN0IHRvIHdoaWNoIHRoZSBtZXRob2QgaXMgYWRkZWRcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIG9mIG1ldGhvZCB0byBhZGRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG1ldGhvZCBmdW5jdGlvbiB0byBiZSB1c2VkIGZvciBgbmFtZWAsIHdoZW4gY2FsbGVkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjaGFpbmluZ0JlaGF2aW9yIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBldmVyeSB0aW1lIHRoZSBwcm9wZXJ0eSBpcyBhY2Nlc3NlZFxuICogQG5hbWUgYWRkQ2hhaW5hYmxlTWV0aG9kXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGN0eCwgbmFtZSwgbWV0aG9kLCBjaGFpbmluZ0JlaGF2aW9yKSB7XG4gIGlmICh0eXBlb2YgY2hhaW5pbmdCZWhhdmlvciAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIGNoYWluaW5nQmVoYXZpb3IgPSBmdW5jdGlvbiAoKSB7IH07XG4gIH1cblxuICB2YXIgY2hhaW5hYmxlQmVoYXZpb3IgPSB7XG4gICAgICBtZXRob2Q6IG1ldGhvZFxuICAgICwgY2hhaW5pbmdCZWhhdmlvcjogY2hhaW5pbmdCZWhhdmlvclxuICB9O1xuXG4gIC8vIHNhdmUgdGhlIG1ldGhvZHMgc28gd2UgY2FuIG92ZXJ3cml0ZSB0aGVtIGxhdGVyLCBpZiB3ZSBuZWVkIHRvLlxuICBpZiAoIWN0eC5fX21ldGhvZHMpIHtcbiAgICBjdHguX19tZXRob2RzID0ge307XG4gIH1cbiAgY3R4Ll9fbWV0aG9kc1tuYW1lXSA9IGNoYWluYWJsZUJlaGF2aW9yO1xuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjdHgsIG5hbWUsXG4gICAgeyBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY2hhaW5hYmxlQmVoYXZpb3IuY2hhaW5pbmdCZWhhdmlvci5jYWxsKHRoaXMpO1xuXG4gICAgICAgIHZhciBhc3NlcnQgPSBmdW5jdGlvbiBhc3NlcnQoKSB7XG4gICAgICAgICAgdmFyIG9sZF9zc2ZpID0gZmxhZyh0aGlzLCAnc3NmaScpO1xuICAgICAgICAgIGlmIChvbGRfc3NmaSAmJiBjb25maWcuaW5jbHVkZVN0YWNrID09PSBmYWxzZSlcbiAgICAgICAgICAgIGZsYWcodGhpcywgJ3NzZmknLCBhc3NlcnQpO1xuICAgICAgICAgIHZhciByZXN1bHQgPSBjaGFpbmFibGVCZWhhdmlvci5tZXRob2QuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICByZXR1cm4gcmVzdWx0ID09PSB1bmRlZmluZWQgPyB0aGlzIDogcmVzdWx0O1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIFVzZSBgX19wcm90b19fYCBpZiBhdmFpbGFibGVcbiAgICAgICAgaWYgKGhhc1Byb3RvU3VwcG9ydCkge1xuICAgICAgICAgIC8vIEluaGVyaXQgYWxsIHByb3BlcnRpZXMgZnJvbSB0aGUgb2JqZWN0IGJ5IHJlcGxhY2luZyB0aGUgYEZ1bmN0aW9uYCBwcm90b3R5cGVcbiAgICAgICAgICB2YXIgcHJvdG90eXBlID0gYXNzZXJ0Ll9fcHJvdG9fXyA9IE9iamVjdC5jcmVhdGUodGhpcyk7XG4gICAgICAgICAgLy8gUmVzdG9yZSB0aGUgYGNhbGxgIGFuZCBgYXBwbHlgIG1ldGhvZHMgZnJvbSBgRnVuY3Rpb25gXG4gICAgICAgICAgcHJvdG90eXBlLmNhbGwgPSBjYWxsO1xuICAgICAgICAgIHByb3RvdHlwZS5hcHBseSA9IGFwcGx5O1xuICAgICAgICB9XG4gICAgICAgIC8vIE90aGVyd2lzZSwgcmVkZWZpbmUgYWxsIHByb3BlcnRpZXMgKHNsb3chKVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICB2YXIgYXNzZXJ0ZXJOYW1lcyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKGN0eCk7XG4gICAgICAgICAgYXNzZXJ0ZXJOYW1lcy5mb3JFYWNoKGZ1bmN0aW9uIChhc3NlcnRlck5hbWUpIHtcbiAgICAgICAgICAgIGlmICghZXhjbHVkZU5hbWVzLnRlc3QoYXNzZXJ0ZXJOYW1lKSkge1xuICAgICAgICAgICAgICB2YXIgcGQgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGN0eCwgYXNzZXJ0ZXJOYW1lKTtcbiAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGFzc2VydCwgYXNzZXJ0ZXJOYW1lLCBwZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB0cmFuc2ZlckZsYWdzKHRoaXMsIGFzc2VydCk7XG4gICAgICAgIHJldHVybiBhc3NlcnQ7XG4gICAgICB9XG4gICAgLCBjb25maWd1cmFibGU6IHRydWVcbiAgfSk7XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gYWRkTWV0aG9kIHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi4vY29uZmlnJyk7XG5cbi8qKlxuICogIyMjIC5hZGRNZXRob2QgKGN0eCwgbmFtZSwgbWV0aG9kKVxuICpcbiAqIEFkZHMgYSBtZXRob2QgdG8gdGhlIHByb3RvdHlwZSBvZiBhbiBvYmplY3QuXG4gKlxuICogICAgIHV0aWxzLmFkZE1ldGhvZChjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUsICdmb28nLCBmdW5jdGlvbiAoc3RyKSB7XG4gKiAgICAgICB2YXIgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gKiAgICAgICBuZXcgY2hhaS5Bc3NlcnRpb24ob2JqKS50by5iZS5lcXVhbChzdHIpO1xuICogICAgIH0pO1xuICpcbiAqIENhbiBhbHNvIGJlIGFjY2Vzc2VkIGRpcmVjdGx5IGZyb20gYGNoYWkuQXNzZXJ0aW9uYC5cbiAqXG4gKiAgICAgY2hhaS5Bc3NlcnRpb24uYWRkTWV0aG9kKCdmb28nLCBmbik7XG4gKlxuICogVGhlbiBjYW4gYmUgdXNlZCBhcyBhbnkgb3RoZXIgYXNzZXJ0aW9uLlxuICpcbiAqICAgICBleHBlY3QoZm9vU3RyKS50by5iZS5mb28oJ2JhcicpO1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjdHggb2JqZWN0IHRvIHdoaWNoIHRoZSBtZXRob2QgaXMgYWRkZWRcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIG9mIG1ldGhvZCB0byBhZGRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG1ldGhvZCBmdW5jdGlvbiB0byBiZSB1c2VkIGZvciBuYW1lXG4gKiBAbmFtZSBhZGRNZXRob2RcbiAqIEBhcGkgcHVibGljXG4gKi9cbnZhciBmbGFnID0gcmVxdWlyZSgnLi9mbGFnJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGN0eCwgbmFtZSwgbWV0aG9kKSB7XG4gIGN0eFtuYW1lXSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgb2xkX3NzZmkgPSBmbGFnKHRoaXMsICdzc2ZpJyk7XG4gICAgaWYgKG9sZF9zc2ZpICYmIGNvbmZpZy5pbmNsdWRlU3RhY2sgPT09IGZhbHNlKVxuICAgICAgZmxhZyh0aGlzLCAnc3NmaScsIGN0eFtuYW1lXSk7XG4gICAgdmFyIHJlc3VsdCA9IG1ldGhvZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIHJldHVybiByZXN1bHQgPT09IHVuZGVmaW5lZCA/IHRoaXMgOiByZXN1bHQ7XG4gIH07XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gYWRkUHJvcGVydHkgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIGFkZFByb3BlcnR5IChjdHgsIG5hbWUsIGdldHRlcilcbiAqXG4gKiBBZGRzIGEgcHJvcGVydHkgdG8gdGhlIHByb3RvdHlwZSBvZiBhbiBvYmplY3QuXG4gKlxuICogICAgIHV0aWxzLmFkZFByb3BlcnR5KGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZSwgJ2ZvbycsIGZ1bmN0aW9uICgpIHtcbiAqICAgICAgIHZhciBvYmogPSB1dGlscy5mbGFnKHRoaXMsICdvYmplY3QnKTtcbiAqICAgICAgIG5ldyBjaGFpLkFzc2VydGlvbihvYmopLnRvLmJlLmluc3RhbmNlb2YoRm9vKTtcbiAqICAgICB9KTtcbiAqXG4gKiBDYW4gYWxzbyBiZSBhY2Nlc3NlZCBkaXJlY3RseSBmcm9tIGBjaGFpLkFzc2VydGlvbmAuXG4gKlxuICogICAgIGNoYWkuQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdmb28nLCBmbik7XG4gKlxuICogVGhlbiBjYW4gYmUgdXNlZCBhcyBhbnkgb3RoZXIgYXNzZXJ0aW9uLlxuICpcbiAqICAgICBleHBlY3QobXlGb28pLnRvLmJlLmZvbztcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY3R4IG9iamVjdCB0byB3aGljaCB0aGUgcHJvcGVydHkgaXMgYWRkZWRcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIG9mIHByb3BlcnR5IHRvIGFkZFxuICogQHBhcmFtIHtGdW5jdGlvbn0gZ2V0dGVyIGZ1bmN0aW9uIHRvIGJlIHVzZWQgZm9yIG5hbWVcbiAqIEBuYW1lIGFkZFByb3BlcnR5XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGN0eCwgbmFtZSwgZ2V0dGVyKSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjdHgsIG5hbWUsXG4gICAgeyBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGdldHRlci5jYWxsKHRoaXMpO1xuICAgICAgICByZXR1cm4gcmVzdWx0ID09PSB1bmRlZmluZWQgPyB0aGlzIDogcmVzdWx0O1xuICAgICAgfVxuICAgICwgY29uZmlndXJhYmxlOiB0cnVlXG4gIH0pO1xufTtcbiIsIi8qIVxuICogQ2hhaSAtIGZsYWcgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIGZsYWcob2JqZWN0ICxrZXksIFt2YWx1ZV0pXG4gKlxuICogR2V0IG9yIHNldCBhIGZsYWcgdmFsdWUgb24gYW4gb2JqZWN0LiBJZiBhXG4gKiB2YWx1ZSBpcyBwcm92aWRlZCBpdCB3aWxsIGJlIHNldCwgZWxzZSBpdCB3aWxsXG4gKiByZXR1cm4gdGhlIGN1cnJlbnRseSBzZXQgdmFsdWUgb3IgYHVuZGVmaW5lZGAgaWZcbiAqIHRoZSB2YWx1ZSBpcyBub3Qgc2V0LlxuICpcbiAqICAgICB1dGlscy5mbGFnKHRoaXMsICdmb28nLCAnYmFyJyk7IC8vIHNldHRlclxuICogICAgIHV0aWxzLmZsYWcodGhpcywgJ2ZvbycpOyAvLyBnZXR0ZXIsIHJldHVybnMgYGJhcmBcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IChjb25zdHJ1Y3RlZCBBc3NlcnRpb25cbiAqIEBwYXJhbSB7U3RyaW5nfSBrZXlcbiAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlIChvcHRpb25hbClcbiAqIEBuYW1lIGZsYWdcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9iaiwga2V5LCB2YWx1ZSkge1xuICB2YXIgZmxhZ3MgPSBvYmouX19mbGFncyB8fCAob2JqLl9fZmxhZ3MgPSBPYmplY3QuY3JlYXRlKG51bGwpKTtcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpIHtcbiAgICBmbGFnc1trZXldID0gdmFsdWU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGZsYWdzW2tleV07XG4gIH1cbn07XG4iLCIvKiFcbiAqIENoYWkgLSBnZXRBY3R1YWwgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyBnZXRBY3R1YWwob2JqZWN0LCBbYWN0dWFsXSlcbiAqXG4gKiBSZXR1cm5zIHRoZSBgYWN0dWFsYCB2YWx1ZSBmb3IgYW4gQXNzZXJ0aW9uXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCAoY29uc3RydWN0ZWQgQXNzZXJ0aW9uKVxuICogQHBhcmFtIHtBcmd1bWVudHN9IGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZS5hc3NlcnQgYXJndW1lbnRzXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqLCBhcmdzKSB7XG4gIHJldHVybiBhcmdzLmxlbmd0aCA+IDQgPyBhcmdzWzRdIDogb2JqLl9vYmo7XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gZ2V0RW51bWVyYWJsZVByb3BlcnRpZXMgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIC5nZXRFbnVtZXJhYmxlUHJvcGVydGllcyhvYmplY3QpXG4gKlxuICogVGhpcyBhbGxvd3MgdGhlIHJldHJpZXZhbCBvZiBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIG9mIGFuIG9iamVjdCxcbiAqIGluaGVyaXRlZCBvciBub3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICogQHJldHVybnMge0FycmF5fVxuICogQG5hbWUgZ2V0RW51bWVyYWJsZVByb3BlcnRpZXNcbiAqIEBhcGkgcHVibGljXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBnZXRFbnVtZXJhYmxlUHJvcGVydGllcyhvYmplY3QpIHtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuICBmb3IgKHZhciBuYW1lIGluIG9iamVjdCkge1xuICAgIHJlc3VsdC5wdXNoKG5hbWUpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gbWVzc2FnZSBjb21wb3NpdGlvbiB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBNb2R1bGUgZGVwZW5kYW5jaWVzXG4gKi9cblxudmFyIGZsYWcgPSByZXF1aXJlKCcuL2ZsYWcnKVxuICAsIGdldEFjdHVhbCA9IHJlcXVpcmUoJy4vZ2V0QWN0dWFsJylcbiAgLCBpbnNwZWN0ID0gcmVxdWlyZSgnLi9pbnNwZWN0JylcbiAgLCBvYmpEaXNwbGF5ID0gcmVxdWlyZSgnLi9vYmpEaXNwbGF5Jyk7XG5cbi8qKlxuICogIyMjIC5nZXRNZXNzYWdlKG9iamVjdCwgbWVzc2FnZSwgbmVnYXRlTWVzc2FnZSlcbiAqXG4gKiBDb25zdHJ1Y3QgdGhlIGVycm9yIG1lc3NhZ2UgYmFzZWQgb24gZmxhZ3NcbiAqIGFuZCB0ZW1wbGF0ZSB0YWdzLiBUZW1wbGF0ZSB0YWdzIHdpbGwgcmV0dXJuXG4gKiBhIHN0cmluZ2lmaWVkIGluc3BlY3Rpb24gb2YgdGhlIG9iamVjdCByZWZlcmVuY2VkLlxuICpcbiAqIE1lc3NhZ2UgdGVtcGxhdGUgdGFnczpcbiAqIC0gYCN7dGhpc31gIGN1cnJlbnQgYXNzZXJ0ZWQgb2JqZWN0XG4gKiAtIGAje2FjdH1gIGFjdHVhbCB2YWx1ZVxuICogLSBgI3tleHB9YCBleHBlY3RlZCB2YWx1ZVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgKGNvbnN0cnVjdGVkIEFzc2VydGlvbilcbiAqIEBwYXJhbSB7QXJndW1lbnRzfSBjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUuYXNzZXJ0IGFyZ3VtZW50c1xuICogQG5hbWUgZ2V0TWVzc2FnZVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmosIGFyZ3MpIHtcbiAgdmFyIG5lZ2F0ZSA9IGZsYWcob2JqLCAnbmVnYXRlJylcbiAgICAsIHZhbCA9IGZsYWcob2JqLCAnb2JqZWN0JylcbiAgICAsIGV4cGVjdGVkID0gYXJnc1szXVxuICAgICwgYWN0dWFsID0gZ2V0QWN0dWFsKG9iaiwgYXJncylcbiAgICAsIG1zZyA9IG5lZ2F0ZSA/IGFyZ3NbMl0gOiBhcmdzWzFdXG4gICAgLCBmbGFnTXNnID0gZmxhZyhvYmosICdtZXNzYWdlJyk7XG5cbiAgbXNnID0gbXNnIHx8ICcnO1xuICBtc2cgPSBtc2dcbiAgICAucmVwbGFjZSgvI3t0aGlzfS9nLCBvYmpEaXNwbGF5KHZhbCkpXG4gICAgLnJlcGxhY2UoLyN7YWN0fS9nLCBvYmpEaXNwbGF5KGFjdHVhbCkpXG4gICAgLnJlcGxhY2UoLyN7ZXhwfS9nLCBvYmpEaXNwbGF5KGV4cGVjdGVkKSk7XG5cbiAgcmV0dXJuIGZsYWdNc2cgPyBmbGFnTXNnICsgJzogJyArIG1zZyA6IG1zZztcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBnZXROYW1lIHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKipcbiAqICMgZ2V0TmFtZShmdW5jKVxuICpcbiAqIEdldHMgdGhlIG5hbWUgb2YgYSBmdW5jdGlvbiwgaW4gYSBjcm9zcy1icm93c2VyIHdheS5cbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBhIGZ1bmN0aW9uICh1c3VhbGx5IGEgY29uc3RydWN0b3IpXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZnVuYykge1xuICBpZiAoZnVuYy5uYW1lKSByZXR1cm4gZnVuYy5uYW1lO1xuXG4gIHZhciBtYXRjaCA9IC9eXFxzP2Z1bmN0aW9uIChbXihdKilcXCgvLmV4ZWMoZnVuYyk7XG4gIHJldHVybiBtYXRjaCAmJiBtYXRjaFsxXSA/IG1hdGNoWzFdIDogXCJcIjtcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBnZXRQYXRoVmFsdWUgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2xvZ2ljYWxwYXJhZG94L2ZpbHRyXG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKipcbiAqICMjIyAuZ2V0UGF0aFZhbHVlKHBhdGgsIG9iamVjdClcbiAqXG4gKiBUaGlzIGFsbG93cyB0aGUgcmV0cmlldmFsIG9mIHZhbHVlcyBpbiBhblxuICogb2JqZWN0IGdpdmVuIGEgc3RyaW5nIHBhdGguXG4gKlxuICogICAgIHZhciBvYmogPSB7XG4gKiAgICAgICAgIHByb3AxOiB7XG4gKiAgICAgICAgICAgICBhcnI6IFsnYScsICdiJywgJ2MnXVxuICogICAgICAgICAgICwgc3RyOiAnSGVsbG8nXG4gKiAgICAgICAgIH1cbiAqICAgICAgICwgcHJvcDI6IHtcbiAqICAgICAgICAgICAgIGFycjogWyB7IG5lc3RlZDogJ1VuaXZlcnNlJyB9IF1cbiAqICAgICAgICAgICAsIHN0cjogJ0hlbGxvIGFnYWluISdcbiAqICAgICAgICAgfVxuICogICAgIH1cbiAqXG4gKiBUaGUgZm9sbG93aW5nIHdvdWxkIGJlIHRoZSByZXN1bHRzLlxuICpcbiAqICAgICBnZXRQYXRoVmFsdWUoJ3Byb3AxLnN0cicsIG9iaik7IC8vIEhlbGxvXG4gKiAgICAgZ2V0UGF0aFZhbHVlKCdwcm9wMS5hdHRbMl0nLCBvYmopOyAvLyBiXG4gKiAgICAgZ2V0UGF0aFZhbHVlKCdwcm9wMi5hcnJbMF0ubmVzdGVkJywgb2JqKTsgLy8gVW5pdmVyc2VcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gcGF0aFxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICogQHJldHVybnMge09iamVjdH0gdmFsdWUgb3IgYHVuZGVmaW5lZGBcbiAqIEBuYW1lIGdldFBhdGhWYWx1ZVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG52YXIgZ2V0UGF0aFZhbHVlID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocGF0aCwgb2JqKSB7XG4gIHZhciBwYXJzZWQgPSBwYXJzZVBhdGgocGF0aCk7XG4gIHJldHVybiBfZ2V0UGF0aFZhbHVlKHBhcnNlZCwgb2JqKTtcbn07XG5cbi8qIVxuICogIyMgcGFyc2VQYXRoKHBhdGgpXG4gKlxuICogSGVscGVyIGZ1bmN0aW9uIHVzZWQgdG8gcGFyc2Ugc3RyaW5nIG9iamVjdFxuICogcGF0aHMuIFVzZSBpbiBjb25qdW5jdGlvbiB3aXRoIGBfZ2V0UGF0aFZhbHVlYC5cbiAqXG4gKiAgICAgIHZhciBwYXJzZWQgPSBwYXJzZVBhdGgoJ215b2JqZWN0LnByb3BlcnR5LnN1YnByb3AnKTtcbiAqXG4gKiAjIyMgUGF0aHM6XG4gKlxuICogKiBDYW4gYmUgYXMgbmVhciBpbmZpbml0ZWx5IGRlZXAgYW5kIG5lc3RlZFxuICogKiBBcnJheXMgYXJlIGFsc28gdmFsaWQgdXNpbmcgdGhlIGZvcm1hbCBgbXlvYmplY3QuZG9jdW1lbnRbM10ucHJvcGVydHlgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYXRoXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBwYXJzZWRcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIHBhcnNlUGF0aCAocGF0aCkge1xuICB2YXIgc3RyID0gcGF0aC5yZXBsYWNlKC9cXFsvZywgJy5bJylcbiAgICAsIHBhcnRzID0gc3RyLm1hdGNoKC8oXFxcXFxcLnxbXi5dKz8pKy9nKTtcbiAgcmV0dXJuIHBhcnRzLm1hcChmdW5jdGlvbiAodmFsdWUpIHtcbiAgICB2YXIgcmUgPSAvXFxbKFxcZCspXFxdJC9cbiAgICAgICwgbUFyciA9IHJlLmV4ZWModmFsdWUpXG4gICAgaWYgKG1BcnIpIHJldHVybiB7IGk6IHBhcnNlRmxvYXQobUFyclsxXSkgfTtcbiAgICBlbHNlIHJldHVybiB7IHA6IHZhbHVlIH07XG4gIH0pO1xufTtcblxuLyohXG4gKiAjIyBfZ2V0UGF0aFZhbHVlKHBhcnNlZCwgb2JqKVxuICpcbiAqIEhlbHBlciBjb21wYW5pb24gZnVuY3Rpb24gZm9yIGAucGFyc2VQYXRoYCB0aGF0IHJldHVybnNcbiAqIHRoZSB2YWx1ZSBsb2NhdGVkIGF0IHRoZSBwYXJzZWQgYWRkcmVzcy5cbiAqXG4gKiAgICAgIHZhciB2YWx1ZSA9IGdldFBhdGhWYWx1ZShwYXJzZWQsIG9iaik7XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IHBhcnNlZCBkZWZpbml0aW9uIGZyb20gYHBhcnNlUGF0aGAuXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IHRvIHNlYXJjaCBhZ2FpbnN0XG4gKiBAcmV0dXJucyB7T2JqZWN0fFVuZGVmaW5lZH0gdmFsdWVcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIF9nZXRQYXRoVmFsdWUgKHBhcnNlZCwgb2JqKSB7XG4gIHZhciB0bXAgPSBvYmpcbiAgICAsIHJlcztcbiAgZm9yICh2YXIgaSA9IDAsIGwgPSBwYXJzZWQubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgdmFyIHBhcnQgPSBwYXJzZWRbaV07XG4gICAgaWYgKHRtcCkge1xuICAgICAgaWYgKCd1bmRlZmluZWQnICE9PSB0eXBlb2YgcGFydC5wKVxuICAgICAgICB0bXAgPSB0bXBbcGFydC5wXTtcbiAgICAgIGVsc2UgaWYgKCd1bmRlZmluZWQnICE9PSB0eXBlb2YgcGFydC5pKVxuICAgICAgICB0bXAgPSB0bXBbcGFydC5pXTtcbiAgICAgIGlmIChpID09IChsIC0gMSkpIHJlcyA9IHRtcDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzO1xufTtcbiIsIi8qIVxuICogQ2hhaSAtIGdldFByb3BlcnRpZXMgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIC5nZXRQcm9wZXJ0aWVzKG9iamVjdClcbiAqXG4gKiBUaGlzIGFsbG93cyB0aGUgcmV0cmlldmFsIG9mIHByb3BlcnR5IG5hbWVzIG9mIGFuIG9iamVjdCwgZW51bWVyYWJsZSBvciBub3QsXG4gKiBpbmhlcml0ZWQgb3Igbm90LlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAqIEByZXR1cm5zIHtBcnJheX1cbiAqIEBuYW1lIGdldFByb3BlcnRpZXNcbiAqIEBhcGkgcHVibGljXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBnZXRQcm9wZXJ0aWVzKG9iamVjdCkge1xuICB2YXIgcmVzdWx0ID0gT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoc3ViamVjdCk7XG5cbiAgZnVuY3Rpb24gYWRkUHJvcGVydHkocHJvcGVydHkpIHtcbiAgICBpZiAocmVzdWx0LmluZGV4T2YocHJvcGVydHkpID09PSAtMSkge1xuICAgICAgcmVzdWx0LnB1c2gocHJvcGVydHkpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihzdWJqZWN0KTtcbiAgd2hpbGUgKHByb3RvICE9PSBudWxsKSB7XG4gICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMocHJvdG8pLmZvckVhY2goYWRkUHJvcGVydHkpO1xuICAgIHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHByb3RvKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59O1xuIiwiLyohXG4gKiBjaGFpXG4gKiBDb3B5cmlnaHQoYykgMjAxMSBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qIVxuICogTWFpbiBleHBvcnRzXG4gKi9cblxudmFyIGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG4vKiFcbiAqIHRlc3QgdXRpbGl0eVxuICovXG5cbmV4cG9ydHMudGVzdCA9IHJlcXVpcmUoJy4vdGVzdCcpO1xuXG4vKiFcbiAqIHR5cGUgdXRpbGl0eVxuICovXG5cbmV4cG9ydHMudHlwZSA9IHJlcXVpcmUoJy4vdHlwZScpO1xuXG4vKiFcbiAqIG1lc3NhZ2UgdXRpbGl0eVxuICovXG5cbmV4cG9ydHMuZ2V0TWVzc2FnZSA9IHJlcXVpcmUoJy4vZ2V0TWVzc2FnZScpO1xuXG4vKiFcbiAqIGFjdHVhbCB1dGlsaXR5XG4gKi9cblxuZXhwb3J0cy5nZXRBY3R1YWwgPSByZXF1aXJlKCcuL2dldEFjdHVhbCcpO1xuXG4vKiFcbiAqIEluc3BlY3QgdXRpbFxuICovXG5cbmV4cG9ydHMuaW5zcGVjdCA9IHJlcXVpcmUoJy4vaW5zcGVjdCcpO1xuXG4vKiFcbiAqIE9iamVjdCBEaXNwbGF5IHV0aWxcbiAqL1xuXG5leHBvcnRzLm9iakRpc3BsYXkgPSByZXF1aXJlKCcuL29iakRpc3BsYXknKTtcblxuLyohXG4gKiBGbGFnIHV0aWxpdHlcbiAqL1xuXG5leHBvcnRzLmZsYWcgPSByZXF1aXJlKCcuL2ZsYWcnKTtcblxuLyohXG4gKiBGbGFnIHRyYW5zZmVycmluZyB1dGlsaXR5XG4gKi9cblxuZXhwb3J0cy50cmFuc2ZlckZsYWdzID0gcmVxdWlyZSgnLi90cmFuc2ZlckZsYWdzJyk7XG5cbi8qIVxuICogRGVlcCBlcXVhbCB1dGlsaXR5XG4gKi9cblxuZXhwb3J0cy5lcWwgPSByZXF1aXJlKCdkZWVwLWVxbCcpO1xuXG4vKiFcbiAqIERlZXAgcGF0aCB2YWx1ZVxuICovXG5cbmV4cG9ydHMuZ2V0UGF0aFZhbHVlID0gcmVxdWlyZSgnLi9nZXRQYXRoVmFsdWUnKTtcblxuLyohXG4gKiBGdW5jdGlvbiBuYW1lXG4gKi9cblxuZXhwb3J0cy5nZXROYW1lID0gcmVxdWlyZSgnLi9nZXROYW1lJyk7XG5cbi8qIVxuICogYWRkIFByb3BlcnR5XG4gKi9cblxuZXhwb3J0cy5hZGRQcm9wZXJ0eSA9IHJlcXVpcmUoJy4vYWRkUHJvcGVydHknKTtcblxuLyohXG4gKiBhZGQgTWV0aG9kXG4gKi9cblxuZXhwb3J0cy5hZGRNZXRob2QgPSByZXF1aXJlKCcuL2FkZE1ldGhvZCcpO1xuXG4vKiFcbiAqIG92ZXJ3cml0ZSBQcm9wZXJ0eVxuICovXG5cbmV4cG9ydHMub3ZlcndyaXRlUHJvcGVydHkgPSByZXF1aXJlKCcuL292ZXJ3cml0ZVByb3BlcnR5Jyk7XG5cbi8qIVxuICogb3ZlcndyaXRlIE1ldGhvZFxuICovXG5cbmV4cG9ydHMub3ZlcndyaXRlTWV0aG9kID0gcmVxdWlyZSgnLi9vdmVyd3JpdGVNZXRob2QnKTtcblxuLyohXG4gKiBBZGQgYSBjaGFpbmFibGUgbWV0aG9kXG4gKi9cblxuZXhwb3J0cy5hZGRDaGFpbmFibGVNZXRob2QgPSByZXF1aXJlKCcuL2FkZENoYWluYWJsZU1ldGhvZCcpO1xuXG4vKiFcbiAqIE92ZXJ3cml0ZSBjaGFpbmFibGUgbWV0aG9kXG4gKi9cblxuZXhwb3J0cy5vdmVyd3JpdGVDaGFpbmFibGVNZXRob2QgPSByZXF1aXJlKCcuL292ZXJ3cml0ZUNoYWluYWJsZU1ldGhvZCcpO1xuXG4iLCIvLyBUaGlzIGlzIChhbG1vc3QpIGRpcmVjdGx5IGZyb20gTm9kZS5qcyB1dGlsc1xuLy8gaHR0cHM6Ly9naXRodWIuY29tL2pveWVudC9ub2RlL2Jsb2IvZjhjMzM1ZDBjYWY0N2YxNmQzMTQxM2Y4OWFhMjhlZGEzODc4ZTNhYS9saWIvdXRpbC5qc1xuXG52YXIgZ2V0TmFtZSA9IHJlcXVpcmUoJy4vZ2V0TmFtZScpO1xudmFyIGdldFByb3BlcnRpZXMgPSByZXF1aXJlKCcuL2dldFByb3BlcnRpZXMnKTtcbnZhciBnZXRFbnVtZXJhYmxlUHJvcGVydGllcyA9IHJlcXVpcmUoJy4vZ2V0RW51bWVyYWJsZVByb3BlcnRpZXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBpbnNwZWN0O1xuXG4vKipcbiAqIEVjaG9zIHRoZSB2YWx1ZSBvZiBhIHZhbHVlLiBUcnlzIHRvIHByaW50IHRoZSB2YWx1ZSBvdXRcbiAqIGluIHRoZSBiZXN0IHdheSBwb3NzaWJsZSBnaXZlbiB0aGUgZGlmZmVyZW50IHR5cGVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBwcmludCBvdXQuXG4gKiBAcGFyYW0ge0Jvb2xlYW59IHNob3dIaWRkZW4gRmxhZyB0aGF0IHNob3dzIGhpZGRlbiAobm90IGVudW1lcmFibGUpXG4gKiAgICBwcm9wZXJ0aWVzIG9mIG9iamVjdHMuXG4gKiBAcGFyYW0ge051bWJlcn0gZGVwdGggRGVwdGggaW4gd2hpY2ggdG8gZGVzY2VuZCBpbiBvYmplY3QuIERlZmF1bHQgaXMgMi5cbiAqIEBwYXJhbSB7Qm9vbGVhbn0gY29sb3JzIEZsYWcgdG8gdHVybiBvbiBBTlNJIGVzY2FwZSBjb2RlcyB0byBjb2xvciB0aGVcbiAqICAgIG91dHB1dC4gRGVmYXVsdCBpcyBmYWxzZSAobm8gY29sb3JpbmcpLlxuICovXG5mdW5jdGlvbiBpbnNwZWN0KG9iaiwgc2hvd0hpZGRlbiwgZGVwdGgsIGNvbG9ycykge1xuICB2YXIgY3R4ID0ge1xuICAgIHNob3dIaWRkZW46IHNob3dIaWRkZW4sXG4gICAgc2VlbjogW10sXG4gICAgc3R5bGl6ZTogZnVuY3Rpb24gKHN0cikgeyByZXR1cm4gc3RyOyB9XG4gIH07XG4gIHJldHVybiBmb3JtYXRWYWx1ZShjdHgsIG9iaiwgKHR5cGVvZiBkZXB0aCA9PT0gJ3VuZGVmaW5lZCcgPyAyIDogZGVwdGgpKTtcbn1cblxuLy8gaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vMTA0NDEyOC9cbnZhciBnZXRPdXRlckhUTUwgPSBmdW5jdGlvbihlbGVtZW50KSB7XG4gIGlmICgnb3V0ZXJIVE1MJyBpbiBlbGVtZW50KSByZXR1cm4gZWxlbWVudC5vdXRlckhUTUw7XG4gIHZhciBucyA9IFwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbFwiO1xuICB2YXIgY29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKG5zLCAnXycpO1xuICB2YXIgZWxlbVByb3RvID0gKHdpbmRvdy5IVE1MRWxlbWVudCB8fCB3aW5kb3cuRWxlbWVudCkucHJvdG90eXBlO1xuICB2YXIgeG1sU2VyaWFsaXplciA9IG5ldyBYTUxTZXJpYWxpemVyKCk7XG4gIHZhciBodG1sO1xuICBpZiAoZG9jdW1lbnQueG1sVmVyc2lvbikge1xuICAgIHJldHVybiB4bWxTZXJpYWxpemVyLnNlcmlhbGl6ZVRvU3RyaW5nKGVsZW1lbnQpO1xuICB9IGVsc2Uge1xuICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZChlbGVtZW50LmNsb25lTm9kZShmYWxzZSkpO1xuICAgIGh0bWwgPSBjb250YWluZXIuaW5uZXJIVE1MLnJlcGxhY2UoJz48JywgJz4nICsgZWxlbWVudC5pbm5lckhUTUwgKyAnPCcpO1xuICAgIGNvbnRhaW5lci5pbm5lckhUTUwgPSAnJztcbiAgICByZXR1cm4gaHRtbDtcbiAgfVxufTtcblxuLy8gUmV0dXJucyB0cnVlIGlmIG9iamVjdCBpcyBhIERPTSBlbGVtZW50LlxudmFyIGlzRE9NRWxlbWVudCA9IGZ1bmN0aW9uIChvYmplY3QpIHtcbiAgaWYgKHR5cGVvZiBIVE1MRWxlbWVudCA9PT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm4gb2JqZWN0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQ7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG9iamVjdCAmJlxuICAgICAgdHlwZW9mIG9iamVjdCA9PT0gJ29iamVjdCcgJiZcbiAgICAgIG9iamVjdC5ub2RlVHlwZSA9PT0gMSAmJlxuICAgICAgdHlwZW9mIG9iamVjdC5ub2RlTmFtZSA9PT0gJ3N0cmluZyc7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGZvcm1hdFZhbHVlKGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcykge1xuICAvLyBQcm92aWRlIGEgaG9vayBmb3IgdXNlci1zcGVjaWZpZWQgaW5zcGVjdCBmdW5jdGlvbnMuXG4gIC8vIENoZWNrIHRoYXQgdmFsdWUgaXMgYW4gb2JqZWN0IHdpdGggYW4gaW5zcGVjdCBmdW5jdGlvbiBvbiBpdFxuICBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlLmluc3BlY3QgPT09ICdmdW5jdGlvbicgJiZcbiAgICAgIC8vIEZpbHRlciBvdXQgdGhlIHV0aWwgbW9kdWxlLCBpdCdzIGluc3BlY3QgZnVuY3Rpb24gaXMgc3BlY2lhbFxuICAgICAgdmFsdWUuaW5zcGVjdCAhPT0gZXhwb3J0cy5pbnNwZWN0ICYmXG4gICAgICAvLyBBbHNvIGZpbHRlciBvdXQgYW55IHByb3RvdHlwZSBvYmplY3RzIHVzaW5nIHRoZSBjaXJjdWxhciBjaGVjay5cbiAgICAgICEodmFsdWUuY29uc3RydWN0b3IgJiYgdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlID09PSB2YWx1ZSkpIHtcbiAgICB2YXIgcmV0ID0gdmFsdWUuaW5zcGVjdChyZWN1cnNlVGltZXMpO1xuICAgIGlmICh0eXBlb2YgcmV0ICE9PSAnc3RyaW5nJykge1xuICAgICAgcmV0ID0gZm9ybWF0VmFsdWUoY3R4LCByZXQsIHJlY3Vyc2VUaW1lcyk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvLyBQcmltaXRpdmUgdHlwZXMgY2Fubm90IGhhdmUgcHJvcGVydGllc1xuICB2YXIgcHJpbWl0aXZlID0gZm9ybWF0UHJpbWl0aXZlKGN0eCwgdmFsdWUpO1xuICBpZiAocHJpbWl0aXZlKSB7XG4gICAgcmV0dXJuIHByaW1pdGl2ZTtcbiAgfVxuXG4gIC8vIElmIGl0J3MgRE9NIGVsZW0sIGdldCBvdXRlciBIVE1MLlxuICBpZiAoaXNET01FbGVtZW50KHZhbHVlKSkge1xuICAgIHJldHVybiBnZXRPdXRlckhUTUwodmFsdWUpO1xuICB9XG5cbiAgLy8gTG9vayB1cCB0aGUga2V5cyBvZiB0aGUgb2JqZWN0LlxuICB2YXIgdmlzaWJsZUtleXMgPSBnZXRFbnVtZXJhYmxlUHJvcGVydGllcyh2YWx1ZSk7XG4gIHZhciBrZXlzID0gY3R4LnNob3dIaWRkZW4gPyBnZXRQcm9wZXJ0aWVzKHZhbHVlKSA6IHZpc2libGVLZXlzO1xuXG4gIC8vIFNvbWUgdHlwZSBvZiBvYmplY3Qgd2l0aG91dCBwcm9wZXJ0aWVzIGNhbiBiZSBzaG9ydGN1dHRlZC5cbiAgLy8gSW4gSUUsIGVycm9ycyBoYXZlIGEgc2luZ2xlIGBzdGFja2AgcHJvcGVydHksIG9yIGlmIHRoZXkgYXJlIHZhbmlsbGEgYEVycm9yYCxcbiAgLy8gYSBgc3RhY2tgIHBsdXMgYGRlc2NyaXB0aW9uYCBwcm9wZXJ0eTsgaWdub3JlIHRob3NlIGZvciBjb25zaXN0ZW5jeS5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwIHx8IChpc0Vycm9yKHZhbHVlKSAmJiAoXG4gICAgICAoa2V5cy5sZW5ndGggPT09IDEgJiYga2V5c1swXSA9PT0gJ3N0YWNrJykgfHxcbiAgICAgIChrZXlzLmxlbmd0aCA9PT0gMiAmJiBrZXlzWzBdID09PSAnZGVzY3JpcHRpb24nICYmIGtleXNbMV0gPT09ICdzdGFjaycpXG4gICAgICkpKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdmFyIG5hbWUgPSBnZXROYW1lKHZhbHVlKTtcbiAgICAgIHZhciBuYW1lU3VmZml4ID0gbmFtZSA/ICc6ICcgKyBuYW1lIDogJyc7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJ1tGdW5jdGlvbicgKyBuYW1lU3VmZml4ICsgJ10nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgICBpZiAoaXNSZWdFeHAodmFsdWUpKSB7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoUmVnRXhwLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSwgJ3JlZ2V4cCcpO1xuICAgIH1cbiAgICBpZiAoaXNEYXRlKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKERhdGUucHJvdG90eXBlLnRvVVRDU3RyaW5nLmNhbGwodmFsdWUpLCAnZGF0ZScpO1xuICAgIH1cbiAgICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBmb3JtYXRFcnJvcih2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgdmFyIGJhc2UgPSAnJywgYXJyYXkgPSBmYWxzZSwgYnJhY2VzID0gWyd7JywgJ30nXTtcblxuICAvLyBNYWtlIEFycmF5IHNheSB0aGF0IHRoZXkgYXJlIEFycmF5XG4gIGlmIChpc0FycmF5KHZhbHVlKSkge1xuICAgIGFycmF5ID0gdHJ1ZTtcbiAgICBicmFjZXMgPSBbJ1snLCAnXSddO1xuICB9XG5cbiAgLy8gTWFrZSBmdW5jdGlvbnMgc2F5IHRoYXQgdGhleSBhcmUgZnVuY3Rpb25zXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICB2YXIgbmFtZSA9IGdldE5hbWUodmFsdWUpO1xuICAgIHZhciBuYW1lU3VmZml4ID0gbmFtZSA/ICc6ICcgKyBuYW1lIDogJyc7XG4gICAgYmFzZSA9ICcgW0Z1bmN0aW9uJyArIG5hbWVTdWZmaXggKyAnXSc7XG4gIH1cblxuICAvLyBNYWtlIFJlZ0V4cHMgc2F5IHRoYXQgdGhleSBhcmUgUmVnRXhwc1xuICBpZiAoaXNSZWdFeHAodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gIH1cblxuICAvLyBNYWtlIGRhdGVzIHdpdGggcHJvcGVydGllcyBmaXJzdCBzYXkgdGhlIGRhdGVcbiAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICBiYXNlID0gJyAnICsgRGF0ZS5wcm90b3R5cGUudG9VVENTdHJpbmcuY2FsbCh2YWx1ZSk7XG4gIH1cblxuICAvLyBNYWtlIGVycm9yIHdpdGggbWVzc2FnZSBmaXJzdCBzYXkgdGhlIGVycm9yXG4gIGlmIChpc0Vycm9yKHZhbHVlKSkge1xuICAgIHJldHVybiBmb3JtYXRFcnJvcih2YWx1ZSk7XG4gIH1cblxuICBpZiAoa2V5cy5sZW5ndGggPT09IDAgJiYgKCFhcnJheSB8fCB2YWx1ZS5sZW5ndGggPT0gMCkpIHtcbiAgICByZXR1cm4gYnJhY2VzWzBdICsgYmFzZSArIGJyYWNlc1sxXTtcbiAgfVxuXG4gIGlmIChyZWN1cnNlVGltZXMgPCAwKSB7XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbT2JqZWN0XScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9XG5cbiAgY3R4LnNlZW4ucHVzaCh2YWx1ZSk7XG5cbiAgdmFyIG91dHB1dDtcbiAgaWYgKGFycmF5KSB7XG4gICAgb3V0cHV0ID0gZm9ybWF0QXJyYXkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5cyk7XG4gIH0gZWxzZSB7XG4gICAgb3V0cHV0ID0ga2V5cy5tYXAoZnVuY3Rpb24oa2V5KSB7XG4gICAgICByZXR1cm4gZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5LCBhcnJheSk7XG4gICAgfSk7XG4gIH1cblxuICBjdHguc2Vlbi5wb3AoKTtcblxuICByZXR1cm4gcmVkdWNlVG9TaW5nbGVTdHJpbmcob3V0cHV0LCBiYXNlLCBicmFjZXMpO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFByaW1pdGl2ZShjdHgsIHZhbHVlKSB7XG4gIHN3aXRjaCAodHlwZW9mIHZhbHVlKSB7XG4gICAgY2FzZSAndW5kZWZpbmVkJzpcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgndW5kZWZpbmVkJywgJ3VuZGVmaW5lZCcpO1xuXG4gICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgIHZhciBzaW1wbGUgPSAnXFwnJyArIEpTT04uc3RyaW5naWZ5KHZhbHVlKS5yZXBsYWNlKC9eXCJ8XCIkL2csICcnKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXCIvZywgJ1wiJykgKyAnXFwnJztcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShzaW1wbGUsICdzdHJpbmcnKTtcblxuICAgIGNhc2UgJ251bWJlcic6XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJycgKyB2YWx1ZSwgJ251bWJlcicpO1xuXG4gICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJycgKyB2YWx1ZSwgJ2Jvb2xlYW4nKTtcbiAgfVxuICAvLyBGb3Igc29tZSByZWFzb24gdHlwZW9mIG51bGwgaXMgXCJvYmplY3RcIiwgc28gc3BlY2lhbCBjYXNlIGhlcmUuXG4gIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgIHJldHVybiBjdHguc3R5bGl6ZSgnbnVsbCcsICdudWxsJyk7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRFcnJvcih2YWx1ZSkge1xuICByZXR1cm4gJ1snICsgRXJyb3IucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpICsgJ10nO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpIHtcbiAgdmFyIG91dHB1dCA9IFtdO1xuICBmb3IgKHZhciBpID0gMCwgbCA9IHZhbHVlLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodmFsdWUsIFN0cmluZyhpKSkpIHtcbiAgICAgIG91dHB1dC5wdXNoKGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsXG4gICAgICAgICAgU3RyaW5nKGkpLCB0cnVlKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dHB1dC5wdXNoKCcnKTtcbiAgICB9XG4gIH1cbiAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgIGlmICgha2V5Lm1hdGNoKC9eXFxkKyQvKSkge1xuICAgICAgb3V0cHV0LnB1c2goZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cyxcbiAgICAgICAgICBrZXksIHRydWUpKTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gb3V0cHV0O1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpIHtcbiAgdmFyIG5hbWUsIHN0cjtcbiAgaWYgKHZhbHVlLl9fbG9va3VwR2V0dGVyX18pIHtcbiAgICBpZiAodmFsdWUuX19sb29rdXBHZXR0ZXJfXyhrZXkpKSB7XG4gICAgICBpZiAodmFsdWUuX19sb29rdXBTZXR0ZXJfXyhrZXkpKSB7XG4gICAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbR2V0dGVyL1NldHRlcl0nLCAnc3BlY2lhbCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHZhbHVlLl9fbG9va3VwU2V0dGVyX18oa2V5KSkge1xuICAgICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW1NldHRlcl0nLCAnc3BlY2lhbCcpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBpZiAodmlzaWJsZUtleXMuaW5kZXhPZihrZXkpIDwgMCkge1xuICAgIG5hbWUgPSAnWycgKyBrZXkgKyAnXSc7XG4gIH1cbiAgaWYgKCFzdHIpIHtcbiAgICBpZiAoY3R4LnNlZW4uaW5kZXhPZih2YWx1ZVtrZXldKSA8IDApIHtcbiAgICAgIGlmIChyZWN1cnNlVGltZXMgPT09IG51bGwpIHtcbiAgICAgICAgc3RyID0gZm9ybWF0VmFsdWUoY3R4LCB2YWx1ZVtrZXldLCBudWxsKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0ciA9IGZvcm1hdFZhbHVlKGN0eCwgdmFsdWVba2V5XSwgcmVjdXJzZVRpbWVzIC0gMSk7XG4gICAgICB9XG4gICAgICBpZiAoc3RyLmluZGV4T2YoJ1xcbicpID4gLTEpIHtcbiAgICAgICAgaWYgKGFycmF5KSB7XG4gICAgICAgICAgc3RyID0gc3RyLnNwbGl0KCdcXG4nKS5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgcmV0dXJuICcgICcgKyBsaW5lO1xuICAgICAgICAgIH0pLmpvaW4oJ1xcbicpLnN1YnN0cigyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzdHIgPSAnXFxuJyArIHN0ci5zcGxpdCgnXFxuJykubWFwKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgICAgICAgIHJldHVybiAnICAgJyArIGxpbmU7XG4gICAgICAgICAgfSkuam9pbignXFxuJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tDaXJjdWxhcl0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuICBpZiAodHlwZW9mIG5hbWUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKGFycmF5ICYmIGtleS5tYXRjaCgvXlxcZCskLykpIHtcbiAgICAgIHJldHVybiBzdHI7XG4gICAgfVxuICAgIG5hbWUgPSBKU09OLnN0cmluZ2lmeSgnJyArIGtleSk7XG4gICAgaWYgKG5hbWUubWF0Y2goL15cIihbYS16QS1aX11bYS16QS1aXzAtOV0qKVwiJC8pKSB7XG4gICAgICBuYW1lID0gbmFtZS5zdWJzdHIoMSwgbmFtZS5sZW5ndGggLSAyKTtcbiAgICAgIG5hbWUgPSBjdHguc3R5bGl6ZShuYW1lLCAnbmFtZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuYW1lID0gbmFtZS5yZXBsYWNlKC8nL2csIFwiXFxcXCdcIilcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcXFxcIi9nLCAnXCInKVxuICAgICAgICAgICAgICAgICAucmVwbGFjZSgvKF5cInxcIiQpL2csIFwiJ1wiKTtcbiAgICAgIG5hbWUgPSBjdHguc3R5bGl6ZShuYW1lLCAnc3RyaW5nJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5hbWUgKyAnOiAnICsgc3RyO1xufVxuXG5cbmZ1bmN0aW9uIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKSB7XG4gIHZhciBudW1MaW5lc0VzdCA9IDA7XG4gIHZhciBsZW5ndGggPSBvdXRwdXQucmVkdWNlKGZ1bmN0aW9uKHByZXYsIGN1cikge1xuICAgIG51bUxpbmVzRXN0Kys7XG4gICAgaWYgKGN1ci5pbmRleE9mKCdcXG4nKSA+PSAwKSBudW1MaW5lc0VzdCsrO1xuICAgIHJldHVybiBwcmV2ICsgY3VyLmxlbmd0aCArIDE7XG4gIH0sIDApO1xuXG4gIGlmIChsZW5ndGggPiA2MCkge1xuICAgIHJldHVybiBicmFjZXNbMF0gK1xuICAgICAgICAgICAoYmFzZSA9PT0gJycgPyAnJyA6IGJhc2UgKyAnXFxuICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgb3V0cHV0LmpvaW4oJyxcXG4gICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgYnJhY2VzWzFdO1xuICB9XG5cbiAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyAnICcgKyBvdXRwdXQuam9pbignLCAnKSArICcgJyArIGJyYWNlc1sxXTtcbn1cblxuZnVuY3Rpb24gaXNBcnJheShhcikge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShhcikgfHxcbiAgICAgICAgICh0eXBlb2YgYXIgPT09ICdvYmplY3QnICYmIG9iamVjdFRvU3RyaW5nKGFyKSA9PT0gJ1tvYmplY3QgQXJyYXldJyk7XG59XG5cbmZ1bmN0aW9uIGlzUmVnRXhwKHJlKSB7XG4gIHJldHVybiB0eXBlb2YgcmUgPT09ICdvYmplY3QnICYmIG9iamVjdFRvU3RyaW5nKHJlKSA9PT0gJ1tvYmplY3QgUmVnRXhwXSc7XG59XG5cbmZ1bmN0aW9uIGlzRGF0ZShkKSB7XG4gIHJldHVybiB0eXBlb2YgZCA9PT0gJ29iamVjdCcgJiYgb2JqZWN0VG9TdHJpbmcoZCkgPT09ICdbb2JqZWN0IERhdGVdJztcbn1cblxuZnVuY3Rpb24gaXNFcnJvcihlKSB7XG4gIHJldHVybiB0eXBlb2YgZSA9PT0gJ29iamVjdCcgJiYgb2JqZWN0VG9TdHJpbmcoZSkgPT09ICdbb2JqZWN0IEVycm9yXSc7XG59XG5cbmZ1bmN0aW9uIG9iamVjdFRvU3RyaW5nKG8pIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTtcbn1cbiIsIi8qIVxuICogQ2hhaSAtIGZsYWcgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qIVxuICogTW9kdWxlIGRlcGVuZGFuY2llc1xuICovXG5cbnZhciBpbnNwZWN0ID0gcmVxdWlyZSgnLi9pbnNwZWN0Jyk7XG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi4vY29uZmlnJyk7XG5cbi8qKlxuICogIyMjIC5vYmpEaXNwbGF5IChvYmplY3QpXG4gKlxuICogRGV0ZXJtaW5lcyBpZiBhbiBvYmplY3Qgb3IgYW4gYXJyYXkgbWF0Y2hlc1xuICogY3JpdGVyaWEgdG8gYmUgaW5zcGVjdGVkIGluLWxpbmUgZm9yIGVycm9yXG4gKiBtZXNzYWdlcyBvciBzaG91bGQgYmUgdHJ1bmNhdGVkLlxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IGphdmFzY3JpcHQgb2JqZWN0IHRvIGluc3BlY3RcbiAqIEBuYW1lIG9iakRpc3BsYXlcbiAqIEBhcGkgcHVibGljXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7XG4gIHZhciBzdHIgPSBpbnNwZWN0KG9iailcbiAgICAsIHR5cGUgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKTtcblxuICBpZiAoY29uZmlnLnRydW5jYXRlVGhyZXNob2xkICYmIHN0ci5sZW5ndGggPj0gY29uZmlnLnRydW5jYXRlVGhyZXNob2xkKSB7XG4gICAgaWYgKHR5cGUgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXScpIHtcbiAgICAgIHJldHVybiAhb2JqLm5hbWUgfHwgb2JqLm5hbWUgPT09ICcnXG4gICAgICAgID8gJ1tGdW5jdGlvbl0nXG4gICAgICAgIDogJ1tGdW5jdGlvbjogJyArIG9iai5uYW1lICsgJ10nO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ1tvYmplY3QgQXJyYXldJykge1xuICAgICAgcmV0dXJuICdbIEFycmF5KCcgKyBvYmoubGVuZ3RoICsgJykgXSc7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnW29iamVjdCBPYmplY3RdJykge1xuICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhvYmopXG4gICAgICAgICwga3N0ciA9IGtleXMubGVuZ3RoID4gMlxuICAgICAgICAgID8ga2V5cy5zcGxpY2UoMCwgMikuam9pbignLCAnKSArICcsIC4uLidcbiAgICAgICAgICA6IGtleXMuam9pbignLCAnKTtcbiAgICAgIHJldHVybiAneyBPYmplY3QgKCcgKyBrc3RyICsgJykgfSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBzdHI7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBzdHI7XG4gIH1cbn07XG4iLCIvKiFcbiAqIENoYWkgLSBvdmVyd3JpdGVDaGFpbmFibGVNZXRob2QgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIG92ZXJ3cml0ZUNoYWluYWJsZU1ldGhvZCAoY3R4LCBuYW1lLCBmbilcbiAqXG4gKiBPdmVyd2l0ZXMgYW4gYWxyZWFkeSBleGlzdGluZyBjaGFpbmFibGUgbWV0aG9kXG4gKiBhbmQgcHJvdmlkZXMgYWNjZXNzIHRvIHRoZSBwcmV2aW91cyBmdW5jdGlvbiBvclxuICogcHJvcGVydHkuICBNdXN0IHJldHVybiBmdW5jdGlvbnMgdG8gYmUgdXNlZCBmb3JcbiAqIG5hbWUuXG4gKlxuICogICAgIHV0aWxzLm92ZXJ3cml0ZUNoYWluYWJsZU1ldGhvZChjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUsICdsZW5ndGgnLFxuICogICAgICAgZnVuY3Rpb24gKF9zdXBlcikge1xuICogICAgICAgfVxuICogICAgICwgZnVuY3Rpb24gKF9zdXBlcikge1xuICogICAgICAgfVxuICogICAgICk7XG4gKlxuICogQ2FuIGFsc28gYmUgYWNjZXNzZWQgZGlyZWN0bHkgZnJvbSBgY2hhaS5Bc3NlcnRpb25gLlxuICpcbiAqICAgICBjaGFpLkFzc2VydGlvbi5vdmVyd3JpdGVDaGFpbmFibGVNZXRob2QoJ2ZvbycsIGZuLCBmbik7XG4gKlxuICogVGhlbiBjYW4gYmUgdXNlZCBhcyBhbnkgb3RoZXIgYXNzZXJ0aW9uLlxuICpcbiAqICAgICBleHBlY3QobXlGb28pLnRvLmhhdmUubGVuZ3RoKDMpO1xuICogICAgIGV4cGVjdChteUZvbykudG8uaGF2ZS5sZW5ndGguYWJvdmUoMyk7XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGN0eCBvYmplY3Qgd2hvc2UgbWV0aG9kIC8gcHJvcGVydHkgaXMgdG8gYmUgb3ZlcndyaXR0ZW5cbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIG9mIG1ldGhvZCAvIHByb3BlcnR5IHRvIG92ZXJ3cml0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gbWV0aG9kIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIGZ1bmN0aW9uIHRvIGJlIHVzZWQgZm9yIG5hbWVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNoYWluaW5nQmVoYXZpb3IgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEgZnVuY3Rpb24gdG8gYmUgdXNlZCBmb3IgcHJvcGVydHlcbiAqIEBuYW1lIG92ZXJ3cml0ZUNoYWluYWJsZU1ldGhvZFxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjdHgsIG5hbWUsIG1ldGhvZCwgY2hhaW5pbmdCZWhhdmlvcikge1xuICB2YXIgY2hhaW5hYmxlQmVoYXZpb3IgPSBjdHguX19tZXRob2RzW25hbWVdO1xuXG4gIHZhciBfY2hhaW5pbmdCZWhhdmlvciA9IGNoYWluYWJsZUJlaGF2aW9yLmNoYWluaW5nQmVoYXZpb3I7XG4gIGNoYWluYWJsZUJlaGF2aW9yLmNoYWluaW5nQmVoYXZpb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHJlc3VsdCA9IGNoYWluaW5nQmVoYXZpb3IoX2NoYWluaW5nQmVoYXZpb3IpLmNhbGwodGhpcyk7XG4gICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gdGhpcyA6IHJlc3VsdDtcbiAgfTtcblxuICB2YXIgX21ldGhvZCA9IGNoYWluYWJsZUJlaGF2aW9yLm1ldGhvZDtcbiAgY2hhaW5hYmxlQmVoYXZpb3IubWV0aG9kID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciByZXN1bHQgPSBtZXRob2QoX21ldGhvZCkuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICByZXR1cm4gcmVzdWx0ID09PSB1bmRlZmluZWQgPyB0aGlzIDogcmVzdWx0O1xuICB9O1xufTtcbiIsIi8qIVxuICogQ2hhaSAtIG92ZXJ3cml0ZU1ldGhvZCB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyoqXG4gKiAjIyMgb3ZlcndyaXRlTWV0aG9kIChjdHgsIG5hbWUsIGZuKVxuICpcbiAqIE92ZXJ3aXRlcyBhbiBhbHJlYWR5IGV4aXN0aW5nIG1ldGhvZCBhbmQgcHJvdmlkZXNcbiAqIGFjY2VzcyB0byBwcmV2aW91cyBmdW5jdGlvbi4gTXVzdCByZXR1cm4gZnVuY3Rpb25cbiAqIHRvIGJlIHVzZWQgZm9yIG5hbWUuXG4gKlxuICogICAgIHV0aWxzLm92ZXJ3cml0ZU1ldGhvZChjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUsICdlcXVhbCcsIGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAqICAgICAgIHJldHVybiBmdW5jdGlvbiAoc3RyKSB7XG4gKiAgICAgICAgIHZhciBvYmogPSB1dGlscy5mbGFnKHRoaXMsICdvYmplY3QnKTtcbiAqICAgICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIEZvbykge1xuICogICAgICAgICAgIG5ldyBjaGFpLkFzc2VydGlvbihvYmoudmFsdWUpLnRvLmVxdWFsKHN0cik7XG4gKiAgICAgICAgIH0gZWxzZSB7XG4gKiAgICAgICAgICAgX3N1cGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gKiAgICAgICAgIH1cbiAqICAgICAgIH1cbiAqICAgICB9KTtcbiAqXG4gKiBDYW4gYWxzbyBiZSBhY2Nlc3NlZCBkaXJlY3RseSBmcm9tIGBjaGFpLkFzc2VydGlvbmAuXG4gKlxuICogICAgIGNoYWkuQXNzZXJ0aW9uLm92ZXJ3cml0ZU1ldGhvZCgnZm9vJywgZm4pO1xuICpcbiAqIFRoZW4gY2FuIGJlIHVzZWQgYXMgYW55IG90aGVyIGFzc2VydGlvbi5cbiAqXG4gKiAgICAgZXhwZWN0KG15Rm9vKS50by5lcXVhbCgnYmFyJyk7XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGN0eCBvYmplY3Qgd2hvc2UgbWV0aG9kIGlzIHRvIGJlIG92ZXJ3cml0dGVuXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiBtZXRob2QgdG8gb3ZlcndyaXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBtZXRob2QgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEgZnVuY3Rpb24gdG8gYmUgdXNlZCBmb3IgbmFtZVxuICogQG5hbWUgb3ZlcndyaXRlTWV0aG9kXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGN0eCwgbmFtZSwgbWV0aG9kKSB7XG4gIHZhciBfbWV0aG9kID0gY3R4W25hbWVdXG4gICAgLCBfc3VwZXIgPSBmdW5jdGlvbiAoKSB7IHJldHVybiB0aGlzOyB9O1xuXG4gIGlmIChfbWV0aG9kICYmICdmdW5jdGlvbicgPT09IHR5cGVvZiBfbWV0aG9kKVxuICAgIF9zdXBlciA9IF9tZXRob2Q7XG5cbiAgY3R4W25hbWVdID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciByZXN1bHQgPSBtZXRob2QoX3N1cGVyKS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIHJldHVybiByZXN1bHQgPT09IHVuZGVmaW5lZCA/IHRoaXMgOiByZXN1bHQ7XG4gIH1cbn07XG4iLCIvKiFcbiAqIENoYWkgLSBvdmVyd3JpdGVQcm9wZXJ0eSB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyoqXG4gKiAjIyMgb3ZlcndyaXRlUHJvcGVydHkgKGN0eCwgbmFtZSwgZm4pXG4gKlxuICogT3ZlcndpdGVzIGFuIGFscmVhZHkgZXhpc3RpbmcgcHJvcGVydHkgZ2V0dGVyIGFuZCBwcm92aWRlc1xuICogYWNjZXNzIHRvIHByZXZpb3VzIHZhbHVlLiBNdXN0IHJldHVybiBmdW5jdGlvbiB0byB1c2UgYXMgZ2V0dGVyLlxuICpcbiAqICAgICB1dGlscy5vdmVyd3JpdGVQcm9wZXJ0eShjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUsICdvaycsIGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAqICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gKiAgICAgICAgIHZhciBvYmogPSB1dGlscy5mbGFnKHRoaXMsICdvYmplY3QnKTtcbiAqICAgICAgICAgaWYgKG9iaiBpbnN0YW5jZW9mIEZvbykge1xuICogICAgICAgICAgIG5ldyBjaGFpLkFzc2VydGlvbihvYmoubmFtZSkudG8uZXF1YWwoJ2JhcicpO1xuICogICAgICAgICB9IGVsc2Uge1xuICogICAgICAgICAgIF9zdXBlci5jYWxsKHRoaXMpO1xuICogICAgICAgICB9XG4gKiAgICAgICB9XG4gKiAgICAgfSk7XG4gKlxuICpcbiAqIENhbiBhbHNvIGJlIGFjY2Vzc2VkIGRpcmVjdGx5IGZyb20gYGNoYWkuQXNzZXJ0aW9uYC5cbiAqXG4gKiAgICAgY2hhaS5Bc3NlcnRpb24ub3ZlcndyaXRlUHJvcGVydHkoJ2ZvbycsIGZuKTtcbiAqXG4gKiBUaGVuIGNhbiBiZSB1c2VkIGFzIGFueSBvdGhlciBhc3NlcnRpb24uXG4gKlxuICogICAgIGV4cGVjdChteUZvbykudG8uYmUub2s7XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGN0eCBvYmplY3Qgd2hvc2UgcHJvcGVydHkgaXMgdG8gYmUgb3ZlcndyaXR0ZW5cbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIG9mIHByb3BlcnR5IHRvIG92ZXJ3cml0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZ2V0dGVyIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIGdldHRlciBmdW5jdGlvbiB0byBiZSB1c2VkIGZvciBuYW1lXG4gKiBAbmFtZSBvdmVyd3JpdGVQcm9wZXJ0eVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjdHgsIG5hbWUsIGdldHRlcikge1xuICB2YXIgX2dldCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoY3R4LCBuYW1lKVxuICAgICwgX3N1cGVyID0gZnVuY3Rpb24gKCkge307XG5cbiAgaWYgKF9nZXQgJiYgJ2Z1bmN0aW9uJyA9PT0gdHlwZW9mIF9nZXQuZ2V0KVxuICAgIF9zdXBlciA9IF9nZXQuZ2V0XG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGN0eCwgbmFtZSxcbiAgICB7IGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgcmVzdWx0ID0gZ2V0dGVyKF9zdXBlcikuY2FsbCh0aGlzKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gdGhpcyA6IHJlc3VsdDtcbiAgICAgIH1cbiAgICAsIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICB9KTtcbn07XG4iLCIvKiFcbiAqIENoYWkgLSB0ZXN0IHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKiFcbiAqIE1vZHVsZSBkZXBlbmRhbmNpZXNcbiAqL1xuXG52YXIgZmxhZyA9IHJlcXVpcmUoJy4vZmxhZycpO1xuXG4vKipcbiAqICMgdGVzdChvYmplY3QsIGV4cHJlc3Npb24pXG4gKlxuICogVGVzdCBhbmQgb2JqZWN0IGZvciBleHByZXNzaW9uLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgKGNvbnN0cnVjdGVkIEFzc2VydGlvbilcbiAqIEBwYXJhbSB7QXJndW1lbnRzfSBjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUuYXNzZXJ0IGFyZ3VtZW50c1xuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9iaiwgYXJncykge1xuICB2YXIgbmVnYXRlID0gZmxhZyhvYmosICduZWdhdGUnKVxuICAgICwgZXhwciA9IGFyZ3NbMF07XG4gIHJldHVybiBuZWdhdGUgPyAhZXhwciA6IGV4cHI7XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gdHJhbnNmZXJGbGFncyB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyoqXG4gKiAjIyMgdHJhbnNmZXJGbGFncyhhc3NlcnRpb24sIG9iamVjdCwgaW5jbHVkZUFsbCA9IHRydWUpXG4gKlxuICogVHJhbnNmZXIgYWxsIHRoZSBmbGFncyBmb3IgYGFzc2VydGlvbmAgdG8gYG9iamVjdGAuIElmXG4gKiBgaW5jbHVkZUFsbGAgaXMgc2V0IHRvIGBmYWxzZWAsIHRoZW4gdGhlIGJhc2UgQ2hhaVxuICogYXNzZXJ0aW9uIGZsYWdzIChuYW1lbHkgYG9iamVjdGAsIGBzc2ZpYCwgYW5kIGBtZXNzYWdlYClcbiAqIHdpbGwgbm90IGJlIHRyYW5zZmVycmVkLlxuICpcbiAqXG4gKiAgICAgdmFyIG5ld0Fzc2VydGlvbiA9IG5ldyBBc3NlcnRpb24oKTtcbiAqICAgICB1dGlscy50cmFuc2ZlckZsYWdzKGFzc2VydGlvbiwgbmV3QXNzZXJ0aW9uKTtcbiAqXG4gKiAgICAgdmFyIGFub3RoZXJBc3Nlcml0b24gPSBuZXcgQXNzZXJ0aW9uKG15T2JqKTtcbiAqICAgICB1dGlscy50cmFuc2ZlckZsYWdzKGFzc2VydGlvbiwgYW5vdGhlckFzc2VydGlvbiwgZmFsc2UpO1xuICpcbiAqIEBwYXJhbSB7QXNzZXJ0aW9ufSBhc3NlcnRpb24gdGhlIGFzc2VydGlvbiB0byB0cmFuc2ZlciB0aGUgZmxhZ3MgZnJvbVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCB0aGUgb2JqZWN0IHRvIHRyYW5zZmVyIHRoZSBmbGFncyB0b287IHVzdWFsbHkgYSBuZXcgYXNzZXJ0aW9uXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGluY2x1ZGVBbGxcbiAqIEBuYW1lIGdldEFsbEZsYWdzXG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChhc3NlcnRpb24sIG9iamVjdCwgaW5jbHVkZUFsbCkge1xuICB2YXIgZmxhZ3MgPSBhc3NlcnRpb24uX19mbGFncyB8fCAoYXNzZXJ0aW9uLl9fZmxhZ3MgPSBPYmplY3QuY3JlYXRlKG51bGwpKTtcblxuICBpZiAoIW9iamVjdC5fX2ZsYWdzKSB7XG4gICAgb2JqZWN0Ll9fZmxhZ3MgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuICB9XG5cbiAgaW5jbHVkZUFsbCA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDMgPyBpbmNsdWRlQWxsIDogdHJ1ZTtcblxuICBmb3IgKHZhciBmbGFnIGluIGZsYWdzKSB7XG4gICAgaWYgKGluY2x1ZGVBbGwgfHxcbiAgICAgICAgKGZsYWcgIT09ICdvYmplY3QnICYmIGZsYWcgIT09ICdzc2ZpJyAmJiBmbGFnICE9ICdtZXNzYWdlJykpIHtcbiAgICAgIG9iamVjdC5fX2ZsYWdzW2ZsYWddID0gZmxhZ3NbZmxhZ107XG4gICAgfVxuICB9XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gdHlwZSB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBEZXRlY3RhYmxlIGphdmFzY3JpcHQgbmF0aXZlc1xuICovXG5cbnZhciBuYXRpdmVzID0ge1xuICAgICdbb2JqZWN0IEFyZ3VtZW50c10nOiAnYXJndW1lbnRzJ1xuICAsICdbb2JqZWN0IEFycmF5XSc6ICdhcnJheSdcbiAgLCAnW29iamVjdCBEYXRlXSc6ICdkYXRlJ1xuICAsICdbb2JqZWN0IEZ1bmN0aW9uXSc6ICdmdW5jdGlvbidcbiAgLCAnW29iamVjdCBOdW1iZXJdJzogJ251bWJlcidcbiAgLCAnW29iamVjdCBSZWdFeHBdJzogJ3JlZ2V4cCdcbiAgLCAnW29iamVjdCBTdHJpbmddJzogJ3N0cmluZydcbn07XG5cbi8qKlxuICogIyMjIHR5cGUob2JqZWN0KVxuICpcbiAqIEJldHRlciBpbXBsZW1lbnRhdGlvbiBvZiBgdHlwZW9mYCBkZXRlY3Rpb24gdGhhdCBjYW5cbiAqIGJlIHVzZWQgY3Jvc3MtYnJvd3Nlci4gSGFuZGxlcyB0aGUgaW5jb25zaXN0ZW5jaWVzIG9mXG4gKiBBcnJheSwgYG51bGxgLCBhbmQgYHVuZGVmaW5lZGAgZGV0ZWN0aW9uLlxuICpcbiAqICAgICB1dGlscy50eXBlKHt9KSAvLyAnb2JqZWN0J1xuICogICAgIHV0aWxzLnR5cGUobnVsbCkgLy8gYG51bGwnXG4gKiAgICAgdXRpbHMudHlwZSh1bmRlZmluZWQpIC8vIGB1bmRlZmluZWRgXG4gKiAgICAgdXRpbHMudHlwZShbXSkgLy8gYGFycmF5YFxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IG9iamVjdCB0byBkZXRlY3QgdHlwZSBvZlxuICogQG5hbWUgdHlwZVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7XG4gIHZhciBzdHIgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKTtcbiAgaWYgKG5hdGl2ZXNbc3RyXSkgcmV0dXJuIG5hdGl2ZXNbc3RyXTtcbiAgaWYgKG9iaiA9PT0gbnVsbCkgcmV0dXJuICdudWxsJztcbiAgaWYgKG9iaiA9PT0gdW5kZWZpbmVkKSByZXR1cm4gJ3VuZGVmaW5lZCc7XG4gIGlmIChvYmogPT09IE9iamVjdChvYmopKSByZXR1cm4gJ29iamVjdCc7XG4gIHJldHVybiB0eXBlb2Ygb2JqO1xufTtcbiIsIi8qIVxuICogYXNzZXJ0aW9uLWVycm9yXG4gKiBDb3B5cmlnaHQoYykgMjAxMyBKYWtlIEx1ZXIgPGpha2VAcXVhbGlhbmN5LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qIVxuICogUmV0dXJuIGEgZnVuY3Rpb24gdGhhdCB3aWxsIGNvcHkgcHJvcGVydGllcyBmcm9tXG4gKiBvbmUgb2JqZWN0IHRvIGFub3RoZXIgZXhjbHVkaW5nIGFueSBvcmlnaW5hbGx5XG4gKiBsaXN0ZWQuIFJldHVybmVkIGZ1bmN0aW9uIHdpbGwgY3JlYXRlIGEgbmV3IGB7fWAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGV4Y2x1ZGVkIHByb3BlcnRpZXMgLi4uXG4gKiBAcmV0dXJuIHtGdW5jdGlvbn1cbiAqL1xuXG5mdW5jdGlvbiBleGNsdWRlICgpIHtcbiAgdmFyIGV4Y2x1ZGVzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXG4gIGZ1bmN0aW9uIGV4Y2x1ZGVQcm9wcyAocmVzLCBvYmopIHtcbiAgICBPYmplY3Qua2V5cyhvYmopLmZvckVhY2goZnVuY3Rpb24gKGtleSkge1xuICAgICAgaWYgKCF+ZXhjbHVkZXMuaW5kZXhPZihrZXkpKSByZXNba2V5XSA9IG9ialtrZXldO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uIGV4dGVuZEV4Y2x1ZGUgKCkge1xuICAgIHZhciBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMpXG4gICAgICAsIGkgPSAwXG4gICAgICAsIHJlcyA9IHt9O1xuXG4gICAgZm9yICg7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBleGNsdWRlUHJvcHMocmVzLCBhcmdzW2ldKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xuICB9O1xufTtcblxuLyohXG4gKiBQcmltYXJ5IEV4cG9ydHNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IEFzc2VydGlvbkVycm9yO1xuXG4vKipcbiAqICMjIyBBc3NlcnRpb25FcnJvclxuICpcbiAqIEFuIGV4dGVuc2lvbiBvZiB0aGUgSmF2YVNjcmlwdCBgRXJyb3JgIGNvbnN0cnVjdG9yIGZvclxuICogYXNzZXJ0aW9uIGFuZCB2YWxpZGF0aW9uIHNjZW5hcmlvcy5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICogQHBhcmFtIHtPYmplY3R9IHByb3BlcnRpZXMgdG8gaW5jbHVkZSAob3B0aW9uYWwpXG4gKiBAcGFyYW0ge2NhbGxlZX0gc3RhcnQgc3RhY2sgZnVuY3Rpb24gKG9wdGlvbmFsKVxuICovXG5cbmZ1bmN0aW9uIEFzc2VydGlvbkVycm9yIChtZXNzYWdlLCBfcHJvcHMsIHNzZikge1xuICB2YXIgZXh0ZW5kID0gZXhjbHVkZSgnbmFtZScsICdtZXNzYWdlJywgJ3N0YWNrJywgJ2NvbnN0cnVjdG9yJywgJ3RvSlNPTicpXG4gICAgLCBwcm9wcyA9IGV4dGVuZChfcHJvcHMgfHwge30pO1xuXG4gIC8vIGRlZmF1bHQgdmFsdWVzXG4gIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2UgfHwgJ1Vuc3BlY2lmaWVkIEFzc2VydGlvbkVycm9yJztcbiAgdGhpcy5zaG93RGlmZiA9IGZhbHNlO1xuXG4gIC8vIGNvcHkgZnJvbSBwcm9wZXJ0aWVzXG4gIGZvciAodmFyIGtleSBpbiBwcm9wcykge1xuICAgIHRoaXNba2V5XSA9IHByb3BzW2tleV07XG4gIH1cblxuICAvLyBjYXB0dXJlIHN0YWNrIHRyYWNlXG4gIHNzZiA9IHNzZiB8fCBhcmd1bWVudHMuY2FsbGVlO1xuICBpZiAoc3NmICYmIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKSB7XG4gICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgc3NmKTtcbiAgfVxufVxuXG4vKiFcbiAqIEluaGVyaXQgZnJvbSBFcnJvci5wcm90b3R5cGVcbiAqL1xuXG5Bc3NlcnRpb25FcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEVycm9yLnByb3RvdHlwZSk7XG5cbi8qIVxuICogU3RhdGljYWxseSBzZXQgbmFtZVxuICovXG5cbkFzc2VydGlvbkVycm9yLnByb3RvdHlwZS5uYW1lID0gJ0Fzc2VydGlvbkVycm9yJztcblxuLyohXG4gKiBFbnN1cmUgY29ycmVjdCBjb25zdHJ1Y3RvclxuICovXG5cbkFzc2VydGlvbkVycm9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEFzc2VydGlvbkVycm9yO1xuXG4vKipcbiAqIEFsbG93IGVycm9ycyB0byBiZSBjb252ZXJ0ZWQgdG8gSlNPTiBmb3Igc3RhdGljIHRyYW5zZmVyLlxuICpcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gaW5jbHVkZSBzdGFjayAoZGVmYXVsdDogYHRydWVgKVxuICogQHJldHVybiB7T2JqZWN0fSBvYmplY3QgdGhhdCBjYW4gYmUgYEpTT04uc3RyaW5naWZ5YFxuICovXG5cbkFzc2VydGlvbkVycm9yLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiAoc3RhY2spIHtcbiAgdmFyIGV4dGVuZCA9IGV4Y2x1ZGUoJ2NvbnN0cnVjdG9yJywgJ3RvSlNPTicsICdzdGFjaycpXG4gICAgLCBwcm9wcyA9IGV4dGVuZCh7IG5hbWU6IHRoaXMubmFtZSB9LCB0aGlzKTtcblxuICAvLyBpbmNsdWRlIHN0YWNrIGlmIGV4aXN0cyBhbmQgbm90IHR1cm5lZCBvZmZcbiAgaWYgKGZhbHNlICE9PSBzdGFjayAmJiB0aGlzLnN0YWNrKSB7XG4gICAgcHJvcHMuc3RhY2sgPSB0aGlzLnN0YWNrO1xuICB9XG5cbiAgcmV0dXJuIHByb3BzO1xufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9saWIvZXFsJyk7XG4iLCIvKiFcbiAqIGRlZXAtZXFsXG4gKiBDb3B5cmlnaHQoYykgMjAxMyBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qIVxuICogTW9kdWxlIGRlcGVuZGVuY2llc1xuICovXG5cbnZhciB0eXBlID0gcmVxdWlyZSgndHlwZS1kZXRlY3QnKTtcblxuLyohXG4gKiBCdWZmZXIuaXNCdWZmZXIgYnJvd3NlciBzaGltXG4gKi9cblxudmFyIEJ1ZmZlcjtcbnRyeSB7IEJ1ZmZlciA9IHJlcXVpcmUoJ2J1ZmZlcicpLkJ1ZmZlcjsgfVxuY2F0Y2goZXgpIHtcbiAgQnVmZmVyID0ge307XG4gIEJ1ZmZlci5pc0J1ZmZlciA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gZmFsc2U7IH1cbn1cblxuLyohXG4gKiBQcmltYXJ5IEV4cG9ydFxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZGVlcEVxdWFsO1xuXG4vKipcbiAqIEFzc2VydCBzdXBlci1zdHJpY3QgKGVnYWwpIGVxdWFsaXR5IGJldHdlZW5cbiAqIHR3byBvYmplY3RzIG9mIGFueSB0eXBlLlxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IGFcbiAqIEBwYXJhbSB7TWl4ZWR9IGJcbiAqIEBwYXJhbSB7QXJyYXl9IG1lbW9pc2VkIChvcHRpb25hbClcbiAqIEByZXR1cm4ge0Jvb2xlYW59IGVxdWFsIG1hdGNoXG4gKi9cblxuZnVuY3Rpb24gZGVlcEVxdWFsKGEsIGIsIG0pIHtcbiAgaWYgKHNhbWVWYWx1ZShhLCBiKSkge1xuICAgIHJldHVybiB0cnVlO1xuICB9IGVsc2UgaWYgKCdkYXRlJyA9PT0gdHlwZShhKSkge1xuICAgIHJldHVybiBkYXRlRXF1YWwoYSwgYik7XG4gIH0gZWxzZSBpZiAoJ3JlZ2V4cCcgPT09IHR5cGUoYSkpIHtcbiAgICByZXR1cm4gcmVnZXhwRXF1YWwoYSwgYik7XG4gIH0gZWxzZSBpZiAoQnVmZmVyLmlzQnVmZmVyKGEpKSB7XG4gICAgcmV0dXJuIGJ1ZmZlckVxdWFsKGEsIGIpO1xuICB9IGVsc2UgaWYgKCdhcmd1bWVudHMnID09PSB0eXBlKGEpKSB7XG4gICAgcmV0dXJuIGFyZ3VtZW50c0VxdWFsKGEsIGIsIG0pO1xuICB9IGVsc2UgaWYgKCF0eXBlRXF1YWwoYSwgYikpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH0gZWxzZSBpZiAoKCdvYmplY3QnICE9PSB0eXBlKGEpICYmICdvYmplY3QnICE9PSB0eXBlKGIpKVxuICAmJiAoJ2FycmF5JyAhPT0gdHlwZShhKSAmJiAnYXJyYXknICE9PSB0eXBlKGIpKSkge1xuICAgIHJldHVybiBzYW1lVmFsdWUoYSwgYik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG9iamVjdEVxdWFsKGEsIGIsIG0pO1xuICB9XG59XG5cbi8qIVxuICogU3RyaWN0IChlZ2FsKSBlcXVhbGl0eSB0ZXN0LiBFbnN1cmVzIHRoYXQgTmFOIGFsd2F5c1xuICogZXF1YWxzIE5hTiBhbmQgYC0wYCBkb2VzIG5vdCBlcXVhbCBgKzBgLlxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IGFcbiAqIEBwYXJhbSB7TWl4ZWR9IGJcbiAqIEByZXR1cm4ge0Jvb2xlYW59IGVxdWFsIG1hdGNoXG4gKi9cblxuZnVuY3Rpb24gc2FtZVZhbHVlKGEsIGIpIHtcbiAgaWYgKGEgPT09IGIpIHJldHVybiBhICE9PSAwIHx8IDEgLyBhID09PSAxIC8gYjtcbiAgcmV0dXJuIGEgIT09IGEgJiYgYiAhPT0gYjtcbn1cblxuLyohXG4gKiBDb21wYXJlIHRoZSB0eXBlcyBvZiB0d28gZ2l2ZW4gb2JqZWN0cyBhbmRcbiAqIHJldHVybiBpZiB0aGV5IGFyZSBlcXVhbC4gTm90ZSB0aGF0IGFuIEFycmF5XG4gKiBoYXMgYSB0eXBlIG9mIGBhcnJheWAgKG5vdCBgb2JqZWN0YCkgYW5kIGFyZ3VtZW50c1xuICogaGF2ZSBhIHR5cGUgb2YgYGFyZ3VtZW50c2AgKG5vdCBgYXJyYXlgL2BvYmplY3RgKS5cbiAqXG4gKiBAcGFyYW0ge01peGVkfSBhXG4gKiBAcGFyYW0ge01peGVkfSBiXG4gKiBAcmV0dXJuIHtCb29sZWFufSByZXN1bHRcbiAqL1xuXG5mdW5jdGlvbiB0eXBlRXF1YWwoYSwgYikge1xuICByZXR1cm4gdHlwZShhKSA9PT0gdHlwZShiKTtcbn1cblxuLyohXG4gKiBDb21wYXJlIHR3byBEYXRlIG9iamVjdHMgYnkgYXNzZXJ0aW5nIHRoYXRcbiAqIHRoZSB0aW1lIHZhbHVlcyBhcmUgZXF1YWwgdXNpbmcgYHNhdmVWYWx1ZWAuXG4gKlxuICogQHBhcmFtIHtEYXRlfSBhXG4gKiBAcGFyYW0ge0RhdGV9IGJcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHJlc3VsdFxuICovXG5cbmZ1bmN0aW9uIGRhdGVFcXVhbChhLCBiKSB7XG4gIGlmICgnZGF0ZScgIT09IHR5cGUoYikpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHNhbWVWYWx1ZShhLmdldFRpbWUoKSwgYi5nZXRUaW1lKCkpO1xufVxuXG4vKiFcbiAqIENvbXBhcmUgdHdvIHJlZ3VsYXIgZXhwcmVzc2lvbnMgYnkgY29udmVydGluZyB0aGVtXG4gKiB0byBzdHJpbmcgYW5kIGNoZWNraW5nIGZvciBgc2FtZVZhbHVlYC5cbiAqXG4gKiBAcGFyYW0ge1JlZ0V4cH0gYVxuICogQHBhcmFtIHtSZWdFeHB9IGJcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHJlc3VsdFxuICovXG5cbmZ1bmN0aW9uIHJlZ2V4cEVxdWFsKGEsIGIpIHtcbiAgaWYgKCdyZWdleHAnICE9PSB0eXBlKGIpKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiBzYW1lVmFsdWUoYS50b1N0cmluZygpLCBiLnRvU3RyaW5nKCkpO1xufVxuXG4vKiFcbiAqIEFzc2VydCBkZWVwIGVxdWFsaXR5IG9mIHR3byBgYXJndW1lbnRzYCBvYmplY3RzLlxuICogVW5mb3J0dW5hdGVseSwgdGhlc2UgbXVzdCBiZSBzbGljZWQgdG8gYXJyYXlzXG4gKiBwcmlvciB0byB0ZXN0IHRvIGVuc3VyZSBubyBiYWQgYmVoYXZpb3IuXG4gKlxuICogQHBhcmFtIHtBcmd1bWVudHN9IGFcbiAqIEBwYXJhbSB7QXJndW1lbnRzfSBiXG4gKiBAcGFyYW0ge0FycmF5fSBtZW1vaXplIChvcHRpb25hbClcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHJlc3VsdFxuICovXG5cbmZ1bmN0aW9uIGFyZ3VtZW50c0VxdWFsKGEsIGIsIG0pIHtcbiAgaWYgKCdhcmd1bWVudHMnICE9PSB0eXBlKGIpKSByZXR1cm4gZmFsc2U7XG4gIGEgPSBbXS5zbGljZS5jYWxsKGEpO1xuICBiID0gW10uc2xpY2UuY2FsbChiKTtcbiAgcmV0dXJuIGRlZXBFcXVhbChhLCBiLCBtKTtcbn1cblxuLyohXG4gKiBHZXQgZW51bWVyYWJsZSBwcm9wZXJ0aWVzIG9mIGEgZ2l2ZW4gb2JqZWN0LlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBhXG4gKiBAcmV0dXJuIHtBcnJheX0gcHJvcGVydHkgbmFtZXNcbiAqL1xuXG5mdW5jdGlvbiBlbnVtZXJhYmxlKGEpIHtcbiAgdmFyIHJlcyA9IFtdO1xuICBmb3IgKHZhciBrZXkgaW4gYSkgcmVzLnB1c2goa2V5KTtcbiAgcmV0dXJuIHJlcztcbn1cblxuLyohXG4gKiBTaW1wbGUgZXF1YWxpdHkgZm9yIGZsYXQgaXRlcmFibGUgb2JqZWN0c1xuICogc3VjaCBhcyBBcnJheXMgb3IgTm9kZS5qcyBidWZmZXJzLlxuICpcbiAqIEBwYXJhbSB7SXRlcmFibGV9IGFcbiAqIEBwYXJhbSB7SXRlcmFibGV9IGJcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHJlc3VsdFxuICovXG5cbmZ1bmN0aW9uIGl0ZXJhYmxlRXF1YWwoYSwgYikge1xuICBpZiAoYS5sZW5ndGggIT09ICBiLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBpID0gMDtcbiAgdmFyIG1hdGNoID0gdHJ1ZTtcblxuICBmb3IgKDsgaSA8IGEubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoYVtpXSAhPT0gYltpXSkge1xuICAgICAgbWF0Y2ggPSBmYWxzZTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBtYXRjaDtcbn1cblxuLyohXG4gKiBFeHRlbnNpb24gdG8gYGl0ZXJhYmxlRXF1YWxgIHNwZWNpZmljYWxseVxuICogZm9yIE5vZGUuanMgQnVmZmVycy5cbiAqXG4gKiBAcGFyYW0ge0J1ZmZlcn0gYVxuICogQHBhcmFtIHtNaXhlZH0gYlxuICogQHJldHVybiB7Qm9vbGVhbn0gcmVzdWx0XG4gKi9cblxuZnVuY3Rpb24gYnVmZmVyRXF1YWwoYSwgYikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihiKSkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gaXRlcmFibGVFcXVhbChhLCBiKTtcbn1cblxuLyohXG4gKiBCbG9jayBmb3IgYG9iamVjdEVxdWFsYCBlbnN1cmluZyBub24tZXhpc3RpbmdcbiAqIHZhbHVlcyBkb24ndCBnZXQgaW4uXG4gKlxuICogQHBhcmFtIHtNaXhlZH0gb2JqZWN0XG4gKiBAcmV0dXJuIHtCb29sZWFufSByZXN1bHRcbiAqL1xuXG5mdW5jdGlvbiBpc1ZhbHVlKGEpIHtcbiAgcmV0dXJuIGEgIT09IG51bGwgJiYgYSAhPT0gdW5kZWZpbmVkO1xufVxuXG4vKiFcbiAqIFJlY3Vyc2l2ZWx5IGNoZWNrIHRoZSBlcXVhbGl0eSBvZiB0d28gb2JqZWN0cy5cbiAqIE9uY2UgYmFzaWMgc2FtZW5lc3MgaGFzIGJlZW4gZXN0YWJsaXNoZWQgaXQgd2lsbFxuICogZGVmZXIgdG8gYGRlZXBFcXVhbGAgZm9yIGVhY2ggZW51bWVyYWJsZSBrZXlcbiAqIGluIHRoZSBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtNaXhlZH0gYVxuICogQHBhcmFtIHtNaXhlZH0gYlxuICogQHJldHVybiB7Qm9vbGVhbn0gcmVzdWx0XG4gKi9cblxuZnVuY3Rpb24gb2JqZWN0RXF1YWwoYSwgYiwgbSkge1xuICBpZiAoIWlzVmFsdWUoYSkgfHwgIWlzVmFsdWUoYikpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoYS5wcm90b3R5cGUgIT09IGIucHJvdG90eXBlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgdmFyIGk7XG4gIGlmIChtKSB7XG4gICAgZm9yIChpID0gMDsgaSA8IG0ubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmICgobVtpXVswXSA9PT0gYSAmJiBtW2ldWzFdID09PSBiKVxuICAgICAgfHwgIChtW2ldWzBdID09PSBiICYmIG1baV1bMV0gPT09IGEpKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBtID0gW107XG4gIH1cblxuICB0cnkge1xuICAgIHZhciBrYSA9IGVudW1lcmFibGUoYSk7XG4gICAgdmFyIGtiID0gZW51bWVyYWJsZShiKTtcbiAgfSBjYXRjaCAoZXgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBrYS5zb3J0KCk7XG4gIGtiLnNvcnQoKTtcblxuICBpZiAoIWl0ZXJhYmxlRXF1YWwoa2EsIGtiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIG0ucHVzaChbIGEsIGIgXSk7XG5cbiAgdmFyIGtleTtcbiAgZm9yIChpID0ga2EubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBrZXkgPSBrYVtpXTtcbiAgICBpZiAoIWRlZXBFcXVhbChhW2tleV0sIGJba2V5XSwgbSkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cbiIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9saWIvdHlwZScpO1xuIiwiLyohXG4gKiB0eXBlLWRldGVjdFxuICogQ29weXJpZ2h0KGMpIDIwMTMgamFrZSBsdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKiFcbiAqIFByaW1hcnkgRXhwb3J0c1xuICovXG5cbnZhciBleHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSBnZXRUeXBlO1xuXG4vKiFcbiAqIERldGVjdGFibGUgamF2YXNjcmlwdCBuYXRpdmVzXG4gKi9cblxudmFyIG5hdGl2ZXMgPSB7XG4gICAgJ1tvYmplY3QgQXJyYXldJzogJ2FycmF5J1xuICAsICdbb2JqZWN0IFJlZ0V4cF0nOiAncmVnZXhwJ1xuICAsICdbb2JqZWN0IEZ1bmN0aW9uXSc6ICdmdW5jdGlvbidcbiAgLCAnW29iamVjdCBBcmd1bWVudHNdJzogJ2FyZ3VtZW50cydcbiAgLCAnW29iamVjdCBEYXRlXSc6ICdkYXRlJ1xufTtcblxuLyoqXG4gKiAjIyMgdHlwZU9mIChvYmopXG4gKlxuICogVXNlIHNldmVyYWwgZGlmZmVyZW50IHRlY2huaXF1ZXMgdG8gZGV0ZXJtaW5lXG4gKiB0aGUgdHlwZSBvZiBvYmplY3QgYmVpbmcgdGVzdGVkLlxuICpcbiAqXG4gKiBAcGFyYW0ge01peGVkfSBvYmplY3RcbiAqIEByZXR1cm4ge1N0cmluZ30gb2JqZWN0IHR5cGVcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZnVuY3Rpb24gZ2V0VHlwZSAob2JqKSB7XG4gIHZhciBzdHIgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKTtcbiAgaWYgKG5hdGl2ZXNbc3RyXSkgcmV0dXJuIG5hdGl2ZXNbc3RyXTtcbiAgaWYgKG9iaiA9PT0gbnVsbCkgcmV0dXJuICdudWxsJztcbiAgaWYgKG9iaiA9PT0gdW5kZWZpbmVkKSByZXR1cm4gJ3VuZGVmaW5lZCc7XG4gIGlmIChvYmogPT09IE9iamVjdChvYmopKSByZXR1cm4gJ29iamVjdCc7XG4gIHJldHVybiB0eXBlb2Ygb2JqO1xufVxuXG5leHBvcnRzLkxpYnJhcnkgPSBMaWJyYXJ5O1xuXG4vKipcbiAqICMjIyBMaWJyYXJ5XG4gKlxuICogQ3JlYXRlIGEgcmVwb3NpdG9yeSBmb3IgY3VzdG9tIHR5cGUgZGV0ZWN0aW9uLlxuICpcbiAqIGBgYGpzXG4gKiB2YXIgbGliID0gbmV3IHR5cGUuTGlicmFyeTtcbiAqIGBgYFxuICpcbiAqL1xuXG5mdW5jdGlvbiBMaWJyYXJ5ICgpIHtcbiAgdGhpcy50ZXN0cyA9IHt9O1xufVxuXG4vKipcbiAqICMjIyMgLm9mIChvYmopXG4gKlxuICogRXhwb3NlIHJlcGxhY2VtZW50IGB0eXBlb2ZgIGRldGVjdGlvbiB0byB0aGUgbGlicmFyeS5cbiAqXG4gKiBgYGBqc1xuICogaWYgKCdzdHJpbmcnID09PSBsaWIub2YoJ2hlbGxvIHdvcmxkJykpIHtcbiAqICAgLy8gLi4uXG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0ge01peGVkfSBvYmplY3QgdG8gdGVzdFxuICogQHJldHVybiB7U3RyaW5nfSB0eXBlXG4gKi9cblxuTGlicmFyeS5wcm90b3R5cGUub2YgPSBnZXRUeXBlO1xuXG4vKipcbiAqICMjIyMgLmRlZmluZSAodHlwZSwgdGVzdClcbiAqXG4gKiBBZGQgYSB0ZXN0IHRvIGZvciB0aGUgYC50ZXN0KClgIGFzc2VydGlvbi5cbiAqXG4gKiBDYW4gYmUgZGVmaW5lZCBhcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbjpcbiAqXG4gKiBgYGBqc1xuICogbGliLmRlZmluZSgnaW50JywgL15bMC05XSskLyk7XG4gKiBgYGBcbiAqXG4gKiAuLi4gb3IgYXMgYSBmdW5jdGlvbjpcbiAqXG4gKiBgYGBqc1xuICogbGliLmRlZmluZSgnYmxuJywgZnVuY3Rpb24gKG9iaikge1xuICogICBpZiAoJ2Jvb2xlYW4nID09PSBsaWIub2Yob2JqKSkgcmV0dXJuIHRydWU7XG4gKiAgIHZhciBibG5zID0gWyAneWVzJywgJ25vJywgJ3RydWUnLCAnZmFsc2UnLCAxLCAwIF07XG4gKiAgIGlmICgnc3RyaW5nJyA9PT0gbGliLm9mKG9iaikpIG9iaiA9IG9iai50b0xvd2VyQ2FzZSgpO1xuICogICByZXR1cm4gISEgfmJsbnMuaW5kZXhPZihvYmopO1xuICogfSk7XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gdHlwZVxuICogQHBhcmFtIHtSZWdFeHB8RnVuY3Rpb259IHRlc3RcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuTGlicmFyeS5wcm90b3R5cGUuZGVmaW5lID0gZnVuY3Rpb24gKHR5cGUsIHRlc3QpIHtcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHJldHVybiB0aGlzLnRlc3RzW3R5cGVdO1xuICB0aGlzLnRlc3RzW3R5cGVdID0gdGVzdDtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqICMjIyMgLnRlc3QgKG9iaiwgdGVzdClcbiAqXG4gKiBBc3NlcnQgdGhhdCBhbiBvYmplY3QgaXMgb2YgdHlwZS4gV2lsbCBmaXJzdFxuICogY2hlY2sgbmF0aXZlcywgYW5kIGlmIHRoYXQgZG9lcyBub3QgcGFzcyBpdCB3aWxsXG4gKiB1c2UgdGhlIHVzZXIgZGVmaW5lZCBjdXN0b20gdGVzdHMuXG4gKlxuICogYGBganNcbiAqIGFzc2VydChsaWIudGVzdCgnMScsICdpbnQnKSk7XG4gKiBhc3NlcnQobGliLnRlc3QoJ3llcycsICdibG4nKSk7XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0ge01peGVkfSBvYmplY3RcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gKiBAcmV0dXJuIHtCb29sZWFufSByZXN1bHRcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuTGlicmFyeS5wcm90b3R5cGUudGVzdCA9IGZ1bmN0aW9uIChvYmosIHR5cGUpIHtcbiAgaWYgKHR5cGUgPT09IGdldFR5cGUob2JqKSkgcmV0dXJuIHRydWU7XG4gIHZhciB0ZXN0ID0gdGhpcy50ZXN0c1t0eXBlXTtcblxuICBpZiAodGVzdCAmJiAncmVnZXhwJyA9PT0gZ2V0VHlwZSh0ZXN0KSkge1xuICAgIHJldHVybiB0ZXN0LnRlc3Qob2JqKTtcbiAgfSBlbHNlIGlmICh0ZXN0ICYmICdmdW5jdGlvbicgPT09IGdldFR5cGUodGVzdCkpIHtcbiAgICByZXR1cm4gdGVzdChvYmopO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcignVHlwZSB0ZXN0IFwiJyArIHR5cGUgKyAnXCIgbm90IGRlZmluZWQgb3IgaW52YWxpZC4nKTtcbiAgfVxufTtcbiIsIi8qIVxuICogVGhlIGJ1ZmZlciBtb2R1bGUgZnJvbSBub2RlLmpzLCBmb3IgdGhlIGJyb3dzZXIuXG4gKlxuICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGZlcm9zc0BmZXJvc3Mub3JnPiA8aHR0cDovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cblxudmFyIGJhc2U2NCA9IHJlcXVpcmUoJ2Jhc2U2NC1qcycpXG52YXIgaWVlZTc1NCA9IHJlcXVpcmUoJ2llZWU3NTQnKVxuXG5leHBvcnRzLkJ1ZmZlciA9IEJ1ZmZlclxuZXhwb3J0cy5TbG93QnVmZmVyID0gQnVmZmVyXG5leHBvcnRzLklOU1BFQ1RfTUFYX0JZVEVTID0gNTBcbkJ1ZmZlci5wb29sU2l6ZSA9IDgxOTJcblxuLyoqXG4gKiBJZiBgQnVmZmVyLl91c2VUeXBlZEFycmF5c2A6XG4gKiAgID09PSB0cnVlICAgIFVzZSBVaW50OEFycmF5IGltcGxlbWVudGF0aW9uIChmYXN0ZXN0KVxuICogICA9PT0gZmFsc2UgICBVc2UgT2JqZWN0IGltcGxlbWVudGF0aW9uIChjb21wYXRpYmxlIGRvd24gdG8gSUU2KVxuICovXG5CdWZmZXIuX3VzZVR5cGVkQXJyYXlzID0gKGZ1bmN0aW9uICgpIHtcbiAgLy8gRGV0ZWN0IGlmIGJyb3dzZXIgc3VwcG9ydHMgVHlwZWQgQXJyYXlzLiBTdXBwb3J0ZWQgYnJvd3NlcnMgYXJlIElFIDEwKywgRmlyZWZveCA0KyxcbiAgLy8gQ2hyb21lIDcrLCBTYWZhcmkgNS4xKywgT3BlcmEgMTEuNissIGlPUyA0LjIrLiBJZiB0aGUgYnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IGFkZGluZ1xuICAvLyBwcm9wZXJ0aWVzIHRvIGBVaW50OEFycmF5YCBpbnN0YW5jZXMsIHRoZW4gdGhhdCdzIHRoZSBzYW1lIGFzIG5vIGBVaW50OEFycmF5YCBzdXBwb3J0XG4gIC8vIGJlY2F1c2Ugd2UgbmVlZCB0byBiZSBhYmxlIHRvIGFkZCBhbGwgdGhlIG5vZGUgQnVmZmVyIEFQSSBtZXRob2RzLiBUaGlzIGlzIGFuIGlzc3VlXG4gIC8vIGluIEZpcmVmb3ggNC0yOS4gTm93IGZpeGVkOiBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD02OTU0MzhcbiAgdHJ5IHtcbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDApXG4gICAgdmFyIGFyciA9IG5ldyBVaW50OEFycmF5KGJ1ZilcbiAgICBhcnIuZm9vID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gNDIgfVxuICAgIHJldHVybiA0MiA9PT0gYXJyLmZvbygpICYmXG4gICAgICAgIHR5cGVvZiBhcnIuc3ViYXJyYXkgPT09ICdmdW5jdGlvbicgLy8gQ2hyb21lIDktMTAgbGFjayBgc3ViYXJyYXlgXG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufSkoKVxuXG4vKipcbiAqIENsYXNzOiBCdWZmZXJcbiAqID09PT09PT09PT09PT1cbiAqXG4gKiBUaGUgQnVmZmVyIGNvbnN0cnVjdG9yIHJldHVybnMgaW5zdGFuY2VzIG9mIGBVaW50OEFycmF5YCB0aGF0IGFyZSBhdWdtZW50ZWRcbiAqIHdpdGggZnVuY3Rpb24gcHJvcGVydGllcyBmb3IgYWxsIHRoZSBub2RlIGBCdWZmZXJgIEFQSSBmdW5jdGlvbnMuIFdlIHVzZVxuICogYFVpbnQ4QXJyYXlgIHNvIHRoYXQgc3F1YXJlIGJyYWNrZXQgbm90YXRpb24gd29ya3MgYXMgZXhwZWN0ZWQgLS0gaXQgcmV0dXJuc1xuICogYSBzaW5nbGUgb2N0ZXQuXG4gKlxuICogQnkgYXVnbWVudGluZyB0aGUgaW5zdGFuY2VzLCB3ZSBjYW4gYXZvaWQgbW9kaWZ5aW5nIHRoZSBgVWludDhBcnJheWBcbiAqIHByb3RvdHlwZS5cbiAqL1xuZnVuY3Rpb24gQnVmZmVyIChzdWJqZWN0LCBlbmNvZGluZywgbm9aZXJvKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBCdWZmZXIpKVxuICAgIHJldHVybiBuZXcgQnVmZmVyKHN1YmplY3QsIGVuY29kaW5nLCBub1plcm8pXG5cbiAgdmFyIHR5cGUgPSB0eXBlb2Ygc3ViamVjdFxuXG4gIC8vIFdvcmthcm91bmQ6IG5vZGUncyBiYXNlNjQgaW1wbGVtZW50YXRpb24gYWxsb3dzIGZvciBub24tcGFkZGVkIHN0cmluZ3NcbiAgLy8gd2hpbGUgYmFzZTY0LWpzIGRvZXMgbm90LlxuICBpZiAoZW5jb2RpbmcgPT09ICdiYXNlNjQnICYmIHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgc3ViamVjdCA9IHN0cmluZ3RyaW0oc3ViamVjdClcbiAgICB3aGlsZSAoc3ViamVjdC5sZW5ndGggJSA0ICE9PSAwKSB7XG4gICAgICBzdWJqZWN0ID0gc3ViamVjdCArICc9J1xuICAgIH1cbiAgfVxuXG4gIC8vIEZpbmQgdGhlIGxlbmd0aFxuICB2YXIgbGVuZ3RoXG4gIGlmICh0eXBlID09PSAnbnVtYmVyJylcbiAgICBsZW5ndGggPSBjb2VyY2Uoc3ViamVjdClcbiAgZWxzZSBpZiAodHlwZSA9PT0gJ3N0cmluZycpXG4gICAgbGVuZ3RoID0gQnVmZmVyLmJ5dGVMZW5ndGgoc3ViamVjdCwgZW5jb2RpbmcpXG4gIGVsc2UgaWYgKHR5cGUgPT09ICdvYmplY3QnKVxuICAgIGxlbmd0aCA9IGNvZXJjZShzdWJqZWN0Lmxlbmd0aCkgLy8gYXNzdW1lIHRoYXQgb2JqZWN0IGlzIGFycmF5LWxpa2VcbiAgZWxzZVxuICAgIHRocm93IG5ldyBFcnJvcignRmlyc3QgYXJndW1lbnQgbmVlZHMgdG8gYmUgYSBudW1iZXIsIGFycmF5IG9yIHN0cmluZy4nKVxuXG4gIHZhciBidWZcbiAgaWYgKEJ1ZmZlci5fdXNlVHlwZWRBcnJheXMpIHtcbiAgICAvLyBQcmVmZXJyZWQ6IFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlIGZvciBiZXN0IHBlcmZvcm1hbmNlXG4gICAgYnVmID0gQnVmZmVyLl9hdWdtZW50KG5ldyBVaW50OEFycmF5KGxlbmd0aCkpXG4gIH0gZWxzZSB7XG4gICAgLy8gRmFsbGJhY2s6IFJldHVybiBUSElTIGluc3RhbmNlIG9mIEJ1ZmZlciAoY3JlYXRlZCBieSBgbmV3YClcbiAgICBidWYgPSB0aGlzXG4gICAgYnVmLmxlbmd0aCA9IGxlbmd0aFxuICAgIGJ1Zi5faXNCdWZmZXIgPSB0cnVlXG4gIH1cblxuICB2YXIgaVxuICBpZiAoQnVmZmVyLl91c2VUeXBlZEFycmF5cyAmJiB0eXBlb2Ygc3ViamVjdC5ieXRlTGVuZ3RoID09PSAnbnVtYmVyJykge1xuICAgIC8vIFNwZWVkIG9wdGltaXphdGlvbiAtLSB1c2Ugc2V0IGlmIHdlJ3JlIGNvcHlpbmcgZnJvbSBhIHR5cGVkIGFycmF5XG4gICAgYnVmLl9zZXQoc3ViamVjdClcbiAgfSBlbHNlIGlmIChpc0FycmF5aXNoKHN1YmplY3QpKSB7XG4gICAgLy8gVHJlYXQgYXJyYXktaXNoIG9iamVjdHMgYXMgYSBieXRlIGFycmF5XG4gICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoQnVmZmVyLmlzQnVmZmVyKHN1YmplY3QpKVxuICAgICAgICBidWZbaV0gPSBzdWJqZWN0LnJlYWRVSW50OChpKVxuICAgICAgZWxzZVxuICAgICAgICBidWZbaV0gPSBzdWJqZWN0W2ldXG4gICAgfVxuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgYnVmLndyaXRlKHN1YmplY3QsIDAsIGVuY29kaW5nKVxuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdudW1iZXInICYmICFCdWZmZXIuX3VzZVR5cGVkQXJyYXlzICYmICFub1plcm8pIHtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIGJ1ZltpXSA9IDBcbiAgICB9XG4gIH1cblxuICByZXR1cm4gYnVmXG59XG5cbi8vIFNUQVRJQyBNRVRIT0RTXG4vLyA9PT09PT09PT09PT09PVxuXG5CdWZmZXIuaXNFbmNvZGluZyA9IGZ1bmN0aW9uIChlbmNvZGluZykge1xuICBzd2l0Y2ggKFN0cmluZyhlbmNvZGluZykudG9Mb3dlckNhc2UoKSkge1xuICAgIGNhc2UgJ2hleCc6XG4gICAgY2FzZSAndXRmOCc6XG4gICAgY2FzZSAndXRmLTgnOlxuICAgIGNhc2UgJ2FzY2lpJzpcbiAgICBjYXNlICdiaW5hcnknOlxuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgY2FzZSAncmF3JzpcbiAgICBjYXNlICd1Y3MyJzpcbiAgICBjYXNlICd1Y3MtMic6XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgcmV0dXJuIHRydWVcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGZhbHNlXG4gIH1cbn1cblxuQnVmZmVyLmlzQnVmZmVyID0gZnVuY3Rpb24gKGIpIHtcbiAgcmV0dXJuICEhKGIgIT09IG51bGwgJiYgYiAhPT0gdW5kZWZpbmVkICYmIGIuX2lzQnVmZmVyKVxufVxuXG5CdWZmZXIuYnl0ZUxlbmd0aCA9IGZ1bmN0aW9uIChzdHIsIGVuY29kaW5nKSB7XG4gIHZhciByZXRcbiAgc3RyID0gc3RyICsgJydcbiAgc3dpdGNoIChlbmNvZGluZyB8fCAndXRmOCcpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgICAgcmV0ID0gc3RyLmxlbmd0aCAvIDJcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAndXRmOCc6XG4gICAgY2FzZSAndXRmLTgnOlxuICAgICAgcmV0ID0gdXRmOFRvQnl0ZXMoc3RyKS5sZW5ndGhcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnYXNjaWknOlxuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgY2FzZSAncmF3JzpcbiAgICAgIHJldCA9IHN0ci5sZW5ndGhcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgIHJldCA9IGJhc2U2NFRvQnl0ZXMoc3RyKS5sZW5ndGhcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndWNzLTInOlxuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgIHJldCA9IHN0ci5sZW5ndGggKiAyXG4gICAgICBicmVha1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gZW5jb2RpbmcnKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuQnVmZmVyLmNvbmNhdCA9IGZ1bmN0aW9uIChsaXN0LCB0b3RhbExlbmd0aCkge1xuICBhc3NlcnQoaXNBcnJheShsaXN0KSwgJ1VzYWdlOiBCdWZmZXIuY29uY2F0KGxpc3QsIFt0b3RhbExlbmd0aF0pXFxuJyArXG4gICAgICAnbGlzdCBzaG91bGQgYmUgYW4gQXJyYXkuJylcblxuICBpZiAobGlzdC5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbmV3IEJ1ZmZlcigwKVxuICB9IGVsc2UgaWYgKGxpc3QubGVuZ3RoID09PSAxKSB7XG4gICAgcmV0dXJuIGxpc3RbMF1cbiAgfVxuXG4gIHZhciBpXG4gIGlmICh0eXBlb2YgdG90YWxMZW5ndGggIT09ICdudW1iZXInKSB7XG4gICAgdG90YWxMZW5ndGggPSAwXG4gICAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRvdGFsTGVuZ3RoICs9IGxpc3RbaV0ubGVuZ3RoXG4gICAgfVxuICB9XG5cbiAgdmFyIGJ1ZiA9IG5ldyBCdWZmZXIodG90YWxMZW5ndGgpXG4gIHZhciBwb3MgPSAwXG4gIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGl0ZW0gPSBsaXN0W2ldXG4gICAgaXRlbS5jb3B5KGJ1ZiwgcG9zKVxuICAgIHBvcyArPSBpdGVtLmxlbmd0aFxuICB9XG4gIHJldHVybiBidWZcbn1cblxuLy8gQlVGRkVSIElOU1RBTkNFIE1FVEhPRFNcbi8vID09PT09PT09PT09PT09PT09PT09PT09XG5cbmZ1bmN0aW9uIF9oZXhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIG9mZnNldCA9IE51bWJlcihvZmZzZXQpIHx8IDBcbiAgdmFyIHJlbWFpbmluZyA9IGJ1Zi5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKCFsZW5ndGgpIHtcbiAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgfSBlbHNlIHtcbiAgICBsZW5ndGggPSBOdW1iZXIobGVuZ3RoKVxuICAgIGlmIChsZW5ndGggPiByZW1haW5pbmcpIHtcbiAgICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICAgIH1cbiAgfVxuXG4gIC8vIG11c3QgYmUgYW4gZXZlbiBudW1iZXIgb2YgZGlnaXRzXG4gIHZhciBzdHJMZW4gPSBzdHJpbmcubGVuZ3RoXG4gIGFzc2VydChzdHJMZW4gJSAyID09PSAwLCAnSW52YWxpZCBoZXggc3RyaW5nJylcblxuICBpZiAobGVuZ3RoID4gc3RyTGVuIC8gMikge1xuICAgIGxlbmd0aCA9IHN0ckxlbiAvIDJcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGJ5dGUgPSBwYXJzZUludChzdHJpbmcuc3Vic3RyKGkgKiAyLCAyKSwgMTYpXG4gICAgYXNzZXJ0KCFpc05hTihieXRlKSwgJ0ludmFsaWQgaGV4IHN0cmluZycpXG4gICAgYnVmW29mZnNldCArIGldID0gYnl0ZVxuICB9XG4gIEJ1ZmZlci5fY2hhcnNXcml0dGVuID0gaSAqIDJcbiAgcmV0dXJuIGlcbn1cblxuZnVuY3Rpb24gX3V0ZjhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHZhciBjaGFyc1dyaXR0ZW4gPSBCdWZmZXIuX2NoYXJzV3JpdHRlbiA9XG4gICAgYmxpdEJ1ZmZlcih1dGY4VG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxuICByZXR1cm4gY2hhcnNXcml0dGVuXG59XG5cbmZ1bmN0aW9uIF9hc2NpaVdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgdmFyIGNoYXJzV3JpdHRlbiA9IEJ1ZmZlci5fY2hhcnNXcml0dGVuID1cbiAgICBibGl0QnVmZmVyKGFzY2lpVG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxuICByZXR1cm4gY2hhcnNXcml0dGVuXG59XG5cbmZ1bmN0aW9uIF9iaW5hcnlXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBfYXNjaWlXcml0ZShidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIF9iYXNlNjRXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHZhciBjaGFyc1dyaXR0ZW4gPSBCdWZmZXIuX2NoYXJzV3JpdHRlbiA9XG4gICAgYmxpdEJ1ZmZlcihiYXNlNjRUb0J5dGVzKHN0cmluZyksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG4gIHJldHVybiBjaGFyc1dyaXR0ZW5cbn1cblxuZnVuY3Rpb24gX3V0ZjE2bGVXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHZhciBjaGFyc1dyaXR0ZW4gPSBCdWZmZXIuX2NoYXJzV3JpdHRlbiA9XG4gICAgYmxpdEJ1ZmZlcih1dGYxNmxlVG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxuICByZXR1cm4gY2hhcnNXcml0dGVuXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGUgPSBmdW5jdGlvbiAoc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCwgZW5jb2RpbmcpIHtcbiAgLy8gU3VwcG9ydCBib3RoIChzdHJpbmcsIG9mZnNldCwgbGVuZ3RoLCBlbmNvZGluZylcbiAgLy8gYW5kIHRoZSBsZWdhY3kgKHN0cmluZywgZW5jb2RpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICBpZiAoaXNGaW5pdGUob2Zmc2V0KSkge1xuICAgIGlmICghaXNGaW5pdGUobGVuZ3RoKSkge1xuICAgICAgZW5jb2RpbmcgPSBsZW5ndGhcbiAgICAgIGxlbmd0aCA9IHVuZGVmaW5lZFxuICAgIH1cbiAgfSBlbHNlIHsgIC8vIGxlZ2FjeVxuICAgIHZhciBzd2FwID0gZW5jb2RpbmdcbiAgICBlbmNvZGluZyA9IG9mZnNldFxuICAgIG9mZnNldCA9IGxlbmd0aFxuICAgIGxlbmd0aCA9IHN3YXBcbiAgfVxuXG4gIG9mZnNldCA9IE51bWJlcihvZmZzZXQpIHx8IDBcbiAgdmFyIHJlbWFpbmluZyA9IHRoaXMubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmICghbGVuZ3RoKSB7XG4gICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gIH0gZWxzZSB7XG4gICAgbGVuZ3RoID0gTnVtYmVyKGxlbmd0aClcbiAgICBpZiAobGVuZ3RoID4gcmVtYWluaW5nKSB7XG4gICAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgICB9XG4gIH1cbiAgZW5jb2RpbmcgPSBTdHJpbmcoZW5jb2RpbmcgfHwgJ3V0ZjgnKS50b0xvd2VyQ2FzZSgpXG5cbiAgdmFyIHJldFxuICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgY2FzZSAnaGV4JzpcbiAgICAgIHJldCA9IF9oZXhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICd1dGY4JzpcbiAgICBjYXNlICd1dGYtOCc6XG4gICAgICByZXQgPSBfdXRmOFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgIHJldCA9IF9hc2NpaVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICByZXQgPSBfYmluYXJ5V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgIHJldCA9IF9iYXNlNjRXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICd1Y3MyJzpcbiAgICBjYXNlICd1Y3MtMic6XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgcmV0ID0gX3V0ZjE2bGVXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGVuY29kaW5nJylcbiAgfVxuICByZXR1cm4gcmV0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoZW5jb2RpbmcsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHNlbGYgPSB0aGlzXG5cbiAgZW5jb2RpbmcgPSBTdHJpbmcoZW5jb2RpbmcgfHwgJ3V0ZjgnKS50b0xvd2VyQ2FzZSgpXG4gIHN0YXJ0ID0gTnVtYmVyKHN0YXJ0KSB8fCAwXG4gIGVuZCA9IChlbmQgIT09IHVuZGVmaW5lZClcbiAgICA/IE51bWJlcihlbmQpXG4gICAgOiBlbmQgPSBzZWxmLmxlbmd0aFxuXG4gIC8vIEZhc3RwYXRoIGVtcHR5IHN0cmluZ3NcbiAgaWYgKGVuZCA9PT0gc3RhcnQpXG4gICAgcmV0dXJuICcnXG5cbiAgdmFyIHJldFxuICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgY2FzZSAnaGV4JzpcbiAgICAgIHJldCA9IF9oZXhTbGljZShzZWxmLCBzdGFydCwgZW5kKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICd1dGY4JzpcbiAgICBjYXNlICd1dGYtOCc6XG4gICAgICByZXQgPSBfdXRmOFNsaWNlKHNlbGYsIHN0YXJ0LCBlbmQpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgIHJldCA9IF9hc2NpaVNsaWNlKHNlbGYsIHN0YXJ0LCBlbmQpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICByZXQgPSBfYmluYXJ5U2xpY2Uoc2VsZiwgc3RhcnQsIGVuZClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgIHJldCA9IF9iYXNlNjRTbGljZShzZWxmLCBzdGFydCwgZW5kKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICd1Y3MyJzpcbiAgICBjYXNlICd1Y3MtMic6XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgcmV0ID0gX3V0ZjE2bGVTbGljZShzZWxmLCBzdGFydCwgZW5kKVxuICAgICAgYnJlYWtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGVuY29kaW5nJylcbiAgfVxuICByZXR1cm4gcmV0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4ge1xuICAgIHR5cGU6ICdCdWZmZXInLFxuICAgIGRhdGE6IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHRoaXMuX2FyciB8fCB0aGlzLCAwKVxuICB9XG59XG5cbi8vIGNvcHkodGFyZ2V0QnVmZmVyLCB0YXJnZXRTdGFydD0wLCBzb3VyY2VTdGFydD0wLCBzb3VyY2VFbmQ9YnVmZmVyLmxlbmd0aClcbkJ1ZmZlci5wcm90b3R5cGUuY29weSA9IGZ1bmN0aW9uICh0YXJnZXQsIHRhcmdldF9zdGFydCwgc3RhcnQsIGVuZCkge1xuICB2YXIgc291cmNlID0gdGhpc1xuXG4gIGlmICghc3RhcnQpIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCAmJiBlbmQgIT09IDApIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICghdGFyZ2V0X3N0YXJ0KSB0YXJnZXRfc3RhcnQgPSAwXG5cbiAgLy8gQ29weSAwIGJ5dGVzOyB3ZSdyZSBkb25lXG4gIGlmIChlbmQgPT09IHN0YXJ0KSByZXR1cm5cbiAgaWYgKHRhcmdldC5sZW5ndGggPT09IDAgfHwgc291cmNlLmxlbmd0aCA9PT0gMCkgcmV0dXJuXG5cbiAgLy8gRmF0YWwgZXJyb3IgY29uZGl0aW9uc1xuICBhc3NlcnQoZW5kID49IHN0YXJ0LCAnc291cmNlRW5kIDwgc291cmNlU3RhcnQnKVxuICBhc3NlcnQodGFyZ2V0X3N0YXJ0ID49IDAgJiYgdGFyZ2V0X3N0YXJ0IDwgdGFyZ2V0Lmxlbmd0aCxcbiAgICAgICd0YXJnZXRTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgYXNzZXJ0KHN0YXJ0ID49IDAgJiYgc3RhcnQgPCBzb3VyY2UubGVuZ3RoLCAnc291cmNlU3RhcnQgb3V0IG9mIGJvdW5kcycpXG4gIGFzc2VydChlbmQgPj0gMCAmJiBlbmQgPD0gc291cmNlLmxlbmd0aCwgJ3NvdXJjZUVuZCBvdXQgb2YgYm91bmRzJylcblxuICAvLyBBcmUgd2Ugb29iP1xuICBpZiAoZW5kID4gdGhpcy5sZW5ndGgpXG4gICAgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKHRhcmdldC5sZW5ndGggLSB0YXJnZXRfc3RhcnQgPCBlbmQgLSBzdGFydClcbiAgICBlbmQgPSB0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0X3N0YXJ0ICsgc3RhcnRcblxuICB2YXIgbGVuID0gZW5kIC0gc3RhcnRcblxuICBpZiAobGVuIDwgMTAwIHx8ICFCdWZmZXIuX3VzZVR5cGVkQXJyYXlzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKylcbiAgICAgIHRhcmdldFtpICsgdGFyZ2V0X3N0YXJ0XSA9IHRoaXNbaSArIHN0YXJ0XVxuICB9IGVsc2Uge1xuICAgIHRhcmdldC5fc2V0KHRoaXMuc3ViYXJyYXkoc3RhcnQsIHN0YXJ0ICsgbGVuKSwgdGFyZ2V0X3N0YXJ0KVxuICB9XG59XG5cbmZ1bmN0aW9uIF9iYXNlNjRTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGlmIChzdGFydCA9PT0gMCAmJiBlbmQgPT09IGJ1Zi5sZW5ndGgpIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmKVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBiYXNlNjQuZnJvbUJ5dGVBcnJheShidWYuc2xpY2Uoc3RhcnQsIGVuZCkpXG4gIH1cbn1cblxuZnVuY3Rpb24gX3V0ZjhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXMgPSAnJ1xuICB2YXIgdG1wID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgaWYgKGJ1ZltpXSA8PSAweDdGKSB7XG4gICAgICByZXMgKz0gZGVjb2RlVXRmOENoYXIodG1wKSArIFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldKVxuICAgICAgdG1wID0gJydcbiAgICB9IGVsc2Uge1xuICAgICAgdG1wICs9ICclJyArIGJ1ZltpXS50b1N0cmluZygxNilcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzICsgZGVjb2RlVXRmOENoYXIodG1wKVxufVxuXG5mdW5jdGlvbiBfYXNjaWlTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspXG4gICAgcmV0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldKVxuICByZXR1cm4gcmV0XG59XG5cbmZ1bmN0aW9uIF9iaW5hcnlTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHJldHVybiBfYXNjaWlTbGljZShidWYsIHN0YXJ0LCBlbmQpXG59XG5cbmZ1bmN0aW9uIF9oZXhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG5cbiAgaWYgKCFzdGFydCB8fCBzdGFydCA8IDApIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCB8fCBlbmQgPCAwIHx8IGVuZCA+IGxlbikgZW5kID0gbGVuXG5cbiAgdmFyIG91dCA9ICcnXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgb3V0ICs9IHRvSGV4KGJ1ZltpXSlcbiAgfVxuICByZXR1cm4gb3V0XG59XG5cbmZ1bmN0aW9uIF91dGYxNmxlU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgYnl0ZXMgPSBidWYuc2xpY2Uoc3RhcnQsIGVuZClcbiAgdmFyIHJlcyA9ICcnXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpICs9IDIpIHtcbiAgICByZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShieXRlc1tpXSArIGJ5dGVzW2krMV0gKiAyNTYpXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnNsaWNlID0gZnVuY3Rpb24gKHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoXG4gIHN0YXJ0ID0gY2xhbXAoc3RhcnQsIGxlbiwgMClcbiAgZW5kID0gY2xhbXAoZW5kLCBsZW4sIGxlbilcblxuICBpZiAoQnVmZmVyLl91c2VUeXBlZEFycmF5cykge1xuICAgIHJldHVybiBCdWZmZXIuX2F1Z21lbnQodGhpcy5zdWJhcnJheShzdGFydCwgZW5kKSlcbiAgfSBlbHNlIHtcbiAgICB2YXIgc2xpY2VMZW4gPSBlbmQgLSBzdGFydFxuICAgIHZhciBuZXdCdWYgPSBuZXcgQnVmZmVyKHNsaWNlTGVuLCB1bmRlZmluZWQsIHRydWUpXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzbGljZUxlbjsgaSsrKSB7XG4gICAgICBuZXdCdWZbaV0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gICAgcmV0dXJuIG5ld0J1ZlxuICB9XG59XG5cbi8vIGBnZXRgIHdpbGwgYmUgcmVtb3ZlZCBpbiBOb2RlIDAuMTMrXG5CdWZmZXIucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIChvZmZzZXQpIHtcbiAgY29uc29sZS5sb2coJy5nZXQoKSBpcyBkZXByZWNhdGVkLiBBY2Nlc3MgdXNpbmcgYXJyYXkgaW5kZXhlcyBpbnN0ZWFkLicpXG4gIHJldHVybiB0aGlzLnJlYWRVSW50OChvZmZzZXQpXG59XG5cbi8vIGBzZXRgIHdpbGwgYmUgcmVtb3ZlZCBpbiBOb2RlIDAuMTMrXG5CdWZmZXIucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uICh2LCBvZmZzZXQpIHtcbiAgY29uc29sZS5sb2coJy5zZXQoKSBpcyBkZXByZWNhdGVkLiBBY2Nlc3MgdXNpbmcgYXJyYXkgaW5kZXhlcyBpbnN0ZWFkLicpXG4gIHJldHVybiB0aGlzLndyaXRlVUludDgodiwgb2Zmc2V0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50OCA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgPCB0aGlzLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIGlmIChvZmZzZXQgPj0gdGhpcy5sZW5ndGgpXG4gICAgcmV0dXJuXG5cbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XVxufVxuXG5mdW5jdGlvbiBfcmVhZFVJbnQxNiAoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAxIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIHZhciB2YWxcbiAgaWYgKGxpdHRsZUVuZGlhbikge1xuICAgIHZhbCA9IGJ1ZltvZmZzZXRdXG4gICAgaWYgKG9mZnNldCArIDEgPCBsZW4pXG4gICAgICB2YWwgfD0gYnVmW29mZnNldCArIDFdIDw8IDhcbiAgfSBlbHNlIHtcbiAgICB2YWwgPSBidWZbb2Zmc2V0XSA8PCA4XG4gICAgaWYgKG9mZnNldCArIDEgPCBsZW4pXG4gICAgICB2YWwgfD0gYnVmW29mZnNldCArIDFdXG4gIH1cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiBfcmVhZFVJbnQxNih0aGlzLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiBfcmVhZFVJbnQxNih0aGlzLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gX3JlYWRVSW50MzIgKGJ1Ziwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0ICsgMyA8IGJ1Zi5sZW5ndGgsICdUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICB2YXIgdmFsXG4gIGlmIChsaXR0bGVFbmRpYW4pIHtcbiAgICBpZiAob2Zmc2V0ICsgMiA8IGxlbilcbiAgICAgIHZhbCA9IGJ1ZltvZmZzZXQgKyAyXSA8PCAxNlxuICAgIGlmIChvZmZzZXQgKyAxIDwgbGVuKVxuICAgICAgdmFsIHw9IGJ1ZltvZmZzZXQgKyAxXSA8PCA4XG4gICAgdmFsIHw9IGJ1ZltvZmZzZXRdXG4gICAgaWYgKG9mZnNldCArIDMgPCBsZW4pXG4gICAgICB2YWwgPSB2YWwgKyAoYnVmW29mZnNldCArIDNdIDw8IDI0ID4+PiAwKVxuICB9IGVsc2Uge1xuICAgIGlmIChvZmZzZXQgKyAxIDwgbGVuKVxuICAgICAgdmFsID0gYnVmW29mZnNldCArIDFdIDw8IDE2XG4gICAgaWYgKG9mZnNldCArIDIgPCBsZW4pXG4gICAgICB2YWwgfD0gYnVmW29mZnNldCArIDJdIDw8IDhcbiAgICBpZiAob2Zmc2V0ICsgMyA8IGxlbilcbiAgICAgIHZhbCB8PSBidWZbb2Zmc2V0ICsgM11cbiAgICB2YWwgPSB2YWwgKyAoYnVmW29mZnNldF0gPDwgMjQgPj4+IDApXG4gIH1cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiBfcmVhZFVJbnQzMih0aGlzLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiBfcmVhZFVJbnQzMih0aGlzLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50OCA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLFxuICAgICAgICAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgPCB0aGlzLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIGlmIChvZmZzZXQgPj0gdGhpcy5sZW5ndGgpXG4gICAgcmV0dXJuXG5cbiAgdmFyIG5lZyA9IHRoaXNbb2Zmc2V0XSAmIDB4ODBcbiAgaWYgKG5lZylcbiAgICByZXR1cm4gKDB4ZmYgLSB0aGlzW29mZnNldF0gKyAxKSAqIC0xXG4gIGVsc2VcbiAgICByZXR1cm4gdGhpc1tvZmZzZXRdXG59XG5cbmZ1bmN0aW9uIF9yZWFkSW50MTYgKGJ1Ziwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0ICsgMSA8IGJ1Zi5sZW5ndGgsICdUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICB2YXIgdmFsID0gX3JlYWRVSW50MTYoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgdHJ1ZSlcbiAgdmFyIG5lZyA9IHZhbCAmIDB4ODAwMFxuICBpZiAobmVnKVxuICAgIHJldHVybiAoMHhmZmZmIC0gdmFsICsgMSkgKiAtMVxuICBlbHNlXG4gICAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkxFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIF9yZWFkSW50MTYodGhpcywgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiBfcmVhZEludDE2KHRoaXMsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiBfcmVhZEludDMyIChidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDMgPCBidWYubGVuZ3RoLCAnVHJ5aW5nIHRvIHJlYWQgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICB9XG5cbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcbiAgaWYgKG9mZnNldCA+PSBsZW4pXG4gICAgcmV0dXJuXG5cbiAgdmFyIHZhbCA9IF9yZWFkVUludDMyKGJ1Ziwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIHRydWUpXG4gIHZhciBuZWcgPSB2YWwgJiAweDgwMDAwMDAwXG4gIGlmIChuZWcpXG4gICAgcmV0dXJuICgweGZmZmZmZmZmIC0gdmFsICsgMSkgKiAtMVxuICBlbHNlXG4gICAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkxFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIF9yZWFkSW50MzIodGhpcywgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJCRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiBfcmVhZEludDMyKHRoaXMsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiBfcmVhZEZsb2F0IChidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgKyAzIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIHJldHVybiBpZWVlNzU0LnJlYWQoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0TEUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gX3JlYWRGbG9hdCh0aGlzLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdEJFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIF9yZWFkRmxvYXQodGhpcywgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIF9yZWFkRG91YmxlIChidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgKyA3IDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIHJldHVybiBpZWVlNzU0LnJlYWQoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgNTIsIDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUxFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIF9yZWFkRG91YmxlKHRoaXMsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUJFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIF9yZWFkRG91YmxlKHRoaXMsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDggPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsLCAnbWlzc2luZyB2YWx1ZScpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0IDwgdGhpcy5sZW5ndGgsICd0cnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICAgIHZlcmlmdWludCh2YWx1ZSwgMHhmZilcbiAgfVxuXG4gIGlmIChvZmZzZXQgPj0gdGhpcy5sZW5ndGgpIHJldHVyblxuXG4gIHRoaXNbb2Zmc2V0XSA9IHZhbHVlXG59XG5cbmZ1bmN0aW9uIF93cml0ZVVJbnQxNiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCwgJ21pc3NpbmcgdmFsdWUnKVxuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAxIDwgYnVmLmxlbmd0aCwgJ3RyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gICAgdmVyaWZ1aW50KHZhbHVlLCAweGZmZmYpXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICBmb3IgKHZhciBpID0gMCwgaiA9IE1hdGgubWluKGxlbiAtIG9mZnNldCwgMik7IGkgPCBqOyBpKyspIHtcbiAgICBidWZbb2Zmc2V0ICsgaV0gPVxuICAgICAgICAodmFsdWUgJiAoMHhmZiA8PCAoOCAqIChsaXR0bGVFbmRpYW4gPyBpIDogMSAtIGkpKSkpID4+PlxuICAgICAgICAgICAgKGxpdHRsZUVuZGlhbiA/IGkgOiAxIC0gaSkgKiA4XG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkxFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIF93cml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIF93cml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIF93cml0ZVVJbnQzMiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCwgJ21pc3NpbmcgdmFsdWUnKVxuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAzIDwgYnVmLmxlbmd0aCwgJ3RyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gICAgdmVyaWZ1aW50KHZhbHVlLCAweGZmZmZmZmZmKVxuICB9XG5cbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcbiAgaWYgKG9mZnNldCA+PSBsZW4pXG4gICAgcmV0dXJuXG5cbiAgZm9yICh2YXIgaSA9IDAsIGogPSBNYXRoLm1pbihsZW4gLSBvZmZzZXQsIDQpOyBpIDwgajsgaSsrKSB7XG4gICAgYnVmW29mZnNldCArIGldID1cbiAgICAgICAgKHZhbHVlID4+PiAobGl0dGxlRW5kaWFuID8gaSA6IDMgLSBpKSAqIDgpICYgMHhmZlxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJMRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBfd3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJCRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBfd3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50OCA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwsICdtaXNzaW5nIHZhbHVlJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgPCB0aGlzLmxlbmd0aCwgJ1RyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gICAgdmVyaWZzaW50KHZhbHVlLCAweDdmLCAtMHg4MClcbiAgfVxuXG4gIGlmIChvZmZzZXQgPj0gdGhpcy5sZW5ndGgpXG4gICAgcmV0dXJuXG5cbiAgaWYgKHZhbHVlID49IDApXG4gICAgdGhpcy53cml0ZVVJbnQ4KHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KVxuICBlbHNlXG4gICAgdGhpcy53cml0ZVVJbnQ4KDB4ZmYgKyB2YWx1ZSArIDEsIG9mZnNldCwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIF93cml0ZUludDE2IChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsLCAnbWlzc2luZyB2YWx1ZScpXG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDEgPCBidWYubGVuZ3RoLCAnVHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgICB2ZXJpZnNpbnQodmFsdWUsIDB4N2ZmZiwgLTB4ODAwMClcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIGlmICh2YWx1ZSA+PSAwKVxuICAgIF93cml0ZVVJbnQxNihidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpXG4gIGVsc2VcbiAgICBfd3JpdGVVSW50MTYoYnVmLCAweGZmZmYgKyB2YWx1ZSArIDEsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDE2TEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgX3dyaXRlSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIF93cml0ZUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gX3dyaXRlSW50MzIgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwsICdtaXNzaW5nIHZhbHVlJylcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0ICsgMyA8IGJ1Zi5sZW5ndGgsICdUcnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICAgIHZlcmlmc2ludCh2YWx1ZSwgMHg3ZmZmZmZmZiwgLTB4ODAwMDAwMDApXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICBpZiAodmFsdWUgPj0gMClcbiAgICBfd3JpdGVVSW50MzIoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KVxuICBlbHNlXG4gICAgX3dyaXRlVUludDMyKGJ1ZiwgMHhmZmZmZmZmZiArIHZhbHVlICsgMSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJMRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBfd3JpdGVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyQkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgX3dyaXRlSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiBfd3JpdGVGbG9hdCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCwgJ21pc3NpbmcgdmFsdWUnKVxuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAzIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gICAgdmVyaWZJRUVFNzU0KHZhbHVlLCAzLjQwMjgyMzQ2NjM4NTI4ODZlKzM4LCAtMy40MDI4MjM0NjYzODUyODg2ZSszOClcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIGllZWU3NTQud3JpdGUoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDIzLCA0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXRMRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBfd3JpdGVGbG9hdCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0QkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgX3dyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiBfd3JpdGVEb3VibGUgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwsICdtaXNzaW5nIHZhbHVlJylcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0ICsgNyA8IGJ1Zi5sZW5ndGgsXG4gICAgICAgICdUcnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICAgIHZlcmlmSUVFRTc1NCh2YWx1ZSwgMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgsIC0xLjc5NzY5MzEzNDg2MjMxNTdFKzMwOClcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIGllZWU3NTQud3JpdGUoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDUyLCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlTEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgX3dyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgX3dyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuLy8gZmlsbCh2YWx1ZSwgc3RhcnQ9MCwgZW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmZpbGwgPSBmdW5jdGlvbiAodmFsdWUsIHN0YXJ0LCBlbmQpIHtcbiAgaWYgKCF2YWx1ZSkgdmFsdWUgPSAwXG4gIGlmICghc3RhcnQpIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCkgZW5kID0gdGhpcy5sZW5ndGhcblxuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIHZhbHVlID0gdmFsdWUuY2hhckNvZGVBdCgwKVxuICB9XG5cbiAgYXNzZXJ0KHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgJiYgIWlzTmFOKHZhbHVlKSwgJ3ZhbHVlIGlzIG5vdCBhIG51bWJlcicpXG4gIGFzc2VydChlbmQgPj0gc3RhcnQsICdlbmQgPCBzdGFydCcpXG5cbiAgLy8gRmlsbCAwIGJ5dGVzOyB3ZSdyZSBkb25lXG4gIGlmIChlbmQgPT09IHN0YXJ0KSByZXR1cm5cbiAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm5cblxuICBhc3NlcnQoc3RhcnQgPj0gMCAmJiBzdGFydCA8IHRoaXMubGVuZ3RoLCAnc3RhcnQgb3V0IG9mIGJvdW5kcycpXG4gIGFzc2VydChlbmQgPj0gMCAmJiBlbmQgPD0gdGhpcy5sZW5ndGgsICdlbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICB0aGlzW2ldID0gdmFsdWVcbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluc3BlY3QgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBvdXQgPSBbXVxuICB2YXIgbGVuID0gdGhpcy5sZW5ndGhcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgIG91dFtpXSA9IHRvSGV4KHRoaXNbaV0pXG4gICAgaWYgKGkgPT09IGV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVMpIHtcbiAgICAgIG91dFtpICsgMV0gPSAnLi4uJ1xuICAgICAgYnJlYWtcbiAgICB9XG4gIH1cbiAgcmV0dXJuICc8QnVmZmVyICcgKyBvdXQuam9pbignICcpICsgJz4nXG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBgQXJyYXlCdWZmZXJgIHdpdGggdGhlICpjb3BpZWQqIG1lbW9yeSBvZiB0aGUgYnVmZmVyIGluc3RhbmNlLlxuICogQWRkZWQgaW4gTm9kZSAwLjEyLiBPbmx5IGF2YWlsYWJsZSBpbiBicm93c2VycyB0aGF0IHN1cHBvcnQgQXJyYXlCdWZmZXIuXG4gKi9cbkJ1ZmZlci5wcm90b3R5cGUudG9BcnJheUJ1ZmZlciA9IGZ1bmN0aW9uICgpIHtcbiAgaWYgKHR5cGVvZiBVaW50OEFycmF5ICE9PSAndW5kZWZpbmVkJykge1xuICAgIGlmIChCdWZmZXIuX3VzZVR5cGVkQXJyYXlzKSB7XG4gICAgICByZXR1cm4gKG5ldyBCdWZmZXIodGhpcykpLmJ1ZmZlclxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgYnVmID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5sZW5ndGgpXG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gYnVmLmxlbmd0aDsgaSA8IGxlbjsgaSArPSAxKVxuICAgICAgICBidWZbaV0gPSB0aGlzW2ldXG4gICAgICByZXR1cm4gYnVmLmJ1ZmZlclxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0J1ZmZlci50b0FycmF5QnVmZmVyIG5vdCBzdXBwb3J0ZWQgaW4gdGhpcyBicm93c2VyJylcbiAgfVxufVxuXG4vLyBIRUxQRVIgRlVOQ1RJT05TXG4vLyA9PT09PT09PT09PT09PT09XG5cbmZ1bmN0aW9uIHN0cmluZ3RyaW0gKHN0cikge1xuICBpZiAoc3RyLnRyaW0pIHJldHVybiBzdHIudHJpbSgpXG4gIHJldHVybiBzdHIucmVwbGFjZSgvXlxccyt8XFxzKyQvZywgJycpXG59XG5cbnZhciBCUCA9IEJ1ZmZlci5wcm90b3R5cGVcblxuLyoqXG4gKiBBdWdtZW50IGEgVWludDhBcnJheSAqaW5zdGFuY2UqIChub3QgdGhlIFVpbnQ4QXJyYXkgY2xhc3MhKSB3aXRoIEJ1ZmZlciBtZXRob2RzXG4gKi9cbkJ1ZmZlci5fYXVnbWVudCA9IGZ1bmN0aW9uIChhcnIpIHtcbiAgYXJyLl9pc0J1ZmZlciA9IHRydWVcblxuICAvLyBzYXZlIHJlZmVyZW5jZSB0byBvcmlnaW5hbCBVaW50OEFycmF5IGdldC9zZXQgbWV0aG9kcyBiZWZvcmUgb3ZlcndyaXRpbmdcbiAgYXJyLl9nZXQgPSBhcnIuZ2V0XG4gIGFyci5fc2V0ID0gYXJyLnNldFxuXG4gIC8vIGRlcHJlY2F0ZWQsIHdpbGwgYmUgcmVtb3ZlZCBpbiBub2RlIDAuMTMrXG4gIGFyci5nZXQgPSBCUC5nZXRcbiAgYXJyLnNldCA9IEJQLnNldFxuXG4gIGFyci53cml0ZSA9IEJQLndyaXRlXG4gIGFyci50b1N0cmluZyA9IEJQLnRvU3RyaW5nXG4gIGFyci50b0xvY2FsZVN0cmluZyA9IEJQLnRvU3RyaW5nXG4gIGFyci50b0pTT04gPSBCUC50b0pTT05cbiAgYXJyLmNvcHkgPSBCUC5jb3B5XG4gIGFyci5zbGljZSA9IEJQLnNsaWNlXG4gIGFyci5yZWFkVUludDggPSBCUC5yZWFkVUludDhcbiAgYXJyLnJlYWRVSW50MTZMRSA9IEJQLnJlYWRVSW50MTZMRVxuICBhcnIucmVhZFVJbnQxNkJFID0gQlAucmVhZFVJbnQxNkJFXG4gIGFyci5yZWFkVUludDMyTEUgPSBCUC5yZWFkVUludDMyTEVcbiAgYXJyLnJlYWRVSW50MzJCRSA9IEJQLnJlYWRVSW50MzJCRVxuICBhcnIucmVhZEludDggPSBCUC5yZWFkSW50OFxuICBhcnIucmVhZEludDE2TEUgPSBCUC5yZWFkSW50MTZMRVxuICBhcnIucmVhZEludDE2QkUgPSBCUC5yZWFkSW50MTZCRVxuICBhcnIucmVhZEludDMyTEUgPSBCUC5yZWFkSW50MzJMRVxuICBhcnIucmVhZEludDMyQkUgPSBCUC5yZWFkSW50MzJCRVxuICBhcnIucmVhZEZsb2F0TEUgPSBCUC5yZWFkRmxvYXRMRVxuICBhcnIucmVhZEZsb2F0QkUgPSBCUC5yZWFkRmxvYXRCRVxuICBhcnIucmVhZERvdWJsZUxFID0gQlAucmVhZERvdWJsZUxFXG4gIGFyci5yZWFkRG91YmxlQkUgPSBCUC5yZWFkRG91YmxlQkVcbiAgYXJyLndyaXRlVUludDggPSBCUC53cml0ZVVJbnQ4XG4gIGFyci53cml0ZVVJbnQxNkxFID0gQlAud3JpdGVVSW50MTZMRVxuICBhcnIud3JpdGVVSW50MTZCRSA9IEJQLndyaXRlVUludDE2QkVcbiAgYXJyLndyaXRlVUludDMyTEUgPSBCUC53cml0ZVVJbnQzMkxFXG4gIGFyci53cml0ZVVJbnQzMkJFID0gQlAud3JpdGVVSW50MzJCRVxuICBhcnIud3JpdGVJbnQ4ID0gQlAud3JpdGVJbnQ4XG4gIGFyci53cml0ZUludDE2TEUgPSBCUC53cml0ZUludDE2TEVcbiAgYXJyLndyaXRlSW50MTZCRSA9IEJQLndyaXRlSW50MTZCRVxuICBhcnIud3JpdGVJbnQzMkxFID0gQlAud3JpdGVJbnQzMkxFXG4gIGFyci53cml0ZUludDMyQkUgPSBCUC53cml0ZUludDMyQkVcbiAgYXJyLndyaXRlRmxvYXRMRSA9IEJQLndyaXRlRmxvYXRMRVxuICBhcnIud3JpdGVGbG9hdEJFID0gQlAud3JpdGVGbG9hdEJFXG4gIGFyci53cml0ZURvdWJsZUxFID0gQlAud3JpdGVEb3VibGVMRVxuICBhcnIud3JpdGVEb3VibGVCRSA9IEJQLndyaXRlRG91YmxlQkVcbiAgYXJyLmZpbGwgPSBCUC5maWxsXG4gIGFyci5pbnNwZWN0ID0gQlAuaW5zcGVjdFxuICBhcnIudG9BcnJheUJ1ZmZlciA9IEJQLnRvQXJyYXlCdWZmZXJcblxuICByZXR1cm4gYXJyXG59XG5cbi8vIHNsaWNlKHN0YXJ0LCBlbmQpXG5mdW5jdGlvbiBjbGFtcCAoaW5kZXgsIGxlbiwgZGVmYXVsdFZhbHVlKSB7XG4gIGlmICh0eXBlb2YgaW5kZXggIT09ICdudW1iZXInKSByZXR1cm4gZGVmYXVsdFZhbHVlXG4gIGluZGV4ID0gfn5pbmRleDsgIC8vIENvZXJjZSB0byBpbnRlZ2VyLlxuICBpZiAoaW5kZXggPj0gbGVuKSByZXR1cm4gbGVuXG4gIGlmIChpbmRleCA+PSAwKSByZXR1cm4gaW5kZXhcbiAgaW5kZXggKz0gbGVuXG4gIGlmIChpbmRleCA+PSAwKSByZXR1cm4gaW5kZXhcbiAgcmV0dXJuIDBcbn1cblxuZnVuY3Rpb24gY29lcmNlIChsZW5ndGgpIHtcbiAgLy8gQ29lcmNlIGxlbmd0aCB0byBhIG51bWJlciAocG9zc2libHkgTmFOKSwgcm91bmQgdXBcbiAgLy8gaW4gY2FzZSBpdCdzIGZyYWN0aW9uYWwgKGUuZy4gMTIzLjQ1NikgdGhlbiBkbyBhXG4gIC8vIGRvdWJsZSBuZWdhdGUgdG8gY29lcmNlIGEgTmFOIHRvIDAuIEVhc3ksIHJpZ2h0P1xuICBsZW5ndGggPSB+fk1hdGguY2VpbCgrbGVuZ3RoKVxuICByZXR1cm4gbGVuZ3RoIDwgMCA/IDAgOiBsZW5ndGhcbn1cblxuZnVuY3Rpb24gaXNBcnJheSAoc3ViamVjdCkge1xuICByZXR1cm4gKEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24gKHN1YmplY3QpIHtcbiAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHN1YmplY3QpID09PSAnW29iamVjdCBBcnJheV0nXG4gIH0pKHN1YmplY3QpXG59XG5cbmZ1bmN0aW9uIGlzQXJyYXlpc2ggKHN1YmplY3QpIHtcbiAgcmV0dXJuIGlzQXJyYXkoc3ViamVjdCkgfHwgQnVmZmVyLmlzQnVmZmVyKHN1YmplY3QpIHx8XG4gICAgICBzdWJqZWN0ICYmIHR5cGVvZiBzdWJqZWN0ID09PSAnb2JqZWN0JyAmJlxuICAgICAgdHlwZW9mIHN1YmplY3QubGVuZ3RoID09PSAnbnVtYmVyJ1xufVxuXG5mdW5jdGlvbiB0b0hleCAobikge1xuICBpZiAobiA8IDE2KSByZXR1cm4gJzAnICsgbi50b1N0cmluZygxNilcbiAgcmV0dXJuIG4udG9TdHJpbmcoMTYpXG59XG5cbmZ1bmN0aW9uIHV0ZjhUb0J5dGVzIChzdHIpIHtcbiAgdmFyIGJ5dGVBcnJheSA9IFtdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGIgPSBzdHIuY2hhckNvZGVBdChpKVxuICAgIGlmIChiIDw9IDB4N0YpXG4gICAgICBieXRlQXJyYXkucHVzaChzdHIuY2hhckNvZGVBdChpKSlcbiAgICBlbHNlIHtcbiAgICAgIHZhciBzdGFydCA9IGlcbiAgICAgIGlmIChiID49IDB4RDgwMCAmJiBiIDw9IDB4REZGRikgaSsrXG4gICAgICB2YXIgaCA9IGVuY29kZVVSSUNvbXBvbmVudChzdHIuc2xpY2Uoc3RhcnQsIGkrMSkpLnN1YnN0cigxKS5zcGxpdCgnJScpXG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGgubGVuZ3RoOyBqKyspXG4gICAgICAgIGJ5dGVBcnJheS5wdXNoKHBhcnNlSW50KGhbal0sIDE2KSlcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiBhc2NpaVRvQnl0ZXMgKHN0cikge1xuICB2YXIgYnl0ZUFycmF5ID0gW11cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAvLyBOb2RlJ3MgY29kZSBzZWVtcyB0byBiZSBkb2luZyB0aGlzIGFuZCBub3QgJiAweDdGLi5cbiAgICBieXRlQXJyYXkucHVzaChzdHIuY2hhckNvZGVBdChpKSAmIDB4RkYpXG4gIH1cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiB1dGYxNmxlVG9CeXRlcyAoc3RyKSB7XG4gIHZhciBjLCBoaSwgbG9cbiAgdmFyIGJ5dGVBcnJheSA9IFtdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgYyA9IHN0ci5jaGFyQ29kZUF0KGkpXG4gICAgaGkgPSBjID4+IDhcbiAgICBsbyA9IGMgJSAyNTZcbiAgICBieXRlQXJyYXkucHVzaChsbylcbiAgICBieXRlQXJyYXkucHVzaChoaSlcbiAgfVxuXG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gYmFzZTY0VG9CeXRlcyAoc3RyKSB7XG4gIHJldHVybiBiYXNlNjQudG9CeXRlQXJyYXkoc3RyKVxufVxuXG5mdW5jdGlvbiBibGl0QnVmZmVyIChzcmMsIGRzdCwgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgdmFyIHBvc1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKChpICsgb2Zmc2V0ID49IGRzdC5sZW5ndGgpIHx8IChpID49IHNyYy5sZW5ndGgpKVxuICAgICAgYnJlYWtcbiAgICBkc3RbaSArIG9mZnNldF0gPSBzcmNbaV1cbiAgfVxuICByZXR1cm4gaVxufVxuXG5mdW5jdGlvbiBkZWNvZGVVdGY4Q2hhciAoc3RyKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChzdHIpXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKDB4RkZGRCkgLy8gVVRGIDggaW52YWxpZCBjaGFyXG4gIH1cbn1cblxuLypcbiAqIFdlIGhhdmUgdG8gbWFrZSBzdXJlIHRoYXQgdGhlIHZhbHVlIGlzIGEgdmFsaWQgaW50ZWdlci4gVGhpcyBtZWFucyB0aGF0IGl0XG4gKiBpcyBub24tbmVnYXRpdmUuIEl0IGhhcyBubyBmcmFjdGlvbmFsIGNvbXBvbmVudCBhbmQgdGhhdCBpdCBkb2VzIG5vdFxuICogZXhjZWVkIHRoZSBtYXhpbXVtIGFsbG93ZWQgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIHZlcmlmdWludCAodmFsdWUsIG1heCkge1xuICBhc3NlcnQodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJywgJ2Nhbm5vdCB3cml0ZSBhIG5vbi1udW1iZXIgYXMgYSBudW1iZXInKVxuICBhc3NlcnQodmFsdWUgPj0gMCwgJ3NwZWNpZmllZCBhIG5lZ2F0aXZlIHZhbHVlIGZvciB3cml0aW5nIGFuIHVuc2lnbmVkIHZhbHVlJylcbiAgYXNzZXJ0KHZhbHVlIDw9IG1heCwgJ3ZhbHVlIGlzIGxhcmdlciB0aGFuIG1heGltdW0gdmFsdWUgZm9yIHR5cGUnKVxuICBhc3NlcnQoTWF0aC5mbG9vcih2YWx1ZSkgPT09IHZhbHVlLCAndmFsdWUgaGFzIGEgZnJhY3Rpb25hbCBjb21wb25lbnQnKVxufVxuXG5mdW5jdGlvbiB2ZXJpZnNpbnQgKHZhbHVlLCBtYXgsIG1pbikge1xuICBhc3NlcnQodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJywgJ2Nhbm5vdCB3cml0ZSBhIG5vbi1udW1iZXIgYXMgYSBudW1iZXInKVxuICBhc3NlcnQodmFsdWUgPD0gbWF4LCAndmFsdWUgbGFyZ2VyIHRoYW4gbWF4aW11bSBhbGxvd2VkIHZhbHVlJylcbiAgYXNzZXJ0KHZhbHVlID49IG1pbiwgJ3ZhbHVlIHNtYWxsZXIgdGhhbiBtaW5pbXVtIGFsbG93ZWQgdmFsdWUnKVxuICBhc3NlcnQoTWF0aC5mbG9vcih2YWx1ZSkgPT09IHZhbHVlLCAndmFsdWUgaGFzIGEgZnJhY3Rpb25hbCBjb21wb25lbnQnKVxufVxuXG5mdW5jdGlvbiB2ZXJpZklFRUU3NTQgKHZhbHVlLCBtYXgsIG1pbikge1xuICBhc3NlcnQodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJywgJ2Nhbm5vdCB3cml0ZSBhIG5vbi1udW1iZXIgYXMgYSBudW1iZXInKVxuICBhc3NlcnQodmFsdWUgPD0gbWF4LCAndmFsdWUgbGFyZ2VyIHRoYW4gbWF4aW11bSBhbGxvd2VkIHZhbHVlJylcbiAgYXNzZXJ0KHZhbHVlID49IG1pbiwgJ3ZhbHVlIHNtYWxsZXIgdGhhbiBtaW5pbXVtIGFsbG93ZWQgdmFsdWUnKVxufVxuXG5mdW5jdGlvbiBhc3NlcnQgKHRlc3QsIG1lc3NhZ2UpIHtcbiAgaWYgKCF0ZXN0KSB0aHJvdyBuZXcgRXJyb3IobWVzc2FnZSB8fCAnRmFpbGVkIGFzc2VydGlvbicpXG59XG4iLCJ2YXIgbG9va3VwID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8nO1xuXG47KGZ1bmN0aW9uIChleHBvcnRzKSB7XG5cdCd1c2Ugc3RyaWN0JztcblxuICB2YXIgQXJyID0gKHR5cGVvZiBVaW50OEFycmF5ICE9PSAndW5kZWZpbmVkJylcbiAgICA/IFVpbnQ4QXJyYXlcbiAgICA6IEFycmF5XG5cblx0dmFyIFBMVVMgICA9ICcrJy5jaGFyQ29kZUF0KDApXG5cdHZhciBTTEFTSCAgPSAnLycuY2hhckNvZGVBdCgwKVxuXHR2YXIgTlVNQkVSID0gJzAnLmNoYXJDb2RlQXQoMClcblx0dmFyIExPV0VSICA9ICdhJy5jaGFyQ29kZUF0KDApXG5cdHZhciBVUFBFUiAgPSAnQScuY2hhckNvZGVBdCgwKVxuXG5cdGZ1bmN0aW9uIGRlY29kZSAoZWx0KSB7XG5cdFx0dmFyIGNvZGUgPSBlbHQuY2hhckNvZGVBdCgwKVxuXHRcdGlmIChjb2RlID09PSBQTFVTKVxuXHRcdFx0cmV0dXJuIDYyIC8vICcrJ1xuXHRcdGlmIChjb2RlID09PSBTTEFTSClcblx0XHRcdHJldHVybiA2MyAvLyAnLydcblx0XHRpZiAoY29kZSA8IE5VTUJFUilcblx0XHRcdHJldHVybiAtMSAvL25vIG1hdGNoXG5cdFx0aWYgKGNvZGUgPCBOVU1CRVIgKyAxMClcblx0XHRcdHJldHVybiBjb2RlIC0gTlVNQkVSICsgMjYgKyAyNlxuXHRcdGlmIChjb2RlIDwgVVBQRVIgKyAyNilcblx0XHRcdHJldHVybiBjb2RlIC0gVVBQRVJcblx0XHRpZiAoY29kZSA8IExPV0VSICsgMjYpXG5cdFx0XHRyZXR1cm4gY29kZSAtIExPV0VSICsgMjZcblx0fVxuXG5cdGZ1bmN0aW9uIGI2NFRvQnl0ZUFycmF5IChiNjQpIHtcblx0XHR2YXIgaSwgaiwgbCwgdG1wLCBwbGFjZUhvbGRlcnMsIGFyclxuXG5cdFx0aWYgKGI2NC5sZW5ndGggJSA0ID4gMCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHN0cmluZy4gTGVuZ3RoIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA0Jylcblx0XHR9XG5cblx0XHQvLyB0aGUgbnVtYmVyIG9mIGVxdWFsIHNpZ25zIChwbGFjZSBob2xkZXJzKVxuXHRcdC8vIGlmIHRoZXJlIGFyZSB0d28gcGxhY2Vob2xkZXJzLCB0aGFuIHRoZSB0d28gY2hhcmFjdGVycyBiZWZvcmUgaXRcblx0XHQvLyByZXByZXNlbnQgb25lIGJ5dGVcblx0XHQvLyBpZiB0aGVyZSBpcyBvbmx5IG9uZSwgdGhlbiB0aGUgdGhyZWUgY2hhcmFjdGVycyBiZWZvcmUgaXQgcmVwcmVzZW50IDIgYnl0ZXNcblx0XHQvLyB0aGlzIGlzIGp1c3QgYSBjaGVhcCBoYWNrIHRvIG5vdCBkbyBpbmRleE9mIHR3aWNlXG5cdFx0dmFyIGxlbiA9IGI2NC5sZW5ndGhcblx0XHRwbGFjZUhvbGRlcnMgPSAnPScgPT09IGI2NC5jaGFyQXQobGVuIC0gMikgPyAyIDogJz0nID09PSBiNjQuY2hhckF0KGxlbiAtIDEpID8gMSA6IDBcblxuXHRcdC8vIGJhc2U2NCBpcyA0LzMgKyB1cCB0byB0d28gY2hhcmFjdGVycyBvZiB0aGUgb3JpZ2luYWwgZGF0YVxuXHRcdGFyciA9IG5ldyBBcnIoYjY0Lmxlbmd0aCAqIDMgLyA0IC0gcGxhY2VIb2xkZXJzKVxuXG5cdFx0Ly8gaWYgdGhlcmUgYXJlIHBsYWNlaG9sZGVycywgb25seSBnZXQgdXAgdG8gdGhlIGxhc3QgY29tcGxldGUgNCBjaGFyc1xuXHRcdGwgPSBwbGFjZUhvbGRlcnMgPiAwID8gYjY0Lmxlbmd0aCAtIDQgOiBiNjQubGVuZ3RoXG5cblx0XHR2YXIgTCA9IDBcblxuXHRcdGZ1bmN0aW9uIHB1c2ggKHYpIHtcblx0XHRcdGFycltMKytdID0gdlxuXHRcdH1cblxuXHRcdGZvciAoaSA9IDAsIGogPSAwOyBpIDwgbDsgaSArPSA0LCBqICs9IDMpIHtcblx0XHRcdHRtcCA9IChkZWNvZGUoYjY0LmNoYXJBdChpKSkgPDwgMTgpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPDwgMTIpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAyKSkgPDwgNikgfCBkZWNvZGUoYjY0LmNoYXJBdChpICsgMykpXG5cdFx0XHRwdXNoKCh0bXAgJiAweEZGMDAwMCkgPj4gMTYpXG5cdFx0XHRwdXNoKCh0bXAgJiAweEZGMDApID4+IDgpXG5cdFx0XHRwdXNoKHRtcCAmIDB4RkYpXG5cdFx0fVxuXG5cdFx0aWYgKHBsYWNlSG9sZGVycyA9PT0gMikge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAyKSB8IChkZWNvZGUoYjY0LmNoYXJBdChpICsgMSkpID4+IDQpXG5cdFx0XHRwdXNoKHRtcCAmIDB4RkYpXG5cdFx0fSBlbHNlIGlmIChwbGFjZUhvbGRlcnMgPT09IDEpIHtcblx0XHRcdHRtcCA9IChkZWNvZGUoYjY0LmNoYXJBdChpKSkgPDwgMTApIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPDwgNCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDIpKSA+PiAyKVxuXHRcdFx0cHVzaCgodG1wID4+IDgpICYgMHhGRilcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9XG5cblx0XHRyZXR1cm4gYXJyXG5cdH1cblxuXHRmdW5jdGlvbiB1aW50OFRvQmFzZTY0ICh1aW50OCkge1xuXHRcdHZhciBpLFxuXHRcdFx0ZXh0cmFCeXRlcyA9IHVpbnQ4Lmxlbmd0aCAlIDMsIC8vIGlmIHdlIGhhdmUgMSBieXRlIGxlZnQsIHBhZCAyIGJ5dGVzXG5cdFx0XHRvdXRwdXQgPSBcIlwiLFxuXHRcdFx0dGVtcCwgbGVuZ3RoXG5cblx0XHRmdW5jdGlvbiBlbmNvZGUgKG51bSkge1xuXHRcdFx0cmV0dXJuIGxvb2t1cC5jaGFyQXQobnVtKVxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHRyaXBsZXRUb0Jhc2U2NCAobnVtKSB7XG5cdFx0XHRyZXR1cm4gZW5jb2RlKG51bSA+PiAxOCAmIDB4M0YpICsgZW5jb2RlKG51bSA+PiAxMiAmIDB4M0YpICsgZW5jb2RlKG51bSA+PiA2ICYgMHgzRikgKyBlbmNvZGUobnVtICYgMHgzRilcblx0XHR9XG5cblx0XHQvLyBnbyB0aHJvdWdoIHRoZSBhcnJheSBldmVyeSB0aHJlZSBieXRlcywgd2UnbGwgZGVhbCB3aXRoIHRyYWlsaW5nIHN0dWZmIGxhdGVyXG5cdFx0Zm9yIChpID0gMCwgbGVuZ3RoID0gdWludDgubGVuZ3RoIC0gZXh0cmFCeXRlczsgaSA8IGxlbmd0aDsgaSArPSAzKSB7XG5cdFx0XHR0ZW1wID0gKHVpbnQ4W2ldIDw8IDE2KSArICh1aW50OFtpICsgMV0gPDwgOCkgKyAodWludDhbaSArIDJdKVxuXHRcdFx0b3V0cHV0ICs9IHRyaXBsZXRUb0Jhc2U2NCh0ZW1wKVxuXHRcdH1cblxuXHRcdC8vIHBhZCB0aGUgZW5kIHdpdGggemVyb3MsIGJ1dCBtYWtlIHN1cmUgdG8gbm90IGZvcmdldCB0aGUgZXh0cmEgYnl0ZXNcblx0XHRzd2l0Y2ggKGV4dHJhQnl0ZXMpIHtcblx0XHRcdGNhc2UgMTpcblx0XHRcdFx0dGVtcCA9IHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDFdXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUodGVtcCA+PiAyKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wIDw8IDQpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9ICc9PSdcblx0XHRcdFx0YnJlYWtcblx0XHRcdGNhc2UgMjpcblx0XHRcdFx0dGVtcCA9ICh1aW50OFt1aW50OC5sZW5ndGggLSAyXSA8PCA4KSArICh1aW50OFt1aW50OC5sZW5ndGggLSAxXSlcblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSh0ZW1wID4+IDEwKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wID4+IDQpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSgodGVtcCA8PCAyKSAmIDB4M0YpXG5cdFx0XHRcdG91dHB1dCArPSAnPSdcblx0XHRcdFx0YnJlYWtcblx0XHR9XG5cblx0XHRyZXR1cm4gb3V0cHV0XG5cdH1cblxuXHRleHBvcnRzLnRvQnl0ZUFycmF5ID0gYjY0VG9CeXRlQXJyYXlcblx0ZXhwb3J0cy5mcm9tQnl0ZUFycmF5ID0gdWludDhUb0Jhc2U2NFxufSh0eXBlb2YgZXhwb3J0cyA9PT0gJ3VuZGVmaW5lZCcgPyAodGhpcy5iYXNlNjRqcyA9IHt9KSA6IGV4cG9ydHMpKVxuIiwiZXhwb3J0cy5yZWFkID0gZnVuY3Rpb24oYnVmZmVyLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbSxcbiAgICAgIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDEsXG4gICAgICBlTWF4ID0gKDEgPDwgZUxlbikgLSAxLFxuICAgICAgZUJpYXMgPSBlTWF4ID4+IDEsXG4gICAgICBuQml0cyA9IC03LFxuICAgICAgaSA9IGlzTEUgPyAobkJ5dGVzIC0gMSkgOiAwLFxuICAgICAgZCA9IGlzTEUgPyAtMSA6IDEsXG4gICAgICBzID0gYnVmZmVyW29mZnNldCArIGldO1xuXG4gIGkgKz0gZDtcblxuICBlID0gcyAmICgoMSA8PCAoLW5CaXRzKSkgLSAxKTtcbiAgcyA+Pj0gKC1uQml0cyk7XG4gIG5CaXRzICs9IGVMZW47XG4gIGZvciAoOyBuQml0cyA+IDA7IGUgPSBlICogMjU2ICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpO1xuXG4gIG0gPSBlICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpO1xuICBlID4+PSAoLW5CaXRzKTtcbiAgbkJpdHMgKz0gbUxlbjtcbiAgZm9yICg7IG5CaXRzID4gMDsgbSA9IG0gKiAyNTYgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCk7XG5cbiAgaWYgKGUgPT09IDApIHtcbiAgICBlID0gMSAtIGVCaWFzO1xuICB9IGVsc2UgaWYgKGUgPT09IGVNYXgpIHtcbiAgICByZXR1cm4gbSA/IE5hTiA6ICgocyA/IC0xIDogMSkgKiBJbmZpbml0eSk7XG4gIH0gZWxzZSB7XG4gICAgbSA9IG0gKyBNYXRoLnBvdygyLCBtTGVuKTtcbiAgICBlID0gZSAtIGVCaWFzO1xuICB9XG4gIHJldHVybiAocyA/IC0xIDogMSkgKiBtICogTWF0aC5wb3coMiwgZSAtIG1MZW4pO1xufTtcblxuZXhwb3J0cy53cml0ZSA9IGZ1bmN0aW9uKGJ1ZmZlciwgdmFsdWUsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLCBjLFxuICAgICAgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMSxcbiAgICAgIGVNYXggPSAoMSA8PCBlTGVuKSAtIDEsXG4gICAgICBlQmlhcyA9IGVNYXggPj4gMSxcbiAgICAgIHJ0ID0gKG1MZW4gPT09IDIzID8gTWF0aC5wb3coMiwgLTI0KSAtIE1hdGgucG93KDIsIC03NykgOiAwKSxcbiAgICAgIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKSxcbiAgICAgIGQgPSBpc0xFID8gMSA6IC0xLFxuICAgICAgcyA9IHZhbHVlIDwgMCB8fCAodmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlIDwgMCkgPyAxIDogMDtcblxuICB2YWx1ZSA9IE1hdGguYWJzKHZhbHVlKTtcblxuICBpZiAoaXNOYU4odmFsdWUpIHx8IHZhbHVlID09PSBJbmZpbml0eSkge1xuICAgIG0gPSBpc05hTih2YWx1ZSkgPyAxIDogMDtcbiAgICBlID0gZU1heDtcbiAgfSBlbHNlIHtcbiAgICBlID0gTWF0aC5mbG9vcihNYXRoLmxvZyh2YWx1ZSkgLyBNYXRoLkxOMik7XG4gICAgaWYgKHZhbHVlICogKGMgPSBNYXRoLnBvdygyLCAtZSkpIDwgMSkge1xuICAgICAgZS0tO1xuICAgICAgYyAqPSAyO1xuICAgIH1cbiAgICBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIHZhbHVlICs9IHJ0IC8gYztcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsdWUgKz0gcnQgKiBNYXRoLnBvdygyLCAxIC0gZUJpYXMpO1xuICAgIH1cbiAgICBpZiAodmFsdWUgKiBjID49IDIpIHtcbiAgICAgIGUrKztcbiAgICAgIGMgLz0gMjtcbiAgICB9XG5cbiAgICBpZiAoZSArIGVCaWFzID49IGVNYXgpIHtcbiAgICAgIG0gPSAwO1xuICAgICAgZSA9IGVNYXg7XG4gICAgfSBlbHNlIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgbSA9ICh2YWx1ZSAqIGMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pO1xuICAgICAgZSA9IGUgKyBlQmlhcztcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IHZhbHVlICogTWF0aC5wb3coMiwgZUJpYXMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pO1xuICAgICAgZSA9IDA7XG4gICAgfVxuICB9XG5cbiAgZm9yICg7IG1MZW4gPj0gODsgYnVmZmVyW29mZnNldCArIGldID0gbSAmIDB4ZmYsIGkgKz0gZCwgbSAvPSAyNTYsIG1MZW4gLT0gOCk7XG5cbiAgZSA9IChlIDw8IG1MZW4pIHwgbTtcbiAgZUxlbiArPSBtTGVuO1xuICBmb3IgKDsgZUxlbiA+IDA7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IGUgJiAweGZmLCBpICs9IGQsIGUgLz0gMjU2LCBlTGVuIC09IDgpO1xuXG4gIGJ1ZmZlcltvZmZzZXQgKyBpIC0gZF0gfD0gcyAqIDEyODtcbn07XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8vIHNoaW0gZm9yIHVzaW5nIHByb2Nlc3MgaW4gYnJvd3NlclxuXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbnByb2Nlc3MubmV4dFRpY2sgPSAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBjYW5TZXRJbW1lZGlhdGUgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJ1xuICAgICYmIHdpbmRvdy5zZXRJbW1lZGlhdGU7XG4gICAgdmFyIGNhblBvc3QgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJ1xuICAgICYmIHdpbmRvdy5wb3N0TWVzc2FnZSAmJiB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lclxuICAgIDtcblxuICAgIGlmIChjYW5TZXRJbW1lZGlhdGUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChmKSB7IHJldHVybiB3aW5kb3cuc2V0SW1tZWRpYXRlKGYpIH07XG4gICAgfVxuXG4gICAgaWYgKGNhblBvc3QpIHtcbiAgICAgICAgdmFyIHF1ZXVlID0gW107XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICB2YXIgc291cmNlID0gZXYuc291cmNlO1xuICAgICAgICAgICAgaWYgKChzb3VyY2UgPT09IHdpbmRvdyB8fCBzb3VyY2UgPT09IG51bGwpICYmIGV2LmRhdGEgPT09ICdwcm9jZXNzLXRpY2snKSB7XG4gICAgICAgICAgICAgICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgaWYgKHF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZuID0gcXVldWUuc2hpZnQoKTtcbiAgICAgICAgICAgICAgICAgICAgZm4oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHRydWUpO1xuXG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBuZXh0VGljayhmbikge1xuICAgICAgICAgICAgcXVldWUucHVzaChmbik7XG4gICAgICAgICAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ3Byb2Nlc3MtdGljaycsICcqJyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGZ1bmN0aW9uIG5leHRUaWNrKGZuKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZm4sIDApO1xuICAgIH07XG59KSgpO1xuXG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn1cblxuLy8gVE9ETyhzaHR5bG1hbilcbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc0J1ZmZlcihhcmcpIHtcbiAgcmV0dXJuIGFyZyAmJiB0eXBlb2YgYXJnID09PSAnb2JqZWN0J1xuICAgICYmIHR5cGVvZiBhcmcuY29weSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcuZmlsbCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcucmVhZFVJbnQ4ID09PSAnZnVuY3Rpb24nO1xufSIsIihmdW5jdGlvbiAocHJvY2VzcyxnbG9iYWwpe1xuLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbnZhciBmb3JtYXRSZWdFeHAgPSAvJVtzZGolXS9nO1xuZXhwb3J0cy5mb3JtYXQgPSBmdW5jdGlvbihmKSB7XG4gIGlmICghaXNTdHJpbmcoZikpIHtcbiAgICB2YXIgb2JqZWN0cyA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBvYmplY3RzLnB1c2goaW5zcGVjdChhcmd1bWVudHNbaV0pKTtcbiAgICB9XG4gICAgcmV0dXJuIG9iamVjdHMuam9pbignICcpO1xuICB9XG5cbiAgdmFyIGkgPSAxO1xuICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgdmFyIGxlbiA9IGFyZ3MubGVuZ3RoO1xuICB2YXIgc3RyID0gU3RyaW5nKGYpLnJlcGxhY2UoZm9ybWF0UmVnRXhwLCBmdW5jdGlvbih4KSB7XG4gICAgaWYgKHggPT09ICclJScpIHJldHVybiAnJSc7XG4gICAgaWYgKGkgPj0gbGVuKSByZXR1cm4geDtcbiAgICBzd2l0Y2ggKHgpIHtcbiAgICAgIGNhc2UgJyVzJzogcmV0dXJuIFN0cmluZyhhcmdzW2krK10pO1xuICAgICAgY2FzZSAnJWQnOiByZXR1cm4gTnVtYmVyKGFyZ3NbaSsrXSk7XG4gICAgICBjYXNlICclaic6XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGFyZ3NbaSsrXSk7XG4gICAgICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgICAgICByZXR1cm4gJ1tDaXJjdWxhcl0nO1xuICAgICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4geDtcbiAgICB9XG4gIH0pO1xuICBmb3IgKHZhciB4ID0gYXJnc1tpXTsgaSA8IGxlbjsgeCA9IGFyZ3NbKytpXSkge1xuICAgIGlmIChpc051bGwoeCkgfHwgIWlzT2JqZWN0KHgpKSB7XG4gICAgICBzdHIgKz0gJyAnICsgeDtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyICs9ICcgJyArIGluc3BlY3QoeCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBzdHI7XG59O1xuXG5cbi8vIE1hcmsgdGhhdCBhIG1ldGhvZCBzaG91bGQgbm90IGJlIHVzZWQuXG4vLyBSZXR1cm5zIGEgbW9kaWZpZWQgZnVuY3Rpb24gd2hpY2ggd2FybnMgb25jZSBieSBkZWZhdWx0LlxuLy8gSWYgLS1uby1kZXByZWNhdGlvbiBpcyBzZXQsIHRoZW4gaXQgaXMgYSBuby1vcC5cbmV4cG9ydHMuZGVwcmVjYXRlID0gZnVuY3Rpb24oZm4sIG1zZykge1xuICAvLyBBbGxvdyBmb3IgZGVwcmVjYXRpbmcgdGhpbmdzIGluIHRoZSBwcm9jZXNzIG9mIHN0YXJ0aW5nIHVwLlxuICBpZiAoaXNVbmRlZmluZWQoZ2xvYmFsLnByb2Nlc3MpKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGV4cG9ydHMuZGVwcmVjYXRlKGZuLCBtc2cpLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfVxuXG4gIGlmIChwcm9jZXNzLm5vRGVwcmVjYXRpb24gPT09IHRydWUpIHtcbiAgICByZXR1cm4gZm47XG4gIH1cblxuICB2YXIgd2FybmVkID0gZmFsc2U7XG4gIGZ1bmN0aW9uIGRlcHJlY2F0ZWQoKSB7XG4gICAgaWYgKCF3YXJuZWQpIHtcbiAgICAgIGlmIChwcm9jZXNzLnRocm93RGVwcmVjYXRpb24pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7XG4gICAgICB9IGVsc2UgaWYgKHByb2Nlc3MudHJhY2VEZXByZWNhdGlvbikge1xuICAgICAgICBjb25zb2xlLnRyYWNlKG1zZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLmVycm9yKG1zZyk7XG4gICAgICB9XG4gICAgICB3YXJuZWQgPSB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIHJldHVybiBkZXByZWNhdGVkO1xufTtcblxuXG52YXIgZGVidWdzID0ge307XG52YXIgZGVidWdFbnZpcm9uO1xuZXhwb3J0cy5kZWJ1Z2xvZyA9IGZ1bmN0aW9uKHNldCkge1xuICBpZiAoaXNVbmRlZmluZWQoZGVidWdFbnZpcm9uKSlcbiAgICBkZWJ1Z0Vudmlyb24gPSBwcm9jZXNzLmVudi5OT0RFX0RFQlVHIHx8ICcnO1xuICBzZXQgPSBzZXQudG9VcHBlckNhc2UoKTtcbiAgaWYgKCFkZWJ1Z3Nbc2V0XSkge1xuICAgIGlmIChuZXcgUmVnRXhwKCdcXFxcYicgKyBzZXQgKyAnXFxcXGInLCAnaScpLnRlc3QoZGVidWdFbnZpcm9uKSkge1xuICAgICAgdmFyIHBpZCA9IHByb2Nlc3MucGlkO1xuICAgICAgZGVidWdzW3NldF0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG1zZyA9IGV4cG9ydHMuZm9ybWF0LmFwcGx5KGV4cG9ydHMsIGFyZ3VtZW50cyk7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJyVzICVkOiAlcycsIHNldCwgcGlkLCBtc2cpO1xuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVidWdzW3NldF0gPSBmdW5jdGlvbigpIHt9O1xuICAgIH1cbiAgfVxuICByZXR1cm4gZGVidWdzW3NldF07XG59O1xuXG5cbi8qKlxuICogRWNob3MgdGhlIHZhbHVlIG9mIGEgdmFsdWUuIFRyeXMgdG8gcHJpbnQgdGhlIHZhbHVlIG91dFxuICogaW4gdGhlIGJlc3Qgd2F5IHBvc3NpYmxlIGdpdmVuIHRoZSBkaWZmZXJlbnQgdHlwZXMuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIHByaW50IG91dC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIE9wdGlvbmFsIG9wdGlvbnMgb2JqZWN0IHRoYXQgYWx0ZXJzIHRoZSBvdXRwdXQuXG4gKi9cbi8qIGxlZ2FjeTogb2JqLCBzaG93SGlkZGVuLCBkZXB0aCwgY29sb3JzKi9cbmZ1bmN0aW9uIGluc3BlY3Qob2JqLCBvcHRzKSB7XG4gIC8vIGRlZmF1bHQgb3B0aW9uc1xuICB2YXIgY3R4ID0ge1xuICAgIHNlZW46IFtdLFxuICAgIHN0eWxpemU6IHN0eWxpemVOb0NvbG9yXG4gIH07XG4gIC8vIGxlZ2FjeS4uLlxuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+PSAzKSBjdHguZGVwdGggPSBhcmd1bWVudHNbMl07XG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID49IDQpIGN0eC5jb2xvcnMgPSBhcmd1bWVudHNbM107XG4gIGlmIChpc0Jvb2xlYW4ob3B0cykpIHtcbiAgICAvLyBsZWdhY3kuLi5cbiAgICBjdHguc2hvd0hpZGRlbiA9IG9wdHM7XG4gIH0gZWxzZSBpZiAob3B0cykge1xuICAgIC8vIGdvdCBhbiBcIm9wdGlvbnNcIiBvYmplY3RcbiAgICBleHBvcnRzLl9leHRlbmQoY3R4LCBvcHRzKTtcbiAgfVxuICAvLyBzZXQgZGVmYXVsdCBvcHRpb25zXG4gIGlmIChpc1VuZGVmaW5lZChjdHguc2hvd0hpZGRlbikpIGN0eC5zaG93SGlkZGVuID0gZmFsc2U7XG4gIGlmIChpc1VuZGVmaW5lZChjdHguZGVwdGgpKSBjdHguZGVwdGggPSAyO1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LmNvbG9ycykpIGN0eC5jb2xvcnMgPSBmYWxzZTtcbiAgaWYgKGlzVW5kZWZpbmVkKGN0eC5jdXN0b21JbnNwZWN0KSkgY3R4LmN1c3RvbUluc3BlY3QgPSB0cnVlO1xuICBpZiAoY3R4LmNvbG9ycykgY3R4LnN0eWxpemUgPSBzdHlsaXplV2l0aENvbG9yO1xuICByZXR1cm4gZm9ybWF0VmFsdWUoY3R4LCBvYmosIGN0eC5kZXB0aCk7XG59XG5leHBvcnRzLmluc3BlY3QgPSBpbnNwZWN0O1xuXG5cbi8vIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQU5TSV9lc2NhcGVfY29kZSNncmFwaGljc1xuaW5zcGVjdC5jb2xvcnMgPSB7XG4gICdib2xkJyA6IFsxLCAyMl0sXG4gICdpdGFsaWMnIDogWzMsIDIzXSxcbiAgJ3VuZGVybGluZScgOiBbNCwgMjRdLFxuICAnaW52ZXJzZScgOiBbNywgMjddLFxuICAnd2hpdGUnIDogWzM3LCAzOV0sXG4gICdncmV5JyA6IFs5MCwgMzldLFxuICAnYmxhY2snIDogWzMwLCAzOV0sXG4gICdibHVlJyA6IFszNCwgMzldLFxuICAnY3lhbicgOiBbMzYsIDM5XSxcbiAgJ2dyZWVuJyA6IFszMiwgMzldLFxuICAnbWFnZW50YScgOiBbMzUsIDM5XSxcbiAgJ3JlZCcgOiBbMzEsIDM5XSxcbiAgJ3llbGxvdycgOiBbMzMsIDM5XVxufTtcblxuLy8gRG9uJ3QgdXNlICdibHVlJyBub3QgdmlzaWJsZSBvbiBjbWQuZXhlXG5pbnNwZWN0LnN0eWxlcyA9IHtcbiAgJ3NwZWNpYWwnOiAnY3lhbicsXG4gICdudW1iZXInOiAneWVsbG93JyxcbiAgJ2Jvb2xlYW4nOiAneWVsbG93JyxcbiAgJ3VuZGVmaW5lZCc6ICdncmV5JyxcbiAgJ251bGwnOiAnYm9sZCcsXG4gICdzdHJpbmcnOiAnZ3JlZW4nLFxuICAnZGF0ZSc6ICdtYWdlbnRhJyxcbiAgLy8gXCJuYW1lXCI6IGludGVudGlvbmFsbHkgbm90IHN0eWxpbmdcbiAgJ3JlZ2V4cCc6ICdyZWQnXG59O1xuXG5cbmZ1bmN0aW9uIHN0eWxpemVXaXRoQ29sb3Ioc3RyLCBzdHlsZVR5cGUpIHtcbiAgdmFyIHN0eWxlID0gaW5zcGVjdC5zdHlsZXNbc3R5bGVUeXBlXTtcblxuICBpZiAoc3R5bGUpIHtcbiAgICByZXR1cm4gJ1xcdTAwMWJbJyArIGluc3BlY3QuY29sb3JzW3N0eWxlXVswXSArICdtJyArIHN0ciArXG4gICAgICAgICAgICdcXHUwMDFiWycgKyBpbnNwZWN0LmNvbG9yc1tzdHlsZV1bMV0gKyAnbSc7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHN0cjtcbiAgfVxufVxuXG5cbmZ1bmN0aW9uIHN0eWxpemVOb0NvbG9yKHN0ciwgc3R5bGVUeXBlKSB7XG4gIHJldHVybiBzdHI7XG59XG5cblxuZnVuY3Rpb24gYXJyYXlUb0hhc2goYXJyYXkpIHtcbiAgdmFyIGhhc2ggPSB7fTtcblxuICBhcnJheS5mb3JFYWNoKGZ1bmN0aW9uKHZhbCwgaWR4KSB7XG4gICAgaGFzaFt2YWxdID0gdHJ1ZTtcbiAgfSk7XG5cbiAgcmV0dXJuIGhhc2g7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0VmFsdWUoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzKSB7XG4gIC8vIFByb3ZpZGUgYSBob29rIGZvciB1c2VyLXNwZWNpZmllZCBpbnNwZWN0IGZ1bmN0aW9ucy5cbiAgLy8gQ2hlY2sgdGhhdCB2YWx1ZSBpcyBhbiBvYmplY3Qgd2l0aCBhbiBpbnNwZWN0IGZ1bmN0aW9uIG9uIGl0XG4gIGlmIChjdHguY3VzdG9tSW5zcGVjdCAmJlxuICAgICAgdmFsdWUgJiZcbiAgICAgIGlzRnVuY3Rpb24odmFsdWUuaW5zcGVjdCkgJiZcbiAgICAgIC8vIEZpbHRlciBvdXQgdGhlIHV0aWwgbW9kdWxlLCBpdCdzIGluc3BlY3QgZnVuY3Rpb24gaXMgc3BlY2lhbFxuICAgICAgdmFsdWUuaW5zcGVjdCAhPT0gZXhwb3J0cy5pbnNwZWN0ICYmXG4gICAgICAvLyBBbHNvIGZpbHRlciBvdXQgYW55IHByb3RvdHlwZSBvYmplY3RzIHVzaW5nIHRoZSBjaXJjdWxhciBjaGVjay5cbiAgICAgICEodmFsdWUuY29uc3RydWN0b3IgJiYgdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlID09PSB2YWx1ZSkpIHtcbiAgICB2YXIgcmV0ID0gdmFsdWUuaW5zcGVjdChyZWN1cnNlVGltZXMsIGN0eCk7XG4gICAgaWYgKCFpc1N0cmluZyhyZXQpKSB7XG4gICAgICByZXQgPSBmb3JtYXRWYWx1ZShjdHgsIHJldCwgcmVjdXJzZVRpbWVzKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIC8vIFByaW1pdGl2ZSB0eXBlcyBjYW5ub3QgaGF2ZSBwcm9wZXJ0aWVzXG4gIHZhciBwcmltaXRpdmUgPSBmb3JtYXRQcmltaXRpdmUoY3R4LCB2YWx1ZSk7XG4gIGlmIChwcmltaXRpdmUpIHtcbiAgICByZXR1cm4gcHJpbWl0aXZlO1xuICB9XG5cbiAgLy8gTG9vayB1cCB0aGUga2V5cyBvZiB0aGUgb2JqZWN0LlxuICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHZhbHVlKTtcbiAgdmFyIHZpc2libGVLZXlzID0gYXJyYXlUb0hhc2goa2V5cyk7XG5cbiAgaWYgKGN0eC5zaG93SGlkZGVuKSB7XG4gICAga2V5cyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHZhbHVlKTtcbiAgfVxuXG4gIC8vIElFIGRvZXNuJ3QgbWFrZSBlcnJvciBmaWVsZHMgbm9uLWVudW1lcmFibGVcbiAgLy8gaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L2llL2R3dzUyc2J0KHY9dnMuOTQpLmFzcHhcbiAgaWYgKGlzRXJyb3IodmFsdWUpXG4gICAgICAmJiAoa2V5cy5pbmRleE9mKCdtZXNzYWdlJykgPj0gMCB8fCBrZXlzLmluZGV4T2YoJ2Rlc2NyaXB0aW9uJykgPj0gMCkpIHtcbiAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICB9XG5cbiAgLy8gU29tZSB0eXBlIG9mIG9iamVjdCB3aXRob3V0IHByb3BlcnRpZXMgY2FuIGJlIHNob3J0Y3V0dGVkLlxuICBpZiAoa2V5cy5sZW5ndGggPT09IDApIHtcbiAgICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICAgIHZhciBuYW1lID0gdmFsdWUubmFtZSA/ICc6ICcgKyB2YWx1ZS5uYW1lIDogJyc7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJ1tGdW5jdGlvbicgKyBuYW1lICsgJ10nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgICBpZiAoaXNSZWdFeHAodmFsdWUpKSB7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoUmVnRXhwLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSwgJ3JlZ2V4cCcpO1xuICAgIH1cbiAgICBpZiAoaXNEYXRlKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKERhdGUucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAnZGF0ZScpO1xuICAgIH1cbiAgICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBmb3JtYXRFcnJvcih2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgdmFyIGJhc2UgPSAnJywgYXJyYXkgPSBmYWxzZSwgYnJhY2VzID0gWyd7JywgJ30nXTtcblxuICAvLyBNYWtlIEFycmF5IHNheSB0aGF0IHRoZXkgYXJlIEFycmF5XG4gIGlmIChpc0FycmF5KHZhbHVlKSkge1xuICAgIGFycmF5ID0gdHJ1ZTtcbiAgICBicmFjZXMgPSBbJ1snLCAnXSddO1xuICB9XG5cbiAgLy8gTWFrZSBmdW5jdGlvbnMgc2F5IHRoYXQgdGhleSBhcmUgZnVuY3Rpb25zXG4gIGlmIChpc0Z1bmN0aW9uKHZhbHVlKSkge1xuICAgIHZhciBuID0gdmFsdWUubmFtZSA/ICc6ICcgKyB2YWx1ZS5uYW1lIDogJyc7XG4gICAgYmFzZSA9ICcgW0Z1bmN0aW9uJyArIG4gKyAnXSc7XG4gIH1cblxuICAvLyBNYWtlIFJlZ0V4cHMgc2F5IHRoYXQgdGhleSBhcmUgUmVnRXhwc1xuICBpZiAoaXNSZWdFeHAodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gIH1cblxuICAvLyBNYWtlIGRhdGVzIHdpdGggcHJvcGVydGllcyBmaXJzdCBzYXkgdGhlIGRhdGVcbiAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICBiYXNlID0gJyAnICsgRGF0ZS5wcm90b3R5cGUudG9VVENTdHJpbmcuY2FsbCh2YWx1ZSk7XG4gIH1cblxuICAvLyBNYWtlIGVycm9yIHdpdGggbWVzc2FnZSBmaXJzdCBzYXkgdGhlIGVycm9yXG4gIGlmIChpc0Vycm9yKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBmb3JtYXRFcnJvcih2YWx1ZSk7XG4gIH1cblxuICBpZiAoa2V5cy5sZW5ndGggPT09IDAgJiYgKCFhcnJheSB8fCB2YWx1ZS5sZW5ndGggPT0gMCkpIHtcbiAgICByZXR1cm4gYnJhY2VzWzBdICsgYmFzZSArIGJyYWNlc1sxXTtcbiAgfVxuXG4gIGlmIChyZWN1cnNlVGltZXMgPCAwKSB7XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbT2JqZWN0XScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9XG5cbiAgY3R4LnNlZW4ucHVzaCh2YWx1ZSk7XG5cbiAgdmFyIG91dHB1dDtcbiAgaWYgKGFycmF5KSB7XG4gICAgb3V0cHV0ID0gZm9ybWF0QXJyYXkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5cyk7XG4gIH0gZWxzZSB7XG4gICAgb3V0cHV0ID0ga2V5cy5tYXAoZnVuY3Rpb24oa2V5KSB7XG4gICAgICByZXR1cm4gZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5LCBhcnJheSk7XG4gICAgfSk7XG4gIH1cblxuICBjdHguc2Vlbi5wb3AoKTtcblxuICByZXR1cm4gcmVkdWNlVG9TaW5nbGVTdHJpbmcob3V0cHV0LCBiYXNlLCBicmFjZXMpO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFByaW1pdGl2ZShjdHgsIHZhbHVlKSB7XG4gIGlmIChpc1VuZGVmaW5lZCh2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCd1bmRlZmluZWQnLCAndW5kZWZpbmVkJyk7XG4gIGlmIChpc1N0cmluZyh2YWx1ZSkpIHtcbiAgICB2YXIgc2ltcGxlID0gJ1xcJycgKyBKU09OLnN0cmluZ2lmeSh2YWx1ZSkucmVwbGFjZSgvXlwifFwiJC9nLCAnJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKC8nL2csIFwiXFxcXCdcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXCIvZywgJ1wiJykgKyAnXFwnJztcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoc2ltcGxlLCAnc3RyaW5nJyk7XG4gIH1cbiAgaWYgKGlzTnVtYmVyKHZhbHVlKSlcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoJycgKyB2YWx1ZSwgJ251bWJlcicpO1xuICBpZiAoaXNCb29sZWFuKHZhbHVlKSlcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoJycgKyB2YWx1ZSwgJ2Jvb2xlYW4nKTtcbiAgLy8gRm9yIHNvbWUgcmVhc29uIHR5cGVvZiBudWxsIGlzIFwib2JqZWN0XCIsIHNvIHNwZWNpYWwgY2FzZSBoZXJlLlxuICBpZiAoaXNOdWxsKHZhbHVlKSlcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoJ251bGwnLCAnbnVsbCcpO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEVycm9yKHZhbHVlKSB7XG4gIHJldHVybiAnWycgKyBFcnJvci5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgKyAnXSc7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0QXJyYXkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5cykge1xuICB2YXIgb3V0cHV0ID0gW107XG4gIGZvciAodmFyIGkgPSAwLCBsID0gdmFsdWUubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgaWYgKGhhc093blByb3BlcnR5KHZhbHVlLCBTdHJpbmcoaSkpKSB7XG4gICAgICBvdXRwdXQucHVzaChmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLFxuICAgICAgICAgIFN0cmluZyhpKSwgdHJ1ZSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBvdXRwdXQucHVzaCgnJyk7XG4gICAgfVxuICB9XG4gIGtleXMuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICBpZiAoIWtleS5tYXRjaCgvXlxcZCskLykpIHtcbiAgICAgIG91dHB1dC5wdXNoKGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsXG4gICAgICAgICAga2V5LCB0cnVlKSk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIG91dHB1dDtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLCBrZXksIGFycmF5KSB7XG4gIHZhciBuYW1lLCBzdHIsIGRlc2M7XG4gIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHZhbHVlLCBrZXkpIHx8IHsgdmFsdWU6IHZhbHVlW2tleV0gfTtcbiAgaWYgKGRlc2MuZ2V0KSB7XG4gICAgaWYgKGRlc2Muc2V0KSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW0dldHRlci9TZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKGRlc2Muc2V0KSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW1NldHRlcl0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuICBpZiAoIWhhc093blByb3BlcnR5KHZpc2libGVLZXlzLCBrZXkpKSB7XG4gICAgbmFtZSA9ICdbJyArIGtleSArICddJztcbiAgfVxuICBpZiAoIXN0cikge1xuICAgIGlmIChjdHguc2Vlbi5pbmRleE9mKGRlc2MudmFsdWUpIDwgMCkge1xuICAgICAgaWYgKGlzTnVsbChyZWN1cnNlVGltZXMpKSB7XG4gICAgICAgIHN0ciA9IGZvcm1hdFZhbHVlKGN0eCwgZGVzYy52YWx1ZSwgbnVsbCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdHIgPSBmb3JtYXRWYWx1ZShjdHgsIGRlc2MudmFsdWUsIHJlY3Vyc2VUaW1lcyAtIDEpO1xuICAgICAgfVxuICAgICAgaWYgKHN0ci5pbmRleE9mKCdcXG4nKSA+IC0xKSB7XG4gICAgICAgIGlmIChhcnJheSkge1xuICAgICAgICAgIHN0ciA9IHN0ci5zcGxpdCgnXFxuJykubWFwKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgICAgICAgIHJldHVybiAnICAnICsgbGluZTtcbiAgICAgICAgICB9KS5qb2luKCdcXG4nKS5zdWJzdHIoMik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc3RyID0gJ1xcbicgKyBzdHIuc3BsaXQoJ1xcbicpLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICByZXR1cm4gJyAgICcgKyBsaW5lO1xuICAgICAgICAgIH0pLmpvaW4oJ1xcbicpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbQ2lyY3VsYXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH1cbiAgaWYgKGlzVW5kZWZpbmVkKG5hbWUpKSB7XG4gICAgaWYgKGFycmF5ICYmIGtleS5tYXRjaCgvXlxcZCskLykpIHtcbiAgICAgIHJldHVybiBzdHI7XG4gICAgfVxuICAgIG5hbWUgPSBKU09OLnN0cmluZ2lmeSgnJyArIGtleSk7XG4gICAgaWYgKG5hbWUubWF0Y2goL15cIihbYS16QS1aX11bYS16QS1aXzAtOV0qKVwiJC8pKSB7XG4gICAgICBuYW1lID0gbmFtZS5zdWJzdHIoMSwgbmFtZS5sZW5ndGggLSAyKTtcbiAgICAgIG5hbWUgPSBjdHguc3R5bGl6ZShuYW1lLCAnbmFtZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuYW1lID0gbmFtZS5yZXBsYWNlKC8nL2csIFwiXFxcXCdcIilcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcXFxcIi9nLCAnXCInKVxuICAgICAgICAgICAgICAgICAucmVwbGFjZSgvKF5cInxcIiQpL2csIFwiJ1wiKTtcbiAgICAgIG5hbWUgPSBjdHguc3R5bGl6ZShuYW1lLCAnc3RyaW5nJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5hbWUgKyAnOiAnICsgc3RyO1xufVxuXG5cbmZ1bmN0aW9uIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKSB7XG4gIHZhciBudW1MaW5lc0VzdCA9IDA7XG4gIHZhciBsZW5ndGggPSBvdXRwdXQucmVkdWNlKGZ1bmN0aW9uKHByZXYsIGN1cikge1xuICAgIG51bUxpbmVzRXN0Kys7XG4gICAgaWYgKGN1ci5pbmRleE9mKCdcXG4nKSA+PSAwKSBudW1MaW5lc0VzdCsrO1xuICAgIHJldHVybiBwcmV2ICsgY3VyLnJlcGxhY2UoL1xcdTAwMWJcXFtcXGRcXGQ/bS9nLCAnJykubGVuZ3RoICsgMTtcbiAgfSwgMCk7XG5cbiAgaWYgKGxlbmd0aCA+IDYwKSB7XG4gICAgcmV0dXJuIGJyYWNlc1swXSArXG4gICAgICAgICAgIChiYXNlID09PSAnJyA/ICcnIDogYmFzZSArICdcXG4gJykgK1xuICAgICAgICAgICAnICcgK1xuICAgICAgICAgICBvdXRwdXQuam9pbignLFxcbiAgJykgK1xuICAgICAgICAgICAnICcgK1xuICAgICAgICAgICBicmFjZXNbMV07XG4gIH1cblxuICByZXR1cm4gYnJhY2VzWzBdICsgYmFzZSArICcgJyArIG91dHB1dC5qb2luKCcsICcpICsgJyAnICsgYnJhY2VzWzFdO1xufVxuXG5cbi8vIE5PVEU6IFRoZXNlIHR5cGUgY2hlY2tpbmcgZnVuY3Rpb25zIGludGVudGlvbmFsbHkgZG9uJ3QgdXNlIGBpbnN0YW5jZW9mYFxuLy8gYmVjYXVzZSBpdCBpcyBmcmFnaWxlIGFuZCBjYW4gYmUgZWFzaWx5IGZha2VkIHdpdGggYE9iamVjdC5jcmVhdGUoKWAuXG5mdW5jdGlvbiBpc0FycmF5KGFyKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KGFyKTtcbn1cbmV4cG9ydHMuaXNBcnJheSA9IGlzQXJyYXk7XG5cbmZ1bmN0aW9uIGlzQm9vbGVhbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdib29sZWFuJztcbn1cbmV4cG9ydHMuaXNCb29sZWFuID0gaXNCb29sZWFuO1xuXG5mdW5jdGlvbiBpc051bGwoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IG51bGw7XG59XG5leHBvcnRzLmlzTnVsbCA9IGlzTnVsbDtcblxuZnVuY3Rpb24gaXNOdWxsT3JVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT0gbnVsbDtcbn1cbmV4cG9ydHMuaXNOdWxsT3JVbmRlZmluZWQgPSBpc051bGxPclVuZGVmaW5lZDtcblxuZnVuY3Rpb24gaXNOdW1iZXIoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnbnVtYmVyJztcbn1cbmV4cG9ydHMuaXNOdW1iZXIgPSBpc051bWJlcjtcblxuZnVuY3Rpb24gaXNTdHJpbmcoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnc3RyaW5nJztcbn1cbmV4cG9ydHMuaXNTdHJpbmcgPSBpc1N0cmluZztcblxuZnVuY3Rpb24gaXNTeW1ib2woYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnc3ltYm9sJztcbn1cbmV4cG9ydHMuaXNTeW1ib2wgPSBpc1N5bWJvbDtcblxuZnVuY3Rpb24gaXNVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IHZvaWQgMDtcbn1cbmV4cG9ydHMuaXNVbmRlZmluZWQgPSBpc1VuZGVmaW5lZDtcblxuZnVuY3Rpb24gaXNSZWdFeHAocmUpIHtcbiAgcmV0dXJuIGlzT2JqZWN0KHJlKSAmJiBvYmplY3RUb1N0cmluZyhyZSkgPT09ICdbb2JqZWN0IFJlZ0V4cF0nO1xufVxuZXhwb3J0cy5pc1JlZ0V4cCA9IGlzUmVnRXhwO1xuXG5mdW5jdGlvbiBpc09iamVjdChhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdvYmplY3QnICYmIGFyZyAhPT0gbnVsbDtcbn1cbmV4cG9ydHMuaXNPYmplY3QgPSBpc09iamVjdDtcblxuZnVuY3Rpb24gaXNEYXRlKGQpIHtcbiAgcmV0dXJuIGlzT2JqZWN0KGQpICYmIG9iamVjdFRvU3RyaW5nKGQpID09PSAnW29iamVjdCBEYXRlXSc7XG59XG5leHBvcnRzLmlzRGF0ZSA9IGlzRGF0ZTtcblxuZnVuY3Rpb24gaXNFcnJvcihlKSB7XG4gIHJldHVybiBpc09iamVjdChlKSAmJlxuICAgICAgKG9iamVjdFRvU3RyaW5nKGUpID09PSAnW29iamVjdCBFcnJvcl0nIHx8IGUgaW5zdGFuY2VvZiBFcnJvcik7XG59XG5leHBvcnRzLmlzRXJyb3IgPSBpc0Vycm9yO1xuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ2Z1bmN0aW9uJztcbn1cbmV4cG9ydHMuaXNGdW5jdGlvbiA9IGlzRnVuY3Rpb247XG5cbmZ1bmN0aW9uIGlzUHJpbWl0aXZlKGFyZykge1xuICByZXR1cm4gYXJnID09PSBudWxsIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnYm9vbGVhbicgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdudW1iZXInIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnc3RyaW5nJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcgfHwgIC8vIEVTNiBzeW1ib2xcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICd1bmRlZmluZWQnO1xufVxuZXhwb3J0cy5pc1ByaW1pdGl2ZSA9IGlzUHJpbWl0aXZlO1xuXG5leHBvcnRzLmlzQnVmZmVyID0gcmVxdWlyZSgnLi9zdXBwb3J0L2lzQnVmZmVyJyk7XG5cbmZ1bmN0aW9uIG9iamVjdFRvU3RyaW5nKG8pIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTtcbn1cblxuXG5mdW5jdGlvbiBwYWQobikge1xuICByZXR1cm4gbiA8IDEwID8gJzAnICsgbi50b1N0cmluZygxMCkgOiBuLnRvU3RyaW5nKDEwKTtcbn1cblxuXG52YXIgbW9udGhzID0gWydKYW4nLCAnRmViJywgJ01hcicsICdBcHInLCAnTWF5JywgJ0p1bicsICdKdWwnLCAnQXVnJywgJ1NlcCcsXG4gICAgICAgICAgICAgICdPY3QnLCAnTm92JywgJ0RlYyddO1xuXG4vLyAyNiBGZWIgMTY6MTk6MzRcbmZ1bmN0aW9uIHRpbWVzdGFtcCgpIHtcbiAgdmFyIGQgPSBuZXcgRGF0ZSgpO1xuICB2YXIgdGltZSA9IFtwYWQoZC5nZXRIb3VycygpKSxcbiAgICAgICAgICAgICAgcGFkKGQuZ2V0TWludXRlcygpKSxcbiAgICAgICAgICAgICAgcGFkKGQuZ2V0U2Vjb25kcygpKV0uam9pbignOicpO1xuICByZXR1cm4gW2QuZ2V0RGF0ZSgpLCBtb250aHNbZC5nZXRNb250aCgpXSwgdGltZV0uam9pbignICcpO1xufVxuXG5cbi8vIGxvZyBpcyBqdXN0IGEgdGhpbiB3cmFwcGVyIHRvIGNvbnNvbGUubG9nIHRoYXQgcHJlcGVuZHMgYSB0aW1lc3RhbXBcbmV4cG9ydHMubG9nID0gZnVuY3Rpb24oKSB7XG4gIGNvbnNvbGUubG9nKCclcyAtICVzJywgdGltZXN0YW1wKCksIGV4cG9ydHMuZm9ybWF0LmFwcGx5KGV4cG9ydHMsIGFyZ3VtZW50cykpO1xufTtcblxuXG4vKipcbiAqIEluaGVyaXQgdGhlIHByb3RvdHlwZSBtZXRob2RzIGZyb20gb25lIGNvbnN0cnVjdG9yIGludG8gYW5vdGhlci5cbiAqXG4gKiBUaGUgRnVuY3Rpb24ucHJvdG90eXBlLmluaGVyaXRzIGZyb20gbGFuZy5qcyByZXdyaXR0ZW4gYXMgYSBzdGFuZGFsb25lXG4gKiBmdW5jdGlvbiAobm90IG9uIEZ1bmN0aW9uLnByb3RvdHlwZSkuIE5PVEU6IElmIHRoaXMgZmlsZSBpcyB0byBiZSBsb2FkZWRcbiAqIGR1cmluZyBib290c3RyYXBwaW5nIHRoaXMgZnVuY3Rpb24gbmVlZHMgdG8gYmUgcmV3cml0dGVuIHVzaW5nIHNvbWUgbmF0aXZlXG4gKiBmdW5jdGlvbnMgYXMgcHJvdG90eXBlIHNldHVwIHVzaW5nIG5vcm1hbCBKYXZhU2NyaXB0IGRvZXMgbm90IHdvcmsgYXNcbiAqIGV4cGVjdGVkIGR1cmluZyBib290c3RyYXBwaW5nIChzZWUgbWlycm9yLmpzIGluIHIxMTQ5MDMpLlxuICpcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGN0b3IgQ29uc3RydWN0b3IgZnVuY3Rpb24gd2hpY2ggbmVlZHMgdG8gaW5oZXJpdCB0aGVcbiAqICAgICBwcm90b3R5cGUuXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBzdXBlckN0b3IgQ29uc3RydWN0b3IgZnVuY3Rpb24gdG8gaW5oZXJpdCBwcm90b3R5cGUgZnJvbS5cbiAqL1xuZXhwb3J0cy5pbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbmV4cG9ydHMuX2V4dGVuZCA9IGZ1bmN0aW9uKG9yaWdpbiwgYWRkKSB7XG4gIC8vIERvbid0IGRvIGFueXRoaW5nIGlmIGFkZCBpc24ndCBhbiBvYmplY3RcbiAgaWYgKCFhZGQgfHwgIWlzT2JqZWN0KGFkZCkpIHJldHVybiBvcmlnaW47XG5cbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhhZGQpO1xuICB2YXIgaSA9IGtleXMubGVuZ3RoO1xuICB3aGlsZSAoaS0tKSB7XG4gICAgb3JpZ2luW2tleXNbaV1dID0gYWRkW2tleXNbaV1dO1xuICB9XG4gIHJldHVybiBvcmlnaW47XG59O1xuXG5mdW5jdGlvbiBoYXNPd25Qcm9wZXJ0eShvYmosIHByb3ApIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApO1xufVxuXG59KS5jYWxsKHRoaXMscmVxdWlyZShcIjFZaVo1U1wiKSx0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pIiwiKGZ1bmN0aW9uIChzaW5vbkNoYWkpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIC8vIE1vZHVsZSBzeXN0ZW1zIG1hZ2ljIGRhbmNlLlxuXG4gICAgaWYgKHR5cGVvZiByZXF1aXJlID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGV4cG9ydHMgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAvLyBOb2RlSlNcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBzaW5vbkNoYWk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICAvLyBBTURcbiAgICAgICAgZGVmaW5lKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBzaW5vbkNoYWk7XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIE90aGVyIGVudmlyb25tZW50ICh1c3VhbGx5IDxzY3JpcHQ+IHRhZyk6IHBsdWcgaW4gdG8gZ2xvYmFsIGNoYWkgaW5zdGFuY2UgZGlyZWN0bHkuXG4gICAgICAgIGNoYWkudXNlKHNpbm9uQ2hhaSk7XG4gICAgfVxufShmdW5jdGlvbiBzaW5vbkNoYWkoY2hhaSwgdXRpbHMpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIHZhciBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcblxuICAgIGZ1bmN0aW9uIGlzU3B5KHB1dGF0aXZlU3B5KSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgcHV0YXRpdmVTcHkgPT09IFwiZnVuY3Rpb25cIiAmJlxuICAgICAgICAgICAgICAgdHlwZW9mIHB1dGF0aXZlU3B5LmdldENhbGwgPT09IFwiZnVuY3Rpb25cIiAmJlxuICAgICAgICAgICAgICAgdHlwZW9mIHB1dGF0aXZlU3B5LmNhbGxlZFdpdGhFeGFjdGx5ID09PSBcImZ1bmN0aW9uXCI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdGltZXNJbldvcmRzKGNvdW50KSB7XG4gICAgICAgIHJldHVybiBjb3VudCA9PT0gMSA/IFwib25jZVwiIDpcbiAgICAgICAgICAgICAgIGNvdW50ID09PSAyID8gXCJ0d2ljZVwiIDpcbiAgICAgICAgICAgICAgIGNvdW50ID09PSAzID8gXCJ0aHJpY2VcIiA6XG4gICAgICAgICAgICAgICAoY291bnQgfHwgMCkgKyBcIiB0aW1lc1wiO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzQ2FsbChwdXRhdGl2ZUNhbGwpIHtcbiAgICAgICAgcmV0dXJuIHB1dGF0aXZlQ2FsbCAmJiBpc1NweShwdXRhdGl2ZUNhbGwucHJveHkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFzc2VydENhbldvcmtXaXRoKGFzc2VydGlvbikge1xuICAgICAgICBpZiAoIWlzU3B5KGFzc2VydGlvbi5fb2JqKSAmJiAhaXNDYWxsKGFzc2VydGlvbi5fb2JqKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcih1dGlscy5pbnNwZWN0KGFzc2VydGlvbi5fb2JqKSArIFwiIGlzIG5vdCBhIHNweSBvciBhIGNhbGwgdG8gYSBzcHkhXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0TWVzc2FnZXMoc3B5LCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgsIGFsd2F5cywgYXJncykge1xuICAgICAgICB2YXIgdmVyYlBocmFzZSA9IGFsd2F5cyA/IFwiYWx3YXlzIGhhdmUgXCIgOiBcImhhdmUgXCI7XG4gICAgICAgIG5vbk5lZ2F0ZWRTdWZmaXggPSBub25OZWdhdGVkU3VmZml4IHx8IFwiXCI7XG4gICAgICAgIGlmIChpc1NweShzcHkucHJveHkpKSB7XG4gICAgICAgICAgICBzcHkgPSBzcHkucHJveHk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBwcmludGZBcnJheShhcnJheSkge1xuICAgICAgICAgICAgcmV0dXJuIHNweS5wcmludGYuYXBwbHkoc3B5LCBhcnJheSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgYWZmaXJtYXRpdmU6IHByaW50ZkFycmF5KFtcImV4cGVjdGVkICVuIHRvIFwiICsgdmVyYlBocmFzZSArIGFjdGlvbiArIG5vbk5lZ2F0ZWRTdWZmaXhdLmNvbmNhdChhcmdzKSksXG4gICAgICAgICAgICBuZWdhdGl2ZTogcHJpbnRmQXJyYXkoW1wiZXhwZWN0ZWQgJW4gdG8gbm90IFwiICsgdmVyYlBocmFzZSArIGFjdGlvbl0uY29uY2F0KGFyZ3MpKVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNpbm9uUHJvcGVydHkobmFtZSwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4KSB7XG4gICAgICAgIHV0aWxzLmFkZFByb3BlcnR5KGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZSwgbmFtZSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgYXNzZXJ0Q2FuV29ya1dpdGgodGhpcyk7XG5cbiAgICAgICAgICAgIHZhciBtZXNzYWdlcyA9IGdldE1lc3NhZ2VzKHRoaXMuX29iaiwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4LCBmYWxzZSk7XG4gICAgICAgICAgICB0aGlzLmFzc2VydCh0aGlzLl9vYmpbbmFtZV0sIG1lc3NhZ2VzLmFmZmlybWF0aXZlLCBtZXNzYWdlcy5uZWdhdGl2ZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNpbm9uUHJvcGVydHlBc0Jvb2xlYW5NZXRob2QobmFtZSwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4KSB7XG4gICAgICAgIHV0aWxzLmFkZE1ldGhvZChjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUsIG5hbWUsIGZ1bmN0aW9uIChhcmcpIHtcbiAgICAgICAgICAgIGFzc2VydENhbldvcmtXaXRoKHRoaXMpO1xuXG4gICAgICAgICAgICB2YXIgbWVzc2FnZXMgPSBnZXRNZXNzYWdlcyh0aGlzLl9vYmosIGFjdGlvbiwgbm9uTmVnYXRlZFN1ZmZpeCwgZmFsc2UsIFt0aW1lc0luV29yZHMoYXJnKV0pO1xuICAgICAgICAgICAgdGhpcy5hc3NlcnQodGhpcy5fb2JqW25hbWVdID09PSBhcmcsIG1lc3NhZ2VzLmFmZmlybWF0aXZlLCBtZXNzYWdlcy5uZWdhdGl2ZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZVNpbm9uTWV0aG9kSGFuZGxlcihzaW5vbk5hbWUsIGFjdGlvbiwgbm9uTmVnYXRlZFN1ZmZpeCkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgYXNzZXJ0Q2FuV29ya1dpdGgodGhpcyk7XG5cbiAgICAgICAgICAgIHZhciBhbHdheXNTaW5vbk1ldGhvZCA9IFwiYWx3YXlzXCIgKyBzaW5vbk5hbWVbMF0udG9VcHBlckNhc2UoKSArIHNpbm9uTmFtZS5zdWJzdHJpbmcoMSk7XG4gICAgICAgICAgICB2YXIgc2hvdWxkQmVBbHdheXMgPSB1dGlscy5mbGFnKHRoaXMsIFwiYWx3YXlzXCIpICYmIHR5cGVvZiB0aGlzLl9vYmpbYWx3YXlzU2lub25NZXRob2RdID09PSBcImZ1bmN0aW9uXCI7XG4gICAgICAgICAgICB2YXIgc2lub25NZXRob2QgPSBzaG91bGRCZUFsd2F5cyA/IGFsd2F5c1Npbm9uTWV0aG9kIDogc2lub25OYW1lO1xuXG4gICAgICAgICAgICB2YXIgbWVzc2FnZXMgPSBnZXRNZXNzYWdlcyh0aGlzLl9vYmosIGFjdGlvbiwgbm9uTmVnYXRlZFN1ZmZpeCwgc2hvdWxkQmVBbHdheXMsIHNsaWNlLmNhbGwoYXJndW1lbnRzKSk7XG4gICAgICAgICAgICB0aGlzLmFzc2VydCh0aGlzLl9vYmpbc2lub25NZXRob2RdLmFwcGx5KHRoaXMuX29iaiwgYXJndW1lbnRzKSwgbWVzc2FnZXMuYWZmaXJtYXRpdmUsIG1lc3NhZ2VzLm5lZ2F0aXZlKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzaW5vbk1ldGhvZEFzUHJvcGVydHkobmFtZSwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4KSB7XG4gICAgICAgIHZhciBoYW5kbGVyID0gY3JlYXRlU2lub25NZXRob2RIYW5kbGVyKG5hbWUsIGFjdGlvbiwgbm9uTmVnYXRlZFN1ZmZpeCk7XG4gICAgICAgIHV0aWxzLmFkZFByb3BlcnR5KGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZSwgbmFtZSwgaGFuZGxlcik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXhjZXB0aW9uYWxTaW5vbk1ldGhvZChjaGFpTmFtZSwgc2lub25OYW1lLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgpIHtcbiAgICAgICAgdmFyIGhhbmRsZXIgPSBjcmVhdGVTaW5vbk1ldGhvZEhhbmRsZXIoc2lub25OYW1lLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgpO1xuICAgICAgICB1dGlscy5hZGRNZXRob2QoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCBjaGFpTmFtZSwgaGFuZGxlcik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2lub25NZXRob2QobmFtZSwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4KSB7XG4gICAgICAgIGV4Y2VwdGlvbmFsU2lub25NZXRob2QobmFtZSwgbmFtZSwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4KTtcbiAgICB9XG5cbiAgICB1dGlscy5hZGRQcm9wZXJ0eShjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUsIFwiYWx3YXlzXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdXRpbHMuZmxhZyh0aGlzLCBcImFsd2F5c1wiLCB0cnVlKTtcbiAgICB9KTtcblxuICAgIHNpbm9uUHJvcGVydHkoXCJjYWxsZWRcIiwgXCJiZWVuIGNhbGxlZFwiLCBcIiBhdCBsZWFzdCBvbmNlLCBidXQgaXQgd2FzIG5ldmVyIGNhbGxlZFwiKTtcbiAgICBzaW5vblByb3BlcnR5QXNCb29sZWFuTWV0aG9kKFwiY2FsbENvdW50XCIsIFwiYmVlbiBjYWxsZWQgZXhhY3RseSAlMVwiLCBcIiwgYnV0IGl0IHdhcyBjYWxsZWQgJWMlQ1wiKTtcbiAgICBzaW5vblByb3BlcnR5KFwiY2FsbGVkT25jZVwiLCBcImJlZW4gY2FsbGVkIGV4YWN0bHkgb25jZVwiLCBcIiwgYnV0IGl0IHdhcyBjYWxsZWQgJWMlQ1wiKTtcbiAgICBzaW5vblByb3BlcnR5KFwiY2FsbGVkVHdpY2VcIiwgXCJiZWVuIGNhbGxlZCBleGFjdGx5IHR3aWNlXCIsIFwiLCBidXQgaXQgd2FzIGNhbGxlZCAlYyVDXCIpO1xuICAgIHNpbm9uUHJvcGVydHkoXCJjYWxsZWRUaHJpY2VcIiwgXCJiZWVuIGNhbGxlZCBleGFjdGx5IHRocmljZVwiLCBcIiwgYnV0IGl0IHdhcyBjYWxsZWQgJWMlQ1wiKTtcbiAgICBzaW5vbk1ldGhvZEFzUHJvcGVydHkoXCJjYWxsZWRXaXRoTmV3XCIsIFwiYmVlbiBjYWxsZWQgd2l0aCBuZXdcIik7XG4gICAgc2lub25NZXRob2QoXCJjYWxsZWRCZWZvcmVcIiwgXCJiZWVuIGNhbGxlZCBiZWZvcmUgJTFcIik7XG4gICAgc2lub25NZXRob2QoXCJjYWxsZWRBZnRlclwiLCBcImJlZW4gY2FsbGVkIGFmdGVyICUxXCIpO1xuICAgIHNpbm9uTWV0aG9kKFwiY2FsbGVkT25cIiwgXCJiZWVuIGNhbGxlZCB3aXRoICUxIGFzIHRoaXNcIiwgXCIsIGJ1dCBpdCB3YXMgY2FsbGVkIHdpdGggJXQgaW5zdGVhZFwiKTtcbiAgICBzaW5vbk1ldGhvZChcImNhbGxlZFdpdGhcIiwgXCJiZWVuIGNhbGxlZCB3aXRoIGFyZ3VtZW50cyAlKlwiLCBcIiVDXCIpO1xuICAgIHNpbm9uTWV0aG9kKFwiY2FsbGVkV2l0aEV4YWN0bHlcIiwgXCJiZWVuIGNhbGxlZCB3aXRoIGV4YWN0IGFyZ3VtZW50cyAlKlwiLCBcIiVDXCIpO1xuICAgIHNpbm9uTWV0aG9kKFwiY2FsbGVkV2l0aE1hdGNoXCIsIFwiYmVlbiBjYWxsZWQgd2l0aCBhcmd1bWVudHMgbWF0Y2hpbmcgJSpcIiwgXCIlQ1wiKTtcbiAgICBzaW5vbk1ldGhvZChcInJldHVybmVkXCIsIFwicmV0dXJuZWQgJTFcIik7XG4gICAgZXhjZXB0aW9uYWxTaW5vbk1ldGhvZChcInRocm93blwiLCBcInRocmV3XCIsIFwidGhyb3duICUxXCIpO1xufSkpO1xuIiwiLypqc2xpbnQgZXFlcWVxOiBmYWxzZSwgb25ldmFyOiBmYWxzZSwgZm9yaW46IHRydWUsIG5vbWVuOiBmYWxzZSwgcmVnZXhwOiBmYWxzZSwgcGx1c3BsdXM6IGZhbHNlKi9cbi8qZ2xvYmFsIG1vZHVsZSwgcmVxdWlyZSwgX19kaXJuYW1lLCBkb2N1bWVudCovXG4vKipcbiAqIFNpbm9uIGNvcmUgdXRpbGl0aWVzLiBGb3IgaW50ZXJuYWwgdXNlIG9ubHkuXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBzaW5vbiA9IChmdW5jdGlvbiAoZm9ybWF0aW8pIHtcbiAgICB2YXIgZGl2ID0gdHlwZW9mIGRvY3VtZW50ICE9IFwidW5kZWZpbmVkXCIgJiYgZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICB2YXIgaGFzT3duID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcblxuICAgIGZ1bmN0aW9uIGlzRE9NTm9kZShvYmopIHtcbiAgICAgICAgdmFyIHN1Y2Nlc3MgPSBmYWxzZTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgb2JqLmFwcGVuZENoaWxkKGRpdik7XG4gICAgICAgICAgICBzdWNjZXNzID0gZGl2LnBhcmVudE5vZGUgPT0gb2JqO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIG9iai5yZW1vdmVDaGlsZChkaXYpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBmYWlsZWQsIG5vdCBtdWNoIHdlIGNhbiBkbyBhYm91dCB0aGF0XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc3VjY2VzcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0VsZW1lbnQob2JqKSB7XG4gICAgICAgIHJldHVybiBkaXYgJiYgb2JqICYmIG9iai5ub2RlVHlwZSA9PT0gMSAmJiBpc0RPTU5vZGUob2JqKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0Z1bmN0aW9uKG9iaikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gXCJmdW5jdGlvblwiIHx8ICEhKG9iaiAmJiBvYmouY29uc3RydWN0b3IgJiYgb2JqLmNhbGwgJiYgb2JqLmFwcGx5KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1JlYWxseU5hTih2YWwpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWwgPT09ICdudW1iZXInICYmIGlzTmFOKHZhbCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWlycm9yUHJvcGVydGllcyh0YXJnZXQsIHNvdXJjZSkge1xuICAgICAgICBmb3IgKHZhciBwcm9wIGluIHNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKCFoYXNPd24uY2FsbCh0YXJnZXQsIHByb3ApKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0W3Byb3BdID0gc291cmNlW3Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNSZXN0b3JhYmxlIChvYmopIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmogPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2Ygb2JqLnJlc3RvcmUgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmoucmVzdG9yZS5zaW5vbjtcbiAgICB9XG5cbiAgICB2YXIgc2lub24gPSB7XG4gICAgICAgIHdyYXBNZXRob2Q6IGZ1bmN0aW9uIHdyYXBNZXRob2Qob2JqZWN0LCBwcm9wZXJ0eSwgbWV0aG9kKSB7XG4gICAgICAgICAgICBpZiAoIW9iamVjdCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTaG91bGQgd3JhcCBwcm9wZXJ0eSBvZiBvYmplY3RcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWV0aG9kICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJNZXRob2Qgd3JhcHBlciBzaG91bGQgYmUgZnVuY3Rpb25cIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciB3cmFwcGVkTWV0aG9kID0gb2JqZWN0W3Byb3BlcnR5XSxcbiAgICAgICAgICAgICAgICBlcnJvcjtcblxuICAgICAgICAgICAgaWYgKCFpc0Z1bmN0aW9uKHdyYXBwZWRNZXRob2QpKSB7XG4gICAgICAgICAgICAgICAgZXJyb3IgPSBuZXcgVHlwZUVycm9yKFwiQXR0ZW1wdGVkIHRvIHdyYXAgXCIgKyAodHlwZW9mIHdyYXBwZWRNZXRob2QpICsgXCIgcHJvcGVydHkgXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydHkgKyBcIiBhcyBmdW5jdGlvblwiKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAod3JhcHBlZE1ldGhvZC5yZXN0b3JlICYmIHdyYXBwZWRNZXRob2QucmVzdG9yZS5zaW5vbikge1xuICAgICAgICAgICAgICAgIGVycm9yID0gbmV3IFR5cGVFcnJvcihcIkF0dGVtcHRlZCB0byB3cmFwIFwiICsgcHJvcGVydHkgKyBcIiB3aGljaCBpcyBhbHJlYWR5IHdyYXBwZWRcIik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHdyYXBwZWRNZXRob2QuY2FsbGVkQmVmb3JlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHZlcmIgPSAhIXdyYXBwZWRNZXRob2QucmV0dXJucyA/IFwic3R1YmJlZFwiIDogXCJzcGllZCBvblwiO1xuICAgICAgICAgICAgICAgIGVycm9yID0gbmV3IFR5cGVFcnJvcihcIkF0dGVtcHRlZCB0byB3cmFwIFwiICsgcHJvcGVydHkgKyBcIiB3aGljaCBpcyBhbHJlYWR5IFwiICsgdmVyYik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgICAgIGlmICh3cmFwcGVkTWV0aG9kICYmIHdyYXBwZWRNZXRob2QuX3N0YWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yLnN0YWNrICs9ICdcXG4tLS0tLS0tLS0tLS0tLVxcbicgKyB3cmFwcGVkTWV0aG9kLl9zdGFjaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIElFIDggZG9lcyBub3Qgc3VwcG9ydCBoYXNPd25Qcm9wZXJ0eSBvbiB0aGUgd2luZG93IG9iamVjdCBhbmQgRmlyZWZveCBoYXMgYSBwcm9ibGVtXG4gICAgICAgICAgICAvLyB3aGVuIHVzaW5nIGhhc093bi5jYWxsIG9uIG9iamVjdHMgZnJvbSBvdGhlciBmcmFtZXMuXG4gICAgICAgICAgICB2YXIgb3duZWQgPSBvYmplY3QuaGFzT3duUHJvcGVydHkgPyBvYmplY3QuaGFzT3duUHJvcGVydHkocHJvcGVydHkpIDogaGFzT3duLmNhbGwob2JqZWN0LCBwcm9wZXJ0eSk7XG4gICAgICAgICAgICBvYmplY3RbcHJvcGVydHldID0gbWV0aG9kO1xuICAgICAgICAgICAgbWV0aG9kLmRpc3BsYXlOYW1lID0gcHJvcGVydHk7XG4gICAgICAgICAgICAvLyBTZXQgdXAgYSBzdGFjayB0cmFjZSB3aGljaCBjYW4gYmUgdXNlZCBsYXRlciB0byBmaW5kIHdoYXQgbGluZSBvZlxuICAgICAgICAgICAgLy8gY29kZSB0aGUgb3JpZ2luYWwgbWV0aG9kIHdhcyBjcmVhdGVkIG9uLlxuICAgICAgICAgICAgbWV0aG9kLl9zdGFjayA9IChuZXcgRXJyb3IoJ1N0YWNrIFRyYWNlIGZvciBvcmlnaW5hbCcpKS5zdGFjaztcblxuICAgICAgICAgICAgbWV0aG9kLnJlc3RvcmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgLy8gRm9yIHByb3RvdHlwZSBwcm9wZXJ0aWVzIHRyeSB0byByZXNldCBieSBkZWxldGUgZmlyc3QuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBmYWlscyAoZXg6IGxvY2FsU3RvcmFnZSBvbiBtb2JpbGUgc2FmYXJpKSB0aGVuIGZvcmNlIGEgcmVzZXRcbiAgICAgICAgICAgICAgICAvLyB2aWEgZGlyZWN0IGFzc2lnbm1lbnQuXG4gICAgICAgICAgICAgICAgaWYgKCFvd25lZCkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgb2JqZWN0W3Byb3BlcnR5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG9iamVjdFtwcm9wZXJ0eV0gPT09IG1ldGhvZCkge1xuICAgICAgICAgICAgICAgICAgICBvYmplY3RbcHJvcGVydHldID0gd3JhcHBlZE1ldGhvZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBtZXRob2QucmVzdG9yZS5zaW5vbiA9IHRydWU7XG4gICAgICAgICAgICBtaXJyb3JQcm9wZXJ0aWVzKG1ldGhvZCwgd3JhcHBlZE1ldGhvZCk7XG5cbiAgICAgICAgICAgIHJldHVybiBtZXRob2Q7XG4gICAgICAgIH0sXG5cbiAgICAgICAgZXh0ZW5kOiBmdW5jdGlvbiBleHRlbmQodGFyZ2V0KSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMSwgbCA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBsOyBpICs9IDEpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wIGluIGFyZ3VtZW50c1tpXSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldLmhhc093blByb3BlcnR5KHByb3ApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRbcHJvcF0gPSBhcmd1bWVudHNbaV1bcHJvcF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBET05UIEVOVU0gYnVnLCBvbmx5IGNhcmUgYWJvdXQgdG9TdHJpbmdcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50c1tpXS5oYXNPd25Qcm9wZXJ0eShcInRvU3RyaW5nXCIpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBhcmd1bWVudHNbaV0udG9TdHJpbmcgIT0gdGFyZ2V0LnRvU3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQudG9TdHJpbmcgPSBhcmd1bWVudHNbaV0udG9TdHJpbmc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgICAgIH0sXG5cbiAgICAgICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUocHJvdG8pIHtcbiAgICAgICAgICAgIHZhciBGID0gZnVuY3Rpb24gKCkge307XG4gICAgICAgICAgICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBGKCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgZGVlcEVxdWFsOiBmdW5jdGlvbiBkZWVwRXF1YWwoYSwgYikge1xuICAgICAgICAgICAgaWYgKHNpbm9uLm1hdGNoICYmIHNpbm9uLm1hdGNoLmlzTWF0Y2hlcihhKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhLnRlc3QoYik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgYSAhPSAnb2JqZWN0JyB8fCB0eXBlb2YgYiAhPSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgICAgIGlmIChpc1JlYWxseU5hTihhKSAmJiBpc1JlYWxseU5hTihiKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYSA9PT0gYjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChpc0VsZW1lbnQoYSkgfHwgaXNFbGVtZW50KGIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPT09IGI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICgoYSA9PT0gbnVsbCAmJiBiICE9PSBudWxsKSB8fCAoYSAhPT0gbnVsbCAmJiBiID09PSBudWxsKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGEgaW5zdGFuY2VvZiBSZWdFeHAgJiYgYiBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgICByZXR1cm4gKGEuc291cmNlID09PSBiLnNvdXJjZSkgJiYgKGEuZ2xvYmFsID09PSBiLmdsb2JhbCkgJiZcbiAgICAgICAgICAgICAgICAoYS5pZ25vcmVDYXNlID09PSBiLmlnbm9yZUNhc2UpICYmIChhLm11bHRpbGluZSA9PT0gYi5tdWx0aWxpbmUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgYVN0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhKTtcbiAgICAgICAgICAgIGlmIChhU3RyaW5nICE9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChiKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGFTdHJpbmcgPT0gXCJbb2JqZWN0IERhdGVdXCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYS52YWx1ZU9mKCkgPT09IGIudmFsdWVPZigpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcHJvcCwgYUxlbmd0aCA9IDAsIGJMZW5ndGggPSAwO1xuXG4gICAgICAgICAgICBpZiAoYVN0cmluZyA9PSBcIltvYmplY3QgQXJyYXldXCIgJiYgYS5sZW5ndGggIT09IGIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKHByb3AgaW4gYSkge1xuICAgICAgICAgICAgICAgIGFMZW5ndGggKz0gMTtcblxuICAgICAgICAgICAgICAgIGlmICghKHByb3AgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghZGVlcEVxdWFsKGFbcHJvcF0sIGJbcHJvcF0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAocHJvcCBpbiBiKSB7XG4gICAgICAgICAgICAgICAgYkxlbmd0aCArPSAxO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gYUxlbmd0aCA9PSBiTGVuZ3RoO1xuICAgICAgICB9LFxuXG4gICAgICAgIGZ1bmN0aW9uTmFtZTogZnVuY3Rpb24gZnVuY3Rpb25OYW1lKGZ1bmMpIHtcbiAgICAgICAgICAgIHZhciBuYW1lID0gZnVuYy5kaXNwbGF5TmFtZSB8fCBmdW5jLm5hbWU7XG5cbiAgICAgICAgICAgIC8vIFVzZSBmdW5jdGlvbiBkZWNvbXBvc2l0aW9uIGFzIGEgbGFzdCByZXNvcnQgdG8gZ2V0IGZ1bmN0aW9uXG4gICAgICAgICAgICAvLyBuYW1lLiBEb2VzIG5vdCByZWx5IG9uIGZ1bmN0aW9uIGRlY29tcG9zaXRpb24gdG8gd29yayAtIGlmIGl0XG4gICAgICAgICAgICAvLyBkb2Vzbid0IGRlYnVnZ2luZyB3aWxsIGJlIHNsaWdodGx5IGxlc3MgaW5mb3JtYXRpdmVcbiAgICAgICAgICAgIC8vIChpLmUuIHRvU3RyaW5nIHdpbGwgc2F5ICdzcHknIHJhdGhlciB0aGFuICdteUZ1bmMnKS5cbiAgICAgICAgICAgIGlmICghbmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBtYXRjaGVzID0gZnVuYy50b1N0cmluZygpLm1hdGNoKC9mdW5jdGlvbiAoW15cXHNcXChdKykvKTtcbiAgICAgICAgICAgICAgICBuYW1lID0gbWF0Y2hlcyAmJiBtYXRjaGVzWzFdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gbmFtZTtcbiAgICAgICAgfSxcblxuICAgICAgICBmdW5jdGlvblRvU3RyaW5nOiBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmdldENhbGwgJiYgdGhpcy5jYWxsQ291bnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGhpc1ZhbHVlLCBwcm9wLCBpID0gdGhpcy5jYWxsQ291bnQ7XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXNWYWx1ZSA9IHRoaXMuZ2V0Q2FsbChpKS50aGlzVmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgZm9yIChwcm9wIGluIHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXNWYWx1ZVtwcm9wXSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwcm9wO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5kaXNwbGF5TmFtZSB8fCBcInNpbm9uIGZha2VcIjtcbiAgICAgICAgfSxcblxuICAgICAgICBnZXRDb25maWc6IGZ1bmN0aW9uIChjdXN0b20pIHtcbiAgICAgICAgICAgIHZhciBjb25maWcgPSB7fTtcbiAgICAgICAgICAgIGN1c3RvbSA9IGN1c3RvbSB8fCB7fTtcbiAgICAgICAgICAgIHZhciBkZWZhdWx0cyA9IHNpbm9uLmRlZmF1bHRDb25maWc7XG5cbiAgICAgICAgICAgIGZvciAodmFyIHByb3AgaW4gZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGVmYXVsdHMuaGFzT3duUHJvcGVydHkocHJvcCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnW3Byb3BdID0gY3VzdG9tLmhhc093blByb3BlcnR5KHByb3ApID8gY3VzdG9tW3Byb3BdIDogZGVmYXVsdHNbcHJvcF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgICAgICB9LFxuXG4gICAgICAgIGZvcm1hdDogZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICAgICAgcmV0dXJuIFwiXCIgKyB2YWw7XG4gICAgICAgIH0sXG5cbiAgICAgICAgZGVmYXVsdENvbmZpZzoge1xuICAgICAgICAgICAgaW5qZWN0SW50b1RoaXM6IHRydWUsXG4gICAgICAgICAgICBpbmplY3RJbnRvOiBudWxsLFxuICAgICAgICAgICAgcHJvcGVydGllczogW1wic3B5XCIsIFwic3R1YlwiLCBcIm1vY2tcIiwgXCJjbG9ja1wiLCBcInNlcnZlclwiLCBcInJlcXVlc3RzXCJdLFxuICAgICAgICAgICAgdXNlRmFrZVRpbWVyczogdHJ1ZSxcbiAgICAgICAgICAgIHVzZUZha2VTZXJ2ZXI6IHRydWVcbiAgICAgICAgfSxcblxuICAgICAgICB0aW1lc0luV29yZHM6IGZ1bmN0aW9uIHRpbWVzSW5Xb3Jkcyhjb3VudCkge1xuICAgICAgICAgICAgcmV0dXJuIGNvdW50ID09IDEgJiYgXCJvbmNlXCIgfHxcbiAgICAgICAgICAgICAgICBjb3VudCA9PSAyICYmIFwidHdpY2VcIiB8fFxuICAgICAgICAgICAgICAgIGNvdW50ID09IDMgJiYgXCJ0aHJpY2VcIiB8fFxuICAgICAgICAgICAgICAgIChjb3VudCB8fCAwKSArIFwiIHRpbWVzXCI7XG4gICAgICAgIH0sXG5cbiAgICAgICAgY2FsbGVkSW5PcmRlcjogZnVuY3Rpb24gKHNwaWVzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMSwgbCA9IHNwaWVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmICghc3BpZXNbaSAtIDFdLmNhbGxlZEJlZm9yZShzcGllc1tpXSkgfHwgIXNwaWVzW2ldLmNhbGxlZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSxcblxuICAgICAgICBvcmRlckJ5Rmlyc3RDYWxsOiBmdW5jdGlvbiAoc3BpZXMpIHtcbiAgICAgICAgICAgIHJldHVybiBzcGllcy5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICAgICAgICAgICAgLy8gdXVpZCwgd29uJ3QgZXZlciBiZSBlcXVhbFxuICAgICAgICAgICAgICAgIHZhciBhQ2FsbCA9IGEuZ2V0Q2FsbCgwKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNhbGwgPSBiLmdldENhbGwoMCk7XG4gICAgICAgICAgICAgICAgdmFyIGFJZCA9IGFDYWxsICYmIGFDYWxsLmNhbGxJZCB8fCAtMTtcbiAgICAgICAgICAgICAgICB2YXIgYklkID0gYkNhbGwgJiYgYkNhbGwuY2FsbElkIHx8IC0xO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFJZCA8IGJJZCA/IC0xIDogMTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LFxuXG4gICAgICAgIGxvZzogZnVuY3Rpb24gKCkge30sXG5cbiAgICAgICAgbG9nRXJyb3I6IGZ1bmN0aW9uIChsYWJlbCwgZXJyKSB7XG4gICAgICAgICAgICB2YXIgbXNnID0gbGFiZWwgKyBcIiB0aHJldyBleGNlcHRpb246IFwiO1xuICAgICAgICAgICAgc2lub24ubG9nKG1zZyArIFwiW1wiICsgZXJyLm5hbWUgKyBcIl0gXCIgKyBlcnIubWVzc2FnZSk7XG4gICAgICAgICAgICBpZiAoZXJyLnN0YWNrKSB7IHNpbm9uLmxvZyhlcnIuc3RhY2spOyB9XG5cbiAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlID0gbXNnICsgZXJyLm1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyO1xuICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgdHlwZU9mOiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBcIm51bGxcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJ1bmRlZmluZWRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICAgICAgICAgICAgcmV0dXJuIHN0cmluZy5zdWJzdHJpbmcoOCwgc3RyaW5nLmxlbmd0aCAtIDEpLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgY3JlYXRlU3R1Ykluc3RhbmNlOiBmdW5jdGlvbiAoY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY29uc3RydWN0b3IgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJUaGUgY29uc3RydWN0b3Igc2hvdWxkIGJlIGEgZnVuY3Rpb24uXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHNpbm9uLnN0dWIoc2lub24uY3JlYXRlKGNvbnN0cnVjdG9yLnByb3RvdHlwZSkpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHJlc3RvcmU6IGZ1bmN0aW9uIChvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvYmplY3QgIT09IG51bGwgJiYgdHlwZW9mIG9iamVjdCA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3AgaW4gb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1Jlc3RvcmFibGUob2JqZWN0W3Byb3BdKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb2JqZWN0W3Byb3BdLnJlc3RvcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGlzUmVzdG9yYWJsZShvYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0LnJlc3RvcmUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gJ29iamVjdCcgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIG1ha2VQdWJsaWNBUEkocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gc2lub247XG4gICAgICAgIHNpbm9uLnNweSA9IHJlcXVpcmUoXCIuL3Npbm9uL3NweVwiKTtcbiAgICAgICAgc2lub24uc3B5Q2FsbCA9IHJlcXVpcmUoXCIuL3Npbm9uL2NhbGxcIik7XG4gICAgICAgIHNpbm9uLmJlaGF2aW9yID0gcmVxdWlyZShcIi4vc2lub24vYmVoYXZpb3JcIik7XG4gICAgICAgIHNpbm9uLnN0dWIgPSByZXF1aXJlKFwiLi9zaW5vbi9zdHViXCIpO1xuICAgICAgICBzaW5vbi5tb2NrID0gcmVxdWlyZShcIi4vc2lub24vbW9ja1wiKTtcbiAgICAgICAgc2lub24uY29sbGVjdGlvbiA9IHJlcXVpcmUoXCIuL3Npbm9uL2NvbGxlY3Rpb25cIik7XG4gICAgICAgIHNpbm9uLmFzc2VydCA9IHJlcXVpcmUoXCIuL3Npbm9uL2Fzc2VydFwiKTtcbiAgICAgICAgc2lub24uc2FuZGJveCA9IHJlcXVpcmUoXCIuL3Npbm9uL3NhbmRib3hcIik7XG4gICAgICAgIHNpbm9uLnRlc3QgPSByZXF1aXJlKFwiLi9zaW5vbi90ZXN0XCIpO1xuICAgICAgICBzaW5vbi50ZXN0Q2FzZSA9IHJlcXVpcmUoXCIuL3Npbm9uL3Rlc3RfY2FzZVwiKTtcbiAgICAgICAgc2lub24ubWF0Y2ggPSByZXF1aXJlKFwiLi9zaW5vbi9tYXRjaFwiKTtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKG1ha2VQdWJsaWNBUEkpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBmb3JtYXRpbyA9IHJlcXVpcmUoXCJmb3JtYXRpb1wiKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgbWFrZVB1YmxpY0FQSShyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpO1xuICAgIH1cblxuICAgIGlmIChmb3JtYXRpbykge1xuICAgICAgICB2YXIgZm9ybWF0dGVyID0gZm9ybWF0aW8uY29uZmlndXJlKHsgcXVvdGVTdHJpbmdzOiBmYWxzZSB9KTtcbiAgICAgICAgc2lub24uZm9ybWF0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdHRlci5hc2NpaS5hcHBseShmb3JtYXR0ZXIsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHZhciB1dGlsID0gcmVxdWlyZShcInV0aWxcIik7XG4gICAgICAgICAgICBzaW5vbi5mb3JtYXQgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09IFwib2JqZWN0XCIgJiYgdmFsdWUudG9TdHJpbmcgPT09IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcgPyB1dGlsLmluc3BlY3QodmFsdWUpIDogdmFsdWU7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAvKiBOb2RlLCBidXQgbm8gdXRpbCBtb2R1bGUgLSB3b3VsZCBiZSB2ZXJ5IG9sZCwgYnV0IGJldHRlciBzYWZlIHRoYW5cbiAgICAgICAgICAgICBzb3JyeSAqL1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHNpbm9uO1xufSh0eXBlb2YgZm9ybWF0aW8gPT0gXCJvYmplY3RcIiAmJiBmb3JtYXRpbykpO1xuIiwiKGZ1bmN0aW9uIChnbG9iYWwpe1xuLyoqXG4gKiBAZGVwZW5kIC4uL3Npbm9uLmpzXG4gKiBAZGVwZW5kIHN0dWIuanNcbiAqL1xuLypqc2xpbnQgZXFlcWVxOiBmYWxzZSwgb25ldmFyOiBmYWxzZSwgbm9tZW46IGZhbHNlLCBwbHVzcGx1czogZmFsc2UqL1xuLypnbG9iYWwgbW9kdWxlLCByZXF1aXJlLCBzaW5vbiovXG4vKipcbiAqIEFzc2VydGlvbnMgbWF0Y2hpbmcgdGhlIHRlc3Qgc3B5IHJldHJpZXZhbCBpbnRlcmZhY2UuXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiAoc2lub24sIGdsb2JhbCkge1xuICAgIHZhciBjb21tb25KU01vZHVsZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcbiAgICB2YXIgYXNzZXJ0O1xuXG4gICAgaWYgKCFzaW5vbiAmJiBjb21tb25KU01vZHVsZSkge1xuICAgICAgICBzaW5vbiA9IHJlcXVpcmUoXCIuLi9zaW5vblwiKTtcbiAgICB9XG5cbiAgICBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB2ZXJpZnlJc1N0dWIoKSB7XG4gICAgICAgIHZhciBtZXRob2Q7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICBtZXRob2QgPSBhcmd1bWVudHNbaV07XG5cbiAgICAgICAgICAgIGlmICghbWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0LmZhaWwoXCJmYWtlIGlzIG5vdCBhIHNweVwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXRob2QgIT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0LmZhaWwobWV0aG9kICsgXCIgaXMgbm90IGEgZnVuY3Rpb25cIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWV0aG9kLmdldENhbGwgIT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0LmZhaWwobWV0aG9kICsgXCIgaXMgbm90IHN0dWJiZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmYWlsQXNzZXJ0aW9uKG9iamVjdCwgbXNnKSB7XG4gICAgICAgIG9iamVjdCA9IG9iamVjdCB8fCBnbG9iYWw7XG4gICAgICAgIHZhciBmYWlsTWV0aG9kID0gb2JqZWN0LmZhaWwgfHwgYXNzZXJ0LmZhaWw7XG4gICAgICAgIGZhaWxNZXRob2QuY2FsbChvYmplY3QsIG1zZyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWlycm9yUHJvcEFzQXNzZXJ0aW9uKG5hbWUsIG1ldGhvZCwgbWVzc2FnZSkge1xuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PSAyKSB7XG4gICAgICAgICAgICBtZXNzYWdlID0gbWV0aG9kO1xuICAgICAgICAgICAgbWV0aG9kID0gbmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFzc2VydFtuYW1lXSA9IGZ1bmN0aW9uIChmYWtlKSB7XG4gICAgICAgICAgICB2ZXJpZnlJc1N0dWIoZmFrZSk7XG5cbiAgICAgICAgICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgdmFyIGZhaWxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG1ldGhvZCA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICBmYWlsZWQgPSAhbWV0aG9kKGZha2UpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBmYWlsZWQgPSB0eXBlb2YgZmFrZVttZXRob2RdID09IFwiZnVuY3Rpb25cIiA/XG4gICAgICAgICAgICAgICAgICAgICFmYWtlW21ldGhvZF0uYXBwbHkoZmFrZSwgYXJncykgOiAhZmFrZVttZXRob2RdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZmFpbGVkKSB7XG4gICAgICAgICAgICAgICAgZmFpbEFzc2VydGlvbih0aGlzLCBmYWtlLnByaW50Zi5hcHBseShmYWtlLCBbbWVzc2FnZV0uY29uY2F0KGFyZ3MpKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGFzc2VydC5wYXNzKG5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4cG9zZWROYW1lKHByZWZpeCwgcHJvcCkge1xuICAgICAgICByZXR1cm4gIXByZWZpeCB8fCAvXmZhaWwvLnRlc3QocHJvcCkgPyBwcm9wIDpcbiAgICAgICAgICAgIHByZWZpeCArIHByb3Auc2xpY2UoMCwgMSkudG9VcHBlckNhc2UoKSArIHByb3Auc2xpY2UoMSk7XG4gICAgfVxuXG4gICAgYXNzZXJ0ID0ge1xuICAgICAgICBmYWlsRXhjZXB0aW9uOiBcIkFzc2VydEVycm9yXCIsXG5cbiAgICAgICAgZmFpbDogZnVuY3Rpb24gZmFpbChtZXNzYWdlKSB7XG4gICAgICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IobWVzc2FnZSk7XG4gICAgICAgICAgICBlcnJvci5uYW1lID0gdGhpcy5mYWlsRXhjZXB0aW9uIHx8IGFzc2VydC5mYWlsRXhjZXB0aW9uO1xuXG4gICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgfSxcblxuICAgICAgICBwYXNzOiBmdW5jdGlvbiBwYXNzKGFzc2VydGlvbikge30sXG5cbiAgICAgICAgY2FsbE9yZGVyOiBmdW5jdGlvbiBhc3NlcnRDYWxsT3JkZXIoKSB7XG4gICAgICAgICAgICB2ZXJpZnlJc1N0dWIuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHZhciBleHBlY3RlZCA9IFwiXCIsIGFjdHVhbCA9IFwiXCI7XG5cbiAgICAgICAgICAgIGlmICghc2lub24uY2FsbGVkSW5PcmRlcihhcmd1bWVudHMpKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0ZWQgPSBbXS5qb2luLmNhbGwoYXJndW1lbnRzLCBcIiwgXCIpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2FsbHMgPSBzbGljZS5jYWxsKGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpID0gY2FsbHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjYWxsc1stLWldLmNhbGxlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBhY3R1YWwgPSBzaW5vbi5vcmRlckJ5Rmlyc3RDYWxsKGNhbGxzKS5qb2luKFwiLCBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGlzIGZhaWxzLCB3ZSdsbCBqdXN0IGZhbGwgYmFjayB0byB0aGUgYmxhbmsgc3RyaW5nXG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZmFpbEFzc2VydGlvbih0aGlzLCBcImV4cGVjdGVkIFwiICsgZXhwZWN0ZWQgKyBcIiB0byBiZSBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImNhbGxlZCBpbiBvcmRlciBidXQgd2VyZSBjYWxsZWQgYXMgXCIgKyBhY3R1YWwpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQucGFzcyhcImNhbGxPcmRlclwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBjYWxsQ291bnQ6IGZ1bmN0aW9uIGFzc2VydENhbGxDb3VudChtZXRob2QsIGNvdW50KSB7XG4gICAgICAgICAgICB2ZXJpZnlJc1N0dWIobWV0aG9kKTtcblxuICAgICAgICAgICAgaWYgKG1ldGhvZC5jYWxsQ291bnQgIT0gY291bnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgbXNnID0gXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgXCIgKyBzaW5vbi50aW1lc0luV29yZHMoY291bnQpICtcbiAgICAgICAgICAgICAgICAgICAgXCIgYnV0IHdhcyBjYWxsZWQgJWMlQ1wiO1xuICAgICAgICAgICAgICAgIGZhaWxBc3NlcnRpb24odGhpcywgbWV0aG9kLnByaW50Zihtc2cpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0LnBhc3MoXCJjYWxsQ291bnRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgZXhwb3NlOiBmdW5jdGlvbiBleHBvc2UodGFyZ2V0LCBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAoIXRhcmdldCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJ0YXJnZXQgaXMgbnVsbCBvciB1bmRlZmluZWRcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBvID0gb3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgIHZhciBwcmVmaXggPSB0eXBlb2Ygby5wcmVmaXggPT0gXCJ1bmRlZmluZWRcIiAmJiBcImFzc2VydFwiIHx8IG8ucHJlZml4O1xuICAgICAgICAgICAgdmFyIGluY2x1ZGVGYWlsID0gdHlwZW9mIG8uaW5jbHVkZUZhaWwgPT0gXCJ1bmRlZmluZWRcIiB8fCAhIW8uaW5jbHVkZUZhaWw7XG5cbiAgICAgICAgICAgIGZvciAodmFyIG1ldGhvZCBpbiB0aGlzKSB7XG4gICAgICAgICAgICAgICAgaWYgKG1ldGhvZCAhPSBcImV4cG9ydFwiICYmIChpbmNsdWRlRmFpbCB8fCAhL14oZmFpbCkvLnRlc3QobWV0aG9kKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0W2V4cG9zZWROYW1lKHByZWZpeCwgbWV0aG9kKV0gPSB0aGlzW21ldGhvZF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGFyZ2V0O1xuICAgICAgICB9LFxuXG4gICAgICAgIG1hdGNoOiBmdW5jdGlvbiBtYXRjaChhY3R1YWwsIGV4cGVjdGF0aW9uKSB7XG4gICAgICAgICAgICB2YXIgbWF0Y2hlciA9IHNpbm9uLm1hdGNoKGV4cGVjdGF0aW9uKTtcbiAgICAgICAgICAgIGlmIChtYXRjaGVyLnRlc3QoYWN0dWFsKSkge1xuICAgICAgICAgICAgICAgIGFzc2VydC5wYXNzKFwibWF0Y2hcIik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBmb3JtYXR0ZWQgPSBbXG4gICAgICAgICAgICAgICAgICAgIFwiZXhwZWN0ZWQgdmFsdWUgdG8gbWF0Y2hcIixcbiAgICAgICAgICAgICAgICAgICAgXCIgICAgZXhwZWN0ZWQgPSBcIiArIHNpbm9uLmZvcm1hdChleHBlY3RhdGlvbiksXG4gICAgICAgICAgICAgICAgICAgIFwiICAgIGFjdHVhbCA9IFwiICsgc2lub24uZm9ybWF0KGFjdHVhbClcbiAgICAgICAgICAgICAgICBdXG4gICAgICAgICAgICAgICAgZmFpbEFzc2VydGlvbih0aGlzLCBmb3JtYXR0ZWQuam9pbihcIlxcblwiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwiY2FsbGVkXCIsIFwiZXhwZWN0ZWQgJW4gdG8gaGF2ZSBiZWVuIGNhbGxlZCBhdCBsZWFzdCBvbmNlIGJ1dCB3YXMgbmV2ZXIgY2FsbGVkXCIpO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcIm5vdENhbGxlZFwiLCBmdW5jdGlvbiAoc3B5KSB7IHJldHVybiAhc3B5LmNhbGxlZDsgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgXCJleHBlY3RlZCAlbiB0byBub3QgaGF2ZSBiZWVuIGNhbGxlZCBidXQgd2FzIGNhbGxlZCAlYyVDXCIpO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZE9uY2VcIiwgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgb25jZSBidXQgd2FzIGNhbGxlZCAlYyVDXCIpO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZFR3aWNlXCIsIFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIHR3aWNlIGJ1dCB3YXMgY2FsbGVkICVjJUNcIik7XG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwiY2FsbGVkVGhyaWNlXCIsIFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIHRocmljZSBidXQgd2FzIGNhbGxlZCAlYyVDXCIpO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZE9uXCIsIFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIHdpdGggJTEgYXMgdGhpcyBidXQgd2FzIGNhbGxlZCB3aXRoICV0XCIpO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImFsd2F5c0NhbGxlZE9uXCIsIFwiZXhwZWN0ZWQgJW4gdG8gYWx3YXlzIGJlIGNhbGxlZCB3aXRoICUxIGFzIHRoaXMgYnV0IHdhcyBjYWxsZWQgd2l0aCAldFwiKTtcbiAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJjYWxsZWRXaXRoTmV3XCIsIFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIHdpdGggbmV3XCIpO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImFsd2F5c0NhbGxlZFdpdGhOZXdcIiwgXCJleHBlY3RlZCAlbiB0byBhbHdheXMgYmUgY2FsbGVkIHdpdGggbmV3XCIpO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZFdpdGhcIiwgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgd2l0aCBhcmd1bWVudHMgJSolQ1wiKTtcbiAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJjYWxsZWRXaXRoTWF0Y2hcIiwgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgd2l0aCBtYXRjaCAlKiVDXCIpO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImFsd2F5c0NhbGxlZFdpdGhcIiwgXCJleHBlY3RlZCAlbiB0byBhbHdheXMgYmUgY2FsbGVkIHdpdGggYXJndW1lbnRzICUqJUNcIik7XG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwiYWx3YXlzQ2FsbGVkV2l0aE1hdGNoXCIsIFwiZXhwZWN0ZWQgJW4gdG8gYWx3YXlzIGJlIGNhbGxlZCB3aXRoIG1hdGNoICUqJUNcIik7XG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwiY2FsbGVkV2l0aEV4YWN0bHlcIiwgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgd2l0aCBleGFjdCBhcmd1bWVudHMgJSolQ1wiKTtcbiAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJhbHdheXNDYWxsZWRXaXRoRXhhY3RseVwiLCBcImV4cGVjdGVkICVuIHRvIGFsd2F5cyBiZSBjYWxsZWQgd2l0aCBleGFjdCBhcmd1bWVudHMgJSolQ1wiKTtcbiAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJuZXZlckNhbGxlZFdpdGhcIiwgXCJleHBlY3RlZCAlbiB0byBuZXZlciBiZSBjYWxsZWQgd2l0aCBhcmd1bWVudHMgJSolQ1wiKTtcbiAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJuZXZlckNhbGxlZFdpdGhNYXRjaFwiLCBcImV4cGVjdGVkICVuIHRvIG5ldmVyIGJlIGNhbGxlZCB3aXRoIG1hdGNoICUqJUNcIik7XG4gICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwidGhyZXdcIiwgXCIlbiBkaWQgbm90IHRocm93IGV4Y2VwdGlvbiVDXCIpO1xuICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImFsd2F5c1RocmV3XCIsIFwiJW4gZGlkIG5vdCBhbHdheXMgdGhyb3cgZXhjZXB0aW9uJUNcIik7XG5cbiAgICBzaW5vbi5hc3NlcnQgPSBhc3NlcnQ7XG5cbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcIm1vZHVsZVwiXSwgZnVuY3Rpb24obW9kdWxlKSB7IG1vZHVsZS5leHBvcnRzID0gYXNzZXJ0OyB9KTtcbiAgICB9IGVsc2UgaWYgKGNvbW1vbkpTTW9kdWxlKSB7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXNzZXJ0O1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCwgdHlwZW9mIHdpbmRvdyAhPSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogKHR5cGVvZiBzZWxmICE9IFwidW5kZWZpbmVkXCIpID8gc2VsZiA6IGdsb2JhbCkpO1xuXG59KS5jYWxsKHRoaXMsdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KSIsIihmdW5jdGlvbiAocHJvY2Vzcyl7XG4vKipcbiAqIEBkZXBlbmQgLi4vc2lub24uanNcbiAqL1xuLypqc2xpbnQgZXFlcWVxOiBmYWxzZSwgb25ldmFyOiBmYWxzZSovXG4vKmdsb2JhbCBtb2R1bGUsIHJlcXVpcmUsIHNpbm9uLCBwcm9jZXNzLCBzZXRJbW1lZGlhdGUsIHNldFRpbWVvdXQqL1xuLyoqXG4gKiBTdHViIGJlaGF2aW9yXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAYXV0aG9yIFRpbSBGaXNjaGJhY2ggKG1haWxAdGltZmlzY2hiYWNoLmRlKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKHNpbm9uKSB7XG4gICAgdmFyIGNvbW1vbkpTTW9kdWxlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG5cbiAgICBpZiAoIXNpbm9uICYmIGNvbW1vbkpTTW9kdWxlKSB7XG4gICAgICAgIHNpbm9uID0gcmVxdWlyZShcIi4uL3Npbm9uXCIpO1xuICAgIH1cblxuICAgIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcbiAgICB2YXIgam9pbiA9IEFycmF5LnByb3RvdHlwZS5qb2luO1xuICAgIHZhciBwcm90bztcblxuICAgIHZhciBuZXh0VGljayA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcHJvY2VzcyA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgcHJvY2Vzcy5uZXh0VGljayA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzcy5uZXh0VGljaztcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygc2V0SW1tZWRpYXRlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBzZXRJbW1lZGlhdGU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChjYWxsYmFjaywgMCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfSkoKTtcblxuICAgIGZ1bmN0aW9uIHRocm93c0V4Y2VwdGlvbihlcnJvciwgbWVzc2FnZSkge1xuICAgICAgICBpZiAodHlwZW9mIGVycm9yID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIHRoaXMuZXhjZXB0aW9uID0gbmV3IEVycm9yKG1lc3NhZ2UgfHwgXCJcIik7XG4gICAgICAgICAgICB0aGlzLmV4Y2VwdGlvbi5uYW1lID0gZXJyb3I7XG4gICAgICAgIH0gZWxzZSBpZiAoIWVycm9yKSB7XG4gICAgICAgICAgICB0aGlzLmV4Y2VwdGlvbiA9IG5ldyBFcnJvcihcIkVycm9yXCIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5leGNlcHRpb24gPSBlcnJvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldENhbGxiYWNrKGJlaGF2aW9yLCBhcmdzKSB7XG4gICAgICAgIHZhciBjYWxsQXJnQXQgPSBiZWhhdmlvci5jYWxsQXJnQXQ7XG5cbiAgICAgICAgaWYgKGNhbGxBcmdBdCA8IDApIHtcbiAgICAgICAgICAgIHZhciBjYWxsQXJnUHJvcCA9IGJlaGF2aW9yLmNhbGxBcmdQcm9wO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGFyZ3MubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFjYWxsQXJnUHJvcCAmJiB0eXBlb2YgYXJnc1tpXSA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFyZ3NbaV07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGNhbGxBcmdQcm9wICYmIGFyZ3NbaV0gJiZcbiAgICAgICAgICAgICAgICAgICAgdHlwZW9mIGFyZ3NbaV1bY2FsbEFyZ1Byb3BdID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXJnc1tpXVtjYWxsQXJnUHJvcF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhcmdzW2NhbGxBcmdBdF07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Q2FsbGJhY2tFcnJvcihiZWhhdmlvciwgZnVuYywgYXJncykge1xuICAgICAgICBpZiAoYmVoYXZpb3IuY2FsbEFyZ0F0IDwgMCkge1xuICAgICAgICAgICAgdmFyIG1zZztcblxuICAgICAgICAgICAgaWYgKGJlaGF2aW9yLmNhbGxBcmdQcm9wKSB7XG4gICAgICAgICAgICAgICAgbXNnID0gc2lub24uZnVuY3Rpb25OYW1lKGJlaGF2aW9yLnN0dWIpICtcbiAgICAgICAgICAgICAgICAgICAgXCIgZXhwZWN0ZWQgdG8geWllbGQgdG8gJ1wiICsgYmVoYXZpb3IuY2FsbEFyZ1Byb3AgK1xuICAgICAgICAgICAgICAgICAgICBcIicsIGJ1dCBubyBvYmplY3Qgd2l0aCBzdWNoIGEgcHJvcGVydHkgd2FzIHBhc3NlZC5cIjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbXNnID0gc2lub24uZnVuY3Rpb25OYW1lKGJlaGF2aW9yLnN0dWIpICtcbiAgICAgICAgICAgICAgICAgICAgXCIgZXhwZWN0ZWQgdG8geWllbGQsIGJ1dCBubyBjYWxsYmFjayB3YXMgcGFzc2VkLlwiO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgbXNnICs9IFwiIFJlY2VpdmVkIFtcIiArIGpvaW4uY2FsbChhcmdzLCBcIiwgXCIpICsgXCJdXCI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBtc2c7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gXCJhcmd1bWVudCBhdCBpbmRleCBcIiArIGJlaGF2aW9yLmNhbGxBcmdBdCArIFwiIGlzIG5vdCBhIGZ1bmN0aW9uOiBcIiArIGZ1bmM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2FsbENhbGxiYWNrKGJlaGF2aW9yLCBhcmdzKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYmVoYXZpb3IuY2FsbEFyZ0F0ID09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgIHZhciBmdW5jID0gZ2V0Q2FsbGJhY2soYmVoYXZpb3IsIGFyZ3MpO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIGZ1bmMgIT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihnZXRDYWxsYmFja0Vycm9yKGJlaGF2aW9yLCBmdW5jLCBhcmdzKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChiZWhhdmlvci5jYWxsYmFja0FzeW5jKSB7XG4gICAgICAgICAgICAgICAgbmV4dFRpY2soZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIGZ1bmMuYXBwbHkoYmVoYXZpb3IuY2FsbGJhY2tDb250ZXh0LCBiZWhhdmlvci5jYWxsYmFja0FyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGZ1bmMuYXBwbHkoYmVoYXZpb3IuY2FsbGJhY2tDb250ZXh0LCBiZWhhdmlvci5jYWxsYmFja0FyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcm90byA9IHtcbiAgICAgICAgY3JlYXRlOiBmdW5jdGlvbihzdHViKSB7XG4gICAgICAgICAgICB2YXIgYmVoYXZpb3IgPSBzaW5vbi5leHRlbmQoe30sIHNpbm9uLmJlaGF2aW9yKTtcbiAgICAgICAgICAgIGRlbGV0ZSBiZWhhdmlvci5jcmVhdGU7XG4gICAgICAgICAgICBiZWhhdmlvci5zdHViID0gc3R1YjtcblxuICAgICAgICAgICAgcmV0dXJuIGJlaGF2aW9yO1xuICAgICAgICB9LFxuXG4gICAgICAgIGlzUHJlc2VudDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gKHR5cGVvZiB0aGlzLmNhbGxBcmdBdCA9PSAnbnVtYmVyJyB8fFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmV4Y2VwdGlvbiB8fFxuICAgICAgICAgICAgICAgICAgICB0eXBlb2YgdGhpcy5yZXR1cm5BcmdBdCA9PSAnbnVtYmVyJyB8fFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJldHVyblRoaXMgfHxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXR1cm5WYWx1ZURlZmluZWQpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGludm9rZTogZnVuY3Rpb24oY29udGV4dCwgYXJncykge1xuICAgICAgICAgICAgY2FsbENhbGxiYWNrKHRoaXMsIGFyZ3MpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5leGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyB0aGlzLmV4Y2VwdGlvbjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaXMucmV0dXJuQXJnQXQgPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXJnc1t0aGlzLnJldHVybkFyZ0F0XTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5yZXR1cm5UaGlzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJldHVyblZhbHVlO1xuICAgICAgICB9LFxuXG4gICAgICAgIG9uQ2FsbDogZnVuY3Rpb24oaW5kZXgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0dWIub25DYWxsKGluZGV4KTtcbiAgICAgICAgfSxcblxuICAgICAgICBvbkZpcnN0Q2FsbDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdHViLm9uRmlyc3RDYWxsKCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgb25TZWNvbmRDYWxsOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0dWIub25TZWNvbmRDYWxsKCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgb25UaGlyZENhbGw6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3R1Yi5vblRoaXJkQ2FsbCgpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHdpdGhBcmdzOiBmdW5jdGlvbigvKiBhcmd1bWVudHMgKi8pIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRGVmaW5pbmcgYSBzdHViIGJ5IGludm9raW5nIFwic3R1Yi5vbkNhbGwoLi4uKS53aXRoQXJncyguLi4pXCIgaXMgbm90IHN1cHBvcnRlZC4gJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJ1VzZSBcInN0dWIud2l0aEFyZ3MoLi4uKS5vbkNhbGwoLi4uKVwiIHRvIGRlZmluZSBzZXF1ZW50aWFsIGJlaGF2aW9yIGZvciBjYWxscyB3aXRoIGNlcnRhaW4gYXJndW1lbnRzLicpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGNhbGxzQXJnOiBmdW5jdGlvbiBjYWxsc0FyZyhwb3MpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcG9zICE9IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgaW5kZXggaXMgbm90IG51bWJlclwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jYWxsQXJnQXQgPSBwb3M7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXJndW1lbnRzID0gW107XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrQ29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMuY2FsbEFyZ1Byb3AgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXN5bmMgPSBmYWxzZTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG5cbiAgICAgICAgY2FsbHNBcmdPbjogZnVuY3Rpb24gY2FsbHNBcmdPbihwb3MsIGNvbnRleHQpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcG9zICE9IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgaW5kZXggaXMgbm90IG51bWJlclwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgY29udGV4dCAhPSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcImFyZ3VtZW50IGNvbnRleHQgaXMgbm90IGFuIG9iamVjdFwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jYWxsQXJnQXQgPSBwb3M7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXJndW1lbnRzID0gW107XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrQ29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgICAgICB0aGlzLmNhbGxBcmdQcm9wID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FzeW5jID0gZmFsc2U7XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9LFxuXG4gICAgICAgIGNhbGxzQXJnV2l0aDogZnVuY3Rpb24gY2FsbHNBcmdXaXRoKHBvcykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBwb3MgIT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBpbmRleCBpcyBub3QgbnVtYmVyXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmNhbGxBcmdBdCA9IHBvcztcbiAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBcmd1bWVudHMgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrQ29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMuY2FsbEFyZ1Byb3AgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXN5bmMgPSBmYWxzZTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG5cbiAgICAgICAgY2FsbHNBcmdPbldpdGg6IGZ1bmN0aW9uIGNhbGxzQXJnV2l0aChwb3MsIGNvbnRleHQpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcG9zICE9IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgaW5kZXggaXMgbm90IG51bWJlclwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgY29udGV4dCAhPSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcImFyZ3VtZW50IGNvbnRleHQgaXMgbm90IGFuIG9iamVjdFwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jYWxsQXJnQXQgPSBwb3M7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXJndW1lbnRzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgICAgICAgICAgdGhpcy5jYWxsYmFja0NvbnRleHQgPSBjb250ZXh0O1xuICAgICAgICAgICAgdGhpcy5jYWxsQXJnUHJvcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSxcblxuICAgICAgICB5aWVsZHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuY2FsbEFyZ0F0ID0gLTE7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXJndW1lbnRzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuICAgICAgICAgICAgdGhpcy5jYWxsYmFja0NvbnRleHQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLmNhbGxBcmdQcm9wID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FzeW5jID0gZmFsc2U7XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9LFxuXG4gICAgICAgIHlpZWxkc09uOiBmdW5jdGlvbiAoY29udGV4dCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBjb250ZXh0ICE9IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgY29udGV4dCBpcyBub3QgYW4gb2JqZWN0XCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmNhbGxBcmdBdCA9IC0xO1xuICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FyZ3VtZW50cyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tDb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgICAgIHRoaXMuY2FsbEFyZ1Byb3AgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXN5bmMgPSBmYWxzZTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG5cbiAgICAgICAgeWllbGRzVG86IGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGxBcmdBdCA9IC0xO1xuICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FyZ3VtZW50cyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tDb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgdGhpcy5jYWxsQXJnUHJvcCA9IHByb3A7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXN5bmMgPSBmYWxzZTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG5cbiAgICAgICAgeWllbGRzVG9PbjogZnVuY3Rpb24gKHByb3AsIGNvbnRleHQpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY29udGV4dCAhPSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcImFyZ3VtZW50IGNvbnRleHQgaXMgbm90IGFuIG9iamVjdFwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jYWxsQXJnQXQgPSAtMTtcbiAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBcmd1bWVudHMgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrQ29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgICAgICB0aGlzLmNhbGxBcmdQcm9wID0gcHJvcDtcbiAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSxcblxuXG4gICAgICAgIFwidGhyb3dzXCI6IHRocm93c0V4Y2VwdGlvbixcbiAgICAgICAgdGhyb3dzRXhjZXB0aW9uOiB0aHJvd3NFeGNlcHRpb24sXG5cbiAgICAgICAgcmV0dXJuczogZnVuY3Rpb24gcmV0dXJucyh2YWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5yZXR1cm5WYWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgdGhpcy5yZXR1cm5WYWx1ZURlZmluZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSxcblxuICAgICAgICByZXR1cm5zQXJnOiBmdW5jdGlvbiByZXR1cm5zQXJnKHBvcykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBwb3MgIT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBpbmRleCBpcyBub3QgbnVtYmVyXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJldHVybkFyZ0F0ID0gcG9zO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSxcblxuICAgICAgICByZXR1cm5zVGhpczogZnVuY3Rpb24gcmV0dXJuc1RoaXMoKSB7XG4gICAgICAgICAgICB0aGlzLnJldHVyblRoaXMgPSB0cnVlO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBjcmVhdGUgYXN5bmNocm9ub3VzIHZlcnNpb25zIG9mIGNhbGxzQXJnKiBhbmQgeWllbGRzKiBtZXRob2RzXG4gICAgZm9yICh2YXIgbWV0aG9kIGluIHByb3RvKSB7XG4gICAgICAgIC8vIG5lZWQgdG8gYXZvaWQgY3JlYXRpbmcgYW5vdGhlcmFzeW5jIHZlcnNpb25zIG9mIHRoZSBuZXdseSBhZGRlZCBhc3luYyBtZXRob2RzXG4gICAgICAgIGlmIChwcm90by5oYXNPd25Qcm9wZXJ0eShtZXRob2QpICYmXG4gICAgICAgICAgICBtZXRob2QubWF0Y2goL14oY2FsbHNBcmd8eWllbGRzKS8pICYmXG4gICAgICAgICAgICAhbWV0aG9kLm1hdGNoKC9Bc3luYy8pKSB7XG4gICAgICAgICAgICBwcm90b1ttZXRob2QgKyAnQXN5bmMnXSA9IChmdW5jdGlvbiAoc3luY0ZuTmFtZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB0aGlzW3N5bmNGbk5hbWVdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0pKG1ldGhvZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBzaW5vbi5iZWhhdmlvciA9IHByb3RvO1xuXG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJtb2R1bGVcIl0sIGZ1bmN0aW9uKG1vZHVsZSkgeyBtb2R1bGUuZXhwb3J0cyA9IHByb3RvOyB9KTtcbiAgICB9IGVsc2UgaWYgKGNvbW1vbkpTTW9kdWxlKSB7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gcHJvdG87XG4gICAgfVxufSh0eXBlb2Ygc2lub24gPT0gXCJvYmplY3RcIiAmJiBzaW5vbiB8fCBudWxsKSk7XG5cbn0pLmNhbGwodGhpcyxyZXF1aXJlKFwiMVlpWjVTXCIpKSIsIi8qKlxuICAqIEBkZXBlbmQgLi4vc2lub24uanNcbiAgKiBAZGVwZW5kIG1hdGNoLmpzXG4gICovXG4vKmpzbGludCBlcWVxZXE6IGZhbHNlLCBvbmV2YXI6IGZhbHNlLCBwbHVzcGx1czogZmFsc2UqL1xuLypnbG9iYWwgbW9kdWxlLCByZXF1aXJlLCBzaW5vbiovXG4vKipcbiAgKiBTcHkgY2FsbHNcbiAgKlxuICAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICAqIEBhdXRob3IgTWF4aW1pbGlhbiBBbnRvbmkgKG1haWxAbWF4YW50b25pLmRlKVxuICAqIEBsaWNlbnNlIEJTRFxuICAqXG4gICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gICogQ29weXJpZ2h0IChjKSAyMDEzIE1heGltaWxpYW4gQW50b25pXG4gICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIHZhciBjb21tb25KU01vZHVsZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIGlmICghc2lub24gJiYgY29tbW9uSlNNb2R1bGUpIHtcbiAgICAgICAgc2lub24gPSByZXF1aXJlKFwiLi4vc2lub25cIik7XG4gICAgfVxuXG4gICAgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdGhyb3dZaWVsZEVycm9yKHByb3h5LCB0ZXh0LCBhcmdzKSB7XG4gICAgICAgIHZhciBtc2cgPSBzaW5vbi5mdW5jdGlvbk5hbWUocHJveHkpICsgdGV4dDtcbiAgICAgICAgaWYgKGFyZ3MubGVuZ3RoKSB7XG4gICAgICAgICAgICBtc2cgKz0gXCIgUmVjZWl2ZWQgW1wiICsgc2xpY2UuY2FsbChhcmdzKS5qb2luKFwiLCBcIikgKyBcIl1cIjtcbiAgICAgICAgfVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcbiAgICB9XG5cbiAgICB2YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG5cbiAgICB2YXIgY2FsbFByb3RvID0ge1xuICAgICAgICBjYWxsZWRPbjogZnVuY3Rpb24gY2FsbGVkT24odGhpc1ZhbHVlKSB7XG4gICAgICAgICAgICBpZiAoc2lub24ubWF0Y2ggJiYgc2lub24ubWF0Y2guaXNNYXRjaGVyKHRoaXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpc1ZhbHVlLnRlc3QodGhpcy50aGlzVmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGhpc1ZhbHVlID09PSB0aGlzVmFsdWU7XG4gICAgICAgIH0sXG5cbiAgICAgICAgY2FsbGVkV2l0aDogZnVuY3Rpb24gY2FsbGVkV2l0aCgpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IGw7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgIGlmICghc2lub24uZGVlcEVxdWFsKGFyZ3VtZW50c1tpXSwgdGhpcy5hcmdzW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSxcblxuICAgICAgICBjYWxsZWRXaXRoTWF0Y2g6IGZ1bmN0aW9uIGNhbGxlZFdpdGhNYXRjaCgpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IGw7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgIHZhciBhY3R1YWwgPSB0aGlzLmFyZ3NbaV07XG4gICAgICAgICAgICAgICAgdmFyIGV4cGVjdGF0aW9uID0gYXJndW1lbnRzW2ldO1xuICAgICAgICAgICAgICAgIGlmICghc2lub24ubWF0Y2ggfHwgIXNpbm9uLm1hdGNoKGV4cGVjdGF0aW9uKS50ZXN0KGFjdHVhbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9LFxuXG4gICAgICAgIGNhbGxlZFdpdGhFeGFjdGx5OiBmdW5jdGlvbiBjYWxsZWRXaXRoRXhhY3RseSgpIHtcbiAgICAgICAgICAgIHJldHVybiBhcmd1bWVudHMubGVuZ3RoID09IHRoaXMuYXJncy5sZW5ndGggJiZcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxlZFdpdGguYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfSxcblxuICAgICAgICBub3RDYWxsZWRXaXRoOiBmdW5jdGlvbiBub3RDYWxsZWRXaXRoKCkge1xuICAgICAgICAgICAgcmV0dXJuICF0aGlzLmNhbGxlZFdpdGguYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfSxcblxuICAgICAgICBub3RDYWxsZWRXaXRoTWF0Y2g6IGZ1bmN0aW9uIG5vdENhbGxlZFdpdGhNYXRjaCgpIHtcbiAgICAgICAgICAgIHJldHVybiAhdGhpcy5jYWxsZWRXaXRoTWF0Y2guYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfSxcblxuICAgICAgICByZXR1cm5lZDogZnVuY3Rpb24gcmV0dXJuZWQodmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiBzaW5vbi5kZWVwRXF1YWwodmFsdWUsIHRoaXMucmV0dXJuVmFsdWUpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHRocmV3OiBmdW5jdGlvbiB0aHJldyhlcnJvcikge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBlcnJvciA9PT0gXCJ1bmRlZmluZWRcIiB8fCAhdGhpcy5leGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gISF0aGlzLmV4Y2VwdGlvbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXhjZXB0aW9uID09PSBlcnJvciB8fCB0aGlzLmV4Y2VwdGlvbi5uYW1lID09PSBlcnJvcjtcbiAgICAgICAgfSxcblxuICAgICAgICBjYWxsZWRXaXRoTmV3OiBmdW5jdGlvbiBjYWxsZWRXaXRoTmV3KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJveHkucHJvdG90eXBlICYmIHRoaXMudGhpc1ZhbHVlIGluc3RhbmNlb2YgdGhpcy5wcm94eTtcbiAgICAgICAgfSxcblxuICAgICAgICBjYWxsZWRCZWZvcmU6IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2FsbElkIDwgb3RoZXIuY2FsbElkO1xuICAgICAgICB9LFxuXG4gICAgICAgIGNhbGxlZEFmdGVyOiBmdW5jdGlvbiAob3RoZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNhbGxJZCA+IG90aGVyLmNhbGxJZDtcbiAgICAgICAgfSxcblxuICAgICAgICBjYWxsQXJnOiBmdW5jdGlvbiAocG9zKSB7XG4gICAgICAgICAgICB0aGlzLmFyZ3NbcG9zXSgpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGNhbGxBcmdPbjogZnVuY3Rpb24gKHBvcywgdGhpc1ZhbHVlKSB7XG4gICAgICAgICAgICB0aGlzLmFyZ3NbcG9zXS5hcHBseSh0aGlzVmFsdWUpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGNhbGxBcmdXaXRoOiBmdW5jdGlvbiAocG9zKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGxBcmdPbldpdGguYXBwbHkodGhpcywgW3BvcywgbnVsbF0uY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSkpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGNhbGxBcmdPbldpdGg6IGZ1bmN0aW9uIChwb3MsIHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgdmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgICAgICAgICB0aGlzLmFyZ3NbcG9zXS5hcHBseSh0aGlzVmFsdWUsIGFyZ3MpO1xuICAgICAgICB9LFxuXG4gICAgICAgIFwieWllbGRcIjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy55aWVsZE9uLmFwcGx5KHRoaXMsIFtudWxsXS5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMsIDApKSk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgeWllbGRPbjogZnVuY3Rpb24gKHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgdmFyIGFyZ3MgPSB0aGlzLmFyZ3M7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGFyZ3MubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhcmdzW2ldID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgYXJnc1tpXS5hcHBseSh0aGlzVmFsdWUsIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aHJvd1lpZWxkRXJyb3IodGhpcy5wcm94eSwgXCIgY2Fubm90IHlpZWxkIHNpbmNlIG5vIGNhbGxiYWNrIHdhcyBwYXNzZWQuXCIsIGFyZ3MpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHlpZWxkVG86IGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgICAgICAgICB0aGlzLnlpZWxkVG9Pbi5hcHBseSh0aGlzLCBbcHJvcCwgbnVsbF0uY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSkpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHlpZWxkVG9PbjogZnVuY3Rpb24gKHByb3AsIHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgdmFyIGFyZ3MgPSB0aGlzLmFyZ3M7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGFyZ3MubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFyZ3NbaV0gJiYgdHlwZW9mIGFyZ3NbaV1bcHJvcF0gPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICBhcmdzW2ldW3Byb3BdLmFwcGx5KHRoaXNWYWx1ZSwgc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93WWllbGRFcnJvcih0aGlzLnByb3h5LCBcIiBjYW5ub3QgeWllbGQgdG8gJ1wiICsgcHJvcCArXG4gICAgICAgICAgICAgICAgXCInIHNpbmNlIG5vIGNhbGxiYWNrIHdhcyBwYXNzZWQuXCIsIGFyZ3MpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHRvU3RyaW5nOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgY2FsbFN0ciA9IHRoaXMucHJveHkudG9TdHJpbmcoKSArIFwiKFwiO1xuICAgICAgICAgICAgdmFyIGFyZ3MgPSBbXTtcblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSB0aGlzLmFyZ3MubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAgICAgYXJncy5wdXNoKHNpbm9uLmZvcm1hdCh0aGlzLmFyZ3NbaV0pKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY2FsbFN0ciA9IGNhbGxTdHIgKyBhcmdzLmpvaW4oXCIsIFwiKSArIFwiKVwiO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMucmV0dXJuVmFsdWUgIT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgIGNhbGxTdHIgKz0gXCIgPT4gXCIgKyBzaW5vbi5mb3JtYXQodGhpcy5yZXR1cm5WYWx1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmV4Y2VwdGlvbikge1xuICAgICAgICAgICAgICAgIGNhbGxTdHIgKz0gXCIgIVwiICsgdGhpcy5leGNlcHRpb24ubmFtZTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmV4Y2VwdGlvbi5tZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxTdHIgKz0gXCIoXCIgKyB0aGlzLmV4Y2VwdGlvbi5tZXNzYWdlICsgXCIpXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gY2FsbFN0cjtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBjYWxsUHJvdG8uaW52b2tlQ2FsbGJhY2sgPSBjYWxsUHJvdG8ueWllbGQ7XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVTcHlDYWxsKHNweSwgdGhpc1ZhbHVlLCBhcmdzLCByZXR1cm5WYWx1ZSwgZXhjZXB0aW9uLCBpZCkge1xuICAgICAgICBpZiAodHlwZW9mIGlkICE9PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2FsbCBpZCBpcyBub3QgYSBudW1iZXJcIik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHByb3h5Q2FsbCA9IHNpbm9uLmNyZWF0ZShjYWxsUHJvdG8pO1xuICAgICAgICBwcm94eUNhbGwucHJveHkgPSBzcHk7XG4gICAgICAgIHByb3h5Q2FsbC50aGlzVmFsdWUgPSB0aGlzVmFsdWU7XG4gICAgICAgIHByb3h5Q2FsbC5hcmdzID0gYXJncztcbiAgICAgICAgcHJveHlDYWxsLnJldHVyblZhbHVlID0gcmV0dXJuVmFsdWU7XG4gICAgICAgIHByb3h5Q2FsbC5leGNlcHRpb24gPSBleGNlcHRpb247XG4gICAgICAgIHByb3h5Q2FsbC5jYWxsSWQgPSBpZDtcblxuICAgICAgICByZXR1cm4gcHJveHlDYWxsO1xuICAgIH1cbiAgICBjcmVhdGVTcHlDYWxsLnRvU3RyaW5nID0gY2FsbFByb3RvLnRvU3RyaW5nOyAvLyB1c2VkIGJ5IG1vY2tzXG5cbiAgICBzaW5vbi5zcHlDYWxsID0gY3JlYXRlU3B5Q2FsbDtcblxuICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoW1wibW9kdWxlXCJdLCBmdW5jdGlvbihtb2R1bGUpIHsgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVTcHlDYWxsOyB9KTtcbiAgICB9IGVsc2UgaWYgKGNvbW1vbkpTTW9kdWxlKSB7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlU3B5Q2FsbDtcbiAgICB9XG59KHR5cGVvZiBzaW5vbiA9PSBcIm9iamVjdFwiICYmIHNpbm9uIHx8IG51bGwpKTtcblxuIiwiLyoqXG4gKiBAZGVwZW5kIC4uL3Npbm9uLmpzXG4gKiBAZGVwZW5kIHN0dWIuanNcbiAqIEBkZXBlbmQgbW9jay5qc1xuICovXG4vKmpzbGludCBlcWVxZXE6IGZhbHNlLCBvbmV2YXI6IGZhbHNlLCBmb3JpbjogdHJ1ZSovXG4vKmdsb2JhbCBtb2R1bGUsIHJlcXVpcmUsIHNpbm9uKi9cbi8qKlxuICogQ29sbGVjdGlvbnMgb2Ygc3R1YnMsIHNwaWVzIGFuZCBtb2Nrcy5cbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIHZhciBjb21tb25KU01vZHVsZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBwdXNoID0gW10ucHVzaDtcbiAgICB2YXIgaGFzT3duUHJvcGVydHkgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5O1xuXG4gICAgaWYgKCFzaW5vbiAmJiBjb21tb25KU01vZHVsZSkge1xuICAgICAgICBzaW5vbiA9IHJlcXVpcmUoXCIuLi9zaW5vblwiKTtcbiAgICB9XG5cbiAgICBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRGYWtlcyhmYWtlQ29sbGVjdGlvbikge1xuICAgICAgICBpZiAoIWZha2VDb2xsZWN0aW9uLmZha2VzKSB7XG4gICAgICAgICAgICBmYWtlQ29sbGVjdGlvbi5mYWtlcyA9IFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZha2VDb2xsZWN0aW9uLmZha2VzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVhY2goZmFrZUNvbGxlY3Rpb24sIG1ldGhvZCkge1xuICAgICAgICB2YXIgZmFrZXMgPSBnZXRGYWtlcyhmYWtlQ29sbGVjdGlvbik7XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBmYWtlcy5sZW5ndGg7IGkgPCBsOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZmFrZXNbaV1bbWV0aG9kXSA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICBmYWtlc1tpXVttZXRob2RdKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb21wYWN0KGZha2VDb2xsZWN0aW9uKSB7XG4gICAgICAgIHZhciBmYWtlcyA9IGdldEZha2VzKGZha2VDb2xsZWN0aW9uKTtcbiAgICAgICAgdmFyIGkgPSAwO1xuICAgICAgICB3aGlsZSAoaSA8IGZha2VzLmxlbmd0aCkge1xuICAgICAgICAgIGZha2VzLnNwbGljZShpLCAxKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBjb2xsZWN0aW9uID0ge1xuICAgICAgICB2ZXJpZnk6IGZ1bmN0aW9uIHJlc29sdmUoKSB7XG4gICAgICAgICAgICBlYWNoKHRoaXMsIFwidmVyaWZ5XCIpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHJlc3RvcmU6IGZ1bmN0aW9uIHJlc3RvcmUoKSB7XG4gICAgICAgICAgICBlYWNoKHRoaXMsIFwicmVzdG9yZVwiKTtcbiAgICAgICAgICAgIGNvbXBhY3QodGhpcyk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgdmVyaWZ5QW5kUmVzdG9yZTogZnVuY3Rpb24gdmVyaWZ5QW5kUmVzdG9yZSgpIHtcbiAgICAgICAgICAgIHZhciBleGNlcHRpb247XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdGhpcy52ZXJpZnkoKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBleGNlcHRpb24gPSBlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnJlc3RvcmUoKTtcblxuICAgICAgICAgICAgaWYgKGV4Y2VwdGlvbikge1xuICAgICAgICAgICAgICAgIHRocm93IGV4Y2VwdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBhZGQ6IGZ1bmN0aW9uIGFkZChmYWtlKSB7XG4gICAgICAgICAgICBwdXNoLmNhbGwoZ2V0RmFrZXModGhpcyksIGZha2UpO1xuICAgICAgICAgICAgcmV0dXJuIGZha2U7XG4gICAgICAgIH0sXG5cbiAgICAgICAgc3B5OiBmdW5jdGlvbiBzcHkoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQoc2lub24uc3B5LmFwcGx5KHNpbm9uLCBhcmd1bWVudHMpKTtcbiAgICAgICAgfSxcblxuICAgICAgICBzdHViOiBmdW5jdGlvbiBzdHViKG9iamVjdCwgcHJvcGVydHksIHZhbHVlKSB7XG4gICAgICAgICAgICBpZiAocHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICB2YXIgb3JpZ2luYWwgPSBvYmplY3RbcHJvcGVydHldO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvcmlnaW5hbCAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHN0dWIgbm9uLWV4aXN0ZW50IG93biBwcm9wZXJ0eSBcIiArIHByb3BlcnR5KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIG9iamVjdFtwcm9wZXJ0eV0gPSB2YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdG9yZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdFtwcm9wZXJ0eV0gPSBvcmlnaW5hbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFwcm9wZXJ0eSAmJiAhIW9iamVjdCAmJiB0eXBlb2Ygb2JqZWN0ID09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICB2YXIgc3R1YmJlZE9iaiA9IHNpbm9uLnN0dWIuYXBwbHkoc2lub24sIGFyZ3VtZW50cyk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wIGluIHN0dWJiZWRPYmopIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzdHViYmVkT2JqW3Byb3BdID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkKHN0dWJiZWRPYmpbcHJvcF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHN0dWJiZWRPYmo7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFkZChzaW5vbi5zdHViLmFwcGx5KHNpbm9uLCBhcmd1bWVudHMpKTtcbiAgICAgICAgfSxcblxuICAgICAgICBtb2NrOiBmdW5jdGlvbiBtb2NrKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRkKHNpbm9uLm1vY2suYXBwbHkoc2lub24sIGFyZ3VtZW50cykpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGluamVjdDogZnVuY3Rpb24gaW5qZWN0KG9iaikge1xuICAgICAgICAgICAgdmFyIGNvbCA9IHRoaXM7XG5cbiAgICAgICAgICAgIG9iai5zcHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbC5zcHkuYXBwbHkoY29sLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgb2JqLnN0dWIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbC5zdHViLmFwcGx5KGNvbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIG9iai5tb2NrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjb2wubW9jay5hcHBseShjb2wsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHNpbm9uLmNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uO1xuXG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJtb2R1bGVcIl0sIGZ1bmN0aW9uKG1vZHVsZSkgeyBtb2R1bGUuZXhwb3J0cyA9IGNvbGxlY3Rpb247IH0pO1xuICAgIH0gZWxzZSBpZiAoY29tbW9uSlNNb2R1bGUpIHtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjb2xsZWN0aW9uO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyogQGRlcGVuZCAuLi9zaW5vbi5qcyAqL1xuLypqc2xpbnQgZXFlcWVxOiBmYWxzZSwgb25ldmFyOiBmYWxzZSwgcGx1c3BsdXM6IGZhbHNlKi9cbi8qZ2xvYmFsIG1vZHVsZSwgcmVxdWlyZSwgc2lub24qL1xuLyoqXG4gKiBNYXRjaCBmdW5jdGlvbnNcbiAqXG4gKiBAYXV0aG9yIE1heGltaWxpYW4gQW50b25pIChtYWlsQG1heGFudG9uaS5kZSlcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMiBNYXhpbWlsaWFuIEFudG9uaVxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIHZhciBjb21tb25KU01vZHVsZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuXG4gICAgaWYgKCFzaW5vbiAmJiBjb21tb25KU01vZHVsZSkge1xuICAgICAgICBzaW5vbiA9IHJlcXVpcmUoXCIuLi9zaW5vblwiKTtcbiAgICB9XG5cbiAgICBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhc3NlcnRUeXBlKHZhbHVlLCB0eXBlLCBuYW1lKSB7XG4gICAgICAgIHZhciBhY3R1YWwgPSBzaW5vbi50eXBlT2YodmFsdWUpO1xuICAgICAgICBpZiAoYWN0dWFsICE9PSB0eXBlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiRXhwZWN0ZWQgdHlwZSBvZiBcIiArIG5hbWUgKyBcIiB0byBiZSBcIiArXG4gICAgICAgICAgICAgICAgdHlwZSArIFwiLCBidXQgd2FzIFwiICsgYWN0dWFsKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBtYXRjaGVyID0ge1xuICAgICAgICB0b1N0cmluZzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubWVzc2FnZTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiBpc01hdGNoZXIob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBtYXRjaGVyLmlzUHJvdG90eXBlT2Yob2JqZWN0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYXRjaE9iamVjdChleHBlY3RhdGlvbiwgYWN0dWFsKSB7XG4gICAgICAgIGlmIChhY3R1YWwgPT09IG51bGwgfHwgYWN0dWFsID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBrZXkgaW4gZXhwZWN0YXRpb24pIHtcbiAgICAgICAgICAgIGlmIChleHBlY3RhdGlvbi5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGV4cCA9IGV4cGVjdGF0aW9uW2tleV07XG4gICAgICAgICAgICAgICAgdmFyIGFjdCA9IGFjdHVhbFtrZXldO1xuICAgICAgICAgICAgICAgIGlmIChtYXRjaC5pc01hdGNoZXIoZXhwKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWV4cC50ZXN0KGFjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc2lub24udHlwZU9mKGV4cCkgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFtYXRjaE9iamVjdChleHAsIGFjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIXNpbm9uLmRlZXBFcXVhbChleHAsIGFjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBtYXRjaGVyLm9yID0gZnVuY3Rpb24gKG0yKSB7XG4gICAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk1hdGNoZXIgZXhwZWN0ZWRcIik7XG4gICAgICAgIH0gZWxzZSBpZiAoIWlzTWF0Y2hlcihtMikpIHtcbiAgICAgICAgICAgIG0yID0gbWF0Y2gobTIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtMSA9IHRoaXM7XG4gICAgICAgIHZhciBvciA9IHNpbm9uLmNyZWF0ZShtYXRjaGVyKTtcbiAgICAgICAgb3IudGVzdCA9IGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgIHJldHVybiBtMS50ZXN0KGFjdHVhbCkgfHwgbTIudGVzdChhY3R1YWwpO1xuICAgICAgICB9O1xuICAgICAgICBvci5tZXNzYWdlID0gbTEubWVzc2FnZSArIFwiLm9yKFwiICsgbTIubWVzc2FnZSArIFwiKVwiO1xuICAgICAgICByZXR1cm4gb3I7XG4gICAgfTtcblxuICAgIG1hdGNoZXIuYW5kID0gZnVuY3Rpb24gKG0yKSB7XG4gICAgICAgIGlmICghYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk1hdGNoZXIgZXhwZWN0ZWRcIik7XG4gICAgICAgIH0gZWxzZSBpZiAoIWlzTWF0Y2hlcihtMikpIHtcbiAgICAgICAgICAgIG0yID0gbWF0Y2gobTIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtMSA9IHRoaXM7XG4gICAgICAgIHZhciBhbmQgPSBzaW5vbi5jcmVhdGUobWF0Y2hlcik7XG4gICAgICAgIGFuZC50ZXN0ID0gZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgcmV0dXJuIG0xLnRlc3QoYWN0dWFsKSAmJiBtMi50ZXN0KGFjdHVhbCk7XG4gICAgICAgIH07XG4gICAgICAgIGFuZC5tZXNzYWdlID0gbTEubWVzc2FnZSArIFwiLmFuZChcIiArIG0yLm1lc3NhZ2UgKyBcIilcIjtcbiAgICAgICAgcmV0dXJuIGFuZDtcbiAgICB9O1xuXG4gICAgdmFyIG1hdGNoID0gZnVuY3Rpb24gKGV4cGVjdGF0aW9uLCBtZXNzYWdlKSB7XG4gICAgICAgIHZhciBtID0gc2lub24uY3JlYXRlKG1hdGNoZXIpO1xuICAgICAgICB2YXIgdHlwZSA9IHNpbm9uLnR5cGVPZihleHBlY3RhdGlvbik7XG4gICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICBjYXNlIFwib2JqZWN0XCI6XG4gICAgICAgICAgICBpZiAodHlwZW9mIGV4cGVjdGF0aW9uLnRlc3QgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIG0udGVzdCA9IGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV4cGVjdGF0aW9uLnRlc3QoYWN0dWFsKSA9PT0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIG0ubWVzc2FnZSA9IFwibWF0Y2goXCIgKyBzaW5vbi5mdW5jdGlvbk5hbWUoZXhwZWN0YXRpb24udGVzdCkgKyBcIilcIjtcbiAgICAgICAgICAgICAgICByZXR1cm4gbTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBzdHIgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgICAgIGlmIChleHBlY3RhdGlvbi5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ci5wdXNoKGtleSArIFwiOiBcIiArIGV4cGVjdGF0aW9uW2tleV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG0udGVzdCA9IGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWF0Y2hPYmplY3QoZXhwZWN0YXRpb24sIGFjdHVhbCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgbS5tZXNzYWdlID0gXCJtYXRjaChcIiArIHN0ci5qb2luKFwiLCBcIikgKyBcIilcIjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwibnVtYmVyXCI6XG4gICAgICAgICAgICBtLnRlc3QgPSBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGV4cGVjdGF0aW9uID09IGFjdHVhbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBcInN0cmluZ1wiOlxuICAgICAgICAgICAgbS50ZXN0ID0gZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYWN0dWFsICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFjdHVhbC5pbmRleE9mKGV4cGVjdGF0aW9uKSAhPT0gLTE7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgbS5tZXNzYWdlID0gXCJtYXRjaChcXFwiXCIgKyBleHBlY3RhdGlvbiArIFwiXFxcIilcIjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwicmVnZXhwXCI6XG4gICAgICAgICAgICBtLnRlc3QgPSBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhY3R1YWwgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZXhwZWN0YXRpb24udGVzdChhY3R1YWwpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFwiZnVuY3Rpb25cIjpcbiAgICAgICAgICAgIG0udGVzdCA9IGV4cGVjdGF0aW9uO1xuICAgICAgICAgICAgaWYgKG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICBtLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtLm1lc3NhZ2UgPSBcIm1hdGNoKFwiICsgc2lub24uZnVuY3Rpb25OYW1lKGV4cGVjdGF0aW9uKSArIFwiKVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBtLnRlc3QgPSBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICAgIHJldHVybiBzaW5vbi5kZWVwRXF1YWwoZXhwZWN0YXRpb24sIGFjdHVhbCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICghbS5tZXNzYWdlKSB7XG4gICAgICAgICAgICBtLm1lc3NhZ2UgPSBcIm1hdGNoKFwiICsgZXhwZWN0YXRpb24gKyBcIilcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbTtcbiAgICB9O1xuXG4gICAgbWF0Y2guaXNNYXRjaGVyID0gaXNNYXRjaGVyO1xuXG4gICAgbWF0Y2guYW55ID0gbWF0Y2goZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9LCBcImFueVwiKTtcblxuICAgIG1hdGNoLmRlZmluZWQgPSBtYXRjaChmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgIHJldHVybiBhY3R1YWwgIT09IG51bGwgJiYgYWN0dWFsICE9PSB1bmRlZmluZWQ7XG4gICAgfSwgXCJkZWZpbmVkXCIpO1xuXG4gICAgbWF0Y2gudHJ1dGh5ID0gbWF0Y2goZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICByZXR1cm4gISFhY3R1YWw7XG4gICAgfSwgXCJ0cnV0aHlcIik7XG5cbiAgICBtYXRjaC5mYWxzeSA9IG1hdGNoKGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgcmV0dXJuICFhY3R1YWw7XG4gICAgfSwgXCJmYWxzeVwiKTtcblxuICAgIG1hdGNoLnNhbWUgPSBmdW5jdGlvbiAoZXhwZWN0YXRpb24pIHtcbiAgICAgICAgcmV0dXJuIG1hdGNoKGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgIHJldHVybiBleHBlY3RhdGlvbiA9PT0gYWN0dWFsO1xuICAgICAgICB9LCBcInNhbWUoXCIgKyBleHBlY3RhdGlvbiArIFwiKVwiKTtcbiAgICB9O1xuXG4gICAgbWF0Y2gudHlwZU9mID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgYXNzZXJ0VHlwZSh0eXBlLCBcInN0cmluZ1wiLCBcInR5cGVcIik7XG4gICAgICAgIHJldHVybiBtYXRjaChmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICByZXR1cm4gc2lub24udHlwZU9mKGFjdHVhbCkgPT09IHR5cGU7XG4gICAgICAgIH0sIFwidHlwZU9mKFxcXCJcIiArIHR5cGUgKyBcIlxcXCIpXCIpO1xuICAgIH07XG5cbiAgICBtYXRjaC5pbnN0YW5jZU9mID0gZnVuY3Rpb24gKHR5cGUpIHtcbiAgICAgICAgYXNzZXJ0VHlwZSh0eXBlLCBcImZ1bmN0aW9uXCIsIFwidHlwZVwiKTtcbiAgICAgICAgcmV0dXJuIG1hdGNoKGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgIHJldHVybiBhY3R1YWwgaW5zdGFuY2VvZiB0eXBlO1xuICAgICAgICB9LCBcImluc3RhbmNlT2YoXCIgKyBzaW5vbi5mdW5jdGlvbk5hbWUodHlwZSkgKyBcIilcIik7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIGNyZWF0ZVByb3BlcnR5TWF0Y2hlcihwcm9wZXJ0eVRlc3QsIG1lc3NhZ2VQcmVmaXgpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChwcm9wZXJ0eSwgdmFsdWUpIHtcbiAgICAgICAgICAgIGFzc2VydFR5cGUocHJvcGVydHksIFwic3RyaW5nXCIsIFwicHJvcGVydHlcIik7XG4gICAgICAgICAgICB2YXIgb25seVByb3BlcnR5ID0gYXJndW1lbnRzLmxlbmd0aCA9PT0gMTtcbiAgICAgICAgICAgIHZhciBtZXNzYWdlID0gbWVzc2FnZVByZWZpeCArIFwiKFxcXCJcIiArIHByb3BlcnR5ICsgXCJcXFwiXCI7XG4gICAgICAgICAgICBpZiAoIW9ubHlQcm9wZXJ0eSkge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UgKz0gXCIsIFwiICsgdmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtZXNzYWdlICs9IFwiKVwiO1xuICAgICAgICAgICAgcmV0dXJuIG1hdGNoKGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICBpZiAoYWN0dWFsID09PSB1bmRlZmluZWQgfHwgYWN0dWFsID09PSBudWxsIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAhcHJvcGVydHlUZXN0KGFjdHVhbCwgcHJvcGVydHkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9ubHlQcm9wZXJ0eSB8fCBzaW5vbi5kZWVwRXF1YWwodmFsdWUsIGFjdHVhbFtwcm9wZXJ0eV0pO1xuICAgICAgICAgICAgfSwgbWVzc2FnZSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgbWF0Y2guaGFzID0gY3JlYXRlUHJvcGVydHlNYXRjaGVyKGZ1bmN0aW9uIChhY3R1YWwsIHByb3BlcnR5KSB7XG4gICAgICAgIGlmICh0eXBlb2YgYWN0dWFsID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJvcGVydHkgaW4gYWN0dWFsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBhY3R1YWxbcHJvcGVydHldICE9PSB1bmRlZmluZWQ7XG4gICAgfSwgXCJoYXNcIik7XG5cbiAgICBtYXRjaC5oYXNPd24gPSBjcmVhdGVQcm9wZXJ0eU1hdGNoZXIoZnVuY3Rpb24gKGFjdHVhbCwgcHJvcGVydHkpIHtcbiAgICAgICAgcmV0dXJuIGFjdHVhbC5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eSk7XG4gICAgfSwgXCJoYXNPd25cIik7XG5cbiAgICBtYXRjaC5ib29sID0gbWF0Y2gudHlwZU9mKFwiYm9vbGVhblwiKTtcbiAgICBtYXRjaC5udW1iZXIgPSBtYXRjaC50eXBlT2YoXCJudW1iZXJcIik7XG4gICAgbWF0Y2guc3RyaW5nID0gbWF0Y2gudHlwZU9mKFwic3RyaW5nXCIpO1xuICAgIG1hdGNoLm9iamVjdCA9IG1hdGNoLnR5cGVPZihcIm9iamVjdFwiKTtcbiAgICBtYXRjaC5mdW5jID0gbWF0Y2gudHlwZU9mKFwiZnVuY3Rpb25cIik7XG4gICAgbWF0Y2guYXJyYXkgPSBtYXRjaC50eXBlT2YoXCJhcnJheVwiKTtcbiAgICBtYXRjaC5yZWdleHAgPSBtYXRjaC50eXBlT2YoXCJyZWdleHBcIik7XG4gICAgbWF0Y2guZGF0ZSA9IG1hdGNoLnR5cGVPZihcImRhdGVcIik7XG5cbiAgICBzaW5vbi5tYXRjaCA9IG1hdGNoO1xuXG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJtb2R1bGVcIl0sIGZ1bmN0aW9uKG1vZHVsZSkgeyBtb2R1bGUuZXhwb3J0cyA9IG1hdGNoOyB9KTtcbiAgICB9IGVsc2UgaWYgKGNvbW1vbkpTTW9kdWxlKSB7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbWF0Y2g7XG4gICAgfVxufSh0eXBlb2Ygc2lub24gPT0gXCJvYmplY3RcIiAmJiBzaW5vbiB8fCBudWxsKSk7XG4iLCIvKipcbiAqIEBkZXBlbmQgLi4vc2lub24uanNcbiAqIEBkZXBlbmQgc3R1Yi5qc1xuICovXG4vKmpzbGludCBlcWVxZXE6IGZhbHNlLCBvbmV2YXI6IGZhbHNlLCBub21lbjogZmFsc2UqL1xuLypnbG9iYWwgbW9kdWxlLCByZXF1aXJlLCBzaW5vbiovXG4vKipcbiAqIE1vY2sgZnVuY3Rpb25zLlxuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKHNpbm9uKSB7XG4gICAgdmFyIGNvbW1vbkpTTW9kdWxlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIHB1c2ggPSBbXS5wdXNoO1xuICAgIHZhciBtYXRjaDtcblxuICAgIGlmICghc2lub24gJiYgY29tbW9uSlNNb2R1bGUpIHtcbiAgICAgICAgc2lub24gPSByZXF1aXJlKFwiLi4vc2lub25cIik7XG4gICAgfVxuXG4gICAgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbWF0Y2ggPSBzaW5vbi5tYXRjaDtcblxuICAgIGlmICghbWF0Y2ggJiYgY29tbW9uSlNNb2R1bGUpIHtcbiAgICAgICAgbWF0Y2ggPSByZXF1aXJlKFwiLi9tYXRjaFwiKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb2NrKG9iamVjdCkge1xuICAgICAgICBpZiAoIW9iamVjdCkge1xuICAgICAgICAgICAgcmV0dXJuIHNpbm9uLmV4cGVjdGF0aW9uLmNyZWF0ZShcIkFub255bW91cyBtb2NrXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1vY2suY3JlYXRlKG9iamVjdCk7XG4gICAgfVxuXG4gICAgc2lub24ubW9jayA9IG1vY2s7XG5cbiAgICBzaW5vbi5leHRlbmQobW9jaywgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgZnVuY3Rpb24gZWFjaChjb2xsZWN0aW9uLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgaWYgKCFjb2xsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGNvbGxlY3Rpb24ubGVuZ3RoOyBpIDwgbDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soY29sbGVjdGlvbltpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUob2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgaWYgKCFvYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIm9iamVjdCBpcyBudWxsXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtb2NrT2JqZWN0ID0gc2lub24uZXh0ZW5kKHt9LCBtb2NrKTtcbiAgICAgICAgICAgICAgICBtb2NrT2JqZWN0Lm9iamVjdCA9IG9iamVjdDtcbiAgICAgICAgICAgICAgICBkZWxldGUgbW9ja09iamVjdC5jcmVhdGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbW9ja09iamVjdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGV4cGVjdHM6IGZ1bmN0aW9uIGV4cGVjdHMobWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFtZXRob2QpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIm1ldGhvZCBpcyBmYWxzeVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuZXhwZWN0YXRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXhwZWN0YXRpb25zID0ge307XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJveGllcyA9IFtdO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5leHBlY3RhdGlvbnNbbWV0aG9kXSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV4cGVjdGF0aW9uc1ttZXRob2RdID0gW107XG4gICAgICAgICAgICAgICAgICAgIHZhciBtb2NrT2JqZWN0ID0gdGhpcztcblxuICAgICAgICAgICAgICAgICAgICBzaW5vbi53cmFwTWV0aG9kKHRoaXMub2JqZWN0LCBtZXRob2QsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtb2NrT2JqZWN0Lmludm9rZU1ldGhvZChtZXRob2QsIHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbCh0aGlzLnByb3hpZXMsIG1ldGhvZCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGV4cGVjdGF0aW9uID0gc2lub24uZXhwZWN0YXRpb24uY3JlYXRlKG1ldGhvZCk7XG4gICAgICAgICAgICAgICAgcHVzaC5jYWxsKHRoaXMuZXhwZWN0YXRpb25zW21ldGhvZF0sIGV4cGVjdGF0aW9uKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBleHBlY3RhdGlvbjtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlc3RvcmU6IGZ1bmN0aW9uIHJlc3RvcmUoKSB7XG4gICAgICAgICAgICAgICAgdmFyIG9iamVjdCA9IHRoaXMub2JqZWN0O1xuXG4gICAgICAgICAgICAgICAgZWFjaCh0aGlzLnByb3hpZXMsIGZ1bmN0aW9uIChwcm94eSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdFtwcm94eV0ucmVzdG9yZSA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdFtwcm94eV0ucmVzdG9yZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB2ZXJpZnk6IGZ1bmN0aW9uIHZlcmlmeSgpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXhwZWN0YXRpb25zID0gdGhpcy5leHBlY3RhdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2VzID0gW10sIG1ldCA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZWFjaCh0aGlzLnByb3hpZXMsIGZ1bmN0aW9uIChwcm94eSkge1xuICAgICAgICAgICAgICAgICAgICBlYWNoKGV4cGVjdGF0aW9uc1twcm94eV0sIGZ1bmN0aW9uIChleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFleHBlY3RhdGlvbi5tZXQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbChtZXNzYWdlcywgZXhwZWN0YXRpb24udG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbChtZXQsIGV4cGVjdGF0aW9uLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHRoaXMucmVzdG9yZSgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbChtZXNzYWdlcy5jb25jYXQobWV0KS5qb2luKFwiXFxuXCIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBzaW5vbi5leHBlY3RhdGlvbi5wYXNzKG1lc3NhZ2VzLmNvbmNhdChtZXQpLmpvaW4oXCJcXG5cIikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgaW52b2tlTWV0aG9kOiBmdW5jdGlvbiBpbnZva2VNZXRob2QobWV0aG9kLCB0aGlzVmFsdWUsIGFyZ3MpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXhwZWN0YXRpb25zID0gdGhpcy5leHBlY3RhdGlvbnMgJiYgdGhpcy5leHBlY3RhdGlvbnNbbWV0aG9kXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gZXhwZWN0YXRpb25zICYmIGV4cGVjdGF0aW9ucy5sZW5ndGggfHwgMCwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWV4cGVjdGF0aW9uc1tpXS5tZXQoKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgZXhwZWN0YXRpb25zW2ldLmFsbG93c0NhbGwodGhpc1ZhbHVlLCBhcmdzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV4cGVjdGF0aW9uc1tpXS5hcHBseSh0aGlzVmFsdWUsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2VzID0gW10sIGF2YWlsYWJsZSwgZXhoYXVzdGVkID0gMDtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXhwZWN0YXRpb25zW2ldLmFsbG93c0NhbGwodGhpc1ZhbHVlLCBhcmdzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXZhaWxhYmxlID0gYXZhaWxhYmxlIHx8IGV4cGVjdGF0aW9uc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV4aGF1c3RlZCArPSAxO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbChtZXNzYWdlcywgXCIgICAgXCIgKyBleHBlY3RhdGlvbnNbaV0udG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGV4aGF1c3RlZCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXZhaWxhYmxlLmFwcGx5KHRoaXNWYWx1ZSwgYXJncyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbWVzc2FnZXMudW5zaGlmdChcIlVuZXhwZWN0ZWQgY2FsbDogXCIgKyBzaW5vbi5zcHlDYWxsLnRvU3RyaW5nLmNhbGwoe1xuICAgICAgICAgICAgICAgICAgICBwcm94eTogbWV0aG9kLFxuICAgICAgICAgICAgICAgICAgICBhcmdzOiBhcmdzXG4gICAgICAgICAgICAgICAgfSkpO1xuXG4gICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbChtZXNzYWdlcy5qb2luKFwiXFxuXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9KCkpKTtcblxuICAgIHZhciB0aW1lcyA9IHNpbm9uLnRpbWVzSW5Xb3JkcztcblxuICAgIHNpbm9uLmV4cGVjdGF0aW9uID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xuICAgICAgICB2YXIgX2ludm9rZSA9IHNpbm9uLnNweS5pbnZva2U7XG5cbiAgICAgICAgZnVuY3Rpb24gY2FsbENvdW50SW5Xb3JkcyhjYWxsQ291bnQpIHtcbiAgICAgICAgICAgIGlmIChjYWxsQ291bnQgPT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBcIm5ldmVyIGNhbGxlZFwiO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJjYWxsZWQgXCIgKyB0aW1lcyhjYWxsQ291bnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gZXhwZWN0ZWRDYWxsQ291bnRJbldvcmRzKGV4cGVjdGF0aW9uKSB7XG4gICAgICAgICAgICB2YXIgbWluID0gZXhwZWN0YXRpb24ubWluQ2FsbHM7XG4gICAgICAgICAgICB2YXIgbWF4ID0gZXhwZWN0YXRpb24ubWF4Q2FsbHM7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWluID09IFwibnVtYmVyXCIgJiYgdHlwZW9mIG1heCA9PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHN0ciA9IHRpbWVzKG1pbik7XG5cbiAgICAgICAgICAgICAgICBpZiAobWluICE9IG1heCkge1xuICAgICAgICAgICAgICAgICAgICBzdHIgPSBcImF0IGxlYXN0IFwiICsgc3RyICsgXCIgYW5kIGF0IG1vc3QgXCIgKyB0aW1lcyhtYXgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBzdHI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWluID09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJhdCBsZWFzdCBcIiArIHRpbWVzKG1pbik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBcImF0IG1vc3QgXCIgKyB0aW1lcyhtYXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcmVjZWl2ZWRNaW5DYWxscyhleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgdmFyIGhhc01pbkxpbWl0ID0gdHlwZW9mIGV4cGVjdGF0aW9uLm1pbkNhbGxzID09IFwibnVtYmVyXCI7XG4gICAgICAgICAgICByZXR1cm4gIWhhc01pbkxpbWl0IHx8IGV4cGVjdGF0aW9uLmNhbGxDb3VudCA+PSBleHBlY3RhdGlvbi5taW5DYWxscztcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHJlY2VpdmVkTWF4Q2FsbHMoZXhwZWN0YXRpb24pIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZXhwZWN0YXRpb24ubWF4Q2FsbHMgIT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGV4cGVjdGF0aW9uLmNhbGxDb3VudCA9PSBleHBlY3RhdGlvbi5tYXhDYWxscztcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHZlcmlmeU1hdGNoZXIocG9zc2libGVNYXRjaGVyLCBhcmcpe1xuICAgICAgICAgICAgaWYgKG1hdGNoICYmIG1hdGNoLmlzTWF0Y2hlcihwb3NzaWJsZU1hdGNoZXIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvc3NpYmxlTWF0Y2hlci50ZXN0KGFyZyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIG1pbkNhbGxzOiAxLFxuICAgICAgICAgICAgbWF4Q2FsbHM6IDEsXG5cbiAgICAgICAgICAgIGNyZWF0ZTogZnVuY3Rpb24gY3JlYXRlKG1ldGhvZE5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXhwZWN0YXRpb24gPSBzaW5vbi5leHRlbmQoc2lub24uc3R1Yi5jcmVhdGUoKSwgc2lub24uZXhwZWN0YXRpb24pO1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBleHBlY3RhdGlvbi5jcmVhdGU7XG4gICAgICAgICAgICAgICAgZXhwZWN0YXRpb24ubWV0aG9kID0gbWV0aG9kTmFtZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBleHBlY3RhdGlvbjtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGludm9rZTogZnVuY3Rpb24gaW52b2tlKGZ1bmMsIHRoaXNWYWx1ZSwgYXJncykge1xuICAgICAgICAgICAgICAgIHRoaXMudmVyaWZ5Q2FsbEFsbG93ZWQodGhpc1ZhbHVlLCBhcmdzKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBfaW52b2tlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBhdExlYXN0OiBmdW5jdGlvbiBhdExlYXN0KG51bSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbnVtICE9IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIidcIiArIG51bSArIFwiJyBpcyBub3QgbnVtYmVyXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5saW1pdHNTZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXhDYWxscyA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubGltaXRzU2V0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLm1pbkNhbGxzID0gbnVtO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBhdE1vc3Q6IGZ1bmN0aW9uIGF0TW9zdChudW0pIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG51bSAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInXCIgKyBudW0gKyBcIicgaXMgbm90IG51bWJlclwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMubGltaXRzU2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWluQ2FsbHMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxpbWl0c1NldCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5tYXhDYWxscyA9IG51bTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgbmV2ZXI6IGZ1bmN0aW9uIG5ldmVyKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmV4YWN0bHkoMCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBvbmNlOiBmdW5jdGlvbiBvbmNlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmV4YWN0bHkoMSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB0d2ljZTogZnVuY3Rpb24gdHdpY2UoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXhhY3RseSgyKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHRocmljZTogZnVuY3Rpb24gdGhyaWNlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmV4YWN0bHkoMyk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBleGFjdGx5OiBmdW5jdGlvbiBleGFjdGx5KG51bSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbnVtICE9IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIidcIiArIG51bSArIFwiJyBpcyBub3QgYSBudW1iZXJcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5hdExlYXN0KG51bSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYXRNb3N0KG51bSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBtZXQ6IGZ1bmN0aW9uIG1ldCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gIXRoaXMuZmFpbGVkICYmIHJlY2VpdmVkTWluQ2FsbHModGhpcyk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB2ZXJpZnlDYWxsQWxsb3dlZDogZnVuY3Rpb24gdmVyaWZ5Q2FsbEFsbG93ZWQodGhpc1ZhbHVlLCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHJlY2VpdmVkTWF4Q2FsbHModGhpcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mYWlsZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBzaW5vbi5leHBlY3RhdGlvbi5mYWlsKHRoaXMubWV0aG9kICsgXCIgYWxyZWFkeSBjYWxsZWQgXCIgKyB0aW1lcyh0aGlzLm1heENhbGxzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKFwiZXhwZWN0ZWRUaGlzXCIgaW4gdGhpcyAmJiB0aGlzLmV4cGVjdGVkVGhpcyAhPT0gdGhpc1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbm9uLmV4cGVjdGF0aW9uLmZhaWwodGhpcy5tZXRob2QgKyBcIiBjYWxsZWQgd2l0aCBcIiArIHRoaXNWYWx1ZSArIFwiIGFzIHRoaXNWYWx1ZSwgZXhwZWN0ZWQgXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5leHBlY3RlZFRoaXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKFwiZXhwZWN0ZWRBcmd1bWVudHNcIiBpbiB0aGlzKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFhcmdzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbm9uLmV4cGVjdGF0aW9uLmZhaWwodGhpcy5tZXRob2QgKyBcIiByZWNlaXZlZCBubyBhcmd1bWVudHMsIGV4cGVjdGVkIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbm9uLmZvcm1hdCh0aGlzLmV4cGVjdGVkQXJndW1lbnRzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFyZ3MubGVuZ3RoIDwgdGhpcy5leHBlY3RlZEFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbCh0aGlzLm1ldGhvZCArIFwiIHJlY2VpdmVkIHRvbyBmZXcgYXJndW1lbnRzIChcIiArIHNpbm9uLmZvcm1hdChhcmdzKSArXG4gICAgICAgICAgICAgICAgICAgICAgICBcIiksIGV4cGVjdGVkIFwiICsgc2lub24uZm9ybWF0KHRoaXMuZXhwZWN0ZWRBcmd1bWVudHMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5leHBlY3RzRXhhY3RBcmdDb3VudCAmJlxuICAgICAgICAgICAgICAgICAgICBhcmdzLmxlbmd0aCAhPSB0aGlzLmV4cGVjdGVkQXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBzaW5vbi5leHBlY3RhdGlvbi5mYWlsKHRoaXMubWV0aG9kICsgXCIgcmVjZWl2ZWQgdG9vIG1hbnkgYXJndW1lbnRzIChcIiArIHNpbm9uLmZvcm1hdChhcmdzKSArXG4gICAgICAgICAgICAgICAgICAgICAgICBcIiksIGV4cGVjdGVkIFwiICsgc2lub24uZm9ybWF0KHRoaXMuZXhwZWN0ZWRBcmd1bWVudHMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRoaXMuZXhwZWN0ZWRBcmd1bWVudHMubGVuZ3RoOyBpIDwgbDsgaSArPSAxKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF2ZXJpZnlNYXRjaGVyKHRoaXMuZXhwZWN0ZWRBcmd1bWVudHNbaV0sYXJnc1tpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbm9uLmV4cGVjdGF0aW9uLmZhaWwodGhpcy5tZXRob2QgKyBcIiByZWNlaXZlZCB3cm9uZyBhcmd1bWVudHMgXCIgKyBzaW5vbi5mb3JtYXQoYXJncykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiLCBkaWRuJ3QgbWF0Y2ggXCIgKyB0aGlzLmV4cGVjdGVkQXJndW1lbnRzLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW5vbi5kZWVwRXF1YWwodGhpcy5leHBlY3RlZEFyZ3VtZW50c1tpXSwgYXJnc1tpXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbm9uLmV4cGVjdGF0aW9uLmZhaWwodGhpcy5tZXRob2QgKyBcIiByZWNlaXZlZCB3cm9uZyBhcmd1bWVudHMgXCIgKyBzaW5vbi5mb3JtYXQoYXJncykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiLCBleHBlY3RlZCBcIiArIHNpbm9uLmZvcm1hdCh0aGlzLmV4cGVjdGVkQXJndW1lbnRzKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBhbGxvd3NDYWxsOiBmdW5jdGlvbiBhbGxvd3NDYWxsKHRoaXNWYWx1ZSwgYXJncykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLm1ldCgpICYmIHJlY2VpdmVkTWF4Q2FsbHModGhpcykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChcImV4cGVjdGVkVGhpc1wiIGluIHRoaXMgJiYgdGhpcy5leHBlY3RlZFRoaXMgIT09IHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoXCJleHBlY3RlZEFyZ3VtZW50c1wiIGluIHRoaXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGFyZ3MgPSBhcmdzIHx8IFtdO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFyZ3MubGVuZ3RoIDwgdGhpcy5leHBlY3RlZEFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmV4cGVjdHNFeGFjdEFyZ0NvdW50ICYmXG4gICAgICAgICAgICAgICAgICAgIGFyZ3MubGVuZ3RoICE9IHRoaXMuZXhwZWN0ZWRBcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRoaXMuZXhwZWN0ZWRBcmd1bWVudHMubGVuZ3RoOyBpIDwgbDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdmVyaWZ5TWF0Y2hlcih0aGlzLmV4cGVjdGVkQXJndW1lbnRzW2ldLGFyZ3NbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbm9uLmRlZXBFcXVhbCh0aGlzLmV4cGVjdGVkQXJndW1lbnRzW2ldLCBhcmdzW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB3aXRoQXJnczogZnVuY3Rpb24gd2l0aEFyZ3MoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5leHBlY3RlZEFyZ3VtZW50cyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHdpdGhFeGFjdEFyZ3M6IGZ1bmN0aW9uIHdpdGhFeGFjdEFyZ3MoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53aXRoQXJncy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIHRoaXMuZXhwZWN0c0V4YWN0QXJnQ291bnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb246IGZ1bmN0aW9uIG9uKHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZXhwZWN0ZWRUaGlzID0gdGhpc1ZhbHVlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXJncyA9ICh0aGlzLmV4cGVjdGVkQXJndW1lbnRzIHx8IFtdKS5zbGljZSgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmV4cGVjdHNFeGFjdEFyZ0NvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbChhcmdzLCBcIlsuLi5dXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjYWxsU3RyID0gc2lub24uc3B5Q2FsbC50b1N0cmluZy5jYWxsKHtcbiAgICAgICAgICAgICAgICAgICAgcHJveHk6IHRoaXMubWV0aG9kIHx8IFwiYW5vbnltb3VzIG1vY2sgZXhwZWN0YXRpb25cIixcbiAgICAgICAgICAgICAgICAgICAgYXJnczogYXJnc1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBjYWxsU3RyLnJlcGxhY2UoXCIsIFsuLi5cIiwgXCJbLCAuLi5cIikgKyBcIiBcIiArXG4gICAgICAgICAgICAgICAgICAgIGV4cGVjdGVkQ2FsbENvdW50SW5Xb3Jkcyh0aGlzKTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm1ldCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkV4cGVjdGF0aW9uIG1ldDogXCIgKyBtZXNzYWdlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBcIkV4cGVjdGVkIFwiICsgbWVzc2FnZSArIFwiIChcIiArXG4gICAgICAgICAgICAgICAgICAgIGNhbGxDb3VudEluV29yZHModGhpcy5jYWxsQ291bnQpICsgXCIpXCI7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB2ZXJpZnk6IGZ1bmN0aW9uIHZlcmlmeSgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMubWV0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbCh0aGlzLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbm9uLmV4cGVjdGF0aW9uLnBhc3ModGhpcy50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHBhc3M6IGZ1bmN0aW9uKG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgc2lub24uYXNzZXJ0LnBhc3MobWVzc2FnZSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZmFpbDogZnVuY3Rpb24gKG1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXhjZXB0aW9uID0gbmV3IEVycm9yKG1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIGV4Y2VwdGlvbi5uYW1lID0gXCJFeHBlY3RhdGlvbkVycm9yXCI7XG5cbiAgICAgICAgICAgICAgICB0aHJvdyBleGNlcHRpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfSgpKTtcblxuICAgIHNpbm9uLm1vY2sgPSBtb2NrO1xuXG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJtb2R1bGVcIl0sIGZ1bmN0aW9uKG1vZHVsZSkgeyBtb2R1bGUuZXhwb3J0cyA9IG1vY2s7IH0pO1xuICAgIH0gZWxzZSBpZiAoY29tbW9uSlNNb2R1bGUpIHtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtb2NrO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIC4uL3Npbm9uLmpzXG4gKiBAZGVwZW5kIGNvbGxlY3Rpb24uanNcbiAqIEBkZXBlbmQgdXRpbC9mYWtlX3RpbWVycy5qc1xuICogQGRlcGVuZCB1dGlsL2Zha2Vfc2VydmVyX3dpdGhfY2xvY2suanNcbiAqL1xuLypqc2xpbnQgZXFlcWVxOiBmYWxzZSwgb25ldmFyOiBmYWxzZSwgcGx1c3BsdXM6IGZhbHNlKi9cbi8qZ2xvYmFsIHJlcXVpcmUsIG1vZHVsZSovXG4vKipcbiAqIE1hbmFnZXMgZmFrZSBjb2xsZWN0aW9ucyBhcyB3ZWxsIGFzIGZha2UgdXRpbGl0aWVzIHN1Y2ggYXMgU2lub24nc1xuICogdGltZXJzIGFuZCBmYWtlIFhIUiBpbXBsZW1lbnRhdGlvbiBpbiBvbmUgY29udmVuaWVudCBvYmplY3QuXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbmlmICh0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIikge1xuICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuLi9zaW5vblwiKTtcbiAgICBzaW5vbi5leHRlbmQoc2lub24sIHJlcXVpcmUoXCIuL3V0aWwvZmFrZV90aW1lcnNcIikpO1xufVxuXG4oZnVuY3Rpb24gKCkge1xuICAgIHZhciBwdXNoID0gW10ucHVzaDtcblxuICAgIGZ1bmN0aW9uIGV4cG9zZVZhbHVlKHNhbmRib3gsIGNvbmZpZywga2V5LCB2YWx1ZSkge1xuICAgICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29uZmlnLmluamVjdEludG8gJiYgIShrZXkgaW4gY29uZmlnLmluamVjdEludG8pKSB7XG4gICAgICAgICAgICBjb25maWcuaW5qZWN0SW50b1trZXldID0gdmFsdWU7XG4gICAgICAgICAgICBzYW5kYm94LmluamVjdGVkS2V5cy5wdXNoKGtleSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwdXNoLmNhbGwoc2FuZGJveC5hcmdzLCB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwcmVwYXJlU2FuZGJveEZyb21Db25maWcoY29uZmlnKSB7XG4gICAgICAgIHZhciBzYW5kYm94ID0gc2lub24uY3JlYXRlKHNpbm9uLnNhbmRib3gpO1xuXG4gICAgICAgIGlmIChjb25maWcudXNlRmFrZVNlcnZlcikge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcudXNlRmFrZVNlcnZlciA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgc2FuZGJveC5zZXJ2ZXJQcm90b3R5cGUgPSBjb25maWcudXNlRmFrZVNlcnZlcjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc2FuZGJveC51c2VGYWtlU2VydmVyKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29uZmlnLnVzZUZha2VUaW1lcnMpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY29uZmlnLnVzZUZha2VUaW1lcnMgPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgIHNhbmRib3gudXNlRmFrZVRpbWVycy5hcHBseShzYW5kYm94LCBjb25maWcudXNlRmFrZVRpbWVycyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHNhbmRib3gudXNlRmFrZVRpbWVycygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgfVxuXG4gICAgc2lub24uc2FuZGJveCA9IHNpbm9uLmV4dGVuZChzaW5vbi5jcmVhdGUoc2lub24uY29sbGVjdGlvbiksIHtcbiAgICAgICAgdXNlRmFrZVRpbWVyczogZnVuY3Rpb24gdXNlRmFrZVRpbWVycygpIHtcbiAgICAgICAgICAgIHRoaXMuY2xvY2sgPSBzaW5vbi51c2VGYWtlVGltZXJzLmFwcGx5KHNpbm9uLCBhcmd1bWVudHMpO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQodGhpcy5jbG9jayk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgc2VydmVyUHJvdG90eXBlOiBzaW5vbi5mYWtlU2VydmVyLFxuXG4gICAgICAgIHVzZUZha2VTZXJ2ZXI6IGZ1bmN0aW9uIHVzZUZha2VTZXJ2ZXIoKSB7XG4gICAgICAgICAgICB2YXIgcHJvdG8gPSB0aGlzLnNlcnZlclByb3RvdHlwZSB8fCBzaW5vbi5mYWtlU2VydmVyO1xuXG4gICAgICAgICAgICBpZiAoIXByb3RvIHx8ICFwcm90by5jcmVhdGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5zZXJ2ZXIgPSBwcm90by5jcmVhdGUoKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFkZCh0aGlzLnNlcnZlcik7XG4gICAgICAgIH0sXG5cbiAgICAgICAgaW5qZWN0OiBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgICAgICBzaW5vbi5jb2xsZWN0aW9uLmluamVjdC5jYWxsKHRoaXMsIG9iaik7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmNsb2NrKSB7XG4gICAgICAgICAgICAgICAgb2JqLmNsb2NrID0gdGhpcy5jbG9jaztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRoaXMuc2VydmVyKSB7XG4gICAgICAgICAgICAgICAgb2JqLnNlcnZlciA9IHRoaXMuc2VydmVyO1xuICAgICAgICAgICAgICAgIG9iai5yZXF1ZXN0cyA9IHRoaXMuc2VydmVyLnJlcXVlc3RzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgICB9LFxuXG4gICAgICAgIHJlc3RvcmU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHNpbm9uLmNvbGxlY3Rpb24ucmVzdG9yZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgdGhpcy5yZXN0b3JlQ29udGV4dCgpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHJlc3RvcmVDb250ZXh0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5pbmplY3RlZEtleXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgaiA9IHRoaXMuaW5qZWN0ZWRLZXlzLmxlbmd0aDsgaSA8IGo7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5pbmplY3RJbnRvW3RoaXMuaW5qZWN0ZWRLZXlzW2ldXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5pbmplY3RlZEtleXMgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uIChjb25maWcpIHtcbiAgICAgICAgICAgIGlmICghY29uZmlnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNpbm9uLmNyZWF0ZShzaW5vbi5zYW5kYm94KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHNhbmRib3ggPSBwcmVwYXJlU2FuZGJveEZyb21Db25maWcoY29uZmlnKTtcbiAgICAgICAgICAgIHNhbmRib3guYXJncyA9IHNhbmRib3guYXJncyB8fCBbXTtcbiAgICAgICAgICAgIHNhbmRib3guaW5qZWN0ZWRLZXlzID0gW107XG4gICAgICAgICAgICBzYW5kYm94LmluamVjdEludG8gPSBjb25maWcuaW5qZWN0SW50bztcbiAgICAgICAgICAgIHZhciBwcm9wLCB2YWx1ZSwgZXhwb3NlZCA9IHNhbmRib3guaW5qZWN0KHt9KTtcblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5wcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBjb25maWcucHJvcGVydGllcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcCA9IGNvbmZpZy5wcm9wZXJ0aWVzW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGV4cG9zZWRbcHJvcF0gfHwgcHJvcCA9PSBcInNhbmRib3hcIiAmJiBzYW5kYm94O1xuICAgICAgICAgICAgICAgICAgICBleHBvc2VWYWx1ZShzYW5kYm94LCBjb25maWcsIHByb3AsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGV4cG9zZVZhbHVlKHNhbmRib3gsIGNvbmZpZywgXCJzYW5kYm94XCIsIHZhbHVlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHNpbm9uLnNhbmRib3gudXNlRmFrZVhNTEh0dHBSZXF1ZXN0ID0gc2lub24uc2FuZGJveC51c2VGYWtlU2VydmVyO1xuXG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJtb2R1bGVcIl0sIGZ1bmN0aW9uKG1vZHVsZSkgeyBtb2R1bGUuZXhwb3J0cyA9IHNpbm9uLnNhbmRib3g7IH0pO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgJiYgbW9kdWxlLmV4cG9ydHMpIHtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBzaW5vbi5zYW5kYm94O1xuICAgIH1cbn0oKSk7XG4iLCIvKipcbiAgKiBAZGVwZW5kIC4uL3Npbm9uLmpzXG4gICogQGRlcGVuZCBjYWxsLmpzXG4gICovXG4vKmpzbGludCBlcWVxZXE6IGZhbHNlLCBvbmV2YXI6IGZhbHNlLCBwbHVzcGx1czogZmFsc2UqL1xuLypnbG9iYWwgbW9kdWxlLCByZXF1aXJlLCBzaW5vbiovXG4vKipcbiAgKiBTcHkgZnVuY3Rpb25zXG4gICpcbiAgKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAgKiBAbGljZW5zZSBCU0RcbiAgKlxuICAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiAoc2lub24pIHtcbiAgICB2YXIgY29tbW9uSlNNb2R1bGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgcHVzaCA9IEFycmF5LnByb3RvdHlwZS5wdXNoO1xuICAgIHZhciBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcbiAgICB2YXIgY2FsbElkID0gMDtcblxuICAgIGlmICghc2lub24gJiYgY29tbW9uSlNNb2R1bGUpIHtcbiAgICAgICAgc2lub24gPSByZXF1aXJlKFwiLi4vc2lub25cIik7XG4gICAgfVxuXG4gICAgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc3B5KG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICAgICAgaWYgKCFwcm9wZXJ0eSAmJiB0eXBlb2Ygb2JqZWN0ID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgcmV0dXJuIHNweS5jcmVhdGUob2JqZWN0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghb2JqZWN0ICYmICFwcm9wZXJ0eSkge1xuICAgICAgICAgICAgcmV0dXJuIHNweS5jcmVhdGUoZnVuY3Rpb24gKCkgeyB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBtZXRob2QgPSBvYmplY3RbcHJvcGVydHldO1xuICAgICAgICByZXR1cm4gc2lub24ud3JhcE1ldGhvZChvYmplY3QsIHByb3BlcnR5LCBzcHkuY3JlYXRlKG1ldGhvZCkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1hdGNoaW5nRmFrZShmYWtlcywgYXJncywgc3RyaWN0KSB7XG4gICAgICAgIGlmICghZmFrZXMpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gZmFrZXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoZmFrZXNbaV0ubWF0Y2hlcyhhcmdzLCBzdHJpY3QpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZha2VzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5jcmVtZW50Q2FsbENvdW50KCkge1xuICAgICAgICB0aGlzLmNhbGxlZCA9IHRydWU7XG4gICAgICAgIHRoaXMuY2FsbENvdW50ICs9IDE7XG4gICAgICAgIHRoaXMubm90Q2FsbGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuY2FsbGVkT25jZSA9IHRoaXMuY2FsbENvdW50ID09IDE7XG4gICAgICAgIHRoaXMuY2FsbGVkVHdpY2UgPSB0aGlzLmNhbGxDb3VudCA9PSAyO1xuICAgICAgICB0aGlzLmNhbGxlZFRocmljZSA9IHRoaXMuY2FsbENvdW50ID09IDM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlQ2FsbFByb3BlcnRpZXMoKSB7XG4gICAgICAgIHRoaXMuZmlyc3RDYWxsID0gdGhpcy5nZXRDYWxsKDApO1xuICAgICAgICB0aGlzLnNlY29uZENhbGwgPSB0aGlzLmdldENhbGwoMSk7XG4gICAgICAgIHRoaXMudGhpcmRDYWxsID0gdGhpcy5nZXRDYWxsKDIpO1xuICAgICAgICB0aGlzLmxhc3RDYWxsID0gdGhpcy5nZXRDYWxsKHRoaXMuY2FsbENvdW50IC0gMSk7XG4gICAgfVxuXG4gICAgdmFyIHZhcnMgPSBcImEsYixjLGQsZSxmLGcsaCxpLGosayxsXCI7XG4gICAgZnVuY3Rpb24gY3JlYXRlUHJveHkoZnVuYykge1xuICAgICAgICAvLyBSZXRhaW4gdGhlIGZ1bmN0aW9uIGxlbmd0aDpcbiAgICAgICAgdmFyIHA7XG4gICAgICAgIGlmIChmdW5jLmxlbmd0aCkge1xuICAgICAgICAgICAgZXZhbChcInAgPSAoZnVuY3Rpb24gcHJveHkoXCIgKyB2YXJzLnN1YnN0cmluZygwLCBmdW5jLmxlbmd0aCAqIDIgLSAxKSArXG4gICAgICAgICAgICAgICAgXCIpIHsgcmV0dXJuIHAuaW52b2tlKGZ1bmMsIHRoaXMsIHNsaWNlLmNhbGwoYXJndW1lbnRzKSk7IH0pO1wiKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHAgPSBmdW5jdGlvbiBwcm94eSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcC5pbnZva2UoZnVuYywgdGhpcywgc2xpY2UuY2FsbChhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHA7XG4gICAgfVxuXG4gICAgdmFyIHV1aWQgPSAwO1xuXG4gICAgLy8gUHVibGljIEFQSVxuICAgIHZhciBzcHlBcGkgPSB7XG4gICAgICAgIHJlc2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5ub3RDYWxsZWQgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy5jYWxsZWRPbmNlID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmNhbGxlZFR3aWNlID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmNhbGxlZFRocmljZSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5jYWxsQ291bnQgPSAwO1xuICAgICAgICAgICAgdGhpcy5maXJzdENhbGwgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5zZWNvbmRDYWxsID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMudGhpcmRDYWxsID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMubGFzdENhbGwgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5hcmdzID0gW107XG4gICAgICAgICAgICB0aGlzLnJldHVyblZhbHVlcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy50aGlzVmFsdWVzID0gW107XG4gICAgICAgICAgICB0aGlzLmV4Y2VwdGlvbnMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuY2FsbElkcyA9IFtdO1xuICAgICAgICAgICAgaWYgKHRoaXMuZmFrZXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuZmFrZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mYWtlc1tpXS5yZXNldCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShmdW5jKSB7XG4gICAgICAgICAgICB2YXIgbmFtZTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBmdW5jICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIGZ1bmMgPSBmdW5jdGlvbiAoKSB7IH07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG5hbWUgPSBzaW5vbi5mdW5jdGlvbk5hbWUoZnVuYyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBwcm94eSA9IGNyZWF0ZVByb3h5KGZ1bmMpO1xuXG4gICAgICAgICAgICBzaW5vbi5leHRlbmQocHJveHksIHNweSk7XG4gICAgICAgICAgICBkZWxldGUgcHJveHkuY3JlYXRlO1xuICAgICAgICAgICAgc2lub24uZXh0ZW5kKHByb3h5LCBmdW5jKTtcblxuICAgICAgICAgICAgcHJveHkucmVzZXQoKTtcbiAgICAgICAgICAgIHByb3h5LnByb3RvdHlwZSA9IGZ1bmMucHJvdG90eXBlO1xuICAgICAgICAgICAgcHJveHkuZGlzcGxheU5hbWUgPSBuYW1lIHx8IFwic3B5XCI7XG4gICAgICAgICAgICBwcm94eS50b1N0cmluZyA9IHNpbm9uLmZ1bmN0aW9uVG9TdHJpbmc7XG4gICAgICAgICAgICBwcm94eS5fY3JlYXRlID0gc2lub24uc3B5LmNyZWF0ZTtcbiAgICAgICAgICAgIHByb3h5LmlkID0gXCJzcHkjXCIgKyB1dWlkKys7XG5cbiAgICAgICAgICAgIHJldHVybiBwcm94eTtcbiAgICAgICAgfSxcblxuICAgICAgICBpbnZva2U6IGZ1bmN0aW9uIGludm9rZShmdW5jLCB0aGlzVmFsdWUsIGFyZ3MpIHtcbiAgICAgICAgICAgIHZhciBtYXRjaGluZyA9IG1hdGNoaW5nRmFrZSh0aGlzLmZha2VzLCBhcmdzKTtcbiAgICAgICAgICAgIHZhciBleGNlcHRpb24sIHJldHVyblZhbHVlO1xuXG4gICAgICAgICAgICBpbmNyZW1lbnRDYWxsQ291bnQuY2FsbCh0aGlzKTtcbiAgICAgICAgICAgIHB1c2guY2FsbCh0aGlzLnRoaXNWYWx1ZXMsIHRoaXNWYWx1ZSk7XG4gICAgICAgICAgICBwdXNoLmNhbGwodGhpcy5hcmdzLCBhcmdzKTtcbiAgICAgICAgICAgIHB1c2guY2FsbCh0aGlzLmNhbGxJZHMsIGNhbGxJZCsrKTtcblxuICAgICAgICAgICAgLy8gTWFrZSBjYWxsIHByb3BlcnRpZXMgYXZhaWxhYmxlIGZyb20gd2l0aGluIHRoZSBzcGllZCBmdW5jdGlvbjpcbiAgICAgICAgICAgIGNyZWF0ZUNhbGxQcm9wZXJ0aWVzLmNhbGwodGhpcyk7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVyblZhbHVlID0gbWF0Y2hpbmcuaW52b2tlKGZ1bmMsIHRoaXNWYWx1ZSwgYXJncyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSAodGhpcy5mdW5jIHx8IGZ1bmMpLmFwcGx5KHRoaXNWYWx1ZSwgYXJncyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHRoaXNDYWxsID0gdGhpcy5nZXRDYWxsKHRoaXMuY2FsbENvdW50IC0gMSk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXNDYWxsLmNhbGxlZFdpdGhOZXcoKSAmJiB0eXBlb2YgcmV0dXJuVmFsdWUgIT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVyblZhbHVlID0gdGhpc1ZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICBleGNlcHRpb24gPSBlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwdXNoLmNhbGwodGhpcy5leGNlcHRpb25zLCBleGNlcHRpb24pO1xuICAgICAgICAgICAgcHVzaC5jYWxsKHRoaXMucmV0dXJuVmFsdWVzLCByZXR1cm5WYWx1ZSk7XG5cbiAgICAgICAgICAgIC8vIE1ha2UgcmV0dXJuIHZhbHVlIGFuZCBleGNlcHRpb24gYXZhaWxhYmxlIGluIHRoZSBjYWxsczpcbiAgICAgICAgICAgIGNyZWF0ZUNhbGxQcm9wZXJ0aWVzLmNhbGwodGhpcyk7XG5cbiAgICAgICAgICAgIGlmIChleGNlcHRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRocm93IGV4Y2VwdGlvbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJldHVyblZhbHVlO1xuICAgICAgICB9LFxuXG4gICAgICAgIG5hbWVkOiBmdW5jdGlvbiBuYW1lZChuYW1lKSB7XG4gICAgICAgICAgICB0aGlzLmRpc3BsYXlOYW1lID0gbmFtZTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9LFxuXG4gICAgICAgIGdldENhbGw6IGZ1bmN0aW9uIGdldENhbGwoaSkge1xuICAgICAgICAgICAgaWYgKGkgPCAwIHx8IGkgPj0gdGhpcy5jYWxsQ291bnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHNpbm9uLnNweUNhbGwodGhpcywgdGhpcy50aGlzVmFsdWVzW2ldLCB0aGlzLmFyZ3NbaV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJldHVyblZhbHVlc1tpXSwgdGhpcy5leGNlcHRpb25zW2ldLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYWxsSWRzW2ldKTtcbiAgICAgICAgfSxcblxuICAgICAgICBnZXRDYWxsczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGNhbGxzID0gW107XG4gICAgICAgICAgICB2YXIgaTtcblxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY2FsbENvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICBjYWxscy5wdXNoKHRoaXMuZ2V0Q2FsbChpKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBjYWxscztcbiAgICAgICAgfSxcblxuICAgICAgICBjYWxsZWRCZWZvcmU6IGZ1bmN0aW9uIGNhbGxlZEJlZm9yZShzcHlGbikge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNhbGxlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFzcHlGbi5jYWxsZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2FsbElkc1swXSA8IHNweUZuLmNhbGxJZHNbc3B5Rm4uY2FsbElkcy5sZW5ndGggLSAxXTtcbiAgICAgICAgfSxcblxuICAgICAgICBjYWxsZWRBZnRlcjogZnVuY3Rpb24gY2FsbGVkQWZ0ZXIoc3B5Rm4pIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5jYWxsZWQgfHwgIXNweUZuLmNhbGxlZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2FsbElkc1t0aGlzLmNhbGxDb3VudCAtIDFdID4gc3B5Rm4uY2FsbElkc1tzcHlGbi5jYWxsQ291bnQgLSAxXTtcbiAgICAgICAgfSxcblxuICAgICAgICB3aXRoQXJnczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cyk7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmZha2VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hdGNoID0gbWF0Y2hpbmdGYWtlKHRoaXMuZmFrZXMsIGFyZ3MsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuZmFrZXMgPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIG9yaWdpbmFsID0gdGhpcztcbiAgICAgICAgICAgIHZhciBmYWtlID0gdGhpcy5fY3JlYXRlKCk7XG4gICAgICAgICAgICBmYWtlLm1hdGNoaW5nQWd1bWVudHMgPSBhcmdzO1xuICAgICAgICAgICAgZmFrZS5wYXJlbnQgPSB0aGlzO1xuICAgICAgICAgICAgcHVzaC5jYWxsKHRoaXMuZmFrZXMsIGZha2UpO1xuXG4gICAgICAgICAgICBmYWtlLndpdGhBcmdzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbC53aXRoQXJncy5hcHBseShvcmlnaW5hbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5hcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGZha2UubWF0Y2hlcyh0aGlzLmFyZ3NbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGluY3JlbWVudENhbGxDb3VudC5jYWxsKGZha2UpO1xuICAgICAgICAgICAgICAgICAgICBwdXNoLmNhbGwoZmFrZS50aGlzVmFsdWVzLCB0aGlzLnRoaXNWYWx1ZXNbaV0pO1xuICAgICAgICAgICAgICAgICAgICBwdXNoLmNhbGwoZmFrZS5hcmdzLCB0aGlzLmFyZ3NbaV0pO1xuICAgICAgICAgICAgICAgICAgICBwdXNoLmNhbGwoZmFrZS5yZXR1cm5WYWx1ZXMsIHRoaXMucmV0dXJuVmFsdWVzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgcHVzaC5jYWxsKGZha2UuZXhjZXB0aW9ucywgdGhpcy5leGNlcHRpb25zW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgcHVzaC5jYWxsKGZha2UuY2FsbElkcywgdGhpcy5jYWxsSWRzW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjcmVhdGVDYWxsUHJvcGVydGllcy5jYWxsKGZha2UpO1xuXG4gICAgICAgICAgICByZXR1cm4gZmFrZTtcbiAgICAgICAgfSxcblxuICAgICAgICBtYXRjaGVzOiBmdW5jdGlvbiAoYXJncywgc3RyaWN0KSB7XG4gICAgICAgICAgICB2YXIgbWFyZ3MgPSB0aGlzLm1hdGNoaW5nQWd1bWVudHM7XG5cbiAgICAgICAgICAgIGlmIChtYXJncy5sZW5ndGggPD0gYXJncy5sZW5ndGggJiZcbiAgICAgICAgICAgICAgICBzaW5vbi5kZWVwRXF1YWwobWFyZ3MsIGFyZ3Muc2xpY2UoMCwgbWFyZ3MubGVuZ3RoKSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gIXN0cmljdCB8fCBtYXJncy5sZW5ndGggPT0gYXJncy5sZW5ndGg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgcHJpbnRmOiBmdW5jdGlvbiAoZm9ybWF0KSB7XG4gICAgICAgICAgICB2YXIgc3B5ID0gdGhpcztcbiAgICAgICAgICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgdmFyIGZvcm1hdHRlcjtcblxuICAgICAgICAgICAgcmV0dXJuIChmb3JtYXQgfHwgXCJcIikucmVwbGFjZSgvJSguKS9nLCBmdW5jdGlvbiAobWF0Y2gsIHNwZWNpZnllcikge1xuICAgICAgICAgICAgICAgIGZvcm1hdHRlciA9IHNweUFwaS5mb3JtYXR0ZXJzW3NwZWNpZnllcl07XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGZvcm1hdHRlciA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZvcm1hdHRlci5jYWxsKG51bGwsIHNweSwgYXJncyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNOYU4ocGFyc2VJbnQoc3BlY2lmeWVyLCAxMCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzaW5vbi5mb3JtYXQoYXJnc1tzcGVjaWZ5ZXIgLSAxXSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiJVwiICsgc3BlY2lmeWVyO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gZGVsZWdhdGVUb0NhbGxzKG1ldGhvZCwgbWF0Y2hBbnksIGFjdHVhbCwgbm90Q2FsbGVkKSB7XG4gICAgICAgIHNweUFwaVttZXRob2RdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmNhbGxlZCkge1xuICAgICAgICAgICAgICAgIGlmIChub3RDYWxsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5vdENhbGxlZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBjdXJyZW50Q2FsbDtcbiAgICAgICAgICAgIHZhciBtYXRjaGVzID0gMDtcblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSB0aGlzLmNhbGxDb3VudDsgaSA8IGw7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgIGN1cnJlbnRDYWxsID0gdGhpcy5nZXRDYWxsKGkpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRDYWxsW2FjdHVhbCB8fCBtZXRob2RdLmFwcGx5KGN1cnJlbnRDYWxsLCBhcmd1bWVudHMpKSB7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoZXMgKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2hBbnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hlcyA9PT0gdGhpcy5jYWxsQ291bnQ7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZGVsZWdhdGVUb0NhbGxzKFwiY2FsbGVkT25cIiwgdHJ1ZSk7XG4gICAgZGVsZWdhdGVUb0NhbGxzKFwiYWx3YXlzQ2FsbGVkT25cIiwgZmFsc2UsIFwiY2FsbGVkT25cIik7XG4gICAgZGVsZWdhdGVUb0NhbGxzKFwiY2FsbGVkV2l0aFwiLCB0cnVlKTtcbiAgICBkZWxlZ2F0ZVRvQ2FsbHMoXCJjYWxsZWRXaXRoTWF0Y2hcIiwgdHJ1ZSk7XG4gICAgZGVsZWdhdGVUb0NhbGxzKFwiYWx3YXlzQ2FsbGVkV2l0aFwiLCBmYWxzZSwgXCJjYWxsZWRXaXRoXCIpO1xuICAgIGRlbGVnYXRlVG9DYWxscyhcImFsd2F5c0NhbGxlZFdpdGhNYXRjaFwiLCBmYWxzZSwgXCJjYWxsZWRXaXRoTWF0Y2hcIik7XG4gICAgZGVsZWdhdGVUb0NhbGxzKFwiY2FsbGVkV2l0aEV4YWN0bHlcIiwgdHJ1ZSk7XG4gICAgZGVsZWdhdGVUb0NhbGxzKFwiYWx3YXlzQ2FsbGVkV2l0aEV4YWN0bHlcIiwgZmFsc2UsIFwiY2FsbGVkV2l0aEV4YWN0bHlcIik7XG4gICAgZGVsZWdhdGVUb0NhbGxzKFwibmV2ZXJDYWxsZWRXaXRoXCIsIGZhbHNlLCBcIm5vdENhbGxlZFdpdGhcIixcbiAgICAgICAgZnVuY3Rpb24gKCkgeyByZXR1cm4gdHJ1ZTsgfSk7XG4gICAgZGVsZWdhdGVUb0NhbGxzKFwibmV2ZXJDYWxsZWRXaXRoTWF0Y2hcIiwgZmFsc2UsIFwibm90Q2FsbGVkV2l0aE1hdGNoXCIsXG4gICAgICAgIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRydWU7IH0pO1xuICAgIGRlbGVnYXRlVG9DYWxscyhcInRocmV3XCIsIHRydWUpO1xuICAgIGRlbGVnYXRlVG9DYWxscyhcImFsd2F5c1RocmV3XCIsIGZhbHNlLCBcInRocmV3XCIpO1xuICAgIGRlbGVnYXRlVG9DYWxscyhcInJldHVybmVkXCIsIHRydWUpO1xuICAgIGRlbGVnYXRlVG9DYWxscyhcImFsd2F5c1JldHVybmVkXCIsIGZhbHNlLCBcInJldHVybmVkXCIpO1xuICAgIGRlbGVnYXRlVG9DYWxscyhcImNhbGxlZFdpdGhOZXdcIiwgdHJ1ZSk7XG4gICAgZGVsZWdhdGVUb0NhbGxzKFwiYWx3YXlzQ2FsbGVkV2l0aE5ld1wiLCBmYWxzZSwgXCJjYWxsZWRXaXRoTmV3XCIpO1xuICAgIGRlbGVnYXRlVG9DYWxscyhcImNhbGxBcmdcIiwgZmFsc2UsIFwiY2FsbEFyZ1dpdGhcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy50b1N0cmluZygpICsgXCIgY2Fubm90IGNhbGwgYXJnIHNpbmNlIGl0IHdhcyBub3QgeWV0IGludm9rZWQuXCIpO1xuICAgIH0pO1xuICAgIHNweUFwaS5jYWxsQXJnV2l0aCA9IHNweUFwaS5jYWxsQXJnO1xuICAgIGRlbGVnYXRlVG9DYWxscyhcImNhbGxBcmdPblwiLCBmYWxzZSwgXCJjYWxsQXJnT25XaXRoXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKHRoaXMudG9TdHJpbmcoKSArIFwiIGNhbm5vdCBjYWxsIGFyZyBzaW5jZSBpdCB3YXMgbm90IHlldCBpbnZva2VkLlwiKTtcbiAgICB9KTtcbiAgICBzcHlBcGkuY2FsbEFyZ09uV2l0aCA9IHNweUFwaS5jYWxsQXJnT247XG4gICAgZGVsZWdhdGVUb0NhbGxzKFwieWllbGRcIiwgZmFsc2UsIFwieWllbGRcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy50b1N0cmluZygpICsgXCIgY2Fubm90IHlpZWxkIHNpbmNlIGl0IHdhcyBub3QgeWV0IGludm9rZWQuXCIpO1xuICAgIH0pO1xuICAgIC8vIFwiaW52b2tlQ2FsbGJhY2tcIiBpcyBhbiBhbGlhcyBmb3IgXCJ5aWVsZFwiIHNpbmNlIFwieWllbGRcIiBpcyBpbnZhbGlkIGluIHN0cmljdCBtb2RlLlxuICAgIHNweUFwaS5pbnZva2VDYWxsYmFjayA9IHNweUFwaS55aWVsZDtcbiAgICBkZWxlZ2F0ZVRvQ2FsbHMoXCJ5aWVsZE9uXCIsIGZhbHNlLCBcInlpZWxkT25cIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy50b1N0cmluZygpICsgXCIgY2Fubm90IHlpZWxkIHNpbmNlIGl0IHdhcyBub3QgeWV0IGludm9rZWQuXCIpO1xuICAgIH0pO1xuICAgIGRlbGVnYXRlVG9DYWxscyhcInlpZWxkVG9cIiwgZmFsc2UsIFwieWllbGRUb1wiLCBmdW5jdGlvbiAocHJvcGVydHkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKHRoaXMudG9TdHJpbmcoKSArIFwiIGNhbm5vdCB5aWVsZCB0byAnXCIgKyBwcm9wZXJ0eSArXG4gICAgICAgICAgICBcIicgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5cIik7XG4gICAgfSk7XG4gICAgZGVsZWdhdGVUb0NhbGxzKFwieWllbGRUb09uXCIsIGZhbHNlLCBcInlpZWxkVG9PblwiLCBmdW5jdGlvbiAocHJvcGVydHkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKHRoaXMudG9TdHJpbmcoKSArIFwiIGNhbm5vdCB5aWVsZCB0byAnXCIgKyBwcm9wZXJ0eSArXG4gICAgICAgICAgICBcIicgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5cIik7XG4gICAgfSk7XG5cbiAgICBzcHlBcGkuZm9ybWF0dGVycyA9IHtcbiAgICAgICAgXCJjXCI6IGZ1bmN0aW9uIChzcHkpIHtcbiAgICAgICAgICAgIHJldHVybiBzaW5vbi50aW1lc0luV29yZHMoc3B5LmNhbGxDb3VudCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgXCJuXCI6IGZ1bmN0aW9uIChzcHkpIHtcbiAgICAgICAgICAgIHJldHVybiBzcHkudG9TdHJpbmcoKTtcbiAgICAgICAgfSxcblxuICAgICAgICBcIkNcIjogZnVuY3Rpb24gKHNweSkge1xuICAgICAgICAgICAgdmFyIGNhbGxzID0gW107XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gc3B5LmNhbGxDb3VudDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgICAgIHZhciBzdHJpbmdpZmllZENhbGwgPSBcIiAgICBcIiArIHNweS5nZXRDYWxsKGkpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgaWYgKC9cXG4vLnRlc3QoY2FsbHNbaSAtIDFdKSkge1xuICAgICAgICAgICAgICAgICAgICBzdHJpbmdpZmllZENhbGwgPSBcIlxcblwiICsgc3RyaW5naWZpZWRDYWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwoY2FsbHMsIHN0cmluZ2lmaWVkQ2FsbCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBjYWxscy5sZW5ndGggPiAwID8gXCJcXG5cIiArIGNhbGxzLmpvaW4oXCJcXG5cIikgOiBcIlwiO1xuICAgICAgICB9LFxuXG4gICAgICAgIFwidFwiOiBmdW5jdGlvbiAoc3B5KSB7XG4gICAgICAgICAgICB2YXIgb2JqZWN0cyA9IFtdO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHNweS5jYWxsQ291bnQ7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwob2JqZWN0cywgc2lub24uZm9ybWF0KHNweS50aGlzVmFsdWVzW2ldKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBvYmplY3RzLmpvaW4oXCIsIFwiKTtcbiAgICAgICAgfSxcblxuICAgICAgICBcIipcIjogZnVuY3Rpb24gKHNweSwgYXJncykge1xuICAgICAgICAgICAgdmFyIGZvcm1hdHRlZCA9IFtdO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGFyZ3MubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAgICAgcHVzaC5jYWxsKGZvcm1hdHRlZCwgc2lub24uZm9ybWF0KGFyZ3NbaV0pKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdHRlZC5qb2luKFwiLCBcIik7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgc2lub24uZXh0ZW5kKHNweSwgc3B5QXBpKTtcblxuICAgIHNweS5zcHlDYWxsID0gc2lub24uc3B5Q2FsbDtcbiAgICBzaW5vbi5zcHkgPSBzcHk7XG5cbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcIm1vZHVsZVwiXSwgZnVuY3Rpb24obW9kdWxlKSB7IG1vZHVsZS5leHBvcnRzID0gc3B5OyB9KTtcbiAgICB9IGVsc2UgaWYgKGNvbW1vbkpTTW9kdWxlKSB7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gc3B5O1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIC4uL3Npbm9uLmpzXG4gKiBAZGVwZW5kIHNweS5qc1xuICogQGRlcGVuZCBiZWhhdmlvci5qc1xuICovXG4vKmpzbGludCBlcWVxZXE6IGZhbHNlLCBvbmV2YXI6IGZhbHNlKi9cbi8qZ2xvYmFsIG1vZHVsZSwgcmVxdWlyZSwgc2lub24qL1xuLyoqXG4gKiBTdHViIGZ1bmN0aW9uc1xuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKHNpbm9uKSB7XG4gICAgdmFyIGNvbW1vbkpTTW9kdWxlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG5cbiAgICBpZiAoIXNpbm9uICYmIGNvbW1vbkpTTW9kdWxlKSB7XG4gICAgICAgIHNpbm9uID0gcmVxdWlyZShcIi4uL3Npbm9uXCIpO1xuICAgIH1cblxuICAgIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0dWIob2JqZWN0LCBwcm9wZXJ0eSwgZnVuYykge1xuICAgICAgICBpZiAoISFmdW5jICYmIHR5cGVvZiBmdW5jICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkN1c3RvbSBzdHViIHNob3VsZCBiZSBmdW5jdGlvblwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB3cmFwcGVyO1xuXG4gICAgICAgIGlmIChmdW5jKSB7XG4gICAgICAgICAgICB3cmFwcGVyID0gc2lub24uc3B5ICYmIHNpbm9uLnNweS5jcmVhdGUgPyBzaW5vbi5zcHkuY3JlYXRlKGZ1bmMpIDogZnVuYztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHdyYXBwZXIgPSBzdHViLmNyZWF0ZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFvYmplY3QgJiYgdHlwZW9mIHByb3BlcnR5ID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICByZXR1cm4gc2lub24uc3R1Yi5jcmVhdGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgcHJvcGVydHkgPT09IFwidW5kZWZpbmVkXCIgJiYgdHlwZW9mIG9iamVjdCA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBwcm9wIGluIG9iamVjdCkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0W3Byb3BdID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgc3R1YihvYmplY3QsIHByb3ApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzaW5vbi53cmFwTWV0aG9kKG9iamVjdCwgcHJvcGVydHksIHdyYXBwZXIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldERlZmF1bHRCZWhhdmlvcihzdHViKSB7XG4gICAgICAgIHJldHVybiBzdHViLmRlZmF1bHRCZWhhdmlvciB8fCBnZXRQYXJlbnRCZWhhdmlvdXIoc3R1YikgfHwgc2lub24uYmVoYXZpb3IuY3JlYXRlKHN0dWIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFBhcmVudEJlaGF2aW91cihzdHViKSB7XG4gICAgICAgIHJldHVybiAoc3R1Yi5wYXJlbnQgJiYgZ2V0Q3VycmVudEJlaGF2aW9yKHN0dWIucGFyZW50KSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Q3VycmVudEJlaGF2aW9yKHN0dWIpIHtcbiAgICAgICAgdmFyIGJlaGF2aW9yID0gc3R1Yi5iZWhhdmlvcnNbc3R1Yi5jYWxsQ291bnQgLSAxXTtcbiAgICAgICAgcmV0dXJuIGJlaGF2aW9yICYmIGJlaGF2aW9yLmlzUHJlc2VudCgpID8gYmVoYXZpb3IgOiBnZXREZWZhdWx0QmVoYXZpb3Ioc3R1Yik7XG4gICAgfVxuXG4gICAgdmFyIHV1aWQgPSAwO1xuXG4gICAgc2lub24uZXh0ZW5kKHN0dWIsIChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBwcm90byA9IHtcbiAgICAgICAgICAgIGNyZWF0ZTogZnVuY3Rpb24gY3JlYXRlKCkge1xuICAgICAgICAgICAgICAgIHZhciBmdW5jdGlvblN0dWIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBnZXRDdXJyZW50QmVoYXZpb3IoZnVuY3Rpb25TdHViKS5pbnZva2UodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb25TdHViLmlkID0gXCJzdHViI1wiICsgdXVpZCsrO1xuICAgICAgICAgICAgICAgIHZhciBvcmlnID0gZnVuY3Rpb25TdHViO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uU3R1YiA9IHNpbm9uLnNweS5jcmVhdGUoZnVuY3Rpb25TdHViKTtcbiAgICAgICAgICAgICAgICBmdW5jdGlvblN0dWIuZnVuYyA9IG9yaWc7XG5cbiAgICAgICAgICAgICAgICBzaW5vbi5leHRlbmQoZnVuY3Rpb25TdHViLCBzdHViKTtcbiAgICAgICAgICAgICAgICBmdW5jdGlvblN0dWIuX2NyZWF0ZSA9IHNpbm9uLnN0dWIuY3JlYXRlO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uU3R1Yi5kaXNwbGF5TmFtZSA9IFwic3R1YlwiO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uU3R1Yi50b1N0cmluZyA9IHNpbm9uLmZ1bmN0aW9uVG9TdHJpbmc7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvblN0dWIuZGVmYXVsdEJlaGF2aW9yID0gbnVsbDtcbiAgICAgICAgICAgICAgICBmdW5jdGlvblN0dWIuYmVoYXZpb3JzID0gW107XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb25TdHViO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgcmVzZXRCZWhhdmlvcjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBpO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5kZWZhdWx0QmVoYXZpb3IgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMuYmVoYXZpb3JzID0gW107XG5cbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZXR1cm5WYWx1ZTtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5yZXR1cm5BcmdBdDtcbiAgICAgICAgICAgICAgICB0aGlzLnJldHVyblRoaXMgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmZha2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmZha2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZha2VzW2ldLnJlc2V0QmVoYXZpb3IoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uQ2FsbDogZnVuY3Rpb24oaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuYmVoYXZpb3JzW2luZGV4XSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmJlaGF2aW9yc1tpbmRleF0gPSBzaW5vbi5iZWhhdmlvci5jcmVhdGUodGhpcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYmVoYXZpb3JzW2luZGV4XTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uRmlyc3RDYWxsOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5vbkNhbGwoMCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBvblNlY29uZENhbGw6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9uQ2FsbCgxKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uVGhpcmRDYWxsOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5vbkNhbGwoMik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgZm9yICh2YXIgbWV0aG9kIGluIHNpbm9uLmJlaGF2aW9yKSB7XG4gICAgICAgICAgICBpZiAoc2lub24uYmVoYXZpb3IuaGFzT3duUHJvcGVydHkobWV0aG9kKSAmJlxuICAgICAgICAgICAgICAgICFwcm90by5oYXNPd25Qcm9wZXJ0eShtZXRob2QpICYmXG4gICAgICAgICAgICAgICAgbWV0aG9kICE9ICdjcmVhdGUnICYmXG4gICAgICAgICAgICAgICAgbWV0aG9kICE9ICd3aXRoQXJncycgJiZcbiAgICAgICAgICAgICAgICBtZXRob2QgIT0gJ2ludm9rZScpIHtcbiAgICAgICAgICAgICAgICBwcm90b1ttZXRob2RdID0gKGZ1bmN0aW9uKGJlaGF2aW9yTWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVmYXVsdEJlaGF2aW9yID0gdGhpcy5kZWZhdWx0QmVoYXZpb3IgfHwgc2lub24uYmVoYXZpb3IuY3JlYXRlKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWZhdWx0QmVoYXZpb3JbYmVoYXZpb3JNZXRob2RdLmFwcGx5KHRoaXMuZGVmYXVsdEJlaGF2aW9yLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfShtZXRob2QpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwcm90bztcbiAgICB9KCkpKTtcblxuICAgIHNpbm9uLnN0dWIgPSBzdHViO1xuXG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbXCJtb2R1bGVcIl0sIGZ1bmN0aW9uKG1vZHVsZSkgeyBtb2R1bGUuZXhwb3J0cyA9IHN0dWI7IH0pO1xuICAgIH0gZWxzZSBpZiAoY29tbW9uSlNNb2R1bGUpIHtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBzdHViO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIC4uL3Npbm9uLmpzXG4gKiBAZGVwZW5kIHN0dWIuanNcbiAqIEBkZXBlbmQgbW9jay5qc1xuICogQGRlcGVuZCBzYW5kYm94LmpzXG4gKi9cbi8qanNsaW50IGVxZXFlcTogZmFsc2UsIG9uZXZhcjogZmFsc2UsIGZvcmluOiB0cnVlLCBwbHVzcGx1czogZmFsc2UqL1xuLypnbG9iYWwgbW9kdWxlLCByZXF1aXJlLCBzaW5vbiovXG4vKipcbiAqIFRlc3QgZnVuY3Rpb24sIHNhbmRib3hlcyBmYWtlc1xuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKHNpbm9uKSB7XG4gICAgdmFyIGNvbW1vbkpTTW9kdWxlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG5cbiAgICBpZiAoIXNpbm9uICYmIGNvbW1vbkpTTW9kdWxlKSB7XG4gICAgICAgIHNpbm9uID0gcmVxdWlyZShcIi4uL3Npbm9uXCIpO1xuICAgIH1cblxuICAgIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRlc3QoY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgY2FsbGJhY2s7XG5cbiAgICAgICAgaWYgKHR5cGUgIT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwic2lub24udGVzdCBuZWVkcyB0byB3cmFwIGEgdGVzdCBmdW5jdGlvbiwgZ290IFwiICsgdHlwZSk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBzaW5vblNhbmRib3hlZFRlc3QoKSB7XG4gICAgICAgICAgICB2YXIgY29uZmlnID0gc2lub24uZ2V0Q29uZmlnKHNpbm9uLmNvbmZpZyk7XG4gICAgICAgICAgICBjb25maWcuaW5qZWN0SW50byA9IGNvbmZpZy5pbmplY3RJbnRvVGhpcyAmJiB0aGlzIHx8IGNvbmZpZy5pbmplY3RJbnRvO1xuICAgICAgICAgICAgdmFyIHNhbmRib3ggPSBzaW5vbi5zYW5kYm94LmNyZWF0ZShjb25maWcpO1xuICAgICAgICAgICAgdmFyIGV4Y2VwdGlvbiwgcmVzdWx0O1xuICAgICAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpLmNvbmNhdChzYW5kYm94LmFyZ3MpO1xuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGNhbGxiYWNrLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGV4Y2VwdGlvbiA9IGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgZXhjZXB0aW9uICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgc2FuZGJveC5yZXN0b3JlKCk7XG4gICAgICAgICAgICAgICAgdGhyb3cgZXhjZXB0aW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgc2FuZGJveC52ZXJpZnlBbmRSZXN0b3JlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGNhbGxiYWNrLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIHNpbm9uQXN5bmNTYW5kYm94ZWRUZXN0KGNhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNpbm9uU2FuZGJveGVkVGVzdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzaW5vblNhbmRib3hlZFRlc3Q7XG4gICAgfVxuXG4gICAgdGVzdC5jb25maWcgPSB7XG4gICAgICAgIGluamVjdEludG9UaGlzOiB0cnVlLFxuICAgICAgICBpbmplY3RJbnRvOiBudWxsLFxuICAgICAgICBwcm9wZXJ0aWVzOiBbXCJzcHlcIiwgXCJzdHViXCIsIFwibW9ja1wiLCBcImNsb2NrXCIsIFwic2VydmVyXCIsIFwicmVxdWVzdHNcIl0sXG4gICAgICAgIHVzZUZha2VUaW1lcnM6IHRydWUsXG4gICAgICAgIHVzZUZha2VTZXJ2ZXI6IHRydWVcbiAgICB9O1xuXG4gICAgc2lub24udGVzdCA9IHRlc3Q7XG5cbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKFtcIm1vZHVsZVwiXSwgZnVuY3Rpb24obW9kdWxlKSB7IG1vZHVsZS5leHBvcnRzID0gdGVzdDsgfSk7XG4gICAgfSBlbHNlIGlmIChjb21tb25KU01vZHVsZSkge1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHRlc3Q7XG4gICAgfVxufSh0eXBlb2Ygc2lub24gPT0gXCJvYmplY3RcIiAmJiBzaW5vbiB8fCBudWxsKSk7XG4iLCIvKipcbiAqIEBkZXBlbmQgLi4vc2lub24uanNcbiAqIEBkZXBlbmQgdGVzdC5qc1xuICovXG4vKmpzbGludCBlcWVxZXE6IGZhbHNlLCBvbmV2YXI6IGZhbHNlLCBlcWVxZXE6IGZhbHNlKi9cbi8qZ2xvYmFsIG1vZHVsZSwgcmVxdWlyZSwgc2lub24qL1xuLyoqXG4gKiBUZXN0IGNhc2UsIHNhbmRib3hlcyBhbGwgdGVzdCBmdW5jdGlvbnNcbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIHZhciBjb21tb25KU01vZHVsZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuXG4gICAgaWYgKCFzaW5vbiAmJiBjb21tb25KU01vZHVsZSkge1xuICAgICAgICBzaW5vbiA9IHJlcXVpcmUoXCIuLi9zaW5vblwiKTtcbiAgICB9XG5cbiAgICBpZiAoIXNpbm9uIHx8ICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5KSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVUZXN0KHByb3BlcnR5LCBzZXRVcCwgdGVhckRvd24pIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChzZXRVcCkge1xuICAgICAgICAgICAgICAgIHNldFVwLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBleGNlcHRpb24sIHJlc3VsdDtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBwcm9wZXJ0eS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGV4Y2VwdGlvbiA9IGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0ZWFyRG93bikge1xuICAgICAgICAgICAgICAgIHRlYXJEb3duLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChleGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBleGNlcHRpb247XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdGVzdENhc2UodGVzdHMsIHByZWZpeCkge1xuICAgICAgICAvKmpzbDppZ25vcmUqL1xuICAgICAgICBpZiAoIXRlc3RzIHx8IHR5cGVvZiB0ZXN0cyAhPSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwic2lub24udGVzdENhc2UgbmVlZHMgYW4gb2JqZWN0IHdpdGggdGVzdCBmdW5jdGlvbnNcIik7XG4gICAgICAgIH1cbiAgICAgICAgLypqc2w6ZW5kKi9cblxuICAgICAgICBwcmVmaXggPSBwcmVmaXggfHwgXCJ0ZXN0XCI7XG4gICAgICAgIHZhciByUHJlZml4ID0gbmV3IFJlZ0V4cChcIl5cIiArIHByZWZpeCk7XG4gICAgICAgIHZhciBtZXRob2RzID0ge30sIHRlc3ROYW1lLCBwcm9wZXJ0eSwgbWV0aG9kO1xuICAgICAgICB2YXIgc2V0VXAgPSB0ZXN0cy5zZXRVcDtcbiAgICAgICAgdmFyIHRlYXJEb3duID0gdGVzdHMudGVhckRvd247XG5cbiAgICAgICAgZm9yICh0ZXN0TmFtZSBpbiB0ZXN0cykge1xuICAgICAgICAgICAgaWYgKHRlc3RzLmhhc093blByb3BlcnR5KHRlc3ROYW1lKSkge1xuICAgICAgICAgICAgICAgIHByb3BlcnR5ID0gdGVzdHNbdGVzdE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgaWYgKC9eKHNldFVwfHRlYXJEb3duKSQvLnRlc3QodGVzdE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcHJvcGVydHkgPT0gXCJmdW5jdGlvblwiICYmIHJQcmVmaXgudGVzdCh0ZXN0TmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gcHJvcGVydHk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHNldFVwIHx8IHRlYXJEb3duKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSBjcmVhdGVUZXN0KHByb3BlcnR5LCBzZXRVcCwgdGVhckRvd24pO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kc1t0ZXN0TmFtZV0gPSBzaW5vbi50ZXN0KG1ldGhvZCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kc1t0ZXN0TmFtZV0gPSB0ZXN0c1t0ZXN0TmFtZV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1ldGhvZHM7XG4gICAgfVxuXG4gICAgc2lub24udGVzdENhc2UgPSB0ZXN0Q2FzZTtcblxuICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoW1wibW9kdWxlXCJdLCBmdW5jdGlvbihtb2R1bGUpIHsgbW9kdWxlLmV4cG9ydHMgPSB0ZXN0Q2FzZTsgfSk7XG4gICAgfSBlbHNlIGlmIChjb21tb25KU01vZHVsZSkge1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHRlc3RDYXNlO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiKGZ1bmN0aW9uIChnbG9iYWwpe1xuLypqc2xpbnQgZXFlcWVxOiBmYWxzZSwgcGx1c3BsdXM6IGZhbHNlLCBldmlsOiB0cnVlLCBvbmV2YXI6IGZhbHNlLCBicm93c2VyOiB0cnVlLCBmb3JpbjogZmFsc2UqL1xuLypnbG9iYWwgbW9kdWxlLCByZXF1aXJlLCB3aW5kb3cqL1xuLyoqXG4gKiBGYWtlIHRpbWVyIEFQSVxuICogc2V0VGltZW91dFxuICogc2V0SW50ZXJ2YWxcbiAqIGNsZWFyVGltZW91dFxuICogY2xlYXJJbnRlcnZhbFxuICogdGlja1xuICogcmVzZXRcbiAqIERhdGVcbiAqXG4gKiBJbnNwaXJlZCBieSBqc1VuaXRNb2NrVGltZU91dCBmcm9tIEpzVW5pdFxuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG5pZiAodHlwZW9mIHNpbm9uID09IFwidW5kZWZpbmVkXCIpIHtcbiAgICB2YXIgc2lub24gPSB7fTtcbn1cblxuKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAvLyBub2RlIGV4cGVjdHMgc2V0VGltZW91dC9zZXRJbnRlcnZhbCB0byByZXR1cm4gYSBmbiBvYmplY3Qgdy8gLnJlZigpLy51bnJlZigpXG4gICAgLy8gYnJvd3NlcnMsIGEgbnVtYmVyLlxuICAgIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vY2pvaGFuc2VuL1Npbm9uLkpTL3B1bGwvNDM2XG4gICAgdmFyIHRpbWVvdXRSZXN1bHQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge30sIDApO1xuICAgIHZhciBhZGRUaW1lclJldHVybnNPYmplY3QgPSB0eXBlb2YgdGltZW91dFJlc3VsdCA9PT0gJ29iamVjdCc7XG4gICAgY2xlYXJUaW1lb3V0KHRpbWVvdXRSZXN1bHQpO1xuXG4gICAgdmFyIGlkID0gMTtcblxuICAgIGZ1bmN0aW9uIGFkZFRpbWVyKGFyZ3MsIHJlY3VycmluZykge1xuICAgICAgICBpZiAoYXJncy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkZ1bmN0aW9uIHJlcXVpcmVzIGF0IGxlYXN0IDEgcGFyYW1ldGVyXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBhcmdzWzBdID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYWxsYmFjayBtdXN0IGJlIHByb3ZpZGVkIHRvIHRpbWVyIGNhbGxzXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHRvSWQgPSBpZCsrO1xuICAgICAgICB2YXIgZGVsYXkgPSBhcmdzWzFdIHx8IDA7XG5cbiAgICAgICAgaWYgKCF0aGlzLnRpbWVvdXRzKSB7XG4gICAgICAgICAgICB0aGlzLnRpbWVvdXRzID0ge307XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnRpbWVvdXRzW3RvSWRdID0ge1xuICAgICAgICAgICAgaWQ6IHRvSWQsXG4gICAgICAgICAgICBmdW5jOiBhcmdzWzBdLFxuICAgICAgICAgICAgY2FsbEF0OiB0aGlzLm5vdyArIGRlbGF5LFxuICAgICAgICAgICAgaW52b2tlQXJnczogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJncywgMilcbiAgICAgICAgfTtcblxuICAgICAgICBpZiAocmVjdXJyaW5nID09PSB0cnVlKSB7XG4gICAgICAgICAgICB0aGlzLnRpbWVvdXRzW3RvSWRdLmludGVydmFsID0gZGVsYXk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoYWRkVGltZXJSZXR1cm5zT2JqZWN0KSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGlkOiB0b0lkLFxuICAgICAgICAgICAgICAgIHJlZjogZnVuY3Rpb24oKSB7fSxcbiAgICAgICAgICAgICAgICB1bnJlZjogZnVuY3Rpb24oKSB7fVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0b0lkO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFyc2VUaW1lKHN0cikge1xuICAgICAgICBpZiAoIXN0cikge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc3RyaW5ncyA9IHN0ci5zcGxpdChcIjpcIik7XG4gICAgICAgIHZhciBsID0gc3RyaW5ncy5sZW5ndGgsIGkgPSBsO1xuICAgICAgICB2YXIgbXMgPSAwLCBwYXJzZWQ7XG5cbiAgICAgICAgaWYgKGwgPiAzIHx8ICEvXihcXGRcXGQ6KXswLDJ9XFxkXFxkPyQvLnRlc3Qoc3RyKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGljayBvbmx5IHVuZGVyc3RhbmRzIG51bWJlcnMgYW5kICdoOm06cydcIik7XG4gICAgICAgIH1cblxuICAgICAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgICAgICBwYXJzZWQgPSBwYXJzZUludChzdHJpbmdzW2ldLCAxMCk7XG5cbiAgICAgICAgICAgIGlmIChwYXJzZWQgPj0gNjApIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHRpbWUgXCIgKyBzdHIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBtcyArPSBwYXJzZWQgKiBNYXRoLnBvdyg2MCwgKGwgLSBpIC0gMSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG1zICogMTAwMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVPYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHZhciBuZXdPYmplY3Q7XG5cbiAgICAgICAgaWYgKE9iamVjdC5jcmVhdGUpIHtcbiAgICAgICAgICAgIG5ld09iamVjdCA9IE9iamVjdC5jcmVhdGUob2JqZWN0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciBGID0gZnVuY3Rpb24gKCkge307XG4gICAgICAgICAgICBGLnByb3RvdHlwZSA9IG9iamVjdDtcbiAgICAgICAgICAgIG5ld09iamVjdCA9IG5ldyBGKCk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXdPYmplY3QuRGF0ZS5jbG9jayA9IG5ld09iamVjdDtcbiAgICAgICAgcmV0dXJuIG5ld09iamVjdDtcbiAgICB9XG5cbiAgICBzaW5vbi5jbG9jayA9IHtcbiAgICAgICAgbm93OiAwLFxuXG4gICAgICAgIGNyZWF0ZTogZnVuY3Rpb24gY3JlYXRlKG5vdykge1xuICAgICAgICAgICAgdmFyIGNsb2NrID0gY3JlYXRlT2JqZWN0KHRoaXMpO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5vdyA9PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgY2xvY2subm93ID0gbm93O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoISFub3cgJiYgdHlwZW9mIG5vdyA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIm5vdyBzaG91bGQgYmUgbWlsbGlzZWNvbmRzIHNpbmNlIFVOSVggZXBvY2hcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBjbG9jaztcbiAgICAgICAgfSxcblxuICAgICAgICBzZXRUaW1lb3V0OiBmdW5jdGlvbiBzZXRUaW1lb3V0KGNhbGxiYWNrLCB0aW1lb3V0KSB7XG4gICAgICAgICAgICByZXR1cm4gYWRkVGltZXIuY2FsbCh0aGlzLCBhcmd1bWVudHMsIGZhbHNlKTtcbiAgICAgICAgfSxcblxuICAgICAgICBjbGVhclRpbWVvdXQ6IGZ1bmN0aW9uIGNsZWFyVGltZW91dCh0aW1lcklkKSB7XG4gICAgICAgICAgICBpZiAoIXRpbWVySWQpIHtcbiAgICAgICAgICAgICAgICAvLyBudWxsIGFwcGVhcnMgdG8gYmUgYWxsb3dlZCBpbiBtb3N0IGJyb3dzZXJzLCBhbmQgYXBwZWFycyB0byBiZSByZWxpZWQgdXBvbiBieSBzb21lIGxpYnJhcmllcywgbGlrZSBCb290c3RyYXAgY2Fyb3VzZWxcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMudGltZW91dHMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRpbWVvdXRzID0gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBpbiBOb2RlLCB0aW1lcklkIGlzIGFuIG9iamVjdCB3aXRoIC5yZWYoKS8udW5yZWYoKSwgYW5kXG4gICAgICAgICAgICAvLyBpdHMgLmlkIGZpZWxkIGlzIHRoZSBhY3R1YWwgdGltZXIgaWQuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHRpbWVySWQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgIHRpbWVySWQgPSB0aW1lcklkLmlkXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGltZXJJZCBpbiB0aGlzLnRpbWVvdXRzKSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMudGltZW91dHNbdGltZXJJZF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgc2V0SW50ZXJ2YWw6IGZ1bmN0aW9uIHNldEludGVydmFsKGNhbGxiYWNrLCB0aW1lb3V0KSB7XG4gICAgICAgICAgICByZXR1cm4gYWRkVGltZXIuY2FsbCh0aGlzLCBhcmd1bWVudHMsIHRydWUpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGNsZWFySW50ZXJ2YWw6IGZ1bmN0aW9uIGNsZWFySW50ZXJ2YWwodGltZXJJZCkge1xuICAgICAgICAgICAgdGhpcy5jbGVhclRpbWVvdXQodGltZXJJZCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgc2V0SW1tZWRpYXRlOiBmdW5jdGlvbiBzZXRJbW1lZGlhdGUoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIHZhciBwYXNzVGhydUFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuXG4gICAgICAgICAgICByZXR1cm4gYWRkVGltZXIuY2FsbCh0aGlzLCBbY2FsbGJhY2ssIDBdLmNvbmNhdChwYXNzVGhydUFyZ3MpLCBmYWxzZSk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgY2xlYXJJbW1lZGlhdGU6IGZ1bmN0aW9uIGNsZWFySW1tZWRpYXRlKHRpbWVySWQpIHtcbiAgICAgICAgICAgIHRoaXMuY2xlYXJUaW1lb3V0KHRpbWVySWQpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHRpY2s6IGZ1bmN0aW9uIHRpY2sobXMpIHtcbiAgICAgICAgICAgIG1zID0gdHlwZW9mIG1zID09IFwibnVtYmVyXCIgPyBtcyA6IHBhcnNlVGltZShtcyk7XG4gICAgICAgICAgICB2YXIgdGlja0Zyb20gPSB0aGlzLm5vdywgdGlja1RvID0gdGhpcy5ub3cgKyBtcywgcHJldmlvdXMgPSB0aGlzLm5vdztcbiAgICAgICAgICAgIHZhciB0aW1lciA9IHRoaXMuZmlyc3RUaW1lckluUmFuZ2UodGlja0Zyb20sIHRpY2tUbyk7XG5cbiAgICAgICAgICAgIHZhciBmaXJzdEV4Y2VwdGlvbjtcbiAgICAgICAgICAgIHdoaWxlICh0aW1lciAmJiB0aWNrRnJvbSA8PSB0aWNrVG8pIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy50aW1lb3V0c1t0aW1lci5pZF0pIHtcbiAgICAgICAgICAgICAgICAgICAgdGlja0Zyb20gPSB0aGlzLm5vdyA9IHRpbWVyLmNhbGxBdDtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGxUaW1lcih0aW1lcik7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICBmaXJzdEV4Y2VwdGlvbiA9IGZpcnN0RXhjZXB0aW9uIHx8IGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aW1lciA9IHRoaXMuZmlyc3RUaW1lckluUmFuZ2UocHJldmlvdXMsIHRpY2tUbyk7XG4gICAgICAgICAgICAgICAgcHJldmlvdXMgPSB0aWNrRnJvbTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5ub3cgPSB0aWNrVG87XG5cbiAgICAgICAgICAgIGlmIChmaXJzdEV4Y2VwdGlvbikge1xuICAgICAgICAgICAgICB0aHJvdyBmaXJzdEV4Y2VwdGlvbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubm93O1xuICAgICAgICB9LFxuXG4gICAgICAgIGZpcnN0VGltZXJJblJhbmdlOiBmdW5jdGlvbiAoZnJvbSwgdG8pIHtcbiAgICAgICAgICAgIHZhciB0aW1lciwgc21hbGxlc3QgPSBudWxsLCBvcmlnaW5hbFRpbWVyO1xuXG4gICAgICAgICAgICBmb3IgKHZhciBpZCBpbiB0aGlzLnRpbWVvdXRzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMudGltZW91dHMuaGFzT3duUHJvcGVydHkoaWQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnRpbWVvdXRzW2lkXS5jYWxsQXQgPCBmcm9tIHx8IHRoaXMudGltZW91dHNbaWRdLmNhbGxBdCA+IHRvKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChzbWFsbGVzdCA9PT0gbnVsbCB8fCB0aGlzLnRpbWVvdXRzW2lkXS5jYWxsQXQgPCBzbWFsbGVzdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ2luYWxUaW1lciA9IHRoaXMudGltZW91dHNbaWRdO1xuICAgICAgICAgICAgICAgICAgICAgICAgc21hbGxlc3QgPSB0aGlzLnRpbWVvdXRzW2lkXS5jYWxsQXQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVyID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZ1bmM6IHRoaXMudGltZW91dHNbaWRdLmZ1bmMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbEF0OiB0aGlzLnRpbWVvdXRzW2lkXS5jYWxsQXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJ2YWw6IHRoaXMudGltZW91dHNbaWRdLmludGVydmFsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkOiB0aGlzLnRpbWVvdXRzW2lkXS5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnZva2VBcmdzOiB0aGlzLnRpbWVvdXRzW2lkXS5pbnZva2VBcmdzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGltZXIgfHwgbnVsbDtcbiAgICAgICAgfSxcblxuICAgICAgICBjYWxsVGltZXI6IGZ1bmN0aW9uICh0aW1lcikge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aW1lci5pbnRlcnZhbCA9PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50aW1lb3V0c1t0aW1lci5pZF0uY2FsbEF0ICs9IHRpbWVyLmludGVydmFsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy50aW1lb3V0c1t0aW1lci5pZF07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aW1lci5mdW5jID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICB0aW1lci5mdW5jLmFwcGx5KG51bGwsIHRpbWVyLmludm9rZUFyZ3MpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGV2YWwodGltZXIuZnVuYyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICB2YXIgZXhjZXB0aW9uID0gZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCF0aGlzLnRpbWVvdXRzW3RpbWVyLmlkXSkge1xuICAgICAgICAgICAgICAgIGlmIChleGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgIHRocm93IGV4Y2VwdGlvbjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgIHRocm93IGV4Y2VwdGlvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICByZXNldDogZnVuY3Rpb24gcmVzZXQoKSB7XG4gICAgICAgICAgICB0aGlzLnRpbWVvdXRzID0ge307XG4gICAgICAgIH0sXG5cbiAgICAgICAgRGF0ZTogKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBOYXRpdmVEYXRlID0gRGF0ZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gQ2xvY2tEYXRlKHllYXIsIG1vbnRoLCBkYXRlLCBob3VyLCBtaW51dGUsIHNlY29uZCwgbXMpIHtcbiAgICAgICAgICAgICAgICAvLyBEZWZlbnNpdmUgYW5kIHZlcmJvc2UgdG8gYXZvaWQgcG90ZW50aWFsIGhhcm0gaW4gcGFzc2luZ1xuICAgICAgICAgICAgICAgIC8vIGV4cGxpY2l0IHVuZGVmaW5lZCB3aGVuIHVzZXIgZG9lcyBub3QgcGFzcyBhcmd1bWVudFxuICAgICAgICAgICAgICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKENsb2NrRGF0ZS5jbG9jay5ub3cpO1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKHllYXIpO1xuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKHllYXIsIG1vbnRoKTtcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgTmF0aXZlRGF0ZSh5ZWFyLCBtb250aCwgZGF0ZSk7XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IE5hdGl2ZURhdGUoeWVhciwgbW9udGgsIGRhdGUsIGhvdXIpO1xuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKHllYXIsIG1vbnRoLCBkYXRlLCBob3VyLCBtaW51dGUpO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKHllYXIsIG1vbnRoLCBkYXRlLCBob3VyLCBtaW51dGUsIHNlY29uZCk7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKHllYXIsIG1vbnRoLCBkYXRlLCBob3VyLCBtaW51dGUsIHNlY29uZCwgbXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIG1pcnJvckRhdGVQcm9wZXJ0aWVzKENsb2NrRGF0ZSwgTmF0aXZlRGF0ZSk7XG4gICAgICAgIH0oKSlcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbWlycm9yRGF0ZVByb3BlcnRpZXModGFyZ2V0LCBzb3VyY2UpIHtcbiAgICAgICAgaWYgKHNvdXJjZS5ub3cpIHtcbiAgICAgICAgICAgIHRhcmdldC5ub3cgPSBmdW5jdGlvbiBub3coKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRhcmdldC5jbG9jay5ub3c7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVsZXRlIHRhcmdldC5ub3c7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc291cmNlLnRvU291cmNlKSB7XG4gICAgICAgICAgICB0YXJnZXQudG9Tb3VyY2UgPSBmdW5jdGlvbiB0b1NvdXJjZSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc291cmNlLnRvU291cmNlKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGVsZXRlIHRhcmdldC50b1NvdXJjZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRhcmdldC50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgcmV0dXJuIHNvdXJjZS50b1N0cmluZygpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHRhcmdldC5wcm90b3R5cGUgPSBzb3VyY2UucHJvdG90eXBlO1xuICAgICAgICB0YXJnZXQucGFyc2UgPSBzb3VyY2UucGFyc2U7XG4gICAgICAgIHRhcmdldC5VVEMgPSBzb3VyY2UuVVRDO1xuICAgICAgICB0YXJnZXQucHJvdG90eXBlLnRvVVRDU3RyaW5nID0gc291cmNlLnByb3RvdHlwZS50b1VUQ1N0cmluZztcblxuICAgICAgICBmb3IgKHZhciBwcm9wIGluIHNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKHNvdXJjZS5oYXNPd25Qcm9wZXJ0eShwcm9wKSkge1xuICAgICAgICAgICAgICAgIHRhcmdldFtwcm9wXSA9IHNvdXJjZVtwcm9wXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgfVxuXG4gICAgdmFyIG1ldGhvZHMgPSBbXCJEYXRlXCIsIFwic2V0VGltZW91dFwiLCBcInNldEludGVydmFsXCIsXG4gICAgICAgICAgICAgICAgICAgXCJjbGVhclRpbWVvdXRcIiwgXCJjbGVhckludGVydmFsXCJdO1xuXG4gICAgaWYgKHR5cGVvZiBnbG9iYWwuc2V0SW1tZWRpYXRlICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIG1ldGhvZHMucHVzaChcInNldEltbWVkaWF0ZVwiKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIGdsb2JhbC5jbGVhckltbWVkaWF0ZSAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICBtZXRob2RzLnB1c2goXCJjbGVhckltbWVkaWF0ZVwiKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXN0b3JlKCkge1xuICAgICAgICB2YXIgbWV0aG9kO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gdGhpcy5tZXRob2RzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgbWV0aG9kID0gdGhpcy5tZXRob2RzW2ldO1xuXG4gICAgICAgICAgICBpZiAoZ2xvYmFsW21ldGhvZF0uaGFkT3duUHJvcGVydHkpIHtcbiAgICAgICAgICAgICAgICBnbG9iYWxbbWV0aG9kXSA9IHRoaXNbXCJfXCIgKyBtZXRob2RdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgZ2xvYmFsW21ldGhvZF07XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByZXZlbnQgbXVsdGlwbGUgZXhlY3V0aW9ucyB3aGljaCB3aWxsIGNvbXBsZXRlbHkgcmVtb3ZlIHRoZXNlIHByb3BzXG4gICAgICAgIHRoaXMubWV0aG9kcyA9IFtdO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0dWJHbG9iYWwobWV0aG9kLCBjbG9jaykge1xuICAgICAgICBjbG9ja1ttZXRob2RdLmhhZE93blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGdsb2JhbCwgbWV0aG9kKTtcbiAgICAgICAgY2xvY2tbXCJfXCIgKyBtZXRob2RdID0gZ2xvYmFsW21ldGhvZF07XG5cbiAgICAgICAgaWYgKG1ldGhvZCA9PSBcIkRhdGVcIikge1xuICAgICAgICAgICAgdmFyIGRhdGUgPSBtaXJyb3JEYXRlUHJvcGVydGllcyhjbG9ja1ttZXRob2RdLCBnbG9iYWxbbWV0aG9kXSk7XG4gICAgICAgICAgICBnbG9iYWxbbWV0aG9kXSA9IGRhdGU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnbG9iYWxbbWV0aG9kXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY2xvY2tbbWV0aG9kXS5hcHBseShjbG9jaywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIGZvciAodmFyIHByb3AgaW4gY2xvY2tbbWV0aG9kXSkge1xuICAgICAgICAgICAgICAgIGlmIChjbG9ja1ttZXRob2RdLmhhc093blByb3BlcnR5KHByb3ApKSB7XG4gICAgICAgICAgICAgICAgICAgIGdsb2JhbFttZXRob2RdW3Byb3BdID0gY2xvY2tbbWV0aG9kXVtwcm9wXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBnbG9iYWxbbWV0aG9kXS5jbG9jayA9IGNsb2NrO1xuICAgIH1cblxuICAgIHNpbm9uLnVzZUZha2VUaW1lcnMgPSBmdW5jdGlvbiB1c2VGYWtlVGltZXJzKG5vdykge1xuICAgICAgICB2YXIgY2xvY2sgPSBzaW5vbi5jbG9jay5jcmVhdGUobm93KTtcbiAgICAgICAgY2xvY2sucmVzdG9yZSA9IHJlc3RvcmU7XG4gICAgICAgIGNsb2NrLm1ldGhvZHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlb2Ygbm93ID09IFwibnVtYmVyXCIgPyAxIDogMCk7XG5cbiAgICAgICAgaWYgKGNsb2NrLm1ldGhvZHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBjbG9jay5tZXRob2RzID0gbWV0aG9kcztcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gY2xvY2subWV0aG9kcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgIHN0dWJHbG9iYWwoY2xvY2subWV0aG9kc1tpXSwgY2xvY2spO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNsb2NrO1xuICAgIH07XG59KHR5cGVvZiBnbG9iYWwgIT0gXCJ1bmRlZmluZWRcIiAmJiB0eXBlb2YgZ2xvYmFsICE9PSBcImZ1bmN0aW9uXCIgPyBnbG9iYWwgOiB0aGlzKSk7XG5cbnNpbm9uLnRpbWVycyA9IHtcbiAgICBzZXRUaW1lb3V0OiBzZXRUaW1lb3V0LFxuICAgIGNsZWFyVGltZW91dDogY2xlYXJUaW1lb3V0LFxuICAgIHNldEltbWVkaWF0ZTogKHR5cGVvZiBzZXRJbW1lZGlhdGUgIT09IFwidW5kZWZpbmVkXCIgPyBzZXRJbW1lZGlhdGUgOiB1bmRlZmluZWQpLFxuICAgIGNsZWFySW1tZWRpYXRlOiAodHlwZW9mIGNsZWFySW1tZWRpYXRlICE9PSBcInVuZGVmaW5lZFwiID8gY2xlYXJJbW1lZGlhdGU6IHVuZGVmaW5lZCksXG4gICAgc2V0SW50ZXJ2YWw6IHNldEludGVydmFsLFxuICAgIGNsZWFySW50ZXJ2YWw6IGNsZWFySW50ZXJ2YWwsXG4gICAgRGF0ZTogRGF0ZVxufTtcblxuaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBzaW5vbjtcbn1cblxufSkuY2FsbCh0aGlzLHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSkiLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG4oKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kICYmIGZ1bmN0aW9uIChtKSB7XG4gICAgZGVmaW5lKFwiZm9ybWF0aW9cIiwgW1wic2Ftc2FtXCJdLCBtKTtcbn0pIHx8ICh0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIGZ1bmN0aW9uIChtKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBtKHJlcXVpcmUoXCJzYW1zYW1cIikpO1xufSkgfHwgZnVuY3Rpb24gKG0pIHsgdGhpcy5mb3JtYXRpbyA9IG0odGhpcy5zYW1zYW0pOyB9XG4pKGZ1bmN0aW9uIChzYW1zYW0pIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIHZhciBmb3JtYXRpbyA9IHtcbiAgICAgICAgZXhjbHVkZUNvbnN0cnVjdG9yczogW1wiT2JqZWN0XCIsIC9eLiQvXSxcbiAgICAgICAgcXVvdGVTdHJpbmdzOiB0cnVlXG4gICAgfTtcblxuICAgIHZhciBoYXNPd24gPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5O1xuXG4gICAgdmFyIHNwZWNpYWxPYmplY3RzID0gW107XG4gICAgaWYgKHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgc3BlY2lhbE9iamVjdHMucHVzaCh7IG9iamVjdDogZ2xvYmFsLCB2YWx1ZTogXCJbb2JqZWN0IGdsb2JhbF1cIiB9KTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICBzcGVjaWFsT2JqZWN0cy5wdXNoKHtcbiAgICAgICAgICAgIG9iamVjdDogZG9jdW1lbnQsXG4gICAgICAgICAgICB2YWx1ZTogXCJbb2JqZWN0IEhUTUxEb2N1bWVudF1cIlxuICAgICAgICB9KTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgc3BlY2lhbE9iamVjdHMucHVzaCh7IG9iamVjdDogd2luZG93LCB2YWx1ZTogXCJbb2JqZWN0IFdpbmRvd11cIiB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmdW5jdGlvbk5hbWUoZnVuYykge1xuICAgICAgICBpZiAoIWZ1bmMpIHsgcmV0dXJuIFwiXCI7IH1cbiAgICAgICAgaWYgKGZ1bmMuZGlzcGxheU5hbWUpIHsgcmV0dXJuIGZ1bmMuZGlzcGxheU5hbWU7IH1cbiAgICAgICAgaWYgKGZ1bmMubmFtZSkgeyByZXR1cm4gZnVuYy5uYW1lOyB9XG4gICAgICAgIHZhciBtYXRjaGVzID0gZnVuYy50b1N0cmluZygpLm1hdGNoKC9mdW5jdGlvblxccysoW15cXChdKykvbSk7XG4gICAgICAgIHJldHVybiAobWF0Y2hlcyAmJiBtYXRjaGVzWzFdKSB8fCBcIlwiO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbnN0cnVjdG9yTmFtZShmLCBvYmplY3QpIHtcbiAgICAgICAgdmFyIG5hbWUgPSBmdW5jdGlvbk5hbWUob2JqZWN0ICYmIG9iamVjdC5jb25zdHJ1Y3Rvcik7XG4gICAgICAgIHZhciBleGNsdWRlcyA9IGYuZXhjbHVkZUNvbnN0cnVjdG9ycyB8fFxuICAgICAgICAgICAgICAgIGZvcm1hdGlvLmV4Y2x1ZGVDb25zdHJ1Y3RvcnMgfHwgW107XG5cbiAgICAgICAgdmFyIGksIGw7XG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBleGNsdWRlcy5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZXhjbHVkZXNbaV0gPT09IFwic3RyaW5nXCIgJiYgZXhjbHVkZXNbaV0gPT09IG5hbWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXCJcIjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZXhjbHVkZXNbaV0udGVzdCAmJiBleGNsdWRlc1tpXS50ZXN0KG5hbWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbmFtZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0NpcmN1bGFyKG9iamVjdCwgb2JqZWN0cykge1xuICAgICAgICBpZiAodHlwZW9mIG9iamVjdCAhPT0gXCJvYmplY3RcIikgeyByZXR1cm4gZmFsc2U7IH1cbiAgICAgICAgdmFyIGksIGw7XG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBvYmplY3RzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgaWYgKG9iamVjdHNbaV0gPT09IG9iamVjdCkgeyByZXR1cm4gdHJ1ZTsgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhc2NpaShmLCBvYmplY3QsIHByb2Nlc3NlZCwgaW5kZW50KSB7XG4gICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0ID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICB2YXIgcXMgPSBmLnF1b3RlU3RyaW5ncztcbiAgICAgICAgICAgIHZhciBxdW90ZSA9IHR5cGVvZiBxcyAhPT0gXCJib29sZWFuXCIgfHwgcXM7XG4gICAgICAgICAgICByZXR1cm4gcHJvY2Vzc2VkIHx8IHF1b3RlID8gJ1wiJyArIG9iamVjdCArICdcIicgOiBvYmplY3Q7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIG9iamVjdCA9PT0gXCJmdW5jdGlvblwiICYmICEob2JqZWN0IGluc3RhbmNlb2YgUmVnRXhwKSkge1xuICAgICAgICAgICAgcmV0dXJuIGFzY2lpLmZ1bmMob2JqZWN0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHByb2Nlc3NlZCA9IHByb2Nlc3NlZCB8fCBbXTtcblxuICAgICAgICBpZiAoaXNDaXJjdWxhcihvYmplY3QsIHByb2Nlc3NlZCkpIHsgcmV0dXJuIFwiW0NpcmN1bGFyXVwiOyB9XG5cbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmplY3QpID09PSBcIltvYmplY3QgQXJyYXldXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBhc2NpaS5hcnJheS5jYWxsKGYsIG9iamVjdCwgcHJvY2Vzc2VkKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghb2JqZWN0KSB7IHJldHVybiBTdHJpbmcoKDEvb2JqZWN0KSA9PT0gLUluZmluaXR5ID8gXCItMFwiIDogb2JqZWN0KTsgfVxuICAgICAgICBpZiAoc2Ftc2FtLmlzRWxlbWVudChvYmplY3QpKSB7IHJldHVybiBhc2NpaS5lbGVtZW50KG9iamVjdCk7IH1cblxuICAgICAgICBpZiAodHlwZW9mIG9iamVjdC50b1N0cmluZyA9PT0gXCJmdW5jdGlvblwiICYmXG4gICAgICAgICAgICAgICAgb2JqZWN0LnRvU3RyaW5nICE9PSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gb2JqZWN0LnRvU3RyaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaSwgbDtcbiAgICAgICAgZm9yIChpID0gMCwgbCA9IHNwZWNpYWxPYmplY3RzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgaWYgKG9iamVjdCA9PT0gc3BlY2lhbE9iamVjdHNbaV0ub2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNwZWNpYWxPYmplY3RzW2ldLnZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFzY2lpLm9iamVjdC5jYWxsKGYsIG9iamVjdCwgcHJvY2Vzc2VkLCBpbmRlbnQpO1xuICAgIH1cblxuICAgIGFzY2lpLmZ1bmMgPSBmdW5jdGlvbiAoZnVuYykge1xuICAgICAgICByZXR1cm4gXCJmdW5jdGlvbiBcIiArIGZ1bmN0aW9uTmFtZShmdW5jKSArIFwiKCkge31cIjtcbiAgICB9O1xuXG4gICAgYXNjaWkuYXJyYXkgPSBmdW5jdGlvbiAoYXJyYXksIHByb2Nlc3NlZCkge1xuICAgICAgICBwcm9jZXNzZWQgPSBwcm9jZXNzZWQgfHwgW107XG4gICAgICAgIHByb2Nlc3NlZC5wdXNoKGFycmF5KTtcbiAgICAgICAgdmFyIGksIGwsIHBpZWNlcyA9IFtdO1xuICAgICAgICBmb3IgKGkgPSAwLCBsID0gYXJyYXkubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICBwaWVjZXMucHVzaChhc2NpaSh0aGlzLCBhcnJheVtpXSwgcHJvY2Vzc2VkKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFwiW1wiICsgcGllY2VzLmpvaW4oXCIsIFwiKSArIFwiXVwiO1xuICAgIH07XG5cbiAgICBhc2NpaS5vYmplY3QgPSBmdW5jdGlvbiAob2JqZWN0LCBwcm9jZXNzZWQsIGluZGVudCkge1xuICAgICAgICBwcm9jZXNzZWQgPSBwcm9jZXNzZWQgfHwgW107XG4gICAgICAgIHByb2Nlc3NlZC5wdXNoKG9iamVjdCk7XG4gICAgICAgIGluZGVudCA9IGluZGVudCB8fCAwO1xuICAgICAgICB2YXIgcGllY2VzID0gW10sIHByb3BlcnRpZXMgPSBzYW1zYW0ua2V5cyhvYmplY3QpLnNvcnQoKTtcbiAgICAgICAgdmFyIGxlbmd0aCA9IDM7XG4gICAgICAgIHZhciBwcm9wLCBzdHIsIG9iaiwgaSwgbDtcblxuICAgICAgICBmb3IgKGkgPSAwLCBsID0gcHJvcGVydGllcy5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgIHByb3AgPSBwcm9wZXJ0aWVzW2ldO1xuICAgICAgICAgICAgb2JqID0gb2JqZWN0W3Byb3BdO1xuXG4gICAgICAgICAgICBpZiAoaXNDaXJjdWxhcihvYmosIHByb2Nlc3NlZCkpIHtcbiAgICAgICAgICAgICAgICBzdHIgPSBcIltDaXJjdWxhcl1cIjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3RyID0gYXNjaWkodGhpcywgb2JqLCBwcm9jZXNzZWQsIGluZGVudCArIDIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzdHIgPSAoL1xccy8udGVzdChwcm9wKSA/ICdcIicgKyBwcm9wICsgJ1wiJyA6IHByb3ApICsgXCI6IFwiICsgc3RyO1xuICAgICAgICAgICAgbGVuZ3RoICs9IHN0ci5sZW5ndGg7XG4gICAgICAgICAgICBwaWVjZXMucHVzaChzdHIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNvbnMgPSBjb25zdHJ1Y3Rvck5hbWUodGhpcywgb2JqZWN0KTtcbiAgICAgICAgdmFyIHByZWZpeCA9IGNvbnMgPyBcIltcIiArIGNvbnMgKyBcIl0gXCIgOiBcIlwiO1xuICAgICAgICB2YXIgaXMgPSBcIlwiO1xuICAgICAgICBmb3IgKGkgPSAwLCBsID0gaW5kZW50OyBpIDwgbDsgKytpKSB7IGlzICs9IFwiIFwiOyB9XG5cbiAgICAgICAgaWYgKGxlbmd0aCArIGluZGVudCA+IDgwKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJlZml4ICsgXCJ7XFxuICBcIiArIGlzICsgcGllY2VzLmpvaW4oXCIsXFxuICBcIiArIGlzKSArIFwiXFxuXCIgK1xuICAgICAgICAgICAgICAgIGlzICsgXCJ9XCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHByZWZpeCArIFwieyBcIiArIHBpZWNlcy5qb2luKFwiLCBcIikgKyBcIiB9XCI7XG4gICAgfTtcblxuICAgIGFzY2lpLmVsZW1lbnQgPSBmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgICAgICB2YXIgdGFnTmFtZSA9IGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICB2YXIgYXR0cnMgPSBlbGVtZW50LmF0dHJpYnV0ZXMsIGF0dHIsIHBhaXJzID0gW10sIGF0dHJOYW1lLCBpLCBsLCB2YWw7XG5cbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGF0dHJzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgYXR0ciA9IGF0dHJzLml0ZW0oaSk7XG4gICAgICAgICAgICBhdHRyTmFtZSA9IGF0dHIubm9kZU5hbWUudG9Mb3dlckNhc2UoKS5yZXBsYWNlKFwiaHRtbDpcIiwgXCJcIik7XG4gICAgICAgICAgICB2YWwgPSBhdHRyLm5vZGVWYWx1ZTtcbiAgICAgICAgICAgIGlmIChhdHRyTmFtZSAhPT0gXCJjb250ZW50ZWRpdGFibGVcIiB8fCB2YWwgIT09IFwiaW5oZXJpdFwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEhdmFsKSB7IHBhaXJzLnB1c2goYXR0ck5hbWUgKyBcIj1cXFwiXCIgKyB2YWwgKyBcIlxcXCJcIik7IH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBmb3JtYXR0ZWQgPSBcIjxcIiArIHRhZ05hbWUgKyAocGFpcnMubGVuZ3RoID4gMCA/IFwiIFwiIDogXCJcIik7XG4gICAgICAgIHZhciBjb250ZW50ID0gZWxlbWVudC5pbm5lckhUTUw7XG5cbiAgICAgICAgaWYgKGNvbnRlbnQubGVuZ3RoID4gMjApIHtcbiAgICAgICAgICAgIGNvbnRlbnQgPSBjb250ZW50LnN1YnN0cigwLCAyMCkgKyBcIlsuLi5dXCI7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcmVzID0gZm9ybWF0dGVkICsgcGFpcnMuam9pbihcIiBcIikgKyBcIj5cIiArIGNvbnRlbnQgK1xuICAgICAgICAgICAgICAgIFwiPC9cIiArIHRhZ05hbWUgKyBcIj5cIjtcblxuICAgICAgICByZXR1cm4gcmVzLnJlcGxhY2UoLyBjb250ZW50RWRpdGFibGU9XCJpbmhlcml0XCIvLCBcIlwiKTtcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gRm9ybWF0aW8ob3B0aW9ucykge1xuICAgICAgICBmb3IgKHZhciBvcHQgaW4gb3B0aW9ucykge1xuICAgICAgICAgICAgdGhpc1tvcHRdID0gb3B0aW9uc1tvcHRdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgRm9ybWF0aW8ucHJvdG90eXBlID0ge1xuICAgICAgICBmdW5jdGlvbk5hbWU6IGZ1bmN0aW9uTmFtZSxcblxuICAgICAgICBjb25maWd1cmU6IGZ1bmN0aW9uIChvcHRpb25zKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEZvcm1hdGlvKG9wdGlvbnMpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGNvbnN0cnVjdG9yTmFtZTogZnVuY3Rpb24gKG9iamVjdCkge1xuICAgICAgICAgICAgcmV0dXJuIGNvbnN0cnVjdG9yTmFtZSh0aGlzLCBvYmplY3QpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGFzY2lpOiBmdW5jdGlvbiAob2JqZWN0LCBwcm9jZXNzZWQsIGluZGVudCkge1xuICAgICAgICAgICAgcmV0dXJuIGFzY2lpKHRoaXMsIG9iamVjdCwgcHJvY2Vzc2VkLCBpbmRlbnQpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBGb3JtYXRpby5wcm90b3R5cGU7XG59KTtcblxufSkuY2FsbCh0aGlzLHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSkiLCIoKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kICYmIGZ1bmN0aW9uIChtKSB7IGRlZmluZShcInNhbXNhbVwiLCBtKTsgfSkgfHxcbiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJlxuICAgICAgZnVuY3Rpb24gKG0pIHsgbW9kdWxlLmV4cG9ydHMgPSBtKCk7IH0pIHx8IC8vIE5vZGVcbiBmdW5jdGlvbiAobSkgeyB0aGlzLnNhbXNhbSA9IG0oKTsgfSAvLyBCcm93c2VyIGdsb2JhbHNcbikoZnVuY3Rpb24gKCkge1xuICAgIHZhciBvID0gT2JqZWN0LnByb3RvdHlwZTtcbiAgICB2YXIgZGl2ID0gdHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiICYmIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG5cbiAgICBmdW5jdGlvbiBpc05hTih2YWx1ZSkge1xuICAgICAgICAvLyBVbmxpa2UgZ2xvYmFsIGlzTmFOLCB0aGlzIGF2b2lkcyB0eXBlIGNvZXJjaW9uXG4gICAgICAgIC8vIHR5cGVvZiBjaGVjayBhdm9pZHMgSUUgaG9zdCBvYmplY3QgaXNzdWVzLCBoYXQgdGlwIHRvXG4gICAgICAgIC8vIGxvZGFzaFxuICAgICAgICB2YXIgdmFsID0gdmFsdWU7IC8vIEpzTGludCB0aGlua3MgdmFsdWUgIT09IHZhbHVlIGlzIFwid2VpcmRcIlxuICAgICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiICYmIHZhbHVlICE9PSB2YWw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Q2xhc3ModmFsdWUpIHtcbiAgICAgICAgLy8gUmV0dXJucyB0aGUgaW50ZXJuYWwgW1tDbGFzc11dIGJ5IGNhbGxpbmcgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ1xuICAgICAgICAvLyB3aXRoIHRoZSBwcm92aWRlZCB2YWx1ZSBhcyB0aGlzLiBSZXR1cm4gdmFsdWUgaXMgYSBzdHJpbmcsIG5hbWluZyB0aGVcbiAgICAgICAgLy8gaW50ZXJuYWwgY2xhc3MsIGUuZy4gXCJBcnJheVwiXG4gICAgICAgIHJldHVybiBvLnRvU3RyaW5nLmNhbGwodmFsdWUpLnNwbGl0KC9bIFxcXV0vKVsxXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAbmFtZSBzYW1zYW0uaXNBcmd1bWVudHNcbiAgICAgKiBAcGFyYW0gT2JqZWN0IG9iamVjdFxuICAgICAqXG4gICAgICogUmV0dXJucyBgYHRydWVgYCBpZiBgYG9iamVjdGBgIGlzIGFuIGBgYXJndW1lbnRzYGAgb2JqZWN0LFxuICAgICAqIGBgZmFsc2VgYCBvdGhlcndpc2UuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNBcmd1bWVudHMob2JqZWN0KSB7XG4gICAgICAgIGlmIChnZXRDbGFzcyhvYmplY3QpID09PSAnQXJndW1lbnRzJykgeyByZXR1cm4gdHJ1ZTsgfVxuICAgICAgICBpZiAodHlwZW9mIG9iamVjdCAhPT0gXCJvYmplY3RcIiB8fCB0eXBlb2Ygb2JqZWN0Lmxlbmd0aCAhPT0gXCJudW1iZXJcIiB8fFxuICAgICAgICAgICAgICAgIGdldENsYXNzKG9iamVjdCkgPT09IFwiQXJyYXlcIikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LmNhbGxlZSA9PSBcImZ1bmN0aW9uXCIpIHsgcmV0dXJuIHRydWU7IH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG9iamVjdFtvYmplY3QubGVuZ3RoXSA9IDY7XG4gICAgICAgICAgICBkZWxldGUgb2JqZWN0W29iamVjdC5sZW5ndGhdO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQG5hbWUgc2Ftc2FtLmlzRWxlbWVudFxuICAgICAqIEBwYXJhbSBPYmplY3Qgb2JqZWN0XG4gICAgICpcbiAgICAgKiBSZXR1cm5zIGBgdHJ1ZWBgIGlmIGBgb2JqZWN0YGAgaXMgYSBET00gZWxlbWVudCBub2RlLiBVbmxpa2VcbiAgICAgKiBVbmRlcnNjb3JlLmpzL2xvZGFzaCwgdGhpcyBmdW5jdGlvbiB3aWxsIHJldHVybiBgYGZhbHNlYGAgaWYgYGBvYmplY3RgYFxuICAgICAqIGlzIGFuICplbGVtZW50LWxpa2UqIG9iamVjdCwgaS5lLiBhIHJlZ3VsYXIgb2JqZWN0IHdpdGggYSBgYG5vZGVUeXBlYGBcbiAgICAgKiBwcm9wZXJ0eSB0aGF0IGhvbGRzIHRoZSB2YWx1ZSBgYDFgYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0VsZW1lbnQob2JqZWN0KSB7XG4gICAgICAgIGlmICghb2JqZWN0IHx8IG9iamVjdC5ub2RlVHlwZSAhPT0gMSB8fCAhZGl2KSB7IHJldHVybiBmYWxzZTsgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgb2JqZWN0LmFwcGVuZENoaWxkKGRpdik7XG4gICAgICAgICAgICBvYmplY3QucmVtb3ZlQ2hpbGQoZGl2KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBuYW1lIHNhbXNhbS5rZXlzXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmplY3RcbiAgICAgKlxuICAgICAqIFJldHVybiBhbiBhcnJheSBvZiBvd24gcHJvcGVydHkgbmFtZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24ga2V5cyhvYmplY3QpIHtcbiAgICAgICAgdmFyIGtzID0gW10sIHByb3A7XG4gICAgICAgIGZvciAocHJvcCBpbiBvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wKSkgeyBrcy5wdXNoKHByb3ApOyB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGtzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBuYW1lIHNhbXNhbS5pc0RhdGVcbiAgICAgKiBAcGFyYW0gT2JqZWN0IHZhbHVlXG4gICAgICpcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIG9iamVjdCBpcyBhIGBgRGF0ZWBgLCBvciAqZGF0ZS1saWtlKi4gRHVjayB0eXBpbmdcbiAgICAgKiBvZiBkYXRlIG9iamVjdHMgd29yayBieSBjaGVja2luZyB0aGF0IHRoZSBvYmplY3QgaGFzIGEgYGBnZXRUaW1lYGBcbiAgICAgKiBmdW5jdGlvbiB3aG9zZSByZXR1cm4gdmFsdWUgZXF1YWxzIHRoZSByZXR1cm4gdmFsdWUgZnJvbSB0aGUgb2JqZWN0J3NcbiAgICAgKiBgYHZhbHVlT2ZgYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0RhdGUodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZS5nZXRUaW1lID09IFwiZnVuY3Rpb25cIiAmJlxuICAgICAgICAgICAgdmFsdWUuZ2V0VGltZSgpID09IHZhbHVlLnZhbHVlT2YoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAbmFtZSBzYW1zYW0uaXNOZWdaZXJvXG4gICAgICogQHBhcmFtIE9iamVjdCB2YWx1ZVxuICAgICAqXG4gICAgICogUmV0dXJucyBgYHRydWVgYCBpZiBgYHZhbHVlYGAgaXMgYGAtMGBgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTmVnWmVybyh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlID09PSAtSW5maW5pdHk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQG5hbWUgc2Ftc2FtLmVxdWFsXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmoxXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmoyXG4gICAgICpcbiAgICAgKiBSZXR1cm5zIGBgdHJ1ZWBgIGlmIHR3byBvYmplY3RzIGFyZSBzdHJpY3RseSBlcXVhbC4gQ29tcGFyZWQgdG9cbiAgICAgKiBgYD09PWBgIHRoZXJlIGFyZSB0d28gZXhjZXB0aW9uczpcbiAgICAgKlxuICAgICAqICAgLSBOYU4gaXMgY29uc2lkZXJlZCBlcXVhbCB0byBOYU5cbiAgICAgKiAgIC0gLTAgYW5kICswIGFyZSBub3QgY29uc2lkZXJlZCBlcXVhbFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlkZW50aWNhbChvYmoxLCBvYmoyKSB7XG4gICAgICAgIGlmIChvYmoxID09PSBvYmoyIHx8IChpc05hTihvYmoxKSAmJiBpc05hTihvYmoyKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmoxICE9PSAwIHx8IGlzTmVnWmVybyhvYmoxKSA9PT0gaXNOZWdaZXJvKG9iajIpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBAbmFtZSBzYW1zYW0uZGVlcEVxdWFsXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmoxXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmoyXG4gICAgICpcbiAgICAgKiBEZWVwIGVxdWFsIGNvbXBhcmlzb24uIFR3byB2YWx1ZXMgYXJlIFwiZGVlcCBlcXVhbFwiIGlmOlxuICAgICAqXG4gICAgICogICAtIFRoZXkgYXJlIGVxdWFsLCBhY2NvcmRpbmcgdG8gc2Ftc2FtLmlkZW50aWNhbFxuICAgICAqICAgLSBUaGV5IGFyZSBib3RoIGRhdGUgb2JqZWN0cyByZXByZXNlbnRpbmcgdGhlIHNhbWUgdGltZVxuICAgICAqICAgLSBUaGV5IGFyZSBib3RoIGFycmF5cyBjb250YWluaW5nIGVsZW1lbnRzIHRoYXQgYXJlIGFsbCBkZWVwRXF1YWxcbiAgICAgKiAgIC0gVGhleSBhcmUgb2JqZWN0cyB3aXRoIHRoZSBzYW1lIHNldCBvZiBwcm9wZXJ0aWVzLCBhbmQgZWFjaCBwcm9wZXJ0eVxuICAgICAqICAgICBpbiBgYG9iajFgYCBpcyBkZWVwRXF1YWwgdG8gdGhlIGNvcnJlc3BvbmRpbmcgcHJvcGVydHkgaW4gYGBvYmoyYGBcbiAgICAgKlxuICAgICAqIFN1cHBvcnRzIGN5Y2xpYyBvYmplY3RzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRlZXBFcXVhbEN5Y2xpYyhvYmoxLCBvYmoyKSB7XG5cbiAgICAgICAgLy8gdXNlZCBmb3IgY3ljbGljIGNvbXBhcmlzb25cbiAgICAgICAgLy8gY29udGFpbiBhbHJlYWR5IHZpc2l0ZWQgb2JqZWN0c1xuICAgICAgICB2YXIgb2JqZWN0czEgPSBbXSxcbiAgICAgICAgICAgIG9iamVjdHMyID0gW10sXG4gICAgICAgIC8vIGNvbnRhaW4gcGF0aGVzIChwb3NpdGlvbiBpbiB0aGUgb2JqZWN0IHN0cnVjdHVyZSlcbiAgICAgICAgLy8gb2YgdGhlIGFscmVhZHkgdmlzaXRlZCBvYmplY3RzXG4gICAgICAgIC8vIGluZGV4ZXMgc2FtZSBhcyBpbiBvYmplY3RzIGFycmF5c1xuICAgICAgICAgICAgcGF0aHMxID0gW10sXG4gICAgICAgICAgICBwYXRoczIgPSBbXSxcbiAgICAgICAgLy8gY29udGFpbnMgY29tYmluYXRpb25zIG9mIGFscmVhZHkgY29tcGFyZWQgb2JqZWN0c1xuICAgICAgICAvLyBpbiB0aGUgbWFubmVyOiB7IFwiJDFbJ3JlZiddJDJbJ3JlZiddXCI6IHRydWUgfVxuICAgICAgICAgICAgY29tcGFyZWQgPSB7fTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogdXNlZCB0byBjaGVjaywgaWYgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkgaXMgYW4gb2JqZWN0XG4gICAgICAgICAqIChjeWNsaWMgbG9naWMgaXMgb25seSBuZWVkZWQgZm9yIG9iamVjdHMpXG4gICAgICAgICAqIG9ubHkgbmVlZGVkIGZvciBjeWNsaWMgbG9naWNcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIGlzT2JqZWN0KHZhbHVlKSB7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBCb29sZWFuKSAmJlxuICAgICAgICAgICAgICAgICAgICAhKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkgICAgJiZcbiAgICAgICAgICAgICAgICAgICAgISh2YWx1ZSBpbnN0YW5jZW9mIE51bWJlcikgICYmXG4gICAgICAgICAgICAgICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBSZWdFeHApICAmJlxuICAgICAgICAgICAgICAgICAgICAhKHZhbHVlIGluc3RhbmNlb2YgU3RyaW5nKSkge1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiByZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgZ2l2ZW4gb2JqZWN0IGluIHRoZVxuICAgICAgICAgKiBnaXZlbiBvYmplY3RzIGFycmF5LCAtMSBpZiBub3QgY29udGFpbmVkXG4gICAgICAgICAqIG9ubHkgbmVlZGVkIGZvciBjeWNsaWMgbG9naWNcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIGdldEluZGV4KG9iamVjdHMsIG9iaikge1xuXG4gICAgICAgICAgICB2YXIgaTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBvYmplY3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9iamVjdHNbaV0gPT09IG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGRvZXMgdGhlIHJlY3Vyc2lvbiBmb3IgdGhlIGRlZXAgZXF1YWwgY2hlY2tcbiAgICAgICAgcmV0dXJuIChmdW5jdGlvbiBkZWVwRXF1YWwob2JqMSwgb2JqMiwgcGF0aDEsIHBhdGgyKSB7XG4gICAgICAgICAgICB2YXIgdHlwZTEgPSB0eXBlb2Ygb2JqMTtcbiAgICAgICAgICAgIHZhciB0eXBlMiA9IHR5cGVvZiBvYmoyO1xuXG4gICAgICAgICAgICAvLyA9PSBudWxsIGFsc28gbWF0Y2hlcyB1bmRlZmluZWRcbiAgICAgICAgICAgIGlmIChvYmoxID09PSBvYmoyIHx8XG4gICAgICAgICAgICAgICAgICAgIGlzTmFOKG9iajEpIHx8IGlzTmFOKG9iajIpIHx8XG4gICAgICAgICAgICAgICAgICAgIG9iajEgPT0gbnVsbCB8fCBvYmoyID09IG51bGwgfHxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTEgIT09IFwib2JqZWN0XCIgfHwgdHlwZTIgIT09IFwib2JqZWN0XCIpIHtcblxuICAgICAgICAgICAgICAgIHJldHVybiBpZGVudGljYWwob2JqMSwgb2JqMik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEVsZW1lbnRzIGFyZSBvbmx5IGVxdWFsIGlmIGlkZW50aWNhbChleHBlY3RlZCwgYWN0dWFsKVxuICAgICAgICAgICAgaWYgKGlzRWxlbWVudChvYmoxKSB8fCBpc0VsZW1lbnQob2JqMikpIHsgcmV0dXJuIGZhbHNlOyB9XG5cbiAgICAgICAgICAgIHZhciBpc0RhdGUxID0gaXNEYXRlKG9iajEpLCBpc0RhdGUyID0gaXNEYXRlKG9iajIpO1xuICAgICAgICAgICAgaWYgKGlzRGF0ZTEgfHwgaXNEYXRlMikge1xuICAgICAgICAgICAgICAgIGlmICghaXNEYXRlMSB8fCAhaXNEYXRlMiB8fCBvYmoxLmdldFRpbWUoKSAhPT0gb2JqMi5nZXRUaW1lKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9iajEgaW5zdGFuY2VvZiBSZWdFeHAgJiYgb2JqMiBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgICAgIGlmIChvYmoxLnRvU3RyaW5nKCkgIT09IG9iajIudG9TdHJpbmcoKSkgeyByZXR1cm4gZmFsc2U7IH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGNsYXNzMSA9IGdldENsYXNzKG9iajEpO1xuICAgICAgICAgICAgdmFyIGNsYXNzMiA9IGdldENsYXNzKG9iajIpO1xuICAgICAgICAgICAgdmFyIGtleXMxID0ga2V5cyhvYmoxKTtcbiAgICAgICAgICAgIHZhciBrZXlzMiA9IGtleXMob2JqMik7XG5cbiAgICAgICAgICAgIGlmIChpc0FyZ3VtZW50cyhvYmoxKSB8fCBpc0FyZ3VtZW50cyhvYmoyKSkge1xuICAgICAgICAgICAgICAgIGlmIChvYmoxLmxlbmd0aCAhPT0gb2JqMi5sZW5ndGgpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlMSAhPT0gdHlwZTIgfHwgY2xhc3MxICE9PSBjbGFzczIgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXMxLmxlbmd0aCAhPT0ga2V5czIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBrZXksIGksIGwsXG4gICAgICAgICAgICAgICAgLy8gZm9sbG93aW5nIHZhcnMgYXJlIHVzZWQgZm9yIHRoZSBjeWNsaWMgbG9naWNcbiAgICAgICAgICAgICAgICB2YWx1ZTEsIHZhbHVlMixcbiAgICAgICAgICAgICAgICBpc09iamVjdDEsIGlzT2JqZWN0MixcbiAgICAgICAgICAgICAgICBpbmRleDEsIGluZGV4MixcbiAgICAgICAgICAgICAgICBuZXdQYXRoMSwgbmV3UGF0aDI7XG5cbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGwgPSBrZXlzMS5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICBrZXkgPSBrZXlzMVtpXTtcbiAgICAgICAgICAgICAgICBpZiAoIW8uaGFzT3duUHJvcGVydHkuY2FsbChvYmoyLCBrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBTdGFydCBvZiB0aGUgY3ljbGljIGxvZ2ljXG5cbiAgICAgICAgICAgICAgICB2YWx1ZTEgPSBvYmoxW2tleV07XG4gICAgICAgICAgICAgICAgdmFsdWUyID0gb2JqMltrZXldO1xuXG4gICAgICAgICAgICAgICAgaXNPYmplY3QxID0gaXNPYmplY3QodmFsdWUxKTtcbiAgICAgICAgICAgICAgICBpc09iamVjdDIgPSBpc09iamVjdCh2YWx1ZTIpO1xuXG4gICAgICAgICAgICAgICAgLy8gZGV0ZXJtaW5lLCBpZiB0aGUgb2JqZWN0cyB3ZXJlIGFscmVhZHkgdmlzaXRlZFxuICAgICAgICAgICAgICAgIC8vIChpdCdzIGZhc3RlciB0byBjaGVjayBmb3IgaXNPYmplY3QgZmlyc3QsIHRoYW4gdG9cbiAgICAgICAgICAgICAgICAvLyBnZXQgLTEgZnJvbSBnZXRJbmRleCBmb3Igbm9uIG9iamVjdHMpXG4gICAgICAgICAgICAgICAgaW5kZXgxID0gaXNPYmplY3QxID8gZ2V0SW5kZXgob2JqZWN0czEsIHZhbHVlMSkgOiAtMTtcbiAgICAgICAgICAgICAgICBpbmRleDIgPSBpc09iamVjdDIgPyBnZXRJbmRleChvYmplY3RzMiwgdmFsdWUyKSA6IC0xO1xuXG4gICAgICAgICAgICAgICAgLy8gZGV0ZXJtaW5lIHRoZSBuZXcgcGF0aGVzIG9mIHRoZSBvYmplY3RzXG4gICAgICAgICAgICAgICAgLy8gLSBmb3Igbm9uIGN5Y2xpYyBvYmplY3RzIHRoZSBjdXJyZW50IHBhdGggd2lsbCBiZSBleHRlbmRlZFxuICAgICAgICAgICAgICAgIC8vICAgYnkgY3VycmVudCBwcm9wZXJ0eSBuYW1lXG4gICAgICAgICAgICAgICAgLy8gLSBmb3IgY3ljbGljIG9iamVjdHMgdGhlIHN0b3JlZCBwYXRoIGlzIHRha2VuXG4gICAgICAgICAgICAgICAgbmV3UGF0aDEgPSBpbmRleDEgIT09IC0xXG4gICAgICAgICAgICAgICAgICAgID8gcGF0aHMxW2luZGV4MV1cbiAgICAgICAgICAgICAgICAgICAgOiBwYXRoMSArICdbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXSc7XG4gICAgICAgICAgICAgICAgbmV3UGF0aDIgPSBpbmRleDIgIT09IC0xXG4gICAgICAgICAgICAgICAgICAgID8gcGF0aHMyW2luZGV4Ml1cbiAgICAgICAgICAgICAgICAgICAgOiBwYXRoMiArICdbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXSc7XG5cbiAgICAgICAgICAgICAgICAvLyBzdG9wIHJlY3Vyc2lvbiBpZiBjdXJyZW50IG9iamVjdHMgYXJlIGFscmVhZHkgY29tcGFyZWRcbiAgICAgICAgICAgICAgICBpZiAoY29tcGFyZWRbbmV3UGF0aDEgKyBuZXdQYXRoMl0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtZW1iZXIgdGhlIGN1cnJlbnQgb2JqZWN0cyBhbmQgdGhlaXIgcGF0aGVzXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4MSA9PT0gLTEgJiYgaXNPYmplY3QxKSB7XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdHMxLnB1c2godmFsdWUxKTtcbiAgICAgICAgICAgICAgICAgICAgcGF0aHMxLnB1c2gobmV3UGF0aDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXgyID09PSAtMSAmJiBpc09iamVjdDIpIHtcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0czIucHVzaCh2YWx1ZTIpO1xuICAgICAgICAgICAgICAgICAgICBwYXRoczIucHVzaChuZXdQYXRoMik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtZW1iZXIgdGhhdCB0aGUgY3VycmVudCBvYmplY3RzIGFyZSBhbHJlYWR5IGNvbXBhcmVkXG4gICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0MSAmJiBpc09iamVjdDIpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGFyZWRbbmV3UGF0aDEgKyBuZXdQYXRoMl0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEVuZCBvZiBjeWNsaWMgbG9naWNcblxuICAgICAgICAgICAgICAgIC8vIG5laXRoZXIgdmFsdWUxIG5vciB2YWx1ZTIgaXMgYSBjeWNsZVxuICAgICAgICAgICAgICAgIC8vIGNvbnRpbnVlIHdpdGggbmV4dCBsZXZlbFxuICAgICAgICAgICAgICAgIGlmICghZGVlcEVxdWFsKHZhbHVlMSwgdmFsdWUyLCBuZXdQYXRoMSwgbmV3UGF0aDIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuXG4gICAgICAgIH0ob2JqMSwgb2JqMiwgJyQxJywgJyQyJykpO1xuICAgIH1cblxuICAgIHZhciBtYXRjaDtcblxuICAgIGZ1bmN0aW9uIGFycmF5Q29udGFpbnMoYXJyYXksIHN1YnNldCkge1xuICAgICAgICBpZiAoc3Vic2V0Lmxlbmd0aCA9PT0gMCkgeyByZXR1cm4gdHJ1ZTsgfVxuICAgICAgICB2YXIgaSwgbCwgaiwgaztcbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGFycmF5Lmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgaWYgKG1hdGNoKGFycmF5W2ldLCBzdWJzZXRbMF0pKSB7XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMCwgayA9IHN1YnNldC5sZW5ndGg7IGogPCBrOyArK2opIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFtYXRjaChhcnJheVtpICsgal0sIHN1YnNldFtqXSkpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAbmFtZSBzYW1zYW0ubWF0Y2hcbiAgICAgKiBAcGFyYW0gT2JqZWN0IG9iamVjdFxuICAgICAqIEBwYXJhbSBPYmplY3QgbWF0Y2hlclxuICAgICAqXG4gICAgICogQ29tcGFyZSBhcmJpdHJhcnkgdmFsdWUgYGBvYmplY3RgYCB3aXRoIG1hdGNoZXIuXG4gICAgICovXG4gICAgbWF0Y2ggPSBmdW5jdGlvbiBtYXRjaChvYmplY3QsIG1hdGNoZXIpIHtcbiAgICAgICAgaWYgKG1hdGNoZXIgJiYgdHlwZW9mIG1hdGNoZXIudGVzdCA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hlci50ZXN0KG9iamVjdCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIG1hdGNoZXIgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXIob2JqZWN0KSA9PT0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbWF0Y2hlciA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgbWF0Y2hlciA9IG1hdGNoZXIudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgIHZhciBub3ROdWxsID0gdHlwZW9mIG9iamVjdCA9PT0gXCJzdHJpbmdcIiB8fCAhIW9iamVjdDtcbiAgICAgICAgICAgIHJldHVybiBub3ROdWxsICYmXG4gICAgICAgICAgICAgICAgKFN0cmluZyhvYmplY3QpKS50b0xvd2VyQ2FzZSgpLmluZGV4T2YobWF0Y2hlcikgPj0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbWF0Y2hlciA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXIgPT09IG9iamVjdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbWF0Y2hlciA9PT0gXCJib29sZWFuXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBtYXRjaGVyID09PSBvYmplY3Q7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZ2V0Q2xhc3Mob2JqZWN0KSA9PT0gXCJBcnJheVwiICYmIGdldENsYXNzKG1hdGNoZXIpID09PSBcIkFycmF5XCIpIHtcbiAgICAgICAgICAgIHJldHVybiBhcnJheUNvbnRhaW5zKG9iamVjdCwgbWF0Y2hlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWF0Y2hlciAmJiB0eXBlb2YgbWF0Y2hlciA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgdmFyIHByb3A7XG4gICAgICAgICAgICBmb3IgKHByb3AgaW4gbWF0Y2hlcikge1xuICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IG9iamVjdFtwcm9wXTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcInVuZGVmaW5lZFwiICYmXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlb2Ygb2JqZWN0LmdldEF0dHJpYnV0ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gb2JqZWN0LmdldEF0dHJpYnV0ZShwcm9wKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJ1bmRlZmluZWRcIiB8fCAhbWF0Y2godmFsdWUsIG1hdGNoZXJbcHJvcF0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk1hdGNoZXIgd2FzIG5vdCBhIHN0cmluZywgYSBudW1iZXIsIGEgXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgXCJmdW5jdGlvbiwgYSBib29sZWFuIG9yIGFuIG9iamVjdFwiKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgaXNBcmd1bWVudHM6IGlzQXJndW1lbnRzLFxuICAgICAgICBpc0VsZW1lbnQ6IGlzRWxlbWVudCxcbiAgICAgICAgaXNEYXRlOiBpc0RhdGUsXG4gICAgICAgIGlzTmVnWmVybzogaXNOZWdaZXJvLFxuICAgICAgICBpZGVudGljYWw6IGlkZW50aWNhbCxcbiAgICAgICAgZGVlcEVxdWFsOiBkZWVwRXF1YWxDeWNsaWMsXG4gICAgICAgIG1hdGNoOiBtYXRjaCxcbiAgICAgICAga2V5czoga2V5c1xuICAgIH07XG59KTtcbiIsIi8vICAgICBVbmRlcnNjb3JlLmpzIDEuNi4wXG4vLyAgICAgaHR0cDovL3VuZGVyc2NvcmVqcy5vcmdcbi8vICAgICAoYykgMjAwOS0yMDE0IEplcmVteSBBc2hrZW5hcywgRG9jdW1lbnRDbG91ZCBhbmQgSW52ZXN0aWdhdGl2ZSBSZXBvcnRlcnMgJiBFZGl0b3JzXG4vLyAgICAgVW5kZXJzY29yZSBtYXkgYmUgZnJlZWx5IGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBNSVQgbGljZW5zZS5cblxuKGZ1bmN0aW9uKCkge1xuXG4gIC8vIEJhc2VsaW5lIHNldHVwXG4gIC8vIC0tLS0tLS0tLS0tLS0tXG5cbiAgLy8gRXN0YWJsaXNoIHRoZSByb290IG9iamVjdCwgYHdpbmRvd2AgaW4gdGhlIGJyb3dzZXIsIG9yIGBleHBvcnRzYCBvbiB0aGUgc2VydmVyLlxuICB2YXIgcm9vdCA9IHRoaXM7XG5cbiAgLy8gU2F2ZSB0aGUgcHJldmlvdXMgdmFsdWUgb2YgdGhlIGBfYCB2YXJpYWJsZS5cbiAgdmFyIHByZXZpb3VzVW5kZXJzY29yZSA9IHJvb3QuXztcblxuICAvLyBFc3RhYmxpc2ggdGhlIG9iamVjdCB0aGF0IGdldHMgcmV0dXJuZWQgdG8gYnJlYWsgb3V0IG9mIGEgbG9vcCBpdGVyYXRpb24uXG4gIHZhciBicmVha2VyID0ge307XG5cbiAgLy8gU2F2ZSBieXRlcyBpbiB0aGUgbWluaWZpZWQgKGJ1dCBub3QgZ3ppcHBlZCkgdmVyc2lvbjpcbiAgdmFyIEFycmF5UHJvdG8gPSBBcnJheS5wcm90b3R5cGUsIE9ialByb3RvID0gT2JqZWN0LnByb3RvdHlwZSwgRnVuY1Byb3RvID0gRnVuY3Rpb24ucHJvdG90eXBlO1xuXG4gIC8vIENyZWF0ZSBxdWljayByZWZlcmVuY2UgdmFyaWFibGVzIGZvciBzcGVlZCBhY2Nlc3MgdG8gY29yZSBwcm90b3R5cGVzLlxuICB2YXJcbiAgICBwdXNoICAgICAgICAgICAgID0gQXJyYXlQcm90by5wdXNoLFxuICAgIHNsaWNlICAgICAgICAgICAgPSBBcnJheVByb3RvLnNsaWNlLFxuICAgIGNvbmNhdCAgICAgICAgICAgPSBBcnJheVByb3RvLmNvbmNhdCxcbiAgICB0b1N0cmluZyAgICAgICAgID0gT2JqUHJvdG8udG9TdHJpbmcsXG4gICAgaGFzT3duUHJvcGVydHkgICA9IE9ialByb3RvLmhhc093blByb3BlcnR5O1xuXG4gIC8vIEFsbCAqKkVDTUFTY3JpcHQgNSoqIG5hdGl2ZSBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvbnMgdGhhdCB3ZSBob3BlIHRvIHVzZVxuICAvLyBhcmUgZGVjbGFyZWQgaGVyZS5cbiAgdmFyXG4gICAgbmF0aXZlRm9yRWFjaCAgICAgID0gQXJyYXlQcm90by5mb3JFYWNoLFxuICAgIG5hdGl2ZU1hcCAgICAgICAgICA9IEFycmF5UHJvdG8ubWFwLFxuICAgIG5hdGl2ZVJlZHVjZSAgICAgICA9IEFycmF5UHJvdG8ucmVkdWNlLFxuICAgIG5hdGl2ZVJlZHVjZVJpZ2h0ICA9IEFycmF5UHJvdG8ucmVkdWNlUmlnaHQsXG4gICAgbmF0aXZlRmlsdGVyICAgICAgID0gQXJyYXlQcm90by5maWx0ZXIsXG4gICAgbmF0aXZlRXZlcnkgICAgICAgID0gQXJyYXlQcm90by5ldmVyeSxcbiAgICBuYXRpdmVTb21lICAgICAgICAgPSBBcnJheVByb3RvLnNvbWUsXG4gICAgbmF0aXZlSW5kZXhPZiAgICAgID0gQXJyYXlQcm90by5pbmRleE9mLFxuICAgIG5hdGl2ZUxhc3RJbmRleE9mICA9IEFycmF5UHJvdG8ubGFzdEluZGV4T2YsXG4gICAgbmF0aXZlSXNBcnJheSAgICAgID0gQXJyYXkuaXNBcnJheSxcbiAgICBuYXRpdmVLZXlzICAgICAgICAgPSBPYmplY3Qua2V5cyxcbiAgICBuYXRpdmVCaW5kICAgICAgICAgPSBGdW5jUHJvdG8uYmluZDtcblxuICAvLyBDcmVhdGUgYSBzYWZlIHJlZmVyZW5jZSB0byB0aGUgVW5kZXJzY29yZSBvYmplY3QgZm9yIHVzZSBiZWxvdy5cbiAgdmFyIF8gPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAob2JqIGluc3RhbmNlb2YgXykgcmV0dXJuIG9iajtcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgXykpIHJldHVybiBuZXcgXyhvYmopO1xuICAgIHRoaXMuX3dyYXBwZWQgPSBvYmo7XG4gIH07XG5cbiAgLy8gRXhwb3J0IHRoZSBVbmRlcnNjb3JlIG9iamVjdCBmb3IgKipOb2RlLmpzKiosIHdpdGhcbiAgLy8gYmFja3dhcmRzLWNvbXBhdGliaWxpdHkgZm9yIHRoZSBvbGQgYHJlcXVpcmUoKWAgQVBJLiBJZiB3ZSdyZSBpblxuICAvLyB0aGUgYnJvd3NlciwgYWRkIGBfYCBhcyBhIGdsb2JhbCBvYmplY3QgdmlhIGEgc3RyaW5nIGlkZW50aWZpZXIsXG4gIC8vIGZvciBDbG9zdXJlIENvbXBpbGVyIFwiYWR2YW5jZWRcIiBtb2RlLlxuICBpZiAodHlwZW9mIGV4cG9ydHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgICBleHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSBfO1xuICAgIH1cbiAgICBleHBvcnRzLl8gPSBfO1xuICB9IGVsc2Uge1xuICAgIHJvb3QuXyA9IF87XG4gIH1cblxuICAvLyBDdXJyZW50IHZlcnNpb24uXG4gIF8uVkVSU0lPTiA9ICcxLjYuMCc7XG5cbiAgLy8gQ29sbGVjdGlvbiBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBUaGUgY29ybmVyc3RvbmUsIGFuIGBlYWNoYCBpbXBsZW1lbnRhdGlvbiwgYWthIGBmb3JFYWNoYC5cbiAgLy8gSGFuZGxlcyBvYmplY3RzIHdpdGggdGhlIGJ1aWx0LWluIGBmb3JFYWNoYCwgYXJyYXlzLCBhbmQgcmF3IG9iamVjdHMuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBmb3JFYWNoYCBpZiBhdmFpbGFibGUuXG4gIHZhciBlYWNoID0gXy5lYWNoID0gXy5mb3JFYWNoID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIG9iajtcbiAgICBpZiAobmF0aXZlRm9yRWFjaCAmJiBvYmouZm9yRWFjaCA9PT0gbmF0aXZlRm9yRWFjaCkge1xuICAgICAgb2JqLmZvckVhY2goaXRlcmF0b3IsIGNvbnRleHQpO1xuICAgIH0gZWxzZSBpZiAob2JqLmxlbmd0aCA9PT0gK29iai5sZW5ndGgpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBvYmoubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqW2ldLCBpLCBvYmopID09PSBicmVha2VyKSByZXR1cm47XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0ga2V5cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoaXRlcmF0b3IuY2FsbChjb250ZXh0LCBvYmpba2V5c1tpXV0sIGtleXNbaV0sIG9iaikgPT09IGJyZWFrZXIpIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG9iajtcbiAgfTtcblxuICAvLyBSZXR1cm4gdGhlIHJlc3VsdHMgb2YgYXBwbHlpbmcgdGhlIGl0ZXJhdG9yIHRvIGVhY2ggZWxlbWVudC5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYG1hcGAgaWYgYXZhaWxhYmxlLlxuICBfLm1hcCA9IF8uY29sbGVjdCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIHJlc3VsdHM7XG4gICAgaWYgKG5hdGl2ZU1hcCAmJiBvYmoubWFwID09PSBuYXRpdmVNYXApIHJldHVybiBvYmoubWFwKGl0ZXJhdG9yLCBjb250ZXh0KTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICByZXN1bHRzLnB1c2goaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfTtcblxuICB2YXIgcmVkdWNlRXJyb3IgPSAnUmVkdWNlIG9mIGVtcHR5IGFycmF5IHdpdGggbm8gaW5pdGlhbCB2YWx1ZSc7XG5cbiAgLy8gKipSZWR1Y2UqKiBidWlsZHMgdXAgYSBzaW5nbGUgcmVzdWx0IGZyb20gYSBsaXN0IG9mIHZhbHVlcywgYWthIGBpbmplY3RgLFxuICAvLyBvciBgZm9sZGxgLiBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgcmVkdWNlYCBpZiBhdmFpbGFibGUuXG4gIF8ucmVkdWNlID0gXy5mb2xkbCA9IF8uaW5qZWN0ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgbWVtbywgY29udGV4dCkge1xuICAgIHZhciBpbml0aWFsID0gYXJndW1lbnRzLmxlbmd0aCA+IDI7XG4gICAgaWYgKG9iaiA9PSBudWxsKSBvYmogPSBbXTtcbiAgICBpZiAobmF0aXZlUmVkdWNlICYmIG9iai5yZWR1Y2UgPT09IG5hdGl2ZVJlZHVjZSkge1xuICAgICAgaWYgKGNvbnRleHQpIGl0ZXJhdG9yID0gXy5iaW5kKGl0ZXJhdG9yLCBjb250ZXh0KTtcbiAgICAgIHJldHVybiBpbml0aWFsID8gb2JqLnJlZHVjZShpdGVyYXRvciwgbWVtbykgOiBvYmoucmVkdWNlKGl0ZXJhdG9yKTtcbiAgICB9XG4gICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgaWYgKCFpbml0aWFsKSB7XG4gICAgICAgIG1lbW8gPSB2YWx1ZTtcbiAgICAgICAgaW5pdGlhbCA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtZW1vID0gaXRlcmF0b3IuY2FsbChjb250ZXh0LCBtZW1vLCB2YWx1ZSwgaW5kZXgsIGxpc3QpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmICghaW5pdGlhbCkgdGhyb3cgbmV3IFR5cGVFcnJvcihyZWR1Y2VFcnJvcik7XG4gICAgcmV0dXJuIG1lbW87XG4gIH07XG5cbiAgLy8gVGhlIHJpZ2h0LWFzc29jaWF0aXZlIHZlcnNpb24gb2YgcmVkdWNlLCBhbHNvIGtub3duIGFzIGBmb2xkcmAuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGByZWR1Y2VSaWdodGAgaWYgYXZhaWxhYmxlLlxuICBfLnJlZHVjZVJpZ2h0ID0gXy5mb2xkciA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIG1lbW8sIGNvbnRleHQpIHtcbiAgICB2YXIgaW5pdGlhbCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyO1xuICAgIGlmIChvYmogPT0gbnVsbCkgb2JqID0gW107XG4gICAgaWYgKG5hdGl2ZVJlZHVjZVJpZ2h0ICYmIG9iai5yZWR1Y2VSaWdodCA9PT0gbmF0aXZlUmVkdWNlUmlnaHQpIHtcbiAgICAgIGlmIChjb250ZXh0KSBpdGVyYXRvciA9IF8uYmluZChpdGVyYXRvciwgY29udGV4dCk7XG4gICAgICByZXR1cm4gaW5pdGlhbCA/IG9iai5yZWR1Y2VSaWdodChpdGVyYXRvciwgbWVtbykgOiBvYmoucmVkdWNlUmlnaHQoaXRlcmF0b3IpO1xuICAgIH1cbiAgICB2YXIgbGVuZ3RoID0gb2JqLmxlbmd0aDtcbiAgICBpZiAobGVuZ3RoICE9PSArbGVuZ3RoKSB7XG4gICAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xuICAgICAgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XG4gICAgfVxuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIGluZGV4ID0ga2V5cyA/IGtleXNbLS1sZW5ndGhdIDogLS1sZW5ndGg7XG4gICAgICBpZiAoIWluaXRpYWwpIHtcbiAgICAgICAgbWVtbyA9IG9ialtpbmRleF07XG4gICAgICAgIGluaXRpYWwgPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWVtbyA9IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgbWVtbywgb2JqW2luZGV4XSwgaW5kZXgsIGxpc3QpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmICghaW5pdGlhbCkgdGhyb3cgbmV3IFR5cGVFcnJvcihyZWR1Y2VFcnJvcik7XG4gICAgcmV0dXJuIG1lbW87XG4gIH07XG5cbiAgLy8gUmV0dXJuIHRoZSBmaXJzdCB2YWx1ZSB3aGljaCBwYXNzZXMgYSB0cnV0aCB0ZXN0LiBBbGlhc2VkIGFzIGBkZXRlY3RgLlxuICBfLmZpbmQgPSBfLmRldGVjdCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgdmFyIHJlc3VsdDtcbiAgICBhbnkob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIGlmIChwcmVkaWNhdGUuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKSB7XG4gICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIHRoYXQgcGFzcyBhIHRydXRoIHRlc3QuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBmaWx0ZXJgIGlmIGF2YWlsYWJsZS5cbiAgLy8gQWxpYXNlZCBhcyBgc2VsZWN0YC5cbiAgXy5maWx0ZXIgPSBfLnNlbGVjdCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiByZXN1bHRzO1xuICAgIGlmIChuYXRpdmVGaWx0ZXIgJiYgb2JqLmZpbHRlciA9PT0gbmF0aXZlRmlsdGVyKSByZXR1cm4gb2JqLmZpbHRlcihwcmVkaWNhdGUsIGNvbnRleHQpO1xuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIGlmIChwcmVkaWNhdGUuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKSByZXN1bHRzLnB1c2godmFsdWUpO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9O1xuXG4gIC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIGZvciB3aGljaCBhIHRydXRoIHRlc3QgZmFpbHMuXG4gIF8ucmVqZWN0ID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcbiAgICByZXR1cm4gXy5maWx0ZXIob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIHJldHVybiAhcHJlZGljYXRlLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KTtcbiAgICB9LCBjb250ZXh0KTtcbiAgfTtcblxuICAvLyBEZXRlcm1pbmUgd2hldGhlciBhbGwgb2YgdGhlIGVsZW1lbnRzIG1hdGNoIGEgdHJ1dGggdGVzdC5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYGV2ZXJ5YCBpZiBhdmFpbGFibGUuXG4gIC8vIEFsaWFzZWQgYXMgYGFsbGAuXG4gIF8uZXZlcnkgPSBfLmFsbCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgcHJlZGljYXRlIHx8IChwcmVkaWNhdGUgPSBfLmlkZW50aXR5KTtcbiAgICB2YXIgcmVzdWx0ID0gdHJ1ZTtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiByZXN1bHQ7XG4gICAgaWYgKG5hdGl2ZUV2ZXJ5ICYmIG9iai5ldmVyeSA9PT0gbmF0aXZlRXZlcnkpIHJldHVybiBvYmouZXZlcnkocHJlZGljYXRlLCBjb250ZXh0KTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICBpZiAoIShyZXN1bHQgPSByZXN1bHQgJiYgcHJlZGljYXRlLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KSkpIHJldHVybiBicmVha2VyO1xuICAgIH0pO1xuICAgIHJldHVybiAhIXJlc3VsdDtcbiAgfTtcblxuICAvLyBEZXRlcm1pbmUgaWYgYXQgbGVhc3Qgb25lIGVsZW1lbnQgaW4gdGhlIG9iamVjdCBtYXRjaGVzIGEgdHJ1dGggdGVzdC5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYHNvbWVgIGlmIGF2YWlsYWJsZS5cbiAgLy8gQWxpYXNlZCBhcyBgYW55YC5cbiAgdmFyIGFueSA9IF8uc29tZSA9IF8uYW55ID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcbiAgICBwcmVkaWNhdGUgfHwgKHByZWRpY2F0ZSA9IF8uaWRlbnRpdHkpO1xuICAgIHZhciByZXN1bHQgPSBmYWxzZTtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiByZXN1bHQ7XG4gICAgaWYgKG5hdGl2ZVNvbWUgJiYgb2JqLnNvbWUgPT09IG5hdGl2ZVNvbWUpIHJldHVybiBvYmouc29tZShwcmVkaWNhdGUsIGNvbnRleHQpO1xuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIGlmIChyZXN1bHQgfHwgKHJlc3VsdCA9IHByZWRpY2F0ZS5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdCkpKSByZXR1cm4gYnJlYWtlcjtcbiAgICB9KTtcbiAgICByZXR1cm4gISFyZXN1bHQ7XG4gIH07XG5cbiAgLy8gRGV0ZXJtaW5lIGlmIHRoZSBhcnJheSBvciBvYmplY3QgY29udGFpbnMgYSBnaXZlbiB2YWx1ZSAodXNpbmcgYD09PWApLlxuICAvLyBBbGlhc2VkIGFzIGBpbmNsdWRlYC5cbiAgXy5jb250YWlucyA9IF8uaW5jbHVkZSA9IGZ1bmN0aW9uKG9iaiwgdGFyZ2V0KSB7XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKG5hdGl2ZUluZGV4T2YgJiYgb2JqLmluZGV4T2YgPT09IG5hdGl2ZUluZGV4T2YpIHJldHVybiBvYmouaW5kZXhPZih0YXJnZXQpICE9IC0xO1xuICAgIHJldHVybiBhbnkob2JqLCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSB0YXJnZXQ7XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gSW52b2tlIGEgbWV0aG9kICh3aXRoIGFyZ3VtZW50cykgb24gZXZlcnkgaXRlbSBpbiBhIGNvbGxlY3Rpb24uXG4gIF8uaW52b2tlID0gZnVuY3Rpb24ob2JqLCBtZXRob2QpIHtcbiAgICB2YXIgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICB2YXIgaXNGdW5jID0gXy5pc0Z1bmN0aW9uKG1ldGhvZCk7XG4gICAgcmV0dXJuIF8ubWFwKG9iaiwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJldHVybiAoaXNGdW5jID8gbWV0aG9kIDogdmFsdWVbbWV0aG9kXSkuYXBwbHkodmFsdWUsIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIENvbnZlbmllbmNlIHZlcnNpb24gb2YgYSBjb21tb24gdXNlIGNhc2Ugb2YgYG1hcGA6IGZldGNoaW5nIGEgcHJvcGVydHkuXG4gIF8ucGx1Y2sgPSBmdW5jdGlvbihvYmosIGtleSkge1xuICAgIHJldHVybiBfLm1hcChvYmosIF8ucHJvcGVydHkoa2V5KSk7XG4gIH07XG5cbiAgLy8gQ29udmVuaWVuY2UgdmVyc2lvbiBvZiBhIGNvbW1vbiB1c2UgY2FzZSBvZiBgZmlsdGVyYDogc2VsZWN0aW5nIG9ubHkgb2JqZWN0c1xuICAvLyBjb250YWluaW5nIHNwZWNpZmljIGBrZXk6dmFsdWVgIHBhaXJzLlxuICBfLndoZXJlID0gZnVuY3Rpb24ob2JqLCBhdHRycykge1xuICAgIHJldHVybiBfLmZpbHRlcihvYmosIF8ubWF0Y2hlcyhhdHRycykpO1xuICB9O1xuXG4gIC8vIENvbnZlbmllbmNlIHZlcnNpb24gb2YgYSBjb21tb24gdXNlIGNhc2Ugb2YgYGZpbmRgOiBnZXR0aW5nIHRoZSBmaXJzdCBvYmplY3RcbiAgLy8gY29udGFpbmluZyBzcGVjaWZpYyBga2V5OnZhbHVlYCBwYWlycy5cbiAgXy5maW5kV2hlcmUgPSBmdW5jdGlvbihvYmosIGF0dHJzKSB7XG4gICAgcmV0dXJuIF8uZmluZChvYmosIF8ubWF0Y2hlcyhhdHRycykpO1xuICB9O1xuXG4gIC8vIFJldHVybiB0aGUgbWF4aW11bSBlbGVtZW50IG9yIChlbGVtZW50LWJhc2VkIGNvbXB1dGF0aW9uKS5cbiAgLy8gQ2FuJ3Qgb3B0aW1pemUgYXJyYXlzIG9mIGludGVnZXJzIGxvbmdlciB0aGFuIDY1LDUzNSBlbGVtZW50cy5cbiAgLy8gU2VlIFtXZWJLaXQgQnVnIDgwNzk3XShodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9ODA3OTcpXG4gIF8ubWF4ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGlmICghaXRlcmF0b3IgJiYgXy5pc0FycmF5KG9iaikgJiYgb2JqWzBdID09PSArb2JqWzBdICYmIG9iai5sZW5ndGggPCA2NTUzNSkge1xuICAgICAgcmV0dXJuIE1hdGgubWF4LmFwcGx5KE1hdGgsIG9iaik7XG4gICAgfVxuICAgIHZhciByZXN1bHQgPSAtSW5maW5pdHksIGxhc3RDb21wdXRlZCA9IC1JbmZpbml0eTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICB2YXIgY29tcHV0ZWQgPSBpdGVyYXRvciA/IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KSA6IHZhbHVlO1xuICAgICAgaWYgKGNvbXB1dGVkID4gbGFzdENvbXB1dGVkKSB7XG4gICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICBsYXN0Q29tcHV0ZWQgPSBjb21wdXRlZDtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFJldHVybiB0aGUgbWluaW11bSBlbGVtZW50IChvciBlbGVtZW50LWJhc2VkIGNvbXB1dGF0aW9uKS5cbiAgXy5taW4gPSBmdW5jdGlvbihvYmosIGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgaWYgKCFpdGVyYXRvciAmJiBfLmlzQXJyYXkob2JqKSAmJiBvYmpbMF0gPT09ICtvYmpbMF0gJiYgb2JqLmxlbmd0aCA8IDY1NTM1KSB7XG4gICAgICByZXR1cm4gTWF0aC5taW4uYXBwbHkoTWF0aCwgb2JqKTtcbiAgICB9XG4gICAgdmFyIHJlc3VsdCA9IEluZmluaXR5LCBsYXN0Q29tcHV0ZWQgPSBJbmZpbml0eTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICB2YXIgY29tcHV0ZWQgPSBpdGVyYXRvciA/IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KSA6IHZhbHVlO1xuICAgICAgaWYgKGNvbXB1dGVkIDwgbGFzdENvbXB1dGVkKSB7XG4gICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICBsYXN0Q29tcHV0ZWQgPSBjb21wdXRlZDtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFNodWZmbGUgYW4gYXJyYXksIHVzaW5nIHRoZSBtb2Rlcm4gdmVyc2lvbiBvZiB0aGVcbiAgLy8gW0Zpc2hlci1ZYXRlcyBzaHVmZmxlXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Zpc2hlcuKAk1lhdGVzX3NodWZmbGUpLlxuICBfLnNodWZmbGUgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgcmFuZDtcbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHZhciBzaHVmZmxlZCA9IFtdO1xuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmFuZCA9IF8ucmFuZG9tKGluZGV4KyspO1xuICAgICAgc2h1ZmZsZWRbaW5kZXggLSAxXSA9IHNodWZmbGVkW3JhbmRdO1xuICAgICAgc2h1ZmZsZWRbcmFuZF0gPSB2YWx1ZTtcbiAgICB9KTtcbiAgICByZXR1cm4gc2h1ZmZsZWQ7XG4gIH07XG5cbiAgLy8gU2FtcGxlICoqbioqIHJhbmRvbSB2YWx1ZXMgZnJvbSBhIGNvbGxlY3Rpb24uXG4gIC8vIElmICoqbioqIGlzIG5vdCBzcGVjaWZpZWQsIHJldHVybnMgYSBzaW5nbGUgcmFuZG9tIGVsZW1lbnQuXG4gIC8vIFRoZSBpbnRlcm5hbCBgZ3VhcmRgIGFyZ3VtZW50IGFsbG93cyBpdCB0byB3b3JrIHdpdGggYG1hcGAuXG4gIF8uc2FtcGxlID0gZnVuY3Rpb24ob2JqLCBuLCBndWFyZCkge1xuICAgIGlmIChuID09IG51bGwgfHwgZ3VhcmQpIHtcbiAgICAgIGlmIChvYmoubGVuZ3RoICE9PSArb2JqLmxlbmd0aCkgb2JqID0gXy52YWx1ZXMob2JqKTtcbiAgICAgIHJldHVybiBvYmpbXy5yYW5kb20ob2JqLmxlbmd0aCAtIDEpXTtcbiAgICB9XG4gICAgcmV0dXJuIF8uc2h1ZmZsZShvYmopLnNsaWNlKDAsIE1hdGgubWF4KDAsIG4pKTtcbiAgfTtcblxuICAvLyBBbiBpbnRlcm5hbCBmdW5jdGlvbiB0byBnZW5lcmF0ZSBsb29rdXAgaXRlcmF0b3JzLlxuICB2YXIgbG9va3VwSXRlcmF0b3IgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PSBudWxsKSByZXR1cm4gXy5pZGVudGl0eTtcbiAgICBpZiAoXy5pc0Z1bmN0aW9uKHZhbHVlKSkgcmV0dXJuIHZhbHVlO1xuICAgIHJldHVybiBfLnByb3BlcnR5KHZhbHVlKTtcbiAgfTtcblxuICAvLyBTb3J0IHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24gcHJvZHVjZWQgYnkgYW4gaXRlcmF0b3IuXG4gIF8uc29ydEJ5ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGl0ZXJhdG9yID0gbG9va3VwSXRlcmF0b3IoaXRlcmF0b3IpO1xuICAgIHJldHVybiBfLnBsdWNrKF8ubWFwKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgIGluZGV4OiBpbmRleCxcbiAgICAgICAgY3JpdGVyaWE6IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KVxuICAgICAgfTtcbiAgICB9KS5zb3J0KGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7XG4gICAgICB2YXIgYSA9IGxlZnQuY3JpdGVyaWE7XG4gICAgICB2YXIgYiA9IHJpZ2h0LmNyaXRlcmlhO1xuICAgICAgaWYgKGEgIT09IGIpIHtcbiAgICAgICAgaWYgKGEgPiBiIHx8IGEgPT09IHZvaWQgMCkgcmV0dXJuIDE7XG4gICAgICAgIGlmIChhIDwgYiB8fCBiID09PSB2b2lkIDApIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBsZWZ0LmluZGV4IC0gcmlnaHQuaW5kZXg7XG4gICAgfSksICd2YWx1ZScpO1xuICB9O1xuXG4gIC8vIEFuIGludGVybmFsIGZ1bmN0aW9uIHVzZWQgZm9yIGFnZ3JlZ2F0ZSBcImdyb3VwIGJ5XCIgb3BlcmF0aW9ucy5cbiAgdmFyIGdyb3VwID0gZnVuY3Rpb24oYmVoYXZpb3IpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgaXRlcmF0b3IgPSBsb29rdXBJdGVyYXRvcihpdGVyYXRvcik7XG4gICAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICAgIHZhciBrZXkgPSBpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgb2JqKTtcbiAgICAgICAgYmVoYXZpb3IocmVzdWx0LCBrZXksIHZhbHVlKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICB9O1xuXG4gIC8vIEdyb3VwcyB0aGUgb2JqZWN0J3MgdmFsdWVzIGJ5IGEgY3JpdGVyaW9uLiBQYXNzIGVpdGhlciBhIHN0cmluZyBhdHRyaWJ1dGVcbiAgLy8gdG8gZ3JvdXAgYnksIG9yIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSBjcml0ZXJpb24uXG4gIF8uZ3JvdXBCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwga2V5LCB2YWx1ZSkge1xuICAgIF8uaGFzKHJlc3VsdCwga2V5KSA/IHJlc3VsdFtrZXldLnB1c2godmFsdWUpIDogcmVzdWx0W2tleV0gPSBbdmFsdWVdO1xuICB9KTtcblxuICAvLyBJbmRleGVzIHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24sIHNpbWlsYXIgdG8gYGdyb3VwQnlgLCBidXQgZm9yXG4gIC8vIHdoZW4geW91IGtub3cgdGhhdCB5b3VyIGluZGV4IHZhbHVlcyB3aWxsIGJlIHVuaXF1ZS5cbiAgXy5pbmRleEJ5ID0gZ3JvdXAoZnVuY3Rpb24ocmVzdWx0LCBrZXksIHZhbHVlKSB7XG4gICAgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgfSk7XG5cbiAgLy8gQ291bnRzIGluc3RhbmNlcyBvZiBhbiBvYmplY3QgdGhhdCBncm91cCBieSBhIGNlcnRhaW4gY3JpdGVyaW9uLiBQYXNzXG4gIC8vIGVpdGhlciBhIHN0cmluZyBhdHRyaWJ1dGUgdG8gY291bnQgYnksIG9yIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZVxuICAvLyBjcml0ZXJpb24uXG4gIF8uY291bnRCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwga2V5KSB7XG4gICAgXy5oYXMocmVzdWx0LCBrZXkpID8gcmVzdWx0W2tleV0rKyA6IHJlc3VsdFtrZXldID0gMTtcbiAgfSk7XG5cbiAgLy8gVXNlIGEgY29tcGFyYXRvciBmdW5jdGlvbiB0byBmaWd1cmUgb3V0IHRoZSBzbWFsbGVzdCBpbmRleCBhdCB3aGljaFxuICAvLyBhbiBvYmplY3Qgc2hvdWxkIGJlIGluc2VydGVkIHNvIGFzIHRvIG1haW50YWluIG9yZGVyLiBVc2VzIGJpbmFyeSBzZWFyY2guXG4gIF8uc29ydGVkSW5kZXggPSBmdW5jdGlvbihhcnJheSwgb2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGl0ZXJhdG9yID0gbG9va3VwSXRlcmF0b3IoaXRlcmF0b3IpO1xuICAgIHZhciB2YWx1ZSA9IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqKTtcbiAgICB2YXIgbG93ID0gMCwgaGlnaCA9IGFycmF5Lmxlbmd0aDtcbiAgICB3aGlsZSAobG93IDwgaGlnaCkge1xuICAgICAgdmFyIG1pZCA9IChsb3cgKyBoaWdoKSA+Pj4gMTtcbiAgICAgIGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgYXJyYXlbbWlkXSkgPCB2YWx1ZSA/IGxvdyA9IG1pZCArIDEgOiBoaWdoID0gbWlkO1xuICAgIH1cbiAgICByZXR1cm4gbG93O1xuICB9O1xuXG4gIC8vIFNhZmVseSBjcmVhdGUgYSByZWFsLCBsaXZlIGFycmF5IGZyb20gYW55dGhpbmcgaXRlcmFibGUuXG4gIF8udG9BcnJheSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmICghb2JqKSByZXR1cm4gW107XG4gICAgaWYgKF8uaXNBcnJheShvYmopKSByZXR1cm4gc2xpY2UuY2FsbChvYmopO1xuICAgIGlmIChvYmoubGVuZ3RoID09PSArb2JqLmxlbmd0aCkgcmV0dXJuIF8ubWFwKG9iaiwgXy5pZGVudGl0eSk7XG4gICAgcmV0dXJuIF8udmFsdWVzKG9iaik7XG4gIH07XG5cbiAgLy8gUmV0dXJuIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gYW4gb2JqZWN0LlxuICBfLnNpemUgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiAwO1xuICAgIHJldHVybiAob2JqLmxlbmd0aCA9PT0gK29iai5sZW5ndGgpID8gb2JqLmxlbmd0aCA6IF8ua2V5cyhvYmopLmxlbmd0aDtcbiAgfTtcblxuICAvLyBBcnJheSBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tXG5cbiAgLy8gR2V0IHRoZSBmaXJzdCBlbGVtZW50IG9mIGFuIGFycmF5LiBQYXNzaW5nICoqbioqIHdpbGwgcmV0dXJuIHRoZSBmaXJzdCBOXG4gIC8vIHZhbHVlcyBpbiB0aGUgYXJyYXkuIEFsaWFzZWQgYXMgYGhlYWRgIGFuZCBgdGFrZWAuIFRoZSAqKmd1YXJkKiogY2hlY2tcbiAgLy8gYWxsb3dzIGl0IHRvIHdvcmsgd2l0aCBgXy5tYXBgLlxuICBfLmZpcnN0ID0gXy5oZWFkID0gXy50YWtlID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgaWYgKGFycmF5ID09IG51bGwpIHJldHVybiB2b2lkIDA7XG4gICAgaWYgKChuID09IG51bGwpIHx8IGd1YXJkKSByZXR1cm4gYXJyYXlbMF07XG4gICAgaWYgKG4gPCAwKSByZXR1cm4gW107XG4gICAgcmV0dXJuIHNsaWNlLmNhbGwoYXJyYXksIDAsIG4pO1xuICB9O1xuXG4gIC8vIFJldHVybnMgZXZlcnl0aGluZyBidXQgdGhlIGxhc3QgZW50cnkgb2YgdGhlIGFycmF5LiBFc3BlY2lhbGx5IHVzZWZ1bCBvblxuICAvLyB0aGUgYXJndW1lbnRzIG9iamVjdC4gUGFzc2luZyAqKm4qKiB3aWxsIHJldHVybiBhbGwgdGhlIHZhbHVlcyBpblxuICAvLyB0aGUgYXJyYXksIGV4Y2x1ZGluZyB0aGUgbGFzdCBOLiBUaGUgKipndWFyZCoqIGNoZWNrIGFsbG93cyBpdCB0byB3b3JrIHdpdGhcbiAgLy8gYF8ubWFwYC5cbiAgXy5pbml0aWFsID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgcmV0dXJuIHNsaWNlLmNhbGwoYXJyYXksIDAsIGFycmF5Lmxlbmd0aCAtICgobiA9PSBudWxsKSB8fCBndWFyZCA/IDEgOiBuKSk7XG4gIH07XG5cbiAgLy8gR2V0IHRoZSBsYXN0IGVsZW1lbnQgb2YgYW4gYXJyYXkuIFBhc3NpbmcgKipuKiogd2lsbCByZXR1cm4gdGhlIGxhc3QgTlxuICAvLyB2YWx1ZXMgaW4gdGhlIGFycmF5LiBUaGUgKipndWFyZCoqIGNoZWNrIGFsbG93cyBpdCB0byB3b3JrIHdpdGggYF8ubWFwYC5cbiAgXy5sYXN0ID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgaWYgKGFycmF5ID09IG51bGwpIHJldHVybiB2b2lkIDA7XG4gICAgaWYgKChuID09IG51bGwpIHx8IGd1YXJkKSByZXR1cm4gYXJyYXlbYXJyYXkubGVuZ3RoIC0gMV07XG4gICAgcmV0dXJuIHNsaWNlLmNhbGwoYXJyYXksIE1hdGgubWF4KGFycmF5Lmxlbmd0aCAtIG4sIDApKTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGV2ZXJ5dGhpbmcgYnV0IHRoZSBmaXJzdCBlbnRyeSBvZiB0aGUgYXJyYXkuIEFsaWFzZWQgYXMgYHRhaWxgIGFuZCBgZHJvcGAuXG4gIC8vIEVzcGVjaWFsbHkgdXNlZnVsIG9uIHRoZSBhcmd1bWVudHMgb2JqZWN0LiBQYXNzaW5nIGFuICoqbioqIHdpbGwgcmV0dXJuXG4gIC8vIHRoZSByZXN0IE4gdmFsdWVzIGluIHRoZSBhcnJheS4gVGhlICoqZ3VhcmQqKlxuICAvLyBjaGVjayBhbGxvd3MgaXQgdG8gd29yayB3aXRoIGBfLm1hcGAuXG4gIF8ucmVzdCA9IF8udGFpbCA9IF8uZHJvcCA9IGZ1bmN0aW9uKGFycmF5LCBuLCBndWFyZCkge1xuICAgIHJldHVybiBzbGljZS5jYWxsKGFycmF5LCAobiA9PSBudWxsKSB8fCBndWFyZCA/IDEgOiBuKTtcbiAgfTtcblxuICAvLyBUcmltIG91dCBhbGwgZmFsc3kgdmFsdWVzIGZyb20gYW4gYXJyYXkuXG4gIF8uY29tcGFjdCA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgcmV0dXJuIF8uZmlsdGVyKGFycmF5LCBfLmlkZW50aXR5KTtcbiAgfTtcblxuICAvLyBJbnRlcm5hbCBpbXBsZW1lbnRhdGlvbiBvZiBhIHJlY3Vyc2l2ZSBgZmxhdHRlbmAgZnVuY3Rpb24uXG4gIHZhciBmbGF0dGVuID0gZnVuY3Rpb24oaW5wdXQsIHNoYWxsb3csIG91dHB1dCkge1xuICAgIGlmIChzaGFsbG93ICYmIF8uZXZlcnkoaW5wdXQsIF8uaXNBcnJheSkpIHtcbiAgICAgIHJldHVybiBjb25jYXQuYXBwbHkob3V0cHV0LCBpbnB1dCk7XG4gICAgfVxuICAgIGVhY2goaW5wdXQsIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICBpZiAoXy5pc0FycmF5KHZhbHVlKSB8fCBfLmlzQXJndW1lbnRzKHZhbHVlKSkge1xuICAgICAgICBzaGFsbG93ID8gcHVzaC5hcHBseShvdXRwdXQsIHZhbHVlKSA6IGZsYXR0ZW4odmFsdWUsIHNoYWxsb3csIG91dHB1dCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvdXRwdXQucHVzaCh2YWx1ZSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG91dHB1dDtcbiAgfTtcblxuICAvLyBGbGF0dGVuIG91dCBhbiBhcnJheSwgZWl0aGVyIHJlY3Vyc2l2ZWx5IChieSBkZWZhdWx0KSwgb3IganVzdCBvbmUgbGV2ZWwuXG4gIF8uZmxhdHRlbiA9IGZ1bmN0aW9uKGFycmF5LCBzaGFsbG93KSB7XG4gICAgcmV0dXJuIGZsYXR0ZW4oYXJyYXksIHNoYWxsb3csIFtdKTtcbiAgfTtcblxuICAvLyBSZXR1cm4gYSB2ZXJzaW9uIG9mIHRoZSBhcnJheSB0aGF0IGRvZXMgbm90IGNvbnRhaW4gdGhlIHNwZWNpZmllZCB2YWx1ZShzKS5cbiAgXy53aXRob3V0ID0gZnVuY3Rpb24oYXJyYXkpIHtcbiAgICByZXR1cm4gXy5kaWZmZXJlbmNlKGFycmF5LCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICB9O1xuXG4gIC8vIFNwbGl0IGFuIGFycmF5IGludG8gdHdvIGFycmF5czogb25lIHdob3NlIGVsZW1lbnRzIGFsbCBzYXRpc2Z5IHRoZSBnaXZlblxuICAvLyBwcmVkaWNhdGUsIGFuZCBvbmUgd2hvc2UgZWxlbWVudHMgYWxsIGRvIG5vdCBzYXRpc2Z5IHRoZSBwcmVkaWNhdGUuXG4gIF8ucGFydGl0aW9uID0gZnVuY3Rpb24oYXJyYXksIHByZWRpY2F0ZSkge1xuICAgIHZhciBwYXNzID0gW10sIGZhaWwgPSBbXTtcbiAgICBlYWNoKGFycmF5LCBmdW5jdGlvbihlbGVtKSB7XG4gICAgICAocHJlZGljYXRlKGVsZW0pID8gcGFzcyA6IGZhaWwpLnB1c2goZWxlbSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIFtwYXNzLCBmYWlsXTtcbiAgfTtcblxuICAvLyBQcm9kdWNlIGEgZHVwbGljYXRlLWZyZWUgdmVyc2lvbiBvZiB0aGUgYXJyYXkuIElmIHRoZSBhcnJheSBoYXMgYWxyZWFkeVxuICAvLyBiZWVuIHNvcnRlZCwgeW91IGhhdmUgdGhlIG9wdGlvbiBvZiB1c2luZyBhIGZhc3RlciBhbGdvcml0aG0uXG4gIC8vIEFsaWFzZWQgYXMgYHVuaXF1ZWAuXG4gIF8udW5pcSA9IF8udW5pcXVlID0gZnVuY3Rpb24oYXJyYXksIGlzU29ydGVkLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGlmIChfLmlzRnVuY3Rpb24oaXNTb3J0ZWQpKSB7XG4gICAgICBjb250ZXh0ID0gaXRlcmF0b3I7XG4gICAgICBpdGVyYXRvciA9IGlzU29ydGVkO1xuICAgICAgaXNTb3J0ZWQgPSBmYWxzZTtcbiAgICB9XG4gICAgdmFyIGluaXRpYWwgPSBpdGVyYXRvciA/IF8ubWFwKGFycmF5LCBpdGVyYXRvciwgY29udGV4dCkgOiBhcnJheTtcbiAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgIHZhciBzZWVuID0gW107XG4gICAgZWFjaChpbml0aWFsLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgpIHtcbiAgICAgIGlmIChpc1NvcnRlZCA/ICghaW5kZXggfHwgc2VlbltzZWVuLmxlbmd0aCAtIDFdICE9PSB2YWx1ZSkgOiAhXy5jb250YWlucyhzZWVuLCB2YWx1ZSkpIHtcbiAgICAgICAgc2Vlbi5wdXNoKHZhbHVlKTtcbiAgICAgICAgcmVzdWx0cy5wdXNoKGFycmF5W2luZGV4XSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH07XG5cbiAgLy8gUHJvZHVjZSBhbiBhcnJheSB0aGF0IGNvbnRhaW5zIHRoZSB1bmlvbjogZWFjaCBkaXN0aW5jdCBlbGVtZW50IGZyb20gYWxsIG9mXG4gIC8vIHRoZSBwYXNzZWQtaW4gYXJyYXlzLlxuICBfLnVuaW9uID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIF8udW5pcShfLmZsYXR0ZW4oYXJndW1lbnRzLCB0cnVlKSk7XG4gIH07XG5cbiAgLy8gUHJvZHVjZSBhbiBhcnJheSB0aGF0IGNvbnRhaW5zIGV2ZXJ5IGl0ZW0gc2hhcmVkIGJldHdlZW4gYWxsIHRoZVxuICAvLyBwYXNzZWQtaW4gYXJyYXlzLlxuICBfLmludGVyc2VjdGlvbiA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgdmFyIHJlc3QgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgcmV0dXJuIF8uZmlsdGVyKF8udW5pcShhcnJheSksIGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgIHJldHVybiBfLmV2ZXJ5KHJlc3QsIGZ1bmN0aW9uKG90aGVyKSB7XG4gICAgICAgIHJldHVybiBfLmNvbnRhaW5zKG90aGVyLCBpdGVtKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIFRha2UgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBvbmUgYXJyYXkgYW5kIGEgbnVtYmVyIG9mIG90aGVyIGFycmF5cy5cbiAgLy8gT25seSB0aGUgZWxlbWVudHMgcHJlc2VudCBpbiBqdXN0IHRoZSBmaXJzdCBhcnJheSB3aWxsIHJlbWFpbi5cbiAgXy5kaWZmZXJlbmNlID0gZnVuY3Rpb24oYXJyYXkpIHtcbiAgICB2YXIgcmVzdCA9IGNvbmNhdC5hcHBseShBcnJheVByb3RvLCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICAgIHJldHVybiBfLmZpbHRlcihhcnJheSwgZnVuY3Rpb24odmFsdWUpeyByZXR1cm4gIV8uY29udGFpbnMocmVzdCwgdmFsdWUpOyB9KTtcbiAgfTtcblxuICAvLyBaaXAgdG9nZXRoZXIgbXVsdGlwbGUgbGlzdHMgaW50byBhIHNpbmdsZSBhcnJheSAtLSBlbGVtZW50cyB0aGF0IHNoYXJlXG4gIC8vIGFuIGluZGV4IGdvIHRvZ2V0aGVyLlxuICBfLnppcCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBsZW5ndGggPSBfLm1heChfLnBsdWNrKGFyZ3VtZW50cywgJ2xlbmd0aCcpLmNvbmNhdCgwKSk7XG4gICAgdmFyIHJlc3VsdHMgPSBuZXcgQXJyYXkobGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICByZXN1bHRzW2ldID0gXy5wbHVjayhhcmd1bWVudHMsICcnICsgaSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRzO1xuICB9O1xuXG4gIC8vIENvbnZlcnRzIGxpc3RzIGludG8gb2JqZWN0cy4gUGFzcyBlaXRoZXIgYSBzaW5nbGUgYXJyYXkgb2YgYFtrZXksIHZhbHVlXWBcbiAgLy8gcGFpcnMsIG9yIHR3byBwYXJhbGxlbCBhcnJheXMgb2YgdGhlIHNhbWUgbGVuZ3RoIC0tIG9uZSBvZiBrZXlzLCBhbmQgb25lIG9mXG4gIC8vIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlcy5cbiAgXy5vYmplY3QgPSBmdW5jdGlvbihsaXN0LCB2YWx1ZXMpIHtcbiAgICBpZiAobGlzdCA9PSBudWxsKSByZXR1cm4ge307XG4gICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBsaXN0Lmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodmFsdWVzKSB7XG4gICAgICAgIHJlc3VsdFtsaXN0W2ldXSA9IHZhbHVlc1tpXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdFtsaXN0W2ldWzBdXSA9IGxpc3RbaV1bMV07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gSWYgdGhlIGJyb3dzZXIgZG9lc24ndCBzdXBwbHkgdXMgd2l0aCBpbmRleE9mIChJJ20gbG9va2luZyBhdCB5b3UsICoqTVNJRSoqKSxcbiAgLy8gd2UgbmVlZCB0aGlzIGZ1bmN0aW9uLiBSZXR1cm4gdGhlIHBvc2l0aW9uIG9mIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIGFuXG4gIC8vIGl0ZW0gaW4gYW4gYXJyYXksIG9yIC0xIGlmIHRoZSBpdGVtIGlzIG5vdCBpbmNsdWRlZCBpbiB0aGUgYXJyYXkuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBpbmRleE9mYCBpZiBhdmFpbGFibGUuXG4gIC8vIElmIHRoZSBhcnJheSBpcyBsYXJnZSBhbmQgYWxyZWFkeSBpbiBzb3J0IG9yZGVyLCBwYXNzIGB0cnVlYFxuICAvLyBmb3IgKippc1NvcnRlZCoqIHRvIHVzZSBiaW5hcnkgc2VhcmNoLlxuICBfLmluZGV4T2YgPSBmdW5jdGlvbihhcnJheSwgaXRlbSwgaXNTb3J0ZWQpIHtcbiAgICBpZiAoYXJyYXkgPT0gbnVsbCkgcmV0dXJuIC0xO1xuICAgIHZhciBpID0gMCwgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuICAgIGlmIChpc1NvcnRlZCkge1xuICAgICAgaWYgKHR5cGVvZiBpc1NvcnRlZCA9PSAnbnVtYmVyJykge1xuICAgICAgICBpID0gKGlzU29ydGVkIDwgMCA/IE1hdGgubWF4KDAsIGxlbmd0aCArIGlzU29ydGVkKSA6IGlzU29ydGVkKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGkgPSBfLnNvcnRlZEluZGV4KGFycmF5LCBpdGVtKTtcbiAgICAgICAgcmV0dXJuIGFycmF5W2ldID09PSBpdGVtID8gaSA6IC0xO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAobmF0aXZlSW5kZXhPZiAmJiBhcnJheS5pbmRleE9mID09PSBuYXRpdmVJbmRleE9mKSByZXR1cm4gYXJyYXkuaW5kZXhPZihpdGVtLCBpc1NvcnRlZCk7XG4gICAgZm9yICg7IGkgPCBsZW5ndGg7IGkrKykgaWYgKGFycmF5W2ldID09PSBpdGVtKSByZXR1cm4gaTtcbiAgICByZXR1cm4gLTE7XG4gIH07XG5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYGxhc3RJbmRleE9mYCBpZiBhdmFpbGFibGUuXG4gIF8ubGFzdEluZGV4T2YgPSBmdW5jdGlvbihhcnJheSwgaXRlbSwgZnJvbSkge1xuICAgIGlmIChhcnJheSA9PSBudWxsKSByZXR1cm4gLTE7XG4gICAgdmFyIGhhc0luZGV4ID0gZnJvbSAhPSBudWxsO1xuICAgIGlmIChuYXRpdmVMYXN0SW5kZXhPZiAmJiBhcnJheS5sYXN0SW5kZXhPZiA9PT0gbmF0aXZlTGFzdEluZGV4T2YpIHtcbiAgICAgIHJldHVybiBoYXNJbmRleCA/IGFycmF5Lmxhc3RJbmRleE9mKGl0ZW0sIGZyb20pIDogYXJyYXkubGFzdEluZGV4T2YoaXRlbSk7XG4gICAgfVxuICAgIHZhciBpID0gKGhhc0luZGV4ID8gZnJvbSA6IGFycmF5Lmxlbmd0aCk7XG4gICAgd2hpbGUgKGktLSkgaWYgKGFycmF5W2ldID09PSBpdGVtKSByZXR1cm4gaTtcbiAgICByZXR1cm4gLTE7XG4gIH07XG5cbiAgLy8gR2VuZXJhdGUgYW4gaW50ZWdlciBBcnJheSBjb250YWluaW5nIGFuIGFyaXRobWV0aWMgcHJvZ3Jlc3Npb24uIEEgcG9ydCBvZlxuICAvLyB0aGUgbmF0aXZlIFB5dGhvbiBgcmFuZ2UoKWAgZnVuY3Rpb24uIFNlZVxuICAvLyBbdGhlIFB5dGhvbiBkb2N1bWVudGF0aW9uXShodHRwOi8vZG9jcy5weXRob24ub3JnL2xpYnJhcnkvZnVuY3Rpb25zLmh0bWwjcmFuZ2UpLlxuICBfLnJhbmdlID0gZnVuY3Rpb24oc3RhcnQsIHN0b3AsIHN0ZXApIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8PSAxKSB7XG4gICAgICBzdG9wID0gc3RhcnQgfHwgMDtcbiAgICAgIHN0YXJ0ID0gMDtcbiAgICB9XG4gICAgc3RlcCA9IGFyZ3VtZW50c1syXSB8fCAxO1xuXG4gICAgdmFyIGxlbmd0aCA9IE1hdGgubWF4KE1hdGguY2VpbCgoc3RvcCAtIHN0YXJ0KSAvIHN0ZXApLCAwKTtcbiAgICB2YXIgaWR4ID0gMDtcbiAgICB2YXIgcmFuZ2UgPSBuZXcgQXJyYXkobGVuZ3RoKTtcblxuICAgIHdoaWxlKGlkeCA8IGxlbmd0aCkge1xuICAgICAgcmFuZ2VbaWR4KytdID0gc3RhcnQ7XG4gICAgICBzdGFydCArPSBzdGVwO1xuICAgIH1cblxuICAgIHJldHVybiByYW5nZTtcbiAgfTtcblxuICAvLyBGdW5jdGlvbiAoYWhlbSkgRnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIFJldXNhYmxlIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIGZvciBwcm90b3R5cGUgc2V0dGluZy5cbiAgdmFyIGN0b3IgPSBmdW5jdGlvbigpe307XG5cbiAgLy8gQ3JlYXRlIGEgZnVuY3Rpb24gYm91bmQgdG8gYSBnaXZlbiBvYmplY3QgKGFzc2lnbmluZyBgdGhpc2AsIGFuZCBhcmd1bWVudHMsXG4gIC8vIG9wdGlvbmFsbHkpLiBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgRnVuY3Rpb24uYmluZGAgaWZcbiAgLy8gYXZhaWxhYmxlLlxuICBfLmJpbmQgPSBmdW5jdGlvbihmdW5jLCBjb250ZXh0KSB7XG4gICAgdmFyIGFyZ3MsIGJvdW5kO1xuICAgIGlmIChuYXRpdmVCaW5kICYmIGZ1bmMuYmluZCA9PT0gbmF0aXZlQmluZCkgcmV0dXJuIG5hdGl2ZUJpbmQuYXBwbHkoZnVuYywgc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICBpZiAoIV8uaXNGdW5jdGlvbihmdW5jKSkgdGhyb3cgbmV3IFR5cGVFcnJvcjtcbiAgICBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgIHJldHVybiBib3VuZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIGJvdW5kKSkgcmV0dXJuIGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncy5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7XG4gICAgICBjdG9yLnByb3RvdHlwZSA9IGZ1bmMucHJvdG90eXBlO1xuICAgICAgdmFyIHNlbGYgPSBuZXcgY3RvcjtcbiAgICAgIGN0b3IucHJvdG90eXBlID0gbnVsbDtcbiAgICAgIHZhciByZXN1bHQgPSBmdW5jLmFwcGx5KHNlbGYsIGFyZ3MuY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzKSkpO1xuICAgICAgaWYgKE9iamVjdChyZXN1bHQpID09PSByZXN1bHQpIHJldHVybiByZXN1bHQ7XG4gICAgICByZXR1cm4gc2VsZjtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFBhcnRpYWxseSBhcHBseSBhIGZ1bmN0aW9uIGJ5IGNyZWF0aW5nIGEgdmVyc2lvbiB0aGF0IGhhcyBoYWQgc29tZSBvZiBpdHNcbiAgLy8gYXJndW1lbnRzIHByZS1maWxsZWQsIHdpdGhvdXQgY2hhbmdpbmcgaXRzIGR5bmFtaWMgYHRoaXNgIGNvbnRleHQuIF8gYWN0c1xuICAvLyBhcyBhIHBsYWNlaG9sZGVyLCBhbGxvd2luZyBhbnkgY29tYmluYXRpb24gb2YgYXJndW1lbnRzIHRvIGJlIHByZS1maWxsZWQuXG4gIF8ucGFydGlhbCA9IGZ1bmN0aW9uKGZ1bmMpIHtcbiAgICB2YXIgYm91bmRBcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBwb3NpdGlvbiA9IDA7XG4gICAgICB2YXIgYXJncyA9IGJvdW5kQXJncy5zbGljZSgpO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGFyZ3MubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGFyZ3NbaV0gPT09IF8pIGFyZ3NbaV0gPSBhcmd1bWVudHNbcG9zaXRpb24rK107XG4gICAgICB9XG4gICAgICB3aGlsZSAocG9zaXRpb24gPCBhcmd1bWVudHMubGVuZ3RoKSBhcmdzLnB1c2goYXJndW1lbnRzW3Bvc2l0aW9uKytdKTtcbiAgICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH07XG4gIH07XG5cbiAgLy8gQmluZCBhIG51bWJlciBvZiBhbiBvYmplY3QncyBtZXRob2RzIHRvIHRoYXQgb2JqZWN0LiBSZW1haW5pbmcgYXJndW1lbnRzXG4gIC8vIGFyZSB0aGUgbWV0aG9kIG5hbWVzIHRvIGJlIGJvdW5kLiBVc2VmdWwgZm9yIGVuc3VyaW5nIHRoYXQgYWxsIGNhbGxiYWNrc1xuICAvLyBkZWZpbmVkIG9uIGFuIG9iamVjdCBiZWxvbmcgdG8gaXQuXG4gIF8uYmluZEFsbCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBmdW5jcyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICBpZiAoZnVuY3MubGVuZ3RoID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoJ2JpbmRBbGwgbXVzdCBiZSBwYXNzZWQgZnVuY3Rpb24gbmFtZXMnKTtcbiAgICBlYWNoKGZ1bmNzLCBmdW5jdGlvbihmKSB7IG9ialtmXSA9IF8uYmluZChvYmpbZl0sIG9iaik7IH0pO1xuICAgIHJldHVybiBvYmo7XG4gIH07XG5cbiAgLy8gTWVtb2l6ZSBhbiBleHBlbnNpdmUgZnVuY3Rpb24gYnkgc3RvcmluZyBpdHMgcmVzdWx0cy5cbiAgXy5tZW1vaXplID0gZnVuY3Rpb24oZnVuYywgaGFzaGVyKSB7XG4gICAgdmFyIG1lbW8gPSB7fTtcbiAgICBoYXNoZXIgfHwgKGhhc2hlciA9IF8uaWRlbnRpdHkpO1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBrZXkgPSBoYXNoZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIHJldHVybiBfLmhhcyhtZW1vLCBrZXkpID8gbWVtb1trZXldIDogKG1lbW9ba2V5XSA9IGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKSk7XG4gICAgfTtcbiAgfTtcblxuICAvLyBEZWxheXMgYSBmdW5jdGlvbiBmb3IgdGhlIGdpdmVuIG51bWJlciBvZiBtaWxsaXNlY29uZHMsIGFuZCB0aGVuIGNhbGxzXG4gIC8vIGl0IHdpdGggdGhlIGFyZ3VtZW50cyBzdXBwbGllZC5cbiAgXy5kZWxheSA9IGZ1bmN0aW9uKGZ1bmMsIHdhaXQpIHtcbiAgICB2YXIgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICByZXR1cm4gc2V0VGltZW91dChmdW5jdGlvbigpeyByZXR1cm4gZnVuYy5hcHBseShudWxsLCBhcmdzKTsgfSwgd2FpdCk7XG4gIH07XG5cbiAgLy8gRGVmZXJzIGEgZnVuY3Rpb24sIHNjaGVkdWxpbmcgaXQgdG8gcnVuIGFmdGVyIHRoZSBjdXJyZW50IGNhbGwgc3RhY2sgaGFzXG4gIC8vIGNsZWFyZWQuXG4gIF8uZGVmZXIgPSBmdW5jdGlvbihmdW5jKSB7XG4gICAgcmV0dXJuIF8uZGVsYXkuYXBwbHkoXywgW2Z1bmMsIDFdLmNvbmNhdChzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpKTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24sIHRoYXQsIHdoZW4gaW52b2tlZCwgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBhdCBtb3N0IG9uY2VcbiAgLy8gZHVyaW5nIGEgZ2l2ZW4gd2luZG93IG9mIHRpbWUuIE5vcm1hbGx5LCB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uIHdpbGwgcnVuXG4gIC8vIGFzIG11Y2ggYXMgaXQgY2FuLCB3aXRob3V0IGV2ZXIgZ29pbmcgbW9yZSB0aGFuIG9uY2UgcGVyIGB3YWl0YCBkdXJhdGlvbjtcbiAgLy8gYnV0IGlmIHlvdSdkIGxpa2UgdG8gZGlzYWJsZSB0aGUgZXhlY3V0aW9uIG9uIHRoZSBsZWFkaW5nIGVkZ2UsIHBhc3NcbiAgLy8gYHtsZWFkaW5nOiBmYWxzZX1gLiBUbyBkaXNhYmxlIGV4ZWN1dGlvbiBvbiB0aGUgdHJhaWxpbmcgZWRnZSwgZGl0dG8uXG4gIF8udGhyb3R0bGUgPSBmdW5jdGlvbihmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gICAgdmFyIGNvbnRleHQsIGFyZ3MsIHJlc3VsdDtcbiAgICB2YXIgdGltZW91dCA9IG51bGw7XG4gICAgdmFyIHByZXZpb3VzID0gMDtcbiAgICBvcHRpb25zIHx8IChvcHRpb25zID0ge30pO1xuICAgIHZhciBsYXRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgcHJldmlvdXMgPSBvcHRpb25zLmxlYWRpbmcgPT09IGZhbHNlID8gMCA6IF8ubm93KCk7XG4gICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICBjb250ZXh0ID0gYXJncyA9IG51bGw7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbm93ID0gXy5ub3coKTtcbiAgICAgIGlmICghcHJldmlvdXMgJiYgb3B0aW9ucy5sZWFkaW5nID09PSBmYWxzZSkgcHJldmlvdXMgPSBub3c7XG4gICAgICB2YXIgcmVtYWluaW5nID0gd2FpdCAtIChub3cgLSBwcmV2aW91cyk7XG4gICAgICBjb250ZXh0ID0gdGhpcztcbiAgICAgIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICBpZiAocmVtYWluaW5nIDw9IDApIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgICAgcHJldmlvdXMgPSBub3c7XG4gICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcbiAgICAgIH0gZWxzZSBpZiAoIXRpbWVvdXQgJiYgb3B0aW9ucy50cmFpbGluZyAhPT0gZmFsc2UpIHtcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHJlbWFpbmluZyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uLCB0aGF0LCBhcyBsb25nIGFzIGl0IGNvbnRpbnVlcyB0byBiZSBpbnZva2VkLCB3aWxsIG5vdFxuICAvLyBiZSB0cmlnZ2VyZWQuIFRoZSBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBhZnRlciBpdCBzdG9wcyBiZWluZyBjYWxsZWQgZm9yXG4gIC8vIE4gbWlsbGlzZWNvbmRzLiBJZiBgaW1tZWRpYXRlYCBpcyBwYXNzZWQsIHRyaWdnZXIgdGhlIGZ1bmN0aW9uIG9uIHRoZVxuICAvLyBsZWFkaW5nIGVkZ2UsIGluc3RlYWQgb2YgdGhlIHRyYWlsaW5nLlxuICBfLmRlYm91bmNlID0gZnVuY3Rpb24oZnVuYywgd2FpdCwgaW1tZWRpYXRlKSB7XG4gICAgdmFyIHRpbWVvdXQsIGFyZ3MsIGNvbnRleHQsIHRpbWVzdGFtcCwgcmVzdWx0O1xuXG4gICAgdmFyIGxhdGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbGFzdCA9IF8ubm93KCkgLSB0aW1lc3RhbXA7XG4gICAgICBpZiAobGFzdCA8IHdhaXQpIHtcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQgLSBsYXN0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICBpZiAoIWltbWVkaWF0ZSkge1xuICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgICAgY29udGV4dCA9IGFyZ3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIGNvbnRleHQgPSB0aGlzO1xuICAgICAgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIHRpbWVzdGFtcCA9IF8ubm93KCk7XG4gICAgICB2YXIgY2FsbE5vdyA9IGltbWVkaWF0ZSAmJiAhdGltZW91dDtcbiAgICAgIGlmICghdGltZW91dCkge1xuICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgd2FpdCk7XG4gICAgICB9XG4gICAgICBpZiAoY2FsbE5vdykge1xuICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICBjb250ZXh0ID0gYXJncyA9IG51bGw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGV4ZWN1dGVkIGF0IG1vc3Qgb25lIHRpbWUsIG5vIG1hdHRlciBob3dcbiAgLy8gb2Z0ZW4geW91IGNhbGwgaXQuIFVzZWZ1bCBmb3IgbGF6eSBpbml0aWFsaXphdGlvbi5cbiAgXy5vbmNlID0gZnVuY3Rpb24oZnVuYykge1xuICAgIHZhciByYW4gPSBmYWxzZSwgbWVtbztcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBpZiAocmFuKSByZXR1cm4gbWVtbztcbiAgICAgIHJhbiA9IHRydWU7XG4gICAgICBtZW1vID0gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgZnVuYyA9IG51bGw7XG4gICAgICByZXR1cm4gbWVtbztcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgdGhlIGZpcnN0IGZ1bmN0aW9uIHBhc3NlZCBhcyBhbiBhcmd1bWVudCB0byB0aGUgc2Vjb25kLFxuICAvLyBhbGxvd2luZyB5b3UgdG8gYWRqdXN0IGFyZ3VtZW50cywgcnVuIGNvZGUgYmVmb3JlIGFuZCBhZnRlciwgYW5kXG4gIC8vIGNvbmRpdGlvbmFsbHkgZXhlY3V0ZSB0aGUgb3JpZ2luYWwgZnVuY3Rpb24uXG4gIF8ud3JhcCA9IGZ1bmN0aW9uKGZ1bmMsIHdyYXBwZXIpIHtcbiAgICByZXR1cm4gXy5wYXJ0aWFsKHdyYXBwZXIsIGZ1bmMpO1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiB0aGF0IGlzIHRoZSBjb21wb3NpdGlvbiBvZiBhIGxpc3Qgb2YgZnVuY3Rpb25zLCBlYWNoXG4gIC8vIGNvbnN1bWluZyB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBmdW5jdGlvbiB0aGF0IGZvbGxvd3MuXG4gIF8uY29tcG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBmdW5jcyA9IGFyZ3VtZW50cztcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIGZvciAodmFyIGkgPSBmdW5jcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBhcmdzID0gW2Z1bmNzW2ldLmFwcGx5KHRoaXMsIGFyZ3MpXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhcmdzWzBdO1xuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBvbmx5IGJlIGV4ZWN1dGVkIGFmdGVyIGJlaW5nIGNhbGxlZCBOIHRpbWVzLlxuICBfLmFmdGVyID0gZnVuY3Rpb24odGltZXMsIGZ1bmMpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoLS10aW1lcyA8IDEpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIH1cbiAgICB9O1xuICB9O1xuXG4gIC8vIE9iamVjdCBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIFJldHJpZXZlIHRoZSBuYW1lcyBvZiBhbiBvYmplY3QncyBwcm9wZXJ0aWVzLlxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgT2JqZWN0LmtleXNgXG4gIF8ua2V5cyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmICghXy5pc09iamVjdChvYmopKSByZXR1cm4gW107XG4gICAgaWYgKG5hdGl2ZUtleXMpIHJldHVybiBuYXRpdmVLZXlzKG9iaik7XG4gICAgdmFyIGtleXMgPSBbXTtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSBpZiAoXy5oYXMob2JqLCBrZXkpKSBrZXlzLnB1c2goa2V5KTtcbiAgICByZXR1cm4ga2V5cztcbiAgfTtcblxuICAvLyBSZXRyaWV2ZSB0aGUgdmFsdWVzIG9mIGFuIG9iamVjdCdzIHByb3BlcnRpZXMuXG4gIF8udmFsdWVzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIGtleXMgPSBfLmtleXMob2JqKTtcbiAgICB2YXIgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XG4gICAgdmFyIHZhbHVlcyA9IG5ldyBBcnJheShsZW5ndGgpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhbHVlc1tpXSA9IG9ialtrZXlzW2ldXTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlcztcbiAgfTtcblxuICAvLyBDb252ZXJ0IGFuIG9iamVjdCBpbnRvIGEgbGlzdCBvZiBgW2tleSwgdmFsdWVdYCBwYWlycy5cbiAgXy5wYWlycyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgIHZhciBwYWlycyA9IG5ldyBBcnJheShsZW5ndGgpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHBhaXJzW2ldID0gW2tleXNbaV0sIG9ialtrZXlzW2ldXV07XG4gICAgfVxuICAgIHJldHVybiBwYWlycztcbiAgfTtcblxuICAvLyBJbnZlcnQgdGhlIGtleXMgYW5kIHZhbHVlcyBvZiBhbiBvYmplY3QuIFRoZSB2YWx1ZXMgbXVzdCBiZSBzZXJpYWxpemFibGUuXG4gIF8uaW52ZXJ0ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHJlc3VsdFtvYmpba2V5c1tpXV1dID0ga2V5c1tpXTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBSZXR1cm4gYSBzb3J0ZWQgbGlzdCBvZiB0aGUgZnVuY3Rpb24gbmFtZXMgYXZhaWxhYmxlIG9uIHRoZSBvYmplY3QuXG4gIC8vIEFsaWFzZWQgYXMgYG1ldGhvZHNgXG4gIF8uZnVuY3Rpb25zID0gXy5tZXRob2RzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIG5hbWVzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgaWYgKF8uaXNGdW5jdGlvbihvYmpba2V5XSkpIG5hbWVzLnB1c2goa2V5KTtcbiAgICB9XG4gICAgcmV0dXJuIG5hbWVzLnNvcnQoKTtcbiAgfTtcblxuICAvLyBFeHRlbmQgYSBnaXZlbiBvYmplY3Qgd2l0aCBhbGwgdGhlIHByb3BlcnRpZXMgaW4gcGFzc2VkLWluIG9iamVjdChzKS5cbiAgXy5leHRlbmQgPSBmdW5jdGlvbihvYmopIHtcbiAgICBlYWNoKHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSwgZnVuY3Rpb24oc291cmNlKSB7XG4gICAgICBpZiAoc291cmNlKSB7XG4gICAgICAgIGZvciAodmFyIHByb3AgaW4gc291cmNlKSB7XG4gICAgICAgICAgb2JqW3Byb3BdID0gc291cmNlW3Byb3BdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG9iajtcbiAgfTtcblxuICAvLyBSZXR1cm4gYSBjb3B5IG9mIHRoZSBvYmplY3Qgb25seSBjb250YWluaW5nIHRoZSB3aGl0ZWxpc3RlZCBwcm9wZXJ0aWVzLlxuICBfLnBpY2sgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgY29weSA9IHt9O1xuICAgIHZhciBrZXlzID0gY29uY2F0LmFwcGx5KEFycmF5UHJvdG8sIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgZWFjaChrZXlzLCBmdW5jdGlvbihrZXkpIHtcbiAgICAgIGlmIChrZXkgaW4gb2JqKSBjb3B5W2tleV0gPSBvYmpba2V5XTtcbiAgICB9KTtcbiAgICByZXR1cm4gY29weTtcbiAgfTtcblxuICAgLy8gUmV0dXJuIGEgY29weSBvZiB0aGUgb2JqZWN0IHdpdGhvdXQgdGhlIGJsYWNrbGlzdGVkIHByb3BlcnRpZXMuXG4gIF8ub21pdCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBjb3B5ID0ge307XG4gICAgdmFyIGtleXMgPSBjb25jYXQuYXBwbHkoQXJyYXlQcm90bywgc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICBpZiAoIV8uY29udGFpbnMoa2V5cywga2V5KSkgY29weVtrZXldID0gb2JqW2tleV07XG4gICAgfVxuICAgIHJldHVybiBjb3B5O1xuICB9O1xuXG4gIC8vIEZpbGwgaW4gYSBnaXZlbiBvYmplY3Qgd2l0aCBkZWZhdWx0IHByb3BlcnRpZXMuXG4gIF8uZGVmYXVsdHMgPSBmdW5jdGlvbihvYmopIHtcbiAgICBlYWNoKHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSwgZnVuY3Rpb24oc291cmNlKSB7XG4gICAgICBpZiAoc291cmNlKSB7XG4gICAgICAgIGZvciAodmFyIHByb3AgaW4gc291cmNlKSB7XG4gICAgICAgICAgaWYgKG9ialtwcm9wXSA9PT0gdm9pZCAwKSBvYmpbcHJvcF0gPSBzb3VyY2VbcHJvcF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gb2JqO1xuICB9O1xuXG4gIC8vIENyZWF0ZSBhIChzaGFsbG93LWNsb25lZCkgZHVwbGljYXRlIG9mIGFuIG9iamVjdC5cbiAgXy5jbG9uZSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmICghXy5pc09iamVjdChvYmopKSByZXR1cm4gb2JqO1xuICAgIHJldHVybiBfLmlzQXJyYXkob2JqKSA/IG9iai5zbGljZSgpIDogXy5leHRlbmQoe30sIG9iaik7XG4gIH07XG5cbiAgLy8gSW52b2tlcyBpbnRlcmNlcHRvciB3aXRoIHRoZSBvYmosIGFuZCB0aGVuIHJldHVybnMgb2JqLlxuICAvLyBUaGUgcHJpbWFyeSBwdXJwb3NlIG9mIHRoaXMgbWV0aG9kIGlzIHRvIFwidGFwIGludG9cIiBhIG1ldGhvZCBjaGFpbiwgaW5cbiAgLy8gb3JkZXIgdG8gcGVyZm9ybSBvcGVyYXRpb25zIG9uIGludGVybWVkaWF0ZSByZXN1bHRzIHdpdGhpbiB0aGUgY2hhaW4uXG4gIF8udGFwID0gZnVuY3Rpb24ob2JqLCBpbnRlcmNlcHRvcikge1xuICAgIGludGVyY2VwdG9yKG9iaik7XG4gICAgcmV0dXJuIG9iajtcbiAgfTtcblxuICAvLyBJbnRlcm5hbCByZWN1cnNpdmUgY29tcGFyaXNvbiBmdW5jdGlvbiBmb3IgYGlzRXF1YWxgLlxuICB2YXIgZXEgPSBmdW5jdGlvbihhLCBiLCBhU3RhY2ssIGJTdGFjaykge1xuICAgIC8vIElkZW50aWNhbCBvYmplY3RzIGFyZSBlcXVhbC4gYDAgPT09IC0wYCwgYnV0IHRoZXkgYXJlbid0IGlkZW50aWNhbC5cbiAgICAvLyBTZWUgdGhlIFtIYXJtb255IGBlZ2FsYCBwcm9wb3NhbF0oaHR0cDovL3dpa2kuZWNtYXNjcmlwdC5vcmcvZG9rdS5waHA/aWQ9aGFybW9ueTplZ2FsKS5cbiAgICBpZiAoYSA9PT0gYikgcmV0dXJuIGEgIT09IDAgfHwgMSAvIGEgPT0gMSAvIGI7XG4gICAgLy8gQSBzdHJpY3QgY29tcGFyaXNvbiBpcyBuZWNlc3NhcnkgYmVjYXVzZSBgbnVsbCA9PSB1bmRlZmluZWRgLlxuICAgIGlmIChhID09IG51bGwgfHwgYiA9PSBudWxsKSByZXR1cm4gYSA9PT0gYjtcbiAgICAvLyBVbndyYXAgYW55IHdyYXBwZWQgb2JqZWN0cy5cbiAgICBpZiAoYSBpbnN0YW5jZW9mIF8pIGEgPSBhLl93cmFwcGVkO1xuICAgIGlmIChiIGluc3RhbmNlb2YgXykgYiA9IGIuX3dyYXBwZWQ7XG4gICAgLy8gQ29tcGFyZSBgW1tDbGFzc11dYCBuYW1lcy5cbiAgICB2YXIgY2xhc3NOYW1lID0gdG9TdHJpbmcuY2FsbChhKTtcbiAgICBpZiAoY2xhc3NOYW1lICE9IHRvU3RyaW5nLmNhbGwoYikpIHJldHVybiBmYWxzZTtcbiAgICBzd2l0Y2ggKGNsYXNzTmFtZSkge1xuICAgICAgLy8gU3RyaW5ncywgbnVtYmVycywgZGF0ZXMsIGFuZCBib29sZWFucyBhcmUgY29tcGFyZWQgYnkgdmFsdWUuXG4gICAgICBjYXNlICdbb2JqZWN0IFN0cmluZ10nOlxuICAgICAgICAvLyBQcmltaXRpdmVzIGFuZCB0aGVpciBjb3JyZXNwb25kaW5nIG9iamVjdCB3cmFwcGVycyBhcmUgZXF1aXZhbGVudDsgdGh1cywgYFwiNVwiYCBpc1xuICAgICAgICAvLyBlcXVpdmFsZW50IHRvIGBuZXcgU3RyaW5nKFwiNVwiKWAuXG4gICAgICAgIHJldHVybiBhID09IFN0cmluZyhiKTtcbiAgICAgIGNhc2UgJ1tvYmplY3QgTnVtYmVyXSc6XG4gICAgICAgIC8vIGBOYU5gcyBhcmUgZXF1aXZhbGVudCwgYnV0IG5vbi1yZWZsZXhpdmUuIEFuIGBlZ2FsYCBjb21wYXJpc29uIGlzIHBlcmZvcm1lZCBmb3JcbiAgICAgICAgLy8gb3RoZXIgbnVtZXJpYyB2YWx1ZXMuXG4gICAgICAgIHJldHVybiBhICE9ICthID8gYiAhPSArYiA6IChhID09IDAgPyAxIC8gYSA9PSAxIC8gYiA6IGEgPT0gK2IpO1xuICAgICAgY2FzZSAnW29iamVjdCBEYXRlXSc6XG4gICAgICBjYXNlICdbb2JqZWN0IEJvb2xlYW5dJzpcbiAgICAgICAgLy8gQ29lcmNlIGRhdGVzIGFuZCBib29sZWFucyB0byBudW1lcmljIHByaW1pdGl2ZSB2YWx1ZXMuIERhdGVzIGFyZSBjb21wYXJlZCBieSB0aGVpclxuICAgICAgICAvLyBtaWxsaXNlY29uZCByZXByZXNlbnRhdGlvbnMuIE5vdGUgdGhhdCBpbnZhbGlkIGRhdGVzIHdpdGggbWlsbGlzZWNvbmQgcmVwcmVzZW50YXRpb25zXG4gICAgICAgIC8vIG9mIGBOYU5gIGFyZSBub3QgZXF1aXZhbGVudC5cbiAgICAgICAgcmV0dXJuICthID09ICtiO1xuICAgICAgLy8gUmVnRXhwcyBhcmUgY29tcGFyZWQgYnkgdGhlaXIgc291cmNlIHBhdHRlcm5zIGFuZCBmbGFncy5cbiAgICAgIGNhc2UgJ1tvYmplY3QgUmVnRXhwXSc6XG4gICAgICAgIHJldHVybiBhLnNvdXJjZSA9PSBiLnNvdXJjZSAmJlxuICAgICAgICAgICAgICAgYS5nbG9iYWwgPT0gYi5nbG9iYWwgJiZcbiAgICAgICAgICAgICAgIGEubXVsdGlsaW5lID09IGIubXVsdGlsaW5lICYmXG4gICAgICAgICAgICAgICBhLmlnbm9yZUNhc2UgPT0gYi5pZ25vcmVDYXNlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGEgIT0gJ29iamVjdCcgfHwgdHlwZW9mIGIgIT0gJ29iamVjdCcpIHJldHVybiBmYWxzZTtcbiAgICAvLyBBc3N1bWUgZXF1YWxpdHkgZm9yIGN5Y2xpYyBzdHJ1Y3R1cmVzLiBUaGUgYWxnb3JpdGhtIGZvciBkZXRlY3RpbmcgY3ljbGljXG4gICAgLy8gc3RydWN0dXJlcyBpcyBhZGFwdGVkIGZyb20gRVMgNS4xIHNlY3Rpb24gMTUuMTIuMywgYWJzdHJhY3Qgb3BlcmF0aW9uIGBKT2AuXG4gICAgdmFyIGxlbmd0aCA9IGFTdGFjay5sZW5ndGg7XG4gICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAvLyBMaW5lYXIgc2VhcmNoLiBQZXJmb3JtYW5jZSBpcyBpbnZlcnNlbHkgcHJvcG9ydGlvbmFsIHRvIHRoZSBudW1iZXIgb2ZcbiAgICAgIC8vIHVuaXF1ZSBuZXN0ZWQgc3RydWN0dXJlcy5cbiAgICAgIGlmIChhU3RhY2tbbGVuZ3RoXSA9PSBhKSByZXR1cm4gYlN0YWNrW2xlbmd0aF0gPT0gYjtcbiAgICB9XG4gICAgLy8gT2JqZWN0cyB3aXRoIGRpZmZlcmVudCBjb25zdHJ1Y3RvcnMgYXJlIG5vdCBlcXVpdmFsZW50LCBidXQgYE9iamVjdGBzXG4gICAgLy8gZnJvbSBkaWZmZXJlbnQgZnJhbWVzIGFyZS5cbiAgICB2YXIgYUN0b3IgPSBhLmNvbnN0cnVjdG9yLCBiQ3RvciA9IGIuY29uc3RydWN0b3I7XG4gICAgaWYgKGFDdG9yICE9PSBiQ3RvciAmJiAhKF8uaXNGdW5jdGlvbihhQ3RvcikgJiYgKGFDdG9yIGluc3RhbmNlb2YgYUN0b3IpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIF8uaXNGdW5jdGlvbihiQ3RvcikgJiYgKGJDdG9yIGluc3RhbmNlb2YgYkN0b3IpKVxuICAgICAgICAgICAgICAgICAgICAgICAgJiYgKCdjb25zdHJ1Y3RvcicgaW4gYSAmJiAnY29uc3RydWN0b3InIGluIGIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIC8vIEFkZCB0aGUgZmlyc3Qgb2JqZWN0IHRvIHRoZSBzdGFjayBvZiB0cmF2ZXJzZWQgb2JqZWN0cy5cbiAgICBhU3RhY2sucHVzaChhKTtcbiAgICBiU3RhY2sucHVzaChiKTtcbiAgICB2YXIgc2l6ZSA9IDAsIHJlc3VsdCA9IHRydWU7XG4gICAgLy8gUmVjdXJzaXZlbHkgY29tcGFyZSBvYmplY3RzIGFuZCBhcnJheXMuXG4gICAgaWYgKGNsYXNzTmFtZSA9PSAnW29iamVjdCBBcnJheV0nKSB7XG4gICAgICAvLyBDb21wYXJlIGFycmF5IGxlbmd0aHMgdG8gZGV0ZXJtaW5lIGlmIGEgZGVlcCBjb21wYXJpc29uIGlzIG5lY2Vzc2FyeS5cbiAgICAgIHNpemUgPSBhLmxlbmd0aDtcbiAgICAgIHJlc3VsdCA9IHNpemUgPT0gYi5sZW5ndGg7XG4gICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgIC8vIERlZXAgY29tcGFyZSB0aGUgY29udGVudHMsIGlnbm9yaW5nIG5vbi1udW1lcmljIHByb3BlcnRpZXMuXG4gICAgICAgIHdoaWxlIChzaXplLS0pIHtcbiAgICAgICAgICBpZiAoIShyZXN1bHQgPSBlcShhW3NpemVdLCBiW3NpemVdLCBhU3RhY2ssIGJTdGFjaykpKSBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBEZWVwIGNvbXBhcmUgb2JqZWN0cy5cbiAgICAgIGZvciAodmFyIGtleSBpbiBhKSB7XG4gICAgICAgIGlmIChfLmhhcyhhLCBrZXkpKSB7XG4gICAgICAgICAgLy8gQ291bnQgdGhlIGV4cGVjdGVkIG51bWJlciBvZiBwcm9wZXJ0aWVzLlxuICAgICAgICAgIHNpemUrKztcbiAgICAgICAgICAvLyBEZWVwIGNvbXBhcmUgZWFjaCBtZW1iZXIuXG4gICAgICAgICAgaWYgKCEocmVzdWx0ID0gXy5oYXMoYiwga2V5KSAmJiBlcShhW2tleV0sIGJba2V5XSwgYVN0YWNrLCBiU3RhY2spKSkgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIEVuc3VyZSB0aGF0IGJvdGggb2JqZWN0cyBjb250YWluIHRoZSBzYW1lIG51bWJlciBvZiBwcm9wZXJ0aWVzLlxuICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICBmb3IgKGtleSBpbiBiKSB7XG4gICAgICAgICAgaWYgKF8uaGFzKGIsIGtleSkgJiYgIShzaXplLS0pKSBicmVhaztcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQgPSAhc2l6ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gUmVtb3ZlIHRoZSBmaXJzdCBvYmplY3QgZnJvbSB0aGUgc3RhY2sgb2YgdHJhdmVyc2VkIG9iamVjdHMuXG4gICAgYVN0YWNrLnBvcCgpO1xuICAgIGJTdGFjay5wb3AoKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFBlcmZvcm0gYSBkZWVwIGNvbXBhcmlzb24gdG8gY2hlY2sgaWYgdHdvIG9iamVjdHMgYXJlIGVxdWFsLlxuICBfLmlzRXF1YWwgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgcmV0dXJuIGVxKGEsIGIsIFtdLCBbXSk7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiBhcnJheSwgc3RyaW5nLCBvciBvYmplY3QgZW1wdHk/XG4gIC8vIEFuIFwiZW1wdHlcIiBvYmplY3QgaGFzIG5vIGVudW1lcmFibGUgb3duLXByb3BlcnRpZXMuXG4gIF8uaXNFbXB0eSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIHRydWU7XG4gICAgaWYgKF8uaXNBcnJheShvYmopIHx8IF8uaXNTdHJpbmcob2JqKSkgcmV0dXJuIG9iai5sZW5ndGggPT09IDA7XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikgaWYgKF8uaGFzKG9iaiwga2V5KSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFsdWUgYSBET00gZWxlbWVudD9cbiAgXy5pc0VsZW1lbnQgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gISEob2JqICYmIG9iai5ub2RlVHlwZSA9PT0gMSk7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YWx1ZSBhbiBhcnJheT9cbiAgLy8gRGVsZWdhdGVzIHRvIEVDTUE1J3MgbmF0aXZlIEFycmF5LmlzQXJyYXlcbiAgXy5pc0FycmF5ID0gbmF0aXZlSXNBcnJheSB8fCBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09ICdbb2JqZWN0IEFycmF5XSc7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YXJpYWJsZSBhbiBvYmplY3Q/XG4gIF8uaXNPYmplY3QgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gb2JqID09PSBPYmplY3Qob2JqKTtcbiAgfTtcblxuICAvLyBBZGQgc29tZSBpc1R5cGUgbWV0aG9kczogaXNBcmd1bWVudHMsIGlzRnVuY3Rpb24sIGlzU3RyaW5nLCBpc051bWJlciwgaXNEYXRlLCBpc1JlZ0V4cC5cbiAgZWFjaChbJ0FyZ3VtZW50cycsICdGdW5jdGlvbicsICdTdHJpbmcnLCAnTnVtYmVyJywgJ0RhdGUnLCAnUmVnRXhwJ10sIGZ1bmN0aW9uKG5hbWUpIHtcbiAgICBfWydpcycgKyBuYW1lXSA9IGZ1bmN0aW9uKG9iaikge1xuICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PSAnW29iamVjdCAnICsgbmFtZSArICddJztcbiAgICB9O1xuICB9KTtcblxuICAvLyBEZWZpbmUgYSBmYWxsYmFjayB2ZXJzaW9uIG9mIHRoZSBtZXRob2QgaW4gYnJvd3NlcnMgKGFoZW0sIElFKSwgd2hlcmVcbiAgLy8gdGhlcmUgaXNuJ3QgYW55IGluc3BlY3RhYmxlIFwiQXJndW1lbnRzXCIgdHlwZS5cbiAgaWYgKCFfLmlzQXJndW1lbnRzKGFyZ3VtZW50cykpIHtcbiAgICBfLmlzQXJndW1lbnRzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gISEob2JqICYmIF8uaGFzKG9iaiwgJ2NhbGxlZScpKTtcbiAgICB9O1xuICB9XG5cbiAgLy8gT3B0aW1pemUgYGlzRnVuY3Rpb25gIGlmIGFwcHJvcHJpYXRlLlxuICBpZiAodHlwZW9mICgvLi8pICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgXy5pc0Z1bmN0aW9uID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJztcbiAgICB9O1xuICB9XG5cbiAgLy8gSXMgYSBnaXZlbiBvYmplY3QgYSBmaW5pdGUgbnVtYmVyP1xuICBfLmlzRmluaXRlID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIGlzRmluaXRlKG9iaikgJiYgIWlzTmFOKHBhcnNlRmxvYXQob2JqKSk7XG4gIH07XG5cbiAgLy8gSXMgdGhlIGdpdmVuIHZhbHVlIGBOYU5gPyAoTmFOIGlzIHRoZSBvbmx5IG51bWJlciB3aGljaCBkb2VzIG5vdCBlcXVhbCBpdHNlbGYpLlxuICBfLmlzTmFOID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIF8uaXNOdW1iZXIob2JqKSAmJiBvYmogIT0gK29iajtcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhbHVlIGEgYm9vbGVhbj9cbiAgXy5pc0Jvb2xlYW4gPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gb2JqID09PSB0cnVlIHx8IG9iaiA9PT0gZmFsc2UgfHwgdG9TdHJpbmcuY2FsbChvYmopID09ICdbb2JqZWN0IEJvb2xlYW5dJztcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhbHVlIGVxdWFsIHRvIG51bGw/XG4gIF8uaXNOdWxsID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIG9iaiA9PT0gbnVsbDtcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhcmlhYmxlIHVuZGVmaW5lZD9cbiAgXy5pc1VuZGVmaW5lZCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBvYmogPT09IHZvaWQgMDtcbiAgfTtcblxuICAvLyBTaG9ydGN1dCBmdW5jdGlvbiBmb3IgY2hlY2tpbmcgaWYgYW4gb2JqZWN0IGhhcyBhIGdpdmVuIHByb3BlcnR5IGRpcmVjdGx5XG4gIC8vIG9uIGl0c2VsZiAoaW4gb3RoZXIgd29yZHMsIG5vdCBvbiBhIHByb3RvdHlwZSkuXG4gIF8uaGFzID0gZnVuY3Rpb24ob2JqLCBrZXkpIHtcbiAgICByZXR1cm4gaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGtleSk7XG4gIH07XG5cbiAgLy8gVXRpbGl0eSBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBSdW4gVW5kZXJzY29yZS5qcyBpbiAqbm9Db25mbGljdCogbW9kZSwgcmV0dXJuaW5nIHRoZSBgX2AgdmFyaWFibGUgdG8gaXRzXG4gIC8vIHByZXZpb3VzIG93bmVyLiBSZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoZSBVbmRlcnNjb3JlIG9iamVjdC5cbiAgXy5ub0NvbmZsaWN0ID0gZnVuY3Rpb24oKSB7XG4gICAgcm9vdC5fID0gcHJldmlvdXNVbmRlcnNjb3JlO1xuICAgIHJldHVybiB0aGlzO1xuICB9O1xuXG4gIC8vIEtlZXAgdGhlIGlkZW50aXR5IGZ1bmN0aW9uIGFyb3VuZCBmb3IgZGVmYXVsdCBpdGVyYXRvcnMuXG4gIF8uaWRlbnRpdHkgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfTtcblxuICBfLmNvbnN0YW50ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH07XG4gIH07XG5cbiAgXy5wcm9wZXJ0eSA9IGZ1bmN0aW9uKGtleSkge1xuICAgIHJldHVybiBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiBvYmpba2V5XTtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBwcmVkaWNhdGUgZm9yIGNoZWNraW5nIHdoZXRoZXIgYW4gb2JqZWN0IGhhcyBhIGdpdmVuIHNldCBvZiBga2V5OnZhbHVlYCBwYWlycy5cbiAgXy5tYXRjaGVzID0gZnVuY3Rpb24oYXR0cnMpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ob2JqKSB7XG4gICAgICBpZiAob2JqID09PSBhdHRycykgcmV0dXJuIHRydWU7IC8vYXZvaWQgY29tcGFyaW5nIGFuIG9iamVjdCB0byBpdHNlbGYuXG4gICAgICBmb3IgKHZhciBrZXkgaW4gYXR0cnMpIHtcbiAgICAgICAgaWYgKGF0dHJzW2tleV0gIT09IG9ialtrZXldKVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfTtcblxuICAvLyBSdW4gYSBmdW5jdGlvbiAqKm4qKiB0aW1lcy5cbiAgXy50aW1lcyA9IGZ1bmN0aW9uKG4sIGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgdmFyIGFjY3VtID0gQXJyYXkoTWF0aC5tYXgoMCwgbikpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSBhY2N1bVtpXSA9IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgaSk7XG4gICAgcmV0dXJuIGFjY3VtO1xuICB9O1xuXG4gIC8vIFJldHVybiBhIHJhbmRvbSBpbnRlZ2VyIGJldHdlZW4gbWluIGFuZCBtYXggKGluY2x1c2l2ZSkuXG4gIF8ucmFuZG9tID0gZnVuY3Rpb24obWluLCBtYXgpIHtcbiAgICBpZiAobWF4ID09IG51bGwpIHtcbiAgICAgIG1heCA9IG1pbjtcbiAgICAgIG1pbiA9IDA7XG4gICAgfVxuICAgIHJldHVybiBtaW4gKyBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAobWF4IC0gbWluICsgMSkpO1xuICB9O1xuXG4gIC8vIEEgKHBvc3NpYmx5IGZhc3Rlcikgd2F5IHRvIGdldCB0aGUgY3VycmVudCB0aW1lc3RhbXAgYXMgYW4gaW50ZWdlci5cbiAgXy5ub3cgPSBEYXRlLm5vdyB8fCBmdW5jdGlvbigpIHsgcmV0dXJuIG5ldyBEYXRlKCkuZ2V0VGltZSgpOyB9O1xuXG4gIC8vIExpc3Qgb2YgSFRNTCBlbnRpdGllcyBmb3IgZXNjYXBpbmcuXG4gIHZhciBlbnRpdHlNYXAgPSB7XG4gICAgZXNjYXBlOiB7XG4gICAgICAnJic6ICcmYW1wOycsXG4gICAgICAnPCc6ICcmbHQ7JyxcbiAgICAgICc+JzogJyZndDsnLFxuICAgICAgJ1wiJzogJyZxdW90OycsXG4gICAgICBcIidcIjogJyYjeDI3OydcbiAgICB9XG4gIH07XG4gIGVudGl0eU1hcC51bmVzY2FwZSA9IF8uaW52ZXJ0KGVudGl0eU1hcC5lc2NhcGUpO1xuXG4gIC8vIFJlZ2V4ZXMgY29udGFpbmluZyB0aGUga2V5cyBhbmQgdmFsdWVzIGxpc3RlZCBpbW1lZGlhdGVseSBhYm92ZS5cbiAgdmFyIGVudGl0eVJlZ2V4ZXMgPSB7XG4gICAgZXNjYXBlOiAgIG5ldyBSZWdFeHAoJ1snICsgXy5rZXlzKGVudGl0eU1hcC5lc2NhcGUpLmpvaW4oJycpICsgJ10nLCAnZycpLFxuICAgIHVuZXNjYXBlOiBuZXcgUmVnRXhwKCcoJyArIF8ua2V5cyhlbnRpdHlNYXAudW5lc2NhcGUpLmpvaW4oJ3wnKSArICcpJywgJ2cnKVxuICB9O1xuXG4gIC8vIEZ1bmN0aW9ucyBmb3IgZXNjYXBpbmcgYW5kIHVuZXNjYXBpbmcgc3RyaW5ncyB0by9mcm9tIEhUTUwgaW50ZXJwb2xhdGlvbi5cbiAgXy5lYWNoKFsnZXNjYXBlJywgJ3VuZXNjYXBlJ10sIGZ1bmN0aW9uKG1ldGhvZCkge1xuICAgIF9bbWV0aG9kXSA9IGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgaWYgKHN0cmluZyA9PSBudWxsKSByZXR1cm4gJyc7XG4gICAgICByZXR1cm4gKCcnICsgc3RyaW5nKS5yZXBsYWNlKGVudGl0eVJlZ2V4ZXNbbWV0aG9kXSwgZnVuY3Rpb24obWF0Y2gpIHtcbiAgICAgICAgcmV0dXJuIGVudGl0eU1hcFttZXRob2RdW21hdGNoXTtcbiAgICAgIH0pO1xuICAgIH07XG4gIH0pO1xuXG4gIC8vIElmIHRoZSB2YWx1ZSBvZiB0aGUgbmFtZWQgYHByb3BlcnR5YCBpcyBhIGZ1bmN0aW9uIHRoZW4gaW52b2tlIGl0IHdpdGggdGhlXG4gIC8vIGBvYmplY3RgIGFzIGNvbnRleHQ7IG90aGVyd2lzZSwgcmV0dXJuIGl0LlxuICBfLnJlc3VsdCA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICBpZiAob2JqZWN0ID09IG51bGwpIHJldHVybiB2b2lkIDA7XG4gICAgdmFyIHZhbHVlID0gb2JqZWN0W3Byb3BlcnR5XTtcbiAgICByZXR1cm4gXy5pc0Z1bmN0aW9uKHZhbHVlKSA/IHZhbHVlLmNhbGwob2JqZWN0KSA6IHZhbHVlO1xuICB9O1xuXG4gIC8vIEFkZCB5b3VyIG93biBjdXN0b20gZnVuY3Rpb25zIHRvIHRoZSBVbmRlcnNjb3JlIG9iamVjdC5cbiAgXy5taXhpbiA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGVhY2goXy5mdW5jdGlvbnMob2JqKSwgZnVuY3Rpb24obmFtZSkge1xuICAgICAgdmFyIGZ1bmMgPSBfW25hbWVdID0gb2JqW25hbWVdO1xuICAgICAgXy5wcm90b3R5cGVbbmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBbdGhpcy5fd3JhcHBlZF07XG4gICAgICAgIHB1c2guYXBwbHkoYXJncywgYXJndW1lbnRzKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdC5jYWxsKHRoaXMsIGZ1bmMuYXBwbHkoXywgYXJncykpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgfTtcblxuICAvLyBHZW5lcmF0ZSBhIHVuaXF1ZSBpbnRlZ2VyIGlkICh1bmlxdWUgd2l0aGluIHRoZSBlbnRpcmUgY2xpZW50IHNlc3Npb24pLlxuICAvLyBVc2VmdWwgZm9yIHRlbXBvcmFyeSBET00gaWRzLlxuICB2YXIgaWRDb3VudGVyID0gMDtcbiAgXy51bmlxdWVJZCA9IGZ1bmN0aW9uKHByZWZpeCkge1xuICAgIHZhciBpZCA9ICsraWRDb3VudGVyICsgJyc7XG4gICAgcmV0dXJuIHByZWZpeCA/IHByZWZpeCArIGlkIDogaWQ7XG4gIH07XG5cbiAgLy8gQnkgZGVmYXVsdCwgVW5kZXJzY29yZSB1c2VzIEVSQi1zdHlsZSB0ZW1wbGF0ZSBkZWxpbWl0ZXJzLCBjaGFuZ2UgdGhlXG4gIC8vIGZvbGxvd2luZyB0ZW1wbGF0ZSBzZXR0aW5ncyB0byB1c2UgYWx0ZXJuYXRpdmUgZGVsaW1pdGVycy5cbiAgXy50ZW1wbGF0ZVNldHRpbmdzID0ge1xuICAgIGV2YWx1YXRlICAgIDogLzwlKFtcXHNcXFNdKz8pJT4vZyxcbiAgICBpbnRlcnBvbGF0ZSA6IC88JT0oW1xcc1xcU10rPyklPi9nLFxuICAgIGVzY2FwZSAgICAgIDogLzwlLShbXFxzXFxTXSs/KSU+L2dcbiAgfTtcblxuICAvLyBXaGVuIGN1c3RvbWl6aW5nIGB0ZW1wbGF0ZVNldHRpbmdzYCwgaWYgeW91IGRvbid0IHdhbnQgdG8gZGVmaW5lIGFuXG4gIC8vIGludGVycG9sYXRpb24sIGV2YWx1YXRpb24gb3IgZXNjYXBpbmcgcmVnZXgsIHdlIG5lZWQgb25lIHRoYXQgaXNcbiAgLy8gZ3VhcmFudGVlZCBub3QgdG8gbWF0Y2guXG4gIHZhciBub01hdGNoID0gLyguKV4vO1xuXG4gIC8vIENlcnRhaW4gY2hhcmFjdGVycyBuZWVkIHRvIGJlIGVzY2FwZWQgc28gdGhhdCB0aGV5IGNhbiBiZSBwdXQgaW50byBhXG4gIC8vIHN0cmluZyBsaXRlcmFsLlxuICB2YXIgZXNjYXBlcyA9IHtcbiAgICBcIidcIjogICAgICBcIidcIixcbiAgICAnXFxcXCc6ICAgICAnXFxcXCcsXG4gICAgJ1xccic6ICAgICAncicsXG4gICAgJ1xcbic6ICAgICAnbicsXG4gICAgJ1xcdCc6ICAgICAndCcsXG4gICAgJ1xcdTIwMjgnOiAndTIwMjgnLFxuICAgICdcXHUyMDI5JzogJ3UyMDI5J1xuICB9O1xuXG4gIHZhciBlc2NhcGVyID0gL1xcXFx8J3xcXHJ8XFxufFxcdHxcXHUyMDI4fFxcdTIwMjkvZztcblxuICAvLyBKYXZhU2NyaXB0IG1pY3JvLXRlbXBsYXRpbmcsIHNpbWlsYXIgdG8gSm9obiBSZXNpZydzIGltcGxlbWVudGF0aW9uLlxuICAvLyBVbmRlcnNjb3JlIHRlbXBsYXRpbmcgaGFuZGxlcyBhcmJpdHJhcnkgZGVsaW1pdGVycywgcHJlc2VydmVzIHdoaXRlc3BhY2UsXG4gIC8vIGFuZCBjb3JyZWN0bHkgZXNjYXBlcyBxdW90ZXMgd2l0aGluIGludGVycG9sYXRlZCBjb2RlLlxuICBfLnRlbXBsYXRlID0gZnVuY3Rpb24odGV4dCwgZGF0YSwgc2V0dGluZ3MpIHtcbiAgICB2YXIgcmVuZGVyO1xuICAgIHNldHRpbmdzID0gXy5kZWZhdWx0cyh7fSwgc2V0dGluZ3MsIF8udGVtcGxhdGVTZXR0aW5ncyk7XG5cbiAgICAvLyBDb21iaW5lIGRlbGltaXRlcnMgaW50byBvbmUgcmVndWxhciBleHByZXNzaW9uIHZpYSBhbHRlcm5hdGlvbi5cbiAgICB2YXIgbWF0Y2hlciA9IG5ldyBSZWdFeHAoW1xuICAgICAgKHNldHRpbmdzLmVzY2FwZSB8fCBub01hdGNoKS5zb3VyY2UsXG4gICAgICAoc2V0dGluZ3MuaW50ZXJwb2xhdGUgfHwgbm9NYXRjaCkuc291cmNlLFxuICAgICAgKHNldHRpbmdzLmV2YWx1YXRlIHx8IG5vTWF0Y2gpLnNvdXJjZVxuICAgIF0uam9pbignfCcpICsgJ3wkJywgJ2cnKTtcblxuICAgIC8vIENvbXBpbGUgdGhlIHRlbXBsYXRlIHNvdXJjZSwgZXNjYXBpbmcgc3RyaW5nIGxpdGVyYWxzIGFwcHJvcHJpYXRlbHkuXG4gICAgdmFyIGluZGV4ID0gMDtcbiAgICB2YXIgc291cmNlID0gXCJfX3ArPSdcIjtcbiAgICB0ZXh0LnJlcGxhY2UobWF0Y2hlciwgZnVuY3Rpb24obWF0Y2gsIGVzY2FwZSwgaW50ZXJwb2xhdGUsIGV2YWx1YXRlLCBvZmZzZXQpIHtcbiAgICAgIHNvdXJjZSArPSB0ZXh0LnNsaWNlKGluZGV4LCBvZmZzZXQpXG4gICAgICAgIC5yZXBsYWNlKGVzY2FwZXIsIGZ1bmN0aW9uKG1hdGNoKSB7IHJldHVybiAnXFxcXCcgKyBlc2NhcGVzW21hdGNoXTsgfSk7XG5cbiAgICAgIGlmIChlc2NhcGUpIHtcbiAgICAgICAgc291cmNlICs9IFwiJytcXG4oKF9fdD0oXCIgKyBlc2NhcGUgKyBcIikpPT1udWxsPycnOl8uZXNjYXBlKF9fdCkpK1xcbidcIjtcbiAgICAgIH1cbiAgICAgIGlmIChpbnRlcnBvbGF0ZSkge1xuICAgICAgICBzb3VyY2UgKz0gXCInK1xcbigoX190PShcIiArIGludGVycG9sYXRlICsgXCIpKT09bnVsbD8nJzpfX3QpK1xcbidcIjtcbiAgICAgIH1cbiAgICAgIGlmIChldmFsdWF0ZSkge1xuICAgICAgICBzb3VyY2UgKz0gXCInO1xcblwiICsgZXZhbHVhdGUgKyBcIlxcbl9fcCs9J1wiO1xuICAgICAgfVxuICAgICAgaW5kZXggPSBvZmZzZXQgKyBtYXRjaC5sZW5ndGg7XG4gICAgICByZXR1cm4gbWF0Y2g7XG4gICAgfSk7XG4gICAgc291cmNlICs9IFwiJztcXG5cIjtcblxuICAgIC8vIElmIGEgdmFyaWFibGUgaXMgbm90IHNwZWNpZmllZCwgcGxhY2UgZGF0YSB2YWx1ZXMgaW4gbG9jYWwgc2NvcGUuXG4gICAgaWYgKCFzZXR0aW5ncy52YXJpYWJsZSkgc291cmNlID0gJ3dpdGgob2JqfHx7fSl7XFxuJyArIHNvdXJjZSArICd9XFxuJztcblxuICAgIHNvdXJjZSA9IFwidmFyIF9fdCxfX3A9JycsX19qPUFycmF5LnByb3RvdHlwZS5qb2luLFwiICtcbiAgICAgIFwicHJpbnQ9ZnVuY3Rpb24oKXtfX3ArPV9fai5jYWxsKGFyZ3VtZW50cywnJyk7fTtcXG5cIiArXG4gICAgICBzb3VyY2UgKyBcInJldHVybiBfX3A7XFxuXCI7XG5cbiAgICB0cnkge1xuICAgICAgcmVuZGVyID0gbmV3IEZ1bmN0aW9uKHNldHRpbmdzLnZhcmlhYmxlIHx8ICdvYmonLCAnXycsIHNvdXJjZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZS5zb3VyY2UgPSBzb3VyY2U7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIGlmIChkYXRhKSByZXR1cm4gcmVuZGVyKGRhdGEsIF8pO1xuICAgIHZhciB0ZW1wbGF0ZSA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgIHJldHVybiByZW5kZXIuY2FsbCh0aGlzLCBkYXRhLCBfKTtcbiAgICB9O1xuXG4gICAgLy8gUHJvdmlkZSB0aGUgY29tcGlsZWQgZnVuY3Rpb24gc291cmNlIGFzIGEgY29udmVuaWVuY2UgZm9yIHByZWNvbXBpbGF0aW9uLlxuICAgIHRlbXBsYXRlLnNvdXJjZSA9ICdmdW5jdGlvbignICsgKHNldHRpbmdzLnZhcmlhYmxlIHx8ICdvYmonKSArICcpe1xcbicgKyBzb3VyY2UgKyAnfSc7XG5cbiAgICByZXR1cm4gdGVtcGxhdGU7XG4gIH07XG5cbiAgLy8gQWRkIGEgXCJjaGFpblwiIGZ1bmN0aW9uLCB3aGljaCB3aWxsIGRlbGVnYXRlIHRvIHRoZSB3cmFwcGVyLlxuICBfLmNoYWluID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIF8ob2JqKS5jaGFpbigpO1xuICB9O1xuXG4gIC8vIE9PUFxuICAvLyAtLS0tLS0tLS0tLS0tLS1cbiAgLy8gSWYgVW5kZXJzY29yZSBpcyBjYWxsZWQgYXMgYSBmdW5jdGlvbiwgaXQgcmV0dXJucyBhIHdyYXBwZWQgb2JqZWN0IHRoYXRcbiAgLy8gY2FuIGJlIHVzZWQgT08tc3R5bGUuIFRoaXMgd3JhcHBlciBob2xkcyBhbHRlcmVkIHZlcnNpb25zIG9mIGFsbCB0aGVcbiAgLy8gdW5kZXJzY29yZSBmdW5jdGlvbnMuIFdyYXBwZWQgb2JqZWN0cyBtYXkgYmUgY2hhaW5lZC5cblxuICAvLyBIZWxwZXIgZnVuY3Rpb24gdG8gY29udGludWUgY2hhaW5pbmcgaW50ZXJtZWRpYXRlIHJlc3VsdHMuXG4gIHZhciByZXN1bHQgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gdGhpcy5fY2hhaW4gPyBfKG9iaikuY2hhaW4oKSA6IG9iajtcbiAgfTtcblxuICAvLyBBZGQgYWxsIG9mIHRoZSBVbmRlcnNjb3JlIGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlciBvYmplY3QuXG4gIF8ubWl4aW4oXyk7XG5cbiAgLy8gQWRkIGFsbCBtdXRhdG9yIEFycmF5IGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlci5cbiAgZWFjaChbJ3BvcCcsICdwdXNoJywgJ3JldmVyc2UnLCAnc2hpZnQnLCAnc29ydCcsICdzcGxpY2UnLCAndW5zaGlmdCddLCBmdW5jdGlvbihuYW1lKSB7XG4gICAgdmFyIG1ldGhvZCA9IEFycmF5UHJvdG9bbmFtZV07XG4gICAgXy5wcm90b3R5cGVbbmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBvYmogPSB0aGlzLl93cmFwcGVkO1xuICAgICAgbWV0aG9kLmFwcGx5KG9iaiwgYXJndW1lbnRzKTtcbiAgICAgIGlmICgobmFtZSA9PSAnc2hpZnQnIHx8IG5hbWUgPT0gJ3NwbGljZScpICYmIG9iai5sZW5ndGggPT09IDApIGRlbGV0ZSBvYmpbMF07XG4gICAgICByZXR1cm4gcmVzdWx0LmNhbGwodGhpcywgb2JqKTtcbiAgICB9O1xuICB9KTtcblxuICAvLyBBZGQgYWxsIGFjY2Vzc29yIEFycmF5IGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlci5cbiAgZWFjaChbJ2NvbmNhdCcsICdqb2luJywgJ3NsaWNlJ10sIGZ1bmN0aW9uKG5hbWUpIHtcbiAgICB2YXIgbWV0aG9kID0gQXJyYXlQcm90b1tuYW1lXTtcbiAgICBfLnByb3RvdHlwZVtuYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHJlc3VsdC5jYWxsKHRoaXMsIG1ldGhvZC5hcHBseSh0aGlzLl93cmFwcGVkLCBhcmd1bWVudHMpKTtcbiAgICB9O1xuICB9KTtcblxuICBfLmV4dGVuZChfLnByb3RvdHlwZSwge1xuXG4gICAgLy8gU3RhcnQgY2hhaW5pbmcgYSB3cmFwcGVkIFVuZGVyc2NvcmUgb2JqZWN0LlxuICAgIGNoYWluOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuX2NoYWluID0gdHJ1ZTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvLyBFeHRyYWN0cyB0aGUgcmVzdWx0IGZyb20gYSB3cmFwcGVkIGFuZCBjaGFpbmVkIG9iamVjdC5cbiAgICB2YWx1ZTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fd3JhcHBlZDtcbiAgICB9XG5cbiAgfSk7XG5cbiAgLy8gQU1EIHJlZ2lzdHJhdGlvbiBoYXBwZW5zIGF0IHRoZSBlbmQgZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBBTUQgbG9hZGVyc1xuICAvLyB0aGF0IG1heSBub3QgZW5mb3JjZSBuZXh0LXR1cm4gc2VtYW50aWNzIG9uIG1vZHVsZXMuIEV2ZW4gdGhvdWdoIGdlbmVyYWxcbiAgLy8gcHJhY3RpY2UgZm9yIEFNRCByZWdpc3RyYXRpb24gaXMgdG8gYmUgYW5vbnltb3VzLCB1bmRlcnNjb3JlIHJlZ2lzdGVyc1xuICAvLyBhcyBhIG5hbWVkIG1vZHVsZSBiZWNhdXNlLCBsaWtlIGpRdWVyeSwgaXQgaXMgYSBiYXNlIGxpYnJhcnkgdGhhdCBpc1xuICAvLyBwb3B1bGFyIGVub3VnaCB0byBiZSBidW5kbGVkIGluIGEgdGhpcmQgcGFydHkgbGliLCBidXQgbm90IGJlIHBhcnQgb2ZcbiAgLy8gYW4gQU1EIGxvYWQgcmVxdWVzdC4gVGhvc2UgY2FzZXMgY291bGQgZ2VuZXJhdGUgYW4gZXJyb3Igd2hlbiBhblxuICAvLyBhbm9ueW1vdXMgZGVmaW5lKCkgaXMgY2FsbGVkIG91dHNpZGUgb2YgYSBsb2FkZXIgcmVxdWVzdC5cbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgIGRlZmluZSgndW5kZXJzY29yZScsIFtdLCBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBfO1xuICAgIH0pO1xuICB9XG59KS5jYWxsKHRoaXMpO1xuIiwiY2hhaSAgICAgID0gcmVxdWlyZSgnY2hhaScpXG5leHBlY3QgICAgPSBjaGFpLmV4cGVjdFxuc2hvdWxkICAgID0gY2hhaS5zaG91bGQoKVxuc2lub24gICAgID0gcmVxdWlyZSgnc2lub24nKVxuc2lub25DaGFpID0gcmVxdWlyZSgnc2lub24tY2hhaScpXG5fICAgICAgICAgPSByZXF1aXJlKFwidW5kZXJzY29yZVwiKVxuXG5jaGFpLnVzZShzaW5vbkNoYWkpXG5cbllhdHRhID0gcmVxdWlyZSBcIi4uL2xpYi9GcmFtZXdvcmtzL0pzb25ZYXR0YVwiXG5Db25uZWN0b3JfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuLi9saWIvQ29ubmVjdG9ycy9UZXN0Q29ubmVjdG9yXCJcblxuY2xhc3MgVGVzdFxuICBjb25zdHJ1Y3RvcjogKEBuYW1lX3N1ZmZpeCA9IFwiXCIpLT5cbiAgICBAbnVtYmVyX29mX3Rlc3RfY2FzZXNfbXVsdGlwbGllciA9IDFcbiAgICBAcmVwZWF0X3RoaXMgPSAxICogQG51bWJlcl9vZl90ZXN0X2Nhc2VzX211bHRpcGxpZXJcbiAgICBAZG9Tb21ldGhpbmdfYW1vdW50ID0gMTAwMCAqIEBudW1iZXJfb2ZfdGVzdF9jYXNlc19tdWx0aXBsaWVyXG4gICAgQG51bWJlcl9vZl9lbmdpbmVzID0gIDIgKyBAbnVtYmVyX29mX3Rlc3RfY2FzZXNfbXVsdGlwbGllciAtIDFcblxuICAgIEB0aW1lID0gMFxuICAgIEBvcHMgPSAwXG4gICAgQHRpbWVfbm93ID0gMFxuXG4gICAgQGRlYnVnID0gdHJ1ZVxuXG4gICAgQHJlaW5pdGlhbGl6ZSgpXG5cbiAgcmVpbml0aWFsaXplOiAoKS0+XG5cbiAgICBAdXNlcnMgPSBbXVxuICAgIEBDb25uZWN0b3IgPSBDb25uZWN0b3JfdW5pbml0aWFsaXplZCBAdXNlcnNcbiAgICBmb3IgaSBpbiBbMC4uLkBudW1iZXJfb2ZfZW5naW5lc11cbiAgICAgIEB1c2Vycy5wdXNoKG5ldyBZYXR0YSAoaStAbmFtZV9zdWZmaXgpLCBAQ29ubmVjdG9yKVxuICAgIEB1c2Vyc1swXS52YWwoJ25hbWUnLFwiaVwiKVxuICAgIEBmbHVzaEFsbCgpXG5cbiAgZ2V0U29tZVVzZXI6ICgpLT5cbiAgICBpID0gXy5yYW5kb20gMCwgKEB1c2Vycy5sZW5ndGgtMSlcbiAgICBAdXNlcnNbaV1cblxuICBnZXRSYW5kb21UZXh0OiAoKS0+XG4gICAgY2hhcnMgPSBcImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6XCJcbiAgICBsZW5ndGggPSBfLnJhbmRvbSAwLCAxMFxuICAgIG5leHRjaGFyID0gY2hhcnNbKF8ucmFuZG9tIDAsIChjaGFycy5sZW5ndGgtMSkpXVxuICAgIHRleHQgPSBcIlwiXG4gICAgXyhsZW5ndGgpLnRpbWVzICgpLT4gdGV4dCArPSBuZXh0Y2hhclxuICAgIHRleHRcblxuICBnZW5lcmF0ZUluc2VydE9wOiAodXNlcl9udW0pPT5cbiAgICBwb3MgPSBfLnJhbmRvbSAwLCAoQHVzZXJzW3VzZXJfbnVtXS52YWwoJ25hbWUnKS52YWwoKS5sZW5ndGgtMSlcbiAgICBAdXNlcnNbdXNlcl9udW1dLnZhbCgnbmFtZScpLmluc2VydFRleHQgcG9zLCBAZ2V0UmFuZG9tVGV4dCgpXG4gICAgbnVsbFxuXG4gIGdlbmVyYXRlUmVwbGFjZU9wOiAodXNlcl9udW0pPT5cbiAgICBAdXNlcnNbdXNlcl9udW1dLnZhbCgnbmFtZScpLnJlcGxhY2VUZXh0IEBnZXRSYW5kb21UZXh0KClcbiAgICBudWxsXG5cbiAgZ2VuZXJhdGVEZWxldGVPcDogKHVzZXJfbnVtKT0+XG4gICAgaWYgQHVzZXJzW3VzZXJfbnVtXS52YWwoJ25hbWUnKS52YWwoKS5sZW5ndGggPiAwXG4gICAgICBwb3MgPSBfLnJhbmRvbSAwLCAoQHVzZXJzW3VzZXJfbnVtXS52YWwoJ25hbWUnKS52YWwoKS5sZW5ndGgtMSkgIyBUT0RPISEhIVxuICAgICAgbGVuZ3RoID0gXy5yYW5kb20gMCwgKEB1c2Vyc1t1c2VyX251bV0udmFsKCduYW1lJykudmFsKCkubGVuZ3RoIC0gcG9zKVxuICAgICAgb3BzMSA9IEB1c2Vyc1t1c2VyX251bV0udmFsKCduYW1lJykuZGVsZXRlVGV4dCBwb3MsIGxlbmd0aFxuICAgIHVuZGVmaW5lZFxuXG4gIGdlbmVyYXRlUmFuZG9tT3A6ICh1c2VyX251bSk9PlxuICAgIG9wX2dlbiA9IFtAZ2VuZXJhdGVJbnNlcnRPcCwgQGdlbmVyYXRlRGVsZXRlT3AsIEBnZW5lcmF0ZVJlcGxhY2VPcF1cbiAgICBpID0gXy5yYW5kb20gKG9wX2dlbi5sZW5ndGggLSAxKVxuICAgIG9wID0gb3BfZ2VuW2ldKHVzZXJfbnVtKVxuXG4gIGFwcGx5UmFuZG9tT3A6ICh1c2VyX251bSk9PlxuICAgIHVzZXIgPSBAdXNlcnNbdXNlcl9udW1dXG4gICAgdXNlci5nZXRDb25uZWN0b3IoKS5mbHVzaE9uZVJhbmRvbSgpXG5cbiAgZG9Tb21ldGhpbmc6ICgpLT5cbiAgICB1c2VyX251bSA9IF8ucmFuZG9tIChAbnVtYmVyX29mX2VuZ2luZXMtMSlcbiAgICBjaG9pY2VzID0gW0BhcHBseVJhbmRvbU9wLCBAZ2VuZXJhdGVSYW5kb21PcF1cbiAgICBjaG9pY2UgPSBfLnJhbmRvbSAoY2hvaWNlcy5sZW5ndGgtMSlcbiAgICBjaG9pY2VzW2Nob2ljZV0odXNlcl9udW0pXG5cbiAgZmx1c2hBbGw6ICgpLT5cbiAgICBmb3IgdXNlcix1c2VyX251bWJlciBpbiBAdXNlcnNcbiAgICAgIHVzZXIuZ2V0Q29ubmVjdG9yKCkuZmx1c2hBbGwoKVxuXG4gIGNvbXBhcmVBbGw6ICh0ZXN0X251bWJlciktPlxuICAgIEBmbHVzaEFsbCgpXG5cbiAgICBAdGltZSArPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpIC0gQHRpbWVfbm93XG5cbiAgICBudW1iZXJfb2ZfY3JlYXRlZF9vcGVyYXRpb25zID0gMFxuICAgIGZvciBpIGluIFswLi4uKEB1c2Vycy5sZW5ndGgpXVxuICAgICAgbnVtYmVyX29mX2NyZWF0ZWRfb3BlcmF0aW9ucyArPSBAdXNlcnNbaV0uZ2V0Q29ubmVjdG9yKCkuZ2V0T3BzSW5FeGVjdXRpb25PcmRlcigpLmxlbmd0aFxuICAgIEBvcHMgKz0gbnVtYmVyX29mX2NyZWF0ZWRfb3BlcmF0aW9ucypAdXNlcnMubGVuZ3RoXG5cbiAgICBvcHNfcGVyX21zZWsgPSBNYXRoLmZsb29yKEBvcHMvQHRpbWUpXG4gICAgaWYgdGVzdF9udW1iZXI/XG4gICAgICBjb25zb2xlLmxvZyBcIiN7dGVzdF9udW1iZXJ9LyN7QHJlcGVhdF90aGlzfTogRXZlcnkgY29sbGFib3JhdG9yICgje0B1c2Vycy5sZW5ndGh9KSBhcHBsaWVkICN7bnVtYmVyX29mX2NyZWF0ZWRfb3BlcmF0aW9uc30gb3BzIGluIGEgZGlmZmVyZW50IG9yZGVyLlwiICsgXCIgT3ZlciBhbGwgd2UgY29uc3VtZWQgI3tAb3BzfSBvcGVyYXRpb25zIGluICN7QHRpbWUvMTAwMH0gc2Vjb25kcyAoI3tvcHNfcGVyX21zZWt9IG9wcy9tc2VrKS5cIlxuICAgICNjb25zb2xlLmxvZyB1c2Vyc1swXS52YWwoJ25hbWUnKS52YWwoKVxuICAgIGZvciBpIGluIFswLi4uKEB1c2Vycy5sZW5ndGgtMSldXG4gICAgICBpZiBAZGVidWdcbiAgICAgICAgaWYgKChAdXNlcnNbaV0udmFsKCduYW1lJykudmFsKCkgaXNudCBAdXNlcnNbaSsxXS52YWwoJ25hbWUnKS52YWwoKSkgKSMgYW5kIChudW1iZXJfb2ZfY3JlYXRlZF9vcGVyYXRpb25zIDw9IDYgb3IgdHJ1ZSkpIG9yIGZvdW5kX2Vycm9yXG4gICAgICAgICAgcHJpbnRPcHNJbkV4ZWN1dGlvbk9yZGVyID0gKG90bnVtYmVyLCBvdGhlcm90bnVtYmVyKT0+XG4gICAgICAgICAgICBvcHMgPSBfLmZpbHRlciBAdXNlcnNbb3RudW1iZXJdLmdldENvbm5lY3RvcigpLmdldE9wc0luRXhlY3V0aW9uT3JkZXIoKSwgKG8pLT5cbiAgICAgICAgICAgICAgdHlwZW9mIG8udWlkLm9wX25hbWUgaXNudCAnc3RyaW5nJyBhbmQgby51aWQuY3JlYXRvciBpc250ICdfJ1xuICAgICAgICAgICAgZm9yIHMsaiBpbiBvcHNcbiAgICAgICAgICAgICAgY29uc29sZS5sb2cgXCJvcCN7an0gPSBcIiArIChKU09OLnN0cmluZ2lmeSBzKVxuICAgICAgICAgICAgY29uc29sZS5sb2cgXCJcIlxuICAgICAgICAgICAgcyA9IFwib3BzID0gW1wiXG4gICAgICAgICAgICBmb3IgbyxqIGluIG9wc1xuICAgICAgICAgICAgICBpZiBqIGlzbnQgMFxuICAgICAgICAgICAgICAgIHMgKz0gXCIsIFwiXG4gICAgICAgICAgICAgIHMgKz0gXCJvcCN7an1cIlxuICAgICAgICAgICAgcyArPSBcIl1cIlxuICAgICAgICAgICAgY29uc29sZS5sb2cgc1xuICAgICAgICAgICAgY29uc29sZS5sb2cgXCJAdGVzdF91c2VyLmVuZ2luZS5hcHBseU9wcyBvcHNcIlxuICAgICAgICAgICAgY29uc29sZS5sb2cgXCJleHBlY3QoQHRlc3RfdXNlci52YWwoJ25hbWUnKS52YWwoKSkudG8uZXF1YWwoXFxcIiN7QHVzZXJzW290aGVyb3RudW1iZXJdLnZhbCgnbmFtZScpLnZhbCgpfVxcXCIpXCJcbiAgICAgICAgICAgIG9wc1xuICAgICAgICAgIGNvbnNvbGUubG9nIFwiXCJcbiAgICAgICAgICBjb25zb2xlLmxvZyBcIkZvdW5kIGFuIE9UIFB1enpsZSFcIlxuICAgICAgICAgIGNvbnNvbGUubG9nIFwiT1Qgc3RhdGVzOlwiXG4gICAgICAgICAgZm9yIHUsaiBpbiBAdXNlcnNcbiAgICAgICAgICAgIGNvbnNvbGUubG9nIFwiT1Qje2p9OiBcIit1LnZhbCgnbmFtZScpLnZhbCgpXG4gICAgICAgICAgY29uc29sZS5sb2cgXCJcXG5PVCBleGVjdXRpb24gb3JkZXIgKCN7aX0sI3tpKzF9KTpcIlxuICAgICAgICAgIHByaW50T3BzSW5FeGVjdXRpb25PcmRlciBpLCBpKzFcbiAgICAgICAgICBjb25zb2xlLmxvZyBcIlwiXG4gICAgICAgICAgb3BzID0gcHJpbnRPcHNJbkV4ZWN1dGlvbk9yZGVyIGkrMSwgaVxuXG4gICAgICAgICAgY29uc29sZS5sb2cgXCJcIlxuICAgICAgaWYgKEB1c2Vyc1tpXS52YWwoJ25hbWUnKS52YWwoKSBpc250IEB1c2Vyc1tpKzFdLnZhbCgnbmFtZScpLnZhbCgpKVxuICAgICAgICBjb25zb2xlLmxvZyBcImZvdW5kIGVycm9yXCJcbiAgICAgIGV4cGVjdChAdXNlcnNbaV0udmFsKCduYW1lJykudmFsKCkpLnRvLmVxdWFsKEB1c2Vyc1tpKzFdLnZhbCgnbmFtZScpLnZhbCgpKVxuXG4gIHJ1bjogKCktPlxuICAgIGNvbnNvbGUubG9nICcnXG4gICAgZm9yIHRpbWVzIGluIFsxLi5AcmVwZWF0X3RoaXNdXG4gICAgICBAdGltZV9ub3cgPSAobmV3IERhdGUpLmdldFRpbWUoKVxuICAgICAgZm9yIGkgaW4gWzEuLkBkb1NvbWV0aGluZ19hbW91bnRdXG4gICAgICAgIEBkb1NvbWV0aGluZygpXG5cbiAgICAgIEBjb21wYXJlQWxsKHRpbWVzKVxuICAgICAgQHRlc3RIQmVuY29kaW5nKClcbiAgICAgIGlmIHRpbWVzIGlzbnQgQHJlcGVhdF90aGlzXG4gICAgICAgIEByZWluaXRpYWxpemUoKVxuXG4gIHRlc3RIQmVuY29kaW5nOiAoKS0+XG4gICAgdXNlciA9IG5ldyBZYXR0YSAndGVzdHVzZXInLCAoQ29ubmVjdG9yX3VuaW5pdGlhbGl6ZWQgW10pXG4gICAgdXNlci5lbmdpbmUuYXBwbHlPcHMgQHVzZXJzWzBdLkhCLl9lbmNvZGUoKVxuICAgIGV4cGVjdCh1c2VyLnZhbHVlLm5hbWUudmFsKCkpLnRvLmVxdWFsKEB1c2Vyc1swXS52YWx1ZS5uYW1lLnZhbCgpKVxuXG5kZXNjcmliZSBcIkpzb25ZYXR0YVwiLCAtPlxuICBiZWZvcmVFYWNoIChkb25lKS0+XG4gICAgQHRpbWVvdXQgNTAwMDBcbiAgICBAeVRlc3QgPSBuZXcgVGVzdCgpXG4gICAgQHVzZXJzID0gQHlUZXN0LnVzZXJzXG5cbiAgICBAdGVzdF91c2VyID0gbmV3IFlhdHRhIDAsIChDb25uZWN0b3JfdW5pbml0aWFsaXplZCBbXSlcbiAgICBkb25lKClcblxuICBpdCBcImhhcyBhIEpzb25XcmFwcGVyXCIsIC0+XG4gICAgeSA9IHRoaXMueVRlc3QuZ2V0U29tZVVzZXIoKS5yb290X2VsZW1lbnRcbiAgICB5LnZhbCgneCcsXCJkdHJuXCIsICdpbW11dGFibGUnKVxuICAgIHkudmFsKCdzZXQnLHt4OlwieFwifSwgJ2ltbXV0YWJsZScpXG4gICAgdyA9IHkudmFsdWVcbiAgICB3LnhcbiAgICB3LnNldCA9IHt5OlwiXCJ9XG4gICAgdy54XG4gICAgdy5zZXRcbiAgICB3LnNldC54XG4gICAgZXhwZWN0KHcueCkudG8uZXF1YWwoXCJkdHJuXCIpXG4gICAgZXhwZWN0KHcuc2V0LngpLnRvLmVxdWFsKFwieFwiKVxuXG4gIGl0IFwiaGFuZGxlcyBkb3VibGUtbGF0ZS1qb2luXCIsIC0+XG4gICAgdGVzdCA9IG5ldyBUZXN0KFwiZG91YmxlXCIpXG4gICAgdGVzdC5ydW4oKVxuICAgIEB5VGVzdC5ydW4oKVxuICAgIHUxID0gdGVzdC51c2Vyc1swXVxuICAgIHUyID0gQHlUZXN0LnVzZXJzWzFdXG4gICAgb3BzMSA9IHUxLkhCLl9lbmNvZGUoKVxuICAgIG9wczIgPSB1Mi5IQi5fZW5jb2RlKClcbiAgICB1MS5lbmdpbmUuYXBwbHlPcHMgb3BzMlxuICAgIHUyLmVuZ2luZS5hcHBseU9wcyBvcHMxXG4gICAgZXhwZWN0KHUyLnZhbHVlLm5hbWUudmFsKCkpLnRvLmVxdWFsKHUyLnZhbHVlLm5hbWUudmFsKCkpXG5cblxuXG4gIGl0IFwiY2FuIGhhbmRsZSBjcmVhdG9uIG9mIGNvbXBsZXgganNvblwiLCAtPlxuICAgIEB5VGVzdC5nZXRTb21lVXNlcigpLnZhbCgneCcsIHsnYSc6J2InfSlcbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ2EnLCB7J2EnOntxOlwiZHRybmR0cnRkcm50ZHJucnRkbnJ0ZG5ydGRucnRkbnJkbnJkdFwifX0pXG4gICAgQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdiJywgeydhJzp7fX0pXG4gICAgQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdjJywgeydhJzonYyd9KVxuICAgIEB5VGVzdC5nZXRTb21lVXNlcigpLnZhbCgnYycsIHsnYSc6J2InfSlcbiAgICBAeVRlc3QuY29tcGFyZUFsbCgpXG4gICAgQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsdWUuYS5hLnEuaW5zZXJ0VGV4dCgwLCdBQUEnKVxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsdWUuYS5hLnEudmFsKCkpLnRvLmVxdWFsKFwiQUFBZHRybmR0cnRkcm50ZHJucnRkbnJ0ZG5ydGRucnRkbnJkbnJkdFwiKVxuXG5cbiAgaXQgXCJoYW5kbGVzIHNvbWUgaW1tdXRhYmxlIHRlc3RzXCIsIC0+XG4gICAgQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdzdHJpbmcnLCBcInRleHRcIiwgXCJpbW11dGFibGVcIilcbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ251bWJlcicsIDQsIFwiaW1tdXRhYmxlXCIpXG4gICAgQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdvYmplY3QnLCB7cTpcInJyXCJ9LCBcImltbXV0YWJsZVwiKVxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdzdHJpbmcnKSkudG8uZXF1YWwgXCJ0ZXh0XCJcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdudW1iZXInKSkudG8uZXF1YWwgNFxuICAgIGV4cGVjdChAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ29iamVjdCcpLnZhbCgncScpKS50by5lcXVhbCBcInJyXCJcblxuICBpdCBcImNhbiBoYW5kbGUgbWFueSBlbmdpbmVzLCBtYW55IG9wZXJhdGlvbnMsIGNvbmN1cnJlbnRseSAocmFuZG9tKVwiLCAtPlxuICAgIEB5VGVzdC5ydW4oKVxuXG4gIGl0IFwiY29udmVyZ2VzIHQxXCIsIC0+XG4gICAgb3AwID0ge1widHlwZVwiOlwiRGVsaW1pdGVyXCIsXCJ1aWRcIjp7XCJjcmVhdG9yXCI6MCxcIm9wX251bWJlclwiOjB9LFwibmV4dFwiOntcImNyZWF0b3JcIjowLFwib3BfbnVtYmVyXCI6MX19XG4gICAgb3AxID0ge1widHlwZVwiOlwiRGVsaW1pdGVyXCIsXCJ1aWRcIjp7XCJjcmVhdG9yXCI6MCxcIm9wX251bWJlclwiOjF9LFwicHJldlwiOntcImNyZWF0b3JcIjowLFwib3BfbnVtYmVyXCI6MH19XG4gICAgb3AyID0ge1widHlwZVwiOlwiV29yZFwiLFwidWlkXCI6e1wiY3JlYXRvclwiOjAsXCJvcF9udW1iZXJcIjoyfSxcImJlZ2lubmluZ1wiOntcImNyZWF0b3JcIjowLFwib3BfbnVtYmVyXCI6MH0sXCJlbmRcIjp7XCJjcmVhdG9yXCI6MCxcIm9wX251bWJlclwiOjF9fVxuICAgIG9wMyA9IHtcInR5cGVcIjpcIkFkZE5hbWVcIixcInVpZFwiOntcImNyZWF0b3JcIjowLFwib3BfbnVtYmVyXCI6M30sXCJtYXBfbWFuYWdlclwiOntcImNyZWF0b3JcIjpcIl9cIixcIm9wX251bWJlclwiOlwiX1wifSxcIm5hbWVcIjpcIm5hbWVcIn1cbiAgICBvcDQgPSB7XCJ0eXBlXCI6XCJSZXBsYWNlYWJsZVwiLFwiY29udGVudFwiOntcImNyZWF0b3JcIjowLFwib3BfbnVtYmVyXCI6Mn0sXCJSZXBsYWNlTWFuYWdlclwiOntcImNyZWF0b3JcIjpcIl9cIixcIm9wX251bWJlclwiOlwiX19fUk1fbmFtZVwifSxcInByZXZcIjp7XCJjcmVhdG9yXCI6XCJfXCIsXCJvcF9udW1iZXJcIjpcIl9fX1JNX25hbWVfYmVnaW5uaW5nXCJ9LFwibmV4dFwiOntcImNyZWF0b3JcIjpcIl9cIixcIm9wX251bWJlclwiOlwiX19fUk1fbmFtZV9lbmRcIn0sXCJ1aWRcIjp7XCJjcmVhdG9yXCI6MCxcIm9wX251bWJlclwiOjR9fVxuICAgIG9wNSA9IHtcInR5cGVcIjpcIlRleHRJbnNlcnRcIixcImNvbnRlbnRcIjpcInVcIixcInVpZFwiOntcImNyZWF0b3JcIjoxLFwib3BfbnVtYmVyXCI6Mn0sXCJwcmV2XCI6e1wiY3JlYXRvclwiOjEsXCJvcF9udW1iZXJcIjowfSxcIm5leHRcIjp7XCJjcmVhdG9yXCI6MSxcIm9wX251bWJlclwiOjF9fVxuICAgIG9wNiA9IHtcInR5cGVcIjpcIlRleHRJbnNlcnRcIixcImNvbnRlbnRcIjpcIndcIixcInVpZFwiOntcImNyZWF0b3JcIjoyLFwib3BfbnVtYmVyXCI6MH0sXCJwcmV2XCI6e1wiY3JlYXRvclwiOjAsXCJvcF9udW1iZXJcIjowfSxcIm5leHRcIjp7XCJjcmVhdG9yXCI6MCxcIm9wX251bWJlclwiOjF9fVxuICAgIG9wNyA9IHtcInR5cGVcIjpcIlRleHRJbnNlcnRcIixcImNvbnRlbnRcIjpcImRcIixcInVpZFwiOntcImNyZWF0b3JcIjoxLFwib3BfbnVtYmVyXCI6MH0sXCJwcmV2XCI6e1wiY3JlYXRvclwiOjAsXCJvcF9udW1iZXJcIjowfSxcIm5leHRcIjp7XCJjcmVhdG9yXCI6MixcIm9wX251bWJlclwiOjB9fVxuICAgIG9wOCA9IHtcInR5cGVcIjpcIlRleHRJbnNlcnRcIixcImNvbnRlbnRcIjpcImFcIixcInVpZFwiOntcImNyZWF0b3JcIjoxLFwib3BfbnVtYmVyXCI6MX0sXCJwcmV2XCI6e1wiY3JlYXRvclwiOjEsXCJvcF9udW1iZXJcIjowfSxcIm5leHRcIjp7XCJjcmVhdG9yXCI6MixcIm9wX251bWJlclwiOjB9fVxuXG4gICAgb3BzID0gW29wMCwgb3AxLCBvcDIsIG9wMywgb3A0LCBvcDUsIG9wNiwgb3A3LCBvcDhdXG4gICAgQHRlc3RfdXNlci5lbmdpbmUuYXBwbHlPcHMgb3BzXG4gICAgZXhwZWN0KEB0ZXN0X3VzZXIudmFsKCduYW1lJykudmFsKCkpLnRvLmVxdWFsKFwiZHVhd1wiKVxuXG4iXX0=
|