19293 lines
1.5 MiB
19293 lines
1.5 MiB
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||
var YList;
|
||
|
||
YList = (function() {
|
||
function YList(list) {
|
||
if (list == null) {
|
||
this._list = [];
|
||
} else if (list.constructor === Array) {
|
||
this._list = list;
|
||
} else {
|
||
throw new Error("Y.List expects an Array as a parameter");
|
||
}
|
||
}
|
||
|
||
YList.prototype._name = "List";
|
||
|
||
YList.prototype._getModel = function(types, ops) {
|
||
if (this._model == null) {
|
||
this._model = new ops.ListManager(this).execute();
|
||
this._model.insert(0, this._list);
|
||
}
|
||
delete this._list;
|
||
return this._model;
|
||
};
|
||
|
||
YList.prototype._setModel = function(_model) {
|
||
this._model = _model;
|
||
return delete this._list;
|
||
};
|
||
|
||
YList.prototype.val = function() {
|
||
var _ref;
|
||
return (_ref = this._model).val.apply(_ref, arguments);
|
||
};
|
||
|
||
YList.prototype.ref = function() {
|
||
var _ref;
|
||
return (_ref = this._model).ref.apply(_ref, arguments);
|
||
};
|
||
|
||
YList.prototype.observe = function() {
|
||
var _ref;
|
||
(_ref = this._model).observe.apply(_ref, arguments);
|
||
return this;
|
||
};
|
||
|
||
YList.prototype.unobserve = function() {
|
||
var _ref;
|
||
(_ref = this._model).unobserve.apply(_ref, arguments);
|
||
return this;
|
||
};
|
||
|
||
YList.prototype.insert = function(position, content) {
|
||
return this.insertContents(position, [content]);
|
||
};
|
||
|
||
YList.prototype.insertContents = function(position, contents) {
|
||
if (typeof position !== "number") {
|
||
throw new Error("Y.List.insert expects a Number as the first parameter!");
|
||
}
|
||
this._model.insert(position, contents);
|
||
return this;
|
||
};
|
||
|
||
YList.prototype["delete"] = function(position, length) {
|
||
this._model["delete"](position, length);
|
||
return this;
|
||
};
|
||
|
||
YList.prototype.push = function(content) {
|
||
this._model.push(content);
|
||
return this;
|
||
};
|
||
|
||
YList.prototype.getLength = function() {
|
||
return this._model.getLength();
|
||
};
|
||
|
||
return YList;
|
||
|
||
})();
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
if (window.Y != null) {
|
||
window.Y.List = YList;
|
||
} else {
|
||
throw new Error("You must first import Y!");
|
||
}
|
||
}
|
||
|
||
if (typeof module !== "undefined" && module !== null) {
|
||
module.exports = YList;
|
||
}
|
||
|
||
|
||
},{}],2:[function(require,module,exports){
|
||
var TestConnector;
|
||
|
||
TestConnector = (function() {
|
||
function TestConnector(id) {
|
||
var options;
|
||
this.id = id;
|
||
options = {
|
||
syncMethod: "syncAll",
|
||
role: "slave",
|
||
user_id: this.id,
|
||
perform_send_again: false
|
||
};
|
||
this.on_bound_to_y = (function(_this) {
|
||
return function() {
|
||
_this.init(options);
|
||
_this.execution_order = [];
|
||
_this.receive_buffer = {};
|
||
return _this.receive_handlers.push(function(user, message) {
|
||
return _this.execution_order.push(message);
|
||
});
|
||
};
|
||
})(this);
|
||
}
|
||
|
||
TestConnector.prototype.join = function(conn) {
|
||
var c, cid, _ref, _results;
|
||
if (this.connections[conn.id] == null) {
|
||
this.connections[conn.id] = {
|
||
conn: conn
|
||
};
|
||
this.userJoined(conn.id, "slave");
|
||
conn.join(this);
|
||
this.flushAll();
|
||
conn.flushAll();
|
||
this.flushAll();
|
||
conn.flushAll();
|
||
_ref = conn.connections;
|
||
_results = [];
|
||
for (cid in _ref) {
|
||
c = _ref[cid];
|
||
if (this.connections[cid] == null) {
|
||
_results.push(this.join(c.conn));
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
}
|
||
};
|
||
|
||
TestConnector.prototype.getOpsInExecutionOrder = function() {
|
||
return this.execution_order;
|
||
};
|
||
|
||
TestConnector.prototype.send = function(uid, message) {
|
||
var rb, _name;
|
||
if ((message.sync_step != null) && false) {
|
||
return this.receiveMessage(uid, message);
|
||
} else {
|
||
rb = this.connections[uid].conn.receive_buffer;
|
||
if (rb[_name = this.id] == null) {
|
||
rb[_name] = [];
|
||
}
|
||
return rb[this.id].push(message);
|
||
}
|
||
};
|
||
|
||
TestConnector.prototype.broadcast = function(message) {
|
||
var c, name, _ref, _results;
|
||
_ref = this.connections;
|
||
_results = [];
|
||
for (name in _ref) {
|
||
c = _ref[name];
|
||
_results.push(this.send(name, message));
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
TestConnector.prototype.flushOne = function(uid) {
|
||
var message, _ref;
|
||
if (((_ref = this.receive_buffer[uid]) != null ? _ref.length : void 0) > 0) {
|
||
message = this.receive_buffer[uid].shift();
|
||
return this.receiveMessage(uid, message);
|
||
}
|
||
};
|
||
|
||
TestConnector.prototype.flushOneRandom = function() {
|
||
var c, cid, connlist, i;
|
||
connlist = (function() {
|
||
var _ref, _results;
|
||
_ref = this.receive_buffer;
|
||
_results = [];
|
||
for (cid in _ref) {
|
||
c = _ref[cid];
|
||
_results.push(cid);
|
||
}
|
||
return _results;
|
||
}).call(this);
|
||
i = Math.ceil(Math.random() * connlist.length - 0.5);
|
||
return this.flushOne(connlist[i]);
|
||
};
|
||
|
||
TestConnector.prototype.flushAll = function() {
|
||
var message, messages, n, _i, _len, _ref;
|
||
_ref = this.receive_buffer;
|
||
for (n in _ref) {
|
||
messages = _ref[n];
|
||
for (_i = 0, _len = messages.length; _i < _len; _i++) {
|
||
message = messages[_i];
|
||
this.receiveMessage(n, message);
|
||
}
|
||
}
|
||
return this.receive_buffer = {};
|
||
};
|
||
|
||
return TestConnector;
|
||
|
||
})();
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
if (typeof Y === "undefined" || Y === null) {
|
||
throw new Error("You must import Y first!");
|
||
} else {
|
||
window.Y.TestConnector = TestConnector;
|
||
}
|
||
}
|
||
|
||
if (typeof module !== "undefined" && module !== null) {
|
||
module.exports = TestConnector;
|
||
}
|
||
|
||
|
||
},{}],3:[function(require,module,exports){
|
||
var YText;
|
||
|
||
YText = (function() {
|
||
function YText(text) {
|
||
this.textfields = [];
|
||
if (text == null) {
|
||
this._text = "";
|
||
} else if (text.constructor === String) {
|
||
this._text = text;
|
||
} else {
|
||
throw new Error("Y.Text expects a String as a constructor");
|
||
}
|
||
}
|
||
|
||
YText.prototype._name = "Text";
|
||
|
||
YText.prototype._getModel = function(types, ops) {
|
||
if (this._model == null) {
|
||
this._model = new ops.ListManager(this).execute();
|
||
this.insert(0, this._text);
|
||
}
|
||
delete this._text;
|
||
return this._model;
|
||
};
|
||
|
||
YText.prototype._setModel = function(_model) {
|
||
this._model = _model;
|
||
return delete this._text;
|
||
};
|
||
|
||
YText.prototype.val = function() {
|
||
return this._model.fold("", function(left, o) {
|
||
return left + o.val();
|
||
});
|
||
};
|
||
|
||
YText.prototype.observe = function() {
|
||
return this._model.observe.apply(this._model, arguments);
|
||
};
|
||
|
||
YText.prototype.unobserve = function() {
|
||
return this._model.unobserve.apply(this._model, arguments);
|
||
};
|
||
|
||
YText.prototype.toString = function() {
|
||
return this.val();
|
||
};
|
||
|
||
YText.prototype.insert = function(position, content) {
|
||
var ith;
|
||
if (content.constructor !== String) {
|
||
throw new Error("Y.String.insert expects a String as the second parameter!");
|
||
}
|
||
if (typeof position !== "number") {
|
||
throw new Error("Y.String.insert expects a Number as the first parameter!");
|
||
}
|
||
if (content.length > 0) {
|
||
ith = this._model.getOperationByPosition(position);
|
||
return this._model.insertAfter(ith, content);
|
||
}
|
||
};
|
||
|
||
YText.prototype["delete"] = function(position, length) {
|
||
return this._model["delete"](position, length);
|
||
};
|
||
|
||
YText.prototype.bind = function(textfield, dom_root) {
|
||
var createRange, creator_token, t, word, writeContent, writeRange, _i, _len, _ref;
|
||
if (dom_root == null) {
|
||
dom_root = window;
|
||
}
|
||
if (dom_root.getSelection == null) {
|
||
dom_root = window;
|
||
}
|
||
_ref = this.textfields;
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
t = _ref[_i];
|
||
if (t === textfield) {
|
||
return;
|
||
}
|
||
}
|
||
creator_token = false;
|
||
word = this;
|
||
textfield.value = this.val();
|
||
this.textfields.push(textfield);
|
||
if ((textfield.selectionStart != null) && (textfield.setSelectionRange != null)) {
|
||
createRange = function(fix) {
|
||
var left, right;
|
||
left = textfield.selectionStart;
|
||
right = textfield.selectionEnd;
|
||
if (fix != null) {
|
||
left = fix(left);
|
||
right = fix(right);
|
||
}
|
||
return {
|
||
left: left,
|
||
right: right
|
||
};
|
||
};
|
||
writeRange = function(range) {
|
||
writeContent(word.val());
|
||
return textfield.setSelectionRange(range.left, range.right);
|
||
};
|
||
writeContent = function(content) {
|
||
return textfield.value = content;
|
||
};
|
||
} else {
|
||
createRange = function(fix) {
|
||
var clength, edited_element, range, s;
|
||
range = {};
|
||
s = dom_root.getSelection();
|
||
clength = textfield.textContent.length;
|
||
range.left = Math.min(s.anchorOffset, clength);
|
||
range.right = Math.min(s.focusOffset, clength);
|
||
if (fix != null) {
|
||
range.left = fix(range.left);
|
||
range.right = fix(range.right);
|
||
}
|
||
edited_element = s.focusNode;
|
||
if (edited_element === textfield || edited_element === textfield.childNodes[0]) {
|
||
range.isReal = true;
|
||
} else {
|
||
range.isReal = false;
|
||
}
|
||
return range;
|
||
};
|
||
writeRange = function(range) {
|
||
var r, s, textnode;
|
||
writeContent(word.val());
|
||
textnode = textfield.childNodes[0];
|
||
if (range.isReal && (textnode != null)) {
|
||
if (range.left < 0) {
|
||
range.left = 0;
|
||
}
|
||
range.right = Math.max(range.left, range.right);
|
||
if (range.right > textnode.length) {
|
||
range.right = textnode.length;
|
||
}
|
||
range.left = Math.min(range.left, range.right);
|
||
r = document.createRange();
|
||
r.setStart(textnode, range.left);
|
||
r.setEnd(textnode, range.right);
|
||
s = window.getSelection();
|
||
s.removeAllRanges();
|
||
return s.addRange(r);
|
||
}
|
||
};
|
||
writeContent = function(content) {
|
||
var c, content_array, i, _j, _len1, _results;
|
||
content_array = content.replace(new RegExp("\n", 'g'), " ").split(" ");
|
||
textfield.innerText = "";
|
||
_results = [];
|
||
for (i = _j = 0, _len1 = content_array.length; _j < _len1; i = ++_j) {
|
||
c = content_array[i];
|
||
textfield.innerText += c;
|
||
if (i !== content_array.length - 1) {
|
||
_results.push(textfield.innerHTML += ' ');
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
}
|
||
writeContent(this.val());
|
||
this.observe(function(events) {
|
||
var event, fix, o_pos, r, _j, _len1, _results;
|
||
_results = [];
|
||
for (_j = 0, _len1 = events.length; _j < _len1; _j++) {
|
||
event = events[_j];
|
||
if (!creator_token) {
|
||
if (event.type === "insert") {
|
||
o_pos = event.position;
|
||
fix = function(cursor) {
|
||
if (cursor <= o_pos) {
|
||
return cursor;
|
||
} else {
|
||
cursor += 1;
|
||
return cursor;
|
||
}
|
||
};
|
||
r = createRange(fix);
|
||
_results.push(writeRange(r));
|
||
} else if (event.type === "delete") {
|
||
o_pos = event.position;
|
||
fix = function(cursor) {
|
||
if (cursor < o_pos) {
|
||
return cursor;
|
||
} else {
|
||
cursor -= 1;
|
||
return cursor;
|
||
}
|
||
};
|
||
r = createRange(fix);
|
||
_results.push(writeRange(r));
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
});
|
||
textfield.onkeypress = function(event) {
|
||
var char, diff, pos, r;
|
||
if (word.is_deleted) {
|
||
textfield.onkeypress = null;
|
||
return true;
|
||
}
|
||
creator_token = true;
|
||
char = null;
|
||
if (event.keyCode === 13) {
|
||
char = '\n';
|
||
} else if (event.key != null) {
|
||
if (event.charCode === 32) {
|
||
char = " ";
|
||
} else {
|
||
char = event.key;
|
||
}
|
||
} else {
|
||
char = window.String.fromCharCode(event.keyCode);
|
||
}
|
||
if (char.length > 1) {
|
||
return true;
|
||
} else if (char.length > 0) {
|
||
r = createRange();
|
||
pos = Math.min(r.left, r.right);
|
||
diff = Math.abs(r.right - r.left);
|
||
word["delete"](pos, diff);
|
||
word.insert(pos, char);
|
||
r.left = pos + char.length;
|
||
r.right = r.left;
|
||
writeRange(r);
|
||
}
|
||
event.preventDefault();
|
||
creator_token = false;
|
||
return false;
|
||
};
|
||
textfield.onpaste = function(event) {
|
||
if (word.is_deleted) {
|
||
textfield.onpaste = null;
|
||
return true;
|
||
}
|
||
return event.preventDefault();
|
||
};
|
||
textfield.oncut = function(event) {
|
||
if (word.is_deleted) {
|
||
textfield.oncut = null;
|
||
return true;
|
||
}
|
||
return event.preventDefault();
|
||
};
|
||
return textfield.onkeydown = function(event) {
|
||
var del_length, diff, new_pos, pos, r, val;
|
||
creator_token = true;
|
||
if (word.is_deleted) {
|
||
textfield.onkeydown = null;
|
||
return true;
|
||
}
|
||
r = createRange();
|
||
pos = Math.min(r.left, r.right, word.val().length);
|
||
diff = Math.abs(r.left - r.right);
|
||
if ((event.keyCode != null) && event.keyCode === 8) {
|
||
if (diff > 0) {
|
||
word["delete"](pos, diff);
|
||
r.left = pos;
|
||
r.right = pos;
|
||
writeRange(r);
|
||
} else {
|
||
if ((event.ctrlKey != null) && event.ctrlKey) {
|
||
val = word.val();
|
||
new_pos = pos;
|
||
del_length = 0;
|
||
if (pos > 0) {
|
||
new_pos--;
|
||
del_length++;
|
||
}
|
||
while (new_pos > 0 && val[new_pos] !== " " && val[new_pos] !== '\n') {
|
||
new_pos--;
|
||
del_length++;
|
||
}
|
||
word["delete"](new_pos, pos - new_pos);
|
||
r.left = new_pos;
|
||
r.right = new_pos;
|
||
writeRange(r);
|
||
} else {
|
||
if (pos > 0) {
|
||
word["delete"](pos - 1, 1);
|
||
r.left = pos - 1;
|
||
r.right = pos - 1;
|
||
writeRange(r);
|
||
}
|
||
}
|
||
}
|
||
event.preventDefault();
|
||
creator_token = false;
|
||
return false;
|
||
} else if ((event.keyCode != null) && event.keyCode === 46) {
|
||
if (diff > 0) {
|
||
word["delete"](pos, diff);
|
||
r.left = pos;
|
||
r.right = pos;
|
||
writeRange(r);
|
||
} else {
|
||
word["delete"](pos, 1);
|
||
r.left = pos;
|
||
r.right = pos;
|
||
writeRange(r);
|
||
}
|
||
event.preventDefault();
|
||
creator_token = false;
|
||
return false;
|
||
} else {
|
||
creator_token = false;
|
||
return true;
|
||
}
|
||
};
|
||
};
|
||
|
||
return YText;
|
||
|
||
})();
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
if (window.Y != null) {
|
||
window.Y.Text = YText;
|
||
} else {
|
||
throw new Error("You must first import Y!");
|
||
}
|
||
}
|
||
|
||
if (typeof module !== "undefined" && module !== null) {
|
||
module.exports = YText;
|
||
}
|
||
|
||
|
||
},{}],4:[function(require,module,exports){
|
||
var ConnectorClass, adaptConnector;
|
||
|
||
ConnectorClass = require("./ConnectorClass");
|
||
|
||
adaptConnector = function(connector, engine, HB, execution_listener) {
|
||
var applyHB, encode_state_vector, f, getHB, getStateVector, name, parse_state_vector, send_;
|
||
for (name in ConnectorClass) {
|
||
f = ConnectorClass[name];
|
||
connector[name] = f;
|
||
}
|
||
connector.setIsBoundToY();
|
||
send_ = function(o) {
|
||
if ((o.uid.creator === HB.getUserId()) && (typeof o.uid.op_number !== "string") && (HB.getUserId() !== "_temp")) {
|
||
return connector.broadcast(o);
|
||
}
|
||
};
|
||
if (connector.invokeSync != null) {
|
||
HB.setInvokeSyncHandler(connector.invokeSync);
|
||
}
|
||
execution_listener.push(send_);
|
||
encode_state_vector = function(v) {
|
||
var value, _results;
|
||
_results = [];
|
||
for (name in v) {
|
||
value = v[name];
|
||
_results.push({
|
||
user: name,
|
||
state: value
|
||
});
|
||
}
|
||
return _results;
|
||
};
|
||
parse_state_vector = function(v) {
|
||
var s, state_vector, _i, _len;
|
||
state_vector = {};
|
||
for (_i = 0, _len = v.length; _i < _len; _i++) {
|
||
s = v[_i];
|
||
state_vector[s.user] = s.state;
|
||
}
|
||
return state_vector;
|
||
};
|
||
getStateVector = function() {
|
||
return encode_state_vector(HB.getOperationCounter());
|
||
};
|
||
getHB = function(v) {
|
||
var hb, json, state_vector;
|
||
state_vector = parse_state_vector(v);
|
||
hb = HB._encode(state_vector);
|
||
json = {
|
||
hb: hb,
|
||
state_vector: encode_state_vector(HB.getOperationCounter())
|
||
};
|
||
return json;
|
||
};
|
||
applyHB = function(hb, fromHB) {
|
||
return engine.applyOp(hb, fromHB);
|
||
};
|
||
connector.getStateVector = getStateVector;
|
||
connector.getHB = getHB;
|
||
connector.applyHB = applyHB;
|
||
if (connector.receive_handlers == null) {
|
||
connector.receive_handlers = [];
|
||
}
|
||
return connector.receive_handlers.push(function(sender, op) {
|
||
if (op.uid.creator !== HB.getUserId()) {
|
||
return engine.applyOp(op);
|
||
}
|
||
});
|
||
};
|
||
|
||
module.exports = adaptConnector;
|
||
|
||
|
||
},{"./ConnectorClass":5}],5:[function(require,module,exports){
|
||
module.exports = {
|
||
init: function(options) {
|
||
var req;
|
||
req = (function(_this) {
|
||
return function(name, choices) {
|
||
if (options[name] != null) {
|
||
if ((choices == null) || choices.some(function(c) {
|
||
return c === options[name];
|
||
})) {
|
||
return _this[name] = options[name];
|
||
} else {
|
||
throw new Error("You can set the '" + name + "' option to one of the following choices: " + JSON.encode(choices));
|
||
}
|
||
} else {
|
||
throw new Error("You must specify " + name + ", when initializing the Connector!");
|
||
}
|
||
};
|
||
})(this);
|
||
req("syncMethod", ["syncAll", "master-slave"]);
|
||
req("role", ["master", "slave"]);
|
||
req("user_id");
|
||
if (typeof this.on_user_id_set === "function") {
|
||
this.on_user_id_set(this.user_id);
|
||
}
|
||
if (options.perform_send_again != null) {
|
||
this.perform_send_again = options.perform_send_again;
|
||
} else {
|
||
this.perform_send_again = true;
|
||
}
|
||
if (this.role === "master") {
|
||
this.syncMethod = "syncAll";
|
||
}
|
||
this.is_synced = false;
|
||
this.connections = {};
|
||
if (this.receive_handlers == null) {
|
||
this.receive_handlers = [];
|
||
}
|
||
this.connections = {};
|
||
this.current_sync_target = null;
|
||
this.sent_hb_to_all_users = false;
|
||
return this.is_initialized = true;
|
||
},
|
||
onUserEvent: function(f) {
|
||
if (this.connections_listeners == null) {
|
||
this.connections_listeners = [];
|
||
}
|
||
return this.connections_listeners.push(f);
|
||
},
|
||
isRoleMaster: function() {
|
||
return this.role === "master";
|
||
},
|
||
isRoleSlave: function() {
|
||
return this.role === "slave";
|
||
},
|
||
findNewSyncTarget: function() {
|
||
var c, user, _ref;
|
||
this.current_sync_target = null;
|
||
if (this.syncMethod === "syncAll") {
|
||
_ref = this.connections;
|
||
for (user in _ref) {
|
||
c = _ref[user];
|
||
if (!c.is_synced) {
|
||
this.performSync(user);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (this.current_sync_target == null) {
|
||
this.setStateSynced();
|
||
}
|
||
return null;
|
||
},
|
||
userLeft: function(user) {
|
||
var f, _i, _len, _ref, _results;
|
||
delete this.connections[user];
|
||
this.findNewSyncTarget();
|
||
if (this.connections_listeners != null) {
|
||
_ref = this.connections_listeners;
|
||
_results = [];
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
f = _ref[_i];
|
||
_results.push(f({
|
||
action: "userLeft",
|
||
user: user
|
||
}));
|
||
}
|
||
return _results;
|
||
}
|
||
},
|
||
userJoined: function(user, role) {
|
||
var f, _base, _i, _len, _ref, _results;
|
||
if (role == null) {
|
||
throw new Error("Internal: You must specify the role of the joined user! E.g. userJoined('uid:3939','slave')");
|
||
}
|
||
if ((_base = this.connections)[user] == null) {
|
||
_base[user] = {};
|
||
}
|
||
this.connections[user].is_synced = false;
|
||
if ((!this.is_synced) || this.syncMethod === "syncAll") {
|
||
if (this.syncMethod === "syncAll") {
|
||
this.performSync(user);
|
||
} else if (role === "master") {
|
||
this.performSyncWithMaster(user);
|
||
}
|
||
}
|
||
if (this.connections_listeners != null) {
|
||
_ref = this.connections_listeners;
|
||
_results = [];
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
f = _ref[_i];
|
||
_results.push(f({
|
||
action: "userJoined",
|
||
user: user,
|
||
role: role
|
||
}));
|
||
}
|
||
return _results;
|
||
}
|
||
},
|
||
whenSynced: function(args) {
|
||
if (args.constructor === Function) {
|
||
args = [args];
|
||
}
|
||
if (this.is_synced) {
|
||
return args[0].apply(this, args.slice(1));
|
||
} else {
|
||
if (this.compute_when_synced == null) {
|
||
this.compute_when_synced = [];
|
||
}
|
||
return this.compute_when_synced.push(args);
|
||
}
|
||
},
|
||
onReceive: function(f) {
|
||
return this.receive_handlers.push(f);
|
||
},
|
||
|
||
/*
|
||
* Broadcast a message to all connected peers.
|
||
* @param message {Object} The message to broadcast.
|
||
*
|
||
broadcast: (message)->
|
||
throw new Error "You must implement broadcast!"
|
||
|
||
*
|
||
* Send a message to a peer, or set of peers
|
||
*
|
||
send: (peer_s, message)->
|
||
throw new Error "You must implement send!"
|
||
*/
|
||
performSync: function(user) {
|
||
var hb, o, _hb, _i, _len;
|
||
if (this.current_sync_target == null) {
|
||
this.current_sync_target = user;
|
||
this.send(user, {
|
||
sync_step: "getHB",
|
||
send_again: "true",
|
||
data: this.getStateVector()
|
||
});
|
||
if (!this.sent_hb_to_all_users) {
|
||
this.sent_hb_to_all_users = true;
|
||
hb = this.getHB([]).hb;
|
||
_hb = [];
|
||
for (_i = 0, _len = hb.length; _i < _len; _i++) {
|
||
o = hb[_i];
|
||
_hb.push(o);
|
||
if (_hb.length > 10) {
|
||
this.broadcast({
|
||
sync_step: "applyHB_",
|
||
data: _hb
|
||
});
|
||
_hb = [];
|
||
}
|
||
}
|
||
return this.broadcast({
|
||
sync_step: "applyHB",
|
||
data: _hb
|
||
});
|
||
}
|
||
}
|
||
},
|
||
performSyncWithMaster: function(user) {
|
||
var hb, o, _hb, _i, _len;
|
||
this.current_sync_target = user;
|
||
this.send(user, {
|
||
sync_step: "getHB",
|
||
send_again: "true",
|
||
data: this.getStateVector()
|
||
});
|
||
hb = this.getHB([]).hb;
|
||
_hb = [];
|
||
for (_i = 0, _len = hb.length; _i < _len; _i++) {
|
||
o = hb[_i];
|
||
_hb.push(o);
|
||
if (_hb.length > 10) {
|
||
this.broadcast({
|
||
sync_step: "applyHB_",
|
||
data: _hb
|
||
});
|
||
_hb = [];
|
||
}
|
||
}
|
||
return this.broadcast({
|
||
sync_step: "applyHB",
|
||
data: _hb
|
||
});
|
||
},
|
||
setStateSynced: function() {
|
||
var args, el, f, _i, _len, _ref;
|
||
if (!this.is_synced) {
|
||
this.is_synced = true;
|
||
if (this.compute_when_synced != null) {
|
||
_ref = this.compute_when_synced;
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
el = _ref[_i];
|
||
f = el[0];
|
||
args = el.slice(1);
|
||
f.apply(args);
|
||
}
|
||
delete this.compute_when_synced;
|
||
}
|
||
return null;
|
||
}
|
||
},
|
||
whenReceivedStateVector: function(f) {
|
||
if (this.when_received_state_vector_listeners == null) {
|
||
this.when_received_state_vector_listeners = [];
|
||
}
|
||
return this.when_received_state_vector_listeners.push(f);
|
||
},
|
||
receiveMessage: function(sender, res) {
|
||
var data, f, hb, o, sendApplyHB, send_again, _hb, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _results;
|
||
if (res.sync_step == null) {
|
||
_ref = this.receive_handlers;
|
||
_results = [];
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
f = _ref[_i];
|
||
_results.push(f(sender, res));
|
||
}
|
||
return _results;
|
||
} else {
|
||
if (sender === this.user_id) {
|
||
return;
|
||
}
|
||
if (res.sync_step === "getHB") {
|
||
if (this.when_received_state_vector_listeners != null) {
|
||
_ref1 = this.when_received_state_vector_listeners;
|
||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||
f = _ref1[_j];
|
||
f.call(this, res.data);
|
||
}
|
||
}
|
||
delete this.when_received_state_vector_listeners;
|
||
data = this.getHB(res.data);
|
||
hb = data.hb;
|
||
_hb = [];
|
||
if (this.is_synced) {
|
||
sendApplyHB = (function(_this) {
|
||
return function(m) {
|
||
return _this.send(sender, m);
|
||
};
|
||
})(this);
|
||
} else {
|
||
sendApplyHB = (function(_this) {
|
||
return function(m) {
|
||
return _this.broadcast(m);
|
||
};
|
||
})(this);
|
||
}
|
||
for (_k = 0, _len2 = hb.length; _k < _len2; _k++) {
|
||
o = hb[_k];
|
||
_hb.push(o);
|
||
if (_hb.length > 10) {
|
||
sendApplyHB({
|
||
sync_step: "applyHB_",
|
||
data: _hb
|
||
});
|
||
_hb = [];
|
||
}
|
||
}
|
||
sendApplyHB({
|
||
sync_step: "applyHB",
|
||
data: _hb
|
||
});
|
||
if ((res.send_again != null) && this.perform_send_again) {
|
||
send_again = (function(_this) {
|
||
return function(sv) {
|
||
return function() {
|
||
var _l, _len3;
|
||
hb = _this.getHB(sv).hb;
|
||
for (_l = 0, _len3 = hb.length; _l < _len3; _l++) {
|
||
o = hb[_l];
|
||
_hb.push(o);
|
||
if (_hb.length > 10) {
|
||
_this.send(sender, {
|
||
sync_step: "applyHB_",
|
||
data: _hb
|
||
});
|
||
_hb = [];
|
||
}
|
||
}
|
||
return _this.send(sender, {
|
||
sync_step: "applyHB",
|
||
data: _hb,
|
||
sent_again: "true"
|
||
});
|
||
};
|
||
};
|
||
})(this)(data.state_vector);
|
||
return setTimeout(send_again, 3000);
|
||
}
|
||
} else if (res.sync_step === "applyHB") {
|
||
this.applyHB(res.data, sender === this.current_sync_target);
|
||
if ((this.syncMethod === "syncAll" || (res.sent_again != null)) && (!this.is_synced) && ((this.current_sync_target === sender) || (this.current_sync_target == null))) {
|
||
this.connections[sender].is_synced = true;
|
||
return this.findNewSyncTarget();
|
||
}
|
||
} else if (res.sync_step === "applyHB_") {
|
||
return this.applyHB(res.data, sender === this.current_sync_target);
|
||
}
|
||
}
|
||
},
|
||
parseMessageFromXml: function(m) {
|
||
var parse_array, parse_object;
|
||
parse_array = function(node) {
|
||
var n, _i, _len, _ref, _results;
|
||
_ref = node.children;
|
||
_results = [];
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
n = _ref[_i];
|
||
if (n.getAttribute("isArray") === "true") {
|
||
_results.push(parse_array(n));
|
||
} else {
|
||
_results.push(parse_object(n));
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
parse_object = function(node) {
|
||
var int, json, n, name, value, _i, _len, _ref, _ref1;
|
||
json = {};
|
||
_ref = node.attrs;
|
||
for (name in _ref) {
|
||
value = _ref[name];
|
||
int = parseInt(value);
|
||
if (isNaN(int) || ("" + int) !== value) {
|
||
json[name] = value;
|
||
} else {
|
||
json[name] = int;
|
||
}
|
||
}
|
||
_ref1 = node.children;
|
||
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
|
||
n = _ref1[_i];
|
||
name = n.name;
|
||
if (n.getAttribute("isArray") === "true") {
|
||
json[name] = parse_array(n);
|
||
} else {
|
||
json[name] = parse_object(n);
|
||
}
|
||
}
|
||
return json;
|
||
};
|
||
return parse_object(m);
|
||
},
|
||
encodeMessageToXml: function(m, json) {
|
||
var encode_array, encode_object;
|
||
encode_object = function(m, json) {
|
||
var name, value;
|
||
for (name in json) {
|
||
value = json[name];
|
||
if (value == null) {
|
||
|
||
} else if (value.constructor === Object) {
|
||
encode_object(m.c(name), value);
|
||
} else if (value.constructor === Array) {
|
||
encode_array(m.c(name), value);
|
||
} else {
|
||
m.setAttribute(name, value);
|
||
}
|
||
}
|
||
return m;
|
||
};
|
||
encode_array = function(m, array) {
|
||
var e, _i, _len;
|
||
m.setAttribute("isArray", "true");
|
||
for (_i = 0, _len = array.length; _i < _len; _i++) {
|
||
e = array[_i];
|
||
if (e.constructor === Object) {
|
||
encode_object(m.c("array-element"), e);
|
||
} else {
|
||
encode_array(m.c("array-element"), e);
|
||
}
|
||
}
|
||
return m;
|
||
};
|
||
if (json.constructor === Object) {
|
||
return encode_object(m.c("y", {
|
||
xmlns: "http://y.ninja/connector-stanza"
|
||
}), json);
|
||
} else if (json.constructor === Array) {
|
||
return encode_array(m.c("y", {
|
||
xmlns: "http://y.ninja/connector-stanza"
|
||
}), json);
|
||
} else {
|
||
throw new Error("I can't encode this json!");
|
||
}
|
||
},
|
||
setIsBoundToY: function() {
|
||
if (typeof this.on_bound_to_y === "function") {
|
||
this.on_bound_to_y();
|
||
}
|
||
delete this.when_bound_to_y;
|
||
return this.is_bound_to_y = true;
|
||
}
|
||
};
|
||
|
||
|
||
},{}],6:[function(require,module,exports){
|
||
var Engine;
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
window.unprocessed_counter = 0;
|
||
}
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
window.unprocessed_exec_counter = 0;
|
||
}
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
window.unprocessed_types = [];
|
||
}
|
||
|
||
Engine = (function() {
|
||
function Engine(HB, types) {
|
||
this.HB = HB;
|
||
this.types = types;
|
||
this.unprocessed_ops = [];
|
||
}
|
||
|
||
Engine.prototype.parseOperation = function(json) {
|
||
var type;
|
||
type = this.types[json.type];
|
||
if ((type != null ? type.parse : void 0) != null) {
|
||
return type.parse(json);
|
||
} else {
|
||
throw new Error("You forgot to specify a parser for type " + json.type + ". The message is " + (JSON.stringify(json)) + ".");
|
||
}
|
||
};
|
||
|
||
|
||
/*
|
||
applyOpsBundle: (ops_json)->
|
||
ops = []
|
||
for o in ops_json
|
||
ops.push @parseOperation o
|
||
for o in ops
|
||
if not o.execute()
|
||
@unprocessed_ops.push o
|
||
@tryUnprocessed()
|
||
*/
|
||
|
||
Engine.prototype.applyOpsCheckDouble = function(ops_json) {
|
||
var o, _i, _len, _results;
|
||
_results = [];
|
||
for (_i = 0, _len = ops_json.length; _i < _len; _i++) {
|
||
o = ops_json[_i];
|
||
if (this.HB.getOperation(o.uid) == null) {
|
||
_results.push(this.applyOp(o));
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
Engine.prototype.applyOps = function(ops_json) {
|
||
return this.applyOp(ops_json);
|
||
};
|
||
|
||
Engine.prototype.applyOp = function(op_json_array, fromHB) {
|
||
var o, op_json, _i, _len;
|
||
if (fromHB == null) {
|
||
fromHB = false;
|
||
}
|
||
if (op_json_array.constructor !== Array) {
|
||
op_json_array = [op_json_array];
|
||
}
|
||
for (_i = 0, _len = op_json_array.length; _i < _len; _i++) {
|
||
op_json = op_json_array[_i];
|
||
if (fromHB) {
|
||
op_json.fromHB = "true";
|
||
}
|
||
o = this.parseOperation(op_json);
|
||
o.parsed_from_json = op_json;
|
||
if (op_json.fromHB != null) {
|
||
o.fromHB = op_json.fromHB;
|
||
}
|
||
if (this.HB.getOperation(o) != null) {
|
||
|
||
} else if (((!this.HB.isExpectedOperation(o)) && (o.fromHB == null)) || (!o.execute())) {
|
||
this.unprocessed_ops.push(o);
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
window.unprocessed_types.push(o.type);
|
||
}
|
||
}
|
||
}
|
||
return this.tryUnprocessed();
|
||
};
|
||
|
||
Engine.prototype.tryUnprocessed = function() {
|
||
var old_length, op, unprocessed, _i, _len, _ref;
|
||
while (true) {
|
||
old_length = this.unprocessed_ops.length;
|
||
unprocessed = [];
|
||
_ref = this.unprocessed_ops;
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
op = _ref[_i];
|
||
if (this.HB.getOperation(op) != null) {
|
||
|
||
} else if ((!this.HB.isExpectedOperation(op) && (op.fromHB == null)) || (!op.execute())) {
|
||
unprocessed.push(op);
|
||
}
|
||
}
|
||
this.unprocessed_ops = unprocessed;
|
||
if (this.unprocessed_ops.length === old_length) {
|
||
break;
|
||
}
|
||
}
|
||
if (this.unprocessed_ops.length !== 0) {
|
||
return this.HB.invokeSync();
|
||
}
|
||
};
|
||
|
||
return Engine;
|
||
|
||
})();
|
||
|
||
module.exports = Engine;
|
||
|
||
|
||
},{}],7:[function(require,module,exports){
|
||
var HistoryBuffer,
|
||
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||
|
||
HistoryBuffer = (function() {
|
||
function HistoryBuffer(user_id) {
|
||
this.user_id = user_id;
|
||
this.emptyGarbage = __bind(this.emptyGarbage, this);
|
||
this.operation_counter = {};
|
||
this.buffer = {};
|
||
this.change_listeners = [];
|
||
this.garbage = [];
|
||
this.trash = [];
|
||
this.performGarbageCollection = true;
|
||
this.garbageCollectTimeout = 30000;
|
||
this.reserved_identifier_counter = 0;
|
||
setTimeout(this.emptyGarbage, this.garbageCollectTimeout);
|
||
}
|
||
|
||
HistoryBuffer.prototype.setUserId = function(user_id, state_vector) {
|
||
var buff, counter_diff, o, o_name, _base, _name, _ref;
|
||
this.user_id = user_id;
|
||
if ((_base = this.buffer)[_name = this.user_id] == null) {
|
||
_base[_name] = [];
|
||
}
|
||
buff = this.buffer[this.user_id];
|
||
counter_diff = state_vector[this.user_id] || 0;
|
||
if (this.buffer._temp != null) {
|
||
_ref = this.buffer._temp;
|
||
for (o_name in _ref) {
|
||
o = _ref[o_name];
|
||
o.uid.creator = this.user_id;
|
||
o.uid.op_number += counter_diff;
|
||
buff[o.uid.op_number] = o;
|
||
}
|
||
}
|
||
this.operation_counter[this.user_id] = (this.operation_counter._temp || 0) + counter_diff;
|
||
delete this.operation_counter._temp;
|
||
return delete this.buffer._temp;
|
||
};
|
||
|
||
HistoryBuffer.prototype.emptyGarbage = function() {
|
||
var o, _i, _len, _ref;
|
||
_ref = this.garbage;
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
o = _ref[_i];
|
||
if (typeof o.cleanup === "function") {
|
||
o.cleanup();
|
||
}
|
||
}
|
||
this.garbage = this.trash;
|
||
this.trash = [];
|
||
if (this.garbageCollectTimeout !== -1) {
|
||
this.garbageCollectTimeoutId = setTimeout(this.emptyGarbage, this.garbageCollectTimeout);
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
HistoryBuffer.prototype.getUserId = function() {
|
||
return this.user_id;
|
||
};
|
||
|
||
HistoryBuffer.prototype.addToGarbageCollector = function() {
|
||
var o, _i, _len, _results;
|
||
if (this.performGarbageCollection) {
|
||
_results = [];
|
||
for (_i = 0, _len = arguments.length; _i < _len; _i++) {
|
||
o = arguments[_i];
|
||
if (o != null) {
|
||
_results.push(this.garbage.push(o));
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
}
|
||
};
|
||
|
||
HistoryBuffer.prototype.stopGarbageCollection = function() {
|
||
this.performGarbageCollection = false;
|
||
this.setManualGarbageCollect();
|
||
this.garbage = [];
|
||
return this.trash = [];
|
||
};
|
||
|
||
HistoryBuffer.prototype.setManualGarbageCollect = function() {
|
||
this.garbageCollectTimeout = -1;
|
||
clearTimeout(this.garbageCollectTimeoutId);
|
||
return this.garbageCollectTimeoutId = void 0;
|
||
};
|
||
|
||
HistoryBuffer.prototype.setGarbageCollectTimeout = function(garbageCollectTimeout) {
|
||
this.garbageCollectTimeout = garbageCollectTimeout;
|
||
};
|
||
|
||
HistoryBuffer.prototype.getReservedUniqueIdentifier = function() {
|
||
return {
|
||
creator: '_',
|
||
op_number: "_" + (this.reserved_identifier_counter++)
|
||
};
|
||
};
|
||
|
||
HistoryBuffer.prototype.getOperationCounter = function(user_id) {
|
||
var ctn, res, user, _ref;
|
||
if (user_id == null) {
|
||
res = {};
|
||
_ref = this.operation_counter;
|
||
for (user in _ref) {
|
||
ctn = _ref[user];
|
||
res[user] = ctn;
|
||
}
|
||
return res;
|
||
} else {
|
||
return this.operation_counter[user_id];
|
||
}
|
||
};
|
||
|
||
HistoryBuffer.prototype.isExpectedOperation = function(o) {
|
||
var _base, _name;
|
||
if ((_base = this.operation_counter)[_name = o.uid.creator] == null) {
|
||
_base[_name] = 0;
|
||
}
|
||
o.uid.op_number <= this.operation_counter[o.uid.creator];
|
||
return true;
|
||
};
|
||
|
||
HistoryBuffer.prototype._encode = function(state_vector) {
|
||
var json, o, o_json, o_next, o_number, o_prev, u_name, unknown, user, _ref;
|
||
if (state_vector == null) {
|
||
state_vector = {};
|
||
}
|
||
json = [];
|
||
unknown = function(user, o_number) {
|
||
if ((user == null) || (o_number == null)) {
|
||
throw new Error("dah!");
|
||
}
|
||
return (state_vector[user] == null) || state_vector[user] <= o_number;
|
||
};
|
||
_ref = this.buffer;
|
||
for (u_name in _ref) {
|
||
user = _ref[u_name];
|
||
if (u_name === "_") {
|
||
continue;
|
||
}
|
||
for (o_number in user) {
|
||
o = user[o_number];
|
||
if ((o.uid.noOperation == null) && unknown(u_name, o_number)) {
|
||
o_json = o._encode();
|
||
if (o.next_cl != null) {
|
||
o_next = o.next_cl;
|
||
while ((o_next.next_cl != null) && unknown(o_next.uid.creator, o_next.uid.op_number)) {
|
||
o_next = o_next.next_cl;
|
||
}
|
||
o_json.next = o_next.getUid();
|
||
} else if (o.prev_cl != null) {
|
||
o_prev = o.prev_cl;
|
||
while ((o_prev.prev_cl != null) && unknown(o_prev.uid.creator, o_prev.uid.op_number)) {
|
||
o_prev = o_prev.prev_cl;
|
||
}
|
||
o_json.prev = o_prev.getUid();
|
||
}
|
||
json.push(o_json);
|
||
}
|
||
}
|
||
}
|
||
return json;
|
||
};
|
||
|
||
HistoryBuffer.prototype.getNextOperationIdentifier = function(user_id) {
|
||
var uid;
|
||
if (user_id == null) {
|
||
user_id = this.user_id;
|
||
}
|
||
if (this.operation_counter[user_id] == null) {
|
||
this.operation_counter[user_id] = 0;
|
||
}
|
||
uid = {
|
||
'creator': user_id,
|
||
'op_number': this.operation_counter[user_id]
|
||
};
|
||
this.operation_counter[user_id]++;
|
||
return uid;
|
||
};
|
||
|
||
HistoryBuffer.prototype.getOperation = function(uid) {
|
||
var o, _ref;
|
||
if (uid.uid != null) {
|
||
uid = uid.uid;
|
||
}
|
||
o = (_ref = this.buffer[uid.creator]) != null ? _ref[uid.op_number] : void 0;
|
||
if ((uid.sub != null) && (o != null)) {
|
||
return o.retrieveSub(uid.sub);
|
||
} else {
|
||
return o;
|
||
}
|
||
};
|
||
|
||
HistoryBuffer.prototype.addOperation = function(o) {
|
||
if (this.buffer[o.uid.creator] == null) {
|
||
this.buffer[o.uid.creator] = {};
|
||
}
|
||
if (this.buffer[o.uid.creator][o.uid.op_number] != null) {
|
||
throw new Error("You must not overwrite operations!");
|
||
}
|
||
if ((o.uid.op_number.constructor !== String) && (!this.isExpectedOperation(o)) && (o.fromHB == null)) {
|
||
throw new Error("this operation was not expected!");
|
||
}
|
||
this.addToCounter(o);
|
||
this.buffer[o.uid.creator][o.uid.op_number] = o;
|
||
return o;
|
||
};
|
||
|
||
HistoryBuffer.prototype.removeOperation = function(o) {
|
||
var _ref;
|
||
return (_ref = this.buffer[o.uid.creator]) != null ? delete _ref[o.uid.op_number] : void 0;
|
||
};
|
||
|
||
HistoryBuffer.prototype.setInvokeSyncHandler = function(f) {
|
||
return this.invokeSync = f;
|
||
};
|
||
|
||
HistoryBuffer.prototype.invokeSync = function() {};
|
||
|
||
HistoryBuffer.prototype.renewStateVector = function(state_vector) {
|
||
var state, user, _results;
|
||
_results = [];
|
||
for (user in state_vector) {
|
||
state = state_vector[user];
|
||
if (((this.operation_counter[user] == null) || (this.operation_counter[user] < state_vector[user])) && (state_vector[user] != null)) {
|
||
_results.push(this.operation_counter[user] = state_vector[user]);
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
HistoryBuffer.prototype.addToCounter = function(o) {
|
||
var _base, _name;
|
||
if ((_base = this.operation_counter)[_name = o.uid.creator] == null) {
|
||
_base[_name] = 0;
|
||
}
|
||
if (o.uid.op_number === this.operation_counter[o.uid.creator]) {
|
||
this.operation_counter[o.uid.creator]++;
|
||
}
|
||
while (this.buffer[o.uid.creator][this.operation_counter[o.uid.creator]] != null) {
|
||
this.operation_counter[o.uid.creator]++;
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
return HistoryBuffer;
|
||
|
||
})();
|
||
|
||
module.exports = HistoryBuffer;
|
||
|
||
|
||
},{}],8:[function(require,module,exports){
|
||
var YObject;
|
||
|
||
YObject = (function() {
|
||
function YObject(_object) {
|
||
var name, val, _ref;
|
||
this._object = _object != null ? _object : {};
|
||
if (this._object.constructor === Object) {
|
||
_ref = this._object;
|
||
for (name in _ref) {
|
||
val = _ref[name];
|
||
if (val.constructor === Object) {
|
||
this._object[name] = new YObject(val);
|
||
}
|
||
}
|
||
} else {
|
||
throw new Error("Y.Object accepts Json Objects only");
|
||
}
|
||
}
|
||
|
||
YObject.prototype._name = "Object";
|
||
|
||
YObject.prototype._getModel = function(types, ops) {
|
||
var n, o, _ref;
|
||
if (this._model == null) {
|
||
this._model = new ops.MapManager(this).execute();
|
||
_ref = this._object;
|
||
for (n in _ref) {
|
||
o = _ref[n];
|
||
this._model.val(n, o);
|
||
}
|
||
}
|
||
delete this._object;
|
||
return this._model;
|
||
};
|
||
|
||
YObject.prototype._setModel = function(_model) {
|
||
this._model = _model;
|
||
return delete this._object;
|
||
};
|
||
|
||
YObject.prototype.observe = function(f) {
|
||
this._model.observe(f);
|
||
return this;
|
||
};
|
||
|
||
YObject.prototype.unobserve = function(f) {
|
||
this._model.unobserve(f);
|
||
return this;
|
||
};
|
||
|
||
YObject.prototype.val = function(name, content) {
|
||
var n, res, v, _ref;
|
||
if (this._model != null) {
|
||
return this._model.val.apply(this._model, arguments);
|
||
} else {
|
||
if (content != null) {
|
||
return this._object[name] = content;
|
||
} else if (name != null) {
|
||
return this._object[name];
|
||
} else {
|
||
res = {};
|
||
_ref = this._object;
|
||
for (n in _ref) {
|
||
v = _ref[n];
|
||
res[n] = v;
|
||
}
|
||
return res;
|
||
}
|
||
}
|
||
};
|
||
|
||
YObject.prototype["delete"] = function(name) {
|
||
this._model["delete"](name);
|
||
return this;
|
||
};
|
||
|
||
return YObject;
|
||
|
||
})();
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
if (window.Y != null) {
|
||
window.Y.Object = YObject;
|
||
} else {
|
||
throw new Error("You must first import Y!");
|
||
}
|
||
}
|
||
|
||
if (typeof module !== "undefined" && module !== null) {
|
||
module.exports = YObject;
|
||
}
|
||
|
||
|
||
},{}],9:[function(require,module,exports){
|
||
var __slice = [].slice,
|
||
__hasProp = {}.hasOwnProperty,
|
||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||
|
||
module.exports = function() {
|
||
var execution_listener, ops;
|
||
ops = {};
|
||
execution_listener = [];
|
||
ops.Operation = (function() {
|
||
function Operation(custom_type, uid, content, content_operations) {
|
||
var name, op;
|
||
if (custom_type != null) {
|
||
this.custom_type = custom_type;
|
||
}
|
||
this.is_deleted = false;
|
||
this.garbage_collected = false;
|
||
this.event_listeners = [];
|
||
if (uid != null) {
|
||
this.uid = uid;
|
||
}
|
||
if (content === void 0) {
|
||
|
||
} else if ((content != null) && (content.creator != null)) {
|
||
this.saveOperation('content', content);
|
||
} else {
|
||
this.content = content;
|
||
}
|
||
if (content_operations != null) {
|
||
this.content_operations = {};
|
||
for (name in content_operations) {
|
||
op = content_operations[name];
|
||
this.saveOperation(name, op, 'content_operations');
|
||
}
|
||
}
|
||
}
|
||
|
||
Operation.prototype.type = "Operation";
|
||
|
||
Operation.prototype.getContent = function(name) {
|
||
var content, n, v, _ref, _ref1;
|
||
if (this.content != null) {
|
||
if (this.content.getCustomType != null) {
|
||
return this.content.getCustomType();
|
||
} else if (this.content.constructor === Object) {
|
||
if (name != null) {
|
||
if (this.content[name] != null) {
|
||
return this.content[name];
|
||
} else {
|
||
return this.content_operations[name].getCustomType();
|
||
}
|
||
} else {
|
||
content = {};
|
||
_ref = this.content;
|
||
for (n in _ref) {
|
||
v = _ref[n];
|
||
content[n] = v;
|
||
}
|
||
if (this.content_operations != null) {
|
||
_ref1 = this.content_operations;
|
||
for (n in _ref1) {
|
||
v = _ref1[n];
|
||
v = v.getCustomType();
|
||
content[n] = v;
|
||
}
|
||
}
|
||
return content;
|
||
}
|
||
} else {
|
||
return this.content;
|
||
}
|
||
} else {
|
||
return this.content;
|
||
}
|
||
};
|
||
|
||
Operation.prototype.retrieveSub = function() {
|
||
throw new Error("sub properties are not enable on this operation type!");
|
||
};
|
||
|
||
Operation.prototype.observe = function(f) {
|
||
return this.event_listeners.push(f);
|
||
};
|
||
|
||
Operation.prototype.unobserve = function(f) {
|
||
return this.event_listeners = this.event_listeners.filter(function(g) {
|
||
return f !== g;
|
||
});
|
||
};
|
||
|
||
Operation.prototype.deleteAllObservers = function() {
|
||
return this.event_listeners = [];
|
||
};
|
||
|
||
Operation.prototype["delete"] = function() {
|
||
(new ops.Delete(void 0, this)).execute();
|
||
return null;
|
||
};
|
||
|
||
Operation.prototype.callEvent = function() {
|
||
var callon;
|
||
if (this.custom_type != null) {
|
||
callon = this.getCustomType();
|
||
} else {
|
||
callon = this;
|
||
}
|
||
return this.forwardEvent.apply(this, [callon].concat(__slice.call(arguments)));
|
||
};
|
||
|
||
Operation.prototype.forwardEvent = function() {
|
||
var args, f, op, _i, _len, _ref, _results;
|
||
op = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
|
||
_ref = this.event_listeners;
|
||
_results = [];
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
f = _ref[_i];
|
||
_results.push(f.call.apply(f, [op].concat(__slice.call(args))));
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
Operation.prototype.isDeleted = function() {
|
||
return this.is_deleted;
|
||
};
|
||
|
||
Operation.prototype.applyDelete = function(garbagecollect) {
|
||
if (garbagecollect == null) {
|
||
garbagecollect = true;
|
||
}
|
||
if (!this.garbage_collected) {
|
||
this.is_deleted = true;
|
||
if (garbagecollect) {
|
||
this.garbage_collected = true;
|
||
return this.HB.addToGarbageCollector(this);
|
||
}
|
||
}
|
||
};
|
||
|
||
Operation.prototype.cleanup = function() {
|
||
this.HB.removeOperation(this);
|
||
return this.deleteAllObservers();
|
||
};
|
||
|
||
Operation.prototype.setParent = function(parent) {
|
||
this.parent = parent;
|
||
};
|
||
|
||
Operation.prototype.getParent = function() {
|
||
return this.parent;
|
||
};
|
||
|
||
Operation.prototype.getUid = function() {
|
||
var map_uid;
|
||
if (this.uid.noOperation == null) {
|
||
return this.uid;
|
||
} else {
|
||
if (this.uid.alt != null) {
|
||
map_uid = this.uid.alt.cloneUid();
|
||
map_uid.sub = this.uid.sub;
|
||
return map_uid;
|
||
} else {
|
||
return void 0;
|
||
}
|
||
}
|
||
};
|
||
|
||
Operation.prototype.cloneUid = function() {
|
||
var n, uid, v, _ref;
|
||
uid = {};
|
||
_ref = this.getUid();
|
||
for (n in _ref) {
|
||
v = _ref[n];
|
||
uid[n] = v;
|
||
}
|
||
return uid;
|
||
};
|
||
|
||
Operation.prototype.execute = function() {
|
||
var l, _i, _len;
|
||
if (this.validateSavedOperations()) {
|
||
this.is_executed = true;
|
||
if (this.uid == null) {
|
||
this.uid = this.HB.getNextOperationIdentifier();
|
||
}
|
||
if (this.uid.noOperation == null) {
|
||
this.HB.addOperation(this);
|
||
for (_i = 0, _len = execution_listener.length; _i < _len; _i++) {
|
||
l = execution_listener[_i];
|
||
l(this._encode());
|
||
}
|
||
}
|
||
return this;
|
||
} else {
|
||
return false;
|
||
}
|
||
};
|
||
|
||
Operation.prototype.saveOperation = function(name, op, base) {
|
||
var dest, last_path, path, paths, _base, _i, _len;
|
||
if (base == null) {
|
||
base = "this";
|
||
}
|
||
if ((op != null) && (op._getModel != null)) {
|
||
op = op._getModel(this.custom_types, this.operations);
|
||
}
|
||
if (op == null) {
|
||
|
||
} else if ((op.execute != null) || !((op.op_number != null) && (op.creator != null))) {
|
||
if (base === "this") {
|
||
return this[name] = op;
|
||
} else {
|
||
dest = this[base];
|
||
paths = name.split("/");
|
||
last_path = paths.pop();
|
||
for (_i = 0, _len = paths.length; _i < _len; _i++) {
|
||
path = paths[_i];
|
||
dest = dest[path];
|
||
}
|
||
return dest[last_path] = op;
|
||
}
|
||
} else {
|
||
if (this.unchecked == null) {
|
||
this.unchecked = {};
|
||
}
|
||
if ((_base = this.unchecked)[base] == null) {
|
||
_base[base] = {};
|
||
}
|
||
return this.unchecked[base][name] = op;
|
||
}
|
||
};
|
||
|
||
Operation.prototype.validateSavedOperations = function() {
|
||
var base, base_name, dest, last_path, name, op, op_uid, path, paths, success, uninstantiated, _i, _len, _ref;
|
||
uninstantiated = {};
|
||
success = true;
|
||
_ref = this.unchecked;
|
||
for (base_name in _ref) {
|
||
base = _ref[base_name];
|
||
for (name in base) {
|
||
op_uid = base[name];
|
||
op = this.HB.getOperation(op_uid);
|
||
if (op) {
|
||
if (base_name === "this") {
|
||
this[name] = op;
|
||
} else {
|
||
dest = this[base_name];
|
||
paths = name.split("/");
|
||
last_path = paths.pop();
|
||
for (_i = 0, _len = paths.length; _i < _len; _i++) {
|
||
path = paths[_i];
|
||
dest = dest[path];
|
||
}
|
||
dest[last_path] = op;
|
||
}
|
||
} else {
|
||
if (uninstantiated[base_name] == null) {
|
||
uninstantiated[base_name] = {};
|
||
}
|
||
uninstantiated[base_name][name] = op_uid;
|
||
success = false;
|
||
}
|
||
}
|
||
}
|
||
if (!success) {
|
||
this.unchecked = uninstantiated;
|
||
return false;
|
||
} else {
|
||
delete this.unchecked;
|
||
return this;
|
||
}
|
||
};
|
||
|
||
Operation.prototype.getCustomType = function() {
|
||
var Type, t, _i, _len, _ref;
|
||
if (this.custom_type == null) {
|
||
return this;
|
||
} else {
|
||
if (this.custom_type.constructor === String) {
|
||
Type = this.custom_types;
|
||
_ref = this.custom_type.split(".");
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
t = _ref[_i];
|
||
Type = Type[t];
|
||
}
|
||
this.custom_type = new Type();
|
||
this.custom_type._setModel(this);
|
||
}
|
||
return this.custom_type;
|
||
}
|
||
};
|
||
|
||
Operation.prototype._encode = function(json) {
|
||
var n, o, operations, _ref, _ref1;
|
||
if (json == null) {
|
||
json = {};
|
||
}
|
||
json.type = this.type;
|
||
json.uid = this.getUid();
|
||
if (this.custom_type != null) {
|
||
if (this.custom_type.constructor === String) {
|
||
json.custom_type = this.custom_type;
|
||
} else {
|
||
json.custom_type = this.custom_type._name;
|
||
}
|
||
}
|
||
if (((_ref = this.content) != null ? _ref.getUid : void 0) != null) {
|
||
json.content = this.content.getUid();
|
||
} else {
|
||
json.content = this.content;
|
||
}
|
||
if (this.content_operations != null) {
|
||
operations = {};
|
||
_ref1 = this.content_operations;
|
||
for (n in _ref1) {
|
||
o = _ref1[n];
|
||
if (o._getModel != null) {
|
||
o = o._getModel(this.custom_types, this.operations);
|
||
}
|
||
operations[n] = o.getUid();
|
||
}
|
||
json.content_operations = operations;
|
||
}
|
||
return json;
|
||
};
|
||
|
||
return Operation;
|
||
|
||
})();
|
||
ops.Delete = (function(_super) {
|
||
__extends(Delete, _super);
|
||
|
||
function Delete(custom_type, uid, deletes) {
|
||
this.saveOperation('deletes', deletes);
|
||
Delete.__super__.constructor.call(this, custom_type, uid);
|
||
}
|
||
|
||
Delete.prototype.type = "Delete";
|
||
|
||
Delete.prototype._encode = function() {
|
||
return {
|
||
'type': "Delete",
|
||
'uid': this.getUid(),
|
||
'deletes': this.deletes.getUid()
|
||
};
|
||
};
|
||
|
||
Delete.prototype.execute = function() {
|
||
var res;
|
||
if (this.validateSavedOperations()) {
|
||
res = Delete.__super__.execute.apply(this, arguments);
|
||
if (res) {
|
||
this.deletes.applyDelete(this);
|
||
}
|
||
return res;
|
||
} else {
|
||
return false;
|
||
}
|
||
};
|
||
|
||
return Delete;
|
||
|
||
})(ops.Operation);
|
||
ops.Delete.parse = function(o) {
|
||
var deletes_uid, uid;
|
||
uid = o['uid'], deletes_uid = o['deletes'];
|
||
return new this(null, uid, deletes_uid);
|
||
};
|
||
ops.Insert = (function(_super) {
|
||
__extends(Insert, _super);
|
||
|
||
function Insert(custom_type, content, content_operations, parent, uid, prev_cl, next_cl, origin) {
|
||
this.saveOperation('parent', parent);
|
||
this.saveOperation('prev_cl', prev_cl);
|
||
this.saveOperation('next_cl', next_cl);
|
||
if (origin != null) {
|
||
this.saveOperation('origin', origin);
|
||
} else {
|
||
this.saveOperation('origin', prev_cl);
|
||
}
|
||
Insert.__super__.constructor.call(this, custom_type, uid, content, content_operations);
|
||
}
|
||
|
||
Insert.prototype.type = "Insert";
|
||
|
||
Insert.prototype.val = function() {
|
||
return this.getContent();
|
||
};
|
||
|
||
Insert.prototype.getNext = function(i) {
|
||
var n;
|
||
if (i == null) {
|
||
i = 1;
|
||
}
|
||
n = this;
|
||
while (i > 0 && (n.next_cl != null)) {
|
||
n = n.next_cl;
|
||
if (!n.is_deleted) {
|
||
i--;
|
||
}
|
||
}
|
||
if (n.is_deleted) {
|
||
null;
|
||
}
|
||
return n;
|
||
};
|
||
|
||
Insert.prototype.getPrev = function(i) {
|
||
var n;
|
||
if (i == null) {
|
||
i = 1;
|
||
}
|
||
n = this;
|
||
while (i > 0 && (n.prev_cl != null)) {
|
||
n = n.prev_cl;
|
||
if (!n.is_deleted) {
|
||
i--;
|
||
}
|
||
}
|
||
if (n.is_deleted) {
|
||
return null;
|
||
} else {
|
||
return n;
|
||
}
|
||
};
|
||
|
||
Insert.prototype.applyDelete = function(o) {
|
||
var callLater, garbagecollect;
|
||
if (this.deleted_by == null) {
|
||
this.deleted_by = [];
|
||
}
|
||
callLater = false;
|
||
if ((this.parent != null) && !this.is_deleted && (o != null)) {
|
||
callLater = true;
|
||
}
|
||
if (o != null) {
|
||
this.deleted_by.push(o);
|
||
}
|
||
garbagecollect = false;
|
||
if (this.next_cl.isDeleted()) {
|
||
garbagecollect = true;
|
||
}
|
||
Insert.__super__.applyDelete.call(this, garbagecollect);
|
||
if (callLater) {
|
||
this.parent.callOperationSpecificDeleteEvents(this, o);
|
||
}
|
||
if ((this.prev_cl != null) && this.prev_cl.isDeleted() && this.prev_cl.garbage_collected !== true) {
|
||
return this.prev_cl.applyDelete();
|
||
}
|
||
};
|
||
|
||
Insert.prototype.cleanup = function() {
|
||
var d, o, _i, _len, _ref;
|
||
if (this.next_cl.isDeleted()) {
|
||
_ref = this.deleted_by;
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
d = _ref[_i];
|
||
d.cleanup();
|
||
}
|
||
o = this.next_cl;
|
||
while (o.type !== "Delimiter") {
|
||
if (o.origin === this) {
|
||
o.origin = this.prev_cl;
|
||
}
|
||
o = o.next_cl;
|
||
}
|
||
this.prev_cl.next_cl = this.next_cl;
|
||
this.next_cl.prev_cl = this.prev_cl;
|
||
if (this.content instanceof ops.Operation && !(this.content instanceof ops.Insert)) {
|
||
this.content.referenced_by--;
|
||
if (this.content.referenced_by <= 0 && !this.content.is_deleted) {
|
||
this.content.applyDelete();
|
||
}
|
||
}
|
||
delete this.content;
|
||
return Insert.__super__.cleanup.apply(this, arguments);
|
||
}
|
||
};
|
||
|
||
Insert.prototype.getDistanceToOrigin = function() {
|
||
var d, o;
|
||
d = 0;
|
||
o = this.prev_cl;
|
||
while (true) {
|
||
if (this.origin === o) {
|
||
break;
|
||
}
|
||
d++;
|
||
o = o.prev_cl;
|
||
}
|
||
return d;
|
||
};
|
||
|
||
Insert.prototype.execute = function() {
|
||
var distance_to_origin, i, o, oDistance, _base;
|
||
if (!this.validateSavedOperations()) {
|
||
return false;
|
||
} else {
|
||
if (this.content instanceof ops.Operation) {
|
||
this.content.insert_parent = this;
|
||
if ((_base = this.content).referenced_by == null) {
|
||
_base.referenced_by = 0;
|
||
}
|
||
this.content.referenced_by++;
|
||
}
|
||
if (this.parent != null) {
|
||
if (this.prev_cl == null) {
|
||
this.prev_cl = this.parent.beginning;
|
||
}
|
||
if (this.origin == null) {
|
||
this.origin = this.prev_cl;
|
||
} else if (this.origin === "Delimiter") {
|
||
this.origin = this.parent.beginning;
|
||
}
|
||
if (this.next_cl == null) {
|
||
this.next_cl = this.parent.end;
|
||
}
|
||
}
|
||
if (this.prev_cl != null) {
|
||
distance_to_origin = this.getDistanceToOrigin();
|
||
o = this.prev_cl.next_cl;
|
||
i = distance_to_origin;
|
||
while (true) {
|
||
if (o !== this.next_cl) {
|
||
oDistance = o.getDistanceToOrigin();
|
||
if (oDistance === i) {
|
||
if (o.uid.creator < this.uid.creator) {
|
||
this.prev_cl = o;
|
||
distance_to_origin = i + 1;
|
||
} else {
|
||
|
||
}
|
||
} else if (oDistance < i) {
|
||
if (i - distance_to_origin <= oDistance) {
|
||
this.prev_cl = o;
|
||
distance_to_origin = i + 1;
|
||
} else {
|
||
|
||
}
|
||
} else {
|
||
break;
|
||
}
|
||
i++;
|
||
o = o.next_cl;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
this.next_cl = this.prev_cl.next_cl;
|
||
this.prev_cl.next_cl = this;
|
||
this.next_cl.prev_cl = this;
|
||
}
|
||
this.setParent(this.prev_cl.getParent());
|
||
Insert.__super__.execute.apply(this, arguments);
|
||
this.parent.callOperationSpecificInsertEvents(this);
|
||
return this;
|
||
}
|
||
};
|
||
|
||
Insert.prototype.getPosition = function() {
|
||
var position, prev;
|
||
position = 0;
|
||
prev = this.prev_cl;
|
||
while (true) {
|
||
if (prev instanceof ops.Delimiter) {
|
||
break;
|
||
}
|
||
if (!prev.isDeleted()) {
|
||
position++;
|
||
}
|
||
prev = prev.prev_cl;
|
||
}
|
||
return position;
|
||
};
|
||
|
||
Insert.prototype._encode = function(json) {
|
||
if (json == null) {
|
||
json = {};
|
||
}
|
||
json.prev = this.prev_cl.getUid();
|
||
json.next = this.next_cl.getUid();
|
||
if (this.origin.type === "Delimiter") {
|
||
json.origin = "Delimiter";
|
||
} else if (this.origin !== this.prev_cl) {
|
||
json.origin = this.origin.getUid();
|
||
}
|
||
json.parent = this.parent.getUid();
|
||
return Insert.__super__._encode.call(this, json);
|
||
};
|
||
|
||
return Insert;
|
||
|
||
})(ops.Operation);
|
||
ops.Insert.parse = function(json) {
|
||
var content, content_operations, next, origin, parent, prev, uid;
|
||
content = json['content'], content_operations = json['content_operations'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], parent = json['parent'];
|
||
return new this(null, content, content_operations, parent, uid, prev, next, origin);
|
||
};
|
||
ops.Delimiter = (function(_super) {
|
||
__extends(Delimiter, _super);
|
||
|
||
function Delimiter(prev_cl, next_cl, origin) {
|
||
this.saveOperation('prev_cl', prev_cl);
|
||
this.saveOperation('next_cl', next_cl);
|
||
this.saveOperation('origin', prev_cl);
|
||
Delimiter.__super__.constructor.call(this, null, {
|
||
noOperation: true
|
||
});
|
||
}
|
||
|
||
Delimiter.prototype.type = "Delimiter";
|
||
|
||
Delimiter.prototype.applyDelete = function() {
|
||
var o;
|
||
Delimiter.__super__.applyDelete.call(this);
|
||
o = this.prev_cl;
|
||
while (o != null) {
|
||
o.applyDelete();
|
||
o = o.prev_cl;
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
Delimiter.prototype.cleanup = function() {
|
||
return Delimiter.__super__.cleanup.call(this);
|
||
};
|
||
|
||
Delimiter.prototype.execute = function() {
|
||
var _ref, _ref1;
|
||
if (((_ref = this.unchecked) != null ? _ref['next_cl'] : void 0) != null) {
|
||
return Delimiter.__super__.execute.apply(this, arguments);
|
||
} else if ((_ref1 = this.unchecked) != null ? _ref1['prev_cl'] : void 0) {
|
||
if (this.validateSavedOperations()) {
|
||
if (this.prev_cl.next_cl != null) {
|
||
throw new Error("Probably duplicated operations");
|
||
}
|
||
this.prev_cl.next_cl = this;
|
||
return Delimiter.__super__.execute.apply(this, arguments);
|
||
} else {
|
||
return false;
|
||
}
|
||
} else if ((this.prev_cl != null) && (this.prev_cl.next_cl == null)) {
|
||
delete this.prev_cl.unchecked.next_cl;
|
||
this.prev_cl.next_cl = this;
|
||
return Delimiter.__super__.execute.apply(this, arguments);
|
||
} else if ((this.prev_cl != null) || (this.next_cl != null) || true) {
|
||
return Delimiter.__super__.execute.apply(this, arguments);
|
||
}
|
||
};
|
||
|
||
Delimiter.prototype._encode = function() {
|
||
var _ref, _ref1;
|
||
return {
|
||
'type': this.type,
|
||
'uid': this.getUid(),
|
||
'prev': (_ref = this.prev_cl) != null ? _ref.getUid() : void 0,
|
||
'next': (_ref1 = this.next_cl) != null ? _ref1.getUid() : void 0
|
||
};
|
||
};
|
||
|
||
return Delimiter;
|
||
|
||
})(ops.Operation);
|
||
ops.Delimiter.parse = function(json) {
|
||
var next, prev, uid;
|
||
uid = json['uid'], prev = json['prev'], next = json['next'];
|
||
return new this(uid, prev, next);
|
||
};
|
||
return {
|
||
'operations': ops,
|
||
'execution_listener': execution_listener
|
||
};
|
||
};
|
||
|
||
|
||
},{}],10:[function(require,module,exports){
|
||
var RBTReeByIndex, basic_ops_uninitialized,
|
||
__hasProp = {}.hasOwnProperty,
|
||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||
|
||
basic_ops_uninitialized = require("./Basic");
|
||
|
||
RBTReeByIndex = require('bintrees/lib/rbtree_by_index');
|
||
|
||
module.exports = function() {
|
||
var basic_ops, ops;
|
||
basic_ops = basic_ops_uninitialized();
|
||
ops = basic_ops.operations;
|
||
ops.MapManager = (function(_super) {
|
||
__extends(MapManager, _super);
|
||
|
||
function MapManager(custom_type, uid, content, content_operations) {
|
||
this._map = {};
|
||
MapManager.__super__.constructor.call(this, custom_type, uid, content, content_operations);
|
||
}
|
||
|
||
MapManager.prototype.type = "MapManager";
|
||
|
||
MapManager.prototype.applyDelete = function() {
|
||
var name, p, _ref;
|
||
_ref = this._map;
|
||
for (name in _ref) {
|
||
p = _ref[name];
|
||
p.applyDelete();
|
||
}
|
||
return MapManager.__super__.applyDelete.call(this);
|
||
};
|
||
|
||
MapManager.prototype.cleanup = function() {
|
||
return MapManager.__super__.cleanup.call(this);
|
||
};
|
||
|
||
MapManager.prototype.map = function(f) {
|
||
var n, v, _ref;
|
||
_ref = this._map;
|
||
for (n in _ref) {
|
||
v = _ref[n];
|
||
f(n, v);
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
MapManager.prototype.val = function(name, content) {
|
||
var o, prop, rep, res, result, _ref;
|
||
if (arguments.length > 1) {
|
||
if ((content != null) && (content._getModel != null)) {
|
||
rep = content._getModel(this.custom_types, this.operations);
|
||
} else {
|
||
rep = content;
|
||
}
|
||
this.retrieveSub(name).replace(rep);
|
||
return this.getCustomType();
|
||
} else if (name != null) {
|
||
prop = this._map[name];
|
||
if ((prop != null) && !prop.isContentDeleted()) {
|
||
res = prop.val();
|
||
if (res instanceof ops.Operation) {
|
||
return res.getCustomType();
|
||
} else {
|
||
return res;
|
||
}
|
||
} else {
|
||
return void 0;
|
||
}
|
||
} else {
|
||
result = {};
|
||
_ref = this._map;
|
||
for (name in _ref) {
|
||
o = _ref[name];
|
||
if (!o.isContentDeleted()) {
|
||
result[name] = o.val();
|
||
}
|
||
}
|
||
return result;
|
||
}
|
||
};
|
||
|
||
MapManager.prototype["delete"] = function(name) {
|
||
var _ref;
|
||
if ((_ref = this._map[name]) != null) {
|
||
_ref.deleteContent();
|
||
}
|
||
return this;
|
||
};
|
||
|
||
MapManager.prototype.retrieveSub = function(property_name) {
|
||
var event_properties, event_this, rm, rm_uid;
|
||
if (this._map[property_name] == null) {
|
||
event_properties = {
|
||
name: property_name
|
||
};
|
||
event_this = this;
|
||
rm_uid = {
|
||
noOperation: true,
|
||
sub: property_name,
|
||
alt: this
|
||
};
|
||
rm = new ops.ReplaceManager(null, event_properties, event_this, rm_uid);
|
||
this._map[property_name] = rm;
|
||
rm.setParent(this, property_name);
|
||
rm.execute();
|
||
}
|
||
return this._map[property_name];
|
||
};
|
||
|
||
return MapManager;
|
||
|
||
})(ops.Operation);
|
||
ops.MapManager.parse = function(json) {
|
||
var content, content_operations, custom_type, uid;
|
||
uid = json['uid'], custom_type = json['custom_type'], content = json['content'], content_operations = json['content_operations'];
|
||
return new this(custom_type, uid, content, content_operations);
|
||
};
|
||
ops.ListManager = (function(_super) {
|
||
__extends(ListManager, _super);
|
||
|
||
function ListManager(custom_type, uid, content, content_operations) {
|
||
this.beginning = new ops.Delimiter(void 0, void 0);
|
||
this.end = new ops.Delimiter(this.beginning, void 0);
|
||
this.beginning.next_cl = this.end;
|
||
this.beginning.execute();
|
||
this.end.execute();
|
||
this.shortTree = new RBTreeByIndex();
|
||
this.completeTree = new RBTreeByIndex();
|
||
ListManager.__super__.constructor.call(this, custom_type, uid, content, content_operations);
|
||
}
|
||
|
||
ListManager.prototype.type = "ListManager";
|
||
|
||
ListManager.prototype.applyDelete = function() {
|
||
var o;
|
||
o = this.beginning;
|
||
while (o != null) {
|
||
o.applyDelete();
|
||
o = o.next_cl;
|
||
}
|
||
return ListManager.__super__.applyDelete.call(this);
|
||
};
|
||
|
||
ListManager.prototype.cleanup = function() {
|
||
return ListManager.__super__.cleanup.call(this);
|
||
};
|
||
|
||
ListManager.prototype.toJson = function(transform_to_value) {
|
||
var i, o, val, _i, _len, _results;
|
||
if (transform_to_value == null) {
|
||
transform_to_value = false;
|
||
}
|
||
val = this.val();
|
||
_results = [];
|
||
for (o = _i = 0, _len = val.length; _i < _len; o = ++_i) {
|
||
i = val[o];
|
||
if (o instanceof ops.Object) {
|
||
_results.push(o.toJson(transform_to_value));
|
||
} else if (o instanceof ops.ListManager) {
|
||
_results.push(o.toJson(transform_to_value));
|
||
} else if (transform_to_value && o instanceof ops.Operation) {
|
||
_results.push(o.val());
|
||
} else {
|
||
_results.push(o);
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
ListManager.prototype.execute = function() {
|
||
if (this.validateSavedOperations()) {
|
||
this.beginning.setParent(this);
|
||
this.end.setParent(this);
|
||
return ListManager.__super__.execute.apply(this, arguments);
|
||
} else {
|
||
return false;
|
||
}
|
||
};
|
||
|
||
ListManager.prototype.getLastOperation = function() {
|
||
return this.end.prev_cl;
|
||
};
|
||
|
||
ListManager.prototype.getFirstOperation = function() {
|
||
return this.beginning.next_cl;
|
||
};
|
||
|
||
ListManager.prototype.getNextNonDeleted = function(start) {
|
||
var operation;
|
||
if (start.isDeleted() || (start.node == null)) {
|
||
operation = start.next_cl;
|
||
while (!(operation instanceof ops.Delimiter)) {
|
||
if (operation.is_deleted) {
|
||
operation = operation.next_cl;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
operation = start.node.next.node;
|
||
if (!operation) {
|
||
return false;
|
||
}
|
||
}
|
||
return operation;
|
||
};
|
||
|
||
ListManager.prototype.getPrevNonDeleted = function(start) {
|
||
var operation;
|
||
if (start.isDeleted() || (start.node == null)) {
|
||
operation = start.prev_cl;
|
||
while (!(operation instanceof ops.Delimiter)) {
|
||
if (operation.is_deleted) {
|
||
operation = operation.prev_cl;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
operation = start.node.prev.node;
|
||
if (!operation) {
|
||
return false;
|
||
}
|
||
}
|
||
return operation;
|
||
};
|
||
|
||
ListManager.prototype.toArray = function() {
|
||
return this.shortTree.map(function(operation) {
|
||
return operation.val();
|
||
});
|
||
};
|
||
|
||
ListManager.prototype.map = function(fun) {
|
||
return this.shortTree.map(fun);
|
||
};
|
||
|
||
ListManager.prototype.fold = function(init, fun) {
|
||
return this.shortTree.map(function(operation) {
|
||
return init = fun(init, operation);
|
||
});
|
||
};
|
||
|
||
ListManager.prototype.val = function(pos) {
|
||
if (pos != null) {
|
||
return this.shortTree.find(pos).val();
|
||
} else {
|
||
return this.toArray();
|
||
}
|
||
};
|
||
|
||
ListManager.prototype.ref = function(pos) {
|
||
if (pos != null) {
|
||
return this.shortTree.find(pos);
|
||
} else {
|
||
return this.shortTree.map(function(operation) {
|
||
return operation;
|
||
});
|
||
}
|
||
};
|
||
|
||
ListManager.prototype.getOperationByPosition = function(position) {
|
||
if (position === 0) {
|
||
return this.beginning;
|
||
} else if (position === this.shortTree.size + 1) {
|
||
return this.end;
|
||
} else {
|
||
return this.shortTree.find(position - 1);
|
||
}
|
||
};
|
||
|
||
ListManager.prototype.push = function(content) {
|
||
return this.insertAfter(this.end.prev_cl, [content]);
|
||
};
|
||
|
||
ListManager.prototype.insertAfterHelper = function(root, content) {
|
||
var right;
|
||
if (!root.right) {
|
||
root.bt.right = content;
|
||
return content.bt.parent = root;
|
||
} else {
|
||
return right = root.next_cl;
|
||
}
|
||
};
|
||
|
||
ListManager.prototype.insertAfter = function(left, contents) {
|
||
var c, leftNode, right, rightNode, tmp, _i, _len;
|
||
if (left === this.beginning) {
|
||
leftNode = null;
|
||
rightNode = this.shortTree.findNode(0);
|
||
right = rightNode ? rightNode.data : this.end;
|
||
} else {
|
||
rightNode = left.node.next;
|
||
leftNode = left.node;
|
||
right = rightNode ? rightNode.data : this.end;
|
||
}
|
||
left = right.prev_cl;
|
||
if (contents instanceof ops.Operation) {
|
||
tmp = new ops.Insert(null, content, null, void 0, void 0, left, right);
|
||
tmp.execute();
|
||
} else {
|
||
for (_i = 0, _len = contents.length; _i < _len; _i++) {
|
||
c = contents[_i];
|
||
if ((c != null) && (c._name != null) && (c._getModel != null)) {
|
||
c = c._getModel(this.custom_types, this.operations);
|
||
}
|
||
tmp = new ops.Insert(null, c, null, void 0, void 0, left, right);
|
||
tmp.execute();
|
||
leftNode = tmp.node;
|
||
left = tmp;
|
||
}
|
||
}
|
||
return this;
|
||
};
|
||
|
||
ListManager.prototype.insert = function(position, contents) {
|
||
var ith;
|
||
ith = this.getOperationByPosition(position);
|
||
return this.insertAfter(ith, contents);
|
||
};
|
||
|
||
ListManager.prototype.deleteRef = function(operation, length, dir) {
|
||
var deleteOperation, i, nextOperation, _i;
|
||
if (length == null) {
|
||
length = 1;
|
||
}
|
||
if (dir == null) {
|
||
dir = 'right';
|
||
}
|
||
nextOperation = (function(_this) {
|
||
return function(operation) {
|
||
if (dir === 'right') {
|
||
return _this.getNextNonDeleted(operation);
|
||
} else {
|
||
return _this.getPrevNonDeleted(operation);
|
||
}
|
||
};
|
||
})(this);
|
||
for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) {
|
||
if (operation instanceof ops.Delimiter) {
|
||
break;
|
||
}
|
||
deleteOperation = (new ops.Delete(null, void 0, operation)).execute();
|
||
operation = nextOperation(operation);
|
||
}
|
||
return this;
|
||
};
|
||
|
||
ListManager.prototype["delete"] = function(position, length) {
|
||
var operation;
|
||
if (length == null) {
|
||
length = 1;
|
||
}
|
||
operation = this.getOperationByPosition(position + length);
|
||
return this.deleteRef(operation, length, 'left');
|
||
};
|
||
|
||
ListManager.prototype.callOperationSpecificInsertEvents = function(operation) {
|
||
var getContentType, next, nextNode, prev, prevNode;
|
||
prev = (this.getPrevNonDeleted(operation)) || this.beginning;
|
||
prevNode = prev ? prev.node : null;
|
||
next = (this.getNextNonDeleted(operation)) || this.end;
|
||
nextNode = next ? next.node : null;
|
||
operation.node = operation.node || (this.shortTree.insert_between(prevNode, nextNode, operation));
|
||
operation.completeNode = operation.completeNode || (this.completeTree.insert_between(operation.prev_cl.completeNode, operation.next_cl.completeNode, operation));
|
||
getContentType = function(content) {
|
||
if (content instanceof ops.Operation) {
|
||
return content.getCustomType();
|
||
} else {
|
||
return content;
|
||
}
|
||
};
|
||
return this.callEvent([
|
||
{
|
||
type: "insert",
|
||
reference: operation,
|
||
position: operation.node.position(),
|
||
object: this.getCustomType(),
|
||
changedBy: operation.uid.creator,
|
||
value: getContentType(operation.val())
|
||
}
|
||
]);
|
||
};
|
||
|
||
ListManager.prototype.callOperationSpecificDeleteEvents = function(operation, del_op) {
|
||
var position;
|
||
if (operation.node) {
|
||
position = operation.node.position();
|
||
this.shortTree.remove_node(operation.node);
|
||
operation.node = null;
|
||
}
|
||
return this.callEvent([
|
||
{
|
||
type: "delete",
|
||
reference: operation,
|
||
position: position,
|
||
object: this.getCustomType(),
|
||
length: 1,
|
||
changedBy: del_op.uid.creator,
|
||
oldValue: operation.val()
|
||
}
|
||
]);
|
||
};
|
||
|
||
return ListManager;
|
||
|
||
})(ops.Operation);
|
||
ops.ListManager.parse = function(json) {
|
||
var content, content_operations, custom_type, uid;
|
||
uid = json['uid'], custom_type = json['custom_type'], content = json['content'], content_operations = json['content_operations'];
|
||
return new this(custom_type, uid, content, content_operations);
|
||
};
|
||
ops.Composition = (function(_super) {
|
||
__extends(Composition, _super);
|
||
|
||
function Composition(custom_type, _composition_value, composition_value_operations, uid, tmp_composition_ref) {
|
||
var n, o;
|
||
this._composition_value = _composition_value;
|
||
Composition.__super__.constructor.call(this, custom_type, uid);
|
||
if (tmp_composition_ref != null) {
|
||
this.tmp_composition_ref = tmp_composition_ref;
|
||
} else {
|
||
this.composition_ref = this.end.prev_cl;
|
||
}
|
||
if (composition_value_operations != null) {
|
||
this.composition_value_operations = {};
|
||
for (n in composition_value_operations) {
|
||
o = composition_value_operations[n];
|
||
this.saveOperation(n, o, '_composition_value');
|
||
}
|
||
}
|
||
}
|
||
|
||
Composition.prototype.type = "Composition";
|
||
|
||
Composition.prototype.execute = function() {
|
||
var composition_ref;
|
||
if (this.validateSavedOperations()) {
|
||
this.getCustomType()._setCompositionValue(this._composition_value);
|
||
delete this._composition_value;
|
||
if (this.tmp_composition_ref) {
|
||
composition_ref = this.HB.getOperation(this.tmp_composition_ref);
|
||
if (composition_ref != null) {
|
||
delete this.tmp_composition_ref;
|
||
this.composition_ref = composition_ref;
|
||
}
|
||
}
|
||
return Composition.__super__.execute.apply(this, arguments);
|
||
} else {
|
||
return false;
|
||
}
|
||
};
|
||
|
||
Composition.prototype.callOperationSpecificInsertEvents = function(operation) {
|
||
var o;
|
||
if (this.tmp_composition_ref != null) {
|
||
if (operation.uid.creator === this.tmp_composition_ref.creator && operation.uid.op_number === this.tmp_composition_ref.op_number) {
|
||
this.composition_ref = operation;
|
||
delete this.tmp_composition_ref;
|
||
operation = operation.next_cl;
|
||
if (operation === this.end) {
|
||
return;
|
||
}
|
||
} else {
|
||
return;
|
||
}
|
||
}
|
||
o = this.end.prev_cl;
|
||
while (o !== operation) {
|
||
this.getCustomType()._unapply(o.undo_delta);
|
||
o = o.prev_cl;
|
||
}
|
||
while (o !== this.end) {
|
||
o.undo_delta = this.getCustomType()._apply(o.val());
|
||
o = o.next_cl;
|
||
}
|
||
this.composition_ref = this.end.prev_cl;
|
||
return this.callEvent([
|
||
{
|
||
type: "update",
|
||
changedBy: operation.uid.creator,
|
||
newValue: this.val()
|
||
}
|
||
]);
|
||
};
|
||
|
||
Composition.prototype.callOperationSpecificDeleteEvents = function(operation, del_op) {};
|
||
|
||
Composition.prototype.applyDelta = function(delta, operations) {
|
||
(new ops.Insert(null, delta, operations, this, null, this.end.prev_cl, this.end)).execute();
|
||
return void 0;
|
||
};
|
||
|
||
Composition.prototype._encode = function(json) {
|
||
var custom, n, o, _ref;
|
||
if (json == null) {
|
||
json = {};
|
||
}
|
||
custom = this.getCustomType()._getCompositionValue();
|
||
json.composition_value = custom.composition_value;
|
||
if (custom.composition_value_operations != null) {
|
||
json.composition_value_operations = {};
|
||
_ref = custom.composition_value_operations;
|
||
for (n in _ref) {
|
||
o = _ref[n];
|
||
json.composition_value_operations[n] = o.getUid();
|
||
}
|
||
}
|
||
if (this.composition_ref != null) {
|
||
json.composition_ref = this.composition_ref.getUid();
|
||
} else {
|
||
json.composition_ref = this.tmp_composition_ref;
|
||
}
|
||
return Composition.__super__._encode.call(this, json);
|
||
};
|
||
|
||
return Composition;
|
||
|
||
})(ops.ListManager);
|
||
ops.Composition.parse = function(json) {
|
||
var composition_ref, composition_value, composition_value_operations, custom_type, uid;
|
||
uid = json['uid'], custom_type = json['custom_type'], composition_value = json['composition_value'], composition_value_operations = json['composition_value_operations'], composition_ref = json['composition_ref'];
|
||
return new this(custom_type, composition_value, composition_value_operations, uid, composition_ref);
|
||
};
|
||
ops.ReplaceManager = (function(_super) {
|
||
__extends(ReplaceManager, _super);
|
||
|
||
function ReplaceManager(custom_type, event_properties, event_this, uid) {
|
||
this.event_properties = event_properties;
|
||
this.event_this = event_this;
|
||
if (this.event_properties['object'] == null) {
|
||
this.event_properties['object'] = this.event_this.getCustomType();
|
||
}
|
||
ReplaceManager.__super__.constructor.call(this, custom_type, uid);
|
||
}
|
||
|
||
ReplaceManager.prototype.type = "ReplaceManager";
|
||
|
||
ReplaceManager.prototype.callEventDecorator = function(events) {
|
||
var event, name, prop, _i, _len, _ref;
|
||
if (!this.isDeleted()) {
|
||
for (_i = 0, _len = events.length; _i < _len; _i++) {
|
||
event = events[_i];
|
||
_ref = this.event_properties;
|
||
for (name in _ref) {
|
||
prop = _ref[name];
|
||
event[name] = prop;
|
||
}
|
||
}
|
||
this.event_this.callEvent(events);
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
ReplaceManager.prototype.callOperationSpecificInsertEvents = function(operation) {
|
||
var old_value;
|
||
if (operation.next_cl.type === "Delimiter" && operation.prev_cl.type !== "Delimiter") {
|
||
if (!operation.is_deleted) {
|
||
old_value = operation.prev_cl.val();
|
||
this.callEventDecorator([
|
||
{
|
||
type: "update",
|
||
changedBy: operation.uid.creator,
|
||
oldValue: old_value
|
||
}
|
||
]);
|
||
}
|
||
operation.prev_cl.applyDelete();
|
||
} else if (operation.next_cl.type !== "Delimiter") {
|
||
operation.applyDelete();
|
||
} else {
|
||
this.callEventDecorator([
|
||
{
|
||
type: "add",
|
||
changedBy: operation.uid.creator
|
||
}
|
||
]);
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
ReplaceManager.prototype.callOperationSpecificDeleteEvents = function(operation, del_op) {
|
||
if (operation.next_cl.type === "Delimiter") {
|
||
return this.callEventDecorator([
|
||
{
|
||
type: "delete",
|
||
changedBy: del_op.uid.creator,
|
||
oldValue: operation.val()
|
||
}
|
||
]);
|
||
}
|
||
};
|
||
|
||
ReplaceManager.prototype.replace = function(content, replaceable_uid) {
|
||
var o, relp;
|
||
o = this.getLastOperation();
|
||
relp = (new ops.Insert(null, content, null, this, replaceable_uid, o, o.next_cl)).execute();
|
||
return void 0;
|
||
};
|
||
|
||
ReplaceManager.prototype.isContentDeleted = function() {
|
||
return this.getLastOperation().isDeleted();
|
||
};
|
||
|
||
ReplaceManager.prototype.deleteContent = function() {
|
||
var last_op;
|
||
last_op = this.getLastOperation();
|
||
if ((!last_op.isDeleted()) && last_op.type !== "Delimiter") {
|
||
(new ops.Delete(null, void 0, this.getLastOperation().uid)).execute();
|
||
}
|
||
return void 0;
|
||
};
|
||
|
||
ReplaceManager.prototype.val = function() {
|
||
var o;
|
||
o = this.getLastOperation();
|
||
return typeof o.val === "function" ? o.val() : void 0;
|
||
};
|
||
|
||
return ReplaceManager;
|
||
|
||
})(ops.ListManager);
|
||
return basic_ops;
|
||
};
|
||
|
||
|
||
},{"./Basic":9,"bintrees/lib/rbtree_by_index":12}],11:[function(require,module,exports){
|
||
var Engine, HistoryBuffer, adaptConnector, createY, structured_ops_uninitialized;
|
||
|
||
structured_ops_uninitialized = require("./Operations/Structured");
|
||
|
||
HistoryBuffer = require("./HistoryBuffer");
|
||
|
||
Engine = require("./Engine");
|
||
|
||
adaptConnector = require("./ConnectorAdapter");
|
||
|
||
createY = function(connector) {
|
||
var HB, ct, engine, model, ops, ops_manager, user_id;
|
||
if (connector.user_id != null) {
|
||
user_id = connector.user_id;
|
||
} else {
|
||
user_id = "_temp";
|
||
connector.when_received_state_vector_listeners = [
|
||
function(state_vector) {
|
||
return HB.setUserId(this.user_id, state_vector);
|
||
}
|
||
];
|
||
}
|
||
HB = new HistoryBuffer(user_id);
|
||
ops_manager = structured_ops_uninitialized(HB, this.constructor);
|
||
ops = ops_manager.operations;
|
||
engine = new Engine(HB, ops);
|
||
adaptConnector(connector, engine, HB, ops_manager.execution_listener);
|
||
ops.Operation.prototype.HB = HB;
|
||
ops.Operation.prototype.operations = ops;
|
||
ops.Operation.prototype.engine = engine;
|
||
ops.Operation.prototype.connector = connector;
|
||
ops.Operation.prototype.custom_types = this.constructor;
|
||
ct = new createY.Object();
|
||
model = new ops.MapManager(ct, HB.getReservedUniqueIdentifier()).execute();
|
||
ct._setModel(model);
|
||
return ct;
|
||
};
|
||
|
||
module.exports = createY;
|
||
|
||
if (typeof window !== "undefined" && window !== null) {
|
||
window.Y = createY;
|
||
}
|
||
|
||
createY.Object = require("./ObjectType");
|
||
|
||
|
||
},{"./ConnectorAdapter":4,"./Engine":6,"./HistoryBuffer":7,"./ObjectType":8,"./Operations/Structured":10}],12:[function(require,module,exports){
|
||
var TreeBase = require('./treebase');
|
||
/** algorithm from Cormen, Leiserson - Introduction to algorithm **/
|
||
|
||
function RBTree(comparator) {
|
||
this._root = null;
|
||
this._nil = new Node('nil');
|
||
this._nil.red = false;
|
||
this._nil.weight = 0;
|
||
}
|
||
|
||
RBTree.prototype = new TreeBase();
|
||
|
||
RBTree.prototype.insert = function(position, data) {
|
||
var nodeToInsert = new Node(data);
|
||
if (this.insert_node(position, nodeToInsert)) {
|
||
return nodeToInsert;
|
||
} else {
|
||
return false;
|
||
}
|
||
};
|
||
|
||
RBTree.prototype.insert_node = function(position, nodeToInsert) {
|
||
var node = this._root;
|
||
var insertAfter;
|
||
|
||
if (!node) {
|
||
this._root = nodeToInsert;
|
||
this._root.red = false;
|
||
return true;
|
||
}
|
||
|
||
while (true) {
|
||
if (node.weight === position) { // Insert after max of node subtree
|
||
insertAfter = node.max_tree(function(node) {
|
||
node.weight += 1;
|
||
});
|
||
insertAfter.set_child('right', nodeToInsert);
|
||
nodeToInsert.parent = insertAfter;
|
||
break;
|
||
} else {
|
||
left = node.get_child('left');
|
||
right = node.get_child('right');
|
||
if (!left && position === 0) {
|
||
node.weight += 1;
|
||
node.set_child('left', nodeToInsert);
|
||
nodeToInsert.parent = node;
|
||
break;
|
||
|
||
} else if (left && left.weight >= position) {
|
||
node.weight += 1;
|
||
node = left;
|
||
|
||
} else if (right) {
|
||
position -= (left? left.weight: 0) + 1;
|
||
node.weight += 1;
|
||
node = right;
|
||
|
||
} else {
|
||
node.weight += 1;
|
||
node.set_child('right', nodeToInsert);
|
||
nodeToInsert.parent = node;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
this.insert_correction(nodeToInsert);
|
||
return true;
|
||
};
|
||
|
||
RBTree.prototype.insert_between = function(onLeft, onRight, data) {
|
||
var newNode = new Node(data);
|
||
// onLeft and onRight are neighbors, so they can't have an element in between.
|
||
// For example, if onLeft exists, its right neighbor is either nil or right. If it's onRight,
|
||
// then onRight has no child. If neither left and right exist, the tree is empty.
|
||
if (onLeft && !onLeft.right) {
|
||
onLeft.right = newNode;
|
||
newNode.parent = onLeft;
|
||
|
||
this.insert_correction(newNode);
|
||
} else if (onRight && !onRight.left) {
|
||
onRight.left = newNode;
|
||
newNode.parent = onRight;
|
||
|
||
this.insert_correction(newNode);
|
||
} else {
|
||
this.insert_node(0, newNode);
|
||
}
|
||
newNode.traverse_up(function(node, parent) {
|
||
parent.weight = (parent.left ? parent.left.weight : 0) +
|
||
(parent.right ? parent.right.weight : 0) + 1;
|
||
});
|
||
|
||
return newNode;
|
||
};
|
||
|
||
RBTree.prototype.rotate = function(side, node) {
|
||
// all the comment are with the assumption that side === 'left'
|
||
var neighbor;
|
||
|
||
// get right neighbor
|
||
neighbor = node.get_child(side, true);
|
||
// neighbor's left tree becomes node's right tree
|
||
node.set_child(side, neighbor.get_child(side), true);
|
||
|
||
// if this right tree was non-empty
|
||
if (neighbor.get_child(side)) {
|
||
neighbor.get_child(side).parent = node; // attach neighbor's left child to node
|
||
}
|
||
neighbor.parent = node.parent; // link neighbor's parent to node's parent
|
||
|
||
if (!node.parent) { // no parent === is_root
|
||
this._root = neighbor;
|
||
} else if (node === node.parent.get_child(side)){ // node is left child
|
||
node.parent.set_child(side, neighbor); // node's parent left child is now neighbor
|
||
} else {
|
||
node.parent.set_child(side, neighbor, true); // node's parent right child is now neighbor
|
||
}
|
||
|
||
neighbor.set_child(side, node); // attach node on left of child
|
||
node.parent = neighbor; // set node's parent to neighbor
|
||
|
||
// update node's weight first, then
|
||
node.weight = (node.left? node.left.weight: 0) + (node.right? node.right.weight: 0) + 1;
|
||
neighbor.weight = (neighbor.left? neighbor.left.weight: 0) + (neighbor.right? neighbor.right.weight: 0) + 1;
|
||
};
|
||
|
||
RBTree.prototype.insert_correction = function(node) {
|
||
var self = this;
|
||
function helper(side) {
|
||
var uncle;
|
||
uncle = node.parent.parent.get_child(side, true);
|
||
|
||
if (uncle && uncle.red) { // if uncle is undefined, it's a leaf so it's black
|
||
node.parent.red = false;
|
||
uncle.red = false;
|
||
node.parent.parent.red = true;
|
||
|
||
node = node.parent.parent;
|
||
} else {
|
||
if (node === node.parent.get_child(side, true)) {
|
||
node = node.parent;
|
||
self.rotate(side, node);
|
||
}
|
||
|
||
node.parent.red = false;
|
||
node.parent.parent.red = true;
|
||
|
||
var oppositeSide = side === 'left'? 'right': 'left';
|
||
self.rotate(oppositeSide, node.parent.parent);
|
||
}
|
||
}
|
||
|
||
|
||
while (node.parent && node.parent.red) { // is there's no node.parent, then it means the parent
|
||
// is nil which is black
|
||
|
||
// if node's parent is on left of his parent
|
||
if (node.parent === node.parent.parent.get_child('left')) { // Check that there is a grandparent
|
||
helper('left');
|
||
} else if (node.parent === node.parent.parent.get_child('right')){
|
||
helper('right');
|
||
}
|
||
}
|
||
|
||
this._root.red = false;
|
||
|
||
};
|
||
|
||
RBTree.prototype.find = function() {
|
||
var node = this.findNode.apply(this, arguments);
|
||
if (node) {
|
||
return node.data;
|
||
} else {
|
||
return null;
|
||
}
|
||
};
|
||
|
||
/** Find the node at position @position and return it. If no node is found, returns null.
|
||
* It is also possible to pass a function as second argument. It will be called
|
||
* with each node traversed except for the one found.
|
||
**/
|
||
RBTree.prototype.findNode = function(position, fun) {
|
||
// if the weight is 'n', the biggest index is n-1, so we check that position >= size
|
||
if (position >= this.get_size() || position < 0) {
|
||
return null;
|
||
}
|
||
var node = this._root;
|
||
|
||
if (!node) {
|
||
return null;
|
||
}
|
||
|
||
// Find node to delete
|
||
while (position > 0 || (position === 0 && node.left)) {
|
||
left = node.left;
|
||
right = node.right;
|
||
|
||
if (left && left.weight > position) {
|
||
// when there's a left neighbor with a weight > position to remove,
|
||
// go into this subtree and decrease the subtree weight
|
||
if (fun) {
|
||
fun(node);
|
||
}
|
||
node = left;
|
||
|
||
} else if ((!left && position === 0) || (left && left.weight === position)) {
|
||
break;
|
||
} else if (right) {
|
||
// when there's a right subtee, go into it and decrease the position
|
||
// by the weight of the left subtree - 1 + 1 (for the previous node)
|
||
if (fun) {
|
||
fun(node);
|
||
}
|
||
node = right;
|
||
position -= (left? left.weight: 0) + 1;
|
||
|
||
} else {
|
||
// this should not happen, except if the position is greater than the size of the tree
|
||
throw new Error('this should not happen');
|
||
}
|
||
}
|
||
return node;
|
||
};
|
||
|
||
RBTree.prototype.remove = function(position) {
|
||
// if the weight is 'n', the biggest index is n-1, so we check that position >= size
|
||
var nodeToRemove;
|
||
|
||
nodeToRemove = this.findNode(position, function(node) { node.weight --; });
|
||
|
||
return this.remove_helper(nodeToRemove);
|
||
};
|
||
|
||
RBTree.prototype.remove_helper = function(nodeToRemove) {
|
||
var left, right, nextNode, childNode, parent;
|
||
|
||
// if there's only one child, replace the nodeToRemove to delete by it's child and update
|
||
// the refs.
|
||
// if there's two children, find it's successor and replace the nodeToRemove to delete by his successor
|
||
// and update the refs
|
||
|
||
if (!nodeToRemove.left || !nodeToRemove.right) {
|
||
nextNode = nodeToRemove;
|
||
} else {
|
||
nextNode = nodeToRemove.next(function(node) {
|
||
node.weight -= 1;
|
||
});
|
||
}
|
||
|
||
if (nextNode.left) {
|
||
childNode = nextNode.left;
|
||
parent = nextNode.parent;
|
||
} else {
|
||
childNode = nextNode.right;
|
||
parent = nextNode.parent;
|
||
}
|
||
|
||
if (childNode) {
|
||
childNode.parent = nextNode.parent;
|
||
}
|
||
|
||
|
||
if (!nextNode.parent) {
|
||
this._root = childNode;
|
||
} else {
|
||
if (nextNode === nextNode.parent.left) {
|
||
nextNode.parent.left = childNode;
|
||
} else {
|
||
nextNode.parent.right = childNode;
|
||
}
|
||
}
|
||
|
||
// replace nodeToRemove's data by nextNode's (same as removing nodeToRemove, then inserting nextNode at his place
|
||
// but easier and more efficient)
|
||
if (nextNode !== nodeToRemove) {
|
||
nodeToRemove.data = nextNode.data;
|
||
nodeToRemove.weight = (nodeToRemove.left? nodeToRemove.left.weight: 0) +
|
||
(nodeToRemove.right? nodeToRemove.right.weight: 0) + 1;
|
||
}
|
||
|
||
if (!nextNode.red) {
|
||
this.remove_correction(childNode, parent);
|
||
}
|
||
|
||
return nextNode;
|
||
};
|
||
|
||
RBTree.prototype.remove_node = function(node) {
|
||
node.traverse_up(function(node, parent) {
|
||
parent.weight --;
|
||
});
|
||
|
||
return this.remove_helper(node);
|
||
};
|
||
|
||
RBTree.prototype.remove_correction = function(node, parent) {
|
||
var self = this;
|
||
var oppositeSide;
|
||
var helper = function(side) {
|
||
var neighbor = parent.get_child(side, true);
|
||
|
||
if (neighbor && neighbor.red) {
|
||
neighbor.red = false;
|
||
parent.red = true;
|
||
|
||
self.rotate(side, parent);
|
||
neighbor = parent.get_child(side, true);
|
||
}
|
||
|
||
if ((!neighbor.left || !neighbor.left.red) && (!neighbor.right || !neighbor.right.red )) {
|
||
neighbor.red = true;
|
||
node = parent;
|
||
parent = node.parent;
|
||
} else {
|
||
if (!neighbor.get_child(side, true) || !neighbor.get_child(side, true).red) {
|
||
if (neighbor.get_child(side)) {
|
||
neighbor.get_child(side).red = false;
|
||
}
|
||
neighbor.red = true;
|
||
|
||
oppositeSide = side === 'left'? 'right': 'left';
|
||
self.rotate(oppositeSide, neighbor);
|
||
neighbor = parent.get_child(side, true);
|
||
}
|
||
|
||
neighbor.red = parent? parent.red: false;
|
||
parent.red = false;
|
||
if (neighbor.get_child(side, true)) {
|
||
neighbor.get_child(side, true).red = false;
|
||
}
|
||
|
||
self.rotate(side, parent);
|
||
node = self._root;
|
||
parent = node.parent;
|
||
}
|
||
};
|
||
while (node !== this._root && (!node || !node.red)) {
|
||
if (node === parent.get_child('left')) {
|
||
tmp = helper('left');
|
||
} else if (node === parent.get_child('right')) {
|
||
tmp = helper('right');
|
||
}
|
||
}
|
||
|
||
if (node) {
|
||
node.red = false;
|
||
}
|
||
};
|
||
|
||
RBTree.prototype.get_size = function() {
|
||
return (this._root? this._root.weight : 0);
|
||
};
|
||
|
||
function Node(data) {
|
||
this.data = data;
|
||
this.left = null;
|
||
this.right = null;
|
||
this.parent = null;
|
||
this.red = true;
|
||
this.weight = 1;
|
||
}
|
||
|
||
Node.prototype.get_child = function(side, opposite) {
|
||
if (opposite) {
|
||
side = (side === 'left')? 'right': 'left';
|
||
}
|
||
return side === 'left'? this.left: this.right;
|
||
};
|
||
|
||
Node.prototype.set_child = function(side, node, opposite) {
|
||
if (opposite) {
|
||
side = (side === 'left')? 'right': 'left';
|
||
}
|
||
|
||
if (side === 'left') {
|
||
this.left = node;
|
||
} else {
|
||
this.right = node;
|
||
}
|
||
};
|
||
|
||
Node.prototype.max_tree = function(fun) {
|
||
var node = this;
|
||
|
||
if (fun) {
|
||
fun(node);
|
||
}
|
||
|
||
while (node.right) {
|
||
node = node.right;
|
||
if (fun) {
|
||
fun(node);
|
||
}
|
||
}
|
||
|
||
return node;
|
||
};
|
||
|
||
Node.prototype.min_tree = function(fun) {
|
||
var node = this;
|
||
|
||
if (fun) {
|
||
fun(node);
|
||
}
|
||
|
||
while (node.left) {
|
||
node = node.left;
|
||
if (fun) {
|
||
fun(node);
|
||
}
|
||
}
|
||
|
||
return node;
|
||
};
|
||
|
||
|
||
Node.prototype.next = function(fun) {
|
||
var node, parent;
|
||
if (this.get_child('right')) {
|
||
return this.get_child('right').min_tree(fun);
|
||
}
|
||
|
||
if (fun) {
|
||
fun(this);
|
||
}
|
||
node = this;
|
||
parent = this.parent;
|
||
while (parent && node === parent.get_child('right')) {
|
||
node = parent;
|
||
parent = node.parent;
|
||
|
||
if (fun) {
|
||
fun(parent);
|
||
}
|
||
}
|
||
|
||
return parent;
|
||
};
|
||
|
||
Node.prototype.prev = function(fun) {
|
||
var node, parent;
|
||
if (this.get_child('left')) {
|
||
return this.get_child('left').max_tree(fun);
|
||
}
|
||
|
||
if (fun) {
|
||
fun(this);
|
||
}
|
||
node = this;
|
||
parent = this.parent;
|
||
while (parent && node === parent.get_child('left')) {
|
||
node = parent;
|
||
parent = node.parent;
|
||
|
||
if (fun) {
|
||
fun(parent);
|
||
}
|
||
}
|
||
|
||
return parent;
|
||
};
|
||
|
||
/** Traverse the tree upwards until it reaches the top. For each node traversed,
|
||
* call the function passed as argument with arguments node, parent.
|
||
* The function will be called h-1 times, h being the height of the branch.
|
||
**/
|
||
Node.prototype.traverse_up = function(fun) {
|
||
var parent = this.parent;
|
||
var node = this;
|
||
|
||
while(parent) {
|
||
fun(node, parent);
|
||
node = parent;
|
||
parent = parent.parent;
|
||
}
|
||
};
|
||
|
||
Node.prototype.depth = function() {
|
||
var depth = 0;
|
||
this.traverse_up(function() {
|
||
depth ++;
|
||
});
|
||
return depth;
|
||
};
|
||
|
||
Node.prototype.position = function() {
|
||
var position = this.left? this.left.weight: 0;
|
||
var countFun = function(node, parent) {
|
||
if (parent.right === node) {
|
||
// for the left subtree
|
||
if (parent.left) {
|
||
position += parent.left.weight;
|
||
}
|
||
position += 1; // for the parent
|
||
}
|
||
};
|
||
|
||
this.traverse_up(countFun);
|
||
return position;
|
||
};
|
||
|
||
module.exports = RBTree;
|
||
|
||
},{"./treebase":13}],13:[function(require,module,exports){
|
||
|
||
function TreeBase() {}
|
||
|
||
// removes all nodes from the tree
|
||
TreeBase.prototype.clear = function() {
|
||
this._root = null;
|
||
this.size = 0;
|
||
};
|
||
|
||
// returns node data if found, null otherwise
|
||
TreeBase.prototype.find = function(data) {
|
||
var res = this._root;
|
||
|
||
while(res !== null) {
|
||
var c = this._comparator(data, res.data);
|
||
if(c === 0) {
|
||
return res.data;
|
||
}
|
||
else {
|
||
res = res.get_child(c > 0);
|
||
}
|
||
}
|
||
|
||
return null;
|
||
};
|
||
|
||
// returns iterator to node if found, null otherwise
|
||
TreeBase.prototype.findIter = function(data) {
|
||
var res = this._root;
|
||
var iter = this.iterator();
|
||
|
||
while(res !== null) {
|
||
var c = this._comparator(data, res.data);
|
||
if(c === 0) {
|
||
iter._cursor = res;
|
||
return iter;
|
||
}
|
||
else {
|
||
iter._ancestors.push(res);
|
||
res = res.get_child(c > 0);
|
||
}
|
||
}
|
||
|
||
return null;
|
||
};
|
||
|
||
// Returns an interator to the tree node at or immediately after the item
|
||
TreeBase.prototype.lowerBound = function(item) {
|
||
var cur = this._root;
|
||
var iter = this.iterator();
|
||
var cmp = this._comparator;
|
||
|
||
while(cur !== null) {
|
||
var c = cmp(item, cur.data);
|
||
if(c === 0) {
|
||
iter._cursor = cur;
|
||
return iter;
|
||
}
|
||
iter._ancestors.push(cur);
|
||
cur = cur.get_child(c > 0);
|
||
}
|
||
|
||
for(var i=iter._ancestors.length - 1; i >= 0; --i) {
|
||
cur = iter._ancestors[i];
|
||
if(cmp(item, cur.data) < 0) {
|
||
iter._cursor = cur;
|
||
iter._ancestors.length = i;
|
||
return iter;
|
||
}
|
||
}
|
||
|
||
iter._ancestors.length = 0;
|
||
return iter;
|
||
};
|
||
|
||
// Returns an interator to the tree node immediately after the item
|
||
TreeBase.prototype.upperBound = function(item) {
|
||
var iter = this.lowerBound(item);
|
||
var cmp = this._comparator;
|
||
|
||
while(cmp(iter.data(), item) === 0) {
|
||
iter.next();
|
||
}
|
||
|
||
return iter;
|
||
};
|
||
|
||
// returns null if tree is empty
|
||
TreeBase.prototype.min = function() {
|
||
var res = this._root;
|
||
if(res === null) {
|
||
return null;
|
||
}
|
||
|
||
while(res.left !== null) {
|
||
res = res.left;
|
||
}
|
||
|
||
return res.data;
|
||
};
|
||
|
||
// returns null if tree is empty
|
||
TreeBase.prototype.max = function() {
|
||
var res = this._root;
|
||
if(res === null) {
|
||
return null;
|
||
}
|
||
|
||
while(res.right !== null) {
|
||
res = res.right;
|
||
}
|
||
|
||
return res.data;
|
||
};
|
||
|
||
// returns a null iterator
|
||
// call next() or prev() to point to an element
|
||
TreeBase.prototype.iterator = function() {
|
||
return new Iterator(this);
|
||
};
|
||
|
||
|
||
TreeBase.prototype.eachNode = function(cb) {
|
||
var it=this.iterator(), node;
|
||
var index = 0;
|
||
while((node = it.next()) !== null) {
|
||
cb(node, index);
|
||
index++;
|
||
}
|
||
};
|
||
|
||
// calls cb on each node's data, in order
|
||
TreeBase.prototype.each = function(cb) {
|
||
this.eachNode(function(node, index) {
|
||
cb(node.data, index);
|
||
});
|
||
};
|
||
|
||
|
||
TreeBase.prototype.mapNode = function(cb) {
|
||
var it=this.iterator(), node;
|
||
var results = [];
|
||
var index = 0;
|
||
while((node = it.next()) !== null) {
|
||
results.push(cb(node, index));
|
||
index ++;
|
||
}
|
||
return results;
|
||
};
|
||
|
||
// calls cb on each node-s data, store the result and return it
|
||
TreeBase.prototype.map = function(cb) {
|
||
return this.mapNode(function(node, index) {
|
||
return cb(node.data, index);
|
||
});
|
||
};
|
||
|
||
function Iterator(tree) {
|
||
this._tree = tree;
|
||
this._ancestors = [];
|
||
this._cursor = null;
|
||
}
|
||
|
||
Iterator.prototype.data = function() {
|
||
return this._cursor !== null ? this._cursor.data : null;
|
||
};
|
||
|
||
// if null-iterator, returns first node
|
||
// otherwise, returns next node
|
||
Iterator.prototype.next = function() {
|
||
if(this._cursor === null) {
|
||
var root = this._tree._root;
|
||
if(root !== null) {
|
||
this._minNode(root);
|
||
}
|
||
}
|
||
else {
|
||
if(this._cursor.right === null) {
|
||
// no greater node in subtree, go up to parent
|
||
// if coming from a right child, continue up the stack
|
||
var save;
|
||
do {
|
||
save = this._cursor;
|
||
if(this._ancestors.length) {
|
||
this._cursor = this._ancestors.pop();
|
||
}
|
||
else {
|
||
this._cursor = null;
|
||
break;
|
||
}
|
||
} while(this._cursor.right === save);
|
||
}
|
||
else {
|
||
// get the next node from the subtree
|
||
this._ancestors.push(this._cursor);
|
||
this._minNode(this._cursor.right);
|
||
}
|
||
}
|
||
return this._cursor !== null ? this._cursor : null;
|
||
};
|
||
|
||
// if null-iterator, returns last node
|
||
// otherwise, returns previous node
|
||
Iterator.prototype.prev = function() {
|
||
if(this._cursor === null) {
|
||
var root = this._tree._root;
|
||
if(root !== null) {
|
||
this._maxNode(root);
|
||
}
|
||
}
|
||
else {
|
||
if(this._cursor.left === null) {
|
||
var save;
|
||
do {
|
||
save = this._cursor;
|
||
if(this._ancestors.length) {
|
||
this._cursor = this._ancestors.pop();
|
||
}
|
||
else {
|
||
this._cursor = null;
|
||
break;
|
||
}
|
||
} while(this._cursor.left === save);
|
||
}
|
||
else {
|
||
this._ancestors.push(this._cursor);
|
||
this._maxNode(this._cursor.left);
|
||
}
|
||
}
|
||
return this._cursor !== null ? this._cursor : null;
|
||
};
|
||
|
||
Iterator.prototype._minNode = function(start) {
|
||
while(start.left !== null) {
|
||
this._ancestors.push(start);
|
||
start = start.left;
|
||
}
|
||
this._cursor = start;
|
||
};
|
||
|
||
Iterator.prototype._maxNode = function(start) {
|
||
while(start.right !== null) {
|
||
this._ancestors.push(start);
|
||
start = start.right;
|
||
}
|
||
this._cursor = start;
|
||
};
|
||
|
||
module.exports = TreeBase;
|
||
|
||
},{}],14:[function(require,module,exports){
|
||
module.exports = require('./lib/chai');
|
||
|
||
},{"./lib/chai":15}],15:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
var used = []
|
||
, exports = module.exports = {};
|
||
|
||
/*!
|
||
* Chai version
|
||
*/
|
||
|
||
exports.version = '2.3.0';
|
||
|
||
/*!
|
||
* Assertion Error
|
||
*/
|
||
|
||
exports.AssertionError = require('assertion-error');
|
||
|
||
/*!
|
||
* Utils for plugins (not exported)
|
||
*/
|
||
|
||
var util = require('./chai/utils');
|
||
|
||
/**
|
||
* # .use(function)
|
||
*
|
||
* Provides a way to extend the internals of Chai
|
||
*
|
||
* @param {Function}
|
||
* @returns {this} for chaining
|
||
* @api public
|
||
*/
|
||
|
||
exports.use = function (fn) {
|
||
if (!~used.indexOf(fn)) {
|
||
fn(this, util);
|
||
used.push(fn);
|
||
}
|
||
|
||
return this;
|
||
};
|
||
|
||
/*!
|
||
* Utility Functions
|
||
*/
|
||
|
||
exports.util = util;
|
||
|
||
/*!
|
||
* Configuration
|
||
*/
|
||
|
||
var config = require('./chai/config');
|
||
exports.config = config;
|
||
|
||
/*!
|
||
* Primary `Assertion` prototype
|
||
*/
|
||
|
||
var assertion = require('./chai/assertion');
|
||
exports.use(assertion);
|
||
|
||
/*!
|
||
* Core Assertions
|
||
*/
|
||
|
||
var core = require('./chai/core/assertions');
|
||
exports.use(core);
|
||
|
||
/*!
|
||
* Expect interface
|
||
*/
|
||
|
||
var expect = require('./chai/interface/expect');
|
||
exports.use(expect);
|
||
|
||
/*!
|
||
* Should interface
|
||
*/
|
||
|
||
var should = require('./chai/interface/should');
|
||
exports.use(should);
|
||
|
||
/*!
|
||
* Assert interface
|
||
*/
|
||
|
||
var assert = require('./chai/interface/assert');
|
||
exports.use(assert);
|
||
|
||
},{"./chai/assertion":16,"./chai/config":17,"./chai/core/assertions":18,"./chai/interface/assert":19,"./chai/interface/expect":20,"./chai/interface/should":21,"./chai/utils":34,"assertion-error":43}],16:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* http://chaijs.com
|
||
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
var config = require('./config');
|
||
|
||
module.exports = function (_chai, util) {
|
||
/*!
|
||
* Module dependencies.
|
||
*/
|
||
|
||
var AssertionError = _chai.AssertionError
|
||
, flag = util.flag;
|
||
|
||
/*!
|
||
* Module export.
|
||
*/
|
||
|
||
_chai.Assertion = Assertion;
|
||
|
||
/*!
|
||
* Assertion Constructor
|
||
*
|
||
* Creates object for chaining.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
function Assertion (obj, msg, stack) {
|
||
flag(this, 'ssfi', stack || arguments.callee);
|
||
flag(this, 'object', obj);
|
||
flag(this, 'message', msg);
|
||
}
|
||
|
||
Object.defineProperty(Assertion, 'includeStack', {
|
||
get: function() {
|
||
console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
|
||
return config.includeStack;
|
||
},
|
||
set: function(value) {
|
||
console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
|
||
config.includeStack = value;
|
||
}
|
||
});
|
||
|
||
Object.defineProperty(Assertion, 'showDiff', {
|
||
get: function() {
|
||
console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
|
||
return config.showDiff;
|
||
},
|
||
set: function(value) {
|
||
console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
|
||
config.showDiff = value;
|
||
}
|
||
});
|
||
|
||
Assertion.addProperty = function (name, fn) {
|
||
util.addProperty(this.prototype, name, fn);
|
||
};
|
||
|
||
Assertion.addMethod = function (name, fn) {
|
||
util.addMethod(this.prototype, name, fn);
|
||
};
|
||
|
||
Assertion.addChainableMethod = function (name, fn, chainingBehavior) {
|
||
util.addChainableMethod(this.prototype, name, fn, chainingBehavior);
|
||
};
|
||
|
||
Assertion.overwriteProperty = function (name, fn) {
|
||
util.overwriteProperty(this.prototype, name, fn);
|
||
};
|
||
|
||
Assertion.overwriteMethod = function (name, fn) {
|
||
util.overwriteMethod(this.prototype, name, fn);
|
||
};
|
||
|
||
Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) {
|
||
util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior);
|
||
};
|
||
|
||
/*!
|
||
* ### .assert(expression, message, negateMessage, expected, actual)
|
||
*
|
||
* Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass.
|
||
*
|
||
* @name assert
|
||
* @param {Philosophical} expression to be tested
|
||
* @param {String or Function} message or function that returns message to display if expression fails
|
||
* @param {String or Function} negatedMessage or function that returns negatedMessage to display if negated expression fails
|
||
* @param {Mixed} expected value (remember to check for negation)
|
||
* @param {Mixed} actual (optional) will default to `this.obj`
|
||
* @param {Boolean} showDiff (optional) when set to `true`, assert will display a diff in addition to the message if expression fails
|
||
* @api private
|
||
*/
|
||
|
||
Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) {
|
||
var ok = util.test(this, arguments);
|
||
if (true !== showDiff) showDiff = false;
|
||
if (true !== config.showDiff) showDiff = false;
|
||
|
||
if (!ok) {
|
||
var msg = util.getMessage(this, arguments)
|
||
, actual = util.getActual(this, arguments);
|
||
throw new AssertionError(msg, {
|
||
actual: actual
|
||
, expected: expected
|
||
, showDiff: showDiff
|
||
}, (config.includeStack) ? this.assert : flag(this, 'ssfi'));
|
||
}
|
||
};
|
||
|
||
/*!
|
||
* ### ._obj
|
||
*
|
||
* Quick reference to stored `actual` value for plugin developers.
|
||
*
|
||
* @api private
|
||
*/
|
||
|
||
Object.defineProperty(Assertion.prototype, '_obj',
|
||
{ get: function () {
|
||
return flag(this, 'object');
|
||
}
|
||
, set: function (val) {
|
||
flag(this, 'object', val);
|
||
}
|
||
});
|
||
};
|
||
|
||
},{"./config":17}],17:[function(require,module,exports){
|
||
module.exports = {
|
||
|
||
/**
|
||
* ### config.includeStack
|
||
*
|
||
* User configurable property, influences whether stack trace
|
||
* is included in Assertion error message. Default of false
|
||
* suppresses stack trace in the error message.
|
||
*
|
||
* chai.config.includeStack = true; // enable stack on error
|
||
*
|
||
* @param {Boolean}
|
||
* @api public
|
||
*/
|
||
|
||
includeStack: false,
|
||
|
||
/**
|
||
* ### config.showDiff
|
||
*
|
||
* User configurable property, influences whether or not
|
||
* the `showDiff` flag should be included in the thrown
|
||
* AssertionErrors. `false` will always be `false`; `true`
|
||
* will be true when the assertion has requested a diff
|
||
* be shown.
|
||
*
|
||
* @param {Boolean}
|
||
* @api public
|
||
*/
|
||
|
||
showDiff: true,
|
||
|
||
/**
|
||
* ### config.truncateThreshold
|
||
*
|
||
* User configurable property, sets length threshold for actual and
|
||
* expected values in assertion errors. If this threshold is exceeded, for
|
||
* example for large data structures, the value is replaced with something
|
||
* like `[ Array(3) ]` or `{ Object (prop1, prop2) }`.
|
||
*
|
||
* Set it to zero if you want to disable truncating altogether.
|
||
*
|
||
* This is especially userful when doing assertions on arrays: having this
|
||
* set to a reasonable large value makes the failure messages readily
|
||
* inspectable.
|
||
*
|
||
* chai.config.truncateThreshold = 0; // disable truncating
|
||
*
|
||
* @param {Number}
|
||
* @api public
|
||
*/
|
||
|
||
truncateThreshold: 40
|
||
|
||
};
|
||
|
||
},{}],18:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* http://chaijs.com
|
||
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
module.exports = function (chai, _) {
|
||
var Assertion = chai.Assertion
|
||
, toString = Object.prototype.toString
|
||
, flag = _.flag;
|
||
|
||
/**
|
||
* ### Language Chains
|
||
*
|
||
* The following are provided as chainable getters to
|
||
* improve the readability of your assertions. They
|
||
* do not provide testing capabilities unless they
|
||
* have been overwritten by a plugin.
|
||
*
|
||
* **Chains**
|
||
*
|
||
* - to
|
||
* - be
|
||
* - been
|
||
* - is
|
||
* - that
|
||
* - which
|
||
* - and
|
||
* - has
|
||
* - have
|
||
* - with
|
||
* - at
|
||
* - of
|
||
* - same
|
||
*
|
||
* @name language chains
|
||
* @api public
|
||
*/
|
||
|
||
[ 'to', 'be', 'been'
|
||
, 'is', 'and', 'has', 'have'
|
||
, 'with', 'that', 'which', 'at'
|
||
, 'of', 'same' ].forEach(function (chain) {
|
||
Assertion.addProperty(chain, function () {
|
||
return this;
|
||
});
|
||
});
|
||
|
||
/**
|
||
* ### .not
|
||
*
|
||
* Negates any of assertions following in the chain.
|
||
*
|
||
* expect(foo).to.not.equal('bar');
|
||
* expect(goodFn).to.not.throw(Error);
|
||
* expect({ foo: 'baz' }).to.have.property('foo')
|
||
* .and.not.equal('bar');
|
||
*
|
||
* @name not
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('not', function () {
|
||
flag(this, 'negate', true);
|
||
});
|
||
|
||
/**
|
||
* ### .deep
|
||
*
|
||
* Sets the `deep` flag, later used by the `equal` and
|
||
* `property` assertions.
|
||
*
|
||
* expect(foo).to.deep.equal({ bar: 'baz' });
|
||
* expect({ foo: { bar: { baz: 'quux' } } })
|
||
* .to.have.deep.property('foo.bar.baz', 'quux');
|
||
*
|
||
* `.deep.property` special characters can be escaped
|
||
* by adding two slashes before the `.` or `[]`.
|
||
*
|
||
* var deepCss = { '.link': { '[target]': 42 }};
|
||
* expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
|
||
*
|
||
* @name deep
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('deep', function () {
|
||
flag(this, 'deep', true);
|
||
});
|
||
|
||
/**
|
||
* ### .any
|
||
*
|
||
* Sets the `any` flag, (opposite of the `all` flag)
|
||
* later used in the `keys` assertion.
|
||
*
|
||
* expect(foo).to.have.any.keys('bar', 'baz');
|
||
*
|
||
* @name any
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('any', function () {
|
||
flag(this, 'any', true);
|
||
flag(this, 'all', false)
|
||
});
|
||
|
||
|
||
/**
|
||
* ### .all
|
||
*
|
||
* Sets the `all` flag (opposite of the `any` flag)
|
||
* later used by the `keys` assertion.
|
||
*
|
||
* expect(foo).to.have.all.keys('bar', 'baz');
|
||
*
|
||
* @name all
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('all', function () {
|
||
flag(this, 'all', true);
|
||
flag(this, 'any', false);
|
||
});
|
||
|
||
/**
|
||
* ### .a(type)
|
||
*
|
||
* The `a` and `an` assertions are aliases that can be
|
||
* used either as language chains or to assert a value's
|
||
* type.
|
||
*
|
||
* // typeof
|
||
* expect('test').to.be.a('string');
|
||
* expect({ foo: 'bar' }).to.be.an('object');
|
||
* expect(null).to.be.a('null');
|
||
* expect(undefined).to.be.an('undefined');
|
||
*
|
||
* // language chain
|
||
* expect(foo).to.be.an.instanceof(Foo);
|
||
*
|
||
* @name a
|
||
* @alias an
|
||
* @param {String} type
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function an (type, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
type = type.toLowerCase();
|
||
var obj = flag(this, 'object')
|
||
, article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
|
||
|
||
this.assert(
|
||
type === _.type(obj)
|
||
, 'expected #{this} to be ' + article + type
|
||
, 'expected #{this} not to be ' + article + type
|
||
);
|
||
}
|
||
|
||
Assertion.addChainableMethod('an', an);
|
||
Assertion.addChainableMethod('a', an);
|
||
|
||
/**
|
||
* ### .include(value)
|
||
*
|
||
* The `include` and `contain` assertions can be used as either property
|
||
* based language chains or as methods to assert the inclusion of an object
|
||
* in an array or a substring in a string. When used as language chains,
|
||
* they toggle the `contains` flag for the `keys` assertion.
|
||
*
|
||
* expect([1,2,3]).to.include(2);
|
||
* expect('foobar').to.contain('foo');
|
||
* expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
|
||
*
|
||
* @name include
|
||
* @alias contain
|
||
* @alias includes
|
||
* @alias contains
|
||
* @param {Object|String|Number} obj
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function includeChainingBehavior () {
|
||
flag(this, 'contains', true);
|
||
}
|
||
|
||
function include (val, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
var expected = false;
|
||
if (_.type(obj) === 'array' && _.type(val) === 'object') {
|
||
for (var i in obj) {
|
||
if (_.eql(obj[i], val)) {
|
||
expected = true;
|
||
break;
|
||
}
|
||
}
|
||
} else if (_.type(val) === 'object') {
|
||
if (!flag(this, 'negate')) {
|
||
for (var k in val) new Assertion(obj).property(k, val[k]);
|
||
return;
|
||
}
|
||
var subset = {};
|
||
for (var k in val) subset[k] = obj[k];
|
||
expected = _.eql(subset, val);
|
||
} else {
|
||
expected = obj && ~obj.indexOf(val);
|
||
}
|
||
this.assert(
|
||
expected
|
||
, 'expected #{this} to include ' + _.inspect(val)
|
||
, 'expected #{this} to not include ' + _.inspect(val));
|
||
}
|
||
|
||
Assertion.addChainableMethod('include', include, includeChainingBehavior);
|
||
Assertion.addChainableMethod('contain', include, includeChainingBehavior);
|
||
Assertion.addChainableMethod('contains', include, includeChainingBehavior);
|
||
Assertion.addChainableMethod('includes', include, includeChainingBehavior);
|
||
|
||
/**
|
||
* ### .ok
|
||
*
|
||
* Asserts that the target is truthy.
|
||
*
|
||
* expect('everthing').to.be.ok;
|
||
* expect(1).to.be.ok;
|
||
* expect(false).to.not.be.ok;
|
||
* expect(undefined).to.not.be.ok;
|
||
* expect(null).to.not.be.ok;
|
||
*
|
||
* @name ok
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('ok', function () {
|
||
this.assert(
|
||
flag(this, 'object')
|
||
, 'expected #{this} to be truthy'
|
||
, 'expected #{this} to be falsy');
|
||
});
|
||
|
||
/**
|
||
* ### .true
|
||
*
|
||
* Asserts that the target is `true`.
|
||
*
|
||
* expect(true).to.be.true;
|
||
* expect(1).to.not.be.true;
|
||
*
|
||
* @name true
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('true', function () {
|
||
this.assert(
|
||
true === flag(this, 'object')
|
||
, 'expected #{this} to be true'
|
||
, 'expected #{this} to be false'
|
||
, this.negate ? false : true
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .false
|
||
*
|
||
* Asserts that the target is `false`.
|
||
*
|
||
* expect(false).to.be.false;
|
||
* expect(0).to.not.be.false;
|
||
*
|
||
* @name false
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('false', function () {
|
||
this.assert(
|
||
false === flag(this, 'object')
|
||
, 'expected #{this} to be false'
|
||
, 'expected #{this} to be true'
|
||
, this.negate ? true : false
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .null
|
||
*
|
||
* Asserts that the target is `null`.
|
||
*
|
||
* expect(null).to.be.null;
|
||
* expect(undefined).to.not.be.null;
|
||
*
|
||
* @name null
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('null', function () {
|
||
this.assert(
|
||
null === flag(this, 'object')
|
||
, 'expected #{this} to be null'
|
||
, 'expected #{this} not to be null'
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .undefined
|
||
*
|
||
* Asserts that the target is `undefined`.
|
||
*
|
||
* expect(undefined).to.be.undefined;
|
||
* expect(null).to.not.be.undefined;
|
||
*
|
||
* @name undefined
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('undefined', function () {
|
||
this.assert(
|
||
undefined === flag(this, 'object')
|
||
, 'expected #{this} to be undefined'
|
||
, 'expected #{this} not to be undefined'
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .exist
|
||
*
|
||
* Asserts that the target is neither `null` nor `undefined`.
|
||
*
|
||
* var foo = 'hi'
|
||
* , bar = null
|
||
* , baz;
|
||
*
|
||
* expect(foo).to.exist;
|
||
* expect(bar).to.not.exist;
|
||
* expect(baz).to.not.exist;
|
||
*
|
||
* @name exist
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('exist', function () {
|
||
this.assert(
|
||
null != flag(this, 'object')
|
||
, 'expected #{this} to exist'
|
||
, 'expected #{this} to not exist'
|
||
);
|
||
});
|
||
|
||
|
||
/**
|
||
* ### .empty
|
||
*
|
||
* Asserts that the target's length is `0`. For arrays and strings, it checks
|
||
* the `length` property. For objects, it gets the count of
|
||
* enumerable keys.
|
||
*
|
||
* expect([]).to.be.empty;
|
||
* expect('').to.be.empty;
|
||
* expect({}).to.be.empty;
|
||
*
|
||
* @name empty
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('empty', function () {
|
||
var obj = flag(this, 'object')
|
||
, expected = obj;
|
||
|
||
if (Array.isArray(obj) || 'string' === typeof object) {
|
||
expected = obj.length;
|
||
} else if (typeof obj === 'object') {
|
||
expected = Object.keys(obj).length;
|
||
}
|
||
|
||
this.assert(
|
||
!expected
|
||
, 'expected #{this} to be empty'
|
||
, 'expected #{this} not to be empty'
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .arguments
|
||
*
|
||
* Asserts that the target is an arguments object.
|
||
*
|
||
* function test () {
|
||
* expect(arguments).to.be.arguments;
|
||
* }
|
||
*
|
||
* @name arguments
|
||
* @alias Arguments
|
||
* @api public
|
||
*/
|
||
|
||
function checkArguments () {
|
||
var obj = flag(this, 'object')
|
||
, type = Object.prototype.toString.call(obj);
|
||
this.assert(
|
||
'[object Arguments]' === type
|
||
, 'expected #{this} to be arguments but got ' + type
|
||
, 'expected #{this} to not be arguments'
|
||
);
|
||
}
|
||
|
||
Assertion.addProperty('arguments', checkArguments);
|
||
Assertion.addProperty('Arguments', checkArguments);
|
||
|
||
/**
|
||
* ### .equal(value)
|
||
*
|
||
* Asserts that the target is strictly equal (`===`) to `value`.
|
||
* Alternately, if the `deep` flag is set, asserts that
|
||
* the target is deeply equal to `value`.
|
||
*
|
||
* expect('hello').to.equal('hello');
|
||
* expect(42).to.equal(42);
|
||
* expect(1).to.not.equal(true);
|
||
* expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
|
||
* expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
|
||
*
|
||
* @name equal
|
||
* @alias equals
|
||
* @alias eq
|
||
* @alias deep.equal
|
||
* @param {Mixed} value
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertEqual (val, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
if (flag(this, 'deep')) {
|
||
return this.eql(val);
|
||
} else {
|
||
this.assert(
|
||
val === obj
|
||
, 'expected #{this} to equal #{exp}'
|
||
, 'expected #{this} to not equal #{exp}'
|
||
, val
|
||
, this._obj
|
||
, true
|
||
);
|
||
}
|
||
}
|
||
|
||
Assertion.addMethod('equal', assertEqual);
|
||
Assertion.addMethod('equals', assertEqual);
|
||
Assertion.addMethod('eq', assertEqual);
|
||
|
||
/**
|
||
* ### .eql(value)
|
||
*
|
||
* Asserts that the target is deeply equal to `value`.
|
||
*
|
||
* expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
|
||
* expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);
|
||
*
|
||
* @name eql
|
||
* @alias eqls
|
||
* @param {Mixed} value
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertEql(obj, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
this.assert(
|
||
_.eql(obj, flag(this, 'object'))
|
||
, 'expected #{this} to deeply equal #{exp}'
|
||
, 'expected #{this} to not deeply equal #{exp}'
|
||
, obj
|
||
, this._obj
|
||
, true
|
||
);
|
||
}
|
||
|
||
Assertion.addMethod('eql', assertEql);
|
||
Assertion.addMethod('eqls', assertEql);
|
||
|
||
/**
|
||
* ### .above(value)
|
||
*
|
||
* Asserts that the target is greater than `value`.
|
||
*
|
||
* expect(10).to.be.above(5);
|
||
*
|
||
* Can also be used in conjunction with `length` to
|
||
* assert a minimum length. The benefit being a
|
||
* more informative error message than if the length
|
||
* was supplied directly.
|
||
*
|
||
* expect('foo').to.have.length.above(2);
|
||
* expect([ 1, 2, 3 ]).to.have.length.above(2);
|
||
*
|
||
* @name above
|
||
* @alias gt
|
||
* @alias greaterThan
|
||
* @param {Number} value
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertAbove (n, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
if (flag(this, 'doLength')) {
|
||
new Assertion(obj, msg).to.have.property('length');
|
||
var len = obj.length;
|
||
this.assert(
|
||
len > n
|
||
, 'expected #{this} to have a length above #{exp} but got #{act}'
|
||
, 'expected #{this} to not have a length above #{exp}'
|
||
, n
|
||
, len
|
||
);
|
||
} else {
|
||
this.assert(
|
||
obj > n
|
||
, 'expected #{this} to be above ' + n
|
||
, 'expected #{this} to be at most ' + n
|
||
);
|
||
}
|
||
}
|
||
|
||
Assertion.addMethod('above', assertAbove);
|
||
Assertion.addMethod('gt', assertAbove);
|
||
Assertion.addMethod('greaterThan', assertAbove);
|
||
|
||
/**
|
||
* ### .least(value)
|
||
*
|
||
* Asserts that the target is greater than or equal to `value`.
|
||
*
|
||
* expect(10).to.be.at.least(10);
|
||
*
|
||
* Can also be used in conjunction with `length` to
|
||
* assert a minimum length. The benefit being a
|
||
* more informative error message than if the length
|
||
* was supplied directly.
|
||
*
|
||
* expect('foo').to.have.length.of.at.least(2);
|
||
* expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);
|
||
*
|
||
* @name least
|
||
* @alias gte
|
||
* @param {Number} value
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertLeast (n, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
if (flag(this, 'doLength')) {
|
||
new Assertion(obj, msg).to.have.property('length');
|
||
var len = obj.length;
|
||
this.assert(
|
||
len >= n
|
||
, 'expected #{this} to have a length at least #{exp} but got #{act}'
|
||
, 'expected #{this} to have a length below #{exp}'
|
||
, n
|
||
, len
|
||
);
|
||
} else {
|
||
this.assert(
|
||
obj >= n
|
||
, 'expected #{this} to be at least ' + n
|
||
, 'expected #{this} to be below ' + n
|
||
);
|
||
}
|
||
}
|
||
|
||
Assertion.addMethod('least', assertLeast);
|
||
Assertion.addMethod('gte', assertLeast);
|
||
|
||
/**
|
||
* ### .below(value)
|
||
*
|
||
* Asserts that the target is less than `value`.
|
||
*
|
||
* expect(5).to.be.below(10);
|
||
*
|
||
* Can also be used in conjunction with `length` to
|
||
* assert a maximum length. The benefit being a
|
||
* more informative error message than if the length
|
||
* was supplied directly.
|
||
*
|
||
* expect('foo').to.have.length.below(4);
|
||
* expect([ 1, 2, 3 ]).to.have.length.below(4);
|
||
*
|
||
* @name below
|
||
* @alias lt
|
||
* @alias lessThan
|
||
* @param {Number} value
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertBelow (n, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
if (flag(this, 'doLength')) {
|
||
new Assertion(obj, msg).to.have.property('length');
|
||
var len = obj.length;
|
||
this.assert(
|
||
len < n
|
||
, 'expected #{this} to have a length below #{exp} but got #{act}'
|
||
, 'expected #{this} to not have a length below #{exp}'
|
||
, n
|
||
, len
|
||
);
|
||
} else {
|
||
this.assert(
|
||
obj < n
|
||
, 'expected #{this} to be below ' + n
|
||
, 'expected #{this} to be at least ' + n
|
||
);
|
||
}
|
||
}
|
||
|
||
Assertion.addMethod('below', assertBelow);
|
||
Assertion.addMethod('lt', assertBelow);
|
||
Assertion.addMethod('lessThan', assertBelow);
|
||
|
||
/**
|
||
* ### .most(value)
|
||
*
|
||
* Asserts that the target is less than or equal to `value`.
|
||
*
|
||
* expect(5).to.be.at.most(5);
|
||
*
|
||
* Can also be used in conjunction with `length` to
|
||
* assert a maximum length. The benefit being a
|
||
* more informative error message than if the length
|
||
* was supplied directly.
|
||
*
|
||
* expect('foo').to.have.length.of.at.most(4);
|
||
* expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
|
||
*
|
||
* @name most
|
||
* @alias lte
|
||
* @param {Number} value
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertMost (n, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
if (flag(this, 'doLength')) {
|
||
new Assertion(obj, msg).to.have.property('length');
|
||
var len = obj.length;
|
||
this.assert(
|
||
len <= n
|
||
, 'expected #{this} to have a length at most #{exp} but got #{act}'
|
||
, 'expected #{this} to have a length above #{exp}'
|
||
, n
|
||
, len
|
||
);
|
||
} else {
|
||
this.assert(
|
||
obj <= n
|
||
, 'expected #{this} to be at most ' + n
|
||
, 'expected #{this} to be above ' + n
|
||
);
|
||
}
|
||
}
|
||
|
||
Assertion.addMethod('most', assertMost);
|
||
Assertion.addMethod('lte', assertMost);
|
||
|
||
/**
|
||
* ### .within(start, finish)
|
||
*
|
||
* Asserts that the target is within a range.
|
||
*
|
||
* expect(7).to.be.within(5,10);
|
||
*
|
||
* Can also be used in conjunction with `length` to
|
||
* assert a length range. The benefit being a
|
||
* more informative error message than if the length
|
||
* was supplied directly.
|
||
*
|
||
* expect('foo').to.have.length.within(2,4);
|
||
* expect([ 1, 2, 3 ]).to.have.length.within(2,4);
|
||
*
|
||
* @name within
|
||
* @param {Number} start lowerbound inclusive
|
||
* @param {Number} finish upperbound inclusive
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('within', function (start, finish, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object')
|
||
, range = start + '..' + finish;
|
||
if (flag(this, 'doLength')) {
|
||
new Assertion(obj, msg).to.have.property('length');
|
||
var len = obj.length;
|
||
this.assert(
|
||
len >= start && len <= finish
|
||
, 'expected #{this} to have a length within ' + range
|
||
, 'expected #{this} to not have a length within ' + range
|
||
);
|
||
} else {
|
||
this.assert(
|
||
obj >= start && obj <= finish
|
||
, 'expected #{this} to be within ' + range
|
||
, 'expected #{this} to not be within ' + range
|
||
);
|
||
}
|
||
});
|
||
|
||
/**
|
||
* ### .instanceof(constructor)
|
||
*
|
||
* Asserts that the target is an instance of `constructor`.
|
||
*
|
||
* var Tea = function (name) { this.name = name; }
|
||
* , Chai = new Tea('chai');
|
||
*
|
||
* expect(Chai).to.be.an.instanceof(Tea);
|
||
* expect([ 1, 2, 3 ]).to.be.instanceof(Array);
|
||
*
|
||
* @name instanceof
|
||
* @param {Constructor} constructor
|
||
* @param {String} message _optional_
|
||
* @alias instanceOf
|
||
* @api public
|
||
*/
|
||
|
||
function assertInstanceOf (constructor, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var name = _.getName(constructor);
|
||
this.assert(
|
||
flag(this, 'object') instanceof constructor
|
||
, 'expected #{this} to be an instance of ' + name
|
||
, 'expected #{this} to not be an instance of ' + name
|
||
);
|
||
};
|
||
|
||
Assertion.addMethod('instanceof', assertInstanceOf);
|
||
Assertion.addMethod('instanceOf', assertInstanceOf);
|
||
|
||
/**
|
||
* ### .property(name, [value])
|
||
*
|
||
* Asserts that the target has a property `name`, optionally asserting that
|
||
* the value of that property is strictly equal to `value`.
|
||
* If the `deep` flag is set, you can use dot- and bracket-notation for deep
|
||
* references into objects and arrays.
|
||
*
|
||
* // simple referencing
|
||
* var obj = { foo: 'bar' };
|
||
* expect(obj).to.have.property('foo');
|
||
* expect(obj).to.have.property('foo', 'bar');
|
||
*
|
||
* // deep referencing
|
||
* var deepObj = {
|
||
* green: { tea: 'matcha' }
|
||
* , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
|
||
* };
|
||
*
|
||
* expect(deepObj).to.have.deep.property('green.tea', 'matcha');
|
||
* expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
|
||
* expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');
|
||
*
|
||
* You can also use an array as the starting point of a `deep.property`
|
||
* assertion, or traverse nested arrays.
|
||
*
|
||
* var arr = [
|
||
* [ 'chai', 'matcha', 'konacha' ]
|
||
* , [ { tea: 'chai' }
|
||
* , { tea: 'matcha' }
|
||
* , { tea: 'konacha' } ]
|
||
* ];
|
||
*
|
||
* expect(arr).to.have.deep.property('[0][1]', 'matcha');
|
||
* expect(arr).to.have.deep.property('[1][2].tea', 'konacha');
|
||
*
|
||
* Furthermore, `property` changes the subject of the assertion
|
||
* to be the value of that property from the original object. This
|
||
* permits for further chainable assertions on that property.
|
||
*
|
||
* expect(obj).to.have.property('foo')
|
||
* .that.is.a('string');
|
||
* expect(deepObj).to.have.property('green')
|
||
* .that.is.an('object')
|
||
* .that.deep.equals({ tea: 'matcha' });
|
||
* expect(deepObj).to.have.property('teas')
|
||
* .that.is.an('array')
|
||
* .with.deep.property('[2]')
|
||
* .that.deep.equals({ tea: 'konacha' });
|
||
*
|
||
* Note that dots and bracket in `name` must be backslash-escaped when
|
||
* the `deep` flag is set, while they must NOT be escaped when the `deep`
|
||
* flag is not set.
|
||
*
|
||
* // simple referencing
|
||
* var css = { '.link[target]': 42 };
|
||
* expect(css).to.have.property('.link[target]', 42);
|
||
*
|
||
* // deep referencing
|
||
* var deepCss = { '.link': { '[target]': 42 }};
|
||
* expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
|
||
*
|
||
* @name property
|
||
* @alias deep.property
|
||
* @param {String} name
|
||
* @param {Mixed} value (optional)
|
||
* @param {String} message _optional_
|
||
* @returns value of property for chaining
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('property', function (name, val, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
|
||
var isDeep = !!flag(this, 'deep')
|
||
, descriptor = isDeep ? 'deep property ' : 'property '
|
||
, negate = flag(this, 'negate')
|
||
, obj = flag(this, 'object')
|
||
, pathInfo = isDeep ? _.getPathInfo(name, obj) : null
|
||
, hasProperty = isDeep
|
||
? pathInfo.exists
|
||
: _.hasProperty(name, obj)
|
||
, value = isDeep
|
||
? pathInfo.value
|
||
: obj[name];
|
||
|
||
if (negate && undefined !== val) {
|
||
if (undefined === value) {
|
||
msg = (msg != null) ? msg + ': ' : '';
|
||
throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));
|
||
}
|
||
} else {
|
||
this.assert(
|
||
hasProperty
|
||
, 'expected #{this} to have a ' + descriptor + _.inspect(name)
|
||
, 'expected #{this} to not have ' + descriptor + _.inspect(name));
|
||
}
|
||
|
||
if (undefined !== val) {
|
||
this.assert(
|
||
val === value
|
||
, 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
|
||
, 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'
|
||
, val
|
||
, value
|
||
);
|
||
}
|
||
|
||
flag(this, 'object', value);
|
||
});
|
||
|
||
|
||
/**
|
||
* ### .ownProperty(name)
|
||
*
|
||
* Asserts that the target has an own property `name`.
|
||
*
|
||
* expect('test').to.have.ownProperty('length');
|
||
*
|
||
* @name ownProperty
|
||
* @alias haveOwnProperty
|
||
* @param {String} name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertOwnProperty (name, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
this.assert(
|
||
obj.hasOwnProperty(name)
|
||
, 'expected #{this} to have own property ' + _.inspect(name)
|
||
, 'expected #{this} to not have own property ' + _.inspect(name)
|
||
);
|
||
}
|
||
|
||
Assertion.addMethod('ownProperty', assertOwnProperty);
|
||
Assertion.addMethod('haveOwnProperty', assertOwnProperty);
|
||
|
||
/**
|
||
* ### .ownPropertyDescriptor(name[, descriptor[, message]])
|
||
*
|
||
* Asserts that the target has an own property descriptor `name`, that optionally matches `descriptor`.
|
||
*
|
||
* expect('test').to.have.ownPropertyDescriptor('length');
|
||
* expect('test').to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 4 });
|
||
* expect('test').not.to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 3 });
|
||
* expect('test').ownPropertyDescriptor('length').to.have.property('enumerable', false);
|
||
* expect('test').ownPropertyDescriptor('length').to.have.keys('value');
|
||
*
|
||
* @name ownPropertyDescriptor
|
||
* @alias haveOwnPropertyDescriptor
|
||
* @param {String} name
|
||
* @param {Object} descriptor _optional_
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertOwnPropertyDescriptor (name, descriptor, msg) {
|
||
if (typeof descriptor === 'string') {
|
||
msg = descriptor;
|
||
descriptor = null;
|
||
}
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name);
|
||
if (actualDescriptor && descriptor) {
|
||
this.assert(
|
||
_.eql(descriptor, actualDescriptor)
|
||
, 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor)
|
||
, 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor)
|
||
, descriptor
|
||
, actualDescriptor
|
||
, true
|
||
);
|
||
} else {
|
||
this.assert(
|
||
actualDescriptor
|
||
, 'expected #{this} to have an own property descriptor for ' + _.inspect(name)
|
||
, 'expected #{this} to not have an own property descriptor for ' + _.inspect(name)
|
||
);
|
||
}
|
||
flag(this, 'object', actualDescriptor);
|
||
}
|
||
|
||
Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor);
|
||
Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor);
|
||
|
||
/**
|
||
* ### .length(value)
|
||
*
|
||
* Asserts that the target's `length` property has
|
||
* the expected value.
|
||
*
|
||
* expect([ 1, 2, 3]).to.have.length(3);
|
||
* expect('foobar').to.have.length(6);
|
||
*
|
||
* Can also be used as a chain precursor to a value
|
||
* comparison for the length property.
|
||
*
|
||
* expect('foo').to.have.length.above(2);
|
||
* expect([ 1, 2, 3 ]).to.have.length.above(2);
|
||
* expect('foo').to.have.length.below(4);
|
||
* expect([ 1, 2, 3 ]).to.have.length.below(4);
|
||
* expect('foo').to.have.length.within(2,4);
|
||
* expect([ 1, 2, 3 ]).to.have.length.within(2,4);
|
||
*
|
||
* @name length
|
||
* @alias lengthOf
|
||
* @param {Number} length
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertLengthChain () {
|
||
flag(this, 'doLength', true);
|
||
}
|
||
|
||
function assertLength (n, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
new Assertion(obj, msg).to.have.property('length');
|
||
var len = obj.length;
|
||
|
||
this.assert(
|
||
len == n
|
||
, 'expected #{this} to have a length of #{exp} but got #{act}'
|
||
, 'expected #{this} to not have a length of #{act}'
|
||
, n
|
||
, len
|
||
);
|
||
}
|
||
|
||
Assertion.addChainableMethod('length', assertLength, assertLengthChain);
|
||
Assertion.addMethod('lengthOf', assertLength);
|
||
|
||
/**
|
||
* ### .match(regexp)
|
||
*
|
||
* Asserts that the target matches a regular expression.
|
||
*
|
||
* expect('foobar').to.match(/^foo/);
|
||
*
|
||
* @name match
|
||
* @param {RegExp} RegularExpression
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('match', function (re, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
this.assert(
|
||
re.exec(obj)
|
||
, 'expected #{this} to match ' + re
|
||
, 'expected #{this} not to match ' + re
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .string(string)
|
||
*
|
||
* Asserts that the string target contains another string.
|
||
*
|
||
* expect('foobar').to.have.string('bar');
|
||
*
|
||
* @name string
|
||
* @param {String} string
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('string', function (str, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
new Assertion(obj, msg).is.a('string');
|
||
|
||
this.assert(
|
||
~obj.indexOf(str)
|
||
, 'expected #{this} to contain ' + _.inspect(str)
|
||
, 'expected #{this} to not contain ' + _.inspect(str)
|
||
);
|
||
});
|
||
|
||
|
||
/**
|
||
* ### .keys(key1, [key2], [...])
|
||
*
|
||
* Asserts that the target contains any or all of the passed-in keys.
|
||
* Use in combination with `any`, `all`, `contains`, or `have` will affect
|
||
* what will pass.
|
||
*
|
||
* When used in conjunction with `any`, at least one key that is passed
|
||
* in must exist in the target object. This is regardless whether or not
|
||
* the `have` or `contain` qualifiers are used. Note, either `any` or `all`
|
||
* should be used in the assertion. If neither are used, the assertion is
|
||
* defaulted to `all`.
|
||
*
|
||
* When both `all` and `contain` are used, the target object must have at
|
||
* least all of the passed-in keys but may have more keys not listed.
|
||
*
|
||
* When both `all` and `have` are used, the target object must both contain
|
||
* all of the passed-in keys AND the number of keys in the target object must
|
||
* match the number of keys passed in (in other words, a target object must
|
||
* have all and only all of the passed-in keys).
|
||
*
|
||
* expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz');
|
||
* expect({ foo: 1, bar: 2 }).to.have.any.keys('foo');
|
||
* expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz');
|
||
* expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']);
|
||
* expect({ foo: 1, bar: 2 }).to.contain.any.keys({'foo': 6});
|
||
* expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']);
|
||
* expect({ foo: 1, bar: 2 }).to.have.all.keys({'bar': 6, 'foo': 7});
|
||
* expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']);
|
||
* expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys([{'bar': 6}}]);
|
||
*
|
||
*
|
||
* @name keys
|
||
* @alias key
|
||
* @param {String...|Array|Object} keys
|
||
* @api public
|
||
*/
|
||
|
||
function assertKeys (keys) {
|
||
var obj = flag(this, 'object')
|
||
, str
|
||
, ok = true
|
||
, mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments';
|
||
|
||
switch (_.type(keys)) {
|
||
case "array":
|
||
if (arguments.length > 1) throw (new Error(mixedArgsMsg));
|
||
break;
|
||
case "object":
|
||
if (arguments.length > 1) throw (new Error(mixedArgsMsg));
|
||
keys = Object.keys(keys);
|
||
break;
|
||
default:
|
||
keys = Array.prototype.slice.call(arguments);
|
||
}
|
||
|
||
if (!keys.length) throw new Error('keys required');
|
||
|
||
var actual = Object.keys(obj)
|
||
, expected = keys
|
||
, len = keys.length
|
||
, any = flag(this, 'any')
|
||
, all = flag(this, 'all');
|
||
|
||
if (!any && !all) {
|
||
all = true;
|
||
}
|
||
|
||
// Has any
|
||
if (any) {
|
||
var intersection = expected.filter(function(key) {
|
||
return ~actual.indexOf(key);
|
||
});
|
||
ok = intersection.length > 0;
|
||
}
|
||
|
||
// Has all
|
||
if (all) {
|
||
ok = keys.every(function(key){
|
||
return ~actual.indexOf(key);
|
||
});
|
||
if (!flag(this, 'negate') && !flag(this, 'contains')) {
|
||
ok = ok && keys.length == actual.length;
|
||
}
|
||
}
|
||
|
||
// Key string
|
||
if (len > 1) {
|
||
keys = keys.map(function(key){
|
||
return _.inspect(key);
|
||
});
|
||
var last = keys.pop();
|
||
if (all) {
|
||
str = keys.join(', ') + ', and ' + last;
|
||
}
|
||
if (any) {
|
||
str = keys.join(', ') + ', or ' + last;
|
||
}
|
||
} else {
|
||
str = _.inspect(keys[0]);
|
||
}
|
||
|
||
// Form
|
||
str = (len > 1 ? 'keys ' : 'key ') + str;
|
||
|
||
// Have / include
|
||
str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;
|
||
|
||
// Assertion
|
||
this.assert(
|
||
ok
|
||
, 'expected #{this} to ' + str
|
||
, 'expected #{this} to not ' + str
|
||
, expected.slice(0).sort()
|
||
, actual.sort()
|
||
, true
|
||
);
|
||
}
|
||
|
||
Assertion.addMethod('keys', assertKeys);
|
||
Assertion.addMethod('key', assertKeys);
|
||
|
||
/**
|
||
* ### .throw(constructor)
|
||
*
|
||
* Asserts that the function target will throw a specific error, or specific type of error
|
||
* (as determined using `instanceof`), optionally with a RegExp or string inclusion test
|
||
* for the error's message.
|
||
*
|
||
* var err = new ReferenceError('This is a bad function.');
|
||
* var fn = function () { throw err; }
|
||
* expect(fn).to.throw(ReferenceError);
|
||
* expect(fn).to.throw(Error);
|
||
* expect(fn).to.throw(/bad function/);
|
||
* expect(fn).to.not.throw('good function');
|
||
* expect(fn).to.throw(ReferenceError, /bad function/);
|
||
* expect(fn).to.throw(err);
|
||
* expect(fn).to.not.throw(new RangeError('Out of range.'));
|
||
*
|
||
* Please note that when a throw expectation is negated, it will check each
|
||
* parameter independently, starting with error constructor type. The appropriate way
|
||
* to check for the existence of a type of error but for a message that does not match
|
||
* is to use `and`.
|
||
*
|
||
* expect(fn).to.throw(ReferenceError)
|
||
* .and.not.throw(/good function/);
|
||
*
|
||
* @name throw
|
||
* @alias throws
|
||
* @alias Throw
|
||
* @param {ErrorConstructor} constructor
|
||
* @param {String|RegExp} expected error message
|
||
* @param {String} message _optional_
|
||
* @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
|
||
* @returns error for chaining (null if no error)
|
||
* @api public
|
||
*/
|
||
|
||
function assertThrows (constructor, errMsg, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
new Assertion(obj, msg).is.a('function');
|
||
|
||
var thrown = false
|
||
, desiredError = null
|
||
, name = null
|
||
, thrownError = null;
|
||
|
||
if (arguments.length === 0) {
|
||
errMsg = null;
|
||
constructor = null;
|
||
} else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
|
||
errMsg = constructor;
|
||
constructor = null;
|
||
} else if (constructor && constructor instanceof Error) {
|
||
desiredError = constructor;
|
||
constructor = null;
|
||
errMsg = null;
|
||
} else if (typeof constructor === 'function') {
|
||
name = constructor.prototype.name || constructor.name;
|
||
if (name === 'Error' && constructor !== Error) {
|
||
name = (new constructor()).name;
|
||
}
|
||
} else {
|
||
constructor = null;
|
||
}
|
||
|
||
try {
|
||
obj();
|
||
} catch (err) {
|
||
// first, check desired error
|
||
if (desiredError) {
|
||
this.assert(
|
||
err === desiredError
|
||
, 'expected #{this} to throw #{exp} but #{act} was thrown'
|
||
, 'expected #{this} to not throw #{exp}'
|
||
, (desiredError instanceof Error ? desiredError.toString() : desiredError)
|
||
, (err instanceof Error ? err.toString() : err)
|
||
);
|
||
|
||
flag(this, 'object', err);
|
||
return this;
|
||
}
|
||
|
||
// next, check constructor
|
||
if (constructor) {
|
||
this.assert(
|
||
err instanceof constructor
|
||
, 'expected #{this} to throw #{exp} but #{act} was thrown'
|
||
, 'expected #{this} to not throw #{exp} but #{act} was thrown'
|
||
, name
|
||
, (err instanceof Error ? err.toString() : err)
|
||
);
|
||
|
||
if (!errMsg) {
|
||
flag(this, 'object', err);
|
||
return this;
|
||
}
|
||
}
|
||
|
||
// next, check message
|
||
var message = 'object' === _.type(err) && "message" in err
|
||
? err.message
|
||
: '' + err;
|
||
|
||
if ((message != null) && errMsg && errMsg instanceof RegExp) {
|
||
this.assert(
|
||
errMsg.exec(message)
|
||
, 'expected #{this} to throw error matching #{exp} but got #{act}'
|
||
, 'expected #{this} to throw error not matching #{exp}'
|
||
, errMsg
|
||
, message
|
||
);
|
||
|
||
flag(this, 'object', err);
|
||
return this;
|
||
} else if ((message != null) && errMsg && 'string' === typeof errMsg) {
|
||
this.assert(
|
||
~message.indexOf(errMsg)
|
||
, 'expected #{this} to throw error including #{exp} but got #{act}'
|
||
, 'expected #{this} to throw error not including #{act}'
|
||
, errMsg
|
||
, message
|
||
);
|
||
|
||
flag(this, 'object', err);
|
||
return this;
|
||
} else {
|
||
thrown = true;
|
||
thrownError = err;
|
||
}
|
||
}
|
||
|
||
var actuallyGot = ''
|
||
, expectedThrown = name !== null
|
||
? name
|
||
: desiredError
|
||
? '#{exp}' //_.inspect(desiredError)
|
||
: 'an error';
|
||
|
||
if (thrown) {
|
||
actuallyGot = ' but #{act} was thrown'
|
||
}
|
||
|
||
this.assert(
|
||
thrown === true
|
||
, 'expected #{this} to throw ' + expectedThrown + actuallyGot
|
||
, 'expected #{this} to not throw ' + expectedThrown + actuallyGot
|
||
, (desiredError instanceof Error ? desiredError.toString() : desiredError)
|
||
, (thrownError instanceof Error ? thrownError.toString() : thrownError)
|
||
);
|
||
|
||
flag(this, 'object', thrownError);
|
||
};
|
||
|
||
Assertion.addMethod('throw', assertThrows);
|
||
Assertion.addMethod('throws', assertThrows);
|
||
Assertion.addMethod('Throw', assertThrows);
|
||
|
||
/**
|
||
* ### .respondTo(method)
|
||
*
|
||
* Asserts that the object or class target will respond to a method.
|
||
*
|
||
* Klass.prototype.bar = function(){};
|
||
* expect(Klass).to.respondTo('bar');
|
||
* expect(obj).to.respondTo('bar');
|
||
*
|
||
* To check if a constructor will respond to a static function,
|
||
* set the `itself` flag.
|
||
*
|
||
* Klass.baz = function(){};
|
||
* expect(Klass).itself.to.respondTo('baz');
|
||
*
|
||
* @name respondTo
|
||
* @param {String} method
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('respondTo', function (method, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object')
|
||
, itself = flag(this, 'itself')
|
||
, context = ('function' === _.type(obj) && !itself)
|
||
? obj.prototype[method]
|
||
: obj[method];
|
||
|
||
this.assert(
|
||
'function' === typeof context
|
||
, 'expected #{this} to respond to ' + _.inspect(method)
|
||
, 'expected #{this} to not respond to ' + _.inspect(method)
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .itself
|
||
*
|
||
* Sets the `itself` flag, later used by the `respondTo` assertion.
|
||
*
|
||
* function Foo() {}
|
||
* Foo.bar = function() {}
|
||
* Foo.prototype.baz = function() {}
|
||
*
|
||
* expect(Foo).itself.to.respondTo('bar');
|
||
* expect(Foo).itself.not.to.respondTo('baz');
|
||
*
|
||
* @name itself
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addProperty('itself', function () {
|
||
flag(this, 'itself', true);
|
||
});
|
||
|
||
/**
|
||
* ### .satisfy(method)
|
||
*
|
||
* Asserts that the target passes a given truth test.
|
||
*
|
||
* expect(1).to.satisfy(function(num) { return num > 0; });
|
||
*
|
||
* @name satisfy
|
||
* @param {Function} matcher
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('satisfy', function (matcher, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
var result = matcher(obj);
|
||
this.assert(
|
||
result
|
||
, 'expected #{this} to satisfy ' + _.objDisplay(matcher)
|
||
, 'expected #{this} to not satisfy' + _.objDisplay(matcher)
|
||
, this.negate ? false : true
|
||
, result
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .closeTo(expected, delta)
|
||
*
|
||
* Asserts that the target is equal `expected`, to within a +/- `delta` range.
|
||
*
|
||
* expect(1.5).to.be.closeTo(1, 0.5);
|
||
*
|
||
* @name closeTo
|
||
* @param {Number} expected
|
||
* @param {Number} delta
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('closeTo', function (expected, delta, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
|
||
new Assertion(obj, msg).is.a('number');
|
||
if (_.type(expected) !== 'number' || _.type(delta) !== 'number') {
|
||
throw new Error('the arguments to closeTo must be numbers');
|
||
}
|
||
|
||
this.assert(
|
||
Math.abs(obj - expected) <= delta
|
||
, 'expected #{this} to be close to ' + expected + ' +/- ' + delta
|
||
, 'expected #{this} not to be close to ' + expected + ' +/- ' + delta
|
||
);
|
||
});
|
||
|
||
function isSubsetOf(subset, superset, cmp) {
|
||
return subset.every(function(elem) {
|
||
if (!cmp) return superset.indexOf(elem) !== -1;
|
||
|
||
return superset.some(function(elem2) {
|
||
return cmp(elem, elem2);
|
||
});
|
||
})
|
||
}
|
||
|
||
/**
|
||
* ### .members(set)
|
||
*
|
||
* Asserts that the target is a superset of `set`,
|
||
* or that the target and `set` have the same strictly-equal (===) members.
|
||
* Alternately, if the `deep` flag is set, set members are compared for deep
|
||
* equality.
|
||
*
|
||
* expect([1, 2, 3]).to.include.members([3, 2]);
|
||
* expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
|
||
*
|
||
* expect([4, 2]).to.have.members([2, 4]);
|
||
* expect([5, 2]).to.not.have.members([5, 2, 1]);
|
||
*
|
||
* expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]);
|
||
*
|
||
* @name members
|
||
* @param {Array} set
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
Assertion.addMethod('members', function (subset, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var obj = flag(this, 'object');
|
||
|
||
new Assertion(obj).to.be.an('array');
|
||
new Assertion(subset).to.be.an('array');
|
||
|
||
var cmp = flag(this, 'deep') ? _.eql : undefined;
|
||
|
||
if (flag(this, 'contains')) {
|
||
return this.assert(
|
||
isSubsetOf(subset, obj, cmp)
|
||
, 'expected #{this} to be a superset of #{act}'
|
||
, 'expected #{this} to not be a superset of #{act}'
|
||
, obj
|
||
, subset
|
||
);
|
||
}
|
||
|
||
this.assert(
|
||
isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp)
|
||
, 'expected #{this} to have the same members as #{act}'
|
||
, 'expected #{this} to not have the same members as #{act}'
|
||
, obj
|
||
, subset
|
||
);
|
||
});
|
||
|
||
/**
|
||
* ### .change(function)
|
||
*
|
||
* Asserts that a function changes an object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val += 3 };
|
||
* var noChangeFn = function() { return 'foo' + 'bar'; }
|
||
* expect(fn).to.change(obj, 'val');
|
||
* expect(noChangFn).to.not.change(obj, 'val')
|
||
*
|
||
* @name change
|
||
* @alias changes
|
||
* @alias Change
|
||
* @param {String} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertChanges (object, prop, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var fn = flag(this, 'object');
|
||
new Assertion(object, msg).to.have.property(prop);
|
||
new Assertion(fn).is.a('function');
|
||
|
||
var initial = object[prop];
|
||
fn();
|
||
|
||
this.assert(
|
||
initial !== object[prop]
|
||
, 'expected .' + prop + ' to change'
|
||
, 'expected .' + prop + ' to not change'
|
||
);
|
||
}
|
||
|
||
Assertion.addChainableMethod('change', assertChanges);
|
||
Assertion.addChainableMethod('changes', assertChanges);
|
||
|
||
/**
|
||
* ### .increase(function)
|
||
*
|
||
* Asserts that a function increases an object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 15 };
|
||
* expect(fn).to.increase(obj, 'val');
|
||
*
|
||
* @name increase
|
||
* @alias increases
|
||
* @alias Increase
|
||
* @param {String} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertIncreases (object, prop, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var fn = flag(this, 'object');
|
||
new Assertion(object, msg).to.have.property(prop);
|
||
new Assertion(fn).is.a('function');
|
||
|
||
var initial = object[prop];
|
||
fn();
|
||
|
||
this.assert(
|
||
object[prop] - initial > 0
|
||
, 'expected .' + prop + ' to increase'
|
||
, 'expected .' + prop + ' to not increase'
|
||
);
|
||
}
|
||
|
||
Assertion.addChainableMethod('increase', assertIncreases);
|
||
Assertion.addChainableMethod('increases', assertIncreases);
|
||
|
||
/**
|
||
* ### .decrease(function)
|
||
*
|
||
* Asserts that a function decreases an object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 5 };
|
||
* expect(fn).to.decrease(obj, 'val');
|
||
*
|
||
* @name decrease
|
||
* @alias decreases
|
||
* @alias Decrease
|
||
* @param {String} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
function assertDecreases (object, prop, msg) {
|
||
if (msg) flag(this, 'message', msg);
|
||
var fn = flag(this, 'object');
|
||
new Assertion(object, msg).to.have.property(prop);
|
||
new Assertion(fn).is.a('function');
|
||
|
||
var initial = object[prop];
|
||
fn();
|
||
|
||
this.assert(
|
||
object[prop] - initial < 0
|
||
, 'expected .' + prop + ' to decrease'
|
||
, 'expected .' + prop + ' to not decrease'
|
||
);
|
||
}
|
||
|
||
Assertion.addChainableMethod('decrease', assertDecreases);
|
||
Assertion.addChainableMethod('decreases', assertDecreases);
|
||
|
||
};
|
||
|
||
},{}],19:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
|
||
module.exports = function (chai, util) {
|
||
|
||
/*!
|
||
* Chai dependencies.
|
||
*/
|
||
|
||
var Assertion = chai.Assertion
|
||
, flag = util.flag;
|
||
|
||
/*!
|
||
* Module export.
|
||
*/
|
||
|
||
/**
|
||
* ### assert(expression, message)
|
||
*
|
||
* Write your own test expressions.
|
||
*
|
||
* assert('foo' !== 'bar', 'foo is not bar');
|
||
* assert(Array.isArray([]), 'empty arrays are arrays');
|
||
*
|
||
* @param {Mixed} expression to test for truthiness
|
||
* @param {String} message to display on error
|
||
* @name assert
|
||
* @api public
|
||
*/
|
||
|
||
var assert = chai.assert = function (express, errmsg) {
|
||
var test = new Assertion(null, null, chai.assert);
|
||
test.assert(
|
||
express
|
||
, errmsg
|
||
, '[ negation message unavailable ]'
|
||
);
|
||
};
|
||
|
||
/**
|
||
* ### .fail(actual, expected, [message], [operator])
|
||
*
|
||
* Throw a failure. Node.js `assert` module-compatible.
|
||
*
|
||
* @name fail
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @param {String} operator
|
||
* @api public
|
||
*/
|
||
|
||
assert.fail = function (actual, expected, message, operator) {
|
||
message = message || 'assert.fail()';
|
||
throw new chai.AssertionError(message, {
|
||
actual: actual
|
||
, expected: expected
|
||
, operator: operator
|
||
}, assert.fail);
|
||
};
|
||
|
||
/**
|
||
* ### .ok(object, [message])
|
||
*
|
||
* Asserts that `object` is truthy.
|
||
*
|
||
* assert.ok('everything', 'everything is ok');
|
||
* assert.ok(false, 'this will fail');
|
||
*
|
||
* @name ok
|
||
* @param {Mixed} object to test
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.ok = function (val, msg) {
|
||
new Assertion(val, msg).is.ok;
|
||
};
|
||
|
||
/**
|
||
* ### .notOk(object, [message])
|
||
*
|
||
* Asserts that `object` is falsy.
|
||
*
|
||
* assert.notOk('everything', 'this will fail');
|
||
* assert.notOk(false, 'this will pass');
|
||
*
|
||
* @name notOk
|
||
* @param {Mixed} object to test
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notOk = function (val, msg) {
|
||
new Assertion(val, msg).is.not.ok;
|
||
};
|
||
|
||
/**
|
||
* ### .equal(actual, expected, [message])
|
||
*
|
||
* Asserts non-strict equality (`==`) of `actual` and `expected`.
|
||
*
|
||
* assert.equal(3, '3', '== coerces values to strings');
|
||
*
|
||
* @name equal
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.equal = function (act, exp, msg) {
|
||
var test = new Assertion(act, msg, assert.equal);
|
||
|
||
test.assert(
|
||
exp == flag(test, 'object')
|
||
, 'expected #{this} to equal #{exp}'
|
||
, 'expected #{this} to not equal #{act}'
|
||
, exp
|
||
, act
|
||
);
|
||
};
|
||
|
||
/**
|
||
* ### .notEqual(actual, expected, [message])
|
||
*
|
||
* Asserts non-strict inequality (`!=`) of `actual` and `expected`.
|
||
*
|
||
* assert.notEqual(3, 4, 'these numbers are not equal');
|
||
*
|
||
* @name notEqual
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notEqual = function (act, exp, msg) {
|
||
var test = new Assertion(act, msg, assert.notEqual);
|
||
|
||
test.assert(
|
||
exp != flag(test, 'object')
|
||
, 'expected #{this} to not equal #{exp}'
|
||
, 'expected #{this} to equal #{act}'
|
||
, exp
|
||
, act
|
||
);
|
||
};
|
||
|
||
/**
|
||
* ### .strictEqual(actual, expected, [message])
|
||
*
|
||
* Asserts strict equality (`===`) of `actual` and `expected`.
|
||
*
|
||
* assert.strictEqual(true, true, 'these booleans are strictly equal');
|
||
*
|
||
* @name strictEqual
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.strictEqual = function (act, exp, msg) {
|
||
new Assertion(act, msg).to.equal(exp);
|
||
};
|
||
|
||
/**
|
||
* ### .notStrictEqual(actual, expected, [message])
|
||
*
|
||
* Asserts strict inequality (`!==`) of `actual` and `expected`.
|
||
*
|
||
* assert.notStrictEqual(3, '3', 'no coercion for strict equality');
|
||
*
|
||
* @name notStrictEqual
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notStrictEqual = function (act, exp, msg) {
|
||
new Assertion(act, msg).to.not.equal(exp);
|
||
};
|
||
|
||
/**
|
||
* ### .deepEqual(actual, expected, [message])
|
||
*
|
||
* Asserts that `actual` is deeply equal to `expected`.
|
||
*
|
||
* assert.deepEqual({ tea: 'green' }, { tea: 'green' });
|
||
*
|
||
* @name deepEqual
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.deepEqual = function (act, exp, msg) {
|
||
new Assertion(act, msg).to.eql(exp);
|
||
};
|
||
|
||
/**
|
||
* ### .notDeepEqual(actual, expected, [message])
|
||
*
|
||
* Assert that `actual` is not deeply equal to `expected`.
|
||
*
|
||
* assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });
|
||
*
|
||
* @name notDeepEqual
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notDeepEqual = function (act, exp, msg) {
|
||
new Assertion(act, msg).to.not.eql(exp);
|
||
};
|
||
|
||
/**
|
||
* ### .isTrue(value, [message])
|
||
*
|
||
* Asserts that `value` is true.
|
||
*
|
||
* var teaServed = true;
|
||
* assert.isTrue(teaServed, 'the tea has been served');
|
||
*
|
||
* @name isTrue
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isAbove = function (val, abv, msg) {
|
||
new Assertion(val, msg).to.be.above(abv);
|
||
};
|
||
|
||
/**
|
||
* ### .isAbove(valueToCheck, valueToBeAbove, [message])
|
||
*
|
||
* Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove`
|
||
*
|
||
* assert.isAbove(5, 2, '5 is strictly greater than 2');
|
||
*
|
||
* @name isAbove
|
||
* @param {Mixed} valueToCheck
|
||
* @param {Mixed} valueToBeAbove
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isBelow = function (val, blw, msg) {
|
||
new Assertion(val, msg).to.be.below(blw);
|
||
};
|
||
|
||
/**
|
||
* ### .isBelow(valueToCheck, valueToBeBelow, [message])
|
||
*
|
||
* Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow`
|
||
*
|
||
* assert.isBelow(3, 6, '3 is strictly less than 6');
|
||
*
|
||
* @name isBelow
|
||
* @param {Mixed} valueToCheck
|
||
* @param {Mixed} valueToBeBelow
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isTrue = function (val, msg) {
|
||
new Assertion(val, msg).is['true'];
|
||
};
|
||
|
||
/**
|
||
* ### .isFalse(value, [message])
|
||
*
|
||
* Asserts that `value` is false.
|
||
*
|
||
* var teaServed = false;
|
||
* assert.isFalse(teaServed, 'no tea yet? hmm...');
|
||
*
|
||
* @name isFalse
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isFalse = function (val, msg) {
|
||
new Assertion(val, msg).is['false'];
|
||
};
|
||
|
||
/**
|
||
* ### .isNull(value, [message])
|
||
*
|
||
* Asserts that `value` is null.
|
||
*
|
||
* assert.isNull(err, 'there was no error');
|
||
*
|
||
* @name isNull
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNull = function (val, msg) {
|
||
new Assertion(val, msg).to.equal(null);
|
||
};
|
||
|
||
/**
|
||
* ### .isNotNull(value, [message])
|
||
*
|
||
* Asserts that `value` is not null.
|
||
*
|
||
* var tea = 'tasty chai';
|
||
* assert.isNotNull(tea, 'great, time for tea!');
|
||
*
|
||
* @name isNotNull
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotNull = function (val, msg) {
|
||
new Assertion(val, msg).to.not.equal(null);
|
||
};
|
||
|
||
/**
|
||
* ### .isUndefined(value, [message])
|
||
*
|
||
* Asserts that `value` is `undefined`.
|
||
*
|
||
* var tea;
|
||
* assert.isUndefined(tea, 'no tea defined');
|
||
*
|
||
* @name isUndefined
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isUndefined = function (val, msg) {
|
||
new Assertion(val, msg).to.equal(undefined);
|
||
};
|
||
|
||
/**
|
||
* ### .isDefined(value, [message])
|
||
*
|
||
* Asserts that `value` is not `undefined`.
|
||
*
|
||
* var tea = 'cup of chai';
|
||
* assert.isDefined(tea, 'tea has been defined');
|
||
*
|
||
* @name isDefined
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isDefined = function (val, msg) {
|
||
new Assertion(val, msg).to.not.equal(undefined);
|
||
};
|
||
|
||
/**
|
||
* ### .isFunction(value, [message])
|
||
*
|
||
* Asserts that `value` is a function.
|
||
*
|
||
* function serveTea() { return 'cup of tea'; };
|
||
* assert.isFunction(serveTea, 'great, we can have tea now');
|
||
*
|
||
* @name isFunction
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isFunction = function (val, msg) {
|
||
new Assertion(val, msg).to.be.a('function');
|
||
};
|
||
|
||
/**
|
||
* ### .isNotFunction(value, [message])
|
||
*
|
||
* Asserts that `value` is _not_ a function.
|
||
*
|
||
* var serveTea = [ 'heat', 'pour', 'sip' ];
|
||
* assert.isNotFunction(serveTea, 'great, we have listed the steps');
|
||
*
|
||
* @name isNotFunction
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotFunction = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.a('function');
|
||
};
|
||
|
||
/**
|
||
* ### .isObject(value, [message])
|
||
*
|
||
* Asserts that `value` is an object (as revealed by
|
||
* `Object.prototype.toString`).
|
||
*
|
||
* var selection = { name: 'Chai', serve: 'with spices' };
|
||
* assert.isObject(selection, 'tea selection is an object');
|
||
*
|
||
* @name isObject
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isObject = function (val, msg) {
|
||
new Assertion(val, msg).to.be.a('object');
|
||
};
|
||
|
||
/**
|
||
* ### .isNotObject(value, [message])
|
||
*
|
||
* Asserts that `value` is _not_ an object.
|
||
*
|
||
* var selection = 'chai'
|
||
* assert.isNotObject(selection, 'tea selection is not an object');
|
||
* assert.isNotObject(null, 'null is not an object');
|
||
*
|
||
* @name isNotObject
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotObject = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.a('object');
|
||
};
|
||
|
||
/**
|
||
* ### .isArray(value, [message])
|
||
*
|
||
* Asserts that `value` is an array.
|
||
*
|
||
* var menu = [ 'green', 'chai', 'oolong' ];
|
||
* assert.isArray(menu, 'what kind of tea do we want?');
|
||
*
|
||
* @name isArray
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isArray = function (val, msg) {
|
||
new Assertion(val, msg).to.be.an('array');
|
||
};
|
||
|
||
/**
|
||
* ### .isNotArray(value, [message])
|
||
*
|
||
* Asserts that `value` is _not_ an array.
|
||
*
|
||
* var menu = 'green|chai|oolong';
|
||
* assert.isNotArray(menu, 'what kind of tea do we want?');
|
||
*
|
||
* @name isNotArray
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotArray = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.an('array');
|
||
};
|
||
|
||
/**
|
||
* ### .isString(value, [message])
|
||
*
|
||
* Asserts that `value` is a string.
|
||
*
|
||
* var teaOrder = 'chai';
|
||
* assert.isString(teaOrder, 'order placed');
|
||
*
|
||
* @name isString
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isString = function (val, msg) {
|
||
new Assertion(val, msg).to.be.a('string');
|
||
};
|
||
|
||
/**
|
||
* ### .isNotString(value, [message])
|
||
*
|
||
* Asserts that `value` is _not_ a string.
|
||
*
|
||
* var teaOrder = 4;
|
||
* assert.isNotString(teaOrder, 'order placed');
|
||
*
|
||
* @name isNotString
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotString = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.a('string');
|
||
};
|
||
|
||
/**
|
||
* ### .isNumber(value, [message])
|
||
*
|
||
* Asserts that `value` is a number.
|
||
*
|
||
* var cups = 2;
|
||
* assert.isNumber(cups, 'how many cups');
|
||
*
|
||
* @name isNumber
|
||
* @param {Number} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNumber = function (val, msg) {
|
||
new Assertion(val, msg).to.be.a('number');
|
||
};
|
||
|
||
/**
|
||
* ### .isNotNumber(value, [message])
|
||
*
|
||
* Asserts that `value` is _not_ a number.
|
||
*
|
||
* var cups = '2 cups please';
|
||
* assert.isNotNumber(cups, 'how many cups');
|
||
*
|
||
* @name isNotNumber
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotNumber = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.a('number');
|
||
};
|
||
|
||
/**
|
||
* ### .isBoolean(value, [message])
|
||
*
|
||
* Asserts that `value` is a boolean.
|
||
*
|
||
* var teaReady = true
|
||
* , teaServed = false;
|
||
*
|
||
* assert.isBoolean(teaReady, 'is the tea ready');
|
||
* assert.isBoolean(teaServed, 'has tea been served');
|
||
*
|
||
* @name isBoolean
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isBoolean = function (val, msg) {
|
||
new Assertion(val, msg).to.be.a('boolean');
|
||
};
|
||
|
||
/**
|
||
* ### .isNotBoolean(value, [message])
|
||
*
|
||
* Asserts that `value` is _not_ a boolean.
|
||
*
|
||
* var teaReady = 'yep'
|
||
* , teaServed = 'nope';
|
||
*
|
||
* assert.isNotBoolean(teaReady, 'is the tea ready');
|
||
* assert.isNotBoolean(teaServed, 'has tea been served');
|
||
*
|
||
* @name isNotBoolean
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.isNotBoolean = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.a('boolean');
|
||
};
|
||
|
||
/**
|
||
* ### .typeOf(value, name, [message])
|
||
*
|
||
* Asserts that `value`'s type is `name`, as determined by
|
||
* `Object.prototype.toString`.
|
||
*
|
||
* assert.typeOf({ tea: 'chai' }, 'object', 'we have an object');
|
||
* assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array');
|
||
* assert.typeOf('tea', 'string', 'we have a string');
|
||
* assert.typeOf(/tea/, 'regexp', 'we have a regular expression');
|
||
* assert.typeOf(null, 'null', 'we have a null');
|
||
* assert.typeOf(undefined, 'undefined', 'we have an undefined');
|
||
*
|
||
* @name typeOf
|
||
* @param {Mixed} value
|
||
* @param {String} name
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.typeOf = function (val, type, msg) {
|
||
new Assertion(val, msg).to.be.a(type);
|
||
};
|
||
|
||
/**
|
||
* ### .notTypeOf(value, name, [message])
|
||
*
|
||
* Asserts that `value`'s type is _not_ `name`, as determined by
|
||
* `Object.prototype.toString`.
|
||
*
|
||
* assert.notTypeOf('tea', 'number', 'strings are not numbers');
|
||
*
|
||
* @name notTypeOf
|
||
* @param {Mixed} value
|
||
* @param {String} typeof name
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notTypeOf = function (val, type, msg) {
|
||
new Assertion(val, msg).to.not.be.a(type);
|
||
};
|
||
|
||
/**
|
||
* ### .instanceOf(object, constructor, [message])
|
||
*
|
||
* Asserts that `value` is an instance of `constructor`.
|
||
*
|
||
* var Tea = function (name) { this.name = name; }
|
||
* , chai = new Tea('chai');
|
||
*
|
||
* assert.instanceOf(chai, Tea, 'chai is an instance of tea');
|
||
*
|
||
* @name instanceOf
|
||
* @param {Object} object
|
||
* @param {Constructor} constructor
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.instanceOf = function (val, type, msg) {
|
||
new Assertion(val, msg).to.be.instanceOf(type);
|
||
};
|
||
|
||
/**
|
||
* ### .notInstanceOf(object, constructor, [message])
|
||
*
|
||
* Asserts `value` is not an instance of `constructor`.
|
||
*
|
||
* var Tea = function (name) { this.name = name; }
|
||
* , chai = new String('chai');
|
||
*
|
||
* assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea');
|
||
*
|
||
* @name notInstanceOf
|
||
* @param {Object} object
|
||
* @param {Constructor} constructor
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notInstanceOf = function (val, type, msg) {
|
||
new Assertion(val, msg).to.not.be.instanceOf(type);
|
||
};
|
||
|
||
/**
|
||
* ### .include(haystack, needle, [message])
|
||
*
|
||
* Asserts that `haystack` includes `needle`. Works
|
||
* for strings and arrays.
|
||
*
|
||
* assert.include('foobar', 'bar', 'foobar contains string "bar"');
|
||
* assert.include([ 1, 2, 3 ], 3, 'array contains value');
|
||
*
|
||
* @name include
|
||
* @param {Array|String} haystack
|
||
* @param {Mixed} needle
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.include = function (exp, inc, msg) {
|
||
new Assertion(exp, msg, assert.include).include(inc);
|
||
};
|
||
|
||
/**
|
||
* ### .notInclude(haystack, needle, [message])
|
||
*
|
||
* Asserts that `haystack` does not include `needle`. Works
|
||
* for strings and arrays.
|
||
*i
|
||
* assert.notInclude('foobar', 'baz', 'string not include substring');
|
||
* assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value');
|
||
*
|
||
* @name notInclude
|
||
* @param {Array|String} haystack
|
||
* @param {Mixed} needle
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notInclude = function (exp, inc, msg) {
|
||
new Assertion(exp, msg, assert.notInclude).not.include(inc);
|
||
};
|
||
|
||
/**
|
||
* ### .match(value, regexp, [message])
|
||
*
|
||
* Asserts that `value` matches the regular expression `regexp`.
|
||
*
|
||
* assert.match('foobar', /^foo/, 'regexp matches');
|
||
*
|
||
* @name match
|
||
* @param {Mixed} value
|
||
* @param {RegExp} regexp
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.match = function (exp, re, msg) {
|
||
new Assertion(exp, msg).to.match(re);
|
||
};
|
||
|
||
/**
|
||
* ### .notMatch(value, regexp, [message])
|
||
*
|
||
* Asserts that `value` does not match the regular expression `regexp`.
|
||
*
|
||
* assert.notMatch('foobar', /^foo/, 'regexp does not match');
|
||
*
|
||
* @name notMatch
|
||
* @param {Mixed} value
|
||
* @param {RegExp} regexp
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notMatch = function (exp, re, msg) {
|
||
new Assertion(exp, msg).to.not.match(re);
|
||
};
|
||
|
||
/**
|
||
* ### .property(object, property, [message])
|
||
*
|
||
* Asserts that `object` has a property named by `property`.
|
||
*
|
||
* assert.property({ tea: { green: 'matcha' }}, 'tea');
|
||
*
|
||
* @name property
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.property = function (obj, prop, msg) {
|
||
new Assertion(obj, msg).to.have.property(prop);
|
||
};
|
||
|
||
/**
|
||
* ### .notProperty(object, property, [message])
|
||
*
|
||
* Asserts that `object` does _not_ have a property named by `property`.
|
||
*
|
||
* assert.notProperty({ tea: { green: 'matcha' }}, 'coffee');
|
||
*
|
||
* @name notProperty
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notProperty = function (obj, prop, msg) {
|
||
new Assertion(obj, msg).to.not.have.property(prop);
|
||
};
|
||
|
||
/**
|
||
* ### .deepProperty(object, property, [message])
|
||
*
|
||
* Asserts that `object` has a property named by `property`, which can be a
|
||
* string using dot- and bracket-notation for deep reference.
|
||
*
|
||
* assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green');
|
||
*
|
||
* @name deepProperty
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.deepProperty = function (obj, prop, msg) {
|
||
new Assertion(obj, msg).to.have.deep.property(prop);
|
||
};
|
||
|
||
/**
|
||
* ### .notDeepProperty(object, property, [message])
|
||
*
|
||
* Asserts that `object` does _not_ have a property named by `property`, which
|
||
* can be a string using dot- and bracket-notation for deep reference.
|
||
*
|
||
* assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong');
|
||
*
|
||
* @name notDeepProperty
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.notDeepProperty = function (obj, prop, msg) {
|
||
new Assertion(obj, msg).to.not.have.deep.property(prop);
|
||
};
|
||
|
||
/**
|
||
* ### .propertyVal(object, property, value, [message])
|
||
*
|
||
* Asserts that `object` has a property named by `property` with value given
|
||
* by `value`.
|
||
*
|
||
* assert.propertyVal({ tea: 'is good' }, 'tea', 'is good');
|
||
*
|
||
* @name propertyVal
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.propertyVal = function (obj, prop, val, msg) {
|
||
new Assertion(obj, msg).to.have.property(prop, val);
|
||
};
|
||
|
||
/**
|
||
* ### .propertyNotVal(object, property, value, [message])
|
||
*
|
||
* Asserts that `object` has a property named by `property`, but with a value
|
||
* different from that given by `value`.
|
||
*
|
||
* assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad');
|
||
*
|
||
* @name propertyNotVal
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.propertyNotVal = function (obj, prop, val, msg) {
|
||
new Assertion(obj, msg).to.not.have.property(prop, val);
|
||
};
|
||
|
||
/**
|
||
* ### .deepPropertyVal(object, property, value, [message])
|
||
*
|
||
* Asserts that `object` has a property named by `property` with value given
|
||
* by `value`. `property` can use dot- and bracket-notation for deep
|
||
* reference.
|
||
*
|
||
* assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha');
|
||
*
|
||
* @name deepPropertyVal
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.deepPropertyVal = function (obj, prop, val, msg) {
|
||
new Assertion(obj, msg).to.have.deep.property(prop, val);
|
||
};
|
||
|
||
/**
|
||
* ### .deepPropertyNotVal(object, property, value, [message])
|
||
*
|
||
* Asserts that `object` has a property named by `property`, but with a value
|
||
* different from that given by `value`. `property` can use dot- and
|
||
* bracket-notation for deep reference.
|
||
*
|
||
* assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha');
|
||
*
|
||
* @name deepPropertyNotVal
|
||
* @param {Object} object
|
||
* @param {String} property
|
||
* @param {Mixed} value
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.deepPropertyNotVal = function (obj, prop, val, msg) {
|
||
new Assertion(obj, msg).to.not.have.deep.property(prop, val);
|
||
};
|
||
|
||
/**
|
||
* ### .lengthOf(object, length, [message])
|
||
*
|
||
* Asserts that `object` has a `length` property with the expected value.
|
||
*
|
||
* assert.lengthOf([1,2,3], 3, 'array has length of 3');
|
||
* assert.lengthOf('foobar', 5, 'string has length of 6');
|
||
*
|
||
* @name lengthOf
|
||
* @param {Mixed} object
|
||
* @param {Number} length
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.lengthOf = function (exp, len, msg) {
|
||
new Assertion(exp, msg).to.have.length(len);
|
||
};
|
||
|
||
/**
|
||
* ### .throws(function, [constructor/string/regexp], [string/regexp], [message])
|
||
*
|
||
* Asserts that `function` will throw an error that is an instance of
|
||
* `constructor`, or alternately that it will throw an error with message
|
||
* matching `regexp`.
|
||
*
|
||
* assert.throw(fn, 'function throws a reference error');
|
||
* assert.throw(fn, /function throws a reference error/);
|
||
* assert.throw(fn, ReferenceError);
|
||
* assert.throw(fn, ReferenceError, 'function throws a reference error');
|
||
* assert.throw(fn, ReferenceError, /function throws a reference error/);
|
||
*
|
||
* @name throws
|
||
* @alias throw
|
||
* @alias Throw
|
||
* @param {Function} function
|
||
* @param {ErrorConstructor} constructor
|
||
* @param {RegExp} regexp
|
||
* @param {String} message
|
||
* @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
|
||
* @api public
|
||
*/
|
||
|
||
assert.Throw = function (fn, errt, errs, msg) {
|
||
if ('string' === typeof errt || errt instanceof RegExp) {
|
||
errs = errt;
|
||
errt = null;
|
||
}
|
||
|
||
var assertErr = new Assertion(fn, msg).to.Throw(errt, errs);
|
||
return flag(assertErr, 'object');
|
||
};
|
||
|
||
/**
|
||
* ### .doesNotThrow(function, [constructor/regexp], [message])
|
||
*
|
||
* Asserts that `function` will _not_ throw an error that is an instance of
|
||
* `constructor`, or alternately that it will not throw an error with message
|
||
* matching `regexp`.
|
||
*
|
||
* assert.doesNotThrow(fn, Error, 'function does not throw');
|
||
*
|
||
* @name doesNotThrow
|
||
* @param {Function} function
|
||
* @param {ErrorConstructor} constructor
|
||
* @param {RegExp} regexp
|
||
* @param {String} message
|
||
* @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
|
||
* @api public
|
||
*/
|
||
|
||
assert.doesNotThrow = function (fn, type, msg) {
|
||
if ('string' === typeof type) {
|
||
msg = type;
|
||
type = null;
|
||
}
|
||
|
||
new Assertion(fn, msg).to.not.Throw(type);
|
||
};
|
||
|
||
/**
|
||
* ### .operator(val1, operator, val2, [message])
|
||
*
|
||
* Compares two values using `operator`.
|
||
*
|
||
* assert.operator(1, '<', 2, 'everything is ok');
|
||
* assert.operator(1, '>', 2, 'this will fail');
|
||
*
|
||
* @name operator
|
||
* @param {Mixed} val1
|
||
* @param {String} operator
|
||
* @param {Mixed} val2
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.operator = function (val, operator, val2, msg) {
|
||
var ok;
|
||
switch(operator) {
|
||
case '==':
|
||
ok = val == val2;
|
||
break;
|
||
case '===':
|
||
ok = val === val2;
|
||
break;
|
||
case '>':
|
||
ok = val > val2;
|
||
break;
|
||
case '>=':
|
||
ok = val >= val2;
|
||
break;
|
||
case '<':
|
||
ok = val < val2;
|
||
break;
|
||
case '<=':
|
||
ok = val <= val2;
|
||
break;
|
||
case '!=':
|
||
ok = val != val2;
|
||
break;
|
||
case '!==':
|
||
ok = val !== val2;
|
||
break;
|
||
default:
|
||
throw new Error('Invalid operator "' + operator + '"');
|
||
}
|
||
var test = new Assertion(ok, msg);
|
||
test.assert(
|
||
true === flag(test, 'object')
|
||
, 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2)
|
||
, 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) );
|
||
};
|
||
|
||
/**
|
||
* ### .closeTo(actual, expected, delta, [message])
|
||
*
|
||
* Asserts that the target is equal `expected`, to within a +/- `delta` range.
|
||
*
|
||
* assert.closeTo(1.5, 1, 0.5, 'numbers are close');
|
||
*
|
||
* @name closeTo
|
||
* @param {Number} actual
|
||
* @param {Number} expected
|
||
* @param {Number} delta
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.closeTo = function (act, exp, delta, msg) {
|
||
new Assertion(act, msg).to.be.closeTo(exp, delta);
|
||
};
|
||
|
||
/**
|
||
* ### .sameMembers(set1, set2, [message])
|
||
*
|
||
* Asserts that `set1` and `set2` have the same members.
|
||
* Order is not taken into account.
|
||
*
|
||
* assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members');
|
||
*
|
||
* @name sameMembers
|
||
* @param {Array} set1
|
||
* @param {Array} set2
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.sameMembers = function (set1, set2, msg) {
|
||
new Assertion(set1, msg).to.have.same.members(set2);
|
||
}
|
||
|
||
/**
|
||
* ### .sameDeepMembers(set1, set2, [message])
|
||
*
|
||
* Asserts that `set1` and `set2` have the same members - using a deep equality checking.
|
||
* Order is not taken into account.
|
||
*
|
||
* assert.sameDeepMembers([ {b: 3}, {a: 2}, {c: 5} ], [ {c: 5}, {b: 3}, {a: 2} ], 'same deep members');
|
||
*
|
||
* @name sameDeepMembers
|
||
* @param {Array} set1
|
||
* @param {Array} set2
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.sameDeepMembers = function (set1, set2, msg) {
|
||
new Assertion(set1, msg).to.have.same.deep.members(set2);
|
||
}
|
||
|
||
/**
|
||
* ### .includeMembers(superset, subset, [message])
|
||
*
|
||
* Asserts that `subset` is included in `superset`.
|
||
* Order is not taken into account.
|
||
*
|
||
* assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members');
|
||
*
|
||
* @name includeMembers
|
||
* @param {Array} superset
|
||
* @param {Array} subset
|
||
* @param {String} message
|
||
* @api public
|
||
*/
|
||
|
||
assert.includeMembers = function (superset, subset, msg) {
|
||
new Assertion(superset, msg).to.include.members(subset);
|
||
}
|
||
|
||
/**
|
||
* ### .changes(function, object, property)
|
||
*
|
||
* Asserts that a function changes the value of a property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 22 };
|
||
* assert.changes(fn, obj, 'val');
|
||
*
|
||
* @name changes
|
||
* @param {Function} modifier function
|
||
* @param {Object} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
assert.changes = function (fn, obj, prop) {
|
||
new Assertion(fn).to.change(obj, prop);
|
||
}
|
||
|
||
/**
|
||
* ### .doesNotChange(function, object, property)
|
||
*
|
||
* Asserts that a function does not changes the value of a property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { console.log('foo'); };
|
||
* assert.doesNotChange(fn, obj, 'val');
|
||
*
|
||
* @name doesNotChange
|
||
* @param {Function} modifier function
|
||
* @param {Object} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
assert.doesNotChange = function (fn, obj, prop) {
|
||
new Assertion(fn).to.not.change(obj, prop);
|
||
}
|
||
|
||
/**
|
||
* ### .increases(function, object, property)
|
||
*
|
||
* Asserts that a function increases an object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 13 };
|
||
* assert.increases(fn, obj, 'val');
|
||
*
|
||
* @name increases
|
||
* @param {Function} modifier function
|
||
* @param {Object} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
assert.increases = function (fn, obj, prop) {
|
||
new Assertion(fn).to.increase(obj, prop);
|
||
}
|
||
|
||
/**
|
||
* ### .doesNotIncrease(function, object, property)
|
||
*
|
||
* Asserts that a function does not increase object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 8 };
|
||
* assert.doesNotIncrease(fn, obj, 'val');
|
||
*
|
||
* @name doesNotIncrease
|
||
* @param {Function} modifier function
|
||
* @param {Object} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
assert.doesNotIncrease = function (fn, obj, prop) {
|
||
new Assertion(fn).to.not.increase(obj, prop);
|
||
}
|
||
|
||
/**
|
||
* ### .decreases(function, object, property)
|
||
*
|
||
* Asserts that a function decreases an object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 5 };
|
||
* assert.decreases(fn, obj, 'val');
|
||
*
|
||
* @name decreases
|
||
* @param {Function} modifier function
|
||
* @param {Object} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
assert.decreases = function (fn, obj, prop) {
|
||
new Assertion(fn).to.decrease(obj, prop);
|
||
}
|
||
|
||
/**
|
||
* ### .doesNotDecrease(function, object, property)
|
||
*
|
||
* Asserts that a function does not decreases an object property
|
||
*
|
||
* var obj = { val: 10 };
|
||
* var fn = function() { obj.val = 15 };
|
||
* assert.doesNotDecrease(fn, obj, 'val');
|
||
*
|
||
* @name doesNotDecrease
|
||
* @param {Function} modifier function
|
||
* @param {Object} object
|
||
* @param {String} property name
|
||
* @param {String} message _optional_
|
||
* @api public
|
||
*/
|
||
|
||
assert.doesNotDecrease = function (fn, obj, prop) {
|
||
new Assertion(fn).to.not.decrease(obj, prop);
|
||
}
|
||
|
||
/*!
|
||
* Undocumented / untested
|
||
*/
|
||
|
||
assert.ifError = function (val, msg) {
|
||
new Assertion(val, msg).to.not.be.ok;
|
||
};
|
||
|
||
/*!
|
||
* Aliases.
|
||
*/
|
||
|
||
(function alias(name, as){
|
||
assert[as] = assert[name];
|
||
return alias;
|
||
})
|
||
('Throw', 'throw')
|
||
('Throw', 'throws');
|
||
};
|
||
|
||
},{}],20:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
module.exports = function (chai, util) {
|
||
chai.expect = function (val, message) {
|
||
return new chai.Assertion(val, message);
|
||
};
|
||
|
||
/**
|
||
* ### .fail(actual, expected, [message], [operator])
|
||
*
|
||
* Throw a failure.
|
||
*
|
||
* @name fail
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @param {String} operator
|
||
* @api public
|
||
*/
|
||
|
||
chai.expect.fail = function (actual, expected, message, operator) {
|
||
message = message || 'expect.fail()';
|
||
throw new chai.AssertionError(message, {
|
||
actual: actual
|
||
, expected: expected
|
||
, operator: operator
|
||
}, chai.expect.fail);
|
||
};
|
||
};
|
||
|
||
},{}],21:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* Copyright(c) 2011-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
module.exports = function (chai, util) {
|
||
var Assertion = chai.Assertion;
|
||
|
||
function loadShould () {
|
||
// explicitly define this method as function as to have it's name to include as `ssfi`
|
||
function shouldGetter() {
|
||
if (this instanceof String || this instanceof Number || this instanceof Boolean ) {
|
||
return new Assertion(this.valueOf(), null, shouldGetter);
|
||
}
|
||
return new Assertion(this, null, shouldGetter);
|
||
}
|
||
function shouldSetter(value) {
|
||
// See https://github.com/chaijs/chai/issues/86: this makes
|
||
// `whatever.should = someValue` actually set `someValue`, which is
|
||
// especially useful for `global.should = require('chai').should()`.
|
||
//
|
||
// Note that we have to use [[DefineProperty]] instead of [[Put]]
|
||
// since otherwise we would trigger this very setter!
|
||
Object.defineProperty(this, 'should', {
|
||
value: value,
|
||
enumerable: true,
|
||
configurable: true,
|
||
writable: true
|
||
});
|
||
}
|
||
// modify Object.prototype to have `should`
|
||
Object.defineProperty(Object.prototype, 'should', {
|
||
set: shouldSetter
|
||
, get: shouldGetter
|
||
, configurable: true
|
||
});
|
||
|
||
var should = {};
|
||
|
||
/**
|
||
* ### .fail(actual, expected, [message], [operator])
|
||
*
|
||
* Throw a failure.
|
||
*
|
||
* @name fail
|
||
* @param {Mixed} actual
|
||
* @param {Mixed} expected
|
||
* @param {String} message
|
||
* @param {String} operator
|
||
* @api public
|
||
*/
|
||
|
||
should.fail = function (actual, expected, message, operator) {
|
||
message = message || 'should.fail()';
|
||
throw new chai.AssertionError(message, {
|
||
actual: actual
|
||
, expected: expected
|
||
, operator: operator
|
||
}, should.fail);
|
||
};
|
||
|
||
should.equal = function (val1, val2, msg) {
|
||
new Assertion(val1, msg).to.equal(val2);
|
||
};
|
||
|
||
should.Throw = function (fn, errt, errs, msg) {
|
||
new Assertion(fn, msg).to.Throw(errt, errs);
|
||
};
|
||
|
||
should.exist = function (val, msg) {
|
||
new Assertion(val, msg).to.exist;
|
||
}
|
||
|
||
// negation
|
||
should.not = {}
|
||
|
||
should.not.equal = function (val1, val2, msg) {
|
||
new Assertion(val1, msg).to.not.equal(val2);
|
||
};
|
||
|
||
should.not.Throw = function (fn, errt, errs, msg) {
|
||
new Assertion(fn, msg).to.not.Throw(errt, errs);
|
||
};
|
||
|
||
should.not.exist = function (val, msg) {
|
||
new Assertion(val, msg).to.not.exist;
|
||
}
|
||
|
||
should['throw'] = should['Throw'];
|
||
should.not['throw'] = should.not['Throw'];
|
||
|
||
return should;
|
||
};
|
||
|
||
chai.should = loadShould;
|
||
chai.Should = loadShould;
|
||
};
|
||
|
||
},{}],22:[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":17,"./flag":25,"./transferFlags":41}],23:[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":17,"./flag":25}],24:[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
|
||
});
|
||
};
|
||
|
||
},{}],25:[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];
|
||
}
|
||
};
|
||
|
||
},{}],26:[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;
|
||
};
|
||
|
||
},{}],27:[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;
|
||
};
|
||
|
||
},{}],28:[function(require,module,exports){
|
||
/*!
|
||
* Chai - message composition utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/*!
|
||
* Module dependancies
|
||
*/
|
||
|
||
var flag = require('./flag')
|
||
, getActual = require('./getActual')
|
||
, inspect = require('./inspect')
|
||
, objDisplay = require('./objDisplay');
|
||
|
||
/**
|
||
* ### .getMessage(object, message, negateMessage)
|
||
*
|
||
* Construct the error message based on flags
|
||
* and template tags. Template tags will return
|
||
* a stringified inspection of the object referenced.
|
||
*
|
||
* Message template tags:
|
||
* - `#{this}` current asserted object
|
||
* - `#{act}` actual value
|
||
* - `#{exp}` expected value
|
||
*
|
||
* @param {Object} object (constructed Assertion)
|
||
* @param {Arguments} chai.Assertion.prototype.assert arguments
|
||
* @name getMessage
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function (obj, args) {
|
||
var negate = flag(obj, 'negate')
|
||
, val = flag(obj, 'object')
|
||
, expected = args[3]
|
||
, actual = getActual(obj, args)
|
||
, msg = negate ? args[2] : args[1]
|
||
, flagMsg = flag(obj, 'message');
|
||
|
||
if(typeof msg === "function") msg = msg();
|
||
msg = msg || '';
|
||
msg = msg
|
||
.replace(/#{this}/g, objDisplay(val))
|
||
.replace(/#{act}/g, objDisplay(actual))
|
||
.replace(/#{exp}/g, objDisplay(expected));
|
||
|
||
return flagMsg ? flagMsg + ': ' + msg : msg;
|
||
};
|
||
|
||
},{"./flag":25,"./getActual":26,"./inspect":35,"./objDisplay":36}],29:[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] : "";
|
||
};
|
||
|
||
},{}],30:[function(require,module,exports){
|
||
/*!
|
||
* Chai - getPathInfo utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
var hasProperty = require('./hasProperty');
|
||
|
||
/**
|
||
* ### .getPathInfo(path, object)
|
||
*
|
||
* This allows the retrieval of property info in an
|
||
* object given a string path.
|
||
*
|
||
* The path info consists of an object with the
|
||
* following properties:
|
||
*
|
||
* * parent - The parent object of the property referenced by `path`
|
||
* * name - The name of the final property, a number if it was an array indexer
|
||
* * value - The value of the property, if it exists, otherwise `undefined`
|
||
* * exists - Whether the property exists or not
|
||
*
|
||
* @param {String} path
|
||
* @param {Object} object
|
||
* @returns {Object} info
|
||
* @name getPathInfo
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function getPathInfo(path, obj) {
|
||
var parsed = parsePath(path),
|
||
last = parsed[parsed.length - 1];
|
||
|
||
var info = {
|
||
parent: parsed.length > 1 ? _getPathValue(parsed, obj, parsed.length - 1) : obj,
|
||
name: last.p || last.i,
|
||
value: _getPathValue(parsed, obj),
|
||
};
|
||
info.exists = hasProperty(info.name, info.parent);
|
||
|
||
return info;
|
||
};
|
||
|
||
|
||
/*!
|
||
* ## parsePath(path)
|
||
*
|
||
* Helper function used to parse string object
|
||
* paths. Use in conjunction with `_getPathValue`.
|
||
*
|
||
* var parsed = parsePath('myobject.property.subprop');
|
||
*
|
||
* ### Paths:
|
||
*
|
||
* * Can be as near infinitely deep and nested
|
||
* * Arrays are also valid using the formal `myobject.document[3].property`.
|
||
* * Literal dots and brackets (not delimiter) must be backslash-escaped.
|
||
*
|
||
* @param {String} path
|
||
* @returns {Object} parsed
|
||
* @api private
|
||
*/
|
||
|
||
function parsePath (path) {
|
||
var str = path.replace(/([^\\])\[/g, '$1.[')
|
||
, parts = str.match(/(\\\.|[^.]+?)+/g);
|
||
return parts.map(function (value) {
|
||
var re = /^\[(\d+)\]$/
|
||
, mArr = re.exec(value);
|
||
if (mArr) return { i: parseFloat(mArr[1]) };
|
||
else return { p: value.replace(/\\([.\[\]])/g, '$1') };
|
||
});
|
||
}
|
||
|
||
|
||
/*!
|
||
* ## _getPathValue(parsed, obj)
|
||
*
|
||
* Helper companion function for `.parsePath` that returns
|
||
* the value located at the parsed address.
|
||
*
|
||
* var value = getPathValue(parsed, obj);
|
||
*
|
||
* @param {Object} parsed definition from `parsePath`.
|
||
* @param {Object} object to search against
|
||
* @param {Number} object to search against
|
||
* @returns {Object|Undefined} value
|
||
* @api private
|
||
*/
|
||
|
||
function _getPathValue (parsed, obj, index) {
|
||
var tmp = obj
|
||
, res;
|
||
|
||
index = (index === undefined ? parsed.length : index);
|
||
|
||
for (var i = 0, l = index; i < l; i++) {
|
||
var part = parsed[i];
|
||
if (tmp) {
|
||
if ('undefined' !== typeof part.p)
|
||
tmp = tmp[part.p];
|
||
else if ('undefined' !== typeof part.i)
|
||
tmp = tmp[part.i];
|
||
if (i == (l - 1)) res = tmp;
|
||
} else {
|
||
res = undefined;
|
||
}
|
||
}
|
||
return res;
|
||
}
|
||
|
||
},{"./hasProperty":33}],31:[function(require,module,exports){
|
||
/*!
|
||
* Chai - getPathValue utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* @see https://github.com/logicalparadox/filtr
|
||
* MIT Licensed
|
||
*/
|
||
|
||
var getPathInfo = require('./getPathInfo');
|
||
|
||
/**
|
||
* ### .getPathValue(path, object)
|
||
*
|
||
* This allows the retrieval of values in an
|
||
* object given a string path.
|
||
*
|
||
* var obj = {
|
||
* prop1: {
|
||
* arr: ['a', 'b', 'c']
|
||
* , str: 'Hello'
|
||
* }
|
||
* , prop2: {
|
||
* arr: [ { nested: 'Universe' } ]
|
||
* , str: 'Hello again!'
|
||
* }
|
||
* }
|
||
*
|
||
* The following would be the results.
|
||
*
|
||
* getPathValue('prop1.str', obj); // Hello
|
||
* getPathValue('prop1.att[2]', obj); // b
|
||
* getPathValue('prop2.arr[0].nested', obj); // Universe
|
||
*
|
||
* @param {String} path
|
||
* @param {Object} object
|
||
* @returns {Object} value or `undefined`
|
||
* @name getPathValue
|
||
* @api public
|
||
*/
|
||
module.exports = function(path, obj) {
|
||
var info = getPathInfo(path, obj);
|
||
return info.value;
|
||
};
|
||
|
||
},{"./getPathInfo":30}],32:[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;
|
||
};
|
||
|
||
},{}],33:[function(require,module,exports){
|
||
/*!
|
||
* Chai - hasProperty utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
var type = require('./type');
|
||
|
||
/**
|
||
* ### .hasProperty(object, name)
|
||
*
|
||
* This allows checking whether an object has
|
||
* named property or numeric array index.
|
||
*
|
||
* Basically does the same thing as the `in`
|
||
* operator but works properly with natives
|
||
* and null/undefined values.
|
||
*
|
||
* var obj = {
|
||
* arr: ['a', 'b', 'c']
|
||
* , str: 'Hello'
|
||
* }
|
||
*
|
||
* The following would be the results.
|
||
*
|
||
* hasProperty('str', obj); // true
|
||
* hasProperty('constructor', obj); // true
|
||
* hasProperty('bar', obj); // false
|
||
*
|
||
* hasProperty('length', obj.str); // true
|
||
* hasProperty(1, obj.str); // true
|
||
* hasProperty(5, obj.str); // false
|
||
*
|
||
* hasProperty('length', obj.arr); // true
|
||
* hasProperty(2, obj.arr); // true
|
||
* hasProperty(3, obj.arr); // false
|
||
*
|
||
* @param {Objuect} object
|
||
* @param {String|Number} name
|
||
* @returns {Boolean} whether it exists
|
||
* @name getPathInfo
|
||
* @api public
|
||
*/
|
||
|
||
var literals = {
|
||
'number': Number
|
||
, 'string': String
|
||
};
|
||
|
||
module.exports = function hasProperty(name, obj) {
|
||
var ot = type(obj);
|
||
|
||
// Bad Object, obviously no props at all
|
||
if(ot === 'null' || ot === 'undefined')
|
||
return false;
|
||
|
||
// The `in` operator does not work with certain literals
|
||
// box these before the check
|
||
if(literals[ot] && typeof obj !== 'object')
|
||
obj = new literals[ot](obj);
|
||
|
||
return name in obj;
|
||
};
|
||
|
||
},{"./type":42}],34:[function(require,module,exports){
|
||
/*!
|
||
* chai
|
||
* Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/*!
|
||
* Main exports
|
||
*/
|
||
|
||
var exports = module.exports = {};
|
||
|
||
/*!
|
||
* test utility
|
||
*/
|
||
|
||
exports.test = require('./test');
|
||
|
||
/*!
|
||
* type utility
|
||
*/
|
||
|
||
exports.type = require('./type');
|
||
|
||
/*!
|
||
* message utility
|
||
*/
|
||
|
||
exports.getMessage = require('./getMessage');
|
||
|
||
/*!
|
||
* actual utility
|
||
*/
|
||
|
||
exports.getActual = require('./getActual');
|
||
|
||
/*!
|
||
* Inspect util
|
||
*/
|
||
|
||
exports.inspect = require('./inspect');
|
||
|
||
/*!
|
||
* Object Display util
|
||
*/
|
||
|
||
exports.objDisplay = require('./objDisplay');
|
||
|
||
/*!
|
||
* Flag utility
|
||
*/
|
||
|
||
exports.flag = require('./flag');
|
||
|
||
/*!
|
||
* Flag transferring utility
|
||
*/
|
||
|
||
exports.transferFlags = require('./transferFlags');
|
||
|
||
/*!
|
||
* Deep equal utility
|
||
*/
|
||
|
||
exports.eql = require('deep-eql');
|
||
|
||
/*!
|
||
* Deep path value
|
||
*/
|
||
|
||
exports.getPathValue = require('./getPathValue');
|
||
|
||
/*!
|
||
* Deep path info
|
||
*/
|
||
|
||
exports.getPathInfo = require('./getPathInfo');
|
||
|
||
/*!
|
||
* Check if a property exists
|
||
*/
|
||
|
||
exports.hasProperty = require('./hasProperty');
|
||
|
||
/*!
|
||
* Function name
|
||
*/
|
||
|
||
exports.getName = require('./getName');
|
||
|
||
/*!
|
||
* add Property
|
||
*/
|
||
|
||
exports.addProperty = require('./addProperty');
|
||
|
||
/*!
|
||
* add Method
|
||
*/
|
||
|
||
exports.addMethod = require('./addMethod');
|
||
|
||
/*!
|
||
* overwrite Property
|
||
*/
|
||
|
||
exports.overwriteProperty = require('./overwriteProperty');
|
||
|
||
/*!
|
||
* overwrite Method
|
||
*/
|
||
|
||
exports.overwriteMethod = require('./overwriteMethod');
|
||
|
||
/*!
|
||
* Add a chainable method
|
||
*/
|
||
|
||
exports.addChainableMethod = require('./addChainableMethod');
|
||
|
||
/*!
|
||
* Overwrite chainable method
|
||
*/
|
||
|
||
exports.overwriteChainableMethod = require('./overwriteChainableMethod');
|
||
|
||
|
||
},{"./addChainableMethod":22,"./addMethod":23,"./addProperty":24,"./flag":25,"./getActual":26,"./getMessage":28,"./getName":29,"./getPathInfo":30,"./getPathValue":31,"./hasProperty":33,"./inspect":35,"./objDisplay":36,"./overwriteChainableMethod":37,"./overwriteMethod":38,"./overwriteProperty":39,"./test":40,"./transferFlags":41,"./type":42,"deep-eql":44}],35:[function(require,module,exports){
|
||
// This is (almost) directly from Node.js utils
|
||
// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js
|
||
|
||
var getName = require('./getName');
|
||
var getProperties = require('./getProperties');
|
||
var getEnumerableProperties = require('./getEnumerableProperties');
|
||
|
||
module.exports = inspect;
|
||
|
||
/**
|
||
* Echos the value of a value. Trys to print the value out
|
||
* in the best way possible given the different types.
|
||
*
|
||
* @param {Object} obj The object to print out.
|
||
* @param {Boolean} showHidden Flag that shows hidden (not enumerable)
|
||
* properties of objects.
|
||
* @param {Number} depth Depth in which to descend in object. Default is 2.
|
||
* @param {Boolean} colors Flag to turn on ANSI escape codes to color the
|
||
* output. Default is false (no coloring).
|
||
*/
|
||
function inspect(obj, showHidden, depth, colors) {
|
||
var ctx = {
|
||
showHidden: showHidden,
|
||
seen: [],
|
||
stylize: function (str) { return str; }
|
||
};
|
||
return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth));
|
||
}
|
||
|
||
// Returns true if object is a DOM element.
|
||
var isDOMElement = function (object) {
|
||
if (typeof HTMLElement === 'object') {
|
||
return object instanceof HTMLElement;
|
||
} else {
|
||
return object &&
|
||
typeof object === 'object' &&
|
||
object.nodeType === 1 &&
|
||
typeof object.nodeName === 'string';
|
||
}
|
||
};
|
||
|
||
function formatValue(ctx, value, recurseTimes) {
|
||
// Provide a hook for user-specified inspect functions.
|
||
// Check that value is an object with an inspect function on it
|
||
if (value && typeof value.inspect === 'function' &&
|
||
// Filter out the util module, it's inspect function is special
|
||
value.inspect !== exports.inspect &&
|
||
// Also filter out any prototype objects using the circular check.
|
||
!(value.constructor && value.constructor.prototype === value)) {
|
||
var ret = value.inspect(recurseTimes);
|
||
if (typeof ret !== 'string') {
|
||
ret = formatValue(ctx, ret, recurseTimes);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// Primitive types cannot have properties
|
||
var primitive = formatPrimitive(ctx, value);
|
||
if (primitive) {
|
||
return primitive;
|
||
}
|
||
|
||
// If this is a DOM element, try to get the outer HTML.
|
||
if (isDOMElement(value)) {
|
||
if ('outerHTML' in value) {
|
||
return value.outerHTML;
|
||
// This value does not have an outerHTML attribute,
|
||
// it could still be an XML element
|
||
} else {
|
||
// Attempt to serialize it
|
||
try {
|
||
if (document.xmlVersion) {
|
||
var xmlSerializer = new XMLSerializer();
|
||
return xmlSerializer.serializeToString(value);
|
||
} else {
|
||
// Firefox 11- do not support outerHTML
|
||
// It does, however, support innerHTML
|
||
// Use the following to render the element
|
||
var ns = "http://www.w3.org/1999/xhtml";
|
||
var container = document.createElementNS(ns, '_');
|
||
|
||
container.appendChild(value.cloneNode(false));
|
||
html = container.innerHTML
|
||
.replace('><', '>' + value.innerHTML + '<');
|
||
container.innerHTML = '';
|
||
return html;
|
||
}
|
||
} catch (err) {
|
||
// This could be a non-native DOM implementation,
|
||
// continue with the normal flow:
|
||
// printing the element as if it is an object.
|
||
}
|
||
}
|
||
}
|
||
|
||
// Look up the keys of the object.
|
||
var visibleKeys = getEnumerableProperties(value);
|
||
var keys = ctx.showHidden ? getProperties(value) : visibleKeys;
|
||
|
||
// Some type of object without properties can be shortcutted.
|
||
// In IE, errors have a single `stack` property, or if they are vanilla `Error`,
|
||
// a `stack` plus `description` property; ignore those for consistency.
|
||
if (keys.length === 0 || (isError(value) && (
|
||
(keys.length === 1 && keys[0] === 'stack') ||
|
||
(keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack')
|
||
))) {
|
||
if (typeof value === 'function') {
|
||
var name = getName(value);
|
||
var nameSuffix = name ? ': ' + name : '';
|
||
return ctx.stylize('[Function' + nameSuffix + ']', 'special');
|
||
}
|
||
if (isRegExp(value)) {
|
||
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||
}
|
||
if (isDate(value)) {
|
||
return ctx.stylize(Date.prototype.toUTCString.call(value), 'date');
|
||
}
|
||
if (isError(value)) {
|
||
return formatError(value);
|
||
}
|
||
}
|
||
|
||
var base = '', array = false, braces = ['{', '}'];
|
||
|
||
// Make Array say that they are Array
|
||
if (isArray(value)) {
|
||
array = true;
|
||
braces = ['[', ']'];
|
||
}
|
||
|
||
// Make functions say that they are functions
|
||
if (typeof value === 'function') {
|
||
var name = getName(value);
|
||
var nameSuffix = name ? ': ' + name : '';
|
||
base = ' [Function' + nameSuffix + ']';
|
||
}
|
||
|
||
// Make RegExps say that they are RegExps
|
||
if (isRegExp(value)) {
|
||
base = ' ' + RegExp.prototype.toString.call(value);
|
||
}
|
||
|
||
// Make dates with properties first say the date
|
||
if (isDate(value)) {
|
||
base = ' ' + Date.prototype.toUTCString.call(value);
|
||
}
|
||
|
||
// Make error with message first say the error
|
||
if (isError(value)) {
|
||
return formatError(value);
|
||
}
|
||
|
||
if (keys.length === 0 && (!array || value.length == 0)) {
|
||
return braces[0] + base + braces[1];
|
||
}
|
||
|
||
if (recurseTimes < 0) {
|
||
if (isRegExp(value)) {
|
||
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
|
||
} else {
|
||
return ctx.stylize('[Object]', 'special');
|
||
}
|
||
}
|
||
|
||
ctx.seen.push(value);
|
||
|
||
var output;
|
||
if (array) {
|
||
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
|
||
} else {
|
||
output = keys.map(function(key) {
|
||
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
|
||
});
|
||
}
|
||
|
||
ctx.seen.pop();
|
||
|
||
return reduceToSingleString(output, base, braces);
|
||
}
|
||
|
||
|
||
function formatPrimitive(ctx, value) {
|
||
switch (typeof value) {
|
||
case 'undefined':
|
||
return ctx.stylize('undefined', 'undefined');
|
||
|
||
case 'string':
|
||
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
|
||
.replace(/'/g, "\\'")
|
||
.replace(/\\"/g, '"') + '\'';
|
||
return ctx.stylize(simple, 'string');
|
||
|
||
case 'number':
|
||
if (value === 0 && (1/value) === -Infinity) {
|
||
return ctx.stylize('-0', 'number');
|
||
}
|
||
return ctx.stylize('' + value, 'number');
|
||
|
||
case 'boolean':
|
||
return ctx.stylize('' + value, 'boolean');
|
||
}
|
||
// For some reason typeof null is "object", so special case here.
|
||
if (value === null) {
|
||
return ctx.stylize('null', 'null');
|
||
}
|
||
}
|
||
|
||
|
||
function formatError(value) {
|
||
return '[' + Error.prototype.toString.call(value) + ']';
|
||
}
|
||
|
||
|
||
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
|
||
var output = [];
|
||
for (var i = 0, l = value.length; i < l; ++i) {
|
||
if (Object.prototype.hasOwnProperty.call(value, String(i))) {
|
||
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||
String(i), true));
|
||
} else {
|
||
output.push('');
|
||
}
|
||
}
|
||
keys.forEach(function(key) {
|
||
if (!key.match(/^\d+$/)) {
|
||
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
|
||
key, true));
|
||
}
|
||
});
|
||
return output;
|
||
}
|
||
|
||
|
||
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
|
||
var name, str;
|
||
if (value.__lookupGetter__) {
|
||
if (value.__lookupGetter__(key)) {
|
||
if (value.__lookupSetter__(key)) {
|
||
str = ctx.stylize('[Getter/Setter]', 'special');
|
||
} else {
|
||
str = ctx.stylize('[Getter]', 'special');
|
||
}
|
||
} else {
|
||
if (value.__lookupSetter__(key)) {
|
||
str = ctx.stylize('[Setter]', 'special');
|
||
}
|
||
}
|
||
}
|
||
if (visibleKeys.indexOf(key) < 0) {
|
||
name = '[' + key + ']';
|
||
}
|
||
if (!str) {
|
||
if (ctx.seen.indexOf(value[key]) < 0) {
|
||
if (recurseTimes === null) {
|
||
str = formatValue(ctx, value[key], null);
|
||
} else {
|
||
str = formatValue(ctx, value[key], recurseTimes - 1);
|
||
}
|
||
if (str.indexOf('\n') > -1) {
|
||
if (array) {
|
||
str = str.split('\n').map(function(line) {
|
||
return ' ' + line;
|
||
}).join('\n').substr(2);
|
||
} else {
|
||
str = '\n' + str.split('\n').map(function(line) {
|
||
return ' ' + line;
|
||
}).join('\n');
|
||
}
|
||
}
|
||
} else {
|
||
str = ctx.stylize('[Circular]', 'special');
|
||
}
|
||
}
|
||
if (typeof name === 'undefined') {
|
||
if (array && key.match(/^\d+$/)) {
|
||
return str;
|
||
}
|
||
name = JSON.stringify('' + key);
|
||
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
|
||
name = name.substr(1, name.length - 2);
|
||
name = ctx.stylize(name, 'name');
|
||
} else {
|
||
name = name.replace(/'/g, "\\'")
|
||
.replace(/\\"/g, '"')
|
||
.replace(/(^"|"$)/g, "'");
|
||
name = ctx.stylize(name, 'string');
|
||
}
|
||
}
|
||
|
||
return name + ': ' + str;
|
||
}
|
||
|
||
|
||
function reduceToSingleString(output, base, braces) {
|
||
var numLinesEst = 0;
|
||
var length = output.reduce(function(prev, cur) {
|
||
numLinesEst++;
|
||
if (cur.indexOf('\n') >= 0) numLinesEst++;
|
||
return prev + cur.length + 1;
|
||
}, 0);
|
||
|
||
if (length > 60) {
|
||
return braces[0] +
|
||
(base === '' ? '' : base + '\n ') +
|
||
' ' +
|
||
output.join(',\n ') +
|
||
' ' +
|
||
braces[1];
|
||
}
|
||
|
||
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
|
||
}
|
||
|
||
function isArray(ar) {
|
||
return Array.isArray(ar) ||
|
||
(typeof ar === 'object' && objectToString(ar) === '[object Array]');
|
||
}
|
||
|
||
function isRegExp(re) {
|
||
return typeof re === 'object' && objectToString(re) === '[object RegExp]';
|
||
}
|
||
|
||
function isDate(d) {
|
||
return typeof d === 'object' && objectToString(d) === '[object Date]';
|
||
}
|
||
|
||
function isError(e) {
|
||
return typeof e === 'object' && objectToString(e) === '[object Error]';
|
||
}
|
||
|
||
function objectToString(o) {
|
||
return Object.prototype.toString.call(o);
|
||
}
|
||
|
||
},{"./getEnumerableProperties":27,"./getName":29,"./getProperties":32}],36:[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":17,"./inspect":35}],37:[function(require,module,exports){
|
||
/*!
|
||
* Chai - overwriteChainableMethod utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* ### overwriteChainableMethod (ctx, name, method, chainingBehavior)
|
||
*
|
||
* Overwites an already existing chainable method
|
||
* and provides access to the previous function or
|
||
* property. Must return functions to be used for
|
||
* name.
|
||
*
|
||
* utils.overwriteChainableMethod(chai.Assertion.prototype, 'length',
|
||
* function (_super) {
|
||
* }
|
||
* , function (_super) {
|
||
* }
|
||
* );
|
||
*
|
||
* Can also be accessed directly from `chai.Assertion`.
|
||
*
|
||
* chai.Assertion.overwriteChainableMethod('foo', fn, fn);
|
||
*
|
||
* Then can be used as any other assertion.
|
||
*
|
||
* expect(myFoo).to.have.length(3);
|
||
* expect(myFoo).to.have.length.above(3);
|
||
*
|
||
* @param {Object} ctx object whose method / property is to be overwritten
|
||
* @param {String} name of method / property to overwrite
|
||
* @param {Function} method function that returns a function to be used for name
|
||
* @param {Function} chainingBehavior function that returns a function to be used for property
|
||
* @name overwriteChainableMethod
|
||
* @api public
|
||
*/
|
||
|
||
module.exports = function (ctx, name, method, chainingBehavior) {
|
||
var chainableBehavior = ctx.__methods[name];
|
||
|
||
var _chainingBehavior = chainableBehavior.chainingBehavior;
|
||
chainableBehavior.chainingBehavior = function () {
|
||
var result = chainingBehavior(_chainingBehavior).call(this);
|
||
return result === undefined ? this : result;
|
||
};
|
||
|
||
var _method = chainableBehavior.method;
|
||
chainableBehavior.method = function () {
|
||
var result = method(_method).apply(this, arguments);
|
||
return result === undefined ? this : result;
|
||
};
|
||
};
|
||
|
||
},{}],38:[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;
|
||
}
|
||
};
|
||
|
||
},{}],39:[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
|
||
});
|
||
};
|
||
|
||
},{}],40:[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":25}],41:[function(require,module,exports){
|
||
/*!
|
||
* Chai - transferFlags utility
|
||
* Copyright(c) 2012-2014 Jake Luer <jake@alogicalparadox.com>
|
||
* MIT Licensed
|
||
*/
|
||
|
||
/**
|
||
* ### transferFlags(assertion, object, includeAll = true)
|
||
*
|
||
* Transfer all the flags for `assertion` to `object`. If
|
||
* `includeAll` is set to `false`, then the base Chai
|
||
* assertion flags (namely `object`, `ssfi`, and `message`)
|
||
* will not be transferred.
|
||
*
|
||
*
|
||
* var newAssertion = new Assertion();
|
||
* utils.transferFlags(assertion, newAssertion);
|
||
*
|
||
* var anotherAsseriton = new Assertion(myObj);
|
||
* utils.transferFlags(assertion, anotherAssertion, false);
|
||
*
|
||
* @param {Assertion} assertion the assertion to transfer the flags from
|
||
* @param {Object} object the object to transfer the flags to; usually a new assertion
|
||
* @param {Boolean} includeAll
|
||
* @name transferFlags
|
||
* @api private
|
||
*/
|
||
|
||
module.exports = function (assertion, object, includeAll) {
|
||
var flags = assertion.__flags || (assertion.__flags = Object.create(null));
|
||
|
||
if (!object.__flags) {
|
||
object.__flags = Object.create(null);
|
||
}
|
||
|
||
includeAll = arguments.length === 3 ? includeAll : true;
|
||
|
||
for (var flag in flags) {
|
||
if (includeAll ||
|
||
(flag !== 'object' && flag !== 'ssfi' && flag != 'message')) {
|
||
object.__flags[flag] = flags[flag];
|
||
}
|
||
}
|
||
};
|
||
|
||
},{}],42:[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;
|
||
};
|
||
|
||
},{}],43:[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;
|
||
};
|
||
|
||
},{}],44:[function(require,module,exports){
|
||
module.exports = require('./lib/eql');
|
||
|
||
},{"./lib/eql":45}],45:[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":48,"type-detect":46}],46:[function(require,module,exports){
|
||
module.exports = require('./lib/type');
|
||
|
||
},{"./lib/type":47}],47:[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.');
|
||
}
|
||
};
|
||
|
||
},{}],48:[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":49,"ieee754":50}],49:[function(require,module,exports){
|
||
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||
|
||
;(function (exports) {
|
||
'use strict';
|
||
|
||
var Arr = (typeof Uint8Array !== 'undefined')
|
||
? Uint8Array
|
||
: Array
|
||
|
||
var PLUS = '+'.charCodeAt(0)
|
||
var SLASH = '/'.charCodeAt(0)
|
||
var NUMBER = '0'.charCodeAt(0)
|
||
var LOWER = 'a'.charCodeAt(0)
|
||
var UPPER = 'A'.charCodeAt(0)
|
||
var PLUS_URL_SAFE = '-'.charCodeAt(0)
|
||
var SLASH_URL_SAFE = '_'.charCodeAt(0)
|
||
|
||
function decode (elt) {
|
||
var code = elt.charCodeAt(0)
|
||
if (code === PLUS ||
|
||
code === PLUS_URL_SAFE)
|
||
return 62 // '+'
|
||
if (code === SLASH ||
|
||
code === SLASH_URL_SAFE)
|
||
return 63 // '/'
|
||
if (code < NUMBER)
|
||
return -1 //no match
|
||
if (code < NUMBER + 10)
|
||
return code - NUMBER + 26 + 26
|
||
if (code < UPPER + 26)
|
||
return code - UPPER
|
||
if (code < LOWER + 26)
|
||
return code - LOWER + 26
|
||
}
|
||
|
||
function b64ToByteArray (b64) {
|
||
var i, j, l, tmp, placeHolders, arr
|
||
|
||
if (b64.length % 4 > 0) {
|
||
throw new Error('Invalid string. Length must be a multiple of 4')
|
||
}
|
||
|
||
// the number of equal signs (place holders)
|
||
// if there are two placeholders, than the two characters before it
|
||
// represent one byte
|
||
// if there is only one, then the three characters before it represent 2 bytes
|
||
// this is just a cheap hack to not do indexOf twice
|
||
var len = b64.length
|
||
placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
|
||
|
||
// base64 is 4/3 + up to two characters of the original data
|
||
arr = new Arr(b64.length * 3 / 4 - placeHolders)
|
||
|
||
// if there are placeholders, only get up to the last complete 4 chars
|
||
l = placeHolders > 0 ? b64.length - 4 : b64.length
|
||
|
||
var L = 0
|
||
|
||
function push (v) {
|
||
arr[L++] = v
|
||
}
|
||
|
||
for (i = 0, j = 0; i < l; i += 4, j += 3) {
|
||
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
|
||
push((tmp & 0xFF0000) >> 16)
|
||
push((tmp & 0xFF00) >> 8)
|
||
push(tmp & 0xFF)
|
||
}
|
||
|
||
if (placeHolders === 2) {
|
||
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
|
||
push(tmp & 0xFF)
|
||
} else if (placeHolders === 1) {
|
||
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
|
||
push((tmp >> 8) & 0xFF)
|
||
push(tmp & 0xFF)
|
||
}
|
||
|
||
return arr
|
||
}
|
||
|
||
function uint8ToBase64 (uint8) {
|
||
var i,
|
||
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes
|
||
output = "",
|
||
temp, length
|
||
|
||
function encode (num) {
|
||
return lookup.charAt(num)
|
||
}
|
||
|
||
function tripletToBase64 (num) {
|
||
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)
|
||
}
|
||
|
||
// go through the array every three bytes, we'll deal with trailing stuff later
|
||
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {
|
||
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])
|
||
output += tripletToBase64(temp)
|
||
}
|
||
|
||
// pad the end with zeros, but make sure to not forget the extra bytes
|
||
switch (extraBytes) {
|
||
case 1:
|
||
temp = uint8[uint8.length - 1]
|
||
output += encode(temp >> 2)
|
||
output += encode((temp << 4) & 0x3F)
|
||
output += '=='
|
||
break
|
||
case 2:
|
||
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
|
||
output += encode(temp >> 10)
|
||
output += encode((temp >> 4) & 0x3F)
|
||
output += encode((temp << 2) & 0x3F)
|
||
output += '='
|
||
break
|
||
}
|
||
|
||
return output
|
||
}
|
||
|
||
exports.toByteArray = b64ToByteArray
|
||
exports.fromByteArray = uint8ToBase64
|
||
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
|
||
|
||
},{}],50:[function(require,module,exports){
|
||
exports.read = function (buffer, offset, isLE, mLen, nBytes) {
|
||
var e, m
|
||
var eLen = nBytes * 8 - mLen - 1
|
||
var eMax = (1 << eLen) - 1
|
||
var eBias = eMax >> 1
|
||
var nBits = -7
|
||
var i = isLE ? (nBytes - 1) : 0
|
||
var d = isLE ? -1 : 1
|
||
var 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
|
||
var eLen = nBytes * 8 - mLen - 1
|
||
var eMax = (1 << eLen) - 1
|
||
var eBias = eMax >> 1
|
||
var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
|
||
var i = isLE ? 0 : (nBytes - 1)
|
||
var d = isLE ? 1 : -1
|
||
var 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
|
||
}
|
||
|
||
},{}],51:[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
|
||
}
|
||
}
|
||
|
||
},{}],52:[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');
|
||
};
|
||
|
||
},{}],53:[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';
|
||
}
|
||
},{}],54:[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":53,"1YiZ5S":52,"inherits":51}],55:[function(require,module,exports){
|
||
(function (sinonChai) {
|
||
"use strict";
|
||
|
||
// Module systems magic dance.
|
||
|
||
/* istanbul ignore else */
|
||
if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
|
||
// NodeJS
|
||
module.exports = sinonChai;
|
||
} else if (typeof define === "function" && define.amd) {
|
||
// AMD
|
||
define(function () {
|
||
return sinonChai;
|
||
});
|
||
} else {
|
||
// Other environment (usually <script> tag): plug in to global chai instance directly.
|
||
chai.use(sinonChai);
|
||
}
|
||
}(function sinonChai(chai, utils) {
|
||
"use strict";
|
||
|
||
var slice = Array.prototype.slice;
|
||
|
||
function isSpy(putativeSpy) {
|
||
return typeof putativeSpy === "function" &&
|
||
typeof putativeSpy.getCall === "function" &&
|
||
typeof putativeSpy.calledWithExactly === "function";
|
||
}
|
||
|
||
function timesInWords(count) {
|
||
return count === 1 ? "once" :
|
||
count === 2 ? "twice" :
|
||
count === 3 ? "thrice" :
|
||
(count || 0) + " times";
|
||
}
|
||
|
||
function isCall(putativeCall) {
|
||
return putativeCall && isSpy(putativeCall.proxy);
|
||
}
|
||
|
||
function assertCanWorkWith(assertion) {
|
||
if (!isSpy(assertion._obj) && !isCall(assertion._obj)) {
|
||
throw new TypeError(utils.inspect(assertion._obj) + " is not a spy or a call to a spy!");
|
||
}
|
||
}
|
||
|
||
function getMessages(spy, action, nonNegatedSuffix, always, args) {
|
||
var verbPhrase = always ? "always have " : "have ";
|
||
nonNegatedSuffix = nonNegatedSuffix || "";
|
||
if (isSpy(spy.proxy)) {
|
||
spy = spy.proxy;
|
||
}
|
||
|
||
function printfArray(array) {
|
||
return spy.printf.apply(spy, array);
|
||
}
|
||
|
||
return {
|
||
affirmative: function () {
|
||
return printfArray(["expected %n to " + verbPhrase + action + nonNegatedSuffix].concat(args));
|
||
},
|
||
negative: function () {
|
||
return printfArray(["expected %n to not " + verbPhrase + action].concat(args));
|
||
}
|
||
};
|
||
}
|
||
|
||
function sinonProperty(name, action, nonNegatedSuffix) {
|
||
utils.addProperty(chai.Assertion.prototype, name, function () {
|
||
assertCanWorkWith(this);
|
||
|
||
var messages = getMessages(this._obj, action, nonNegatedSuffix, false);
|
||
this.assert(this._obj[name], messages.affirmative, messages.negative);
|
||
});
|
||
}
|
||
|
||
function sinonPropertyAsBooleanMethod(name, action, nonNegatedSuffix) {
|
||
utils.addMethod(chai.Assertion.prototype, name, function (arg) {
|
||
assertCanWorkWith(this);
|
||
|
||
var messages = getMessages(this._obj, action, nonNegatedSuffix, false, [timesInWords(arg)]);
|
||
this.assert(this._obj[name] === arg, messages.affirmative, messages.negative);
|
||
});
|
||
}
|
||
|
||
function createSinonMethodHandler(sinonName, action, nonNegatedSuffix) {
|
||
return function () {
|
||
assertCanWorkWith(this);
|
||
|
||
var alwaysSinonMethod = "always" + sinonName[0].toUpperCase() + sinonName.substring(1);
|
||
var shouldBeAlways = utils.flag(this, "always") && typeof this._obj[alwaysSinonMethod] === "function";
|
||
var sinonMethod = shouldBeAlways ? alwaysSinonMethod : sinonName;
|
||
|
||
var messages = getMessages(this._obj, action, nonNegatedSuffix, shouldBeAlways, slice.call(arguments));
|
||
this.assert(this._obj[sinonMethod].apply(this._obj, arguments), messages.affirmative, messages.negative);
|
||
};
|
||
}
|
||
|
||
function sinonMethodAsProperty(name, action, nonNegatedSuffix) {
|
||
var handler = createSinonMethodHandler(name, action, nonNegatedSuffix);
|
||
utils.addProperty(chai.Assertion.prototype, name, handler);
|
||
}
|
||
|
||
function exceptionalSinonMethod(chaiName, sinonName, action, nonNegatedSuffix) {
|
||
var handler = createSinonMethodHandler(sinonName, action, nonNegatedSuffix);
|
||
utils.addMethod(chai.Assertion.prototype, chaiName, handler);
|
||
}
|
||
|
||
function sinonMethod(name, action, nonNegatedSuffix) {
|
||
exceptionalSinonMethod(name, name, action, nonNegatedSuffix);
|
||
}
|
||
|
||
utils.addProperty(chai.Assertion.prototype, "always", function () {
|
||
utils.flag(this, "always", true);
|
||
});
|
||
|
||
sinonProperty("called", "been called", " at least once, but it was never called");
|
||
sinonPropertyAsBooleanMethod("callCount", "been called exactly %1", ", but it was called %c%C");
|
||
sinonProperty("calledOnce", "been called exactly once", ", but it was called %c%C");
|
||
sinonProperty("calledTwice", "been called exactly twice", ", but it was called %c%C");
|
||
sinonProperty("calledThrice", "been called exactly thrice", ", but it was called %c%C");
|
||
sinonMethodAsProperty("calledWithNew", "been called with new");
|
||
sinonMethod("calledBefore", "been called before %1");
|
||
sinonMethod("calledAfter", "been called after %1");
|
||
sinonMethod("calledOn", "been called with %1 as this", ", but it was called with %t instead");
|
||
sinonMethod("calledWith", "been called with arguments %*", "%C");
|
||
sinonMethod("calledWithExactly", "been called with exact arguments %*", "%C");
|
||
sinonMethod("calledWithMatch", "been called with arguments matching %*", "%C");
|
||
sinonMethod("returned", "returned %1");
|
||
exceptionalSinonMethod("thrown", "threw", "thrown %1");
|
||
}));
|
||
|
||
},{}],56:[function(require,module,exports){
|
||
/**
|
||
* Sinon core utilities. For internal use only.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
var sinon = (function () {
|
||
var sinon;
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
sinon = module.exports = require("./sinon/util/core");
|
||
require("./sinon/extend");
|
||
require("./sinon/typeOf");
|
||
require("./sinon/times_in_words");
|
||
require("./sinon/spy");
|
||
require("./sinon/call");
|
||
require("./sinon/behavior");
|
||
require("./sinon/stub");
|
||
require("./sinon/mock");
|
||
require("./sinon/collection");
|
||
require("./sinon/assert");
|
||
require("./sinon/sandbox");
|
||
require("./sinon/test");
|
||
require("./sinon/test_case");
|
||
require("./sinon/match");
|
||
require("./sinon/format");
|
||
require("./sinon/log_error");
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
sinon = module.exports;
|
||
} else {
|
||
sinon = {};
|
||
}
|
||
|
||
return sinon;
|
||
}());
|
||
|
||
},{"./sinon/assert":57,"./sinon/behavior":58,"./sinon/call":59,"./sinon/collection":60,"./sinon/extend":61,"./sinon/format":62,"./sinon/log_error":63,"./sinon/match":64,"./sinon/mock":65,"./sinon/sandbox":66,"./sinon/spy":67,"./sinon/stub":68,"./sinon/test":69,"./sinon/test_case":70,"./sinon/times_in_words":71,"./sinon/typeOf":72,"./sinon/util/core":73}],57:[function(require,module,exports){
|
||
(function (global){
|
||
/**
|
||
* @depend times_in_words.js
|
||
* @depend util/core.js
|
||
* @depend match.js
|
||
* @depend format.js
|
||
*/
|
||
/**
|
||
* Assertions matching the test spy retrieval interface.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon, global) {
|
||
var slice = Array.prototype.slice;
|
||
|
||
function makeApi(sinon) {
|
||
var assert;
|
||
|
||
function verifyIsStub() {
|
||
var method;
|
||
|
||
for (var i = 0, l = arguments.length; i < l; ++i) {
|
||
method = arguments[i];
|
||
|
||
if (!method) {
|
||
assert.fail("fake is not a spy");
|
||
}
|
||
|
||
if (method.proxy && method.proxy.isSinonProxy) {
|
||
verifyIsStub(method.proxy);
|
||
} else {
|
||
if (typeof method != "function") {
|
||
assert.fail(method + " is not a function");
|
||
}
|
||
|
||
if (typeof method.getCall != "function") {
|
||
assert.fail(method + " is not stubbed");
|
||
}
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
function failAssertion(object, msg) {
|
||
object = object || global;
|
||
var failMethod = object.fail || assert.fail;
|
||
failMethod.call(object, msg);
|
||
}
|
||
|
||
function mirrorPropAsAssertion(name, method, message) {
|
||
if (arguments.length == 2) {
|
||
message = method;
|
||
method = name;
|
||
}
|
||
|
||
assert[name] = function (fake) {
|
||
verifyIsStub(fake);
|
||
|
||
var args = slice.call(arguments, 1);
|
||
var failed = false;
|
||
|
||
if (typeof method == "function") {
|
||
failed = !method(fake);
|
||
} else {
|
||
failed = typeof fake[method] == "function" ?
|
||
!fake[method].apply(fake, args) : !fake[method];
|
||
}
|
||
|
||
if (failed) {
|
||
failAssertion(this, (fake.printf || fake.proxy.printf).apply(fake, [message].concat(args)));
|
||
} else {
|
||
assert.pass(name);
|
||
}
|
||
};
|
||
}
|
||
|
||
function exposedName(prefix, prop) {
|
||
return !prefix || /^fail/.test(prop) ? prop :
|
||
prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
|
||
}
|
||
|
||
assert = {
|
||
failException: "AssertError",
|
||
|
||
fail: function fail(message) {
|
||
var error = new Error(message);
|
||
error.name = this.failException || assert.failException;
|
||
|
||
throw error;
|
||
},
|
||
|
||
pass: function pass(assertion) {},
|
||
|
||
callOrder: function assertCallOrder() {
|
||
verifyIsStub.apply(null, arguments);
|
||
var expected = "", actual = "";
|
||
|
||
if (!sinon.calledInOrder(arguments)) {
|
||
try {
|
||
expected = [].join.call(arguments, ", ");
|
||
var calls = slice.call(arguments);
|
||
var i = calls.length;
|
||
while (i) {
|
||
if (!calls[--i].called) {
|
||
calls.splice(i, 1);
|
||
}
|
||
}
|
||
actual = sinon.orderByFirstCall(calls).join(", ");
|
||
} catch (e) {
|
||
// If this fails, we'll just fall back to the blank string
|
||
}
|
||
|
||
failAssertion(this, "expected " + expected + " to be " +
|
||
"called in order but were called as " + actual);
|
||
} else {
|
||
assert.pass("callOrder");
|
||
}
|
||
},
|
||
|
||
callCount: function assertCallCount(method, count) {
|
||
verifyIsStub(method);
|
||
|
||
if (method.callCount != count) {
|
||
var msg = "expected %n to be called " + sinon.timesInWords(count) +
|
||
" but was called %c%C";
|
||
failAssertion(this, method.printf(msg));
|
||
} else {
|
||
assert.pass("callCount");
|
||
}
|
||
},
|
||
|
||
expose: function expose(target, options) {
|
||
if (!target) {
|
||
throw new TypeError("target is null or undefined");
|
||
}
|
||
|
||
var o = options || {};
|
||
var prefix = typeof o.prefix == "undefined" && "assert" || o.prefix;
|
||
var includeFail = typeof o.includeFail == "undefined" || !!o.includeFail;
|
||
|
||
for (var method in this) {
|
||
if (method != "expose" && (includeFail || !/^(fail)/.test(method))) {
|
||
target[exposedName(prefix, method)] = this[method];
|
||
}
|
||
}
|
||
|
||
return target;
|
||
},
|
||
|
||
match: function match(actual, expectation) {
|
||
var matcher = sinon.match(expectation);
|
||
if (matcher.test(actual)) {
|
||
assert.pass("match");
|
||
} else {
|
||
var formatted = [
|
||
"expected value to match",
|
||
" expected = " + sinon.format(expectation),
|
||
" actual = " + sinon.format(actual)
|
||
]
|
||
failAssertion(this, formatted.join("\n"));
|
||
}
|
||
}
|
||
};
|
||
|
||
mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
|
||
mirrorPropAsAssertion("notCalled", function (spy) {
|
||
return !spy.called;
|
||
}, "expected %n to not have been called but was called %c%C");
|
||
mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
|
||
mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
|
||
mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
|
||
mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
|
||
mirrorPropAsAssertion("alwaysCalledOn", "expected %n to always be called with %1 as this but was called with %t");
|
||
mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
|
||
mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
|
||
mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
|
||
mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
|
||
mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
|
||
mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
|
||
mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
|
||
mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
|
||
mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
|
||
mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
|
||
mirrorPropAsAssertion("threw", "%n did not throw exception%C");
|
||
mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
|
||
|
||
sinon.assert = assert;
|
||
return assert;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./match");
|
||
require("./format");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
|
||
}(typeof sinon == "object" && sinon || null, typeof window != "undefined" ? window : (typeof self != "undefined") ? self : global));
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"./format":62,"./match":64,"./util/core":73}],58:[function(require,module,exports){
|
||
(function (process){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend extend.js
|
||
*/
|
||
/**
|
||
* Stub behavior
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @author Tim Fischbach (mail@timfischbach.de)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
var slice = Array.prototype.slice;
|
||
var join = Array.prototype.join;
|
||
var useLeftMostCallback = -1;
|
||
var useRightMostCallback = -2;
|
||
|
||
var nextTick = (function () {
|
||
if (typeof process === "object" && typeof process.nextTick === "function") {
|
||
return process.nextTick;
|
||
} else if (typeof setImmediate === "function") {
|
||
return setImmediate;
|
||
} else {
|
||
return function (callback) {
|
||
setTimeout(callback, 0);
|
||
};
|
||
}
|
||
})();
|
||
|
||
function throwsException(error, message) {
|
||
if (typeof error == "string") {
|
||
this.exception = new Error(message || "");
|
||
this.exception.name = error;
|
||
} else if (!error) {
|
||
this.exception = new Error("Error");
|
||
} else {
|
||
this.exception = error;
|
||
}
|
||
|
||
return this;
|
||
}
|
||
|
||
function getCallback(behavior, args) {
|
||
var callArgAt = behavior.callArgAt;
|
||
|
||
if (callArgAt >= 0) {
|
||
return args[callArgAt];
|
||
}
|
||
|
||
var argumentList;
|
||
|
||
if (callArgAt === useLeftMostCallback) {
|
||
argumentList = args;
|
||
}
|
||
|
||
if (callArgAt === useRightMostCallback) {
|
||
argumentList = slice.call(args).reverse();
|
||
}
|
||
|
||
var callArgProp = behavior.callArgProp;
|
||
|
||
for (var i = 0, l = argumentList.length; i < l; ++i) {
|
||
if (!callArgProp && typeof argumentList[i] == "function") {
|
||
return argumentList[i];
|
||
}
|
||
|
||
if (callArgProp && argumentList[i] &&
|
||
typeof argumentList[i][callArgProp] == "function") {
|
||
return argumentList[i][callArgProp];
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
function makeApi(sinon) {
|
||
function getCallbackError(behavior, func, args) {
|
||
if (behavior.callArgAt < 0) {
|
||
var msg;
|
||
|
||
if (behavior.callArgProp) {
|
||
msg = sinon.functionName(behavior.stub) +
|
||
" expected to yield to '" + behavior.callArgProp +
|
||
"', but no object with such a property was passed.";
|
||
} else {
|
||
msg = sinon.functionName(behavior.stub) +
|
||
" expected to yield, but no callback was passed.";
|
||
}
|
||
|
||
if (args.length > 0) {
|
||
msg += " Received [" + join.call(args, ", ") + "]";
|
||
}
|
||
|
||
return msg;
|
||
}
|
||
|
||
return "argument at index " + behavior.callArgAt + " is not a function: " + func;
|
||
}
|
||
|
||
function callCallback(behavior, args) {
|
||
if (typeof behavior.callArgAt == "number") {
|
||
var func = getCallback(behavior, args);
|
||
|
||
if (typeof func != "function") {
|
||
throw new TypeError(getCallbackError(behavior, func, args));
|
||
}
|
||
|
||
if (behavior.callbackAsync) {
|
||
nextTick(function () {
|
||
func.apply(behavior.callbackContext, behavior.callbackArguments);
|
||
});
|
||
} else {
|
||
func.apply(behavior.callbackContext, behavior.callbackArguments);
|
||
}
|
||
}
|
||
}
|
||
|
||
var proto = {
|
||
create: function create(stub) {
|
||
var behavior = sinon.extend({}, sinon.behavior);
|
||
delete behavior.create;
|
||
behavior.stub = stub;
|
||
|
||
return behavior;
|
||
},
|
||
|
||
isPresent: function isPresent() {
|
||
return (typeof this.callArgAt == "number" ||
|
||
this.exception ||
|
||
typeof this.returnArgAt == "number" ||
|
||
this.returnThis ||
|
||
this.returnValueDefined);
|
||
},
|
||
|
||
invoke: function invoke(context, args) {
|
||
callCallback(this, args);
|
||
|
||
if (this.exception) {
|
||
throw this.exception;
|
||
} else if (typeof this.returnArgAt == "number") {
|
||
return args[this.returnArgAt];
|
||
} else if (this.returnThis) {
|
||
return context;
|
||
}
|
||
|
||
return this.returnValue;
|
||
},
|
||
|
||
onCall: function onCall(index) {
|
||
return this.stub.onCall(index);
|
||
},
|
||
|
||
onFirstCall: function onFirstCall() {
|
||
return this.stub.onFirstCall();
|
||
},
|
||
|
||
onSecondCall: function onSecondCall() {
|
||
return this.stub.onSecondCall();
|
||
},
|
||
|
||
onThirdCall: function onThirdCall() {
|
||
return this.stub.onThirdCall();
|
||
},
|
||
|
||
withArgs: function withArgs(/* arguments */) {
|
||
throw new Error("Defining a stub by invoking \"stub.onCall(...).withArgs(...)\" is not supported. " +
|
||
"Use \"stub.withArgs(...).onCall(...)\" to define sequential behavior for calls with certain arguments.");
|
||
},
|
||
|
||
callsArg: function callsArg(pos) {
|
||
if (typeof pos != "number") {
|
||
throw new TypeError("argument index is not number");
|
||
}
|
||
|
||
this.callArgAt = pos;
|
||
this.callbackArguments = [];
|
||
this.callbackContext = undefined;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
callsArgOn: function callsArgOn(pos, context) {
|
||
if (typeof pos != "number") {
|
||
throw new TypeError("argument index is not number");
|
||
}
|
||
if (typeof context != "object") {
|
||
throw new TypeError("argument context is not an object");
|
||
}
|
||
|
||
this.callArgAt = pos;
|
||
this.callbackArguments = [];
|
||
this.callbackContext = context;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
callsArgWith: function callsArgWith(pos) {
|
||
if (typeof pos != "number") {
|
||
throw new TypeError("argument index is not number");
|
||
}
|
||
|
||
this.callArgAt = pos;
|
||
this.callbackArguments = slice.call(arguments, 1);
|
||
this.callbackContext = undefined;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
callsArgOnWith: function callsArgWith(pos, context) {
|
||
if (typeof pos != "number") {
|
||
throw new TypeError("argument index is not number");
|
||
}
|
||
if (typeof context != "object") {
|
||
throw new TypeError("argument context is not an object");
|
||
}
|
||
|
||
this.callArgAt = pos;
|
||
this.callbackArguments = slice.call(arguments, 2);
|
||
this.callbackContext = context;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
yields: function () {
|
||
this.callArgAt = useLeftMostCallback;
|
||
this.callbackArguments = slice.call(arguments, 0);
|
||
this.callbackContext = undefined;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
yieldsRight: function () {
|
||
this.callArgAt = useRightMostCallback;
|
||
this.callbackArguments = slice.call(arguments, 0);
|
||
this.callbackContext = undefined;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
yieldsOn: function (context) {
|
||
if (typeof context != "object") {
|
||
throw new TypeError("argument context is not an object");
|
||
}
|
||
|
||
this.callArgAt = useLeftMostCallback;
|
||
this.callbackArguments = slice.call(arguments, 1);
|
||
this.callbackContext = context;
|
||
this.callArgProp = undefined;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
yieldsTo: function (prop) {
|
||
this.callArgAt = useLeftMostCallback;
|
||
this.callbackArguments = slice.call(arguments, 1);
|
||
this.callbackContext = undefined;
|
||
this.callArgProp = prop;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
yieldsToOn: function (prop, context) {
|
||
if (typeof context != "object") {
|
||
throw new TypeError("argument context is not an object");
|
||
}
|
||
|
||
this.callArgAt = useLeftMostCallback;
|
||
this.callbackArguments = slice.call(arguments, 2);
|
||
this.callbackContext = context;
|
||
this.callArgProp = prop;
|
||
this.callbackAsync = false;
|
||
|
||
return this;
|
||
},
|
||
|
||
throws: throwsException,
|
||
throwsException: throwsException,
|
||
|
||
returns: function returns(value) {
|
||
this.returnValue = value;
|
||
this.returnValueDefined = true;
|
||
|
||
return this;
|
||
},
|
||
|
||
returnsArg: function returnsArg(pos) {
|
||
if (typeof pos != "number") {
|
||
throw new TypeError("argument index is not number");
|
||
}
|
||
|
||
this.returnArgAt = pos;
|
||
|
||
return this;
|
||
},
|
||
|
||
returnsThis: function returnsThis() {
|
||
this.returnThis = true;
|
||
|
||
return this;
|
||
}
|
||
};
|
||
|
||
// create asynchronous versions of callsArg* and yields* methods
|
||
for (var method in proto) {
|
||
// need to avoid creating anotherasync versions of the newly added async methods
|
||
if (proto.hasOwnProperty(method) &&
|
||
method.match(/^(callsArg|yields)/) &&
|
||
!method.match(/Async/)) {
|
||
proto[method + "Async"] = (function (syncFnName) {
|
||
return function () {
|
||
var result = this[syncFnName].apply(this, arguments);
|
||
this.callbackAsync = true;
|
||
return result;
|
||
};
|
||
})(method);
|
||
}
|
||
}
|
||
|
||
sinon.behavior = proto;
|
||
return proto;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./extend");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
}).call(this,require("1YiZ5S"))
|
||
},{"./extend":61,"./util/core":73,"1YiZ5S":52}],59:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend match.js
|
||
* @depend format.js
|
||
*/
|
||
/**
|
||
* Spy calls
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @author Maximilian Antoni (mail@maxantoni.de)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
* Copyright (c) 2013 Maximilian Antoni
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
function throwYieldError(proxy, text, args) {
|
||
var msg = sinon.functionName(proxy) + text;
|
||
if (args.length) {
|
||
msg += " Received [" + slice.call(args).join(", ") + "]";
|
||
}
|
||
throw new Error(msg);
|
||
}
|
||
|
||
var slice = Array.prototype.slice;
|
||
|
||
var callProto = {
|
||
calledOn: function calledOn(thisValue) {
|
||
if (sinon.match && sinon.match.isMatcher(thisValue)) {
|
||
return thisValue.test(this.thisValue);
|
||
}
|
||
return this.thisValue === thisValue;
|
||
},
|
||
|
||
calledWith: function calledWith() {
|
||
var l = arguments.length;
|
||
if (l > this.args.length) {
|
||
return false;
|
||
}
|
||
for (var i = 0; i < l; i += 1) {
|
||
if (!sinon.deepEqual(arguments[i], this.args[i])) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
},
|
||
|
||
calledWithMatch: function calledWithMatch() {
|
||
var l = arguments.length;
|
||
if (l > this.args.length) {
|
||
return false;
|
||
}
|
||
for (var i = 0; i < l; i += 1) {
|
||
var actual = this.args[i];
|
||
var expectation = arguments[i];
|
||
if (!sinon.match || !sinon.match(expectation).test(actual)) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
},
|
||
|
||
calledWithExactly: function calledWithExactly() {
|
||
return arguments.length == this.args.length &&
|
||
this.calledWith.apply(this, arguments);
|
||
},
|
||
|
||
notCalledWith: function notCalledWith() {
|
||
return !this.calledWith.apply(this, arguments);
|
||
},
|
||
|
||
notCalledWithMatch: function notCalledWithMatch() {
|
||
return !this.calledWithMatch.apply(this, arguments);
|
||
},
|
||
|
||
returned: function returned(value) {
|
||
return sinon.deepEqual(value, this.returnValue);
|
||
},
|
||
|
||
threw: function threw(error) {
|
||
if (typeof error === "undefined" || !this.exception) {
|
||
return !!this.exception;
|
||
}
|
||
|
||
return this.exception === error || this.exception.name === error;
|
||
},
|
||
|
||
calledWithNew: function calledWithNew() {
|
||
return this.proxy.prototype && this.thisValue instanceof this.proxy;
|
||
},
|
||
|
||
calledBefore: function (other) {
|
||
return this.callId < other.callId;
|
||
},
|
||
|
||
calledAfter: function (other) {
|
||
return this.callId > other.callId;
|
||
},
|
||
|
||
callArg: function (pos) {
|
||
this.args[pos]();
|
||
},
|
||
|
||
callArgOn: function (pos, thisValue) {
|
||
this.args[pos].apply(thisValue);
|
||
},
|
||
|
||
callArgWith: function (pos) {
|
||
this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
|
||
},
|
||
|
||
callArgOnWith: function (pos, thisValue) {
|
||
var args = slice.call(arguments, 2);
|
||
this.args[pos].apply(thisValue, args);
|
||
},
|
||
|
||
yield: function () {
|
||
this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
|
||
},
|
||
|
||
yieldOn: function (thisValue) {
|
||
var args = this.args;
|
||
for (var i = 0, l = args.length; i < l; ++i) {
|
||
if (typeof args[i] === "function") {
|
||
args[i].apply(thisValue, slice.call(arguments, 1));
|
||
return;
|
||
}
|
||
}
|
||
throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
|
||
},
|
||
|
||
yieldTo: function (prop) {
|
||
this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
|
||
},
|
||
|
||
yieldToOn: function (prop, thisValue) {
|
||
var args = this.args;
|
||
for (var i = 0, l = args.length; i < l; ++i) {
|
||
if (args[i] && typeof args[i][prop] === "function") {
|
||
args[i][prop].apply(thisValue, slice.call(arguments, 2));
|
||
return;
|
||
}
|
||
}
|
||
throwYieldError(this.proxy, " cannot yield to '" + prop +
|
||
"' since no callback was passed.", args);
|
||
},
|
||
|
||
toString: function () {
|
||
var callStr = this.proxy.toString() + "(";
|
||
var args = [];
|
||
|
||
for (var i = 0, l = this.args.length; i < l; ++i) {
|
||
args.push(sinon.format(this.args[i]));
|
||
}
|
||
|
||
callStr = callStr + args.join(", ") + ")";
|
||
|
||
if (typeof this.returnValue != "undefined") {
|
||
callStr += " => " + sinon.format(this.returnValue);
|
||
}
|
||
|
||
if (this.exception) {
|
||
callStr += " !" + this.exception.name;
|
||
|
||
if (this.exception.message) {
|
||
callStr += "(" + this.exception.message + ")";
|
||
}
|
||
}
|
||
|
||
return callStr;
|
||
}
|
||
};
|
||
|
||
callProto.invokeCallback = callProto.yield;
|
||
|
||
function createSpyCall(spy, thisValue, args, returnValue, exception, id) {
|
||
if (typeof id !== "number") {
|
||
throw new TypeError("Call id is not a number");
|
||
}
|
||
var proxyCall = sinon.create(callProto);
|
||
proxyCall.proxy = spy;
|
||
proxyCall.thisValue = thisValue;
|
||
proxyCall.args = args;
|
||
proxyCall.returnValue = returnValue;
|
||
proxyCall.exception = exception;
|
||
proxyCall.callId = id;
|
||
|
||
return proxyCall;
|
||
}
|
||
createSpyCall.toString = callProto.toString; // used by mocks
|
||
|
||
sinon.spyCall = createSpyCall;
|
||
return createSpyCall;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./match");
|
||
require("./format");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./format":62,"./match":64,"./util/core":73}],60:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend spy.js
|
||
* @depend stub.js
|
||
* @depend mock.js
|
||
*/
|
||
/**
|
||
* Collections of stubs, spies and mocks.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
var push = [].push;
|
||
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
||
|
||
function getFakes(fakeCollection) {
|
||
if (!fakeCollection.fakes) {
|
||
fakeCollection.fakes = [];
|
||
}
|
||
|
||
return fakeCollection.fakes;
|
||
}
|
||
|
||
function each(fakeCollection, method) {
|
||
var fakes = getFakes(fakeCollection);
|
||
|
||
for (var i = 0, l = fakes.length; i < l; i += 1) {
|
||
if (typeof fakes[i][method] == "function") {
|
||
fakes[i][method]();
|
||
}
|
||
}
|
||
}
|
||
|
||
function compact(fakeCollection) {
|
||
var fakes = getFakes(fakeCollection);
|
||
var i = 0;
|
||
while (i < fakes.length) {
|
||
fakes.splice(i, 1);
|
||
}
|
||
}
|
||
|
||
function makeApi(sinon) {
|
||
var collection = {
|
||
verify: function resolve() {
|
||
each(this, "verify");
|
||
},
|
||
|
||
restore: function restore() {
|
||
each(this, "restore");
|
||
compact(this);
|
||
},
|
||
|
||
reset: function restore() {
|
||
each(this, "reset");
|
||
},
|
||
|
||
verifyAndRestore: function verifyAndRestore() {
|
||
var exception;
|
||
|
||
try {
|
||
this.verify();
|
||
} catch (e) {
|
||
exception = e;
|
||
}
|
||
|
||
this.restore();
|
||
|
||
if (exception) {
|
||
throw exception;
|
||
}
|
||
},
|
||
|
||
add: function add(fake) {
|
||
push.call(getFakes(this), fake);
|
||
return fake;
|
||
},
|
||
|
||
spy: function spy() {
|
||
return this.add(sinon.spy.apply(sinon, arguments));
|
||
},
|
||
|
||
stub: function stub(object, property, value) {
|
||
if (property) {
|
||
var original = object[property];
|
||
|
||
if (typeof original != "function") {
|
||
if (!hasOwnProperty.call(object, property)) {
|
||
throw new TypeError("Cannot stub non-existent own property " + property);
|
||
}
|
||
|
||
object[property] = value;
|
||
|
||
return this.add({
|
||
restore: function () {
|
||
object[property] = original;
|
||
}
|
||
});
|
||
}
|
||
}
|
||
if (!property && !!object && typeof object == "object") {
|
||
var stubbedObj = sinon.stub.apply(sinon, arguments);
|
||
|
||
for (var prop in stubbedObj) {
|
||
if (typeof stubbedObj[prop] === "function") {
|
||
this.add(stubbedObj[prop]);
|
||
}
|
||
}
|
||
|
||
return stubbedObj;
|
||
}
|
||
|
||
return this.add(sinon.stub.apply(sinon, arguments));
|
||
},
|
||
|
||
mock: function mock() {
|
||
return this.add(sinon.mock.apply(sinon, arguments));
|
||
},
|
||
|
||
inject: function inject(obj) {
|
||
var col = this;
|
||
|
||
obj.spy = function () {
|
||
return col.spy.apply(col, arguments);
|
||
};
|
||
|
||
obj.stub = function () {
|
||
return col.stub.apply(col, arguments);
|
||
};
|
||
|
||
obj.mock = function () {
|
||
return col.mock.apply(col, arguments);
|
||
};
|
||
|
||
return obj;
|
||
}
|
||
};
|
||
|
||
sinon.collection = collection;
|
||
return collection;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./mock");
|
||
require("./spy");
|
||
require("./stub");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./mock":65,"./spy":67,"./stub":68,"./util/core":73}],61:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
|
||
// Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
|
||
var hasDontEnumBug = (function () {
|
||
var obj = {
|
||
constructor: function () {
|
||
return "0";
|
||
},
|
||
toString: function () {
|
||
return "1";
|
||
},
|
||
valueOf: function () {
|
||
return "2";
|
||
},
|
||
toLocaleString: function () {
|
||
return "3";
|
||
},
|
||
prototype: function () {
|
||
return "4";
|
||
},
|
||
isPrototypeOf: function () {
|
||
return "5";
|
||
},
|
||
propertyIsEnumerable: function () {
|
||
return "6";
|
||
},
|
||
hasOwnProperty: function () {
|
||
return "7";
|
||
},
|
||
length: function () {
|
||
return "8";
|
||
},
|
||
unique: function () {
|
||
return "9"
|
||
}
|
||
};
|
||
|
||
var result = [];
|
||
for (var prop in obj) {
|
||
result.push(obj[prop]());
|
||
}
|
||
return result.join("") !== "0123456789";
|
||
})();
|
||
|
||
/* Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will
|
||
* override properties in previous sources.
|
||
*
|
||
* target - The Object to extend
|
||
* sources - Objects to copy properties from.
|
||
*
|
||
* Returns the extended target
|
||
*/
|
||
function extend(target /*, sources */) {
|
||
var sources = Array.prototype.slice.call(arguments, 1),
|
||
source, i, prop;
|
||
|
||
for (i = 0; i < sources.length; i++) {
|
||
source = sources[i];
|
||
|
||
for (prop in source) {
|
||
if (source.hasOwnProperty(prop)) {
|
||
target[prop] = source[prop];
|
||
}
|
||
}
|
||
|
||
// Make sure we copy (own) toString method even when in JScript with DontEnum bug
|
||
// See https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
|
||
if (hasDontEnumBug && source.hasOwnProperty("toString") && source.toString !== target.toString) {
|
||
target.toString = source.toString;
|
||
}
|
||
}
|
||
|
||
return target;
|
||
};
|
||
|
||
sinon.extend = extend;
|
||
return sinon.extend;
|
||
}
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./util/core":73}],62:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
*/
|
||
/**
|
||
* Format functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2014 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon, formatio) {
|
||
function makeApi(sinon) {
|
||
function valueFormatter(value) {
|
||
return "" + value;
|
||
}
|
||
|
||
function getFormatioFormatter() {
|
||
var formatter = formatio.configure({
|
||
quoteStrings: false,
|
||
limitChildrenCount: 250
|
||
});
|
||
|
||
function format() {
|
||
return formatter.ascii.apply(formatter, arguments);
|
||
};
|
||
|
||
return format;
|
||
}
|
||
|
||
function getNodeFormatter(value) {
|
||
function format(value) {
|
||
return typeof value == "object" && value.toString === Object.prototype.toString ? util.inspect(value) : value;
|
||
};
|
||
|
||
try {
|
||
var util = require("util");
|
||
} catch (e) {
|
||
/* Node, but no util module - would be very old, but better safe than sorry */
|
||
}
|
||
|
||
return util ? format : valueFormatter;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function",
|
||
formatter;
|
||
|
||
if (isNode) {
|
||
try {
|
||
formatio = require("formatio");
|
||
} catch (e) {}
|
||
}
|
||
|
||
if (formatio) {
|
||
formatter = getFormatioFormatter()
|
||
} else if (isNode) {
|
||
formatter = getNodeFormatter();
|
||
} else {
|
||
formatter = valueFormatter;
|
||
}
|
||
|
||
sinon.format = formatter;
|
||
return sinon.format;
|
||
}
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(
|
||
(typeof sinon == "object" && sinon || null),
|
||
(typeof formatio == "object" && formatio)
|
||
));
|
||
|
||
},{"./util/core":73,"formatio":80,"util":54}],63:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
*/
|
||
/**
|
||
* Logs errors
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2014 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
// cache a reference to setTimeout, so that our reference won't be stubbed out
|
||
// when using fake timers and errors will still get logged
|
||
// https://github.com/cjohansen/Sinon.JS/issues/381
|
||
var realSetTimeout = setTimeout;
|
||
|
||
function makeApi(sinon) {
|
||
|
||
function log() {}
|
||
|
||
function logError(label, err) {
|
||
var msg = label + " threw exception: ";
|
||
|
||
sinon.log(msg + "[" + err.name + "] " + err.message);
|
||
|
||
if (err.stack) {
|
||
sinon.log(err.stack);
|
||
}
|
||
|
||
logError.setTimeout(function () {
|
||
err.message = msg + err.message;
|
||
throw err;
|
||
}, 0);
|
||
};
|
||
|
||
// wrap realSetTimeout with something we can stub in tests
|
||
logError.setTimeout = function (func, timeout) {
|
||
realSetTimeout(func, timeout);
|
||
}
|
||
|
||
var exports = {};
|
||
exports.log = sinon.log = log;
|
||
exports.logError = sinon.logError = logError;
|
||
|
||
return exports;
|
||
}
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./util/core":73}],64:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend typeOf.js
|
||
*/
|
||
/*jslint eqeqeq: false, onevar: false, plusplus: false*/
|
||
/*global module, require, sinon*/
|
||
/**
|
||
* Match functions
|
||
*
|
||
* @author Maximilian Antoni (mail@maxantoni.de)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2012 Maximilian Antoni
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
function assertType(value, type, name) {
|
||
var actual = sinon.typeOf(value);
|
||
if (actual !== type) {
|
||
throw new TypeError("Expected type of " + name + " to be " +
|
||
type + ", but was " + actual);
|
||
}
|
||
}
|
||
|
||
var matcher = {
|
||
toString: function () {
|
||
return this.message;
|
||
}
|
||
};
|
||
|
||
function isMatcher(object) {
|
||
return matcher.isPrototypeOf(object);
|
||
}
|
||
|
||
function matchObject(expectation, actual) {
|
||
if (actual === null || actual === undefined) {
|
||
return false;
|
||
}
|
||
for (var key in expectation) {
|
||
if (expectation.hasOwnProperty(key)) {
|
||
var exp = expectation[key];
|
||
var act = actual[key];
|
||
if (match.isMatcher(exp)) {
|
||
if (!exp.test(act)) {
|
||
return false;
|
||
}
|
||
} else if (sinon.typeOf(exp) === "object") {
|
||
if (!matchObject(exp, act)) {
|
||
return false;
|
||
}
|
||
} else if (!sinon.deepEqual(exp, act)) {
|
||
return false;
|
||
}
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
matcher.or = function (m2) {
|
||
if (!arguments.length) {
|
||
throw new TypeError("Matcher expected");
|
||
} else if (!isMatcher(m2)) {
|
||
m2 = match(m2);
|
||
}
|
||
var m1 = this;
|
||
var or = sinon.create(matcher);
|
||
or.test = function (actual) {
|
||
return m1.test(actual) || m2.test(actual);
|
||
};
|
||
or.message = m1.message + ".or(" + m2.message + ")";
|
||
return or;
|
||
};
|
||
|
||
matcher.and = function (m2) {
|
||
if (!arguments.length) {
|
||
throw new TypeError("Matcher expected");
|
||
} else if (!isMatcher(m2)) {
|
||
m2 = match(m2);
|
||
}
|
||
var m1 = this;
|
||
var and = sinon.create(matcher);
|
||
and.test = function (actual) {
|
||
return m1.test(actual) && m2.test(actual);
|
||
};
|
||
and.message = m1.message + ".and(" + m2.message + ")";
|
||
return and;
|
||
};
|
||
|
||
var match = function (expectation, message) {
|
||
var m = sinon.create(matcher);
|
||
var type = sinon.typeOf(expectation);
|
||
switch (type) {
|
||
case "object":
|
||
if (typeof expectation.test === "function") {
|
||
m.test = function (actual) {
|
||
return expectation.test(actual) === true;
|
||
};
|
||
m.message = "match(" + sinon.functionName(expectation.test) + ")";
|
||
return m;
|
||
}
|
||
var str = [];
|
||
for (var key in expectation) {
|
||
if (expectation.hasOwnProperty(key)) {
|
||
str.push(key + ": " + expectation[key]);
|
||
}
|
||
}
|
||
m.test = function (actual) {
|
||
return matchObject(expectation, actual);
|
||
};
|
||
m.message = "match(" + str.join(", ") + ")";
|
||
break;
|
||
case "number":
|
||
m.test = function (actual) {
|
||
return expectation == actual;
|
||
};
|
||
break;
|
||
case "string":
|
||
m.test = function (actual) {
|
||
if (typeof actual !== "string") {
|
||
return false;
|
||
}
|
||
return actual.indexOf(expectation) !== -1;
|
||
};
|
||
m.message = "match(\"" + expectation + "\")";
|
||
break;
|
||
case "regexp":
|
||
m.test = function (actual) {
|
||
if (typeof actual !== "string") {
|
||
return false;
|
||
}
|
||
return expectation.test(actual);
|
||
};
|
||
break;
|
||
case "function":
|
||
m.test = expectation;
|
||
if (message) {
|
||
m.message = message;
|
||
} else {
|
||
m.message = "match(" + sinon.functionName(expectation) + ")";
|
||
}
|
||
break;
|
||
default:
|
||
m.test = function (actual) {
|
||
return sinon.deepEqual(expectation, actual);
|
||
};
|
||
}
|
||
if (!m.message) {
|
||
m.message = "match(" + expectation + ")";
|
||
}
|
||
return m;
|
||
};
|
||
|
||
match.isMatcher = isMatcher;
|
||
|
||
match.any = match(function () {
|
||
return true;
|
||
}, "any");
|
||
|
||
match.defined = match(function (actual) {
|
||
return actual !== null && actual !== undefined;
|
||
}, "defined");
|
||
|
||
match.truthy = match(function (actual) {
|
||
return !!actual;
|
||
}, "truthy");
|
||
|
||
match.falsy = match(function (actual) {
|
||
return !actual;
|
||
}, "falsy");
|
||
|
||
match.same = function (expectation) {
|
||
return match(function (actual) {
|
||
return expectation === actual;
|
||
}, "same(" + expectation + ")");
|
||
};
|
||
|
||
match.typeOf = function (type) {
|
||
assertType(type, "string", "type");
|
||
return match(function (actual) {
|
||
return sinon.typeOf(actual) === type;
|
||
}, "typeOf(\"" + type + "\")");
|
||
};
|
||
|
||
match.instanceOf = function (type) {
|
||
assertType(type, "function", "type");
|
||
return match(function (actual) {
|
||
return actual instanceof type;
|
||
}, "instanceOf(" + sinon.functionName(type) + ")");
|
||
};
|
||
|
||
function createPropertyMatcher(propertyTest, messagePrefix) {
|
||
return function (property, value) {
|
||
assertType(property, "string", "property");
|
||
var onlyProperty = arguments.length === 1;
|
||
var message = messagePrefix + "(\"" + property + "\"";
|
||
if (!onlyProperty) {
|
||
message += ", " + value;
|
||
}
|
||
message += ")";
|
||
return match(function (actual) {
|
||
if (actual === undefined || actual === null ||
|
||
!propertyTest(actual, property)) {
|
||
return false;
|
||
}
|
||
return onlyProperty || sinon.deepEqual(value, actual[property]);
|
||
}, message);
|
||
};
|
||
}
|
||
|
||
match.has = createPropertyMatcher(function (actual, property) {
|
||
if (typeof actual === "object") {
|
||
return property in actual;
|
||
}
|
||
return actual[property] !== undefined;
|
||
}, "has");
|
||
|
||
match.hasOwn = createPropertyMatcher(function (actual, property) {
|
||
return actual.hasOwnProperty(property);
|
||
}, "hasOwn");
|
||
|
||
match.bool = match.typeOf("boolean");
|
||
match.number = match.typeOf("number");
|
||
match.string = match.typeOf("string");
|
||
match.object = match.typeOf("object");
|
||
match.func = match.typeOf("function");
|
||
match.array = match.typeOf("array");
|
||
match.regexp = match.typeOf("regexp");
|
||
match.date = match.typeOf("date");
|
||
|
||
sinon.match = match;
|
||
return match;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./typeOf");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./typeOf":72,"./util/core":73}],65:[function(require,module,exports){
|
||
/**
|
||
* @depend times_in_words.js
|
||
* @depend util/core.js
|
||
* @depend call.js
|
||
* @depend extend.js
|
||
* @depend match.js
|
||
* @depend spy.js
|
||
* @depend stub.js
|
||
* @depend format.js
|
||
*/
|
||
/**
|
||
* Mock functions.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
var push = [].push;
|
||
var match = sinon.match;
|
||
|
||
function mock(object) {
|
||
// if (typeof console !== undefined && console.warn) {
|
||
// console.warn("mock will be removed from Sinon.JS v2.0");
|
||
// }
|
||
|
||
if (!object) {
|
||
return sinon.expectation.create("Anonymous mock");
|
||
}
|
||
|
||
return mock.create(object);
|
||
}
|
||
|
||
function each(collection, callback) {
|
||
if (!collection) {
|
||
return;
|
||
}
|
||
|
||
for (var i = 0, l = collection.length; i < l; i += 1) {
|
||
callback(collection[i]);
|
||
}
|
||
}
|
||
|
||
sinon.extend(mock, {
|
||
create: function create(object) {
|
||
if (!object) {
|
||
throw new TypeError("object is null");
|
||
}
|
||
|
||
var mockObject = sinon.extend({}, mock);
|
||
mockObject.object = object;
|
||
delete mockObject.create;
|
||
|
||
return mockObject;
|
||
},
|
||
|
||
expects: function expects(method) {
|
||
if (!method) {
|
||
throw new TypeError("method is falsy");
|
||
}
|
||
|
||
if (!this.expectations) {
|
||
this.expectations = {};
|
||
this.proxies = [];
|
||
}
|
||
|
||
if (!this.expectations[method]) {
|
||
this.expectations[method] = [];
|
||
var mockObject = this;
|
||
|
||
sinon.wrapMethod(this.object, method, function () {
|
||
return mockObject.invokeMethod(method, this, arguments);
|
||
});
|
||
|
||
push.call(this.proxies, method);
|
||
}
|
||
|
||
var expectation = sinon.expectation.create(method);
|
||
push.call(this.expectations[method], expectation);
|
||
|
||
return expectation;
|
||
},
|
||
|
||
restore: function restore() {
|
||
var object = this.object;
|
||
|
||
each(this.proxies, function (proxy) {
|
||
if (typeof object[proxy].restore == "function") {
|
||
object[proxy].restore();
|
||
}
|
||
});
|
||
},
|
||
|
||
verify: function verify() {
|
||
var expectations = this.expectations || {};
|
||
var messages = [], met = [];
|
||
|
||
each(this.proxies, function (proxy) {
|
||
each(expectations[proxy], function (expectation) {
|
||
if (!expectation.met()) {
|
||
push.call(messages, expectation.toString());
|
||
} else {
|
||
push.call(met, expectation.toString());
|
||
}
|
||
});
|
||
});
|
||
|
||
this.restore();
|
||
|
||
if (messages.length > 0) {
|
||
sinon.expectation.fail(messages.concat(met).join("\n"));
|
||
} else if (met.length > 0) {
|
||
sinon.expectation.pass(messages.concat(met).join("\n"));
|
||
}
|
||
|
||
return true;
|
||
},
|
||
|
||
invokeMethod: function invokeMethod(method, thisValue, args) {
|
||
var expectations = this.expectations && this.expectations[method];
|
||
var length = expectations && expectations.length || 0, i;
|
||
|
||
for (i = 0; i < length; i += 1) {
|
||
if (!expectations[i].met() &&
|
||
expectations[i].allowsCall(thisValue, args)) {
|
||
return expectations[i].apply(thisValue, args);
|
||
}
|
||
}
|
||
|
||
var messages = [], available, exhausted = 0;
|
||
|
||
for (i = 0; i < length; i += 1) {
|
||
if (expectations[i].allowsCall(thisValue, args)) {
|
||
available = available || expectations[i];
|
||
} else {
|
||
exhausted += 1;
|
||
}
|
||
push.call(messages, " " + expectations[i].toString());
|
||
}
|
||
|
||
if (exhausted === 0) {
|
||
return available.apply(thisValue, args);
|
||
}
|
||
|
||
messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
|
||
proxy: method,
|
||
args: args
|
||
}));
|
||
|
||
sinon.expectation.fail(messages.join("\n"));
|
||
}
|
||
});
|
||
|
||
var times = sinon.timesInWords;
|
||
var slice = Array.prototype.slice;
|
||
|
||
function callCountInWords(callCount) {
|
||
if (callCount == 0) {
|
||
return "never called";
|
||
} else {
|
||
return "called " + times(callCount);
|
||
}
|
||
}
|
||
|
||
function expectedCallCountInWords(expectation) {
|
||
var min = expectation.minCalls;
|
||
var max = expectation.maxCalls;
|
||
|
||
if (typeof min == "number" && typeof max == "number") {
|
||
var str = times(min);
|
||
|
||
if (min != max) {
|
||
str = "at least " + str + " and at most " + times(max);
|
||
}
|
||
|
||
return str;
|
||
}
|
||
|
||
if (typeof min == "number") {
|
||
return "at least " + times(min);
|
||
}
|
||
|
||
return "at most " + times(max);
|
||
}
|
||
|
||
function receivedMinCalls(expectation) {
|
||
var hasMinLimit = typeof expectation.minCalls == "number";
|
||
return !hasMinLimit || expectation.callCount >= expectation.minCalls;
|
||
}
|
||
|
||
function receivedMaxCalls(expectation) {
|
||
if (typeof expectation.maxCalls != "number") {
|
||
return false;
|
||
}
|
||
|
||
return expectation.callCount == expectation.maxCalls;
|
||
}
|
||
|
||
function verifyMatcher(possibleMatcher, arg) {
|
||
if (match && match.isMatcher(possibleMatcher)) {
|
||
return possibleMatcher.test(arg);
|
||
} else {
|
||
return true;
|
||
}
|
||
}
|
||
|
||
sinon.expectation = {
|
||
minCalls: 1,
|
||
maxCalls: 1,
|
||
|
||
create: function create(methodName) {
|
||
var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
|
||
delete expectation.create;
|
||
expectation.method = methodName;
|
||
|
||
return expectation;
|
||
},
|
||
|
||
invoke: function invoke(func, thisValue, args) {
|
||
this.verifyCallAllowed(thisValue, args);
|
||
|
||
return sinon.spy.invoke.apply(this, arguments);
|
||
},
|
||
|
||
atLeast: function atLeast(num) {
|
||
if (typeof num != "number") {
|
||
throw new TypeError("'" + num + "' is not number");
|
||
}
|
||
|
||
if (!this.limitsSet) {
|
||
this.maxCalls = null;
|
||
this.limitsSet = true;
|
||
}
|
||
|
||
this.minCalls = num;
|
||
|
||
return this;
|
||
},
|
||
|
||
atMost: function atMost(num) {
|
||
if (typeof num != "number") {
|
||
throw new TypeError("'" + num + "' is not number");
|
||
}
|
||
|
||
if (!this.limitsSet) {
|
||
this.minCalls = null;
|
||
this.limitsSet = true;
|
||
}
|
||
|
||
this.maxCalls = num;
|
||
|
||
return this;
|
||
},
|
||
|
||
never: function never() {
|
||
return this.exactly(0);
|
||
},
|
||
|
||
once: function once() {
|
||
return this.exactly(1);
|
||
},
|
||
|
||
twice: function twice() {
|
||
return this.exactly(2);
|
||
},
|
||
|
||
thrice: function thrice() {
|
||
return this.exactly(3);
|
||
},
|
||
|
||
exactly: function exactly(num) {
|
||
if (typeof num != "number") {
|
||
throw new TypeError("'" + num + "' is not a number");
|
||
}
|
||
|
||
this.atLeast(num);
|
||
return this.atMost(num);
|
||
},
|
||
|
||
met: function met() {
|
||
return !this.failed && receivedMinCalls(this);
|
||
},
|
||
|
||
verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
|
||
if (receivedMaxCalls(this)) {
|
||
this.failed = true;
|
||
sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
|
||
}
|
||
|
||
if ("expectedThis" in this && this.expectedThis !== thisValue) {
|
||
sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
|
||
this.expectedThis);
|
||
}
|
||
|
||
if (!("expectedArguments" in this)) {
|
||
return;
|
||
}
|
||
|
||
if (!args) {
|
||
sinon.expectation.fail(this.method + " received no arguments, expected " +
|
||
sinon.format(this.expectedArguments));
|
||
}
|
||
|
||
if (args.length < this.expectedArguments.length) {
|
||
sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
|
||
"), expected " + sinon.format(this.expectedArguments));
|
||
}
|
||
|
||
if (this.expectsExactArgCount &&
|
||
args.length != this.expectedArguments.length) {
|
||
sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
|
||
"), expected " + sinon.format(this.expectedArguments));
|
||
}
|
||
|
||
for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
|
||
|
||
if (!verifyMatcher(this.expectedArguments[i], args[i])) {
|
||
sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
|
||
", didn't match " + this.expectedArguments.toString());
|
||
}
|
||
|
||
if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
|
||
sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
|
||
", expected " + sinon.format(this.expectedArguments));
|
||
}
|
||
}
|
||
},
|
||
|
||
allowsCall: function allowsCall(thisValue, args) {
|
||
if (this.met() && receivedMaxCalls(this)) {
|
||
return false;
|
||
}
|
||
|
||
if ("expectedThis" in this && this.expectedThis !== thisValue) {
|
||
return false;
|
||
}
|
||
|
||
if (!("expectedArguments" in this)) {
|
||
return true;
|
||
}
|
||
|
||
args = args || [];
|
||
|
||
if (args.length < this.expectedArguments.length) {
|
||
return false;
|
||
}
|
||
|
||
if (this.expectsExactArgCount &&
|
||
args.length != this.expectedArguments.length) {
|
||
return false;
|
||
}
|
||
|
||
for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
|
||
if (!verifyMatcher(this.expectedArguments[i], args[i])) {
|
||
return false;
|
||
}
|
||
|
||
if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
},
|
||
|
||
withArgs: function withArgs() {
|
||
this.expectedArguments = slice.call(arguments);
|
||
return this;
|
||
},
|
||
|
||
withExactArgs: function withExactArgs() {
|
||
this.withArgs.apply(this, arguments);
|
||
this.expectsExactArgCount = true;
|
||
return this;
|
||
},
|
||
|
||
on: function on(thisValue) {
|
||
this.expectedThis = thisValue;
|
||
return this;
|
||
},
|
||
|
||
toString: function () {
|
||
var args = (this.expectedArguments || []).slice();
|
||
|
||
if (!this.expectsExactArgCount) {
|
||
push.call(args, "[...]");
|
||
}
|
||
|
||
var callStr = sinon.spyCall.toString.call({
|
||
proxy: this.method || "anonymous mock expectation",
|
||
args: args
|
||
});
|
||
|
||
var message = callStr.replace(", [...", "[, ...") + " " +
|
||
expectedCallCountInWords(this);
|
||
|
||
if (this.met()) {
|
||
return "Expectation met: " + message;
|
||
}
|
||
|
||
return "Expected " + message + " (" +
|
||
callCountInWords(this.callCount) + ")";
|
||
},
|
||
|
||
verify: function verify() {
|
||
if (!this.met()) {
|
||
sinon.expectation.fail(this.toString());
|
||
} else {
|
||
sinon.expectation.pass(this.toString());
|
||
}
|
||
|
||
return true;
|
||
},
|
||
|
||
pass: function pass(message) {
|
||
sinon.assert.pass(message);
|
||
},
|
||
|
||
fail: function fail(message) {
|
||
var exception = new Error(message);
|
||
exception.name = "ExpectationError";
|
||
|
||
throw exception;
|
||
}
|
||
};
|
||
|
||
sinon.mock = mock;
|
||
return mock;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./times_in_words");
|
||
require("./call");
|
||
require("./extend");
|
||
require("./match");
|
||
require("./spy");
|
||
require("./stub");
|
||
require("./format");
|
||
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./call":59,"./extend":61,"./format":62,"./match":64,"./spy":67,"./stub":68,"./times_in_words":71,"./util/core":73}],66:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend extend.js
|
||
* @depend collection.js
|
||
* @depend util/fake_timers.js
|
||
* @depend util/fake_server_with_clock.js
|
||
*/
|
||
/**
|
||
* Manages fake collections as well as fake utilities such as Sinon's
|
||
* timers and fake XHR implementation in one convenient object.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function () {
|
||
function makeApi(sinon) {
|
||
var push = [].push;
|
||
|
||
function exposeValue(sandbox, config, key, value) {
|
||
if (!value) {
|
||
return;
|
||
}
|
||
|
||
if (config.injectInto && !(key in config.injectInto)) {
|
||
config.injectInto[key] = value;
|
||
sandbox.injectedKeys.push(key);
|
||
} else {
|
||
push.call(sandbox.args, value);
|
||
}
|
||
}
|
||
|
||
function prepareSandboxFromConfig(config) {
|
||
var sandbox = sinon.create(sinon.sandbox);
|
||
|
||
if (config.useFakeServer) {
|
||
if (typeof config.useFakeServer == "object") {
|
||
sandbox.serverPrototype = config.useFakeServer;
|
||
}
|
||
|
||
sandbox.useFakeServer();
|
||
}
|
||
|
||
if (config.useFakeTimers) {
|
||
if (typeof config.useFakeTimers == "object") {
|
||
sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
|
||
} else {
|
||
sandbox.useFakeTimers();
|
||
}
|
||
}
|
||
|
||
return sandbox;
|
||
}
|
||
|
||
sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
|
||
useFakeTimers: function useFakeTimers() {
|
||
this.clock = sinon.useFakeTimers.apply(sinon, arguments);
|
||
|
||
return this.add(this.clock);
|
||
},
|
||
|
||
serverPrototype: sinon.fakeServer,
|
||
|
||
useFakeServer: function useFakeServer() {
|
||
var proto = this.serverPrototype || sinon.fakeServer;
|
||
|
||
if (!proto || !proto.create) {
|
||
return null;
|
||
}
|
||
|
||
this.server = proto.create();
|
||
return this.add(this.server);
|
||
},
|
||
|
||
inject: function (obj) {
|
||
sinon.collection.inject.call(this, obj);
|
||
|
||
if (this.clock) {
|
||
obj.clock = this.clock;
|
||
}
|
||
|
||
if (this.server) {
|
||
obj.server = this.server;
|
||
obj.requests = this.server.requests;
|
||
}
|
||
|
||
obj.match = sinon.match;
|
||
|
||
return obj;
|
||
},
|
||
|
||
restore: function () {
|
||
sinon.collection.restore.apply(this, arguments);
|
||
this.restoreContext();
|
||
},
|
||
|
||
restoreContext: function () {
|
||
if (this.injectedKeys) {
|
||
for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
|
||
delete this.injectInto[this.injectedKeys[i]];
|
||
}
|
||
this.injectedKeys = [];
|
||
}
|
||
},
|
||
|
||
create: function (config) {
|
||
if (!config) {
|
||
return sinon.create(sinon.sandbox);
|
||
}
|
||
|
||
var sandbox = prepareSandboxFromConfig(config);
|
||
sandbox.args = sandbox.args || [];
|
||
sandbox.injectedKeys = [];
|
||
sandbox.injectInto = config.injectInto;
|
||
var prop, value, exposed = sandbox.inject({});
|
||
|
||
if (config.properties) {
|
||
for (var i = 0, l = config.properties.length; i < l; i++) {
|
||
prop = config.properties[i];
|
||
value = exposed[prop] || prop == "sandbox" && sandbox;
|
||
exposeValue(sandbox, config, prop, value);
|
||
}
|
||
} else {
|
||
exposeValue(sandbox, config, "sandbox", value);
|
||
}
|
||
|
||
return sandbox;
|
||
},
|
||
|
||
match: sinon.match
|
||
});
|
||
|
||
sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
|
||
|
||
return sinon.sandbox;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./extend");
|
||
require("./util/fake_server_with_clock");
|
||
require("./util/fake_timers");
|
||
require("./collection");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}());
|
||
|
||
},{"./collection":60,"./extend":61,"./util/core":73,"./util/fake_server_with_clock":76,"./util/fake_timers":77}],67:[function(require,module,exports){
|
||
/**
|
||
* @depend times_in_words.js
|
||
* @depend util/core.js
|
||
* @depend extend.js
|
||
* @depend call.js
|
||
* @depend format.js
|
||
*/
|
||
/**
|
||
* Spy functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
|
||
function makeApi(sinon) {
|
||
var push = Array.prototype.push;
|
||
var slice = Array.prototype.slice;
|
||
var callId = 0;
|
||
|
||
function spy(object, property, types) {
|
||
if (!property && typeof object == "function") {
|
||
return spy.create(object);
|
||
}
|
||
|
||
if (!object && !property) {
|
||
return spy.create(function () { });
|
||
}
|
||
|
||
if (types) {
|
||
var methodDesc = sinon.getPropertyDescriptor(object, property);
|
||
for (var i = 0; i < types.length; i++) {
|
||
methodDesc[types[i]] = spy.create(methodDesc[types[i]]);
|
||
}
|
||
return sinon.wrapMethod(object, property, methodDesc);
|
||
} else {
|
||
var method = object[property];
|
||
return sinon.wrapMethod(object, property, spy.create(method));
|
||
}
|
||
}
|
||
|
||
function matchingFake(fakes, args, strict) {
|
||
if (!fakes) {
|
||
return;
|
||
}
|
||
|
||
for (var i = 0, l = fakes.length; i < l; i++) {
|
||
if (fakes[i].matches(args, strict)) {
|
||
return fakes[i];
|
||
}
|
||
}
|
||
}
|
||
|
||
function incrementCallCount() {
|
||
this.called = true;
|
||
this.callCount += 1;
|
||
this.notCalled = false;
|
||
this.calledOnce = this.callCount == 1;
|
||
this.calledTwice = this.callCount == 2;
|
||
this.calledThrice = this.callCount == 3;
|
||
}
|
||
|
||
function createCallProperties() {
|
||
this.firstCall = this.getCall(0);
|
||
this.secondCall = this.getCall(1);
|
||
this.thirdCall = this.getCall(2);
|
||
this.lastCall = this.getCall(this.callCount - 1);
|
||
}
|
||
|
||
var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
|
||
function createProxy(func, proxyLength) {
|
||
// Retain the function length:
|
||
var p;
|
||
if (proxyLength) {
|
||
eval("p = (function proxy(" + vars.substring(0, proxyLength * 2 - 1) +
|
||
") { return p.invoke(func, this, slice.call(arguments)); });");
|
||
} else {
|
||
p = function proxy() {
|
||
return p.invoke(func, this, slice.call(arguments));
|
||
};
|
||
}
|
||
p.isSinonProxy = true;
|
||
return p;
|
||
}
|
||
|
||
var uuid = 0;
|
||
|
||
// Public API
|
||
var spyApi = {
|
||
reset: function () {
|
||
if (this.invoking) {
|
||
var err = new Error("Cannot reset Sinon function while invoking it. " +
|
||
"Move the call to .reset outside of the callback.");
|
||
err.name = "InvalidResetException";
|
||
throw err;
|
||
}
|
||
|
||
this.called = false;
|
||
this.notCalled = true;
|
||
this.calledOnce = false;
|
||
this.calledTwice = false;
|
||
this.calledThrice = false;
|
||
this.callCount = 0;
|
||
this.firstCall = null;
|
||
this.secondCall = null;
|
||
this.thirdCall = null;
|
||
this.lastCall = null;
|
||
this.args = [];
|
||
this.returnValues = [];
|
||
this.thisValues = [];
|
||
this.exceptions = [];
|
||
this.callIds = [];
|
||
if (this.fakes) {
|
||
for (var i = 0; i < this.fakes.length; i++) {
|
||
this.fakes[i].reset();
|
||
}
|
||
}
|
||
|
||
return this;
|
||
},
|
||
|
||
create: function create(func, spyLength) {
|
||
var name;
|
||
|
||
if (typeof func != "function") {
|
||
func = function () { };
|
||
} else {
|
||
name = sinon.functionName(func);
|
||
}
|
||
|
||
if (!spyLength) {
|
||
spyLength = func.length;
|
||
}
|
||
|
||
var proxy = createProxy(func, spyLength);
|
||
|
||
sinon.extend(proxy, spy);
|
||
delete proxy.create;
|
||
sinon.extend(proxy, func);
|
||
|
||
proxy.reset();
|
||
proxy.prototype = func.prototype;
|
||
proxy.displayName = name || "spy";
|
||
proxy.toString = sinon.functionToString;
|
||
proxy.instantiateFake = sinon.spy.create;
|
||
proxy.id = "spy#" + uuid++;
|
||
|
||
return proxy;
|
||
},
|
||
|
||
invoke: function invoke(func, thisValue, args) {
|
||
var matching = matchingFake(this.fakes, args);
|
||
var exception, returnValue;
|
||
|
||
incrementCallCount.call(this);
|
||
push.call(this.thisValues, thisValue);
|
||
push.call(this.args, args);
|
||
push.call(this.callIds, callId++);
|
||
|
||
// Make call properties available from within the spied function:
|
||
createCallProperties.call(this);
|
||
|
||
try {
|
||
this.invoking = true;
|
||
|
||
if (matching) {
|
||
returnValue = matching.invoke(func, thisValue, args);
|
||
} else {
|
||
returnValue = (this.func || func).apply(thisValue, args);
|
||
}
|
||
|
||
var thisCall = this.getCall(this.callCount - 1);
|
||
if (thisCall.calledWithNew() && typeof returnValue !== "object") {
|
||
returnValue = thisValue;
|
||
}
|
||
} catch (e) {
|
||
exception = e;
|
||
} finally {
|
||
delete this.invoking;
|
||
}
|
||
|
||
push.call(this.exceptions, exception);
|
||
push.call(this.returnValues, returnValue);
|
||
|
||
// Make return value and exception available in the calls:
|
||
createCallProperties.call(this);
|
||
|
||
if (exception !== undefined) {
|
||
throw exception;
|
||
}
|
||
|
||
return returnValue;
|
||
},
|
||
|
||
named: function named(name) {
|
||
this.displayName = name;
|
||
return this;
|
||
},
|
||
|
||
getCall: function getCall(i) {
|
||
if (i < 0 || i >= this.callCount) {
|
||
return null;
|
||
}
|
||
|
||
return sinon.spyCall(this, this.thisValues[i], this.args[i],
|
||
this.returnValues[i], this.exceptions[i],
|
||
this.callIds[i]);
|
||
},
|
||
|
||
getCalls: function () {
|
||
var calls = [];
|
||
var i;
|
||
|
||
for (i = 0; i < this.callCount; i++) {
|
||
calls.push(this.getCall(i));
|
||
}
|
||
|
||
return calls;
|
||
},
|
||
|
||
calledBefore: function calledBefore(spyFn) {
|
||
if (!this.called) {
|
||
return false;
|
||
}
|
||
|
||
if (!spyFn.called) {
|
||
return true;
|
||
}
|
||
|
||
return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
|
||
},
|
||
|
||
calledAfter: function calledAfter(spyFn) {
|
||
if (!this.called || !spyFn.called) {
|
||
return false;
|
||
}
|
||
|
||
return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
|
||
},
|
||
|
||
withArgs: function () {
|
||
var args = slice.call(arguments);
|
||
|
||
if (this.fakes) {
|
||
var match = matchingFake(this.fakes, args, true);
|
||
|
||
if (match) {
|
||
return match;
|
||
}
|
||
} else {
|
||
this.fakes = [];
|
||
}
|
||
|
||
var original = this;
|
||
var fake = this.instantiateFake();
|
||
fake.matchingAguments = args;
|
||
fake.parent = this;
|
||
push.call(this.fakes, fake);
|
||
|
||
fake.withArgs = function () {
|
||
return original.withArgs.apply(original, arguments);
|
||
};
|
||
|
||
for (var i = 0; i < this.args.length; i++) {
|
||
if (fake.matches(this.args[i])) {
|
||
incrementCallCount.call(fake);
|
||
push.call(fake.thisValues, this.thisValues[i]);
|
||
push.call(fake.args, this.args[i]);
|
||
push.call(fake.returnValues, this.returnValues[i]);
|
||
push.call(fake.exceptions, this.exceptions[i]);
|
||
push.call(fake.callIds, this.callIds[i]);
|
||
}
|
||
}
|
||
createCallProperties.call(fake);
|
||
|
||
return fake;
|
||
},
|
||
|
||
matches: function (args, strict) {
|
||
var margs = this.matchingAguments;
|
||
|
||
if (margs.length <= args.length &&
|
||
sinon.deepEqual(margs, args.slice(0, margs.length))) {
|
||
return !strict || margs.length == args.length;
|
||
}
|
||
},
|
||
|
||
printf: function (format) {
|
||
var spy = this;
|
||
var args = slice.call(arguments, 1);
|
||
var formatter;
|
||
|
||
return (format || "").replace(/%(.)/g, function (match, specifyer) {
|
||
formatter = spyApi.formatters[specifyer];
|
||
|
||
if (typeof formatter == "function") {
|
||
return formatter.call(null, spy, args);
|
||
} else if (!isNaN(parseInt(specifyer, 10))) {
|
||
return sinon.format(args[specifyer - 1]);
|
||
}
|
||
|
||
return "%" + specifyer;
|
||
});
|
||
}
|
||
};
|
||
|
||
function delegateToCalls(method, matchAny, actual, notCalled) {
|
||
spyApi[method] = function () {
|
||
if (!this.called) {
|
||
if (notCalled) {
|
||
return notCalled.apply(this, arguments);
|
||
}
|
||
return false;
|
||
}
|
||
|
||
var currentCall;
|
||
var matches = 0;
|
||
|
||
for (var i = 0, l = this.callCount; i < l; i += 1) {
|
||
currentCall = this.getCall(i);
|
||
|
||
if (currentCall[actual || method].apply(currentCall, arguments)) {
|
||
matches += 1;
|
||
|
||
if (matchAny) {
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
|
||
return matches === this.callCount;
|
||
};
|
||
}
|
||
|
||
delegateToCalls("calledOn", true);
|
||
delegateToCalls("alwaysCalledOn", false, "calledOn");
|
||
delegateToCalls("calledWith", true);
|
||
delegateToCalls("calledWithMatch", true);
|
||
delegateToCalls("alwaysCalledWith", false, "calledWith");
|
||
delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
|
||
delegateToCalls("calledWithExactly", true);
|
||
delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
|
||
delegateToCalls("neverCalledWith", false, "notCalledWith", function () {
|
||
return true;
|
||
});
|
||
delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch", function () {
|
||
return true;
|
||
});
|
||
delegateToCalls("threw", true);
|
||
delegateToCalls("alwaysThrew", false, "threw");
|
||
delegateToCalls("returned", true);
|
||
delegateToCalls("alwaysReturned", false, "returned");
|
||
delegateToCalls("calledWithNew", true);
|
||
delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
|
||
delegateToCalls("callArg", false, "callArgWith", function () {
|
||
throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
|
||
});
|
||
spyApi.callArgWith = spyApi.callArg;
|
||
delegateToCalls("callArgOn", false, "callArgOnWith", function () {
|
||
throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
|
||
});
|
||
spyApi.callArgOnWith = spyApi.callArgOn;
|
||
delegateToCalls("yield", false, "yield", function () {
|
||
throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
|
||
});
|
||
// "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
|
||
spyApi.invokeCallback = spyApi.yield;
|
||
delegateToCalls("yieldOn", false, "yieldOn", function () {
|
||
throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
|
||
});
|
||
delegateToCalls("yieldTo", false, "yieldTo", function (property) {
|
||
throw new Error(this.toString() + " cannot yield to '" + property +
|
||
"' since it was not yet invoked.");
|
||
});
|
||
delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
|
||
throw new Error(this.toString() + " cannot yield to '" + property +
|
||
"' since it was not yet invoked.");
|
||
});
|
||
|
||
spyApi.formatters = {
|
||
c: function (spy) {
|
||
return sinon.timesInWords(spy.callCount);
|
||
},
|
||
|
||
n: function (spy) {
|
||
return spy.toString();
|
||
},
|
||
|
||
C: function (spy) {
|
||
var calls = [];
|
||
|
||
for (var i = 0, l = spy.callCount; i < l; ++i) {
|
||
var stringifiedCall = " " + spy.getCall(i).toString();
|
||
if (/\n/.test(calls[i - 1])) {
|
||
stringifiedCall = "\n" + stringifiedCall;
|
||
}
|
||
push.call(calls, stringifiedCall);
|
||
}
|
||
|
||
return calls.length > 0 ? "\n" + calls.join("\n") : "";
|
||
},
|
||
|
||
t: function (spy) {
|
||
var objects = [];
|
||
|
||
for (var i = 0, l = spy.callCount; i < l; ++i) {
|
||
push.call(objects, sinon.format(spy.thisValues[i]));
|
||
}
|
||
|
||
return objects.join(", ");
|
||
},
|
||
|
||
"*": function (spy, args) {
|
||
var formatted = [];
|
||
|
||
for (var i = 0, l = args.length; i < l; ++i) {
|
||
push.call(formatted, sinon.format(args[i]));
|
||
}
|
||
|
||
return formatted.join(", ");
|
||
}
|
||
};
|
||
|
||
sinon.extend(spy, spyApi);
|
||
|
||
spy.spyCall = sinon.spyCall;
|
||
sinon.spy = spy;
|
||
|
||
return spy;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./call");
|
||
require("./extend");
|
||
require("./times_in_words");
|
||
require("./format");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./call":59,"./extend":61,"./format":62,"./times_in_words":71,"./util/core":73}],68:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend extend.js
|
||
* @depend spy.js
|
||
* @depend behavior.js
|
||
*/
|
||
/**
|
||
* Stub functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
function stub(object, property, func) {
|
||
if (!!func && typeof func != "function" && typeof func != "object") {
|
||
throw new TypeError("Custom stub should be a function or a property descriptor");
|
||
}
|
||
|
||
var wrapper;
|
||
|
||
if (func) {
|
||
if (typeof func == "function") {
|
||
wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
|
||
} else {
|
||
wrapper = func;
|
||
if (sinon.spy && sinon.spy.create) {
|
||
var types = sinon.objectKeys(wrapper);
|
||
for (var i = 0; i < types.length; i++) {
|
||
wrapper[types[i]] = sinon.spy.create(wrapper[types[i]]);
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
var stubLength = 0;
|
||
if (typeof object == "object" && typeof object[property] == "function") {
|
||
stubLength = object[property].length;
|
||
}
|
||
wrapper = stub.create(stubLength);
|
||
}
|
||
|
||
if (!object && typeof property === "undefined") {
|
||
return sinon.stub.create();
|
||
}
|
||
|
||
if (typeof property === "undefined" && typeof object == "object") {
|
||
for (var prop in object) {
|
||
if (typeof sinon.getPropertyDescriptor(object, prop).value === "function") {
|
||
stub(object, prop);
|
||
}
|
||
}
|
||
|
||
return object;
|
||
}
|
||
|
||
return sinon.wrapMethod(object, property, wrapper);
|
||
}
|
||
|
||
function getDefaultBehavior(stub) {
|
||
return stub.defaultBehavior || getParentBehaviour(stub) || sinon.behavior.create(stub);
|
||
}
|
||
|
||
function getParentBehaviour(stub) {
|
||
return (stub.parent && getCurrentBehavior(stub.parent));
|
||
}
|
||
|
||
function getCurrentBehavior(stub) {
|
||
var behavior = stub.behaviors[stub.callCount - 1];
|
||
return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stub);
|
||
}
|
||
|
||
var uuid = 0;
|
||
|
||
var proto = {
|
||
create: function create(stubLength) {
|
||
var functionStub = function () {
|
||
return getCurrentBehavior(functionStub).invoke(this, arguments);
|
||
};
|
||
|
||
functionStub.id = "stub#" + uuid++;
|
||
var orig = functionStub;
|
||
functionStub = sinon.spy.create(functionStub, stubLength);
|
||
functionStub.func = orig;
|
||
|
||
sinon.extend(functionStub, stub);
|
||
functionStub.instantiateFake = sinon.stub.create;
|
||
functionStub.displayName = "stub";
|
||
functionStub.toString = sinon.functionToString;
|
||
|
||
functionStub.defaultBehavior = null;
|
||
functionStub.behaviors = [];
|
||
|
||
return functionStub;
|
||
},
|
||
|
||
resetBehavior: function () {
|
||
var i;
|
||
|
||
this.defaultBehavior = null;
|
||
this.behaviors = [];
|
||
|
||
delete this.returnValue;
|
||
delete this.returnArgAt;
|
||
this.returnThis = false;
|
||
|
||
if (this.fakes) {
|
||
for (i = 0; i < this.fakes.length; i++) {
|
||
this.fakes[i].resetBehavior();
|
||
}
|
||
}
|
||
},
|
||
|
||
onCall: function onCall(index) {
|
||
if (!this.behaviors[index]) {
|
||
this.behaviors[index] = sinon.behavior.create(this);
|
||
}
|
||
|
||
return this.behaviors[index];
|
||
},
|
||
|
||
onFirstCall: function onFirstCall() {
|
||
return this.onCall(0);
|
||
},
|
||
|
||
onSecondCall: function onSecondCall() {
|
||
return this.onCall(1);
|
||
},
|
||
|
||
onThirdCall: function onThirdCall() {
|
||
return this.onCall(2);
|
||
}
|
||
};
|
||
|
||
for (var method in sinon.behavior) {
|
||
if (sinon.behavior.hasOwnProperty(method) &&
|
||
!proto.hasOwnProperty(method) &&
|
||
method != "create" &&
|
||
method != "withArgs" &&
|
||
method != "invoke") {
|
||
proto[method] = (function (behaviorMethod) {
|
||
return function () {
|
||
this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
|
||
this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
|
||
return this;
|
||
};
|
||
}(method));
|
||
}
|
||
}
|
||
|
||
sinon.extend(stub, proto);
|
||
sinon.stub = stub;
|
||
|
||
return stub;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./behavior");
|
||
require("./spy");
|
||
require("./extend");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./behavior":58,"./extend":61,"./spy":67,"./util/core":73}],69:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend sandbox.js
|
||
*/
|
||
/**
|
||
* Test function, sandboxes fakes
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
var slice = Array.prototype.slice;
|
||
|
||
function test(callback) {
|
||
var type = typeof callback;
|
||
|
||
if (type != "function") {
|
||
throw new TypeError("sinon.test needs to wrap a test function, got " + type);
|
||
}
|
||
|
||
function sinonSandboxedTest() {
|
||
var config = sinon.getConfig(sinon.config);
|
||
config.injectInto = config.injectIntoThis && this || config.injectInto;
|
||
var sandbox = sinon.sandbox.create(config);
|
||
var args = slice.call(arguments);
|
||
var oldDone = args.length && args[args.length - 1];
|
||
var exception, result;
|
||
|
||
if (typeof oldDone == "function") {
|
||
args[args.length - 1] = function sinonDone(result) {
|
||
if (result) {
|
||
sandbox.restore();
|
||
throw exception;
|
||
} else {
|
||
sandbox.verifyAndRestore();
|
||
}
|
||
oldDone(result);
|
||
};
|
||
}
|
||
|
||
try {
|
||
result = callback.apply(this, args.concat(sandbox.args));
|
||
} catch (e) {
|
||
exception = e;
|
||
}
|
||
|
||
if (typeof oldDone != "function") {
|
||
if (typeof exception !== "undefined") {
|
||
sandbox.restore();
|
||
throw exception;
|
||
} else {
|
||
sandbox.verifyAndRestore();
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
if (callback.length) {
|
||
return function sinonAsyncSandboxedTest(callback) {
|
||
return sinonSandboxedTest.apply(this, arguments);
|
||
};
|
||
}
|
||
|
||
return sinonSandboxedTest;
|
||
}
|
||
|
||
test.config = {
|
||
injectIntoThis: true,
|
||
injectInto: null,
|
||
properties: ["spy", "stub", "mock", "clock", "server", "requests"],
|
||
useFakeTimers: true,
|
||
useFakeServer: true
|
||
};
|
||
|
||
sinon.test = test;
|
||
return test;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./sandbox");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (sinon) {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./sandbox":66,"./util/core":73}],70:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
* @depend test.js
|
||
*/
|
||
/**
|
||
* Test case, sandboxes all test functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function createTest(property, setUp, tearDown) {
|
||
return function () {
|
||
if (setUp) {
|
||
setUp.apply(this, arguments);
|
||
}
|
||
|
||
var exception, result;
|
||
|
||
try {
|
||
result = property.apply(this, arguments);
|
||
} catch (e) {
|
||
exception = e;
|
||
}
|
||
|
||
if (tearDown) {
|
||
tearDown.apply(this, arguments);
|
||
}
|
||
|
||
if (exception) {
|
||
throw exception;
|
||
}
|
||
|
||
return result;
|
||
};
|
||
}
|
||
|
||
function makeApi(sinon) {
|
||
function testCase(tests, prefix) {
|
||
if (!tests || typeof tests != "object") {
|
||
throw new TypeError("sinon.testCase needs an object with test functions");
|
||
}
|
||
|
||
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) && !/^(setUp|tearDown)$/.test(testName)) {
|
||
property = tests[testName];
|
||
|
||
if (typeof property == "function" && rPrefix.test(testName)) {
|
||
method = property;
|
||
|
||
if (setUp || tearDown) {
|
||
method = createTest(property, setUp, tearDown);
|
||
}
|
||
|
||
methods[testName] = sinon.test(method);
|
||
} else {
|
||
methods[testName] = tests[testName];
|
||
}
|
||
}
|
||
}
|
||
|
||
return methods;
|
||
}
|
||
|
||
sinon.testCase = testCase;
|
||
return testCase;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
require("./test");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./test":69,"./util/core":73}],71:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
function makeApi(sinon) {
|
||
|
||
function timesInWords(count) {
|
||
switch (count) {
|
||
case 1:
|
||
return "once";
|
||
case 2:
|
||
return "twice";
|
||
case 3:
|
||
return "thrice";
|
||
default:
|
||
return (count || 0) + " times";
|
||
}
|
||
}
|
||
|
||
sinon.timesInWords = timesInWords;
|
||
return sinon.timesInWords;
|
||
}
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{"./util/core":73}],72:[function(require,module,exports){
|
||
/**
|
||
* @depend util/core.js
|
||
*/
|
||
/**
|
||
* Format functions
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2014 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon, formatio) {
|
||
function makeApi(sinon) {
|
||
function typeOf(value) {
|
||
if (value === null) {
|
||
return "null";
|
||
} else if (value === undefined) {
|
||
return "undefined";
|
||
}
|
||
var string = Object.prototype.toString.call(value);
|
||
return string.substring(8, string.length - 1).toLowerCase();
|
||
};
|
||
|
||
sinon.typeOf = typeOf;
|
||
return sinon.typeOf;
|
||
}
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./util/core");
|
||
module.exports = makeApi(sinon);
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(
|
||
(typeof sinon == "object" && sinon || null),
|
||
(typeof formatio == "object" && formatio)
|
||
));
|
||
|
||
},{"./util/core":73}],73:[function(require,module,exports){
|
||
/**
|
||
* @depend ../../sinon.js
|
||
*/
|
||
/**
|
||
* Sinon core utilities. For internal use only.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (sinon) {
|
||
var div = typeof document != "undefined" && document.createElement("div");
|
||
var hasOwn = Object.prototype.hasOwnProperty;
|
||
|
||
function isDOMNode(obj) {
|
||
var success = false;
|
||
|
||
try {
|
||
obj.appendChild(div);
|
||
success = div.parentNode == obj;
|
||
} catch (e) {
|
||
return false;
|
||
} finally {
|
||
try {
|
||
obj.removeChild(div);
|
||
} catch (e) {
|
||
// Remove failed, not much we can do about that
|
||
}
|
||
}
|
||
|
||
return success;
|
||
}
|
||
|
||
function isElement(obj) {
|
||
return div && obj && obj.nodeType === 1 && isDOMNode(obj);
|
||
}
|
||
|
||
function isFunction(obj) {
|
||
return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
|
||
}
|
||
|
||
function isReallyNaN(val) {
|
||
return typeof val === "number" && isNaN(val);
|
||
}
|
||
|
||
function mirrorProperties(target, source) {
|
||
for (var prop in source) {
|
||
if (!hasOwn.call(target, prop)) {
|
||
target[prop] = source[prop];
|
||
}
|
||
}
|
||
}
|
||
|
||
function isRestorable(obj) {
|
||
return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
|
||
}
|
||
|
||
// Cheap way to detect if we have ES5 support.
|
||
var hasES5Support = "keys" in Object;
|
||
|
||
function makeApi(sinon) {
|
||
sinon.wrapMethod = function wrapMethod(object, property, method) {
|
||
if (!object) {
|
||
throw new TypeError("Should wrap property of object");
|
||
}
|
||
|
||
if (typeof method != "function" && typeof method != "object") {
|
||
throw new TypeError("Method wrapper should be a function or a property descriptor");
|
||
}
|
||
|
||
function checkWrappedMethod(wrappedMethod) {
|
||
if (!isFunction(wrappedMethod)) {
|
||
error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
|
||
property + " as function");
|
||
} else if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
|
||
error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
|
||
} else if (wrappedMethod.calledBefore) {
|
||
var verb = !!wrappedMethod.returns ? "stubbed" : "spied on";
|
||
error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
|
||
}
|
||
|
||
if (error) {
|
||
if (wrappedMethod && wrappedMethod.stackTrace) {
|
||
error.stack += "\n--------------\n" + wrappedMethod.stackTrace;
|
||
}
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
var error, wrappedMethod;
|
||
|
||
// IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
|
||
// when using hasOwn.call on objects from other frames.
|
||
var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
|
||
|
||
if (hasES5Support) {
|
||
var methodDesc = (typeof method == "function") ? {value: method} : method,
|
||
wrappedMethodDesc = sinon.getPropertyDescriptor(object, property),
|
||
i;
|
||
|
||
if (!wrappedMethodDesc) {
|
||
error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
|
||
property + " as function");
|
||
} else if (wrappedMethodDesc.restore && wrappedMethodDesc.restore.sinon) {
|
||
error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
|
||
}
|
||
if (error) {
|
||
if (wrappedMethodDesc && wrappedMethodDesc.stackTrace) {
|
||
error.stack += "\n--------------\n" + wrappedMethodDesc.stackTrace;
|
||
}
|
||
throw error;
|
||
}
|
||
|
||
var types = sinon.objectKeys(methodDesc);
|
||
for (i = 0; i < types.length; i++) {
|
||
wrappedMethod = wrappedMethodDesc[types[i]];
|
||
checkWrappedMethod(wrappedMethod);
|
||
}
|
||
|
||
mirrorProperties(methodDesc, wrappedMethodDesc);
|
||
for (i = 0; i < types.length; i++) {
|
||
mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]);
|
||
}
|
||
Object.defineProperty(object, property, methodDesc);
|
||
} else {
|
||
wrappedMethod = object[property];
|
||
checkWrappedMethod(wrappedMethod);
|
||
object[property] = method;
|
||
method.displayName = property;
|
||
}
|
||
|
||
method.displayName = property;
|
||
|
||
// Set up a stack trace which can be used later to find what line of
|
||
// code the original method was created on.
|
||
method.stackTrace = (new Error("Stack Trace for original")).stack;
|
||
|
||
method.restore = function () {
|
||
// For prototype properties try to reset by delete first.
|
||
// If this fails (ex: localStorage on mobile safari) then force a reset
|
||
// via direct assignment.
|
||
if (!owned) {
|
||
// In some cases `delete` may throw an error
|
||
try {
|
||
delete object[property];
|
||
} catch (e) {}
|
||
// For native code functions `delete` fails without throwing an error
|
||
// on Chrome < 43, PhantomJS, etc.
|
||
} else if (hasES5Support) {
|
||
Object.defineProperty(object, property, wrappedMethodDesc);
|
||
}
|
||
|
||
// Use strict equality comparison to check failures then force a reset
|
||
// via direct assignment.
|
||
if (object[property] === method) {
|
||
object[property] = wrappedMethod;
|
||
}
|
||
};
|
||
|
||
method.restore.sinon = true;
|
||
|
||
if (!hasES5Support) {
|
||
mirrorProperties(method, wrappedMethod);
|
||
}
|
||
|
||
return method;
|
||
};
|
||
|
||
sinon.create = function create(proto) {
|
||
var F = function () {};
|
||
F.prototype = proto;
|
||
return new F();
|
||
};
|
||
|
||
sinon.deepEqual = function deepEqual(a, b) {
|
||
if (sinon.match && sinon.match.isMatcher(a)) {
|
||
return a.test(b);
|
||
}
|
||
|
||
if (typeof a != "object" || typeof b != "object") {
|
||
if (isReallyNaN(a) && isReallyNaN(b)) {
|
||
return true;
|
||
} else {
|
||
return a === b;
|
||
}
|
||
}
|
||
|
||
if (isElement(a) || isElement(b)) {
|
||
return a === b;
|
||
}
|
||
|
||
if (a === b) {
|
||
return true;
|
||
}
|
||
|
||
if ((a === null && b !== null) || (a !== null && b === null)) {
|
||
return false;
|
||
}
|
||
|
||
if (a instanceof RegExp && b instanceof RegExp) {
|
||
return (a.source === b.source) && (a.global === b.global) &&
|
||
(a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
|
||
}
|
||
|
||
var aString = Object.prototype.toString.call(a);
|
||
if (aString != Object.prototype.toString.call(b)) {
|
||
return false;
|
||
}
|
||
|
||
if (aString == "[object Date]") {
|
||
return a.valueOf() === b.valueOf();
|
||
}
|
||
|
||
var prop, aLength = 0, bLength = 0;
|
||
|
||
if (aString == "[object Array]" && a.length !== b.length) {
|
||
return false;
|
||
}
|
||
|
||
for (prop in a) {
|
||
aLength += 1;
|
||
|
||
if (!(prop in b)) {
|
||
return false;
|
||
}
|
||
|
||
if (!deepEqual(a[prop], b[prop])) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
for (prop in b) {
|
||
bLength += 1;
|
||
}
|
||
|
||
return aLength == bLength;
|
||
};
|
||
|
||
sinon.functionName = function functionName(func) {
|
||
var name = func.displayName || func.name;
|
||
|
||
// Use function decomposition as a last resort to get function
|
||
// name. Does not rely on function decomposition to work - if it
|
||
// doesn't debugging will be slightly less informative
|
||
// (i.e. toString will say 'spy' rather than 'myFunc').
|
||
if (!name) {
|
||
var matches = func.toString().match(/function ([^\s\(]+)/);
|
||
name = matches && matches[1];
|
||
}
|
||
|
||
return name;
|
||
};
|
||
|
||
sinon.functionToString = function toString() {
|
||
if (this.getCall && this.callCount) {
|
||
var thisValue, prop, i = this.callCount;
|
||
|
||
while (i--) {
|
||
thisValue = this.getCall(i).thisValue;
|
||
|
||
for (prop in thisValue) {
|
||
if (thisValue[prop] === this) {
|
||
return prop;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return this.displayName || "sinon fake";
|
||
};
|
||
|
||
sinon.objectKeys = function objectKeys(obj) {
|
||
if (obj !== Object(obj)) {
|
||
throw new TypeError("sinon.objectKeys called on a non-object");
|
||
}
|
||
|
||
var keys = [];
|
||
var key;
|
||
for (key in obj) {
|
||
if (hasOwn.call(obj, key)) {
|
||
keys.push(key);
|
||
}
|
||
}
|
||
|
||
return keys;
|
||
};
|
||
|
||
sinon.getPropertyDescriptor = function getPropertyDescriptor(object, property) {
|
||
var proto = object, descriptor;
|
||
while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
|
||
proto = Object.getPrototypeOf(proto);
|
||
}
|
||
return descriptor;
|
||
}
|
||
|
||
sinon.getConfig = function (custom) {
|
||
var config = {};
|
||
custom = custom || {};
|
||
var defaults = sinon.defaultConfig;
|
||
|
||
for (var prop in defaults) {
|
||
if (defaults.hasOwnProperty(prop)) {
|
||
config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
|
||
}
|
||
}
|
||
|
||
return config;
|
||
};
|
||
|
||
sinon.defaultConfig = {
|
||
injectIntoThis: true,
|
||
injectInto: null,
|
||
properties: ["spy", "stub", "mock", "clock", "server", "requests"],
|
||
useFakeTimers: true,
|
||
useFakeServer: true
|
||
};
|
||
|
||
sinon.timesInWords = function timesInWords(count) {
|
||
return count == 1 && "once" ||
|
||
count == 2 && "twice" ||
|
||
count == 3 && "thrice" ||
|
||
(count || 0) + " times";
|
||
};
|
||
|
||
sinon.calledInOrder = function (spies) {
|
||
for (var i = 1, l = spies.length; i < l; i++) {
|
||
if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
};
|
||
|
||
sinon.orderByFirstCall = function (spies) {
|
||
return spies.sort(function (a, b) {
|
||
// uuid, won't ever be equal
|
||
var aCall = a.getCall(0);
|
||
var bCall = b.getCall(0);
|
||
var aId = aCall && aCall.callId || -1;
|
||
var bId = bCall && bCall.callId || -1;
|
||
|
||
return aId < bId ? -1 : 1;
|
||
});
|
||
};
|
||
|
||
sinon.createStubInstance = function (constructor) {
|
||
if (typeof constructor !== "function") {
|
||
throw new TypeError("The constructor should be a function.");
|
||
}
|
||
return sinon.stub(sinon.create(constructor.prototype));
|
||
};
|
||
|
||
sinon.restore = function (object) {
|
||
if (object !== null && typeof object === "object") {
|
||
for (var prop in object) {
|
||
if (isRestorable(object[prop])) {
|
||
object[prop].restore();
|
||
}
|
||
}
|
||
} else if (isRestorable(object)) {
|
||
object.restore();
|
||
}
|
||
};
|
||
|
||
return sinon;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports) {
|
||
makeApi(exports);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports);
|
||
} else if (!sinon) {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof sinon == "object" && sinon || null));
|
||
|
||
},{}],74:[function(require,module,exports){
|
||
/**
|
||
* Minimal Event interface implementation
|
||
*
|
||
* Original implementation by Sven Fuchs: https://gist.github.com/995028
|
||
* Modifications and tests by Christian Johansen.
|
||
*
|
||
* @author Sven Fuchs (svenfuchs@artweb-design.de)
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2011 Sven Fuchs, Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
if (typeof sinon == "undefined") {
|
||
this.sinon = {};
|
||
}
|
||
|
||
(function () {
|
||
var push = [].push;
|
||
|
||
function makeApi(sinon) {
|
||
sinon.Event = function Event(type, bubbles, cancelable, target) {
|
||
this.initEvent(type, bubbles, cancelable, target);
|
||
};
|
||
|
||
sinon.Event.prototype = {
|
||
initEvent: function (type, bubbles, cancelable, target) {
|
||
this.type = type;
|
||
this.bubbles = bubbles;
|
||
this.cancelable = cancelable;
|
||
this.target = target;
|
||
},
|
||
|
||
stopPropagation: function () {},
|
||
|
||
preventDefault: function () {
|
||
this.defaultPrevented = true;
|
||
}
|
||
};
|
||
|
||
sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
|
||
this.initEvent(type, false, false, target);
|
||
this.loaded = progressEventRaw.loaded || null;
|
||
this.total = progressEventRaw.total || null;
|
||
this.lengthComputable = !!progressEventRaw.total;
|
||
};
|
||
|
||
sinon.ProgressEvent.prototype = new sinon.Event();
|
||
|
||
sinon.ProgressEvent.prototype.constructor = sinon.ProgressEvent;
|
||
|
||
sinon.CustomEvent = function CustomEvent(type, customData, target) {
|
||
this.initEvent(type, false, false, target);
|
||
this.detail = customData.detail || null;
|
||
};
|
||
|
||
sinon.CustomEvent.prototype = new sinon.Event();
|
||
|
||
sinon.CustomEvent.prototype.constructor = sinon.CustomEvent;
|
||
|
||
sinon.EventTarget = {
|
||
addEventListener: function addEventListener(event, listener) {
|
||
this.eventListeners = this.eventListeners || {};
|
||
this.eventListeners[event] = this.eventListeners[event] || [];
|
||
push.call(this.eventListeners[event], listener);
|
||
},
|
||
|
||
removeEventListener: function removeEventListener(event, listener) {
|
||
var listeners = this.eventListeners && this.eventListeners[event] || [];
|
||
|
||
for (var i = 0, l = listeners.length; i < l; ++i) {
|
||
if (listeners[i] == listener) {
|
||
return listeners.splice(i, 1);
|
||
}
|
||
}
|
||
},
|
||
|
||
dispatchEvent: function dispatchEvent(event) {
|
||
var type = event.type;
|
||
var listeners = this.eventListeners && this.eventListeners[type] || [];
|
||
|
||
for (var i = 0; i < listeners.length; i++) {
|
||
if (typeof listeners[i] == "function") {
|
||
listeners[i].call(this, event);
|
||
} else {
|
||
listeners[i].handleEvent(event);
|
||
}
|
||
}
|
||
|
||
return !!event.defaultPrevented;
|
||
}
|
||
};
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require) {
|
||
var sinon = require("./core");
|
||
makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require);
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}());
|
||
|
||
},{"./core":73}],75:[function(require,module,exports){
|
||
/**
|
||
* @depend fake_xdomain_request.js
|
||
* @depend fake_xml_http_request.js
|
||
* @depend ../format.js
|
||
* @depend ../log_error.js
|
||
*/
|
||
/**
|
||
* The Sinon "server" mimics a web server that receives requests from
|
||
* sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
|
||
* both synchronously and asynchronously. To respond synchronuously, canned
|
||
* answers have to be provided upfront.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
if (typeof sinon == "undefined") {
|
||
var sinon = {};
|
||
}
|
||
|
||
(function () {
|
||
var push = [].push;
|
||
function F() {}
|
||
|
||
function create(proto) {
|
||
F.prototype = proto;
|
||
return new F();
|
||
}
|
||
|
||
function responseArray(handler) {
|
||
var response = handler;
|
||
|
||
if (Object.prototype.toString.call(handler) != "[object Array]") {
|
||
response = [200, {}, handler];
|
||
}
|
||
|
||
if (typeof response[2] != "string") {
|
||
throw new TypeError("Fake server response body should be string, but was " +
|
||
typeof response[2]);
|
||
}
|
||
|
||
return response;
|
||
}
|
||
|
||
var wloc = typeof window !== "undefined" ? window.location : {};
|
||
var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
|
||
|
||
function matchOne(response, reqMethod, reqUrl) {
|
||
var rmeth = response.method;
|
||
var matchMethod = !rmeth || rmeth.toLowerCase() == reqMethod.toLowerCase();
|
||
var url = response.url;
|
||
var matchUrl = !url || url == reqUrl || (typeof url.test == "function" && url.test(reqUrl));
|
||
|
||
return matchMethod && matchUrl;
|
||
}
|
||
|
||
function match(response, request) {
|
||
var requestUrl = request.url;
|
||
|
||
if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
|
||
requestUrl = requestUrl.replace(rCurrLoc, "");
|
||
}
|
||
|
||
if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
|
||
if (typeof response.response == "function") {
|
||
var ru = response.url;
|
||
var args = [request].concat(ru && typeof ru.exec == "function" ? ru.exec(requestUrl).slice(1) : []);
|
||
return response.response.apply(response, args);
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
function makeApi(sinon) {
|
||
sinon.fakeServer = {
|
||
create: function () {
|
||
var server = create(this);
|
||
if (!sinon.xhr.supportsCORS) {
|
||
this.xhr = sinon.useFakeXDomainRequest();
|
||
} else {
|
||
this.xhr = sinon.useFakeXMLHttpRequest();
|
||
}
|
||
server.requests = [];
|
||
|
||
this.xhr.onCreate = function (xhrObj) {
|
||
server.addRequest(xhrObj);
|
||
};
|
||
|
||
return server;
|
||
},
|
||
|
||
addRequest: function addRequest(xhrObj) {
|
||
var server = this;
|
||
push.call(this.requests, xhrObj);
|
||
|
||
xhrObj.onSend = function () {
|
||
server.handleRequest(this);
|
||
|
||
if (server.respondImmediately) {
|
||
server.respond();
|
||
} else if (server.autoRespond && !server.responding) {
|
||
setTimeout(function () {
|
||
server.responding = false;
|
||
server.respond();
|
||
}, server.autoRespondAfter || 10);
|
||
|
||
server.responding = true;
|
||
}
|
||
};
|
||
},
|
||
|
||
getHTTPMethod: function getHTTPMethod(request) {
|
||
if (this.fakeHTTPMethods && /post/i.test(request.method)) {
|
||
var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
|
||
return !!matches ? matches[1] : request.method;
|
||
}
|
||
|
||
return request.method;
|
||
},
|
||
|
||
handleRequest: function handleRequest(xhr) {
|
||
if (xhr.async) {
|
||
if (!this.queue) {
|
||
this.queue = [];
|
||
}
|
||
|
||
push.call(this.queue, xhr);
|
||
} else {
|
||
this.processRequest(xhr);
|
||
}
|
||
},
|
||
|
||
log: function log(response, request) {
|
||
var str;
|
||
|
||
str = "Request:\n" + sinon.format(request) + "\n\n";
|
||
str += "Response:\n" + sinon.format(response) + "\n\n";
|
||
|
||
sinon.log(str);
|
||
},
|
||
|
||
respondWith: function respondWith(method, url, body) {
|
||
if (arguments.length == 1 && typeof method != "function") {
|
||
this.response = responseArray(method);
|
||
return;
|
||
}
|
||
|
||
if (!this.responses) {
|
||
this.responses = [];
|
||
}
|
||
|
||
if (arguments.length == 1) {
|
||
body = method;
|
||
url = method = null;
|
||
}
|
||
|
||
if (arguments.length == 2) {
|
||
body = url;
|
||
url = method;
|
||
method = null;
|
||
}
|
||
|
||
push.call(this.responses, {
|
||
method: method,
|
||
url: url,
|
||
response: typeof body == "function" ? body : responseArray(body)
|
||
});
|
||
},
|
||
|
||
respond: function respond() {
|
||
if (arguments.length > 0) {
|
||
this.respondWith.apply(this, arguments);
|
||
}
|
||
|
||
var queue = this.queue || [];
|
||
var requests = queue.splice(0, queue.length);
|
||
var request;
|
||
|
||
while (request = requests.shift()) {
|
||
this.processRequest(request);
|
||
}
|
||
},
|
||
|
||
processRequest: function processRequest(request) {
|
||
try {
|
||
if (request.aborted) {
|
||
return;
|
||
}
|
||
|
||
var response = this.response || [404, {}, ""];
|
||
|
||
if (this.responses) {
|
||
for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
|
||
if (match.call(this, this.responses[i], request)) {
|
||
response = this.responses[i].response;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (request.readyState != 4) {
|
||
this.log(response, request);
|
||
|
||
request.respond(response[0], response[1], response[2]);
|
||
}
|
||
} catch (e) {
|
||
sinon.logError("Fake server request processing", e);
|
||
}
|
||
},
|
||
|
||
restore: function restore() {
|
||
return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
|
||
}
|
||
};
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./core");
|
||
require("./fake_xdomain_request");
|
||
require("./fake_xml_http_request");
|
||
require("../format");
|
||
makeApi(sinon);
|
||
module.exports = sinon;
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}());
|
||
|
||
},{"../format":62,"./core":73,"./fake_xdomain_request":78,"./fake_xml_http_request":79}],76:[function(require,module,exports){
|
||
/**
|
||
* @depend fake_server.js
|
||
* @depend fake_timers.js
|
||
*/
|
||
/**
|
||
* Add-on for sinon.fakeServer that automatically handles a fake timer along with
|
||
* the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
|
||
* 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
|
||
* it polls the object for completion with setInterval. Dispite the direct
|
||
* motivation, there is nothing jQuery-specific in this file, so it can be used
|
||
* in any environment where the ajax implementation depends on setInterval or
|
||
* setTimeout.
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function () {
|
||
function makeApi(sinon) {
|
||
function Server() {}
|
||
Server.prototype = sinon.fakeServer;
|
||
|
||
sinon.fakeServerWithClock = new Server();
|
||
|
||
sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
|
||
if (xhr.async) {
|
||
if (typeof setTimeout.clock == "object") {
|
||
this.clock = setTimeout.clock;
|
||
} else {
|
||
this.clock = sinon.useFakeTimers();
|
||
this.resetClock = true;
|
||
}
|
||
|
||
if (!this.longestTimeout) {
|
||
var clockSetTimeout = this.clock.setTimeout;
|
||
var clockSetInterval = this.clock.setInterval;
|
||
var server = this;
|
||
|
||
this.clock.setTimeout = function (fn, timeout) {
|
||
server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
|
||
|
||
return clockSetTimeout.apply(this, arguments);
|
||
};
|
||
|
||
this.clock.setInterval = function (fn, timeout) {
|
||
server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
|
||
|
||
return clockSetInterval.apply(this, arguments);
|
||
};
|
||
}
|
||
}
|
||
|
||
return sinon.fakeServer.addRequest.call(this, xhr);
|
||
};
|
||
|
||
sinon.fakeServerWithClock.respond = function respond() {
|
||
var returnVal = sinon.fakeServer.respond.apply(this, arguments);
|
||
|
||
if (this.clock) {
|
||
this.clock.tick(this.longestTimeout || 0);
|
||
this.longestTimeout = 0;
|
||
|
||
if (this.resetClock) {
|
||
this.clock.restore();
|
||
this.resetClock = false;
|
||
}
|
||
}
|
||
|
||
return returnVal;
|
||
};
|
||
|
||
sinon.fakeServerWithClock.restore = function restore() {
|
||
if (this.clock) {
|
||
this.clock.restore();
|
||
}
|
||
|
||
return sinon.fakeServer.restore.apply(this, arguments);
|
||
};
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require) {
|
||
var sinon = require("./core");
|
||
require("./fake_server");
|
||
require("./fake_timers");
|
||
makeApi(sinon);
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require);
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}());
|
||
|
||
},{"./core":73,"./fake_server":75,"./fake_timers":77}],77:[function(require,module,exports){
|
||
(function (global){
|
||
/*global lolex */
|
||
|
||
/**
|
||
* Fake timer API
|
||
* setTimeout
|
||
* setInterval
|
||
* clearTimeout
|
||
* clearInterval
|
||
* tick
|
||
* reset
|
||
* Date
|
||
*
|
||
* Inspired by jsUnitMockTimeOut from JsUnit
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
if (typeof sinon == "undefined") {
|
||
var sinon = {};
|
||
}
|
||
|
||
(function (global) {
|
||
function makeApi(sinon, lol) {
|
||
var llx = typeof lolex !== "undefined" ? lolex : lol;
|
||
|
||
sinon.useFakeTimers = function () {
|
||
var now, methods = Array.prototype.slice.call(arguments);
|
||
|
||
if (typeof methods[0] === "string") {
|
||
now = 0;
|
||
} else {
|
||
now = methods.shift();
|
||
}
|
||
|
||
var clock = llx.install(now || 0, methods);
|
||
clock.restore = clock.uninstall;
|
||
return clock;
|
||
};
|
||
|
||
sinon.clock = {
|
||
create: function (now) {
|
||
return llx.createClock(now);
|
||
}
|
||
};
|
||
|
||
sinon.timers = {
|
||
setTimeout: setTimeout,
|
||
clearTimeout: clearTimeout,
|
||
setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
|
||
clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate : undefined),
|
||
setInterval: setInterval,
|
||
clearInterval: clearInterval,
|
||
Date: Date
|
||
};
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, epxorts, module, lolex) {
|
||
var sinon = require("./core");
|
||
makeApi(sinon, lolex);
|
||
module.exports = sinon;
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module, require("lolex"));
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
}(typeof global != "undefined" && typeof global !== "function" ? global : this));
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"./core":73,"lolex":81}],78:[function(require,module,exports){
|
||
(function (global){
|
||
/**
|
||
* @depend core.js
|
||
* @depend ../extend.js
|
||
* @depend event.js
|
||
* @depend ../log_error.js
|
||
*/
|
||
/**
|
||
* Fake XDomainRequest object
|
||
*/
|
||
"use strict";
|
||
|
||
if (typeof sinon == "undefined") {
|
||
this.sinon = {};
|
||
}
|
||
|
||
// wrapper for global
|
||
(function (global) {
|
||
var xdr = { XDomainRequest: global.XDomainRequest };
|
||
xdr.GlobalXDomainRequest = global.XDomainRequest;
|
||
xdr.supportsXDR = typeof xdr.GlobalXDomainRequest != "undefined";
|
||
xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest : false;
|
||
|
||
function makeApi(sinon) {
|
||
sinon.xdr = xdr;
|
||
|
||
function FakeXDomainRequest() {
|
||
this.readyState = FakeXDomainRequest.UNSENT;
|
||
this.requestBody = null;
|
||
this.requestHeaders = {};
|
||
this.status = 0;
|
||
this.timeout = null;
|
||
|
||
if (typeof FakeXDomainRequest.onCreate == "function") {
|
||
FakeXDomainRequest.onCreate(this);
|
||
}
|
||
}
|
||
|
||
function verifyState(xdr) {
|
||
if (xdr.readyState !== FakeXDomainRequest.OPENED) {
|
||
throw new Error("INVALID_STATE_ERR");
|
||
}
|
||
|
||
if (xdr.sendFlag) {
|
||
throw new Error("INVALID_STATE_ERR");
|
||
}
|
||
}
|
||
|
||
function verifyRequestSent(xdr) {
|
||
if (xdr.readyState == FakeXDomainRequest.UNSENT) {
|
||
throw new Error("Request not sent");
|
||
}
|
||
if (xdr.readyState == FakeXDomainRequest.DONE) {
|
||
throw new Error("Request done");
|
||
}
|
||
}
|
||
|
||
function verifyResponseBodyType(body) {
|
||
if (typeof body != "string") {
|
||
var error = new Error("Attempted to respond to fake XDomainRequest with " +
|
||
body + ", which is not a string.");
|
||
error.name = "InvalidBodyException";
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
sinon.extend(FakeXDomainRequest.prototype, sinon.EventTarget, {
|
||
open: function open(method, url) {
|
||
this.method = method;
|
||
this.url = url;
|
||
|
||
this.responseText = null;
|
||
this.sendFlag = false;
|
||
|
||
this.readyStateChange(FakeXDomainRequest.OPENED);
|
||
},
|
||
|
||
readyStateChange: function readyStateChange(state) {
|
||
this.readyState = state;
|
||
var eventName = "";
|
||
switch (this.readyState) {
|
||
case FakeXDomainRequest.UNSENT:
|
||
break;
|
||
case FakeXDomainRequest.OPENED:
|
||
break;
|
||
case FakeXDomainRequest.LOADING:
|
||
if (this.sendFlag) {
|
||
//raise the progress event
|
||
eventName = "onprogress";
|
||
}
|
||
break;
|
||
case FakeXDomainRequest.DONE:
|
||
if (this.isTimeout) {
|
||
eventName = "ontimeout"
|
||
} else if (this.errorFlag || (this.status < 200 || this.status > 299)) {
|
||
eventName = "onerror";
|
||
} else {
|
||
eventName = "onload"
|
||
}
|
||
break;
|
||
}
|
||
|
||
// raising event (if defined)
|
||
if (eventName) {
|
||
if (typeof this[eventName] == "function") {
|
||
try {
|
||
this[eventName]();
|
||
} catch (e) {
|
||
sinon.logError("Fake XHR " + eventName + " handler", e);
|
||
}
|
||
}
|
||
}
|
||
},
|
||
|
||
send: function send(data) {
|
||
verifyState(this);
|
||
|
||
if (!/^(get|head)$/i.test(this.method)) {
|
||
this.requestBody = data;
|
||
}
|
||
this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
|
||
|
||
this.errorFlag = false;
|
||
this.sendFlag = true;
|
||
this.readyStateChange(FakeXDomainRequest.OPENED);
|
||
|
||
if (typeof this.onSend == "function") {
|
||
this.onSend(this);
|
||
}
|
||
},
|
||
|
||
abort: function abort() {
|
||
this.aborted = true;
|
||
this.responseText = null;
|
||
this.errorFlag = true;
|
||
|
||
if (this.readyState > sinon.FakeXDomainRequest.UNSENT && this.sendFlag) {
|
||
this.readyStateChange(sinon.FakeXDomainRequest.DONE);
|
||
this.sendFlag = false;
|
||
}
|
||
},
|
||
|
||
setResponseBody: function setResponseBody(body) {
|
||
verifyRequestSent(this);
|
||
verifyResponseBodyType(body);
|
||
|
||
var chunkSize = this.chunkSize || 10;
|
||
var index = 0;
|
||
this.responseText = "";
|
||
|
||
do {
|
||
this.readyStateChange(FakeXDomainRequest.LOADING);
|
||
this.responseText += body.substring(index, index + chunkSize);
|
||
index += chunkSize;
|
||
} while (index < body.length);
|
||
|
||
this.readyStateChange(FakeXDomainRequest.DONE);
|
||
},
|
||
|
||
respond: function respond(status, contentType, body) {
|
||
// content-type ignored, since XDomainRequest does not carry this
|
||
// we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease
|
||
// test integration across browsers
|
||
this.status = typeof status == "number" ? status : 200;
|
||
this.setResponseBody(body || "");
|
||
},
|
||
|
||
simulatetimeout: function simulatetimeout() {
|
||
this.status = 0;
|
||
this.isTimeout = true;
|
||
// Access to this should actually throw an error
|
||
this.responseText = undefined;
|
||
this.readyStateChange(FakeXDomainRequest.DONE);
|
||
}
|
||
});
|
||
|
||
sinon.extend(FakeXDomainRequest, {
|
||
UNSENT: 0,
|
||
OPENED: 1,
|
||
LOADING: 3,
|
||
DONE: 4
|
||
});
|
||
|
||
sinon.useFakeXDomainRequest = function useFakeXDomainRequest() {
|
||
sinon.FakeXDomainRequest.restore = function restore(keepOnCreate) {
|
||
if (xdr.supportsXDR) {
|
||
global.XDomainRequest = xdr.GlobalXDomainRequest;
|
||
}
|
||
|
||
delete sinon.FakeXDomainRequest.restore;
|
||
|
||
if (keepOnCreate !== true) {
|
||
delete sinon.FakeXDomainRequest.onCreate;
|
||
}
|
||
};
|
||
if (xdr.supportsXDR) {
|
||
global.XDomainRequest = sinon.FakeXDomainRequest;
|
||
}
|
||
return sinon.FakeXDomainRequest;
|
||
};
|
||
|
||
sinon.FakeXDomainRequest = FakeXDomainRequest;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./core");
|
||
require("../extend");
|
||
require("./event");
|
||
require("../log_error");
|
||
makeApi(sinon);
|
||
module.exports = sinon;
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
})(typeof global !== "undefined" ? global : self);
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"../extend":61,"../log_error":63,"./core":73,"./event":74}],79:[function(require,module,exports){
|
||
(function (global){
|
||
/**
|
||
* @depend core.js
|
||
* @depend ../extend.js
|
||
* @depend event.js
|
||
* @depend ../log_error.js
|
||
*/
|
||
/**
|
||
* Fake XMLHttpRequest object
|
||
*
|
||
* @author Christian Johansen (christian@cjohansen.no)
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2013 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
(function (global) {
|
||
|
||
var supportsProgress = typeof ProgressEvent !== "undefined";
|
||
var supportsCustomEvent = typeof CustomEvent !== "undefined";
|
||
var supportsFormData = typeof FormData !== "undefined";
|
||
var sinonXhr = { XMLHttpRequest: global.XMLHttpRequest };
|
||
sinonXhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
|
||
sinonXhr.GlobalActiveXObject = global.ActiveXObject;
|
||
sinonXhr.supportsActiveX = typeof sinonXhr.GlobalActiveXObject != "undefined";
|
||
sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest != "undefined";
|
||
sinonXhr.workingXHR = sinonXhr.supportsXHR ? sinonXhr.GlobalXMLHttpRequest : sinonXhr.supportsActiveX
|
||
? function () {
|
||
return new sinonXhr.GlobalActiveXObject("MSXML2.XMLHTTP.3.0")
|
||
} : false;
|
||
sinonXhr.supportsCORS = sinonXhr.supportsXHR && "withCredentials" in (new sinonXhr.GlobalXMLHttpRequest());
|
||
|
||
/*jsl:ignore*/
|
||
var unsafeHeaders = {
|
||
"Accept-Charset": true,
|
||
"Accept-Encoding": true,
|
||
Connection: true,
|
||
"Content-Length": true,
|
||
Cookie: true,
|
||
Cookie2: true,
|
||
"Content-Transfer-Encoding": true,
|
||
Date: true,
|
||
Expect: true,
|
||
Host: true,
|
||
"Keep-Alive": true,
|
||
Referer: true,
|
||
TE: true,
|
||
Trailer: true,
|
||
"Transfer-Encoding": true,
|
||
Upgrade: true,
|
||
"User-Agent": true,
|
||
Via: true
|
||
};
|
||
/*jsl:end*/
|
||
|
||
// Note that for FakeXMLHttpRequest to work pre ES5
|
||
// we lose some of the alignment with the spec.
|
||
// To ensure as close a match as possible,
|
||
// set responseType before calling open, send or respond;
|
||
function FakeXMLHttpRequest() {
|
||
this.readyState = FakeXMLHttpRequest.UNSENT;
|
||
this.requestHeaders = {};
|
||
this.requestBody = null;
|
||
this.status = 0;
|
||
this.statusText = "";
|
||
this.upload = new UploadProgress();
|
||
this.responseType = "";
|
||
this.response = "";
|
||
if (sinonXhr.supportsCORS) {
|
||
this.withCredentials = false;
|
||
}
|
||
|
||
var xhr = this;
|
||
var events = ["loadstart", "load", "abort", "loadend"];
|
||
|
||
function addEventListener(eventName) {
|
||
xhr.addEventListener(eventName, function (event) {
|
||
var listener = xhr["on" + eventName];
|
||
|
||
if (listener && typeof listener == "function") {
|
||
listener.call(this, event);
|
||
}
|
||
});
|
||
}
|
||
|
||
for (var i = events.length - 1; i >= 0; i--) {
|
||
addEventListener(events[i]);
|
||
}
|
||
|
||
if (typeof FakeXMLHttpRequest.onCreate == "function") {
|
||
FakeXMLHttpRequest.onCreate(this);
|
||
}
|
||
}
|
||
|
||
// An upload object is created for each
|
||
// FakeXMLHttpRequest and allows upload
|
||
// events to be simulated using uploadProgress
|
||
// and uploadError.
|
||
function UploadProgress() {
|
||
this.eventListeners = {
|
||
progress: [],
|
||
load: [],
|
||
abort: [],
|
||
error: []
|
||
}
|
||
}
|
||
|
||
UploadProgress.prototype.addEventListener = function addEventListener(event, listener) {
|
||
this.eventListeners[event].push(listener);
|
||
};
|
||
|
||
UploadProgress.prototype.removeEventListener = function removeEventListener(event, listener) {
|
||
var listeners = this.eventListeners[event] || [];
|
||
|
||
for (var i = 0, l = listeners.length; i < l; ++i) {
|
||
if (listeners[i] == listener) {
|
||
return listeners.splice(i, 1);
|
||
}
|
||
}
|
||
};
|
||
|
||
UploadProgress.prototype.dispatchEvent = function dispatchEvent(event) {
|
||
var listeners = this.eventListeners[event.type] || [];
|
||
|
||
for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
|
||
listener(event);
|
||
}
|
||
};
|
||
|
||
function verifyState(xhr) {
|
||
if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
|
||
throw new Error("INVALID_STATE_ERR");
|
||
}
|
||
|
||
if (xhr.sendFlag) {
|
||
throw new Error("INVALID_STATE_ERR");
|
||
}
|
||
}
|
||
|
||
function getHeader(headers, header) {
|
||
header = header.toLowerCase();
|
||
|
||
for (var h in headers) {
|
||
if (h.toLowerCase() == header) {
|
||
return h;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
// filtering to enable a white-list version of Sinon FakeXhr,
|
||
// where whitelisted requests are passed through to real XHR
|
||
function each(collection, callback) {
|
||
if (!collection) {
|
||
return;
|
||
}
|
||
|
||
for (var i = 0, l = collection.length; i < l; i += 1) {
|
||
callback(collection[i]);
|
||
}
|
||
}
|
||
function some(collection, callback) {
|
||
for (var index = 0; index < collection.length; index++) {
|
||
if (callback(collection[index]) === true) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
// largest arity in XHR is 5 - XHR#open
|
||
var apply = function (obj, method, args) {
|
||
switch (args.length) {
|
||
case 0: return obj[method]();
|
||
case 1: return obj[method](args[0]);
|
||
case 2: return obj[method](args[0], args[1]);
|
||
case 3: return obj[method](args[0], args[1], args[2]);
|
||
case 4: return obj[method](args[0], args[1], args[2], args[3]);
|
||
case 5: return obj[method](args[0], args[1], args[2], args[3], args[4]);
|
||
}
|
||
};
|
||
|
||
FakeXMLHttpRequest.filters = [];
|
||
FakeXMLHttpRequest.addFilter = function addFilter(fn) {
|
||
this.filters.push(fn)
|
||
};
|
||
var IE6Re = /MSIE 6/;
|
||
FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) {
|
||
var xhr = new sinonXhr.workingXHR();
|
||
each([
|
||
"open",
|
||
"setRequestHeader",
|
||
"send",
|
||
"abort",
|
||
"getResponseHeader",
|
||
"getAllResponseHeaders",
|
||
"addEventListener",
|
||
"overrideMimeType",
|
||
"removeEventListener"
|
||
], function (method) {
|
||
fakeXhr[method] = function () {
|
||
return apply(xhr, method, arguments);
|
||
};
|
||
});
|
||
|
||
var copyAttrs = function (args) {
|
||
each(args, function (attr) {
|
||
try {
|
||
fakeXhr[attr] = xhr[attr]
|
||
} catch (e) {
|
||
if (!IE6Re.test(navigator.userAgent)) {
|
||
throw e;
|
||
}
|
||
}
|
||
});
|
||
};
|
||
|
||
var stateChange = function stateChange() {
|
||
fakeXhr.readyState = xhr.readyState;
|
||
if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
|
||
copyAttrs(["status", "statusText"]);
|
||
}
|
||
if (xhr.readyState >= FakeXMLHttpRequest.LOADING) {
|
||
copyAttrs(["responseText", "response"]);
|
||
}
|
||
if (xhr.readyState === FakeXMLHttpRequest.DONE) {
|
||
copyAttrs(["responseXML"]);
|
||
}
|
||
if (fakeXhr.onreadystatechange) {
|
||
fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
|
||
}
|
||
};
|
||
|
||
if (xhr.addEventListener) {
|
||
for (var event in fakeXhr.eventListeners) {
|
||
if (fakeXhr.eventListeners.hasOwnProperty(event)) {
|
||
each(fakeXhr.eventListeners[event], function (handler) {
|
||
xhr.addEventListener(event, handler);
|
||
});
|
||
}
|
||
}
|
||
xhr.addEventListener("readystatechange", stateChange);
|
||
} else {
|
||
xhr.onreadystatechange = stateChange;
|
||
}
|
||
apply(xhr, "open", xhrArgs);
|
||
};
|
||
FakeXMLHttpRequest.useFilters = false;
|
||
|
||
function verifyRequestOpened(xhr) {
|
||
if (xhr.readyState != FakeXMLHttpRequest.OPENED) {
|
||
throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
|
||
}
|
||
}
|
||
|
||
function verifyRequestSent(xhr) {
|
||
if (xhr.readyState == FakeXMLHttpRequest.DONE) {
|
||
throw new Error("Request done");
|
||
}
|
||
}
|
||
|
||
function verifyHeadersReceived(xhr) {
|
||
if (xhr.async && xhr.readyState != FakeXMLHttpRequest.HEADERS_RECEIVED) {
|
||
throw new Error("No headers received");
|
||
}
|
||
}
|
||
|
||
function verifyResponseBodyType(body) {
|
||
if (typeof body != "string") {
|
||
var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
|
||
body + ", which is not a string.");
|
||
error.name = "InvalidBodyException";
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
FakeXMLHttpRequest.parseXML = function parseXML(text) {
|
||
var xmlDoc;
|
||
|
||
if (typeof DOMParser != "undefined") {
|
||
var parser = new DOMParser();
|
||
xmlDoc = parser.parseFromString(text, "text/xml");
|
||
} else {
|
||
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
|
||
xmlDoc.async = "false";
|
||
xmlDoc.loadXML(text);
|
||
}
|
||
|
||
return xmlDoc;
|
||
};
|
||
|
||
FakeXMLHttpRequest.statusCodes = {
|
||
100: "Continue",
|
||
101: "Switching Protocols",
|
||
200: "OK",
|
||
201: "Created",
|
||
202: "Accepted",
|
||
203: "Non-Authoritative Information",
|
||
204: "No Content",
|
||
205: "Reset Content",
|
||
206: "Partial Content",
|
||
207: "Multi-Status",
|
||
300: "Multiple Choice",
|
||
301: "Moved Permanently",
|
||
302: "Found",
|
||
303: "See Other",
|
||
304: "Not Modified",
|
||
305: "Use Proxy",
|
||
307: "Temporary Redirect",
|
||
400: "Bad Request",
|
||
401: "Unauthorized",
|
||
402: "Payment Required",
|
||
403: "Forbidden",
|
||
404: "Not Found",
|
||
405: "Method Not Allowed",
|
||
406: "Not Acceptable",
|
||
407: "Proxy Authentication Required",
|
||
408: "Request Timeout",
|
||
409: "Conflict",
|
||
410: "Gone",
|
||
411: "Length Required",
|
||
412: "Precondition Failed",
|
||
413: "Request Entity Too Large",
|
||
414: "Request-URI Too Long",
|
||
415: "Unsupported Media Type",
|
||
416: "Requested Range Not Satisfiable",
|
||
417: "Expectation Failed",
|
||
422: "Unprocessable Entity",
|
||
500: "Internal Server Error",
|
||
501: "Not Implemented",
|
||
502: "Bad Gateway",
|
||
503: "Service Unavailable",
|
||
504: "Gateway Timeout",
|
||
505: "HTTP Version Not Supported"
|
||
};
|
||
|
||
function makeApi(sinon) {
|
||
sinon.xhr = sinonXhr;
|
||
|
||
sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
|
||
async: true,
|
||
|
||
open: function open(method, url, async, username, password) {
|
||
this.method = method;
|
||
this.url = url;
|
||
this.async = typeof async == "boolean" ? async : true;
|
||
this.username = username;
|
||
this.password = password;
|
||
this.responseText = null;
|
||
this.response = this.responseType === "json" ? null : "";
|
||
this.responseXML = null;
|
||
this.requestHeaders = {};
|
||
this.sendFlag = false;
|
||
|
||
if (FakeXMLHttpRequest.useFilters === true) {
|
||
var xhrArgs = arguments;
|
||
var defake = some(FakeXMLHttpRequest.filters, function (filter) {
|
||
return filter.apply(this, xhrArgs)
|
||
});
|
||
if (defake) {
|
||
return FakeXMLHttpRequest.defake(this, arguments);
|
||
}
|
||
}
|
||
this.readyStateChange(FakeXMLHttpRequest.OPENED);
|
||
},
|
||
|
||
readyStateChange: function readyStateChange(state) {
|
||
this.readyState = state;
|
||
|
||
if (typeof this.onreadystatechange == "function") {
|
||
try {
|
||
this.onreadystatechange();
|
||
} catch (e) {
|
||
sinon.logError("Fake XHR onreadystatechange handler", e);
|
||
}
|
||
}
|
||
|
||
switch (this.readyState) {
|
||
case FakeXMLHttpRequest.DONE:
|
||
if (supportsProgress) {
|
||
this.upload.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
|
||
this.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
|
||
}
|
||
this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
|
||
this.dispatchEvent(new sinon.Event("load", false, false, this));
|
||
this.dispatchEvent(new sinon.Event("loadend", false, false, this));
|
||
break;
|
||
}
|
||
|
||
this.dispatchEvent(new sinon.Event("readystatechange"));
|
||
},
|
||
|
||
setRequestHeader: function setRequestHeader(header, value) {
|
||
verifyState(this);
|
||
|
||
if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
|
||
throw new Error("Refused to set unsafe header \"" + header + "\"");
|
||
}
|
||
|
||
if (this.requestHeaders[header]) {
|
||
this.requestHeaders[header] += "," + value;
|
||
} else {
|
||
this.requestHeaders[header] = value;
|
||
}
|
||
},
|
||
|
||
// Helps testing
|
||
setResponseHeaders: function setResponseHeaders(headers) {
|
||
verifyRequestOpened(this);
|
||
this.responseHeaders = {};
|
||
|
||
for (var header in headers) {
|
||
if (headers.hasOwnProperty(header)) {
|
||
this.responseHeaders[header] = headers[header];
|
||
}
|
||
}
|
||
|
||
if (this.async) {
|
||
this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
|
||
} else {
|
||
this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
|
||
}
|
||
},
|
||
|
||
// Currently treats ALL data as a DOMString (i.e. no Document)
|
||
send: function send(data) {
|
||
verifyState(this);
|
||
|
||
if (!/^(get|head)$/i.test(this.method)) {
|
||
var contentType = getHeader(this.requestHeaders, "Content-Type");
|
||
if (this.requestHeaders[contentType]) {
|
||
var value = this.requestHeaders[contentType].split(";");
|
||
this.requestHeaders[contentType] = value[0] + ";charset=utf-8";
|
||
} else if (supportsFormData && !(data instanceof FormData)) {
|
||
this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
|
||
}
|
||
|
||
this.requestBody = data;
|
||
}
|
||
|
||
this.errorFlag = false;
|
||
this.sendFlag = this.async;
|
||
this.response = this.responseType === "json" ? null : "";
|
||
this.readyStateChange(FakeXMLHttpRequest.OPENED);
|
||
|
||
if (typeof this.onSend == "function") {
|
||
this.onSend(this);
|
||
}
|
||
|
||
this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
|
||
},
|
||
|
||
abort: function abort() {
|
||
this.aborted = true;
|
||
this.responseText = null;
|
||
this.response = this.responseType === "json" ? null : "";
|
||
this.errorFlag = true;
|
||
this.requestHeaders = {};
|
||
this.responseHeaders = {};
|
||
|
||
if (this.readyState > FakeXMLHttpRequest.UNSENT && this.sendFlag) {
|
||
this.readyStateChange(FakeXMLHttpRequest.DONE);
|
||
this.sendFlag = false;
|
||
}
|
||
|
||
this.readyState = FakeXMLHttpRequest.UNSENT;
|
||
|
||
this.dispatchEvent(new sinon.Event("abort", false, false, this));
|
||
|
||
this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
|
||
|
||
if (typeof this.onerror === "function") {
|
||
this.onerror();
|
||
}
|
||
},
|
||
|
||
getResponseHeader: function getResponseHeader(header) {
|
||
if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
|
||
return null;
|
||
}
|
||
|
||
if (/^Set-Cookie2?$/i.test(header)) {
|
||
return null;
|
||
}
|
||
|
||
header = getHeader(this.responseHeaders, header);
|
||
|
||
return this.responseHeaders[header] || null;
|
||
},
|
||
|
||
getAllResponseHeaders: function getAllResponseHeaders() {
|
||
if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
|
||
return "";
|
||
}
|
||
|
||
var headers = "";
|
||
|
||
for (var header in this.responseHeaders) {
|
||
if (this.responseHeaders.hasOwnProperty(header) &&
|
||
!/^Set-Cookie2?$/i.test(header)) {
|
||
headers += header + ": " + this.responseHeaders[header] + "\r\n";
|
||
}
|
||
}
|
||
|
||
return headers;
|
||
},
|
||
|
||
setResponseBody: function setResponseBody(body) {
|
||
verifyRequestSent(this);
|
||
verifyHeadersReceived(this);
|
||
verifyResponseBodyType(body);
|
||
|
||
var chunkSize = this.chunkSize || 10;
|
||
var index = 0;
|
||
this.responseText = "";
|
||
|
||
do {
|
||
if (this.async) {
|
||
this.readyStateChange(FakeXMLHttpRequest.LOADING);
|
||
}
|
||
|
||
this.responseText += body.substring(index, index + chunkSize);
|
||
index += chunkSize;
|
||
} while (index < body.length);
|
||
|
||
var type = this.getResponseHeader("Content-Type");
|
||
|
||
if (this.responseText &&
|
||
(!type || /(text\/xml)|(application\/xml)|(\+xml)/.test(type))) {
|
||
try {
|
||
this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
|
||
} catch (e) {
|
||
// Unable to parse XML - no biggie
|
||
}
|
||
}
|
||
|
||
this.response = this.responseType === "json" ? JSON.parse(this.responseText) : this.responseText;
|
||
this.readyStateChange(FakeXMLHttpRequest.DONE);
|
||
},
|
||
|
||
respond: function respond(status, headers, body) {
|
||
this.status = typeof status == "number" ? status : 200;
|
||
this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
|
||
this.setResponseHeaders(headers || {});
|
||
this.setResponseBody(body || "");
|
||
},
|
||
|
||
uploadProgress: function uploadProgress(progressEventRaw) {
|
||
if (supportsProgress) {
|
||
this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
|
||
}
|
||
},
|
||
|
||
downloadProgress: function downloadProgress(progressEventRaw) {
|
||
if (supportsProgress) {
|
||
this.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
|
||
}
|
||
},
|
||
|
||
uploadError: function uploadError(error) {
|
||
if (supportsCustomEvent) {
|
||
this.upload.dispatchEvent(new sinon.CustomEvent("error", {detail: error}));
|
||
}
|
||
}
|
||
});
|
||
|
||
sinon.extend(FakeXMLHttpRequest, {
|
||
UNSENT: 0,
|
||
OPENED: 1,
|
||
HEADERS_RECEIVED: 2,
|
||
LOADING: 3,
|
||
DONE: 4
|
||
});
|
||
|
||
sinon.useFakeXMLHttpRequest = function () {
|
||
FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
|
||
if (sinonXhr.supportsXHR) {
|
||
global.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest;
|
||
}
|
||
|
||
if (sinonXhr.supportsActiveX) {
|
||
global.ActiveXObject = sinonXhr.GlobalActiveXObject;
|
||
}
|
||
|
||
delete FakeXMLHttpRequest.restore;
|
||
|
||
if (keepOnCreate !== true) {
|
||
delete FakeXMLHttpRequest.onCreate;
|
||
}
|
||
};
|
||
if (sinonXhr.supportsXHR) {
|
||
global.XMLHttpRequest = FakeXMLHttpRequest;
|
||
}
|
||
|
||
if (sinonXhr.supportsActiveX) {
|
||
global.ActiveXObject = function ActiveXObject(objId) {
|
||
if (objId == "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
|
||
|
||
return new FakeXMLHttpRequest();
|
||
}
|
||
|
||
return new sinonXhr.GlobalActiveXObject(objId);
|
||
};
|
||
}
|
||
|
||
return FakeXMLHttpRequest;
|
||
};
|
||
|
||
sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
|
||
}
|
||
|
||
var isNode = typeof module !== "undefined" && module.exports && typeof require == "function";
|
||
var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
|
||
|
||
function loadDependencies(require, exports, module) {
|
||
var sinon = require("./core");
|
||
require("../extend");
|
||
require("./event");
|
||
require("../log_error");
|
||
makeApi(sinon);
|
||
module.exports = sinon;
|
||
}
|
||
|
||
if (isAMD) {
|
||
define(loadDependencies);
|
||
} else if (isNode) {
|
||
loadDependencies(require, module.exports, module);
|
||
} else if (typeof sinon === "undefined") {
|
||
return;
|
||
} else {
|
||
makeApi(sinon);
|
||
}
|
||
|
||
})(typeof global !== "undefined" ? global : self);
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"../extend":61,"../log_error":63,"./core":73,"./event":74}],80:[function(require,module,exports){
|
||
(function (global){
|
||
((typeof define === "function" && define.amd && function (m) {
|
||
define("formatio", ["samsam"], m);
|
||
}) || (typeof module === "object" && function (m) {
|
||
module.exports = m(require("samsam"));
|
||
}) || function (m) { this.formatio = m(this.samsam); }
|
||
)(function (samsam) {
|
||
"use strict";
|
||
|
||
var formatio = {
|
||
excludeConstructors: ["Object", /^.$/],
|
||
quoteStrings: true,
|
||
limitChildrenCount: 0
|
||
};
|
||
|
||
var hasOwn = Object.prototype.hasOwnProperty;
|
||
|
||
var specialObjects = [];
|
||
if (typeof global !== "undefined") {
|
||
specialObjects.push({ object: global, value: "[object global]" });
|
||
}
|
||
if (typeof document !== "undefined") {
|
||
specialObjects.push({
|
||
object: document,
|
||
value: "[object HTMLDocument]"
|
||
});
|
||
}
|
||
if (typeof window !== "undefined") {
|
||
specialObjects.push({ object: window, value: "[object Window]" });
|
||
}
|
||
|
||
function functionName(func) {
|
||
if (!func) { return ""; }
|
||
if (func.displayName) { return func.displayName; }
|
||
if (func.name) { return func.name; }
|
||
var matches = func.toString().match(/function\s+([^\(]+)/m);
|
||
return (matches && matches[1]) || "";
|
||
}
|
||
|
||
function constructorName(f, object) {
|
||
var name = functionName(object && object.constructor);
|
||
var excludes = f.excludeConstructors ||
|
||
formatio.excludeConstructors || [];
|
||
|
||
var i, l;
|
||
for (i = 0, l = excludes.length; i < l; ++i) {
|
||
if (typeof excludes[i] === "string" && excludes[i] === name) {
|
||
return "";
|
||
} else if (excludes[i].test && excludes[i].test(name)) {
|
||
return "";
|
||
}
|
||
}
|
||
|
||
return name;
|
||
}
|
||
|
||
function isCircular(object, objects) {
|
||
if (typeof object !== "object") { return false; }
|
||
var i, l;
|
||
for (i = 0, l = objects.length; i < l; ++i) {
|
||
if (objects[i] === object) { return true; }
|
||
}
|
||
return false;
|
||
}
|
||
|
||
function ascii(f, object, processed, indent) {
|
||
if (typeof object === "string") {
|
||
var qs = f.quoteStrings;
|
||
var quote = typeof qs !== "boolean" || qs;
|
||
return processed || quote ? '"' + object + '"' : object;
|
||
}
|
||
|
||
if (typeof object === "function" && !(object instanceof RegExp)) {
|
||
return ascii.func(object);
|
||
}
|
||
|
||
processed = processed || [];
|
||
|
||
if (isCircular(object, processed)) { return "[Circular]"; }
|
||
|
||
if (Object.prototype.toString.call(object) === "[object Array]") {
|
||
return ascii.array.call(f, object, processed);
|
||
}
|
||
|
||
if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
|
||
if (samsam.isElement(object)) { return ascii.element(object); }
|
||
|
||
if (typeof object.toString === "function" &&
|
||
object.toString !== Object.prototype.toString) {
|
||
return object.toString();
|
||
}
|
||
|
||
var i, l;
|
||
for (i = 0, l = specialObjects.length; i < l; i++) {
|
||
if (object === specialObjects[i].object) {
|
||
return specialObjects[i].value;
|
||
}
|
||
}
|
||
|
||
return ascii.object.call(f, object, processed, indent);
|
||
}
|
||
|
||
ascii.func = function (func) {
|
||
return "function " + functionName(func) + "() {}";
|
||
};
|
||
|
||
ascii.array = function (array, processed) {
|
||
processed = processed || [];
|
||
processed.push(array);
|
||
var pieces = [];
|
||
var i, l;
|
||
l = (this.limitChildrenCount > 0) ?
|
||
Math.min(this.limitChildrenCount, array.length) : array.length;
|
||
|
||
for (i = 0; i < l; ++i) {
|
||
pieces.push(ascii(this, array[i], processed));
|
||
}
|
||
|
||
if(l < array.length)
|
||
pieces.push("[... " + (array.length - l) + " more elements]");
|
||
|
||
return "[" + pieces.join(", ") + "]";
|
||
};
|
||
|
||
ascii.object = function (object, processed, indent) {
|
||
processed = processed || [];
|
||
processed.push(object);
|
||
indent = indent || 0;
|
||
var pieces = [], properties = samsam.keys(object).sort();
|
||
var length = 3;
|
||
var prop, str, obj, i, k, l;
|
||
l = (this.limitChildrenCount > 0) ?
|
||
Math.min(this.limitChildrenCount, properties.length) : properties.length;
|
||
|
||
for (i = 0; i < l; ++i) {
|
||
prop = properties[i];
|
||
obj = object[prop];
|
||
|
||
if (isCircular(obj, processed)) {
|
||
str = "[Circular]";
|
||
} else {
|
||
str = ascii(this, obj, processed, indent + 2);
|
||
}
|
||
|
||
str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
|
||
length += str.length;
|
||
pieces.push(str);
|
||
}
|
||
|
||
var cons = constructorName(this, object);
|
||
var prefix = cons ? "[" + cons + "] " : "";
|
||
var is = "";
|
||
for (i = 0, k = indent; i < k; ++i) { is += " "; }
|
||
|
||
if(l < properties.length)
|
||
pieces.push("[... " + (properties.length - l) + " more elements]");
|
||
|
||
if (length + indent > 80) {
|
||
return prefix + "{\n " + is + pieces.join(",\n " + is) + "\n" +
|
||
is + "}";
|
||
}
|
||
return prefix + "{ " + pieces.join(", ") + " }";
|
||
};
|
||
|
||
ascii.element = function (element) {
|
||
var tagName = element.tagName.toLowerCase();
|
||
var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
|
||
|
||
for (i = 0, l = attrs.length; i < l; ++i) {
|
||
attr = attrs.item(i);
|
||
attrName = attr.nodeName.toLowerCase().replace("html:", "");
|
||
val = attr.nodeValue;
|
||
if (attrName !== "contenteditable" || val !== "inherit") {
|
||
if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
|
||
}
|
||
}
|
||
|
||
var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
|
||
var content = element.innerHTML;
|
||
|
||
if (content.length > 20) {
|
||
content = content.substr(0, 20) + "[...]";
|
||
}
|
||
|
||
var res = formatted + pairs.join(" ") + ">" + content +
|
||
"</" + tagName + ">";
|
||
|
||
return res.replace(/ contentEditable="inherit"/, "");
|
||
};
|
||
|
||
function Formatio(options) {
|
||
for (var opt in options) {
|
||
this[opt] = options[opt];
|
||
}
|
||
}
|
||
|
||
Formatio.prototype = {
|
||
functionName: functionName,
|
||
|
||
configure: function (options) {
|
||
return new Formatio(options);
|
||
},
|
||
|
||
constructorName: function (object) {
|
||
return constructorName(this, object);
|
||
},
|
||
|
||
ascii: function (object, processed, indent) {
|
||
return ascii(this, object, processed, indent);
|
||
}
|
||
};
|
||
|
||
return Formatio.prototype;
|
||
});
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{"samsam":82}],81:[function(require,module,exports){
|
||
(function (global){
|
||
/*jslint eqeqeq: false, plusplus: false, evil: true, onevar: false, browser: true, forin: false*/
|
||
/*global global*/
|
||
/**
|
||
* @author Christian Johansen (christian@cjohansen.no) and contributors
|
||
* @license BSD
|
||
*
|
||
* Copyright (c) 2010-2014 Christian Johansen
|
||
*/
|
||
"use strict";
|
||
|
||
// node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
|
||
// browsers, a number.
|
||
// see https://github.com/cjohansen/Sinon.JS/pull/436
|
||
var timeoutResult = setTimeout(function() {}, 0);
|
||
var addTimerReturnsObject = typeof timeoutResult === "object";
|
||
clearTimeout(timeoutResult);
|
||
|
||
var NativeDate = Date;
|
||
var id = 1;
|
||
|
||
/**
|
||
* Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
|
||
* number of milliseconds. This is used to support human-readable strings passed
|
||
* to clock.tick()
|
||
*/
|
||
function parseTime(str) {
|
||
if (!str) {
|
||
return 0;
|
||
}
|
||
|
||
var strings = str.split(":");
|
||
var l = strings.length, i = l;
|
||
var ms = 0, parsed;
|
||
|
||
if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
|
||
throw new Error("tick only understands numbers and 'h:m:s'");
|
||
}
|
||
|
||
while (i--) {
|
||
parsed = parseInt(strings[i], 10);
|
||
|
||
if (parsed >= 60) {
|
||
throw new Error("Invalid time " + str);
|
||
}
|
||
|
||
ms += parsed * Math.pow(60, (l - i - 1));
|
||
}
|
||
|
||
return ms * 1000;
|
||
}
|
||
|
||
/**
|
||
* Used to grok the `now` parameter to createClock.
|
||
*/
|
||
function getEpoch(epoch) {
|
||
if (!epoch) { return 0; }
|
||
if (typeof epoch.getTime === "function") { return epoch.getTime(); }
|
||
if (typeof epoch === "number") { return epoch; }
|
||
throw new TypeError("now should be milliseconds since UNIX epoch");
|
||
}
|
||
|
||
function inRange(from, to, timer) {
|
||
return timer && timer.callAt >= from && timer.callAt <= to;
|
||
}
|
||
|
||
function mirrorDateProperties(target, source) {
|
||
if (source.now) {
|
||
target.now = function now() {
|
||
return target.clock.now;
|
||
};
|
||
} else {
|
||
delete target.now;
|
||
}
|
||
|
||
if (source.toSource) {
|
||
target.toSource = function toSource() {
|
||
return source.toSource();
|
||
};
|
||
} else {
|
||
delete target.toSource;
|
||
}
|
||
|
||
target.toString = function toString() {
|
||
return source.toString();
|
||
};
|
||
|
||
target.prototype = source.prototype;
|
||
target.parse = source.parse;
|
||
target.UTC = source.UTC;
|
||
target.prototype.toUTCString = source.prototype.toUTCString;
|
||
|
||
for (var prop in source) {
|
||
if (source.hasOwnProperty(prop)) {
|
||
target[prop] = source[prop];
|
||
}
|
||
}
|
||
|
||
return target;
|
||
}
|
||
|
||
function createDate() {
|
||
function ClockDate(year, month, date, hour, minute, second, ms) {
|
||
// Defensive and verbose to avoid potential harm in passing
|
||
// explicit undefined when user does not pass argument
|
||
switch (arguments.length) {
|
||
case 0:
|
||
return new NativeDate(ClockDate.clock.now);
|
||
case 1:
|
||
return new NativeDate(year);
|
||
case 2:
|
||
return new NativeDate(year, month);
|
||
case 3:
|
||
return new NativeDate(year, month, date);
|
||
case 4:
|
||
return new NativeDate(year, month, date, hour);
|
||
case 5:
|
||
return new NativeDate(year, month, date, hour, minute);
|
||
case 6:
|
||
return new NativeDate(year, month, date, hour, minute, second);
|
||
default:
|
||
return new NativeDate(year, month, date, hour, minute, second, ms);
|
||
}
|
||
}
|
||
|
||
return mirrorDateProperties(ClockDate, NativeDate);
|
||
}
|
||
|
||
function addTimer(clock, timer) {
|
||
if (typeof timer.func === "undefined") {
|
||
throw new Error("Callback must be provided to timer calls");
|
||
}
|
||
|
||
if (!clock.timers) {
|
||
clock.timers = {};
|
||
}
|
||
|
||
timer.id = id++;
|
||
timer.createdAt = clock.now;
|
||
timer.callAt = clock.now + (timer.delay || 0);
|
||
|
||
clock.timers[timer.id] = timer;
|
||
|
||
if (addTimerReturnsObject) {
|
||
return {
|
||
id: timer.id,
|
||
ref: function() {},
|
||
unref: function() {}
|
||
};
|
||
}
|
||
else {
|
||
return timer.id;
|
||
}
|
||
}
|
||
|
||
function firstTimerInRange(clock, from, to) {
|
||
var timers = clock.timers, timer = null;
|
||
|
||
for (var id in timers) {
|
||
if (!inRange(from, to, timers[id])) {
|
||
continue;
|
||
}
|
||
|
||
if (!timer || ~compareTimers(timer, timers[id])) {
|
||
timer = timers[id];
|
||
}
|
||
}
|
||
|
||
return timer;
|
||
}
|
||
|
||
function compareTimers(a, b) {
|
||
// Sort first by absolute timing
|
||
if (a.callAt < b.callAt) {
|
||
return -1;
|
||
}
|
||
if (a.callAt > b.callAt) {
|
||
return 1;
|
||
}
|
||
|
||
// Sort next by immediate, immediate timers take precedence
|
||
if (a.immediate && !b.immediate) {
|
||
return -1;
|
||
}
|
||
if (!a.immediate && b.immediate) {
|
||
return 1;
|
||
}
|
||
|
||
// Sort next by creation time, earlier-created timers take precedence
|
||
if (a.createdAt < b.createdAt) {
|
||
return -1;
|
||
}
|
||
if (a.createdAt > b.createdAt) {
|
||
return 1;
|
||
}
|
||
|
||
// Sort next by id, lower-id timers take precedence
|
||
if (a.id < b.id) {
|
||
return -1;
|
||
}
|
||
if (a.id > b.id) {
|
||
return 1;
|
||
}
|
||
|
||
// As timer ids are unique, no fallback `0` is necessary
|
||
}
|
||
|
||
function callTimer(clock, timer) {
|
||
if (typeof timer.interval == "number") {
|
||
clock.timers[timer.id].callAt += timer.interval;
|
||
} else {
|
||
delete clock.timers[timer.id];
|
||
}
|
||
|
||
try {
|
||
if (typeof timer.func == "function") {
|
||
timer.func.apply(null, timer.args);
|
||
} else {
|
||
eval(timer.func);
|
||
}
|
||
} catch (e) {
|
||
var exception = e;
|
||
}
|
||
|
||
if (!clock.timers[timer.id]) {
|
||
if (exception) {
|
||
throw exception;
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (exception) {
|
||
throw exception;
|
||
}
|
||
}
|
||
|
||
function uninstall(clock, target) {
|
||
var method;
|
||
|
||
for (var i = 0, l = clock.methods.length; i < l; i++) {
|
||
method = clock.methods[i];
|
||
|
||
if (target[method].hadOwnProperty) {
|
||
target[method] = clock["_" + method];
|
||
} else {
|
||
try {
|
||
delete target[method];
|
||
} catch (e) {}
|
||
}
|
||
}
|
||
|
||
// Prevent multiple executions which will completely remove these props
|
||
clock.methods = [];
|
||
}
|
||
|
||
function hijackMethod(target, method, clock) {
|
||
clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
|
||
clock["_" + method] = target[method];
|
||
|
||
if (method == "Date") {
|
||
var date = mirrorDateProperties(clock[method], target[method]);
|
||
target[method] = date;
|
||
} else {
|
||
target[method] = function () {
|
||
return clock[method].apply(clock, arguments);
|
||
};
|
||
|
||
for (var prop in clock[method]) {
|
||
if (clock[method].hasOwnProperty(prop)) {
|
||
target[method][prop] = clock[method][prop];
|
||
}
|
||
}
|
||
}
|
||
|
||
target[method].clock = clock;
|
||
}
|
||
|
||
var timers = {
|
||
setTimeout: setTimeout,
|
||
clearTimeout: clearTimeout,
|
||
setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
|
||
clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate: undefined),
|
||
setInterval: setInterval,
|
||
clearInterval: clearInterval,
|
||
Date: Date
|
||
};
|
||
|
||
var keys = Object.keys || function (obj) {
|
||
var ks = [];
|
||
for (var key in obj) {
|
||
ks.push(key);
|
||
}
|
||
return ks;
|
||
};
|
||
|
||
exports.timers = timers;
|
||
|
||
var createClock = exports.createClock = function (now) {
|
||
var clock = {
|
||
now: getEpoch(now),
|
||
timeouts: {},
|
||
Date: createDate()
|
||
};
|
||
|
||
clock.Date.clock = clock;
|
||
|
||
clock.setTimeout = function setTimeout(func, timeout) {
|
||
return addTimer(clock, {
|
||
func: func,
|
||
args: Array.prototype.slice.call(arguments, 2),
|
||
delay: timeout
|
||
});
|
||
};
|
||
|
||
clock.clearTimeout = function clearTimeout(timerId) {
|
||
if (!timerId) {
|
||
// null appears to be allowed in most browsers, and appears to be
|
||
// relied upon by some libraries, like Bootstrap carousel
|
||
return;
|
||
}
|
||
if (!clock.timers) {
|
||
clock.timers = [];
|
||
}
|
||
// in Node, timerId is an object with .ref()/.unref(), and
|
||
// its .id field is the actual timer id.
|
||
if (typeof timerId === "object") {
|
||
timerId = timerId.id
|
||
}
|
||
if (timerId in clock.timers) {
|
||
delete clock.timers[timerId];
|
||
}
|
||
};
|
||
|
||
clock.setInterval = function setInterval(func, timeout) {
|
||
return addTimer(clock, {
|
||
func: func,
|
||
args: Array.prototype.slice.call(arguments, 2),
|
||
delay: timeout,
|
||
interval: timeout
|
||
});
|
||
};
|
||
|
||
clock.clearInterval = function clearInterval(timerId) {
|
||
clock.clearTimeout(timerId);
|
||
};
|
||
|
||
clock.setImmediate = function setImmediate(func) {
|
||
return addTimer(clock, {
|
||
func: func,
|
||
args: Array.prototype.slice.call(arguments, 1),
|
||
immediate: true
|
||
});
|
||
};
|
||
|
||
clock.clearImmediate = function clearImmediate(timerId) {
|
||
clock.clearTimeout(timerId);
|
||
};
|
||
|
||
clock.tick = function tick(ms) {
|
||
ms = typeof ms == "number" ? ms : parseTime(ms);
|
||
var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now;
|
||
var timer = firstTimerInRange(clock, tickFrom, tickTo);
|
||
|
||
var firstException;
|
||
while (timer && tickFrom <= tickTo) {
|
||
if (clock.timers[timer.id]) {
|
||
tickFrom = clock.now = timer.callAt;
|
||
try {
|
||
callTimer(clock, timer);
|
||
} catch (e) {
|
||
firstException = firstException || e;
|
||
}
|
||
}
|
||
|
||
timer = firstTimerInRange(clock, previous, tickTo);
|
||
previous = tickFrom;
|
||
}
|
||
|
||
clock.now = tickTo;
|
||
|
||
if (firstException) {
|
||
throw firstException;
|
||
}
|
||
|
||
return clock.now;
|
||
};
|
||
|
||
clock.reset = function reset() {
|
||
clock.timers = {};
|
||
};
|
||
|
||
return clock;
|
||
};
|
||
|
||
exports.install = function install(target, now, toFake) {
|
||
if (typeof target === "number") {
|
||
toFake = now;
|
||
now = target;
|
||
target = null;
|
||
}
|
||
|
||
if (!target) {
|
||
target = global;
|
||
}
|
||
|
||
var clock = createClock(now);
|
||
|
||
clock.uninstall = function () {
|
||
uninstall(clock, target);
|
||
};
|
||
|
||
clock.methods = toFake || [];
|
||
|
||
if (clock.methods.length === 0) {
|
||
clock.methods = keys(timers);
|
||
}
|
||
|
||
for (var i = 0, l = clock.methods.length; i < l; i++) {
|
||
hijackMethod(target, clock.methods[i], clock);
|
||
}
|
||
|
||
return clock;
|
||
};
|
||
|
||
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
|
||
},{}],82:[function(require,module,exports){
|
||
((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
|
||
(typeof module === "object" &&
|
||
function (m) { module.exports = m(); }) || // Node
|
||
function (m) { this.samsam = m(); } // Browser globals
|
||
)(function () {
|
||
var o = Object.prototype;
|
||
var div = typeof document !== "undefined" && document.createElement("div");
|
||
|
||
function isNaN(value) {
|
||
// Unlike global isNaN, this avoids type coercion
|
||
// typeof check avoids IE host object issues, hat tip to
|
||
// lodash
|
||
var val = value; // JsLint thinks value !== value is "weird"
|
||
return typeof value === "number" && value !== val;
|
||
}
|
||
|
||
function getClass(value) {
|
||
// Returns the internal [[Class]] by calling Object.prototype.toString
|
||
// with the provided value as this. Return value is a string, naming the
|
||
// internal class, e.g. "Array"
|
||
return o.toString.call(value).split(/[ \]]/)[1];
|
||
}
|
||
|
||
/**
|
||
* @name samsam.isArguments
|
||
* @param Object object
|
||
*
|
||
* Returns ``true`` if ``object`` is an ``arguments`` object,
|
||
* ``false`` otherwise.
|
||
*/
|
||
function isArguments(object) {
|
||
if (getClass(object) === 'Arguments') { return true; }
|
||
if (typeof object !== "object" || typeof object.length !== "number" ||
|
||
getClass(object) === "Array") {
|
||
return false;
|
||
}
|
||
if (typeof object.callee == "function") { return true; }
|
||
try {
|
||
object[object.length] = 6;
|
||
delete object[object.length];
|
||
} catch (e) {
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* @name samsam.isElement
|
||
* @param Object object
|
||
*
|
||
* Returns ``true`` if ``object`` is a DOM element node. Unlike
|
||
* Underscore.js/lodash, this function will return ``false`` if ``object``
|
||
* is an *element-like* object, i.e. a regular object with a ``nodeType``
|
||
* property that holds the value ``1``.
|
||
*/
|
||
function isElement(object) {
|
||
if (!object || object.nodeType !== 1 || !div) { return false; }
|
||
try {
|
||
object.appendChild(div);
|
||
object.removeChild(div);
|
||
} catch (e) {
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* @name samsam.keys
|
||
* @param Object object
|
||
*
|
||
* Return an array of own property names.
|
||
*/
|
||
function keys(object) {
|
||
var ks = [], prop;
|
||
for (prop in object) {
|
||
if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
|
||
}
|
||
return ks;
|
||
}
|
||
|
||
/**
|
||
* @name samsam.isDate
|
||
* @param Object value
|
||
*
|
||
* Returns true if the object is a ``Date``, or *date-like*. Duck typing
|
||
* of date objects work by checking that the object has a ``getTime``
|
||
* function whose return value equals the return value from the object's
|
||
* ``valueOf``.
|
||
*/
|
||
function isDate(value) {
|
||
return typeof value.getTime == "function" &&
|
||
value.getTime() == value.valueOf();
|
||
}
|
||
|
||
/**
|
||
* @name samsam.isNegZero
|
||
* @param Object value
|
||
*
|
||
* Returns ``true`` if ``value`` is ``-0``.
|
||
*/
|
||
function isNegZero(value) {
|
||
return value === 0 && 1 / value === -Infinity;
|
||
}
|
||
|
||
/**
|
||
* @name samsam.equal
|
||
* @param Object obj1
|
||
* @param Object obj2
|
||
*
|
||
* Returns ``true`` if two objects are strictly equal. Compared to
|
||
* ``===`` there are two exceptions:
|
||
*
|
||
* - NaN is considered equal to NaN
|
||
* - -0 and +0 are not considered equal
|
||
*/
|
||
function identical(obj1, obj2) {
|
||
if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
|
||
return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* @name samsam.deepEqual
|
||
* @param Object obj1
|
||
* @param Object obj2
|
||
*
|
||
* Deep equal comparison. Two values are "deep equal" if:
|
||
*
|
||
* - They are equal, according to samsam.identical
|
||
* - They are both date objects representing the same time
|
||
* - They are both arrays containing elements that are all deepEqual
|
||
* - They are objects with the same set of properties, and each property
|
||
* in ``obj1`` is deepEqual to the corresponding property in ``obj2``
|
||
*
|
||
* Supports cyclic objects.
|
||
*/
|
||
function deepEqualCyclic(obj1, obj2) {
|
||
|
||
// used for cyclic comparison
|
||
// contain already visited objects
|
||
var objects1 = [],
|
||
objects2 = [],
|
||
// contain pathes (position in the object structure)
|
||
// of the already visited objects
|
||
// indexes same as in objects arrays
|
||
paths1 = [],
|
||
paths2 = [],
|
||
// contains combinations of already compared objects
|
||
// in the manner: { "$1['ref']$2['ref']": true }
|
||
compared = {};
|
||
|
||
/**
|
||
* used to check, if the value of a property is an object
|
||
* (cyclic logic is only needed for objects)
|
||
* only needed for cyclic logic
|
||
*/
|
||
function isObject(value) {
|
||
|
||
if (typeof value === 'object' && value !== null &&
|
||
!(value instanceof Boolean) &&
|
||
!(value instanceof Date) &&
|
||
!(value instanceof Number) &&
|
||
!(value instanceof RegExp) &&
|
||
!(value instanceof String)) {
|
||
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* returns the index of the given object in the
|
||
* given objects array, -1 if not contained
|
||
* only needed for cyclic logic
|
||
*/
|
||
function getIndex(objects, obj) {
|
||
|
||
var i;
|
||
for (i = 0; i < objects.length; i++) {
|
||
if (objects[i] === obj) {
|
||
return i;
|
||
}
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
// does the recursion for the deep equal check
|
||
return (function deepEqual(obj1, obj2, path1, path2) {
|
||
var type1 = typeof obj1;
|
||
var type2 = typeof obj2;
|
||
|
||
// == null also matches undefined
|
||
if (obj1 === obj2 ||
|
||
isNaN(obj1) || isNaN(obj2) ||
|
||
obj1 == null || obj2 == null ||
|
||
type1 !== "object" || type2 !== "object") {
|
||
|
||
return identical(obj1, obj2);
|
||
}
|
||
|
||
// Elements are only equal if identical(expected, actual)
|
||
if (isElement(obj1) || isElement(obj2)) { return false; }
|
||
|
||
var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
|
||
if (isDate1 || isDate2) {
|
||
if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
|
||
if (obj1.toString() !== obj2.toString()) { return false; }
|
||
}
|
||
|
||
var class1 = getClass(obj1);
|
||
var class2 = getClass(obj2);
|
||
var keys1 = keys(obj1);
|
||
var keys2 = keys(obj2);
|
||
|
||
if (isArguments(obj1) || isArguments(obj2)) {
|
||
if (obj1.length !== obj2.length) { return false; }
|
||
} else {
|
||
if (type1 !== type2 || class1 !== class2 ||
|
||
keys1.length !== keys2.length) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
var key, i, l,
|
||
// following vars are used for the cyclic logic
|
||
value1, value2,
|
||
isObject1, isObject2,
|
||
index1, index2,
|
||
newPath1, newPath2;
|
||
|
||
for (i = 0, l = keys1.length; i < l; i++) {
|
||
key = keys1[i];
|
||
if (!o.hasOwnProperty.call(obj2, key)) {
|
||
return false;
|
||
}
|
||
|
||
// Start of the cyclic logic
|
||
|
||
value1 = obj1[key];
|
||
value2 = obj2[key];
|
||
|
||
isObject1 = isObject(value1);
|
||
isObject2 = isObject(value2);
|
||
|
||
// determine, if the objects were already visited
|
||
// (it's faster to check for isObject first, than to
|
||
// get -1 from getIndex for non objects)
|
||
index1 = isObject1 ? getIndex(objects1, value1) : -1;
|
||
index2 = isObject2 ? getIndex(objects2, value2) : -1;
|
||
|
||
// determine the new pathes of the objects
|
||
// - for non cyclic objects the current path will be extended
|
||
// by current property name
|
||
// - for cyclic objects the stored path is taken
|
||
newPath1 = index1 !== -1
|
||
? paths1[index1]
|
||
: path1 + '[' + JSON.stringify(key) + ']';
|
||
newPath2 = index2 !== -1
|
||
? paths2[index2]
|
||
: path2 + '[' + JSON.stringify(key) + ']';
|
||
|
||
// stop recursion if current objects are already compared
|
||
if (compared[newPath1 + newPath2]) {
|
||
return true;
|
||
}
|
||
|
||
// remember the current objects and their pathes
|
||
if (index1 === -1 && isObject1) {
|
||
objects1.push(value1);
|
||
paths1.push(newPath1);
|
||
}
|
||
if (index2 === -1 && isObject2) {
|
||
objects2.push(value2);
|
||
paths2.push(newPath2);
|
||
}
|
||
|
||
// remember that the current objects are already compared
|
||
if (isObject1 && isObject2) {
|
||
compared[newPath1 + newPath2] = true;
|
||
}
|
||
|
||
// End of cyclic logic
|
||
|
||
// neither value1 nor value2 is a cycle
|
||
// continue with next level
|
||
if (!deepEqual(value1, value2, newPath1, newPath2)) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
return true;
|
||
|
||
}(obj1, obj2, '$1', '$2'));
|
||
}
|
||
|
||
var match;
|
||
|
||
function arrayContains(array, subset) {
|
||
if (subset.length === 0) { return true; }
|
||
var i, l, j, k;
|
||
for (i = 0, l = array.length; i < l; ++i) {
|
||
if (match(array[i], subset[0])) {
|
||
for (j = 0, k = subset.length; j < k; ++j) {
|
||
if (!match(array[i + j], subset[j])) { return false; }
|
||
}
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
/**
|
||
* @name samsam.match
|
||
* @param Object object
|
||
* @param Object matcher
|
||
*
|
||
* Compare arbitrary value ``object`` with matcher.
|
||
*/
|
||
match = function match(object, matcher) {
|
||
if (matcher && typeof matcher.test === "function") {
|
||
return matcher.test(object);
|
||
}
|
||
|
||
if (typeof matcher === "function") {
|
||
return matcher(object) === true;
|
||
}
|
||
|
||
if (typeof matcher === "string") {
|
||
matcher = matcher.toLowerCase();
|
||
var notNull = typeof object === "string" || !!object;
|
||
return notNull &&
|
||
(String(object)).toLowerCase().indexOf(matcher) >= 0;
|
||
}
|
||
|
||
if (typeof matcher === "number") {
|
||
return matcher === object;
|
||
}
|
||
|
||
if (typeof matcher === "boolean") {
|
||
return matcher === object;
|
||
}
|
||
|
||
if (typeof(matcher) === "undefined") {
|
||
return typeof(object) === "undefined";
|
||
}
|
||
|
||
if (matcher === null) {
|
||
return object === null;
|
||
}
|
||
|
||
if (getClass(object) === "Array" && getClass(matcher) === "Array") {
|
||
return arrayContains(object, matcher);
|
||
}
|
||
|
||
if (matcher && typeof matcher === "object") {
|
||
if (matcher === object) {
|
||
return true;
|
||
}
|
||
var prop;
|
||
for (prop in matcher) {
|
||
var value = object[prop];
|
||
if (typeof value === "undefined" &&
|
||
typeof object.getAttribute === "function") {
|
||
value = object.getAttribute(prop);
|
||
}
|
||
if (matcher[prop] === null || typeof matcher[prop] === 'undefined') {
|
||
if (value !== matcher[prop]) {
|
||
return false;
|
||
}
|
||
} else if (typeof value === "undefined" || !match(value, matcher[prop])) {
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
|
||
throw new Error("Matcher was not a string, a number, a " +
|
||
"function, a boolean or an object");
|
||
};
|
||
|
||
return {
|
||
isArguments: isArguments,
|
||
isElement: isElement,
|
||
isDate: isDate,
|
||
isNegZero: isNegZero,
|
||
identical: identical,
|
||
deepEqual: deepEqualCyclic,
|
||
match: match,
|
||
keys: keys
|
||
};
|
||
});
|
||
|
||
},{}],83:[function(require,module,exports){
|
||
// Underscore.js 1.8.3
|
||
// http://underscorejs.org
|
||
// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||
// Underscore may be freely distributed under the MIT license.
|
||
|
||
(function() {
|
||
|
||
// Baseline setup
|
||
// --------------
|
||
|
||
// Establish the root object, `window` in the browser, or `exports` on the server.
|
||
var root = this;
|
||
|
||
// Save the previous value of the `_` variable.
|
||
var previousUnderscore = root._;
|
||
|
||
// Save bytes in the minified (but not gzipped) version:
|
||
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
|
||
|
||
// Create quick reference variables for speed access to core prototypes.
|
||
var
|
||
push = ArrayProto.push,
|
||
slice = ArrayProto.slice,
|
||
toString = ObjProto.toString,
|
||
hasOwnProperty = ObjProto.hasOwnProperty;
|
||
|
||
// All **ECMAScript 5** native function implementations that we hope to use
|
||
// are declared here.
|
||
var
|
||
nativeIsArray = Array.isArray,
|
||
nativeKeys = Object.keys,
|
||
nativeBind = FuncProto.bind,
|
||
nativeCreate = Object.create;
|
||
|
||
// Naked function reference for surrogate-prototype-swapping.
|
||
var Ctor = function(){};
|
||
|
||
// Create a safe reference to the Underscore object for use below.
|
||
var _ = function(obj) {
|
||
if (obj instanceof _) return obj;
|
||
if (!(this instanceof _)) return new _(obj);
|
||
this._wrapped = obj;
|
||
};
|
||
|
||
// Export the Underscore object for **Node.js**, with
|
||
// backwards-compatibility for the old `require()` API. If we're in
|
||
// the browser, add `_` as a global object.
|
||
if (typeof exports !== 'undefined') {
|
||
if (typeof module !== 'undefined' && module.exports) {
|
||
exports = module.exports = _;
|
||
}
|
||
exports._ = _;
|
||
} else {
|
||
root._ = _;
|
||
}
|
||
|
||
// Current version.
|
||
_.VERSION = '1.8.3';
|
||
|
||
// Internal function that returns an efficient (for current engines) version
|
||
// of the passed-in callback, to be repeatedly applied in other Underscore
|
||
// functions.
|
||
var optimizeCb = function(func, context, argCount) {
|
||
if (context === void 0) return func;
|
||
switch (argCount == null ? 3 : argCount) {
|
||
case 1: return function(value) {
|
||
return func.call(context, value);
|
||
};
|
||
case 2: return function(value, other) {
|
||
return func.call(context, value, other);
|
||
};
|
||
case 3: return function(value, index, collection) {
|
||
return func.call(context, value, index, collection);
|
||
};
|
||
case 4: return function(accumulator, value, index, collection) {
|
||
return func.call(context, accumulator, value, index, collection);
|
||
};
|
||
}
|
||
return function() {
|
||
return func.apply(context, arguments);
|
||
};
|
||
};
|
||
|
||
// A mostly-internal function to generate callbacks that can be applied
|
||
// to each element in a collection, returning the desired result — either
|
||
// identity, an arbitrary callback, a property matcher, or a property accessor.
|
||
var cb = function(value, context, argCount) {
|
||
if (value == null) return _.identity;
|
||
if (_.isFunction(value)) return optimizeCb(value, context, argCount);
|
||
if (_.isObject(value)) return _.matcher(value);
|
||
return _.property(value);
|
||
};
|
||
_.iteratee = function(value, context) {
|
||
return cb(value, context, Infinity);
|
||
};
|
||
|
||
// An internal function for creating assigner functions.
|
||
var createAssigner = function(keysFunc, undefinedOnly) {
|
||
return function(obj) {
|
||
var length = arguments.length;
|
||
if (length < 2 || obj == null) return obj;
|
||
for (var index = 1; index < length; index++) {
|
||
var source = arguments[index],
|
||
keys = keysFunc(source),
|
||
l = keys.length;
|
||
for (var i = 0; i < l; i++) {
|
||
var key = keys[i];
|
||
if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key];
|
||
}
|
||
}
|
||
return obj;
|
||
};
|
||
};
|
||
|
||
// An internal function for creating a new object that inherits from another.
|
||
var baseCreate = function(prototype) {
|
||
if (!_.isObject(prototype)) return {};
|
||
if (nativeCreate) return nativeCreate(prototype);
|
||
Ctor.prototype = prototype;
|
||
var result = new Ctor;
|
||
Ctor.prototype = null;
|
||
return result;
|
||
};
|
||
|
||
var property = function(key) {
|
||
return function(obj) {
|
||
return obj == null ? void 0 : obj[key];
|
||
};
|
||
};
|
||
|
||
// Helper for collection methods to determine whether a collection
|
||
// should be iterated as an array or as an object
|
||
// Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength
|
||
// Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094
|
||
var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1;
|
||
var getLength = property('length');
|
||
var isArrayLike = function(collection) {
|
||
var length = getLength(collection);
|
||
return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX;
|
||
};
|
||
|
||
// Collection Functions
|
||
// --------------------
|
||
|
||
// The cornerstone, an `each` implementation, aka `forEach`.
|
||
// Handles raw objects in addition to array-likes. Treats all
|
||
// sparse array-likes as if they were dense.
|
||
_.each = _.forEach = function(obj, iteratee, context) {
|
||
iteratee = optimizeCb(iteratee, context);
|
||
var i, length;
|
||
if (isArrayLike(obj)) {
|
||
for (i = 0, length = obj.length; i < length; i++) {
|
||
iteratee(obj[i], i, obj);
|
||
}
|
||
} else {
|
||
var keys = _.keys(obj);
|
||
for (i = 0, length = keys.length; i < length; i++) {
|
||
iteratee(obj[keys[i]], keys[i], obj);
|
||
}
|
||
}
|
||
return obj;
|
||
};
|
||
|
||
// Return the results of applying the iteratee to each element.
|
||
_.map = _.collect = function(obj, iteratee, context) {
|
||
iteratee = cb(iteratee, context);
|
||
var keys = !isArrayLike(obj) && _.keys(obj),
|
||
length = (keys || obj).length,
|
||
results = Array(length);
|
||
for (var index = 0; index < length; index++) {
|
||
var currentKey = keys ? keys[index] : index;
|
||
results[index] = iteratee(obj[currentKey], currentKey, obj);
|
||
}
|
||
return results;
|
||
};
|
||
|
||
// Create a reducing function iterating left or right.
|
||
function createReduce(dir) {
|
||
// Optimized iterator function as using arguments.length
|
||
// in the main function will deoptimize the, see #1991.
|
||
function iterator(obj, iteratee, memo, keys, index, length) {
|
||
for (; index >= 0 && index < length; index += dir) {
|
||
var currentKey = keys ? keys[index] : index;
|
||
memo = iteratee(memo, obj[currentKey], currentKey, obj);
|
||
}
|
||
return memo;
|
||
}
|
||
|
||
return function(obj, iteratee, memo, context) {
|
||
iteratee = optimizeCb(iteratee, context, 4);
|
||
var keys = !isArrayLike(obj) && _.keys(obj),
|
||
length = (keys || obj).length,
|
||
index = dir > 0 ? 0 : length - 1;
|
||
// Determine the initial value if none is provided.
|
||
if (arguments.length < 3) {
|
||
memo = obj[keys ? keys[index] : index];
|
||
index += dir;
|
||
}
|
||
return iterator(obj, iteratee, memo, keys, index, length);
|
||
};
|
||
}
|
||
|
||
// **Reduce** builds up a single result from a list of values, aka `inject`,
|
||
// or `foldl`.
|
||
_.reduce = _.foldl = _.inject = createReduce(1);
|
||
|
||
// The right-associative version of reduce, also known as `foldr`.
|
||
_.reduceRight = _.foldr = createReduce(-1);
|
||
|
||
// Return the first value which passes a truth test. Aliased as `detect`.
|
||
_.find = _.detect = function(obj, predicate, context) {
|
||
var key;
|
||
if (isArrayLike(obj)) {
|
||
key = _.findIndex(obj, predicate, context);
|
||
} else {
|
||
key = _.findKey(obj, predicate, context);
|
||
}
|
||
if (key !== void 0 && key !== -1) return obj[key];
|
||
};
|
||
|
||
// Return all the elements that pass a truth test.
|
||
// Aliased as `select`.
|
||
_.filter = _.select = function(obj, predicate, context) {
|
||
var results = [];
|
||
predicate = cb(predicate, context);
|
||
_.each(obj, function(value, index, list) {
|
||
if (predicate(value, index, list)) results.push(value);
|
||
});
|
||
return results;
|
||
};
|
||
|
||
// Return all the elements for which a truth test fails.
|
||
_.reject = function(obj, predicate, context) {
|
||
return _.filter(obj, _.negate(cb(predicate)), context);
|
||
};
|
||
|
||
// Determine whether all of the elements match a truth test.
|
||
// Aliased as `all`.
|
||
_.every = _.all = function(obj, predicate, context) {
|
||
predicate = cb(predicate, context);
|
||
var keys = !isArrayLike(obj) && _.keys(obj),
|
||
length = (keys || obj).length;
|
||
for (var index = 0; index < length; index++) {
|
||
var currentKey = keys ? keys[index] : index;
|
||
if (!predicate(obj[currentKey], currentKey, obj)) return false;
|
||
}
|
||
return true;
|
||
};
|
||
|
||
// Determine if at least one element in the object matches a truth test.
|
||
// Aliased as `any`.
|
||
_.some = _.any = function(obj, predicate, context) {
|
||
predicate = cb(predicate, context);
|
||
var keys = !isArrayLike(obj) && _.keys(obj),
|
||
length = (keys || obj).length;
|
||
for (var index = 0; index < length; index++) {
|
||
var currentKey = keys ? keys[index] : index;
|
||
if (predicate(obj[currentKey], currentKey, obj)) return true;
|
||
}
|
||
return false;
|
||
};
|
||
|
||
// Determine if the array or object contains a given item (using `===`).
|
||
// Aliased as `includes` and `include`.
|
||
_.contains = _.includes = _.include = function(obj, item, fromIndex, guard) {
|
||
if (!isArrayLike(obj)) obj = _.values(obj);
|
||
if (typeof fromIndex != 'number' || guard) fromIndex = 0;
|
||
return _.indexOf(obj, item, fromIndex) >= 0;
|
||
};
|
||
|
||
// Invoke a method (with arguments) on every item in a collection.
|
||
_.invoke = function(obj, method) {
|
||
var args = slice.call(arguments, 2);
|
||
var isFunc = _.isFunction(method);
|
||
return _.map(obj, function(value) {
|
||
var func = isFunc ? method : value[method];
|
||
return func == null ? func : func.apply(value, args);
|
||
});
|
||
};
|
||
|
||
// Convenience version of a common use case of `map`: fetching a property.
|
||
_.pluck = function(obj, key) {
|
||
return _.map(obj, _.property(key));
|
||
};
|
||
|
||
// Convenience version of a common use case of `filter`: selecting only objects
|
||
// containing specific `key:value` pairs.
|
||
_.where = function(obj, attrs) {
|
||
return _.filter(obj, _.matcher(attrs));
|
||
};
|
||
|
||
// Convenience version of a common use case of `find`: getting the first object
|
||
// containing specific `key:value` pairs.
|
||
_.findWhere = function(obj, attrs) {
|
||
return _.find(obj, _.matcher(attrs));
|
||
};
|
||
|
||
// Return the maximum element (or element-based computation).
|
||
_.max = function(obj, iteratee, context) {
|
||
var result = -Infinity, lastComputed = -Infinity,
|
||
value, computed;
|
||
if (iteratee == null && obj != null) {
|
||
obj = isArrayLike(obj) ? obj : _.values(obj);
|
||
for (var i = 0, length = obj.length; i < length; i++) {
|
||
value = obj[i];
|
||
if (value > result) {
|
||
result = value;
|
||
}
|
||
}
|
||
} else {
|
||
iteratee = cb(iteratee, context);
|
||
_.each(obj, function(value, index, list) {
|
||
computed = iteratee(value, index, list);
|
||
if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
|
||
result = value;
|
||
lastComputed = computed;
|
||
}
|
||
});
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Return the minimum element (or element-based computation).
|
||
_.min = function(obj, iteratee, context) {
|
||
var result = Infinity, lastComputed = Infinity,
|
||
value, computed;
|
||
if (iteratee == null && obj != null) {
|
||
obj = isArrayLike(obj) ? obj : _.values(obj);
|
||
for (var i = 0, length = obj.length; i < length; i++) {
|
||
value = obj[i];
|
||
if (value < result) {
|
||
result = value;
|
||
}
|
||
}
|
||
} else {
|
||
iteratee = cb(iteratee, context);
|
||
_.each(obj, function(value, index, list) {
|
||
computed = iteratee(value, index, list);
|
||
if (computed < lastComputed || computed === Infinity && result === Infinity) {
|
||
result = value;
|
||
lastComputed = computed;
|
||
}
|
||
});
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Shuffle a collection, using the modern version of the
|
||
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle).
|
||
_.shuffle = function(obj) {
|
||
var set = isArrayLike(obj) ? obj : _.values(obj);
|
||
var length = set.length;
|
||
var shuffled = Array(length);
|
||
for (var index = 0, rand; index < length; index++) {
|
||
rand = _.random(0, index);
|
||
if (rand !== index) shuffled[index] = shuffled[rand];
|
||
shuffled[rand] = set[index];
|
||
}
|
||
return shuffled;
|
||
};
|
||
|
||
// Sample **n** random values from a collection.
|
||
// If **n** is not specified, returns a single random element.
|
||
// The internal `guard` argument allows it to work with `map`.
|
||
_.sample = function(obj, n, guard) {
|
||
if (n == null || guard) {
|
||
if (!isArrayLike(obj)) obj = _.values(obj);
|
||
return obj[_.random(obj.length - 1)];
|
||
}
|
||
return _.shuffle(obj).slice(0, Math.max(0, n));
|
||
};
|
||
|
||
// Sort the object's values by a criterion produced by an iteratee.
|
||
_.sortBy = function(obj, iteratee, context) {
|
||
iteratee = cb(iteratee, context);
|
||
return _.pluck(_.map(obj, function(value, index, list) {
|
||
return {
|
||
value: value,
|
||
index: index,
|
||
criteria: iteratee(value, index, list)
|
||
};
|
||
}).sort(function(left, right) {
|
||
var a = left.criteria;
|
||
var b = right.criteria;
|
||
if (a !== b) {
|
||
if (a > b || a === void 0) return 1;
|
||
if (a < b || b === void 0) return -1;
|
||
}
|
||
return left.index - right.index;
|
||
}), 'value');
|
||
};
|
||
|
||
// An internal function used for aggregate "group by" operations.
|
||
var group = function(behavior) {
|
||
return function(obj, iteratee, context) {
|
||
var result = {};
|
||
iteratee = cb(iteratee, context);
|
||
_.each(obj, function(value, index) {
|
||
var key = iteratee(value, index, obj);
|
||
behavior(result, value, key);
|
||
});
|
||
return result;
|
||
};
|
||
};
|
||
|
||
// Groups the object's values by a criterion. Pass either a string attribute
|
||
// to group by, or a function that returns the criterion.
|
||
_.groupBy = group(function(result, value, key) {
|
||
if (_.has(result, key)) result[key].push(value); else result[key] = [value];
|
||
});
|
||
|
||
// Indexes the object's values by a criterion, similar to `groupBy`, but for
|
||
// when you know that your index values will be unique.
|
||
_.indexBy = group(function(result, value, key) {
|
||
result[key] = value;
|
||
});
|
||
|
||
// Counts instances of an object that group by a certain criterion. Pass
|
||
// either a string attribute to count by, or a function that returns the
|
||
// criterion.
|
||
_.countBy = group(function(result, value, key) {
|
||
if (_.has(result, key)) result[key]++; else result[key] = 1;
|
||
});
|
||
|
||
// Safely create a real, live array from anything iterable.
|
||
_.toArray = function(obj) {
|
||
if (!obj) return [];
|
||
if (_.isArray(obj)) return slice.call(obj);
|
||
if (isArrayLike(obj)) return _.map(obj, _.identity);
|
||
return _.values(obj);
|
||
};
|
||
|
||
// Return the number of elements in an object.
|
||
_.size = function(obj) {
|
||
if (obj == null) return 0;
|
||
return isArrayLike(obj) ? obj.length : _.keys(obj).length;
|
||
};
|
||
|
||
// Split a collection into two arrays: one whose elements all satisfy the given
|
||
// predicate, and one whose elements all do not satisfy the predicate.
|
||
_.partition = function(obj, predicate, context) {
|
||
predicate = cb(predicate, context);
|
||
var pass = [], fail = [];
|
||
_.each(obj, function(value, key, obj) {
|
||
(predicate(value, key, obj) ? pass : fail).push(value);
|
||
});
|
||
return [pass, fail];
|
||
};
|
||
|
||
// Array Functions
|
||
// ---------------
|
||
|
||
// Get the first element of an array. Passing **n** will return the first N
|
||
// values in the array. Aliased as `head` and `take`. The **guard** check
|
||
// allows it to work with `_.map`.
|
||
_.first = _.head = _.take = function(array, n, guard) {
|
||
if (array == null) return void 0;
|
||
if (n == null || guard) return array[0];
|
||
return _.initial(array, array.length - n);
|
||
};
|
||
|
||
// Returns everything but the last entry of the array. Especially useful on
|
||
// the arguments object. Passing **n** will return all the values in
|
||
// the array, excluding the last N.
|
||
_.initial = function(array, n, guard) {
|
||
return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n)));
|
||
};
|
||
|
||
// Get the last element of an array. Passing **n** will return the last N
|
||
// values in the array.
|
||
_.last = function(array, n, guard) {
|
||
if (array == null) return void 0;
|
||
if (n == null || guard) return array[array.length - 1];
|
||
return _.rest(array, Math.max(0, array.length - n));
|
||
};
|
||
|
||
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
|
||
// Especially useful on the arguments object. Passing an **n** will return
|
||
// the rest N values in the array.
|
||
_.rest = _.tail = _.drop = function(array, n, guard) {
|
||
return slice.call(array, n == null || guard ? 1 : n);
|
||
};
|
||
|
||
// Trim out all falsy values from an array.
|
||
_.compact = function(array) {
|
||
return _.filter(array, _.identity);
|
||
};
|
||
|
||
// Internal implementation of a recursive `flatten` function.
|
||
var flatten = function(input, shallow, strict, startIndex) {
|
||
var output = [], idx = 0;
|
||
for (var i = startIndex || 0, length = getLength(input); i < length; i++) {
|
||
var value = input[i];
|
||
if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) {
|
||
//flatten current level of array or arguments object
|
||
if (!shallow) value = flatten(value, shallow, strict);
|
||
var j = 0, len = value.length;
|
||
output.length += len;
|
||
while (j < len) {
|
||
output[idx++] = value[j++];
|
||
}
|
||
} else if (!strict) {
|
||
output[idx++] = value;
|
||
}
|
||
}
|
||
return output;
|
||
};
|
||
|
||
// Flatten out an array, either recursively (by default), or just one level.
|
||
_.flatten = function(array, shallow) {
|
||
return flatten(array, shallow, false);
|
||
};
|
||
|
||
// Return a version of the array that does not contain the specified value(s).
|
||
_.without = function(array) {
|
||
return _.difference(array, slice.call(arguments, 1));
|
||
};
|
||
|
||
// Produce a duplicate-free version of the array. If the array has already
|
||
// been sorted, you have the option of using a faster algorithm.
|
||
// Aliased as `unique`.
|
||
_.uniq = _.unique = function(array, isSorted, iteratee, context) {
|
||
if (!_.isBoolean(isSorted)) {
|
||
context = iteratee;
|
||
iteratee = isSorted;
|
||
isSorted = false;
|
||
}
|
||
if (iteratee != null) iteratee = cb(iteratee, context);
|
||
var result = [];
|
||
var seen = [];
|
||
for (var i = 0, length = getLength(array); i < length; i++) {
|
||
var value = array[i],
|
||
computed = iteratee ? iteratee(value, i, array) : value;
|
||
if (isSorted) {
|
||
if (!i || seen !== computed) result.push(value);
|
||
seen = computed;
|
||
} else if (iteratee) {
|
||
if (!_.contains(seen, computed)) {
|
||
seen.push(computed);
|
||
result.push(value);
|
||
}
|
||
} else if (!_.contains(result, value)) {
|
||
result.push(value);
|
||
}
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Produce an array that contains the union: each distinct element from all of
|
||
// the passed-in arrays.
|
||
_.union = function() {
|
||
return _.uniq(flatten(arguments, true, true));
|
||
};
|
||
|
||
// Produce an array that contains every item shared between all the
|
||
// passed-in arrays.
|
||
_.intersection = function(array) {
|
||
var result = [];
|
||
var argsLength = arguments.length;
|
||
for (var i = 0, length = getLength(array); i < length; i++) {
|
||
var item = array[i];
|
||
if (_.contains(result, item)) continue;
|
||
for (var j = 1; j < argsLength; j++) {
|
||
if (!_.contains(arguments[j], item)) break;
|
||
}
|
||
if (j === argsLength) result.push(item);
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Take the difference between one array and a number of other arrays.
|
||
// Only the elements present in just the first array will remain.
|
||
_.difference = function(array) {
|
||
var rest = flatten(arguments, true, true, 1);
|
||
return _.filter(array, function(value){
|
||
return !_.contains(rest, value);
|
||
});
|
||
};
|
||
|
||
// Zip together multiple lists into a single array -- elements that share
|
||
// an index go together.
|
||
_.zip = function() {
|
||
return _.unzip(arguments);
|
||
};
|
||
|
||
// Complement of _.zip. Unzip accepts an array of arrays and groups
|
||
// each array's elements on shared indices
|
||
_.unzip = function(array) {
|
||
var length = array && _.max(array, getLength).length || 0;
|
||
var result = Array(length);
|
||
|
||
for (var index = 0; index < length; index++) {
|
||
result[index] = _.pluck(array, index);
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Converts lists into objects. Pass either a single array of `[key, value]`
|
||
// pairs, or two parallel arrays of the same length -- one of keys, and one of
|
||
// the corresponding values.
|
||
_.object = function(list, values) {
|
||
var result = {};
|
||
for (var i = 0, length = getLength(list); i < length; i++) {
|
||
if (values) {
|
||
result[list[i]] = values[i];
|
||
} else {
|
||
result[list[i][0]] = list[i][1];
|
||
}
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Generator function to create the findIndex and findLastIndex functions
|
||
function createPredicateIndexFinder(dir) {
|
||
return function(array, predicate, context) {
|
||
predicate = cb(predicate, context);
|
||
var length = getLength(array);
|
||
var index = dir > 0 ? 0 : length - 1;
|
||
for (; index >= 0 && index < length; index += dir) {
|
||
if (predicate(array[index], index, array)) return index;
|
||
}
|
||
return -1;
|
||
};
|
||
}
|
||
|
||
// Returns the first index on an array-like that passes a predicate test
|
||
_.findIndex = createPredicateIndexFinder(1);
|
||
_.findLastIndex = createPredicateIndexFinder(-1);
|
||
|
||
// Use a comparator function to figure out the smallest index at which
|
||
// an object should be inserted so as to maintain order. Uses binary search.
|
||
_.sortedIndex = function(array, obj, iteratee, context) {
|
||
iteratee = cb(iteratee, context, 1);
|
||
var value = iteratee(obj);
|
||
var low = 0, high = getLength(array);
|
||
while (low < high) {
|
||
var mid = Math.floor((low + high) / 2);
|
||
if (iteratee(array[mid]) < value) low = mid + 1; else high = mid;
|
||
}
|
||
return low;
|
||
};
|
||
|
||
// Generator function to create the indexOf and lastIndexOf functions
|
||
function createIndexFinder(dir, predicateFind, sortedIndex) {
|
||
return function(array, item, idx) {
|
||
var i = 0, length = getLength(array);
|
||
if (typeof idx == 'number') {
|
||
if (dir > 0) {
|
||
i = idx >= 0 ? idx : Math.max(idx + length, i);
|
||
} else {
|
||
length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1;
|
||
}
|
||
} else if (sortedIndex && idx && length) {
|
||
idx = sortedIndex(array, item);
|
||
return array[idx] === item ? idx : -1;
|
||
}
|
||
if (item !== item) {
|
||
idx = predicateFind(slice.call(array, i, length), _.isNaN);
|
||
return idx >= 0 ? idx + i : -1;
|
||
}
|
||
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) {
|
||
if (array[idx] === item) return idx;
|
||
}
|
||
return -1;
|
||
};
|
||
}
|
||
|
||
// Return the position of the first occurrence of an item in an array,
|
||
// or -1 if the item is not included in the array.
|
||
// If the array is large and already in sort order, pass `true`
|
||
// for **isSorted** to use binary search.
|
||
_.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex);
|
||
_.lastIndexOf = createIndexFinder(-1, _.findLastIndex);
|
||
|
||
// Generate an integer Array containing an arithmetic progression. A port of
|
||
// the native Python `range()` function. See
|
||
// [the Python documentation](http://docs.python.org/library/functions.html#range).
|
||
_.range = function(start, stop, step) {
|
||
if (stop == null) {
|
||
stop = start || 0;
|
||
start = 0;
|
||
}
|
||
step = step || 1;
|
||
|
||
var length = Math.max(Math.ceil((stop - start) / step), 0);
|
||
var range = Array(length);
|
||
|
||
for (var idx = 0; idx < length; idx++, start += step) {
|
||
range[idx] = start;
|
||
}
|
||
|
||
return range;
|
||
};
|
||
|
||
// Function (ahem) Functions
|
||
// ------------------
|
||
|
||
// Determines whether to execute a function as a constructor
|
||
// or a normal function with the provided arguments
|
||
var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) {
|
||
if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args);
|
||
var self = baseCreate(sourceFunc.prototype);
|
||
var result = sourceFunc.apply(self, args);
|
||
if (_.isObject(result)) return result;
|
||
return self;
|
||
};
|
||
|
||
// Create a function bound to a given object (assigning `this`, and arguments,
|
||
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if
|
||
// available.
|
||
_.bind = function(func, context) {
|
||
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
|
||
if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function');
|
||
var args = slice.call(arguments, 2);
|
||
var bound = function() {
|
||
return executeBound(func, bound, context, this, args.concat(slice.call(arguments)));
|
||
};
|
||
return bound;
|
||
};
|
||
|
||
// Partially apply a function by creating a version that has had some of its
|
||
// arguments pre-filled, without changing its dynamic `this` context. _ acts
|
||
// as a placeholder, allowing any combination of arguments to be pre-filled.
|
||
_.partial = function(func) {
|
||
var boundArgs = slice.call(arguments, 1);
|
||
var bound = function() {
|
||
var position = 0, length = boundArgs.length;
|
||
var args = Array(length);
|
||
for (var i = 0; i < length; i++) {
|
||
args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i];
|
||
}
|
||
while (position < arguments.length) args.push(arguments[position++]);
|
||
return executeBound(func, bound, this, this, args);
|
||
};
|
||
return bound;
|
||
};
|
||
|
||
// Bind a number of an object's methods to that object. Remaining arguments
|
||
// are the method names to be bound. Useful for ensuring that all callbacks
|
||
// defined on an object belong to it.
|
||
_.bindAll = function(obj) {
|
||
var i, length = arguments.length, key;
|
||
if (length <= 1) throw new Error('bindAll must be passed function names');
|
||
for (i = 1; i < length; i++) {
|
||
key = arguments[i];
|
||
obj[key] = _.bind(obj[key], obj);
|
||
}
|
||
return obj;
|
||
};
|
||
|
||
// Memoize an expensive function by storing its results.
|
||
_.memoize = function(func, hasher) {
|
||
var memoize = function(key) {
|
||
var cache = memoize.cache;
|
||
var address = '' + (hasher ? hasher.apply(this, arguments) : key);
|
||
if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
|
||
return cache[address];
|
||
};
|
||
memoize.cache = {};
|
||
return memoize;
|
||
};
|
||
|
||
// Delays a function for the given number of milliseconds, and then calls
|
||
// it with the arguments supplied.
|
||
_.delay = function(func, wait) {
|
||
var args = slice.call(arguments, 2);
|
||
return setTimeout(function(){
|
||
return func.apply(null, args);
|
||
}, wait);
|
||
};
|
||
|
||
// Defers a function, scheduling it to run after the current call stack has
|
||
// cleared.
|
||
_.defer = _.partial(_.delay, _, 1);
|
||
|
||
// Returns a function, that, when invoked, will only be triggered at most once
|
||
// during a given window of time. Normally, the throttled function will run
|
||
// as much as it can, without ever going more than once per `wait` duration;
|
||
// but if you'd like to disable the execution on the leading edge, pass
|
||
// `{leading: false}`. To disable execution on the trailing edge, ditto.
|
||
_.throttle = function(func, wait, options) {
|
||
var context, args, result;
|
||
var timeout = null;
|
||
var previous = 0;
|
||
if (!options) options = {};
|
||
var later = function() {
|
||
previous = options.leading === false ? 0 : _.now();
|
||
timeout = null;
|
||
result = func.apply(context, args);
|
||
if (!timeout) context = args = null;
|
||
};
|
||
return function() {
|
||
var now = _.now();
|
||
if (!previous && options.leading === false) previous = now;
|
||
var remaining = wait - (now - previous);
|
||
context = this;
|
||
args = arguments;
|
||
if (remaining <= 0 || remaining > wait) {
|
||
if (timeout) {
|
||
clearTimeout(timeout);
|
||
timeout = null;
|
||
}
|
||
previous = now;
|
||
result = func.apply(context, args);
|
||
if (!timeout) context = args = null;
|
||
} else if (!timeout && options.trailing !== false) {
|
||
timeout = setTimeout(later, remaining);
|
||
}
|
||
return result;
|
||
};
|
||
};
|
||
|
||
// Returns a function, that, as long as it continues to be invoked, will not
|
||
// be triggered. The function will be called after it stops being called for
|
||
// N milliseconds. If `immediate` is passed, trigger the function on the
|
||
// leading edge, instead of the trailing.
|
||
_.debounce = function(func, wait, immediate) {
|
||
var timeout, args, context, timestamp, result;
|
||
|
||
var later = function() {
|
||
var last = _.now() - timestamp;
|
||
|
||
if (last < wait && last >= 0) {
|
||
timeout = setTimeout(later, wait - last);
|
||
} else {
|
||
timeout = null;
|
||
if (!immediate) {
|
||
result = func.apply(context, args);
|
||
if (!timeout) context = args = null;
|
||
}
|
||
}
|
||
};
|
||
|
||
return function() {
|
||
context = this;
|
||
args = arguments;
|
||
timestamp = _.now();
|
||
var callNow = immediate && !timeout;
|
||
if (!timeout) timeout = setTimeout(later, wait);
|
||
if (callNow) {
|
||
result = func.apply(context, args);
|
||
context = args = null;
|
||
}
|
||
|
||
return result;
|
||
};
|
||
};
|
||
|
||
// Returns the first function passed as an argument to the second,
|
||
// allowing you to adjust arguments, run code before and after, and
|
||
// conditionally execute the original function.
|
||
_.wrap = function(func, wrapper) {
|
||
return _.partial(wrapper, func);
|
||
};
|
||
|
||
// Returns a negated version of the passed-in predicate.
|
||
_.negate = function(predicate) {
|
||
return function() {
|
||
return !predicate.apply(this, arguments);
|
||
};
|
||
};
|
||
|
||
// Returns a function that is the composition of a list of functions, each
|
||
// consuming the return value of the function that follows.
|
||
_.compose = function() {
|
||
var args = arguments;
|
||
var start = args.length - 1;
|
||
return function() {
|
||
var i = start;
|
||
var result = args[start].apply(this, arguments);
|
||
while (i--) result = args[i].call(this, result);
|
||
return result;
|
||
};
|
||
};
|
||
|
||
// Returns a function that will only be executed on and after the Nth call.
|
||
_.after = function(times, func) {
|
||
return function() {
|
||
if (--times < 1) {
|
||
return func.apply(this, arguments);
|
||
}
|
||
};
|
||
};
|
||
|
||
// Returns a function that will only be executed up to (but not including) the Nth call.
|
||
_.before = function(times, func) {
|
||
var memo;
|
||
return function() {
|
||
if (--times > 0) {
|
||
memo = func.apply(this, arguments);
|
||
}
|
||
if (times <= 1) func = null;
|
||
return memo;
|
||
};
|
||
};
|
||
|
||
// Returns a function that will be executed at most one time, no matter how
|
||
// often you call it. Useful for lazy initialization.
|
||
_.once = _.partial(_.before, 2);
|
||
|
||
// Object Functions
|
||
// ----------------
|
||
|
||
// Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed.
|
||
var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString');
|
||
var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString',
|
||
'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString'];
|
||
|
||
function collectNonEnumProps(obj, keys) {
|
||
var nonEnumIdx = nonEnumerableProps.length;
|
||
var constructor = obj.constructor;
|
||
var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto;
|
||
|
||
// Constructor is a special case.
|
||
var prop = 'constructor';
|
||
if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop);
|
||
|
||
while (nonEnumIdx--) {
|
||
prop = nonEnumerableProps[nonEnumIdx];
|
||
if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) {
|
||
keys.push(prop);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Retrieve the names of an object's own properties.
|
||
// Delegates to **ECMAScript 5**'s native `Object.keys`
|
||
_.keys = function(obj) {
|
||
if (!_.isObject(obj)) return [];
|
||
if (nativeKeys) return nativeKeys(obj);
|
||
var keys = [];
|
||
for (var key in obj) if (_.has(obj, key)) keys.push(key);
|
||
// Ahem, IE < 9.
|
||
if (hasEnumBug) collectNonEnumProps(obj, keys);
|
||
return keys;
|
||
};
|
||
|
||
// Retrieve all the property names of an object.
|
||
_.allKeys = function(obj) {
|
||
if (!_.isObject(obj)) return [];
|
||
var keys = [];
|
||
for (var key in obj) keys.push(key);
|
||
// Ahem, IE < 9.
|
||
if (hasEnumBug) collectNonEnumProps(obj, keys);
|
||
return keys;
|
||
};
|
||
|
||
// Retrieve the values of an object's properties.
|
||
_.values = function(obj) {
|
||
var keys = _.keys(obj);
|
||
var length = keys.length;
|
||
var values = Array(length);
|
||
for (var i = 0; i < length; i++) {
|
||
values[i] = obj[keys[i]];
|
||
}
|
||
return values;
|
||
};
|
||
|
||
// Returns the results of applying the iteratee to each element of the object
|
||
// In contrast to _.map it returns an object
|
||
_.mapObject = function(obj, iteratee, context) {
|
||
iteratee = cb(iteratee, context);
|
||
var keys = _.keys(obj),
|
||
length = keys.length,
|
||
results = {},
|
||
currentKey;
|
||
for (var index = 0; index < length; index++) {
|
||
currentKey = keys[index];
|
||
results[currentKey] = iteratee(obj[currentKey], currentKey, obj);
|
||
}
|
||
return results;
|
||
};
|
||
|
||
// Convert an object into a list of `[key, value]` pairs.
|
||
_.pairs = function(obj) {
|
||
var keys = _.keys(obj);
|
||
var length = keys.length;
|
||
var pairs = Array(length);
|
||
for (var i = 0; i < length; i++) {
|
||
pairs[i] = [keys[i], obj[keys[i]]];
|
||
}
|
||
return pairs;
|
||
};
|
||
|
||
// Invert the keys and values of an object. The values must be serializable.
|
||
_.invert = function(obj) {
|
||
var result = {};
|
||
var keys = _.keys(obj);
|
||
for (var i = 0, length = keys.length; i < length; i++) {
|
||
result[obj[keys[i]]] = keys[i];
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Return a sorted list of the function names available on the object.
|
||
// Aliased as `methods`
|
||
_.functions = _.methods = function(obj) {
|
||
var names = [];
|
||
for (var key in obj) {
|
||
if (_.isFunction(obj[key])) names.push(key);
|
||
}
|
||
return names.sort();
|
||
};
|
||
|
||
// Extend a given object with all the properties in passed-in object(s).
|
||
_.extend = createAssigner(_.allKeys);
|
||
|
||
// Assigns a given object with all the own properties in the passed-in object(s)
|
||
// (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
|
||
_.extendOwn = _.assign = createAssigner(_.keys);
|
||
|
||
// Returns the first key on an object that passes a predicate test
|
||
_.findKey = function(obj, predicate, context) {
|
||
predicate = cb(predicate, context);
|
||
var keys = _.keys(obj), key;
|
||
for (var i = 0, length = keys.length; i < length; i++) {
|
||
key = keys[i];
|
||
if (predicate(obj[key], key, obj)) return key;
|
||
}
|
||
};
|
||
|
||
// Return a copy of the object only containing the whitelisted properties.
|
||
_.pick = function(object, oiteratee, context) {
|
||
var result = {}, obj = object, iteratee, keys;
|
||
if (obj == null) return result;
|
||
if (_.isFunction(oiteratee)) {
|
||
keys = _.allKeys(obj);
|
||
iteratee = optimizeCb(oiteratee, context);
|
||
} else {
|
||
keys = flatten(arguments, false, false, 1);
|
||
iteratee = function(value, key, obj) { return key in obj; };
|
||
obj = Object(obj);
|
||
}
|
||
for (var i = 0, length = keys.length; i < length; i++) {
|
||
var key = keys[i];
|
||
var value = obj[key];
|
||
if (iteratee(value, key, obj)) result[key] = value;
|
||
}
|
||
return result;
|
||
};
|
||
|
||
// Return a copy of the object without the blacklisted properties.
|
||
_.omit = function(obj, iteratee, context) {
|
||
if (_.isFunction(iteratee)) {
|
||
iteratee = _.negate(iteratee);
|
||
} else {
|
||
var keys = _.map(flatten(arguments, false, false, 1), String);
|
||
iteratee = function(value, key) {
|
||
return !_.contains(keys, key);
|
||
};
|
||
}
|
||
return _.pick(obj, iteratee, context);
|
||
};
|
||
|
||
// Fill in a given object with default properties.
|
||
_.defaults = createAssigner(_.allKeys, true);
|
||
|
||
// Creates an object that inherits from the given prototype object.
|
||
// If additional properties are provided then they will be added to the
|
||
// created object.
|
||
_.create = function(prototype, props) {
|
||
var result = baseCreate(prototype);
|
||
if (props) _.extendOwn(result, props);
|
||
return result;
|
||
};
|
||
|
||
// Create a (shallow-cloned) duplicate of an object.
|
||
_.clone = function(obj) {
|
||
if (!_.isObject(obj)) return obj;
|
||
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
|
||
};
|
||
|
||
// Invokes interceptor with the obj, and then returns obj.
|
||
// The primary purpose of this method is to "tap into" a method chain, in
|
||
// order to perform operations on intermediate results within the chain.
|
||
_.tap = function(obj, interceptor) {
|
||
interceptor(obj);
|
||
return obj;
|
||
};
|
||
|
||
// Returns whether an object has a given set of `key:value` pairs.
|
||
_.isMatch = function(object, attrs) {
|
||
var keys = _.keys(attrs), length = keys.length;
|
||
if (object == null) return !length;
|
||
var obj = Object(object);
|
||
for (var i = 0; i < length; i++) {
|
||
var key = keys[i];
|
||
if (attrs[key] !== obj[key] || !(key in obj)) return false;
|
||
}
|
||
return true;
|
||
};
|
||
|
||
|
||
// Internal recursive comparison function for `isEqual`.
|
||
var eq = function(a, b, aStack, bStack) {
|
||
// Identical objects are equal. `0 === -0`, but they aren't identical.
|
||
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
|
||
if (a === b) return a !== 0 || 1 / a === 1 / b;
|
||
// A strict comparison is necessary because `null == undefined`.
|
||
if (a == null || b == null) return a === b;
|
||
// Unwrap any wrapped objects.
|
||
if (a instanceof _) a = a._wrapped;
|
||
if (b instanceof _) b = b._wrapped;
|
||
// Compare `[[Class]]` names.
|
||
var className = toString.call(a);
|
||
if (className !== toString.call(b)) return false;
|
||
switch (className) {
|
||
// Strings, numbers, regular expressions, dates, and booleans are compared by value.
|
||
case '[object RegExp]':
|
||
// RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i')
|
||
case '[object String]':
|
||
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
|
||
// equivalent to `new String("5")`.
|
||
return '' + a === '' + b;
|
||
case '[object Number]':
|
||
// `NaN`s are equivalent, but non-reflexive.
|
||
// Object(NaN) is equivalent to NaN
|
||
if (+a !== +a) return +b !== +b;
|
||
// An `egal` comparison is performed for other numeric values.
|
||
return +a === 0 ? 1 / +a === 1 / b : +a === +b;
|
||
case '[object Date]':
|
||
case '[object Boolean]':
|
||
// Coerce dates and booleans to numeric primitive values. Dates are compared by their
|
||
// millisecond representations. Note that invalid dates with millisecond representations
|
||
// of `NaN` are not equivalent.
|
||
return +a === +b;
|
||
}
|
||
|
||
var areArrays = className === '[object Array]';
|
||
if (!areArrays) {
|
||
if (typeof a != 'object' || typeof b != 'object') return false;
|
||
|
||
// Objects with different constructors are not equivalent, but `Object`s or `Array`s
|
||
// from different frames are.
|
||
var aCtor = a.constructor, bCtor = b.constructor;
|
||
if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor &&
|
||
_.isFunction(bCtor) && bCtor instanceof bCtor)
|
||
&& ('constructor' in a && 'constructor' in b)) {
|
||
return false;
|
||
}
|
||
}
|
||
// Assume equality for cyclic structures. The algorithm for detecting cyclic
|
||
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
|
||
|
||
// Initializing stack of traversed objects.
|
||
// It's done here since we only need them for objects and arrays comparison.
|
||
aStack = aStack || [];
|
||
bStack = bStack || [];
|
||
var length = aStack.length;
|
||
while (length--) {
|
||
// Linear search. Performance is inversely proportional to the number of
|
||
// unique nested structures.
|
||
if (aStack[length] === a) return bStack[length] === b;
|
||
}
|
||
|
||
// Add the first object to the stack of traversed objects.
|
||
aStack.push(a);
|
||
bStack.push(b);
|
||
|
||
// Recursively compare objects and arrays.
|
||
if (areArrays) {
|
||
// Compare array lengths to determine if a deep comparison is necessary.
|
||
length = a.length;
|
||
if (length !== b.length) return false;
|
||
// Deep compare the contents, ignoring non-numeric properties.
|
||
while (length--) {
|
||
if (!eq(a[length], b[length], aStack, bStack)) return false;
|
||
}
|
||
} else {
|
||
// Deep compare objects.
|
||
var keys = _.keys(a), key;
|
||
length = keys.length;
|
||
// Ensure that both objects contain the same number of properties before comparing deep equality.
|
||
if (_.keys(b).length !== length) return false;
|
||
while (length--) {
|
||
// Deep compare each member
|
||
key = keys[length];
|
||
if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false;
|
||
}
|
||
}
|
||
// Remove the first object from the stack of traversed objects.
|
||
aStack.pop();
|
||
bStack.pop();
|
||
return true;
|
||
};
|
||
|
||
// Perform a deep comparison to check if two objects are equal.
|
||
_.isEqual = function(a, b) {
|
||
return eq(a, b);
|
||
};
|
||
|
||
// Is a given array, string, or object empty?
|
||
// An "empty" object has no enumerable own-properties.
|
||
_.isEmpty = function(obj) {
|
||
if (obj == null) return true;
|
||
if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0;
|
||
return _.keys(obj).length === 0;
|
||
};
|
||
|
||
// Is a given value a DOM element?
|
||
_.isElement = function(obj) {
|
||
return !!(obj && obj.nodeType === 1);
|
||
};
|
||
|
||
// Is a given value an array?
|
||
// Delegates to ECMA5's native Array.isArray
|
||
_.isArray = nativeIsArray || function(obj) {
|
||
return toString.call(obj) === '[object Array]';
|
||
};
|
||
|
||
// Is a given variable an object?
|
||
_.isObject = function(obj) {
|
||
var type = typeof obj;
|
||
return type === 'function' || type === 'object' && !!obj;
|
||
};
|
||
|
||
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError.
|
||
_.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) {
|
||
_['is' + name] = function(obj) {
|
||
return toString.call(obj) === '[object ' + name + ']';
|
||
};
|
||
});
|
||
|
||
// Define a fallback version of the method in browsers (ahem, IE < 9), where
|
||
// there isn't any inspectable "Arguments" type.
|
||
if (!_.isArguments(arguments)) {
|
||
_.isArguments = function(obj) {
|
||
return _.has(obj, 'callee');
|
||
};
|
||
}
|
||
|
||
// Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8,
|
||
// IE 11 (#1621), and in Safari 8 (#1929).
|
||
if (typeof /./ != 'function' && typeof Int8Array != 'object') {
|
||
_.isFunction = function(obj) {
|
||
return typeof obj == 'function' || false;
|
||
};
|
||
}
|
||
|
||
// Is a given object a finite number?
|
||
_.isFinite = function(obj) {
|
||
return isFinite(obj) && !isNaN(parseFloat(obj));
|
||
};
|
||
|
||
// Is the given value `NaN`? (NaN is the only number which does not equal itself).
|
||
_.isNaN = function(obj) {
|
||
return _.isNumber(obj) && obj !== +obj;
|
||
};
|
||
|
||
// Is a given value a boolean?
|
||
_.isBoolean = function(obj) {
|
||
return obj === true || obj === false || toString.call(obj) === '[object Boolean]';
|
||
};
|
||
|
||
// Is a given value equal to null?
|
||
_.isNull = function(obj) {
|
||
return obj === null;
|
||
};
|
||
|
||
// Is a given variable undefined?
|
||
_.isUndefined = function(obj) {
|
||
return obj === void 0;
|
||
};
|
||
|
||
// Shortcut function for checking if an object has a given property directly
|
||
// on itself (in other words, not on a prototype).
|
||
_.has = function(obj, key) {
|
||
return obj != null && hasOwnProperty.call(obj, key);
|
||
};
|
||
|
||
// Utility Functions
|
||
// -----------------
|
||
|
||
// Run Underscore.js in *noConflict* mode, returning the `_` variable to its
|
||
// previous owner. Returns a reference to the Underscore object.
|
||
_.noConflict = function() {
|
||
root._ = previousUnderscore;
|
||
return this;
|
||
};
|
||
|
||
// Keep the identity function around for default iteratees.
|
||
_.identity = function(value) {
|
||
return value;
|
||
};
|
||
|
||
// Predicate-generating functions. Often useful outside of Underscore.
|
||
_.constant = function(value) {
|
||
return function() {
|
||
return value;
|
||
};
|
||
};
|
||
|
||
_.noop = function(){};
|
||
|
||
_.property = property;
|
||
|
||
// Generates a function for a given object that returns a given property.
|
||
_.propertyOf = function(obj) {
|
||
return obj == null ? function(){} : function(key) {
|
||
return obj[key];
|
||
};
|
||
};
|
||
|
||
// Returns a predicate for checking whether an object has a given set of
|
||
// `key:value` pairs.
|
||
_.matcher = _.matches = function(attrs) {
|
||
attrs = _.extendOwn({}, attrs);
|
||
return function(obj) {
|
||
return _.isMatch(obj, attrs);
|
||
};
|
||
};
|
||
|
||
// Run a function **n** times.
|
||
_.times = function(n, iteratee, context) {
|
||
var accum = Array(Math.max(0, n));
|
||
iteratee = optimizeCb(iteratee, context, 1);
|
||
for (var i = 0; i < n; i++) accum[i] = iteratee(i);
|
||
return accum;
|
||
};
|
||
|
||
// Return a random integer between min and max (inclusive).
|
||
_.random = function(min, max) {
|
||
if (max == null) {
|
||
max = min;
|
||
min = 0;
|
||
}
|
||
return min + Math.floor(Math.random() * (max - min + 1));
|
||
};
|
||
|
||
// A (possibly faster) way to get the current timestamp as an integer.
|
||
_.now = Date.now || function() {
|
||
return new Date().getTime();
|
||
};
|
||
|
||
// List of HTML entities for escaping.
|
||
var escapeMap = {
|
||
'&': '&',
|
||
'<': '<',
|
||
'>': '>',
|
||
'"': '"',
|
||
"'": ''',
|
||
'`': '`'
|
||
};
|
||
var unescapeMap = _.invert(escapeMap);
|
||
|
||
// Functions for escaping and unescaping strings to/from HTML interpolation.
|
||
var createEscaper = function(map) {
|
||
var escaper = function(match) {
|
||
return map[match];
|
||
};
|
||
// Regexes for identifying a key that needs to be escaped
|
||
var source = '(?:' + _.keys(map).join('|') + ')';
|
||
var testRegexp = RegExp(source);
|
||
var replaceRegexp = RegExp(source, 'g');
|
||
return function(string) {
|
||
string = string == null ? '' : '' + string;
|
||
return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string;
|
||
};
|
||
};
|
||
_.escape = createEscaper(escapeMap);
|
||
_.unescape = createEscaper(unescapeMap);
|
||
|
||
// If the value of the named `property` is a function then invoke it with the
|
||
// `object` as context; otherwise, return it.
|
||
_.result = function(object, property, fallback) {
|
||
var value = object == null ? void 0 : object[property];
|
||
if (value === void 0) {
|
||
value = fallback;
|
||
}
|
||
return _.isFunction(value) ? value.call(object) : value;
|
||
};
|
||
|
||
// Generate a unique integer id (unique within the entire client session).
|
||
// Useful for temporary DOM ids.
|
||
var idCounter = 0;
|
||
_.uniqueId = function(prefix) {
|
||
var id = ++idCounter + '';
|
||
return prefix ? prefix + id : id;
|
||
};
|
||
|
||
// By default, Underscore uses ERB-style template delimiters, change the
|
||
// following template settings to use alternative delimiters.
|
||
_.templateSettings = {
|
||
evaluate : /<%([\s\S]+?)%>/g,
|
||
interpolate : /<%=([\s\S]+?)%>/g,
|
||
escape : /<%-([\s\S]+?)%>/g
|
||
};
|
||
|
||
// When customizing `templateSettings`, if you don't want to define an
|
||
// interpolation, evaluation or escaping regex, we need one that is
|
||
// guaranteed not to match.
|
||
var noMatch = /(.)^/;
|
||
|
||
// Certain characters need to be escaped so that they can be put into a
|
||
// string literal.
|
||
var escapes = {
|
||
"'": "'",
|
||
'\\': '\\',
|
||
'\r': 'r',
|
||
'\n': 'n',
|
||
'\u2028': 'u2028',
|
||
'\u2029': 'u2029'
|
||
};
|
||
|
||
var escaper = /\\|'|\r|\n|\u2028|\u2029/g;
|
||
|
||
var escapeChar = function(match) {
|
||
return '\\' + escapes[match];
|
||
};
|
||
|
||
// JavaScript micro-templating, similar to John Resig's implementation.
|
||
// Underscore templating handles arbitrary delimiters, preserves whitespace,
|
||
// and correctly escapes quotes within interpolated code.
|
||
// NB: `oldSettings` only exists for backwards compatibility.
|
||
_.template = function(text, settings, oldSettings) {
|
||
if (!settings && oldSettings) settings = oldSettings;
|
||
settings = _.defaults({}, settings, _.templateSettings);
|
||
|
||
// Combine delimiters into one regular expression via alternation.
|
||
var matcher = RegExp([
|
||
(settings.escape || noMatch).source,
|
||
(settings.interpolate || noMatch).source,
|
||
(settings.evaluate || noMatch).source
|
||
].join('|') + '|$', 'g');
|
||
|
||
// Compile the template source, escaping string literals appropriately.
|
||
var index = 0;
|
||
var source = "__p+='";
|
||
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
|
||
source += text.slice(index, offset).replace(escaper, escapeChar);
|
||
index = offset + match.length;
|
||
|
||
if (escape) {
|
||
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'";
|
||
} else if (interpolate) {
|
||
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'";
|
||
} else if (evaluate) {
|
||
source += "';\n" + evaluate + "\n__p+='";
|
||
}
|
||
|
||
// Adobe VMs need the match returned to produce the correct offest.
|
||
return match;
|
||
});
|
||
source += "';\n";
|
||
|
||
// If a variable is not specified, place data values in local scope.
|
||
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
|
||
|
||
source = "var __t,__p='',__j=Array.prototype.join," +
|
||
"print=function(){__p+=__j.call(arguments,'');};\n" +
|
||
source + 'return __p;\n';
|
||
|
||
try {
|
||
var render = new Function(settings.variable || 'obj', '_', source);
|
||
} catch (e) {
|
||
e.source = source;
|
||
throw e;
|
||
}
|
||
|
||
var template = function(data) {
|
||
return render.call(this, data, _);
|
||
};
|
||
|
||
// Provide the compiled source as a convenience for precompilation.
|
||
var argument = settings.variable || 'obj';
|
||
template.source = 'function(' + argument + '){\n' + source + '}';
|
||
|
||
return template;
|
||
};
|
||
|
||
// Add a "chain" function. Start chaining a wrapped Underscore object.
|
||
_.chain = function(obj) {
|
||
var instance = _(obj);
|
||
instance._chain = true;
|
||
return instance;
|
||
};
|
||
|
||
// OOP
|
||
// ---------------
|
||
// If Underscore is called as a function, it returns a wrapped object that
|
||
// can be used OO-style. This wrapper holds altered versions of all the
|
||
// underscore functions. Wrapped objects may be chained.
|
||
|
||
// Helper function to continue chaining intermediate results.
|
||
var result = function(instance, obj) {
|
||
return instance._chain ? _(obj).chain() : obj;
|
||
};
|
||
|
||
// Add your own custom functions to the Underscore object.
|
||
_.mixin = function(obj) {
|
||
_.each(_.functions(obj), function(name) {
|
||
var func = _[name] = obj[name];
|
||
_.prototype[name] = function() {
|
||
var args = [this._wrapped];
|
||
push.apply(args, arguments);
|
||
return result(this, func.apply(_, args));
|
||
};
|
||
});
|
||
};
|
||
|
||
// Add all of the Underscore functions to the wrapper object.
|
||
_.mixin(_);
|
||
|
||
// Add all mutator Array functions to the wrapper.
|
||
_.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
||
var method = ArrayProto[name];
|
||
_.prototype[name] = function() {
|
||
var obj = this._wrapped;
|
||
method.apply(obj, arguments);
|
||
if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0];
|
||
return result(this, obj);
|
||
};
|
||
});
|
||
|
||
// Add all accessor Array functions to the wrapper.
|
||
_.each(['concat', 'join', 'slice'], function(name) {
|
||
var method = ArrayProto[name];
|
||
_.prototype[name] = function() {
|
||
return result(this, method.apply(this._wrapped, arguments));
|
||
};
|
||
});
|
||
|
||
// Extracts the result from a wrapped and chained object.
|
||
_.prototype.value = function() {
|
||
return this._wrapped;
|
||
};
|
||
|
||
// Provide unwrapping proxy for some methods used in engine operations
|
||
// such as arithmetic and JSON stringification.
|
||
_.prototype.valueOf = _.prototype.toJSON = _.prototype.value;
|
||
|
||
_.prototype.toString = function() {
|
||
return '' + this._wrapped;
|
||
};
|
||
|
||
// AMD registration happens at the end for compatibility with AMD loaders
|
||
// that may not enforce next-turn semantics on modules. Even though general
|
||
// practice for AMD registration is to be anonymous, underscore registers
|
||
// as a named module because, like jQuery, it is a base library that is
|
||
// popular enough to be bundled in a third party lib, but not be part of
|
||
// an AMD load request. Those cases could generate an error when an
|
||
// anonymous define() is called outside of a loader request.
|
||
if (typeof define === 'function' && define.amd) {
|
||
define('underscore', [], function() {
|
||
return _;
|
||
});
|
||
}
|
||
}.call(this));
|
||
|
||
},{}],84:[function(require,module,exports){
|
||
var Connector, Test, Y, chai, expect, sinon, sinonChai, _,
|
||
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||
|
||
chai = require('chai');
|
||
|
||
expect = chai.expect;
|
||
|
||
sinon = require('sinon');
|
||
|
||
sinonChai = require('sinon-chai');
|
||
|
||
_ = require("underscore");
|
||
|
||
chai.use(sinonChai);
|
||
|
||
Connector = require("../../y-test/lib/y-test.coffee");
|
||
|
||
Y = null;
|
||
|
||
module.exports = Test = (function() {
|
||
function Test(name_suffix, Yjs) {
|
||
var gf, t, _i, _j, _len, _len1, _ref, _ref1;
|
||
this.name_suffix = name_suffix != null ? name_suffix : "";
|
||
this.applyRandomOp = __bind(this.applyRandomOp, this);
|
||
this.generateRandomOp = __bind(this.generateRandomOp, this);
|
||
this.getGeneratingFunctions = __bind(this.getGeneratingFunctions, this);
|
||
Y = Yjs;
|
||
this.number_of_test_cases_multiplier = 1;
|
||
this.repeat_this = 1 * this.number_of_test_cases_multiplier;
|
||
this.doSomething_amount = 123 * this.number_of_test_cases_multiplier;
|
||
this.number_of_engines = 5 + this.number_of_test_cases_multiplier - 1;
|
||
this.time = 0;
|
||
this.ops = 0;
|
||
this.time_now = 0;
|
||
this.max_depth = 3;
|
||
this.debug = false;
|
||
this.reinitialize();
|
||
_ref = this.getGeneratingFunctions(0);
|
||
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
|
||
gf = _ref[_i];
|
||
if (!((gf.types != null) && (gf.f != null))) {
|
||
throw new Error("Generating Functions are not initialized properly!");
|
||
}
|
||
_ref1 = gf.types;
|
||
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
|
||
t = _ref1[_j];
|
||
if (t == null) {
|
||
throw new Error("You havent includedt this type in Y (do require 'y-whatever')");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Test.prototype.reinitialize = function() {
|
||
var i, u, user, _i, _j, _len, _ref, _ref1;
|
||
this.users = [];
|
||
for (i = _i = 0, _ref = this.number_of_engines; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
|
||
u = this.makeNewUser(i + this.name_suffix);
|
||
_ref1 = this.users;
|
||
for (_j = 0, _len = _ref1.length; _j < _len; _j++) {
|
||
user = _ref1[_j];
|
||
u._model.connector.join(user._model.connector);
|
||
}
|
||
this.users.push(u);
|
||
}
|
||
if (typeof this.initUsers === "function") {
|
||
this.initUsers(this.users[0]);
|
||
}
|
||
return this.flushAll();
|
||
};
|
||
|
||
Test.prototype.makeNewUser = function(user) {
|
||
user._model.HB.stopGarbageCollection();
|
||
return user;
|
||
};
|
||
|
||
Test.prototype.getSomeUser = function() {
|
||
var i;
|
||
i = _.random(0, this.users.length - 1);
|
||
return this.users[i];
|
||
};
|
||
|
||
Test.prototype.getRandomText = function(chars, min_length) {
|
||
var length, nextchar, text;
|
||
if (min_length == null) {
|
||
min_length = 0;
|
||
}
|
||
if (chars == null) {
|
||
chars = "abcdefghijklmnopqrstuvwxyz";
|
||
}
|
||
length = _.random(min_length, 10);
|
||
nextchar = chars[_.random(0, chars.length - 1)];
|
||
text = "";
|
||
_(length).times(function() {
|
||
return text += nextchar;
|
||
});
|
||
return text;
|
||
};
|
||
|
||
Test.prototype.getRandomObject = function() {
|
||
var key1, key2, result, val1, val2;
|
||
result = {};
|
||
key1 = this.getRandomKey();
|
||
key2 = this.getRandomKey();
|
||
val1 = this.getRandomText();
|
||
val2 = null;
|
||
if (_.random(0, 1) === 1) {
|
||
val2 = this.getRandomObject();
|
||
} else {
|
||
val2 = this.getRandomText();
|
||
}
|
||
result[key1] = val1;
|
||
result[key2] = val2;
|
||
return result;
|
||
};
|
||
|
||
Test.prototype.getRandomKey = function() {
|
||
return this.getRandomText([1, 2, 'x', 'y'], 1);
|
||
};
|
||
|
||
Test.prototype.getGeneratingFunctions = function(user_num) {
|
||
var types;
|
||
types = this.users[user_num]._model.operations;
|
||
return [];
|
||
};
|
||
|
||
Test.prototype.getRandomRoot = function(user_num) {
|
||
throw new Error("implement me!");
|
||
};
|
||
|
||
Test.prototype.compare = function(o1, o2, depth) {
|
||
var i, name, o, val, _i, _j, _len, _len1, _ref, _ref1, _results, _results1, _results2;
|
||
if (depth == null) {
|
||
depth = this.max_depth + 1;
|
||
}
|
||
if (o1 === o2 || depth <= 0) {
|
||
return true;
|
||
} else if ((o1._name != null) && o1._name !== o2._name) {
|
||
throw new Error("different types");
|
||
} else if (o1._model != null) {
|
||
return this.compare(o1._model, o2._model, depth);
|
||
} else if (o1.type === "MapManager") {
|
||
_ref = o1.val();
|
||
_results = [];
|
||
for (name in _ref) {
|
||
val = _ref[name];
|
||
_results.push(this.compare(val, o2.val(name), depth - 1));
|
||
}
|
||
return _results;
|
||
} else if (o1.type === "ListManager") {
|
||
_ref1 = o1.val();
|
||
_results1 = [];
|
||
for (i = _i = 0, _len = _ref1.length; _i < _len; i = ++_i) {
|
||
val = _ref1[i];
|
||
_results1.push(this.compare(val, o2.val(i), depth - 1));
|
||
}
|
||
return _results1;
|
||
} else if (o1.constructor === Array && o2.constructor === Array) {
|
||
if (o1.length !== o2.length) {
|
||
throw new Error("The Arrays do not have the same size!");
|
||
}
|
||
_results2 = [];
|
||
for (i = _j = 0, _len1 = o1.length; _j < _len1; i = ++_j) {
|
||
o = o1[i];
|
||
_results2.push(this.compare(o, o2[i], depth - 1));
|
||
}
|
||
return _results2;
|
||
} else if (o1 !== o2) {
|
||
throw new Error("different values");
|
||
} else {
|
||
throw new Error("I don't know what to do .. ");
|
||
}
|
||
};
|
||
|
||
Test.prototype.generateRandomOp = function(user_num) {
|
||
var choices, i, y;
|
||
y = this.getRandomRoot(user_num);
|
||
choices = this.getGeneratingFunctions(user_num).filter(function(gf) {
|
||
return _.some(gf.types, function(type) {
|
||
return y instanceof type;
|
||
});
|
||
});
|
||
if (choices.length === 0) {
|
||
console.dir(y);
|
||
throw new Error("You forgot to specify a test generation methot for this Operation! (" + y.type + ")");
|
||
}
|
||
i = _.random(0, choices.length - 1);
|
||
return choices[i].f(y);
|
||
};
|
||
|
||
Test.prototype.applyRandomOp = function(user_num) {
|
||
var user;
|
||
user = this.users[user_num];
|
||
return user._model.connector.flushOneRandom();
|
||
};
|
||
|
||
Test.prototype.doSomething = function() {
|
||
var choice, choices, user_num;
|
||
user_num = _.random(this.number_of_engines - 1);
|
||
choices = [this.applyRandomOp, this.generateRandomOp];
|
||
choice = _.random(choices.length - 1);
|
||
return choices[choice](user_num);
|
||
};
|
||
|
||
Test.prototype.flushAll = function(final) {
|
||
var ops, user, user_number, _i, _j, _len, _len1, _ref, _ref1, _results;
|
||
final = false;
|
||
if (this.users.length <= 1 || !final) {
|
||
_ref = this.users;
|
||
_results = [];
|
||
for (user_number = _i = 0, _len = _ref.length; _i < _len; user_number = ++_i) {
|
||
user = _ref[user_number];
|
||
_results.push(user._model.connector.flushAll());
|
||
}
|
||
return _results;
|
||
} else {
|
||
_ref1 = this.users.slice(1);
|
||
for (user_number = _j = 0, _len1 = _ref1.length; _j < _len1; user_number = ++_j) {
|
||
user = _ref1[user_number];
|
||
user._model.connector.flushAll();
|
||
}
|
||
ops = this.users[1].getHistoryBuffer()._encode(this.users[0].HB.getOperationCounter());
|
||
return this.users[0].engine.applyOpsCheckDouble(ops);
|
||
}
|
||
};
|
||
|
||
Test.prototype.compareAll = function(test_number) {
|
||
var i, j, number_of_created_operations, ops, ops_per_msek, printOpsInExecutionOrder, u, _i, _j, _k, _len, _ref, _ref1, _ref2, _results;
|
||
this.flushAll(true);
|
||
this.time += (new Date()).getTime() - this.time_now;
|
||
number_of_created_operations = 0;
|
||
for (i = _i = 0, _ref = this.users.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
|
||
number_of_created_operations += this.users[i]._model.connector.getOpsInExecutionOrder().length;
|
||
}
|
||
this.ops += number_of_created_operations * this.users.length;
|
||
ops_per_msek = Math.floor(this.ops / this.time);
|
||
if (test_number != null) {
|
||
console.log(("" + test_number + "/" + this.repeat_this + ": " + number_of_created_operations + " were created and applied on (" + this.users.length + ") users ops in a different order.") + (" Over all we consumed " + this.ops + " operations in " + (this.time / 1000) + " seconds (" + ops_per_msek + " ops/msek)."));
|
||
}
|
||
_results = [];
|
||
for (i = _j = 0, _ref1 = this.users.length - 1; 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
|
||
if (this.debug) {
|
||
if (!_.isEqual(this.getContent(i), this.getContent(i + 1))) {
|
||
printOpsInExecutionOrder = (function(_this) {
|
||
return function(otnumber, otherotnumber) {
|
||
var j, o, ops, s, _k, _l, _len, _len1;
|
||
ops = _.filter(_this.users[otnumber]._model.connector.getOpsInExecutionOrder(), function(o) {
|
||
return typeof o.uid.op_name !== 'string' && o.uid.creator !== '_';
|
||
});
|
||
for (j = _k = 0, _len = ops.length; _k < _len; j = ++_k) {
|
||
s = ops[j];
|
||
console.log(("op" + j + " = ") + (JSON.stringify(s)));
|
||
}
|
||
console.log("");
|
||
s = "ops = [";
|
||
for (j = _l = 0, _len1 = ops.length; _l < _len1; j = ++_l) {
|
||
o = ops[j];
|
||
if (j !== 0) {
|
||
s += ", ";
|
||
}
|
||
s += "op" + j;
|
||
}
|
||
s += "]";
|
||
console.log(s);
|
||
console.log("@test_user.engine.applyOps ops");
|
||
console.log("expect(@test_user.val('name').val()).to.equal(\"" + (_this.users[otherotnumber].val('name').val()) + "\")");
|
||
return ops;
|
||
};
|
||
})(this);
|
||
console.log("");
|
||
console.log("Found an OT Puzzle!");
|
||
console.log("OT states:");
|
||
_ref2 = this.users;
|
||
for (j = _k = 0, _len = _ref2.length; _k < _len; j = ++_k) {
|
||
u = _ref2[j];
|
||
console.log(("OT" + j + ": ") + u.val('name').val());
|
||
}
|
||
console.log("\nOT execution order (" + i + "," + (i + 1) + "):");
|
||
printOpsInExecutionOrder(i, i + 1);
|
||
console.log("");
|
||
ops = printOpsInExecutionOrder(i + 1, i);
|
||
console.log("");
|
||
}
|
||
}
|
||
_results.push(expect(this.compare(this.users[i], this.users[i + 1])).to.not.be.undefined);
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
Test.prototype.run = function() {
|
||
var i, times, u, _i, _j, _k, _l, _len, _ref, _ref1, _ref2, _ref3, _results;
|
||
if (this.debug) {
|
||
console.log('');
|
||
}
|
||
_results = [];
|
||
for (times = _i = 1, _ref = this.repeat_this; 1 <= _ref ? _i <= _ref : _i >= _ref; times = 1 <= _ref ? ++_i : --_i) {
|
||
this.time_now = (new Date).getTime();
|
||
for (i = _j = 1, _ref1 = Math.floor(this.doSomething_amount / 2); 1 <= _ref1 ? _j <= _ref1 : _j >= _ref1; i = 1 <= _ref1 ? ++_j : --_j) {
|
||
this.doSomething();
|
||
}
|
||
this.flushAll(false);
|
||
_ref2 = this.users;
|
||
for (_k = 0, _len = _ref2.length; _k < _len; _k++) {
|
||
u = _ref2[_k];
|
||
u._model.HB.emptyGarbage();
|
||
}
|
||
for (i = _l = 1, _ref3 = Math.floor(this.doSomething_amount / 2); 1 <= _ref3 ? _l <= _ref3 : _l >= _ref3; i = 1 <= _ref3 ? ++_l : --_l) {
|
||
this.doSomething();
|
||
}
|
||
this.compareAll(times);
|
||
this.testHBencoding();
|
||
if (times !== this.repeat_this) {
|
||
_results.push(this.reinitialize());
|
||
} else {
|
||
_results.push(void 0);
|
||
}
|
||
}
|
||
return _results;
|
||
};
|
||
|
||
Test.prototype.testHBencoding = function() {
|
||
this.users[this.users.length] = this.makeNewUser(-1.);
|
||
this.users[this.users.length - 1]._model.HB.renewStateVector(this.users[0]._model.HB.getOperationCounter());
|
||
this.users[this.users.length - 1]._model.engine.applyOps(this.users[0]._model.HB._encode());
|
||
return expect(this.compare(this.users[this.users.length - 1], this.users[0])).to.not.be.undefined;
|
||
};
|
||
|
||
return Test;
|
||
|
||
})();
|
||
|
||
|
||
},{"../../y-test/lib/y-test.coffee":2,"chai":14,"sinon":56,"sinon-chai":55,"underscore":83}],85:[function(require,module,exports){
|
||
var ObjectTest, TestSuite, Y, chai, expect, should, sinon, sinonChai, _,
|
||
__hasProp = {}.hasOwnProperty,
|
||
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
|
||
|
||
chai = require('chai');
|
||
|
||
expect = chai.expect;
|
||
|
||
should = chai.should();
|
||
|
||
sinon = require('sinon');
|
||
|
||
sinonChai = require('sinon-chai');
|
||
|
||
_ = require("underscore");
|
||
|
||
chai.use(sinonChai);
|
||
|
||
Y = require("../lib/y.coffee");
|
||
|
||
Y.Test = require("../../y-test/lib/y-test.coffee");
|
||
|
||
Y.Text = require("../../y-text/lib/y-text");
|
||
|
||
Y.List = require("../../y-list/lib/y-list");
|
||
|
||
TestSuite = require("./TestSuite");
|
||
|
||
ObjectTest = (function(_super) {
|
||
__extends(ObjectTest, _super);
|
||
|
||
function ObjectTest(suffix) {
|
||
ObjectTest.__super__.constructor.call(this, suffix, Y);
|
||
}
|
||
|
||
ObjectTest.prototype.makeNewUser = function(userId) {
|
||
var conn;
|
||
conn = new Y.Test(userId);
|
||
return ObjectTest.__super__.makeNewUser.call(this, new Y(conn));
|
||
};
|
||
|
||
ObjectTest.prototype.type = "ObjectTest";
|
||
|
||
ObjectTest.prototype.getRandomRoot = function(user_num, root, depth) {
|
||
var elems, oname, p, val;
|
||
if (depth == null) {
|
||
depth = this.max_depth;
|
||
}
|
||
if (root == null) {
|
||
root = this.users[user_num];
|
||
}
|
||
if (depth === 0 || _.random(0, 1) === 1) {
|
||
return root;
|
||
} else {
|
||
depth--;
|
||
elems = null;
|
||
if (root._name === "Object") {
|
||
elems = (function() {
|
||
var _ref, _results;
|
||
_ref = root.val();
|
||
_results = [];
|
||
for (oname in _ref) {
|
||
val = _ref[oname];
|
||
_results.push(val);
|
||
}
|
||
return _results;
|
||
})();
|
||
} else if (root._name === "Array") {
|
||
elems = root.val();
|
||
} else {
|
||
return root;
|
||
}
|
||
elems = elems.filter(function(elem) {
|
||
return (elem != null) && ((elem._name === "Array") || (elem._name === "Object"));
|
||
});
|
||
if (elems.length === 0) {
|
||
return root;
|
||
} else {
|
||
p = elems[_.random(0, elems.length - 1)];
|
||
return this.getRandomRoot(user_num, p, depth);
|
||
}
|
||
}
|
||
};
|
||
|
||
ObjectTest.prototype.getGeneratingFunctions = function(user_num) {
|
||
return ObjectTest.__super__.getGeneratingFunctions.call(this, user_num).concat([
|
||
{
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var key, list, name, o;
|
||
list = (function() {
|
||
var _ref, _results;
|
||
_ref = y.val();
|
||
_results = [];
|
||
for (name in _ref) {
|
||
o = _ref[name];
|
||
_results.push(name);
|
||
}
|
||
return _results;
|
||
})();
|
||
if (list.length > 0) {
|
||
key = list[_.random(0, list.length - 1)];
|
||
return y["delete"](key);
|
||
}
|
||
};
|
||
})(this),
|
||
types: [Y.Object]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
return y.val(_this.getRandomKey(), new Y.Object(_this.getRandomObject()));
|
||
};
|
||
})(this),
|
||
types: [Y.Object]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
return y.val(_this.getRandomKey(), new Y.Text(_this.getRandomText()));
|
||
};
|
||
})(this),
|
||
types: [Y.Object]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
return y.val(_this.getRandomKey(), new Y.List(_this.getRandomText().split("")));
|
||
};
|
||
})(this),
|
||
types: [Y.Object]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var i, list;
|
||
list = y.val();
|
||
if (list.length > 0) {
|
||
i = _.random(0, list.length - 1);
|
||
return y["delete"](i);
|
||
}
|
||
};
|
||
})(this),
|
||
types: [Y.List]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var l;
|
||
l = y.val().length;
|
||
return y.insert(_.random(0, l - 1), new Y.Object(_this.getRandomObject()));
|
||
};
|
||
})(this),
|
||
types: [Y.List]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var l;
|
||
l = y.val().length;
|
||
return y.insert(_.random(0, l - 1), new Y.Text(_this.getRandomText()));
|
||
};
|
||
})(this),
|
||
types: [Y.List]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var l;
|
||
l = y.val().length;
|
||
return y.insert(_.random(0, l - 1), new Y.List(_this.getRandomText().split("")));
|
||
};
|
||
})(this),
|
||
types: [Y.List]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var l;
|
||
l = y.val().length;
|
||
return y.insert(_.random(0, l - 1), _.random(0, 42));
|
||
};
|
||
})(this),
|
||
types: [Y.List]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
return y.val(_this.getRandomKey(), _this.getRandomRoot(user_num));
|
||
};
|
||
})(this),
|
||
types: [Y.Object]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
var l;
|
||
l = y.val().length;
|
||
return y.insert(_.random(0, l - 1), _this.getRandomRoot(user_num));
|
||
};
|
||
})(this),
|
||
types: [Y.List]
|
||
}, {
|
||
f: (function(_this) {
|
||
return function(y) {
|
||
y;
|
||
var pos;
|
||
pos = _.random(0, y.val().length - 1);
|
||
y.insert(pos, _this.getRandomText());
|
||
return null;
|
||
};
|
||
})(this),
|
||
types: [Y.Text]
|
||
}, {
|
||
f: function(y) {
|
||
var length, ops1, pos;
|
||
if (y.val().length > 0) {
|
||
pos = _.random(0, y.val().length - 1);
|
||
length = _.random(0, y.val().length - pos);
|
||
ops1 = y["delete"](pos, length);
|
||
}
|
||
return void 0;
|
||
},
|
||
types: [Y.Text]
|
||
}
|
||
]);
|
||
};
|
||
|
||
return ObjectTest;
|
||
|
||
})(TestSuite);
|
||
|
||
module.exports = ObjectTest;
|
||
|
||
describe("Object Test", function() {
|
||
this.timeout(500000);
|
||
beforeEach(function(done) {
|
||
this.yTest = new ObjectTest();
|
||
this.users = this.yTest.users;
|
||
this.test_user = this.yTest.makeNewUser("test_user");
|
||
return done();
|
||
});
|
||
it("can handle many engines, many operations, concurrently (random)", function() {
|
||
console.log("");
|
||
return this.yTest.run();
|
||
});
|
||
it("has a working test suite", function() {
|
||
return this.yTest.compareAll();
|
||
});
|
||
it("handles double-late-join", function() {
|
||
var ops1, ops2, test, u1, u2;
|
||
test = new ObjectTest("double");
|
||
test.run();
|
||
this.yTest.run();
|
||
u1 = test.users[0];
|
||
u2 = this.yTest.users[1];
|
||
ops1 = u1._model.HB._encode();
|
||
ops2 = u2._model.HB._encode();
|
||
u1._model.engine.applyOp(ops2, true);
|
||
u2._model.engine.applyOp(ops1, true);
|
||
return expect(this.yTest.compare(u1, u2)).to.not.be.undefined;
|
||
});
|
||
it("can handle creaton of complex json (1)", function() {
|
||
var q;
|
||
this.yTest.users[0].val('a', new Y.Text('q'));
|
||
this.yTest.users[1].val('a', new Y.Text('t'));
|
||
this.yTest.compareAll();
|
||
q = this.yTest.users[2].val('a');
|
||
q.insert(0, 'A');
|
||
this.yTest.compareAll();
|
||
return expect(this.yTest.getSomeUser().val("a").val()).to.equal("At");
|
||
});
|
||
it("can handle creaton of complex json (2)", function() {
|
||
var q;
|
||
this.yTest.getSomeUser().val('x', new Y.Object({
|
||
'a': 'b'
|
||
}));
|
||
this.yTest.getSomeUser().val('a', new Y.Object({
|
||
'a': {
|
||
q: new Y.Text("dtrndtrtdrntdrnrtdnrtdnrtdnrtdnrdnrdt")
|
||
}
|
||
}));
|
||
this.yTest.getSomeUser().val('b', new Y.Object({
|
||
'a': {}
|
||
}));
|
||
this.yTest.getSomeUser().val('c', new Y.Object({
|
||
'a': 'c'
|
||
}));
|
||
this.yTest.getSomeUser().val('c', new Y.Object({
|
||
'a': 'b'
|
||
}));
|
||
this.yTest.compareAll();
|
||
q = this.yTest.getSomeUser().val("a").val("a").val("q");
|
||
q.insert(0, 'A');
|
||
this.yTest.compareAll();
|
||
return expect(this.yTest.getSomeUser().val("a").val("a").val("q").val()).to.equal("Adtrndtrtdrntdrnrtdnrtdnrtdnrtdnrdnrdt");
|
||
});
|
||
it("can handle creaton of complex json (3)", function() {
|
||
var w;
|
||
this.yTest.users[0].val('l', new Y.List([1, 2, 3]));
|
||
this.yTest.users[1].val('l', new Y.List([4, 5, 6]));
|
||
this.yTest.compareAll();
|
||
this.yTest.users[2].val('l').insert(0, 'A');
|
||
w = this.yTest.users[1].val('l').insert(0, new Y.Text('B')).val(0);
|
||
w.insert(1, "C");
|
||
expect(w.val()).to.equal("BC");
|
||
return this.yTest.compareAll();
|
||
});
|
||
it("handles immutables and primitive data types", function() {
|
||
this.yTest.getSomeUser().val('string', "text");
|
||
this.yTest.getSomeUser().val('number', 4);
|
||
this.yTest.getSomeUser().val('object', new Y.Object({
|
||
q: "rr"
|
||
}));
|
||
this.yTest.getSomeUser().val('null', null);
|
||
this.yTest.compareAll();
|
||
expect(this.yTest.getSomeUser().val('string')).to.equal("text");
|
||
expect(this.yTest.getSomeUser().val('number')).to.equal(4);
|
||
expect(this.yTest.getSomeUser().val('object').val('q')).to.equal("rr");
|
||
return expect(this.yTest.getSomeUser().val('null') === null).to.be.ok;
|
||
});
|
||
it("handles immutables and primitive data types (2)", function() {
|
||
this.yTest.users[0].val('string', "text");
|
||
this.yTest.users[1].val('number', 4);
|
||
this.yTest.users[2].val('object', new Y.Object({
|
||
q: "rr"
|
||
}));
|
||
this.yTest.users[0].val('null', null);
|
||
this.yTest.compareAll();
|
||
expect(this.yTest.getSomeUser().val('string')).to.equal("text");
|
||
expect(this.yTest.getSomeUser().val('number')).to.equal(4);
|
||
expect(this.yTest.getSomeUser().val('object').val('q')).to.equal("rr");
|
||
return expect(this.yTest.getSomeUser().val('null') === null).to.be.ok;
|
||
});
|
||
it("Observers work on JSON Types (add type observers, local and foreign)", function() {
|
||
var last_task, observer1, observer2, u, v;
|
||
u = this.yTest.users[0];
|
||
this.yTest.flushAll();
|
||
last_task = null;
|
||
observer1 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("add");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.changedBy).to.equal('0');
|
||
expect(change.name).to.equal("newStuff");
|
||
return last_task = "observer1";
|
||
};
|
||
u.observe(observer1);
|
||
u.val("newStuff", new Y.Text("someStuff"));
|
||
expect(last_task).to.equal("observer1");
|
||
u.unobserve(observer1);
|
||
observer2 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("add");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.changedBy).to.equal('1');
|
||
expect(change.name).to.equal("moreStuff");
|
||
return last_task = "observer2";
|
||
};
|
||
u.observe(observer2);
|
||
v = this.yTest.users[1];
|
||
v.val("moreStuff", "someMoreStuff");
|
||
this.yTest.flushAll();
|
||
expect(last_task).to.equal("observer2");
|
||
return u.unobserve(observer2);
|
||
});
|
||
it("Observers work on JSON Types (update type observers, local and foreign)", function() {
|
||
var last_task, observer1, observer2, u, v;
|
||
u = this.yTest.users[0].val("newStuff", new Y.Text("oldStuff")).val("moreStuff", new Y.Text("moreOldStuff"));
|
||
this.yTest.flushAll();
|
||
last_task = null;
|
||
observer1 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("update");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.changedBy).to.equal('0');
|
||
expect(change.name).to.equal("newStuff");
|
||
expect(change.oldValue.val()).to.equal("oldStuff");
|
||
return last_task = "observer1";
|
||
};
|
||
u.observe(observer1);
|
||
u.val("newStuff", "someStuff");
|
||
expect(last_task).to.equal("observer1");
|
||
u.unobserve(observer1);
|
||
observer2 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("update");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.changedBy).to.equal('1');
|
||
expect(change.name).to.equal("moreStuff");
|
||
expect(change.oldValue.val()).to.equal("moreOldStuff");
|
||
return last_task = "observer2";
|
||
};
|
||
u.observe(observer2);
|
||
v = this.yTest.users[1];
|
||
v.val("moreStuff", "someMoreStuff");
|
||
this.yTest.flushAll();
|
||
expect(last_task).to.equal("observer2");
|
||
return u.unobserve(observer2);
|
||
});
|
||
it("Observers work on JSON Types (delete type observers, local and foreign)", function() {
|
||
var last_task, observer1, observer2, u, v;
|
||
u = this.yTest.users[0].val("newStuff", new Y.Text("oldStuff")).val("moreStuff", new Y.Text("moreOldStuff"));
|
||
this.yTest.flushAll();
|
||
last_task = null;
|
||
observer1 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("delete");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.changedBy).to.equal('0');
|
||
expect(change.name).to.equal("newStuff");
|
||
expect(change.oldValue.val()).to.equal("oldStuff");
|
||
return last_task = "observer1";
|
||
};
|
||
u.observe(observer1);
|
||
u["delete"]("newStuff");
|
||
expect(last_task).to.equal("observer1");
|
||
u.unobserve(observer1);
|
||
observer2 = function(changes) {
|
||
var change;
|
||
expect(changes.length).to.equal(1);
|
||
change = changes[0];
|
||
expect(change.type).to.equal("delete");
|
||
expect(change.object).to.equal(u);
|
||
expect(change.changedBy).to.equal('1');
|
||
expect(change.name).to.equal("moreStuff");
|
||
expect(change.oldValue.val()).to.equal("moreOldStuff");
|
||
return last_task = "observer2";
|
||
};
|
||
u.observe(observer2);
|
||
v = this.yTest.users[1];
|
||
v["delete"]("moreStuff");
|
||
this.yTest.flushAll();
|
||
expect(last_task).to.equal("observer2");
|
||
return u.unobserve(observer2);
|
||
});
|
||
return it("can handle circular JSON", function() {
|
||
var u;
|
||
u = this.yTest.users[0];
|
||
u.val("me", u);
|
||
this.yTest.compareAll();
|
||
u.val("stuff", new Y.Object({
|
||
x: true
|
||
}));
|
||
u.val("same_stuff", u.val("stuff"));
|
||
u.val("same_stuff").val("x", 5);
|
||
expect(u.val("same_stuff").val("x")).to.equal(5);
|
||
this.yTest.compareAll();
|
||
u.val("stuff").val("y", u.val("stuff"));
|
||
return this.yTest.compareAll();
|
||
});
|
||
});
|
||
|
||
|
||
},{"../../y-list/lib/y-list":1,"../../y-test/lib/y-test.coffee":2,"../../y-text/lib/y-text":3,"../lib/y.coffee":11,"./TestSuite":84,"chai":14,"sinon":56,"sinon-chai":55,"underscore":83}]},{},[85])
|
||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3ktbGlzdC9saWIveS1saXN0LmNvZmZlZSIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95LXRlc3QvbGliL3ktdGVzdC5jb2ZmZWUiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveS10ZXh0L2xpYi95LXRleHQuY29mZmVlIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9saWIvQ29ubmVjdG9yQWRhcHRlci5jb2ZmZWUiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL2xpYi9Db25uZWN0b3JDbGFzcy5jb2ZmZWUiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL2xpYi9FbmdpbmUuY29mZmVlIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9saWIvSGlzdG9yeUJ1ZmZlci5jb2ZmZWUiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL2xpYi9PYmplY3RUeXBlLmNvZmZlZSIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbGliL09wZXJhdGlvbnMvQmFzaWMuY29mZmVlIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9saWIvT3BlcmF0aW9ucy9TdHJ1Y3R1cmVkLmNvZmZlZSIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbGliL3kuY29mZmVlIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvYmludHJlZXMvbGliL3JidHJlZV9ieV9pbmRleC5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL2JpbnRyZWVzL2xpYi90cmVlYmFzZS5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL2NoYWkvaW5kZXguanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS9hc3NlcnRpb24uanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL2NvbmZpZy5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvY29yZS9hc3NlcnRpb25zLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS9pbnRlcmZhY2UvYXNzZXJ0LmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS9pbnRlcmZhY2UvZXhwZWN0LmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS9pbnRlcmZhY2Uvc2hvdWxkLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9hZGRDaGFpbmFibGVNZXRob2QuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2FkZE1ldGhvZC5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvYWRkUHJvcGVydHkuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2ZsYWcuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2dldEFjdHVhbC5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvZ2V0RW51bWVyYWJsZVByb3BlcnRpZXMuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2dldE1lc3NhZ2UuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2dldE5hbWUuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2dldFBhdGhJbmZvLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9nZXRQYXRoVmFsdWUuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2dldFByb3BlcnRpZXMuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL2hhc1Byb3BlcnR5LmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9pbmRleC5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvaW5zcGVjdC5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvb2JqRGlzcGxheS5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL2NoYWkvbGliL2NoYWkvdXRpbHMvb3ZlcndyaXRlQ2hhaW5hYmxlTWV0aG9kLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy9vdmVyd3JpdGVNZXRob2QuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9jaGFpL2xpYi9jaGFpL3V0aWxzL292ZXJ3cml0ZVByb3BlcnR5LmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy90ZXN0LmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy90cmFuc2ZlckZsYWdzLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9saWIvY2hhaS91dGlscy90eXBlLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9ub2RlX21vZHVsZXMvYXNzZXJ0aW9uLWVycm9yL2luZGV4LmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9ub2RlX21vZHVsZXMvZGVlcC1lcWwvaW5kZXguanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9jaGFpL25vZGVfbW9kdWxlcy9kZWVwLWVxbC9saWIvZXFsLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9ub2RlX21vZHVsZXMvZGVlcC1lcWwvbm9kZV9tb2R1bGVzL3R5cGUtZGV0ZWN0L2luZGV4LmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvY2hhaS9ub2RlX21vZHVsZXMvZGVlcC1lcWwvbm9kZV9tb2R1bGVzL3R5cGUtZGV0ZWN0L2xpYi90eXBlLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9idWZmZXIvaW5kZXguanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9ub2RlX21vZHVsZXMvYmFzZTY0LWpzL2xpYi9iNjQuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9ndWxwLWJyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2J1ZmZlci9ub2RlX21vZHVsZXMvaWVlZTc1NC9pbmRleC5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvaW5oZXJpdHMvaW5oZXJpdHNfYnJvd3Nlci5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL2d1bHAtYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3N1cHBvcnQvaXNCdWZmZXJCcm93c2VyLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy91dGlsL3V0aWwuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9zaW5vbi1jaGFpL2xpYi9zaW5vbi1jaGFpLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL2Fzc2VydC5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi9iZWhhdmlvci5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi9jYWxsLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL2NvbGxlY3Rpb24uanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vZXh0ZW5kLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL2Zvcm1hdC5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi9sb2dfZXJyb3IuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vbWF0Y2guanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vbW9jay5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi9zYW5kYm94LmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL3NweS5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi9zdHViLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL3Rlc3QuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vdGVzdF9jYXNlLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL3RpbWVzX2luX3dvcmRzLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL3R5cGVPZi5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi91dGlsL2NvcmUuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vdXRpbC9ldmVudC5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi91dGlsL2Zha2Vfc2VydmVyLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL3V0aWwvZmFrZV9zZXJ2ZXJfd2l0aF9jbG9jay5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL3Npbm9uL2xpYi9zaW5vbi91dGlsL2Zha2VfdGltZXJzLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvc2lub24vbGliL3Npbm9uL3V0aWwvZmFrZV94ZG9tYWluX3JlcXVlc3QuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9zaW5vbi9saWIvc2lub24vdXRpbC9mYWtlX3htbF9odHRwX3JlcXVlc3QuanMiLCIvaG9tZS9jY2MvRG9jdW1lbnRzL3Byb2cvTGluYWdvcmEveWpzL25vZGVfbW9kdWxlcy9zaW5vbi9ub2RlX21vZHVsZXMvZm9ybWF0aW8vbGliL2Zvcm1hdGlvLmpzIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy9ub2RlX21vZHVsZXMvc2lub24vbm9kZV9tb2R1bGVzL2xvbGV4L3NyYy9sb2xleC5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL3Npbm9uL25vZGVfbW9kdWxlcy9zYW1zYW0vbGliL3NhbXNhbS5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvbm9kZV9tb2R1bGVzL3VuZGVyc2NvcmUvdW5kZXJzY29yZS5qcyIsIi9ob21lL2NjYy9Eb2N1bWVudHMvcHJvZy9MaW5hZ29yYS95anMvdGVzdC9UZXN0U3VpdGUuY29mZmVlIiwiL2hvbWUvY2NjL0RvY3VtZW50cy9wcm9nL0xpbmFnb3JhL3lqcy90ZXN0L29iamVjdC10ZXN0LmNvZmZlZSJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBLElBQUEsS0FBQTs7QUFBQTtBQUtlLEVBQUEsZUFBQyxJQUFELEdBQUE7QUFDWCxJQUFBLElBQU8sWUFBUDtBQUNFLE1BQUEsSUFBQyxDQUFBLEtBQUQsR0FBUyxFQUFULENBREY7S0FBQSxNQUVLLElBQUcsSUFBSSxDQUFDLFdBQUwsS0FBb0IsS0FBdkI7QUFDSCxNQUFBLElBQUMsQ0FBQSxLQUFELEdBQVMsSUFBVCxDQURHO0tBQUEsTUFBQTtBQUdILFlBQVUsSUFBQSxLQUFBLENBQU0sd0NBQU4sQ0FBVixDQUhHO0tBSE07RUFBQSxDQUFiOztBQUFBLGtCQVFBLEtBQUEsR0FBTyxNQVJQLENBQUE7O0FBQUEsa0JBVUEsU0FBQSxHQUFXLFNBQUMsS0FBRCxFQUFRLEdBQVIsR0FBQTtBQUNULElBQUEsSUFBTyxtQkFBUDtBQUNFLE1BQUEsSUFBQyxDQUFBLE1BQUQsR0FBYyxJQUFBLEdBQUcsQ0FBQyxXQUFKLENBQWdCLElBQWhCLENBQWtCLENBQUMsT0FBbkIsQ0FBQSxDQUFkLENBQUE7QUFBQSxNQUNBLElBQUMsQ0FBQSxNQUFNLENBQUMsTUFBUixDQUFlLENBQWYsRUFBa0IsSUFBQyxDQUFBLEtBQW5CLENBREEsQ0FERjtLQUFBO0FBQUEsSUFHQSxNQUFBLENBQUEsSUFBUSxDQUFBLEtBSFIsQ0FBQTtXQUtBLElBQUMsQ0FBQSxPQU5RO0VBQUEsQ0FWWCxDQUFBOztBQUFBLGtCQWtCQSxTQUFBLEdBQVcsU0FBRSxNQUFGLEdBQUE7QUFDVCxJQURVLElBQUMsQ0FBQSxTQUFBLE1BQ1gsQ0FBQTtXQUFBLE1BQUEsQ0FBQSxJQUFRLENBQUEsTUFEQztFQUFBLENBbEJYLENBQUE7O0FBQUEsa0JBcUJBLEdBQUEsR0FBSyxTQUFBLEdBQUE7QUFDSCxRQUFBLElBQUE7V0FBQSxRQUFBLElBQUMsQ0FBQSxNQUFELENBQU8sQ0FBQyxHQUFSLGFBQVksU0FBWixFQURHO0VBQUEsQ0FyQkwsQ0FBQTs7QUFBQSxrQkF3QkEsR0FBQSxHQUFLLFNBQUEsR0FBQTtBQUNILFFBQUEsSUFBQTtXQUFBLFFBQUEsSUFBQyxDQUFBLE1BQUQsQ0FBTyxDQUFDLEdBQVIsYUFBWSxTQUFaLEVBREc7RUFBQSxDQXhCTCxDQUFBOztBQUFBLGtCQTRCQSxPQUFBLEdBQVMsU0FBQSxHQUFBO0FBQ1AsUUFBQSxJQUFBO0FBQUEsSUFBQSxRQUFBLElBQUMsQ0FBQSxNQUFELENBQU8sQ0FBQyxPQUFSLGFBQWdCLFNBQWhCLENBQUEsQ0FBQTtXQUNBLEtBRk87RUFBQSxDQTVCVCxDQUFBOztBQUFBLGtCQWdDQSxTQUFBLEdBQVcsU0FBQSxHQUFBO0FBQ1QsUUFBQSxJQUFBO0FBQUEsSUFBQSxRQUFBLElBQUMsQ0FBQSxNQUFELENBQU8sQ0FBQyxTQUFSLGFBQWtCLFNBQWxCLENBQUEsQ0FBQTtXQUNBLEtBRlM7RUFBQSxDQWhDWCxDQUFBOztBQUFBLGtCQXlDQSxNQUFBLEdBQVEsU0FBQyxRQUFELEVBQVcsT0FBWCxHQUFBO1dBQ04sSUFBQyxDQUFBLGNBQUQsQ0FBZ0IsUUFBaEIsRUFBMEIsQ0FBQyxPQUFELENBQTFCLEVBRE07RUFBQSxDQXpDUixDQUFBOztBQUFBLGtCQTRDQSxjQUFBLEdBQWdCLFNBQUMsUUFBRCxFQUFXLFFBQVgsR0FBQTtBQUNkLElBQUEsSUFBRyxNQUFBLENBQUEsUUFBQSxLQUFxQixRQUF4QjtBQUNFLFlBQVUsSUFBQSxLQUFBLENBQU0sd0RBQU4sQ0FBVixDQURGO0tBQUE7QUFBQSxJQUdBLElBQUMsQ0FBQSxNQUFNLENBQUMsTUFBUixDQUFlLFFBQWYsRUFBeUIsUUFBekIsQ0FIQSxDQUFBO1dBSUEsS0FMYztFQUFBLENBNUNoQixDQUFBOztBQUFBLGtCQW1EQSxTQUFBLEdBQVEsU0FBQyxRQUFELEVBQVcsTUFBWCxHQUFBO0FBQ04sSUFBQSxJQUFDLENBQUEsTUFBTSxDQUFDLFFBQUQsQ0FBUCxDQUFlLFFBQWYsRUFBeUIsTUFBekIsQ0FBQSxDQUFBO1dBQ0EsS0FGTTtFQUFBLENBbkRSLENBQUE7O0FBQUEsa0JBdURBLElBQUEsR0FBTSxTQUFDLE9BQUQsR0FBQTtBQUNKLElBQUEsSUFBQyxDQUFBLE1BQU0sQ0FBQyxJQUFSLENBQWEsT0FBYixDQUFBLENBQUE7V0FDQSxLQUZJO0VBQUEsQ0F2RE4sQ0FBQTs7QUFBQSxrQkEyREEsU0FBQSxHQUFXLFNBQUEsR0FBQTtXQUNULElBQUMsQ0FBQSxNQUFNLENBQUMsU0FBUixDQUFBLEVBRFM7RUFBQSxDQTNEWCxDQUFBOztlQUFBOztJQUxGLENBQUE7O0FBbUVBLElBQUcsZ0RBQUg7QUFDRSxFQUFBLElBQUcsZ0JBQUg7QUFDRSxJQUFBLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBVCxHQUFnQixLQUFoQixDQURGO0dBQUEsTUFBQTtBQUdFLFVBQVUsSUFBQSxLQUFBLENBQU0sMEJBQU4sQ0FBVixDQUhGO0dBREY7Q0FuRUE7O0FBeUVBLElBQUcsZ0RBQUg7QUFDRSxFQUFBLE1BQU0sQ0FBQyxPQUFQLEdBQWlCLEtBQWpCLENBREY7Q0F6RUE7Ozs7QUNJQSxJQUFBLGFBQUE7O0FBQUE7QUFLZSxFQUFBLHVCQUFFLEVBQUYsR0FBQTtBQUNYLFFBQUEsT0FBQTtBQUFBLElBRFksSUFBQyxDQUFBLEtBQUEsRUFDYixDQUFBO0FBQUEsSUFBQSxPQUFBLEdBQ0U7QUFBQSxNQUFBLFVBQUEsRUFBWSxTQUFaO0FBQUEsTUFDQSxJQUFBLEVBQU0sT0FETjtBQUFBLE1BRUEsT0FBQSxFQUFTLElBQUMsQ0FBQSxFQUZWO0FBQUEsTUFHQSxrQkFBQSxFQUFvQixLQUhwQjtLQURGLENBQUE7QUFBQSxJQU1BLElBQUMsQ0FBQSxhQUFELEdBQWlCLENBQUEsU0FBQSxLQUFBLEdBQUE7YUFBQSxTQUFBLEdBQUE7QUFDZixRQUFBLEtBQUMsQ0FBQSxJQUFELENBQU0sT0FBTixDQUFBLENBQUE7QUFBQSxRQUlBLEtBQUMsQ0FBQSxlQUFELEdBQW1CLEVBSm5CLENBQUE7QUFBQSxRQU1BLEtBQUMsQ0FBQSxjQUFELEdBQWtCLEVBTmxCLENBQUE7ZUFRQSxLQUFDLENBQUEsZ0JBQWdCLENBQUMsSUFBbEIsQ0FBdUIsU0FBQyxJQUFELEVBQU8sT0FBUCxHQUFBO2lCQUNyQixLQUFDLENBQUEsZUFBZSxDQUFDLElBQWpCLENBQXNCLE9BQXRCLEVBRHFCO1FBQUEsQ0FBdkIsRUFUZTtNQUFBLEVBQUE7SUFBQSxDQUFBLENBQUEsQ0FBQSxJQUFBLENBTmpCLENBRFc7RUFBQSxDQUFiOztBQUFBLDBCQW9CQSxJQUFBLEdBQU0sU0FBQyxJQUFELEdBQUE7QUFDSixRQUFBLHNCQUFBO0FBQUEsSUFBQSxJQUFPLGlDQUFQO0FBQ0UsTUFBQSxJQUFDLENBQUEsV0FBWSxDQUFBLElBQUksQ0FBQyxFQUFMLENBQWIsR0FBd0I7QUFBQSxRQUFDLElBQUEsRUFBTyxJQUFSO09BQXhCLENBQUE7QUFBQSxNQUNBLElBQUMsQ0FBQSxVQUFELENBQVksSUFBSSxDQUFDLEVBQWpCLEVBQXFCLE9BQXJCLENBREEsQ0FBQTtBQUFBLE1BRUEsSUFBSSxDQUFDLElBQUwsQ0FBVSxJQUFWLENBRkEsQ0FBQTtBQUFBLE1BR0EsSUFBQyxDQUFBLFFBQUQsQ0FBQSxDQUhBLENBQUE7QUFBQSxNQUlBLElBQUksQ0FBQyxRQUFMLENBQUEsQ0FKQSxDQUFBO0FBQUEsTUFLQSxJQUFDLENBQUEsUUFBRCxDQUFBLENBTEEsQ0FBQTtBQUFBLE1BTUEsSUFBSSxDQUFDLFFBQUwsQ0FBQSxDQU5BLENBQUE7QUFPQTtBQUFBO1dBQUEsV0FBQTtzQkFBQTtBQUNFLFFBQUEsSUFBTyw2QkFBUDt3QkFDRSxJQUFDLENBQUEsSUFBRCxDQUFNLENBQUMsQ0FBQyxJQUFSLEdBREY7U0FBQSxNQUFBO2dDQUFBO1NBREY7QUFBQTtzQkFSRjtLQURJO0VBQUEsQ0FwQk4sQ0FBQTs7QUFBQSwwQkFzQ0Esc0JBQUEsR0FBd0IsU0FBQSxHQUFBO1dBQ3RCLElBQUMsQ0FBQSxnQkFEcUI7RUFBQSxDQXRDeEIsQ0FBQTs7QUFBQSwwQkE2Q0EsSUFBQSxHQUFNLFNBQUMsR0FBRCxFQUFNLE9BQU4sR0FBQTtBQUNKLFFBQUEsU0FBQTtBQUFBLElBQUEsSUFBRywyQkFBQSxJQUF1QixLQUExQjthQUNFLElBQUMsQ0FBQSxjQUFELENBQWdCLEdBQWhCLEVBQXFCLE9BQXJCLEVBREY7S0FBQSxNQUFBO0FBR0UsTUFBQSxFQUFBLEdBQUssSUFBQyxDQUFBLFdBQVksQ0FBQSxHQUFBLENBQUksQ0FBQyxJQUFJLENBQUMsY0FBNUIsQ0FBQTs7UUFDQSxZQUFXO09BRFg7YUFFQSxFQUFHLENBQUEsSUFBQyxDQUFBLEVBQUQsQ0FBSSxDQUFDLElBQVIsQ0FBYSxPQUFiLEVBTEY7S0FESTtFQUFBLENBN0NOLENBQUE7O0FBQUEsMEJBcURBLFNBQUEsR0FBVyxTQUFDLE9BQUQsR0FBQTtBQUNULFFBQUEsdUJBQUE7QUFBQTtBQUFBO1NBQUEsWUFBQTtxQkFBQTtBQUNFLG9CQUFBLElBQUMsQ0FBQSxJQUFELENBQU0sSUFBTixFQUFZLE9BQVosRUFBQSxDQURGO0FBQUE7b0JBRFM7RUFBQSxDQXJEWCxDQUFBOztBQUFBLDBCQTREQSxRQUFBLEdBQVUsU0FBQyxHQUFELEdBQUE7QUFDUixRQUFBLGFBQUE7QUFBQSxJQUFBLHFEQUF1QixDQUFFLGdCQUF0QixHQUErQixDQUFsQztBQUNFLE1BQUEsT0FBQSxHQUFVLElBQUMsQ0FBQSxjQUFlLENBQUEsR0FBQSxDQUFJLENBQUMsS0FBckIsQ0FBQSxDQUFWLENBQUE7YUFDQSxJQUFDLENBQUEsY0FBRCxDQUFnQixHQUFoQixFQUFxQixPQUFyQixFQUZGO0tBRFE7RUFBQSxDQTVEVixDQUFBOztBQUFBLDBCQXFFQSxjQUFBLEdBQWdCLFNBQUEsR0FBQTtBQUNkLFFBQUEsbUJBQUE7QUFBQSxJQUFBLFFBQUE7O0FBQVc7QUFBQTtXQUFBLFdBQUE7c0JBQUE7QUFDVCxzQkFBQSxJQUFBLENBRFM7QUFBQTs7aUJBQVgsQ0FBQTtBQUFBLElBRUEsQ0FBQSxHQUFJLElBQUksQ0FBQyxJQUFMLENBQVUsSUFBSSxDQUFDLE1BQUwsQ0FBQSxDQUFBLEdBQWMsUUFBUSxDQUFDLE1BQXZCLEdBQThCLEdBQXhDLENBRkosQ0FBQTtXQUdBLElBQUMsQ0FBQSxRQUFELENBQVUsUUFBUyxDQUFBLENBQUEsQ0FBbkIsRUFKYztFQUFBLENBckVoQixDQUFBOztBQUFBLDBCQThFQSxRQUFBLEdBQVUsU0FBQSxHQUFBO0FBQ1IsUUFBQSxvQ0FBQTtBQUFBO0FBQUEsU0FBQSxTQUFBO3lCQUFBO0FBQ0UsV0FBQSwrQ0FBQTsrQkFBQTtBQUNFLFFBQUEsSUFBQyxDQUFBLGNBQUQsQ0FBZ0IsQ0FBaEIsRUFBbUIsT0FBbkIsQ0FBQSxDQURGO0FBQUEsT0FERjtBQUFBLEtBQUE7V0FJQSxJQUFDLENBQUEsY0FBRCxHQUFrQixHQUxWO0VBQUEsQ0E5RVYsQ0FBQTs7dUJBQUE7O0lBTEYsQ0FBQTs7QUEyRkEsSUFBRyxnREFBSDtBQUNFLEVBQUEsSUFBTyxzQ0FBUDtBQUNFLFVBQVUsSUFBQSxLQUFBLENBQU0sMEJBQU4sQ0FBVixDQURGO0dBQUEsTUFBQTtBQUdFLElBQUEsTUFBTSxDQUFDLENBQUMsQ0FBQyxhQUFULEdBQXlCLGFBQXpCLENBSEY7R0FERjtDQTNGQTs7QUFpR0EsSUFBRyxnREFBSDtBQUNFLEVBQUEsTUFBTSxDQUFDLE9BQVAsR0FBaUIsYUFBakIsQ0FERjtDQWpHQTs7OztBQ0NBLElBQUEsS0FBQTs7QUFBQTtBQU1lLEVBQUEsZUFBQyxJQUFELEdBQUE7QUFDWCxJQUFBLElBQUMsQ0FBQSxVQUFELEdBQWMsRUFBZCxDQUFBO0FBQ0EsSUFBQSxJQUFPLFlBQVA7QUFDRSxNQUFBLElBQUMsQ0FBQSxLQUFELEdBQVMsRUFBVCxDQURGO0tBQUEsTUFFSyxJQUFHLElBQUksQ0FBQyxXQUFMLEtBQW9CLE1BQXZCO0FBQ0gsTUFBQSxJQUFDLENBQUEsS0FBRCxHQUFTLElBQVQsQ0FERztLQUFBLE1BQUE7QUFHSCxZQUFVLElBQUEsS0FBQSxDQUFNLDBDQUFOLENBQVYsQ0FIRztLQUpNO0VBQUEsQ0FBYjs7QUFBQSxrQkFTQSxLQUFBLEdBQU8sTUFUUCxDQUFBOztBQUFBLGtCQVdBLFNBQUEsR0FBVyxTQUFDLEtBQUQsRUFBUSxHQUFSLEdBQUE7QUFDVCxJQUFBLElBQU8sbUJBQVA7QUFDRSxNQUFBLElBQUMsQ0FBQSxNQUFELEdBQWMsSUFBQSxHQUFHLENBQUMsV0FBSixDQUFnQixJQUFoQixDQUFrQixDQUFDLE9BQW5CLENBQUEsQ0FBZCxDQUFBO0FBQUEsTUFDQSxJQUFDLENBQUEsTUFBRCxDQUFRLENBQVIsRUFBVyxJQUFDLENBQUEsS0FBWixDQURBLENBREY7S0FBQTtBQUFBLElBR0EsTUFBQSxDQUFBLElBQVEsQ0FBQSxLQUhSLENBQUE7V0FJQSxJQUFDLENBQUEsT0FMUTtFQUFBLENBWFgsQ0FBQTs7QUFBQSxrQkFrQkEsU0FBQSxHQUFXLFNBQUUsTUFBRixHQUFBO0FBQ1QsSUFEVSxJQUFDLENBQUEsU0FBQSxNQUNYLENBQUE7V0FBQSxNQUFBLENBQUEsSUFBUSxDQUFBLE1BREM7RUFBQSxDQWxCWCxDQUFBOztBQUFBLGtCQXlCQSxHQUFBLEdBQUssU0FBQSxHQUFBO1dBQ0gsSUFBQyxDQUFBLE1BQU0sQ0FBQyxJQUFSLENBQWEsRUFBYixFQUFpQixTQUFDLElBQUQsRUFBTyxDQUFQLEdBQUE7YUFDZixJQUFBLEdBQU8sQ0FBQyxDQUFDLEdBQUYsQ0FBQSxFQURRO0lBQUEsQ0FBakIsRUFERztFQUFBLENBekJMLENBQUE7O0FBQUEsa0JBNkJBLE9BQUEsR0FBUyxTQUFBLEdBQUE7V0FDUCxJQUFDLENBQUEsTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFoQixDQUFzQixJQUFDLENBQUEsTUFBdkIsRUFBK0IsU0FBL0IsRUFETztFQUFBLENBN0JULENBQUE7O0FBQUEsa0JBZ0NBLFNBQUEsR0FBVyxTQUFBLEdBQUE7V0FDVCxJQUFDLENBQUEsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFsQixDQUF3QixJQUFDLENBQUEsTUFBekIsRUFBaUMsU0FBakMsRUFEUztFQUFBLENBaENYLENBQUE7O0FBQUEsa0JBdUNBLFFBQUEsR0FBVSxTQUFBLEdBQUE7V0FDUixJQUFDLENBQUEsR0FBRCxDQUFBLEVBRFE7RUFBQSxDQXZDVixDQUFBOztBQUFBLGtCQStDQSxNQUFBLEdBQVEsU0FBQyxRQUFELEVBQVcsT0FBWCxHQUFBO0FBQ04sUUFBQSxHQUFBO0FBQUEsSUFBQSxJQUFHLE9BQU8sQ0FBQyxXQUFSLEtBQXlCLE1BQTVCO0FBQ0UsWUFBVSxJQUFBLEtBQUEsQ0FBTSwyREFBTixDQUFWLENBREY7S0FBQTtBQUVBLElBQUEsSUFBRyxNQUFBLENBQUEsUUFBQSxLQUFxQixRQUF4QjtBQUNFLFlBQVUsSUFBQSxLQUFBLENBQU0sMERBQU4sQ0FBVixDQURGO0tBRkE7QUFJQSxJQUFBLElBQUcsT0FBTyxDQUFDLE1BQVIsR0FBaUIsQ0FBcEI7QUFDRSxNQUFBLEdBQUEsR0FBTSxJQUFDLENBQUEsTUFBTSxDQUFDLHNCQUFSLENBQStCLFFBQS9CLENBQU4sQ0FBQTthQUdBLElBQUMsQ0FBQSxNQUFNLENBQUMsV0FBUixDQUFvQixHQUFwQixFQUF5QixPQUF6QixFQUpGO0tBTE07RUFBQSxDQS9DUixDQUFBOztBQUFBLGtCQTBEQSxTQUFBLEdBQVEsU0FBQyxRQUFELEVBQVcsTUFBWCxHQUFBO1dBQ04sSUFBQyxDQUFBLE1BQU0sQ0FBQyxRQUFELENBQVAsQ0FBZSxRQUFmLEVBQXlCLE1BQXpCLEVBRE07RUFBQSxDQTFEUixDQUFBOztBQUFBLGtCQW9FQSxJQUFBLEdBQU0sU0FBQyxTQUFELEVBQVksUUFBWixHQUFBO0FBQ0osUUFBQSw2RUFBQTs7TUFBQSxXQUFZO0tBQVo7QUFDQSxJQUFBLElBQVEsNkJBQVI7QUFDRSxNQUFBLFFBQUEsR0FBVyxNQUFYLENBREY7S0FEQTtBQUtBO0FBQUEsU0FBQSwyQ0FBQTttQkFBQTtBQUNFLE1BQUEsSUFBRyxDQUFBLEtBQUssU0FBUjtBQUNFLGNBQUEsQ0FERjtPQURGO0FBQUEsS0FMQTtBQUFBLElBUUEsYUFBQSxHQUFnQixLQVJoQixDQUFBO0FBQUEsSUFVQSxJQUFBLEdBQU8sSUFWUCxDQUFBO0FBQUEsSUFXQSxTQUFTLENBQUMsS0FBVixHQUFrQixJQUFDLENBQUEsR0FBRCxDQUFBLENBWGxCLENBQUE7QUFBQSxJQVlBLElBQUMsQ0FBQSxVQUFVLENBQUMsSUFBWixDQUFpQixTQUFqQixDQVpBLENBQUE7QUFjQSxJQUFBLElBQUcsa0NBQUEsSUFBOEIscUNBQWpDO0FBQ0UsTUFBQSxXQUFBLEdBQWMsU0FBQyxHQUFELEdBQUE7QUFDWixZQUFBLFdBQUE7QUFBQSxRQUFBLElBQUEsR0FBTyxTQUFTLENBQUMsY0FBakIsQ0FBQTtBQUFBLFFBQ0EsS0FBQSxHQUFRLFNBQVMsQ0FBQyxZQURsQixDQUFBO0FBRUEsUUFBQSxJQUFHLFdBQUg7QUFDRSxVQUFBLElBQUEsR0FBTyxHQUFBLENBQUksSUFBSixDQUFQLENBQUE7QUFBQSxVQUNBLEtBQUEsR0FBUSxHQUFBLENBQUksS0FBSixDQURSLENBREY7U0FGQTtlQUtBO0FBQUEsVUFDRSxJQUFBLEVBQU0sSUFEUjtBQUFBLFVBRUUsS0FBQSxFQUFPLEtBRlQ7VUFOWTtNQUFBLENBQWQsQ0FBQTtBQUFBLE1BV0EsVUFBQSxHQUFhLFNBQUMsS0FBRCxHQUFBO0FBQ1gsUUFBQSxZQUFBLENBQWEsSUFBSSxDQUFDLEdBQUwsQ0FBQSxDQUFiLENBQUEsQ0FBQTtlQUNBLFNBQVMsQ0FBQyxpQkFBVixDQUE0QixLQUFLLENBQUMsSUFBbEMsRUFBd0MsS0FBSyxDQUFDLEtBQTlDLEVBRlc7TUFBQSxDQVhiLENBQUE7QUFBQSxNQWVBLFlBQUEsR0FBZSxTQUFDLE9BQUQsR0FBQTtlQUNiLFNBQVMsQ0FBQyxLQUFWLEdBQWtCLFFBREw7TUFBQSxDQWZmLENBREY7S0FBQSxNQUFBO0FBbUJFLE1BQUEsV0FBQSxHQUFjLFNBQUMsR0FBRCxHQUFBO0FBQ1osWUFBQSxpQ0FBQTtBQUFBLFFBQUEsS0FBQSxHQUFRLEVBQVIsQ0FBQTtBQUFBLFFBQ0EsQ0FBQSxHQUFJLFFBQVEsQ0FBQyxZQUFULENBQUEsQ0FESixDQUFBO0FBQUEsUUFFQSxPQUFBLEdBQVUsU0FBUyxDQUFDLFdBQVcsQ0FBQyxNQUZoQyxDQUFBO0FBQUEsUUFHQSxLQUFLLENBQUMsSUFBTixHQUFhLElBQUksQ0FBQyxHQUFMLENBQVMsQ0FBQyxDQUFDLFlBQVgsRUFBeUIsT0FBekIsQ0FIYixDQUFBO0FBQUEsUUFJQSxLQUFLLENBQUMsS0FBTixHQUFjLElBQUksQ0FBQyxHQUFMLENBQVMsQ0FBQyxDQUFDLFdBQVgsRUFBd0IsT0FBeEIsQ0FKZCxDQUFBO0FBS0EsUUFBQSxJQUFHLFdBQUg7QUFDRSxVQUFBLEtBQUssQ0FBQyxJQUFOLEdBQWEsR0FBQSxDQUFJLEtBQUssQ0FBQyxJQUFWLENBQWIsQ0FBQTtBQUFBLFVBQ0EsS0FBSyxDQUFDLEtBQU4sR0FBYyxHQUFBLENBQUksS0FBSyxDQUFDLEtBQVYsQ0FEZCxDQURGO1NBTEE7QUFBQSxRQVNBLGNBQUEsR0FBaUIsQ0FBQyxDQUFDLFNBVG5CLENBQUE7QUFVQSxRQUFBLElBQUcsY0FBQSxLQUFrQixTQUFsQixJQUErQixjQUFBLEtBQWtCLFNBQVMsQ0FBQyxVQUFXLENBQUEsQ0FBQSxDQUF6RTtBQUNFLFVBQUEsS0FBSyxDQUFDLE1BQU4sR0FBZSxJQUFmLENBREY7U0FBQSxNQUFBO0FBR0UsVUFBQSxLQUFLLENBQUMsTUFBTixHQUFlLEtBQWYsQ0FIRjtTQVZBO2VBY0EsTUFmWTtNQUFBLENBQWQsQ0FBQTtBQUFBLE1BaUJBLFVBQUEsR0FBYSxTQUFDLEtBQUQsR0FBQTtBQUNYLFlBQUEsY0FBQTtBQUFBLFFBQUEsWUFBQSxDQUFhLElBQUksQ0FBQyxHQUFMLENBQUEsQ0FBYixDQUFBLENBQUE7QUFBQSxRQUNBLFFBQUEsR0FBVyxTQUFTLENBQUMsVUFBVyxDQUFBLENBQUEsQ0FEaEMsQ0FBQTtBQUVBLFFBQUEsSUFBRyxLQUFLLENBQUMsTUFBTixJQUFpQixrQkFBcEI7QUFDRSxVQUFBLElBQUcsS0FBSyxDQUFDLElBQU4sR0FBYSxDQUFoQjtBQUNFLFlBQUEsS0FBSyxDQUFDLElBQU4sR0FBYSxDQUFiLENBREY7V0FBQTtBQUFBLFVBRUEsS0FBSyxDQUFDLEtBQU4sR0FBYyxJQUFJLENBQUMsR0FBTCxDQUFTLEtBQUssQ0FBQyxJQUFmLEVBQXFCLEtBQUssQ0FBQyxLQUEzQixDQUZkLENBQUE7QUFHQSxVQUFBLElBQUcsS0FBSyxDQUFDLEtBQU4sR0FBYyxRQUFRLENBQUMsTUFBMUI7QUFDRSxZQUFBLEtBQUssQ0FBQyxLQUFOLEdBQWMsUUFBUSxDQUFDLE1BQXZCLENBREY7V0FIQTtBQUFBLFVBS0EsS0FBSyxDQUFDLElBQU4sR0FBYSxJQUFJLENBQUMsR0FBTCxDQUFTLEtBQUssQ0FBQyxJQUFmLEVBQXFCLEtBQUssQ0FBQyxLQUEzQixDQUxiLENBQUE7QUFBQSxVQU1BLENBQUEsR0FBSSxRQUFRLENBQUMsV0FBVCxDQUFBLENBTkosQ0FBQTtBQUFBLFVBT0EsQ0FBQyxDQUFDLFFBQUYsQ0FBVyxRQUFYLEVBQXFCLEtBQUssQ0FBQyxJQUEzQixDQVBBLENBQUE7QUFBQSxVQVFBLENBQUMsQ0FBQyxNQUFGLENBQVMsUUFBVCxFQUFtQixLQUFLLENBQUMsS0FBekIsQ0FSQSxDQUFBO0FBQUEsVUFTQSxDQUFBLEdBQUksTUFBTSxDQUFDLFlBQVAsQ0FBQSxDQVRKLENBQUE7QUFBQSxVQVVBLENBQUMsQ0FBQyxlQUFGLENBQUEsQ0FWQSxDQUFBO2lCQVdBLENBQUMsQ0FBQyxRQUFGLENBQVcsQ0FBWCxFQVpGO1NBSFc7TUFBQSxDQWpCYixDQUFBO0FBQUEsTUFpQ0EsWUFBQSxHQUFlLFNBQUMsT0FBRCxHQUFBO0FBQ2IsWUFBQSx3Q0FBQTtBQUFBLFFBQUEsYUFBQSxHQUFnQixPQUFPLENBQUMsT0FBUixDQUFvQixJQUFBLE1BQUEsQ0FBTyxJQUFQLEVBQVksR0FBWixDQUFwQixFQUFxQyxHQUFyQyxDQUF5QyxDQUFDLEtBQTFDLENBQWdELEdBQWhELENBQWhCLENBQUE7QUFBQSxRQUNBLFNBQVMsQ0FBQyxTQUFWLEdBQXNCLEVBRHRCLENBQUE7QUFFQTthQUFBLDhEQUFBOytCQUFBO0FBQ0UsVUFBQSxTQUFTLENBQUMsU0FBVixJQUF1QixDQUF2QixDQUFBO0FBQ0EsVUFBQSxJQUFHLENBQUEsS0FBTyxhQUFhLENBQUMsTUFBZCxHQUFxQixDQUEvQjswQkFDRSxTQUFTLENBQUMsU0FBVixJQUF1QixVQUR6QjtXQUFBLE1BQUE7a0NBQUE7V0FGRjtBQUFBO3dCQUhhO01BQUEsQ0FqQ2YsQ0FuQkY7S0FkQTtBQUFBLElBMEVBLFlBQUEsQ0FBYSxJQUFJLENBQUMsR0FBTCxDQUFBLENBQWIsQ0ExRUEsQ0FBQTtBQUFBLElBNEVBLElBQUMsQ0FBQSxPQUFELENBQVMsU0FBQyxNQUFELEdBQUE7QUFDUCxVQUFBLHlDQUFBO0FBQUE7V0FBQSwrQ0FBQTsyQkFBQTtBQUNFLFFBQUEsSUFBRyxDQUFBLGFBQUg7QUFDRSxVQUFBLElBQUcsS0FBSyxDQUFDLElBQU4sS0FBYyxRQUFqQjtBQUNFLFlBQUEsS0FBQSxHQUFRLEtBQUssQ0FBQyxRQUFkLENBQUE7QUFBQSxZQUNBLEdBQUEsR0FBTSxTQUFDLE1BQUQsR0FBQTtBQUNKLGNBQUEsSUFBRyxNQUFBLElBQVUsS0FBYjt1QkFDRSxPQURGO2VBQUEsTUFBQTtBQUdFLGdCQUFBLE1BQUEsSUFBVSxDQUFWLENBQUE7dUJBQ0EsT0FKRjtlQURJO1lBQUEsQ0FETixDQUFBO0FBQUEsWUFPQSxDQUFBLEdBQUksV0FBQSxDQUFZLEdBQVosQ0FQSixDQUFBO0FBQUEsMEJBUUEsVUFBQSxDQUFXLENBQVgsRUFSQSxDQURGO1dBQUEsTUFXSyxJQUFHLEtBQUssQ0FBQyxJQUFOLEtBQWMsUUFBakI7QUFDSCxZQUFBLEtBQUEsR0FBUSxLQUFLLENBQUMsUUFBZCxDQUFBO0FBQUEsWUFDQSxHQUFBLEdBQU0sU0FBQyxNQUFELEdBQUE7QUFDSixjQUFBLElBQUcsTUFBQSxHQUFTLEtBQVo7dUJBQ0UsT0FERjtlQUFBLE1BQUE7QUFHRSxnQkFBQSxNQUFBLElBQVUsQ0FBVixDQUFBO3VCQUNBLE9BSkY7ZUFESTtZQUFBLENBRE4sQ0FBQTtBQUFBLFlBT0EsQ0FBQSxHQUFJLFdBQUEsQ0FBWSxHQUFaLENBUEosQ0FBQTtBQUFBLDBCQVFBLFVBQUEsQ0FBVyxDQUFYLEVBUkEsQ0FERztXQUFBLE1BQUE7a0NBQUE7V0FaUDtTQUFBLE1BQUE7Z0NBQUE7U0FERjtBQUFBO3NCQURPO0lBQUEsQ0FBVCxDQTVFQSxDQUFBO0FBQUEsSUFzR0EsU0FBUyxDQUFDLFVBQVYsR0FBdUIsU0FBQyxLQUFELEdBQUE7QUFDckIsVUFBQSxrQkFBQTtBQUFBLE1BQUEsSUFBRyxJQUFJLENBQUMsVUFBUjtBQUVFLFFBQUEsU0FBUyxDQUFDLFVBQVYsR0FBdUIsSUFBdkIsQ0FBQTtBQUNBLGVBQU8sSUFBUCxDQUhGO09BQUE7QUFBQSxNQUlBLGFBQUEsR0FBZ0IsSUFKaEIsQ0FBQTtBQUFBLE1BS0EsSUFBQSxHQUFPLElBTFAsQ0FBQTtBQU1BLE1BQUEsSUFBRyxLQUFLLENBQUMsT0FBTixLQUFpQixFQUFwQjtBQUNFLFFBQUEsSUFBQSxHQUFPLElBQVAsQ0FERjtPQUFBLE1BRUssSUFBRyxpQkFBSDtBQUNILFFBQUEsSUFBRyxLQUFLLENBQUMsUUFBTixLQUFrQixFQUFyQjtBQUNFLFVBQUEsSUFBQSxHQUFPLEdBQVAsQ0FERjtTQUFBLE1BQUE7QUFHRSxVQUFBLElBQUEsR0FBTyxLQUFLLENBQUMsR0FBYixDQUhGO1NBREc7T0FBQSxNQUFBO0FBTUgsUUFBQSxJQUFBLEdBQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxZQUFkLENBQTJCLEtBQUssQ0FBQyxPQUFqQyxDQUFQLENBTkc7T0FSTDtBQWVBLE1BQUEsSUFBRyxJQUFJLENBQUMsTUFBTCxHQUFjLENBQWpCO0FBQ0UsZUFBTyxJQUFQLENBREY7T0FBQSxNQUVLLElBQUcsSUFBSSxDQUFDLE1BQUwsR0FBYyxDQUFqQjtBQUNILFFBQUEsQ0FBQSxHQUFJLFdBQUEsQ0FBQSxDQUFKLENBQUE7QUFBQSxRQUNBLEdBQUEsR0FBTSxJQUFJLENBQUMsR0FBTCxDQUFTLENBQUMsQ0FBQyxJQUFYLEVBQWlCLENBQUMsQ0FBQyxLQUFuQixDQUROLENBQUE7QUFBQSxRQUVBLElBQUEsR0FBTyxJQUFJLENBQUMsR0FBTCxDQUFTLENBQUMsQ0FBQyxLQUFGLEdBQVUsQ0FBQyxDQUFDLElBQXJCLENBRlAsQ0FBQTtBQUFBLFFBR0EsSUFBSSxDQUFDLFFBQUQsQ0FBSixDQUFZLEdBQVosRUFBaUIsSUFBakIsQ0FIQSxDQUFBO0FBQUEsUUFJQSxJQUFJLENBQUMsTUFBTCxDQUFZLEdBQVosRUFBaUIsSUFBakIsQ0FKQSxDQUFBO0FBQUEsUUFLQSxDQUFDLENBQUMsSUFBRixHQUFTLEdBQUEsR0FBTSxJQUFJLENBQUMsTUFMcEIsQ0FBQTtBQUFBLFFBTUEsQ0FBQyxDQUFDLEtBQUYsR0FBVSxDQUFDLENBQUMsSUFOWixDQUFBO0FBQUEsUUFPQSxVQUFBLENBQVcsQ0FBWCxDQVBBLENBREc7T0FqQkw7QUFBQSxNQTJCQSxLQUFLLENBQUMsY0FBTixDQUFBLENBM0JBLENBQUE7QUFBQSxNQTRCQSxhQUFBLEdBQWdCLEtBNUJoQixDQUFBO2FBNkJBLE1BOUJxQjtJQUFBLENBdEd2QixDQUFBO0FBQUEsSUFzSUEsU0FBUyxDQUFDLE9BQVYsR0FBb0IsU0FBQyxLQUFELEdBQUE7QUFDbEIsTUFBQSxJQUFHLElBQUksQ0FBQyxVQUFSO0FBRUUsUUFBQSxTQUFTLENBQUMsT0FBVixHQUFvQixJQUFwQixDQUFBO0FBQ0EsZUFBTyxJQUFQLENBSEY7T0FBQTthQUlBLEtBQUssQ0FBQyxjQUFOLENBQUEsRUFMa0I7SUFBQSxDQXRJcEIsQ0FBQTtBQUFBLElBNElBLFNBQVMsQ0FBQyxLQUFWLEdBQWtCLFNBQUMsS0FBRCxHQUFBO0FBQ2hCLE1BQUEsSUFBRyxJQUFJLENBQUMsVUFBUjtBQUVFLFFBQUEsU0FBUyxDQUFDLEtBQVYsR0FBa0IsSUFBbEIsQ0FBQTtBQUNBLGVBQU8sSUFBUCxDQUhGO09BQUE7YUFJQSxLQUFLLENBQUMsY0FBTixDQUFBLEVBTGdCO0lBQUEsQ0E1SWxCLENBQUE7V0EwSkEsU0FBUyxDQUFDLFNBQVYsR0FBc0IsU0FBQyxLQUFELEdBQUE7QUFDcEIsVUFBQSxzQ0FBQTtBQUFBLE1BQUEsYUFBQSxHQUFnQixJQUFoQixDQUFBO0FBQ0EsTUFBQSxJQUFHLElBQUksQ0FBQyxVQUFSO0FBRUUsUUFBQSxTQUFTLENBQUMsU0FBVixHQUFzQixJQUF0QixDQUFBO0FBQ0EsZUFBTyxJQUFQLENBSEY7T0FEQTtBQUFBLE1BS0EsQ0FBQSxHQUFJLFdBQUEsQ0FBQSxDQUxKLENBQUE7QUFBQSxNQU1BLEdBQUEsR0FBTSxJQUFJLENBQUMsR0FBTCxDQUFTLENBQUMsQ0FBQyxJQUFYLEVBQWlCLENBQUMsQ0FBQyxLQUFuQixFQUEwQixJQUFJLENBQUMsR0FBTCxDQUFBLENBQVUsQ0FBQyxNQUFyQyxDQU5OLENBQUE7QUFBQSxNQU9BLElBQUEsR0FBTyxJQUFJLENBQUMsR0FBTCxDQUFTLENBQUMsQ0FBQyxJQUFGLEdBQVMsQ0FBQyxDQUFDLEtBQXBCLENBUFAsQ0FBQTtBQVFBLE1BQUEsSUFBRyx1QkFBQSxJQUFtQixLQUFLLENBQUMsT0FBTixLQUFpQixDQUF2QztBQUNFLFFBQUEsSUFBRyxJQUFBLEdBQU8sQ0FBVjtBQUNFLFVBQUEsSUFBSSxDQUFDLFFBQUQsQ0FBSixDQUFZLEdBQVosRUFBaUIsSUFBakIsQ0FBQSxDQUFBO0FBQUEsVUFDQSxDQUFDLENBQUMsSUFBRixHQUFTLEdBRFQsQ0FBQTtBQUFBLFVBRUEsQ0FBQyxDQUFDLEtBQUYsR0FBVSxHQUZWLENBQUE7QUFBQSxVQUdBLFVBQUEsQ0FBVyxDQUFYLENBSEEsQ0FERjtTQUFBLE1BQUE7QUFNRSxVQUFBLElBQUcsdUJBQUEsSUFBbUIsS0FBSyxDQUFDLE9BQTVCO0FBQ0UsWUFBQSxHQUFBLEdBQU0sSUFBSSxDQUFDLEdBQUwsQ0FBQSxDQUFOLENBQUE7QUFBQSxZQUNBLE9BQUEsR0FBVSxHQURWLENBQUE7QUFBQSxZQUVBLFVBQUEsR0FBYSxDQUZiLENBQUE7QUFHQSxZQUFBLElBQUcsR0FBQSxHQUFNLENBQVQ7QUFDRSxjQUFBLE9BQUEsRUFBQSxDQUFBO0FBQUEsY0FDQSxVQUFBLEVBREEsQ0FERjthQUhBO0FBTUEsbUJBQU0sT0FBQSxHQUFVLENBQVYsSUFBZ0IsR0FBSSxDQUFBLE9BQUEsQ0FBSixLQUFrQixHQUFsQyxJQUEwQyxHQUFJLENBQUEsT0FBQSxDQUFKLEtBQWtCLElBQWxFLEdBQUE7QUFDRSxjQUFBLE9BQUEsRUFBQSxDQUFBO0FBQUEsY0FDQSxVQUFBLEVBREEsQ0FERjtZQUFBLENBTkE7QUFBQSxZQVNBLElBQUksQ0FBQyxRQUFELENBQUosQ0FBWSxPQUFaLEVBQXNCLEdBQUEsR0FBSSxPQUExQixDQVRBLENBQUE7QUFBQSxZQVVBLENBQUMsQ0FBQyxJQUFGLEdBQVMsT0FWVCxDQUFBO0FBQUEsWUFXQSxDQUFDLENBQUMsS0FBRixHQUFVLE9BWFYsQ0FBQTtBQUFBLFlBWUEsVUFBQSxDQUFXLENBQVgsQ0FaQSxDQURGO1dBQUEsTUFBQTtBQWVFLFlBQUEsSUFBRyxHQUFBLEdBQU0sQ0FBVDtBQUNFLGNBQUEsSUFBSSxDQUFDLFFBQUQsQ0FBSixDQUFhLEdBQUEsR0FBSSxDQUFqQixFQUFxQixDQUFyQixDQUFBLENBQUE7QUFBQSxjQUNBLENBQUMsQ0FBQyxJQUFGLEdBQVMsR0FBQSxHQUFJLENBRGIsQ0FBQTtBQUFBLGNBRUEsQ0FBQyxDQUFDLEtBQUYsR0FBVSxHQUFBLEdBQUksQ0FGZCxDQUFBO0FBQUEsY0FHQSxVQUFBLENBQVcsQ0FBWCxDQUhBLENBREY7YUFmRjtXQU5GO1NBQUE7QUFBQSxRQTBCQSxLQUFLLENBQUMsY0FBTixDQUFBLENBMUJBLENBQUE7QUFBQSxRQTJCQSxhQUFBLEdBQWdCLEtBM0JoQixDQUFBO0FBNEJBLGVBQU8sS0FBUCxDQTdCRjtPQUFBLE1BOEJLLElBQUcsdUJBQUEsSUFBbUIsS0FBSyxDQUFDLE9BQU4sS0FBaUIsRUFBdkM7QUFDSCxRQUFBLElBQUcsSUFBQSxHQUFPLENBQVY7QUFDRSxVQUFBLElBQUksQ0FBQyxRQUFELENBQUosQ0FBWSxHQUFaLEVBQWlCLElBQWpCLENBQUEsQ0FBQTtBQUFBLFVBQ0EsQ0FBQyxDQUFDLElBQUYsR0FBUyxHQURULENBQUE7QUFBQSxVQUVBLENBQUMsQ0FBQyxLQUFGLEdBQVUsR0FGVixDQUFBO0FBQUEsVUFHQSxVQUFBLENBQVcsQ0FBWCxDQUhBLENBREY7U0FBQSxNQUFBO0FBTUUsVUFBQSxJQUFJLENBQUMsUUFBRCxDQUFKLENBQVksR0FBWixFQUFpQixDQUFqQixDQUFBLENBQUE7QUFBQSxVQUNBLENBQUMsQ0FBQyxJQUFGLEdBQVMsR0FEVCxDQUFBO0FBQUEsVUFFQSxDQUFDLENBQUMsS0FBRixHQUFVLEdBRlYsQ0FBQTtBQUFBLFVBR0EsVUFBQSxDQUFXLENBQVgsQ0FIQSxDQU5GO1NBQUE7QUFBQSxRQVVBLEtBQUssQ0FBQyxjQUFOLENBQUEsQ0FWQSxDQUFBO0FBQUEsUUFXQSxhQUFBLEdBQWdCLEtBWGhCLENBQUE7QUFZQSxlQUFPLEtBQVAsQ0FiRztPQUFBLE1BQUE7QUFlSCxRQUFBLGFBQUEsR0FBZ0IsS0FBaEIsQ0FBQTtlQUNBLEtBaEJHO09BdkNlO0lBQUEsRUEzSmxCO0VBQUEsQ0FwRU4sQ0FBQTs7ZUFBQTs7SUFORixDQUFBOztBQStSQSxJQUFHLGdEQUFIO0FBQ0UsRUFBQSxJQUFHLGdCQUFIO0FBQ0UsSUFBQSxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQVQsR0FBZ0IsS0FBaEIsQ0FERjtHQUFBLE1BQUE7QUFHRSxVQUFVLElBQUEsS0FBQSxDQUFNLDBCQUFOLENBQVYsQ0FIRjtHQURGO0NBL1JBOztBQXFTQSxJQUFHLGdEQUFIO0FBQ0UsRUFBQSxNQUFNLENBQUMsT0FBUCxHQUFpQixLQUFqQixDQURGO0NBclNBOzs7O0FDSkEsSUFBQSw4QkFBQTs7QUFBQSxjQUFBLEdBQWlCLE9BQUEsQ0FBUSxrQkFBUixDQUFqQixDQUFBOztBQUFBLGNBTUEsR0FBaUIsU0FBQyxTQUFELEVBQVksTUFBWixFQUFvQixFQUFwQixFQUF3QixrQkFBeEIsR0FBQTtBQUVmLE1BQUEsdUZBQUE7QUFBQSxPQUFBLHNCQUFBOzZCQUFBO0FBQ0UsSUFBQSxTQUFVLENBQUEsSUFBQSxDQUFWLEdBQWtCLENBQWxCLENBREY7QUFBQSxHQUFBO0FBQUEsRUFHQSxTQUFTLENBQUMsYUFBVixDQUFBLENBSEEsQ0FBQTtBQUFBLEVBS0EsS0FBQSxHQUFRLFNBQUMsQ0FBRCxHQUFBO0FBQ04sSUFBQSxJQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFOLEtBQWlCLEVBQUUsQ0FBQyxTQUFILENBQUEsQ0FBbEIsQ0FBQSxJQUNDLENBQUMsTUFBQSxDQUFBLENBQVEsQ0FBQyxHQUFHLENBQUMsU0FBYixLQUE0QixRQUE3QixDQURELElBRUMsQ0FBQyxFQUFFLENBQUMsU0FBSCxDQUFBLENBQUEsS0FBb0IsT0FBckIsQ0FGSjthQUdFLFNBQVMsQ0FBQyxTQUFWLENBQW9CLENBQXBCLEVBSEY7S0FETTtFQUFBLENBTFIsQ0FBQTtBQVdBLEVBQUEsSUFBRyw0QkFBSDtBQUNFLElBQUEsRUFBRSxDQUFDLG9CQUFILENBQXdCLFNBQVMsQ0FBQyxVQUFsQyxDQUFBLENBREY7R0FYQTtBQUFBLEVBY0Esa0JBQWtCLENBQUMsSUFBbkIsQ0FBd0IsS0FBeEIsQ0FkQSxDQUFBO0FBQUEsRUFpQkEsbUJBQUEsR0FBc0IsU0FBQyxDQUFELEdBQUE7QUFDcEIsUUFBQSxlQUFBO0FBQUE7U0FBQSxTQUFBO3NCQUFBO0FBQ0Usb0JBQUE7QUFBQSxRQUFBLElBQUEsRUFBTSxJQUFOO0FBQUEsUUFDQSxLQUFBLEVBQU8sS0FEUDtRQUFBLENBREY7QUFBQTtvQkFEb0I7RUFBQSxDQWpCdEIsQ0FBQTtBQUFBLEVBcUJBLGtCQUFBLEdBQXFCLFNBQUMsQ0FBRCxHQUFBO0FBQ25CLFFBQUEseUJBQUE7QUFBQSxJQUFBLFlBQUEsR0FBZSxFQUFmLENBQUE7QUFDQSxTQUFBLHdDQUFBO2dCQUFBO0FBQ0UsTUFBQSxZQUFhLENBQUEsQ0FBQyxDQUFDLElBQUYsQ0FBYixHQUF1QixDQUFDLENBQUMsS0FBekIsQ0FERjtBQUFBLEtBREE7V0FHQSxhQUptQjtFQUFBLENBckJyQixDQUFBO0FBQUEsRUEyQkEsY0FBQSxHQUFpQixTQUFBLEdBQUE7V0FDZixtQkFBQSxDQUFvQixFQUFFLENBQUMsbUJBQUgsQ0FBQSxDQUFwQixFQURlO0VBQUEsQ0EzQmpCLENBQUE7QUFBQSxFQThCQSxLQUFBLEdBQVEsU0FBQyxDQUFELEdBQUE7QUFDTixRQUFBLHNCQUFBO0FBQUEsSUFBQSxZQUFBLEdBQWUsa0JBQUEsQ0FBbUIsQ0FBbkIsQ0FBZixDQUFBO0FBQUEsSUFDQSxFQUFBLEdBQUssRUFBRSxDQUFDLE9BQUgsQ0FBVyxZQUFYLENBREwsQ0FBQTtBQUFBLElBRUEsSUFBQSxHQUNFO0FBQUEsTUFBQSxFQUFBLEVBQUksRUFBSjtBQUFBLE1BQ0EsWUFBQSxFQUFjLG1CQUFBLENBQW9CLEVBQUUsQ0FBQyxtQkFBSCxDQUFBLENBQXBCLENBRGQ7S0FIRixDQUFBO1dBS0EsS0FOTTtFQUFBLENBOUJSLENBQUE7QUFBQSxFQXNDQSxPQUFBLEdBQVUsU0FBQyxFQUFELEVBQUssTUFBTCxHQUFBO1dBQ1IsTUFBTSxDQUFDLE9BQVAsQ0FBZSxFQUFmLEVBQW1CLE1BQW5CLEVBRFE7RUFBQSxDQXRDVixDQUFBO0FBQUEsRUF5Q0EsU0FBUyxDQUFDLGNBQVYsR0FBMkIsY0F6QzNCLENBQUE7QUFBQSxFQTBDQSxTQUFTLENBQUMsS0FBVixHQUFrQixLQTFDbEIsQ0FBQTtBQUFBLEVBMkNBLFNBQVMsQ0FBQyxPQUFWLEdBQW9CLE9BM0NwQixDQUFBOztJQTZDQSxTQUFTLENBQUMsbUJBQW9CO0dBN0M5QjtTQThDQSxTQUFTLENBQUMsZ0JBQWdCLENBQUMsSUFBM0IsQ0FBZ0MsU0FBQyxNQUFELEVBQVMsRUFBVCxHQUFBO0FBQzlCLElBQUEsSUFBRyxFQUFFLENBQUMsR0FBRyxDQUFDLE9BQVAsS0FBb0IsRUFBRSxDQUFDLFNBQUgsQ0FBQSxDQUF2QjthQUNFLE1BQU0sQ0FBQyxPQUFQLENBQWUsRUFBZixFQURGO0tBRDhCO0VBQUEsQ0FBaEMsRUFoRGU7QUFBQSxDQU5qQixDQUFBOztBQUFBLE1BMkRNLENBQUMsT0FBUCxHQUFpQixjQTNEakIsQ0FBQTs7OztBQ0FBLE1BQU0sQ0FBQyxPQUFQLEdBUUU7QUFBQSxFQUFBLElBQUEsRUFBTSxTQUFDLE9BQUQsR0FBQTtBQUNKLFFBQUEsR0FBQTtBQUFBLElBQUEsR0FBQSxHQUFNLENBQUEsU0FBQSxLQUFBLEdBQUE7YUFBQSxTQUFDLElBQUQsRUFBTyxPQUFQLEdBQUE7QUFDSixRQUFBLElBQUcscUJBQUg7QUFDRSxVQUFBLElBQUcsQ0FBSyxlQUFMLENBQUEsSUFBa0IsT0FBTyxDQUFDLElBQVIsQ0FBYSxTQUFDLENBQUQsR0FBQTttQkFBSyxDQUFBLEtBQUssT0FBUSxDQUFBLElBQUEsRUFBbEI7VUFBQSxDQUFiLENBQXJCO21CQUNFLEtBQUUsQ0FBQSxJQUFBLENBQUYsR0FBVSxPQUFRLENBQUEsSUFBQSxFQURwQjtXQUFBLE1BQUE7QUFHRSxrQkFBVSxJQUFBLEtBQUEsQ0FBTSxtQkFBQSxHQUFvQixJQUFwQixHQUF5Qiw0Q0FBekIsR0FBc0UsSUFBSSxDQUFDLE1BQUwsQ0FBWSxPQUFaLENBQTVFLENBQVYsQ0FIRjtXQURGO1NBQUEsTUFBQTtBQU1FLGdCQUFVLElBQUEsS0FBQSxDQUFNLG1CQUFBLEdBQW9CLElBQXBCLEdBQXlCLG9DQUEvQixDQUFWLENBTkY7U0FESTtNQUFBLEVBQUE7SUFBQSxDQUFBLENBQUEsQ0FBQSxJQUFBLENBQU4sQ0FBQTtBQUFBLElBU0EsR0FBQSxDQUFJLFlBQUosRUFBa0IsQ0FBQyxTQUFELEVBQVksY0FBWixDQUFsQixDQVRBLENBQUE7QUFBQSxJQVVBLEdBQUEsQ0FBSSxNQUFKLEVBQVksQ0FBQyxRQUFELEVBQVcsT0FBWCxDQUFaLENBVkEsQ0FBQTtBQUFBLElBV0EsR0FBQSxDQUFJLFNBQUosQ0FYQSxDQUFBOztNQVlBLElBQUMsQ0FBQSxlQUFnQixJQUFDLENBQUE7S0FabEI7QUFnQkEsSUFBQSxJQUFHLGtDQUFIO0FBQ0UsTUFBQSxJQUFDLENBQUEsa0JBQUQsR0FBc0IsT0FBTyxDQUFDLGtCQUE5QixDQURGO0tBQUEsTUFBQTtBQUdFLE1BQUEsSUFBQyxDQUFBLGtCQUFELEdBQXNCLElBQXRCLENBSEY7S0FoQkE7QUFzQkEsSUFBQSxJQUFHLElBQUMsQ0FBQSxJQUFELEtBQVMsUUFBWjtBQUNFLE1BQUEsSUFBQyxDQUFBLFVBQUQsR0FBYyxTQUFkLENBREY7S0F0QkE7QUFBQSxJQTBCQSxJQUFDLENBQUEsU0FBRCxHQUFhLEtBMUJiLENBQUE7QUFBQSxJQTRCQSxJQUFDLENBQUEsV0FBRCxHQUFlLEVBNUJmLENBQUE7O01BOEJBLElBQUMsQ0FBQSxtQkFBb0I7S0E5QnJCO0FBQUEsSUFpQ0EsSUFBQyxDQUFBLFdBQUQsR0FBZSxFQWpDZixDQUFBO0FBQUEsSUFrQ0EsSUFBQyxDQUFBLG1CQUFELEdBQXVCLElBbEN2QixDQUFBO0FBQUEsSUFtQ0EsSUFBQyxDQUFBLG9CQUFELEdBQXdCLEtBbkN4QixDQUFBO1dBb0NBLElBQUMsQ0FBQSxjQUFELEdBQWtCLEtBckNkO0VBQUEsQ0FBTjtBQUFBLEVBdUNBLFdBQUEsRUFBYSxTQUFDLENBQUQsR0FBQTs7TUFDWCxJQUFDLENBQUEsd0JBQXlCO0tBQTFCO1dBQ0EsSUFBQyxDQUFBLHFCQUFxQixDQUFDLElBQXZCLENBQTRCLENBQTVCLEVBRlc7RUFBQSxDQXZDYjtBQUFBLEVBMkNBLFlBQUEsRUFBYyxTQUFBLEdBQUE7V0FDWixJQUFDLENBQUEsSUFBRCxLQUFTLFNBREc7RUFBQSxDQTNDZDtBQUFBLEVBOENBLFdBQUEsRUFBYSxTQUFBLEdBQUE7V0FDWCxJQUFDLENBQUEsSUFBRCxLQUFTLFFBREU7RUFBQSxDQTlDYjtBQUFBLEVBaURBLGlCQUFBLEVBQW1CLFNBQUEsR0FBQTtBQUNqQixRQUFBLGFBQUE7QUFBQSxJQUFBLElBQUMsQ0FBQSxtQkFBRCxHQUF1QixJQUF2QixDQUFBO0FBQ0EsSUFBQSxJQUFHLElBQUMsQ0FBQSxVQUFELEtBQWUsU0FBbEI7QUFDRTtBQUFBLFdBQUEsWUFBQTt1QkFBQTtBQUNFLFFBQUEsSUFBRyxDQUFBLENBQUssQ0FBQyxTQUFUO0FBQ0UsVUFBQSxJQUFDLENBQUEsV0FBRCxDQUFhLElBQWIsQ0FBQSxDQUFBO0FBQ0EsZ0JBRkY7U0FERjtBQUFBLE9BREY7S0FEQTtBQU1BLElBQUEsSUFBTyxnQ0FBUDtBQUNFLE1BQUEsSUFBQyxDQUFBLGNBQUQsQ0FBQSxDQUFBLENBREY7S0FOQTtXQVFBLEtBVGlCO0VBQUEsQ0FqRG5CO0FBQUEsRUE0REEsUUFBQSxFQUFVLFNBQUMsSUFBRCxHQUFBO0FBQ1IsUUFBQSwyQkFBQTtBQUFBLElBQUEsTUFBQSxDQUFBLElBQVEsQ0FBQSxXQUFZLENBQUEsSUFBQSxDQUFwQixDQUFBO0FBQUEsSUFDQSxJQUFDLENBQUEsaUJBQUQsQ0FBQSxDQURBLENBQUE7QUFFQSxJQUFBLElBQUcsa0NBQUg7QUFDRTtBQUFBO1dBQUEsMkNBQUE7cUJBQUE7QUFDRSxzQkFBQSxDQUFBLENBQUU7QUFBQSxVQUNBLE1BQUEsRUFBUSxVQURSO0FBQUEsVUFFQSxJQUFBLEVBQU0sSUFGTjtTQUFGLEVBQUEsQ0FERjtBQUFBO3NCQURGO0tBSFE7RUFBQSxDQTVEVjtBQUFBLEVBdUVBLFVBQUEsRUFBWSxTQUFDLElBQUQsRUFBTyxJQUFQLEdBQUE7QUFDVixRQUFBLGtDQUFBO0FBQUEsSUFBQSxJQUFPLFlBQVA7QUFDRSxZQUFVLElBQUEsS0FBQSxDQUFNLDZGQUFOLENBQVYsQ0FERjtLQUFBOztXQUdhLENBQUEsSUFBQSxJQUFTO0tBSHRCO0FBQUEsSUFJQSxJQUFDLENBQUEsV0FBWSxDQUFBLElBQUEsQ0FBSyxDQUFDLFNBQW5CLEdBQStCLEtBSi9CLENBQUE7QUFNQSxJQUFBLElBQUcsQ0FBQyxDQUFBLElBQUssQ0FBQSxTQUFOLENBQUEsSUFBb0IsSUFBQyxDQUFBLFVBQUQsS0FBZSxTQUF0QztBQUNFLE1BQUEsSUFBRyxJQUFDLENBQUEsVUFBRCxLQUFlLFNBQWxCO0FBQ0UsUUFBQSxJQUFDLENBQUEsV0FBRCxDQUFhLElBQWIsQ0FBQSxDQURGO09BQUEsTUFFSyxJQUFHLElBQUEsS0FBUSxRQUFYO0FBRUgsUUFBQSxJQUFDLENBQUEscUJBQUQsQ0FBdUIsSUFBdkIsQ0FBQSxDQUZHO09BSFA7S0FOQTtBQWFBLElBQUEsSUFBRyxrQ0FBSDtBQUNFO0FBQUE7V0FBQSwyQ0FBQTtxQkFBQTtBQUNFLHNCQUFBLENBQUEsQ0FBRTtBQUFBLFVBQ0EsTUFBQSxFQUFRLFlBRFI7QUFBQSxVQUVBLElBQUEsRUFBTSxJQUZOO0FBQUEsVUFHQSxJQUFBLEVBQU0sSUFITjtTQUFGLEVBQUEsQ0FERjtBQUFBO3NCQURGO0tBZFU7RUFBQSxDQXZFWjtBQUFBLEVBaUdBLFVBQUEsRUFBWSxTQUFDLElBQUQsR0FBQTtBQUNWLElBQUEsSUFBRyxJQUFJLENBQUMsV0FBTCxLQUFvQixRQUF2QjtBQUNFLE1BQUEsSUFBQSxHQUFPLENBQUMsSUFBRCxDQUFQLENBREY7S0FBQTtBQUVBLElBQUEsSUFBRyxJQUFDLENBQUEsU0FBSjthQUNFLElBQUssQ0FBQSxDQUFBLENBQUUsQ0FBQyxLQUFSLENBQWMsSUFBZCxFQUFvQixJQUFLLFNBQXpCLEVBREY7S0FBQSxNQUFBOztRQUdFLElBQUMsQ0FBQSxzQkFBdUI7T0FBeEI7YUFDQSxJQUFDLENBQUEsbUJBQW1CLENBQUMsSUFBckIsQ0FBMEIsSUFBMUIsRUFKRjtLQUhVO0VBQUEsQ0FqR1o7QUFBQSxFQThHQSxTQUFBLEVBQVcsU0FBQyxDQUFELEdBQUE7V0FDVCxJQUFDLENBQUEsZ0JBQWdCLENBQUMsSUFBbEIsQ0FBdUIsQ0FBdkIsRUFEUztFQUFBLENBOUdYO0FBaUhBO0FBQUE7Ozs7Ozs7Ozs7OztLQWpIQTtBQUFBLEVBa0lBLFdBQUEsRUFBYSxTQUFDLElBQUQsR0FBQTtBQUNYLFFBQUEsb0JBQUE7QUFBQSxJQUFBLElBQU8sZ0NBQVA7QUFDRSxNQUFBLElBQUMsQ0FBQSxtQkFBRCxHQUF1QixJQUF2QixDQUFBO0FBQUEsTUFDQSxJQUFDLENBQUEsSUFBRCxDQUFNLElBQU4sRUFDRTtBQUFBLFFBQUEsU0FBQSxFQUFXLE9BQVg7QUFBQSxRQUNBLFVBQUEsRUFBWSxNQURaO0FBQUEsUUFFQSxJQUFBLEVBQU0sSUFBQyxDQUFBLGNBQUQsQ0FBQSxDQUZOO09BREYsQ0FEQSxDQUFBO0FBS0EsTUFBQSxJQUFHLENBQUEsSUFBSyxDQUFBLG9CQUFSO0FBQ0UsUUFBQSxJQUFDLENBQUEsb0JBQUQsR0FBd0IsSUFBeEIsQ0FBQTtBQUFBLFFBRUEsRUFBQSxHQUFLLElBQUMsQ0FBQSxLQUFELENBQU8sRUFBUCxDQUFVLENBQUMsRUFGaEIsQ0FBQTtBQUFBLFFBR0EsR0FBQSxHQUFNLEVBSE4sQ0FBQTtBQUlBLGFBQUEseUNBQUE7cUJBQUE7QUFDRSxVQUFBLEdBQUcsQ0FBQyxJQUFKLENBQVMsQ0FBVCxDQUFBLENBQUE7QUFDQSxVQUFBLElBQUcsR0FBRyxDQUFDLE1BQUosR0FBYSxFQUFoQjtBQUNFLFlBQUEsSUFBQyxDQUFBLFNBQUQsQ0FDRTtBQUFBLGNBQUEsU0FBQSxFQUFXLFVBQVg7QUFBQSxjQUNBLElBQUEsRUFBTSxHQUROO2FBREYsQ0FBQSxDQUFBO0FBQUEsWUFHQSxHQUFBLEdBQU0sRUFITixDQURGO1dBRkY7QUFBQSxTQUpBO2VBV0EsSUFBQyxDQUFBLFNBQUQsQ0FDRTtBQUFBLFVBQUEsU0FBQSxFQUFXLFNBQVg7QUFBQSxVQUNBLElBQUEsRUFBTSxHQUROO1NBREYsRUFaRjtPQU5GO0tBRFc7RUFBQSxDQWxJYjtBQUFBLEVBK0pBLHFCQUFBLEVBQXVCLFNBQUMsSUFBRCxHQUFBO0FBQ3JCLFFBQUEsb0JBQUE7QUFBQSxJQUFBLElBQUMsQ0FBQSxtQkFBRCxHQUF1QixJQUF2QixDQUFBO0FBQUEsSUFDQSxJQUFDLENBQUEsSUFBRCxDQUFNLElBQU4sRUFDRTtBQUFBLE1BQUEsU0FBQSxFQUFXLE9BQVg7QUFBQSxNQUNBLFVBQUEsRUFBWSxNQURaO0FBQUEsTUFFQSxJQUFBLEVBQU0sSUFBQyxDQUFBLGNBQUQsQ0FBQSxDQUZOO0tBREYsQ0FEQSxDQUFBO0FBQUEsSUFLQSxFQUFBLEdBQUssSUFBQyxDQUFBLEtBQUQsQ0FBTyxFQUFQLENBQVUsQ0FBQyxFQUxoQixDQUFBO0FBQUEsSUFNQSxHQUFBLEdBQU0sRUFOTixDQUFBO0FBT0EsU0FBQSx5Q0FBQTtpQkFBQTtBQUNFLE1BQUEsR0FBRyxDQUFDLElBQUosQ0FBUyxDQUFULENBQUEsQ0FBQTtBQUNBLE1BQUEsSUFBRyxHQUFHLENBQUMsTUFBSixHQUFhLEVBQWhCO0FBQ0UsUUFBQSxJQUFDLENBQUEsU0FBRCxDQUNFO0FBQUEsVUFBQSxTQUFBLEVBQVcsVUFBWDtBQUFBLFVBQ0EsSUFBQSxFQUFNLEdBRE47U0FERixDQUFBLENBQUE7QUFBQSxRQUdBLEdBQUEsR0FBTSxFQUhOLENBREY7T0FGRjtBQUFBLEtBUEE7V0FjQSxJQUFDLENBQUEsU0FBRCxDQUNFO0FBQUEsTUFBQSxTQUFBLEVBQVcsU0FBWDtBQUFBLE1BQ0EsSUFBQSxFQUFNLEdBRE47S0FERixFQWZxQjtFQUFBLENBL0p2QjtBQUFBLEVBcUxBLGNBQUEsRUFBZ0IsU0FBQSxHQUFBO0FBQ2QsUUFBQSwyQkFBQTtBQUFBLElBQUEsSUFBRyxDQUFBLElBQUssQ0FBQSxTQUFSO0FBQ0UsTUFBQSxJQUFDLENBQUEsU0FBRCxHQUFhLElBQWIsQ0FBQTtBQUNBLE1BQUEsSUFBRyxnQ0FBSDtBQUNFO0FBQUEsYUFBQSwyQ0FBQTt3QkFBQTtBQUNFLFVBQUEsQ0FBQSxHQUFJLEVBQUcsQ0FBQSxDQUFBLENBQVAsQ0FBQTtBQUFBLFVBQ0EsSUFBQSxHQUFPLEVBQUcsU0FEVixDQUFBO0FBQUEsVUFFQSxDQUFDLENBQUMsS0FBRixDQUFRLElBQVIsQ0FGQSxDQURGO0FBQUEsU0FBQTtBQUFBLFFBSUEsTUFBQSxDQUFBLElBQVEsQ0FBQSxtQkFKUixDQURGO09BREE7YUFPQSxLQVJGO0tBRGM7RUFBQSxDQXJMaEI7QUFBQSxFQWlNQSx1QkFBQSxFQUF5QixTQUFDLENBQUQsR0FBQTs7TUFDdkIsSUFBQyxDQUFBLHVDQUF3QztLQUF6QztXQUNBLElBQUMsQ0FBQSxvQ0FBb0MsQ0FBQyxJQUF0QyxDQUEyQyxDQUEzQyxFQUZ1QjtFQUFBLENBak16QjtBQUFBLEVBeU1BLGNBQUEsRUFBZ0IsU0FBQyxNQUFELEVBQVMsR0FBVCxHQUFBO0FBQ2QsUUFBQSxtR0FBQTtBQUFBLElBQUEsSUFBTyxxQkFBUDtBQUNFO0FBQUE7V0FBQSwyQ0FBQTtxQkFBQTtBQUNFLHNCQUFBLENBQUEsQ0FBRSxNQUFGLEVBQVUsR0FBVixFQUFBLENBREY7QUFBQTtzQkFERjtLQUFBLE1BQUE7QUFJRSxNQUFBLElBQUcsTUFBQSxLQUFVLElBQUMsQ0FBQSxPQUFkO0FBQ0UsY0FBQSxDQURGO09BQUE7QUFFQSxNQUFBLElBQUcsR0FBRyxDQUFDLFNBQUosS0FBaUIsT0FBcEI7QUFFRSxRQUFBLElBQUcsaURBQUg7QUFDRTtBQUFBLGVBQUEsOENBQUE7MEJBQUE7QUFDRSxZQUFBLENBQUMsQ0FBQyxJQUFGLENBQU8sSUFBUCxFQUFhLEdBQUcsQ0FBQyxJQUFqQixDQUFBLENBREY7QUFBQSxXQURGO1NBQUE7QUFBQSxRQUdBLE1BQUEsQ0FBQSxJQUFRLENBQUEsb0NBSFIsQ0FBQTtBQUFBLFFBS0EsSUFBQSxHQUFPLElBQUMsQ0FBQSxLQUFELENBQU8sR0FBRyxDQUFDLElBQVgsQ0FMUCxDQUFBO0FBQUEsUUFNQSxFQUFBLEdBQUssSUFBSSxDQUFDLEVBTlYsQ0FBQTtBQUFBLFFBT0EsR0FBQSxHQUFNLEVBUE4sQ0FBQTtBQWFBLFFBQUEsSUFBRyxJQUFDLENBQUEsU0FBSjtBQUNFLFVBQUEsV0FBQSxHQUFjLENBQUEsU0FBQSxLQUFBLEdBQUE7bUJBQUEsU0FBQyxDQUFELEdBQUE7cUJBQ1osS0FBQyxDQUFBLElBQUQsQ0FBTSxNQUFOLEVBQWMsQ0FBZCxFQURZO1lBQUEsRUFBQTtVQUFBLENBQUEsQ0FBQSxDQUFBLElBQUEsQ0FBZCxDQURGO1NBQUEsTUFBQTtBQUlFLFVBQUEsV0FBQSxHQUFjLENBQUEsU0FBQSxLQUFBLEdBQUE7bUJBQUEsU0FBQyxDQUFELEdBQUE7cUJBQ1osS0FBQyxDQUFBLFNBQUQsQ0FBVyxDQUFYLEVBRFk7WUFBQSxFQUFBO1VBQUEsQ0FBQSxDQUFBLENBQUEsSUFBQSxDQUFkLENBSkY7U0FiQTtBQW9CQSxhQUFBLDJDQUFBO3FCQUFBO0FBQ0UsVUFBQSxHQUFHLENBQUMsSUFBSixDQUFTLENBQVQsQ0FBQSxDQUFBO0FBQ0EsVUFBQSxJQUFHLEdBQUcsQ0FBQyxNQUFKLEdBQWEsRUFBaEI7QUFDRSxZQUFBLFdBQUEsQ0FDRTtBQUFBLGNBQUEsU0FBQSxFQUFXLFVBQVg7QUFBQSxjQUNBLElBQUEsRUFBTSxHQUROO2FBREYsQ0FBQSxDQUFBO0FBQUEsWUFHQSxHQUFBLEdBQU0sRUFITixDQURGO1dBRkY7QUFBQSxTQXBCQTtBQUFBLFFBNEJBLFdBQUEsQ0FDRTtBQUFBLFVBQUEsU0FBQSxFQUFZLFNBQVo7QUFBQSxVQUNBLElBQUEsRUFBTSxHQUROO1NBREYsQ0E1QkEsQ0FBQTtBQWdDQSxRQUFBLElBQUcsd0JBQUEsSUFBb0IsSUFBQyxDQUFBLGtCQUF4QjtBQUNFLFVBQUEsVUFBQSxHQUFnQixDQUFBLFNBQUEsS0FBQSxHQUFBO21CQUFBLFNBQUMsRUFBRCxHQUFBO3FCQUNkLFNBQUEsR0FBQTtBQUNFLG9CQUFBLFNBQUE7QUFBQSxnQkFBQSxFQUFBLEdBQUssS0FBQyxDQUFBLEtBQUQsQ0FBTyxFQUFQLENBQVUsQ0FBQyxFQUFoQixDQUFBO0FBQ0EscUJBQUEsMkNBQUE7NkJBQUE7QUFDRSxrQkFBQSxHQUFHLENBQUMsSUFBSixDQUFTLENBQVQsQ0FBQSxDQUFBO0FBQ0Esa0JBQUEsSUFBRyxHQUFHLENBQUMsTUFBSixHQUFhLEVBQWhCO0FBQ0Usb0JBQUEsS0FBQyxDQUFBLElBQUQsQ0FBTSxNQUFOLEVBQ0U7QUFBQSxzQkFBQSxTQUFBLEVBQVcsVUFBWDtBQUFBLHNCQUNBLElBQUEsRUFBTSxHQUROO3FCQURGLENBQUEsQ0FBQTtBQUFBLG9CQUdBLEdBQUEsR0FBTSxFQUhOLENBREY7bUJBRkY7QUFBQSxpQkFEQTt1QkFRQSxLQUFDLENBQUEsSUFBRCxDQUFNLE1BQU4sRUFDRTtBQUFBLGtCQUFBLFNBQUEsRUFBVyxTQUFYO0FBQUEsa0JBQ0EsSUFBQSxFQUFNLEdBRE47QUFBQSxrQkFFQSxVQUFBLEVBQVksTUFGWjtpQkFERixFQVRGO2NBQUEsRUFEYztZQUFBLEVBQUE7VUFBQSxDQUFBLENBQUEsQ0FBQSxJQUFBLENBQUgsQ0FBUyxJQUFJLENBQUMsWUFBZCxDQUFiLENBQUE7aUJBY0EsVUFBQSxDQUFXLFVBQVgsRUFBdUIsSUFBdkIsRUFmRjtTQWxDRjtPQUFBLE1Ba0RLLElBQUcsR0FBRyxDQUFDLFNBQUosS0FBaUIsU0FBcEI7QUFDSCxRQUFBLElBQUMsQ0FBQSxPQUFELENBQVMsR0FBRyxDQUFDLElBQWIsRUFBbUIsTUFBQSxLQUFVLElBQUMsQ0FBQSxtQkFBOUIsQ0FBQSxDQUFBO0FBRUEsUUFBQSxJQUFHLENBQUMsSUFBQyxDQUFBLFVBQUQsS0FBZSxTQUFmLElBQTRCLHdCQUE3QixDQUFBLElBQWtELENBQUMsQ0FBQSxJQUFLLENBQUEsU0FBTixDQUFsRCxJQUF1RSxDQUFDLENBQUMsSUFBQyxDQUFBLG1CQUFELEtBQXdCLE1BQXpCLENBQUEsSUFBb0MsQ0FBSyxnQ0FBTCxDQUFyQyxDQUExRTtBQUNFLFVBQUEsSUFBQyxDQUFBLFdBQVksQ0FBQSxNQUFBLENBQU8sQ0FBQyxTQUFyQixHQUFpQyxJQUFqQyxDQUFBO2lCQUNBLElBQUMsQ0FBQSxpQkFBRCxDQUFBLEVBRkY7U0FIRztPQUFBLE1BT0EsSUFBRyxHQUFHLENBQUMsU0FBSixLQUFpQixVQUFwQjtlQUNILElBQUMsQ0FBQSxPQUFELENBQVMsR0FBRyxDQUFDLElBQWIsRUFBbUIsTUFBQSxLQUFVLElBQUMsQ0FBQSxtQkFBOUIsRUFERztPQS9EUDtLQURjO0VBQUEsQ0F6TWhCO0FBQUEsRUF3UkEsbUJBQUEsRUFBcUIsU0FBQyxDQUFELEdBQUE7QUFDbkIsUUFBQSx5QkFBQTtBQUFBLElBQUEsV0FBQSxHQUFjLFNBQUMsSUFBRCxHQUFBO0FBQ1osVUFBQSwyQkFBQTtBQUFBO0FBQUE7V0FBQSwyQ0FBQTtxQkFBQTtBQUNFLFFBQUEsSUFBRyxDQUFDLENBQUMsWUFBRixDQUFlLFNBQWYsQ0FBQSxLQUE2QixNQUFoQzt3QkFDRSxXQUFBLENBQVksQ0FBWixHQURGO1NBQUEsTUFBQTt3QkFHRSxZQUFBLENBQWEsQ0FBYixHQUhGO1NBREY7QUFBQTtzQkFEWTtJQUFBLENBQWQsQ0FBQTtBQUFBLElBT0EsWUFBQSxHQUFlLFNBQUMsSUFBRCxHQUFBO0FBQ2IsVUFBQSxnREFBQTtBQUFBLE1BQUEsSUFBQSxHQUFPLEVBQVAsQ0FBQTtBQUNBO0FBQUEsV0FBQSxZQUFBOzJCQUFBO0FBQ0UsUUFBQSxHQUFBLEdBQU0sUUFBQSxDQUFTLEtBQVQsQ0FBTixDQUFBO0FBQ0EsUUFBQSxJQUFHLEtBQUEsQ0FBTSxHQUFOLENBQUEsSUFBYyxDQUFDLEVBQUEsR0FBRyxHQUFKLENBQUEsS0FBYyxLQUEvQjtBQUNFLFVBQUEsSUFBSyxDQUFBLElBQUEsQ0FBTCxHQUFhLEtBQWIsQ0FERjtTQUFBLE1BQUE7QUFHRSxVQUFBLElBQUssQ0FBQSxJQUFBLENBQUwsR0FBYSxHQUFiLENBSEY7U0FGRjtBQUFBLE9BREE7QUFPQTtBQUFBLFdBQUEsNENBQUE7c0JBQUE7QUFDRSxRQUFBLElBQUEsR0FBTyxDQUFDLENBQUMsSUFBVCxDQUFBO0FBQ0EsUUFBQSxJQUFHLENBQUMsQ0FBQyxZQUFGLENBQWUsU0FBZixDQUFBLEtBQTZCLE1BQWhDO0FBQ0UsVUFBQSxJQUFLLENBQUEsSUFBQSxDQUFMLEdBQWEsV0FBQSxDQUFZLENBQVosQ0FBYixDQURGO1NBQUEsTUFBQTtBQUdFLFVBQUEsSUFBSyxDQUFBLElBQUEsQ0FBTCxHQUFhLFlBQUEsQ0FBYSxDQUFiLENBQWIsQ0FIRjtTQUZGO0FBQUEsT0FQQTthQWFBLEtBZGE7SUFBQSxDQVBmLENBQUE7V0FzQkEsWUFBQSxDQUFhLENBQWIsRUF2Qm1CO0VBQUEsQ0F4UnJCO0FBQUEsRUEwVEEsa0JBQUEsRUFBb0IsU0FBQyxDQUFELEVBQUksSUFBSixHQUFBO0FBRWxCLFFBQUEsMkJBQUE7QUFBQSxJQUFBLGFBQUEsR0FBZ0IsU0FBQyxDQUFELEVBQUksSUFBSixHQUFBO0FBQ2QsVUFBQSxXQUFBO0FBQUEsV0FBQSxZQUFBOzJCQUFBO0FBQ0UsUUFBQSxJQUFPLGFBQVA7QUFBQTtTQUFBLE1BRUssSUFBRyxLQUFLLENBQUMsV0FBTixLQUFxQixNQUF4QjtBQUNILFVBQUEsYUFBQSxDQUFjLENBQUMsQ0FBQyxDQUFGLENBQUksSUFBSixDQUFkLEVBQXlCLEtBQXpCLENBQUEsQ0FERztTQUFBLE1BRUEsSUFBRyxLQUFLLENBQUMsV0FBTixLQUFxQixLQUF4QjtBQUNILFVBQUEsWUFBQSxDQUFhLENBQUMsQ0FBQyxDQUFGLENBQUksSUFBSixDQUFiLEVBQXdCLEtBQXhCLENBQUEsQ0FERztTQUFBLE1BQUE7QUFHSCxVQUFBLENBQUMsQ0FBQyxZQUFGLENBQWUsSUFBZixFQUFvQixLQUFwQixDQUFBLENBSEc7U0FMUDtBQUFBLE9BQUE7YUFTQSxFQVZjO0lBQUEsQ0FBaEIsQ0FBQTtBQUFBLElBV0EsWUFBQSxHQUFlLFNBQUMsQ0FBRCxFQUFJLEtBQUosR0FBQTtBQUNiLFVBQUEsV0FBQTtBQUFBLE1BQUEsQ0FBQyxDQUFDLFlBQUYsQ0FBZSxTQUFmLEVBQXlCLE1BQXpCLENBQUEsQ0FBQTtBQUNBLFdBQUEsNENBQUE7c0JBQUE7QUFDRSxRQUFBLElBQUcsQ0FBQyxDQUFDLFdBQUYsS0FBaUIsTUFBcEI7QUFDRSxVQUFBLGFBQUEsQ0FBYyxDQUFDLENBQUMsQ0FBRixDQUFJLGVBQUosQ0FBZCxFQUFvQyxDQUFwQyxDQUFBLENBREY7U0FBQSxNQUFBO0FBR0UsVUFBQSxZQUFBLENBQWEsQ0FBQyxDQUFDLENBQUYsQ0FBSSxlQUFKLENBQWIsRUFBbUMsQ0FBbkMsQ0FBQSxDQUhGO1NBREY7QUFBQSxPQURBO2FBTUEsRUFQYTtJQUFBLENBWGYsQ0FBQTtBQW1CQSxJQUFBLElBQUcsSUFBSSxDQUFDLFdBQUwsS0FBb0IsTUFBdkI7YUFDRSxhQUFBLENBQWMsQ0FBQyxDQUFDLENBQUYsQ0FBSSxHQUFKLEVBQVE7QUFBQSxRQUFDLEtBQUEsRUFBTSxpQ0FBUDtPQUFSLENBQWQsRUFBa0UsSUFBbEUsRUFERjtLQUFBLE1BRUssSUFBRyxJQUFJLENBQUMsV0FBTCxLQUFvQixLQUF2QjthQUNILFlBQUEsQ0FBYSxDQUFDLENBQUMsQ0FBRixDQUFJLEdBQUosRUFBUTtBQUFBLFFBQUMsS0FBQSxFQUFNLGlDQUFQO09BQVIsQ0FBYixFQUFpRSxJQUFqRSxFQURHO0tBQUEsTUFBQTtBQUdILFlBQVUsSUFBQSxLQUFBLENBQU0sMkJBQU4sQ0FBVixDQUhHO0tBdkJhO0VBQUEsQ0ExVHBCO0FBQUEsRUFzVkEsYUFBQSxFQUFlLFNBQUEsR0FBQTs7TUFDYixJQUFDLENBQUE7S0FBRDtBQUFBLElBQ0EsTUFBQSxDQUFBLElBQVEsQ0FBQSxlQURSLENBQUE7V0FFQSxJQUFDLENBQUEsYUFBRCxHQUFpQixLQUhKO0VBQUEsQ0F0VmY7Q0FSRixDQUFBOzs7O0FDQUEsSUFBQSxNQUFBOzs7RUFBQSxNQUFNLENBQUUsbUJBQVIsR0FBOEI7Q0FBOUI7OztFQUNBLE1BQU0sQ0FBRSx3QkFBUixHQUFtQztDQURuQzs7O0VBRUEsTUFBTSxDQUFFLGlCQUFSLEdBQTRCO0NBRjVCOztBQUFBO0FBY2UsRUFBQSxnQkFBRSxFQUFGLEVBQU8sS0FBUCxHQUFBO0FBQ1gsSUFEWSxJQUFDLENBQUEsS0FBQSxFQUNiLENBQUE7QUFBQSxJQURpQixJQUFDLENBQUEsUUFBQSxLQUNsQixDQUFBO0FBQUEsSUFBQSxJQUFDLENBQUEsZUFBRCxHQUFtQixFQUFuQixDQURXO0VBQUEsQ0FBYjs7QUFBQSxtQkFNQSxjQUFBLEdBQWdCLFNBQUMsSUFBRCxHQUFBO0FBQ2QsUUFBQSxJQUFBO0FBQUEsSUFBQSxJQUFBLEdBQU8sSUFBQyxDQUFBLEtBQU0sQ0FBQSxJQUFJLENBQUMsSUFBTCxDQUFkLENBQUE7QUFDQSxJQUFBLElBQUcsNENBQUg7YUFDRSxJQUFJLENBQUMsS0FBTCxDQUFXLElBQVgsRUFERjtLQUFBLE1BQUE7QUFHRSxZQUFVLElBQUEsS0FBQSxDQUFPLDBDQUFBLEdBQXlDLElBQUksQ0FBQyxJQUE5QyxHQUFvRCxtQkFBcEQsR0FBc0UsQ0FBQSxJQUFJLENBQUMsU0FBTCxDQUFlLElBQWYsQ0FBQSxDQUF0RSxHQUEyRixHQUFsRyxDQUFWLENBSEY7S0FGYztFQUFBLENBTmhCLENBQUE7O0FBaUJBO0FBQUE7Ozs7Ozs7OztLQWpCQTs7QUFBQSxtQkFnQ0EsbUJBQUEsR0FBcUIsU0FBQyxRQUFELEdBQUE7QUFDbkIsUUFBQSxxQkFBQTtBQUFBO1NBQUEsK0NBQUE7dUJBQUE7QUFDRSxNQUFBLElBQU8sbUNBQVA7c0JBQ0UsSUFBQyxDQUFBLE9BQUQsQ0FBUyxDQUFULEdBREY7T0FBQSxNQUFBOzhCQUFBO09BREY7QUFBQTtvQkFEbUI7RUFBQSxDQWhDckIsQ0FBQTs7QUFBQSxtQkF3Q0EsUUFBQSxHQUFVLFNBQUMsUUFBRCxHQUFBO1dBQ1IsSUFBQyxDQUFBLE9BQUQsQ0FBUyxRQUFULEVBRFE7RUFBQSxDQXhDVixDQUFBOztBQUFBLG1CQWdEQSxPQUFBLEdBQVMsU0FBQyxhQUFELEVBQWdCLE1BQWhCLEdBQUE7QUFDUCxRQUFBLG9CQUFBOztNQUR1QixTQUFTO0tBQ2hDO0FBQUEsSUFBQSxJQUFHLGFBQWEsQ0FBQyxXQUFkLEtBQStCLEtBQWxDO0FBQ0UsTUFBQSxhQUFBLEdBQWdCLENBQUMsYUFBRCxDQUFoQixDQURGO0tBQUE7QUFFQSxTQUFBLG9EQUFBO2tDQUFBO0FBQ0UsTUFBQSxJQUFHLE1BQUg7QUFDRSxRQUFBLE9BQU8sQ0FBQyxNQUFSLEdBQWlCLE1BQWpCLENBREY7T0FBQTtBQUFBLE1BR0EsQ0FBQSxHQUFJLElBQUMsQ0FBQSxjQUFELENBQWdCLE9BQWhCLENBSEosQ0FBQTtBQUFBLE1BSUEsQ0FBQyxDQUFDLGdCQUFGLEdBQXFCLE9BSnJCLENBQUE7QUFLQSxNQUFBLElBQUcsc0JBQUg7QUFDRSxRQUFBLENBQUMsQ0FBQyxNQUFGLEdBQVcsT0FBTyxDQUFDLE1BQW5CLENBREY7T0FMQTtBQVFBLE1BQUEsSUFBRywrQkFBSDtBQUFBO09BQUEsTUFFSyxJQUFHLENBQUMsQ0FBQyxDQUFBLElBQUssQ0FBQSxFQUFFLENBQUMsbUJBQUosQ0FBd0IsQ0FBeEIsQ0FBTCxDQUFBLElBQXFDLENBQUssZ0JBQUwsQ0FBdEMsQ0FBQSxJQUEwRCxDQUFDLENBQUEsQ0FBSyxDQUFDLE9BQUYsQ0FBQSxDQUFMLENBQTdEO0FBQ0gsUUFBQSxJQUFDLENBQUEsZUFBZSxDQUFDLElBQWpCLENBQXNCLENBQXRCLENBQUEsQ0FBQTs7VUFDQSxNQUFNLENBQUUsaUJBQWlCLENBQUMsSUFBMUIsQ0FBK0IsQ0FBQyxDQUFDLElBQWpDO1NBRkc7T0FYUDtBQUFBLEtBRkE7V0FnQkEsSUFBQyxDQUFBLGNBQUQsQ0FBQSxFQWpCTztFQUFBLENBaERULENBQUE7O0FBQUEsbUJBdUVBLGNBQUEsR0FBZ0IsU0FBQSxHQUFBO0FBQ2QsUUFBQSwyQ0FBQTtBQUFBLFdBQU0sSUFBTixHQUFBO0FBQ0UsTUFBQSxVQUFBLEdBQWEsSUFBQyxDQUFBLGVBQWUsQ0FBQyxNQUE5QixDQUFBO0FBQUEsTUFDQSxXQUFBLEdBQWMsRUFEZCxDQUFBO0FBRUE7QUFBQSxXQUFBLDJDQUFBO3NCQUFBO0FBQ0UsUUFBQSxJQUFHLGdDQUFIO0FBQUE7U0FBQSxNQUVLLElBQUcsQ0FBQyxDQUFBLElBQUssQ0FBQSxFQUFFLENBQUMsbUJBQUosQ0FBd0IsRUFBeEIsQ0FBSixJQUFvQyxDQUFLLGlCQUFMLENBQXJDLENBQUEsSUFBMEQsQ0FBQyxDQUFBLEVBQU0sQ0FBQyxPQUFILENBQUEsQ0FBTCxDQUE3RDtBQUNILFVBQUEsV0FBVyxDQUFDLElBQVosQ0FBaUIsRUFBakIsQ0FBQSxDQURHO1NBSFA7QUFBQSxPQUZBO0FBQUEsTUFPQSxJQUFDLENBQUEsZUFBRCxHQUFtQixXQVBuQixDQUFBO0FBUUEsTUFBQSxJQUFHLElBQUMsQ0FBQSxlQUFlLENBQUMsTUFBakIsS0FBMkIsVUFBOUI7QUFDRSxjQURGO09BVEY7SUFBQSxDQUFBO0FBV0EsSUFBQSxJQUFHLElBQUMsQ0FBQSxlQUFlLENBQUMsTUFBakIsS0FBNkIsQ0FBaEM7YUFDRSxJQUFDLENBQUEsRUFBRSxDQUFDLFVBQUosQ0FBQSxFQURGO0tBWmM7RUFBQSxDQXZFaEIsQ0FBQTs7Z0JBQUE7O0lBZEYsQ0FBQTs7QUFBQSxNQXFHTSxDQUFDLE9BQVAsR0FBaUIsTUFyR2pCLENBQUE7Ozs7QUNNQSxJQUFBLGFBQUE7RUFBQSxrRkFBQTs7QUFBQTtBQU1lLEVBQUEsdUJBQUUsT0FBRixHQUFBO0FBQ1gsSUFEWSxJQUFDLENBQUEsVUFBQSxPQUNiLENBQUE7QUFBQSx1REFBQSxDQUFBO0FBQUEsSUFBQSxJQUFDLENBQUEsaUJBQUQsR0FBcUIsRUFBckIsQ0FBQTtBQUFBLElBQ0EsSUFBQyxDQUFBLE1BQUQsR0FBVSxFQURWLENBQUE7QUFBQSxJQUVBLElBQUMsQ0FBQSxnQkFBRCxHQUFvQixFQUZwQixDQUFBO0FBQUEsSUFHQSxJQUFDLENBQUEsT0FBRCxHQUFXLEVBSFgsQ0FBQTtBQUFBLElBSUEsSUFBQyxDQUFBLEtBQUQsR0FBUyxFQUpULENBQUE7QUFBQSxJQUtBLElBQUMsQ0FBQSx3QkFBRCxHQUE0QixJQUw1QixDQUFBO0FBQUEsSUFNQSxJQUFDLENBQUEscUJBQUQsR0FBeUIsS0FOekIsQ0FBQTtBQUFBLElBT0EsSUFBQyxDQUFBLDJCQUFELEdBQStCLENBUC9CLENBQUE7QUFBQSxJQVFBLFVBQUEsQ0FBVyxJQUFDLENBQUEsWUFBWixFQUEwQixJQUFDLENBQUEscUJBQTNCLENBUkEsQ0FEVztFQUFBLENBQWI7O0FBQUEsMEJBaUJBLFNBQUEsR0FBVyxTQUFFLE9BQUYsRUFBVyxZQUFYLEdBQUE7QUFDVCxRQUFBLGlEQUFBO0FBQUEsSUFEVSxJQUFDLENBQUEsVUFBQSxPQUNYLENBQUE7O3FCQUFxQjtLQUFyQjtBQUFBLElBQ0EsSUFBQSxHQUFPLElBQUMsQ0FBQSxNQUFPLENBQUEsSUFBQyxDQUFBLE9BQUQsQ0FEZixDQUFBO0FBQUEsSUFNQSxZQUFBLEdBQWUsWUFBYSxDQUFBLElBQUMsQ0FBQSxPQUFELENBQWIsSUFBMEIsQ0FOekMsQ0FBQTtBQVFBLElBQUEsSUFBRyx5QkFBSDtBQUNFO0FBQUEsV0FBQSxjQUFBO3lCQUFBO0FBQ0UsUUFBQSxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU4sR0FBZ0IsSUFBQyxDQUFBLE9BQWpCLENBQUE7QUFBQSxRQUNBLENBQUMsQ0FBQyxHQUFHLENBQUMsU0FBTixJQUFtQixZQURuQixDQUFBO0FBQUEsUUFFQSxJQUFLLENBQUEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxTQUFOLENBQUwsR0FBd0IsQ0FGeEIsQ0FERjtBQUFBLE9BREY7S0FSQTtBQUFBLElBY0EsSUFBQyxDQUFBLGlCQUFrQixDQUFBLElBQUMsQ0FBQSxPQUFELENBQW5CLEdBQStCLENBQUMsSUFBQyxDQUFBLGlCQUFpQixDQUFDLEtBQW5CLElBQTRCLENBQTdCLENBQUEsR0FBa0MsWUFkakUsQ0FBQTtBQUFBLElBZ0JBLE1BQUEsQ0FBQSxJQUFRLENBQUEsaUJBQWlCLENBQUMsS0FoQjFCLENBQUE7V0FpQkEsTUFBQSxDQUFBLElBQVEsQ0FBQSxNQUFNLENBQUMsTUFsQk47RUFBQSxDQWpCWCxDQUFBOztBQUFBLDBCQXNDQSxZQUFBLEdBQWMsU0FBQSxHQUFBO0FBQ1osUUFBQSxpQkFBQTtBQUFBO0FBQUEsU0FBQSwyQ0FBQTttQkFBQTs7UUFFRSxDQUFDLENBQUM7T0FGSjtBQUFBLEtBQUE7QUFBQSxJQUlBLElBQUMsQ0FBQSxPQUFELEdBQVcsSUFBQyxDQUFBLEtBSlosQ0FBQTtBQUFBLElBS0EsSUFBQyxDQUFBLEtBQUQsR0FBUyxFQUxULENBQUE7QUFNQSxJQUFBLElBQUcsSUFBQyxDQUFBLHFCQUFELEtBQTRCLENBQUEsQ0FBL0I7QUFDRSxNQUFBLElBQUMsQ0FBQSx1QkFBRCxHQUEyQixVQUFBLENBQVcsSUFBQyxDQUFBLFlBQVosRUFBMEIsSUFBQyxDQUFBLHFCQUEzQixDQUEzQixDQURGO0tBTkE7V0FRQSxPQVRZO0VBQUEsQ0F0Q2QsQ0FBQTs7QUFBQSwwQkFvREEsU0FBQSxHQUFXLFNBQUEsR0FBQTtXQUNULElBQUMsQ0FBQSxRQURRO0VBQUEsQ0FwRFgsQ0FBQTs7QUFBQSwwQkF1REEscUJBQUEsR0FBdUIsU0FBQSxHQUFBO0FBQ3JCLFFBQUEscUJBQUE7QUFBQSxJQUFBLElBQUcsSUFBQyxDQUFBLHdCQUFKO0FBQ0U7V0FBQSxnREFBQTswQkFBQTtBQUNFLFFBQUEsSUFBRyxTQUFIO3dCQUNFLElBQUMsQ0FBQSxPQUFPLENBQUMsSUFBVCxDQUFjLENBQWQsR0FERjtTQUFBLE1BQUE7Z0NBQUE7U0FERjtBQUFBO3NCQURGO0tBRHFCO0VBQUEsQ0F2RHZCLENBQUE7O0FBQUEsMEJBNkRBLHFCQUFBLEdBQXVCLFNBQUEsR0FBQTtBQUNyQixJQUFBLElBQUMsQ0FBQSx3QkFBRCxHQUE0QixLQUE1QixDQUFBO0FBQUEsSUFDQSxJQUFDLENBQUEsdUJBQUQsQ0FBQSxDQURBLENBQUE7QUFBQSxJQUVBLElBQUMsQ0FBQSxPQUFELEdBQVcsRUFGWCxDQUFBO1dBR0EsSUFBQyxDQUFBLEtBQUQsR0FBUyxHQUpZO0VBQUEsQ0E3RHZCLENBQUE7O0FBQUEsMEJBbUVBLHVCQUFBLEdBQXlCLFNBQUEsR0FBQTtBQUN2QixJQUFBLElBQUMsQ0FBQSxxQkFBRCxHQUF5QixDQUFBLENBQXpCLENBQUE7QUFBQSxJQUNBLFlBQUEsQ0FBYSxJQUFDLENBQUEsdUJBQWQsQ0FEQSxDQUFBO1dBRUEsSUFBQyxDQUFBLHVCQUFELEdBQTJCLE9BSEo7RUFBQSxDQW5FekIsQ0FBQTs7QUFBQSwwQkF3RUEsd0JBQUEsR0FBMEIsU0FBRSxxQkFBRixHQUFBO0FBQXlCLElBQXhCLElBQUMsQ0FBQSx3QkFBQSxxQkFBdUIsQ0FBekI7RUFBQSxDQXhFMUIsQ0FBQTs7QUFBQSwwQkErRUEsMkJBQUEsR0FBNkIsU0FBQSxHQUFBO1dBQzNCO0FBQUEsTUFDRSxPQUFBLEVBQVUsR0FEWjtBQUFBLE1BRUUsU0FBQSxFQUFhLEdBQUEsR0FBRSxDQUFBLElBQUMsQ0FBQSwyQkFBRCxFQUFBLENBRmpCO01BRDJCO0VBQUEsQ0EvRTdCLENBQUE7O0FBQUEsMEJBd0ZBLG1CQUFBLEdBQXFCLFNBQUMsT0FBRCxHQUFBO0FBQ25CLFFBQUEsb0JBQUE7QUFBQSxJQUFBLElBQU8sZUFBUDtBQUNFLE1BQUEsR0FBQSxHQUFNLEVBQU4sQ0FBQTtBQUNBO0FBQUEsV0FBQSxZQUFBO3lCQUFBO0FBQ0UsUUFBQSxHQUFJLENBQUEsSUFBQSxDQUFKLEdBQVksR0FBWixDQURGO0FBQUEsT0FEQTthQUdBLElBSkY7S0FBQSxNQUFBO2FBTUUsSUFBQyxDQUFBLGlCQUFrQixDQUFBLE9BQUEsRUFOckI7S0FEbUI7RUFBQSxDQXhGckIsQ0FBQTs7QUFBQSwwQkFpR0EsbUJBQUEsR0FBcUIsU0FBQyxDQUFELEdBQUE7QUFDbkIsUUFBQSxZQUFBOztxQkFBcUM7S0FBckM7QUFBQSxJQUNBLENBQUMsQ0FBQyxHQUFHLENBQUMsU0FBTixJQUFtQixJQUFDLENBQUEsaUJBQWtCLENBQUEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFOLENBRHRDLENBQUE7V0FFQSxLQUhtQjtFQUFBLENBakdyQixDQUFBOztBQUFBLDBCQXlHQSxPQUFBLEdBQVMsU0FBQyxZQUFELEdBQUE7QUFDUCxRQUFBLHNFQUFBOztNQURRLGVBQWE7S0FDckI7QUFBQSxJQUFBLElBQUEsR0FBTyxFQUFQLENBQUE7QUFBQSxJQUNBLE9BQUEsR0FBVSxTQUFDLElBQUQsRUFBTyxRQUFQLEdBQUE7QUFDUixNQUFBLElBQUcsQ0FBSyxZQUFMLENBQUEsSUFBZSxDQUFLLGdCQUFMLENBQWxCO0FBQ0UsY0FBVSxJQUFBLEtBQUEsQ0FBTSxNQUFOLENBQVYsQ0FERjtPQUFBO2FBRUksNEJBQUosSUFBMkIsWUFBYSxDQUFBLElBQUEsQ0FBYixJQUFzQixTQUh6QztJQUFBLENBRFYsQ0FBQTtBQU1BO0FBQUEsU0FBQSxjQUFBOzBCQUFBO0FBRUUsTUFBQSxJQUFHLE1BQUEsS0FBVSxHQUFiO0FBQ0UsaUJBREY7T0FBQTtBQUVBLFdBQUEsZ0JBQUE7MkJBQUE7QUFDRSxRQUFBLElBQUcsQ0FBSyx5QkFBTCxDQUFBLElBQTZCLE9BQUEsQ0FBUSxNQUFSLEVBQWdCLFFBQWhCLENBQWhDO0FBRUUsVUFBQSxNQUFBLEdBQVMsQ0FBQyxDQUFDLE9BQUYsQ0FBQSxDQUFULENBQUE7QUFDQSxVQUFBLElBQUcsaUJBQUg7QUFFRSxZQUFBLE1BQUEsR0FBUyxDQUFDLENBQUMsT0FBWCxDQUFBO0FBQ0EsbUJBQU0sd0JBQUEsSUFBb0IsT0FBQSxDQUFRLE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FBbkIsRUFBNEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxTQUF2QyxDQUExQixHQUFBO0FBQ0UsY0FBQSxNQUFBLEdBQVMsTUFBTSxDQUFDLE9BQWhCLENBREY7WUFBQSxDQURBO0FBQUEsWUFHQSxNQUFNLENBQUMsSUFBUCxHQUFjLE1BQU0sQ0FBQyxNQUFQLENBQUEsQ0FIZCxDQUZGO1dBQUEsTUFNSyxJQUFHLGlCQUFIO0FBRUgsWUFBQSxNQUFBLEdBQVMsQ0FBQyxDQUFDLE9BQVgsQ0FBQTtBQUNBLG1CQUFNLHdCQUFBLElBQW9CLE9BQUEsQ0FBUSxNQUFNLENBQUMsR0FBRyxDQUFDLE9BQW5CLEVBQTRCLE1BQU0sQ0FBQyxHQUFHLENBQUMsU0FBdkMsQ0FBMUIsR0FBQTtBQUNFLGNBQUEsTUFBQSxHQUFTLE1BQU0sQ0FBQyxPQUFoQixDQURGO1lBQUEsQ0FEQTtBQUFBLFlBR0EsTUFBTSxDQUFDLElBQVAsR0FBYyxNQUFNLENBQUMsTUFBUCxDQUFBLENBSGQsQ0FGRztXQVBMO0FBQUEsVUFhQSxJQUFJLENBQUMsSUFBTCxDQUFVLE1BQVYsQ0FiQSxDQUZGO1NBREY7QUFBQSxPQUpGO0FBQUEsS0FOQTtXQTRCQSxLQTdCTztFQUFBLENBekdULENBQUE7O0FBQUEsMEJBNklBLDBCQUFBLEdBQTRCLFNBQUMsT0FBRCxHQUFBO0FBQzFCLFFBQUEsR0FBQTtBQUFBLElBQUEsSUFBTyxlQUFQO0FBQ0UsTUFBQSxPQUFBLEdBQVUsSUFBQyxDQUFBLE9BQVgsQ0FERjtLQUFBO0FBRUEsSUFBQSxJQUFPLHVDQUFQO0FBQ0UsTUFBQSxJQUFDLENBQUEsaUJBQWtCLENBQUEsT0FBQSxDQUFuQixHQUE4QixDQUE5QixDQURGO0tBRkE7QUFBQSxJQUlBLEdBQUEsR0FDRTtBQUFBLE1BQUEsU0FBQSxFQUFZLE9BQVo7QUFBQSxNQUNBLFdBQUEsRUFBYyxJQUFDLENBQUEsaUJBQWtCLENBQUEsT0FBQSxDQURqQztLQUxGLENBQUE7QUFBQSxJQU9BLElBQUMsQ0FBQSxpQkFBa0IsQ0FBQSxPQUFBLENBQW5CLEVBUEEsQ0FBQTtXQVFBLElBVDBCO0VBQUEsQ0E3STVCLENBQUE7O0FBQUEsMEJBOEpBLFlBQUEsR0FBYyxTQUFDLEdBQUQsR0FBQTtBQUNaLFFBQUEsT0FBQTtBQUFBLElBQUEsSUFBRyxlQUFIO0FBQ0UsTUFBQSxHQUFBLEdBQU0sR0FBRyxDQUFDLEdBQVYsQ0FERjtLQUFBO0FBQUEsSUFFQSxDQUFBLG1EQUEwQixDQUFBLEdBQUcsQ0FBQyxTQUFKLFVBRjFCLENBQUE7QUFHQSxJQUFBLElBQUcsaUJBQUEsSUFBYSxXQUFoQjthQUNFLENBQUMsQ0FBQyxXQUFGLENBQWMsR0FBRyxDQUFDLEdBQWxCLEVBREY7S0FBQSxNQUFBO2FBR0UsRUFIRjtLQUpZO0VBQUEsQ0E5SmQsQ0FBQTs7QUFBQSwwQkEyS0EsWUFBQSxHQUFjLFNBQUMsQ0FBRCxHQUFBO0FBQ1osSUFBQSxJQUFPLGtDQUFQO0FBQ0UsTUFBQSxJQUFDLENBQUEsTUFBTyxDQUFBLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTixDQUFSLEdBQXlCLEVBQXpCLENBREY7S0FBQTtBQUVBLElBQUEsSUFBRyxtREFBSDtBQUNFLFlBQVUsSUFBQSxLQUFBLENBQU0sb0NBQU4sQ0FBVixDQURGO0tBRkE7QUFJQSxJQUFBLElBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxXQUFoQixLQUFpQyxNQUFsQyxDQUFBLElBQThDLENBQUMsQ0FBQSxJQUFLLENBQUEsbUJBQUQsQ0FBcUIsQ0FBckIsQ0FBTCxDQUE5QyxJQUFnRixDQUFLLGdCQUFMLENBQW5GO0FBQ0UsWUFBVSxJQUFBLEtBQUEsQ0FBTSxrQ0FBTixDQUFWLENBREY7S0FKQTtBQUFBLElBTUEsSUFBQyxDQUFBLFlBQUQsQ0FBYyxDQUFkLENBTkEsQ0FBQTtBQUFBLElBT0EsSUFBQyxDQUFBLE1BQU8sQ0FBQSxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU4sQ0FBZSxDQUFBLENBQUMsQ0FBQyxHQUFHLENBQUMsU0FBTixDQUF2QixHQUEwQyxDQVAxQyxDQUFBO1dBUUEsRUFUWTtFQUFBLENBM0tkLENBQUE7O0FBQUEsMEJBc0xBLGVBQUEsR0FBaUIsU0FBQyxDQUFELEdBQUE7QUFDZixRQUFBLElBQUE7eURBQUEsTUFBQSxDQUFBLElBQStCLENBQUEsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxTQUFOLFdBRGhCO0VBQUEsQ0F0TGpCLENBQUE7O0FBQUEsMEJBNExBLG9CQUFBLEdBQXNCLFNBQUMsQ0FBRCxHQUFBO1dBQ3BCLElBQUMsQ0FBQSxVQUFELEdBQWMsRUFETTtFQUFBLENBNUx0QixDQUFBOztBQUFBLDBCQWdNQSxVQUFBLEdBQVksU0FBQSxHQUFBLENBaE1aLENBQUE7O0FBQUEsMEJBb01BLGdCQUFBLEdBQWtCLFNBQUMsWUFBRCxHQUFBO0FBQ2hCLFFBQUEscUJBQUE7QUFBQTtTQUFBLG9CQUFBO2lDQUFBO0FBQ0UsTUFBQSxJQUFHLENBQUMsQ0FBSyxvQ0FBTCxDQUFBLElBQW1DLENBQUMsSUFBQyxDQUFBLGlCQUFrQixDQUFBLElBQUEsQ0FBbkIsR0FBMkIsWUFBYSxDQUFBLElBQUEsQ0FBekMsQ0FBcEMsQ0FBQSxJQUF5Riw0QkFBNUY7c0JBQ0UsSUFBQyxDQUFBLGlCQUFrQixDQUFBLElBQUEsQ0FBbkIsR0FBMkIsWUFBYSxDQUFBLElBQUEsR0FEMUM7T0FBQSxNQUFBOzhCQUFBO09BREY7QUFBQTtvQkFEZ0I7RUFBQSxDQXBNbEIsQ0FBQTs7QUFBQSwwQkE0TUEsWUFBQSxHQUFjLFNBQUMsQ0FBRCxHQUFBO0FBQ1osUUFBQSxZQUFBOztxQkFBcUM7S0FBckM7QUFFQSxJQUFBLElBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxTQUFOLEtBQW1CLElBQUMsQ0FBQSxpQkFBa0IsQ0FBQSxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU4sQ0FBekM7QUFDRSxNQUFBLElBQUMsQ0FBQSxpQkFBa0IsQ0FBQSxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU4sQ0FBbkIsRUFBQSxDQURGO0tBRkE7QUFJQSxXQUFNLHlFQUFOLEdBQUE7QUFDRSxNQUFBLElBQUMsQ0FBQSxpQkFBa0IsQ0FBQSxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU4sQ0FBbkIsRUFBQSxDQURGO0lBQUEsQ0FKQTtXQU1BLE9BUFk7RUFBQSxDQTVNZCxDQUFBOzt1QkFBQTs7SUFORixDQUFBOztBQUFBLE1BMk5NLENBQUMsT0FBUCxHQUFpQixhQTNOakIsQ0FBQTs7OztBQ05BLElBQUEsT0FBQTs7QUFBQTtBQUVlLEVBQUEsaUJBQUUsT0FBRixHQUFBO0FBQ1gsUUFBQSxlQUFBO0FBQUEsSUFEWSxJQUFDLENBQUEsNEJBQUEsVUFBVSxFQUN2QixDQUFBO0FBQUEsSUFBQSxJQUFHLElBQUMsQ0FBQSxPQUFPLENBQUMsV0FBVCxLQUF3QixNQUEzQjtBQUNFO0FBQUEsV0FBQSxZQUFBO3lCQUFBO0FBQ0UsUUFBQSxJQUFHLEdBQUcsQ0FBQyxXQUFKLEtBQW1CLE1BQXRCO0FBQ0UsVUFBQSxJQUFDLENBQUEsT0FBUSxDQUFBLElBQUEsQ0FBVCxHQUFxQixJQUFBLE9BQUEsQ0FBUSxHQUFSLENBQXJCLENBREY7U0FERjtBQUFBLE9BREY7S0FBQSxNQUFBO0FBS0UsWUFBVSxJQUFBLEtBQUEsQ0FBTSxvQ0FBTixDQUFWLENBTEY7S0FEVztFQUFBLENBQWI7O0FBQUEsb0JBUUEsS0FBQSxHQUFPLFFBUlAsQ0FBQTs7QUFBQSxvQkFVQSxTQUFBLEdBQVcsU0FBQyxLQUFELEVBQVEsR0FBUixHQUFBO0FBQ1QsUUFBQSxVQUFBO0FBQUEsSUFBQSxJQUFPLG1CQUFQO0FBQ0UsTUFBQSxJQUFDLENBQUEsTUFBRCxHQUFjLElBQUEsR0FBRyxDQUFDLFVBQUosQ0FBZSxJQUFmLENBQWlCLENBQUMsT0FBbEIsQ0FBQSxDQUFkLENBQUE7QUFDQTtBQUFBLFdBQUEsU0FBQTtvQkFBQTtBQUNFLFFBQUEsSUFBQyxDQUFBLE1BQU0sQ0FBQyxHQUFSLENBQVksQ0FBWixFQUFlLENBQWYsQ0FBQSxDQURGO0FBQUEsT0FGRjtLQUFBO0FBQUEsSUFJQSxNQUFBLENBQUEsSUFBUSxDQUFBLE9BSlIsQ0FBQTtXQUtBLElBQUMsQ0FBQSxPQU5RO0VBQUEsQ0FWWCxDQUFBOztBQUFBLG9CQWtCQSxTQUFBLEdBQVcsU0FBRSxNQUFGLEdBQUE7QUFDVCxJQURVLElBQUMsQ0FBQSxTQUFBLE1BQ1gsQ0FBQTtXQUFBLE1BQUEsQ0FBQSxJQUFRLENBQUEsUUFEQztFQUFBLENBbEJYLENBQUE7O0FBQUEsb0JBcUJBLE9BQUEsR0FBUyxTQUFDLENBQUQsR0FBQTtBQUNQLElBQUEsSUFBQyxDQUFBLE1BQU0sQ0FBQyxPQUFSLENBQWdCLENBQWhCLENBQUEsQ0FBQTtXQUNBLEtBRk87RUFBQSxDQXJCVCxDQUFBOztBQUFBLG9CQXlCQSxTQUFBLEdBQVcsU0FBQyxDQUFELEdBQUE7QUFDVCxJQUFBLElBQUMsQ0FBQSxNQUFNLENBQUMsU0FBUixDQUFrQixDQUFsQixDQUFBLENBQUE7V0FDQSxLQUZTO0VBQUEsQ0F6QlgsQ0FBQTs7QUFBQSxvQkE2Q0EsR0FBQSxHQUFLLFNBQUMsSUFBRCxFQUFPLE9BQVAsR0FBQTtBQUNILFFBQUEsZUFBQTtBQUFBLElBQUEsSUFBRyxtQkFBSDthQUNFLElBQUMsQ0FBQSxNQUFNLENBQUMsR0FBRyxDQUFDLEtBQVosQ0FBa0IsSUFBQyxDQUFBLE1BQW5CLEVBQTJCLFNBQTNCLEVBREY7S0FBQSxNQUFBO0FBR0UsTUFBQSxJQUFHLGVBQUg7ZUFDRSxJQUFDLENBQUEsT0FBUSxDQUFBLElBQUEsQ0FBVCxHQUFpQixRQURuQjtPQUFBLE1BRUssSUFBRyxZQUFIO2VBQ0gsSUFBQyxDQUFBLE9BQVEsQ0FBQSxJQUFBLEVBRE47T0FBQSxNQUFBO0FBR0gsUUFBQSxHQUFBLEdBQU0sRUFBTixDQUFBO0FBQ0E7QUFBQSxhQUFBLFNBQUE7c0JBQUE7QUFDRSxVQUFBLEdBQUksQ0FBQSxDQUFBLENBQUosR0FBUyxDQUFULENBREY7QUFBQSxTQURBO2VBR0EsSUFORztPQUxQO0tBREc7RUFBQSxDQTdDTCxDQUFBOztBQUFBLG9CQTJEQSxTQUFBLEdBQVEsU0FBQyxJQUFELEdBQUE7QUFDTixJQUFBLElBQUMsQ0FBQSxNQUFNLENBQUMsUUFBRCxDQUFQLENBQWUsSUFBZixDQUFBLENBQUE7V0FDQSxLQUZNO0VBQUEsQ0EzRFIsQ0FBQTs7aUJBQUE7O0lBRkYsQ0FBQTs7QUFpRUEsSUFBRyxnREFBSDtBQUNFLEVBQUEsSUFBRyxnQkFBSDtBQUNFLElBQUEsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFULEdBQWtCLE9BQWxCLENBREY7R0FBQSxNQUFBO0FBR0UsVUFBVSxJQUFBLEtBQUEsQ0FBTSwwQkFBTixDQUFWLENBSEY7R0FERjtDQWpFQTs7QUF1RUEsSUFBRyxnREFBSDtBQUNFLEVBQUEsTUFBTSxDQUFDLE9BQVAsR0FBaUIsT0FBakIsQ0FERjtDQXZFQTs7OztBQ0RBLElBQUE7O2lTQUFBOztBQUFBLE1BQU0sQ0FBQyxPQUFQLEdBQWlCLFNBQUEsR0FBQTtBQUVmLE1BQUEsdUJBQUE7QUFBQSxFQUFBLEdBQUEsR0FBTSxFQUFOLENBQUE7QUFBQSxFQUNBLGtCQUFBLEdBQXFCLEVBRHJCLENBQUE7QUFBQSxFQWdCTSxHQUFHLENBQUM7QUFNSyxJQUFBLG1CQUFDLFdBQUQsRUFBYyxHQUFkLEVBQW1CLE9BQW5CLEVBQTRCLGtCQUE1QixHQUFBO0FBQ1gsVUFBQSxRQUFBO0FBQUEsTUFBQSxJQUFHLG1CQUFIO0FBQ0UsUUFBQSxJQUFDLENBQUEsV0FBRCxHQUFlLFdBQWYsQ0FERjtPQUFBO0FBQUEsTUFFQSxJQUFDLENBQUEsVUFBRCxHQUFjLEtBRmQsQ0FBQTtBQUFBLE1BR0EsSUFBQyxDQUFBLGlCQUFELEdBQXFCLEtBSHJCLENBQUE7QUFBQSxNQUlBLElBQUMsQ0FBQSxlQUFELEdBQW1CLEVBSm5CLENBQUE7QUFLQSxNQUFBLElBQUcsV0FBSDtBQUNFLFFBQUEsSUFBQyxDQUFBLEdBQUQsR0FBTyxHQUFQLENBREY7T0FMQTtBQVNBLE1BQUEsSUFBRyxPQUFBLEtBQVcsTUFBZDtBQUFBO09BQUEsTUFFSyxJQUFHLGlCQUFBLElBQWEseUJBQWhCO0FBQ0gsUUFBQSxJQUFDLENBQUEsYUFBRCxDQUFlLFNBQWYsRUFBMEIsT0FBMUIsQ0FBQSxDQURHO09BQUEsTUFBQTtBQUdILFFBQUEsSUFBQyxDQUFBLE9BQUQsR0FBVyxPQUFYLENBSEc7T0FYTDtBQWVBLE1BQUEsSUFBRywwQkFBSDtBQUNFLFFBQUEsSUFBQyxDQUFBLGtCQUFELEdBQXNCLEVBQXRCLENBQUE7QUFDQSxhQUFBLDBCQUFBO3dDQUFBO0FBQ0UsVUFBQSxJQUFDLENBQUEsYUFBRCxDQUFlLElBQWYsRUFBcUIsRUFBckIsRUFBeUIsb0JBQXpCLENBQUEsQ0FERjtBQUFBLFNBRkY7T0FoQlc7SUFBQSxDQUFiOztBQUFBLHdCQXFCQSxJQUFBLEdBQU0sV0FyQk4sQ0FBQTs7QUFBQSx3QkF1QkEsVUFBQSxHQUFZLFNBQUMsSUFBRCxHQUFBO0FBQ1YsVUFBQSwwQkFBQTtBQUFBLE1BQUEsSUFBRyxvQkFBSDtBQUNFLFFBQUEsSUFBRyxrQ0FBSDtpQkFDRSxJQUFDLENBQUEsT0FBTyxDQUFDLGFBQVQsQ0FBQSxFQURGO1NBQUEsTUFFSyxJQUFHLElBQUMsQ0FBQSxPQUFPLENBQUMsV0FBVCxLQUF3QixNQUEzQjtBQUNILFVBQUEsSUFBRyxZQUFIO0FBQ0UsWUFBQSxJQUFHLDBCQUFIO3FCQUNFLElBQUMsQ0FBQSxPQUFRLENBQUEsSUFBQSxFQURYO2FBQUEsTUFBQTtxQkFHRSxJQUFDLENBQUEsa0JBQW1CLENBQUEsSUFBQSxDQUFLLENBQUMsYUFBMUIsQ0FBQSxFQUhGO2FBREY7V0FBQSxNQUFBO0FBTUUsWUFBQSxPQUFBLEdBQVUsRUFBVixDQUFBO0FBQ0E7QUFBQSxpQkFBQSxTQUFBOzBCQUFBO0FBQ0UsY0FBQSxPQUFRLENBQUEsQ0FBQSxDQUFSLEdBQWEsQ0FBYixDQURGO0FBQUEsYUFEQTtBQUdBLFlBQUEsSUFBRywrQkFBSDtBQUNFO0FBQUEsbUJBQUEsVUFBQTs2QkFBQTtBQUNFLGdCQUFBLENBQUEsR0FBSSxDQUFDLENBQUMsYUFBRixDQUFBLENBQUosQ0FBQTtBQUFBLGdCQUNBLE9BQVEsQ0FBQSxDQUFBLENBQVIsR0FBYSxDQURiLENBREY7QUFBQSxlQURGO2FBSEE7bUJBT0EsUUFiRjtXQURHO1NBQUEsTUFBQTtpQkFnQkgsSUFBQyxDQUFBLFFBaEJFO1NBSFA7T0FBQSxNQUFBO2VBcUJFLElBQUMsQ0FBQSxRQXJCSDtPQURVO0lBQUEsQ0F2QlosQ0FBQTs7QUFBQSx3QkErQ0EsV0FBQSxHQUFhLFNBQUEsR0FBQTtBQUNYLFlBQVUsSUFBQSxLQUFBLENBQU0sdURBQU4sQ0FBVixDQURXO0lBQUEsQ0EvQ2IsQ0FBQTs7QUFBQSx3QkFzREEsT0FBQSxHQUFTLFNBQUMsQ0FBRCxHQUFBO2FBQ1AsSUFBQyxDQUFBLGVBQWUsQ0FBQyxJQUFqQixDQUFzQixDQUF0QixFQURPO0lBQUEsQ0F0RFQsQ0FBQTs7QUFBQSx3QkErREEsU0FBQSxHQUFXLFNBQUMsQ0FBRCxHQUFBO2FBQ1QsSUFBQyxDQUFBLGVBQUQsR0FBbUIsSUFBQyxDQUFBLGVBQWUsQ0FBQyxNQUFqQixDQUF3QixTQUFDLENBQUQsR0FBQTtlQUN6QyxDQUFBLEtBQU8sRUFEa0M7TUFBQSxDQUF4QixFQURWO0lBQUEsQ0EvRFgsQ0FBQTs7QUFBQSx3QkF3RUEsa0JBQUEsR0FBb0IsU0FBQSxHQUFBO2FBQ2xCLElBQUMsQ0FBQSxlQUFELEdBQW1CLEdBREQ7SUFBQSxDQXhFcEIsQ0FBQTs7QUFBQSx3QkEyRUEsU0FBQSxHQUFRLFNBQUEsR0FBQTtBQUNOLE1BQUEsQ0FBSyxJQUFBLEdBQUcsQ0FBQyxNQUFKLENBQVcsTUFBWCxFQUFzQixJQUF0QixDQUFMLENBQTZCLENBQUMsT0FBOUIsQ0FBQSxDQUFBLENBQUE7YUFDQSxLQUZNO0lBQUEsQ0EzRVIsQ0FBQTs7QUFBQSx3QkFtRkEsU0FBQSxHQUFXLFNBQUEsR0FBQTtBQUNULFVBQUEsTUFBQTtBQUFBLE1BQUEsSUFBRyx3QkFBSDtBQUNFLFFBQUEsTUFBQSxHQUFTLElBQUMsQ0FBQSxhQUFELENBQUEsQ0FBVCxDQURGO09BQUEsTUFBQTtBQUdFLFFBQUEsTUFBQSxHQUFTLElBQVQsQ0FIRjtPQUFBO2FBSUEsSUFBQyxDQUFBLFlBQUQsYUFBYyxDQUFBLE1BQVEsU0FBQSxhQUFBLFNBQUEsQ0FBQSxDQUF0QixFQUxTO0lBQUEsQ0FuRlgsQ0FBQTs7QUFBQSx3QkE2RkEsWUFBQSxHQUFjLFNBQUEsR0FBQTtBQUNaLFVBQUEscUNBQUE7QUFBQSxNQURhLG1CQUFJLDhEQUNqQixDQUFBO0FBQUE7QUFBQTtXQUFBLDJDQUFBO3FCQUFBO0FBQ0Usc0JBQUEsQ0FBQyxDQUFDLElBQUYsVUFBTyxDQUFBLEVBQUksU0FBQSxhQUFBLElBQUEsQ0FBQSxDQUFYLEVBQUEsQ0FERjtBQUFBO3NCQURZO0lBQUEsQ0E3RmQsQ0FBQTs7QUFBQSx3QkFpR0EsU0FBQSxHQUFXLFNBQUEsR0FBQTthQUNULElBQUMsQ0FBQSxXQURRO0lBQUEsQ0FqR1gsQ0FBQTs7QUFBQSx3QkFvR0EsV0FBQSxHQUFhLFNBQUMsY0FBRCxHQUFBOztRQUFDLGlCQUFpQjtPQUM3QjtBQUFBLE1BQUEsSUFBRyxDQUFBLElBQUssQ0FBQSxpQkFBUjtBQUVFLFFBQUEsSUFBQyxDQUFBLFVBQUQsR0FBYyxJQUFkLENBQUE7QUFDQSxRQUFBLElBQUcsY0FBSDtBQUNFLFVBQUEsSUFBQyxDQUFBLGlCQUFELEdBQXFCLElBQXJCLENBQUE7aUJBQ0EsSUFBQyxDQUFBLEVBQUUsQ0FBQyxxQkFBSixDQUEwQixJQUExQixFQUZGO1NBSEY7T0FEVztJQUFBLENBcEdiLENBQUE7O0FBQUEsd0JBNEdBLE9BQUEsR0FBUyxTQUFBLEdBQUE7QUFFUCxNQUFBLElBQUMsQ0FBQSxFQUFFLENBQUMsZUFBSixDQUFvQixJQUFwQixDQUFBLENBQUE7YUFDQSxJQUFDLENBQUEsa0JBQUQsQ0FBQSxFQUhPO0lBQUEsQ0E1R1QsQ0FBQTs7QUFBQSx3QkFvSEEsU0FBQSxHQUFXLFNBQUUsTUFBRixHQUFBO0FBQVUsTUFBVCxJQUFDLENBQUEsU0FBQSxNQUFRLENBQVY7SUFBQSxDQXBIWCxDQUFBOztBQUFBLHdCQXlIQSxTQUFBLEdBQVcsU0FBQSxHQUFBO2FBQ1QsSUFBQyxDQUFBLE9BRFE7SUFBQSxDQXpIWCxDQUFBOztBQUFBLHdCQStIQSxNQUFBLEdBQVEsU0FBQSxHQUFBO0FBQ04sVUFBQSxPQUFBO0FBQUEsTUFBQSxJQUFPLDRCQUFQO2VBQ0UsSUFBQyxDQUFBLElBREg7T0FBQSxNQUFBO0FBR0UsUUFBQSxJQUFHLG9CQUFIO0FBQ0UsVUFBQSxPQUFBLEdBQVUsSUFBQyxDQUFBLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBVCxDQUFBLENBQVYsQ0FBQTtBQUFBLFVBQ0EsT0FBTyxDQUFDLEdBQVIsR0FBYyxJQUFDLENBQUEsR0FBRyxDQUFDLEdBRG5CLENBQUE7aUJBRUEsUUFIRjtTQUFBLE1BQUE7aUJBS0UsT0FMRjtTQUhGO09BRE07SUFBQSxDQS9IUixDQUFBOztBQUFBLHdCQTBJQSxRQUFBLEdBQVUsU0FBQSxHQUFBO0FBQ1IsVUFBQSxlQUFBO0FBQUEsTUFBQSxHQUFBLEdBQU0sRUFBTixDQUFBO0FBQ0E7QUFBQSxXQUFBLFNBQUE7b0JBQUE7QUFDRSxRQUFBLEdBQUksQ0FBQSxDQUFBLENBQUosR0FBUyxDQUFULENBREY7QUFBQSxPQURBO2FBR0EsSUFKUTtJQUFBLENBMUlWLENBQUE7O0FBQUEsd0JBc0pBLE9BQUEsR0FBUyxTQUFBLEdBQUE7QUFDUCxVQUFBLFdBQUE7QUFBQSxNQUFBLElBQUcsSUFBQyxDQUFBLHVCQUFELENBQUEsQ0FBSDtBQUNFLFFBQUEsSUFBQyxDQUFBLFdBQUQsR0FBZSxJQUFmLENBQUE7QUFDQSxRQUFBLElBQU8sZ0JBQVA7QUFJRSxVQUFBLElBQUMsQ0FBQSxHQUFELEdBQU8sSUFBQyxDQUFBLEVBQUUsQ0FBQywwQkFBSixDQUFBLENBQVAsQ0FKRjtTQURBO0FBTUEsUUFBQSxJQUFPLDRCQUFQO0FBQ0UsVUFBQSxJQUFDLENBQUEsRUFBRSxDQUFDLFlBQUosQ0FBaUIsSUFBakIsQ0FBQSxDQUFBO0FBQ0EsZUFBQSx5REFBQTt1Q0FBQTtBQUNFLFlBQUEsQ0FBQSxDQUFFLElBQUMsQ0FBQSxPQUFELENBQUEsQ0FBRixDQUFBLENBREY7QUFBQSxXQUZGO1NBTkE7ZUFVQSxLQVhGO09BQUEsTUFBQTtlQWFFLE1BYkY7T0FETztJQUFBLENBdEpULENBQUE7O0FBQUEsd0JBd0xBLGFBQUEsR0FBZSxTQUFDLElBQUQsRUFBTyxFQUFQLEVBQVcsSUFBWCxHQUFBO0FBQ2IsVUFBQSw2Q0FBQTs7UUFEd0IsT0FBTztPQUMvQjtBQUFBLE1BQUEsSUFBRyxZQUFBLElBQVEsc0JBQVg7QUFDRSxRQUFBLEVBQUEsR0FBSyxFQUFFLENBQUMsU0FBSCxDQUFhLElBQUMsQ0FBQSxZQUFkLEVBQTRCLElBQUMsQ0FBQSxVQUE3QixDQUFMLENBREY7T0FBQTtBQU9BLE1BQUEsSUFBTyxVQUFQO0FBQUE7T0FBQSxNQUVLLElBQUcsb0JBQUEsSUFBZSxDQUFBLENBQUssc0JBQUEsSUFBa0Isb0JBQW5CLENBQXRCO0FBR0gsUUFBQSxJQUFHLElBQUEsS0FBUSxNQUFYO2lCQUNFLElBQUUsQ0FBQSxJQUFBLENBQUYsR0FBVSxHQURaO1NBQUEsTUFBQTtBQUdFLFVBQUEsSUFBQSxHQUFPLElBQUUsQ0FBQSxJQUFBLENBQVQsQ0FBQTtBQUFBLFVBQ0EsS0FBQSxHQUFRLElBQUksQ0FBQyxLQUFMLENBQVcsR0FBWCxDQURSLENBQUE7QUFBQSxVQUVBLFNBQUEsR0FBWSxLQUFLLENBQUMsR0FBTixDQUFBLENBRlosQ0FBQTtBQUdBLGVBQUEsNENBQUE7NkJBQUE7QUFDRSxZQUFBLElBQUEsR0FBTyxJQUFLLENBQUEsSUFBQSxDQUFaLENBREY7QUFBQSxXQUhBO2lCQUtBLElBQUssQ0FBQSxTQUFBLENBQUwsR0FBa0IsR0FScEI7U0FIRztPQUFBLE1BQUE7O1VBY0gsSUFBQyxDQUFBLFlBQWE7U0FBZDs7ZUFDVyxDQUFBLElBQUEsSUFBUztTQURwQjtlQUVBLElBQUMsQ0FBQSxTQUFVLENBQUEsSUFBQSxDQUFNLENBQUEsSUFBQSxDQUFqQixHQUF5QixHQWhCdEI7T0FWUTtJQUFBLENBeExmLENBQUE7O0FBQUEsd0JBMk5BLHVCQUFBLEdBQXlCLFNBQUEsR0FBQTtBQUN2QixVQUFBLHdHQUFBO0FBQUEsTUFBQSxjQUFBLEdBQWlCLEVBQWpCLENBQUE7QUFBQSxNQUNBLE9BQUEsR0FBVSxJQURWLENBQUE7QUFFQTtBQUFBLFdBQUEsaUJBQUE7K0JBQUE7QUFDRSxhQUFBLFlBQUE7OEJBQUE7QUFDRSxVQUFBLEVBQUEsR0FBSyxJQUFDLENBQUEsRUFBRSxDQUFDLFlBQUosQ0FBaUIsTUFBakIsQ0FBTCxDQUFBO0FBQ0EsVUFBQSxJQUFHLEVBQUg7QUFDRSxZQUFBLElBQUcsU0FBQSxLQUFhLE1BQWhCO0FBQ0UsY0FBQSxJQUFFLENBQUEsSUFBQSxDQUFGLEdBQVUsRUFBVixDQURGO2FBQUEsTUFBQTtBQUdFLGNBQUEsSUFBQSxHQUFPLElBQUUsQ0FBQSxTQUFBLENBQVQsQ0FBQTtBQUFBLGNBQ0EsS0FBQSxHQUFRLElBQUksQ0FBQyxLQUFMLENBQVcsR0FBWCxDQURSLENBQUE7QUFBQSxjQUVBLFNBQUEsR0FBWSxLQUFLLENBQUMsR0FBTixDQUFBLENBRlosQ0FBQTtBQUdBLG1CQUFBLDRDQUFBO2lDQUFBO0FBQ0UsZ0JBQUEsSUFBQSxHQUFPLElBQUssQ0FBQSxJQUFBLENBQVosQ0FERjtBQUFBLGVBSEE7QUFBQSxjQUtBLElBQUssQ0FBQSxTQUFBLENBQUwsR0FBa0IsRUFMbEIsQ0FIRjthQURGO1dBQUEsTUFBQTs7Y0FXRSxjQUFlLENBQUEsU0FBQSxJQUFjO2FBQTdCO0FBQUEsWUFDQSxjQUFlLENBQUEsU0FBQSxDQUFXLENBQUEsSUFBQSxDQUExQixHQUFrQyxNQURsQyxDQUFBO0FBQUEsWUFFQSxPQUFBLEdBQVUsS0FGVixDQVhGO1dBRkY7QUFBQSxTQURGO0FBQUEsT0FGQTtBQW1CQSxNQUFBLElBQUcsQ0FBQSxPQUFIO0FBQ0UsUUFBQSxJQUFDLENBQUEsU0FBRCxHQUFhLGNBQWIsQ0FBQTtBQUNBLGVBQU8sS0FBUCxDQUZGO09BQUEsTUFBQTtBQUlFLFFBQUEsTUFBQSxDQUFBLElBQVEsQ0FBQSxTQUFSLENBQUE7QUFDQSxlQUFPLElBQVAsQ0FMRjtPQXBCdUI7SUFBQSxDQTNOekIsQ0FBQTs7QUFBQSx3QkFzUEEsYUFBQSxHQUFlLFNBQUEsR0FBQTtBQUNiLFVBQUEsdUJBQUE7QUFBQSxNQUFBLElBQU8sd0JBQVA7ZUFFRSxLQUZGO09BQUEsTUFBQTtBQUlFLFFBQUEsSUFBRyxJQUFDLENBQUEsV0FBVyxDQUFDLFdBQWIsS0FBNEIsTUFBL0I7QUFFRSxVQUFBLElBQUEsR0FBTyxJQUFDLENBQUEsWUFBUixDQUFBO0FBQ0E7QUFBQSxlQUFBLDJDQUFBO3lCQUFBO0FBQ0UsWUFBQSxJQUFBLEdBQU8sSUFBSyxDQUFBLENBQUEsQ0FBWixDQURGO0FBQUEsV0FEQTtBQUFBLFVBR0EsSUFBQyxDQUFBLFdBQUQsR0FBbUIsSUFBQSxJQUFBLENBQUEsQ0FIbkIsQ0FBQTtBQUFBLFVBSUEsSUFBQyxDQUFBLFdBQVcsQ0FBQyxTQUFiLENBQXVCLElBQXZCLENBSkEsQ0FGRjtTQUFBO2VBT0EsSUFBQyxDQUFBLFlBWEg7T0FEYTtJQUFBLENBdFBmLENBQUE7O0FBQUEsd0JBd1FBLE9BQUEsR0FBUyxTQUFDLElBQUQsR0FBQTtBQUNQLFVBQUEsNkJBQUE7O1FBRFEsT0FBTztPQUNmO0FBQUEsTUFBQSxJQUFJLENBQUMsSUFBTCxHQUFZLElBQUMsQ0FBQSxJQUFiLENBQUE7QUFBQSxNQUNBLElBQUksQ0FBQyxHQUFMLEdBQVcsSUFBQyxDQUFBLE1BQUQsQ0FBQSxDQURYLENBQUE7QUFFQSxNQUFBLElBQUcsd0JBQUg7QUFDRSxRQUFBLElBQUcsSUFBQyxDQUFBLFdBQVcsQ0FBQyxXQUFiLEtBQTRCLE1BQS9CO0FBQ0UsVUFBQSxJQUFJLENBQUMsV0FBTCxHQUFtQixJQUFDLENBQUEsV0FBcEIsQ0FERjtTQUFBLE1BQUE7QUFHRSxVQUFBLElBQUksQ0FBQyxXQUFMLEdBQW1CLElBQUMsQ0FBQSxXQUFXLENBQUMsS0FBaEMsQ0FIRjtTQURGO09BRkE7QUFRQSxNQUFBLElBQUcsOERBQUg7QUFDRSxRQUFBLElBQUksQ0FBQyxPQUFMLEdBQWUsSUFBQyxDQUFBLE9BQU8sQ0FBQyxNQUFULENBQUEsQ0FBZixDQURGO09BQUEsTUFBQTtBQUdFLFFBQUEsSUFBSSxDQUFDLE9BQUwsR0FBZSxJQUFDLENBQUEsT0FBaEIsQ0FIRjtPQVJBO0FBWUEsTUFBQSxJQUFHLCtCQUFIO0FBQ0UsUUFBQSxVQUFBLEdBQWEsRUFBYixDQUFBO0FBQ0E7QUFBQSxhQUFBLFVBQUE7dUJBQUE7QUFDRSxVQUFBLElBQUcsbUJBQUg7QUFDRSxZQUFBLENBQUEsR0FBSSxDQUFDLENBQUMsU0FBRixDQUFZLElBQUMsQ0FBQSxZQUFiLEVBQTJCLElBQUMsQ0FBQSxVQUE1QixDQUFKLENBREY7V0FBQTtBQUFBLFVBRUEsVUFBVyxDQUFBLENBQUEsQ0FBWCxHQUFnQixDQUFDLENBQUMsTUFBRixDQUFBLENBRmhCLENBREY7QUFBQSxTQURBO0FBQUEsUUFLQSxJQUFJLENBQUMsa0JBQUwsR0FBMEIsVUFMMUIsQ0FERjtPQVpBO2FBbUJBLEtBcEJPO0lBQUEsQ0F4UVQsQ0FBQTs7cUJBQUE7O01BdEJGLENBQUE7QUFBQSxFQXdUTSxHQUFHLENBQUM7QUFNUiw2QkFBQSxDQUFBOztBQUFhLElBQUEsZ0JBQUMsV0FBRCxFQUFjLEdBQWQsRUFBbUIsT0FBbkIsR0FBQTtBQUNYLE1BQUEsSUFBQyxDQUFBLGFBQUQsQ0FBZSxTQUFmLEVBQTBCLE9BQTFCLENBQUEsQ0FBQTtBQUFBLE1BQ0Esd0NBQU0sV0FBTixFQUFtQixHQUFuQixDQURBLENBRFc7SUFBQSxDQUFiOztBQUFBLHFCQUlBLElBQUEsR0FBTSxRQUpOLENBQUE7O0FBQUEscUJBV0EsT0FBQSxHQUFTLFNBQUEsR0FBQTthQUNQO0FBQUEsUUFDRSxNQUFBLEVBQVEsUUFEVjtBQUFBLFFBRUUsS0FBQSxFQUFPLElBQUMsQ0FBQSxNQUFELENBQUEsQ0FGVDtBQUFBLFFBR0UsU0FBQSxFQUFXLElBQUMsQ0FBQSxPQUFPLENBQUMsTUFBVCxDQUFBLENBSGI7UUFETztJQUFBLENBWFQsQ0FBQTs7QUFBQSxxQkFzQkEsT0FBQSxHQUFTLFNBQUEsR0FBQTtBQUNQLFVBQUEsR0FBQTtBQUFBLE1BQUEsSUFBRyxJQUFDLENBQUEsdUJBQUQsQ0FBQSxDQUFIO0FBQ0UsUUFBQSxHQUFBLEdBQU0scUNBQUEsU0FBQSxDQUFOLENBQUE7QUFDQSxRQUFBLElBQUcsR0FBSDtBQUNFLFVBQUEsSUFBQyxDQUFBLE9BQU8sQ0FBQyxXQUFULENBQXFCLElBQXJCLENBQUEsQ0FERjtTQURBO2VBR0EsSUFKRjtPQUFBLE1BQUE7ZUFNRSxNQU5GO09BRE87SUFBQSxDQXRCVCxDQUFBOztrQkFBQTs7S0FOdUIsR0FBRyxDQUFDLFVBeFQ3QixDQUFBO0FBQUEsRUFnV0EsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFYLEdBQW1CLFNBQUMsQ0FBRCxHQUFBO0FBQ2pCLFFBQUEsZ0JBQUE7QUFBQSxJQUNVLFFBQVIsTUFERixFQUVhLGdCQUFYLFVBRkYsQ0FBQTtXQUlJLElBQUEsSUFBQSxDQUFLLElBQUwsRUFBVyxHQUFYLEVBQWdCLFdBQWhCLEVBTGE7RUFBQSxDQWhXbkIsQ0FBQTtBQUFBLEVBaVhNLEdBQUcsQ0FBQztBQU9SLDZCQUFBLENBQUE7O0FBQWEsSUFBQSxnQkFBQyxXQUFELEVBQWMsT0FBZCxFQUF1QixrQkFBdkIsRUFBMkMsTUFBM0MsRUFBbUQsR0FBbkQsRUFBd0QsT0FBeEQsRUFBaUUsT0FBakUsRUFBMEUsTUFBMUUsR0FBQTtBQUNYLE1BQUEsSUFBQyxDQUFBLGFBQUQsQ0FBZSxRQUFmLEVBQXlCLE1BQXpCLENBQUEsQ0FBQTtBQUFBLE1BQ0EsSUFBQyxDQUFBLGFBQUQsQ0FBZSxTQUFmLEVBQTBCLE9BQTFCLENBREEsQ0FBQTtBQUFBLE1BRUEsSUFBQyxDQUFBLGFBQUQsQ0FBZSxTQUFmLEVBQTBCLE9BQTFCLENBRkEsQ0FBQTtBQUdBLE1BQUEsSUFBRyxjQUFIO0FBQ0UsUUFBQSxJQUFDLENBQUEsYUFBRCxDQUFlLFFBQWYsRUFBeUIsTUFBekIsQ0FBQSxDQURGO09BQUEsTUFBQTtBQUdFLFFBQUEsSUFBQyxDQUFBLGFBQUQsQ0FBZSxRQUFmLEVBQXlCLE9BQXpCLENBQUEsQ0FIRjtPQUhBO0FBQUEsTUFPQSx3Q0FBTSxXQUFOLEVBQW1CLEdBQW5CLEVBQXdCLE9BQXhCLEVBQWlDLGtCQUFqQyxDQVBBLENBRFc7SUFBQSxDQUFiOztBQUFBLHFCQVVBLElBQUEsR0FBTSxRQVZOLENBQUE7O0FBQUEscUJBWUEsR0FBQSxHQUFLLFNBQUEsR0FBQTthQUNILElBQUMsQ0FBQSxVQUFELENBQUEsRUFERztJQUFBLENBWkwsQ0FBQTs7QUFBQSxxQkFlQSxPQUFBLEdBQVMsU0FBQyxDQUFELEdBQUE7QUFDUCxVQUFBLENBQUE7O1FBRFEsSUFBRTtPQUNWO0FBQUEsTUFBQSxDQUFBLEdBQUksSUFBSixDQUFBO0FBQ0EsYUFBTSxDQUFBLEdBQUksQ0FBSixJQUFVLG1CQUFoQixHQUFBO0FBQ0UsUUFBQSxDQUFBLEdBQUksQ0FBQyxDQUFDLE9BQU4sQ0FBQTtBQUNBLFFBQUEsSUFBRyxDQUFBLENBQUssQ0FBQyxVQUFUO0FBQ0UsVUFBQSxDQUFBLEVBQUEsQ0FERjtTQUZGO01BQUEsQ0FEQTtBQUtBLE1BQUEsSUFBRyxDQUFDLENBQUMsVUFBTDtBQUNFLFFBQUEsSUFBQSxDQURGO09BTEE7YUFPQSxFQVJPO0lBQUEsQ0FmVCxDQUFBOztBQUFBLHFCQXlCQSxPQUFBLEdBQVMsU0FBQyxDQUFELEdBQUE7QUFDUCxVQUFBLENBQUE7O1FBRFEsSUFBRTtPQUNWO0FBQUEsTUFBQSxDQUFBLEdBQUksSUFBSixDQUFBO0FBQ0EsYUFBTSxDQUFBLEdBQUksQ0FBSixJQUFVLG1CQUFoQixHQUFBO0FBQ0UsUUFBQSxDQUFBLEdBQUksQ0FBQyxDQUFDLE9BQU4sQ0FBQTtBQUNBLFFBQUEsSUFBRyxDQUFBLENBQUssQ0FBQyxVQUFUO0FBQ0UsVUFBQSxDQUFBLEVBQUEsQ0FERjtTQUZGO01BQUEsQ0FEQTtBQUtBLE1BQUEsSUFBRyxDQUFDLENBQUMsVUFBTDtlQUNFLEtBREY7T0FBQSxNQUFBO2VBR0UsRUFIRjtPQU5PO0lBQUEsQ0F6QlQsQ0FBQTs7QUFBQSxxQkF3Q0EsV0FBQSxHQUFhLFNBQUMsQ0FBRCxHQUFBO0FBQ1gsVUFBQSx5QkFBQTs7UUFBQSxJQUFDLENBQUEsYUFBYztPQUFmO0FBQUEsTUFDQSxTQUFBLEdBQVksS0FEWixDQUFBO0FBRUEsTUFBQSxJQUFHLHFCQUFBLElBQWEsQ0FBQSxJQUFLLENBQUEsVUFBbEIsSUFBaUMsV0FBcEM7QUFFRSxRQUFBLFNBQUEsR0FBWSxJQUFaLENBRkY7T0FGQTtBQUtBLE1BQUEsSUFBRyxTQUFIO0FBQ0UsUUFBQSxJQUFDLENBQUEsVUFBVSxDQUFDLElBQVosQ0FBaUIsQ0FBakIsQ0FBQSxDQURGO09BTEE7QUFBQSxNQU9BLGNBQUEsR0FBaUIsS0FQakIsQ0FBQTtBQVFBLE1BQUEsSUFBRyxJQUFDLENBQUEsT0FBTyxDQUFDLFNBQVQsQ0FBQSxDQUFIO0FBQ0UsUUFBQSxjQUFBLEdBQWlCLElBQWpCLENBREY7T0FSQTtBQUFBLE1BVUEsd0NBQU0sY0FBTixDQVZBLENBQUE7QUFXQSxNQUFBLElBQUcsU0FBSDtBQUNFLFFBQUEsSUFBQyxDQUFBLE1BQU0sQ0FBQyxpQ0FBUixDQUEwQyxJQUExQyxFQUFnRCxDQUFoRCxDQUFBLENBREY7T0FYQTtBQWFBLE1BQUEsSUFBRyxzQkFBQSxJQUFjLElBQUMsQ0FBQSxPQUFPLENBQUMsU0FBVCxDQUFBLENBQWQsSUFBdUMsSUFBQyxDQUFBLE9BQU8sQ0FBQyxpQkFBVCxLQUFnQyxJQUExRTtlQUVFLElBQUMsQ0FBQSxPQUFPLENBQUMsV0FBVCxDQUFBLEVBRkY7T0FkVztJQUFBLENBeENiLENBQUE7O0FBQUEscUJBMERBLE9BQUEsR0FBUyxTQUFBLEdBQUE7QUFDUCxVQUFBLG9CQUFBO0FBQUEsTUFBQSxJQUFHLElBQUMsQ0FBQSxPQUFPLENBQUMsU0FBVCxDQUFBLENBQUg7QUFFRTtBQUFBLGFBQUEsMkNBQUE7dUJBQUE7QUFDRSxVQUFBLENBQUMsQ0FBQyxPQUFGLENBQUEsQ0FBQSxDQURGO0FBQUEsU0FBQTtBQUFBLFFBS0EsQ0FBQSxHQUFJLElBQUMsQ0FBQSxPQUxMLENBQUE7QUFNQSxlQUFNLENBQUMsQ0FBQyxJQUFGLEtBQVksV0FBbEIsR0FBQTtBQUNFLFVBQUEsSUFBRyxDQUFDLENBQUMsTUFBRixLQUFZLElBQWY7QUFDRSxZQUFBLENBQUMsQ0FBQyxNQUFGLEdBQVcsSUFBQyxDQUFBLE9BQVosQ0FERjtXQUFBO0FBQUEsVUFFQSxDQUFBLEdBQUksQ0FBQyxDQUFDLE9BRk4sQ0FERjtRQUFBLENBTkE7QUFBQSxRQVdBLElBQUMsQ0FBQSxPQUFPLENBQUMsT0FBVCxHQUFtQixJQUFDLENBQUEsT0FYcEIsQ0FBQTtBQUFBLFFBWUEsSUFBQyxDQUFBLE9BQU8sQ0FBQyxPQUFULEdBQW1CLElBQUMsQ0FBQSxPQVpwQixDQUFBO0FBb0JBLFFBQUEsSUFBRyxJQUFDLENBQUEsT0FBRCxZQUFvQixHQUFHLENBQUMsU0FBeEIsSUFBc0MsQ0FBQSxDQUFLLElBQUMsQ0FBQSxPQUFELFlBQW9CLEdBQUcsQ0FBQyxNQUF6QixDQUE3QztBQUNFLFVBQUEsSUFBQyxDQUFBLE9BQU8sQ0FBQyxhQUFULEVBQUEsQ0FBQTtBQUNBLFVBQUEsSUFBRyxJQUFDLENBQUEsT0FBTyxDQUFDLGFBQVQsSUFBMEIsQ0FBMUIsSUFBZ0MsQ0FBQSxJQUFLLENBQUEsT0FBTyxDQUFDLFVBQWhEO0FBQ0UsWUFBQSxJQUFDLENBQUEsT0FBTyxDQUFDLFdBQVQsQ0FBQSxDQUFBLENBREY7V0FGRjtTQXBCQTtBQUFBLFFBd0JBLE1BQUEsQ0FBQSxJQUFRLENBQUEsT0F4QlIsQ0FBQTtlQXlCQSxxQ0FBQSxTQUFBLEVBM0JGO09BRE87SUFBQSxDQTFEVCxDQUFBOztBQUFBLHFCQStGQSxtQkFBQSxHQUFxQixTQUFBLEdBQUE7QUFDbkIsVUFBQSxJQUFBO0FBQUEsTUFBQSxDQUFBLEdBQUksQ0FBSixDQUFBO0FBQUEsTUFDQSxDQUFBLEdBQUksSUFBQyxDQUFBLE9BREwsQ0FBQTtBQUVBLGFBQU0sSUFBTixHQUFBO0FBQ0UsUUFBQSxJQUFHLElBQUMsQ0FBQSxNQUFELEtBQVcsQ0FBZDtBQUNFLGdCQURGO1NBQUE7QUFBQSxRQUVBLENBQUEsRUFGQSxDQUFBO0FBQUEsUUFHQSxDQUFBLEdBQUksQ0FBQyxDQUFDLE9BSE4sQ0FERjtNQUFBLENBRkE7YUFPQSxFQVJtQjtJQUFBLENBL0ZyQixDQUFBOztBQUFBLHFCQTRHQSxPQUFBLEdBQVMsU0FBQSxHQUFBO0FBQ1AsVUFBQSwwQ0FBQTtBQUFBLE1BQUEsSUFBRyxDQUFBLElBQUssQ0FBQSx1QkFBRCxDQUFBLENBQVA7QUFDRSxlQUFPLEtBQVAsQ0FERjtPQUFBLE1BQUE7QUFHRSxRQUFBLElBQUcsSUFBQyxDQUFBLE9BQUQsWUFBb0IsR0FBRyxDQUFDLFNBQTNCO0FBQ0UsVUFBQSxJQUFDLENBQUEsT0FBTyxDQUFDLGFBQVQsR0FBeUIsSUFBekIsQ0FBQTs7aUJBQ1EsQ0FBQyxnQkFBaUI7V0FEMUI7QUFBQSxVQUVBLElBQUMsQ0FBQSxPQUFPLENBQUMsYUFBVCxFQUZBLENBREY7U0FBQTtBQUlBLFFBQUEsSUFBRyxtQkFBSDtBQUNFLFVBQUEsSUFBTyxvQkFBUDtBQUNFLFlBQUEsSUFBQyxDQUFBLE9BQUQsR0FBVyxJQUFDLENBQUEsTUFBTSxDQUFDLFNBQW5CLENBREY7V0FBQTtBQUVBLFVBQUEsSUFBTyxtQkFBUDtBQUNFLFlBQUEsSUFBQyxDQUFBLE1BQUQsR0FBVSxJQUFDLENBQUEsT0FBWCxDQURGO1dBQUEsTUFFSyxJQUFHLElBQUMsQ0FBQSxNQUFELEtBQVcsV0FBZDtBQUNILFlBQUEsSUFBQyxDQUFBLE1BQUQsR0FBVSxJQUFDLENBQUEsTUFBTSxDQUFDLFNBQWxCLENBREc7V0FKTDtBQU1BLFVBQUEsSUFBTyxvQkFBUDtBQUNFLFlBQUEsSUFBQyxDQUFBLE9BQUQsR0FBVyxJQUFDLENBQUEsTUFBTSxDQUFDLEdBQW5CLENBREY7V0FQRjtTQUpBO0FBYUEsUUFBQSxJQUFHLG9CQUFIO0FBQ0UsVUFBQSxrQkFBQSxHQUFxQixJQUFDLENBQUEsbUJBQUQsQ0FBQSxDQUFyQixDQUFBO0FBQUEsVUFDQSxDQUFBLEdBQUksSUFBQyxDQUFBLE9BQU8sQ0FBQyxPQURiLENBQUE7QUFBQSxVQUVBLENBQUEsR0FBSSxrQkFGSixDQUFBO0FBaUJBLGlCQUFNLElBQU4sR0FBQTtBQUNFLFlBQUEsSUFBRyxDQUFBLEtBQU8sSUFBQyxDQUFBLE9BQVg7QUFDRSxjQUFBLFNBQUEsR0FBWSxDQUFDLENBQUMsbUJBQUYsQ0FBQSxDQUFaLENBQUE7QUFFQSxjQUFBLElBQUcsU0FBQSxLQUFhLENBQWhCO0FBRUUsZ0JBQUEsSUFBRyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU4sR0FBZ0IsSUFBQyxDQUFBLEdBQUcsQ0FBQyxPQUF4QjtBQUNFLGtCQUFBLElBQUMsQ0FBQSxPQUFELEdBQVcsQ0FBWCxDQUFBO0FBQUEsa0JBQ0Esa0JBQUEsR0FBcUIsQ0FBQSxHQUFJLENBRHpCLENBREY7aUJBQUEsTUFBQTtBQUFBO2lCQUZGO2VBQUEsTUFPSyxJQUFHLFNBQUEsR0FBWSxDQUFmO0FBRUgsZ0JBQUEsSUFBRyxDQUFBLEdBQUksa0JBQUosSUFBMEIsU0FBN0I7QUFDRSxrQkFBQSxJQUFDLENBQUEsT0FBRCxHQUFXLENBQVgsQ0FBQTtBQUFBLGtCQUNBLGtCQUFBLEdBQXFCLENBQUEsR0FBSSxDQUR6QixDQURGO2lCQUFBLE1BQUE7QUFBQTtpQkFGRztlQUFBLE1BQUE7QUFTSCxzQkFURztlQVRMO0FBQUEsY0FtQkEsQ0FBQSxFQW5CQSxDQUFBO0FBQUEsY0FvQkEsQ0FBQSxHQUFJLENBQUMsQ0FBQyxPQXBCTixDQURGO2FBQUEsTUFBQTtBQXdCRSxvQkF4QkY7YUFERjtVQUFBLENBakJBO0FBQUEsVUE0Q0EsSUFBQyxDQUFBLE9BQUQsR0FBVyxJQUFDLENBQUEsT0FBTyxDQUFDLE9BNUNwQixDQUFBO0FBQUEsVUE2Q0EsSUFBQyxDQUFBLE9BQU8sQ0FBQyxPQUFULEdBQW1CLElBN0NuQixDQUFBO0FBQUEsVUE4Q0EsSUFBQyxDQUFBLE9BQU8sQ0FBQyxPQUFULEdBQW1CLElBOUNuQixDQURGO1NBYkE7QUFBQSxRQThEQSxJQUFDLENBQUEsU0FBRCxDQUFXLElBQUMsQ0FBQSxPQUFPLENBQUMsU0FBVCxDQUFBLENBQVgsQ0E5REEsQ0FBQTtBQUFBLFFBK0RBLHFDQUFBLFNBQUEsQ0EvREEsQ0FBQTtBQUFBLFFBZ0VBLElBQUMsQ0FBQSxNQUFNLENBQUMsaUNBQVIsQ0FBMEMsSUFBMUMsQ0FoRUEsQ0FBQTtlQWlFQSxLQXBFRjtPQURPO0lBQUEsQ0E1R1QsQ0FBQTs7QUFBQSxxQkFzTEEsV0FBQSxHQUFhLFNBQUEsR0FBQTtBQUNYLFVBQUEsY0FBQTtBQUFBLE1BQUEsUUFBQSxHQUFXLENBQVgsQ0FBQTtBQUFBLE1BQ0EsSUFBQSxHQUFPLElBQUMsQ0FBQSxPQURSLENBQUE7QUFFQSxhQUFNLElBQU4sR0FBQTtBQUNFLFFBQUEsSUFBRyxJQUFBLFlBQWdCLEdBQUcsQ0FBQyxTQUF2QjtBQUNFLGdCQURGO1NBQUE7QUFFQSxRQUFBLElBQUcsQ0FBQSxJQUFRLENBQUMsU0FBTCxDQUFBLENBQVA7QUFDRSxVQUFBLFFBQUEsRUFBQSxDQURGO1NBRkE7QUFBQSxRQUlBLElBQUEsR0FBTyxJQUFJLENBQUMsT0FKWixDQURGO01BQUEsQ0FGQTthQVFBLFNBVFc7SUFBQSxDQXRMYixDQUFBOztBQUFBLHFCQXFNQSxPQUFBLEdBQVMsU0FBQyxJQUFELEdBQUE7O1FBQUMsT0FBTztPQUNmO0FBQUEsTUFBQSxJQUFJLENBQUMsSUFBTCxHQUFZLElBQUMsQ0FBQSxPQUFPLENBQUMsTUFBVCxDQUFBLENBQVosQ0FBQTtBQUFBLE1BQ0EsSUFBSSxDQUFDLElBQUwsR0FBWSxJQUFDLENBQUEsT0FBTyxDQUFDLE1BQVQsQ0FBQSxDQURaLENBQUE7QUFHQSxNQUFBLElBQUcsSUFBQyxDQUFBLE1BQU0sQ0FBQyxJQUFSLEtBQWdCLFdBQW5CO0FBQ0UsUUFBQSxJQUFJLENBQUMsTUFBTCxHQUFjLFdBQWQsQ0FERjtPQUFBLE1BRUssSUFBRyxJQUFDLENBQUEsTUFBRCxLQUFhLElBQUMsQ0FBQSxPQUFqQjtBQUNILFFBQUEsSUFBSSxDQUFDLE1BQUwsR0FBYyxJQUFDLENBQUEsTUFBTSxDQUFDLE1BQVIsQ0FBQSxDQUFkLENBREc7T0FMTDtBQUFBLE1BU0EsSUFBSSxDQUFDLE1BQUwsR0FBYyxJQUFDLENBQUEsTUFBTSxDQUFDLE1BQVIsQ0FBQSxDQVRkLENBQUE7YUFXQSxvQ0FBTSxJQUFOLEVBWk87SUFBQSxDQXJNVCxDQUFBOztrQkFBQTs7S0FQdUIsR0FBRyxDQUFDLFVBalg3QixDQUFBO0FBQUEsRUEya0JBLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBWCxHQUFtQixTQUFDLElBQUQsR0FBQTtBQUNqQixRQUFBLDREQUFBO0FBQUEsSUFDYyxlQUFaLFVBREYsRUFFeUIsMEJBQXZCLHFCQUZGLEVBR1UsV0FBUixNQUhGLEVBSVUsWUFBUixPQUpGLEVBS1UsWUFBUixPQUxGLEVBTWEsY0FBWCxTQU5GLEVBT2EsY0FBWCxTQVBGLENBQUE7V0FTSSxJQUFBLElBQUEsQ0FBSyxJQUFMLEVBQVcsT0FBWCxFQUFvQixrQkFBcEIsRUFBd0MsTUFBeEMsRUFBZ0QsR0FBaEQsRUFBcUQsSUFBckQsRUFBMkQsSUFBM0QsRUFBaUUsTUFBakUsRUFWYTtFQUFBLENBM2tCbkIsQ0FBQTtBQUFBLEVBNmxCTSxHQUFHLENBQUM7QUFNUixnQ0FBQSxDQUFBOztBQUFhLElBQUEsbUJBQUMsT0FBRCxFQUFVLE9BQVYsRUFBbUIsTUFBbkIsR0FBQTtBQUNYLE1BQUEsSUFBQyxDQUFBLGFBQUQsQ0FBZSxTQUFmLEVBQTBCLE9BQTFCLENBQUEsQ0FBQTtBQUFBLE1BQ0EsSUFBQyxDQUFBLGFBQUQsQ0FBZSxTQUFmLEVBQTBCLE9BQTFCLENBREEsQ0FBQTtBQUFBLE1BRUEsSUFBQyxDQUFBLGFBQUQsQ0FBZSxRQUFmLEVBQXlCLE9BQXpCLENBRkEsQ0FBQTtBQUFBLE1BR0EsMkNBQU0sSUFBTixFQUFZO0FBQUEsUUFBQyxXQUFBLEVBQWEsSUFBZDtPQUFaLENBSEEsQ0FEVztJQUFBLENBQWI7O0FBQUEsd0JBTUEsSUFBQSxHQUFNLFdBTk4sQ0FBQTs7QUFBQSx3QkFRQSxXQUFBLEdBQWEsU0FBQSxHQUFBO0FBQ1gsVUFBQSxDQUFBO0FBQUEsTUFBQSx5Q0FBQSxDQUFBLENBQUE7QUFBQSxNQUNBLENBQUEsR0FBSSxJQUFDLENBQUEsT0FETCxDQUFBO0FBRUEsYUFBTSxTQUFOLEdBQUE7QUFDRSxRQUFBLENBQUMsQ0FBQyxXQUFGLENBQUEsQ0FBQSxDQUFBO0FBQUEsUUFDQSxDQUFBLEdBQUksQ0FBQyxDQUFDLE9BRE4sQ0FERjtNQUFBLENBRkE7YUFLQSxPQU5XO0lBQUEsQ0FSYixDQUFBOztBQUFBLHdCQWdCQSxPQUFBLEdBQVMsU0FBQSxHQUFBO2FBQ1AscUNBQUEsRUFETztJQUFBLENBaEJULENBQUE7O0FBQUEsd0JBc0JBLE9BQUEsR0FBUyxTQUFBLEdBQUE7QUFDUCxVQUFBLFdBQUE7QUFBQSxNQUFBLElBQUcsb0VBQUg7ZUFDRSx3Q0FBQSxTQUFBLEVBREY7T0FBQSxNQUVLLDRDQUFlLENBQUEsU0FBQSxVQUFmO0FBQ0gsUUFBQSxJQUFHLElBQUMsQ0FBQSx1QkFBRCxDQUFBLENBQUg7QUFDRSxVQUFBLElBQUcsNEJBQUg7QUFDRSxrQkFBVSxJQUFBLEtBQUEsQ0FBTSxnQ0FBTixDQUFWLENBREY7V0FBQTtBQUFBLFVBRUEsSUFBQyxDQUFBLE9BQU8sQ0FBQyxPQUFULEdBQW1CLElBRm5CLENBQUE7aUJBR0Esd0NBQUEsU0FBQSxFQUpGO1NBQUEsTUFBQTtpQkFNRSxNQU5GO1NBREc7T0FBQSxNQVFBLElBQUcsc0JBQUEsSUFBa0IsOEJBQXJCO0FBQ0gsUUFBQSxNQUFBLENBQUEsSUFBUSxDQUFBLE9BQU8sQ0FBQyxTQUFTLENBQUMsT0FBMUIsQ0FBQTtBQUFBLFFBQ0EsSUFBQyxDQUFBLE9BQU8sQ0FBQyxPQUFULEdBQW1CLElBRG5CLENBQUE7ZUFFQSx3Q0FBQSxTQUFBLEVBSEc7T0FBQSxNQUlBLElBQUcsc0JBQUEsSUFBYSxzQkFBYixJQUEwQixJQUE3QjtlQUNILHdDQUFBLFNBQUEsRUFERztPQWZFO0lBQUEsQ0F0QlQsQ0FBQTs7QUFBQSx3QkE2Q0EsT0FBQSxHQUFTLFNBQUEsR0FBQTtBQUNQLFVBQUEsV0FBQTthQUFBO0FBQUEsUUFDRSxNQUFBLEVBQVMsSUFBQyxDQUFBLElBRFo7QUFBQSxRQUVFLEtBQUEsRUFBUSxJQUFDLENBQUEsTUFBRCxDQUFBLENBRlY7QUFBQSxRQUdFLE1BQUEsc0NBQWlCLENBQUUsTUFBVixDQUFBLFVBSFg7QUFBQSxRQUlFLE1BQUEsd0NBQWlCLENBQUUsTUFBVixDQUFBLFVBSlg7UUFETztJQUFBLENBN0NULENBQUE7O3FCQUFBOztLQU4wQixHQUFHLENBQUMsVUE3bEJoQyxDQUFBO0FBQUEsRUF3cEJBLEdBQUcsQ0FBQyxTQUFTLENBQUMsS0FBZCxHQUFzQixTQUFDLElBQUQsR0FBQTtBQUNwQixRQUFBLGVBQUE7QUFBQSxJQUNRLFdBQVIsTUFEQSxFQUVTLFlBQVQsT0FGQSxFQUdTLFlBQVQsT0FIQSxDQUFBO1dBS0ksSUFBQSxJQUFBLENBQUssR0FBTCxFQUFVLElBQVYsRUFBZ0IsSUFBaEIsRUFOZ0I7RUFBQSxDQXhwQnRCLENBQUE7U0FpcUJBO0FBQUEsSUFDRSxZQUFBLEVBQWUsR0FEakI7QUFBQSxJQUVFLG9CQUFBLEVBQXVCLGtCQUZ6QjtJQW5xQmU7QUFBQSxDQUFqQixDQUFBOzs7O0FDQUEsSUFBQSxzQ0FBQTtFQUFBO2lTQUFBOztBQUFBLHVCQUFBLEdBQTBCLE9BQUEsQ0FBUSxTQUFSLENBQTFCLENBQUE7O0FBQUEsYUFDQSxHQUFnQixPQUFBLENBQVEsOEJBQVIsQ0FEaEIsQ0FBQTs7QUFBQSxNQUdNLENBQUMsT0FBUCxHQUFpQixTQUFBLEdBQUE7QUFDZixNQUFBLGNBQUE7QUFBQSxFQUFBLFNBQUEsR0FBWSx1QkFBQSxDQUFBLENBQVosQ0FBQTtBQUFBLEVBQ0EsR0FBQSxHQUFNLFNBQVMsQ0FBQyxVQURoQixDQUFBO0FBQUEsRUFPTSxHQUFHLENBQUM7QUFLUixpQ0FBQSxDQUFBOztBQUFhLElBQUEsb0JBQUMsV0FBRCxFQUFjLEdBQWQsRUFBbUIsT0FBbkIsRUFBNEIsa0JBQTVCLEdBQUE7QUFDWCxNQUFBLElBQUMsQ0FBQSxJQUFELEdBQVEsRUFBUixDQUFBO0FBQUEsTUFDQSw0Q0FBTSxXQUFOLEVBQW1CLEdBQW5CLEVBQXdCLE9BQXhCLEVBQWlDLGtCQUFqQyxDQURBLENBRFc7SUFBQSxDQUFiOztBQUFBLHlCQUlBLElBQUEsR0FBTSxZQUpOLENBQUE7O0FBQUEseUJBTUEsV0FBQSxHQUFhLFNBQUEsR0FBQTtBQUNYLFVBQUEsYUFBQTtBQUFBO0FBQUEsV0FBQSxZQUFBO3VCQUFBO0FBQ0UsUUFBQSxDQUFDLENBQUMsV0FBRixDQUFBLENBQUEsQ0FERjtBQUFBLE9BQUE7YUFFQSwwQ0FBQSxFQUhXO0lBQUEsQ0FOYixDQUFBOztBQUFBLHlCQVdBLE9BQUEsR0FBUyxTQUFBLEdBQUE7YUFDUCxzQ0FBQSxFQURPO0lBQUEsQ0FYVCxDQUFBOztBQUFBLHlCQWNBLEdBQUEsR0FBSyxTQUFDLENBQUQsR0FBQTtBQUNILFVBQUEsVUFBQTtBQUFBO0FBQUEsV0FBQSxTQUFBO29CQUFBO0FBQ0UsUUFBQSxDQUFBLENBQUUsQ0FBRixFQUFJLENBQUosQ0FBQSxDQURGO0FBQUEsT0FBQTthQUVBLE9BSEc7SUFBQSxDQWRMLENBQUE7O0FBQUEseUJBc0JBLEdBQUEsR0FBSyxTQUFDLElBQUQsRUFBTyxPQUFQLEdBQUE7QUFDSCxVQUFBLCtCQUFBO0FBQUEsTUFBQSxJQUFHLFNBQVMsQ0FBQyxNQUFWLEdBQW1CLENBQXRCO0FBQ0UsUUFBQSxJQUFHLGlCQUFBLElBQWEsMkJBQWhCO0FBQ0UsVUFBQSxHQUFBLEdBQU0sT0FBTyxDQUFDLFNBQVIsQ0FBa0IsSUFBQyxDQUFBLFlBQW5CLEVBQWlDLElBQUMsQ0FBQSxVQUFsQyxDQUFOLENBREY7U0FBQSxNQUFBO0FBR0UsVUFBQSxHQUFBLEdBQU0sT0FBTixDQUhGO1NBQUE7QUFBQSxRQUlBLElBQUMsQ0FBQSxXQUFELENBQWEsSUFBYixDQUFrQixDQUFDLE9BQW5CLENBQTJCLEdBQTNCLENBSkEsQ0FBQTtlQUtBLElBQUMsQ0FBQSxhQUFELENBQUEsRUFORjtPQUFBLE1BT0ssSUFBRyxZQUFIO0FBQ0gsUUFBQSxJQUFBLEdBQU8sSUFBQyxDQUFBLElBQUssQ0FBQSxJQUFBLENBQWIsQ0FBQTtBQUNBLFFBQUEsSUFBRyxjQUFBLElBQVUsQ0FBQSxJQUFRLENBQUMsZ0JBQUwsQ0FBQSxDQUFqQjtBQUNFLFVBQUEsR0FBQSxHQUFNLElBQUksQ0FBQyxHQUFMLENBQUEsQ0FBTixDQUFBO0FBQ0EsVUFBQSxJQUFHLEdBQUEsWUFBZSxHQUFHLENBQUMsU0FBdEI7bUJBQ0UsR0FBRyxDQUFDLGFBQUosQ0FBQSxFQURGO1dBQUEsTUFBQTttQkFHRSxJQUhGO1dBRkY7U0FBQSxNQUFBO2lCQU9FLE9BUEY7U0FGRztPQUFBLE1BQUE7QUFXSCxRQUFBLE1BQUEsR0FBUyxFQUFULENBQUE7QUFDQTtBQUFBLGFBQUEsWUFBQTt5QkFBQTtBQUNFLFVBQUEsSUFBRyxDQUFBLENBQUssQ0FBQyxnQkFBRixDQUFBLENBQVA7QUFDRSxZQUFBLE1BQU8sQ0FBQSxJQUFBLENBQVAsR0FBZSxDQUFDLENBQUMsR0FBRixDQUFBLENBQWYsQ0FERjtXQURGO0FBQUEsU0FEQTtlQUlBLE9BZkc7T0FSRjtJQUFBLENBdEJMLENBQUE7O0FBQUEseUJBK0NBLFNBQUEsR0FBUSxTQUFDLElBQUQsR0FBQTtBQUNOLFVBQUEsSUFBQTs7WUFBVyxDQUFFLGFBQWIsQ0FBQTtPQUFBO2FBQ0EsS0FGTTtJQUFBLENBL0NSLENBQUE7O0FBQUEseUJBbURBLFdBQUEsR0FBYSxTQUFDLGFBQUQsR0FBQTtBQUNYLFVBQUEsd0NBQUE7QUFBQSxNQUFBLElBQU8sZ0NBQVA7QUFDRSxRQUFBLGdCQUFBLEdBQ0U7QUFBQSxVQUFBLElBQUEsRUFBTSxhQUFOO1NBREYsQ0FBQTtBQUFBLFFBRUEsVUFBQSxHQUFhLElBRmIsQ0FBQTtBQUFBLFFBR0EsTUFBQSxHQUNFO0FBQUEsVUFBQSxXQUFBLEVBQWEsSUFBYjtBQUFBLFVBQ0EsR0FBQSxFQUFLLGFBREw7QUFBQSxVQUVBLEdBQUEsRUFBSyxJQUZMO1NBSkYsQ0FBQTtBQUFBLFFBT0EsRUFBQSxHQUFTLElBQUEsR0FBRyxDQUFDLGNBQUosQ0FBbUIsSUFBbkIsRUFBeUIsZ0JBQXpCLEVBQTJDLFVBQTNDLEVBQXVELE1BQXZELENBUFQsQ0FBQTtBQUFBLFFBUUEsSUFBQyxDQUFBLElBQUssQ0FBQSxhQUFBLENBQU4sR0FBdUIsRUFSdkIsQ0FBQTtBQUFBLFFBU0EsRUFBRSxDQUFDLFNBQUgsQ0FBYSxJQUFiLEVBQWdCLGFBQWhCLENBVEEsQ0FBQTtBQUFBLFFBVUEsRUFBRSxDQUFDLE9BQUgsQ0FBQSxDQVZBLENBREY7T0FBQTthQVlBLElBQUMsQ0FBQSxJQUFLLENBQUEsYUFBQSxFQWJLO0lBQUEsQ0FuRGIsQ0FBQTs7c0JBQUE7O0tBTDJCLEdBQUcsQ0FBQyxVQVBqQyxDQUFBO0FBQUEsRUE4RUEsR0FBRyxDQUFDLFVBQVUsQ0FBQyxLQUFmLEdBQXVCLFNBQUMsSUFBRCxHQUFBO0FBQ3JCLFFBQUEsNkNBQUE7QUFBQSxJQUNVLFdBQVIsTUFERixFQUVrQixtQkFBaEIsY0FGRixFQUdjLGVBQVosVUFIRixFQUl5QiwwQkFBdkIscUJBSkYsQ0FBQTtXQU1JLElBQUEsSUFBQSxDQUFLLFdBQUwsRUFBa0IsR0FBbEIsRUFBdUIsT0FBdkIsRUFBZ0Msa0JBQWhDLEVBUGlCO0VBQUEsQ0E5RXZCLENBQUE7QUFBQSxFQTZGTSxHQUFHLENBQUM7QUFPUixrQ0FBQSxDQUFBOztBQUFhLElBQUEscUJBQUMsV0FBRCxFQUFjLEdBQWQsRUFBbUIsT0FBbkIsRUFBNEIsa0JBQTVCLEdBQUE7QUFDWCxNQUFBLElBQUMsQ0FBQSxTQUFELEdBQWlCLElBQUEsR0FBRyxDQUFDLFNBQUosQ0FBYyxNQUFkLEVBQXlCLE1BQXpCLENBQWpCLENBQUE7QUFBQSxNQUNBLElBQUMsQ0FBQSxHQUFELEdBQWlCLElBQUEsR0FBRyxDQUFDLFNBQUosQ0FBYyxJQUFDLENBQUEsU0FBZixFQUEwQixNQUExQixDQURqQixDQUFBO0FBQUEsTUFFQSxJQUFDLENBQUEsU0FBUyxDQUFDLE9BQVgsR0FBcUIsSUFBQyxDQUFBLEdBRnRCLENBQUE7QUFBQSxNQUdBLElBQUMsQ0FBQSxTQUFTLENBQUMsT0FBWCxDQUFBLENBSEEsQ0FBQTtBQUFBLE1BSUEsSUFBQyxDQUFBLEdBQUcsQ0FBQyxPQUFMLENBQUEsQ0FKQSxDQUFBO0FBQUEsTUFRQSxJQUFDLENBQUEsU0FBRCxHQUFpQixJQUFBLGFBQUEsQ0FBQSxDQVJqQixDQUFBO0FBQUEsTUFVQSxJQUFDLENBQUEsWUFBRCxHQUFvQixJQUFBLGFBQUEsQ0FBQSxDQVZwQixDQUFBO0FBQUEsTUFZQSw2Q0FBTSxXQUFOLEVBQW1CLEdBQW5CLEVBQXdCLE9BQXhCLEVBQWlDLGtCQUFqQyxDQVpBLENBRFc7SUFBQSxDQUFiOztBQUFBLDBCQWVBLElBQUEsR0FBTSxhQWZOLENBQUE7O0FBQUEsMEJBa0JBLFdBQUEsR0FBYSxTQUFBLEdBQUE7QUFDWCxVQUFBLENBQUE7QUFBQSxNQUFBLENBQUEsR0FBSSxJQUFDLENBQUEsU0FBTCxDQUFBO0FBQ0EsYUFBTSxTQUFOLEdBQUE7QUFDRSxRQUFBLENBQUMsQ0FBQyxXQUFGLENBQUEsQ0FBQSxDQUFBO0FBQUEsUUFDQSxDQUFBLEdBQUksQ0FBQyxDQUFDLE9BRE4sQ0FERjtNQUFBLENBREE7YUFJQSwyQ0FBQSxFQUxXO0lBQUEsQ0FsQmIsQ0FBQTs7QUFBQSwwQkF5QkEsT0FBQSxHQUFTLFNBQUEsR0FBQTthQUNQLHVDQUFBLEVBRE87SUFBQSxDQXpCVCxDQUFBOztBQUFBLDBCQTZCQSxNQUFBLEdBQVEsU0FBQyxrQkFBRCxHQUFBO0FBQ04sVUFBQSw2QkFBQTs7UUFETyxxQkFBcUI7T0FDNUI7QUFBQSxNQUFBLEdBQUEsR0FBTSxJQUFDLENBQUEsR0FBRCxDQUFBLENBQU4sQ0FBQTtBQUNBO1dBQUEsa0RBQUE7bUJBQUE7QUFDRSxRQUFBLElBQUcsQ0FBQSxZQUFhLEdBQUcsQ0FBQyxNQUFwQjt3QkFDRSxDQUFDLENBQUMsTUFBRixDQUFTLGtCQUFULEdBREY7U0FBQSxNQUVLLElBQUcsQ0FBQSxZQUFhLEdBQUcsQ0FBQyxXQUFwQjt3QkFDSCxDQUFDLENBQUMsTUFBRixDQUFTLGtCQUFULEdBREc7U0FBQSxNQUVBLElBQUcsa0JBQUEsSUFBdUIsQ0FBQSxZQUFhLEdBQUcsQ0FBQyxTQUEzQzt3QkFDSCxDQUFDLENBQUMsR0FBRixDQUFBLEdBREc7U0FBQSxNQUFBO3dCQUdILEdBSEc7U0FMUDtBQUFBO3NCQUZNO0lBQUEsQ0E3QlIsQ0FBQTs7QUFBQSwwQkE2Q0EsT0FBQSxHQUFTLFNBQUEsR0FBQTtBQUNQLE1BQUEsSUFBRyxJQUFDLENBQUEsdUJBQUQsQ0FBQSxDQUFIO0FBQ0UsUUFBQSxJQUFDLENBQUEsU0FBUyxDQUFDLFNBQVgsQ0FBcUIsSUFBckIsQ0FBQSxDQUFBO0FBQUEsUUFDQSxJQUFDLENBQUEsR0FBRyxDQUFDLFNBQUwsQ0FBZSxJQUFmLENBREEsQ0FBQTtlQUVBLDBDQUFBLFNBQUEsRUFIRjtPQUFBLE1BQUE7ZUFLRSxNQUxGO09BRE87SUFBQSxDQTdDVCxDQUFBOztBQUFBLDBCQXNEQSxnQkFBQSxHQUFrQixTQUFBLEdBQUE7YUFDaEIsSUFBQyxDQUFBLEdBQUcsQ0FBQyxRQURXO0lBQUEsQ0F0RGxCLENBQUE7O0FBQUEsMEJBMERBLGlCQUFBLEdBQW1CLFNBQUEsR0FBQTthQUNqQixJQUFDLENBQUEsU0FBUyxDQUFDLFFBRE07SUFBQSxDQTFEbkIsQ0FBQTs7QUFBQSwwQkE4REEsaUJBQUEsR0FBbUIsU0FBQyxLQUFELEdBQUE7QUFDakIsVUFBQSxTQUFBO0FBQUEsTUFBQSxJQUFHLEtBQUssQ0FBQyxTQUFOLENBQUEsQ0FBQSxJQUF5QixvQkFBNUI7QUFDRSxRQUFBLFNBQUEsR0FBWSxLQUFLLENBQUMsT0FBbEIsQ0FBQTtBQUNBLGVBQU0sQ0FBQSxDQUFNLFNBQUEsWUFBcUIsR0FBRyxDQUFDLFNBQTFCLENBQVgsR0FBQTtBQUNFLFVBQUEsSUFBRyxTQUFTLENBQUMsVUFBYjtBQUNFLFlBQUEsU0FBQSxHQUFZLFNBQVMsQ0FBQyxPQUF0QixDQURGO1dBQUEsTUFBQTtBQUdFLGtCQUhGO1dBREY7UUFBQSxDQUZGO09BQUEsTUFBQTtBQVFFLFFBQUEsU0FBQSxHQUFZLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQTVCLENBQUE7QUFDQSxRQUFBLElBQUcsQ0FBQSxTQUFIO0FBQ0UsaUJBQU8sS0FBUCxDQURGO1NBVEY7T0FBQTthQVlBLFVBYmlCO0lBQUEsQ0E5RG5CLENBQUE7O0FBQUEsMEJBNkVBLGlCQUFBLEdBQW1CLFNBQUMsS0FBRCxHQUFBO0FBQ2pCLFVBQUEsU0FBQTtBQUFBLE1BQUEsSUFBRyxLQUFLLENBQUMsU0FBTixDQUFBLENBQUEsSUFBeUIsb0JBQTVCO0FBQ0UsUUFBQSxTQUFBLEdBQVksS0FBSyxDQUFDLE9BQWxCLENBQUE7QUFDQSxlQUFNLENBQUEsQ0FBTSxTQUFBLFlBQXFCLEdBQUcsQ0FBQyxTQUExQixDQUFYLEdBQUE7QUFDRSxVQUFBLElBQUcsU0FBUyxDQUFDLFVBQWI7QUFDRSxZQUFBLFNBQUEsR0FBWSxTQUFTLENBQUMsT0FBdEIsQ0FERjtXQUFBLE1BQUE7QUFHRSxrQkFIRjtXQURGO1FBQUEsQ0FGRjtPQUFBLE1BQUE7QUFRRSxRQUFBLFNBQUEsR0FBWSxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUE1QixDQUFBO0FBQ0EsUUFBQSxJQUFHLENBQUEsU0FBSDtBQUNFLGlCQUFPLEtBQVAsQ0FERjtTQVRGO09BQUE7YUFZQSxVQWJpQjtJQUFBLENBN0VuQixDQUFBOztBQUFBLDBCQStGQSxPQUFBLEdBQVMsU0FBQSxHQUFBO2FBQ1AsSUFBQyxDQUFBLFNBQVMsQ0FBQyxHQUFYLENBQWUsU0FBQyxTQUFELEdBQUE7ZUFDYixTQUFTLENBQUMsR0FBVixDQUFBLEVBRGE7TUFBQSxDQUFmLEVBRE87SUFBQSxDQS9GVCxDQUFBOztBQUFBLDBCQW1HQSxHQUFBLEdBQUssU0FBQyxHQUFELEdBQUE7YUFDSCxJQUFDLENBQUEsU0FBUyxDQUFDLEdBQVgsQ0FBZSxHQUFmLEVBREc7SUFBQSxDQW5HTCxDQUFBOztBQUFBLDBCQXNHQSxJQUFBLEdBQU0sU0FBQyxJQUFELEVBQU8sR0FBUCxHQUFBO2FBQ0osSUFBQyxDQUFBLFNBQVMsQ0FBQyxHQUFYLENBQWUsU0FBQyxTQUFELEdBQUE7ZUFDYixJQUFBLEdBQU8sR0FBQSxDQUFJLElBQUosRUFBVSxTQUFWLEVBRE07TUFBQSxDQUFmLEVBREk7SUFBQSxDQXRHTixDQUFBOztBQUFBLDBCQTBHQSxHQUFBLEdBQUssU0FBQyxHQUFELEdBQUE7QUFDSCxNQUFBLElBQUcsV0FBSDtlQUNFLElBQUMsQ0FBQSxTQUFTLENBQUMsSUFBWCxDQUFnQixHQUFoQixDQUFvQixDQUFDLEdBQXJCLENBQUEsRUFERjtPQUFBLE1BQUE7ZUFHRSxJQUFDLENBQUEsT0FBRCxDQUFBLEVBSEY7T0FERztJQUFBLENBMUdMLENBQUE7O0FBQUEsMEJBZ0hBLEdBQUEsR0FBSyxTQUFDLEdBQUQsR0FBQTtBQUNILE1BQUEsSUFBRyxXQUFIO2VBQ0UsSUFBQyxDQUFBLFNBQVMsQ0FBQyxJQUFYLENBQWdCLEdBQWhCLEVBREY7T0FBQSxNQUFBO2VBR0UsSUFBQyxDQUFBLFNBQVMsQ0FBQyxHQUFYLENBQWUsU0FBQyxTQUFELEdBQUE7aUJBQ2IsVUFEYTtRQUFBLENBQWYsRUFIRjtPQURHO0lBQUEsQ0FoSEwsQ0FBQTs7QUFBQSwwQkE0SEEsc0JBQUEsR0FBd0IsU0FBQyxRQUFELEdBQUE7QUFDdEIsTUFBQSxJQUFHLFFBQUEsS0FBWSxDQUFmO2VBQ0UsSUFBQyxDQUFBLFVBREg7T0FBQSxNQUVLLElBQUcsUUFBQSxLQUFZLElBQUMsQ0FBQSxTQUFTLENBQUMsSUFBWCxHQUFrQixDQUFqQztlQUNILElBQUMsQ0FBQSxJQURFO09BQUEsTUFBQTtlQUdILElBQUMsQ0FBQSxTQUFTLENBQUMsSUFBWCxDQUFpQixRQUFBLEdBQVMsQ0FBMUIsRUFIRztPQUhpQjtJQUFBLENBNUh4QixDQUFBOztBQUFBLDBCQW9JQSxJQUFBLEdBQU0sU0FBQyxPQUFELEdBQUE7YUFDSixJQUFDLENBQUEsV0FBRCxDQUFhLElBQUMsQ0FBQSxHQUFHLENBQUMsT0FBbEIsRUFBMkIsQ0FBQyxPQUFELENBQTNCLEVBREk7SUFBQSxDQXBJTixDQUFBOztBQUFBLDBCQXVJQSxpQkFBQSxHQUFtQixTQUFDLElBQUQsRUFBTyxPQUFQLEdBQUE7QUFDakIsVUFBQSxLQUFBO0FBQUEsTUFBQSxJQUFHLENBQUEsSUFBSyxDQUFDLEtBQVQ7QUFDRSxRQUFBLElBQUksQ0FBQyxFQUFFLENBQUMsS0FBUixHQUFnQixPQUFoQixDQUFBO2VBQ0EsT0FBTyxDQUFDLEVBQUUsQ0FBQyxNQUFYLEdBQW9CLEtBRnRCO09BQUEsTUFBQTtlQUlFLEtBQUEsR0FBUSxJQUFJLENBQUMsUUFKZjtPQURpQjtJQUFBLENBdkluQixDQUFBOztBQUFBLDBCQStJQSxXQUFBLEdBQWEsU0FBQyxJQUFELEVBQU8sUUFBUCxHQUFBO0FBQ1gsVUFBQSw0Q0FBQTtBQUFBLE1BQUEsSUFBRyxJQUFBLEtBQVEsSUFBQyxDQUFBLFNBQVo7QUFDRSxRQUFBLFFBQUEsR0FBVyxJQUFYLENBQUE7QUFBQSxRQUNBLFNBQUEsR0FBWSxJQUFDLENBQUEsU0FBUyxDQUFDLFFBQVgsQ0FBb0IsQ0FBcEIsQ0FEWixDQUFBO0FBQUEsUUFFQSxLQUFBLEdBQVcsU0FBSCxHQUFrQixTQUFTLENBQUMsSUFBNUIsR0FBc0MsSUFBQyxDQUFBLEdBRi9DLENBREY7T0FBQSxNQUFBO0FBTUUsUUFBQSxTQUFBLEdBQVksSUFBSSxDQUFDLElBQUksQ0FBQyxJQUF0QixDQUFBO0FBQUEsUUFDQSxRQUFBLEdBQVcsSUFBSSxDQUFDLElBRGhCLENBQUE7QUFBQSxRQUVBLEtBQUEsR0FBVyxTQUFILEdBQWtCLFNBQVMsQ0FBQyxJQUE1QixHQUFzQyxJQUFDLENBQUEsR0FGL0MsQ0FORjtPQUFBO0FBQUEsTUFVQSxJQUFBLEdBQU8sS0FBSyxDQUFDLE9BVmIsQ0FBQTtBQWFBLE1BQUEsSUFBRyxRQUFBLFlBQW9CLEdBQUcsQ0FBQyxTQUEzQjtBQUNFLFFBQUEsR0FBQSxHQUFVLElBQUEsR0FBRyxDQUFDLE1BQUosQ0FBVyxJQUFYLEVBQWlCLE9BQWpCLEVBQTBCLElBQTFCLEVBQWdDLE1BQWhDLEVBQTJDLE1BQTNDLEVBQXNELElBQXRELEVBQTRELEtBQTVELENBQVYsQ0FBQTtBQUFBLFFBQ0EsR0FBRyxDQUFDLE9BQUosQ0FBQSxDQURBLENBREY7T0FBQSxNQUFBO0FBSUUsYUFBQSwrQ0FBQTsyQkFBQTtBQUNFLFVBQUEsSUFBRyxXQUFBLElBQU8saUJBQVAsSUFBb0IscUJBQXZCO0FBQ0UsWUFBQSxDQUFBLEdBQUksQ0FBQyxDQUFDLFNBQUYsQ0FBWSxJQUFDLENBQUEsWUFBYixFQUEyQixJQUFDLENBQUEsVUFBNUIsQ0FBSixDQURGO1dBQUE7QUFBQSxVQUVBLEdBQUEsR0FBVSxJQUFBLEdBQUcsQ0FBQyxNQUFKLENBQVcsSUFBWCxFQUFpQixDQUFqQixFQUFvQixJQUFwQixFQUEwQixNQUExQixFQUFxQyxNQUFyQyxFQUFnRCxJQUFoRCxFQUFzRCxLQUF0RCxDQUZWLENBQUE7QUFBQSxVQUdBLEdBQUcsQ0FBQyxPQUFKLENBQUEsQ0FIQSxDQUFBO0FBQUEsVUFJQSxRQUFBLEdBQVcsR0FBRyxDQUFDLElBSmYsQ0FBQTtBQUFBLFVBTUEsSUFBQSxHQUFPLEdBTlAsQ0FERjtBQUFBLFNBSkY7T0FiQTthQXlCQSxLQTFCVztJQUFBLENBL0liLENBQUE7O0FBQUEsMEJBaUxBLE1BQUEsR0FBUSxTQUFDLFFBQUQsRUFBVyxRQUFYLEdBQUE7QUFDTixVQUFBLEdBQUE7QUFBQSxNQUFBLEdBQUEsR0FBTSxJQUFDLENBQUEsc0JBQUQsQ0FBd0IsUUFBeEIsQ0FBTixDQUFBO2FBR0EsSUFBQyxDQUFBLFdBQUQsQ0FBYSxHQUFiLEVBQWtCLFFBQWxCLEVBSk07SUFBQSxDQWpMUixDQUFBOztBQUFBLDBCQTRMQSxTQUFBLEdBQVcsU0FBQyxTQUFELEVBQVksTUFBWixFQUF3QixHQUF4QixHQUFBO0FBQ1QsVUFBQSxxQ0FBQTs7UUFEcUIsU0FBUztPQUM5Qjs7UUFEaUMsTUFBTTtPQUN2QztBQUFBLE1BQUEsYUFBQSxHQUFnQixDQUFBLFNBQUEsS0FBQSxHQUFBO2VBQUEsU0FBQyxTQUFELEdBQUE7QUFDZCxVQUFBLElBQUcsR0FBQSxLQUFPLE9BQVY7bUJBQXVCLEtBQUMsQ0FBQSxpQkFBRCxDQUFtQixTQUFuQixFQUF2QjtXQUFBLE1BQUE7bUJBQXlELEtBQUMsQ0FBQSxpQkFBRCxDQUFtQixTQUFuQixFQUF6RDtXQURjO1FBQUEsRUFBQTtNQUFBLENBQUEsQ0FBQSxDQUFBLElBQUEsQ0FBaEIsQ0FBQTtBQUdBLFdBQVMsa0ZBQVQsR0FBQTtBQUNFLFFBQUEsSUFBRyxTQUFBLFlBQXFCLEdBQUcsQ0FBQyxTQUE1QjtBQUNFLGdCQURGO1NBQUE7QUFBQSxRQUVBLGVBQUEsR0FBa0IsQ0FBSyxJQUFBLEdBQUcsQ0FBQyxNQUFKLENBQVcsSUFBWCxFQUFpQixNQUFqQixFQUE0QixTQUE1QixDQUFMLENBQTJDLENBQUMsT0FBNUMsQ0FBQSxDQUZsQixDQUFBO0FBQUEsUUFJQSxTQUFBLEdBQVksYUFBQSxDQUFjLFNBQWQsQ0FKWixDQURGO0FBQUEsT0FIQTthQVNBLEtBVlM7SUFBQSxDQTVMWCxDQUFBOztBQUFBLDBCQXdNQSxTQUFBLEdBQVEsU0FBQyxRQUFELEVBQVcsTUFBWCxHQUFBO0FBQ04sVUFBQSxTQUFBOztRQURpQixTQUFTO09BQzFCO0FBQUEsTUFBQSxTQUFBLEdBQVksSUFBQyxDQUFBLHNCQUFELENBQXdCLFFBQUEsR0FBUyxNQUFqQyxDQUFaLENBQUE7YUFFQSxJQUFDLENBQUEsU0FBRCxDQUFXLFNBQVgsRUFBc0IsTUFBdEIsRUFBOEIsTUFBOUIsRUFITTtJQUFBLENBeE1SLENBQUE7O0FBQUEsMEJBOE1BLGlDQUFBLEdBQW1DLFNBQUMsU0FBRCxHQUFBO0FBQ2pDLFVBQUEsOENBQUE7QUFBQSxNQUFBLElBQUEsR0FBTyxDQUFDLElBQUMsQ0FBQSxpQkFBRCxDQUFtQixTQUFuQixDQUFELENBQUEsSUFBa0MsSUFBQyxDQUFBLFNBQTFDLENBQUE7QUFBQSxNQUNBLFFBQUEsR0FBYyxJQUFILEdBQWEsSUFBSSxDQUFDLElBQWxCLEdBQTRCLElBRHZDLENBQUE7QUFBQSxNQUdBLElBQUEsR0FBTyxDQUFDLElBQUMsQ0FBQSxpQkFBRCxDQUFtQixTQUFuQixDQUFELENBQUEsSUFBa0MsSUFBQyxDQUFBLEdBSDFDLENBQUE7QUFBQSxNQUlBLFFBQUEsR0FBYyxJQUFILEdBQWEsSUFBSSxDQUFDLElBQWxCLEdBQTRCLElBSnZDLENBQUE7QUFBQSxNQUtBLFNBQVMsQ0FBQyxJQUFWLEdBQWlCLFNBQVMsQ0FBQyxJQUFWLElBQWtCLENBQUMsSUFBQyxDQUFBLFNBQVMsQ0FBQyxjQUFYLENBQTBCLFFBQTFCLEVBQW9DLFFBQXBDLEVBQThDLFNBQTlDLENBQUQsQ0FMbkMsQ0FBQTtBQUFBLE1BTUEsU0FBUyxDQUFDLFlBQVYsR0FBeUIsU0FBUyxDQUFDLFlBQVYsSUFBMEIsQ0FBQyxJQUFDLENBQUEsWUFBWSxDQUFDLGNBQWQsQ0FBNkIsU0FBUyxDQUFDLE9BQU8sQ0FBQyxZQUEvQyxFQUE2RCxTQUFTLENBQUMsT0FBTyxDQUFDLFlBQS9FLEVBQTZGLFNBQTdGLENBQUQsQ0FObkQsQ0FBQTtBQUFBLE1BUUEsY0FBQSxHQUFpQixTQUFDLE9BQUQsR0FBQTtBQUNmLFFBQUEsSUFBRyxPQUFBLFlBQW1CLEdBQUcsQ0FBQyxTQUExQjtpQkFDRSxPQUFPLENBQUMsYUFBUixDQUFBLEVBREY7U0FBQSxNQUFBO2lCQUdFLFFBSEY7U0FEZTtNQUFBLENBUmpCLENBQUE7YUFjQSxJQUFDLENBQUEsU0FBRCxDQUFXO1FBQ1Q7QUFBQSxVQUFBLElBQUEsRUFBTSxRQUFOO0FBQUEsVUFDQSxTQUFBLEVBQVcsU0FEWDtBQUFBLFVBRUEsUUFBQSxFQUFVLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBZixDQUFBLENBRlY7QUFBQSxVQUdBLE1BQUEsRUFBUSxJQUFDLENBQUEsYUFBRCxDQUFBLENBSFI7QUFBQSxVQUlBLFNBQUEsRUFBVyxTQUFTLENBQUMsR0FBRyxDQUFDLE9BSnpCO0FBQUEsVUFLQSxLQUFBLEVBQU8sY0FBQSxDQUFlLFNBQVMsQ0FBQyxHQUFWLENBQUEsQ0FBZixDQUxQO1NBRFM7T0FBWCxFQWZpQztJQUFBLENBOU1uQyxDQUFBOztBQUFBLDBCQXNPQSxpQ0FBQSxHQUFtQyxTQUFDLFNBQUQsRUFBWSxNQUFaLEdBQUE7QUFDakMsVUFBQSxRQUFBO0FBQUEsTUFBQSxJQUFHLFNBQVMsQ0FBQyxJQUFiO0FBQ0UsUUFBQSxRQUFBLEdBQVcsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFmLENBQUEsQ0FBWCxDQUFBO0FBQUEsUUFDQSxJQUFDLENBQUEsU0FBUyxDQUFDLFdBQVgsQ0FBdUIsU0FBUyxDQUFDLElBQWpDLENBREEsQ0FBQTtBQUFBLFFBRUEsU0FBUyxDQUFDLElBQVYsR0FBaUIsSUFGakIsQ0FERjtPQUFBO2FBS0EsSUFBQyxDQUFBLFNBQUQsQ0FBVztRQUNUO0FBQUEsVUFBQSxJQUFBLEVBQU0sUUFBTjtBQUFBLFVBQ0EsU0FBQSxFQUFXLFNBRFg7QUFBQSxVQUVBLFFBQUEsRUFBVSxRQUZWO0FBQUEsVUFHQSxNQUFBLEVBQVEsSUFBQyxDQUFBLGFBQUQsQ0FBQSxDQUhSO0FBQUEsVUFJQSxNQUFBLEVBQVEsQ0FKUjtBQUFBLFVBS0EsU0FBQSxFQUFXLE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FMdEI7QUFBQSxVQU1BLFFBQUEsRUFBVSxTQUFTLENBQUMsR0FBVixDQUFBLENBTlY7U0FEUztPQUFYLEVBTmlDO0lBQUEsQ0F0T25DLENBQUE7O3VCQUFBOztLQVA0QixHQUFHLENBQUMsVUE3RmxDLENBQUE7QUFBQSxFQTBWQSxHQUFHLENBQUMsV0FBVyxDQUFDLEtBQWhCLEdBQXdCLFNBQUMsSUFBRCxHQUFBO0FBQ3RCLFFBQUEsNkNBQUE7QUFBQSxJQUNVLFdBQVIsTUFERixFQUVpQixtQkFBZixjQUZGLEVBR2MsZUFBWixVQUhGLEVBSXlCLDBCQUF2QixxQkFKRixDQUFBO1dBTUksSUFBQSxJQUFBLENBQUssV0FBTCxFQUFrQixHQUFsQixFQUF1QixPQUF2QixFQUFnQyxrQkFBaEMsRUFQa0I7RUFBQSxDQTFWeEIsQ0FBQTtBQUFBLEVBbVdNLEdBQUcsQ0FBQztBQUVSLGtDQUFBLENBQUE7O0FBQWEsSUFBQSxxQkFBQyxXQUFELEVBQWUsa0JBQWYsRUFBbUMsNEJBQW5DLEVBQWlFLEdBQWpFLEVBQXNFLG1CQUF0RSxHQUFBO0FBSVgsVUFBQSxJQUFBO0FBQUEsTUFKeUIsSUFBQyxDQUFBLHFCQUFBLGtCQUkxQixDQUFBO0FBQUEsTUFBQSw2Q0FBTSxXQUFOLEVBQW1CLEdBQW5CLENBQUEsQ0FBQTtBQUNBLE1BQUEsSUFBRywyQkFBSDtBQUNFLFFBQUEsSUFBQyxDQUFBLG1CQUFELEdBQXVCLG1CQUF2QixDQURGO09BQUEsTUFBQTtBQUdFLFFBQUEsSUFBQyxDQUFBLGVBQUQsR0FBbUIsSUFBQyxDQUFBLEdBQUcsQ0FBQyxPQUF4QixDQUhGO09BREE7QUFLQSxNQUFBLElBQUcsb0NBQUg7QUFDRSxRQUFBLElBQUMsQ0FBQSw0QkFBRCxHQUFnQyxFQUFoQyxDQUFBO0FBQ0EsYUFBQSxpQ0FBQTs4Q0FBQTtBQUNFLFVBQUEsSUFBQyxDQUFBLGFBQUQsQ0FBZSxDQUFmLEVBQWtCLENBQWxCLEVBQXFCLG9CQUFyQixDQUFBLENBREY7QUFBQSxTQUZGO09BVFc7SUFBQSxDQUFiOztBQUFBLDBCQWNBLElBQUEsR0FBTSxhQWROLENBQUE7O0FBQUEsMEJBb0JBLE9BQUEsR0FBUyxTQUFBLEdBQUE7QUFDUCxVQUFBLGVBQUE7QUFBQSxNQUFBLElBQUcsSUFBQyxDQUFBLHVCQUFELENBQUEsQ0FBSDtBQUNFLFFBQUEsSUFBQyxDQUFBLGFBQUQsQ0FBQSxDQUFnQixDQUFDLG9CQUFqQixDQUFzQyxJQUFDLENBQUEsa0JBQXZDLENBQUEsQ0FBQTtBQUFBLFFBQ0EsTUFBQSxDQUFBLElBQVEsQ0FBQSxrQkFEUixDQUFBO0FBR0EsUUFBQSxJQUFHLElBQUMsQ0FBQSxtQkFBSjtBQUNFLFVBQUEsZUFBQSxHQUFrQixJQUFDLENBQUEsRUFBRSxDQUFDLFlBQUosQ0FBaUIsSUFBQyxDQUFBLG1CQUFsQixDQUFsQixDQUFBO0FBQ0EsVUFBQSxJQUFHLHVCQUFIO0FBQ0UsWUFBQSxNQUFBLENBQUEsSUFBUSxDQUFBLG1CQUFSLENBQUE7QUFBQSxZQUNBLElBQUMsQ0FBQSxlQUFELEdBQW1CLGVBRG5CLENBREY7V0FGRjtTQUhBO2VBUUEsMENBQUEsU0FBQSxFQVRGO09BQUEsTUFBQTtlQVdFLE1BWEY7T0FETztJQUFBLENBcEJULENBQUE7O0FBQUEsMEJBcUNBLGlDQUFBLEdBQW1DLFNBQUMsU0FBRCxHQUFBO0FBQ2pDLFVBQUEsQ0FBQTtBQUFBLE1BQUEsSUFBRyxnQ0FBSDtBQUNFLFFBQUEsSUFBRyxTQUFTLENBQUMsR0FBRyxDQUFDLE9BQWQsS0FBeUIsSUFBQyxDQUFBLG1CQUFtQixDQUFDLE9BQTlDLElBQTBELFNBQVMsQ0FBQyxHQUFHLENBQUMsU0FBZCxLQUEyQixJQUFDLENBQUEsbUJBQW1CLENBQUMsU0FBN0c7QUFDRSxVQUFBLElBQUMsQ0FBQSxlQUFELEdBQW1CLFNBQW5CLENBQUE7QUFBQSxVQUNBLE1BQUEsQ0FBQSxJQUFRLENBQUEsbUJBRFIsQ0FBQTtBQUFBLFVBRUEsU0FBQSxHQUFZLFNBQVMsQ0FBQyxPQUZ0QixDQUFBO0FBR0EsVUFBQSxJQUFHLFNBQUEsS0FBYSxJQUFDLENBQUEsR0FBakI7QUFDRSxrQkFBQSxDQURGO1dBSkY7U0FBQSxNQUFBO0FBT0UsZ0JBQUEsQ0FQRjtTQURGO09BQUE7QUFBQSxNQVVBLENBQUEsR0FBSSxJQUFDLENBQUEsR0FBRyxDQUFDLE9BVlQsQ0FBQTtBQVdBLGFBQU0sQ0FBQSxLQUFPLFNBQWIsR0FBQTtBQUNFLFFBQUEsSUFBQyxDQUFBLGFBQUQsQ0FBQSxDQUFnQixDQUFDLFFBQWpCLENBQTBCLENBQUMsQ0FBQyxVQUE1QixDQUFBLENBQUE7QUFBQSxRQUNBLENBQUEsR0FBSSxDQUFDLENBQUMsT0FETixDQURGO01BQUEsQ0FYQTtBQWNBLGFBQU0sQ0FBQSxLQUFPLElBQUMsQ0FBQSxHQUFkLEdBQUE7QUFDRSxRQUFBLENBQUMsQ0FBQyxVQUFGLEdBQWUsSUFBQyxDQUFBLGFBQUQsQ0FBQSxDQUFnQixDQUFDLE1BQWpCLENBQXdCLENBQUMsQ0FBQyxHQUFGLENBQUEsQ0FBeEIsQ0FBZixDQUFBO0FBQUEsUUFDQSxDQUFBLEdBQUksQ0FBQyxDQUFDLE9BRE4sQ0FERjtNQUFBLENBZEE7QUFBQSxNQWlCQSxJQUFDLENBQUEsZUFBRCxHQUFtQixJQUFDLENBQUEsR0FBRyxDQUFDLE9BakJ4QixDQUFBO2FBbUJBLElBQUMsQ0FBQSxTQUFELENBQVc7UUFDVDtBQUFBLFVBQUEsSUFBQSxFQUFNLFFBQU47QUFBQSxVQUNBLFNBQUEsRUFBVyxTQUFTLENBQUMsR0FBRyxDQUFDLE9BRHpCO0FBQUEsVUFFQSxRQUFBLEVBQVUsSUFBQyxDQUFBLEdBQUQsQ0FBQSxDQUZWO1NBRFM7T0FBWCxFQXBCaUM7SUFBQSxDQXJDbkMsQ0FBQTs7QUFBQSwwQkErREEsaUNBQUEsR0FBbUMsU0FBQyxTQUFELEVBQVksTUFBWixHQUFBLENBL0RuQyxDQUFBOztBQUFBLDBCQTBFQSxVQUFBLEdBQVksU0FBQyxLQUFELEVBQVEsVUFBUixHQUFBO0FBQ1YsTUFBQSxDQUFLLElBQUEsR0FBRyxDQUFDLE1BQUosQ0FBVyxJQUFYLEVBQWlCLEtBQWpCLEVBQXdCLFVBQXhCLEVBQW9DLElBQXBDLEVBQXVDLElBQXZDLEVBQTZDLElBQUMsQ0FBQSxHQUFHLENBQUMsT0FBbEQsRUFBMkQsSUFBQyxDQUFBLEdBQTVELENBQUwsQ0FBcUUsQ0FBQyxPQUF0RSxDQUFBLENBQUEsQ0FBQTthQUNBLE9BRlU7SUFBQSxDQTFFWixDQUFBOztBQUFBLDBCQWlGQSxPQUFBLEdBQVMsU0FBQyxJQUFELEdBQUE7QUFDUCxVQUFBLGtCQUFBOztRQURRLE9BQU87T0FDZjtBQUFBLE1BQUEsTUFBQSxHQUFTLElBQUMsQ0FBQSxhQUFELENBQUEsQ0FBZ0IsQ0FBQyxvQkFBakIsQ0FBQSxDQUFULENBQUE7QUFBQSxNQUNBLElBQUksQ0FBQyxpQkFBTCxHQUF5QixNQUFNLENBQUMsaUJBRGhDLENBQUE7QUFFQSxNQUFBLElBQUcsMkNBQUg7QUFDRSxRQUFBLElBQUksQ0FBQyw0QkFBTCxHQUFvQyxFQUFwQyxDQUFBO0FBQ0E7QUFBQSxhQUFBLFNBQUE7c0JBQUE7QUFDRSxVQUFBLElBQUksQ0FBQyw0QkFBNkIsQ0FBQSxDQUFBLENBQWxDLEdBQXVDLENBQUMsQ0FBQyxNQUFGLENBQUEsQ0FBdkMsQ0FERjtBQUFBLFNBRkY7T0FGQTtBQU1BLE1BQUEsSUFBRyw0QkFBSDtBQUNFLFFBQUEsSUFBSSxDQUFDLGVBQUwsR0FBdUIsSUFBQyxDQUFBLGVBQWUsQ0FBQyxNQUFqQixDQUFBLENBQXZCLENBREY7T0FBQSxNQUFBO0FBR0UsUUFBQSxJQUFJLENBQUMsZUFBTCxHQUF1QixJQUFDLENBQUEsbUJBQXhCLENBSEY7T0FOQTthQVVBLHlDQUFNLElBQU4sRUFYTztJQUFBLENBakZULENBQUE7O3VCQUFBOztLQUY0QixHQUFHLENBQUMsWUFuV2xDLENBQUE7QUFBQSxFQW1jQSxHQUFHLENBQUMsV0FBVyxDQUFDLEtBQWhCLEdBQXdCLFNBQUMsSUFBRCxHQUFBO0FBQ3RCLFFBQUEsa0ZBQUE7QUFBQSxJQUNVLFdBQVIsTUFERixFQUVpQixtQkFBZixjQUZGLEVBR3dCLHlCQUF0QixvQkFIRixFQUltQyxvQ0FBakMsK0JBSkYsRUFLc0IsdUJBQXBCLGtCQUxGLENBQUE7V0FPSSxJQUFBLElBQUEsQ0FBSyxXQUFMLEVBQWtCLGlCQUFsQixFQUFxQyw0QkFBckMsRUFBbUUsR0FBbkUsRUFBd0UsZUFBeEUsRUFSa0I7RUFBQSxDQW5jeEIsQ0FBQTtBQUFBLEVBc2RNLEdBQUcsQ0FBQztBQVFSLHFDQUFBLENBQUE7O0FBQWEsSUFBQSx3QkFBQyxXQUFELEVBQWUsZ0JBQWYsRUFBa0MsVUFBbEMsRUFBOEMsR0FBOUMsR0FBQTtBQUNYLE1BRHlCLElBQUMsQ0FBQSxtQkFBQSxnQkFDMUIsQ0FBQTtBQUFBLE1BRDRDLElBQUMsQ0FBQSxhQUFBLFVBQzdDLENBQUE7QUFBQSxNQUFBLElBQU8sdUNBQVA7QUFDRSxRQUFBLElBQUMsQ0FBQSxnQkFBaUIsQ0FBQSxRQUFBLENBQWxCLEdBQThCLElBQUMsQ0FBQSxVQUFVLENBQUMsYUFBWixDQUFBLENBQTlCLENBREY7T0FBQTtBQUFBLE1BRUEsZ0RBQU0sV0FBTixFQUFtQixHQUFuQixDQUZBLENBRFc7SUFBQSxDQUFiOztBQUFBLDZCQUtBLElBQUEsR0FBTSxnQkFMTixDQUFBOztBQUFBLDZCQWNBLGtCQUFBLEdBQW9CLFNBQUMsTUFBRCxHQUFBO0FBQ2xCLFVBQUEsaUNBQUE7QUFBQSxNQUFBLElBQUcsQ0FBQSxJQUFLLENBQUEsU0FBRCxDQUFBLENBQVA7QUFDRSxhQUFBLDZDQUFBOzZCQUFBO0FBQ0U7QUFBQSxlQUFBLFlBQUE7OEJBQUE7QUFDRSxZQUFBLEtBQU0sQ0FBQSxJQUFBLENBQU4sR0FBYyxJQUFkLENBREY7QUFBQSxXQURGO0FBQUEsU0FBQTtBQUFBLFFBR0EsSUFBQyxDQUFBLFVBQVUsQ0FBQyxTQUFaLENBQXNCLE1BQXRCLENBSEEsQ0FERjtPQUFBO2FBS0EsT0FOa0I7SUFBQSxDQWRwQixDQUFBOztBQUFBLDZCQTJCQSxpQ0FBQSxHQUFtQyxTQUFDLFNBQUQsR0FBQTtBQUNqQyxVQUFBLFNBQUE7QUFBQSxNQUFBLElBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFsQixLQUEwQixXQUExQixJQUEwQyxTQUFTLENBQUMsT0FBTyxDQUFDLElBQWxCLEtBQTRCLFdBQXpFO0FBRUUsUUFBQSxJQUFHLENBQUEsU0FBYSxDQUFDLFVBQWpCO0FBQ0UsVUFBQSxTQUFBLEdBQVksU0FBUyxDQUFDLE9BQU8sQ0FBQyxHQUFsQixDQUFBLENBQVosQ0FBQTtBQUFBLFVBQ0EsSUFBQyxDQUFBLGtCQUFELENBQW9CO1lBQ2xCO0FBQUEsY0FBQSxJQUFBLEVBQU0sUUFBTjtBQUFBLGNBQ0EsU0FBQSxFQUFXLFNBQVMsQ0FBQyxHQUFHLENBQUMsT0FEekI7QUFBQSxjQUVBLFFBQUEsRUFBVSxTQUZWO2FBRGtCO1dBQXBCLENBREEsQ0FERjtTQUFBO0FBQUEsUUFPQSxTQUFTLENBQUMsT0FBTyxDQUFDLFdBQWxCLENBQUEsQ0FQQSxDQUZGO09BQUEsTUFVSyxJQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsSUFBbEIsS0FBNEIsV0FBL0I7QUFHSCxRQUFBLFNBQVMsQ0FBQyxXQUFWLENBQUEsQ0FBQSxDQUhHO09BQUEsTUFBQTtBQUtILFFBQUEsSUFBQyxDQUFBLGtCQUFELENBQW9CO1VBQ2xCO0FBQUEsWUFBQSxJQUFBLEVBQU0sS0FBTjtBQUFBLFlBQ0EsU0FBQSxFQUFXLFNBQVMsQ0FBQyxHQUFHLENBQUMsT0FEekI7V0FEa0I7U0FBcEIsQ0FBQSxDQUxHO09BVkw7YUFtQkEsT0FwQmlDO0lBQUEsQ0EzQm5DLENBQUE7O0FBQUEsNkJBaURBLGlDQUFBLEdBQW1DLFNBQUMsU0FBRCxFQUFZLE1BQVosR0FBQTtBQUNqQyxNQUFBLElBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxJQUFsQixLQUEwQixXQUE3QjtlQUNFLElBQUMsQ0FBQSxrQkFBRCxDQUFvQjtVQUNsQjtBQUFBLFlBQUEsSUFBQSxFQUFNLFFBQU47QUFBQSxZQUNBLFNBQUEsRUFBVyxNQUFNLENBQUMsR0FBRyxDQUFDLE9BRHRCO0FBQUEsWUFFQSxRQUFBLEVBQVUsU0FBUyxDQUFDLEdBQVYsQ0FBQSxDQUZWO1dBRGtCO1NBQXBCLEVBREY7T0FEaUM7SUFBQSxDQWpEbkMsQ0FBQTs7QUFBQSw2QkFnRUEsT0FBQSxHQUFTLFNBQUMsT0FBRCxFQUFVLGVBQVYsR0FBQTtBQUNQLFVBQUEsT0FBQTtBQUFBLE1BQUEsQ0FBQSxHQUFJLElBQUMsQ0FBQSxnQkFBRCxDQUFBLENBQUosQ0FBQTtBQUFBLE1BQ0EsSUFBQSxHQUFPLENBQUssSUFBQSxHQUFHLENBQUMsTUFBSixDQUFXLElBQVgsRUFBaUIsT0FBakIsRUFBMEIsSUFBMUIsRUFBZ0MsSUFBaEMsRUFBbUMsZUFBbkMsRUFBb0QsQ0FBcEQsRUFBdUQsQ0FBQyxDQUFDLE9BQXpELENBQUwsQ0FBc0UsQ0FBQyxPQUF2RSxDQUFBLENBRFAsQ0FBQTthQUdBLE9BSk87SUFBQSxDQWhFVCxDQUFBOztBQUFBLDZCQXNFQSxnQkFBQSxHQUFrQixTQUFBLEdBQUE7YUFDaEIsSUFBQyxDQUFBLGdCQUFELENBQUEsQ0FBbUIsQ0FBQyxTQUFwQixDQUFBLEVBRGdCO0lBQUEsQ0F0RWxCLENBQUE7O0FBQUEsNkJBeUVBLGFBQUEsR0FBZSxTQUFBLEdBQUE7QUFDYixVQUFBLE9BQUE7QUFBQSxNQUFBLE9BQUEsR0FBVSxJQUFDLENBQUEsZ0JBQUQsQ0FBQSxDQUFWLENBQUE7QUFDQSxNQUFBLElBQUcsQ0FBQyxDQUFBLE9BQVcsQ0FBQyxTQUFSLENBQUEsQ0FBTCxDQUFBLElBQThCLE9BQU8sQ0FBQyxJQUFSLEtBQWtCLFdBQW5EO0FBQ0UsUUFBQSxDQUFLLElBQUEsR0FBRyxDQUFDLE1BQUosQ0FBVyxJQUFYLEVBQWlCLE1BQWpCLEVBQTRCLElBQUMsQ0FBQSxnQkFBRCxDQUFBLENBQW1CLENBQUMsR0FBaEQsQ0FBTCxDQUF5RCxDQUFDLE9BQTFELENBQUEsQ0FBQSxDQURGO09BREE7YUFHQSxPQUphO0lBQUEsQ0F6RWYsQ0FBQTs7QUFBQSw2QkFtRkEsR0FBQSxHQUFLLFNBQUEsR0FBQTtBQUNILFVBQUEsQ0FBQTtBQUFBLE1BQUEsQ0FBQSxHQUFJLElBQUMsQ0FBQSxnQkFBRCxDQUFBLENBQUosQ0FBQTsyQ0FHQSxDQUFDLENBQUMsZUFKQztJQUFBLENBbkZMLENBQUE7OzBCQUFBOztLQVIrQixHQUFHLENBQUMsWUF0ZHJDLENBQUE7U0F1akJBLFVBeGpCZTtBQUFBLENBSGpCLENBQUE7Ozs7QUNDQSxJQUFBLDRFQUFBOztBQUFBLDRCQUFBLEdBQStCLE9BQUEsQ0FBUSx5QkFBUixDQUEvQixDQUFBOztBQUFBLGFBRUEsR0FBZ0IsT0FBQSxDQUFRLGlCQUFSLENBRmhCLENBQUE7O0FBQUEsTUFHQSxHQUFTLE9BQUEsQ0FBUSxVQUFSLENBSFQsQ0FBQTs7QUFBQSxjQUlBLEdBQWlCLE9BQUEsQ0FBUSxvQkFBUixDQUpqQixDQUFBOztBQUFBLE9BTUEsR0FBVSxTQUFDLFNBQUQsR0FBQTtBQUNSLE1BQUEsZ0RBQUE7QUFBQSxFQUFBLElBQUcseUJBQUg7QUFDRSxJQUFBLE9BQUEsR0FBVSxTQUFTLENBQUMsT0FBcEIsQ0FERjtHQUFBLE1BQUE7QUFHRSxJQUFBLE9BQUEsR0FBVSxPQUFWLENBQUE7QUFBQSxJQUNBLFNBQVMsQ0FBQyxvQ0FBVixHQUFpRDtNQUFDLFNBQUMsWUFBRCxHQUFBO2VBQzlDLEVBQUUsQ0FBQyxTQUFILENBQWEsSUFBSSxDQUFDLE9BQWxCLEVBQTJCLFlBQTNCLEVBRDhDO01BQUEsQ0FBRDtLQURqRCxDQUhGO0dBQUE7QUFBQSxFQU9BLEVBQUEsR0FBUyxJQUFBLGFBQUEsQ0FBYyxPQUFkLENBUFQsQ0FBQTtBQUFBLEVBUUEsV0FBQSxHQUFjLDRCQUFBLENBQTZCLEVBQTdCLEVBQWlDLElBQUksQ0FBQyxXQUF0QyxDQVJkLENBQUE7QUFBQSxFQVNBLEdBQUEsR0FBTSxXQUFXLENBQUMsVUFUbEIsQ0FBQTtBQUFBLEVBV0EsTUFBQSxHQUFhLElBQUEsTUFBQSxDQUFPLEVBQVAsRUFBVyxHQUFYLENBWGIsQ0FBQTtBQUFBLEVBWUEsY0FBQSxDQUFlLFNBQWYsRUFBMEIsTUFBMUIsRUFBa0MsRUFBbEMsRUFBc0MsV0FBVyxDQUFDLGtCQUFsRCxDQVpBLENBQUE7QUFBQSxFQWNBLEdBQUcsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLEVBQXhCLEdBQTZCLEVBZDdCLENBQUE7QUFBQSxFQWVBLEdBQUcsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLFVBQXhCLEdBQXFDLEdBZnJDLENBQUE7QUFBQSxFQWdCQSxHQUFHLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxNQUF4QixHQUFpQyxNQWhCakMsQ0FBQTtBQUFBLEVBaUJBLEdBQUcsQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLFNBQXhCLEdBQW9DLFNBakJwQyxDQUFBO0FBQUEsRUFrQkEsR0FBRyxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsWUFBeEIsR0FBdUMsSUFBSSxDQUFDLFdBbEI1QyxDQUFBO0FBQUEsRUFvQkEsRUFBQSxHQUFTLElBQUEsT0FBTyxDQUFDLE1BQVIsQ0FBQSxDQXBCVCxDQUFBO0FBQUEsRUFxQkEsS0FBQSxHQUFZLElBQUEsR0FBRyxDQUFDLFVBQUosQ0FBZSxFQUFmLEVBQW1CLEVBQUUsQ0FBQywyQkFBSCxDQUFBLENBQW5CLENBQW9ELENBQUMsT0FBckQsQ0FBQSxDQXJCWixDQUFBO0FBQUEsRUFzQkEsRUFBRSxDQUFDLFNBQUgsQ0FBYSxLQUFiLENBdEJBLENBQUE7U0F1QkEsR0F4QlE7QUFBQSxDQU5WLENBQUE7O0FBQUEsTUFnQ00sQ0FBQyxPQUFQLEdBQWlCLE9BaENqQixDQUFBOztBQWlDQSxJQUFHLGdEQUFIO0FBQ0UsRUFBQSxNQUFNLENBQUMsQ0FBUCxHQUFXLE9BQVgsQ0FERjtDQWpDQTs7QUFBQSxPQW9DTyxDQUFDLE1BQVIsR0FBaUIsT0FBQSxDQUFRLGNBQVIsQ0FwQ2pCLENBQUE7Ozs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdmZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pQQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqa0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy91Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN1VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3REQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5R0E7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDalFBO0FBQ0E7O0FDREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1a0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6V0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOVBBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNWNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcFlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9HQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbFBBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDak9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hhQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvWUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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InNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3Rocm93IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIil9dmFyIGY9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGYuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sZixmLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsImNsYXNzIFlMaXN0XG4gICNcbiAgIyBAcHJpdmF0ZVxuICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgI1xuICBjb25zdHJ1Y3RvcjogKGxpc3QpLT5cbiAgICBpZiBub3QgbGlzdD9cbiAgICAgIEBfbGlzdCA9IFtdXG4gICAgZWxzZSBpZiBsaXN0LmNvbnN0cnVjdG9yIGlzIEFycmF5XG4gICAgICBAX2xpc3QgPSBsaXN0XG4gICAgZWxzZVxuICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWS5MaXN0IGV4cGVjdHMgYW4gQXJyYXkgYXMgYSBwYXJhbWV0ZXJcIlxuXG4gIF9uYW1lOiBcIkxpc3RcIlxuXG4gIF9nZXRNb2RlbDogKHR5cGVzLCBvcHMpLT5cbiAgICBpZiBub3QgQF9tb2RlbD9cbiAgICAgIEBfbW9kZWwgPSBuZXcgb3BzLkxpc3RNYW5hZ2VyKEApLmV4ZWN1dGUoKVxuICAgICAgQF9tb2RlbC5pbnNlcnQgMCwgQF9saXN0XG4gICAgZGVsZXRlIEBfbGlzdFxuXG4gICAgQF9tb2RlbFxuXG4gIF9zZXRNb2RlbDogKEBfbW9kZWwpLT5cbiAgICBkZWxldGUgQF9saXN0XG5cbiAgdmFsOiAoKS0+XG4gICAgQF9tb2RlbC52YWwgYXJndW1lbnRzLi4uXG5cbiAgcmVmOiAoKS0+XG4gICAgQF9tb2RlbC5yZWYgYXJndW1lbnRzLi4uXG5cblxuICBvYnNlcnZlOiAoKS0+XG4gICAgQF9tb2RlbC5vYnNlcnZlIGFyZ3VtZW50cy4uLlxuICAgIEBcblxuICB1bm9ic2VydmU6ICgpLT5cbiAgICBAX21vZGVsLnVub2JzZXJ2ZSBhcmd1bWVudHMuLi5cbiAgICBAXG5cbiAgI1xuICAjIEluc2VydHMgYW4gT2JqZWN0IGludG8gdGhlIGxpc3QuXG4gICNcbiAgIyBAcmV0dXJuIHtMaXN0TWFuYWdlciBUeXBlfSBUaGlzIFN0cmluZyBvYmplY3QuXG4gICNcbiAgaW5zZXJ0OiAocG9zaXRpb24sIGNvbnRlbnQpLT5cbiAgICBAaW5zZXJ0Q29udGVudHMgcG9zaXRpb24sIFtjb250ZW50XVxuXG4gIGluc2VydENvbnRlbnRzOiAocG9zaXRpb24sIGNvbnRlbnRzKS0+XG4gICAgaWYgdHlwZW9mIHBvc2l0aW9uIGlzbnQgXCJudW1iZXJcIlxuICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWS5MaXN0Lmluc2VydCBleHBlY3RzIGEgTnVtYmVyIGFzIHRoZSBmaXJzdCBwYXJhbWV0ZXIhXCJcblxuICAgIEBfbW9kZWwuaW5zZXJ0IHBvc2l0aW9uLCBjb250ZW50c1xuICAgIEBcblxuICBkZWxldGU6IChwb3NpdGlvbiwgbGVuZ3RoKS0+XG4gICAgQF9tb2RlbC5kZWxldGUgcG9zaXRpb24sIGxlbmd0aFxuICAgIEBcblxuICBwdXNoOiAoY29udGVudCktPlxuICAgIEBfbW9kZWwucHVzaCBjb250ZW50XG4gICAgQFxuXG4gIGdldExlbmd0aDogKCkgLT5cbiAgICBAX21vZGVsLmdldExlbmd0aCgpXG5cbmlmIHdpbmRvdz9cbiAgaWYgd2luZG93Llk/XG4gICAgd2luZG93LlkuTGlzdCA9IFlMaXN0XG4gIGVsc2VcbiAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBmaXJzdCBpbXBvcnQgWSFcIlxuXG5pZiBtb2R1bGU/XG4gIG1vZHVsZS5leHBvcnRzID0gWUxpc3RcbiIsIlxuI1xuIyBBIHRyaXZpYWwgQ29ubmVjdG9yIHRoYXQgc2ltdWxhdGVzIG5ldHdvcmsgZGVsYXkuXG4jXG5jbGFzcyBUZXN0Q29ubmVjdG9yXG5cbiAgI1xuICAjIEBwYXJhbSBpZCB7U3RyaW5nfSBTb21lIHVuaXF1ZSBpZFxuICAjXG4gIGNvbnN0cnVjdG9yOiAoQGlkKS0+XG4gICAgb3B0aW9ucyA9XG4gICAgICBzeW5jTWV0aG9kOiBcInN5bmNBbGxcIlxuICAgICAgcm9sZTogXCJzbGF2ZVwiXG4gICAgICB1c2VyX2lkOiBAaWQgIyBUT0RPOiBmb3Igbm93LCB3ZSBzYXZlIHRoZSB1c2VyX2lkIHVuZGVyIEBpZCBBTkQgQHVzZXJfaWQsIGJ1dCBjaGFuZ2UgdGhpcyBsYXRlci4uXG4gICAgICBwZXJmb3JtX3NlbmRfYWdhaW46IGZhbHNlXG5cbiAgICBAb25fYm91bmRfdG9feSA9ICgpPT5cbiAgICAgIEBpbml0IG9wdGlvbnNcblxuICAgICAgIyBJZiB5b3UgdGhpbmsgb2Ygb3BlcmF0aW9ucywgdGhpcyB3aWxsIG1pcnJvciB0aGVcbiAgICAgICMgZXhlY2l0b24gb3JkZXIgb2Ygb3BlcmF0aW9ucyAod2hlbiBhIG1lc3NhZ2UgaXMgc2VuZCwgb3IgcmVjZWl2ZWQgaXQgaXMgcHV0IGludG8gdGhpcylcbiAgICAgIEBleGVjdXRpb25fb3JkZXIgPSBbXVxuICAgICAgIyBUaGUgbWVzc2FnZXMgYXJlIGJ1ZmZlcmVkIHVuZGVyIHRoZSBuYW1lIG9mIHRlaCBzZW5kaW5nIHVzZXIuXG4gICAgICBAcmVjZWl2ZV9idWZmZXIgPSB7fVxuXG4gICAgICBAcmVjZWl2ZV9oYW5kbGVycy5wdXNoICh1c2VyLCBtZXNzYWdlKT0+XG4gICAgICAgIEBleGVjdXRpb25fb3JkZXIucHVzaCBtZXNzYWdlXG5cbiAgIyBqb2luIGFub3RoZXIgdXNlciBjb25uZWN0b3JcbiAgam9pbjogKGNvbm4pLT5cbiAgICBpZiBub3QgQGNvbm5lY3Rpb25zW2Nvbm4uaWRdP1xuICAgICAgQGNvbm5lY3Rpb25zW2Nvbm4uaWRdID0ge2Nvbm4gOiBjb25ufVxuICAgICAgQHVzZXJKb2luZWQgY29ubi5pZCwgXCJzbGF2ZVwiXG4gICAgICBjb25uLmpvaW4gQFxuICAgICAgQGZsdXNoQWxsKClcbiAgICAgIGNvbm4uZmx1c2hBbGwoKVxuICAgICAgQGZsdXNoQWxsKClcbiAgICAgIGNvbm4uZmx1c2hBbGwoKVxuICAgICAgZm9yIGNpZCxjIG9mIGNvbm4uY29ubmVjdGlvbnNcbiAgICAgICAgaWYgbm90IEBjb25uZWN0aW9uc1tjaWRdP1xuICAgICAgICAgIEBqb2luIGMuY29ublxuXG5cblxuICAjXG4gICMgR2V0IHRoZSBvcHMgaW4gdGhlIGV4ZWN1dGlvbiBvcmRlci5cbiAgI1xuICBnZXRPcHNJbkV4ZWN1dGlvbk9yZGVyOiAoKS0+XG4gICAgQGV4ZWN1dGlvbl9vcmRlclxuXG4gICNcbiAgIyBTZW5kIGEgbWVzc2FnZSB0byBhbm90aGVyIHBlZXJcbiAgIyBAcGFyYW0ge09wZXJhdGlvbn0gbyBUaGUgb3BlcmF0aW9uIHRoYXQgd2FzIGV4ZWN1dGVkLlxuICAjXG4gIHNlbmQ6ICh1aWQsIG1lc3NhZ2UpLT5cbiAgICBpZiBtZXNzYWdlLnN5bmNfc3RlcD8gYW5kIGZhbHNlICMgVE9ETzogZmFsc2VcbiAgICAgIEByZWNlaXZlTWVzc2FnZSB1aWQsIG1lc3NhZ2VcbiAgICBlbHNlXG4gICAgICByYiA9IEBjb25uZWN0aW9uc1t1aWRdLmNvbm4ucmVjZWl2ZV9idWZmZXJcbiAgICAgIHJiW0BpZF0gPz0gW11cbiAgICAgIHJiW0BpZF0ucHVzaCBtZXNzYWdlXG5cbiAgYnJvYWRjYXN0OiAobWVzc2FnZSktPlxuICAgIGZvciBuYW1lLCBjIG9mIEBjb25uZWN0aW9uc1xuICAgICAgQHNlbmQgbmFtZSwgbWVzc2FnZVxuXG4gICNcbiAgIyBGbHVzaCBvbmUgb3BlcmF0aW9uIGZyb20gdGhlIGxpbmUgb2YgYSBzcGVjaWZpYyB1c2VyLlxuICAjXG4gIGZsdXNoT25lOiAodWlkKS0+XG4gICAgaWYgQHJlY2VpdmVfYnVmZmVyW3VpZF0/Lmxlbmd0aCA+IDBcbiAgICAgIG1lc3NhZ2UgPSBAcmVjZWl2ZV9idWZmZXJbdWlkXS5zaGlmdCgpXG4gICAgICBAcmVjZWl2ZU1lc3NhZ2UodWlkLCBtZXNzYWdlKVxuXG5cbiAgI1xuICAjIEZsdXNoIG9uZSBvcGVyYXRpb24gb24gYSByYW5kb20gbGluZS5cbiAgI1xuICBmbHVzaE9uZVJhbmRvbTogKCktPlxuICAgIGNvbm5saXN0ID0gZm9yIGNpZCxjIG9mIEByZWNlaXZlX2J1ZmZlclxuICAgICAgY2lkXG4gICAgaSA9IE1hdGguY2VpbChNYXRoLnJhbmRvbSgpKmNvbm5saXN0Lmxlbmd0aC0wLjUpXG4gICAgQGZsdXNoT25lIGNvbm5saXN0W2ldXG5cbiAgI1xuICAjIEZsdXNoIGFsbCBvcGVyYXRpb25zIG9uIGV2ZXJ5IGxpbmUuXG4gICNcbiAgZmx1c2hBbGw6ICgpLT5cbiAgICBmb3IgbixtZXNzYWdlcyBvZiBAcmVjZWl2ZV9idWZmZXJcbiAgICAgIGZvciBtZXNzYWdlIGluIG1lc3NhZ2VzXG4gICAgICAgIEByZWNlaXZlTWVzc2FnZShuLCBtZXNzYWdlKVxuXG4gICAgQHJlY2VpdmVfYnVmZmVyID0ge31cblxuXG5pZiB3aW5kb3c/XG4gIGlmIG5vdCBZP1xuICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBtdXN0IGltcG9ydCBZIGZpcnN0IVwiXG4gIGVsc2VcbiAgICB3aW5kb3cuWS5UZXN0Q29ubmVjdG9yID0gVGVzdENvbm5lY3RvclxuXG5pZiBtb2R1bGU/XG4gIG1vZHVsZS5leHBvcnRzID0gVGVzdENvbm5lY3RvclxuIiwiXG5cbiNcbiMgSGFuZGxlcyBhIFN0cmluZy1saWtlIGRhdGEgc3RydWN0dXJlcyB3aXRoIHN1cHBvcnQgZm9yIGluc2VydC9kZWxldGUgYXQgYSB3b3JkLXBvc2l0aW9uLlxuI1xuY2xhc3MgWVRleHRcblxuICAjXG4gICMgQHByaXZhdGVcbiAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICNcbiAgY29uc3RydWN0b3I6ICh0ZXh0KS0+XG4gICAgQHRleHRmaWVsZHMgPSBbXVxuICAgIGlmIG5vdCB0ZXh0P1xuICAgICAgQF90ZXh0ID0gXCJcIlxuICAgIGVsc2UgaWYgdGV4dC5jb25zdHJ1Y3RvciBpcyBTdHJpbmdcbiAgICAgIEBfdGV4dCA9IHRleHRcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZLlRleHQgZXhwZWN0cyBhIFN0cmluZyBhcyBhIGNvbnN0cnVjdG9yXCJcblxuICBfbmFtZTogXCJUZXh0XCJcblxuICBfZ2V0TW9kZWw6ICh0eXBlcywgb3BzKS0+XG4gICAgaWYgbm90IEBfbW9kZWw/XG4gICAgICBAX21vZGVsID0gbmV3IG9wcy5MaXN0TWFuYWdlcihAKS5leGVjdXRlKClcbiAgICAgIEBpbnNlcnQgMCwgQF90ZXh0XG4gICAgZGVsZXRlIEBfdGV4dFxuICAgIEBfbW9kZWxcblxuICBfc2V0TW9kZWw6IChAX21vZGVsKS0+XG4gICAgZGVsZXRlIEBfdGV4dFxuXG4gICNcbiAgIyBHZXQgdGhlIFN0cmluZy1yZXByZXNlbnRhdGlvbiBvZiB0aGlzIHdvcmQuXG4gICMgQHJldHVybiB7U3RyaW5nfSBUaGUgU3RyaW5nLXJlcHJlc2VudGF0aW9uIG9mIHRoaXMgb2JqZWN0LlxuICAjXG4gIHZhbDogKCktPlxuICAgIEBfbW9kZWwuZm9sZCBcIlwiLCAobGVmdCwgbyktPlxuICAgICAgbGVmdCArIG8udmFsKClcblxuICBvYnNlcnZlOiAoKS0+XG4gICAgQF9tb2RlbC5vYnNlcnZlLmFwcGx5IEBfbW9kZWwsIGFyZ3VtZW50c1xuXG4gIHVub2JzZXJ2ZTogKCktPlxuICAgIEBfbW9kZWwudW5vYnNlcnZlLmFwcGx5IEBfbW9kZWwsIGFyZ3VtZW50c1xuXG4gICNcbiAgIyBTYW1lIGFzIFN0cmluZy52YWxcbiAgIyBAc2VlIFN0cmluZy52YWxcbiAgI1xuICB0b1N0cmluZzogKCktPlxuICAgIEB2YWwoKVxuXG4gICNcbiAgIyBJbnNlcnRzIGEgc3RyaW5nIGludG8gdGhlIHdvcmQuXG4gICNcbiAgIyBAcmV0dXJuIHtMaXN0TWFuYWdlciBUeXBlfSBUaGlzIFN0cmluZyBvYmplY3QuXG4gICNcbiAgaW5zZXJ0OiAocG9zaXRpb24sIGNvbnRlbnQpLT5cbiAgICBpZiBjb250ZW50LmNvbnN0cnVjdG9yIGlzbnQgU3RyaW5nXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZLlN0cmluZy5pbnNlcnQgZXhwZWN0cyBhIFN0cmluZyBhcyB0aGUgc2Vjb25kIHBhcmFtZXRlciFcIlxuICAgIGlmIHR5cGVvZiBwb3NpdGlvbiBpc250IFwibnVtYmVyXCJcbiAgICAgIHRocm93IG5ldyBFcnJvciBcIlkuU3RyaW5nLmluc2VydCBleHBlY3RzIGEgTnVtYmVyIGFzIHRoZSBmaXJzdCBwYXJhbWV0ZXIhXCJcbiAgICBpZiBjb250ZW50Lmxlbmd0aCA+IDBcbiAgICAgIGl0aCA9IEBfbW9kZWwuZ2V0T3BlcmF0aW9uQnlQb3NpdGlvbiBwb3NpdGlvblxuICAgICAgIyB0aGUgKGktMSl0aCBjaGFyYWN0ZXIuIGUuZy4gXCJhYmNcIiB0aGUgMXRoIGNoYXJhY3RlciBpcyBcImFcIlxuICAgICAgIyB0aGUgMHRoIGNoYXJhY3RlciBpcyB0aGUgbGVmdCBEZWxpbWl0ZXJcbiAgICAgIEBfbW9kZWwuaW5zZXJ0QWZ0ZXIgaXRoLCBjb250ZW50XG5cbiAgZGVsZXRlOiAocG9zaXRpb24sIGxlbmd0aCktPlxuICAgIEBfbW9kZWwuZGVsZXRlIHBvc2l0aW9uLCBsZW5ndGhcblxuICAjXG4gICMgQmluZCB0aGlzIFN0cmluZyB0byBhIHRleHRmaWVsZCBvciBpbnB1dCBmaWVsZC5cbiAgI1xuICAjIEBleGFtcGxlXG4gICMgICB2YXIgdGV4dGJveCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwidGV4dGZpZWxkXCIpO1xuICAjICAgeS5iaW5kKHRleHRib3gpO1xuICAjXG4gIGJpbmQ6ICh0ZXh0ZmllbGQsIGRvbV9yb290KS0+XG4gICAgZG9tX3Jvb3QgPz0gd2luZG93XG4gICAgaWYgKG5vdCBkb21fcm9vdC5nZXRTZWxlY3Rpb24/KVxuICAgICAgZG9tX3Jvb3QgPSB3aW5kb3dcblxuICAgICMgZG9uJ3QgZHVwbGljYXRlIVxuICAgIGZvciB0IGluIEB0ZXh0ZmllbGRzXG4gICAgICBpZiB0IGlzIHRleHRmaWVsZFxuICAgICAgICByZXR1cm5cbiAgICBjcmVhdG9yX3Rva2VuID0gZmFsc2U7XG5cbiAgICB3b3JkID0gQFxuICAgIHRleHRmaWVsZC52YWx1ZSA9IEB2YWwoKVxuICAgIEB0ZXh0ZmllbGRzLnB1c2ggdGV4dGZpZWxkXG5cbiAgICBpZiB0ZXh0ZmllbGQuc2VsZWN0aW9uU3RhcnQ/IGFuZCB0ZXh0ZmllbGQuc2V0U2VsZWN0aW9uUmFuZ2U/XG4gICAgICBjcmVhdGVSYW5nZSA9IChmaXgpLT5cbiAgICAgICAgbGVmdCA9IHRleHRmaWVsZC5zZWxlY3Rpb25TdGFydFxuICAgICAgICByaWdodCA9IHRleHRmaWVsZC5zZWxlY3Rpb25FbmRcbiAgICAgICAgaWYgZml4P1xuICAgICAgICAgIGxlZnQgPSBmaXggbGVmdFxuICAgICAgICAgIHJpZ2h0ID0gZml4IHJpZ2h0XG4gICAgICAgIHtcbiAgICAgICAgICBsZWZ0OiBsZWZ0XG4gICAgICAgICAgcmlnaHQ6IHJpZ2h0XG4gICAgICAgIH1cblxuICAgICAgd3JpdGVSYW5nZSA9IChyYW5nZSktPlxuICAgICAgICB3cml0ZUNvbnRlbnQgd29yZC52YWwoKVxuICAgICAgICB0ZXh0ZmllbGQuc2V0U2VsZWN0aW9uUmFuZ2UgcmFuZ2UubGVmdCwgcmFuZ2UucmlnaHRcblxuICAgICAgd3JpdGVDb250ZW50ID0gKGNvbnRlbnQpLT5cbiAgICAgICAgdGV4dGZpZWxkLnZhbHVlID0gY29udGVudFxuICAgIGVsc2VcbiAgICAgIGNyZWF0ZVJhbmdlID0gKGZpeCktPlxuICAgICAgICByYW5nZSA9IHt9XG4gICAgICAgIHMgPSBkb21fcm9vdC5nZXRTZWxlY3Rpb24oKVxuICAgICAgICBjbGVuZ3RoID0gdGV4dGZpZWxkLnRleHRDb250ZW50Lmxlbmd0aFxuICAgICAgICByYW5nZS5sZWZ0ID0gTWF0aC5taW4gcy5hbmNob3JPZmZzZXQsIGNsZW5ndGhcbiAgICAgICAgcmFuZ2UucmlnaHQgPSBNYXRoLm1pbiBzLmZvY3VzT2Zmc2V0LCBjbGVuZ3RoXG4gICAgICAgIGlmIGZpeD9cbiAgICAgICAgICByYW5nZS5sZWZ0ID0gZml4IHJhbmdlLmxlZnRcbiAgICAgICAgICByYW5nZS5yaWdodCA9IGZpeCByYW5nZS5yaWdodFxuXG4gICAgICAgIGVkaXRlZF9lbGVtZW50ID0gcy5mb2N1c05vZGVcbiAgICAgICAgaWYgZWRpdGVkX2VsZW1lbnQgaXMgdGV4dGZpZWxkIG9yIGVkaXRlZF9lbGVtZW50IGlzIHRleHRmaWVsZC5jaGlsZE5vZGVzWzBdXG4gICAgICAgICAgcmFuZ2UuaXNSZWFsID0gdHJ1ZVxuICAgICAgICBlbHNlXG4gICAgICAgICAgcmFuZ2UuaXNSZWFsID0gZmFsc2VcbiAgICAgICAgcmFuZ2VcblxuICAgICAgd3JpdGVSYW5nZSA9IChyYW5nZSktPlxuICAgICAgICB3cml0ZUNvbnRlbnQgd29yZC52YWwoKVxuICAgICAgICB0ZXh0bm9kZSA9IHRleHRmaWVsZC5jaGlsZE5vZGVzWzBdXG4gICAgICAgIGlmIHJhbmdlLmlzUmVhbCBhbmQgdGV4dG5vZGU/XG4gICAgICAgICAgaWYgcmFuZ2UubGVmdCA8IDBcbiAgICAgICAgICAgIHJhbmdlLmxlZnQgPSAwXG4gICAgICAgICAgcmFuZ2UucmlnaHQgPSBNYXRoLm1heCByYW5nZS5sZWZ0LCByYW5nZS5yaWdodFxuICAgICAgICAgIGlmIHJhbmdlLnJpZ2h0ID4gdGV4dG5vZGUubGVuZ3RoXG4gICAgICAgICAgICByYW5nZS5yaWdodCA9IHRleHRub2RlLmxlbmd0aFxuICAgICAgICAgIHJhbmdlLmxlZnQgPSBNYXRoLm1pbiByYW5nZS5sZWZ0LCByYW5nZS5yaWdodFxuICAgICAgICAgIHIgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpXG4gICAgICAgICAgci5zZXRTdGFydCh0ZXh0bm9kZSwgcmFuZ2UubGVmdClcbiAgICAgICAgICByLnNldEVuZCh0ZXh0bm9kZSwgcmFuZ2UucmlnaHQpXG4gICAgICAgICAgcyA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKVxuICAgICAgICAgIHMucmVtb3ZlQWxsUmFuZ2VzKClcbiAgICAgICAgICBzLmFkZFJhbmdlKHIpXG4gICAgICB3cml0ZUNvbnRlbnQgPSAoY29udGVudCktPlxuICAgICAgICBjb250ZW50X2FycmF5ID0gY29udGVudC5yZXBsYWNlKG5ldyBSZWdFeHAoXCJcXG5cIiwnZycpLFwiIFwiKS5zcGxpdChcIiBcIilcbiAgICAgICAgdGV4dGZpZWxkLmlubmVyVGV4dCA9IFwiXCJcbiAgICAgICAgZm9yIGMsIGkgaW4gY29udGVudF9hcnJheVxuICAgICAgICAgIHRleHRmaWVsZC5pbm5lclRleHQgKz0gY1xuICAgICAgICAgIGlmIGkgaXNudCBjb250ZW50X2FycmF5Lmxlbmd0aC0xXG4gICAgICAgICAgICB0ZXh0ZmllbGQuaW5uZXJIVE1MICs9ICcmbmJzcDsnXG5cbiAgICB3cml0ZUNvbnRlbnQgdGhpcy52YWwoKVxuXG4gICAgQG9ic2VydmUgKGV2ZW50cyktPlxuICAgICAgZm9yIGV2ZW50IGluIGV2ZW50c1xuICAgICAgICBpZiBub3QgY3JlYXRvcl90b2tlblxuICAgICAgICAgIGlmIGV2ZW50LnR5cGUgaXMgXCJpbnNlcnRcIlxuICAgICAgICAgICAgb19wb3MgPSBldmVudC5wb3NpdGlvblxuICAgICAgICAgICAgZml4ID0gKGN1cnNvciktPlxuICAgICAgICAgICAgICBpZiBjdXJzb3IgPD0gb19wb3NcbiAgICAgICAgICAgICAgICBjdXJzb3JcbiAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIGN1cnNvciArPSAxXG4gICAgICAgICAgICAgICAgY3Vyc29yXG4gICAgICAgICAgICByID0gY3JlYXRlUmFuZ2UgZml4XG4gICAgICAgICAgICB3cml0ZVJhbmdlIHJcblxuICAgICAgICAgIGVsc2UgaWYgZXZlbnQudHlwZSBpcyBcImRlbGV0ZVwiXG4gICAgICAgICAgICBvX3BvcyA9IGV2ZW50LnBvc2l0aW9uXG4gICAgICAgICAgICBmaXggPSAoY3Vyc29yKS0+XG4gICAgICAgICAgICAgIGlmIGN1cnNvciA8IG9fcG9zXG4gICAgICAgICAgICAgICAgY3Vyc29yXG4gICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICBjdXJzb3IgLT0gMVxuICAgICAgICAgICAgICAgIGN1cnNvclxuICAgICAgICAgICAgciA9IGNyZWF0ZVJhbmdlIGZpeFxuICAgICAgICAgICAgd3JpdGVSYW5nZSByXG5cbiAgICAjIGNvbnN1bWUgYWxsIHRleHQtaW5zZXJ0IGNoYW5nZXMuXG4gICAgdGV4dGZpZWxkLm9ua2V5cHJlc3MgPSAoZXZlbnQpLT5cbiAgICAgIGlmIHdvcmQuaXNfZGVsZXRlZFxuICAgICAgICAjIGlmIHdvcmQgaXMgZGVsZXRlZCwgZG8gbm90IGRvIGFueXRoaW5nIGV2ZXIgYWdhaW5cbiAgICAgICAgdGV4dGZpZWxkLm9ua2V5cHJlc3MgPSBudWxsXG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICBjcmVhdG9yX3Rva2VuID0gdHJ1ZVxuICAgICAgY2hhciA9IG51bGxcbiAgICAgIGlmIGV2ZW50LmtleUNvZGUgaXMgMTNcbiAgICAgICAgY2hhciA9ICdcXG4nXG4gICAgICBlbHNlIGlmIGV2ZW50LmtleT9cbiAgICAgICAgaWYgZXZlbnQuY2hhckNvZGUgaXMgMzJcbiAgICAgICAgICBjaGFyID0gXCIgXCJcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGNoYXIgPSBldmVudC5rZXlcbiAgICAgIGVsc2VcbiAgICAgICAgY2hhciA9IHdpbmRvdy5TdHJpbmcuZnJvbUNoYXJDb2RlIGV2ZW50LmtleUNvZGVcbiAgICAgIGlmIGNoYXIubGVuZ3RoID4gMVxuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgZWxzZSBpZiBjaGFyLmxlbmd0aCA+IDBcbiAgICAgICAgciA9IGNyZWF0ZVJhbmdlKClcbiAgICAgICAgcG9zID0gTWF0aC5taW4gci5sZWZ0LCByLnJpZ2h0XG4gICAgICAgIGRpZmYgPSBNYXRoLmFicyhyLnJpZ2h0IC0gci5sZWZ0KVxuICAgICAgICB3b3JkLmRlbGV0ZSBwb3MsIGRpZmZcbiAgICAgICAgd29yZC5pbnNlcnQgcG9zLCBjaGFyXG4gICAgICAgIHIubGVmdCA9IHBvcyArIGNoYXIubGVuZ3RoXG4gICAgICAgIHIucmlnaHQgPSByLmxlZnRcbiAgICAgICAgd3JpdGVSYW5nZSByXG5cbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KClcbiAgICAgIGNyZWF0b3JfdG9rZW4gPSBmYWxzZVxuICAgICAgZmFsc2VcblxuICAgIHRleHRmaWVsZC5vbnBhc3RlID0gKGV2ZW50KS0+XG4gICAgICBpZiB3b3JkLmlzX2RlbGV0ZWRcbiAgICAgICAgIyBpZiB3b3JkIGlzIGRlbGV0ZWQsIGRvIG5vdCBkbyBhbnl0aGluZyBldmVyIGFnYWluXG4gICAgICAgIHRleHRmaWVsZC5vbnBhc3RlID0gbnVsbFxuICAgICAgICByZXR1cm4gdHJ1ZVxuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKVxuICAgIHRleHRmaWVsZC5vbmN1dCA9IChldmVudCktPlxuICAgICAgaWYgd29yZC5pc19kZWxldGVkXG4gICAgICAgICMgaWYgd29yZCBpcyBkZWxldGVkLCBkbyBub3QgZG8gYW55dGhpbmcgZXZlciBhZ2FpblxuICAgICAgICB0ZXh0ZmllbGQub25jdXQgPSBudWxsXG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpXG5cbiAgICAjXG4gICAgIyBjb25zdW1lIGRlbGV0ZXMuIE5vdGUgdGhhdFxuICAgICMgICBjaHJvbWU6IHdvbid0IGNvbnN1bWUgZGVsZXRpb25zIG9uIGtleXByZXNzIGV2ZW50LlxuICAgICMgICBrZXlDb2RlIGlzIGRlcHJlY2F0ZWQuIEJVVDogSSBkb24ndCBzZWUgYW5vdGhlciB3YXkuXG4gICAgIyAgICAgc2luY2UgZXZlbnQua2V5IGlzIG5vdCBpbXBsZW1lbnRlZCBpbiB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIGNocm9tZS5cbiAgICAjICAgICBFdmVyeSBicm93c2VyIHN1cHBvcnRzIGtleUNvZGUuIExldCdzIHN0aWNrIHdpdGggaXQgZm9yIG5vdy4uXG4gICAgI1xuICAgIHRleHRmaWVsZC5vbmtleWRvd24gPSAoZXZlbnQpLT5cbiAgICAgIGNyZWF0b3JfdG9rZW4gPSB0cnVlXG4gICAgICBpZiB3b3JkLmlzX2RlbGV0ZWRcbiAgICAgICAgIyBpZiB3b3JkIGlzIGRlbGV0ZWQsIGRvIG5vdCBkbyBhbnl0aGluZyBldmVyIGFnYWluXG4gICAgICAgIHRleHRmaWVsZC5vbmtleWRvd24gPSBudWxsXG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICByID0gY3JlYXRlUmFuZ2UoKVxuICAgICAgcG9zID0gTWF0aC5taW4oci5sZWZ0LCByLnJpZ2h0LCB3b3JkLnZhbCgpLmxlbmd0aClcbiAgICAgIGRpZmYgPSBNYXRoLmFicyhyLmxlZnQgLSByLnJpZ2h0KVxuICAgICAgaWYgZXZlbnQua2V5Q29kZT8gYW5kIGV2ZW50LmtleUNvZGUgaXMgOCAjIEJhY2tzcGFjZVxuICAgICAgICBpZiBkaWZmID4gMFxuICAgICAgICAgIHdvcmQuZGVsZXRlIHBvcywgZGlmZlxuICAgICAgICAgIHIubGVmdCA9IHBvc1xuICAgICAgICAgIHIucmlnaHQgPSBwb3NcbiAgICAgICAgICB3cml0ZVJhbmdlIHJcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGlmIGV2ZW50LmN0cmxLZXk/IGFuZCBldmVudC5jdHJsS2V5XG4gICAgICAgICAgICB2YWwgPSB3b3JkLnZhbCgpXG4gICAgICAgICAgICBuZXdfcG9zID0gcG9zXG4gICAgICAgICAgICBkZWxfbGVuZ3RoID0gMFxuICAgICAgICAgICAgaWYgcG9zID4gMFxuICAgICAgICAgICAgICBuZXdfcG9zLS1cbiAgICAgICAgICAgICAgZGVsX2xlbmd0aCsrXG4gICAgICAgICAgICB3aGlsZSBuZXdfcG9zID4gMCBhbmQgdmFsW25ld19wb3NdIGlzbnQgXCIgXCIgYW5kIHZhbFtuZXdfcG9zXSBpc250ICdcXG4nXG4gICAgICAgICAgICAgIG5ld19wb3MtLVxuICAgICAgICAgICAgICBkZWxfbGVuZ3RoKytcbiAgICAgICAgICAgIHdvcmQuZGVsZXRlIG5ld19wb3MsIChwb3MtbmV3X3BvcylcbiAgICAgICAgICAgIHIubGVmdCA9IG5ld19wb3NcbiAgICAgICAgICAgIHIucmlnaHQgPSBuZXdfcG9zXG4gICAgICAgICAgICB3cml0ZVJhbmdlIHJcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBpZiBwb3MgPiAwXG4gICAgICAgICAgICAgIHdvcmQuZGVsZXRlIChwb3MtMSksIDFcbiAgICAgICAgICAgICAgci5sZWZ0ID0gcG9zLTFcbiAgICAgICAgICAgICAgci5yaWdodCA9IHBvcy0xXG4gICAgICAgICAgICAgIHdyaXRlUmFuZ2UgclxuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpXG4gICAgICAgIGNyZWF0b3JfdG9rZW4gPSBmYWxzZVxuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIGVsc2UgaWYgZXZlbnQua2V5Q29kZT8gYW5kIGV2ZW50LmtleUNvZGUgaXMgNDYgIyBEZWxldGVcbiAgICAgICAgaWYgZGlmZiA+IDBcbiAgICAgICAgICB3b3JkLmRlbGV0ZSBwb3MsIGRpZmZcbiAgICAgICAgICByLmxlZnQgPSBwb3NcbiAgICAgICAgICByLnJpZ2h0ID0gcG9zXG4gICAgICAgICAgd3JpdGVSYW5nZSByXG4gICAgICAgIGVsc2VcbiAgICAgICAgICB3b3JkLmRlbGV0ZSBwb3MsIDFcbiAgICAgICAgICByLmxlZnQgPSBwb3NcbiAgICAgICAgICByLnJpZ2h0ID0gcG9zXG4gICAgICAgICAgd3JpdGVSYW5nZSByXG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KClcbiAgICAgICAgY3JlYXRvcl90b2tlbiA9IGZhbHNlXG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgZWxzZVxuICAgICAgICBjcmVhdG9yX3Rva2VuID0gZmFsc2VcbiAgICAgICAgdHJ1ZVxuXG5cbmlmIHdpbmRvdz9cbiAgaWYgd2luZG93Llk/XG4gICAgd2luZG93LlkuVGV4dCA9IFlUZXh0XG4gIGVsc2VcbiAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBmaXJzdCBpbXBvcnQgWSFcIlxuXG5pZiBtb2R1bGU/XG4gIG1vZHVsZS5leHBvcnRzID0gWVRleHRcblxuXG5cblxuXG5cblxuIiwiXG5Db25uZWN0b3JDbGFzcyA9IHJlcXVpcmUgXCIuL0Nvbm5lY3RvckNsYXNzXCJcbiNcbiMgQHBhcmFtIHtFbmdpbmV9IGVuZ2luZSBUaGUgdHJhbnNmb3JtYXRpb24gZW5naW5lXG4jIEBwYXJhbSB7SGlzdG9yeUJ1ZmZlcn0gSEJcbiMgQHBhcmFtIHtBcnJheTxGdW5jdGlvbj59IGV4ZWN1dGlvbl9saXN0ZW5lciBZb3UgbXVzdCBlbnN1cmUgdGhhdCB3aGVuZXZlciBhbiBvcGVyYXRpb24gaXMgZXhlY3V0ZWQsIGV2ZXJ5IGZ1bmN0aW9uIGluIHRoaXMgQXJyYXkgaXMgY2FsbGVkLlxuI1xuYWRhcHRDb25uZWN0b3IgPSAoY29ubmVjdG9yLCBlbmdpbmUsIEhCLCBleGVjdXRpb25fbGlzdGVuZXIpLT5cblxuICBmb3IgbmFtZSwgZiBvZiBDb25uZWN0b3JDbGFzc1xuICAgIGNvbm5lY3RvcltuYW1lXSA9IGZcblxuICBjb25uZWN0b3Iuc2V0SXNCb3VuZFRvWSgpXG5cbiAgc2VuZF8gPSAobyktPlxuICAgIGlmIChvLnVpZC5jcmVhdG9yIGlzIEhCLmdldFVzZXJJZCgpKSBhbmRcbiAgICAgICAgKHR5cGVvZiBvLnVpZC5vcF9udW1iZXIgaXNudCBcInN0cmluZ1wiKSBhbmQgIyBUT0RPOiBpIGRvbid0IHRoaW5rIHRoYXQgd2UgbmVlZCB0aGlzIGFueW1vcmUuLlxuICAgICAgICAoSEIuZ2V0VXNlcklkKCkgaXNudCBcIl90ZW1wXCIpXG4gICAgICBjb25uZWN0b3IuYnJvYWRjYXN0IG9cblxuICBpZiBjb25uZWN0b3IuaW52b2tlU3luYz9cbiAgICBIQi5zZXRJbnZva2VTeW5jSGFuZGxlciBjb25uZWN0b3IuaW52b2tlU3luY1xuXG4gIGV4ZWN1dGlvbl9saXN0ZW5lci5wdXNoIHNlbmRfXG4gICMgRm9yIHRoZSBYTVBQQ29ubmVjdG9yOiBsZXRzIHNlbmQgaXQgYXMgYW4gYXJyYXlcbiAgIyB0aGVyZWZvcmUsIHdlIGhhdmUgdG8gcmVzdHJ1Y3R1cmUgaXQgbGF0ZXJcbiAgZW5jb2RlX3N0YXRlX3ZlY3RvciA9ICh2KS0+XG4gICAgZm9yIG5hbWUsdmFsdWUgb2YgdlxuICAgICAgdXNlcjogbmFtZVxuICAgICAgc3RhdGU6IHZhbHVlXG4gIHBhcnNlX3N0YXRlX3ZlY3RvciA9ICh2KS0+XG4gICAgc3RhdGVfdmVjdG9yID0ge31cbiAgICBmb3IgcyBpbiB2XG4gICAgICBzdGF0ZV92ZWN0b3Jbcy51c2VyXSA9IHMuc3RhdGVcbiAgICBzdGF0ZV92ZWN0b3JcblxuICBnZXRTdGF0ZVZlY3RvciA9ICgpLT5cbiAgICBlbmNvZGVfc3RhdGVfdmVjdG9yIEhCLmdldE9wZXJhdGlvbkNvdW50ZXIoKVxuXG4gIGdldEhCID0gKHYpLT5cbiAgICBzdGF0ZV92ZWN0b3IgPSBwYXJzZV9zdGF0ZV92ZWN0b3IgdlxuICAgIGhiID0gSEIuX2VuY29kZSBzdGF0ZV92ZWN0b3JcbiAgICBqc29uID1cbiAgICAgIGhiOiBoYlxuICAgICAgc3RhdGVfdmVjdG9yOiBlbmNvZGVfc3RhdGVfdmVjdG9yIEhCLmdldE9wZXJhdGlvbkNvdW50ZXIoKVxuICAgIGpzb25cblxuICBhcHBseUhCID0gKGhiLCBmcm9tSEIpLT5cbiAgICBlbmdpbmUuYXBwbHlPcCBoYiwgZnJvbUhCXG5cbiAgY29ubmVjdG9yLmdldFN0YXRlVmVjdG9yID0gZ2V0U3RhdGVWZWN0b3JcbiAgY29ubmVjdG9yLmdldEhCID0gZ2V0SEJcbiAgY29ubmVjdG9yLmFwcGx5SEIgPSBhcHBseUhCXG5cbiAgY29ubmVjdG9yLnJlY2VpdmVfaGFuZGxlcnMgPz0gW11cbiAgY29ubmVjdG9yLnJlY2VpdmVfaGFuZGxlcnMucHVzaCAoc2VuZGVyLCBvcCktPlxuICAgIGlmIG9wLnVpZC5jcmVhdG9yIGlzbnQgSEIuZ2V0VXNlcklkKClcbiAgICAgIGVuZ2luZS5hcHBseU9wIG9wXG5cblxubW9kdWxlLmV4cG9ydHMgPSBhZGFwdENvbm5lY3RvclxuIiwiXG5tb2R1bGUuZXhwb3J0cyA9XG4gICNcbiAgIyBAcGFyYW1zIG5ldyBDb25uZWN0b3Iob3B0aW9ucylcbiAgIyAgIEBwYXJhbSBvcHRpb25zLnN5bmNNZXRob2Qge1N0cmluZ30gIGlzIGVpdGhlciBcInN5bmNBbGxcIiBvciBcIm1hc3Rlci1zbGF2ZVwiLlxuICAjICAgQHBhcmFtIG9wdGlvbnMucm9sZSB7U3RyaW5nfSBUaGUgcm9sZSBvZiB0aGlzIGNsaWVudFxuICAjICAgICAgICAgICAgKHNsYXZlIG9yIG1hc3RlciAob25seSB1c2VkIHdoZW4gc3luY01ldGhvZCBpcyBtYXN0ZXItc2xhdmUpKVxuICAjICAgQHBhcmFtIG9wdGlvbnMucGVyZm9ybV9zZW5kX2FnYWluIHtCb29sZWFufSBXaGV0ZWhyIHRvIHdoZXRoZXIgdG8gcmVzZW5kIHRoZSBIQiBhZnRlciBzb21lIHRpbWUgcGVyaW9kLiBUaGlzIHJlZHVjZXMgc3luYyBlcnJvcnMsIGJ1dCBoYXMgc29tZSBvdmVyaGVhZCAob3B0aW9uYWwpXG4gICNcbiAgaW5pdDogKG9wdGlvbnMpLT5cbiAgICByZXEgPSAobmFtZSwgY2hvaWNlcyk9PlxuICAgICAgaWYgb3B0aW9uc1tuYW1lXT9cbiAgICAgICAgaWYgKG5vdCBjaG9pY2VzPykgb3IgY2hvaWNlcy5zb21lKChjKS0+YyBpcyBvcHRpb25zW25hbWVdKVxuICAgICAgICAgIEBbbmFtZV0gPSBvcHRpb25zW25hbWVdXG4gICAgICAgIGVsc2VcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgY2FuIHNldCB0aGUgJ1wiK25hbWUrXCInIG9wdGlvbiB0byBvbmUgb2YgdGhlIGZvbGxvd2luZyBjaG9pY2VzOiBcIitKU09OLmVuY29kZShjaG9pY2VzKVxuICAgICAgZWxzZVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBzcGVjaWZ5IFwiK25hbWUrXCIsIHdoZW4gaW5pdGlhbGl6aW5nIHRoZSBDb25uZWN0b3IhXCJcblxuICAgIHJlcSBcInN5bmNNZXRob2RcIiwgW1wic3luY0FsbFwiLCBcIm1hc3Rlci1zbGF2ZVwiXVxuICAgIHJlcSBcInJvbGVcIiwgW1wibWFzdGVyXCIsIFwic2xhdmVcIl1cbiAgICByZXEgXCJ1c2VyX2lkXCJcbiAgICBAb25fdXNlcl9pZF9zZXQ/KEB1c2VyX2lkKVxuXG4gICAgIyB3aGV0aGVyIHRvIHJlc2VuZCB0aGUgSEIgYWZ0ZXIgc29tZSB0aW1lIHBlcmlvZC4gVGhpcyByZWR1Y2VzIHN5bmMgZXJyb3JzLlxuICAgICMgQnV0IHRoaXMgaXMgbm90IG5lY2Vzc2FyeSBpbiB0aGUgdGVzdC1jb25uZWN0b3JcbiAgICBpZiBvcHRpb25zLnBlcmZvcm1fc2VuZF9hZ2Fpbj9cbiAgICAgIEBwZXJmb3JtX3NlbmRfYWdhaW4gPSBvcHRpb25zLnBlcmZvcm1fc2VuZF9hZ2FpblxuICAgIGVsc2VcbiAgICAgIEBwZXJmb3JtX3NlbmRfYWdhaW4gPSB0cnVlXG5cbiAgICAjIEEgTWFzdGVyIHNob3VsZCBzeW5jIHdpdGggZXZlcnlvbmUhIFRPRE86IHJlYWxseT8gLSBmb3Igbm93IGl0cyBzYWZlciB0aGlzIHdheSFcbiAgICBpZiBAcm9sZSBpcyBcIm1hc3RlclwiXG4gICAgICBAc3luY01ldGhvZCA9IFwic3luY0FsbFwiXG5cbiAgICAjIGlzIHNldCB0byB0cnVlIHdoZW4gdGhpcyBpcyBzeW5jZWQgd2l0aCBhbGwgb3RoZXIgY29ubmVjdGlvbnNcbiAgICBAaXNfc3luY2VkID0gZmFsc2VcbiAgICAjIFBlZXJqcyBDb25uZWN0aW9uczoga2V5OiBjb25uLWlkLCB2YWx1ZTogb2JqZWN0XG4gICAgQGNvbm5lY3Rpb25zID0ge31cbiAgICAjIExpc3Qgb2YgZnVuY3Rpb25zIHRoYXQgc2hhbGwgcHJvY2VzcyBpbmNvbWluZyBkYXRhXG4gICAgQHJlY2VpdmVfaGFuZGxlcnMgPz0gW11cblxuICAgICMgd2hldGhlciB0aGlzIGluc3RhbmNlIGlzIGJvdW5kIHRvIGFueSB5IGluc3RhbmNlXG4gICAgQGNvbm5lY3Rpb25zID0ge31cbiAgICBAY3VycmVudF9zeW5jX3RhcmdldCA9IG51bGxcbiAgICBAc2VudF9oYl90b19hbGxfdXNlcnMgPSBmYWxzZVxuICAgIEBpc19pbml0aWFsaXplZCA9IHRydWVcblxuICBvblVzZXJFdmVudDogKGYpLT5cbiAgICBAY29ubmVjdGlvbnNfbGlzdGVuZXJzID89IFtdXG4gICAgQGNvbm5lY3Rpb25zX2xpc3RlbmVycy5wdXNoIGZcblxuICBpc1JvbGVNYXN0ZXI6IC0+XG4gICAgQHJvbGUgaXMgXCJtYXN0ZXJcIlxuXG4gIGlzUm9sZVNsYXZlOiAtPlxuICAgIEByb2xlIGlzIFwic2xhdmVcIlxuXG4gIGZpbmROZXdTeW5jVGFyZ2V0OiAoKS0+XG4gICAgQGN1cnJlbnRfc3luY190YXJnZXQgPSBudWxsXG4gICAgaWYgQHN5bmNNZXRob2QgaXMgXCJzeW5jQWxsXCJcbiAgICAgIGZvciB1c2VyLCBjIG9mIEBjb25uZWN0aW9uc1xuICAgICAgICBpZiBub3QgYy5pc19zeW5jZWRcbiAgICAgICAgICBAcGVyZm9ybVN5bmMgdXNlclxuICAgICAgICAgIGJyZWFrXG4gICAgaWYgbm90IEBjdXJyZW50X3N5bmNfdGFyZ2V0P1xuICAgICAgQHNldFN0YXRlU3luY2VkKClcbiAgICBudWxsXG5cbiAgdXNlckxlZnQ6ICh1c2VyKS0+XG4gICAgZGVsZXRlIEBjb25uZWN0aW9uc1t1c2VyXVxuICAgIEBmaW5kTmV3U3luY1RhcmdldCgpXG4gICAgaWYgQGNvbm5lY3Rpb25zX2xpc3RlbmVycz9cbiAgICAgIGZvciBmIGluIEBjb25uZWN0aW9uc19saXN0ZW5lcnNcbiAgICAgICAgZiB7XG4gICAgICAgICAgYWN0aW9uOiBcInVzZXJMZWZ0XCJcbiAgICAgICAgICB1c2VyOiB1c2VyXG4gICAgICAgIH1cblxuXG4gIHVzZXJKb2luZWQ6ICh1c2VyLCByb2xlKS0+XG4gICAgaWYgbm90IHJvbGU/XG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJJbnRlcm5hbDogWW91IG11c3Qgc3BlY2lmeSB0aGUgcm9sZSBvZiB0aGUgam9pbmVkIHVzZXIhIEUuZy4gdXNlckpvaW5lZCgndWlkOjM5MzknLCdzbGF2ZScpXCJcbiAgICAjIGEgdXNlciBqb2luZWQgdGhlIHJvb21cbiAgICBAY29ubmVjdGlvbnNbdXNlcl0gPz0ge31cbiAgICBAY29ubmVjdGlvbnNbdXNlcl0uaXNfc3luY2VkID0gZmFsc2VcblxuICAgIGlmIChub3QgQGlzX3N5bmNlZCkgb3IgQHN5bmNNZXRob2QgaXMgXCJzeW5jQWxsXCJcbiAgICAgIGlmIEBzeW5jTWV0aG9kIGlzIFwic3luY0FsbFwiXG4gICAgICAgIEBwZXJmb3JtU3luYyB1c2VyXG4gICAgICBlbHNlIGlmIHJvbGUgaXMgXCJtYXN0ZXJcIlxuICAgICAgICAjIFRPRE86IFdoYXQgaWYgdGhlcmUgYXJlIHR3byBtYXN0ZXJzPyBQcmV2ZW50IHNlbmRpbmcgZXZlcnl0aGluZyB0d28gdGltZXMhXG4gICAgICAgIEBwZXJmb3JtU3luY1dpdGhNYXN0ZXIgdXNlclxuXG4gICAgaWYgQGNvbm5lY3Rpb25zX2xpc3RlbmVycz9cbiAgICAgIGZvciBmIGluIEBjb25uZWN0aW9uc19saXN0ZW5lcnNcbiAgICAgICAgZiB7XG4gICAgICAgICAgYWN0aW9uOiBcInVzZXJKb2luZWRcIlxuICAgICAgICAgIHVzZXI6IHVzZXJcbiAgICAgICAgICByb2xlOiByb2xlXG4gICAgICAgIH1cblxuICAjXG4gICMgRXhlY3V0ZSBhIGZ1bmN0aW9uIF93aGVuXyB3ZSBhcmUgY29ubmVjdGVkLiBJZiBub3QgY29ubmVjdGVkLCB3YWl0IHVudGlsIGNvbm5lY3RlZC5cbiAgIyBAcGFyYW0gZiB7RnVuY3Rpb259IFdpbGwgYmUgZXhlY3V0ZWQgb24gdGhlIENvbm5lY3RvciBjb250ZXh0LlxuICAjXG4gIHdoZW5TeW5jZWQ6IChhcmdzKS0+XG4gICAgaWYgYXJncy5jb25zdHJ1Y3RvciBpcyBGdW5jdGlvblxuICAgICAgYXJncyA9IFthcmdzXVxuICAgIGlmIEBpc19zeW5jZWRcbiAgICAgIGFyZ3NbMF0uYXBwbHkgdGhpcywgYXJnc1sxLi5dXG4gICAgZWxzZVxuICAgICAgQGNvbXB1dGVfd2hlbl9zeW5jZWQgPz0gW11cbiAgICAgIEBjb21wdXRlX3doZW5fc3luY2VkLnB1c2ggYXJnc1xuXG4gICNcbiAgIyBFeGVjdXRlIGFuIGZ1bmN0aW9uIHdoZW4gYSBtZXNzYWdlIGlzIHJlY2VpdmVkLlxuICAjIEBwYXJhbSBmIHtGdW5jdGlvbn0gV2lsbCBiZSBleGVjdXRlZCBvbiB0aGUgUGVlckpzLUNvbm5lY3RvciBjb250ZXh0LiBmIHdpbGwgYmUgY2FsbGVkIHdpdGggKHNlbmRlcl9pZCwgYnJvYWRjYXN0IHt0cnVlfGZhbHNlfSwgbWVzc2FnZSkuXG4gICNcbiAgb25SZWNlaXZlOiAoZiktPlxuICAgIEByZWNlaXZlX2hhbmRsZXJzLnB1c2ggZlxuXG4gICMjI1xuICAjIEJyb2FkY2FzdCBhIG1lc3NhZ2UgdG8gYWxsIGNvbm5lY3RlZCBwZWVycy5cbiAgIyBAcGFyYW0gbWVzc2FnZSB7T2JqZWN0fSBUaGUgbWVzc2FnZSB0byBicm9hZGNhc3QuXG4gICNcbiAgYnJvYWRjYXN0OiAobWVzc2FnZSktPlxuICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBtdXN0IGltcGxlbWVudCBicm9hZGNhc3QhXCJcblxuICAjXG4gICMgU2VuZCBhIG1lc3NhZ2UgdG8gYSBwZWVyLCBvciBzZXQgb2YgcGVlcnNcbiAgI1xuICBzZW5kOiAocGVlcl9zLCBtZXNzYWdlKS0+XG4gICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3QgaW1wbGVtZW50IHNlbmQhXCJcbiAgIyMjXG5cbiAgI1xuICAjIHBlcmZvcm0gYSBzeW5jIHdpdGggYSBzcGVjaWZpYyB1c2VyLlxuICAjXG4gIHBlcmZvcm1TeW5jOiAodXNlciktPlxuICAgIGlmIG5vdCBAY3VycmVudF9zeW5jX3RhcmdldD9cbiAgICAgIEBjdXJyZW50X3N5bmNfdGFyZ2V0ID0gdXNlclxuICAgICAgQHNlbmQgdXNlcixcbiAgICAgICAgc3luY19zdGVwOiBcImdldEhCXCJcbiAgICAgICAgc2VuZF9hZ2FpbjogXCJ0cnVlXCJcbiAgICAgICAgZGF0YTogQGdldFN0YXRlVmVjdG9yKClcbiAgICAgIGlmIG5vdCBAc2VudF9oYl90b19hbGxfdXNlcnNcbiAgICAgICAgQHNlbnRfaGJfdG9fYWxsX3VzZXJzID0gdHJ1ZVxuXG4gICAgICAgIGhiID0gQGdldEhCKFtdKS5oYlxuICAgICAgICBfaGIgPSBbXVxuICAgICAgICBmb3IgbyBpbiBoYlxuICAgICAgICAgIF9oYi5wdXNoIG9cbiAgICAgICAgICBpZiBfaGIubGVuZ3RoID4gMTBcbiAgICAgICAgICAgIEBicm9hZGNhc3RcbiAgICAgICAgICAgICAgc3luY19zdGVwOiBcImFwcGx5SEJfXCJcbiAgICAgICAgICAgICAgZGF0YTogX2hiXG4gICAgICAgICAgICBfaGIgPSBbXVxuICAgICAgICBAYnJvYWRjYXN0XG4gICAgICAgICAgc3luY19zdGVwOiBcImFwcGx5SEJcIlxuICAgICAgICAgIGRhdGE6IF9oYlxuXG5cblxuICAjXG4gICMgV2hlbiBhIG1hc3RlciBub2RlIGpvaW5lZCB0aGUgcm9vbSwgcGVyZm9ybSB0aGlzIHN5bmMgd2l0aCBoaW0uIEl0IHdpbGwgYXNrIHRoZSBtYXN0ZXIgZm9yIHRoZSBIQixcbiAgIyBhbmQgd2lsbCBicm9hZGNhc3QgaGlzIG93biBIQlxuICAjXG4gIHBlcmZvcm1TeW5jV2l0aE1hc3RlcjogKHVzZXIpLT5cbiAgICBAY3VycmVudF9zeW5jX3RhcmdldCA9IHVzZXJcbiAgICBAc2VuZCB1c2VyLFxuICAgICAgc3luY19zdGVwOiBcImdldEhCXCJcbiAgICAgIHNlbmRfYWdhaW46IFwidHJ1ZVwiXG4gICAgICBkYXRhOiBAZ2V0U3RhdGVWZWN0b3IoKVxuICAgIGhiID0gQGdldEhCKFtdKS5oYlxuICAgIF9oYiA9IFtdXG4gICAgZm9yIG8gaW4gaGJcbiAgICAgIF9oYi5wdXNoIG9cbiAgICAgIGlmIF9oYi5sZW5ndGggPiAxMFxuICAgICAgICBAYnJvYWRjYXN0XG4gICAgICAgICAgc3luY19zdGVwOiBcImFwcGx5SEJfXCJcbiAgICAgICAgICBkYXRhOiBfaGJcbiAgICAgICAgX2hiID0gW11cbiAgICBAYnJvYWRjYXN0XG4gICAgICBzeW5jX3N0ZXA6IFwiYXBwbHlIQlwiXG4gICAgICBkYXRhOiBfaGJcblxuICAjXG4gICMgWW91IGFyZSBzdXJlIHRoYXQgYWxsIGNsaWVudHMgYXJlIHN5bmNlZCwgY2FsbCB0aGlzIGZ1bmN0aW9uLlxuICAjXG4gIHNldFN0YXRlU3luY2VkOiAoKS0+XG4gICAgaWYgbm90IEBpc19zeW5jZWRcbiAgICAgIEBpc19zeW5jZWQgPSB0cnVlXG4gICAgICBpZiBAY29tcHV0ZV93aGVuX3N5bmNlZD9cbiAgICAgICAgZm9yIGVsIGluIEBjb21wdXRlX3doZW5fc3luY2VkXG4gICAgICAgICAgZiA9IGVsWzBdXG4gICAgICAgICAgYXJncyA9IGVsWzEuLl1cbiAgICAgICAgICBmLmFwcGx5KGFyZ3MpXG4gICAgICAgIGRlbGV0ZSBAY29tcHV0ZV93aGVuX3N5bmNlZFxuICAgICAgbnVsbFxuXG4gICMgZXhlY3V0ZWQgd2hlbiB0aGUgYSBzdGF0ZV92ZWN0b3IgaXMgcmVjZWl2ZWQuIGxpc3RlbmVyIHdpbGwgYmUgY2FsbGVkIG9ubHkgb25jZSFcbiAgd2hlblJlY2VpdmVkU3RhdGVWZWN0b3I6IChmKS0+XG4gICAgQHdoZW5fcmVjZWl2ZWRfc3RhdGVfdmVjdG9yX2xpc3RlbmVycyA/PSBbXVxuICAgIEB3aGVuX3JlY2VpdmVkX3N0YXRlX3ZlY3Rvcl9saXN0ZW5lcnMucHVzaCBmXG5cblxuICAjXG4gICMgWW91IHJlY2VpdmVkIGEgcmF3IG1lc3NhZ2UsIGFuZCB5b3Uga25vdyB0aGF0IGl0IGlzIGludGVuZGVkIGZvciB0byBZanMuIFRoZW4gY2FsbCB0aGlzIGZ1bmN0aW9uLlxuICAjXG4gIHJlY2VpdmVNZXNzYWdlOiAoc2VuZGVyLCByZXMpLT5cbiAgICBpZiBub3QgcmVzLnN5bmNfc3RlcD9cbiAgICAgIGZvciBmIGluIEByZWNlaXZlX2hhbmRsZXJzXG4gICAgICAgIGYgc2VuZGVyLCByZXNcbiAgICBlbHNlXG4gICAgICBpZiBzZW5kZXIgaXMgQHVzZXJfaWRcbiAgICAgICAgcmV0dXJuXG4gICAgICBpZiByZXMuc3luY19zdGVwIGlzIFwiZ2V0SEJcIlxuICAgICAgICAjIGNhbGwgbGlzdGVuZXJzXG4gICAgICAgIGlmIEB3aGVuX3JlY2VpdmVkX3N0YXRlX3ZlY3Rvcl9saXN0ZW5lcnM/XG4gICAgICAgICAgZm9yIGYgaW4gQHdoZW5fcmVjZWl2ZWRfc3RhdGVfdmVjdG9yX2xpc3RlbmVyc1xuICAgICAgICAgICAgZi5jYWxsIHRoaXMsIHJlcy5kYXRhXG4gICAgICAgIGRlbGV0ZSBAd2hlbl9yZWNlaXZlZF9zdGF0ZV92ZWN0b3JfbGlzdGVuZXJzXG5cbiAgICAgICAgZGF0YSA9IEBnZXRIQihyZXMuZGF0YSlcbiAgICAgICAgaGIgPSBkYXRhLmhiXG4gICAgICAgIF9oYiA9IFtdXG4gICAgICAgICMgYWx3YXlzIGJyb2FkY2FzdCwgd2hlbiBub3Qgc3luY2VkLlxuICAgICAgICAjIFRoaXMgcmVkdWNlcyBlcnJvcnMsIHdoZW4gdGhlIGNsaWVudHMgZ29lcyBvZmZsaW5lIHByZW1hdHVyZWx5LlxuICAgICAgICAjIFdoZW4gdGhpcyBjbGllbnQgb25seSBzeW5jcyB0byBvbmUgb3RoZXIgY2xpZW50cywgYnV0IGxvb3NlcyBjb25uZWN0b3JzLFxuICAgICAgICAjIGJlZm9yZSBzeW5jaW5nIHRvIHRoZSBvdGhlciBjbGllbnRzLCB0aGUgb25saW5lIGNsaWVudHMgaGF2ZSBkaWZmZXJlbnQgc3RhdGVzLlxuICAgICAgICAjIFNpbmNlIHdlIGRvIG5vdCB3YW50IHRvIHBlcmZvcm0gcmVndWxhciBzeW5jcywgdGhpcyBpcyBhIGdvb2QgYWx0ZXJuYXRpdmVcbiAgICAgICAgaWYgQGlzX3N5bmNlZFxuICAgICAgICAgIHNlbmRBcHBseUhCID0gKG0pPT5cbiAgICAgICAgICAgIEBzZW5kIHNlbmRlciwgbVxuICAgICAgICBlbHNlXG4gICAgICAgICAgc2VuZEFwcGx5SEIgPSAobSk9PlxuICAgICAgICAgICAgQGJyb2FkY2FzdCBtXG5cbiAgICAgICAgZm9yIG8gaW4gaGJcbiAgICAgICAgICBfaGIucHVzaCBvXG4gICAgICAgICAgaWYgX2hiLmxlbmd0aCA+IDEwXG4gICAgICAgICAgICBzZW5kQXBwbHlIQlxuICAgICAgICAgICAgICBzeW5jX3N0ZXA6IFwiYXBwbHlIQl9cIlxuICAgICAgICAgICAgICBkYXRhOiBfaGJcbiAgICAgICAgICAgIF9oYiA9IFtdXG5cbiAgICAgICAgc2VuZEFwcGx5SEJcbiAgICAgICAgICBzeW5jX3N0ZXAgOiBcImFwcGx5SEJcIlxuICAgICAgICAgIGRhdGE6IF9oYlxuXG4gICAgICAgIGlmIHJlcy5zZW5kX2FnYWluPyBhbmQgQHBlcmZvcm1fc2VuZF9hZ2FpblxuICAgICAgICAgIHNlbmRfYWdhaW4gPSBkbyAoc3YgPSBkYXRhLnN0YXRlX3ZlY3Rvcik9PlxuICAgICAgICAgICAgKCk9PlxuICAgICAgICAgICAgICBoYiA9IEBnZXRIQihzdikuaGJcbiAgICAgICAgICAgICAgZm9yIG8gaW4gaGJcbiAgICAgICAgICAgICAgICBfaGIucHVzaCBvXG4gICAgICAgICAgICAgICAgaWYgX2hiLmxlbmd0aCA+IDEwXG4gICAgICAgICAgICAgICAgICBAc2VuZCBzZW5kZXIsXG4gICAgICAgICAgICAgICAgICAgIHN5bmNfc3RlcDogXCJhcHBseUhCX1wiXG4gICAgICAgICAgICAgICAgICAgIGRhdGE6IF9oYlxuICAgICAgICAgICAgICAgICAgX2hiID0gW11cbiAgICAgICAgICAgICAgQHNlbmQgc2VuZGVyLFxuICAgICAgICAgICAgICAgIHN5bmNfc3RlcDogXCJhcHBseUhCXCIsXG4gICAgICAgICAgICAgICAgZGF0YTogX2hiXG4gICAgICAgICAgICAgICAgc2VudF9hZ2FpbjogXCJ0cnVlXCJcbiAgICAgICAgICBzZXRUaW1lb3V0IHNlbmRfYWdhaW4sIDMwMDBcbiAgICAgIGVsc2UgaWYgcmVzLnN5bmNfc3RlcCBpcyBcImFwcGx5SEJcIlxuICAgICAgICBAYXBwbHlIQihyZXMuZGF0YSwgc2VuZGVyIGlzIEBjdXJyZW50X3N5bmNfdGFyZ2V0KVxuXG4gICAgICAgIGlmIChAc3luY01ldGhvZCBpcyBcInN5bmNBbGxcIiBvciByZXMuc2VudF9hZ2Fpbj8pIGFuZCAobm90IEBpc19zeW5jZWQpIGFuZCAoKEBjdXJyZW50X3N5bmNfdGFyZ2V0IGlzIHNlbmRlcikgb3IgKG5vdCBAY3VycmVudF9zeW5jX3RhcmdldD8pKVxuICAgICAgICAgIEBjb25uZWN0aW9uc1tzZW5kZXJdLmlzX3N5bmNlZCA9IHRydWVcbiAgICAgICAgICBAZmluZE5ld1N5bmNUYXJnZXQoKVxuXG4gICAgICBlbHNlIGlmIHJlcy5zeW5jX3N0ZXAgaXMgXCJhcHBseUhCX1wiXG4gICAgICAgIEBhcHBseUhCKHJlcy5kYXRhLCBzZW5kZXIgaXMgQGN1cnJlbnRfc3luY190YXJnZXQpXG5cblxuICAjIEN1cnJlbnRseSwgdGhlIEhCIGVuY29kZXMgb3BlcmF0aW9ucyBhcyBKU09OLiBGb3IgdGhlIG1vbWVudCBJIHdhbnQgdG8ga2VlcCBpdFxuICAjIHRoYXQgd2F5LiBNYXliZSB3ZSBzdXBwb3J0IGVuY29kaW5nIGluIHRoZSBIQiBhcyBYTUwgaW4gdGhlIGZ1dHVyZSwgYnV0IGZvciBub3cgSSBkb24ndCB3YW50XG4gICMgdG9vIG11Y2ggb3ZlcmhlYWQuIFkgaXMgdmVyeSBsaWtlbHkgdG8gZ2V0IGNoYW5nZWQgYSBsb3QgaW4gdGhlIGZ1dHVyZVxuICAjXG4gICMgQmVjYXVzZSB3ZSBkb24ndCB3YW50IHRvIGVuY29kZSBKU09OIGFzIHN0cmluZyAod2l0aCBjaGFyYWN0ZXIgZXNjYXBpbmcsIHdpY2ggbWFrZXMgaXQgcHJldHR5IG11Y2ggdW5yZWFkYWJsZSlcbiAgIyB3ZSBlbmNvZGUgdGhlIEpTT04gYXMgWE1MLlxuICAjXG4gICMgV2hlbiB0aGUgSEIgc3VwcG9ydCBlbmNvZGluZyBhcyBYTUwsIHRoZSBmb3JtYXQgc2hvdWxkIGxvb2sgcHJldHR5IG11Y2ggbGlrZSB0aGlzLlxuXG4gICMgZG9lcyBub3Qgc3VwcG9ydCBwcmltaXRpdmUgdmFsdWVzIGFzIGFycmF5IGVsZW1lbnRzXG4gICMgZXhwZWN0cyBhbiBsdHggKGxlc3MgdGhhbiB4bWwpIG9iamVjdFxuICBwYXJzZU1lc3NhZ2VGcm9tWG1sOiAobSktPlxuICAgIHBhcnNlX2FycmF5ID0gKG5vZGUpLT5cbiAgICAgIGZvciBuIGluIG5vZGUuY2hpbGRyZW5cbiAgICAgICAgaWYgbi5nZXRBdHRyaWJ1dGUoXCJpc0FycmF5XCIpIGlzIFwidHJ1ZVwiXG4gICAgICAgICAgcGFyc2VfYXJyYXkgblxuICAgICAgICBlbHNlXG4gICAgICAgICAgcGFyc2Vfb2JqZWN0IG5cblxuICAgIHBhcnNlX29iamVjdCA9IChub2RlKS0+XG4gICAgICBqc29uID0ge31cbiAgICAgIGZvciBuYW1lLCB2YWx1ZSAgb2Ygbm9kZS5hdHRyc1xuICAgICAgICBpbnQgPSBwYXJzZUludCh2YWx1ZSlcbiAgICAgICAgaWYgaXNOYU4oaW50KSBvciAoXCJcIitpbnQpIGlzbnQgdmFsdWVcbiAgICAgICAgICBqc29uW25hbWVdID0gdmFsdWVcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGpzb25bbmFtZV0gPSBpbnRcbiAgICAgIGZvciBuIGluIG5vZGUuY2hpbGRyZW5cbiAgICAgICAgbmFtZSA9IG4ubmFtZVxuICAgICAgICBpZiBuLmdldEF0dHJpYnV0ZShcImlzQXJyYXlcIikgaXMgXCJ0cnVlXCJcbiAgICAgICAgICBqc29uW25hbWVdID0gcGFyc2VfYXJyYXkgblxuICAgICAgICBlbHNlXG4gICAgICAgICAganNvbltuYW1lXSA9IHBhcnNlX29iamVjdCBuXG4gICAgICBqc29uXG4gICAgcGFyc2Vfb2JqZWN0IG1cblxuICAjIGVuY29kZSBtZXNzYWdlIGluIHhtbFxuICAjIHdlIHVzZSBzdHJpbmcgYmVjYXVzZSBTdHJvcGhlIG9ubHkgYWNjZXB0cyBhbiBcInhtbC1zdHJpbmdcIi4uXG4gICMgU28ge2E6NCxiOntjOjV9fSB3aWxsIGxvb2sgbGlrZVxuICAjIDx5IGE9XCI0XCI+XG4gICMgICA8YiBjPVwiNVwiPjwvYj5cbiAgIyA8L3k+XG4gICMgbSAtIGx0eCBlbGVtZW50XG4gICMganNvbiAtIGd1ZXNzIGl0IDspXG4gICNcbiAgZW5jb2RlTWVzc2FnZVRvWG1sOiAobSwganNvbiktPlxuICAgICMgYXR0cmlidXRlcyBpcyBvcHRpb25hbFxuICAgIGVuY29kZV9vYmplY3QgPSAobSwganNvbiktPlxuICAgICAgZm9yIG5hbWUsdmFsdWUgb2YganNvblxuICAgICAgICBpZiBub3QgdmFsdWU/XG4gICAgICAgICAgIyBub3BcbiAgICAgICAgZWxzZSBpZiB2YWx1ZS5jb25zdHJ1Y3RvciBpcyBPYmplY3RcbiAgICAgICAgICBlbmNvZGVfb2JqZWN0IG0uYyhuYW1lKSwgdmFsdWVcbiAgICAgICAgZWxzZSBpZiB2YWx1ZS5jb25zdHJ1Y3RvciBpcyBBcnJheVxuICAgICAgICAgIGVuY29kZV9hcnJheSBtLmMobmFtZSksIHZhbHVlXG4gICAgICAgIGVsc2VcbiAgICAgICAgICBtLnNldEF0dHJpYnV0ZShuYW1lLHZhbHVlKVxuICAgICAgbVxuICAgIGVuY29kZV9hcnJheSA9IChtLCBhcnJheSktPlxuICAgICAgbS5zZXRBdHRyaWJ1dGUoXCJpc0FycmF5XCIsXCJ0cnVlXCIpXG4gICAgICBmb3IgZSBpbiBhcnJheVxuICAgICAgICBpZiBlLmNvbnN0cnVjdG9yIGlzIE9iamVjdFxuICAgICAgICAgIGVuY29kZV9vYmplY3QgbS5jKFwiYXJyYXktZWxlbWVudFwiKSwgZVxuICAgICAgICBlbHNlXG4gICAgICAgICAgZW5jb2RlX2FycmF5IG0uYyhcImFycmF5LWVsZW1lbnRcIiksIGVcbiAgICAgIG1cbiAgICBpZiBqc29uLmNvbnN0cnVjdG9yIGlzIE9iamVjdFxuICAgICAgZW5jb2RlX29iamVjdCBtLmMoXCJ5XCIse3htbG5zOlwiaHR0cDovL3kubmluamEvY29ubmVjdG9yLXN0YW56YVwifSksIGpzb25cbiAgICBlbHNlIGlmIGpzb24uY29uc3RydWN0b3IgaXMgQXJyYXlcbiAgICAgIGVuY29kZV9hcnJheSBtLmMoXCJ5XCIse3htbG5zOlwiaHR0cDovL3kubmluamEvY29ubmVjdG9yLXN0YW56YVwifSksIGpzb25cbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJJIGNhbid0IGVuY29kZSB0aGlzIGpzb24hXCJcblxuICBzZXRJc0JvdW5kVG9ZOiAoKS0+XG4gICAgQG9uX2JvdW5kX3RvX3k/KClcbiAgICBkZWxldGUgQHdoZW5fYm91bmRfdG9feVxuICAgIEBpc19ib3VuZF90b195ID0gdHJ1ZVxuIiwiXG53aW5kb3c/LnVucHJvY2Vzc2VkX2NvdW50ZXIgPSAwICMgZGVsIHRoaXNcbndpbmRvdz8udW5wcm9jZXNzZWRfZXhlY19jb3VudGVyID0gMCAjIFRPRE9cbndpbmRvdz8udW5wcm9jZXNzZWRfdHlwZXMgPSBbXVxuXG4jXG4jIEBub2RvY1xuIyBUaGUgRW5naW5lIGhhbmRsZXMgaG93IGFuZCBpbiB3aGljaCBvcmRlciB0byBleGVjdXRlIG9wZXJhdGlvbnMgYW5kIGFkZCBvcGVyYXRpb25zIHRvIHRoZSBIaXN0b3J5QnVmZmVyLlxuI1xuY2xhc3MgRW5naW5lXG5cbiAgI1xuICAjIEBwYXJhbSB7SGlzdG9yeUJ1ZmZlcn0gSEJcbiAgIyBAcGFyYW0ge09iamVjdH0gdHlwZXMgbGlzdCBvZiBhdmFpbGFibGUgdHlwZXNcbiAgI1xuICBjb25zdHJ1Y3RvcjogKEBIQiwgQHR5cGVzKS0+XG4gICAgQHVucHJvY2Vzc2VkX29wcyA9IFtdXG5cbiAgI1xuICAjIFBhcnNlcyBhbiBvcGVyYXRpbyBmcm9tIHRoZSBqc29uIGZvcm1hdC4gSXQgdXNlcyB0aGUgc3BlY2lmaWVkIHBhcnNlciBpbiB5b3VyIE9wZXJhdGlvblR5cGUgbW9kdWxlLlxuICAjXG4gIHBhcnNlT3BlcmF0aW9uOiAoanNvbiktPlxuICAgIHR5cGUgPSBAdHlwZXNbanNvbi50eXBlXVxuICAgIGlmIHR5cGU/LnBhcnNlP1xuICAgICAgdHlwZS5wYXJzZSBqc29uXG4gICAgZWxzZVxuICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IGZvcmdvdCB0byBzcGVjaWZ5IGEgcGFyc2VyIGZvciB0eXBlICN7anNvbi50eXBlfS4gVGhlIG1lc3NhZ2UgaXMgI3tKU09OLnN0cmluZ2lmeSBqc29ufS5cIlxuXG5cbiAgI1xuICAjIEFwcGx5IGEgc2V0IG9mIG9wZXJhdGlvbnMuIEUuZy4gdGhlIG9wZXJhdGlvbnMgeW91IHJlY2VpdmVkIGZyb20gYW5vdGhlciB1c2VycyBIQi5fZW5jb2RlKCkuXG4gICMgQG5vdGUgWW91IG11c3Qgbm90IHVzZSB0aGlzIG1ldGhvZCB3aGVuIHlvdSBhbHJlYWR5IGhhdmUgb3BzIGluIHlvdXIgSEIhXG4gICMjI1xuICBhcHBseU9wc0J1bmRsZTogKG9wc19qc29uKS0+XG4gICAgb3BzID0gW11cbiAgICBmb3IgbyBpbiBvcHNfanNvblxuICAgICAgb3BzLnB1c2ggQHBhcnNlT3BlcmF0aW9uIG9cbiAgICBmb3IgbyBpbiBvcHNcbiAgICAgIGlmIG5vdCBvLmV4ZWN1dGUoKVxuICAgICAgICBAdW5wcm9jZXNzZWRfb3BzLnB1c2ggb1xuICAgIEB0cnlVbnByb2Nlc3NlZCgpXG4gICMjI1xuXG4gICNcbiAgIyBTYW1lIGFzIGFwcGx5T3BzIGJ1dCBvcGVyYXRpb25zIHRoYXQgYXJlIGFscmVhZHkgaW4gdGhlIEhCIGFyZSBub3QgYXBwbGllZC5cbiAgIyBAc2VlIEVuZ2luZS5hcHBseU9wc1xuICAjXG4gIGFwcGx5T3BzQ2hlY2tEb3VibGU6IChvcHNfanNvbiktPlxuICAgIGZvciBvIGluIG9wc19qc29uXG4gICAgICBpZiBub3QgQEhCLmdldE9wZXJhdGlvbihvLnVpZCk/XG4gICAgICAgIEBhcHBseU9wIG9cblxuICAjXG4gICMgQXBwbHkgYSBzZXQgb2Ygb3BlcmF0aW9ucy4gKEhlbHBlciBmb3IgdXNpbmcgYXBwbHlPcCBvbiBBcnJheXMpXG4gICMgQHNlZSBFbmdpbmUuYXBwbHlPcFxuICBhcHBseU9wczogKG9wc19qc29uKS0+XG4gICAgQGFwcGx5T3Agb3BzX2pzb25cblxuICAjXG4gICMgQXBwbHkgYW4gb3BlcmF0aW9uIHRoYXQgeW91IHJlY2VpdmVkIGZyb20gYW5vdGhlciBwZWVyLlxuICAjIFRPRE86IG1ha2UgdGhpcyBtb3JlIGVmZmljaWVudCEhXG4gICMgLSBvcGVyYXRpb25zIG1heSBvbmx5IGV4ZWN1dGVkIGluIG9yZGVyIGJ5IGNyZWF0b3IsIG9yZGVyIHRoZW0gaW4gb2JqZWN0IG9mIGFycmF5cyAoa2V5IGJ5IGNyZWF0b3IpXG4gICMgLSB5b3UgY2FuIHByb2JhYmx5IG1ha2Ugc29tZXRoaW5nIGxpa2UgZGVwZW5kZW5jaWVzIChjcmVhdG9yMSB3YWl0cyBmb3IgY3JlYXRvcjIpXG4gIGFwcGx5T3A6IChvcF9qc29uX2FycmF5LCBmcm9tSEIgPSBmYWxzZSktPlxuICAgIGlmIG9wX2pzb25fYXJyYXkuY29uc3RydWN0b3IgaXNudCBBcnJheVxuICAgICAgb3BfanNvbl9hcnJheSA9IFtvcF9qc29uX2FycmF5XVxuICAgIGZvciBvcF9qc29uIGluIG9wX2pzb25fYXJyYXlcbiAgICAgIGlmIGZyb21IQlxuICAgICAgICBvcF9qc29uLmZyb21IQiA9IFwidHJ1ZVwiICMgZXhlY3V0ZSBpbW1lZGlhdGVseSwgaWZcbiAgICAgICMgJHBhcnNlX2FuZF9leGVjdXRlIHdpbGwgcmV0dXJuIGZhbHNlIGlmICRvX2pzb24gd2FzIHBhcnNlZCBhbmQgZXhlY3V0ZWQsIG90aGVyd2lzZSB0aGUgcGFyc2VkIG9wZXJhZGlvblxuICAgICAgbyA9IEBwYXJzZU9wZXJhdGlvbiBvcF9qc29uXG4gICAgICBvLnBhcnNlZF9mcm9tX2pzb24gPSBvcF9qc29uXG4gICAgICBpZiBvcF9qc29uLmZyb21IQj9cbiAgICAgICAgby5mcm9tSEIgPSBvcF9qc29uLmZyb21IQlxuICAgICAgIyBASEIuYWRkT3BlcmF0aW9uIG9cbiAgICAgIGlmIEBIQi5nZXRPcGVyYXRpb24obyk/XG4gICAgICAgICMgbm9wXG4gICAgICBlbHNlIGlmICgobm90IEBIQi5pc0V4cGVjdGVkT3BlcmF0aW9uKG8pKSBhbmQgKG5vdCBvLmZyb21IQj8pKSBvciAobm90IG8uZXhlY3V0ZSgpKVxuICAgICAgICBAdW5wcm9jZXNzZWRfb3BzLnB1c2ggb1xuICAgICAgICB3aW5kb3c/LnVucHJvY2Vzc2VkX3R5cGVzLnB1c2ggby50eXBlICMgVE9ETzogZGVsZXRlIHRoaXNcbiAgICBAdHJ5VW5wcm9jZXNzZWQoKVxuXG4gICNcbiAgIyBDYWxsIHRoaXMgbWV0aG9kIHdoZW4geW91IGFwcGxpZWQgYSBuZXcgb3BlcmF0aW9uLlxuICAjIEl0IGNoZWNrcyBpZiBvcGVyYXRpb25zIHRoYXQgd2VyZSBwcmV2aW91c2x5IG5vdCBleGVjdXRhYmxlIGFyZSBub3cgZXhlY3V0YWJsZS5cbiAgI1xuICB0cnlVbnByb2Nlc3NlZDogKCktPlxuICAgIHdoaWxlIHRydWVcbiAgICAgIG9sZF9sZW5ndGggPSBAdW5wcm9jZXNzZWRfb3BzLmxlbmd0aFxuICAgICAgdW5wcm9jZXNzZWQgPSBbXVxuICAgICAgZm9yIG9wIGluIEB1bnByb2Nlc3NlZF9vcHNcbiAgICAgICAgaWYgQEhCLmdldE9wZXJhdGlvbihvcCk/XG4gICAgICAgICAgIyBub3BcbiAgICAgICAgZWxzZSBpZiAobm90IEBIQi5pc0V4cGVjdGVkT3BlcmF0aW9uKG9wKSBhbmQgKG5vdCBvcC5mcm9tSEI/KSkgb3IgKG5vdCBvcC5leGVjdXRlKCkpXG4gICAgICAgICAgdW5wcm9jZXNzZWQucHVzaCBvcFxuICAgICAgQHVucHJvY2Vzc2VkX29wcyA9IHVucHJvY2Vzc2VkXG4gICAgICBpZiBAdW5wcm9jZXNzZWRfb3BzLmxlbmd0aCBpcyBvbGRfbGVuZ3RoXG4gICAgICAgIGJyZWFrXG4gICAgaWYgQHVucHJvY2Vzc2VkX29wcy5sZW5ndGggaXNudCAwXG4gICAgICBASEIuaW52b2tlU3luYygpXG5cblxubW9kdWxlLmV4cG9ydHMgPSBFbmdpbmVcblxuXG5cblxuXG5cblxuXG5cblxuXG5cbiIsIlxuI1xuIyBAbm9kb2NcbiMgQW4gb2JqZWN0IHRoYXQgaG9sZHMgYWxsIGFwcGxpZWQgb3BlcmF0aW9ucy5cbiNcbiMgQG5vdGUgVGhlIEhpc3RvcnlCdWZmZXIgaXMgY29tbW9ubHkgYWJicmV2aWF0ZWQgdG8gSEIuXG4jXG5jbGFzcyBIaXN0b3J5QnVmZmVyXG5cbiAgI1xuICAjIENyZWF0ZXMgYW4gZW1wdHkgSEIuXG4gICMgQHBhcmFtIHtPYmplY3R9IHVzZXJfaWQgQ3JlYXRvciBvZiB0aGUgSEIuXG4gICNcbiAgY29uc3RydWN0b3I6IChAdXNlcl9pZCktPlxuICAgIEBvcGVyYXRpb25fY291bnRlciA9IHt9XG4gICAgQGJ1ZmZlciA9IHt9XG4gICAgQGNoYW5nZV9saXN0ZW5lcnMgPSBbXVxuICAgIEBnYXJiYWdlID0gW10gIyBXaWxsIGJlIGNsZWFuZWQgb24gbmV4dCBjYWxsIG9mIGdhcmJhZ2VDb2xsZWN0b3JcbiAgICBAdHJhc2ggPSBbXSAjIElzIGRlbGV0ZWQuIFdhaXQgdW50aWwgaXQgaXMgbm90IHVzZWQgYW55bW9yZS5cbiAgICBAcGVyZm9ybUdhcmJhZ2VDb2xsZWN0aW9uID0gdHJ1ZVxuICAgIEBnYXJiYWdlQ29sbGVjdFRpbWVvdXQgPSAzMDAwMFxuICAgIEByZXNlcnZlZF9pZGVudGlmaWVyX2NvdW50ZXIgPSAwXG4gICAgc2V0VGltZW91dCBAZW1wdHlHYXJiYWdlLCBAZ2FyYmFnZUNvbGxlY3RUaW1lb3V0XG5cbiAgIyBBdCB0aGUgYmVnaW5uaW5nICh3aGVuIHRoZSB1c2VyIGlkIHdhcyBub3QgYXNzaWduZWQgeWV0KSxcbiAgIyB0aGUgb3BlcmF0aW9ucyBhcmUgYWRkZWQgdG8gYnVmZmVyLl90ZW1wLiBXaGVuIHlvdSBmaW5hbGx5IGdldCB5b3VyIHVzZXIgaWQsXG4gICMgdGhlIG9wZXJhdGlvbnMgYXJlIGNvcGllcyBmcm9tIGJ1ZmZlci5fdGVtcCB0byBidWZmZXJbaWRdLiBGdXJ0aGVybW9yZSwgd2hlbiBidWZmZXJbaWRdIGRvZXMgYWxyZWFkeSBjb250YWluIG9wZXJhdGlvbnNcbiAgIyAoYmVjYXVzZSBvZiBhIHByZXZpb3VzIHNlc3Npb24pLCB0aGUgdWlkLm9wX251bWJlcnMgb2YgdGhlIG9wZXJhdGlvbnMgaGF2ZSB0byBiZSByZWFzc2lnbmVkLlxuICAjIFRoaXMgaXMgd2hhdCB0aGlzIGZ1bmN0aW9uIGRvZXMuIEl0IGFkZHMgdGhlbSB0byBidWZmZXJbaWRdLFxuICAjIGFuZCBhc3NpZ25zIHRoZW0gdGhlIGNvcnJlY3QgdWlkLm9wX251bWJlciBhbmQgdWlkLmNyZWF0b3JcbiAgc2V0VXNlcklkOiAoQHVzZXJfaWQsIHN0YXRlX3ZlY3RvciktPlxuICAgIEBidWZmZXJbQHVzZXJfaWRdID89IFtdXG4gICAgYnVmZiA9IEBidWZmZXJbQHVzZXJfaWRdXG5cbiAgICAjIHdlIGFzc3VtZWQgdGhhdCB3ZSBzdGFydGVkIHdpdGggY291bnRlciA9IDAuXG4gICAgIyB3aGVuIHdlIHJlY2VpdmUgdGhhIHN0YXRlX3ZlY3RvciwgYW5kIGFjdHVhbGx5IGhhdmVcbiAgICAjIGNvdW50ZXIgPSAxMC4gVGhlbiB3ZSBoYXZlIHRvIGFkZCAxMCB0byBldmVyeSBvcF9jb3VudGVyXG4gICAgY291bnRlcl9kaWZmID0gc3RhdGVfdmVjdG9yW0B1c2VyX2lkXSBvciAwXG5cbiAgICBpZiBAYnVmZmVyLl90ZW1wP1xuICAgICAgZm9yIG9fbmFtZSxvIG9mIEBidWZmZXIuX3RlbXBcbiAgICAgICAgby51aWQuY3JlYXRvciA9IEB1c2VyX2lkXG4gICAgICAgIG8udWlkLm9wX251bWJlciArPSBjb3VudGVyX2RpZmZcbiAgICAgICAgYnVmZltvLnVpZC5vcF9udW1iZXJdID0gb1xuXG4gICAgQG9wZXJhdGlvbl9jb3VudGVyW0B1c2VyX2lkXSA9IChAb3BlcmF0aW9uX2NvdW50ZXIuX3RlbXAgb3IgMCkgKyBjb3VudGVyX2RpZmZcblxuICAgIGRlbGV0ZSBAb3BlcmF0aW9uX2NvdW50ZXIuX3RlbXBcbiAgICBkZWxldGUgQGJ1ZmZlci5fdGVtcFxuXG5cbiAgZW1wdHlHYXJiYWdlOiAoKT0+XG4gICAgZm9yIG8gaW4gQGdhcmJhZ2VcbiAgICAgICNpZiBAZ2V0T3BlcmF0aW9uQ291bnRlcihvLnVpZC5jcmVhdG9yKSA+IG8udWlkLm9wX251bWJlclxuICAgICAgby5jbGVhbnVwPygpXG5cbiAgICBAZ2FyYmFnZSA9IEB0cmFzaFxuICAgIEB0cmFzaCA9IFtdXG4gICAgaWYgQGdhcmJhZ2VDb2xsZWN0VGltZW91dCBpc250IC0xXG4gICAgICBAZ2FyYmFnZUNvbGxlY3RUaW1lb3V0SWQgPSBzZXRUaW1lb3V0IEBlbXB0eUdhcmJhZ2UsIEBnYXJiYWdlQ29sbGVjdFRpbWVvdXRcbiAgICB1bmRlZmluZWRcblxuICAjXG4gICMgR2V0IHRoZSB1c2VyIGlkIHdpdGggd2ljaCB0aGUgSGlzdG9yeSBCdWZmZXIgd2FzIGluaXRpYWxpemVkLlxuICAjXG4gIGdldFVzZXJJZDogKCktPlxuICAgIEB1c2VyX2lkXG5cbiAgYWRkVG9HYXJiYWdlQ29sbGVjdG9yOiAoKS0+XG4gICAgaWYgQHBlcmZvcm1HYXJiYWdlQ29sbGVjdGlvblxuICAgICAgZm9yIG8gaW4gYXJndW1lbnRzXG4gICAgICAgIGlmIG8/XG4gICAgICAgICAgQGdhcmJhZ2UucHVzaCBvXG5cbiAgc3RvcEdhcmJhZ2VDb2xsZWN0aW9uOiAoKS0+XG4gICAgQHBlcmZvcm1HYXJiYWdlQ29sbGVjdGlvbiA9IGZhbHNlXG4gICAgQHNldE1hbnVhbEdhcmJhZ2VDb2xsZWN0KClcbiAgICBAZ2FyYmFnZSA9IFtdXG4gICAgQHRyYXNoID0gW11cblxuICBzZXRNYW51YWxHYXJiYWdlQ29sbGVjdDogKCktPlxuICAgIEBnYXJiYWdlQ29sbGVjdFRpbWVvdXQgPSAtMVxuICAgIGNsZWFyVGltZW91dCBAZ2FyYmFnZUNvbGxlY3RUaW1lb3V0SWRcbiAgICBAZ2FyYmFnZUNvbGxlY3RUaW1lb3V0SWQgPSB1bmRlZmluZWRcblxuICBzZXRHYXJiYWdlQ29sbGVjdFRpbWVvdXQ6IChAZ2FyYmFnZUNvbGxlY3RUaW1lb3V0KS0+XG5cbiAgI1xuICAjIEkgcHJvcG9zZSB0byB1c2UgaXQgaW4geW91ciBGcmFtZXdvcmssIHRvIGNyZWF0ZSBzb21ldGhpbmcgbGlrZSBhIHJvb3QgZWxlbWVudC5cbiAgIyBBbiBvcGVyYXRpb24gd2l0aCB0aGlzIGlkZW50aWZpZXIgaXMgbm90IHByb3BhZ2F0ZWQgdG8gb3RoZXIgY2xpZW50cy5cbiAgIyBUaGlzIGlzIHdoeSBldmVyeWJvZGUgbXVzdCBjcmVhdGUgdGhlIHNhbWUgb3BlcmF0aW9uIHdpdGggdGhpcyB1aWQuXG4gICNcbiAgZ2V0UmVzZXJ2ZWRVbmlxdWVJZGVudGlmaWVyOiAoKS0+XG4gICAge1xuICAgICAgY3JlYXRvciA6ICdfJ1xuICAgICAgb3BfbnVtYmVyIDogXCJfI3tAcmVzZXJ2ZWRfaWRlbnRpZmllcl9jb3VudGVyKyt9XCJcbiAgICB9XG5cbiAgI1xuICAjIEdldCB0aGUgb3BlcmF0aW9uIGNvdW50ZXIgdGhhdCBkZXNjcmliZXMgdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIGRvY3VtZW50LlxuICAjXG4gIGdldE9wZXJhdGlvbkNvdW50ZXI6ICh1c2VyX2lkKS0+XG4gICAgaWYgbm90IHVzZXJfaWQ/XG4gICAgICByZXMgPSB7fVxuICAgICAgZm9yIHVzZXIsY3RuIG9mIEBvcGVyYXRpb25fY291bnRlclxuICAgICAgICByZXNbdXNlcl0gPSBjdG5cbiAgICAgIHJlc1xuICAgIGVsc2VcbiAgICAgIEBvcGVyYXRpb25fY291bnRlclt1c2VyX2lkXVxuXG4gIGlzRXhwZWN0ZWRPcGVyYXRpb246IChvKS0+XG4gICAgQG9wZXJhdGlvbl9jb3VudGVyW28udWlkLmNyZWF0b3JdID89IDBcbiAgICBvLnVpZC5vcF9udW1iZXIgPD0gQG9wZXJhdGlvbl9jb3VudGVyW28udWlkLmNyZWF0b3JdXG4gICAgdHJ1ZSAjVE9ETzogISEgdGhpcyBjb3VsZCBicmVhayBzdHVmZi4gQnV0IEkgZHVubm8gd2h5XG5cbiAgI1xuICAjIEVuY29kZSB0aGlzIG9wZXJhdGlvbiBpbiBzdWNoIGEgd2F5IHRoYXQgaXQgY2FuIGJlIHBhcnNlZCBieSByZW1vdGUgcGVlcnMuXG4gICMgVE9ETzogTWFrZSB0aGlzIG1vcmUgZWZmaWNpZW50IVxuICBfZW5jb2RlOiAoc3RhdGVfdmVjdG9yPXt9KS0+XG4gICAganNvbiA9IFtdXG4gICAgdW5rbm93biA9ICh1c2VyLCBvX251bWJlciktPlxuICAgICAgaWYgKG5vdCB1c2VyPykgb3IgKG5vdCBvX251bWJlcj8pXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcImRhaCFcIlxuICAgICAgbm90IHN0YXRlX3ZlY3Rvclt1c2VyXT8gb3Igc3RhdGVfdmVjdG9yW3VzZXJdIDw9IG9fbnVtYmVyXG5cbiAgICBmb3IgdV9uYW1lLHVzZXIgb2YgQGJ1ZmZlclxuICAgICAgIyBUT0RPIG5leHQsIGlmIEBzdGF0ZV92ZWN0b3JbdXNlcl0gPD0gc3RhdGVfdmVjdG9yW3VzZXJdXG4gICAgICBpZiB1X25hbWUgaXMgXCJfXCJcbiAgICAgICAgY29udGludWVcbiAgICAgIGZvciBvX251bWJlcixvIG9mIHVzZXJcbiAgICAgICAgaWYgKG5vdCBvLnVpZC5ub09wZXJhdGlvbj8pIGFuZCB1bmtub3duKHVfbmFtZSwgb19udW1iZXIpXG4gICAgICAgICAgIyBpdHMgbmVjZXNzYXJ5IHRvIHNlbmQgaXQsIGFuZCBub3Qga25vd24gaW4gc3RhdGVfdmVjdG9yXG4gICAgICAgICAgb19qc29uID0gby5fZW5jb2RlKClcbiAgICAgICAgICBpZiBvLm5leHRfY2w/ICMgYXBwbGllcyBmb3IgYWxsIG9wcyBidXQgdGhlIG1vc3QgcmlnaHQgZGVsaW1pdGVyIVxuICAgICAgICAgICAgIyBzZWFyY2ggZm9yIHRoZSBuZXh0IF9rbm93bl8gb3BlcmF0aW9uLiAoV2hlbiBzdGF0ZV92ZWN0b3IgaXMge30gdGhlbiB0aGlzIGlzIHRoZSBEZWxpbWl0ZXIpXG4gICAgICAgICAgICBvX25leHQgPSBvLm5leHRfY2xcbiAgICAgICAgICAgIHdoaWxlIG9fbmV4dC5uZXh0X2NsPyBhbmQgdW5rbm93bihvX25leHQudWlkLmNyZWF0b3IsIG9fbmV4dC51aWQub3BfbnVtYmVyKVxuICAgICAgICAgICAgICBvX25leHQgPSBvX25leHQubmV4dF9jbFxuICAgICAgICAgICAgb19qc29uLm5leHQgPSBvX25leHQuZ2V0VWlkKClcbiAgICAgICAgICBlbHNlIGlmIG8ucHJldl9jbD8gIyBtb3N0IHJpZ2h0IGRlbGltaXRlciBvbmx5IVxuICAgICAgICAgICAgIyBzYW1lIGFzIHRoZSBhYm92ZSB3aXRoIHByZXYuXG4gICAgICAgICAgICBvX3ByZXYgPSBvLnByZXZfY2xcbiAgICAgICAgICAgIHdoaWxlIG9fcHJldi5wcmV2X2NsPyBhbmQgdW5rbm93bihvX3ByZXYudWlkLmNyZWF0b3IsIG9fcHJldi51aWQub3BfbnVtYmVyKVxuICAgICAgICAgICAgICBvX3ByZXYgPSBvX3ByZXYucHJldl9jbFxuICAgICAgICAgICAgb19qc29uLnByZXYgPSBvX3ByZXYuZ2V0VWlkKClcbiAgICAgICAgICBqc29uLnB1c2ggb19qc29uXG5cbiAgICBqc29uXG5cbiAgI1xuICAjIEdldCB0aGUgbnVtYmVyIG9mIG9wZXJhdGlvbnMgdGhhdCB3ZXJlIGNyZWF0ZWQgYnkgYSB1c2VyLlxuICAjIEFjY29yZGluZ2x5IHlvdSB3aWxsIGdldCB0aGUgbmV4dCBvcGVyYXRpb24gbnVtYmVyIHRoYXQgaXMgZXhwZWN0ZWQgZnJvbSB0aGF0IHVzZXIuXG4gICMgVGhpcyB3aWxsIGluY3JlbWVudCB0aGUgb3BlcmF0aW9uIGNvdW50ZXIuXG4gICNcbiAgZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXI6ICh1c2VyX2lkKS0+XG4gICAgaWYgbm90IHVzZXJfaWQ/XG4gICAgICB1c2VyX2lkID0gQHVzZXJfaWRcbiAgICBpZiBub3QgQG9wZXJhdGlvbl9jb3VudGVyW3VzZXJfaWRdP1xuICAgICAgQG9wZXJhdGlvbl9jb3VudGVyW3VzZXJfaWRdID0gMFxuICAgIHVpZCA9XG4gICAgICAnY3JlYXRvcicgOiB1c2VyX2lkXG4gICAgICAnb3BfbnVtYmVyJyA6IEBvcGVyYXRpb25fY291bnRlclt1c2VyX2lkXVxuICAgIEBvcGVyYXRpb25fY291bnRlclt1c2VyX2lkXSsrXG4gICAgdWlkXG5cbiAgI1xuICAjIFJldHJpZXZlIGFuIG9wZXJhdGlvbiBmcm9tIGEgdW5pcXVlIGlkLlxuICAjXG4gICMgd2hlbiB1aWQgaGFzIGEgXCJzdWJcIiBwcm9wZXJ0eSwgdGhlIHZhbHVlIG9mIGl0IHdpbGwgYmUgYXBwbGllZFxuICAjIG9uIHRoZSBvcGVyYXRpb25zIHJldHJpZXZlU3ViIG1ldGhvZCAod2hpY2ggbXVzdCEgYmUgZGVmaW5lZClcbiAgI1xuICBnZXRPcGVyYXRpb246ICh1aWQpLT5cbiAgICBpZiB1aWQudWlkP1xuICAgICAgdWlkID0gdWlkLnVpZFxuICAgIG8gPSBAYnVmZmVyW3VpZC5jcmVhdG9yXT9bdWlkLm9wX251bWJlcl1cbiAgICBpZiB1aWQuc3ViPyBhbmQgbz9cbiAgICAgIG8ucmV0cmlldmVTdWIgdWlkLnN1YlxuICAgIGVsc2VcbiAgICAgIG9cblxuICAjXG4gICMgQWRkIGFuIG9wZXJhdGlvbiB0byB0aGUgSEIuIE5vdGUgdGhhdCB0aGlzIHdpbGwgbm90IGxpbmsgaXQgYWdhaW5zdFxuICAjIG90aGVyIG9wZXJhdGlvbnMgKGl0IHdvbnQgZXhlY3V0ZWQpXG4gICNcbiAgYWRkT3BlcmF0aW9uOiAobyktPlxuICAgIGlmIG5vdCBAYnVmZmVyW28udWlkLmNyZWF0b3JdP1xuICAgICAgQGJ1ZmZlcltvLnVpZC5jcmVhdG9yXSA9IHt9XG4gICAgaWYgQGJ1ZmZlcltvLnVpZC5jcmVhdG9yXVtvLnVpZC5vcF9udW1iZXJdP1xuICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3Qgbm90IG92ZXJ3cml0ZSBvcGVyYXRpb25zIVwiXG4gICAgaWYgKG8udWlkLm9wX251bWJlci5jb25zdHJ1Y3RvciBpc250IFN0cmluZykgYW5kIChub3QgQGlzRXhwZWN0ZWRPcGVyYXRpb24obykpIGFuZCAobm90IG8uZnJvbUhCPykgIyB5b3UgYWxyZWFkeSBkbyB0aGlzIGluIHRoZSBlbmdpbmUsIHNvIGRlbGV0ZSBpdCBoZXJlIVxuICAgICAgdGhyb3cgbmV3IEVycm9yIFwidGhpcyBvcGVyYXRpb24gd2FzIG5vdCBleHBlY3RlZCFcIlxuICAgIEBhZGRUb0NvdW50ZXIobylcbiAgICBAYnVmZmVyW28udWlkLmNyZWF0b3JdW28udWlkLm9wX251bWJlcl0gPSBvXG4gICAgb1xuXG4gIHJlbW92ZU9wZXJhdGlvbjogKG8pLT5cbiAgICBkZWxldGUgQGJ1ZmZlcltvLnVpZC5jcmVhdG9yXT9bby51aWQub3BfbnVtYmVyXVxuXG4gICMgV2hlbiB0aGUgSEIgZGV0ZXJtaW5lcyBpbmNvbnNpc3RlbmNpZXMsIHRoZW4gdGhlIGludm9rZVN5bmNcbiAgIyBoYW5kbGVyIHdpbCBiZSBjYWxsZWQsIHdoaWNoIHNob3VsZCBzb21laG93IGludm9rZSB0aGUgc3luYyB3aXRoIGFub3RoZXIgY29sbGFib3JhdG9yLlxuICAjIFRoZSBwYXJhbWV0ZXIgb2YgdGhlIHN5bmMgaGFuZGxlciBpcyB0aGUgdXNlcl9pZCB3aXRoIHdpY2ggYW4gaW5jb25zaXN0ZW5jeSB3YXMgZGV0ZXJtaW5lZFxuICBzZXRJbnZva2VTeW5jSGFuZGxlcjogKGYpLT5cbiAgICBAaW52b2tlU3luYyA9IGZcblxuICAjIGVtcHR5IHBlciBkZWZhdWx0ICMgVE9ETzogZG8gaSBuZWVkIHRoaXM/XG4gIGludm9rZVN5bmM6ICgpLT5cblxuICAjIGFmdGVyIHlvdSByZWNlaXZlZCB0aGUgSEIgb2YgYW5vdGhlciB1c2VyIChpbiB0aGUgc3luYyBwcm9jZXNzKSxcbiAgIyB5b3UgcmVuZXcgeW91ciBvd24gc3RhdGVfdmVjdG9yIHRvIHRoZSBzdGF0ZV92ZWN0b3Igb2YgdGhlIG90aGVyIHVzZXJcbiAgcmVuZXdTdGF0ZVZlY3RvcjogKHN0YXRlX3ZlY3RvciktPlxuICAgIGZvciB1c2VyLHN0YXRlIG9mIHN0YXRlX3ZlY3RvclxuICAgICAgaWYgKChub3QgQG9wZXJhdGlvbl9jb3VudGVyW3VzZXJdPykgb3IgKEBvcGVyYXRpb25fY291bnRlclt1c2VyXSA8IHN0YXRlX3ZlY3Rvclt1c2VyXSkpIGFuZCBzdGF0ZV92ZWN0b3JbdXNlcl0/XG4gICAgICAgIEBvcGVyYXRpb25fY291bnRlclt1c2VyXSA9IHN0YXRlX3ZlY3Rvclt1c2VyXVxuXG4gICNcbiAgIyBJbmNyZW1lbnQgdGhlIG9wZXJhdGlvbl9jb3VudGVyIHRoYXQgZGVmaW5lcyB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgRW5naW5lLlxuICAjXG4gIGFkZFRvQ291bnRlcjogKG8pLT5cbiAgICBAb3BlcmF0aW9uX2NvdW50ZXJbby51aWQuY3JlYXRvcl0gPz0gMFxuICAgICMgVE9ETzogY2hlY2sgaWYgb3BlcmF0aW9ucyBhcmUgc2VuZCBpbiBvcmRlclxuICAgIGlmIG8udWlkLm9wX251bWJlciBpcyBAb3BlcmF0aW9uX2NvdW50ZXJbby51aWQuY3JlYXRvcl1cbiAgICAgIEBvcGVyYXRpb25fY291bnRlcltvLnVpZC5jcmVhdG9yXSsrXG4gICAgd2hpbGUgQGJ1ZmZlcltvLnVpZC5jcmVhdG9yXVtAb3BlcmF0aW9uX2NvdW50ZXJbby51aWQuY3JlYXRvcl1dP1xuICAgICAgQG9wZXJhdGlvbl9jb3VudGVyW28udWlkLmNyZWF0b3JdKytcbiAgICB1bmRlZmluZWRcblxubW9kdWxlLmV4cG9ydHMgPSBIaXN0b3J5QnVmZmVyXG4iLCJcbmNsYXNzIFlPYmplY3RcblxuICBjb25zdHJ1Y3RvcjogKEBfb2JqZWN0ID0ge30pLT5cbiAgICBpZiBAX29iamVjdC5jb25zdHJ1Y3RvciBpcyBPYmplY3RcbiAgICAgIGZvciBuYW1lLCB2YWwgb2YgQF9vYmplY3RcbiAgICAgICAgaWYgdmFsLmNvbnN0cnVjdG9yIGlzIE9iamVjdFxuICAgICAgICAgIEBfb2JqZWN0W25hbWVdID0gbmV3IFlPYmplY3QodmFsKVxuICAgIGVsc2VcbiAgICAgIHRocm93IG5ldyBFcnJvciBcIlkuT2JqZWN0IGFjY2VwdHMgSnNvbiBPYmplY3RzIG9ubHlcIlxuXG4gIF9uYW1lOiBcIk9iamVjdFwiXG5cbiAgX2dldE1vZGVsOiAodHlwZXMsIG9wcyktPlxuICAgIGlmIG5vdCBAX21vZGVsP1xuICAgICAgQF9tb2RlbCA9IG5ldyBvcHMuTWFwTWFuYWdlcihAKS5leGVjdXRlKClcbiAgICAgIGZvciBuLG8gb2YgQF9vYmplY3RcbiAgICAgICAgQF9tb2RlbC52YWwgbiwgb1xuICAgIGRlbGV0ZSBAX29iamVjdFxuICAgIEBfbW9kZWxcblxuICBfc2V0TW9kZWw6IChAX21vZGVsKS0+XG4gICAgZGVsZXRlIEBfb2JqZWN0XG5cbiAgb2JzZXJ2ZTogKGYpLT5cbiAgICBAX21vZGVsLm9ic2VydmUgZlxuICAgIEBcblxuICB1bm9ic2VydmU6IChmKS0+XG4gICAgQF9tb2RlbC51bm9ic2VydmUgZlxuICAgIEBcblxuICAjXG4gICMgQG92ZXJsb2FkIHZhbCgpXG4gICMgICBHZXQgdGhpcyBhcyBhIEpzb24gb2JqZWN0LlxuICAjICAgQHJldHVybiBbSnNvbl1cbiAgI1xuICAjIEBvdmVybG9hZCB2YWwobmFtZSlcbiAgIyAgIEdldCB2YWx1ZSBvZiBhIHByb3BlcnR5LlxuICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgb2JqZWN0IHByb3BlcnR5LlxuICAjICAgQHJldHVybiBbKl0gRGVwZW5kcyBvbiB0aGUgdmFsdWUgb2YgdGhlIHByb3BlcnR5LlxuICAjXG4gICMgQG92ZXJsb2FkIHZhbChuYW1lLCBjb250ZW50KVxuICAjICAgU2V0IGEgbmV3IHByb3BlcnR5LlxuICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgb2JqZWN0IHByb3BlcnR5LlxuICAjICAgQHBhcmFtIHtPYmplY3R8U3RyaW5nfSBjb250ZW50IENvbnRlbnQgb2YgdGhlIG9iamVjdCBwcm9wZXJ0eS5cbiAgIyAgIEByZXR1cm4gW09iamVjdCBUeXBlXSBUaGlzIG9iamVjdC4gKHN1cHBvcnRzIGNoYWluaW5nKVxuICAjXG4gIHZhbDogKG5hbWUsIGNvbnRlbnQpLT5cbiAgICBpZiBAX21vZGVsP1xuICAgICAgQF9tb2RlbC52YWwuYXBwbHkgQF9tb2RlbCwgYXJndW1lbnRzXG4gICAgZWxzZVxuICAgICAgaWYgY29udGVudD9cbiAgICAgICAgQF9vYmplY3RbbmFtZV0gPSBjb250ZW50XG4gICAgICBlbHNlIGlmIG5hbWU/XG4gICAgICAgIEBfb2JqZWN0W25hbWVdXG4gICAgICBlbHNlXG4gICAgICAgIHJlcyA9IHt9XG4gICAgICAgIGZvciBuLHYgb2YgQF9vYmplY3RcbiAgICAgICAgICByZXNbbl0gPSB2XG4gICAgICAgIHJlc1xuXG4gIGRlbGV0ZTogKG5hbWUpLT5cbiAgICBAX21vZGVsLmRlbGV0ZShuYW1lKVxuICAgIEBcblxuaWYgd2luZG93P1xuICBpZiB3aW5kb3cuWT9cbiAgICB3aW5kb3cuWS5PYmplY3QgPSBZT2JqZWN0XG4gIGVsc2VcbiAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBmaXJzdCBpbXBvcnQgWSFcIlxuXG5pZiBtb2R1bGU/XG4gIG1vZHVsZS5leHBvcnRzID0gWU9iamVjdFxuIiwibW9kdWxlLmV4cG9ydHMgPSAoKS0+XG4gICMgQHNlZSBFbmdpbmUucGFyc2VcbiAgb3BzID0ge31cbiAgZXhlY3V0aW9uX2xpc3RlbmVyID0gW11cblxuICAjXG4gICMgQHByaXZhdGVcbiAgIyBAYWJzdHJhY3RcbiAgIyBAbm9kb2NcbiAgIyBBIGdlbmVyaWMgaW50ZXJmYWNlIHRvIG9wcy5cbiAgI1xuICAjIEFuIG9wZXJhdGlvbiBoYXMgdGhlIGZvbGxvd2luZyBtZXRob2RzOlxuICAjICogX2VuY29kZTogZW5jb2RlcyBhbiBvcGVyYXRpb24gKG5lZWRlZCBvbmx5IGlmIGluc3RhbmNlIG9mIHRoaXMgb3BlcmF0aW9uIGlzIHNlbnQpLlxuICAjICogZXhlY3V0ZTogZXhlY3V0ZSB0aGUgZWZmZWN0cyBvZiB0aGlzIG9wZXJhdGlvbnMuIEdvb2QgZXhhbXBsZXMgYXJlIEluc2VydC10eXBlIGFuZCBBZGROYW1lLXR5cGVcbiAgIyAqIHZhbDogaW4gdGhlIGNhc2UgdGhhdCB0aGUgb3BlcmF0aW9uIGhvbGRzIGEgdmFsdWVcbiAgI1xuICAjIEZ1cnRoZXJtb3JlIGFuIGVuY29kYWJsZSBvcGVyYXRpb24gaGFzIGEgcGFyc2VyLiBXZSBleHRlbmQgdGhlIHBhcnNlciBvYmplY3QgaW4gb3JkZXIgdG8gcGFyc2UgZW5jb2RlZCBvcGVyYXRpb25zLlxuICAjXG4gIGNsYXNzIG9wcy5PcGVyYXRpb25cblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci5cbiAgICAjIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQgYmVmb3JlIGF0IHRoZSBlbmQgb2YgdGhlIGV4ZWN1dGlvbiBzZXF1ZW5jZVxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKGN1c3RvbV90eXBlLCB1aWQsIGNvbnRlbnQsIGNvbnRlbnRfb3BlcmF0aW9ucyktPlxuICAgICAgaWYgY3VzdG9tX3R5cGU/XG4gICAgICAgIEBjdXN0b21fdHlwZSA9IGN1c3RvbV90eXBlXG4gICAgICBAaXNfZGVsZXRlZCA9IGZhbHNlXG4gICAgICBAZ2FyYmFnZV9jb2xsZWN0ZWQgPSBmYWxzZVxuICAgICAgQGV2ZW50X2xpc3RlbmVycyA9IFtdICMgVE9ETzogcmVuYW1lIHRvIG9ic2VydmVycyBvciBzdGggbGlrZSB0aGF0XG4gICAgICBpZiB1aWQ/XG4gICAgICAgIEB1aWQgPSB1aWRcblxuICAgICAgIyBzZWUgZW5jb2RlIHRvIHNlZSwgd2h5IHdlIGFyZSBkb2luZyBpdCB0aGlzIHdheVxuICAgICAgaWYgY29udGVudCBpcyB1bmRlZmluZWRcbiAgICAgICAgIyBub3BcbiAgICAgIGVsc2UgaWYgY29udGVudD8gYW5kIGNvbnRlbnQuY3JlYXRvcj9cbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ2NvbnRlbnQnLCBjb250ZW50XG4gICAgICBlbHNlXG4gICAgICAgIEBjb250ZW50ID0gY29udGVudFxuICAgICAgaWYgY29udGVudF9vcGVyYXRpb25zP1xuICAgICAgICBAY29udGVudF9vcGVyYXRpb25zID0ge31cbiAgICAgICAgZm9yIG5hbWUsIG9wIG9mIGNvbnRlbnRfb3BlcmF0aW9uc1xuICAgICAgICAgIEBzYXZlT3BlcmF0aW9uIG5hbWUsIG9wLCAnY29udGVudF9vcGVyYXRpb25zJ1xuXG4gICAgdHlwZTogXCJPcGVyYXRpb25cIlxuXG4gICAgZ2V0Q29udGVudDogKG5hbWUpLT5cbiAgICAgIGlmIEBjb250ZW50P1xuICAgICAgICBpZiBAY29udGVudC5nZXRDdXN0b21UeXBlP1xuICAgICAgICAgIEBjb250ZW50LmdldEN1c3RvbVR5cGUoKVxuICAgICAgICBlbHNlIGlmIEBjb250ZW50LmNvbnN0cnVjdG9yIGlzIE9iamVjdFxuICAgICAgICAgIGlmIG5hbWU/XG4gICAgICAgICAgICBpZiBAY29udGVudFtuYW1lXT9cbiAgICAgICAgICAgICAgQGNvbnRlbnRbbmFtZV1cbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgQGNvbnRlbnRfb3BlcmF0aW9uc1tuYW1lXS5nZXRDdXN0b21UeXBlKClcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBjb250ZW50ID0ge31cbiAgICAgICAgICAgIGZvciBuLHYgb2YgQGNvbnRlbnRcbiAgICAgICAgICAgICAgY29udGVudFtuXSA9IHZcbiAgICAgICAgICAgIGlmIEBjb250ZW50X29wZXJhdGlvbnM/XG4gICAgICAgICAgICAgIGZvciBuLHYgb2YgQGNvbnRlbnRfb3BlcmF0aW9uc1xuICAgICAgICAgICAgICAgIHYgPSB2LmdldEN1c3RvbVR5cGUoKVxuICAgICAgICAgICAgICAgIGNvbnRlbnRbbl0gPSB2XG4gICAgICAgICAgICBjb250ZW50XG4gICAgICAgIGVsc2VcbiAgICAgICAgICBAY29udGVudFxuICAgICAgZWxzZVxuICAgICAgICBAY29udGVudFxuXG4gICAgcmV0cmlldmVTdWI6ICgpLT5cbiAgICAgIHRocm93IG5ldyBFcnJvciBcInN1YiBwcm9wZXJ0aWVzIGFyZSBub3QgZW5hYmxlIG9uIHRoaXMgb3BlcmF0aW9uIHR5cGUhXCJcblxuICAgICNcbiAgICAjIEFkZCBhbiBldmVudCBsaXN0ZW5lci4gSXQgZGVwZW5kcyBvbiB0aGUgb3BlcmF0aW9uIHdoaWNoIGV2ZW50cyBhcmUgc3VwcG9ydGVkLlxuICAgICMgQHBhcmFtIHtGdW5jdGlvbn0gZiBmIGlzIGV4ZWN1dGVkIGluIGNhc2UgdGhlIGV2ZW50IGZpcmVzLlxuICAgICNcbiAgICBvYnNlcnZlOiAoZiktPlxuICAgICAgQGV2ZW50X2xpc3RlbmVycy5wdXNoIGZcblxuICAgICNcbiAgICAjIERlbGV0ZXMgZnVuY3Rpb24gZnJvbSB0aGUgb2JzZXJ2ZXIgbGlzdFxuICAgICMgQHNlZSBPcGVyYXRpb24ub2JzZXJ2ZVxuICAgICNcbiAgICAjIEBvdmVybG9hZCB1bm9ic2VydmUoZXZlbnQsIGYpXG4gICAgIyAgIEBwYXJhbSBmICAgICB7RnVuY3Rpb259IFRoZSBmdW5jdGlvbiB0aGF0IHlvdSB3YW50IHRvIGRlbGV0ZVxuICAgIHVub2JzZXJ2ZTogKGYpLT5cbiAgICAgIEBldmVudF9saXN0ZW5lcnMgPSBAZXZlbnRfbGlzdGVuZXJzLmZpbHRlciAoZyktPlxuICAgICAgICBmIGlzbnQgZ1xuXG4gICAgI1xuICAgICMgRGVsZXRlcyBhbGwgc3Vic2NyaWJlZCBldmVudCBsaXN0ZW5lcnMuXG4gICAgIyBUaGlzIHNob3VsZCBiZSBjYWxsZWQsIGUuZy4gYWZ0ZXIgdGhpcyBoYXMgYmVlbiByZXBsYWNlZC5cbiAgICAjIChUaGVuIG9ubHkgb25lIHJlcGxhY2UgZXZlbnQgc2hvdWxkIGZpcmUuIClcbiAgICAjIFRoaXMgaXMgYWxzbyBjYWxsZWQgaW4gdGhlIGNsZWFudXAgbWV0aG9kLlxuICAgIGRlbGV0ZUFsbE9ic2VydmVyczogKCktPlxuICAgICAgQGV2ZW50X2xpc3RlbmVycyA9IFtdXG5cbiAgICBkZWxldGU6ICgpLT5cbiAgICAgIChuZXcgb3BzLkRlbGV0ZSB1bmRlZmluZWQsIEApLmV4ZWN1dGUoKVxuICAgICAgbnVsbFxuXG4gICAgI1xuICAgICMgRmlyZSBhbiBldmVudC5cbiAgICAjIFRPRE86IERvIHNvbWV0aGluZyB3aXRoIHRpbWVvdXRzLiBZb3UgZG9uJ3Qgd2FudCB0aGlzIHRvIGZpcmUgZm9yIGV2ZXJ5IG9wZXJhdGlvbiAoZS5nLiBpbnNlcnQpLlxuICAgICMgVE9ETzogZG8geW91IG5lZWQgY2FsbEV2ZW50K2ZvcndhcmRFdmVudD8gT25seSBvbmUgc3VmZmljZXMgcHJvYmFibHlcbiAgICBjYWxsRXZlbnQ6ICgpLT5cbiAgICAgIGlmIEBjdXN0b21fdHlwZT9cbiAgICAgICAgY2FsbG9uID0gQGdldEN1c3RvbVR5cGUoKVxuICAgICAgZWxzZVxuICAgICAgICBjYWxsb24gPSBAXG4gICAgICBAZm9yd2FyZEV2ZW50IGNhbGxvbiwgYXJndW1lbnRzLi4uXG5cbiAgICAjXG4gICAgIyBGaXJlIGFuIGV2ZW50IGFuZCBzcGVjaWZ5IGluIHdoaWNoIGNvbnRleHQgdGhlIGxpc3RlbmVyIGlzIGNhbGxlZCAoc2V0ICd0aGlzJykuXG4gICAgIyBUT0RPOiBkbyB5b3UgbmVlZCB0aGlzID9cbiAgICBmb3J3YXJkRXZlbnQ6IChvcCwgYXJncy4uLiktPlxuICAgICAgZm9yIGYgaW4gQGV2ZW50X2xpc3RlbmVyc1xuICAgICAgICBmLmNhbGwgb3AsIGFyZ3MuLi5cblxuICAgIGlzRGVsZXRlZDogKCktPlxuICAgICAgQGlzX2RlbGV0ZWRcblxuICAgIGFwcGx5RGVsZXRlOiAoZ2FyYmFnZWNvbGxlY3QgPSB0cnVlKS0+XG4gICAgICBpZiBub3QgQGdhcmJhZ2VfY29sbGVjdGVkXG4gICAgICAgICNjb25zb2xlLmxvZyBcImFwcGx5RGVsZXRlOiAje0B0eXBlfVwiXG4gICAgICAgIEBpc19kZWxldGVkID0gdHJ1ZVxuICAgICAgICBpZiBnYXJiYWdlY29sbGVjdFxuICAgICAgICAgIEBnYXJiYWdlX2NvbGxlY3RlZCA9IHRydWVcbiAgICAgICAgICBASEIuYWRkVG9HYXJiYWdlQ29sbGVjdG9yIEBcblxuICAgIGNsZWFudXA6ICgpLT5cbiAgICAgICNjb25zb2xlLmxvZyBcImNsZWFudXA6ICN7QHR5cGV9XCJcbiAgICAgIEBIQi5yZW1vdmVPcGVyYXRpb24gQFxuICAgICAgQGRlbGV0ZUFsbE9ic2VydmVycygpXG5cbiAgICAjXG4gICAgIyBTZXQgdGhlIHBhcmVudCBvZiB0aGlzIG9wZXJhdGlvbi5cbiAgICAjXG4gICAgc2V0UGFyZW50OiAoQHBhcmVudCktPlxuXG4gICAgI1xuICAgICMgR2V0IHRoZSBwYXJlbnQgb2YgdGhpcyBvcGVyYXRpb24uXG4gICAgI1xuICAgIGdldFBhcmVudDogKCktPlxuICAgICAgQHBhcmVudFxuXG4gICAgI1xuICAgICMgQ29tcHV0ZXMgYSB1bmlxdWUgaWRlbnRpZmllciAodWlkKSB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uXG4gICAgI1xuICAgIGdldFVpZDogKCktPlxuICAgICAgaWYgbm90IEB1aWQubm9PcGVyYXRpb24/XG4gICAgICAgIEB1aWRcbiAgICAgIGVsc2VcbiAgICAgICAgaWYgQHVpZC5hbHQ/ICMgY291bGQgYmUgKHNhZmVseSkgdW5kZWZpbmVkXG4gICAgICAgICAgbWFwX3VpZCA9IEB1aWQuYWx0LmNsb25lVWlkKClcbiAgICAgICAgICBtYXBfdWlkLnN1YiA9IEB1aWQuc3ViXG4gICAgICAgICAgbWFwX3VpZFxuICAgICAgICBlbHNlXG4gICAgICAgICAgdW5kZWZpbmVkXG5cbiAgICBjbG9uZVVpZDogKCktPlxuICAgICAgdWlkID0ge31cbiAgICAgIGZvciBuLHYgb2YgQGdldFVpZCgpXG4gICAgICAgIHVpZFtuXSA9IHZcbiAgICAgIHVpZFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIElmIG5vdCBhbHJlYWR5IGRvbmUsIHNldCB0aGUgdWlkXG4gICAgIyBBZGQgdGhpcyB0byB0aGUgSEJcbiAgICAjIE5vdGlmeSB0aGUgYWxsIHRoZSBsaXN0ZW5lcnMuXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIEBpc19leGVjdXRlZCA9IHRydWVcbiAgICAgICAgaWYgbm90IEB1aWQ/XG4gICAgICAgICAgIyBXaGVuIHRoaXMgb3BlcmF0aW9uIHdhcyBjcmVhdGVkIHdpdGhvdXQgYSB1aWQsIHRoZW4gc2V0IGl0IGhlcmUuXG4gICAgICAgICAgIyBUaGVyZSBpcyBvbmx5IG9uZSBvdGhlciBwbGFjZSwgd2hlcmUgdGhpcyBjYW4gYmUgZG9uZSAtIGJlZm9yZSBhbiBJbnNlcnRpb25cbiAgICAgICAgICAjIGlzIGV4ZWN1dGVkIChiZWNhdXNlIHdlIG5lZWQgdGhlIGNyZWF0b3JfaWQpXG4gICAgICAgICAgQHVpZCA9IEBIQi5nZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllcigpXG4gICAgICAgIGlmIG5vdCBAdWlkLm5vT3BlcmF0aW9uP1xuICAgICAgICAgIEBIQi5hZGRPcGVyYXRpb24gQFxuICAgICAgICAgIGZvciBsIGluIGV4ZWN1dGlvbl9saXN0ZW5lclxuICAgICAgICAgICAgbCBAX2VuY29kZSgpXG4gICAgICAgIEBcbiAgICAgIGVsc2VcbiAgICAgICAgZmFsc2VcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBPcGVyYXRpb25zIG1heSBkZXBlbmQgb24gb3RoZXIgb3BlcmF0aW9ucyAobGlua2VkIGxpc3RzLCBldGMuKS5cbiAgICAjIFRoZSBzYXZlT3BlcmF0aW9uIGFuZCB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucyBtZXRob2RzIHByb3ZpZGVcbiAgICAjIGFuIGVhc3kgd2F5IHRvIHJlZmVyIHRvIHRoZXNlIG9wZXJhdGlvbnMgdmlhIGFuIHVpZCBvciBvYmplY3QgcmVmZXJlbmNlLlxuICAgICNcbiAgICAjIEZvciBleGFtcGxlOiBXZSBjYW4gY3JlYXRlIGEgbmV3IERlbGV0ZSBvcGVyYXRpb24gdGhhdCBkZWxldGVzIHRoZSBvcGVyYXRpb24gJG8gbGlrZSB0aGlzXG4gICAgIyAgICAgLSB2YXIgZCA9IG5ldyBEZWxldGUodWlkLCAkbyk7ICAgb3JcbiAgICAjICAgICAtIHZhciBkID0gbmV3IERlbGV0ZSh1aWQsICRvLmdldFVpZCgpKTtcbiAgICAjIEVpdGhlciB3YXkgd2Ugd2FudCB0byBhY2Nlc3MgJG8gdmlhIGQuZGVsZXRlcy4gSW4gdGhlIHNlY29uZCBjYXNlIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zIG11c3QgYmUgY2FsbGVkIGZpcnN0LlxuICAgICNcbiAgICAjIEBvdmVybG9hZCBzYXZlT3BlcmF0aW9uKG5hbWUsIG9wX3VpZClcbiAgICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGlvbi4gQWZ0ZXIgdmFsaWRhdGluZyAod2l0aCB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucykgdGhlIGluc3RhbnRpYXRlZCBvcGVyYXRpb24gd2lsbCBiZSBhY2Nlc3NpYmxlIHZpYSB0aGlzW25hbWVdLlxuICAgICMgICBAcGFyYW0ge09iamVjdH0gb3BfdWlkIEEgdWlkIHRoYXQgcmVmZXJzIHRvIGFuIG9wZXJhdGlvblxuICAgICMgQG92ZXJsb2FkIHNhdmVPcGVyYXRpb24obmFtZSwgb3ApXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpb24uIEFmdGVyIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiBvcCBpcyBhY2Nlc3NpYmxlIHZpYSB0aGlzW25hbWVdLlxuICAgICMgICBAcGFyYW0ge09wZXJhdGlvbn0gb3AgQW4gT3BlcmF0aW9uIG9iamVjdFxuICAgICNcbiAgICBzYXZlT3BlcmF0aW9uOiAobmFtZSwgb3AsIGJhc2UgPSBcInRoaXNcIiktPlxuICAgICAgaWYgb3A/IGFuZCBvcC5fZ2V0TW9kZWw/XG4gICAgICAgIG9wID0gb3AuX2dldE1vZGVsKEBjdXN0b21fdHlwZXMsIEBvcGVyYXRpb25zKVxuICAgICAgI1xuICAgICAgIyBFdmVyeSBpbnN0YW5jZSBvZiAkT3BlcmF0aW9uIG11c3QgaGF2ZSBhbiAkZXhlY3V0ZSBmdW5jdGlvbi5cbiAgICAgICMgV2UgdXNlIGR1Y2stdHlwaW5nIHRvIGNoZWNrIGlmIG9wIGlzIGluc3RhbnRpYXRlZCBzaW5jZSB0aGVyZVxuICAgICAgIyBjb3VsZCBleGlzdCBtdWx0aXBsZSBjbGFzc2VzIG9mICRPcGVyYXRpb25cbiAgICAgICNcbiAgICAgIGlmIG5vdCBvcD9cbiAgICAgICAgIyBub3BcbiAgICAgIGVsc2UgaWYgb3AuZXhlY3V0ZT8gb3Igbm90IChvcC5vcF9udW1iZXI/IGFuZCBvcC5jcmVhdG9yPylcbiAgICAgICAgIyBpcyBpbnN0YW50aWF0ZWQsIG9yIG9wIGlzIHN0cmluZy4gQ3VycmVudGx5IFwiRGVsaW1pdGVyXCIgaXMgc2F2ZWQgYXMgc3RyaW5nXG4gICAgICAgICMgKGluIGNvbWJpbmF0aW9uIHdpdGggQHBhcmVudCB5b3UgY2FuIHJldHJpZXZlIHRoZSBkZWxpbWl0ZXIuLilcbiAgICAgICAgaWYgYmFzZSBpcyBcInRoaXNcIlxuICAgICAgICAgIEBbbmFtZV0gPSBvcFxuICAgICAgICBlbHNlXG4gICAgICAgICAgZGVzdCA9IEBbYmFzZV1cbiAgICAgICAgICBwYXRocyA9IG5hbWUuc3BsaXQoXCIvXCIpXG4gICAgICAgICAgbGFzdF9wYXRoID0gcGF0aHMucG9wKClcbiAgICAgICAgICBmb3IgcGF0aCBpbiBwYXRoc1xuICAgICAgICAgICAgZGVzdCA9IGRlc3RbcGF0aF1cbiAgICAgICAgICBkZXN0W2xhc3RfcGF0aF0gPSBvcFxuICAgICAgZWxzZVxuICAgICAgICAjIG5vdCBpbml0aWFsaXplZC4gRG8gaXQgd2hlbiBjYWxsaW5nICR2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIEB1bmNoZWNrZWQgPz0ge31cbiAgICAgICAgQHVuY2hlY2tlZFtiYXNlXSA/PSB7fVxuICAgICAgICBAdW5jaGVja2VkW2Jhc2VdW25hbWVdID0gb3BcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBBZnRlciBjYWxsaW5nIHRoaXMgZnVuY3Rpb24gYWxsIG5vdCBpbnN0YW50aWF0ZWQgb3BlcmF0aW9ucyB3aWxsIGJlIGFjY2Vzc2libGUuXG4gICAgIyBAc2VlIE9wZXJhdGlvbi5zYXZlT3BlcmF0aW9uXG4gICAgI1xuICAgICMgQHJldHVybiBbQm9vbGVhbl0gV2hldGhlciBpdCB3YXMgcG9zc2libGUgdG8gaW5zdGFudGlhdGUgYWxsIG9wZXJhdGlvbnMuXG4gICAgI1xuICAgIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zOiAoKS0+XG4gICAgICB1bmluc3RhbnRpYXRlZCA9IHt9XG4gICAgICBzdWNjZXNzID0gdHJ1ZVxuICAgICAgZm9yIGJhc2VfbmFtZSwgYmFzZSBvZiBAdW5jaGVja2VkXG4gICAgICAgIGZvciBuYW1lLCBvcF91aWQgb2YgYmFzZVxuICAgICAgICAgIG9wID0gQEhCLmdldE9wZXJhdGlvbiBvcF91aWRcbiAgICAgICAgICBpZiBvcFxuICAgICAgICAgICAgaWYgYmFzZV9uYW1lIGlzIFwidGhpc1wiXG4gICAgICAgICAgICAgIEBbbmFtZV0gPSBvcFxuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICBkZXN0ID0gQFtiYXNlX25hbWVdXG4gICAgICAgICAgICAgIHBhdGhzID0gbmFtZS5zcGxpdChcIi9cIilcbiAgICAgICAgICAgICAgbGFzdF9wYXRoID0gcGF0aHMucG9wKClcbiAgICAgICAgICAgICAgZm9yIHBhdGggaW4gcGF0aHNcbiAgICAgICAgICAgICAgICBkZXN0ID0gZGVzdFtwYXRoXVxuICAgICAgICAgICAgICBkZXN0W2xhc3RfcGF0aF0gPSBvcFxuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIHVuaW5zdGFudGlhdGVkW2Jhc2VfbmFtZV0gPz0ge31cbiAgICAgICAgICAgIHVuaW5zdGFudGlhdGVkW2Jhc2VfbmFtZV1bbmFtZV0gPSBvcF91aWRcbiAgICAgICAgICAgIHN1Y2Nlc3MgPSBmYWxzZVxuICAgICAgaWYgbm90IHN1Y2Nlc3NcbiAgICAgICAgQHVuY2hlY2tlZCA9IHVuaW5zdGFudGlhdGVkXG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgZWxzZVxuICAgICAgICBkZWxldGUgQHVuY2hlY2tlZFxuICAgICAgICByZXR1cm4gQFxuXG4gICAgZ2V0Q3VzdG9tVHlwZTogKCktPlxuICAgICAgaWYgbm90IEBjdXN0b21fdHlwZT9cbiAgICAgICAgIyB0aHJvdyBuZXcgRXJyb3IgXCJUaGlzIG9wZXJhdGlvbiB3YXMgbm90IGluaXRpYWxpemVkIHdpdGggYSBjdXN0b20gdHlwZVwiXG4gICAgICAgIEBcbiAgICAgIGVsc2VcbiAgICAgICAgaWYgQGN1c3RvbV90eXBlLmNvbnN0cnVjdG9yIGlzIFN0cmluZ1xuICAgICAgICAgICMgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkIHlldCAob25seSB0aGUgbmFtZSBpcyBzcGVjaWZpZWQpXG4gICAgICAgICAgVHlwZSA9IEBjdXN0b21fdHlwZXNcbiAgICAgICAgICBmb3IgdCBpbiBAY3VzdG9tX3R5cGUuc3BsaXQoXCIuXCIpXG4gICAgICAgICAgICBUeXBlID0gVHlwZVt0XVxuICAgICAgICAgIEBjdXN0b21fdHlwZSA9IG5ldyBUeXBlKClcbiAgICAgICAgICBAY3VzdG9tX3R5cGUuX3NldE1vZGVsIEBcbiAgICAgICAgQGN1c3RvbV90eXBlXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKGpzb24gPSB7fSktPlxuICAgICAganNvbi50eXBlID0gQHR5cGVcbiAgICAgIGpzb24udWlkID0gQGdldFVpZCgpXG4gICAgICBpZiBAY3VzdG9tX3R5cGU/XG4gICAgICAgIGlmIEBjdXN0b21fdHlwZS5jb25zdHJ1Y3RvciBpcyBTdHJpbmdcbiAgICAgICAgICBqc29uLmN1c3RvbV90eXBlID0gQGN1c3RvbV90eXBlXG4gICAgICAgIGVsc2VcbiAgICAgICAgICBqc29uLmN1c3RvbV90eXBlID0gQGN1c3RvbV90eXBlLl9uYW1lXG5cbiAgICAgIGlmIEBjb250ZW50Py5nZXRVaWQ/XG4gICAgICAgIGpzb24uY29udGVudCA9IEBjb250ZW50LmdldFVpZCgpXG4gICAgICBlbHNlXG4gICAgICAgIGpzb24uY29udGVudCA9IEBjb250ZW50XG4gICAgICBpZiBAY29udGVudF9vcGVyYXRpb25zP1xuICAgICAgICBvcGVyYXRpb25zID0ge31cbiAgICAgICAgZm9yIG4sbyBvZiBAY29udGVudF9vcGVyYXRpb25zXG4gICAgICAgICAgaWYgby5fZ2V0TW9kZWw/XG4gICAgICAgICAgICBvID0gby5fZ2V0TW9kZWwoQGN1c3RvbV90eXBlcywgQG9wZXJhdGlvbnMpXG4gICAgICAgICAgb3BlcmF0aW9uc1tuXSA9IG8uZ2V0VWlkKClcbiAgICAgICAganNvbi5jb250ZW50X29wZXJhdGlvbnMgPSBvcGVyYXRpb25zXG4gICAgICBqc29uXG5cbiAgI1xuICAjIEBub2RvY1xuICAjIEEgc2ltcGxlIERlbGV0ZS10eXBlIG9wZXJhdGlvbiB0aGF0IGRlbGV0ZXMgYW4gb3BlcmF0aW9uLlxuICAjXG4gIGNsYXNzIG9wcy5EZWxldGUgZXh0ZW5kcyBvcHMuT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gZGVsZXRlcyBVSUQgb3IgcmVmZXJlbmNlIG9mIHRoZSBvcGVyYXRpb24gdGhhdCB0aGlzIHRvIGJlIGRlbGV0ZWQuXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAoY3VzdG9tX3R5cGUsIHVpZCwgZGVsZXRlcyktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ2RlbGV0ZXMnLCBkZWxldGVzXG4gICAgICBzdXBlciBjdXN0b21fdHlwZSwgdWlkXG5cbiAgICB0eXBlOiBcIkRlbGV0ZVwiXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgQ29udmVydCBhbGwgcmVsZXZhbnQgaW5mb3JtYXRpb24gb2YgdGhpcyBvcGVyYXRpb24gdG8gdGhlIGpzb24tZm9ybWF0LlxuICAgICMgVGhpcyByZXN1bHQgY2FuIGJlIHNlbnQgdG8gb3RoZXIgY2xpZW50cy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAge1xuICAgICAgICAndHlwZSc6IFwiRGVsZXRlXCJcbiAgICAgICAgJ3VpZCc6IEBnZXRVaWQoKVxuICAgICAgICAnZGVsZXRlcyc6IEBkZWxldGVzLmdldFVpZCgpXG4gICAgICB9XG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgQXBwbHkgdGhlIGRlbGV0aW9uLlxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICByZXMgPSBzdXBlclxuICAgICAgICBpZiByZXNcbiAgICAgICAgICBAZGVsZXRlcy5hcHBseURlbGV0ZSBAXG4gICAgICAgIHJlc1xuICAgICAgZWxzZVxuICAgICAgICBmYWxzZVxuXG4gICNcbiAgIyBEZWZpbmUgaG93IHRvIHBhcnNlIERlbGV0ZSBvcGVyYXRpb25zLlxuICAjXG4gIG9wcy5EZWxldGUucGFyc2UgPSAobyktPlxuICAgIHtcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAnZGVsZXRlcyc6IGRlbGV0ZXNfdWlkXG4gICAgfSA9IG9cbiAgICBuZXcgdGhpcyhudWxsLCB1aWQsIGRlbGV0ZXNfdWlkKVxuXG4gICNcbiAgIyBAbm9kb2NcbiAgIyBBIHNpbXBsZSBpbnNlcnQtdHlwZSBvcGVyYXRpb24uXG4gICNcbiAgIyBBbiBpbnNlcnQgb3BlcmF0aW9uIGlzIGFsd2F5cyBwb3NpdGlvbmVkIGJldHdlZW4gdHdvIG90aGVyIGluc2VydCBvcGVyYXRpb25zLlxuICAjIEludGVybmFsbHkgdGhpcyBpcyByZWFsaXplZCBhcyBhc3NvY2lhdGl2ZSBsaXN0cywgd2hlcmVieSBlYWNoIGluc2VydCBvcGVyYXRpb24gaGFzIGEgcHJlZGVjZXNzb3IgYW5kIGEgc3VjY2Vzc29yLlxuICAjIEZvciB0aGUgc2FrZSBvZiBlZmZpY2llbmN5IHdlIG1haW50YWluIHR3byBsaXN0czpcbiAgIyAgIC0gVGhlIHNob3J0LWxpc3QgKGFiYnJldi4gc2wpIG1haW50YWlucyBvbmx5IHRoZSBvcGVyYXRpb25zIHRoYXQgYXJlIG5vdCBkZWxldGVkICh1bmltcGxlbWVudGVkLCBnb29kIGlkZWE/KVxuICAjICAgLSBUaGUgY29tcGxldGUtbGlzdCAoYWJicmV2LiBjbCkgbWFpbnRhaW5zIGFsbCBvcGVyYXRpb25zXG4gICNcbiAgY2xhc3Mgb3BzLkluc2VydCBleHRlbmRzIG9wcy5PcGVyYXRpb25cblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBwcmV2X2NsIFRoZSBwcmVkZWNlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gbmV4dF9jbCBUaGUgc3VjY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcbiAgICAjXG4gICAgY29uc3RydWN0b3I6IChjdXN0b21fdHlwZSwgY29udGVudCwgY29udGVudF9vcGVyYXRpb25zLCBwYXJlbnQsIHVpZCwgcHJldl9jbCwgbmV4dF9jbCwgb3JpZ2luKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncGFyZW50JywgcGFyZW50XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncHJldl9jbCcsIHByZXZfY2xcbiAgICAgIEBzYXZlT3BlcmF0aW9uICduZXh0X2NsJywgbmV4dF9jbFxuICAgICAgaWYgb3JpZ2luP1xuICAgICAgICBAc2F2ZU9wZXJhdGlvbiAnb3JpZ2luJywgb3JpZ2luXG4gICAgICBlbHNlXG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBwcmV2X2NsXG4gICAgICBzdXBlciBjdXN0b21fdHlwZSwgdWlkLCBjb250ZW50LCBjb250ZW50X29wZXJhdGlvbnNcblxuICAgIHR5cGU6IFwiSW5zZXJ0XCJcblxuICAgIHZhbDogKCktPlxuICAgICAgQGdldENvbnRlbnQoKVxuXG4gICAgZ2V0TmV4dDogKGk9MSktPlxuICAgICAgbiA9IEBcbiAgICAgIHdoaWxlIGkgPiAwIGFuZCBuLm5leHRfY2w/XG4gICAgICAgIG4gPSBuLm5leHRfY2xcbiAgICAgICAgaWYgbm90IG4uaXNfZGVsZXRlZFxuICAgICAgICAgIGktLVxuICAgICAgaWYgbi5pc19kZWxldGVkXG4gICAgICAgIG51bGxcbiAgICAgIG5cblxuICAgIGdldFByZXY6IChpPTEpLT5cbiAgICAgIG4gPSBAXG4gICAgICB3aGlsZSBpID4gMCBhbmQgbi5wcmV2X2NsP1xuICAgICAgICBuID0gbi5wcmV2X2NsXG4gICAgICAgIGlmIG5vdCBuLmlzX2RlbGV0ZWRcbiAgICAgICAgICBpLS1cbiAgICAgIGlmIG4uaXNfZGVsZXRlZFxuICAgICAgICBudWxsXG4gICAgICBlbHNlXG4gICAgICAgIG5cblxuICAgICNcbiAgICAjIHNldCBjb250ZW50IHRvIG51bGwgYW5kIG90aGVyIHN0dWZmXG4gICAgIyBAcHJpdmF0ZVxuICAgICNcbiAgICBhcHBseURlbGV0ZTogKG8pLT5cbiAgICAgIEBkZWxldGVkX2J5ID89IFtdXG4gICAgICBjYWxsTGF0ZXIgPSBmYWxzZVxuICAgICAgaWYgQHBhcmVudD8gYW5kIG5vdCBAaXNfZGVsZXRlZCBhbmQgbz8gIyBvPyA6IGlmIG5vdCBvPywgdGhlbiB0aGUgZGVsaW1pdGVyIGRlbGV0ZWQgdGhpcyBJbnNlcnRpb24uIEZ1cnRoZXJtb3JlLCBpdCB3b3VsZCBiZSB3cm9uZyB0byBjYWxsIGl0LiBUT0RPOiBtYWtlIHRoaXMgbW9yZSBleHByZXNzaXZlIGFuZCBzYXZlXG4gICAgICAgICMgY2FsbCBpZmYgd2Fzbid0IGRlbGV0ZWQgZWFybHllclxuICAgICAgICBjYWxsTGF0ZXIgPSB0cnVlXG4gICAgICBpZiBvP1xuICAgICAgICBAZGVsZXRlZF9ieS5wdXNoIG9cbiAgICAgIGdhcmJhZ2Vjb2xsZWN0ID0gZmFsc2VcbiAgICAgIGlmIEBuZXh0X2NsLmlzRGVsZXRlZCgpXG4gICAgICAgIGdhcmJhZ2Vjb2xsZWN0ID0gdHJ1ZVxuICAgICAgc3VwZXIgZ2FyYmFnZWNvbGxlY3RcbiAgICAgIGlmIGNhbGxMYXRlclxuICAgICAgICBAcGFyZW50LmNhbGxPcGVyYXRpb25TcGVjaWZpY0RlbGV0ZUV2ZW50cyh0aGlzLCBvKVxuICAgICAgaWYgQHByZXZfY2w/IGFuZCBAcHJldl9jbC5pc0RlbGV0ZWQoKSBhbmQgQHByZXZfY2wuZ2FyYmFnZV9jb2xsZWN0ZWQgaXNudCB0cnVlXG4gICAgICAgICMgZ2FyYmFnZSBjb2xsZWN0IHByZXZfY2xcbiAgICAgICAgQHByZXZfY2wuYXBwbHlEZWxldGUoKVxuXG4gICAgY2xlYW51cDogKCktPlxuICAgICAgaWYgQG5leHRfY2wuaXNEZWxldGVkKClcbiAgICAgICAgIyBkZWxldGUgYWxsIG9wcyB0aGF0IGRlbGV0ZSB0aGlzIGluc2VydGlvblxuICAgICAgICBmb3IgZCBpbiBAZGVsZXRlZF9ieVxuICAgICAgICAgIGQuY2xlYW51cCgpXG5cbiAgICAgICAgIyB0aHJvdyBuZXcgRXJyb3IgXCJyaWdodCBpcyBub3QgZGVsZXRlZC4gaW5jb25zaXN0ZW5jeSEsIHdyYXJhcmFyXCJcbiAgICAgICAgIyBjaGFuZ2Ugb3JpZ2luIHJlZmVyZW5jZXMgdG8gdGhlIHJpZ2h0XG4gICAgICAgIG8gPSBAbmV4dF9jbFxuICAgICAgICB3aGlsZSBvLnR5cGUgaXNudCBcIkRlbGltaXRlclwiXG4gICAgICAgICAgaWYgby5vcmlnaW4gaXMgQFxuICAgICAgICAgICAgby5vcmlnaW4gPSBAcHJldl9jbFxuICAgICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgIyByZWNvbm5lY3QgbGVmdC9yaWdodFxuICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQG5leHRfY2xcbiAgICAgICAgQG5leHRfY2wucHJldl9jbCA9IEBwcmV2X2NsXG5cbiAgICAgICAgIyBkZWxldGUgY29udGVudFxuICAgICAgICAjIC0gd2UgbXVzdCBub3QgZG8gdGhpcyBpbiBhcHBseURlbGV0ZSwgYmVjYXVzZSB0aGlzIHdvdWxkIGxlYWQgdG8gaW5jb25zaXN0ZW5jaWVzXG4gICAgICAgICMgKGUuZy4gdGhlIGZvbGxvd2luZyBvcGVyYXRpb24gb3JkZXIgbXVzdCBiZSBpbnZlcnRpYmxlIDpcbiAgICAgICAgIyAgIEluc2VydCByZWZlcnMgdG8gY29udGVudCwgdGhlbiB0aGUgY29udGVudCBpcyBkZWxldGVkKVxuICAgICAgICAjIFRoZXJlZm9yZSwgd2UgaGF2ZSB0byBkbyB0aGlzIGluIHRoZSBjbGVhbnVwXG4gICAgICAgICMgKiBOT0RFOiBXZSBuZXZlciBkZWxldGUgSW5zZXJ0aW9ucyFcbiAgICAgICAgaWYgQGNvbnRlbnQgaW5zdGFuY2VvZiBvcHMuT3BlcmF0aW9uIGFuZCBub3QgKEBjb250ZW50IGluc3RhbmNlb2Ygb3BzLkluc2VydClcbiAgICAgICAgICBAY29udGVudC5yZWZlcmVuY2VkX2J5LS1cbiAgICAgICAgICBpZiBAY29udGVudC5yZWZlcmVuY2VkX2J5IDw9IDAgYW5kIG5vdCBAY29udGVudC5pc19kZWxldGVkXG4gICAgICAgICAgICBAY29udGVudC5hcHBseURlbGV0ZSgpXG4gICAgICAgIGRlbGV0ZSBAY29udGVudFxuICAgICAgICBzdXBlclxuICAgICAgIyBlbHNlXG4gICAgICAjICAgU29tZW9uZSBpbnNlcnRlZCBzb21ldGhpbmcgaW4gdGhlIG1lYW50aW1lLlxuICAgICAgIyAgIFJlbWVtYmVyOiB0aGlzIGNhbiBvbmx5IGJlIGdhcmJhZ2UgY29sbGVjdGVkIHdoZW4gbmV4dF9jbCBpcyBkZWxldGVkXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgVGhlIGFtb3VudCBvZiBwb3NpdGlvbnMgdGhhdCAkdGhpcyBvcGVyYXRpb24gd2FzIG1vdmVkIHRvIHRoZSByaWdodC5cbiAgICAjXG4gICAgZ2V0RGlzdGFuY2VUb09yaWdpbjogKCktPlxuICAgICAgZCA9IDBcbiAgICAgIG8gPSBAcHJldl9jbFxuICAgICAgd2hpbGUgdHJ1ZVxuICAgICAgICBpZiBAb3JpZ2luIGlzIG9cbiAgICAgICAgICBicmVha1xuICAgICAgICBkKytcbiAgICAgICAgbyA9IG8ucHJldl9jbFxuICAgICAgZFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIEluY2x1ZGUgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGFzc29jaWF0aXZlIGxpc3RzLlxuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIG5vdCBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIGVsc2VcbiAgICAgICAgaWYgQGNvbnRlbnQgaW5zdGFuY2VvZiBvcHMuT3BlcmF0aW9uXG4gICAgICAgICAgQGNvbnRlbnQuaW5zZXJ0X3BhcmVudCA9IEAgIyBUT0RPOiB0aGlzIGlzIHByb2JhYmx5IG5vdCBuZWNlc3NhcnkgYW5kIG9ubHkgbmljZSBmb3IgZGVidWdnaW5nXG4gICAgICAgICAgQGNvbnRlbnQucmVmZXJlbmNlZF9ieSA/PSAwXG4gICAgICAgICAgQGNvbnRlbnQucmVmZXJlbmNlZF9ieSsrXG4gICAgICAgIGlmIEBwYXJlbnQ/XG4gICAgICAgICAgaWYgbm90IEBwcmV2X2NsP1xuICAgICAgICAgICAgQHByZXZfY2wgPSBAcGFyZW50LmJlZ2lubmluZ1xuICAgICAgICAgIGlmIG5vdCBAb3JpZ2luP1xuICAgICAgICAgICAgQG9yaWdpbiA9IEBwcmV2X2NsXG4gICAgICAgICAgZWxzZSBpZiBAb3JpZ2luIGlzIFwiRGVsaW1pdGVyXCJcbiAgICAgICAgICAgIEBvcmlnaW4gPSBAcGFyZW50LmJlZ2lubmluZ1xuICAgICAgICAgIGlmIG5vdCBAbmV4dF9jbD9cbiAgICAgICAgICAgIEBuZXh0X2NsID0gQHBhcmVudC5lbmRcbiAgICAgICAgaWYgQHByZXZfY2w/XG4gICAgICAgICAgZGlzdGFuY2VfdG9fb3JpZ2luID0gQGdldERpc3RhbmNlVG9PcmlnaW4oKSAjIG1vc3QgY2FzZXM6IDBcbiAgICAgICAgICBvID0gQHByZXZfY2wubmV4dF9jbFxuICAgICAgICAgIGkgPSBkaXN0YW5jZV90b19vcmlnaW4gIyBsb29wIGNvdW50ZXJcblxuICAgICAgICAgICMgJHRoaXMgaGFzIHRvIGZpbmQgYSB1bmlxdWUgcG9zaXRpb24gYmV0d2VlbiBvcmlnaW4gYW5kIHRoZSBuZXh0IGtub3duIGNoYXJhY3RlclxuICAgICAgICAgICMgY2FzZSAxOiAkb3JpZ2luIGVxdWFscyAkby5vcmlnaW46IHRoZSAkY3JlYXRvciBwYXJhbWV0ZXIgZGVjaWRlcyBpZiBsZWZ0IG9yIHJpZ2h0XG4gICAgICAgICAgIyAgICAgICAgIGxldCAkT0w9IFtvMSxvMixvMyxvNF0sIHdoZXJlYnkgJHRoaXMgaXMgdG8gYmUgaW5zZXJ0ZWQgYmV0d2VlbiBvMSBhbmQgbzRcbiAgICAgICAgICAjICAgICAgICAgbzIsbzMgYW5kIG80IG9yaWdpbiBpcyAxICh0aGUgcG9zaXRpb24gb2YgbzIpXG4gICAgICAgICAgIyAgICAgICAgIHRoZXJlIGlzIHRoZSBjYXNlIHRoYXQgJHRoaXMuY3JlYXRvciA8IG8yLmNyZWF0b3IsIGJ1dCBvMy5jcmVhdG9yIDwgJHRoaXMuY3JlYXRvclxuICAgICAgICAgICMgICAgICAgICB0aGVuIG8yIGtub3dzIG8zLiBTaW5jZSBvbiBhbm90aGVyIGNsaWVudCAkT0wgY291bGQgYmUgW28xLG8zLG80XSB0aGUgcHJvYmxlbSBpcyBjb21wbGV4XG4gICAgICAgICAgIyAgICAgICAgIHRoZXJlZm9yZSAkdGhpcyB3b3VsZCBiZSBhbHdheXMgdG8gdGhlIHJpZ2h0IG9mIG8zXG4gICAgICAgICAgIyBjYXNlIDI6ICRvcmlnaW4gPCAkby5vcmlnaW5cbiAgICAgICAgICAjICAgICAgICAgaWYgY3VycmVudCAkdGhpcyBpbnNlcnRfcG9zaXRpb24gPiAkbyBvcmlnaW46ICR0aGlzIGluc1xuICAgICAgICAgICMgICAgICAgICBlbHNlICRpbnNlcnRfcG9zaXRpb24gd2lsbCBub3QgY2hhbmdlXG4gICAgICAgICAgIyAgICAgICAgIChtYXliZSB3ZSBlbmNvdW50ZXIgY2FzZSAxIGxhdGVyLCB0aGVuIHRoaXMgd2lsbCBiZSB0byB0aGUgcmlnaHQgb2YgJG8pXG4gICAgICAgICAgIyBjYXNlIDM6ICRvcmlnaW4gPiAkby5vcmlnaW5cbiAgICAgICAgICAjICAgICAgICAgJHRoaXMgaW5zZXJ0X3Bvc2l0aW9uIGlzIHRvIHRoZSBsZWZ0IG9mICRvIChmb3JldmVyISlcbiAgICAgICAgICB3aGlsZSB0cnVlXG4gICAgICAgICAgICBpZiBvIGlzbnQgQG5leHRfY2xcbiAgICAgICAgICAgICAgb0Rpc3RhbmNlID0gby5nZXREaXN0YW5jZVRvT3JpZ2luKClcbiAgICAgICAgICAgICAgIyAkbyBoYXBwZW5lZCBjb25jdXJyZW50bHlcbiAgICAgICAgICAgICAgaWYgb0Rpc3RhbmNlIGlzIGlcbiAgICAgICAgICAgICAgICAjIGNhc2UgMVxuICAgICAgICAgICAgICAgIGlmIG8udWlkLmNyZWF0b3IgPCBAdWlkLmNyZWF0b3JcbiAgICAgICAgICAgICAgICAgIEBwcmV2X2NsID0gb1xuICAgICAgICAgICAgICAgICAgZGlzdGFuY2VfdG9fb3JpZ2luID0gaSArIDFcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAjIG5vcFxuICAgICAgICAgICAgICBlbHNlIGlmIG9EaXN0YW5jZSA8IGlcbiAgICAgICAgICAgICAgICAjIGNhc2UgMlxuICAgICAgICAgICAgICAgIGlmIGkgLSBkaXN0YW5jZV90b19vcmlnaW4gPD0gb0Rpc3RhbmNlXG4gICAgICAgICAgICAgICAgICBAcHJldl9jbCA9IG9cbiAgICAgICAgICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IGkgKyAxXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgI25vcFxuICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgIyBjYXNlIDNcbiAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICBpKytcbiAgICAgICAgICAgICAgbyA9IG8ubmV4dF9jbFxuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAjICR0aGlzIGtub3dzIHRoYXQgJG8gZXhpc3RzLFxuICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICMgbm93IHJlY29ubmVjdCBldmVyeXRoaW5nXG4gICAgICAgICAgQG5leHRfY2wgPSBAcHJldl9jbC5uZXh0X2NsXG4gICAgICAgICAgQHByZXZfY2wubmV4dF9jbCA9IEBcbiAgICAgICAgICBAbmV4dF9jbC5wcmV2X2NsID0gQFxuXG4gICAgICAgIEBzZXRQYXJlbnQgQHByZXZfY2wuZ2V0UGFyZW50KCkgIyBkbyBJbnNlcnRpb25zIGFsd2F5cyBoYXZlIGEgcGFyZW50P1xuICAgICAgICBzdXBlciAjIG5vdGlmeSB0aGUgZXhlY3V0aW9uX2xpc3RlbmVyc1xuICAgICAgICBAcGFyZW50LmNhbGxPcGVyYXRpb25TcGVjaWZpY0luc2VydEV2ZW50cyh0aGlzKVxuICAgICAgICBAXG5cbiAgICAjXG4gICAgIyBDb21wdXRlIHRoZSBwb3NpdGlvbiBvZiB0aGlzIG9wZXJhdGlvbi5cbiAgICAjXG4gICAgZ2V0UG9zaXRpb246ICgpLT5cbiAgICAgIHBvc2l0aW9uID0gMFxuICAgICAgcHJldiA9IEBwcmV2X2NsXG4gICAgICB3aGlsZSB0cnVlXG4gICAgICAgIGlmIHByZXYgaW5zdGFuY2VvZiBvcHMuRGVsaW1pdGVyXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgaWYgbm90IHByZXYuaXNEZWxldGVkKClcbiAgICAgICAgICBwb3NpdGlvbisrXG4gICAgICAgIHByZXYgPSBwcmV2LnByZXZfY2xcbiAgICAgIHBvc2l0aW9uXG5cbiAgICAjXG4gICAgIyBDb252ZXJ0IGFsbCByZWxldmFudCBpbmZvcm1hdGlvbiBvZiB0aGlzIG9wZXJhdGlvbiB0byB0aGUganNvbi1mb3JtYXQuXG4gICAgIyBUaGlzIHJlc3VsdCBjYW4gYmUgc2VuZCB0byBvdGhlciBjbGllbnRzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoanNvbiA9IHt9KS0+XG4gICAgICBqc29uLnByZXYgPSBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAganNvbi5uZXh0ID0gQG5leHRfY2wuZ2V0VWlkKClcblxuICAgICAgaWYgQG9yaWdpbi50eXBlIGlzIFwiRGVsaW1pdGVyXCJcbiAgICAgICAganNvbi5vcmlnaW4gPSBcIkRlbGltaXRlclwiXG4gICAgICBlbHNlIGlmIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uLm9yaWdpbiA9IEBvcmlnaW4uZ2V0VWlkKClcblxuICAgICAgIyBpZiBub3QgKGpzb24ucHJldj8gYW5kIGpzb24ubmV4dD8pXG4gICAgICBqc29uLnBhcmVudCA9IEBwYXJlbnQuZ2V0VWlkKClcblxuICAgICAgc3VwZXIganNvblxuXG4gIG9wcy5JbnNlcnQucGFyc2UgPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICdjb250ZW50X29wZXJhdGlvbnMnIDogY29udGVudF9vcGVyYXRpb25zXG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ3ByZXYnOiBwcmV2XG4gICAgICAnbmV4dCc6IG5leHRcbiAgICAgICdvcmlnaW4nIDogb3JpZ2luXG4gICAgICAncGFyZW50JyA6IHBhcmVudFxuICAgIH0gPSBqc29uXG4gICAgbmV3IHRoaXMgbnVsbCwgY29udGVudCwgY29udGVudF9vcGVyYXRpb25zLCBwYXJlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cbiAgI1xuICAjIEBub2RvY1xuICAjIEEgZGVsaW1pdGVyIGlzIHBsYWNlZCBhdCB0aGUgZW5kIGFuZCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBhc3NvY2lhdGl2ZSBsaXN0cy5cbiAgIyBUaGlzIGlzIG5lY2Vzc2FyeSBpbiBvcmRlciB0byBoYXZlIGEgYmVnaW5uaW5nIGFuZCBhbiBlbmQgZXZlbiBpZiB0aGUgY29udGVudFxuICAjIG9mIHRoZSBFbmdpbmUgaXMgZW1wdHkuXG4gICNcbiAgY2xhc3Mgb3BzLkRlbGltaXRlciBleHRlbmRzIG9wcy5PcGVyYXRpb25cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gcHJldl9jbCBUaGUgcHJlZGVjZXNzb3Igb2YgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGNvbXBsZXRlLWxpc3QgKGNsKVxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG5leHRfY2wgVGhlIHN1Y2Nlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAocHJldl9jbCwgbmV4dF9jbCwgb3JpZ2luKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncHJldl9jbCcsIHByZXZfY2xcbiAgICAgIEBzYXZlT3BlcmF0aW9uICduZXh0X2NsJywgbmV4dF9jbFxuICAgICAgQHNhdmVPcGVyYXRpb24gJ29yaWdpbicsIHByZXZfY2xcbiAgICAgIHN1cGVyIG51bGwsIHtub09wZXJhdGlvbjogdHJ1ZX1cblxuICAgIHR5cGU6IFwiRGVsaW1pdGVyXCJcblxuICAgIGFwcGx5RGVsZXRlOiAoKS0+XG4gICAgICBzdXBlcigpXG4gICAgICBvID0gQHByZXZfY2xcbiAgICAgIHdoaWxlIG8/XG4gICAgICAgIG8uYXBwbHlEZWxldGUoKVxuICAgICAgICBvID0gby5wcmV2X2NsXG4gICAgICB1bmRlZmluZWRcblxuICAgIGNsZWFudXA6ICgpLT5cbiAgICAgIHN1cGVyKClcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEB1bmNoZWNrZWQ/WyduZXh0X2NsJ10/XG4gICAgICAgIHN1cGVyXG4gICAgICBlbHNlIGlmIEB1bmNoZWNrZWQ/WydwcmV2X2NsJ11cbiAgICAgICAgaWYgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgICBpZiBAcHJldl9jbC5uZXh0X2NsP1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiUHJvYmFibHkgZHVwbGljYXRlZCBvcGVyYXRpb25zXCJcbiAgICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxuICAgICAgICAgIHN1cGVyXG4gICAgICAgIGVsc2VcbiAgICAgICAgICBmYWxzZVxuICAgICAgZWxzZSBpZiBAcHJldl9jbD8gYW5kIG5vdCBAcHJldl9jbC5uZXh0X2NsP1xuICAgICAgICBkZWxldGUgQHByZXZfY2wudW5jaGVja2VkLm5leHRfY2xcbiAgICAgICAgQHByZXZfY2wubmV4dF9jbCA9IEBcbiAgICAgICAgc3VwZXJcbiAgICAgIGVsc2UgaWYgQHByZXZfY2w/IG9yIEBuZXh0X2NsPyBvciB0cnVlICMgVE9ETzogYXJlIHlvdSBzdXJlPyBUaGlzIGNhbiBoYXBwZW4gcmlnaHQ/XG4gICAgICAgIHN1cGVyXG4gICAgICAjZWxzZVxuICAgICAgIyAgdGhyb3cgbmV3IEVycm9yIFwiRGVsaW1pdGVyIGlzIHVuc3VmZmljaWVudCBkZWZpbmVkIVwiXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICB7XG4gICAgICAgICd0eXBlJyA6IEB0eXBlXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICdwcmV2JyA6IEBwcmV2X2NsPy5nZXRVaWQoKVxuICAgICAgICAnbmV4dCcgOiBAbmV4dF9jbD8uZ2V0VWlkKClcbiAgICAgIH1cblxuICBvcHMuRGVsaW1pdGVyLnBhcnNlID0gKGpzb24pLT5cbiAgICB7XG4gICAgJ3VpZCcgOiB1aWRcbiAgICAncHJldicgOiBwcmV2XG4gICAgJ25leHQnIDogbmV4dFxuICAgIH0gPSBqc29uXG4gICAgbmV3IHRoaXModWlkLCBwcmV2LCBuZXh0KVxuXG4gICMgVGhpcyBpcyB3aGF0IHRoaXMgbW9kdWxlIGV4cG9ydHMgYWZ0ZXIgaW5pdGlhbGl6aW5nIGl0IHdpdGggdGhlIEhpc3RvcnlCdWZmZXJcbiAge1xuICAgICdvcGVyYXRpb25zJyA6IG9wc1xuICAgICdleGVjdXRpb25fbGlzdGVuZXInIDogZXhlY3V0aW9uX2xpc3RlbmVyXG4gIH1cbiIsImJhc2ljX29wc191bmluaXRpYWxpemVkID0gcmVxdWlyZSBcIi4vQmFzaWNcIlxuUkJUUmVlQnlJbmRleCA9IHJlcXVpcmUgJ2JpbnRyZWVzL2xpYi9yYnRyZWVfYnlfaW5kZXgnXG5cbm1vZHVsZS5leHBvcnRzID0gKCktPlxuICBiYXNpY19vcHMgPSBiYXNpY19vcHNfdW5pbml0aWFsaXplZCgpXG4gIG9wcyA9IGJhc2ljX29wcy5vcGVyYXRpb25zXG5cbiAgI1xuICAjIEBub2RvY1xuICAjIE1hbmFnZXMgbWFwIGxpa2Ugb2JqZWN0cy4gRS5nLiBKc29uLVR5cGUgYW5kIFhNTCBhdHRyaWJ1dGVzLlxuICAjXG4gIGNsYXNzIG9wcy5NYXBNYW5hZ2VyIGV4dGVuZHMgb3BzLk9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKGN1c3RvbV90eXBlLCB1aWQsIGNvbnRlbnQsIGNvbnRlbnRfb3BlcmF0aW9ucyktPlxuICAgICAgQF9tYXAgPSB7fVxuICAgICAgc3VwZXIgY3VzdG9tX3R5cGUsIHVpZCwgY29udGVudCwgY29udGVudF9vcGVyYXRpb25zXG5cbiAgICB0eXBlOiBcIk1hcE1hbmFnZXJcIlxuXG4gICAgYXBwbHlEZWxldGU6ICgpLT5cbiAgICAgIGZvciBuYW1lLHAgb2YgQF9tYXBcbiAgICAgICAgcC5hcHBseURlbGV0ZSgpXG4gICAgICBzdXBlcigpXG5cbiAgICBjbGVhbnVwOiAoKS0+XG4gICAgICBzdXBlcigpXG5cbiAgICBtYXA6IChmKS0+XG4gICAgICBmb3Igbix2IG9mIEBfbWFwXG4gICAgICAgIGYobix2KVxuICAgICAgdW5kZWZpbmVkXG5cbiAgICAjXG4gICAgIyBAc2VlIEpzb25PcGVyYXRpb25zLnZhbFxuICAgICNcbiAgICB2YWw6IChuYW1lLCBjb250ZW50KS0+XG4gICAgICBpZiBhcmd1bWVudHMubGVuZ3RoID4gMVxuICAgICAgICBpZiBjb250ZW50PyBhbmQgY29udGVudC5fZ2V0TW9kZWw/XG4gICAgICAgICAgcmVwID0gY29udGVudC5fZ2V0TW9kZWwoQGN1c3RvbV90eXBlcywgQG9wZXJhdGlvbnMpXG4gICAgICAgIGVsc2VcbiAgICAgICAgICByZXAgPSBjb250ZW50XG4gICAgICAgIEByZXRyaWV2ZVN1YihuYW1lKS5yZXBsYWNlIHJlcFxuICAgICAgICBAZ2V0Q3VzdG9tVHlwZSgpXG4gICAgICBlbHNlIGlmIG5hbWU/XG4gICAgICAgIHByb3AgPSBAX21hcFtuYW1lXVxuICAgICAgICBpZiBwcm9wPyBhbmQgbm90IHByb3AuaXNDb250ZW50RGVsZXRlZCgpXG4gICAgICAgICAgcmVzID0gcHJvcC52YWwoKVxuICAgICAgICAgIGlmIHJlcyBpbnN0YW5jZW9mIG9wcy5PcGVyYXRpb25cbiAgICAgICAgICAgIHJlcy5nZXRDdXN0b21UeXBlKClcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICByZXNcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHVuZGVmaW5lZFxuICAgICAgZWxzZVxuICAgICAgICByZXN1bHQgPSB7fVxuICAgICAgICBmb3IgbmFtZSxvIG9mIEBfbWFwXG4gICAgICAgICAgaWYgbm90IG8uaXNDb250ZW50RGVsZXRlZCgpXG4gICAgICAgICAgICByZXN1bHRbbmFtZV0gPSBvLnZhbCgpXG4gICAgICAgIHJlc3VsdFxuXG4gICAgZGVsZXRlOiAobmFtZSktPlxuICAgICAgQF9tYXBbbmFtZV0/LmRlbGV0ZUNvbnRlbnQoKVxuICAgICAgQFxuXG4gICAgcmV0cmlldmVTdWI6IChwcm9wZXJ0eV9uYW1lKS0+XG4gICAgICBpZiBub3QgQF9tYXBbcHJvcGVydHlfbmFtZV0/XG4gICAgICAgIGV2ZW50X3Byb3BlcnRpZXMgPVxuICAgICAgICAgIG5hbWU6IHByb3BlcnR5X25hbWVcbiAgICAgICAgZXZlbnRfdGhpcyA9IEBcbiAgICAgICAgcm1fdWlkID1cbiAgICAgICAgICBub09wZXJhdGlvbjogdHJ1ZVxuICAgICAgICAgIHN1YjogcHJvcGVydHlfbmFtZVxuICAgICAgICAgIGFsdDogQFxuICAgICAgICBybSA9IG5ldyBvcHMuUmVwbGFjZU1hbmFnZXIgbnVsbCwgZXZlbnRfcHJvcGVydGllcywgZXZlbnRfdGhpcywgcm1fdWlkICMgdGhpcyBvcGVyYXRpb24gc2hhbGwgbm90IGJlIHNhdmVkIGluIHRoZSBIQlxuICAgICAgICBAX21hcFtwcm9wZXJ0eV9uYW1lXSA9IHJtXG4gICAgICAgIHJtLnNldFBhcmVudCBALCBwcm9wZXJ0eV9uYW1lXG4gICAgICAgIHJtLmV4ZWN1dGUoKVxuICAgICAgQF9tYXBbcHJvcGVydHlfbmFtZV1cblxuICBvcHMuTWFwTWFuYWdlci5wYXJzZSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdjdXN0b21fdHlwZScgOiBjdXN0b21fdHlwZVxuICAgICAgJ2NvbnRlbnQnIDogY29udGVudFxuICAgICAgJ2NvbnRlbnRfb3BlcmF0aW9ucycgOiBjb250ZW50X29wZXJhdGlvbnNcbiAgICB9ID0ganNvblxuICAgIG5ldyB0aGlzKGN1c3RvbV90eXBlLCB1aWQsIGNvbnRlbnQsIGNvbnRlbnRfb3BlcmF0aW9ucylcblxuXG5cbiAgI1xuICAjIEBub2RvY1xuICAjIE1hbmFnZXMgYSBsaXN0IG9mIEluc2VydC10eXBlIG9wZXJhdGlvbnMuXG4gICNcbiAgY2xhc3Mgb3BzLkxpc3RNYW5hZ2VyIGV4dGVuZHMgb3BzLk9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQSBMaXN0TWFuYWdlciBtYWludGFpbnMgYSBub24tZW1wdHkgbGlzdCB0aGF0IGhhcyBhIGJlZ2lubmluZyBhbmQgYW4gZW5kIChib3RoIERlbGltaXRlcnMhKVxuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGJlZ2lubmluZyBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGVuZCBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxuICAgIGNvbnN0cnVjdG9yOiAoY3VzdG9tX3R5cGUsIHVpZCwgY29udGVudCwgY29udGVudF9vcGVyYXRpb25zKS0+XG4gICAgICBAYmVnaW5uaW5nID0gbmV3IG9wcy5EZWxpbWl0ZXIgdW5kZWZpbmVkLCB1bmRlZmluZWRcbiAgICAgIEBlbmQgPSAgICAgICBuZXcgb3BzLkRlbGltaXRlciBAYmVnaW5uaW5nLCB1bmRlZmluZWRcbiAgICAgIEBiZWdpbm5pbmcubmV4dF9jbCA9IEBlbmRcbiAgICAgIEBiZWdpbm5pbmcuZXhlY3V0ZSgpXG4gICAgICBAZW5kLmV4ZWN1dGUoKVxuXG5cbiAgICAgICMgVGhlIHNob3J0IHRyZWUgaXMgc3RvcmluZyB0aGUgbm9uIGRlbGV0ZWQgb3BlcmF0aW9uc1xuICAgICAgQHNob3J0VHJlZSA9IG5ldyBSQlRyZWVCeUluZGV4KClcbiAgICAgICMgVGhlIGNvbXBsZXRlIHRyZWUgaXMgc3RvcmluZyBhbGwgdGhlIG9wZXJhdGlvbnNcbiAgICAgIEBjb21wbGV0ZVRyZWUgPSBuZXcgUkJUcmVlQnlJbmRleCgpXG5cbiAgICAgIHN1cGVyIGN1c3RvbV90eXBlLCB1aWQsIGNvbnRlbnQsIGNvbnRlbnRfb3BlcmF0aW9uc1xuXG4gICAgdHlwZTogXCJMaXN0TWFuYWdlclwiXG5cblxuICAgIGFwcGx5RGVsZXRlOiAoKS0+XG4gICAgICBvID0gQGJlZ2lubmluZ1xuICAgICAgd2hpbGUgbz9cbiAgICAgICAgby5hcHBseURlbGV0ZSgpXG4gICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgIHN1cGVyKClcblxuICAgIGNsZWFudXA6ICgpLT5cbiAgICAgIHN1cGVyKClcblxuXG4gICAgdG9Kc29uOiAodHJhbnNmb3JtX3RvX3ZhbHVlID0gZmFsc2UpLT5cbiAgICAgIHZhbCA9IEB2YWwoKVxuICAgICAgZm9yIGksIG8gaW4gdmFsXG4gICAgICAgIGlmIG8gaW5zdGFuY2VvZiBvcHMuT2JqZWN0XG4gICAgICAgICAgby50b0pzb24odHJhbnNmb3JtX3RvX3ZhbHVlKVxuICAgICAgICBlbHNlIGlmIG8gaW5zdGFuY2VvZiBvcHMuTGlzdE1hbmFnZXJcbiAgICAgICAgICBvLnRvSnNvbih0cmFuc2Zvcm1fdG9fdmFsdWUpXG4gICAgICAgIGVsc2UgaWYgdHJhbnNmb3JtX3RvX3ZhbHVlIGFuZCBvIGluc3RhbmNlb2Ygb3BzLk9wZXJhdGlvblxuICAgICAgICAgIG8udmFsKClcbiAgICAgICAgZWxzZVxuICAgICAgICAgIG9cblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBAc2VlIE9wZXJhdGlvbi5leGVjdXRlXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIEBiZWdpbm5pbmcuc2V0UGFyZW50IEBcbiAgICAgICAgQGVuZC5zZXRQYXJlbnQgQFxuICAgICAgICBzdXBlclxuICAgICAgZWxzZVxuICAgICAgICBmYWxzZVxuXG4gICAgIyBHZXQgdGhlIGVsZW1lbnQgcHJldmlvdXMgdG8gdGhlIGRlbGVtaXRlciBhdCB0aGUgZW5kXG4gICAgZ2V0TGFzdE9wZXJhdGlvbjogKCktPlxuICAgICAgQGVuZC5wcmV2X2NsXG5cbiAgICAjIHNpbWlsYXIgdG8gdGhlIGFib3ZlXG4gICAgZ2V0Rmlyc3RPcGVyYXRpb246ICgpLT5cbiAgICAgIEBiZWdpbm5pbmcubmV4dF9jbFxuXG4gICAgIyBnZXQgdGhlIG5leHQgbm9uLWRlbGV0ZWQgb3BlcmF0aW9uXG4gICAgZ2V0TmV4dE5vbkRlbGV0ZWQ6IChzdGFydCktPlxuICAgICAgaWYgc3RhcnQuaXNEZWxldGVkKCkgb3Igbm90IHN0YXJ0Lm5vZGU/XG4gICAgICAgIG9wZXJhdGlvbiA9IHN0YXJ0Lm5leHRfY2xcbiAgICAgICAgd2hpbGUgbm90ICgob3BlcmF0aW9uIGluc3RhbmNlb2Ygb3BzLkRlbGltaXRlcikpXG4gICAgICAgICAgaWYgb3BlcmF0aW9uLmlzX2RlbGV0ZWRcbiAgICAgICAgICAgIG9wZXJhdGlvbiA9IG9wZXJhdGlvbi5uZXh0X2NsXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgYnJlYWtcbiAgICAgIGVsc2VcbiAgICAgICAgb3BlcmF0aW9uID0gc3RhcnQubm9kZS5uZXh0Lm5vZGVcbiAgICAgICAgaWYgbm90IG9wZXJhdGlvblxuICAgICAgICAgIHJldHVybiBmYWxzZVxuXG4gICAgICBvcGVyYXRpb25cblxuICAgIGdldFByZXZOb25EZWxldGVkOiAoc3RhcnQpIC0+XG4gICAgICBpZiBzdGFydC5pc0RlbGV0ZWQoKSBvciBub3Qgc3RhcnQubm9kZT9cbiAgICAgICAgb3BlcmF0aW9uID0gc3RhcnQucHJldl9jbFxuICAgICAgICB3aGlsZSBub3QgKChvcGVyYXRpb24gaW5zdGFuY2VvZiBvcHMuRGVsaW1pdGVyKSlcbiAgICAgICAgICBpZiBvcGVyYXRpb24uaXNfZGVsZXRlZFxuICAgICAgICAgICAgb3BlcmF0aW9uID0gb3BlcmF0aW9uLnByZXZfY2xcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBicmVha1xuICAgICAgZWxzZVxuICAgICAgICBvcGVyYXRpb24gPSBzdGFydC5ub2RlLnByZXYubm9kZVxuICAgICAgICBpZiBub3Qgb3BlcmF0aW9uXG4gICAgICAgICAgcmV0dXJuIGZhbHNlXG5cbiAgICAgIG9wZXJhdGlvblxuXG5cbiAgICAjIFRyYW5zZm9ybXMgdGhlIGxpc3QgdG8gYW4gYXJyYXlcbiAgICAjIERvZXNuJ3QgcmV0dXJuIGxlZnQtcmlnaHQgZGVsaW1pdGVyLlxuICAgIHRvQXJyYXk6ICgpLT5cbiAgICAgIEBzaG9ydFRyZWUubWFwIChvcGVyYXRpb24pIC0+XG4gICAgICAgIG9wZXJhdGlvbi52YWwoKVxuXG4gICAgbWFwOiAoZnVuKS0+XG4gICAgICBAc2hvcnRUcmVlLm1hcCBmdW5cblxuICAgIGZvbGQ6IChpbml0LCBmdW4pLT5cbiAgICAgIEBzaG9ydFRyZWUubWFwIChvcGVyYXRpb24pIC0+XG4gICAgICAgIGluaXQgPSBmdW4oaW5pdCwgb3BlcmF0aW9uKVxuXG4gICAgdmFsOiAocG9zKS0+XG4gICAgICBpZiBwb3M/XG4gICAgICAgIEBzaG9ydFRyZWUuZmluZChwb3MpLnZhbCgpXG4gICAgICBlbHNlXG4gICAgICAgIEB0b0FycmF5KClcblxuICAgIHJlZjogKHBvcyktPlxuICAgICAgaWYgcG9zP1xuICAgICAgICBAc2hvcnRUcmVlLmZpbmQocG9zKVxuICAgICAgZWxzZVxuICAgICAgICBAc2hvcnRUcmVlLm1hcCAob3BlcmF0aW9uKSAtPlxuICAgICAgICAgIG9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgUmV0cmlldmVzIHRoZSB4LXRoIG5vdCBkZWxldGVkIGVsZW1lbnQuXG4gICAgIyBlLmcuIFwiYWJjXCIgOiB0aGUgMXRoIGNoYXJhY3RlciBpcyBcImFcIlxuICAgICMgdGhlIDB0aCBjaGFyYWN0ZXIgaXMgdGhlIGxlZnQgRGVsaW1pdGVyXG4gICAgI1xuICAgIGdldE9wZXJhdGlvbkJ5UG9zaXRpb246IChwb3NpdGlvbiktPlxuICAgICAgaWYgcG9zaXRpb24gPT0gMFxuICAgICAgICBAYmVnaW5uaW5nXG4gICAgICBlbHNlIGlmIHBvc2l0aW9uID09IEBzaG9ydFRyZWUuc2l6ZSArIDFcbiAgICAgICAgQGVuZFxuICAgICAgZWxzZVxuICAgICAgICBAc2hvcnRUcmVlLmZpbmQgKHBvc2l0aW9uLTEpXG5cbiAgICBwdXNoOiAoY29udGVudCktPlxuICAgICAgQGluc2VydEFmdGVyIEBlbmQucHJldl9jbCwgW2NvbnRlbnRdXG5cbiAgICBpbnNlcnRBZnRlckhlbHBlcjogKHJvb3QsIGNvbnRlbnQpLT5cbiAgICAgIGlmICFyb290LnJpZ2h0XG4gICAgICAgIHJvb3QuYnQucmlnaHQgPSBjb250ZW50XG4gICAgICAgIGNvbnRlbnQuYnQucGFyZW50ID0gcm9vdFxuICAgICAgZWxzZVxuICAgICAgICByaWdodCA9IHJvb3QubmV4dF9jbFxuXG5cbiAgICBpbnNlcnRBZnRlcjogKGxlZnQsIGNvbnRlbnRzKS0+XG4gICAgICBpZiBsZWZ0IGlzIEBiZWdpbm5pbmdcbiAgICAgICAgbGVmdE5vZGUgPSBudWxsXG4gICAgICAgIHJpZ2h0Tm9kZSA9IEBzaG9ydFRyZWUuZmluZE5vZGUgMFxuICAgICAgICByaWdodCA9IGlmIHJpZ2h0Tm9kZSB0aGVuIHJpZ2h0Tm9kZS5kYXRhIGVsc2UgQGVuZFxuICAgICAgZWxzZVxuICAgICAgICAjIGxlZnQubm9kZSBzaG91bGQgYWx3YXlzIGV4aXN0IChpbnNlcnQgYWZ0ZXIgYSBub24tZGVsZXRlZCBlbGVtZW50KVxuICAgICAgICByaWdodE5vZGUgPSBsZWZ0Lm5vZGUubmV4dFxuICAgICAgICBsZWZ0Tm9kZSA9IGxlZnQubm9kZVxuICAgICAgICByaWdodCA9IGlmIHJpZ2h0Tm9kZSB0aGVuIHJpZ2h0Tm9kZS5kYXRhIGVsc2UgQGVuZFxuXG4gICAgICBsZWZ0ID0gcmlnaHQucHJldl9jbFxuXG4gICAgICAjIFRPRE86IGFsd2F5cyBleHBlY3QgYW4gYXJyYXkgYXMgY29udGVudC4gVGhlbiB5b3UgY2FuIGNvbWJpbmUgdGhpcyB3aXRoIHRoZSBvdGhlciBvcHRpb24gKGVsc2UpXG4gICAgICBpZiBjb250ZW50cyBpbnN0YW5jZW9mIG9wcy5PcGVyYXRpb25cbiAgICAgICAgdG1wID0gbmV3IG9wcy5JbnNlcnQgbnVsbCwgY29udGVudCwgbnVsbCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIGxlZnQsIHJpZ2h0XG4gICAgICAgIHRtcC5leGVjdXRlKClcbiAgICAgIGVsc2VcbiAgICAgICAgZm9yIGMgaW4gY29udGVudHNcbiAgICAgICAgICBpZiBjPyBhbmQgYy5fbmFtZT8gYW5kIGMuX2dldE1vZGVsP1xuICAgICAgICAgICAgYyA9IGMuX2dldE1vZGVsKEBjdXN0b21fdHlwZXMsIEBvcGVyYXRpb25zKVxuICAgICAgICAgIHRtcCA9IG5ldyBvcHMuSW5zZXJ0IG51bGwsIGMsIG51bGwsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBsZWZ0LCByaWdodFxuICAgICAgICAgIHRtcC5leGVjdXRlKClcbiAgICAgICAgICBsZWZ0Tm9kZSA9IHRtcC5ub2RlXG5cbiAgICAgICAgICBsZWZ0ID0gdG1wXG4gICAgICBAXG5cbiAgICAjXG4gICAgIyBJbnNlcnRzIGFuIGFycmF5IG9mIGNvbnRlbnQgaW50byB0aGlzIGxpc3QuXG4gICAgIyBATm90ZTogVGhpcyBleHBlY3RzIGFuIGFycmF5IGFzIGNvbnRlbnQhXG4gICAgI1xuICAgICMgQHJldHVybiB7TGlzdE1hbmFnZXIgVHlwZX0gVGhpcyBTdHJpbmcgb2JqZWN0LlxuICAgICNcbiAgICBpbnNlcnQ6IChwb3NpdGlvbiwgY29udGVudHMpLT5cbiAgICAgIGl0aCA9IEBnZXRPcGVyYXRpb25CeVBvc2l0aW9uIHBvc2l0aW9uXG4gICAgICAjIHRoZSAoaS0xKXRoIGNoYXJhY3Rlci4gZS5nLiBcImFiY1wiIHRoZSAxdGggY2hhcmFjdGVyIGlzIFwiYVwiXG4gICAgICAjIHRoZSAwdGggY2hhcmFjdGVyIGlzIHRoZSBsZWZ0IERlbGltaXRlclxuICAgICAgQGluc2VydEFmdGVyIGl0aCwgY29udGVudHNcblxuICAgICNcbiAgICAjIERlbGV0ZXMgYSBwYXJ0IG9mIHRoZSB3b3JkLlxuICAgICNcbiAgICAjIEByZXR1cm4ge0xpc3RNYW5hZ2VyIFR5cGV9IFRoaXMgU3RyaW5nIG9iamVjdFxuICAgICNcbiAgICBkZWxldGVSZWY6IChvcGVyYXRpb24sIGxlbmd0aCA9IDEsIGRpciA9ICdyaWdodCcpIC0+XG4gICAgICBuZXh0T3BlcmF0aW9uID0gKG9wZXJhdGlvbikgPT5cbiAgICAgICAgaWYgZGlyID09ICdyaWdodCcgdGhlbiBAZ2V0TmV4dE5vbkRlbGV0ZWQgb3BlcmF0aW9uIGVsc2UgQGdldFByZXZOb25EZWxldGVkIG9wZXJhdGlvblxuXG4gICAgICBmb3IgaSBpbiBbMC4uLmxlbmd0aF1cbiAgICAgICAgaWYgb3BlcmF0aW9uIGluc3RhbmNlb2Ygb3BzLkRlbGltaXRlclxuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGRlbGV0ZU9wZXJhdGlvbiA9IChuZXcgb3BzLkRlbGV0ZSBudWxsLCB1bmRlZmluZWQsIG9wZXJhdGlvbikuZXhlY3V0ZSgpXG5cbiAgICAgICAgb3BlcmF0aW9uID0gbmV4dE9wZXJhdGlvbiBvcGVyYXRpb25cbiAgICAgIEBcblxuICAgIGRlbGV0ZTogKHBvc2l0aW9uLCBsZW5ndGggPSAxKS0+XG4gICAgICBvcGVyYXRpb24gPSBAZ2V0T3BlcmF0aW9uQnlQb3NpdGlvbihwb3NpdGlvbitsZW5ndGgpICMgcG9zaXRpb24gMCBpbiB0aGlzIGNhc2UgaXMgdGhlIGRlbGV0aW9uIG9mIHRoZSBmaXJzdCBjaGFyYWN0ZXJcblxuICAgICAgQGRlbGV0ZVJlZiBvcGVyYXRpb24sIGxlbmd0aCwgJ2xlZnQnXG5cblxuICAgIGNhbGxPcGVyYXRpb25TcGVjaWZpY0luc2VydEV2ZW50czogKG9wZXJhdGlvbiktPlxuICAgICAgcHJldiA9IChAZ2V0UHJldk5vbkRlbGV0ZWQgb3BlcmF0aW9uKSBvciBAYmVnaW5uaW5nXG4gICAgICBwcmV2Tm9kZSA9IGlmIHByZXYgdGhlbiBwcmV2Lm5vZGUgZWxzZSBudWxsXG5cbiAgICAgIG5leHQgPSAoQGdldE5leHROb25EZWxldGVkIG9wZXJhdGlvbikgb3IgQGVuZFxuICAgICAgbmV4dE5vZGUgPSBpZiBuZXh0IHRoZW4gbmV4dC5ub2RlIGVsc2UgbnVsbFxuICAgICAgb3BlcmF0aW9uLm5vZGUgPSBvcGVyYXRpb24ubm9kZSBvciAoQHNob3J0VHJlZS5pbnNlcnRfYmV0d2VlbiBwcmV2Tm9kZSwgbmV4dE5vZGUsIG9wZXJhdGlvbilcbiAgICAgIG9wZXJhdGlvbi5jb21wbGV0ZU5vZGUgPSBvcGVyYXRpb24uY29tcGxldGVOb2RlIG9yIChAY29tcGxldGVUcmVlLmluc2VydF9iZXR3ZWVuIG9wZXJhdGlvbi5wcmV2X2NsLmNvbXBsZXRlTm9kZSwgb3BlcmF0aW9uLm5leHRfY2wuY29tcGxldGVOb2RlLCBvcGVyYXRpb24pXG5cbiAgICAgIGdldENvbnRlbnRUeXBlID0gKGNvbnRlbnQpLT5cbiAgICAgICAgaWYgY29udGVudCBpbnN0YW5jZW9mIG9wcy5PcGVyYXRpb25cbiAgICAgICAgICBjb250ZW50LmdldEN1c3RvbVR5cGUoKVxuICAgICAgICBlbHNlXG4gICAgICAgICAgY29udGVudFxuXG4gICAgICBAY2FsbEV2ZW50IFtcbiAgICAgICAgdHlwZTogXCJpbnNlcnRcIlxuICAgICAgICByZWZlcmVuY2U6IG9wZXJhdGlvblxuICAgICAgICBwb3NpdGlvbjogb3BlcmF0aW9uLm5vZGUucG9zaXRpb24oKVxuICAgICAgICBvYmplY3Q6IEBnZXRDdXN0b21UeXBlKClcbiAgICAgICAgY2hhbmdlZEJ5OiBvcGVyYXRpb24udWlkLmNyZWF0b3JcbiAgICAgICAgdmFsdWU6IGdldENvbnRlbnRUeXBlIG9wZXJhdGlvbi52YWwoKVxuICAgICAgXVxuXG4gICAgY2FsbE9wZXJhdGlvblNwZWNpZmljRGVsZXRlRXZlbnRzOiAob3BlcmF0aW9uLCBkZWxfb3ApLT5cbiAgICAgIGlmIG9wZXJhdGlvbi5ub2RlXG4gICAgICAgIHBvc2l0aW9uID0gb3BlcmF0aW9uLm5vZGUucG9zaXRpb24oKVxuICAgICAgICBAc2hvcnRUcmVlLnJlbW92ZV9ub2RlIG9wZXJhdGlvbi5ub2RlXG4gICAgICAgIG9wZXJhdGlvbi5ub2RlID0gbnVsbFxuXG4gICAgICBAY2FsbEV2ZW50IFtcbiAgICAgICAgdHlwZTogXCJkZWxldGVcIlxuICAgICAgICByZWZlcmVuY2U6IG9wZXJhdGlvblxuICAgICAgICBwb3NpdGlvbjogcG9zaXRpb25cbiAgICAgICAgb2JqZWN0OiBAZ2V0Q3VzdG9tVHlwZSgpICMgVE9ETzogWW91IGNhbiBjb21iaW5lIGdldFBvc2l0aW9uICsgZ2V0UGFyZW50IGluIGEgbW9yZSBlZmZpY2llbnQgbWFubmVyISAob25seSBsZWZ0IERlbGltaXRlciB3aWxsIGhvbGQgQHBhcmVudClcbiAgICAgICAgbGVuZ3RoOiAxXG4gICAgICAgIGNoYW5nZWRCeTogZGVsX29wLnVpZC5jcmVhdG9yXG4gICAgICAgIG9sZFZhbHVlOiBvcGVyYXRpb24udmFsKClcbiAgICAgIF1cblxuICBvcHMuTGlzdE1hbmFnZXIucGFyc2UgPSAoanNvbiktPlxuICAgIHtcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAnY3VzdG9tX3R5cGUnOiBjdXN0b21fdHlwZVxuICAgICAgJ2NvbnRlbnQnIDogY29udGVudFxuICAgICAgJ2NvbnRlbnRfb3BlcmF0aW9ucycgOiBjb250ZW50X29wZXJhdGlvbnNcbiAgICB9ID0ganNvblxuICAgIG5ldyB0aGlzKGN1c3RvbV90eXBlLCB1aWQsIGNvbnRlbnQsIGNvbnRlbnRfb3BlcmF0aW9ucylcblxuICBjbGFzcyBvcHMuQ29tcG9zaXRpb24gZXh0ZW5kcyBvcHMuTGlzdE1hbmFnZXJcblxuICAgIGNvbnN0cnVjdG9yOiAoY3VzdG9tX3R5cGUsIEBfY29tcG9zaXRpb25fdmFsdWUsIGNvbXBvc2l0aW9uX3ZhbHVlX29wZXJhdGlvbnMsIHVpZCwgdG1wX2NvbXBvc2l0aW9uX3JlZiktPlxuICAgICAgIyB3ZSBjYW4ndCB1c2UgQHNldmVPcGVyYXRpb24gJ2NvbXBvc2l0aW9uX3JlZicsIHRtcF9jb21wb3NpdGlvbl9yZWYgaGVyZSxcbiAgICAgICMgYmVjYXVzZSB0aGVuIHRoZXJlIGlzIGEgXCJsb29wXCIgKGluc2VydGlvbiByZWZlcnMgdG8gcGFyZW50LCByZWZlcnMgdG8gaW5zZXJ0aW9uLi4pXG4gICAgICAjIFRoaXMgaXMgd2h5IHdlIGhhdmUgdG8gY2hlY2sgaW4gQGNhbGxPcGVyYXRpb25TcGVjaWZpY0luc2VydEV2ZW50cyB1bnRpbCB3ZSBmaW5kIGl0XG4gICAgICBzdXBlciBjdXN0b21fdHlwZSwgdWlkXG4gICAgICBpZiB0bXBfY29tcG9zaXRpb25fcmVmP1xuICAgICAgICBAdG1wX2NvbXBvc2l0aW9uX3JlZiA9IHRtcF9jb21wb3NpdGlvbl9yZWZcbiAgICAgIGVsc2VcbiAgICAgICAgQGNvbXBvc2l0aW9uX3JlZiA9IEBlbmQucHJldl9jbFxuICAgICAgaWYgY29tcG9zaXRpb25fdmFsdWVfb3BlcmF0aW9ucz9cbiAgICAgICAgQGNvbXBvc2l0aW9uX3ZhbHVlX29wZXJhdGlvbnMgPSB7fVxuICAgICAgICBmb3IgbixvIG9mIGNvbXBvc2l0aW9uX3ZhbHVlX29wZXJhdGlvbnNcbiAgICAgICAgICBAc2F2ZU9wZXJhdGlvbiBuLCBvLCAnX2NvbXBvc2l0aW9uX3ZhbHVlJ1xuXG4gICAgdHlwZTogXCJDb21wb3NpdGlvblwiXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgQHNlZSBPcGVyYXRpb24uZXhlY3V0ZVxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICBAZ2V0Q3VzdG9tVHlwZSgpLl9zZXRDb21wb3NpdGlvblZhbHVlIEBfY29tcG9zaXRpb25fdmFsdWVcbiAgICAgICAgZGVsZXRlIEBfY29tcG9zaXRpb25fdmFsdWVcbiAgICAgICAgIyBjaGVjayBpZiB0bXBfY29tcG9zaXRpb25fcmVmIGFscmVhZHkgZXhpc3RzXG4gICAgICAgIGlmIEB0bXBfY29tcG9zaXRpb25fcmVmXG4gICAgICAgICAgY29tcG9zaXRpb25fcmVmID0gQEhCLmdldE9wZXJhdGlvbiBAdG1wX2NvbXBvc2l0aW9uX3JlZlxuICAgICAgICAgIGlmIGNvbXBvc2l0aW9uX3JlZj9cbiAgICAgICAgICAgIGRlbGV0ZSBAdG1wX2NvbXBvc2l0aW9uX3JlZlxuICAgICAgICAgICAgQGNvbXBvc2l0aW9uX3JlZiA9IGNvbXBvc2l0aW9uX3JlZlxuICAgICAgICBzdXBlclxuICAgICAgZWxzZVxuICAgICAgICBmYWxzZVxuXG4gICAgI1xuICAgICMgVGhpcyBpcyBjYWxsZWQsIHdoZW4gdGhlIEluc2VydC1vcGVyYXRpb24gd2FzIHN1Y2Nlc3NmdWxseSBleGVjdXRlZC5cbiAgICAjXG4gICAgY2FsbE9wZXJhdGlvblNwZWNpZmljSW5zZXJ0RXZlbnRzOiAob3BlcmF0aW9uKS0+XG4gICAgICBpZiBAdG1wX2NvbXBvc2l0aW9uX3JlZj9cbiAgICAgICAgaWYgb3BlcmF0aW9uLnVpZC5jcmVhdG9yIGlzIEB0bXBfY29tcG9zaXRpb25fcmVmLmNyZWF0b3IgYW5kIG9wZXJhdGlvbi51aWQub3BfbnVtYmVyIGlzIEB0bXBfY29tcG9zaXRpb25fcmVmLm9wX251bWJlclxuICAgICAgICAgIEBjb21wb3NpdGlvbl9yZWYgPSBvcGVyYXRpb25cbiAgICAgICAgICBkZWxldGUgQHRtcF9jb21wb3NpdGlvbl9yZWZcbiAgICAgICAgICBvcGVyYXRpb24gPSBvcGVyYXRpb24ubmV4dF9jbFxuICAgICAgICAgIGlmIG9wZXJhdGlvbiBpcyBAZW5kXG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgZWxzZVxuICAgICAgICAgIHJldHVyblxuXG4gICAgICBvID0gQGVuZC5wcmV2X2NsXG4gICAgICB3aGlsZSBvIGlzbnQgb3BlcmF0aW9uXG4gICAgICAgIEBnZXRDdXN0b21UeXBlKCkuX3VuYXBwbHkgby51bmRvX2RlbHRhXG4gICAgICAgIG8gPSBvLnByZXZfY2xcbiAgICAgIHdoaWxlIG8gaXNudCBAZW5kXG4gICAgICAgIG8udW5kb19kZWx0YSA9IEBnZXRDdXN0b21UeXBlKCkuX2FwcGx5IG8udmFsKClcbiAgICAgICAgbyA9IG8ubmV4dF9jbFxuICAgICAgQGNvbXBvc2l0aW9uX3JlZiA9IEBlbmQucHJldl9jbFxuXG4gICAgICBAY2FsbEV2ZW50IFtcbiAgICAgICAgdHlwZTogXCJ1cGRhdGVcIlxuICAgICAgICBjaGFuZ2VkQnk6IG9wZXJhdGlvbi51aWQuY3JlYXRvclxuICAgICAgICBuZXdWYWx1ZTogQHZhbCgpXG4gICAgICBdXG5cbiAgICBjYWxsT3BlcmF0aW9uU3BlY2lmaWNEZWxldGVFdmVudHM6IChvcGVyYXRpb24sIGRlbF9vcCktPlxuICAgICAgcmV0dXJuXG5cbiAgICAjXG4gICAgIyBDcmVhdGUgYSBuZXcgRGVsdGFcbiAgICAjIC0gaW5zZXJ0cyBuZXcgQ29udGVudCBhdCB0aGUgZW5kIG9mIHRoZSBsaXN0XG4gICAgIyAtIHVwZGF0ZXMgdGhlIGNvbXBvc2l0aW9uX3ZhbHVlXG4gICAgIyAtIHVwZGF0ZXMgdGhlIGNvbXBvc2l0aW9uX3JlZlxuICAgICNcbiAgICAjIEBwYXJhbSBkZWx0YSBUaGUgZGVsdGEgdGhhdCBpcyBhcHBsaWVkIHRvIHRoZSBjb21wb3NpdGlvbl92YWx1ZVxuICAgICNcbiAgICBhcHBseURlbHRhOiAoZGVsdGEsIG9wZXJhdGlvbnMpLT5cbiAgICAgIChuZXcgb3BzLkluc2VydCBudWxsLCBkZWx0YSwgb3BlcmF0aW9ucywgQCwgbnVsbCwgQGVuZC5wcmV2X2NsLCBAZW5kKS5leGVjdXRlKClcbiAgICAgIHVuZGVmaW5lZFxuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKGpzb24gPSB7fSktPlxuICAgICAgY3VzdG9tID0gQGdldEN1c3RvbVR5cGUoKS5fZ2V0Q29tcG9zaXRpb25WYWx1ZSgpXG4gICAgICBqc29uLmNvbXBvc2l0aW9uX3ZhbHVlID0gY3VzdG9tLmNvbXBvc2l0aW9uX3ZhbHVlXG4gICAgICBpZiBjdXN0b20uY29tcG9zaXRpb25fdmFsdWVfb3BlcmF0aW9ucz9cbiAgICAgICAganNvbi5jb21wb3NpdGlvbl92YWx1ZV9vcGVyYXRpb25zID0ge31cbiAgICAgICAgZm9yIG4sbyBvZiBjdXN0b20uY29tcG9zaXRpb25fdmFsdWVfb3BlcmF0aW9uc1xuICAgICAgICAgIGpzb24uY29tcG9zaXRpb25fdmFsdWVfb3BlcmF0aW9uc1tuXSA9IG8uZ2V0VWlkKClcbiAgICAgIGlmIEBjb21wb3NpdGlvbl9yZWY/XG4gICAgICAgIGpzb24uY29tcG9zaXRpb25fcmVmID0gQGNvbXBvc2l0aW9uX3JlZi5nZXRVaWQoKVxuICAgICAgZWxzZVxuICAgICAgICBqc29uLmNvbXBvc2l0aW9uX3JlZiA9IEB0bXBfY29tcG9zaXRpb25fcmVmXG4gICAgICBzdXBlciBqc29uXG5cbiAgb3BzLkNvbXBvc2l0aW9uLnBhcnNlID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ2N1c3RvbV90eXBlJzogY3VzdG9tX3R5cGVcbiAgICAgICdjb21wb3NpdGlvbl92YWx1ZScgOiBjb21wb3NpdGlvbl92YWx1ZVxuICAgICAgJ2NvbXBvc2l0aW9uX3ZhbHVlX29wZXJhdGlvbnMnIDogY29tcG9zaXRpb25fdmFsdWVfb3BlcmF0aW9uc1xuICAgICAgJ2NvbXBvc2l0aW9uX3JlZicgOiBjb21wb3NpdGlvbl9yZWZcbiAgICB9ID0ganNvblxuICAgIG5ldyB0aGlzKGN1c3RvbV90eXBlLCBjb21wb3NpdGlvbl92YWx1ZSwgY29tcG9zaXRpb25fdmFsdWVfb3BlcmF0aW9ucywgdWlkLCBjb21wb3NpdGlvbl9yZWYpXG5cblxuICAjXG4gICMgQG5vZG9jXG4gICMgQWRkcyBzdXBwb3J0IGZvciByZXBsYWNlLiBUaGUgUmVwbGFjZU1hbmFnZXIgbWFuYWdlcyBSZXBsYWNlYWJsZSBvcGVyYXRpb25zLlxuICAjIEVhY2ggUmVwbGFjZWFibGUgaG9sZHMgYSB2YWx1ZSB0aGF0IGlzIG5vdyByZXBsYWNlYWJsZS5cbiAgI1xuICAjIFRoZSBUZXh0VHlwZS10eXBlIGhhcyBpbXBsZW1lbnRlZCBzdXBwb3J0IGZvciByZXBsYWNlXG4gICMgQHNlZSBUZXh0VHlwZVxuICAjXG4gIGNsYXNzIG9wcy5SZXBsYWNlTWFuYWdlciBleHRlbmRzIG9wcy5MaXN0TWFuYWdlclxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSBldmVudF9wcm9wZXJ0aWVzIERlY29yYXRlcyB0aGUgZXZlbnQgdGhhdCBpcyB0aHJvd24gYnkgdGhlIFJNXG4gICAgIyBAcGFyYW0ge09iamVjdH0gZXZlbnRfdGhpcyBUaGUgb2JqZWN0IG9uIHdoaWNoIHRoZSBldmVudCBzaGFsbCBiZSBleGVjdXRlZFxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IGluaXRpYWxfY29udGVudCBJbml0aWFsaXplIHRoaXMgd2l0aCBhIFJlcGxhY2VhYmxlIHRoYXQgaG9sZHMgdGhlIGluaXRpYWxfY29udGVudC5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7RGVsaW1pdGVyfSBiZWdpbm5pbmcgUmVmZXJlbmNlIG9yIE9iamVjdC5cbiAgICAjIEBwYXJhbSB7RGVsaW1pdGVyfSBlbmQgUmVmZXJlbmNlIG9yIE9iamVjdC5cbiAgICBjb25zdHJ1Y3RvcjogKGN1c3RvbV90eXBlLCBAZXZlbnRfcHJvcGVydGllcywgQGV2ZW50X3RoaXMsIHVpZCktPlxuICAgICAgaWYgbm90IEBldmVudF9wcm9wZXJ0aWVzWydvYmplY3QnXT9cbiAgICAgICAgQGV2ZW50X3Byb3BlcnRpZXNbJ29iamVjdCddID0gQGV2ZW50X3RoaXMuZ2V0Q3VzdG9tVHlwZSgpXG4gICAgICBzdXBlciBjdXN0b21fdHlwZSwgdWlkXG5cbiAgICB0eXBlOiBcIlJlcGxhY2VNYW5hZ2VyXCJcblxuICAgICNcbiAgICAjIFRoaXMgZG9lc24ndCB0aHJvdyB0aGUgc2FtZSBldmVudHMgYXMgdGhlIExpc3RNYW5hZ2VyLiBUaGVyZWZvcmUsIHRoZVxuICAgICMgUmVwbGFjZWFibGVzIGFsc28gbm90IHRocm93IHRoZSBzYW1lIGV2ZW50cy5cbiAgICAjIFNvLCBSZXBsYWNlTWFuYWdlciBhbmQgTGlzdE1hbmFnZXIgYm90aCBpbXBsZW1lbnRcbiAgICAjIHRoZXNlIGZ1bmN0aW9ucyB0aGF0IGFyZSBjYWxsZWQgd2hlbiBhbiBJbnNlcnRpb24gaXMgZXhlY3V0ZWQgKGF0IHRoZSBlbmQpLlxuICAgICNcbiAgICAjXG4gICAgY2FsbEV2ZW50RGVjb3JhdG9yOiAoZXZlbnRzKS0+XG4gICAgICBpZiBub3QgQGlzRGVsZXRlZCgpXG4gICAgICAgIGZvciBldmVudCBpbiBldmVudHNcbiAgICAgICAgICBmb3IgbmFtZSxwcm9wIG9mIEBldmVudF9wcm9wZXJ0aWVzXG4gICAgICAgICAgICBldmVudFtuYW1lXSA9IHByb3BcbiAgICAgICAgQGV2ZW50X3RoaXMuY2FsbEV2ZW50IGV2ZW50c1xuICAgICAgdW5kZWZpbmVkXG5cbiAgICAjXG4gICAgIyBUaGlzIGlzIGNhbGxlZCwgd2hlbiB0aGUgSW5zZXJ0LXR5cGUgd2FzIHN1Y2Nlc3NmdWxseSBleGVjdXRlZC5cbiAgICAjIFRPRE86IGNvbnNpZGVyIGRvaW5nIHRoaXMgaW4gYSBtb3JlIGNvbnNpc3RlbnQgbWFubmVyLiBUaGlzIGNvdWxkIGFsc28gYmVcbiAgICAjIGRvbmUgd2l0aCBleGVjdXRlLiBCdXQgY3VycmVudGx5LCB0aGVyZSBhcmUgbm8gc3BlY2l0YWwgSW5zZXJ0LW9wcyBmb3IgTGlzdE1hbmFnZXIuXG4gICAgI1xuICAgIGNhbGxPcGVyYXRpb25TcGVjaWZpY0luc2VydEV2ZW50czogKG9wZXJhdGlvbiktPlxuICAgICAgaWYgb3BlcmF0aW9uLm5leHRfY2wudHlwZSBpcyBcIkRlbGltaXRlclwiIGFuZCBvcGVyYXRpb24ucHJldl9jbC50eXBlIGlzbnQgXCJEZWxpbWl0ZXJcIlxuICAgICAgICAjIHRoaXMgcmVwbGFjZXMgYW5vdGhlciBSZXBsYWNlYWJsZVxuICAgICAgICBpZiBub3Qgb3BlcmF0aW9uLmlzX2RlbGV0ZWQgIyBXaGVuIHRoaXMgaXMgcmVjZWl2ZWQgZnJvbSB0aGUgSEIsIHRoaXMgY291bGQgYWxyZWFkeSBiZSBkZWxldGVkIVxuICAgICAgICAgIG9sZF92YWx1ZSA9IG9wZXJhdGlvbi5wcmV2X2NsLnZhbCgpXG4gICAgICAgICAgQGNhbGxFdmVudERlY29yYXRvciBbXG4gICAgICAgICAgICB0eXBlOiBcInVwZGF0ZVwiXG4gICAgICAgICAgICBjaGFuZ2VkQnk6IG9wZXJhdGlvbi51aWQuY3JlYXRvclxuICAgICAgICAgICAgb2xkVmFsdWU6IG9sZF92YWx1ZVxuICAgICAgICAgIF1cbiAgICAgICAgb3BlcmF0aW9uLnByZXZfY2wuYXBwbHlEZWxldGUoKVxuICAgICAgZWxzZSBpZiBvcGVyYXRpb24ubmV4dF9jbC50eXBlIGlzbnQgXCJEZWxpbWl0ZXJcIlxuICAgICAgICAjIFRoaXMgd29uJ3QgYmUgcmVjb2duaXplZCBieSB0aGUgdXNlciwgYmVjYXVzZSBhbm90aGVyXG4gICAgICAgICMgY29uY3VycmVudCBvcGVyYXRpb24gaXMgc2V0IGFzIHRoZSBjdXJyZW50IHZhbHVlIG9mIHRoZSBSTVxuICAgICAgICBvcGVyYXRpb24uYXBwbHlEZWxldGUoKVxuICAgICAgZWxzZSAjIHByZXYgX2FuZF8gbmV4dCBhcmUgRGVsaW1pdGVycy4gVGhpcyBpcyB0aGUgZmlyc3QgY3JlYXRlZCBSZXBsYWNlYWJsZSBpbiB0aGUgUk1cbiAgICAgICAgQGNhbGxFdmVudERlY29yYXRvciBbXG4gICAgICAgICAgdHlwZTogXCJhZGRcIlxuICAgICAgICAgIGNoYW5nZWRCeTogb3BlcmF0aW9uLnVpZC5jcmVhdG9yXG4gICAgICAgIF1cbiAgICAgIHVuZGVmaW5lZFxuXG4gICAgY2FsbE9wZXJhdGlvblNwZWNpZmljRGVsZXRlRXZlbnRzOiAob3BlcmF0aW9uLCBkZWxfb3ApLT5cbiAgICAgIGlmIG9wZXJhdGlvbi5uZXh0X2NsLnR5cGUgaXMgXCJEZWxpbWl0ZXJcIlxuICAgICAgICBAY2FsbEV2ZW50RGVjb3JhdG9yIFtcbiAgICAgICAgICB0eXBlOiBcImRlbGV0ZVwiXG4gICAgICAgICAgY2hhbmdlZEJ5OiBkZWxfb3AudWlkLmNyZWF0b3JcbiAgICAgICAgICBvbGRWYWx1ZTogb3BlcmF0aW9uLnZhbCgpXG4gICAgICAgIF1cblxuXG4gICAgI1xuICAgICMgUmVwbGFjZSB0aGUgZXhpc3Rpbmcgd29yZCB3aXRoIGEgbmV3IHdvcmQuXG4gICAgI1xuICAgICMgQHBhcmFtIGNvbnRlbnQge09wZXJhdGlvbn0gVGhlIG5ldyB2YWx1ZSBvZiB0aGlzIFJlcGxhY2VNYW5hZ2VyLlxuICAgICMgQHBhcmFtIHJlcGxhY2VhYmxlX3VpZCB7VUlEfSBPcHRpb25hbDogVW5pcXVlIGlkIG9mIHRoZSBSZXBsYWNlYWJsZSB0aGF0IGlzIGNyZWF0ZWRcbiAgICAjXG4gICAgcmVwbGFjZTogKGNvbnRlbnQsIHJlcGxhY2VhYmxlX3VpZCktPlxuICAgICAgbyA9IEBnZXRMYXN0T3BlcmF0aW9uKClcbiAgICAgIHJlbHAgPSAobmV3IG9wcy5JbnNlcnQgbnVsbCwgY29udGVudCwgbnVsbCwgQCwgcmVwbGFjZWFibGVfdWlkLCBvLCBvLm5leHRfY2wpLmV4ZWN1dGUoKVxuICAgICAgIyBUT0RPOiBkZWxldGUgcmVwbCAoZm9yIGRlYnVnZ2luZylcbiAgICAgIHVuZGVmaW5lZFxuXG4gICAgaXNDb250ZW50RGVsZXRlZDogKCktPlxuICAgICAgQGdldExhc3RPcGVyYXRpb24oKS5pc0RlbGV0ZWQoKVxuXG4gICAgZGVsZXRlQ29udGVudDogKCktPlxuICAgICAgbGFzdF9vcCA9IEBnZXRMYXN0T3BlcmF0aW9uKClcbiAgICAgIGlmIChub3QgbGFzdF9vcC5pc0RlbGV0ZWQoKSkgYW5kIGxhc3Rfb3AudHlwZSBpc250IFwiRGVsaW1pdGVyXCJcbiAgICAgICAgKG5ldyBvcHMuRGVsZXRlIG51bGwsIHVuZGVmaW5lZCwgQGdldExhc3RPcGVyYXRpb24oKS51aWQpLmV4ZWN1dGUoKVxuICAgICAgdW5kZWZpbmVkXG5cbiAgICAjXG4gICAgIyBHZXQgdGhlIHZhbHVlIG9mIHRoaXNcbiAgICAjIEByZXR1cm4ge1N0cmluZ31cbiAgICAjXG4gICAgdmFsOiAoKS0+XG4gICAgICBvID0gQGdldExhc3RPcGVyYXRpb24oKVxuICAgICAgI2lmIG8gaW5zdGFuY2VvZiBvcHMuRGVsaW1pdGVyXG4gICAgICAgICMgdGhyb3cgbmV3IEVycm9yIFwiUmVwbGFjZSBNYW5hZ2VyIGRvZXNuJ3QgY29udGFpbiBhbnl0aGluZy5cIlxuICAgICAgby52YWw/KCkgIyA/IC0gZm9yIHRoZSBjYXNlIHRoYXQgKGN1cnJlbnRseSkgdGhlIFJNIGRvZXMgbm90IGNvbnRhaW4gYW55dGhpbmcgKHRoZW4gbyBpcyBhIERlbGltaXRlcilcblxuICBiYXNpY19vcHNcbiIsIlxuc3RydWN0dXJlZF9vcHNfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuL09wZXJhdGlvbnMvU3RydWN0dXJlZFwiXG5cbkhpc3RvcnlCdWZmZXIgPSByZXF1aXJlIFwiLi9IaXN0b3J5QnVmZmVyXCJcbkVuZ2luZSA9IHJlcXVpcmUgXCIuL0VuZ2luZVwiXG5hZGFwdENvbm5lY3RvciA9IHJlcXVpcmUgXCIuL0Nvbm5lY3RvckFkYXB0ZXJcIlxuXG5jcmVhdGVZID0gKGNvbm5lY3RvciktPlxuICBpZiBjb25uZWN0b3IudXNlcl9pZD9cbiAgICB1c2VyX2lkID0gY29ubmVjdG9yLnVzZXJfaWQgIyBUT0RPOiBjaGFuZ2UgdG8gZ2V0VW5pcXVlSWQoKVxuICBlbHNlXG4gICAgdXNlcl9pZCA9IFwiX3RlbXBcIlxuICAgIGNvbm5lY3Rvci53aGVuX3JlY2VpdmVkX3N0YXRlX3ZlY3Rvcl9saXN0ZW5lcnMgPSBbKHN0YXRlX3ZlY3RvciktPlxuICAgICAgICBIQi5zZXRVc2VySWQgdGhpcy51c2VyX2lkLCBzdGF0ZV92ZWN0b3JcbiAgICAgIF1cbiAgSEIgPSBuZXcgSGlzdG9yeUJ1ZmZlciB1c2VyX2lkXG4gIG9wc19tYW5hZ2VyID0gc3RydWN0dXJlZF9vcHNfdW5pbml0aWFsaXplZCBIQiwgdGhpcy5jb25zdHJ1Y3RvclxuICBvcHMgPSBvcHNfbWFuYWdlci5vcGVyYXRpb25zXG5cbiAgZW5naW5lID0gbmV3IEVuZ2luZSBIQiwgb3BzXG4gIGFkYXB0Q29ubmVjdG9yIGNvbm5lY3RvciwgZW5naW5lLCBIQiwgb3BzX21hbmFnZXIuZXhlY3V0aW9uX2xpc3RlbmVyXG5cbiAgb3BzLk9wZXJhdGlvbi5wcm90b3R5cGUuSEIgPSBIQlxuICBvcHMuT3BlcmF0aW9uLnByb3RvdHlwZS5vcGVyYXRpb25zID0gb3BzXG4gIG9wcy5PcGVyYXRpb24ucHJvdG90eXBlLmVuZ2luZSA9IGVuZ2luZVxuICBvcHMuT3BlcmF0aW9uLnByb3RvdHlwZS5jb25uZWN0b3IgPSBjb25uZWN0b3JcbiAgb3BzLk9wZXJhdGlvbi5wcm90b3R5cGUuY3VzdG9tX3R5cGVzID0gdGhpcy5jb25zdHJ1Y3RvclxuXG4gIGN0ID0gbmV3IGNyZWF0ZVkuT2JqZWN0KClcbiAgbW9kZWwgPSBuZXcgb3BzLk1hcE1hbmFnZXIoY3QsIEhCLmdldFJlc2VydmVkVW5pcXVlSWRlbnRpZmllcigpKS5leGVjdXRlKClcbiAgY3QuX3NldE1vZGVsIG1vZGVsXG4gIGN0XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlWVxuaWYgd2luZG93P1xuICB3aW5kb3cuWSA9IGNyZWF0ZVlcblxuY3JlYXRlWS5PYmplY3QgPSByZXF1aXJlIFwiLi9PYmplY3RUeXBlXCJcbiIsInZhciBUcmVlQmFzZSA9IHJlcXVpcmUoJy4vdHJlZWJhc2UnKTtcbi8qKiBhbGdvcml0aG0gZnJvbSBDb3JtZW4sIExlaXNlcnNvbiAtIEludHJvZHVjdGlvbiB0byBhbGdvcml0aG0gKiovXG5cbmZ1bmN0aW9uIFJCVHJlZShjb21wYXJhdG9yKSB7XG4gICAgdGhpcy5fcm9vdCA9IG51bGw7XG4gICAgdGhpcy5fbmlsID0gbmV3IE5vZGUoJ25pbCcpO1xuICAgIHRoaXMuX25pbC5yZWQgPSBmYWxzZTtcbiAgICB0aGlzLl9uaWwud2VpZ2h0ID0gMDtcbn1cblxuUkJUcmVlLnByb3RvdHlwZSA9IG5ldyBUcmVlQmFzZSgpO1xuXG5SQlRyZWUucHJvdG90eXBlLmluc2VydCA9IGZ1bmN0aW9uKHBvc2l0aW9uLCBkYXRhKSB7XG4gIHZhciBub2RlVG9JbnNlcnQgPSBuZXcgTm9kZShkYXRhKTtcbiAgaWYgKHRoaXMuaW5zZXJ0X25vZGUocG9zaXRpb24sIG5vZGVUb0luc2VydCkpIHtcbiAgICByZXR1cm4gbm9kZVRvSW5zZXJ0O1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufTtcblxuUkJUcmVlLnByb3RvdHlwZS5pbnNlcnRfbm9kZSA9IGZ1bmN0aW9uKHBvc2l0aW9uLCBub2RlVG9JbnNlcnQpIHtcbiAgdmFyIG5vZGUgPSB0aGlzLl9yb290O1xuICB2YXIgaW5zZXJ0QWZ0ZXI7XG5cbiAgaWYgKCFub2RlKSB7XG4gICAgdGhpcy5fcm9vdCA9IG5vZGVUb0luc2VydDtcbiAgICB0aGlzLl9yb290LnJlZCA9IGZhbHNlO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBpZiAobm9kZS53ZWlnaHQgPT09IHBvc2l0aW9uKSB7IC8vIEluc2VydCBhZnRlciBtYXggb2Ygbm9kZSBzdWJ0cmVlXG4gICAgICBpbnNlcnRBZnRlciA9IG5vZGUubWF4X3RyZWUoZnVuY3Rpb24obm9kZSkge1xuICAgICAgICBub2RlLndlaWdodCArPSAxO1xuICAgICAgfSk7XG4gICAgICBpbnNlcnRBZnRlci5zZXRfY2hpbGQoJ3JpZ2h0Jywgbm9kZVRvSW5zZXJ0KTtcbiAgICAgIG5vZGVUb0luc2VydC5wYXJlbnQgPSBpbnNlcnRBZnRlcjtcbiAgICAgIGJyZWFrO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZWZ0ID0gbm9kZS5nZXRfY2hpbGQoJ2xlZnQnKTtcbiAgICAgIHJpZ2h0ID0gbm9kZS5nZXRfY2hpbGQoJ3JpZ2h0Jyk7XG4gICAgICBpZiAoIWxlZnQgJiYgcG9zaXRpb24gPT09IDApIHtcbiAgICAgICAgbm9kZS53ZWlnaHQgKz0gMTtcbiAgICAgICAgbm9kZS5zZXRfY2hpbGQoJ2xlZnQnLCBub2RlVG9JbnNlcnQpO1xuICAgICAgICBub2RlVG9JbnNlcnQucGFyZW50ID0gbm9kZTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIH0gZWxzZSBpZiAobGVmdCAmJiBsZWZ0LndlaWdodCA+PSBwb3NpdGlvbikge1xuICAgICAgICBub2RlLndlaWdodCArPSAxO1xuICAgICAgICBub2RlID0gbGVmdDtcblxuICAgICAgfSBlbHNlIGlmIChyaWdodCkge1xuICAgICAgICBwb3NpdGlvbiAtPSAobGVmdD8gbGVmdC53ZWlnaHQ6IDApICsgMTtcbiAgICAgICAgbm9kZS53ZWlnaHQgKz0gMTtcbiAgICAgICAgbm9kZSA9IHJpZ2h0O1xuXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBub2RlLndlaWdodCArPSAxO1xuICAgICAgICBub2RlLnNldF9jaGlsZCgncmlnaHQnLCBub2RlVG9JbnNlcnQpO1xuICAgICAgICBub2RlVG9JbnNlcnQucGFyZW50ID0gbm9kZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdGhpcy5pbnNlcnRfY29ycmVjdGlvbihub2RlVG9JbnNlcnQpO1xuICByZXR1cm4gdHJ1ZTtcbn07XG5cblJCVHJlZS5wcm90b3R5cGUuaW5zZXJ0X2JldHdlZW4gPSBmdW5jdGlvbihvbkxlZnQsIG9uUmlnaHQsIGRhdGEpIHtcbiAgdmFyIG5ld05vZGUgPSBuZXcgTm9kZShkYXRhKTtcbiAgLy8gb25MZWZ0IGFuZCBvblJpZ2h0IGFyZSBuZWlnaGJvcnMsIHNvIHRoZXkgY2FuJ3QgaGF2ZSBhbiBlbGVtZW50IGluIGJldHdlZW4uXG4gIC8vIEZvciBleGFtcGxlLCBpZiBvbkxlZnQgZXhpc3RzLCBpdHMgcmlnaHQgbmVpZ2hib3IgaXMgZWl0aGVyIG5pbCBvciByaWdodC4gSWYgaXQncyBvblJpZ2h0LFxuICAvLyB0aGVuIG9uUmlnaHQgaGFzIG5vIGNoaWxkLiBJZiBuZWl0aGVyIGxlZnQgYW5kIHJpZ2h0IGV4aXN0LCB0aGUgdHJlZSBpcyBlbXB0eS5cbiAgaWYgKG9uTGVmdCAmJiAhb25MZWZ0LnJpZ2h0KSB7XG4gICAgb25MZWZ0LnJpZ2h0ID0gbmV3Tm9kZTtcbiAgICBuZXdOb2RlLnBhcmVudCA9IG9uTGVmdDtcblxuICAgIHRoaXMuaW5zZXJ0X2NvcnJlY3Rpb24obmV3Tm9kZSk7XG4gIH0gZWxzZSBpZiAob25SaWdodCAmJiAhb25SaWdodC5sZWZ0KSB7XG4gICAgb25SaWdodC5sZWZ0ID0gbmV3Tm9kZTtcbiAgICBuZXdOb2RlLnBhcmVudCA9IG9uUmlnaHQ7XG5cbiAgICB0aGlzLmluc2VydF9jb3JyZWN0aW9uKG5ld05vZGUpO1xuICB9IGVsc2Uge1xuICAgIHRoaXMuaW5zZXJ0X25vZGUoMCwgbmV3Tm9kZSk7XG4gIH1cbiAgbmV3Tm9kZS50cmF2ZXJzZV91cChmdW5jdGlvbihub2RlLCBwYXJlbnQpIHtcbiAgICBwYXJlbnQud2VpZ2h0ID0gKHBhcmVudC5sZWZ0ID8gcGFyZW50LmxlZnQud2VpZ2h0IDogMCkgK1xuICAgICAgICAocGFyZW50LnJpZ2h0ID8gcGFyZW50LnJpZ2h0LndlaWdodCA6IDApICsgMTtcbiAgfSk7XG5cbiAgcmV0dXJuIG5ld05vZGU7XG59O1xuXG5SQlRyZWUucHJvdG90eXBlLnJvdGF0ZSA9IGZ1bmN0aW9uKHNpZGUsIG5vZGUpIHtcbiAgLy8gYWxsIHRoZSBjb21tZW50IGFyZSB3aXRoIHRoZSBhc3N1bXB0aW9uIHRoYXQgc2lkZSA9PT0gJ2xlZnQnXG4gIHZhciBuZWlnaGJvcjtcblxuICAvLyBnZXQgcmlnaHQgbmVpZ2hib3JcbiAgbmVpZ2hib3IgPSBub2RlLmdldF9jaGlsZChzaWRlLCB0cnVlKTtcbiAgLy8gbmVpZ2hib3IncyBsZWZ0IHRyZWUgYmVjb21lcyBub2RlJ3MgcmlnaHQgdHJlZVxuICBub2RlLnNldF9jaGlsZChzaWRlLCBuZWlnaGJvci5nZXRfY2hpbGQoc2lkZSksIHRydWUpO1xuXG4gIC8vIGlmIHRoaXMgcmlnaHQgdHJlZSB3YXMgbm9uLWVtcHR5XG4gIGlmIChuZWlnaGJvci5nZXRfY2hpbGQoc2lkZSkpIHtcbiAgICBuZWlnaGJvci5nZXRfY2hpbGQoc2lkZSkucGFyZW50ID0gbm9kZTsgLy8gYXR0YWNoIG5laWdoYm9yJ3MgbGVmdCBjaGlsZCB0byBub2RlXG4gIH1cbiAgbmVpZ2hib3IucGFyZW50ID0gbm9kZS5wYXJlbnQ7IC8vIGxpbmsgbmVpZ2hib3IncyBwYXJlbnQgdG8gbm9kZSdzIHBhcmVudFxuXG4gIGlmICghbm9kZS5wYXJlbnQpIHsgLy8gbm8gcGFyZW50ID09PSBpc19yb290XG4gICAgdGhpcy5fcm9vdCA9IG5laWdoYm9yO1xuICB9IGVsc2UgaWYgKG5vZGUgPT09IG5vZGUucGFyZW50LmdldF9jaGlsZChzaWRlKSl7IC8vIG5vZGUgaXMgbGVmdCBjaGlsZFxuICAgIG5vZGUucGFyZW50LnNldF9jaGlsZChzaWRlLCBuZWlnaGJvcik7IC8vIG5vZGUncyBwYXJlbnQgbGVmdCBjaGlsZCBpcyBub3cgbmVpZ2hib3JcbiAgfSBlbHNlIHtcbiAgICBub2RlLnBhcmVudC5zZXRfY2hpbGQoc2lkZSwgbmVpZ2hib3IsIHRydWUpOyAvLyBub2RlJ3MgcGFyZW50IHJpZ2h0IGNoaWxkIGlzIG5vdyBuZWlnaGJvclxuICB9XG5cbiAgbmVpZ2hib3Iuc2V0X2NoaWxkKHNpZGUsIG5vZGUpOyAvLyBhdHRhY2ggbm9kZSBvbiBsZWZ0IG9mIGNoaWxkXG4gIG5vZGUucGFyZW50ID0gbmVpZ2hib3I7IC8vIHNldCBub2RlJ3MgcGFyZW50IHRvIG5laWdoYm9yXG5cbiAgLy8gdXBkYXRlIG5vZGUncyB3ZWlnaHQgZmlyc3QsIHRoZW5cbiAgbm9kZS53ZWlnaHQgPSAobm9kZS5sZWZ0PyBub2RlLmxlZnQud2VpZ2h0OiAwKSArIChub2RlLnJpZ2h0PyBub2RlLnJpZ2h0LndlaWdodDogMCkgKyAxO1xuICBuZWlnaGJvci53ZWlnaHQgPSAobmVpZ2hib3IubGVmdD8gbmVpZ2hib3IubGVmdC53ZWlnaHQ6IDApICsgKG5laWdoYm9yLnJpZ2h0PyBuZWlnaGJvci5yaWdodC53ZWlnaHQ6IDApICsgMTtcbn07XG5cblJCVHJlZS5wcm90b3R5cGUuaW5zZXJ0X2NvcnJlY3Rpb24gPSBmdW5jdGlvbihub2RlKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgZnVuY3Rpb24gaGVscGVyKHNpZGUpIHtcbiAgICB2YXIgdW5jbGU7XG4gICAgdW5jbGUgPSBub2RlLnBhcmVudC5wYXJlbnQuZ2V0X2NoaWxkKHNpZGUsIHRydWUpO1xuXG4gICAgaWYgKHVuY2xlICYmIHVuY2xlLnJlZCkgeyAvLyBpZiB1bmNsZSBpcyB1bmRlZmluZWQsIGl0J3MgYSBsZWFmIHNvIGl0J3MgYmxhY2tcbiAgICAgIG5vZGUucGFyZW50LnJlZCAgICAgICAgPSBmYWxzZTtcbiAgICAgIHVuY2xlLnJlZCAgICAgICAgICAgICAgPSBmYWxzZTtcbiAgICAgIG5vZGUucGFyZW50LnBhcmVudC5yZWQgPSB0cnVlO1xuXG4gICAgICBub2RlID0gbm9kZS5wYXJlbnQucGFyZW50O1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAobm9kZSA9PT0gbm9kZS5wYXJlbnQuZ2V0X2NoaWxkKHNpZGUsIHRydWUpKSB7XG4gICAgICAgIG5vZGUgPSBub2RlLnBhcmVudDtcbiAgICAgICAgc2VsZi5yb3RhdGUoc2lkZSwgbm9kZSk7XG4gICAgICB9XG5cbiAgICAgIG5vZGUucGFyZW50LnJlZCAgICAgICAgPSBmYWxzZTtcbiAgICAgIG5vZGUucGFyZW50LnBhcmVudC5yZWQgPSB0cnVlO1xuXG4gICAgICB2YXIgb3Bwb3NpdGVTaWRlID0gc2lkZSA9PT0gJ2xlZnQnPyAncmlnaHQnOiAnbGVmdCc7XG4gICAgICBzZWxmLnJvdGF0ZShvcHBvc2l0ZVNpZGUsIG5vZGUucGFyZW50LnBhcmVudCk7XG4gICAgfVxuICB9XG5cblxuICB3aGlsZSAobm9kZS5wYXJlbnQgJiYgbm9kZS5wYXJlbnQucmVkKSB7IC8vIGlzIHRoZXJlJ3Mgbm8gbm9kZS5wYXJlbnQsIHRoZW4gaXQgbWVhbnMgdGhlIHBhcmVudFxuICAgIC8vIGlzIG5pbCB3aGljaCBpcyBibGFja1xuXG4gICAgLy8gaWYgbm9kZSdzIHBhcmVudCBpcyBvbiBsZWZ0IG9mIGhpcyBwYXJlbnRcbiAgICBpZiAobm9kZS5wYXJlbnQgPT09IG5vZGUucGFyZW50LnBhcmVudC5nZXRfY2hpbGQoJ2xlZnQnKSkgeyAvLyBDaGVjayB0aGF0IHRoZXJlIGlzIGEgZ3JhbmRwYXJlbnRcbiAgICAgIGhlbHBlcignbGVmdCcpO1xuICAgIH0gZWxzZSBpZiAobm9kZS5wYXJlbnQgPT09IG5vZGUucGFyZW50LnBhcmVudC5nZXRfY2hpbGQoJ3JpZ2h0Jykpe1xuICAgICAgaGVscGVyKCdyaWdodCcpO1xuICAgIH1cbiAgfVxuXG4gIHRoaXMuX3Jvb3QucmVkID0gZmFsc2U7XG5cbn07XG5cblJCVHJlZS5wcm90b3R5cGUuZmluZCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgbm9kZSA9IHRoaXMuZmluZE5vZGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgaWYgKG5vZGUpIHtcbiAgICByZXR1cm4gbm9kZS5kYXRhO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBudWxsO1xuICB9XG59O1xuXG4vKiogRmluZCB0aGUgbm9kZSBhdCBwb3NpdGlvbiBAcG9zaXRpb24gYW5kIHJldHVybiBpdC4gSWYgbm8gbm9kZSBpcyBmb3VuZCwgcmV0dXJucyBudWxsLlxuICogSXQgaXMgYWxzbyBwb3NzaWJsZSB0byBwYXNzIGEgZnVuY3Rpb24gYXMgc2Vjb25kIGFyZ3VtZW50LiBJdCB3aWxsIGJlIGNhbGxlZFxuICogd2l0aCBlYWNoIG5vZGUgdHJhdmVyc2VkIGV4Y2VwdCBmb3IgdGhlIG9uZSBmb3VuZC5cbioqL1xuUkJUcmVlLnByb3RvdHlwZS5maW5kTm9kZSA9IGZ1bmN0aW9uKHBvc2l0aW9uLCBmdW4pIHtcbiAgLy8gaWYgdGhlIHdlaWdodCBpcyAnbicsIHRoZSBiaWdnZXN0IGluZGV4IGlzIG4tMSwgc28gd2UgY2hlY2sgdGhhdCBwb3NpdGlvbiA+PSBzaXplXG4gIGlmIChwb3NpdGlvbiA+PSB0aGlzLmdldF9zaXplKCkgfHwgcG9zaXRpb24gPCAwKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbiAgdmFyIG5vZGUgPSB0aGlzLl9yb290O1xuXG4gIGlmICghbm9kZSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLy8gRmluZCBub2RlIHRvIGRlbGV0ZVxuICB3aGlsZSAocG9zaXRpb24gPiAwIHx8IChwb3NpdGlvbiA9PT0gMCAmJiBub2RlLmxlZnQpKSB7XG4gICAgbGVmdCA9IG5vZGUubGVmdDtcbiAgICByaWdodCA9IG5vZGUucmlnaHQ7XG5cbiAgICBpZiAobGVmdCAmJiBsZWZ0LndlaWdodCA+IHBvc2l0aW9uKSB7XG4gICAgICAvLyB3aGVuIHRoZXJlJ3MgYSBsZWZ0IG5laWdoYm9yIHdpdGggYSB3ZWlnaHQgPiBwb3NpdGlvbiB0byByZW1vdmUsXG4gICAgICAvLyBnbyBpbnRvIHRoaXMgc3VidHJlZSBhbmQgZGVjcmVhc2UgdGhlIHN1YnRyZWUgd2VpZ2h0XG4gICAgICBpZiAoZnVuKSB7XG4gICAgICAgIGZ1bihub2RlKTtcbiAgICAgIH1cbiAgICAgIG5vZGUgPSBsZWZ0O1xuXG4gICAgfSBlbHNlIGlmICgoIWxlZnQgJiYgcG9zaXRpb24gPT09IDApIHx8IChsZWZ0ICYmIGxlZnQud2VpZ2h0ID09PSBwb3NpdGlvbikpIHtcbiAgICAgIGJyZWFrO1xuICAgIH0gZWxzZSBpZiAocmlnaHQpIHtcbiAgICAgIC8vIHdoZW4gdGhlcmUncyBhIHJpZ2h0IHN1YnRlZSwgZ28gaW50byBpdCBhbmQgZGVjcmVhc2UgdGhlIHBvc2l0aW9uXG4gICAgICAvLyBieSB0aGUgd2VpZ2h0IG9mIHRoZSBsZWZ0IHN1YnRyZWUgLSAxICsgMSAoZm9yIHRoZSBwcmV2aW91cyBub2RlKVxuICAgICAgaWYgKGZ1bikge1xuICAgICAgICBmdW4obm9kZSk7XG4gICAgICB9XG4gICAgICBub2RlID0gcmlnaHQ7XG4gICAgICBwb3NpdGlvbiAtPSAobGVmdD8gbGVmdC53ZWlnaHQ6IDApICsgMTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAvLyB0aGlzIHNob3VsZCBub3QgaGFwcGVuLCBleGNlcHQgaWYgdGhlIHBvc2l0aW9uIGlzIGdyZWF0ZXIgdGhhbiB0aGUgc2l6ZSBvZiB0aGUgdHJlZVxuICAgICAgdGhyb3cgbmV3IEVycm9yKCd0aGlzIHNob3VsZCBub3QgaGFwcGVuJyk7XG4gICAgfVxuICB9XG4gIHJldHVybiBub2RlO1xufTtcblxuUkJUcmVlLnByb3RvdHlwZS5yZW1vdmUgPSBmdW5jdGlvbihwb3NpdGlvbikge1xuICAvLyBpZiB0aGUgd2VpZ2h0IGlzICduJywgdGhlIGJpZ2dlc3QgaW5kZXggaXMgbi0xLCBzbyB3ZSBjaGVjayB0aGF0IHBvc2l0aW9uID49IHNpemVcbiAgdmFyIG5vZGVUb1JlbW92ZTtcblxuICBub2RlVG9SZW1vdmUgPSB0aGlzLmZpbmROb2RlKHBvc2l0aW9uLCBmdW5jdGlvbihub2RlKSB7IG5vZGUud2VpZ2h0IC0tOyB9KTtcblxuICByZXR1cm4gdGhpcy5yZW1vdmVfaGVscGVyKG5vZGVUb1JlbW92ZSk7XG59O1xuXG5SQlRyZWUucHJvdG90eXBlLnJlbW92ZV9oZWxwZXIgPSBmdW5jdGlvbihub2RlVG9SZW1vdmUpIHtcbiAgdmFyIGxlZnQsIHJpZ2h0LCBuZXh0Tm9kZSwgY2hpbGROb2RlLCBwYXJlbnQ7XG5cbiAgLy8gaWYgdGhlcmUncyBvbmx5IG9uZSBjaGlsZCwgcmVwbGFjZSB0aGUgbm9kZVRvUmVtb3ZlIHRvIGRlbGV0ZSBieSBpdCdzIGNoaWxkIGFuZCB1cGRhdGVcbiAgLy8gdGhlIHJlZnMuXG4gIC8vIGlmIHRoZXJlJ3MgdHdvIGNoaWxkcmVuLCBmaW5kIGl0J3Mgc3VjY2Vzc29yIGFuZCByZXBsYWNlIHRoZSBub2RlVG9SZW1vdmUgdG8gZGVsZXRlIGJ5IGhpcyBzdWNjZXNzb3JcbiAgLy8gYW5kIHVwZGF0ZSB0aGUgcmVmc1xuXG4gIGlmICghbm9kZVRvUmVtb3ZlLmxlZnQgfHwgIW5vZGVUb1JlbW92ZS5yaWdodCkge1xuICAgIG5leHROb2RlID0gbm9kZVRvUmVtb3ZlO1xuICB9IGVsc2Uge1xuICAgIG5leHROb2RlID0gbm9kZVRvUmVtb3ZlLm5leHQoZnVuY3Rpb24obm9kZSkge1xuICAgICAgbm9kZS53ZWlnaHQgLT0gMTtcbiAgICB9KTtcbiAgfVxuXG4gIGlmIChuZXh0Tm9kZS5sZWZ0KSB7XG4gICAgY2hpbGROb2RlID0gbmV4dE5vZGUubGVmdDtcbiAgICBwYXJlbnQgPSBuZXh0Tm9kZS5wYXJlbnQ7XG4gIH0gZWxzZSB7XG4gICAgY2hpbGROb2RlID0gbmV4dE5vZGUucmlnaHQ7XG4gICAgcGFyZW50ID0gbmV4dE5vZGUucGFyZW50O1xuICB9XG5cbiAgaWYgKGNoaWxkTm9kZSkge1xuICAgIGNoaWxkTm9kZS5wYXJlbnQgPSBuZXh0Tm9kZS5wYXJlbnQ7XG4gIH1cblxuXG4gIGlmICghbmV4dE5vZGUucGFyZW50KSB7XG4gICAgdGhpcy5fcm9vdCA9IGNoaWxkTm9kZTtcbiAgfSBlbHNlIHtcbiAgICBpZiAobmV4dE5vZGUgPT09IG5leHROb2RlLnBhcmVudC5sZWZ0KSB7XG4gICAgICBuZXh0Tm9kZS5wYXJlbnQubGVmdCA9IGNoaWxkTm9kZTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV4dE5vZGUucGFyZW50LnJpZ2h0ID0gY2hpbGROb2RlO1xuICAgIH1cbiAgfVxuXG4gIC8vIHJlcGxhY2Ugbm9kZVRvUmVtb3ZlJ3MgZGF0YSBieSBuZXh0Tm9kZSdzIChzYW1lIGFzIHJlbW92aW5nIG5vZGVUb1JlbW92ZSwgdGhlbiBpbnNlcnRpbmcgbmV4dE5vZGUgYXQgaGlzIHBsYWNlXG4gIC8vIGJ1dCBlYXNpZXIgYW5kIG1vcmUgZWZmaWNpZW50KVxuICBpZiAobmV4dE5vZGUgIT09IG5vZGVUb1JlbW92ZSkge1xuICAgIG5vZGVUb1JlbW92ZS5kYXRhID0gbmV4dE5vZGUuZGF0YTtcbiAgICBub2RlVG9SZW1vdmUud2VpZ2h0ID0gKG5vZGVUb1JlbW92ZS5sZWZ0PyBub2RlVG9SZW1vdmUubGVmdC53ZWlnaHQ6IDApICtcbiAgICAgIChub2RlVG9SZW1vdmUucmlnaHQ/IG5vZGVUb1JlbW92ZS5yaWdodC53ZWlnaHQ6IDApICsgMTtcbiAgfVxuXG4gIGlmICghbmV4dE5vZGUucmVkKSB7XG4gICAgdGhpcy5yZW1vdmVfY29ycmVjdGlvbihjaGlsZE5vZGUsIHBhcmVudCk7XG4gIH1cblxuICByZXR1cm4gbmV4dE5vZGU7XG59O1xuXG5SQlRyZWUucHJvdG90eXBlLnJlbW92ZV9ub2RlID0gZnVuY3Rpb24obm9kZSkge1xuICBub2RlLnRyYXZlcnNlX3VwKGZ1bmN0aW9uKG5vZGUsIHBhcmVudCkge1xuICAgIHBhcmVudC53ZWlnaHQgLS07XG4gIH0pO1xuXG4gIHJldHVybiB0aGlzLnJlbW92ZV9oZWxwZXIobm9kZSk7XG59O1xuXG5SQlRyZWUucHJvdG90eXBlLnJlbW92ZV9jb3JyZWN0aW9uID0gZnVuY3Rpb24obm9kZSwgcGFyZW50KSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdmFyIG9wcG9zaXRlU2lkZTtcbiAgdmFyIGhlbHBlciA9IGZ1bmN0aW9uKHNpZGUpIHtcbiAgICB2YXIgbmVpZ2hib3IgPSBwYXJlbnQuZ2V0X2NoaWxkKHNpZGUsIHRydWUpO1xuXG4gICAgaWYgKG5laWdoYm9yICYmIG5laWdoYm9yLnJlZCkge1xuICAgICAgbmVpZ2hib3IucmVkID0gZmFsc2U7XG4gICAgICBwYXJlbnQucmVkICAgPSB0cnVlO1xuXG4gICAgICBzZWxmLnJvdGF0ZShzaWRlLCBwYXJlbnQpO1xuICAgICAgbmVpZ2hib3IgPSBwYXJlbnQuZ2V0X2NoaWxkKHNpZGUsIHRydWUpO1xuICAgIH1cblxuICAgIGlmICgoIW5laWdoYm9yLmxlZnQgfHwgIW5laWdoYm9yLmxlZnQucmVkKSAmJiAoIW5laWdoYm9yLnJpZ2h0IHx8ICFuZWlnaGJvci5yaWdodC5yZWQgKSkge1xuICAgICAgbmVpZ2hib3IucmVkID0gdHJ1ZTtcbiAgICAgIG5vZGUgPSBwYXJlbnQ7XG4gICAgICBwYXJlbnQgPSBub2RlLnBhcmVudDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKCFuZWlnaGJvci5nZXRfY2hpbGQoc2lkZSwgdHJ1ZSkgfHwgIW5laWdoYm9yLmdldF9jaGlsZChzaWRlLCB0cnVlKS5yZWQpIHtcbiAgICAgICAgaWYgKG5laWdoYm9yLmdldF9jaGlsZChzaWRlKSkge1xuICAgICAgICAgIG5laWdoYm9yLmdldF9jaGlsZChzaWRlKS5yZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBuZWlnaGJvci5yZWQgPSB0cnVlO1xuXG4gICAgICAgIG9wcG9zaXRlU2lkZSA9IHNpZGUgPT09ICdsZWZ0Jz8gJ3JpZ2h0JzogJ2xlZnQnO1xuICAgICAgICBzZWxmLnJvdGF0ZShvcHBvc2l0ZVNpZGUsIG5laWdoYm9yKTtcbiAgICAgICAgbmVpZ2hib3IgPSBwYXJlbnQuZ2V0X2NoaWxkKHNpZGUsIHRydWUpO1xuICAgICAgfVxuXG4gICAgICBuZWlnaGJvci5yZWQgPSBwYXJlbnQ/IHBhcmVudC5yZWQ6IGZhbHNlO1xuICAgICAgcGFyZW50LnJlZCAgID0gZmFsc2U7XG4gICAgICBpZiAobmVpZ2hib3IuZ2V0X2NoaWxkKHNpZGUsIHRydWUpKSB7XG4gICAgICAgIG5laWdoYm9yLmdldF9jaGlsZChzaWRlLCB0cnVlKS5yZWQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgc2VsZi5yb3RhdGUoc2lkZSwgcGFyZW50KTtcbiAgICAgIG5vZGUgPSBzZWxmLl9yb290O1xuICAgICAgcGFyZW50ID0gbm9kZS5wYXJlbnQ7XG4gICAgfVxuICB9O1xuICB3aGlsZSAobm9kZSAhPT0gdGhpcy5fcm9vdCAmJiAoIW5vZGUgfHwgIW5vZGUucmVkKSkge1xuICAgIGlmIChub2RlID09PSBwYXJlbnQuZ2V0X2NoaWxkKCdsZWZ0JykpIHtcbiAgICAgIHRtcCA9IGhlbHBlcignbGVmdCcpO1xuICAgIH0gZWxzZSBpZiAobm9kZSA9PT0gcGFyZW50LmdldF9jaGlsZCgncmlnaHQnKSkge1xuICAgICAgdG1wID0gaGVscGVyKCdyaWdodCcpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChub2RlKSB7XG4gICAgbm9kZS5yZWQgPSBmYWxzZTtcbiAgfVxufTtcblxuUkJUcmVlLnByb3RvdHlwZS5nZXRfc2l6ZSA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gKHRoaXMuX3Jvb3Q/IHRoaXMuX3Jvb3Qud2VpZ2h0IDogMCk7XG59O1xuXG5mdW5jdGlvbiBOb2RlKGRhdGEpIHtcbiAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgIHRoaXMubGVmdCA9IG51bGw7XG4gICAgdGhpcy5yaWdodCA9IG51bGw7XG4gICAgdGhpcy5wYXJlbnQgPSBudWxsO1xuICAgIHRoaXMucmVkID0gdHJ1ZTtcbiAgICB0aGlzLndlaWdodCA9IDE7XG59XG5cbk5vZGUucHJvdG90eXBlLmdldF9jaGlsZCA9IGZ1bmN0aW9uKHNpZGUsIG9wcG9zaXRlKSB7XG4gIGlmIChvcHBvc2l0ZSkge1xuICAgIHNpZGUgPSAoc2lkZSA9PT0gJ2xlZnQnKT8gJ3JpZ2h0JzogJ2xlZnQnO1xuICB9XG4gIHJldHVybiBzaWRlID09PSAnbGVmdCc/IHRoaXMubGVmdDogdGhpcy5yaWdodDtcbn07XG5cbk5vZGUucHJvdG90eXBlLnNldF9jaGlsZCA9IGZ1bmN0aW9uKHNpZGUsIG5vZGUsIG9wcG9zaXRlKSB7XG4gIGlmIChvcHBvc2l0ZSkge1xuICAgIHNpZGUgPSAoc2lkZSA9PT0gJ2xlZnQnKT8gJ3JpZ2h0JzogJ2xlZnQnO1xuICB9XG5cbiAgaWYgKHNpZGUgPT09ICdsZWZ0Jykge1xuICAgIHRoaXMubGVmdCA9IG5vZGU7XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5yaWdodCA9IG5vZGU7XG4gIH1cbn07XG5cbk5vZGUucHJvdG90eXBlLm1heF90cmVlID0gZnVuY3Rpb24oZnVuKSB7XG4gIHZhciBub2RlID0gdGhpcztcblxuICBpZiAoZnVuKSB7XG4gICAgZnVuKG5vZGUpO1xuICB9XG5cbiAgd2hpbGUgKG5vZGUucmlnaHQpIHtcbiAgICBub2RlID0gbm9kZS5yaWdodDtcbiAgICBpZiAoZnVuKSB7XG4gICAgICBmdW4obm9kZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5vZGU7XG59O1xuXG5Ob2RlLnByb3RvdHlwZS5taW5fdHJlZSA9IGZ1bmN0aW9uKGZ1bikge1xuICB2YXIgbm9kZSA9IHRoaXM7XG5cbiAgaWYgKGZ1bikge1xuICAgIGZ1bihub2RlKTtcbiAgfVxuXG4gIHdoaWxlIChub2RlLmxlZnQpIHtcbiAgICBub2RlID0gbm9kZS5sZWZ0O1xuICAgIGlmIChmdW4pIHtcbiAgICAgIGZ1bihub2RlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbm9kZTtcbn07XG5cblxuTm9kZS5wcm90b3R5cGUubmV4dCA9IGZ1bmN0aW9uKGZ1bikge1xuICB2YXIgbm9kZSwgcGFyZW50O1xuICBpZiAodGhpcy5nZXRfY2hpbGQoJ3JpZ2h0JykpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRfY2hpbGQoJ3JpZ2h0JykubWluX3RyZWUoZnVuKTtcbiAgfVxuXG4gIGlmIChmdW4pIHtcbiAgICBmdW4odGhpcyk7XG4gIH1cbiAgbm9kZSA9IHRoaXM7XG4gIHBhcmVudCA9IHRoaXMucGFyZW50O1xuICB3aGlsZSAocGFyZW50ICYmIG5vZGUgPT09IHBhcmVudC5nZXRfY2hpbGQoJ3JpZ2h0JykpIHtcbiAgICBub2RlID0gcGFyZW50O1xuICAgIHBhcmVudCA9IG5vZGUucGFyZW50O1xuXG4gICAgaWYgKGZ1bikge1xuICAgICAgZnVuKHBhcmVudCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHBhcmVudDtcbn07XG5cbk5vZGUucHJvdG90eXBlLnByZXYgPSBmdW5jdGlvbihmdW4pIHtcbiAgdmFyIG5vZGUsIHBhcmVudDtcbiAgaWYgKHRoaXMuZ2V0X2NoaWxkKCdsZWZ0JykpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRfY2hpbGQoJ2xlZnQnKS5tYXhfdHJlZShmdW4pO1xuICB9XG5cbiAgaWYgKGZ1bikge1xuICAgIGZ1bih0aGlzKTtcbiAgfVxuICBub2RlID0gdGhpcztcbiAgcGFyZW50ID0gdGhpcy5wYXJlbnQ7XG4gIHdoaWxlIChwYXJlbnQgJiYgbm9kZSA9PT0gcGFyZW50LmdldF9jaGlsZCgnbGVmdCcpKSB7XG4gICAgbm9kZSA9IHBhcmVudDtcbiAgICBwYXJlbnQgPSBub2RlLnBhcmVudDtcblxuICAgIGlmIChmdW4pIHtcbiAgICAgIGZ1bihwYXJlbnQpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBwYXJlbnQ7XG59O1xuXG4vKiogVHJhdmVyc2UgdGhlIHRyZWUgdXB3YXJkcyB1bnRpbCBpdCByZWFjaGVzIHRoZSB0b3AuIEZvciBlYWNoIG5vZGUgdHJhdmVyc2VkLFxuICAqIGNhbGwgdGhlIGZ1bmN0aW9uIHBhc3NlZCBhcyBhcmd1bWVudCB3aXRoIGFyZ3VtZW50cyBub2RlLCBwYXJlbnQuXG4gICogVGhlIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIGgtMSB0aW1lcywgaCBiZWluZyB0aGUgaGVpZ2h0IG9mIHRoZSBicmFuY2guXG4gICoqL1xuTm9kZS5wcm90b3R5cGUudHJhdmVyc2VfdXAgPSBmdW5jdGlvbihmdW4pIHtcbiAgdmFyIHBhcmVudCA9IHRoaXMucGFyZW50O1xuICB2YXIgbm9kZSA9IHRoaXM7XG5cbiAgd2hpbGUocGFyZW50KSB7XG4gICAgZnVuKG5vZGUsIHBhcmVudCk7XG4gICAgbm9kZSA9IHBhcmVudDtcbiAgICBwYXJlbnQgPSBwYXJlbnQucGFyZW50O1xuICB9XG59O1xuXG5Ob2RlLnByb3RvdHlwZS5kZXB0aCA9IGZ1bmN0aW9uKCkge1xuICB2YXIgZGVwdGggPSAwO1xuICB0aGlzLnRyYXZlcnNlX3VwKGZ1bmN0aW9uKCkge1xuICAgIGRlcHRoICsrO1xuICB9KTtcbiAgcmV0dXJuIGRlcHRoO1xufTtcblxuTm9kZS5wcm90b3R5cGUucG9zaXRpb24gPSBmdW5jdGlvbigpIHtcbiAgdmFyIHBvc2l0aW9uID0gdGhpcy5sZWZ0PyB0aGlzLmxlZnQud2VpZ2h0OiAwO1xuICB2YXIgY291bnRGdW4gPSBmdW5jdGlvbihub2RlLCBwYXJlbnQpIHtcbiAgICBpZiAocGFyZW50LnJpZ2h0ID09PSBub2RlKSB7XG4gICAgICAvLyBmb3IgdGhlIGxlZnQgc3VidHJlZVxuICAgICAgaWYgKHBhcmVudC5sZWZ0KSB7XG4gICAgICAgIHBvc2l0aW9uICs9IHBhcmVudC5sZWZ0LndlaWdodDtcbiAgICAgIH1cbiAgICAgIHBvc2l0aW9uICs9IDE7IC8vIGZvciB0aGUgcGFyZW50XG4gICAgfVxuICB9O1xuXG4gIHRoaXMudHJhdmVyc2VfdXAoY291bnRGdW4pO1xuICByZXR1cm4gcG9zaXRpb247XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFJCVHJlZTtcbiIsIlxuZnVuY3Rpb24gVHJlZUJhc2UoKSB7fVxuXG4vLyByZW1vdmVzIGFsbCBub2RlcyBmcm9tIHRoZSB0cmVlXG5UcmVlQmFzZS5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl9yb290ID0gbnVsbDtcbiAgICB0aGlzLnNpemUgPSAwO1xufTtcblxuLy8gcmV0dXJucyBub2RlIGRhdGEgaWYgZm91bmQsIG51bGwgb3RoZXJ3aXNlXG5UcmVlQmFzZS5wcm90b3R5cGUuZmluZCA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICB2YXIgcmVzID0gdGhpcy5fcm9vdDtcblxuICAgIHdoaWxlKHJlcyAhPT0gbnVsbCkge1xuICAgICAgICB2YXIgYyA9IHRoaXMuX2NvbXBhcmF0b3IoZGF0YSwgcmVzLmRhdGEpO1xuICAgICAgICBpZihjID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzLmRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICByZXMgPSByZXMuZ2V0X2NoaWxkKGMgPiAwKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xufTtcblxuLy8gcmV0dXJucyBpdGVyYXRvciB0byBub2RlIGlmIGZvdW5kLCBudWxsIG90aGVyd2lzZVxuVHJlZUJhc2UucHJvdG90eXBlLmZpbmRJdGVyID0gZnVuY3Rpb24oZGF0YSkge1xuICAgIHZhciByZXMgPSB0aGlzLl9yb290O1xuICAgIHZhciBpdGVyID0gdGhpcy5pdGVyYXRvcigpO1xuXG4gICAgd2hpbGUocmVzICE9PSBudWxsKSB7XG4gICAgICAgIHZhciBjID0gdGhpcy5fY29tcGFyYXRvcihkYXRhLCByZXMuZGF0YSk7XG4gICAgICAgIGlmKGMgPT09IDApIHtcbiAgICAgICAgICAgIGl0ZXIuX2N1cnNvciA9IHJlcztcbiAgICAgICAgICAgIHJldHVybiBpdGVyO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaXRlci5fYW5jZXN0b3JzLnB1c2gocmVzKTtcbiAgICAgICAgICAgIHJlcyA9IHJlcy5nZXRfY2hpbGQoYyA+IDApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59O1xuXG4vLyBSZXR1cm5zIGFuIGludGVyYXRvciB0byB0aGUgdHJlZSBub2RlIGF0IG9yIGltbWVkaWF0ZWx5IGFmdGVyIHRoZSBpdGVtXG5UcmVlQmFzZS5wcm90b3R5cGUubG93ZXJCb3VuZCA9IGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICB2YXIgY3VyID0gdGhpcy5fcm9vdDtcbiAgICB2YXIgaXRlciA9IHRoaXMuaXRlcmF0b3IoKTtcbiAgICB2YXIgY21wID0gdGhpcy5fY29tcGFyYXRvcjtcblxuICAgIHdoaWxlKGN1ciAhPT0gbnVsbCkge1xuICAgICAgICB2YXIgYyA9IGNtcChpdGVtLCBjdXIuZGF0YSk7XG4gICAgICAgIGlmKGMgPT09IDApIHtcbiAgICAgICAgICAgIGl0ZXIuX2N1cnNvciA9IGN1cjtcbiAgICAgICAgICAgIHJldHVybiBpdGVyO1xuICAgICAgICB9XG4gICAgICAgIGl0ZXIuX2FuY2VzdG9ycy5wdXNoKGN1cik7XG4gICAgICAgIGN1ciA9IGN1ci5nZXRfY2hpbGQoYyA+IDApO1xuICAgIH1cblxuICAgIGZvcih2YXIgaT1pdGVyLl9hbmNlc3RvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHtcbiAgICAgICAgY3VyID0gaXRlci5fYW5jZXN0b3JzW2ldO1xuICAgICAgICBpZihjbXAoaXRlbSwgY3VyLmRhdGEpIDwgMCkge1xuICAgICAgICAgICAgaXRlci5fY3Vyc29yID0gY3VyO1xuICAgICAgICAgICAgaXRlci5fYW5jZXN0b3JzLmxlbmd0aCA9IGk7XG4gICAgICAgICAgICByZXR1cm4gaXRlcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGl0ZXIuX2FuY2VzdG9ycy5sZW5ndGggPSAwO1xuICAgIHJldHVybiBpdGVyO1xufTtcblxuLy8gUmV0dXJucyBhbiBpbnRlcmF0b3IgdG8gdGhlIHRyZWUgbm9kZSBpbW1lZGlhdGVseSBhZnRlciB0aGUgaXRlbVxuVHJlZUJhc2UucHJvdG90eXBlLnVwcGVyQm91bmQgPSBmdW5jdGlvbihpdGVtKSB7XG4gICAgdmFyIGl0ZXIgPSB0aGlzLmxvd2VyQm91bmQoaXRlbSk7XG4gICAgdmFyIGNtcCA9IHRoaXMuX2NvbXBhcmF0b3I7XG5cbiAgICB3aGlsZShjbXAoaXRlci5kYXRhKCksIGl0ZW0pID09PSAwKSB7XG4gICAgICAgIGl0ZXIubmV4dCgpO1xuICAgIH1cblxuICAgIHJldHVybiBpdGVyO1xufTtcblxuLy8gcmV0dXJucyBudWxsIGlmIHRyZWUgaXMgZW1wdHlcblRyZWVCYXNlLnByb3RvdHlwZS5taW4gPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcmVzID0gdGhpcy5fcm9vdDtcbiAgICBpZihyZXMgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgd2hpbGUocmVzLmxlZnQgIT09IG51bGwpIHtcbiAgICAgICAgcmVzID0gcmVzLmxlZnQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlcy5kYXRhO1xufTtcblxuLy8gcmV0dXJucyBudWxsIGlmIHRyZWUgaXMgZW1wdHlcblRyZWVCYXNlLnByb3RvdHlwZS5tYXggPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgcmVzID0gdGhpcy5fcm9vdDtcbiAgICBpZihyZXMgPT09IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgd2hpbGUocmVzLnJpZ2h0ICE9PSBudWxsKSB7XG4gICAgICAgIHJlcyA9IHJlcy5yaWdodDtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzLmRhdGE7XG59O1xuXG4vLyByZXR1cm5zIGEgbnVsbCBpdGVyYXRvclxuLy8gY2FsbCBuZXh0KCkgb3IgcHJldigpIHRvIHBvaW50IHRvIGFuIGVsZW1lbnRcblRyZWVCYXNlLnByb3RvdHlwZS5pdGVyYXRvciA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBuZXcgSXRlcmF0b3IodGhpcyk7XG59O1xuXG5cblRyZWVCYXNlLnByb3RvdHlwZS5lYWNoTm9kZSA9IGZ1bmN0aW9uKGNiKSB7XG4gICAgdmFyIGl0PXRoaXMuaXRlcmF0b3IoKSwgbm9kZTtcbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHdoaWxlKChub2RlID0gaXQubmV4dCgpKSAhPT0gbnVsbCkge1xuICAgICAgICBjYihub2RlLCBpbmRleCk7XG4gICAgICAgIGluZGV4Kys7XG4gICAgfVxufTtcblxuLy8gY2FsbHMgY2Igb24gZWFjaCBub2RlJ3MgZGF0YSwgaW4gb3JkZXJcblRyZWVCYXNlLnByb3RvdHlwZS5lYWNoID0gZnVuY3Rpb24oY2IpIHtcbiAgICB0aGlzLmVhY2hOb2RlKGZ1bmN0aW9uKG5vZGUsIGluZGV4KSB7XG4gICAgICAgIGNiKG5vZGUuZGF0YSwgaW5kZXgpO1xuICAgIH0pO1xufTtcblxuXG5UcmVlQmFzZS5wcm90b3R5cGUubWFwTm9kZSA9IGZ1bmN0aW9uKGNiKSB7XG4gICAgdmFyIGl0PXRoaXMuaXRlcmF0b3IoKSwgbm9kZTtcbiAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgIHZhciBpbmRleCA9IDA7XG4gICAgd2hpbGUoKG5vZGUgPSBpdC5uZXh0KCkpICE9PSBudWxsKSB7XG4gICAgICAgIHJlc3VsdHMucHVzaChjYihub2RlLCBpbmRleCkpO1xuICAgICAgICBpbmRleCArKztcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdHM7XG59O1xuXG4vLyBjYWxscyBjYiBvbiBlYWNoIG5vZGUtcyBkYXRhLCBzdG9yZSB0aGUgcmVzdWx0IGFuZCByZXR1cm4gaXRcblRyZWVCYXNlLnByb3RvdHlwZS5tYXAgPSBmdW5jdGlvbihjYikge1xuICAgIHJldHVybiB0aGlzLm1hcE5vZGUoZnVuY3Rpb24obm9kZSwgaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIGNiKG5vZGUuZGF0YSwgaW5kZXgpO1xuICAgIH0pO1xufTtcblxuZnVuY3Rpb24gSXRlcmF0b3IodHJlZSkge1xuICAgIHRoaXMuX3RyZWUgPSB0cmVlO1xuICAgIHRoaXMuX2FuY2VzdG9ycyA9IFtdO1xuICAgIHRoaXMuX2N1cnNvciA9IG51bGw7XG59XG5cbkl0ZXJhdG9yLnByb3RvdHlwZS5kYXRhID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX2N1cnNvciAhPT0gbnVsbCA/IHRoaXMuX2N1cnNvci5kYXRhIDogbnVsbDtcbn07XG5cbi8vIGlmIG51bGwtaXRlcmF0b3IsIHJldHVybnMgZmlyc3Qgbm9kZVxuLy8gb3RoZXJ3aXNlLCByZXR1cm5zIG5leHQgbm9kZVxuSXRlcmF0b3IucHJvdG90eXBlLm5leHQgPSBmdW5jdGlvbigpIHtcbiAgICBpZih0aGlzLl9jdXJzb3IgPT09IG51bGwpIHtcbiAgICAgICAgdmFyIHJvb3QgPSB0aGlzLl90cmVlLl9yb290O1xuICAgICAgICBpZihyb290ICE9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLl9taW5Ob2RlKHJvb3QpO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBpZih0aGlzLl9jdXJzb3IucmlnaHQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIG5vIGdyZWF0ZXIgbm9kZSBpbiBzdWJ0cmVlLCBnbyB1cCB0byBwYXJlbnRcbiAgICAgICAgICAgIC8vIGlmIGNvbWluZyBmcm9tIGEgcmlnaHQgY2hpbGQsIGNvbnRpbnVlIHVwIHRoZSBzdGFja1xuICAgICAgICAgICAgdmFyIHNhdmU7XG4gICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgc2F2ZSA9IHRoaXMuX2N1cnNvcjtcbiAgICAgICAgICAgICAgICBpZih0aGlzLl9hbmNlc3RvcnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2N1cnNvciA9IHRoaXMuX2FuY2VzdG9ycy5wb3AoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2N1cnNvciA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gd2hpbGUodGhpcy5fY3Vyc29yLnJpZ2h0ID09PSBzYXZlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8vIGdldCB0aGUgbmV4dCBub2RlIGZyb20gdGhlIHN1YnRyZWVcbiAgICAgICAgICAgIHRoaXMuX2FuY2VzdG9ycy5wdXNoKHRoaXMuX2N1cnNvcik7XG4gICAgICAgICAgICB0aGlzLl9taW5Ob2RlKHRoaXMuX2N1cnNvci5yaWdodCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2N1cnNvciAhPT0gbnVsbCA/IHRoaXMuX2N1cnNvciA6IG51bGw7XG59O1xuXG4vLyBpZiBudWxsLWl0ZXJhdG9yLCByZXR1cm5zIGxhc3Qgbm9kZVxuLy8gb3RoZXJ3aXNlLCByZXR1cm5zIHByZXZpb3VzIG5vZGVcbkl0ZXJhdG9yLnByb3RvdHlwZS5wcmV2ID0gZnVuY3Rpb24oKSB7XG4gICAgaWYodGhpcy5fY3Vyc29yID09PSBudWxsKSB7XG4gICAgICAgIHZhciByb290ID0gdGhpcy5fdHJlZS5fcm9vdDtcbiAgICAgICAgaWYocm9vdCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5fbWF4Tm9kZShyb290KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWYodGhpcy5fY3Vyc29yLmxlZnQgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBzYXZlO1xuICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgIHNhdmUgPSB0aGlzLl9jdXJzb3I7XG4gICAgICAgICAgICAgICAgaWYodGhpcy5fYW5jZXN0b3JzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jdXJzb3IgPSB0aGlzLl9hbmNlc3RvcnMucG9wKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jdXJzb3IgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IHdoaWxlKHRoaXMuX2N1cnNvci5sZWZ0ID09PSBzYXZlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2FuY2VzdG9ycy5wdXNoKHRoaXMuX2N1cnNvcik7XG4gICAgICAgICAgICB0aGlzLl9tYXhOb2RlKHRoaXMuX2N1cnNvci5sZWZ0KTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fY3Vyc29yICE9PSBudWxsID8gdGhpcy5fY3Vyc29yIDogbnVsbDtcbn07XG5cbkl0ZXJhdG9yLnByb3RvdHlwZS5fbWluTm9kZSA9IGZ1bmN0aW9uKHN0YXJ0KSB7XG4gICAgd2hpbGUoc3RhcnQubGVmdCAhPT0gbnVsbCkge1xuICAgICAgICB0aGlzLl9hbmNlc3RvcnMucHVzaChzdGFydCk7XG4gICAgICAgIHN0YXJ0ID0gc3RhcnQubGVmdDtcbiAgICB9XG4gICAgdGhpcy5fY3Vyc29yID0gc3RhcnQ7XG59O1xuXG5JdGVyYXRvci5wcm90b3R5cGUuX21heE5vZGUgPSBmdW5jdGlvbihzdGFydCkge1xuICAgIHdoaWxlKHN0YXJ0LnJpZ2h0ICE9PSBudWxsKSB7XG4gICAgICAgIHRoaXMuX2FuY2VzdG9ycy5wdXNoKHN0YXJ0KTtcbiAgICAgICAgc3RhcnQgPSBzdGFydC5yaWdodDtcbiAgICB9XG4gICAgdGhpcy5fY3Vyc29yID0gc3RhcnQ7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFRyZWVCYXNlO1xuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL2xpYi9jaGFpJyk7XG4iLCIvKiFcbiAqIGNoYWlcbiAqIENvcHlyaWdodChjKSAyMDExLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG52YXIgdXNlZCA9IFtdXG4gICwgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbi8qIVxuICogQ2hhaSB2ZXJzaW9uXG4gKi9cblxuZXhwb3J0cy52ZXJzaW9uID0gJzIuMy4wJztcblxuLyohXG4gKiBBc3NlcnRpb24gRXJyb3JcbiAqL1xuXG5leHBvcnRzLkFzc2VydGlvbkVycm9yID0gcmVxdWlyZSgnYXNzZXJ0aW9uLWVycm9yJyk7XG5cbi8qIVxuICogVXRpbHMgZm9yIHBsdWdpbnMgKG5vdCBleHBvcnRlZClcbiAqL1xuXG52YXIgdXRpbCA9IHJlcXVpcmUoJy4vY2hhaS91dGlscycpO1xuXG4vKipcbiAqICMgLnVzZShmdW5jdGlvbilcbiAqXG4gKiBQcm92aWRlcyBhIHdheSB0byBleHRlbmQgdGhlIGludGVybmFscyBvZiBDaGFpXG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn1cbiAqIEByZXR1cm5zIHt0aGlzfSBmb3IgY2hhaW5pbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZXhwb3J0cy51c2UgPSBmdW5jdGlvbiAoZm4pIHtcbiAgaWYgKCF+dXNlZC5pbmRleE9mKGZuKSkge1xuICAgIGZuKHRoaXMsIHV0aWwpO1xuICAgIHVzZWQucHVzaChmbik7XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cbi8qIVxuICogVXRpbGl0eSBGdW5jdGlvbnNcbiAqL1xuXG5leHBvcnRzLnV0aWwgPSB1dGlsO1xuXG4vKiFcbiAqIENvbmZpZ3VyYXRpb25cbiAqL1xuXG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi9jaGFpL2NvbmZpZycpO1xuZXhwb3J0cy5jb25maWcgPSBjb25maWc7XG5cbi8qIVxuICogUHJpbWFyeSBgQXNzZXJ0aW9uYCBwcm90b3R5cGVcbiAqL1xuXG52YXIgYXNzZXJ0aW9uID0gcmVxdWlyZSgnLi9jaGFpL2Fzc2VydGlvbicpO1xuZXhwb3J0cy51c2UoYXNzZXJ0aW9uKTtcblxuLyohXG4gKiBDb3JlIEFzc2VydGlvbnNcbiAqL1xuXG52YXIgY29yZSA9IHJlcXVpcmUoJy4vY2hhaS9jb3JlL2Fzc2VydGlvbnMnKTtcbmV4cG9ydHMudXNlKGNvcmUpO1xuXG4vKiFcbiAqIEV4cGVjdCBpbnRlcmZhY2VcbiAqL1xuXG52YXIgZXhwZWN0ID0gcmVxdWlyZSgnLi9jaGFpL2ludGVyZmFjZS9leHBlY3QnKTtcbmV4cG9ydHMudXNlKGV4cGVjdCk7XG5cbi8qIVxuICogU2hvdWxkIGludGVyZmFjZVxuICovXG5cbnZhciBzaG91bGQgPSByZXF1aXJlKCcuL2NoYWkvaW50ZXJmYWNlL3Nob3VsZCcpO1xuZXhwb3J0cy51c2Uoc2hvdWxkKTtcblxuLyohXG4gKiBBc3NlcnQgaW50ZXJmYWNlXG4gKi9cblxudmFyIGFzc2VydCA9IHJlcXVpcmUoJy4vY2hhaS9pbnRlcmZhY2UvYXNzZXJ0Jyk7XG5leHBvcnRzLnVzZShhc3NlcnQpO1xuIiwiLyohXG4gKiBjaGFpXG4gKiBodHRwOi8vY2hhaWpzLmNvbVxuICogQ29weXJpZ2h0KGMpIDIwMTEtMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbnZhciBjb25maWcgPSByZXF1aXJlKCcuL2NvbmZpZycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChfY2hhaSwgdXRpbCkge1xuICAvKiFcbiAgICogTW9kdWxlIGRlcGVuZGVuY2llcy5cbiAgICovXG5cbiAgdmFyIEFzc2VydGlvbkVycm9yID0gX2NoYWkuQXNzZXJ0aW9uRXJyb3JcbiAgICAsIGZsYWcgPSB1dGlsLmZsYWc7XG5cbiAgLyohXG4gICAqIE1vZHVsZSBleHBvcnQuXG4gICAqL1xuXG4gIF9jaGFpLkFzc2VydGlvbiA9IEFzc2VydGlvbjtcblxuICAvKiFcbiAgICogQXNzZXJ0aW9uIENvbnN0cnVjdG9yXG4gICAqXG4gICAqIENyZWF0ZXMgb2JqZWN0IGZvciBjaGFpbmluZy5cbiAgICpcbiAgICogQGFwaSBwcml2YXRlXG4gICAqL1xuXG4gIGZ1bmN0aW9uIEFzc2VydGlvbiAob2JqLCBtc2csIHN0YWNrKSB7XG4gICAgZmxhZyh0aGlzLCAnc3NmaScsIHN0YWNrIHx8IGFyZ3VtZW50cy5jYWxsZWUpO1xuICAgIGZsYWcodGhpcywgJ29iamVjdCcsIG9iaik7XG4gICAgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gIH1cblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoQXNzZXJ0aW9uLCAnaW5jbHVkZVN0YWNrJywge1xuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ0Fzc2VydGlvbi5pbmNsdWRlU3RhY2sgaXMgZGVwcmVjYXRlZCwgdXNlIGNoYWkuY29uZmlnLmluY2x1ZGVTdGFjayBpbnN0ZWFkLicpO1xuICAgICAgcmV0dXJuIGNvbmZpZy5pbmNsdWRlU3RhY2s7XG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ0Fzc2VydGlvbi5pbmNsdWRlU3RhY2sgaXMgZGVwcmVjYXRlZCwgdXNlIGNoYWkuY29uZmlnLmluY2x1ZGVTdGFjayBpbnN0ZWFkLicpO1xuICAgICAgY29uZmlnLmluY2x1ZGVTdGFjayA9IHZhbHVlO1xuICAgIH1cbiAgfSk7XG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFzc2VydGlvbiwgJ3Nob3dEaWZmJywge1xuICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ0Fzc2VydGlvbi5zaG93RGlmZiBpcyBkZXByZWNhdGVkLCB1c2UgY2hhaS5jb25maWcuc2hvd0RpZmYgaW5zdGVhZC4nKTtcbiAgICAgIHJldHVybiBjb25maWcuc2hvd0RpZmY7XG4gICAgfSxcbiAgICBzZXQ6IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ0Fzc2VydGlvbi5zaG93RGlmZiBpcyBkZXByZWNhdGVkLCB1c2UgY2hhaS5jb25maWcuc2hvd0RpZmYgaW5zdGVhZC4nKTtcbiAgICAgIGNvbmZpZy5zaG93RGlmZiA9IHZhbHVlO1xuICAgIH1cbiAgfSk7XG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5ID0gZnVuY3Rpb24gKG5hbWUsIGZuKSB7XG4gICAgdXRpbC5hZGRQcm9wZXJ0eSh0aGlzLnByb3RvdHlwZSwgbmFtZSwgZm4pO1xuICB9O1xuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QgPSBmdW5jdGlvbiAobmFtZSwgZm4pIHtcbiAgICB1dGlsLmFkZE1ldGhvZCh0aGlzLnByb3RvdHlwZSwgbmFtZSwgZm4pO1xuICB9O1xuXG4gIEFzc2VydGlvbi5hZGRDaGFpbmFibGVNZXRob2QgPSBmdW5jdGlvbiAobmFtZSwgZm4sIGNoYWluaW5nQmVoYXZpb3IpIHtcbiAgICB1dGlsLmFkZENoYWluYWJsZU1ldGhvZCh0aGlzLnByb3RvdHlwZSwgbmFtZSwgZm4sIGNoYWluaW5nQmVoYXZpb3IpO1xuICB9O1xuXG4gIEFzc2VydGlvbi5vdmVyd3JpdGVQcm9wZXJ0eSA9IGZ1bmN0aW9uIChuYW1lLCBmbikge1xuICAgIHV0aWwub3ZlcndyaXRlUHJvcGVydHkodGhpcy5wcm90b3R5cGUsIG5hbWUsIGZuKTtcbiAgfTtcblxuICBBc3NlcnRpb24ub3ZlcndyaXRlTWV0aG9kID0gZnVuY3Rpb24gKG5hbWUsIGZuKSB7XG4gICAgdXRpbC5vdmVyd3JpdGVNZXRob2QodGhpcy5wcm90b3R5cGUsIG5hbWUsIGZuKTtcbiAgfTtcblxuICBBc3NlcnRpb24ub3ZlcndyaXRlQ2hhaW5hYmxlTWV0aG9kID0gZnVuY3Rpb24gKG5hbWUsIGZuLCBjaGFpbmluZ0JlaGF2aW9yKSB7XG4gICAgdXRpbC5vdmVyd3JpdGVDaGFpbmFibGVNZXRob2QodGhpcy5wcm90b3R5cGUsIG5hbWUsIGZuLCBjaGFpbmluZ0JlaGF2aW9yKTtcbiAgfTtcblxuICAvKiFcbiAgICogIyMjIC5hc3NlcnQoZXhwcmVzc2lvbiwgbWVzc2FnZSwgbmVnYXRlTWVzc2FnZSwgZXhwZWN0ZWQsIGFjdHVhbClcbiAgICpcbiAgICogRXhlY3V0ZXMgYW4gZXhwcmVzc2lvbiBhbmQgY2hlY2sgZXhwZWN0YXRpb25zLiBUaHJvd3MgQXNzZXJ0aW9uRXJyb3IgZm9yIHJlcG9ydGluZyBpZiB0ZXN0IGRvZXNuJ3QgcGFzcy5cbiAgICpcbiAgICogQG5hbWUgYXNzZXJ0XG4gICAqIEBwYXJhbSB7UGhpbG9zb3BoaWNhbH0gZXhwcmVzc2lvbiB0byBiZSB0ZXN0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmcgb3IgRnVuY3Rpb259IG1lc3NhZ2Ugb3IgZnVuY3Rpb24gdGhhdCByZXR1cm5zIG1lc3NhZ2UgdG8gZGlzcGxheSBpZiBleHByZXNzaW9uIGZhaWxzXG4gICAqIEBwYXJhbSB7U3RyaW5nIG9yIEZ1bmN0aW9ufSBuZWdhdGVkTWVzc2FnZSBvciBmdW5jdGlvbiB0aGF0IHJldHVybnMgbmVnYXRlZE1lc3NhZ2UgdG8gZGlzcGxheSBpZiBuZWdhdGVkIGV4cHJlc3Npb24gZmFpbHNcbiAgICogQHBhcmFtIHtNaXhlZH0gZXhwZWN0ZWQgdmFsdWUgKHJlbWVtYmVyIHRvIGNoZWNrIGZvciBuZWdhdGlvbilcbiAgICogQHBhcmFtIHtNaXhlZH0gYWN0dWFsIChvcHRpb25hbCkgd2lsbCBkZWZhdWx0IHRvIGB0aGlzLm9iamBcbiAgICogQHBhcmFtIHtCb29sZWFufSBzaG93RGlmZiAob3B0aW9uYWwpIHdoZW4gc2V0IHRvIGB0cnVlYCwgYXNzZXJ0IHdpbGwgZGlzcGxheSBhIGRpZmYgaW4gYWRkaXRpb24gdG8gdGhlIG1lc3NhZ2UgaWYgZXhwcmVzc2lvbiBmYWlsc1xuICAgKiBAYXBpIHByaXZhdGVcbiAgICovXG5cbiAgQXNzZXJ0aW9uLnByb3RvdHlwZS5hc3NlcnQgPSBmdW5jdGlvbiAoZXhwciwgbXNnLCBuZWdhdGVNc2csIGV4cGVjdGVkLCBfYWN0dWFsLCBzaG93RGlmZikge1xuICAgIHZhciBvayA9IHV0aWwudGVzdCh0aGlzLCBhcmd1bWVudHMpO1xuICAgIGlmICh0cnVlICE9PSBzaG93RGlmZikgc2hvd0RpZmYgPSBmYWxzZTtcbiAgICBpZiAodHJ1ZSAhPT0gY29uZmlnLnNob3dEaWZmKSBzaG93RGlmZiA9IGZhbHNlO1xuXG4gICAgaWYgKCFvaykge1xuICAgICAgdmFyIG1zZyA9IHV0aWwuZ2V0TWVzc2FnZSh0aGlzLCBhcmd1bWVudHMpXG4gICAgICAgICwgYWN0dWFsID0gdXRpbC5nZXRBY3R1YWwodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIHRocm93IG5ldyBBc3NlcnRpb25FcnJvcihtc2csIHtcbiAgICAgICAgICBhY3R1YWw6IGFjdHVhbFxuICAgICAgICAsIGV4cGVjdGVkOiBleHBlY3RlZFxuICAgICAgICAsIHNob3dEaWZmOiBzaG93RGlmZlxuICAgICAgfSwgKGNvbmZpZy5pbmNsdWRlU3RhY2spID8gdGhpcy5hc3NlcnQgOiBmbGFnKHRoaXMsICdzc2ZpJykpO1xuICAgIH1cbiAgfTtcblxuICAvKiFcbiAgICogIyMjIC5fb2JqXG4gICAqXG4gICAqIFF1aWNrIHJlZmVyZW5jZSB0byBzdG9yZWQgYGFjdHVhbGAgdmFsdWUgZm9yIHBsdWdpbiBkZXZlbG9wZXJzLlxuICAgKlxuICAgKiBAYXBpIHByaXZhdGVcbiAgICovXG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEFzc2VydGlvbi5wcm90b3R5cGUsICdfb2JqJyxcbiAgICB7IGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgICB9XG4gICAgLCBzZXQ6IGZ1bmN0aW9uICh2YWwpIHtcbiAgICAgICAgZmxhZyh0aGlzLCAnb2JqZWN0JywgdmFsKTtcbiAgICAgIH1cbiAgfSk7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSB7XG5cbiAgLyoqXG4gICAqICMjIyBjb25maWcuaW5jbHVkZVN0YWNrXG4gICAqXG4gICAqIFVzZXIgY29uZmlndXJhYmxlIHByb3BlcnR5LCBpbmZsdWVuY2VzIHdoZXRoZXIgc3RhY2sgdHJhY2VcbiAgICogaXMgaW5jbHVkZWQgaW4gQXNzZXJ0aW9uIGVycm9yIG1lc3NhZ2UuIERlZmF1bHQgb2YgZmFsc2VcbiAgICogc3VwcHJlc3NlcyBzdGFjayB0cmFjZSBpbiB0aGUgZXJyb3IgbWVzc2FnZS5cbiAgICpcbiAgICogICAgIGNoYWkuY29uZmlnLmluY2x1ZGVTdGFjayA9IHRydWU7ICAvLyBlbmFibGUgc3RhY2sgb24gZXJyb3JcbiAgICpcbiAgICogQHBhcmFtIHtCb29sZWFufVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICAgaW5jbHVkZVN0YWNrOiBmYWxzZSxcblxuICAvKipcbiAgICogIyMjIGNvbmZpZy5zaG93RGlmZlxuICAgKlxuICAgKiBVc2VyIGNvbmZpZ3VyYWJsZSBwcm9wZXJ0eSwgaW5mbHVlbmNlcyB3aGV0aGVyIG9yIG5vdFxuICAgKiB0aGUgYHNob3dEaWZmYCBmbGFnIHNob3VsZCBiZSBpbmNsdWRlZCBpbiB0aGUgdGhyb3duXG4gICAqIEFzc2VydGlvbkVycm9ycy4gYGZhbHNlYCB3aWxsIGFsd2F5cyBiZSBgZmFsc2VgOyBgdHJ1ZWBcbiAgICogd2lsbCBiZSB0cnVlIHdoZW4gdGhlIGFzc2VydGlvbiBoYXMgcmVxdWVzdGVkIGEgZGlmZlxuICAgKiBiZSBzaG93bi5cbiAgICpcbiAgICogQHBhcmFtIHtCb29sZWFufVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBzaG93RGlmZjogdHJ1ZSxcblxuICAvKipcbiAgICogIyMjIGNvbmZpZy50cnVuY2F0ZVRocmVzaG9sZFxuICAgKlxuICAgKiBVc2VyIGNvbmZpZ3VyYWJsZSBwcm9wZXJ0eSwgc2V0cyBsZW5ndGggdGhyZXNob2xkIGZvciBhY3R1YWwgYW5kXG4gICAqIGV4cGVjdGVkIHZhbHVlcyBpbiBhc3NlcnRpb24gZXJyb3JzLiBJZiB0aGlzIHRocmVzaG9sZCBpcyBleGNlZWRlZCwgZm9yXG4gICAqIGV4YW1wbGUgZm9yIGxhcmdlIGRhdGEgc3RydWN0dXJlcywgdGhlIHZhbHVlIGlzIHJlcGxhY2VkIHdpdGggc29tZXRoaW5nXG4gICAqIGxpa2UgYFsgQXJyYXkoMykgXWAgb3IgYHsgT2JqZWN0IChwcm9wMSwgcHJvcDIpIH1gLlxuICAgKlxuICAgKiBTZXQgaXQgdG8gemVybyBpZiB5b3Ugd2FudCB0byBkaXNhYmxlIHRydW5jYXRpbmcgYWx0b2dldGhlci5cbiAgICpcbiAgICogVGhpcyBpcyBlc3BlY2lhbGx5IHVzZXJmdWwgd2hlbiBkb2luZyBhc3NlcnRpb25zIG9uIGFycmF5czogaGF2aW5nIHRoaXNcbiAgICogc2V0IHRvIGEgcmVhc29uYWJsZSBsYXJnZSB2YWx1ZSBtYWtlcyB0aGUgZmFpbHVyZSBtZXNzYWdlcyByZWFkaWx5XG4gICAqIGluc3BlY3RhYmxlLlxuICAgKlxuICAgKiAgICAgY2hhaS5jb25maWcudHJ1bmNhdGVUaHJlc2hvbGQgPSAwOyAgLy8gZGlzYWJsZSB0cnVuY2F0aW5nXG4gICAqXG4gICAqIEBwYXJhbSB7TnVtYmVyfVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICB0cnVuY2F0ZVRocmVzaG9sZDogNDBcblxufTtcbiIsIi8qIVxuICogY2hhaVxuICogaHR0cDovL2NoYWlqcy5jb21cbiAqIENvcHlyaWdodChjKSAyMDExLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjaGFpLCBfKSB7XG4gIHZhciBBc3NlcnRpb24gPSBjaGFpLkFzc2VydGlvblxuICAgICwgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nXG4gICAgLCBmbGFnID0gXy5mbGFnO1xuXG4gIC8qKlxuICAgKiAjIyMgTGFuZ3VhZ2UgQ2hhaW5zXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgYXJlIHByb3ZpZGVkIGFzIGNoYWluYWJsZSBnZXR0ZXJzIHRvXG4gICAqIGltcHJvdmUgdGhlIHJlYWRhYmlsaXR5IG9mIHlvdXIgYXNzZXJ0aW9ucy4gVGhleVxuICAgKiBkbyBub3QgcHJvdmlkZSB0ZXN0aW5nIGNhcGFiaWxpdGllcyB1bmxlc3MgdGhleVxuICAgKiBoYXZlIGJlZW4gb3ZlcndyaXR0ZW4gYnkgYSBwbHVnaW4uXG4gICAqXG4gICAqICoqQ2hhaW5zKipcbiAgICpcbiAgICogLSB0b1xuICAgKiAtIGJlXG4gICAqIC0gYmVlblxuICAgKiAtIGlzXG4gICAqIC0gdGhhdFxuICAgKiAtIHdoaWNoXG4gICAqIC0gYW5kXG4gICAqIC0gaGFzXG4gICAqIC0gaGF2ZVxuICAgKiAtIHdpdGhcbiAgICogLSBhdFxuICAgKiAtIG9mXG4gICAqIC0gc2FtZVxuICAgKlxuICAgKiBAbmFtZSBsYW5ndWFnZSBjaGFpbnNcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgWyAndG8nLCAnYmUnLCAnYmVlbidcbiAgLCAnaXMnLCAnYW5kJywgJ2hhcycsICdoYXZlJ1xuICAsICd3aXRoJywgJ3RoYXQnLCAnd2hpY2gnLCAnYXQnXG4gICwgJ29mJywgJ3NhbWUnIF0uZm9yRWFjaChmdW5jdGlvbiAoY2hhaW4pIHtcbiAgICBBc3NlcnRpb24uYWRkUHJvcGVydHkoY2hhaW4sIGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0pO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5ub3RcbiAgICpcbiAgICogTmVnYXRlcyBhbnkgb2YgYXNzZXJ0aW9ucyBmb2xsb3dpbmcgaW4gdGhlIGNoYWluLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KGZvbykudG8ubm90LmVxdWFsKCdiYXInKTtcbiAgICogICAgIGV4cGVjdChnb29kRm4pLnRvLm5vdC50aHJvdyhFcnJvcik7XG4gICAqICAgICBleHBlY3QoeyBmb286ICdiYXonIH0pLnRvLmhhdmUucHJvcGVydHkoJ2ZvbycpXG4gICAqICAgICAgIC5hbmQubm90LmVxdWFsKCdiYXInKTtcbiAgICpcbiAgICogQG5hbWUgbm90XG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnbm90JywgZnVuY3Rpb24gKCkge1xuICAgIGZsYWcodGhpcywgJ25lZ2F0ZScsIHRydWUpO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5kZWVwXG4gICAqXG4gICAqIFNldHMgdGhlIGBkZWVwYCBmbGFnLCBsYXRlciB1c2VkIGJ5IHRoZSBgZXF1YWxgIGFuZFxuICAgKiBgcHJvcGVydHlgIGFzc2VydGlvbnMuXG4gICAqXG4gICAqICAgICBleHBlY3QoZm9vKS50by5kZWVwLmVxdWFsKHsgYmFyOiAnYmF6JyB9KTtcbiAgICogICAgIGV4cGVjdCh7IGZvbzogeyBiYXI6IHsgYmF6OiAncXV1eCcgfSB9IH0pXG4gICAqICAgICAgIC50by5oYXZlLmRlZXAucHJvcGVydHkoJ2Zvby5iYXIuYmF6JywgJ3F1dXgnKTtcbiAgICpcbiAgICogYC5kZWVwLnByb3BlcnR5YCBzcGVjaWFsIGNoYXJhY3RlcnMgY2FuIGJlIGVzY2FwZWRcbiAgICogYnkgYWRkaW5nIHR3byBzbGFzaGVzIGJlZm9yZSB0aGUgYC5gIG9yIGBbXWAuXG4gICAqXG4gICAqICAgICB2YXIgZGVlcENzcyA9IHsgJy5saW5rJzogeyAnW3RhcmdldF0nOiA0MiB9fTtcbiAgICogICAgIGV4cGVjdChkZWVwQ3NzKS50by5oYXZlLmRlZXAucHJvcGVydHkoJ1xcXFwubGluay5cXFxcW3RhcmdldFxcXFxdJywgNDIpO1xuICAgKlxuICAgKiBAbmFtZSBkZWVwXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnZGVlcCcsIGZ1bmN0aW9uICgpIHtcbiAgICBmbGFnKHRoaXMsICdkZWVwJywgdHJ1ZSk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLmFueVxuICAgKlxuICAgKiBTZXRzIHRoZSBgYW55YCBmbGFnLCAob3Bwb3NpdGUgb2YgdGhlIGBhbGxgIGZsYWcpXG4gICAqIGxhdGVyIHVzZWQgaW4gdGhlIGBrZXlzYCBhc3NlcnRpb24uXG4gICAqXG4gICAqICAgICBleHBlY3QoZm9vKS50by5oYXZlLmFueS5rZXlzKCdiYXInLCAnYmF6Jyk7XG4gICAqXG4gICAqIEBuYW1lIGFueVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkoJ2FueScsIGZ1bmN0aW9uICgpIHtcbiAgICBmbGFnKHRoaXMsICdhbnknLCB0cnVlKTtcbiAgICBmbGFnKHRoaXMsICdhbGwnLCBmYWxzZSlcbiAgfSk7XG5cblxuICAvKipcbiAgICogIyMjIC5hbGxcbiAgICpcbiAgICogU2V0cyB0aGUgYGFsbGAgZmxhZyAob3Bwb3NpdGUgb2YgdGhlIGBhbnlgIGZsYWcpXG4gICAqIGxhdGVyIHVzZWQgYnkgdGhlIGBrZXlzYCBhc3NlcnRpb24uXG4gICAqXG4gICAqICAgICBleHBlY3QoZm9vKS50by5oYXZlLmFsbC5rZXlzKCdiYXInLCAnYmF6Jyk7XG4gICAqXG4gICAqIEBuYW1lIGFsbFxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkoJ2FsbCcsIGZ1bmN0aW9uICgpIHtcbiAgICBmbGFnKHRoaXMsICdhbGwnLCB0cnVlKTtcbiAgICBmbGFnKHRoaXMsICdhbnknLCBmYWxzZSk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLmEodHlwZSlcbiAgICpcbiAgICogVGhlIGBhYCBhbmQgYGFuYCBhc3NlcnRpb25zIGFyZSBhbGlhc2VzIHRoYXQgY2FuIGJlXG4gICAqIHVzZWQgZWl0aGVyIGFzIGxhbmd1YWdlIGNoYWlucyBvciB0byBhc3NlcnQgYSB2YWx1ZSdzXG4gICAqIHR5cGUuXG4gICAqXG4gICAqICAgICAvLyB0eXBlb2ZcbiAgICogICAgIGV4cGVjdCgndGVzdCcpLnRvLmJlLmEoJ3N0cmluZycpO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAnYmFyJyB9KS50by5iZS5hbignb2JqZWN0Jyk7XG4gICAqICAgICBleHBlY3QobnVsbCkudG8uYmUuYSgnbnVsbCcpO1xuICAgKiAgICAgZXhwZWN0KHVuZGVmaW5lZCkudG8uYmUuYW4oJ3VuZGVmaW5lZCcpO1xuICAgKlxuICAgKiAgICAgLy8gbGFuZ3VhZ2UgY2hhaW5cbiAgICogICAgIGV4cGVjdChmb28pLnRvLmJlLmFuLmluc3RhbmNlb2YoRm9vKTtcbiAgICpcbiAgICogQG5hbWUgYVxuICAgKiBAYWxpYXMgYW5cbiAgICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhbiAodHlwZSwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdHlwZSA9IHR5cGUudG9Mb3dlckNhc2UoKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgYXJ0aWNsZSA9IH5bICdhJywgJ2UnLCAnaScsICdvJywgJ3UnIF0uaW5kZXhPZih0eXBlLmNoYXJBdCgwKSkgPyAnYW4gJyA6ICdhICc7XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgdHlwZSA9PT0gXy50eXBlKG9iailcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgJyArIGFydGljbGUgKyB0eXBlXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IG5vdCB0byBiZSAnICsgYXJ0aWNsZSArIHR5cGVcbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZENoYWluYWJsZU1ldGhvZCgnYW4nLCBhbik7XG4gIEFzc2VydGlvbi5hZGRDaGFpbmFibGVNZXRob2QoJ2EnLCBhbik7XG5cbiAgLyoqXG4gICAqICMjIyAuaW5jbHVkZSh2YWx1ZSlcbiAgICpcbiAgICogVGhlIGBpbmNsdWRlYCBhbmQgYGNvbnRhaW5gIGFzc2VydGlvbnMgY2FuIGJlIHVzZWQgYXMgZWl0aGVyIHByb3BlcnR5XG4gICAqIGJhc2VkIGxhbmd1YWdlIGNoYWlucyBvciBhcyBtZXRob2RzIHRvIGFzc2VydCB0aGUgaW5jbHVzaW9uIG9mIGFuIG9iamVjdFxuICAgKiBpbiBhbiBhcnJheSBvciBhIHN1YnN0cmluZyBpbiBhIHN0cmluZy4gV2hlbiB1c2VkIGFzIGxhbmd1YWdlIGNoYWlucyxcbiAgICogdGhleSB0b2dnbGUgdGhlIGBjb250YWluc2AgZmxhZyBmb3IgdGhlIGBrZXlzYCBhc3NlcnRpb24uXG4gICAqXG4gICAqICAgICBleHBlY3QoWzEsMiwzXSkudG8uaW5jbHVkZSgyKTtcbiAgICogICAgIGV4cGVjdCgnZm9vYmFyJykudG8uY29udGFpbignZm9vJyk7XG4gICAqICAgICBleHBlY3QoeyBmb286ICdiYXInLCBoZWxsbzogJ3VuaXZlcnNlJyB9KS50by5pbmNsdWRlLmtleXMoJ2ZvbycpO1xuICAgKlxuICAgKiBAbmFtZSBpbmNsdWRlXG4gICAqIEBhbGlhcyBjb250YWluXG4gICAqIEBhbGlhcyBpbmNsdWRlc1xuICAgKiBAYWxpYXMgY29udGFpbnNcbiAgICogQHBhcmFtIHtPYmplY3R8U3RyaW5nfE51bWJlcn0gb2JqXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gaW5jbHVkZUNoYWluaW5nQmVoYXZpb3IgKCkge1xuICAgIGZsYWcodGhpcywgJ2NvbnRhaW5zJywgdHJ1ZSk7XG4gIH1cblxuICBmdW5jdGlvbiBpbmNsdWRlICh2YWwsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICB2YXIgZXhwZWN0ZWQgPSBmYWxzZTtcbiAgICBpZiAoXy50eXBlKG9iaikgPT09ICdhcnJheScgJiYgXy50eXBlKHZhbCkgPT09ICdvYmplY3QnKSB7XG4gICAgICBmb3IgKHZhciBpIGluIG9iaikge1xuICAgICAgICBpZiAoXy5lcWwob2JqW2ldLCB2YWwpKSB7XG4gICAgICAgICAgZXhwZWN0ZWQgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChfLnR5cGUodmFsKSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmICghZmxhZyh0aGlzLCAnbmVnYXRlJykpIHtcbiAgICAgICAgZm9yICh2YXIgayBpbiB2YWwpIG5ldyBBc3NlcnRpb24ob2JqKS5wcm9wZXJ0eShrLCB2YWxba10pO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB2YXIgc3Vic2V0ID0ge307XG4gICAgICBmb3IgKHZhciBrIGluIHZhbCkgc3Vic2V0W2tdID0gb2JqW2tdO1xuICAgICAgZXhwZWN0ZWQgPSBfLmVxbChzdWJzZXQsIHZhbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGV4cGVjdGVkID0gb2JqICYmIH5vYmouaW5kZXhPZih2YWwpO1xuICAgIH1cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgZXhwZWN0ZWRcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaW5jbHVkZSAnICsgXy5pbnNwZWN0KHZhbClcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGluY2x1ZGUgJyArIF8uaW5zcGVjdCh2YWwpKTtcbiAgfVxuXG4gIEFzc2VydGlvbi5hZGRDaGFpbmFibGVNZXRob2QoJ2luY2x1ZGUnLCBpbmNsdWRlLCBpbmNsdWRlQ2hhaW5pbmdCZWhhdmlvcik7XG4gIEFzc2VydGlvbi5hZGRDaGFpbmFibGVNZXRob2QoJ2NvbnRhaW4nLCBpbmNsdWRlLCBpbmNsdWRlQ2hhaW5pbmdCZWhhdmlvcik7XG4gIEFzc2VydGlvbi5hZGRDaGFpbmFibGVNZXRob2QoJ2NvbnRhaW5zJywgaW5jbHVkZSwgaW5jbHVkZUNoYWluaW5nQmVoYXZpb3IpO1xuICBBc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdpbmNsdWRlcycsIGluY2x1ZGUsIGluY2x1ZGVDaGFpbmluZ0JlaGF2aW9yKTtcblxuICAvKipcbiAgICogIyMjIC5va1xuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyB0cnV0aHkuXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2V2ZXJ0aGluZycpLnRvLmJlLm9rO1xuICAgKiAgICAgZXhwZWN0KDEpLnRvLmJlLm9rO1xuICAgKiAgICAgZXhwZWN0KGZhbHNlKS50by5ub3QuYmUub2s7XG4gICAqICAgICBleHBlY3QodW5kZWZpbmVkKS50by5ub3QuYmUub2s7XG4gICAqICAgICBleHBlY3QobnVsbCkudG8ubm90LmJlLm9rO1xuICAgKlxuICAgKiBAbmFtZSBva1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkoJ29rJywgZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBmbGFnKHRoaXMsICdvYmplY3QnKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSB0cnV0aHknXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGZhbHN5Jyk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLnRydWVcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgYHRydWVgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KHRydWUpLnRvLmJlLnRydWU7XG4gICAqICAgICBleHBlY3QoMSkudG8ubm90LmJlLnRydWU7XG4gICAqXG4gICAqIEBuYW1lIHRydWVcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCd0cnVlJywgZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICB0cnVlID09PSBmbGFnKHRoaXMsICdvYmplY3QnKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSB0cnVlJ1xuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBmYWxzZSdcbiAgICAgICwgdGhpcy5uZWdhdGUgPyBmYWxzZSA6IHRydWVcbiAgICApO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5mYWxzZVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBgZmFsc2VgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KGZhbHNlKS50by5iZS5mYWxzZTtcbiAgICogICAgIGV4cGVjdCgwKS50by5ub3QuYmUuZmFsc2U7XG4gICAqXG4gICAqIEBuYW1lIGZhbHNlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnZmFsc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIGZhbHNlID09PSBmbGFnKHRoaXMsICdvYmplY3QnKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBmYWxzZSdcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgdHJ1ZSdcbiAgICAgICwgdGhpcy5uZWdhdGUgPyB0cnVlIDogZmFsc2VcbiAgICApO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5udWxsXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGBudWxsYC5cbiAgICpcbiAgICogICAgIGV4cGVjdChudWxsKS50by5iZS5udWxsO1xuICAgKiAgICAgZXhwZWN0KHVuZGVmaW5lZCkudG8ubm90LmJlLm51bGw7XG4gICAqXG4gICAqIEBuYW1lIG51bGxcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdudWxsJywgZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBudWxsID09PSBmbGFnKHRoaXMsICdvYmplY3QnKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBudWxsJ1xuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSBub3QgdG8gYmUgbnVsbCdcbiAgICApO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC51bmRlZmluZWRcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgYHVuZGVmaW5lZGAuXG4gICAqXG4gICAqICAgICBleHBlY3QodW5kZWZpbmVkKS50by5iZS51bmRlZmluZWQ7XG4gICAqICAgICBleHBlY3QobnVsbCkudG8ubm90LmJlLnVuZGVmaW5lZDtcbiAgICpcbiAgICogQG5hbWUgdW5kZWZpbmVkXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRQcm9wZXJ0eSgndW5kZWZpbmVkJywgZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICB1bmRlZmluZWQgPT09IGZsYWcodGhpcywgJ29iamVjdCcpXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIHVuZGVmaW5lZCdcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gbm90IHRvIGJlIHVuZGVmaW5lZCdcbiAgICApO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5leGlzdFxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBuZWl0aGVyIGBudWxsYCBub3IgYHVuZGVmaW5lZGAuXG4gICAqXG4gICAqICAgICB2YXIgZm9vID0gJ2hpJ1xuICAgKiAgICAgICAsIGJhciA9IG51bGxcbiAgICogICAgICAgLCBiYXo7XG4gICAqXG4gICAqICAgICBleHBlY3QoZm9vKS50by5leGlzdDtcbiAgICogICAgIGV4cGVjdChiYXIpLnRvLm5vdC5leGlzdDtcbiAgICogICAgIGV4cGVjdChiYXopLnRvLm5vdC5leGlzdDtcbiAgICpcbiAgICogQG5hbWUgZXhpc3RcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdleGlzdCcsIGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgbnVsbCAhPSBmbGFnKHRoaXMsICdvYmplY3QnKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBleGlzdCdcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGV4aXN0J1xuICAgICk7XG4gIH0pO1xuXG5cbiAgLyoqXG4gICAqICMjIyAuZW1wdHlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQncyBsZW5ndGggaXMgYDBgLiBGb3IgYXJyYXlzIGFuZCBzdHJpbmdzLCBpdCBjaGVja3NcbiAgICogdGhlIGBsZW5ndGhgIHByb3BlcnR5LiBGb3Igb2JqZWN0cywgaXQgZ2V0cyB0aGUgY291bnQgb2ZcbiAgICogZW51bWVyYWJsZSBrZXlzLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KFtdKS50by5iZS5lbXB0eTtcbiAgICogICAgIGV4cGVjdCgnJykudG8uYmUuZW1wdHk7XG4gICAqICAgICBleHBlY3Qoe30pLnRvLmJlLmVtcHR5O1xuICAgKlxuICAgKiBAbmFtZSBlbXB0eVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkoJ2VtcHR5JywgZnVuY3Rpb24gKCkge1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKVxuICAgICAgLCBleHBlY3RlZCA9IG9iajtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KG9iaikgfHwgJ3N0cmluZycgPT09IHR5cGVvZiBvYmplY3QpIHtcbiAgICAgIGV4cGVjdGVkID0gb2JqLmxlbmd0aDtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBvYmogPT09ICdvYmplY3QnKSB7XG4gICAgICBleHBlY3RlZCA9IE9iamVjdC5rZXlzKG9iaikubGVuZ3RoO1xuICAgIH1cblxuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAhZXhwZWN0ZWRcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgZW1wdHknXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IG5vdCB0byBiZSBlbXB0eSdcbiAgICApO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5hcmd1bWVudHNcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgYW4gYXJndW1lbnRzIG9iamVjdC5cbiAgICpcbiAgICogICAgIGZ1bmN0aW9uIHRlc3QgKCkge1xuICAgKiAgICAgICBleHBlY3QoYXJndW1lbnRzKS50by5iZS5hcmd1bWVudHM7XG4gICAqICAgICB9XG4gICAqXG4gICAqIEBuYW1lIGFyZ3VtZW50c1xuICAgKiBAYWxpYXMgQXJndW1lbnRzXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGNoZWNrQXJndW1lbnRzICgpIHtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgdHlwZSA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopO1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAnW29iamVjdCBBcmd1bWVudHNdJyA9PT0gdHlwZVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBhcmd1bWVudHMgYnV0IGdvdCAnICsgdHlwZVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgYmUgYXJndW1lbnRzJ1xuICAgICk7XG4gIH1cblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkoJ2FyZ3VtZW50cycsIGNoZWNrQXJndW1lbnRzKTtcbiAgQXNzZXJ0aW9uLmFkZFByb3BlcnR5KCdBcmd1bWVudHMnLCBjaGVja0FyZ3VtZW50cyk7XG5cbiAgLyoqXG4gICAqICMjIyAuZXF1YWwodmFsdWUpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIHN0cmljdGx5IGVxdWFsIChgPT09YCkgdG8gYHZhbHVlYC5cbiAgICogQWx0ZXJuYXRlbHksIGlmIHRoZSBgZGVlcGAgZmxhZyBpcyBzZXQsIGFzc2VydHMgdGhhdFxuICAgKiB0aGUgdGFyZ2V0IGlzIGRlZXBseSBlcXVhbCB0byBgdmFsdWVgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KCdoZWxsbycpLnRvLmVxdWFsKCdoZWxsbycpO1xuICAgKiAgICAgZXhwZWN0KDQyKS50by5lcXVhbCg0Mik7XG4gICAqICAgICBleHBlY3QoMSkudG8ubm90LmVxdWFsKHRydWUpO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAnYmFyJyB9KS50by5ub3QuZXF1YWwoeyBmb286ICdiYXInIH0pO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAnYmFyJyB9KS50by5kZWVwLmVxdWFsKHsgZm9vOiAnYmFyJyB9KTtcbiAgICpcbiAgICogQG5hbWUgZXF1YWxcbiAgICogQGFsaWFzIGVxdWFsc1xuICAgKiBAYWxpYXMgZXFcbiAgICogQGFsaWFzIGRlZXAuZXF1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRFcXVhbCAodmFsLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgaWYgKGZsYWcodGhpcywgJ2RlZXAnKSkge1xuICAgICAgcmV0dXJuIHRoaXMuZXFsKHZhbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIHZhbCA9PT0gb2JqXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gZXF1YWwgI3tleHB9J1xuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBlcXVhbCAje2V4cH0nXG4gICAgICAgICwgdmFsXG4gICAgICAgICwgdGhpcy5fb2JqXG4gICAgICAgICwgdHJ1ZVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdlcXVhbCcsIGFzc2VydEVxdWFsKTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZXF1YWxzJywgYXNzZXJ0RXF1YWwpO1xuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdlcScsIGFzc2VydEVxdWFsKTtcblxuICAvKipcbiAgICogIyMjIC5lcWwodmFsdWUpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGRlZXBseSBlcXVhbCB0byBgdmFsdWVgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAnYmFyJyB9KS50by5lcWwoeyBmb286ICdiYXInIH0pO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5lcWwoWyAxLCAyLCAzIF0pO1xuICAgKlxuICAgKiBAbmFtZSBlcWxcbiAgICogQGFsaWFzIGVxbHNcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRFcWwob2JqLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgXy5lcWwob2JqLCBmbGFnKHRoaXMsICdvYmplY3QnKSlcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gZGVlcGx5IGVxdWFsICN7ZXhwfSdcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGRlZXBseSBlcXVhbCAje2V4cH0nXG4gICAgICAsIG9ialxuICAgICAgLCB0aGlzLl9vYmpcbiAgICAgICwgdHJ1ZVxuICAgICk7XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdlcWwnLCBhc3NlcnRFcWwpO1xuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdlcWxzJywgYXNzZXJ0RXFsKTtcblxuICAvKipcbiAgICogIyMjIC5hYm92ZSh2YWx1ZSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgZ3JlYXRlciB0aGFuIGB2YWx1ZWAuXG4gICAqXG4gICAqICAgICBleHBlY3QoMTApLnRvLmJlLmFib3ZlKDUpO1xuICAgKlxuICAgKiBDYW4gYWxzbyBiZSB1c2VkIGluIGNvbmp1bmN0aW9uIHdpdGggYGxlbmd0aGAgdG9cbiAgICogYXNzZXJ0IGEgbWluaW11bSBsZW5ndGguIFRoZSBiZW5lZml0IGJlaW5nIGFcbiAgICogbW9yZSBpbmZvcm1hdGl2ZSBlcnJvciBtZXNzYWdlIHRoYW4gaWYgdGhlIGxlbmd0aFxuICAgKiB3YXMgc3VwcGxpZWQgZGlyZWN0bHkuXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2ZvbycpLnRvLmhhdmUubGVuZ3RoLmFib3ZlKDIpO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5oYXZlLmxlbmd0aC5hYm92ZSgyKTtcbiAgICpcbiAgICogQG5hbWUgYWJvdmVcbiAgICogQGFsaWFzIGd0XG4gICAqIEBhbGlhcyBncmVhdGVyVGhhblxuICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRBYm92ZSAobiwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIGlmIChmbGFnKHRoaXMsICdkb0xlbmd0aCcpKSB7XG4gICAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5oYXZlLnByb3BlcnR5KCdsZW5ndGgnKTtcbiAgICAgIHZhciBsZW4gPSBvYmoubGVuZ3RoO1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgbGVuID4gblxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGhhdmUgYSBsZW5ndGggYWJvdmUgI3tleHB9IGJ1dCBnb3QgI3thY3R9J1xuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBoYXZlIGEgbGVuZ3RoIGFib3ZlICN7ZXhwfSdcbiAgICAgICAgLCBuXG4gICAgICAgICwgbGVuXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICBvYmogPiBuXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYWJvdmUgJyArIG5cbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBhdCBtb3N0ICcgKyBuXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2Fib3ZlJywgYXNzZXJ0QWJvdmUpO1xuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdndCcsIGFzc2VydEFib3ZlKTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZ3JlYXRlclRoYW4nLCBhc3NlcnRBYm92ZSk7XG5cbiAgLyoqXG4gICAqICMjIyAubGVhc3QodmFsdWUpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byBgdmFsdWVgLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KDEwKS50by5iZS5hdC5sZWFzdCgxMCk7XG4gICAqXG4gICAqIENhbiBhbHNvIGJlIHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCBgbGVuZ3RoYCB0b1xuICAgKiBhc3NlcnQgYSBtaW5pbXVtIGxlbmd0aC4gVGhlIGJlbmVmaXQgYmVpbmcgYVxuICAgKiBtb3JlIGluZm9ybWF0aXZlIGVycm9yIG1lc3NhZ2UgdGhhbiBpZiB0aGUgbGVuZ3RoXG4gICAqIHdhcyBzdXBwbGllZCBkaXJlY3RseS5cbiAgICpcbiAgICogICAgIGV4cGVjdCgnZm9vJykudG8uaGF2ZS5sZW5ndGgub2YuYXQubGVhc3QoMik7XG4gICAqICAgICBleHBlY3QoWyAxLCAyLCAzIF0pLnRvLmhhdmUubGVuZ3RoLm9mLmF0LmxlYXN0KDMpO1xuICAgKlxuICAgKiBAbmFtZSBsZWFzdFxuICAgKiBAYWxpYXMgZ3RlXG4gICAqIEBwYXJhbSB7TnVtYmVyfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGFzc2VydExlYXN0IChuLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgaWYgKGZsYWcodGhpcywgJ2RvTGVuZ3RoJykpIHtcbiAgICAgIG5ldyBBc3NlcnRpb24ob2JqLCBtc2cpLnRvLmhhdmUucHJvcGVydHkoJ2xlbmd0aCcpO1xuICAgICAgdmFyIGxlbiA9IG9iai5sZW5ndGg7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICBsZW4gPj0gblxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGhhdmUgYSBsZW5ndGggYXQgbGVhc3QgI3tleHB9IGJ1dCBnb3QgI3thY3R9J1xuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGhhdmUgYSBsZW5ndGggYmVsb3cgI3tleHB9J1xuICAgICAgICAsIG5cbiAgICAgICAgLCBsZW5cbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIG9iaiA+PSBuXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYXQgbGVhc3QgJyArIG5cbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBiZWxvdyAnICsgblxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdsZWFzdCcsIGFzc2VydExlYXN0KTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZ3RlJywgYXNzZXJ0TGVhc3QpO1xuXG4gIC8qKlxuICAgKiAjIyMgLmJlbG93KHZhbHVlKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBpcyBsZXNzIHRoYW4gYHZhbHVlYC5cbiAgICpcbiAgICogICAgIGV4cGVjdCg1KS50by5iZS5iZWxvdygxMCk7XG4gICAqXG4gICAqIENhbiBhbHNvIGJlIHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCBgbGVuZ3RoYCB0b1xuICAgKiBhc3NlcnQgYSBtYXhpbXVtIGxlbmd0aC4gVGhlIGJlbmVmaXQgYmVpbmcgYVxuICAgKiBtb3JlIGluZm9ybWF0aXZlIGVycm9yIG1lc3NhZ2UgdGhhbiBpZiB0aGUgbGVuZ3RoXG4gICAqIHdhcyBzdXBwbGllZCBkaXJlY3RseS5cbiAgICpcbiAgICogICAgIGV4cGVjdCgnZm9vJykudG8uaGF2ZS5sZW5ndGguYmVsb3coNCk7XG4gICAqICAgICBleHBlY3QoWyAxLCAyLCAzIF0pLnRvLmhhdmUubGVuZ3RoLmJlbG93KDQpO1xuICAgKlxuICAgKiBAbmFtZSBiZWxvd1xuICAgKiBAYWxpYXMgbHRcbiAgICogQGFsaWFzIGxlc3NUaGFuXG4gICAqIEBwYXJhbSB7TnVtYmVyfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGFzc2VydEJlbG93IChuLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgaWYgKGZsYWcodGhpcywgJ2RvTGVuZ3RoJykpIHtcbiAgICAgIG5ldyBBc3NlcnRpb24ob2JqLCBtc2cpLnRvLmhhdmUucHJvcGVydHkoJ2xlbmd0aCcpO1xuICAgICAgdmFyIGxlbiA9IG9iai5sZW5ndGg7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICBsZW4gPCBuXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBhIGxlbmd0aCBiZWxvdyAje2V4cH0gYnV0IGdvdCAje2FjdH0nXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGhhdmUgYSBsZW5ndGggYmVsb3cgI3tleHB9J1xuICAgICAgICAsIG5cbiAgICAgICAgLCBsZW5cbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIG9iaiA8IG5cbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBiZSBiZWxvdyAnICsgblxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGF0IGxlYXN0ICcgKyBuXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2JlbG93JywgYXNzZXJ0QmVsb3cpO1xuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdsdCcsIGFzc2VydEJlbG93KTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnbGVzc1RoYW4nLCBhc3NlcnRCZWxvdyk7XG5cbiAgLyoqXG4gICAqICMjIyAubW9zdCh2YWx1ZSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIGB2YWx1ZWAuXG4gICAqXG4gICAqICAgICBleHBlY3QoNSkudG8uYmUuYXQubW9zdCg1KTtcbiAgICpcbiAgICogQ2FuIGFsc28gYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIGBsZW5ndGhgIHRvXG4gICAqIGFzc2VydCBhIG1heGltdW0gbGVuZ3RoLiBUaGUgYmVuZWZpdCBiZWluZyBhXG4gICAqIG1vcmUgaW5mb3JtYXRpdmUgZXJyb3IgbWVzc2FnZSB0aGFuIGlmIHRoZSBsZW5ndGhcbiAgICogd2FzIHN1cHBsaWVkIGRpcmVjdGx5LlxuICAgKlxuICAgKiAgICAgZXhwZWN0KCdmb28nKS50by5oYXZlLmxlbmd0aC5vZi5hdC5tb3N0KDQpO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5oYXZlLmxlbmd0aC5vZi5hdC5tb3N0KDMpO1xuICAgKlxuICAgKiBAbmFtZSBtb3N0XG4gICAqIEBhbGlhcyBsdGVcbiAgICogQHBhcmFtIHtOdW1iZXJ9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gYXNzZXJ0TW9zdCAobiwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIGlmIChmbGFnKHRoaXMsICdkb0xlbmd0aCcpKSB7XG4gICAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5oYXZlLnByb3BlcnR5KCdsZW5ndGgnKTtcbiAgICAgIHZhciBsZW4gPSBvYmoubGVuZ3RoO1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgbGVuIDw9IG5cbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBoYXZlIGEgbGVuZ3RoIGF0IG1vc3QgI3tleHB9IGJ1dCBnb3QgI3thY3R9J1xuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGhhdmUgYSBsZW5ndGggYWJvdmUgI3tleHB9J1xuICAgICAgICAsIG5cbiAgICAgICAgLCBsZW5cbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIG9iaiA8PSBuXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYXQgbW9zdCAnICsgblxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIGFib3ZlICcgKyBuXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ21vc3QnLCBhc3NlcnRNb3N0KTtcbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnbHRlJywgYXNzZXJ0TW9zdCk7XG5cbiAgLyoqXG4gICAqICMjIyAud2l0aGluKHN0YXJ0LCBmaW5pc2gpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIHdpdGhpbiBhIHJhbmdlLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KDcpLnRvLmJlLndpdGhpbig1LDEwKTtcbiAgICpcbiAgICogQ2FuIGFsc28gYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIGBsZW5ndGhgIHRvXG4gICAqIGFzc2VydCBhIGxlbmd0aCByYW5nZS4gVGhlIGJlbmVmaXQgYmVpbmcgYVxuICAgKiBtb3JlIGluZm9ybWF0aXZlIGVycm9yIG1lc3NhZ2UgdGhhbiBpZiB0aGUgbGVuZ3RoXG4gICAqIHdhcyBzdXBwbGllZCBkaXJlY3RseS5cbiAgICpcbiAgICogICAgIGV4cGVjdCgnZm9vJykudG8uaGF2ZS5sZW5ndGgud2l0aGluKDIsNCk7XG4gICAqICAgICBleHBlY3QoWyAxLCAyLCAzIF0pLnRvLmhhdmUubGVuZ3RoLndpdGhpbigyLDQpO1xuICAgKlxuICAgKiBAbmFtZSB3aXRoaW5cbiAgICogQHBhcmFtIHtOdW1iZXJ9IHN0YXJ0IGxvd2VyYm91bmQgaW5jbHVzaXZlXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBmaW5pc2ggdXBwZXJib3VuZCBpbmNsdXNpdmVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCd3aXRoaW4nLCBmdW5jdGlvbiAoc3RhcnQsIGZpbmlzaCwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpXG4gICAgICAsIHJhbmdlID0gc3RhcnQgKyAnLi4nICsgZmluaXNoO1xuICAgIGlmIChmbGFnKHRoaXMsICdkb0xlbmd0aCcpKSB7XG4gICAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5oYXZlLnByb3BlcnR5KCdsZW5ndGgnKTtcbiAgICAgIHZhciBsZW4gPSBvYmoubGVuZ3RoO1xuICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgbGVuID49IHN0YXJ0ICYmIGxlbiA8PSBmaW5pc2hcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBoYXZlIGEgbGVuZ3RoIHdpdGhpbiAnICsgcmFuZ2VcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgaGF2ZSBhIGxlbmd0aCB3aXRoaW4gJyArIHJhbmdlXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICBvYmogPj0gc3RhcnQgJiYgb2JqIDw9IGZpbmlzaFxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGJlIHdpdGhpbiAnICsgcmFuZ2VcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgYmUgd2l0aGluICcgKyByYW5nZVxuICAgICAgKTtcbiAgICB9XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLmluc3RhbmNlb2YoY29uc3RydWN0b3IpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGFuIGluc3RhbmNlIG9mIGBjb25zdHJ1Y3RvcmAuXG4gICAqXG4gICAqICAgICB2YXIgVGVhID0gZnVuY3Rpb24gKG5hbWUpIHsgdGhpcy5uYW1lID0gbmFtZTsgfVxuICAgKiAgICAgICAsIENoYWkgPSBuZXcgVGVhKCdjaGFpJyk7XG4gICAqXG4gICAqICAgICBleHBlY3QoQ2hhaSkudG8uYmUuYW4uaW5zdGFuY2VvZihUZWEpO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5iZS5pbnN0YW5jZW9mKEFycmF5KTtcbiAgICpcbiAgICogQG5hbWUgaW5zdGFuY2VvZlxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yfSBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhbGlhcyBpbnN0YW5jZU9mXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGFzc2VydEluc3RhbmNlT2YgKGNvbnN0cnVjdG9yLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgbmFtZSA9IF8uZ2V0TmFtZShjb25zdHJ1Y3Rvcik7XG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIGZsYWcodGhpcywgJ29iamVjdCcpIGluc3RhbmNlb2YgY29uc3RydWN0b3JcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYW4gaW5zdGFuY2Ugb2YgJyArIG5hbWVcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGJlIGFuIGluc3RhbmNlIG9mICcgKyBuYW1lXG4gICAgKTtcbiAgfTtcblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdpbnN0YW5jZW9mJywgYXNzZXJ0SW5zdGFuY2VPZik7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2luc3RhbmNlT2YnLCBhc3NlcnRJbnN0YW5jZU9mKTtcblxuICAvKipcbiAgICogIyMjIC5wcm9wZXJ0eShuYW1lLCBbdmFsdWVdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBoYXMgYSBwcm9wZXJ0eSBgbmFtZWAsIG9wdGlvbmFsbHkgYXNzZXJ0aW5nIHRoYXRcbiAgICogdGhlIHZhbHVlIG9mIHRoYXQgcHJvcGVydHkgaXMgc3RyaWN0bHkgZXF1YWwgdG8gIGB2YWx1ZWAuXG4gICAqIElmIHRoZSBgZGVlcGAgZmxhZyBpcyBzZXQsIHlvdSBjYW4gdXNlIGRvdC0gYW5kIGJyYWNrZXQtbm90YXRpb24gZm9yIGRlZXBcbiAgICogcmVmZXJlbmNlcyBpbnRvIG9iamVjdHMgYW5kIGFycmF5cy5cbiAgICpcbiAgICogICAgIC8vIHNpbXBsZSByZWZlcmVuY2luZ1xuICAgKiAgICAgdmFyIG9iaiA9IHsgZm9vOiAnYmFyJyB9O1xuICAgKiAgICAgZXhwZWN0KG9iaikudG8uaGF2ZS5wcm9wZXJ0eSgnZm9vJyk7XG4gICAqICAgICBleHBlY3Qob2JqKS50by5oYXZlLnByb3BlcnR5KCdmb28nLCAnYmFyJyk7XG4gICAqXG4gICAqICAgICAvLyBkZWVwIHJlZmVyZW5jaW5nXG4gICAqICAgICB2YXIgZGVlcE9iaiA9IHtcbiAgICogICAgICAgICBncmVlbjogeyB0ZWE6ICdtYXRjaGEnIH1cbiAgICogICAgICAgLCB0ZWFzOiBbICdjaGFpJywgJ21hdGNoYScsIHsgdGVhOiAna29uYWNoYScgfSBdXG4gICAqICAgICB9O1xuICAgKlxuICAgKiAgICAgZXhwZWN0KGRlZXBPYmopLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eSgnZ3JlZW4udGVhJywgJ21hdGNoYScpO1xuICAgKiAgICAgZXhwZWN0KGRlZXBPYmopLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eSgndGVhc1sxXScsICdtYXRjaGEnKTtcbiAgICogICAgIGV4cGVjdChkZWVwT2JqKS50by5oYXZlLmRlZXAucHJvcGVydHkoJ3RlYXNbMl0udGVhJywgJ2tvbmFjaGEnKTtcbiAgICpcbiAgICogWW91IGNhbiBhbHNvIHVzZSBhbiBhcnJheSBhcyB0aGUgc3RhcnRpbmcgcG9pbnQgb2YgYSBgZGVlcC5wcm9wZXJ0eWBcbiAgICogYXNzZXJ0aW9uLCBvciB0cmF2ZXJzZSBuZXN0ZWQgYXJyYXlzLlxuICAgKlxuICAgKiAgICAgdmFyIGFyciA9IFtcbiAgICogICAgICAgICBbICdjaGFpJywgJ21hdGNoYScsICdrb25hY2hhJyBdXG4gICAqICAgICAgICwgWyB7IHRlYTogJ2NoYWknIH1cbiAgICogICAgICAgICAsIHsgdGVhOiAnbWF0Y2hhJyB9XG4gICAqICAgICAgICAgLCB7IHRlYTogJ2tvbmFjaGEnIH0gXVxuICAgKiAgICAgXTtcbiAgICpcbiAgICogICAgIGV4cGVjdChhcnIpLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eSgnWzBdWzFdJywgJ21hdGNoYScpO1xuICAgKiAgICAgZXhwZWN0KGFycikudG8uaGF2ZS5kZWVwLnByb3BlcnR5KCdbMV1bMl0udGVhJywgJ2tvbmFjaGEnKTtcbiAgICpcbiAgICogRnVydGhlcm1vcmUsIGBwcm9wZXJ0eWAgY2hhbmdlcyB0aGUgc3ViamVjdCBvZiB0aGUgYXNzZXJ0aW9uXG4gICAqIHRvIGJlIHRoZSB2YWx1ZSBvZiB0aGF0IHByb3BlcnR5IGZyb20gdGhlIG9yaWdpbmFsIG9iamVjdC4gVGhpc1xuICAgKiBwZXJtaXRzIGZvciBmdXJ0aGVyIGNoYWluYWJsZSBhc3NlcnRpb25zIG9uIHRoYXQgcHJvcGVydHkuXG4gICAqXG4gICAqICAgICBleHBlY3Qob2JqKS50by5oYXZlLnByb3BlcnR5KCdmb28nKVxuICAgKiAgICAgICAudGhhdC5pcy5hKCdzdHJpbmcnKTtcbiAgICogICAgIGV4cGVjdChkZWVwT2JqKS50by5oYXZlLnByb3BlcnR5KCdncmVlbicpXG4gICAqICAgICAgIC50aGF0LmlzLmFuKCdvYmplY3QnKVxuICAgKiAgICAgICAudGhhdC5kZWVwLmVxdWFscyh7IHRlYTogJ21hdGNoYScgfSk7XG4gICAqICAgICBleHBlY3QoZGVlcE9iaikudG8uaGF2ZS5wcm9wZXJ0eSgndGVhcycpXG4gICAqICAgICAgIC50aGF0LmlzLmFuKCdhcnJheScpXG4gICAqICAgICAgIC53aXRoLmRlZXAucHJvcGVydHkoJ1syXScpXG4gICAqICAgICAgICAgLnRoYXQuZGVlcC5lcXVhbHMoeyB0ZWE6ICdrb25hY2hhJyB9KTtcbiAgICpcbiAgICogTm90ZSB0aGF0IGRvdHMgYW5kIGJyYWNrZXQgaW4gYG5hbWVgIG11c3QgYmUgYmFja3NsYXNoLWVzY2FwZWQgd2hlblxuICAgKiB0aGUgYGRlZXBgIGZsYWcgaXMgc2V0LCB3aGlsZSB0aGV5IG11c3QgTk9UIGJlIGVzY2FwZWQgd2hlbiB0aGUgYGRlZXBgXG4gICAqIGZsYWcgaXMgbm90IHNldC5cbiAgICpcbiAgICogICAgIC8vIHNpbXBsZSByZWZlcmVuY2luZ1xuICAgKiAgICAgdmFyIGNzcyA9IHsgJy5saW5rW3RhcmdldF0nOiA0MiB9O1xuICAgKiAgICAgZXhwZWN0KGNzcykudG8uaGF2ZS5wcm9wZXJ0eSgnLmxpbmtbdGFyZ2V0XScsIDQyKTtcbiAgICpcbiAgICogICAgIC8vIGRlZXAgcmVmZXJlbmNpbmdcbiAgICogICAgIHZhciBkZWVwQ3NzID0geyAnLmxpbmsnOiB7ICdbdGFyZ2V0XSc6IDQyIH19O1xuICAgKiAgICAgZXhwZWN0KGRlZXBDc3MpLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eSgnXFxcXC5saW5rLlxcXFxbdGFyZ2V0XFxcXF0nLCA0Mik7XG4gICAqXG4gICAqIEBuYW1lIHByb3BlcnR5XG4gICAqIEBhbGlhcyBkZWVwLnByb3BlcnR5XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlIChvcHRpb25hbClcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAcmV0dXJucyB2YWx1ZSBvZiBwcm9wZXJ0eSBmb3IgY2hhaW5pbmdcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgncHJvcGVydHknLCBmdW5jdGlvbiAobmFtZSwgdmFsLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcblxuICAgIHZhciBpc0RlZXAgPSAhIWZsYWcodGhpcywgJ2RlZXAnKVxuICAgICAgLCBkZXNjcmlwdG9yID0gaXNEZWVwID8gJ2RlZXAgcHJvcGVydHkgJyA6ICdwcm9wZXJ0eSAnXG4gICAgICAsIG5lZ2F0ZSA9IGZsYWcodGhpcywgJ25lZ2F0ZScpXG4gICAgICAsIG9iaiA9IGZsYWcodGhpcywgJ29iamVjdCcpXG4gICAgICAsIHBhdGhJbmZvID0gaXNEZWVwID8gXy5nZXRQYXRoSW5mbyhuYW1lLCBvYmopIDogbnVsbFxuICAgICAgLCBoYXNQcm9wZXJ0eSA9IGlzRGVlcFxuICAgICAgICA/IHBhdGhJbmZvLmV4aXN0c1xuICAgICAgICA6IF8uaGFzUHJvcGVydHkobmFtZSwgb2JqKVxuICAgICAgLCB2YWx1ZSA9IGlzRGVlcFxuICAgICAgICA/IHBhdGhJbmZvLnZhbHVlXG4gICAgICAgIDogb2JqW25hbWVdO1xuXG4gICAgaWYgKG5lZ2F0ZSAmJiB1bmRlZmluZWQgIT09IHZhbCkge1xuICAgICAgaWYgKHVuZGVmaW5lZCA9PT0gdmFsdWUpIHtcbiAgICAgICAgbXNnID0gKG1zZyAhPSBudWxsKSA/IG1zZyArICc6ICcgOiAnJztcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyArIF8uaW5zcGVjdChvYmopICsgJyBoYXMgbm8gJyArIGRlc2NyaXB0b3IgKyBfLmluc3BlY3QobmFtZSkpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICBoYXNQcm9wZXJ0eVxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGhhdmUgYSAnICsgZGVzY3JpcHRvciArIF8uaW5zcGVjdChuYW1lKVxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBoYXZlICcgKyBkZXNjcmlwdG9yICsgXy5pbnNwZWN0KG5hbWUpKTtcbiAgICB9XG5cbiAgICBpZiAodW5kZWZpbmVkICE9PSB2YWwpIHtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIHZhbCA9PT0gdmFsdWVcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBoYXZlIGEgJyArIGRlc2NyaXB0b3IgKyBfLmluc3BlY3QobmFtZSkgKyAnIG9mICN7ZXhwfSwgYnV0IGdvdCAje2FjdH0nXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGhhdmUgYSAnICsgZGVzY3JpcHRvciArIF8uaW5zcGVjdChuYW1lKSArICcgb2YgI3thY3R9J1xuICAgICAgICAsIHZhbFxuICAgICAgICAsIHZhbHVlXG4gICAgICApO1xuICAgIH1cblxuICAgIGZsYWcodGhpcywgJ29iamVjdCcsIHZhbHVlKTtcbiAgfSk7XG5cblxuICAvKipcbiAgICogIyMjIC5vd25Qcm9wZXJ0eShuYW1lKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIHRhcmdldCBoYXMgYW4gb3duIHByb3BlcnR5IGBuYW1lYC5cbiAgICpcbiAgICogICAgIGV4cGVjdCgndGVzdCcpLnRvLmhhdmUub3duUHJvcGVydHkoJ2xlbmd0aCcpO1xuICAgKlxuICAgKiBAbmFtZSBvd25Qcm9wZXJ0eVxuICAgKiBAYWxpYXMgaGF2ZU93blByb3BlcnR5XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gYXNzZXJ0T3duUHJvcGVydHkgKG5hbWUsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgb2JqLmhhc093blByb3BlcnR5KG5hbWUpXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIGhhdmUgb3duIHByb3BlcnR5ICcgKyBfLmluc3BlY3QobmFtZSlcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGhhdmUgb3duIHByb3BlcnR5ICcgKyBfLmluc3BlY3QobmFtZSlcbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgnb3duUHJvcGVydHknLCBhc3NlcnRPd25Qcm9wZXJ0eSk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2hhdmVPd25Qcm9wZXJ0eScsIGFzc2VydE93blByb3BlcnR5KTtcblxuICAvKipcbiAgICogIyMjIC5vd25Qcm9wZXJ0eURlc2NyaXB0b3IobmFtZVssIGRlc2NyaXB0b3JbLCBtZXNzYWdlXV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGhhcyBhbiBvd24gcHJvcGVydHkgZGVzY3JpcHRvciBgbmFtZWAsIHRoYXQgb3B0aW9uYWxseSBtYXRjaGVzIGBkZXNjcmlwdG9yYC5cbiAgICpcbiAgICogICAgIGV4cGVjdCgndGVzdCcpLnRvLmhhdmUub3duUHJvcGVydHlEZXNjcmlwdG9yKCdsZW5ndGgnKTtcbiAgICogICAgIGV4cGVjdCgndGVzdCcpLnRvLmhhdmUub3duUHJvcGVydHlEZXNjcmlwdG9yKCdsZW5ndGgnLCB7IGVudW1lcmFibGU6IGZhbHNlLCBjb25maWd1cmFibGU6IGZhbHNlLCB3cml0YWJsZTogZmFsc2UsIHZhbHVlOiA0IH0pO1xuICAgKiAgICAgZXhwZWN0KCd0ZXN0Jykubm90LnRvLmhhdmUub3duUHJvcGVydHlEZXNjcmlwdG9yKCdsZW5ndGgnLCB7IGVudW1lcmFibGU6IGZhbHNlLCBjb25maWd1cmFibGU6IGZhbHNlLCB3cml0YWJsZTogZmFsc2UsIHZhbHVlOiAzIH0pO1xuICAgKiAgICAgZXhwZWN0KCd0ZXN0Jykub3duUHJvcGVydHlEZXNjcmlwdG9yKCdsZW5ndGgnKS50by5oYXZlLnByb3BlcnR5KCdlbnVtZXJhYmxlJywgZmFsc2UpO1xuICAgKiAgICAgZXhwZWN0KCd0ZXN0Jykub3duUHJvcGVydHlEZXNjcmlwdG9yKCdsZW5ndGgnKS50by5oYXZlLmtleXMoJ3ZhbHVlJyk7XG4gICAqXG4gICAqIEBuYW1lIG93blByb3BlcnR5RGVzY3JpcHRvclxuICAgKiBAYWxpYXMgaGF2ZU93blByb3BlcnR5RGVzY3JpcHRvclxuICAgKiBAcGFyYW0ge1N0cmluZ30gbmFtZVxuICAgKiBAcGFyYW0ge09iamVjdH0gZGVzY3JpcHRvciBfb3B0aW9uYWxfXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gYXNzZXJ0T3duUHJvcGVydHlEZXNjcmlwdG9yIChuYW1lLCBkZXNjcmlwdG9yLCBtc2cpIHtcbiAgICBpZiAodHlwZW9mIGRlc2NyaXB0b3IgPT09ICdzdHJpbmcnKSB7XG4gICAgICBtc2cgPSBkZXNjcmlwdG9yO1xuICAgICAgZGVzY3JpcHRvciA9IG51bGw7XG4gICAgfVxuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICB2YXIgYWN0dWFsRGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoT2JqZWN0KG9iaiksIG5hbWUpO1xuICAgIGlmIChhY3R1YWxEZXNjcmlwdG9yICYmIGRlc2NyaXB0b3IpIHtcbiAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgIF8uZXFsKGRlc2NyaXB0b3IsIGFjdHVhbERlc2NyaXB0b3IpXG4gICAgICAgICwgJ2V4cGVjdGVkIHRoZSBvd24gcHJvcGVydHkgZGVzY3JpcHRvciBmb3IgJyArIF8uaW5zcGVjdChuYW1lKSArICcgb24gI3t0aGlzfSB0byBtYXRjaCAnICsgXy5pbnNwZWN0KGRlc2NyaXB0b3IpICsgJywgZ290ICcgKyBfLmluc3BlY3QoYWN0dWFsRGVzY3JpcHRvcilcbiAgICAgICAgLCAnZXhwZWN0ZWQgdGhlIG93biBwcm9wZXJ0eSBkZXNjcmlwdG9yIGZvciAnICsgXy5pbnNwZWN0KG5hbWUpICsgJyBvbiAje3RoaXN9IHRvIG5vdCBtYXRjaCAnICsgXy5pbnNwZWN0KGRlc2NyaXB0b3IpXG4gICAgICAgICwgZGVzY3JpcHRvclxuICAgICAgICAsIGFjdHVhbERlc2NyaXB0b3JcbiAgICAgICAgLCB0cnVlXG4gICAgICApO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICBhY3R1YWxEZXNjcmlwdG9yXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBhbiBvd24gcHJvcGVydHkgZGVzY3JpcHRvciBmb3IgJyArIF8uaW5zcGVjdChuYW1lKVxuICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBoYXZlIGFuIG93biBwcm9wZXJ0eSBkZXNjcmlwdG9yIGZvciAnICsgXy5pbnNwZWN0KG5hbWUpXG4gICAgICApO1xuICAgIH1cbiAgICBmbGFnKHRoaXMsICdvYmplY3QnLCBhY3R1YWxEZXNjcmlwdG9yKTtcbiAgfVxuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ293blByb3BlcnR5RGVzY3JpcHRvcicsIGFzc2VydE93blByb3BlcnR5RGVzY3JpcHRvcik7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2hhdmVPd25Qcm9wZXJ0eURlc2NyaXB0b3InLCBhc3NlcnRPd25Qcm9wZXJ0eURlc2NyaXB0b3IpO1xuXG4gIC8qKlxuICAgKiAjIyMgLmxlbmd0aCh2YWx1ZSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQncyBgbGVuZ3RoYCBwcm9wZXJ0eSBoYXNcbiAgICogdGhlIGV4cGVjdGVkIHZhbHVlLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgM10pLnRvLmhhdmUubGVuZ3RoKDMpO1xuICAgKiAgICAgZXhwZWN0KCdmb29iYXInKS50by5oYXZlLmxlbmd0aCg2KTtcbiAgICpcbiAgICogQ2FuIGFsc28gYmUgdXNlZCBhcyBhIGNoYWluIHByZWN1cnNvciB0byBhIHZhbHVlXG4gICAqIGNvbXBhcmlzb24gZm9yIHRoZSBsZW5ndGggcHJvcGVydHkuXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2ZvbycpLnRvLmhhdmUubGVuZ3RoLmFib3ZlKDIpO1xuICAgKiAgICAgZXhwZWN0KFsgMSwgMiwgMyBdKS50by5oYXZlLmxlbmd0aC5hYm92ZSgyKTtcbiAgICogICAgIGV4cGVjdCgnZm9vJykudG8uaGF2ZS5sZW5ndGguYmVsb3coNCk7XG4gICAqICAgICBleHBlY3QoWyAxLCAyLCAzIF0pLnRvLmhhdmUubGVuZ3RoLmJlbG93KDQpO1xuICAgKiAgICAgZXhwZWN0KCdmb28nKS50by5oYXZlLmxlbmd0aC53aXRoaW4oMiw0KTtcbiAgICogICAgIGV4cGVjdChbIDEsIDIsIDMgXSkudG8uaGF2ZS5sZW5ndGgud2l0aGluKDIsNCk7XG4gICAqXG4gICAqIEBuYW1lIGxlbmd0aFxuICAgKiBAYWxpYXMgbGVuZ3RoT2ZcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGxlbmd0aFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGFzc2VydExlbmd0aENoYWluICgpIHtcbiAgICBmbGFnKHRoaXMsICdkb0xlbmd0aCcsIHRydWUpO1xuICB9XG5cbiAgZnVuY3Rpb24gYXNzZXJ0TGVuZ3RoIChuLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5wcm9wZXJ0eSgnbGVuZ3RoJyk7XG4gICAgdmFyIGxlbiA9IG9iai5sZW5ndGg7XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgbGVuID09IG5cbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSBhIGxlbmd0aCBvZiAje2V4cH0gYnV0IGdvdCAje2FjdH0nXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBoYXZlIGEgbGVuZ3RoIG9mICN7YWN0fSdcbiAgICAgICwgblxuICAgICAgLCBsZW5cbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZENoYWluYWJsZU1ldGhvZCgnbGVuZ3RoJywgYXNzZXJ0TGVuZ3RoLCBhc3NlcnRMZW5ndGhDaGFpbik7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2xlbmd0aE9mJywgYXNzZXJ0TGVuZ3RoKTtcblxuICAvKipcbiAgICogIyMjIC5tYXRjaChyZWdleHApXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IG1hdGNoZXMgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gICAqXG4gICAqICAgICBleHBlY3QoJ2Zvb2JhcicpLnRvLm1hdGNoKC9eZm9vLyk7XG4gICAqXG4gICAqIEBuYW1lIG1hdGNoXG4gICAqIEBwYXJhbSB7UmVnRXhwfSBSZWd1bGFyRXhwcmVzc2lvblxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ21hdGNoJywgZnVuY3Rpb24gKHJlLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIHJlLmV4ZWMob2JqKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBtYXRjaCAnICsgcmVcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gbm90IHRvIG1hdGNoICcgKyByZVxuICAgICk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLnN0cmluZyhzdHJpbmcpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgc3RyaW5nIHRhcmdldCBjb250YWlucyBhbm90aGVyIHN0cmluZy5cbiAgICpcbiAgICogICAgIGV4cGVjdCgnZm9vYmFyJykudG8uaGF2ZS5zdHJpbmcoJ2JhcicpO1xuICAgKlxuICAgKiBAbmFtZSBzdHJpbmdcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN0cmluZ1xuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ3N0cmluZycsIGZ1bmN0aW9uIChzdHIsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS5pcy5hKCdzdHJpbmcnKTtcblxuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICB+b2JqLmluZGV4T2Yoc3RyKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBjb250YWluICcgKyBfLmluc3BlY3Qoc3RyKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgY29udGFpbiAnICsgXy5pbnNwZWN0KHN0cilcbiAgICApO1xuICB9KTtcblxuXG4gIC8qKlxuICAgKiAjIyMgLmtleXMoa2V5MSwgW2tleTJdLCBbLi4uXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgY29udGFpbnMgYW55IG9yIGFsbCBvZiB0aGUgcGFzc2VkLWluIGtleXMuXG4gICAqIFVzZSBpbiBjb21iaW5hdGlvbiB3aXRoIGBhbnlgLCBgYWxsYCwgYGNvbnRhaW5zYCwgb3IgYGhhdmVgIHdpbGwgYWZmZWN0XG4gICAqIHdoYXQgd2lsbCBwYXNzLlxuICAgKlxuICAgKiBXaGVuIHVzZWQgaW4gY29uanVuY3Rpb24gd2l0aCBgYW55YCwgYXQgbGVhc3Qgb25lIGtleSB0aGF0IGlzIHBhc3NlZFxuICAgKiBpbiBtdXN0IGV4aXN0IGluIHRoZSB0YXJnZXQgb2JqZWN0LiBUaGlzIGlzIHJlZ2FyZGxlc3Mgd2hldGhlciBvciBub3RcbiAgICogdGhlIGBoYXZlYCBvciBgY29udGFpbmAgcXVhbGlmaWVycyBhcmUgdXNlZC4gTm90ZSwgZWl0aGVyIGBhbnlgIG9yIGBhbGxgXG4gICAqIHNob3VsZCBiZSB1c2VkIGluIHRoZSBhc3NlcnRpb24uIElmIG5laXRoZXIgYXJlIHVzZWQsIHRoZSBhc3NlcnRpb24gaXNcbiAgICogZGVmYXVsdGVkIHRvIGBhbGxgLlxuICAgKlxuICAgKiBXaGVuIGJvdGggYGFsbGAgYW5kIGBjb250YWluYCBhcmUgdXNlZCwgdGhlIHRhcmdldCBvYmplY3QgbXVzdCBoYXZlIGF0XG4gICAqIGxlYXN0IGFsbCBvZiB0aGUgcGFzc2VkLWluIGtleXMgYnV0IG1heSBoYXZlIG1vcmUga2V5cyBub3QgbGlzdGVkLlxuICAgKlxuICAgKiBXaGVuIGJvdGggYGFsbGAgYW5kIGBoYXZlYCBhcmUgdXNlZCwgdGhlIHRhcmdldCBvYmplY3QgbXVzdCBib3RoIGNvbnRhaW5cbiAgICogYWxsIG9mIHRoZSBwYXNzZWQtaW4ga2V5cyBBTkQgdGhlIG51bWJlciBvZiBrZXlzIGluIHRoZSB0YXJnZXQgb2JqZWN0IG11c3RcbiAgICogbWF0Y2ggdGhlIG51bWJlciBvZiBrZXlzIHBhc3NlZCBpbiAoaW4gb3RoZXIgd29yZHMsIGEgdGFyZ2V0IG9iamVjdCBtdXN0XG4gICAqIGhhdmUgYWxsIGFuZCBvbmx5IGFsbCBvZiB0aGUgcGFzc2VkLWluIGtleXMpLlxuICAgKlxuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAxLCBiYXI6IDIgfSkudG8uaGF2ZS5hbnkua2V5cygnZm9vJywgJ2JheicpO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAxLCBiYXI6IDIgfSkudG8uaGF2ZS5hbnkua2V5cygnZm9vJyk7XG4gICAqICAgICBleHBlY3QoeyBmb286IDEsIGJhcjogMiB9KS50by5jb250YWluLmFueS5rZXlzKCdiYXInLCAnYmF6Jyk7XG4gICAqICAgICBleHBlY3QoeyBmb286IDEsIGJhcjogMiB9KS50by5jb250YWluLmFueS5rZXlzKFsnZm9vJ10pO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAxLCBiYXI6IDIgfSkudG8uY29udGFpbi5hbnkua2V5cyh7J2Zvbyc6IDZ9KTtcbiAgICogICAgIGV4cGVjdCh7IGZvbzogMSwgYmFyOiAyIH0pLnRvLmhhdmUuYWxsLmtleXMoWydiYXInLCAnZm9vJ10pO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAxLCBiYXI6IDIgfSkudG8uaGF2ZS5hbGwua2V5cyh7J2Jhcic6IDYsICdmb28nOiA3fSk7XG4gICAqICAgICBleHBlY3QoeyBmb286IDEsIGJhcjogMiwgYmF6OiAzIH0pLnRvLmNvbnRhaW4uYWxsLmtleXMoWydiYXInLCAnZm9vJ10pO1xuICAgKiAgICAgZXhwZWN0KHsgZm9vOiAxLCBiYXI6IDIsIGJhejogMyB9KS50by5jb250YWluLmFsbC5rZXlzKFt7J2Jhcic6IDZ9fV0pO1xuICAgKlxuICAgKlxuICAgKiBAbmFtZSBrZXlzXG4gICAqIEBhbGlhcyBrZXlcbiAgICogQHBhcmFtIHtTdHJpbmcuLi58QXJyYXl8T2JqZWN0fSBrZXlzXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGZ1bmN0aW9uIGFzc2VydEtleXMgKGtleXMpIHtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgc3RyXG4gICAgICAsIG9rID0gdHJ1ZVxuICAgICAgLCBtaXhlZEFyZ3NNc2cgPSAna2V5cyBtdXN0IGJlIGdpdmVuIHNpbmdsZSBhcmd1bWVudCBvZiBBcnJheXxPYmplY3R8U3RyaW5nLCBvciBtdWx0aXBsZSBTdHJpbmcgYXJndW1lbnRzJztcblxuICAgIHN3aXRjaCAoXy50eXBlKGtleXMpKSB7XG4gICAgICBjYXNlIFwiYXJyYXlcIjpcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB0aHJvdyAobmV3IEVycm9yKG1peGVkQXJnc01zZykpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgXCJvYmplY3RcIjpcbiAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB0aHJvdyAobmV3IEVycm9yKG1peGVkQXJnc01zZykpO1xuICAgICAgICBrZXlzID0gT2JqZWN0LmtleXMoa2V5cyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAga2V5cyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG4gICAgfVxuXG4gICAgaWYgKCFrZXlzLmxlbmd0aCkgdGhyb3cgbmV3IEVycm9yKCdrZXlzIHJlcXVpcmVkJyk7XG5cbiAgICB2YXIgYWN0dWFsID0gT2JqZWN0LmtleXMob2JqKVxuICAgICAgLCBleHBlY3RlZCA9IGtleXNcbiAgICAgICwgbGVuID0ga2V5cy5sZW5ndGhcbiAgICAgICwgYW55ID0gZmxhZyh0aGlzLCAnYW55JylcbiAgICAgICwgYWxsID0gZmxhZyh0aGlzLCAnYWxsJyk7XG5cbiAgICBpZiAoIWFueSAmJiAhYWxsKSB7XG4gICAgICBhbGwgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIEhhcyBhbnlcbiAgICBpZiAoYW55KSB7XG4gICAgICB2YXIgaW50ZXJzZWN0aW9uID0gZXhwZWN0ZWQuZmlsdGVyKGZ1bmN0aW9uKGtleSkge1xuICAgICAgICByZXR1cm4gfmFjdHVhbC5pbmRleE9mKGtleSk7XG4gICAgICB9KTtcbiAgICAgIG9rID0gaW50ZXJzZWN0aW9uLmxlbmd0aCA+IDA7XG4gICAgfVxuXG4gICAgLy8gSGFzIGFsbFxuICAgIGlmIChhbGwpIHtcbiAgICAgIG9rID0ga2V5cy5ldmVyeShmdW5jdGlvbihrZXkpe1xuICAgICAgICByZXR1cm4gfmFjdHVhbC5pbmRleE9mKGtleSk7XG4gICAgICB9KTtcbiAgICAgIGlmICghZmxhZyh0aGlzLCAnbmVnYXRlJykgJiYgIWZsYWcodGhpcywgJ2NvbnRhaW5zJykpIHtcbiAgICAgICAgb2sgPSBvayAmJiBrZXlzLmxlbmd0aCA9PSBhY3R1YWwubGVuZ3RoO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEtleSBzdHJpbmdcbiAgICBpZiAobGVuID4gMSkge1xuICAgICAga2V5cyA9IGtleXMubWFwKGZ1bmN0aW9uKGtleSl7XG4gICAgICAgIHJldHVybiBfLmluc3BlY3Qoa2V5KTtcbiAgICAgIH0pO1xuICAgICAgdmFyIGxhc3QgPSBrZXlzLnBvcCgpO1xuICAgICAgaWYgKGFsbCkge1xuICAgICAgICBzdHIgPSBrZXlzLmpvaW4oJywgJykgKyAnLCBhbmQgJyArIGxhc3Q7XG4gICAgICB9XG4gICAgICBpZiAoYW55KSB7XG4gICAgICAgIHN0ciA9IGtleXMuam9pbignLCAnKSArICcsIG9yICcgKyBsYXN0O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzdHIgPSBfLmluc3BlY3Qoa2V5c1swXSk7XG4gICAgfVxuXG4gICAgLy8gRm9ybVxuICAgIHN0ciA9IChsZW4gPiAxID8gJ2tleXMgJyA6ICdrZXkgJykgKyBzdHI7XG5cbiAgICAvLyBIYXZlIC8gaW5jbHVkZVxuICAgIHN0ciA9IChmbGFnKHRoaXMsICdjb250YWlucycpID8gJ2NvbnRhaW4gJyA6ICdoYXZlICcpICsgc3RyO1xuXG4gICAgLy8gQXNzZXJ0aW9uXG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIG9rXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvICcgKyBzdHJcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90ICcgKyBzdHJcbiAgICAgICwgZXhwZWN0ZWQuc2xpY2UoMCkuc29ydCgpXG4gICAgICAsIGFjdHVhbC5zb3J0KClcbiAgICAgICwgdHJ1ZVxuICAgICk7XG4gIH1cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdrZXlzJywgYXNzZXJ0S2V5cyk7XG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2tleScsIGFzc2VydEtleXMpO1xuXG4gIC8qKlxuICAgKiAjIyMgLnRocm93KGNvbnN0cnVjdG9yKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgdGhlIGZ1bmN0aW9uIHRhcmdldCB3aWxsIHRocm93IGEgc3BlY2lmaWMgZXJyb3IsIG9yIHNwZWNpZmljIHR5cGUgb2YgZXJyb3JcbiAgICogKGFzIGRldGVybWluZWQgdXNpbmcgYGluc3RhbmNlb2ZgKSwgb3B0aW9uYWxseSB3aXRoIGEgUmVnRXhwIG9yIHN0cmluZyBpbmNsdXNpb24gdGVzdFxuICAgKiBmb3IgdGhlIGVycm9yJ3MgbWVzc2FnZS5cbiAgICpcbiAgICogICAgIHZhciBlcnIgPSBuZXcgUmVmZXJlbmNlRXJyb3IoJ1RoaXMgaXMgYSBiYWQgZnVuY3Rpb24uJyk7XG4gICAqICAgICB2YXIgZm4gPSBmdW5jdGlvbiAoKSB7IHRocm93IGVycjsgfVxuICAgKiAgICAgZXhwZWN0KGZuKS50by50aHJvdyhSZWZlcmVuY2VFcnJvcik7XG4gICAqICAgICBleHBlY3QoZm4pLnRvLnRocm93KEVycm9yKTtcbiAgICogICAgIGV4cGVjdChmbikudG8udGhyb3coL2JhZCBmdW5jdGlvbi8pO1xuICAgKiAgICAgZXhwZWN0KGZuKS50by5ub3QudGhyb3coJ2dvb2QgZnVuY3Rpb24nKTtcbiAgICogICAgIGV4cGVjdChmbikudG8udGhyb3coUmVmZXJlbmNlRXJyb3IsIC9iYWQgZnVuY3Rpb24vKTtcbiAgICogICAgIGV4cGVjdChmbikudG8udGhyb3coZXJyKTtcbiAgICogICAgIGV4cGVjdChmbikudG8ubm90LnRocm93KG5ldyBSYW5nZUVycm9yKCdPdXQgb2YgcmFuZ2UuJykpO1xuICAgKlxuICAgKiBQbGVhc2Ugbm90ZSB0aGF0IHdoZW4gYSB0aHJvdyBleHBlY3RhdGlvbiBpcyBuZWdhdGVkLCBpdCB3aWxsIGNoZWNrIGVhY2hcbiAgICogcGFyYW1ldGVyIGluZGVwZW5kZW50bHksIHN0YXJ0aW5nIHdpdGggZXJyb3IgY29uc3RydWN0b3IgdHlwZS4gVGhlIGFwcHJvcHJpYXRlIHdheVxuICAgKiB0byBjaGVjayBmb3IgdGhlIGV4aXN0ZW5jZSBvZiBhIHR5cGUgb2YgZXJyb3IgYnV0IGZvciBhIG1lc3NhZ2UgdGhhdCBkb2VzIG5vdCBtYXRjaFxuICAgKiBpcyB0byB1c2UgYGFuZGAuXG4gICAqXG4gICAqICAgICBleHBlY3QoZm4pLnRvLnRocm93KFJlZmVyZW5jZUVycm9yKVxuICAgKiAgICAgICAgLmFuZC5ub3QudGhyb3coL2dvb2QgZnVuY3Rpb24vKTtcbiAgICpcbiAgICogQG5hbWUgdGhyb3dcbiAgICogQGFsaWFzIHRocm93c1xuICAgKiBAYWxpYXMgVGhyb3dcbiAgICogQHBhcmFtIHtFcnJvckNvbnN0cnVjdG9yfSBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge1N0cmluZ3xSZWdFeHB9IGV4cGVjdGVkIGVycm9yIG1lc3NhZ2VcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Vycm9yI0Vycm9yX3R5cGVzXG4gICAqIEByZXR1cm5zIGVycm9yIGZvciBjaGFpbmluZyAobnVsbCBpZiBubyBlcnJvcilcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgZnVuY3Rpb24gYXNzZXJ0VGhyb3dzIChjb25zdHJ1Y3RvciwgZXJyTXNnLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykuaXMuYSgnZnVuY3Rpb24nKTtcblxuICAgIHZhciB0aHJvd24gPSBmYWxzZVxuICAgICAgLCBkZXNpcmVkRXJyb3IgPSBudWxsXG4gICAgICAsIG5hbWUgPSBudWxsXG4gICAgICAsIHRocm93bkVycm9yID0gbnVsbDtcblxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICBlcnJNc2cgPSBudWxsO1xuICAgICAgY29uc3RydWN0b3IgPSBudWxsO1xuICAgIH0gZWxzZSBpZiAoY29uc3RydWN0b3IgJiYgKGNvbnN0cnVjdG9yIGluc3RhbmNlb2YgUmVnRXhwIHx8ICdzdHJpbmcnID09PSB0eXBlb2YgY29uc3RydWN0b3IpKSB7XG4gICAgICBlcnJNc2cgPSBjb25zdHJ1Y3RvcjtcbiAgICAgIGNvbnN0cnVjdG9yID0gbnVsbDtcbiAgICB9IGVsc2UgaWYgKGNvbnN0cnVjdG9yICYmIGNvbnN0cnVjdG9yIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgIGRlc2lyZWRFcnJvciA9IGNvbnN0cnVjdG9yO1xuICAgICAgY29uc3RydWN0b3IgPSBudWxsO1xuICAgICAgZXJyTXNnID0gbnVsbDtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBjb25zdHJ1Y3RvciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgbmFtZSA9IGNvbnN0cnVjdG9yLnByb3RvdHlwZS5uYW1lIHx8IGNvbnN0cnVjdG9yLm5hbWU7XG4gICAgICBpZiAobmFtZSA9PT0gJ0Vycm9yJyAmJiBjb25zdHJ1Y3RvciAhPT0gRXJyb3IpIHtcbiAgICAgICAgbmFtZSA9IChuZXcgY29uc3RydWN0b3IoKSkubmFtZTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3RydWN0b3IgPSBudWxsO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBvYmooKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8vIGZpcnN0LCBjaGVjayBkZXNpcmVkIGVycm9yXG4gICAgICBpZiAoZGVzaXJlZEVycm9yKSB7XG4gICAgICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICAgICAgZXJyID09PSBkZXNpcmVkRXJyb3JcbiAgICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIHRocm93ICN7ZXhwfSBidXQgI3thY3R9IHdhcyB0aHJvd24nXG4gICAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgdGhyb3cgI3tleHB9J1xuICAgICAgICAgICwgKGRlc2lyZWRFcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZGVzaXJlZEVycm9yLnRvU3RyaW5nKCkgOiBkZXNpcmVkRXJyb3IpXG4gICAgICAgICAgLCAoZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIudG9TdHJpbmcoKSA6IGVycilcbiAgICAgICAgKTtcblxuICAgICAgICBmbGFnKHRoaXMsICdvYmplY3QnLCBlcnIpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgIH1cblxuICAgICAgLy8gbmV4dCwgY2hlY2sgY29uc3RydWN0b3JcbiAgICAgIGlmIChjb25zdHJ1Y3Rvcikge1xuICAgICAgICB0aGlzLmFzc2VydChcbiAgICAgICAgICAgIGVyciBpbnN0YW5jZW9mIGNvbnN0cnVjdG9yXG4gICAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byB0aHJvdyAje2V4cH0gYnV0ICN7YWN0fSB3YXMgdGhyb3duJ1xuICAgICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IHRocm93ICN7ZXhwfSBidXQgI3thY3R9IHdhcyB0aHJvd24nXG4gICAgICAgICAgLCBuYW1lXG4gICAgICAgICAgLCAoZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIudG9TdHJpbmcoKSA6IGVycilcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoIWVyck1zZykge1xuICAgICAgICAgIGZsYWcodGhpcywgJ29iamVjdCcsIGVycik7XG4gICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gbmV4dCwgY2hlY2sgbWVzc2FnZVxuICAgICAgdmFyIG1lc3NhZ2UgPSAnb2JqZWN0JyA9PT0gXy50eXBlKGVycikgJiYgXCJtZXNzYWdlXCIgaW4gZXJyXG4gICAgICAgID8gZXJyLm1lc3NhZ2VcbiAgICAgICAgOiAnJyArIGVycjtcblxuICAgICAgaWYgKChtZXNzYWdlICE9IG51bGwpICYmIGVyck1zZyAmJiBlcnJNc2cgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgICBlcnJNc2cuZXhlYyhtZXNzYWdlKVxuICAgICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gdGhyb3cgZXJyb3IgbWF0Y2hpbmcgI3tleHB9IGJ1dCBnb3QgI3thY3R9J1xuICAgICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gdGhyb3cgZXJyb3Igbm90IG1hdGNoaW5nICN7ZXhwfSdcbiAgICAgICAgICAsIGVyck1zZ1xuICAgICAgICAgICwgbWVzc2FnZVxuICAgICAgICApO1xuXG4gICAgICAgIGZsYWcodGhpcywgJ29iamVjdCcsIGVycik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfSBlbHNlIGlmICgobWVzc2FnZSAhPSBudWxsKSAmJiBlcnJNc2cgJiYgJ3N0cmluZycgPT09IHR5cGVvZiBlcnJNc2cpIHtcbiAgICAgICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICAgICB+bWVzc2FnZS5pbmRleE9mKGVyck1zZylcbiAgICAgICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIHRocm93IGVycm9yIGluY2x1ZGluZyAje2V4cH0gYnV0IGdvdCAje2FjdH0nXG4gICAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byB0aHJvdyBlcnJvciBub3QgaW5jbHVkaW5nICN7YWN0fSdcbiAgICAgICAgICAsIGVyck1zZ1xuICAgICAgICAgICwgbWVzc2FnZVxuICAgICAgICApO1xuXG4gICAgICAgIGZsYWcodGhpcywgJ29iamVjdCcsIGVycik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3duID0gdHJ1ZTtcbiAgICAgICAgdGhyb3duRXJyb3IgPSBlcnI7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGFjdHVhbGx5R290ID0gJydcbiAgICAgICwgZXhwZWN0ZWRUaHJvd24gPSBuYW1lICE9PSBudWxsXG4gICAgICAgID8gbmFtZVxuICAgICAgICA6IGRlc2lyZWRFcnJvclxuICAgICAgICAgID8gJyN7ZXhwfScgLy9fLmluc3BlY3QoZGVzaXJlZEVycm9yKVxuICAgICAgICAgIDogJ2FuIGVycm9yJztcblxuICAgIGlmICh0aHJvd24pIHtcbiAgICAgIGFjdHVhbGx5R290ID0gJyBidXQgI3thY3R9IHdhcyB0aHJvd24nXG4gICAgfVxuXG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgIHRocm93biA9PT0gdHJ1ZVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byB0aHJvdyAnICsgZXhwZWN0ZWRUaHJvd24gKyBhY3R1YWxseUdvdFxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgdGhyb3cgJyArIGV4cGVjdGVkVGhyb3duICsgYWN0dWFsbHlHb3RcbiAgICAgICwgKGRlc2lyZWRFcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZGVzaXJlZEVycm9yLnRvU3RyaW5nKCkgOiBkZXNpcmVkRXJyb3IpXG4gICAgICAsICh0aHJvd25FcnJvciBpbnN0YW5jZW9mIEVycm9yID8gdGhyb3duRXJyb3IudG9TdHJpbmcoKSA6IHRocm93bkVycm9yKVxuICAgICk7XG5cbiAgICBmbGFnKHRoaXMsICdvYmplY3QnLCB0aHJvd25FcnJvcik7XG4gIH07XG5cbiAgQXNzZXJ0aW9uLmFkZE1ldGhvZCgndGhyb3cnLCBhc3NlcnRUaHJvd3MpO1xuICBBc3NlcnRpb24uYWRkTWV0aG9kKCd0aHJvd3MnLCBhc3NlcnRUaHJvd3MpO1xuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdUaHJvdycsIGFzc2VydFRocm93cyk7XG5cbiAgLyoqXG4gICAqICMjIyAucmVzcG9uZFRvKG1ldGhvZClcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSBvYmplY3Qgb3IgY2xhc3MgdGFyZ2V0IHdpbGwgcmVzcG9uZCB0byBhIG1ldGhvZC5cbiAgICpcbiAgICogICAgIEtsYXNzLnByb3RvdHlwZS5iYXIgPSBmdW5jdGlvbigpe307XG4gICAqICAgICBleHBlY3QoS2xhc3MpLnRvLnJlc3BvbmRUbygnYmFyJyk7XG4gICAqICAgICBleHBlY3Qob2JqKS50by5yZXNwb25kVG8oJ2JhcicpO1xuICAgKlxuICAgKiBUbyBjaGVjayBpZiBhIGNvbnN0cnVjdG9yIHdpbGwgcmVzcG9uZCB0byBhIHN0YXRpYyBmdW5jdGlvbixcbiAgICogc2V0IHRoZSBgaXRzZWxmYCBmbGFnLlxuICAgKlxuICAgKiAgICAgS2xhc3MuYmF6ID0gZnVuY3Rpb24oKXt9O1xuICAgKiAgICAgZXhwZWN0KEtsYXNzKS5pdHNlbGYudG8ucmVzcG9uZFRvKCdiYXonKTtcbiAgICpcbiAgICogQG5hbWUgcmVzcG9uZFRvXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXRob2RcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdyZXNwb25kVG8nLCBmdW5jdGlvbiAobWV0aG9kLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0JylcbiAgICAgICwgaXRzZWxmID0gZmxhZyh0aGlzLCAnaXRzZWxmJylcbiAgICAgICwgY29udGV4dCA9ICgnZnVuY3Rpb24nID09PSBfLnR5cGUob2JqKSAmJiAhaXRzZWxmKVxuICAgICAgICA/IG9iai5wcm90b3R5cGVbbWV0aG9kXVxuICAgICAgICA6IG9ialttZXRob2RdO1xuXG4gICAgdGhpcy5hc3NlcnQoXG4gICAgICAgICdmdW5jdGlvbicgPT09IHR5cGVvZiBjb250ZXh0XG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIHJlc3BvbmQgdG8gJyArIF8uaW5zcGVjdChtZXRob2QpXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCByZXNwb25kIHRvICcgKyBfLmluc3BlY3QobWV0aG9kKVxuICAgICk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiAjIyMgLml0c2VsZlxuICAgKlxuICAgKiBTZXRzIHRoZSBgaXRzZWxmYCBmbGFnLCBsYXRlciB1c2VkIGJ5IHRoZSBgcmVzcG9uZFRvYCBhc3NlcnRpb24uXG4gICAqXG4gICAqICAgICBmdW5jdGlvbiBGb28oKSB7fVxuICAgKiAgICAgRm9vLmJhciA9IGZ1bmN0aW9uKCkge31cbiAgICogICAgIEZvby5wcm90b3R5cGUuYmF6ID0gZnVuY3Rpb24oKSB7fVxuICAgKlxuICAgKiAgICAgZXhwZWN0KEZvbykuaXRzZWxmLnRvLnJlc3BvbmRUbygnYmFyJyk7XG4gICAqICAgICBleHBlY3QoRm9vKS5pdHNlbGYubm90LnRvLnJlc3BvbmRUbygnYmF6Jyk7XG4gICAqXG4gICAqIEBuYW1lIGl0c2VsZlxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkUHJvcGVydHkoJ2l0c2VsZicsIGZ1bmN0aW9uICgpIHtcbiAgICBmbGFnKHRoaXMsICdpdHNlbGYnLCB0cnVlKTtcbiAgfSk7XG5cbiAgLyoqXG4gICAqICMjIyAuc2F0aXNmeShtZXRob2QpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IHBhc3NlcyBhIGdpdmVuIHRydXRoIHRlc3QuXG4gICAqXG4gICAqICAgICBleHBlY3QoMSkudG8uc2F0aXNmeShmdW5jdGlvbihudW0pIHsgcmV0dXJuIG51bSA+IDA7IH0pO1xuICAgKlxuICAgKiBAbmFtZSBzYXRpc2Z5XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IG1hdGNoZXJcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBBc3NlcnRpb24uYWRkTWV0aG9kKCdzYXRpc2Z5JywgZnVuY3Rpb24gKG1hdGNoZXIsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBvYmogPSBmbGFnKHRoaXMsICdvYmplY3QnKTtcbiAgICB2YXIgcmVzdWx0ID0gbWF0Y2hlcihvYmopO1xuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICByZXN1bHRcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gc2F0aXNmeSAnICsgXy5vYmpEaXNwbGF5KG1hdGNoZXIpXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBzYXRpc2Z5JyArIF8ub2JqRGlzcGxheShtYXRjaGVyKVxuICAgICAgLCB0aGlzLm5lZ2F0ZSA/IGZhbHNlIDogdHJ1ZVxuICAgICAgLCByZXN1bHRcbiAgICApO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5jbG9zZVRvKGV4cGVjdGVkLCBkZWx0YSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IHRoZSB0YXJnZXQgaXMgZXF1YWwgYGV4cGVjdGVkYCwgdG8gd2l0aGluIGEgKy8tIGBkZWx0YWAgcmFuZ2UuXG4gICAqXG4gICAqICAgICBleHBlY3QoMS41KS50by5iZS5jbG9zZVRvKDEsIDAuNSk7XG4gICAqXG4gICAqIEBuYW1lIGNsb3NlVG9cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkZWx0YVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ2Nsb3NlVG8nLCBmdW5jdGlvbiAoZXhwZWN0ZWQsIGRlbHRhLCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG5cbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS5pcy5hKCdudW1iZXInKTtcbiAgICBpZiAoXy50eXBlKGV4cGVjdGVkKSAhPT0gJ251bWJlcicgfHwgXy50eXBlKGRlbHRhKSAhPT0gJ251bWJlcicpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndGhlIGFyZ3VtZW50cyB0byBjbG9zZVRvIG11c3QgYmUgbnVtYmVycycpO1xuICAgIH1cblxuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgICBNYXRoLmFicyhvYmogLSBleHBlY3RlZCkgPD0gZGVsdGFcbiAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgY2xvc2UgdG8gJyArIGV4cGVjdGVkICsgJyArLy0gJyArIGRlbHRhXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IG5vdCB0byBiZSBjbG9zZSB0byAnICsgZXhwZWN0ZWQgKyAnICsvLSAnICsgZGVsdGFcbiAgICApO1xuICB9KTtcblxuICBmdW5jdGlvbiBpc1N1YnNldE9mKHN1YnNldCwgc3VwZXJzZXQsIGNtcCkge1xuICAgIHJldHVybiBzdWJzZXQuZXZlcnkoZnVuY3Rpb24oZWxlbSkge1xuICAgICAgaWYgKCFjbXApIHJldHVybiBzdXBlcnNldC5pbmRleE9mKGVsZW0pICE9PSAtMTtcblxuICAgICAgcmV0dXJuIHN1cGVyc2V0LnNvbWUoZnVuY3Rpb24oZWxlbTIpIHtcbiAgICAgICAgcmV0dXJuIGNtcChlbGVtLCBlbGVtMik7XG4gICAgICB9KTtcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqICMjIyAubWVtYmVycyhzZXQpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGEgc3VwZXJzZXQgb2YgYHNldGAsXG4gICAqIG9yIHRoYXQgdGhlIHRhcmdldCBhbmQgYHNldGAgaGF2ZSB0aGUgc2FtZSBzdHJpY3RseS1lcXVhbCAoPT09KSBtZW1iZXJzLlxuICAgKiBBbHRlcm5hdGVseSwgaWYgdGhlIGBkZWVwYCBmbGFnIGlzIHNldCwgc2V0IG1lbWJlcnMgYXJlIGNvbXBhcmVkIGZvciBkZWVwXG4gICAqIGVxdWFsaXR5LlxuICAgKlxuICAgKiAgICAgZXhwZWN0KFsxLCAyLCAzXSkudG8uaW5jbHVkZS5tZW1iZXJzKFszLCAyXSk7XG4gICAqICAgICBleHBlY3QoWzEsIDIsIDNdKS50by5ub3QuaW5jbHVkZS5tZW1iZXJzKFszLCAyLCA4XSk7XG4gICAqXG4gICAqICAgICBleHBlY3QoWzQsIDJdKS50by5oYXZlLm1lbWJlcnMoWzIsIDRdKTtcbiAgICogICAgIGV4cGVjdChbNSwgMl0pLnRvLm5vdC5oYXZlLm1lbWJlcnMoWzUsIDIsIDFdKTtcbiAgICpcbiAgICogICAgIGV4cGVjdChbeyBpZDogMSB9XSkudG8uZGVlcC5pbmNsdWRlLm1lbWJlcnMoW3sgaWQ6IDEgfV0pO1xuICAgKlxuICAgKiBAbmFtZSBtZW1iZXJzXG4gICAqIEBwYXJhbSB7QXJyYXl9IHNldFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIEFzc2VydGlvbi5hZGRNZXRob2QoJ21lbWJlcnMnLCBmdW5jdGlvbiAoc3Vic2V0LCBtc2cpIHtcbiAgICBpZiAobXNnKSBmbGFnKHRoaXMsICdtZXNzYWdlJywgbXNnKTtcbiAgICB2YXIgb2JqID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG5cbiAgICBuZXcgQXNzZXJ0aW9uKG9iaikudG8uYmUuYW4oJ2FycmF5Jyk7XG4gICAgbmV3IEFzc2VydGlvbihzdWJzZXQpLnRvLmJlLmFuKCdhcnJheScpO1xuXG4gICAgdmFyIGNtcCA9IGZsYWcodGhpcywgJ2RlZXAnKSA/IF8uZXFsIDogdW5kZWZpbmVkO1xuXG4gICAgaWYgKGZsYWcodGhpcywgJ2NvbnRhaW5zJykpIHtcbiAgICAgIHJldHVybiB0aGlzLmFzc2VydChcbiAgICAgICAgICBpc1N1YnNldE9mKHN1YnNldCwgb2JqLCBjbXApXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gYmUgYSBzdXBlcnNldCBvZiAje2FjdH0nXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gbm90IGJlIGEgc3VwZXJzZXQgb2YgI3thY3R9J1xuICAgICAgICAsIG9ialxuICAgICAgICAsIHN1YnNldFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgICAgaXNTdWJzZXRPZihvYmosIHN1YnNldCwgY21wKSAmJiBpc1N1YnNldE9mKHN1YnNldCwgb2JqLCBjbXApXG4gICAgICAgICwgJ2V4cGVjdGVkICN7dGhpc30gdG8gaGF2ZSB0aGUgc2FtZSBtZW1iZXJzIGFzICN7YWN0fSdcbiAgICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgaGF2ZSB0aGUgc2FtZSBtZW1iZXJzIGFzICN7YWN0fSdcbiAgICAgICAgLCBvYmpcbiAgICAgICAgLCBzdWJzZXRcbiAgICApO1xuICB9KTtcblxuICAvKipcbiAgICogIyMjIC5jaGFuZ2UoZnVuY3Rpb24pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBhIGZ1bmN0aW9uIGNoYW5nZXMgYW4gb2JqZWN0IHByb3BlcnR5XG4gICAqXG4gICAqICAgICB2YXIgb2JqID0geyB2YWw6IDEwIH07XG4gICAqICAgICB2YXIgZm4gPSBmdW5jdGlvbigpIHsgb2JqLnZhbCArPSAzIH07XG4gICAqICAgICB2YXIgbm9DaGFuZ2VGbiA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gJ2ZvbycgKyAnYmFyJzsgfVxuICAgKiAgICAgZXhwZWN0KGZuKS50by5jaGFuZ2Uob2JqLCAndmFsJyk7XG4gICAqICAgICBleHBlY3Qobm9DaGFuZ0ZuKS50by5ub3QuY2hhbmdlKG9iaiwgJ3ZhbCcpXG4gICAqXG4gICAqIEBuYW1lIGNoYW5nZVxuICAgKiBAYWxpYXMgY2hhbmdlc1xuICAgKiBAYWxpYXMgQ2hhbmdlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRDaGFuZ2VzIChvYmplY3QsIHByb3AsIG1zZykge1xuICAgIGlmIChtc2cpIGZsYWcodGhpcywgJ21lc3NhZ2UnLCBtc2cpO1xuICAgIHZhciBmbiA9IGZsYWcodGhpcywgJ29iamVjdCcpO1xuICAgIG5ldyBBc3NlcnRpb24ob2JqZWN0LCBtc2cpLnRvLmhhdmUucHJvcGVydHkocHJvcCk7XG4gICAgbmV3IEFzc2VydGlvbihmbikuaXMuYSgnZnVuY3Rpb24nKTtcblxuICAgIHZhciBpbml0aWFsID0gb2JqZWN0W3Byb3BdO1xuICAgIGZuKCk7XG5cbiAgICB0aGlzLmFzc2VydChcbiAgICAgIGluaXRpYWwgIT09IG9iamVjdFtwcm9wXVxuICAgICAgLCAnZXhwZWN0ZWQgLicgKyBwcm9wICsgJyB0byBjaGFuZ2UnXG4gICAgICAsICdleHBlY3RlZCAuJyArIHByb3AgKyAnIHRvIG5vdCBjaGFuZ2UnXG4gICAgKTtcbiAgfVxuXG4gIEFzc2VydGlvbi5hZGRDaGFpbmFibGVNZXRob2QoJ2NoYW5nZScsIGFzc2VydENoYW5nZXMpO1xuICBBc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdjaGFuZ2VzJywgYXNzZXJ0Q2hhbmdlcyk7XG5cbiAgLyoqXG4gICAqICMjIyAuaW5jcmVhc2UoZnVuY3Rpb24pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBhIGZ1bmN0aW9uIGluY3JlYXNlcyBhbiBvYmplY3QgcHJvcGVydHlcbiAgICpcbiAgICogICAgIHZhciBvYmogPSB7IHZhbDogMTAgfTtcbiAgICogICAgIHZhciBmbiA9IGZ1bmN0aW9uKCkgeyBvYmoudmFsID0gMTUgfTtcbiAgICogICAgIGV4cGVjdChmbikudG8uaW5jcmVhc2Uob2JqLCAndmFsJyk7XG4gICAqXG4gICAqIEBuYW1lIGluY3JlYXNlXG4gICAqIEBhbGlhcyBpbmNyZWFzZXNcbiAgICogQGFsaWFzIEluY3JlYXNlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnRJbmNyZWFzZXMgKG9iamVjdCwgcHJvcCwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIGZuID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgbmV3IEFzc2VydGlvbihvYmplY3QsIG1zZykudG8uaGF2ZS5wcm9wZXJ0eShwcm9wKTtcbiAgICBuZXcgQXNzZXJ0aW9uKGZuKS5pcy5hKCdmdW5jdGlvbicpO1xuXG4gICAgdmFyIGluaXRpYWwgPSBvYmplY3RbcHJvcF07XG4gICAgZm4oKTtcblxuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgb2JqZWN0W3Byb3BdIC0gaW5pdGlhbCA+IDBcbiAgICAgICwgJ2V4cGVjdGVkIC4nICsgcHJvcCArICcgdG8gaW5jcmVhc2UnXG4gICAgICAsICdleHBlY3RlZCAuJyArIHByb3AgKyAnIHRvIG5vdCBpbmNyZWFzZSdcbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZENoYWluYWJsZU1ldGhvZCgnaW5jcmVhc2UnLCBhc3NlcnRJbmNyZWFzZXMpO1xuICBBc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdpbmNyZWFzZXMnLCBhc3NlcnRJbmNyZWFzZXMpO1xuXG4gIC8qKlxuICAgKiAjIyMgLmRlY3JlYXNlKGZ1bmN0aW9uKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYSBmdW5jdGlvbiBkZWNyZWFzZXMgYW4gb2JqZWN0IHByb3BlcnR5XG4gICAqXG4gICAqICAgICB2YXIgb2JqID0geyB2YWw6IDEwIH07XG4gICAqICAgICB2YXIgZm4gPSBmdW5jdGlvbigpIHsgb2JqLnZhbCA9IDUgfTtcbiAgICogICAgIGV4cGVjdChmbikudG8uZGVjcmVhc2Uob2JqLCAndmFsJyk7XG4gICAqXG4gICAqIEBuYW1lIGRlY3JlYXNlXG4gICAqIEBhbGlhcyBkZWNyZWFzZXNcbiAgICogQGFsaWFzIERlY3JlYXNlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBmdW5jdGlvbiBhc3NlcnREZWNyZWFzZXMgKG9iamVjdCwgcHJvcCwgbXNnKSB7XG4gICAgaWYgKG1zZykgZmxhZyh0aGlzLCAnbWVzc2FnZScsIG1zZyk7XG4gICAgdmFyIGZuID0gZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gICAgbmV3IEFzc2VydGlvbihvYmplY3QsIG1zZykudG8uaGF2ZS5wcm9wZXJ0eShwcm9wKTtcbiAgICBuZXcgQXNzZXJ0aW9uKGZuKS5pcy5hKCdmdW5jdGlvbicpO1xuXG4gICAgdmFyIGluaXRpYWwgPSBvYmplY3RbcHJvcF07XG4gICAgZm4oKTtcblxuICAgIHRoaXMuYXNzZXJ0KFxuICAgICAgb2JqZWN0W3Byb3BdIC0gaW5pdGlhbCA8IDBcbiAgICAgICwgJ2V4cGVjdGVkIC4nICsgcHJvcCArICcgdG8gZGVjcmVhc2UnXG4gICAgICAsICdleHBlY3RlZCAuJyArIHByb3AgKyAnIHRvIG5vdCBkZWNyZWFzZSdcbiAgICApO1xuICB9XG5cbiAgQXNzZXJ0aW9uLmFkZENoYWluYWJsZU1ldGhvZCgnZGVjcmVhc2UnLCBhc3NlcnREZWNyZWFzZXMpO1xuICBBc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdkZWNyZWFzZXMnLCBhc3NlcnREZWNyZWFzZXMpO1xuXG59O1xuIiwiLyohXG4gKiBjaGFpXG4gKiBDb3B5cmlnaHQoYykgMjAxMS0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjaGFpLCB1dGlsKSB7XG5cbiAgLyohXG4gICAqIENoYWkgZGVwZW5kZW5jaWVzLlxuICAgKi9cblxuICB2YXIgQXNzZXJ0aW9uID0gY2hhaS5Bc3NlcnRpb25cbiAgICAsIGZsYWcgPSB1dGlsLmZsYWc7XG5cbiAgLyohXG4gICAqIE1vZHVsZSBleHBvcnQuXG4gICAqL1xuXG4gIC8qKlxuICAgKiAjIyMgYXNzZXJ0KGV4cHJlc3Npb24sIG1lc3NhZ2UpXG4gICAqXG4gICAqIFdyaXRlIHlvdXIgb3duIHRlc3QgZXhwcmVzc2lvbnMuXG4gICAqXG4gICAqICAgICBhc3NlcnQoJ2ZvbycgIT09ICdiYXInLCAnZm9vIGlzIG5vdCBiYXInKTtcbiAgICogICAgIGFzc2VydChBcnJheS5pc0FycmF5KFtdKSwgJ2VtcHR5IGFycmF5cyBhcmUgYXJyYXlzJyk7XG4gICAqXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGV4cHJlc3Npb24gdG8gdGVzdCBmb3IgdHJ1dGhpbmVzc1xuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSB0byBkaXNwbGF5IG9uIGVycm9yXG4gICAqIEBuYW1lIGFzc2VydFxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICB2YXIgYXNzZXJ0ID0gY2hhaS5hc3NlcnQgPSBmdW5jdGlvbiAoZXhwcmVzcywgZXJybXNnKSB7XG4gICAgdmFyIHRlc3QgPSBuZXcgQXNzZXJ0aW9uKG51bGwsIG51bGwsIGNoYWkuYXNzZXJ0KTtcbiAgICB0ZXN0LmFzc2VydChcbiAgICAgICAgZXhwcmVzc1xuICAgICAgLCBlcnJtc2dcbiAgICAgICwgJ1sgbmVnYXRpb24gbWVzc2FnZSB1bmF2YWlsYWJsZSBdJ1xuICAgICk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBbbWVzc2FnZV0sIFtvcGVyYXRvcl0pXG4gICAqXG4gICAqIFRocm93IGEgZmFpbHVyZS4gTm9kZS5qcyBgYXNzZXJ0YCBtb2R1bGUtY29tcGF0aWJsZS5cbiAgICpcbiAgICogQG5hbWUgZmFpbFxuICAgKiBAcGFyYW0ge01peGVkfSBhY3R1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gZXhwZWN0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQHBhcmFtIHtTdHJpbmd9IG9wZXJhdG9yXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5mYWlsID0gZnVuY3Rpb24gKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UsIG9wZXJhdG9yKSB7XG4gICAgbWVzc2FnZSA9IG1lc3NhZ2UgfHwgJ2Fzc2VydC5mYWlsKCknO1xuICAgIHRocm93IG5ldyBjaGFpLkFzc2VydGlvbkVycm9yKG1lc3NhZ2UsIHtcbiAgICAgICAgYWN0dWFsOiBhY3R1YWxcbiAgICAgICwgZXhwZWN0ZWQ6IGV4cGVjdGVkXG4gICAgICAsIG9wZXJhdG9yOiBvcGVyYXRvclxuICAgIH0sIGFzc2VydC5mYWlsKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5vayhvYmplY3QsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBvYmplY3RgIGlzIHRydXRoeS5cbiAgICpcbiAgICogICAgIGFzc2VydC5vaygnZXZlcnl0aGluZycsICdldmVyeXRoaW5nIGlzIG9rJyk7XG4gICAqICAgICBhc3NlcnQub2soZmFsc2UsICd0aGlzIHdpbGwgZmFpbCcpO1xuICAgKlxuICAgKiBAbmFtZSBva1xuICAgKiBAcGFyYW0ge01peGVkfSBvYmplY3QgdG8gdGVzdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQub2sgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS5pcy5vaztcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5ub3RPayhvYmplY3QsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBvYmplY3RgIGlzIGZhbHN5LlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm5vdE9rKCdldmVyeXRoaW5nJywgJ3RoaXMgd2lsbCBmYWlsJyk7XG4gICAqICAgICBhc3NlcnQubm90T2soZmFsc2UsICd0aGlzIHdpbGwgcGFzcycpO1xuICAgKlxuICAgKiBAbmFtZSBub3RPa1xuICAgKiBAcGFyYW0ge01peGVkfSBvYmplY3QgdG8gdGVzdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubm90T2sgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS5pcy5ub3Qub2s7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuZXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIG5vbi1zdHJpY3QgZXF1YWxpdHkgKGA9PWApIG9mIGBhY3R1YWxgIGFuZCBgZXhwZWN0ZWRgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LmVxdWFsKDMsICczJywgJz09IGNvZXJjZXMgdmFsdWVzIHRvIHN0cmluZ3MnKTtcbiAgICpcbiAgICogQG5hbWUgZXF1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gYWN0dWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5lcXVhbCA9IGZ1bmN0aW9uIChhY3QsIGV4cCwgbXNnKSB7XG4gICAgdmFyIHRlc3QgPSBuZXcgQXNzZXJ0aW9uKGFjdCwgbXNnLCBhc3NlcnQuZXF1YWwpO1xuXG4gICAgdGVzdC5hc3NlcnQoXG4gICAgICAgIGV4cCA9PSBmbGFnKHRlc3QsICdvYmplY3QnKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBlcXVhbCAje2V4cH0nXG4gICAgICAsICdleHBlY3RlZCAje3RoaXN9IHRvIG5vdCBlcXVhbCAje2FjdH0nXG4gICAgICAsIGV4cFxuICAgICAgLCBhY3RcbiAgICApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyBub24tc3RyaWN0IGluZXF1YWxpdHkgKGAhPWApIG9mIGBhY3R1YWxgIGFuZCBgZXhwZWN0ZWRgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm5vdEVxdWFsKDMsIDQsICd0aGVzZSBudW1iZXJzIGFyZSBub3QgZXF1YWwnKTtcbiAgICpcbiAgICogQG5hbWUgbm90RXF1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gYWN0dWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5ub3RFcXVhbCA9IGZ1bmN0aW9uIChhY3QsIGV4cCwgbXNnKSB7XG4gICAgdmFyIHRlc3QgPSBuZXcgQXNzZXJ0aW9uKGFjdCwgbXNnLCBhc3NlcnQubm90RXF1YWwpO1xuXG4gICAgdGVzdC5hc3NlcnQoXG4gICAgICAgIGV4cCAhPSBmbGFnKHRlc3QsICdvYmplY3QnKVxuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBub3QgZXF1YWwgI3tleHB9J1xuICAgICAgLCAnZXhwZWN0ZWQgI3t0aGlzfSB0byBlcXVhbCAje2FjdH0nXG4gICAgICAsIGV4cFxuICAgICAgLCBhY3RcbiAgICApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLnN0cmljdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyBzdHJpY3QgZXF1YWxpdHkgKGA9PT1gKSBvZiBgYWN0dWFsYCBhbmQgYGV4cGVjdGVkYC5cbiAgICpcbiAgICogICAgIGFzc2VydC5zdHJpY3RFcXVhbCh0cnVlLCB0cnVlLCAndGhlc2UgYm9vbGVhbnMgYXJlIHN0cmljdGx5IGVxdWFsJyk7XG4gICAqXG4gICAqIEBuYW1lIHN0cmljdEVxdWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGFjdHVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBleHBlY3RlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuc3RyaWN0RXF1YWwgPSBmdW5jdGlvbiAoYWN0LCBleHAsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24oYWN0LCBtc2cpLnRvLmVxdWFsKGV4cCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAubm90U3RyaWN0RXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHN0cmljdCBpbmVxdWFsaXR5IChgIT09YCkgb2YgYGFjdHVhbGAgYW5kIGBleHBlY3RlZGAuXG4gICAqXG4gICAqICAgICBhc3NlcnQubm90U3RyaWN0RXF1YWwoMywgJzMnLCAnbm8gY29lcmNpb24gZm9yIHN0cmljdCBlcXVhbGl0eScpO1xuICAgKlxuICAgKiBAbmFtZSBub3RTdHJpY3RFcXVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBhY3R1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gZXhwZWN0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm5vdFN0cmljdEVxdWFsID0gZnVuY3Rpb24gKGFjdCwgZXhwLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGFjdCwgbXNnKS50by5ub3QuZXF1YWwoZXhwKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5kZWVwRXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYGFjdHVhbGAgaXMgZGVlcGx5IGVxdWFsIHRvIGBleHBlY3RlZGAuXG4gICAqXG4gICAqICAgICBhc3NlcnQuZGVlcEVxdWFsKHsgdGVhOiAnZ3JlZW4nIH0sIHsgdGVhOiAnZ3JlZW4nIH0pO1xuICAgKlxuICAgKiBAbmFtZSBkZWVwRXF1YWxcbiAgICogQHBhcmFtIHtNaXhlZH0gYWN0dWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5kZWVwRXF1YWwgPSBmdW5jdGlvbiAoYWN0LCBleHAsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24oYWN0LCBtc2cpLnRvLmVxbChleHApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdERlZXBFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydCB0aGF0IGBhY3R1YWxgIGlzIG5vdCBkZWVwbHkgZXF1YWwgdG8gYGV4cGVjdGVkYC5cbiAgICpcbiAgICogICAgIGFzc2VydC5ub3REZWVwRXF1YWwoeyB0ZWE6ICdncmVlbicgfSwgeyB0ZWE6ICdqYXNtaW5lJyB9KTtcbiAgICpcbiAgICogQG5hbWUgbm90RGVlcEVxdWFsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGFjdHVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBleHBlY3RlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubm90RGVlcEVxdWFsID0gZnVuY3Rpb24gKGFjdCwgZXhwLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGFjdCwgbXNnKS50by5ub3QuZXFsKGV4cCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNUcnVlKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIHRydWUuXG4gICAqXG4gICAqICAgICB2YXIgdGVhU2VydmVkID0gdHJ1ZTtcbiAgICogICAgIGFzc2VydC5pc1RydWUodGVhU2VydmVkLCAndGhlIHRlYSBoYXMgYmVlbiBzZXJ2ZWQnKTtcbiAgICpcbiAgICogQG5hbWUgaXNUcnVlXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc0Fib3ZlID0gZnVuY3Rpb24gKHZhbCwgYWJ2LCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5iZS5hYm92ZShhYnYpO1xuICB9O1xuXG4gICAvKipcbiAgICogIyMjIC5pc0Fib3ZlKHZhbHVlVG9DaGVjaywgdmFsdWVUb0JlQWJvdmUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyBgdmFsdWVUb0NoZWNrYCBpcyBzdHJpY3RseSBncmVhdGVyIHRoYW4gKD4pIGB2YWx1ZVRvQmVBYm92ZWBcbiAgICpcbiAgICogICAgIGFzc2VydC5pc0Fib3ZlKDUsIDIsICc1IGlzIHN0cmljdGx5IGdyZWF0ZXIgdGhhbiAyJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzQWJvdmVcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVUb0NoZWNrXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlVG9CZUFib3ZlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc0JlbG93ID0gZnVuY3Rpb24gKHZhbCwgYmx3LCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5iZS5iZWxvdyhibHcpO1xuICB9O1xuXG4gICAvKipcbiAgICogIyMjIC5pc0JlbG93KHZhbHVlVG9DaGVjaywgdmFsdWVUb0JlQmVsb3csIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyBgdmFsdWVUb0NoZWNrYCBpcyBzdHJpY3RseSBsZXNzIHRoYW4gKDwpIGB2YWx1ZVRvQmVCZWxvd2BcbiAgICpcbiAgICogICAgIGFzc2VydC5pc0JlbG93KDMsIDYsICczIGlzIHN0cmljdGx5IGxlc3MgdGhhbiA2Jyk7XG4gICAqXG4gICAqIEBuYW1lIGlzQmVsb3dcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVUb0NoZWNrXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlVG9CZUJlbG93XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc1RydWUgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS5pc1sndHJ1ZSddO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzRmFsc2UodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgZmFsc2UuXG4gICAqXG4gICAqICAgICB2YXIgdGVhU2VydmVkID0gZmFsc2U7XG4gICAqICAgICBhc3NlcnQuaXNGYWxzZSh0ZWFTZXJ2ZWQsICdubyB0ZWEgeWV0PyBobW0uLi4nKTtcbiAgICpcbiAgICogQG5hbWUgaXNGYWxzZVxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNGYWxzZSA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLmlzWydmYWxzZSddO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzTnVsbCh2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBudWxsLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LmlzTnVsbChlcnIsICd0aGVyZSB3YXMgbm8gZXJyb3InKTtcbiAgICpcbiAgICogQG5hbWUgaXNOdWxsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc051bGwgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5lcXVhbChudWxsKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc05vdE51bGwodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgbm90IG51bGwuXG4gICAqXG4gICAqICAgICB2YXIgdGVhID0gJ3Rhc3R5IGNoYWknO1xuICAgKiAgICAgYXNzZXJ0LmlzTm90TnVsbCh0ZWEsICdncmVhdCwgdGltZSBmb3IgdGVhIScpO1xuICAgKlxuICAgKiBAbmFtZSBpc05vdE51bGxcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzTm90TnVsbCA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLm5vdC5lcXVhbChudWxsKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc1VuZGVmaW5lZCh2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBgdW5kZWZpbmVkYC5cbiAgICpcbiAgICogICAgIHZhciB0ZWE7XG4gICAqICAgICBhc3NlcnQuaXNVbmRlZmluZWQodGVhLCAnbm8gdGVhIGRlZmluZWQnKTtcbiAgICpcbiAgICogQG5hbWUgaXNVbmRlZmluZWRcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzVW5kZWZpbmVkID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uZXF1YWwodW5kZWZpbmVkKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc0RlZmluZWQodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgbm90IGB1bmRlZmluZWRgLlxuICAgKlxuICAgKiAgICAgdmFyIHRlYSA9ICdjdXAgb2YgY2hhaSc7XG4gICAqICAgICBhc3NlcnQuaXNEZWZpbmVkKHRlYSwgJ3RlYSBoYXMgYmVlbiBkZWZpbmVkJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzRGVmaW5lZFxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNEZWZpbmVkID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8ubm90LmVxdWFsKHVuZGVmaW5lZCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNGdW5jdGlvbih2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBhIGZ1bmN0aW9uLlxuICAgKlxuICAgKiAgICAgZnVuY3Rpb24gc2VydmVUZWEoKSB7IHJldHVybiAnY3VwIG9mIHRlYSc7IH07XG4gICAqICAgICBhc3NlcnQuaXNGdW5jdGlvbihzZXJ2ZVRlYSwgJ2dyZWF0LCB3ZSBjYW4gaGF2ZSB0ZWEgbm93Jyk7XG4gICAqXG4gICAqIEBuYW1lIGlzRnVuY3Rpb25cbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzRnVuY3Rpb24gPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5iZS5hKCdmdW5jdGlvbicpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzTm90RnVuY3Rpb24odmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgX25vdF8gYSBmdW5jdGlvbi5cbiAgICpcbiAgICogICAgIHZhciBzZXJ2ZVRlYSA9IFsgJ2hlYXQnLCAncG91cicsICdzaXAnIF07XG4gICAqICAgICBhc3NlcnQuaXNOb3RGdW5jdGlvbihzZXJ2ZVRlYSwgJ2dyZWF0LCB3ZSBoYXZlIGxpc3RlZCB0aGUgc3RlcHMnKTtcbiAgICpcbiAgICogQG5hbWUgaXNOb3RGdW5jdGlvblxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNOb3RGdW5jdGlvbiA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLm5vdC5iZS5hKCdmdW5jdGlvbicpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmlzT2JqZWN0KHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIGFuIG9iamVjdCAoYXMgcmV2ZWFsZWQgYnlcbiAgICogYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdgKS5cbiAgICpcbiAgICogICAgIHZhciBzZWxlY3Rpb24gPSB7IG5hbWU6ICdDaGFpJywgc2VydmU6ICd3aXRoIHNwaWNlcycgfTtcbiAgICogICAgIGFzc2VydC5pc09iamVjdChzZWxlY3Rpb24sICd0ZWEgc2VsZWN0aW9uIGlzIGFuIG9iamVjdCcpO1xuICAgKlxuICAgKiBAbmFtZSBpc09iamVjdFxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNPYmplY3QgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5iZS5hKCdvYmplY3QnKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc05vdE9iamVjdCh2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBfbm90XyBhbiBvYmplY3QuXG4gICAqXG4gICAqICAgICB2YXIgc2VsZWN0aW9uID0gJ2NoYWknXG4gICAqICAgICBhc3NlcnQuaXNOb3RPYmplY3Qoc2VsZWN0aW9uLCAndGVhIHNlbGVjdGlvbiBpcyBub3QgYW4gb2JqZWN0Jyk7XG4gICAqICAgICBhc3NlcnQuaXNOb3RPYmplY3QobnVsbCwgJ251bGwgaXMgbm90IGFuIG9iamVjdCcpO1xuICAgKlxuICAgKiBAbmFtZSBpc05vdE9iamVjdFxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNOb3RPYmplY3QgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuYSgnb2JqZWN0Jyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNBcnJheSh2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBhbiBhcnJheS5cbiAgICpcbiAgICogICAgIHZhciBtZW51ID0gWyAnZ3JlZW4nLCAnY2hhaScsICdvb2xvbmcnIF07XG4gICAqICAgICBhc3NlcnQuaXNBcnJheShtZW51LCAnd2hhdCBraW5kIG9mIHRlYSBkbyB3ZSB3YW50PycpO1xuICAgKlxuICAgKiBAbmFtZSBpc0FycmF5XG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc0FycmF5ID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uYmUuYW4oJ2FycmF5Jyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNOb3RBcnJheSh2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBfbm90XyBhbiBhcnJheS5cbiAgICpcbiAgICogICAgIHZhciBtZW51ID0gJ2dyZWVufGNoYWl8b29sb25nJztcbiAgICogICAgIGFzc2VydC5pc05vdEFycmF5KG1lbnUsICd3aGF0IGtpbmQgb2YgdGVhIGRvIHdlIHdhbnQ/Jyk7XG4gICAqXG4gICAqIEBuYW1lIGlzTm90QXJyYXlcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzTm90QXJyYXkgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuYW4oJ2FycmF5Jyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNTdHJpbmcodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgYSBzdHJpbmcuXG4gICAqXG4gICAqICAgICB2YXIgdGVhT3JkZXIgPSAnY2hhaSc7XG4gICAqICAgICBhc3NlcnQuaXNTdHJpbmcodGVhT3JkZXIsICdvcmRlciBwbGFjZWQnKTtcbiAgICpcbiAgICogQG5hbWUgaXNTdHJpbmdcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzU3RyaW5nID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uYmUuYSgnc3RyaW5nJyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNOb3RTdHJpbmcodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgX25vdF8gYSBzdHJpbmcuXG4gICAqXG4gICAqICAgICB2YXIgdGVhT3JkZXIgPSA0O1xuICAgKiAgICAgYXNzZXJ0LmlzTm90U3RyaW5nKHRlYU9yZGVyLCAnb3JkZXIgcGxhY2VkJyk7XG4gICAqXG4gICAqIEBuYW1lIGlzTm90U3RyaW5nXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc05vdFN0cmluZyA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLm5vdC5iZS5hKCdzdHJpbmcnKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pc051bWJlcih2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBpcyBhIG51bWJlci5cbiAgICpcbiAgICogICAgIHZhciBjdXBzID0gMjtcbiAgICogICAgIGFzc2VydC5pc051bWJlcihjdXBzLCAnaG93IG1hbnkgY3VwcycpO1xuICAgKlxuICAgKiBAbmFtZSBpc051bWJlclxuICAgKiBAcGFyYW0ge051bWJlcn0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzTnVtYmVyID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uYmUuYSgnbnVtYmVyJyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNOb3ROdW1iZXIodmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgX25vdF8gYSBudW1iZXIuXG4gICAqXG4gICAqICAgICB2YXIgY3VwcyA9ICcyIGN1cHMgcGxlYXNlJztcbiAgICogICAgIGFzc2VydC5pc05vdE51bWJlcihjdXBzLCAnaG93IG1hbnkgY3VwcycpO1xuICAgKlxuICAgKiBAbmFtZSBpc05vdE51bWJlclxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaXNOb3ROdW1iZXIgPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuYSgnbnVtYmVyJyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNCb29sZWFuKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIGEgYm9vbGVhbi5cbiAgICpcbiAgICogICAgIHZhciB0ZWFSZWFkeSA9IHRydWVcbiAgICogICAgICAgLCB0ZWFTZXJ2ZWQgPSBmYWxzZTtcbiAgICpcbiAgICogICAgIGFzc2VydC5pc0Jvb2xlYW4odGVhUmVhZHksICdpcyB0aGUgdGVhIHJlYWR5Jyk7XG4gICAqICAgICBhc3NlcnQuaXNCb29sZWFuKHRlYVNlcnZlZCwgJ2hhcyB0ZWEgYmVlbiBzZXJ2ZWQnKTtcbiAgICpcbiAgICogQG5hbWUgaXNCb29sZWFuXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pc0Jvb2xlYW4gPSBmdW5jdGlvbiAodmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5iZS5hKCdib29sZWFuJyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuaXNOb3RCb29sZWFuKHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgIGlzIF9ub3RfIGEgYm9vbGVhbi5cbiAgICpcbiAgICogICAgIHZhciB0ZWFSZWFkeSA9ICd5ZXAnXG4gICAqICAgICAgICwgdGVhU2VydmVkID0gJ25vcGUnO1xuICAgKlxuICAgKiAgICAgYXNzZXJ0LmlzTm90Qm9vbGVhbih0ZWFSZWFkeSwgJ2lzIHRoZSB0ZWEgcmVhZHknKTtcbiAgICogICAgIGFzc2VydC5pc05vdEJvb2xlYW4odGVhU2VydmVkLCAnaGFzIHRlYSBiZWVuIHNlcnZlZCcpO1xuICAgKlxuICAgKiBAbmFtZSBpc05vdEJvb2xlYW5cbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmlzTm90Qm9vbGVhbiA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLm5vdC5iZS5hKCdib29sZWFuJyk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAudHlwZU9mKHZhbHVlLCBuYW1lLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgJ3MgdHlwZSBpcyBgbmFtZWAsIGFzIGRldGVybWluZWQgYnlcbiAgICogYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LnR5cGVPZih7IHRlYTogJ2NoYWknIH0sICdvYmplY3QnLCAnd2UgaGF2ZSBhbiBvYmplY3QnKTtcbiAgICogICAgIGFzc2VydC50eXBlT2YoWydjaGFpJywgJ2phc21pbmUnXSwgJ2FycmF5JywgJ3dlIGhhdmUgYW4gYXJyYXknKTtcbiAgICogICAgIGFzc2VydC50eXBlT2YoJ3RlYScsICdzdHJpbmcnLCAnd2UgaGF2ZSBhIHN0cmluZycpO1xuICAgKiAgICAgYXNzZXJ0LnR5cGVPZigvdGVhLywgJ3JlZ2V4cCcsICd3ZSBoYXZlIGEgcmVndWxhciBleHByZXNzaW9uJyk7XG4gICAqICAgICBhc3NlcnQudHlwZU9mKG51bGwsICdudWxsJywgJ3dlIGhhdmUgYSBudWxsJyk7XG4gICAqICAgICBhc3NlcnQudHlwZU9mKHVuZGVmaW5lZCwgJ3VuZGVmaW5lZCcsICd3ZSBoYXZlIGFuIHVuZGVmaW5lZCcpO1xuICAgKlxuICAgKiBAbmFtZSB0eXBlT2ZcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LnR5cGVPZiA9IGZ1bmN0aW9uICh2YWwsIHR5cGUsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLmJlLmEodHlwZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAubm90VHlwZU9mKHZhbHVlLCBuYW1lLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgdmFsdWVgJ3MgdHlwZSBpcyBfbm90XyBgbmFtZWAsIGFzIGRldGVybWluZWQgYnlcbiAgICogYE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmdgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm5vdFR5cGVPZigndGVhJywgJ251bWJlcicsICdzdHJpbmdzIGFyZSBub3QgbnVtYmVycycpO1xuICAgKlxuICAgKiBAbmFtZSBub3RUeXBlT2ZcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IHR5cGVvZiBuYW1lXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5ub3RUeXBlT2YgPSBmdW5jdGlvbiAodmFsLCB0eXBlLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuYSh0eXBlKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pbnN0YW5jZU9mKG9iamVjdCwgY29uc3RydWN0b3IsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgaXMgYW4gaW5zdGFuY2Ugb2YgYGNvbnN0cnVjdG9yYC5cbiAgICpcbiAgICogICAgIHZhciBUZWEgPSBmdW5jdGlvbiAobmFtZSkgeyB0aGlzLm5hbWUgPSBuYW1lOyB9XG4gICAqICAgICAgICwgY2hhaSA9IG5ldyBUZWEoJ2NoYWknKTtcbiAgICpcbiAgICogICAgIGFzc2VydC5pbnN0YW5jZU9mKGNoYWksIFRlYSwgJ2NoYWkgaXMgYW4gaW5zdGFuY2Ugb2YgdGVhJyk7XG4gICAqXG4gICAqIEBuYW1lIGluc3RhbmNlT2ZcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge0NvbnN0cnVjdG9yfSBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaW5zdGFuY2VPZiA9IGZ1bmN0aW9uICh2YWwsIHR5cGUsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24odmFsLCBtc2cpLnRvLmJlLmluc3RhbmNlT2YodHlwZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAubm90SW5zdGFuY2VPZihvYmplY3QsIGNvbnN0cnVjdG9yLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgYHZhbHVlYCBpcyBub3QgYW4gaW5zdGFuY2Ugb2YgYGNvbnN0cnVjdG9yYC5cbiAgICpcbiAgICogICAgIHZhciBUZWEgPSBmdW5jdGlvbiAobmFtZSkgeyB0aGlzLm5hbWUgPSBuYW1lOyB9XG4gICAqICAgICAgICwgY2hhaSA9IG5ldyBTdHJpbmcoJ2NoYWknKTtcbiAgICpcbiAgICogICAgIGFzc2VydC5ub3RJbnN0YW5jZU9mKGNoYWksIFRlYSwgJ2NoYWkgaXMgbm90IGFuIGluc3RhbmNlIG9mIHRlYScpO1xuICAgKlxuICAgKiBAbmFtZSBub3RJbnN0YW5jZU9mXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtDb25zdHJ1Y3Rvcn0gY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm5vdEluc3RhbmNlT2YgPSBmdW5jdGlvbiAodmFsLCB0eXBlLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuYmUuaW5zdGFuY2VPZih0eXBlKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5pbmNsdWRlKGhheXN0YWNrLCBuZWVkbGUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBoYXlzdGFja2AgaW5jbHVkZXMgYG5lZWRsZWAuIFdvcmtzXG4gICAqIGZvciBzdHJpbmdzIGFuZCBhcnJheXMuXG4gICAqXG4gICAqICAgICBhc3NlcnQuaW5jbHVkZSgnZm9vYmFyJywgJ2JhcicsICdmb29iYXIgY29udGFpbnMgc3RyaW5nIFwiYmFyXCInKTtcbiAgICogICAgIGFzc2VydC5pbmNsdWRlKFsgMSwgMiwgMyBdLCAzLCAnYXJyYXkgY29udGFpbnMgdmFsdWUnKTtcbiAgICpcbiAgICogQG5hbWUgaW5jbHVkZVxuICAgKiBAcGFyYW0ge0FycmF5fFN0cmluZ30gaGF5c3RhY2tcbiAgICogQHBhcmFtIHtNaXhlZH0gbmVlZGxlXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5pbmNsdWRlID0gZnVuY3Rpb24gKGV4cCwgaW5jLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGV4cCwgbXNnLCBhc3NlcnQuaW5jbHVkZSkuaW5jbHVkZShpbmMpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdEluY2x1ZGUoaGF5c3RhY2ssIG5lZWRsZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYGhheXN0YWNrYCBkb2VzIG5vdCBpbmNsdWRlIGBuZWVkbGVgLiBXb3Jrc1xuICAgKiBmb3Igc3RyaW5ncyBhbmQgYXJyYXlzLlxuICAgKmlcbiAgICogICAgIGFzc2VydC5ub3RJbmNsdWRlKCdmb29iYXInLCAnYmF6JywgJ3N0cmluZyBub3QgaW5jbHVkZSBzdWJzdHJpbmcnKTtcbiAgICogICAgIGFzc2VydC5ub3RJbmNsdWRlKFsgMSwgMiwgMyBdLCA0LCAnYXJyYXkgbm90IGluY2x1ZGUgY29udGFpbiB2YWx1ZScpO1xuICAgKlxuICAgKiBAbmFtZSBub3RJbmNsdWRlXG4gICAqIEBwYXJhbSB7QXJyYXl8U3RyaW5nfSBoYXlzdGFja1xuICAgKiBAcGFyYW0ge01peGVkfSBuZWVkbGVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm5vdEluY2x1ZGUgPSBmdW5jdGlvbiAoZXhwLCBpbmMsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24oZXhwLCBtc2csIGFzc2VydC5ub3RJbmNsdWRlKS5ub3QuaW5jbHVkZShpbmMpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm1hdGNoKHZhbHVlLCByZWdleHAsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGB2YWx1ZWAgbWF0Y2hlcyB0aGUgcmVndWxhciBleHByZXNzaW9uIGByZWdleHBgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm1hdGNoKCdmb29iYXInLCAvXmZvby8sICdyZWdleHAgbWF0Y2hlcycpO1xuICAgKlxuICAgKiBAbmFtZSBtYXRjaFxuICAgKiBAcGFyYW0ge01peGVkfSB2YWx1ZVxuICAgKiBAcGFyYW0ge1JlZ0V4cH0gcmVnZXhwXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5tYXRjaCA9IGZ1bmN0aW9uIChleHAsIHJlLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGV4cCwgbXNnKS50by5tYXRjaChyZSk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAubm90TWF0Y2godmFsdWUsIHJlZ2V4cCwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHZhbHVlYCBkb2VzIG5vdCBtYXRjaCB0aGUgcmVndWxhciBleHByZXNzaW9uIGByZWdleHBgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm5vdE1hdGNoKCdmb29iYXInLCAvXmZvby8sICdyZWdleHAgZG9lcyBub3QgbWF0Y2gnKTtcbiAgICpcbiAgICogQG5hbWUgbm90TWF0Y2hcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtSZWdFeHB9IHJlZ2V4cFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubm90TWF0Y2ggPSBmdW5jdGlvbiAoZXhwLCByZSwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihleHAsIG1zZykudG8ubm90Lm1hdGNoKHJlKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5wcm9wZXJ0eShvYmplY3QsIHByb3BlcnR5LCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgb2JqZWN0YCBoYXMgYSBwcm9wZXJ0eSBuYW1lZCBieSBgcHJvcGVydHlgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LnByb3BlcnR5KHsgdGVhOiB7IGdyZWVuOiAnbWF0Y2hhJyB9fSwgJ3RlYScpO1xuICAgKlxuICAgKiBAbmFtZSBwcm9wZXJ0eVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQucHJvcGVydHkgPSBmdW5jdGlvbiAob2JqLCBwcm9wLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5oYXZlLnByb3BlcnR5KHByb3ApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLm5vdFByb3BlcnR5KG9iamVjdCwgcHJvcGVydHksIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBvYmplY3RgIGRvZXMgX25vdF8gaGF2ZSBhIHByb3BlcnR5IG5hbWVkIGJ5IGBwcm9wZXJ0eWAuXG4gICAqXG4gICAqICAgICBhc3NlcnQubm90UHJvcGVydHkoeyB0ZWE6IHsgZ3JlZW46ICdtYXRjaGEnIH19LCAnY29mZmVlJyk7XG4gICAqXG4gICAqIEBuYW1lIG5vdFByb3BlcnR5XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5ub3RQcm9wZXJ0eSA9IGZ1bmN0aW9uIChvYmosIHByb3AsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24ob2JqLCBtc2cpLnRvLm5vdC5oYXZlLnByb3BlcnR5KHByb3ApO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmRlZXBQcm9wZXJ0eShvYmplY3QsIHByb3BlcnR5LCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgb2JqZWN0YCBoYXMgYSBwcm9wZXJ0eSBuYW1lZCBieSBgcHJvcGVydHlgLCB3aGljaCBjYW4gYmUgYVxuICAgKiBzdHJpbmcgdXNpbmcgZG90LSBhbmQgYnJhY2tldC1ub3RhdGlvbiBmb3IgZGVlcCByZWZlcmVuY2UuXG4gICAqXG4gICAqICAgICBhc3NlcnQuZGVlcFByb3BlcnR5KHsgdGVhOiB7IGdyZWVuOiAnbWF0Y2hhJyB9fSwgJ3RlYS5ncmVlbicpO1xuICAgKlxuICAgKiBAbmFtZSBkZWVwUHJvcGVydHlcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmRlZXBQcm9wZXJ0eSA9IGZ1bmN0aW9uIChvYmosIHByb3AsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24ob2JqLCBtc2cpLnRvLmhhdmUuZGVlcC5wcm9wZXJ0eShwcm9wKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5ub3REZWVwUHJvcGVydHkob2JqZWN0LCBwcm9wZXJ0eSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYG9iamVjdGAgZG9lcyBfbm90XyBoYXZlIGEgcHJvcGVydHkgbmFtZWQgYnkgYHByb3BlcnR5YCwgd2hpY2hcbiAgICogY2FuIGJlIGEgc3RyaW5nIHVzaW5nIGRvdC0gYW5kIGJyYWNrZXQtbm90YXRpb24gZm9yIGRlZXAgcmVmZXJlbmNlLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0Lm5vdERlZXBQcm9wZXJ0eSh7IHRlYTogeyBncmVlbjogJ21hdGNoYScgfX0sICd0ZWEub29sb25nJyk7XG4gICAqXG4gICAqIEBuYW1lIG5vdERlZXBQcm9wZXJ0eVxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQubm90RGVlcFByb3BlcnR5ID0gZnVuY3Rpb24gKG9iaiwgcHJvcCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8ubm90LmhhdmUuZGVlcC5wcm9wZXJ0eShwcm9wKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5wcm9wZXJ0eVZhbChvYmplY3QsIHByb3BlcnR5LCB2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYG9iamVjdGAgaGFzIGEgcHJvcGVydHkgbmFtZWQgYnkgYHByb3BlcnR5YCB3aXRoIHZhbHVlIGdpdmVuXG4gICAqIGJ5IGB2YWx1ZWAuXG4gICAqXG4gICAqICAgICBhc3NlcnQucHJvcGVydHlWYWwoeyB0ZWE6ICdpcyBnb29kJyB9LCAndGVhJywgJ2lzIGdvb2QnKTtcbiAgICpcbiAgICogQG5hbWUgcHJvcGVydHlWYWxcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LnByb3BlcnR5VmFsID0gZnVuY3Rpb24gKG9iaiwgcHJvcCwgdmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5oYXZlLnByb3BlcnR5KHByb3AsIHZhbCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAucHJvcGVydHlOb3RWYWwob2JqZWN0LCBwcm9wZXJ0eSwgdmFsdWUsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBvYmplY3RgIGhhcyBhIHByb3BlcnR5IG5hbWVkIGJ5IGBwcm9wZXJ0eWAsIGJ1dCB3aXRoIGEgdmFsdWVcbiAgICogZGlmZmVyZW50IGZyb20gdGhhdCBnaXZlbiBieSBgdmFsdWVgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LnByb3BlcnR5Tm90VmFsKHsgdGVhOiAnaXMgZ29vZCcgfSwgJ3RlYScsICdpcyBiYWQnKTtcbiAgICpcbiAgICogQG5hbWUgcHJvcGVydHlOb3RWYWxcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LnByb3BlcnR5Tm90VmFsID0gZnVuY3Rpb24gKG9iaiwgcHJvcCwgdmFsLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKG9iaiwgbXNnKS50by5ub3QuaGF2ZS5wcm9wZXJ0eShwcm9wLCB2YWwpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmRlZXBQcm9wZXJ0eVZhbChvYmplY3QsIHByb3BlcnR5LCB2YWx1ZSwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYG9iamVjdGAgaGFzIGEgcHJvcGVydHkgbmFtZWQgYnkgYHByb3BlcnR5YCB3aXRoIHZhbHVlIGdpdmVuXG4gICAqIGJ5IGB2YWx1ZWAuIGBwcm9wZXJ0eWAgY2FuIHVzZSBkb3QtIGFuZCBicmFja2V0LW5vdGF0aW9uIGZvciBkZWVwXG4gICAqIHJlZmVyZW5jZS5cbiAgICpcbiAgICogICAgIGFzc2VydC5kZWVwUHJvcGVydHlWYWwoeyB0ZWE6IHsgZ3JlZW46ICdtYXRjaGEnIH19LCAndGVhLmdyZWVuJywgJ21hdGNoYScpO1xuICAgKlxuICAgKiBAbmFtZSBkZWVwUHJvcGVydHlWYWxcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmRlZXBQcm9wZXJ0eVZhbCA9IGZ1bmN0aW9uIChvYmosIHByb3AsIHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8uaGF2ZS5kZWVwLnByb3BlcnR5KHByb3AsIHZhbCk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuZGVlcFByb3BlcnR5Tm90VmFsKG9iamVjdCwgcHJvcGVydHksIHZhbHVlLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgb2JqZWN0YCBoYXMgYSBwcm9wZXJ0eSBuYW1lZCBieSBgcHJvcGVydHlgLCBidXQgd2l0aCBhIHZhbHVlXG4gICAqIGRpZmZlcmVudCBmcm9tIHRoYXQgZ2l2ZW4gYnkgYHZhbHVlYC4gYHByb3BlcnR5YCBjYW4gdXNlIGRvdC0gYW5kXG4gICAqIGJyYWNrZXQtbm90YXRpb24gZm9yIGRlZXAgcmVmZXJlbmNlLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LmRlZXBQcm9wZXJ0eU5vdFZhbCh7IHRlYTogeyBncmVlbjogJ21hdGNoYScgfX0sICd0ZWEuZ3JlZW4nLCAna29uYWNoYScpO1xuICAgKlxuICAgKiBAbmFtZSBkZWVwUHJvcGVydHlOb3RWYWxcbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHlcbiAgICogQHBhcmFtIHtNaXhlZH0gdmFsdWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmRlZXBQcm9wZXJ0eU5vdFZhbCA9IGZ1bmN0aW9uIChvYmosIHByb3AsIHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihvYmosIG1zZykudG8ubm90LmhhdmUuZGVlcC5wcm9wZXJ0eShwcm9wLCB2YWwpO1xuICB9O1xuXG4gIC8qKlxuICAgKiAjIyMgLmxlbmd0aE9mKG9iamVjdCwgbGVuZ3RoLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgb2JqZWN0YCBoYXMgYSBgbGVuZ3RoYCBwcm9wZXJ0eSB3aXRoIHRoZSBleHBlY3RlZCB2YWx1ZS5cbiAgICpcbiAgICogICAgIGFzc2VydC5sZW5ndGhPZihbMSwyLDNdLCAzLCAnYXJyYXkgaGFzIGxlbmd0aCBvZiAzJyk7XG4gICAqICAgICBhc3NlcnQubGVuZ3RoT2YoJ2Zvb2JhcicsIDUsICdzdHJpbmcgaGFzIGxlbmd0aCBvZiA2Jyk7XG4gICAqXG4gICAqIEBuYW1lIGxlbmd0aE9mXG4gICAqIEBwYXJhbSB7TWl4ZWR9IG9iamVjdFxuICAgKiBAcGFyYW0ge051bWJlcn0gbGVuZ3RoXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5sZW5ndGhPZiA9IGZ1bmN0aW9uIChleHAsIGxlbiwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihleHAsIG1zZykudG8uaGF2ZS5sZW5ndGgobGVuKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC50aHJvd3MoZnVuY3Rpb24sIFtjb25zdHJ1Y3Rvci9zdHJpbmcvcmVnZXhwXSwgW3N0cmluZy9yZWdleHBdLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgZnVuY3Rpb25gIHdpbGwgdGhyb3cgYW4gZXJyb3IgdGhhdCBpcyBhbiBpbnN0YW5jZSBvZlxuICAgKiBgY29uc3RydWN0b3JgLCBvciBhbHRlcm5hdGVseSB0aGF0IGl0IHdpbGwgdGhyb3cgYW4gZXJyb3Igd2l0aCBtZXNzYWdlXG4gICAqIG1hdGNoaW5nIGByZWdleHBgLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LnRocm93KGZuLCAnZnVuY3Rpb24gdGhyb3dzIGEgcmVmZXJlbmNlIGVycm9yJyk7XG4gICAqICAgICBhc3NlcnQudGhyb3coZm4sIC9mdW5jdGlvbiB0aHJvd3MgYSByZWZlcmVuY2UgZXJyb3IvKTtcbiAgICogICAgIGFzc2VydC50aHJvdyhmbiwgUmVmZXJlbmNlRXJyb3IpO1xuICAgKiAgICAgYXNzZXJ0LnRocm93KGZuLCBSZWZlcmVuY2VFcnJvciwgJ2Z1bmN0aW9uIHRocm93cyBhIHJlZmVyZW5jZSBlcnJvcicpO1xuICAgKiAgICAgYXNzZXJ0LnRocm93KGZuLCBSZWZlcmVuY2VFcnJvciwgL2Z1bmN0aW9uIHRocm93cyBhIHJlZmVyZW5jZSBlcnJvci8pO1xuICAgKlxuICAgKiBAbmFtZSB0aHJvd3NcbiAgICogQGFsaWFzIHRocm93XG4gICAqIEBhbGlhcyBUaHJvd1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jdGlvblxuICAgKiBAcGFyYW0ge0Vycm9yQ29uc3RydWN0b3J9IGNvbnN0cnVjdG9yXG4gICAqIEBwYXJhbSB7UmVnRXhwfSByZWdleHBcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9FcnJvciNFcnJvcl90eXBlc1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuVGhyb3cgPSBmdW5jdGlvbiAoZm4sIGVycnQsIGVycnMsIG1zZykge1xuICAgIGlmICgnc3RyaW5nJyA9PT0gdHlwZW9mIGVycnQgfHwgZXJydCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgZXJycyA9IGVycnQ7XG4gICAgICBlcnJ0ID0gbnVsbDtcbiAgICB9XG5cbiAgICB2YXIgYXNzZXJ0RXJyID0gbmV3IEFzc2VydGlvbihmbiwgbXNnKS50by5UaHJvdyhlcnJ0LCBlcnJzKTtcbiAgICByZXR1cm4gZmxhZyhhc3NlcnRFcnIsICdvYmplY3QnKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5kb2VzTm90VGhyb3coZnVuY3Rpb24sIFtjb25zdHJ1Y3Rvci9yZWdleHBdLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgZnVuY3Rpb25gIHdpbGwgX25vdF8gdGhyb3cgYW4gZXJyb3IgdGhhdCBpcyBhbiBpbnN0YW5jZSBvZlxuICAgKiBgY29uc3RydWN0b3JgLCBvciBhbHRlcm5hdGVseSB0aGF0IGl0IHdpbGwgbm90IHRocm93IGFuIGVycm9yIHdpdGggbWVzc2FnZVxuICAgKiBtYXRjaGluZyBgcmVnZXhwYC5cbiAgICpcbiAgICogICAgIGFzc2VydC5kb2VzTm90VGhyb3coZm4sIEVycm9yLCAnZnVuY3Rpb24gZG9lcyBub3QgdGhyb3cnKTtcbiAgICpcbiAgICogQG5hbWUgZG9lc05vdFRocm93XG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7RXJyb3JDb25zdHJ1Y3Rvcn0gY29uc3RydWN0b3JcbiAgICogQHBhcmFtIHtSZWdFeHB9IHJlZ2V4cFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0Vycm9yI0Vycm9yX3R5cGVzXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5kb2VzTm90VGhyb3cgPSBmdW5jdGlvbiAoZm4sIHR5cGUsIG1zZykge1xuICAgIGlmICgnc3RyaW5nJyA9PT0gdHlwZW9mIHR5cGUpIHtcbiAgICAgIG1zZyA9IHR5cGU7XG4gICAgICB0eXBlID0gbnVsbDtcbiAgICB9XG5cbiAgICBuZXcgQXNzZXJ0aW9uKGZuLCBtc2cpLnRvLm5vdC5UaHJvdyh0eXBlKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5vcGVyYXRvcih2YWwxLCBvcGVyYXRvciwgdmFsMiwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBDb21wYXJlcyB0d28gdmFsdWVzIHVzaW5nIGBvcGVyYXRvcmAuXG4gICAqXG4gICAqICAgICBhc3NlcnQub3BlcmF0b3IoMSwgJzwnLCAyLCAnZXZlcnl0aGluZyBpcyBvaycpO1xuICAgKiAgICAgYXNzZXJ0Lm9wZXJhdG9yKDEsICc+JywgMiwgJ3RoaXMgd2lsbCBmYWlsJyk7XG4gICAqXG4gICAqIEBuYW1lIG9wZXJhdG9yXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbDFcbiAgICogQHBhcmFtIHtTdHJpbmd9IG9wZXJhdG9yXG4gICAqIEBwYXJhbSB7TWl4ZWR9IHZhbDJcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0Lm9wZXJhdG9yID0gZnVuY3Rpb24gKHZhbCwgb3BlcmF0b3IsIHZhbDIsIG1zZykge1xuICAgIHZhciBvaztcbiAgICBzd2l0Y2gob3BlcmF0b3IpIHtcbiAgICAgIGNhc2UgJz09JzpcbiAgICAgICAgb2sgPSB2YWwgPT0gdmFsMjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICc9PT0nOlxuICAgICAgICBvayA9IHZhbCA9PT0gdmFsMjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICc+JzpcbiAgICAgICAgb2sgPSB2YWwgPiB2YWwyO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJz49JzpcbiAgICAgICAgb2sgPSB2YWwgPj0gdmFsMjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICc8JzpcbiAgICAgICAgb2sgPSB2YWwgPCB2YWwyO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJzw9JzpcbiAgICAgICAgb2sgPSB2YWwgPD0gdmFsMjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICchPSc6XG4gICAgICAgIG9rID0gdmFsICE9IHZhbDI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnIT09JzpcbiAgICAgICAgb2sgPSB2YWwgIT09IHZhbDI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIG9wZXJhdG9yIFwiJyArIG9wZXJhdG9yICsgJ1wiJyk7XG4gICAgfVxuICAgIHZhciB0ZXN0ID0gbmV3IEFzc2VydGlvbihvaywgbXNnKTtcbiAgICB0ZXN0LmFzc2VydChcbiAgICAgICAgdHJ1ZSA9PT0gZmxhZyh0ZXN0LCAnb2JqZWN0JylcbiAgICAgICwgJ2V4cGVjdGVkICcgKyB1dGlsLmluc3BlY3QodmFsKSArICcgdG8gYmUgJyArIG9wZXJhdG9yICsgJyAnICsgdXRpbC5pbnNwZWN0KHZhbDIpXG4gICAgICAsICdleHBlY3RlZCAnICsgdXRpbC5pbnNwZWN0KHZhbCkgKyAnIHRvIG5vdCBiZSAnICsgb3BlcmF0b3IgKyAnICcgKyB1dGlsLmluc3BlY3QodmFsMikgKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5jbG9zZVRvKGFjdHVhbCwgZXhwZWN0ZWQsIGRlbHRhLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCB0aGUgdGFyZ2V0IGlzIGVxdWFsIGBleHBlY3RlZGAsIHRvIHdpdGhpbiBhICsvLSBgZGVsdGFgIHJhbmdlLlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LmNsb3NlVG8oMS41LCAxLCAwLjUsICdudW1iZXJzIGFyZSBjbG9zZScpO1xuICAgKlxuICAgKiBAbmFtZSBjbG9zZVRvXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBhY3R1YWxcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGV4cGVjdGVkXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBkZWx0YVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuY2xvc2VUbyA9IGZ1bmN0aW9uIChhY3QsIGV4cCwgZGVsdGEsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24oYWN0LCBtc2cpLnRvLmJlLmNsb3NlVG8oZXhwLCBkZWx0YSk7XG4gIH07XG5cbiAgLyoqXG4gICAqICMjIyAuc2FtZU1lbWJlcnMoc2V0MSwgc2V0MiwgW21lc3NhZ2VdKVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYHNldDFgIGFuZCBgc2V0MmAgaGF2ZSB0aGUgc2FtZSBtZW1iZXJzLlxuICAgKiBPcmRlciBpcyBub3QgdGFrZW4gaW50byBhY2NvdW50LlxuICAgKlxuICAgKiAgICAgYXNzZXJ0LnNhbWVNZW1iZXJzKFsgMSwgMiwgMyBdLCBbIDIsIDEsIDMgXSwgJ3NhbWUgbWVtYmVycycpO1xuICAgKlxuICAgKiBAbmFtZSBzYW1lTWVtYmVyc1xuICAgKiBAcGFyYW0ge0FycmF5fSBzZXQxXG4gICAqIEBwYXJhbSB7QXJyYXl9IHNldDJcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LnNhbWVNZW1iZXJzID0gZnVuY3Rpb24gKHNldDEsIHNldDIsIG1zZykge1xuICAgIG5ldyBBc3NlcnRpb24oc2V0MSwgbXNnKS50by5oYXZlLnNhbWUubWVtYmVycyhzZXQyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiAjIyMgLnNhbWVEZWVwTWVtYmVycyhzZXQxLCBzZXQyLCBbbWVzc2FnZV0pXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBgc2V0MWAgYW5kIGBzZXQyYCBoYXZlIHRoZSBzYW1lIG1lbWJlcnMgLSB1c2luZyBhIGRlZXAgZXF1YWxpdHkgY2hlY2tpbmcuXG4gICAqIE9yZGVyIGlzIG5vdCB0YWtlbiBpbnRvIGFjY291bnQuXG4gICAqXG4gICAqICAgICBhc3NlcnQuc2FtZURlZXBNZW1iZXJzKFsge2I6IDN9LCB7YTogMn0sIHtjOiA1fSBdLCBbIHtjOiA1fSwge2I6IDN9LCB7YTogMn0gXSwgJ3NhbWUgZGVlcCBtZW1iZXJzJyk7XG4gICAqXG4gICAqIEBuYW1lIHNhbWVEZWVwTWVtYmVyc1xuICAgKiBAcGFyYW0ge0FycmF5fSBzZXQxXG4gICAqIEBwYXJhbSB7QXJyYXl9IHNldDJcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2VcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LnNhbWVEZWVwTWVtYmVycyA9IGZ1bmN0aW9uIChzZXQxLCBzZXQyLCBtc2cpIHtcbiAgICBuZXcgQXNzZXJ0aW9uKHNldDEsIG1zZykudG8uaGF2ZS5zYW1lLmRlZXAubWVtYmVycyhzZXQyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiAjIyMgLmluY2x1ZGVNZW1iZXJzKHN1cGVyc2V0LCBzdWJzZXQsIFttZXNzYWdlXSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGBzdWJzZXRgIGlzIGluY2x1ZGVkIGluIGBzdXBlcnNldGAuXG4gICAqIE9yZGVyIGlzIG5vdCB0YWtlbiBpbnRvIGFjY291bnQuXG4gICAqXG4gICAqICAgICBhc3NlcnQuaW5jbHVkZU1lbWJlcnMoWyAxLCAyLCAzIF0sIFsgMiwgMSBdLCAnaW5jbHVkZSBtZW1iZXJzJyk7XG4gICAqXG4gICAqIEBuYW1lIGluY2x1ZGVNZW1iZXJzXG4gICAqIEBwYXJhbSB7QXJyYXl9IHN1cGVyc2V0XG4gICAqIEBwYXJhbSB7QXJyYXl9IHN1YnNldFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuaW5jbHVkZU1lbWJlcnMgPSBmdW5jdGlvbiAoc3VwZXJzZXQsIHN1YnNldCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbihzdXBlcnNldCwgbXNnKS50by5pbmNsdWRlLm1lbWJlcnMoc3Vic2V0KTtcbiAgfVxuXG4gICAvKipcbiAgICogIyMjIC5jaGFuZ2VzKGZ1bmN0aW9uLCBvYmplY3QsIHByb3BlcnR5KVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYSBmdW5jdGlvbiBjaGFuZ2VzIHRoZSB2YWx1ZSBvZiBhIHByb3BlcnR5XG4gICAqXG4gICAqICAgICB2YXIgb2JqID0geyB2YWw6IDEwIH07XG4gICAqICAgICB2YXIgZm4gPSBmdW5jdGlvbigpIHsgb2JqLnZhbCA9IDIyIH07XG4gICAqICAgICBhc3NlcnQuY2hhbmdlcyhmbiwgb2JqLCAndmFsJyk7XG4gICAqXG4gICAqIEBuYW1lIGNoYW5nZXNcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gbW9kaWZpZXIgZnVuY3Rpb25cbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHkgbmFtZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5jaGFuZ2VzID0gZnVuY3Rpb24gKGZuLCBvYmosIHByb3ApIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGZuKS50by5jaGFuZ2Uob2JqLCBwcm9wKTtcbiAgfVxuXG4gICAvKipcbiAgICogIyMjIC5kb2VzTm90Q2hhbmdlKGZ1bmN0aW9uLCBvYmplY3QsIHByb3BlcnR5KVxuICAgKlxuICAgKiBBc3NlcnRzIHRoYXQgYSBmdW5jdGlvbiBkb2VzIG5vdCBjaGFuZ2VzIHRoZSB2YWx1ZSBvZiBhIHByb3BlcnR5XG4gICAqXG4gICAqICAgICB2YXIgb2JqID0geyB2YWw6IDEwIH07XG4gICAqICAgICB2YXIgZm4gPSBmdW5jdGlvbigpIHsgY29uc29sZS5sb2coJ2ZvbycpOyB9O1xuICAgKiAgICAgYXNzZXJ0LmRvZXNOb3RDaGFuZ2UoZm4sIG9iaiwgJ3ZhbCcpO1xuICAgKlxuICAgKiBAbmFtZSBkb2VzTm90Q2hhbmdlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IG1vZGlmaWVyIGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuZG9lc05vdENoYW5nZSA9IGZ1bmN0aW9uIChmbiwgb2JqLCBwcm9wKSB7XG4gICAgbmV3IEFzc2VydGlvbihmbikudG8ubm90LmNoYW5nZShvYmosIHByb3ApO1xuICB9XG5cbiAgIC8qKlxuICAgKiAjIyMgLmluY3JlYXNlcyhmdW5jdGlvbiwgb2JqZWN0LCBwcm9wZXJ0eSlcbiAgICpcbiAgICogQXNzZXJ0cyB0aGF0IGEgZnVuY3Rpb24gaW5jcmVhc2VzIGFuIG9iamVjdCBwcm9wZXJ0eVxuICAgKlxuICAgKiAgICAgdmFyIG9iaiA9IHsgdmFsOiAxMCB9O1xuICAgKiAgICAgdmFyIGZuID0gZnVuY3Rpb24oKSB7IG9iai52YWwgPSAxMyB9O1xuICAgKiAgICAgYXNzZXJ0LmluY3JlYXNlcyhmbiwgb2JqLCAndmFsJyk7XG4gICAqXG4gICAqIEBuYW1lIGluY3JlYXNlc1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBtb2RpZmllciBmdW5jdGlvblxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eSBuYW1lXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmluY3JlYXNlcyA9IGZ1bmN0aW9uIChmbiwgb2JqLCBwcm9wKSB7XG4gICAgbmV3IEFzc2VydGlvbihmbikudG8uaW5jcmVhc2Uob2JqLCBwcm9wKTtcbiAgfVxuXG4gICAvKipcbiAgICogIyMjIC5kb2VzTm90SW5jcmVhc2UoZnVuY3Rpb24sIG9iamVjdCwgcHJvcGVydHkpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBhIGZ1bmN0aW9uIGRvZXMgbm90IGluY3JlYXNlIG9iamVjdCBwcm9wZXJ0eVxuICAgKlxuICAgKiAgICAgdmFyIG9iaiA9IHsgdmFsOiAxMCB9O1xuICAgKiAgICAgdmFyIGZuID0gZnVuY3Rpb24oKSB7IG9iai52YWwgPSA4IH07XG4gICAqICAgICBhc3NlcnQuZG9lc05vdEluY3JlYXNlKGZuLCBvYmosICd2YWwnKTtcbiAgICpcbiAgICogQG5hbWUgZG9lc05vdEluY3JlYXNlXG4gICAqIEBwYXJhbSB7RnVuY3Rpb259IG1vZGlmaWVyIGZ1bmN0aW9uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3RcbiAgICogQHBhcmFtIHtTdHJpbmd9IHByb3BlcnR5IG5hbWVcbiAgICogQHBhcmFtIHtTdHJpbmd9IG1lc3NhZ2UgX29wdGlvbmFsX1xuICAgKiBAYXBpIHB1YmxpY1xuICAgKi9cblxuICBhc3NlcnQuZG9lc05vdEluY3JlYXNlID0gZnVuY3Rpb24gKGZuLCBvYmosIHByb3ApIHtcbiAgICBuZXcgQXNzZXJ0aW9uKGZuKS50by5ub3QuaW5jcmVhc2Uob2JqLCBwcm9wKTtcbiAgfVxuXG4gICAvKipcbiAgICogIyMjIC5kZWNyZWFzZXMoZnVuY3Rpb24sIG9iamVjdCwgcHJvcGVydHkpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBhIGZ1bmN0aW9uIGRlY3JlYXNlcyBhbiBvYmplY3QgcHJvcGVydHlcbiAgICpcbiAgICogICAgIHZhciBvYmogPSB7IHZhbDogMTAgfTtcbiAgICogICAgIHZhciBmbiA9IGZ1bmN0aW9uKCkgeyBvYmoudmFsID0gNSB9O1xuICAgKiAgICAgYXNzZXJ0LmRlY3JlYXNlcyhmbiwgb2JqLCAndmFsJyk7XG4gICAqXG4gICAqIEBuYW1lIGRlY3JlYXNlc1xuICAgKiBAcGFyYW0ge0Z1bmN0aW9ufSBtb2RpZmllciBmdW5jdGlvblxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBwcm9wZXJ0eSBuYW1lXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlIF9vcHRpb25hbF9cbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgYXNzZXJ0LmRlY3JlYXNlcyA9IGZ1bmN0aW9uIChmbiwgb2JqLCBwcm9wKSB7XG4gICAgbmV3IEFzc2VydGlvbihmbikudG8uZGVjcmVhc2Uob2JqLCBwcm9wKTtcbiAgfVxuXG4gICAvKipcbiAgICogIyMjIC5kb2VzTm90RGVjcmVhc2UoZnVuY3Rpb24sIG9iamVjdCwgcHJvcGVydHkpXG4gICAqXG4gICAqIEFzc2VydHMgdGhhdCBhIGZ1bmN0aW9uIGRvZXMgbm90IGRlY3JlYXNlcyBhbiBvYmplY3QgcHJvcGVydHlcbiAgICpcbiAgICogICAgIHZhciBvYmogPSB7IHZhbDogMTAgfTtcbiAgICogICAgIHZhciBmbiA9IGZ1bmN0aW9uKCkgeyBvYmoudmFsID0gMTUgfTtcbiAgICogICAgIGFzc2VydC5kb2VzTm90RGVjcmVhc2UoZm4sIG9iaiwgJ3ZhbCcpO1xuICAgKlxuICAgKiBAbmFtZSBkb2VzTm90RGVjcmVhc2VcbiAgICogQHBhcmFtIHtGdW5jdGlvbn0gbW9kaWZpZXIgZnVuY3Rpb25cbiAgICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcHJvcGVydHkgbmFtZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZSBfb3B0aW9uYWxfXG4gICAqIEBhcGkgcHVibGljXG4gICAqL1xuXG4gIGFzc2VydC5kb2VzTm90RGVjcmVhc2UgPSBmdW5jdGlvbiAoZm4sIG9iaiwgcHJvcCkge1xuICAgIG5ldyBBc3NlcnRpb24oZm4pLnRvLm5vdC5kZWNyZWFzZShvYmosIHByb3ApO1xuICB9XG5cbiAgLyohXG4gICAqIFVuZG9jdW1lbnRlZCAvIHVudGVzdGVkXG4gICAqL1xuXG4gIGFzc2VydC5pZkVycm9yID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8ubm90LmJlLm9rO1xuICB9O1xuXG4gIC8qIVxuICAgKiBBbGlhc2VzLlxuICAgKi9cblxuICAoZnVuY3Rpb24gYWxpYXMobmFtZSwgYXMpe1xuICAgIGFzc2VydFthc10gPSBhc3NlcnRbbmFtZV07XG4gICAgcmV0dXJuIGFsaWFzO1xuICB9KVxuICAoJ1Rocm93JywgJ3Rocm93JylcbiAgKCdUaHJvdycsICd0aHJvd3MnKTtcbn07XG4iLCIvKiFcbiAqIGNoYWlcbiAqIENvcHlyaWdodChjKSAyMDExLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjaGFpLCB1dGlsKSB7XG4gIGNoYWkuZXhwZWN0ID0gZnVuY3Rpb24gKHZhbCwgbWVzc2FnZSkge1xuICAgIHJldHVybiBuZXcgY2hhaS5Bc3NlcnRpb24odmFsLCBtZXNzYWdlKTtcbiAgfTtcblxuICAvKipcbiAgICogIyMjIC5mYWlsKGFjdHVhbCwgZXhwZWN0ZWQsIFttZXNzYWdlXSwgW29wZXJhdG9yXSlcbiAgICpcbiAgICogVGhyb3cgYSBmYWlsdXJlLlxuICAgKlxuICAgKiBAbmFtZSBmYWlsXG4gICAqIEBwYXJhbSB7TWl4ZWR9IGFjdHVhbFxuICAgKiBAcGFyYW0ge01peGVkfSBleHBlY3RlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgKiBAcGFyYW0ge1N0cmluZ30gb3BlcmF0b3JcbiAgICogQGFwaSBwdWJsaWNcbiAgICovXG5cbiAgY2hhaS5leHBlY3QuZmFpbCA9IGZ1bmN0aW9uIChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCBvcGVyYXRvcikge1xuICAgIG1lc3NhZ2UgPSBtZXNzYWdlIHx8ICdleHBlY3QuZmFpbCgpJztcbiAgICB0aHJvdyBuZXcgY2hhaS5Bc3NlcnRpb25FcnJvcihtZXNzYWdlLCB7XG4gICAgICAgIGFjdHVhbDogYWN0dWFsXG4gICAgICAsIGV4cGVjdGVkOiBleHBlY3RlZFxuICAgICAgLCBvcGVyYXRvcjogb3BlcmF0b3JcbiAgICB9LCBjaGFpLmV4cGVjdC5mYWlsKTtcbiAgfTtcbn07XG4iLCIvKiFcbiAqIGNoYWlcbiAqIENvcHlyaWdodChjKSAyMDExLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjaGFpLCB1dGlsKSB7XG4gIHZhciBBc3NlcnRpb24gPSBjaGFpLkFzc2VydGlvbjtcblxuICBmdW5jdGlvbiBsb2FkU2hvdWxkICgpIHtcbiAgICAvLyBleHBsaWNpdGx5IGRlZmluZSB0aGlzIG1ldGhvZCBhcyBmdW5jdGlvbiBhcyB0byBoYXZlIGl0J3MgbmFtZSB0byBpbmNsdWRlIGFzIGBzc2ZpYFxuICAgIGZ1bmN0aW9uIHNob3VsZEdldHRlcigpIHtcbiAgICAgIGlmICh0aGlzIGluc3RhbmNlb2YgU3RyaW5nIHx8IHRoaXMgaW5zdGFuY2VvZiBOdW1iZXIgfHwgdGhpcyBpbnN0YW5jZW9mIEJvb2xlYW4gKSB7XG4gICAgICAgIHJldHVybiBuZXcgQXNzZXJ0aW9uKHRoaXMudmFsdWVPZigpLCBudWxsLCBzaG91bGRHZXR0ZXIpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG5ldyBBc3NlcnRpb24odGhpcywgbnVsbCwgc2hvdWxkR2V0dGVyKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gc2hvdWxkU2V0dGVyKHZhbHVlKSB7XG4gICAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2NoYWlqcy9jaGFpL2lzc3Vlcy84NjogdGhpcyBtYWtlc1xuICAgICAgLy8gYHdoYXRldmVyLnNob3VsZCA9IHNvbWVWYWx1ZWAgYWN0dWFsbHkgc2V0IGBzb21lVmFsdWVgLCB3aGljaCBpc1xuICAgICAgLy8gZXNwZWNpYWxseSB1c2VmdWwgZm9yIGBnbG9iYWwuc2hvdWxkID0gcmVxdWlyZSgnY2hhaScpLnNob3VsZCgpYC5cbiAgICAgIC8vXG4gICAgICAvLyBOb3RlIHRoYXQgd2UgaGF2ZSB0byB1c2UgW1tEZWZpbmVQcm9wZXJ0eV1dIGluc3RlYWQgb2YgW1tQdXRdXVxuICAgICAgLy8gc2luY2Ugb3RoZXJ3aXNlIHdlIHdvdWxkIHRyaWdnZXIgdGhpcyB2ZXJ5IHNldHRlciFcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLCAnc2hvdWxkJywge1xuICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgIGVudW1lcmFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgd3JpdGFibGU6IHRydWVcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBtb2RpZnkgT2JqZWN0LnByb3RvdHlwZSB0byBoYXZlIGBzaG91bGRgXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE9iamVjdC5wcm90b3R5cGUsICdzaG91bGQnLCB7XG4gICAgICBzZXQ6IHNob3VsZFNldHRlclxuICAgICAgLCBnZXQ6IHNob3VsZEdldHRlclxuICAgICAgLCBjb25maWd1cmFibGU6IHRydWVcbiAgICB9KTtcblxuICAgIHZhciBzaG91bGQgPSB7fTtcblxuICAgIC8qKlxuICAgICAqICMjIyAuZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBbbWVzc2FnZV0sIFtvcGVyYXRvcl0pXG4gICAgICpcbiAgICAgKiBUaHJvdyBhIGZhaWx1cmUuXG4gICAgICpcbiAgICAgKiBAbmFtZSBmYWlsXG4gICAgICogQHBhcmFtIHtNaXhlZH0gYWN0dWFsXG4gICAgICogQHBhcmFtIHtNaXhlZH0gZXhwZWN0ZWRcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gbWVzc2FnZVxuICAgICAqIEBwYXJhbSB7U3RyaW5nfSBvcGVyYXRvclxuICAgICAqIEBhcGkgcHVibGljXG4gICAgICovXG5cbiAgICBzaG91bGQuZmFpbCA9IGZ1bmN0aW9uIChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCBvcGVyYXRvcikge1xuICAgICAgbWVzc2FnZSA9IG1lc3NhZ2UgfHwgJ3Nob3VsZC5mYWlsKCknO1xuICAgICAgdGhyb3cgbmV3IGNoYWkuQXNzZXJ0aW9uRXJyb3IobWVzc2FnZSwge1xuICAgICAgICAgIGFjdHVhbDogYWN0dWFsXG4gICAgICAgICwgZXhwZWN0ZWQ6IGV4cGVjdGVkXG4gICAgICAgICwgb3BlcmF0b3I6IG9wZXJhdG9yXG4gICAgICB9LCBzaG91bGQuZmFpbCk7XG4gICAgfTtcblxuICAgIHNob3VsZC5lcXVhbCA9IGZ1bmN0aW9uICh2YWwxLCB2YWwyLCBtc2cpIHtcbiAgICAgIG5ldyBBc3NlcnRpb24odmFsMSwgbXNnKS50by5lcXVhbCh2YWwyKTtcbiAgICB9O1xuXG4gICAgc2hvdWxkLlRocm93ID0gZnVuY3Rpb24gKGZuLCBlcnJ0LCBlcnJzLCBtc2cpIHtcbiAgICAgIG5ldyBBc3NlcnRpb24oZm4sIG1zZykudG8uVGhyb3coZXJydCwgZXJycyk7XG4gICAgfTtcblxuICAgIHNob3VsZC5leGlzdCA9IGZ1bmN0aW9uICh2YWwsIG1zZykge1xuICAgICAgbmV3IEFzc2VydGlvbih2YWwsIG1zZykudG8uZXhpc3Q7XG4gICAgfVxuXG4gICAgLy8gbmVnYXRpb25cbiAgICBzaG91bGQubm90ID0ge31cblxuICAgIHNob3VsZC5ub3QuZXF1YWwgPSBmdW5jdGlvbiAodmFsMSwgdmFsMiwgbXNnKSB7XG4gICAgICBuZXcgQXNzZXJ0aW9uKHZhbDEsIG1zZykudG8ubm90LmVxdWFsKHZhbDIpO1xuICAgIH07XG5cbiAgICBzaG91bGQubm90LlRocm93ID0gZnVuY3Rpb24gKGZuLCBlcnJ0LCBlcnJzLCBtc2cpIHtcbiAgICAgIG5ldyBBc3NlcnRpb24oZm4sIG1zZykudG8ubm90LlRocm93KGVycnQsIGVycnMpO1xuICAgIH07XG5cbiAgICBzaG91bGQubm90LmV4aXN0ID0gZnVuY3Rpb24gKHZhbCwgbXNnKSB7XG4gICAgICBuZXcgQXNzZXJ0aW9uKHZhbCwgbXNnKS50by5ub3QuZXhpc3Q7XG4gICAgfVxuXG4gICAgc2hvdWxkWyd0aHJvdyddID0gc2hvdWxkWydUaHJvdyddO1xuICAgIHNob3VsZC5ub3RbJ3Rocm93J10gPSBzaG91bGQubm90WydUaHJvdyddO1xuXG4gICAgcmV0dXJuIHNob3VsZDtcbiAgfTtcblxuICBjaGFpLnNob3VsZCA9IGxvYWRTaG91bGQ7XG4gIGNoYWkuU2hvdWxkID0gbG9hZFNob3VsZDtcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBhZGRDaGFpbmluZ01ldGhvZCB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBNb2R1bGUgZGVwZW5kZW5jaWVzXG4gKi9cblxudmFyIHRyYW5zZmVyRmxhZ3MgPSByZXF1aXJlKCcuL3RyYW5zZmVyRmxhZ3MnKTtcbnZhciBmbGFnID0gcmVxdWlyZSgnLi9mbGFnJyk7XG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi4vY29uZmlnJyk7XG5cbi8qIVxuICogTW9kdWxlIHZhcmlhYmxlc1xuICovXG5cbi8vIENoZWNrIHdoZXRoZXIgYF9fcHJvdG9fX2AgaXMgc3VwcG9ydGVkXG52YXIgaGFzUHJvdG9TdXBwb3J0ID0gJ19fcHJvdG9fXycgaW4gT2JqZWN0O1xuXG4vLyBXaXRob3V0IGBfX3Byb3RvX19gIHN1cHBvcnQsIHRoaXMgbW9kdWxlIHdpbGwgbmVlZCB0byBhZGQgcHJvcGVydGllcyB0byBhIGZ1bmN0aW9uLlxuLy8gSG93ZXZlciwgc29tZSBGdW5jdGlvbi5wcm90b3R5cGUgbWV0aG9kcyBjYW5ub3QgYmUgb3ZlcndyaXR0ZW4sXG4vLyBhbmQgdGhlcmUgc2VlbXMgbm8gZWFzeSBjcm9zcy1wbGF0Zm9ybSB3YXkgdG8gZGV0ZWN0IHRoZW0gKEBzZWUgY2hhaWpzL2NoYWkvaXNzdWVzLzY5KS5cbnZhciBleGNsdWRlTmFtZXMgPSAvXig/Omxlbmd0aHxuYW1lfGFyZ3VtZW50c3xjYWxsZXIpJC87XG5cbi8vIENhY2hlIGBGdW5jdGlvbmAgcHJvcGVydGllc1xudmFyIGNhbGwgID0gRnVuY3Rpb24ucHJvdG90eXBlLmNhbGwsXG4gICAgYXBwbHkgPSBGdW5jdGlvbi5wcm90b3R5cGUuYXBwbHk7XG5cbi8qKlxuICogIyMjIGFkZENoYWluYWJsZU1ldGhvZCAoY3R4LCBuYW1lLCBtZXRob2QsIGNoYWluaW5nQmVoYXZpb3IpXG4gKlxuICogQWRkcyBhIG1ldGhvZCB0byBhbiBvYmplY3QsIHN1Y2ggdGhhdCB0aGUgbWV0aG9kIGNhbiBhbHNvIGJlIGNoYWluZWQuXG4gKlxuICogICAgIHV0aWxzLmFkZENoYWluYWJsZU1ldGhvZChjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUsICdmb28nLCBmdW5jdGlvbiAoc3RyKSB7XG4gKiAgICAgICB2YXIgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gKiAgICAgICBuZXcgY2hhaS5Bc3NlcnRpb24ob2JqKS50by5iZS5lcXVhbChzdHIpO1xuICogICAgIH0pO1xuICpcbiAqIENhbiBhbHNvIGJlIGFjY2Vzc2VkIGRpcmVjdGx5IGZyb20gYGNoYWkuQXNzZXJ0aW9uYC5cbiAqXG4gKiAgICAgY2hhaS5Bc3NlcnRpb24uYWRkQ2hhaW5hYmxlTWV0aG9kKCdmb28nLCBmbiwgY2hhaW5pbmdCZWhhdmlvcik7XG4gKlxuICogVGhlIHJlc3VsdCBjYW4gdGhlbiBiZSB1c2VkIGFzIGJvdGggYSBtZXRob2QgYXNzZXJ0aW9uLCBleGVjdXRpbmcgYm90aCBgbWV0aG9kYCBhbmRcbiAqIGBjaGFpbmluZ0JlaGF2aW9yYCwgb3IgYXMgYSBsYW5ndWFnZSBjaGFpbiwgd2hpY2ggb25seSBleGVjdXRlcyBgY2hhaW5pbmdCZWhhdmlvcmAuXG4gKlxuICogICAgIGV4cGVjdChmb29TdHIpLnRvLmJlLmZvbygnYmFyJyk7XG4gKiAgICAgZXhwZWN0KGZvb1N0cikudG8uYmUuZm9vLmVxdWFsKCdmb28nKTtcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY3R4IG9iamVjdCB0byB3aGljaCB0aGUgbWV0aG9kIGlzIGFkZGVkXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiBtZXRob2QgdG8gYWRkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBtZXRob2QgZnVuY3Rpb24gdG8gYmUgdXNlZCBmb3IgYG5hbWVgLCB3aGVuIGNhbGxlZFxuICogQHBhcmFtIHtGdW5jdGlvbn0gY2hhaW5pbmdCZWhhdmlvciBmdW5jdGlvbiB0byBiZSBjYWxsZWQgZXZlcnkgdGltZSB0aGUgcHJvcGVydHkgaXMgYWNjZXNzZWRcbiAqIEBuYW1lIGFkZENoYWluYWJsZU1ldGhvZFxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjdHgsIG5hbWUsIG1ldGhvZCwgY2hhaW5pbmdCZWhhdmlvcikge1xuICBpZiAodHlwZW9mIGNoYWluaW5nQmVoYXZpb3IgIT09ICdmdW5jdGlvbicpIHtcbiAgICBjaGFpbmluZ0JlaGF2aW9yID0gZnVuY3Rpb24gKCkgeyB9O1xuICB9XG5cbiAgdmFyIGNoYWluYWJsZUJlaGF2aW9yID0ge1xuICAgICAgbWV0aG9kOiBtZXRob2RcbiAgICAsIGNoYWluaW5nQmVoYXZpb3I6IGNoYWluaW5nQmVoYXZpb3JcbiAgfTtcblxuICAvLyBzYXZlIHRoZSBtZXRob2RzIHNvIHdlIGNhbiBvdmVyd3JpdGUgdGhlbSBsYXRlciwgaWYgd2UgbmVlZCB0by5cbiAgaWYgKCFjdHguX19tZXRob2RzKSB7XG4gICAgY3R4Ll9fbWV0aG9kcyA9IHt9O1xuICB9XG4gIGN0eC5fX21ldGhvZHNbbmFtZV0gPSBjaGFpbmFibGVCZWhhdmlvcjtcblxuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoY3R4LCBuYW1lLFxuICAgIHsgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNoYWluYWJsZUJlaGF2aW9yLmNoYWluaW5nQmVoYXZpb3IuY2FsbCh0aGlzKTtcblxuICAgICAgICB2YXIgYXNzZXJ0ID0gZnVuY3Rpb24gYXNzZXJ0KCkge1xuICAgICAgICAgIHZhciBvbGRfc3NmaSA9IGZsYWcodGhpcywgJ3NzZmknKTtcbiAgICAgICAgICBpZiAob2xkX3NzZmkgJiYgY29uZmlnLmluY2x1ZGVTdGFjayA9PT0gZmFsc2UpXG4gICAgICAgICAgICBmbGFnKHRoaXMsICdzc2ZpJywgYXNzZXJ0KTtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gY2hhaW5hYmxlQmVoYXZpb3IubWV0aG9kLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gdGhpcyA6IHJlc3VsdDtcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBVc2UgYF9fcHJvdG9fX2AgaWYgYXZhaWxhYmxlXG4gICAgICAgIGlmIChoYXNQcm90b1N1cHBvcnQpIHtcbiAgICAgICAgICAvLyBJbmhlcml0IGFsbCBwcm9wZXJ0aWVzIGZyb20gdGhlIG9iamVjdCBieSByZXBsYWNpbmcgdGhlIGBGdW5jdGlvbmAgcHJvdG90eXBlXG4gICAgICAgICAgdmFyIHByb3RvdHlwZSA9IGFzc2VydC5fX3Byb3RvX18gPSBPYmplY3QuY3JlYXRlKHRoaXMpO1xuICAgICAgICAgIC8vIFJlc3RvcmUgdGhlIGBjYWxsYCBhbmQgYGFwcGx5YCBtZXRob2RzIGZyb20gYEZ1bmN0aW9uYFxuICAgICAgICAgIHByb3RvdHlwZS5jYWxsID0gY2FsbDtcbiAgICAgICAgICBwcm90b3R5cGUuYXBwbHkgPSBhcHBseTtcbiAgICAgICAgfVxuICAgICAgICAvLyBPdGhlcndpc2UsIHJlZGVmaW5lIGFsbCBwcm9wZXJ0aWVzIChzbG93ISlcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdmFyIGFzc2VydGVyTmFtZXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhjdHgpO1xuICAgICAgICAgIGFzc2VydGVyTmFtZXMuZm9yRWFjaChmdW5jdGlvbiAoYXNzZXJ0ZXJOYW1lKSB7XG4gICAgICAgICAgICBpZiAoIWV4Y2x1ZGVOYW1lcy50ZXN0KGFzc2VydGVyTmFtZSkpIHtcbiAgICAgICAgICAgICAgdmFyIHBkID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcihjdHgsIGFzc2VydGVyTmFtZSk7XG4gICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShhc3NlcnQsIGFzc2VydGVyTmFtZSwgcGQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdHJhbnNmZXJGbGFncyh0aGlzLCBhc3NlcnQpO1xuICAgICAgICByZXR1cm4gYXNzZXJ0O1xuICAgICAgfVxuICAgICwgY29uZmlndXJhYmxlOiB0cnVlXG4gIH0pO1xufTtcbiIsIi8qIVxuICogQ2hhaSAtIGFkZE1ldGhvZCB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxudmFyIGNvbmZpZyA9IHJlcXVpcmUoJy4uL2NvbmZpZycpO1xuXG4vKipcbiAqICMjIyAuYWRkTWV0aG9kIChjdHgsIG5hbWUsIG1ldGhvZClcbiAqXG4gKiBBZGRzIGEgbWV0aG9kIHRvIHRoZSBwcm90b3R5cGUgb2YgYW4gb2JqZWN0LlxuICpcbiAqICAgICB1dGlscy5hZGRNZXRob2QoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCAnZm9vJywgZnVuY3Rpb24gKHN0cikge1xuICogICAgICAgdmFyIG9iaiA9IHV0aWxzLmZsYWcodGhpcywgJ29iamVjdCcpO1xuICogICAgICAgbmV3IGNoYWkuQXNzZXJ0aW9uKG9iaikudG8uYmUuZXF1YWwoc3RyKTtcbiAqICAgICB9KTtcbiAqXG4gKiBDYW4gYWxzbyBiZSBhY2Nlc3NlZCBkaXJlY3RseSBmcm9tIGBjaGFpLkFzc2VydGlvbmAuXG4gKlxuICogICAgIGNoYWkuQXNzZXJ0aW9uLmFkZE1ldGhvZCgnZm9vJywgZm4pO1xuICpcbiAqIFRoZW4gY2FuIGJlIHVzZWQgYXMgYW55IG90aGVyIGFzc2VydGlvbi5cbiAqXG4gKiAgICAgZXhwZWN0KGZvb1N0cikudG8uYmUuZm9vKCdiYXInKTtcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gY3R4IG9iamVjdCB0byB3aGljaCB0aGUgbWV0aG9kIGlzIGFkZGVkXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiBtZXRob2QgdG8gYWRkXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBtZXRob2QgZnVuY3Rpb24gdG8gYmUgdXNlZCBmb3IgbmFtZVxuICogQG5hbWUgYWRkTWV0aG9kXG4gKiBAYXBpIHB1YmxpY1xuICovXG52YXIgZmxhZyA9IHJlcXVpcmUoJy4vZmxhZycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjdHgsIG5hbWUsIG1ldGhvZCkge1xuICBjdHhbbmFtZV0gPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIG9sZF9zc2ZpID0gZmxhZyh0aGlzLCAnc3NmaScpO1xuICAgIGlmIChvbGRfc3NmaSAmJiBjb25maWcuaW5jbHVkZVN0YWNrID09PSBmYWxzZSlcbiAgICAgIGZsYWcodGhpcywgJ3NzZmknLCBjdHhbbmFtZV0pO1xuICAgIHZhciByZXN1bHQgPSBtZXRob2QuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICByZXR1cm4gcmVzdWx0ID09PSB1bmRlZmluZWQgPyB0aGlzIDogcmVzdWx0O1xuICB9O1xufTtcbiIsIi8qIVxuICogQ2hhaSAtIGFkZFByb3BlcnR5IHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKipcbiAqICMjIyBhZGRQcm9wZXJ0eSAoY3R4LCBuYW1lLCBnZXR0ZXIpXG4gKlxuICogQWRkcyBhIHByb3BlcnR5IHRvIHRoZSBwcm90b3R5cGUgb2YgYW4gb2JqZWN0LlxuICpcbiAqICAgICB1dGlscy5hZGRQcm9wZXJ0eShjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUsICdmb28nLCBmdW5jdGlvbiAoKSB7XG4gKiAgICAgICB2YXIgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gKiAgICAgICBuZXcgY2hhaS5Bc3NlcnRpb24ob2JqKS50by5iZS5pbnN0YW5jZW9mKEZvbyk7XG4gKiAgICAgfSk7XG4gKlxuICogQ2FuIGFsc28gYmUgYWNjZXNzZWQgZGlyZWN0bHkgZnJvbSBgY2hhaS5Bc3NlcnRpb25gLlxuICpcbiAqICAgICBjaGFpLkFzc2VydGlvbi5hZGRQcm9wZXJ0eSgnZm9vJywgZm4pO1xuICpcbiAqIFRoZW4gY2FuIGJlIHVzZWQgYXMgYW55IG90aGVyIGFzc2VydGlvbi5cbiAqXG4gKiAgICAgZXhwZWN0KG15Rm9vKS50by5iZS5mb287XG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGN0eCBvYmplY3QgdG8gd2hpY2ggdGhlIHByb3BlcnR5IGlzIGFkZGVkXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiBwcm9wZXJ0eSB0byBhZGRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGdldHRlciBmdW5jdGlvbiB0byBiZSB1c2VkIGZvciBuYW1lXG4gKiBAbmFtZSBhZGRQcm9wZXJ0eVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjdHgsIG5hbWUsIGdldHRlcikge1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoY3R4LCBuYW1lLFxuICAgIHsgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBnZXR0ZXIuY2FsbCh0aGlzKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gdGhpcyA6IHJlc3VsdDtcbiAgICAgIH1cbiAgICAsIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICB9KTtcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBmbGFnIHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKipcbiAqICMjIyBmbGFnKG9iamVjdCwga2V5LCBbdmFsdWVdKVxuICpcbiAqIEdldCBvciBzZXQgYSBmbGFnIHZhbHVlIG9uIGFuIG9iamVjdC4gSWYgYVxuICogdmFsdWUgaXMgcHJvdmlkZWQgaXQgd2lsbCBiZSBzZXQsIGVsc2UgaXQgd2lsbFxuICogcmV0dXJuIHRoZSBjdXJyZW50bHkgc2V0IHZhbHVlIG9yIGB1bmRlZmluZWRgIGlmXG4gKiB0aGUgdmFsdWUgaXMgbm90IHNldC5cbiAqXG4gKiAgICAgdXRpbHMuZmxhZyh0aGlzLCAnZm9vJywgJ2JhcicpOyAvLyBzZXR0ZXJcbiAqICAgICB1dGlscy5mbGFnKHRoaXMsICdmb28nKTsgLy8gZ2V0dGVyLCByZXR1cm5zIGBiYXJgXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBjb25zdHJ1Y3RlZCBBc3NlcnRpb25cbiAqIEBwYXJhbSB7U3RyaW5nfSBrZXlcbiAqIEBwYXJhbSB7TWl4ZWR9IHZhbHVlIChvcHRpb25hbClcbiAqIEBuYW1lIGZsYWdcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKG9iaiwga2V5LCB2YWx1ZSkge1xuICB2YXIgZmxhZ3MgPSBvYmouX19mbGFncyB8fCAob2JqLl9fZmxhZ3MgPSBPYmplY3QuY3JlYXRlKG51bGwpKTtcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDMpIHtcbiAgICBmbGFnc1trZXldID0gdmFsdWU7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGZsYWdzW2tleV07XG4gIH1cbn07XG4iLCIvKiFcbiAqIENoYWkgLSBnZXRBY3R1YWwgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyBnZXRBY3R1YWwob2JqZWN0LCBbYWN0dWFsXSlcbiAqXG4gKiBSZXR1cm5zIHRoZSBgYWN0dWFsYCB2YWx1ZSBmb3IgYW4gQXNzZXJ0aW9uXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCAoY29uc3RydWN0ZWQgQXNzZXJ0aW9uKVxuICogQHBhcmFtIHtBcmd1bWVudHN9IGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZS5hc3NlcnQgYXJndW1lbnRzXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqLCBhcmdzKSB7XG4gIHJldHVybiBhcmdzLmxlbmd0aCA+IDQgPyBhcmdzWzRdIDogb2JqLl9vYmo7XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gZ2V0RW51bWVyYWJsZVByb3BlcnRpZXMgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIC5nZXRFbnVtZXJhYmxlUHJvcGVydGllcyhvYmplY3QpXG4gKlxuICogVGhpcyBhbGxvd3MgdGhlIHJldHJpZXZhbCBvZiBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIG9mIGFuIG9iamVjdCxcbiAqIGluaGVyaXRlZCBvciBub3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICogQHJldHVybnMge0FycmF5fVxuICogQG5hbWUgZ2V0RW51bWVyYWJsZVByb3BlcnRpZXNcbiAqIEBhcGkgcHVibGljXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBnZXRFbnVtZXJhYmxlUHJvcGVydGllcyhvYmplY3QpIHtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuICBmb3IgKHZhciBuYW1lIGluIG9iamVjdCkge1xuICAgIHJlc3VsdC5wdXNoKG5hbWUpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gbWVzc2FnZSBjb21wb3NpdGlvbiB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBNb2R1bGUgZGVwZW5kYW5jaWVzXG4gKi9cblxudmFyIGZsYWcgPSByZXF1aXJlKCcuL2ZsYWcnKVxuICAsIGdldEFjdHVhbCA9IHJlcXVpcmUoJy4vZ2V0QWN0dWFsJylcbiAgLCBpbnNwZWN0ID0gcmVxdWlyZSgnLi9pbnNwZWN0JylcbiAgLCBvYmpEaXNwbGF5ID0gcmVxdWlyZSgnLi9vYmpEaXNwbGF5Jyk7XG5cbi8qKlxuICogIyMjIC5nZXRNZXNzYWdlKG9iamVjdCwgbWVzc2FnZSwgbmVnYXRlTWVzc2FnZSlcbiAqXG4gKiBDb25zdHJ1Y3QgdGhlIGVycm9yIG1lc3NhZ2UgYmFzZWQgb24gZmxhZ3NcbiAqIGFuZCB0ZW1wbGF0ZSB0YWdzLiBUZW1wbGF0ZSB0YWdzIHdpbGwgcmV0dXJuXG4gKiBhIHN0cmluZ2lmaWVkIGluc3BlY3Rpb24gb2YgdGhlIG9iamVjdCByZWZlcmVuY2VkLlxuICpcbiAqIE1lc3NhZ2UgdGVtcGxhdGUgdGFnczpcbiAqIC0gYCN7dGhpc31gIGN1cnJlbnQgYXNzZXJ0ZWQgb2JqZWN0XG4gKiAtIGAje2FjdH1gIGFjdHVhbCB2YWx1ZVxuICogLSBgI3tleHB9YCBleHBlY3RlZCB2YWx1ZVxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgKGNvbnN0cnVjdGVkIEFzc2VydGlvbilcbiAqIEBwYXJhbSB7QXJndW1lbnRzfSBjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUuYXNzZXJ0IGFyZ3VtZW50c1xuICogQG5hbWUgZ2V0TWVzc2FnZVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmosIGFyZ3MpIHtcbiAgdmFyIG5lZ2F0ZSA9IGZsYWcob2JqLCAnbmVnYXRlJylcbiAgICAsIHZhbCA9IGZsYWcob2JqLCAnb2JqZWN0JylcbiAgICAsIGV4cGVjdGVkID0gYXJnc1szXVxuICAgICwgYWN0dWFsID0gZ2V0QWN0dWFsKG9iaiwgYXJncylcbiAgICAsIG1zZyA9IG5lZ2F0ZSA/IGFyZ3NbMl0gOiBhcmdzWzFdXG4gICAgLCBmbGFnTXNnID0gZmxhZyhvYmosICdtZXNzYWdlJyk7XG5cbiAgaWYodHlwZW9mIG1zZyA9PT0gXCJmdW5jdGlvblwiKSBtc2cgPSBtc2coKTtcbiAgbXNnID0gbXNnIHx8ICcnO1xuICBtc2cgPSBtc2dcbiAgICAucmVwbGFjZSgvI3t0aGlzfS9nLCBvYmpEaXNwbGF5KHZhbCkpXG4gICAgLnJlcGxhY2UoLyN7YWN0fS9nLCBvYmpEaXNwbGF5KGFjdHVhbCkpXG4gICAgLnJlcGxhY2UoLyN7ZXhwfS9nLCBvYmpEaXNwbGF5KGV4cGVjdGVkKSk7XG5cbiAgcmV0dXJuIGZsYWdNc2cgPyBmbGFnTXNnICsgJzogJyArIG1zZyA6IG1zZztcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBnZXROYW1lIHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKipcbiAqICMgZ2V0TmFtZShmdW5jKVxuICpcbiAqIEdldHMgdGhlIG5hbWUgb2YgYSBmdW5jdGlvbiwgaW4gYSBjcm9zcy1icm93c2VyIHdheS5cbiAqXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBhIGZ1bmN0aW9uICh1c3VhbGx5IGEgY29uc3RydWN0b3IpXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZnVuYykge1xuICBpZiAoZnVuYy5uYW1lKSByZXR1cm4gZnVuYy5uYW1lO1xuXG4gIHZhciBtYXRjaCA9IC9eXFxzP2Z1bmN0aW9uIChbXihdKilcXCgvLmV4ZWMoZnVuYyk7XG4gIHJldHVybiBtYXRjaCAmJiBtYXRjaFsxXSA/IG1hdGNoWzFdIDogXCJcIjtcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBnZXRQYXRoSW5mbyB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxudmFyIGhhc1Byb3BlcnR5ID0gcmVxdWlyZSgnLi9oYXNQcm9wZXJ0eScpO1xuXG4vKipcbiAqICMjIyAuZ2V0UGF0aEluZm8ocGF0aCwgb2JqZWN0KVxuICpcbiAqIFRoaXMgYWxsb3dzIHRoZSByZXRyaWV2YWwgb2YgcHJvcGVydHkgaW5mbyBpbiBhblxuICogb2JqZWN0IGdpdmVuIGEgc3RyaW5nIHBhdGguXG4gKlxuICogVGhlIHBhdGggaW5mbyBjb25zaXN0cyBvZiBhbiBvYmplY3Qgd2l0aCB0aGVcbiAqIGZvbGxvd2luZyBwcm9wZXJ0aWVzOlxuICpcbiAqICogcGFyZW50IC0gVGhlIHBhcmVudCBvYmplY3Qgb2YgdGhlIHByb3BlcnR5IHJlZmVyZW5jZWQgYnkgYHBhdGhgXG4gKiAqIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZmluYWwgcHJvcGVydHksIGEgbnVtYmVyIGlmIGl0IHdhcyBhbiBhcnJheSBpbmRleGVyXG4gKiAqIHZhbHVlIC0gVGhlIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSwgaWYgaXQgZXhpc3RzLCBvdGhlcndpc2UgYHVuZGVmaW5lZGBcbiAqICogZXhpc3RzIC0gV2hldGhlciB0aGUgcHJvcGVydHkgZXhpc3RzIG9yIG5vdFxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYXRoXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0XG4gKiBAcmV0dXJucyB7T2JqZWN0fSBpbmZvXG4gKiBAbmFtZSBnZXRQYXRoSW5mb1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGdldFBhdGhJbmZvKHBhdGgsIG9iaikge1xuICB2YXIgcGFyc2VkID0gcGFyc2VQYXRoKHBhdGgpLFxuICAgICAgbGFzdCA9IHBhcnNlZFtwYXJzZWQubGVuZ3RoIC0gMV07XG5cbiAgdmFyIGluZm8gPSB7XG4gICAgcGFyZW50OiBwYXJzZWQubGVuZ3RoID4gMSA/IF9nZXRQYXRoVmFsdWUocGFyc2VkLCBvYmosIHBhcnNlZC5sZW5ndGggLSAxKSA6IG9iaixcbiAgICBuYW1lOiBsYXN0LnAgfHwgbGFzdC5pLFxuICAgIHZhbHVlOiBfZ2V0UGF0aFZhbHVlKHBhcnNlZCwgb2JqKSxcbiAgfTtcbiAgaW5mby5leGlzdHMgPSBoYXNQcm9wZXJ0eShpbmZvLm5hbWUsIGluZm8ucGFyZW50KTtcblxuICByZXR1cm4gaW5mbztcbn07XG5cblxuLyohXG4gKiAjIyBwYXJzZVBhdGgocGF0aClcbiAqXG4gKiBIZWxwZXIgZnVuY3Rpb24gdXNlZCB0byBwYXJzZSBzdHJpbmcgb2JqZWN0XG4gKiBwYXRocy4gVXNlIGluIGNvbmp1bmN0aW9uIHdpdGggYF9nZXRQYXRoVmFsdWVgLlxuICpcbiAqICAgICAgdmFyIHBhcnNlZCA9IHBhcnNlUGF0aCgnbXlvYmplY3QucHJvcGVydHkuc3VicHJvcCcpO1xuICpcbiAqICMjIyBQYXRoczpcbiAqXG4gKiAqIENhbiBiZSBhcyBuZWFyIGluZmluaXRlbHkgZGVlcCBhbmQgbmVzdGVkXG4gKiAqIEFycmF5cyBhcmUgYWxzbyB2YWxpZCB1c2luZyB0aGUgZm9ybWFsIGBteW9iamVjdC5kb2N1bWVudFszXS5wcm9wZXJ0eWAuXG4gKiAqIExpdGVyYWwgZG90cyBhbmQgYnJhY2tldHMgKG5vdCBkZWxpbWl0ZXIpIG11c3QgYmUgYmFja3NsYXNoLWVzY2FwZWQuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHBhdGhcbiAqIEByZXR1cm5zIHtPYmplY3R9IHBhcnNlZFxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gcGFyc2VQYXRoIChwYXRoKSB7XG4gIHZhciBzdHIgPSBwYXRoLnJlcGxhY2UoLyhbXlxcXFxdKVxcWy9nLCAnJDEuWycpXG4gICAgLCBwYXJ0cyA9IHN0ci5tYXRjaCgvKFxcXFxcXC58W14uXSs/KSsvZyk7XG4gIHJldHVybiBwYXJ0cy5tYXAoZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgdmFyIHJlID0gL15cXFsoXFxkKylcXF0kL1xuICAgICAgLCBtQXJyID0gcmUuZXhlYyh2YWx1ZSk7XG4gICAgaWYgKG1BcnIpIHJldHVybiB7IGk6IHBhcnNlRmxvYXQobUFyclsxXSkgfTtcbiAgICBlbHNlIHJldHVybiB7IHA6IHZhbHVlLnJlcGxhY2UoL1xcXFwoWy5cXFtcXF1dKS9nLCAnJDEnKSB9O1xuICB9KTtcbn1cblxuXG4vKiFcbiAqICMjIF9nZXRQYXRoVmFsdWUocGFyc2VkLCBvYmopXG4gKlxuICogSGVscGVyIGNvbXBhbmlvbiBmdW5jdGlvbiBmb3IgYC5wYXJzZVBhdGhgIHRoYXQgcmV0dXJuc1xuICogdGhlIHZhbHVlIGxvY2F0ZWQgYXQgdGhlIHBhcnNlZCBhZGRyZXNzLlxuICpcbiAqICAgICAgdmFyIHZhbHVlID0gZ2V0UGF0aFZhbHVlKHBhcnNlZCwgb2JqKTtcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gcGFyc2VkIGRlZmluaXRpb24gZnJvbSBgcGFyc2VQYXRoYC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgdG8gc2VhcmNoIGFnYWluc3RcbiAqIEBwYXJhbSB7TnVtYmVyfSBvYmplY3QgdG8gc2VhcmNoIGFnYWluc3RcbiAqIEByZXR1cm5zIHtPYmplY3R8VW5kZWZpbmVkfSB2YWx1ZVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gX2dldFBhdGhWYWx1ZSAocGFyc2VkLCBvYmosIGluZGV4KSB7XG4gIHZhciB0bXAgPSBvYmpcbiAgICAsIHJlcztcblxuICBpbmRleCA9IChpbmRleCA9PT0gdW5kZWZpbmVkID8gcGFyc2VkLmxlbmd0aCA6IGluZGV4KTtcblxuICBmb3IgKHZhciBpID0gMCwgbCA9IGluZGV4OyBpIDwgbDsgaSsrKSB7XG4gICAgdmFyIHBhcnQgPSBwYXJzZWRbaV07XG4gICAgaWYgKHRtcCkge1xuICAgICAgaWYgKCd1bmRlZmluZWQnICE9PSB0eXBlb2YgcGFydC5wKVxuICAgICAgICB0bXAgPSB0bXBbcGFydC5wXTtcbiAgICAgIGVsc2UgaWYgKCd1bmRlZmluZWQnICE9PSB0eXBlb2YgcGFydC5pKVxuICAgICAgICB0bXAgPSB0bXBbcGFydC5pXTtcbiAgICAgIGlmIChpID09IChsIC0gMSkpIHJlcyA9IHRtcDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzO1xufVxuIiwiLyohXG4gKiBDaGFpIC0gZ2V0UGF0aFZhbHVlIHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBAc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9sb2dpY2FscGFyYWRveC9maWx0clxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxudmFyIGdldFBhdGhJbmZvID0gcmVxdWlyZSgnLi9nZXRQYXRoSW5mbycpO1xuXG4vKipcbiAqICMjIyAuZ2V0UGF0aFZhbHVlKHBhdGgsIG9iamVjdClcbiAqXG4gKiBUaGlzIGFsbG93cyB0aGUgcmV0cmlldmFsIG9mIHZhbHVlcyBpbiBhblxuICogb2JqZWN0IGdpdmVuIGEgc3RyaW5nIHBhdGguXG4gKlxuICogICAgIHZhciBvYmogPSB7XG4gKiAgICAgICAgIHByb3AxOiB7XG4gKiAgICAgICAgICAgICBhcnI6IFsnYScsICdiJywgJ2MnXVxuICogICAgICAgICAgICwgc3RyOiAnSGVsbG8nXG4gKiAgICAgICAgIH1cbiAqICAgICAgICwgcHJvcDI6IHtcbiAqICAgICAgICAgICAgIGFycjogWyB7IG5lc3RlZDogJ1VuaXZlcnNlJyB9IF1cbiAqICAgICAgICAgICAsIHN0cjogJ0hlbGxvIGFnYWluISdcbiAqICAgICAgICAgfVxuICogICAgIH1cbiAqXG4gKiBUaGUgZm9sbG93aW5nIHdvdWxkIGJlIHRoZSByZXN1bHRzLlxuICpcbiAqICAgICBnZXRQYXRoVmFsdWUoJ3Byb3AxLnN0cicsIG9iaik7IC8vIEhlbGxvXG4gKiAgICAgZ2V0UGF0aFZhbHVlKCdwcm9wMS5hdHRbMl0nLCBvYmopOyAvLyBiXG4gKiAgICAgZ2V0UGF0aFZhbHVlKCdwcm9wMi5hcnJbMF0ubmVzdGVkJywgb2JqKTsgLy8gVW5pdmVyc2VcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gcGF0aFxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICogQHJldHVybnMge09iamVjdH0gdmFsdWUgb3IgYHVuZGVmaW5lZGBcbiAqIEBuYW1lIGdldFBhdGhWYWx1ZVxuICogQGFwaSBwdWJsaWNcbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihwYXRoLCBvYmopIHtcbiAgdmFyIGluZm8gPSBnZXRQYXRoSW5mbyhwYXRoLCBvYmopO1xuICByZXR1cm4gaW5mby52YWx1ZTtcbn07IFxuIiwiLyohXG4gKiBDaGFpIC0gZ2V0UHJvcGVydGllcyB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyoqXG4gKiAjIyMgLmdldFByb3BlcnRpZXMob2JqZWN0KVxuICpcbiAqIFRoaXMgYWxsb3dzIHRoZSByZXRyaWV2YWwgb2YgcHJvcGVydHkgbmFtZXMgb2YgYW4gb2JqZWN0LCBlbnVtZXJhYmxlIG9yIG5vdCxcbiAqIGluaGVyaXRlZCBvciBub3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdFxuICogQHJldHVybnMge0FycmF5fVxuICogQG5hbWUgZ2V0UHJvcGVydGllc1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGdldFByb3BlcnRpZXMob2JqZWN0KSB7XG4gIHZhciByZXN1bHQgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhzdWJqZWN0KTtcblxuICBmdW5jdGlvbiBhZGRQcm9wZXJ0eShwcm9wZXJ0eSkge1xuICAgIGlmIChyZXN1bHQuaW5kZXhPZihwcm9wZXJ0eSkgPT09IC0xKSB7XG4gICAgICByZXN1bHQucHVzaChwcm9wZXJ0eSk7XG4gICAgfVxuICB9XG5cbiAgdmFyIHByb3RvID0gT2JqZWN0LmdldFByb3RvdHlwZU9mKHN1YmplY3QpO1xuICB3aGlsZSAocHJvdG8gIT09IG51bGwpIHtcbiAgICBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyhwcm90bykuZm9yRWFjaChhZGRQcm9wZXJ0eSk7XG4gICAgcHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YocHJvdG8pO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBoYXNQcm9wZXJ0eSB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxudmFyIHR5cGUgPSByZXF1aXJlKCcuL3R5cGUnKTtcblxuLyoqXG4gKiAjIyMgLmhhc1Byb3BlcnR5KG9iamVjdCwgbmFtZSlcbiAqXG4gKiBUaGlzIGFsbG93cyBjaGVja2luZyB3aGV0aGVyIGFuIG9iamVjdCBoYXNcbiAqIG5hbWVkIHByb3BlcnR5IG9yIG51bWVyaWMgYXJyYXkgaW5kZXguXG4gKlxuICogQmFzaWNhbGx5IGRvZXMgdGhlIHNhbWUgdGhpbmcgYXMgdGhlIGBpbmBcbiAqIG9wZXJhdG9yIGJ1dCB3b3JrcyBwcm9wZXJseSB3aXRoIG5hdGl2ZXNcbiAqIGFuZCBudWxsL3VuZGVmaW5lZCB2YWx1ZXMuXG4gKlxuICogICAgIHZhciBvYmogPSB7XG4gKiAgICAgICAgIGFycjogWydhJywgJ2InLCAnYyddXG4gKiAgICAgICAsIHN0cjogJ0hlbGxvJ1xuICogICAgIH1cbiAqXG4gKiBUaGUgZm9sbG93aW5nIHdvdWxkIGJlIHRoZSByZXN1bHRzLlxuICpcbiAqICAgICBoYXNQcm9wZXJ0eSgnc3RyJywgb2JqKTsgIC8vIHRydWVcbiAqICAgICBoYXNQcm9wZXJ0eSgnY29uc3RydWN0b3InLCBvYmopOyAgLy8gdHJ1ZVxuICogICAgIGhhc1Byb3BlcnR5KCdiYXInLCBvYmopOyAgLy8gZmFsc2VcbiAqICAgICBcbiAqICAgICBoYXNQcm9wZXJ0eSgnbGVuZ3RoJywgb2JqLnN0cik7IC8vIHRydWVcbiAqICAgICBoYXNQcm9wZXJ0eSgxLCBvYmouc3RyKTsgIC8vIHRydWVcbiAqICAgICBoYXNQcm9wZXJ0eSg1LCBvYmouc3RyKTsgIC8vIGZhbHNlXG4gKlxuICogICAgIGhhc1Byb3BlcnR5KCdsZW5ndGgnLCBvYmouYXJyKTsgIC8vIHRydWVcbiAqICAgICBoYXNQcm9wZXJ0eSgyLCBvYmouYXJyKTsgIC8vIHRydWVcbiAqICAgICBoYXNQcm9wZXJ0eSgzLCBvYmouYXJyKTsgIC8vIGZhbHNlXG4gKlxuICogQHBhcmFtIHtPYmp1ZWN0fSBvYmplY3RcbiAqIEBwYXJhbSB7U3RyaW5nfE51bWJlcn0gbmFtZVxuICogQHJldHVybnMge0Jvb2xlYW59IHdoZXRoZXIgaXQgZXhpc3RzXG4gKiBAbmFtZSBnZXRQYXRoSW5mb1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG52YXIgbGl0ZXJhbHMgPSB7XG4gICAgJ251bWJlcic6IE51bWJlclxuICAsICdzdHJpbmcnOiBTdHJpbmdcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaGFzUHJvcGVydHkobmFtZSwgb2JqKSB7XG4gIHZhciBvdCA9IHR5cGUob2JqKTtcblxuICAvLyBCYWQgT2JqZWN0LCBvYnZpb3VzbHkgbm8gcHJvcHMgYXQgYWxsXG4gIGlmKG90ID09PSAnbnVsbCcgfHwgb3QgPT09ICd1bmRlZmluZWQnKVxuICAgIHJldHVybiBmYWxzZTtcblxuICAvLyBUaGUgYGluYCBvcGVyYXRvciBkb2VzIG5vdCB3b3JrIHdpdGggY2VydGFpbiBsaXRlcmFsc1xuICAvLyBib3ggdGhlc2UgYmVmb3JlIHRoZSBjaGVja1xuICBpZihsaXRlcmFsc1tvdF0gJiYgdHlwZW9mIG9iaiAhPT0gJ29iamVjdCcpXG4gICAgb2JqID0gbmV3IGxpdGVyYWxzW290XShvYmopO1xuXG4gIHJldHVybiBuYW1lIGluIG9iajtcbn07XG4iLCIvKiFcbiAqIGNoYWlcbiAqIENvcHlyaWdodChjKSAyMDExIEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBNYWluIGV4cG9ydHNcbiAqL1xuXG52YXIgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbi8qIVxuICogdGVzdCB1dGlsaXR5XG4gKi9cblxuZXhwb3J0cy50ZXN0ID0gcmVxdWlyZSgnLi90ZXN0Jyk7XG5cbi8qIVxuICogdHlwZSB1dGlsaXR5XG4gKi9cblxuZXhwb3J0cy50eXBlID0gcmVxdWlyZSgnLi90eXBlJyk7XG5cbi8qIVxuICogbWVzc2FnZSB1dGlsaXR5XG4gKi9cblxuZXhwb3J0cy5nZXRNZXNzYWdlID0gcmVxdWlyZSgnLi9nZXRNZXNzYWdlJyk7XG5cbi8qIVxuICogYWN0dWFsIHV0aWxpdHlcbiAqL1xuXG5leHBvcnRzLmdldEFjdHVhbCA9IHJlcXVpcmUoJy4vZ2V0QWN0dWFsJyk7XG5cbi8qIVxuICogSW5zcGVjdCB1dGlsXG4gKi9cblxuZXhwb3J0cy5pbnNwZWN0ID0gcmVxdWlyZSgnLi9pbnNwZWN0Jyk7XG5cbi8qIVxuICogT2JqZWN0IERpc3BsYXkgdXRpbFxuICovXG5cbmV4cG9ydHMub2JqRGlzcGxheSA9IHJlcXVpcmUoJy4vb2JqRGlzcGxheScpO1xuXG4vKiFcbiAqIEZsYWcgdXRpbGl0eVxuICovXG5cbmV4cG9ydHMuZmxhZyA9IHJlcXVpcmUoJy4vZmxhZycpO1xuXG4vKiFcbiAqIEZsYWcgdHJhbnNmZXJyaW5nIHV0aWxpdHlcbiAqL1xuXG5leHBvcnRzLnRyYW5zZmVyRmxhZ3MgPSByZXF1aXJlKCcuL3RyYW5zZmVyRmxhZ3MnKTtcblxuLyohXG4gKiBEZWVwIGVxdWFsIHV0aWxpdHlcbiAqL1xuXG5leHBvcnRzLmVxbCA9IHJlcXVpcmUoJ2RlZXAtZXFsJyk7XG5cbi8qIVxuICogRGVlcCBwYXRoIHZhbHVlXG4gKi9cblxuZXhwb3J0cy5nZXRQYXRoVmFsdWUgPSByZXF1aXJlKCcuL2dldFBhdGhWYWx1ZScpO1xuXG4vKiFcbiAqIERlZXAgcGF0aCBpbmZvXG4gKi9cblxuZXhwb3J0cy5nZXRQYXRoSW5mbyA9IHJlcXVpcmUoJy4vZ2V0UGF0aEluZm8nKTtcblxuLyohXG4gKiBDaGVjayBpZiBhIHByb3BlcnR5IGV4aXN0c1xuICovXG5cbmV4cG9ydHMuaGFzUHJvcGVydHkgPSByZXF1aXJlKCcuL2hhc1Byb3BlcnR5Jyk7XG5cbi8qIVxuICogRnVuY3Rpb24gbmFtZVxuICovXG5cbmV4cG9ydHMuZ2V0TmFtZSA9IHJlcXVpcmUoJy4vZ2V0TmFtZScpO1xuXG4vKiFcbiAqIGFkZCBQcm9wZXJ0eVxuICovXG5cbmV4cG9ydHMuYWRkUHJvcGVydHkgPSByZXF1aXJlKCcuL2FkZFByb3BlcnR5Jyk7XG5cbi8qIVxuICogYWRkIE1ldGhvZFxuICovXG5cbmV4cG9ydHMuYWRkTWV0aG9kID0gcmVxdWlyZSgnLi9hZGRNZXRob2QnKTtcblxuLyohXG4gKiBvdmVyd3JpdGUgUHJvcGVydHlcbiAqL1xuXG5leHBvcnRzLm92ZXJ3cml0ZVByb3BlcnR5ID0gcmVxdWlyZSgnLi9vdmVyd3JpdGVQcm9wZXJ0eScpO1xuXG4vKiFcbiAqIG92ZXJ3cml0ZSBNZXRob2RcbiAqL1xuXG5leHBvcnRzLm92ZXJ3cml0ZU1ldGhvZCA9IHJlcXVpcmUoJy4vb3ZlcndyaXRlTWV0aG9kJyk7XG5cbi8qIVxuICogQWRkIGEgY2hhaW5hYmxlIG1ldGhvZFxuICovXG5cbmV4cG9ydHMuYWRkQ2hhaW5hYmxlTWV0aG9kID0gcmVxdWlyZSgnLi9hZGRDaGFpbmFibGVNZXRob2QnKTtcblxuLyohXG4gKiBPdmVyd3JpdGUgY2hhaW5hYmxlIG1ldGhvZFxuICovXG5cbmV4cG9ydHMub3ZlcndyaXRlQ2hhaW5hYmxlTWV0aG9kID0gcmVxdWlyZSgnLi9vdmVyd3JpdGVDaGFpbmFibGVNZXRob2QnKTtcblxuIiwiLy8gVGhpcyBpcyAoYWxtb3N0KSBkaXJlY3RseSBmcm9tIE5vZGUuanMgdXRpbHNcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qb3llbnQvbm9kZS9ibG9iL2Y4YzMzNWQwY2FmNDdmMTZkMzE0MTNmODlhYTI4ZWRhMzg3OGUzYWEvbGliL3V0aWwuanNcblxudmFyIGdldE5hbWUgPSByZXF1aXJlKCcuL2dldE5hbWUnKTtcbnZhciBnZXRQcm9wZXJ0aWVzID0gcmVxdWlyZSgnLi9nZXRQcm9wZXJ0aWVzJyk7XG52YXIgZ2V0RW51bWVyYWJsZVByb3BlcnRpZXMgPSByZXF1aXJlKCcuL2dldEVudW1lcmFibGVQcm9wZXJ0aWVzJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gaW5zcGVjdDtcblxuLyoqXG4gKiBFY2hvcyB0aGUgdmFsdWUgb2YgYSB2YWx1ZS4gVHJ5cyB0byBwcmludCB0aGUgdmFsdWUgb3V0XG4gKiBpbiB0aGUgYmVzdCB3YXkgcG9zc2libGUgZ2l2ZW4gdGhlIGRpZmZlcmVudCB0eXBlcy5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqIFRoZSBvYmplY3QgdG8gcHJpbnQgb3V0LlxuICogQHBhcmFtIHtCb29sZWFufSBzaG93SGlkZGVuIEZsYWcgdGhhdCBzaG93cyBoaWRkZW4gKG5vdCBlbnVtZXJhYmxlKVxuICogICAgcHJvcGVydGllcyBvZiBvYmplY3RzLlxuICogQHBhcmFtIHtOdW1iZXJ9IGRlcHRoIERlcHRoIGluIHdoaWNoIHRvIGRlc2NlbmQgaW4gb2JqZWN0LiBEZWZhdWx0IGlzIDIuXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGNvbG9ycyBGbGFnIHRvIHR1cm4gb24gQU5TSSBlc2NhcGUgY29kZXMgdG8gY29sb3IgdGhlXG4gKiAgICBvdXRwdXQuIERlZmF1bHQgaXMgZmFsc2UgKG5vIGNvbG9yaW5nKS5cbiAqL1xuZnVuY3Rpb24gaW5zcGVjdChvYmosIHNob3dIaWRkZW4sIGRlcHRoLCBjb2xvcnMpIHtcbiAgdmFyIGN0eCA9IHtcbiAgICBzaG93SGlkZGVuOiBzaG93SGlkZGVuLFxuICAgIHNlZW46IFtdLFxuICAgIHN0eWxpemU6IGZ1bmN0aW9uIChzdHIpIHsgcmV0dXJuIHN0cjsgfVxuICB9O1xuICByZXR1cm4gZm9ybWF0VmFsdWUoY3R4LCBvYmosICh0eXBlb2YgZGVwdGggPT09ICd1bmRlZmluZWQnID8gMiA6IGRlcHRoKSk7XG59XG5cbi8vIFJldHVybnMgdHJ1ZSBpZiBvYmplY3QgaXMgYSBET00gZWxlbWVudC5cbnZhciBpc0RPTUVsZW1lbnQgPSBmdW5jdGlvbiAob2JqZWN0KSB7XG4gIGlmICh0eXBlb2YgSFRNTEVsZW1lbnQgPT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIG9iamVjdCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50O1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBvYmplY3QgJiZcbiAgICAgIHR5cGVvZiBvYmplY3QgPT09ICdvYmplY3QnICYmXG4gICAgICBvYmplY3Qubm9kZVR5cGUgPT09IDEgJiZcbiAgICAgIHR5cGVvZiBvYmplY3Qubm9kZU5hbWUgPT09ICdzdHJpbmcnO1xuICB9XG59O1xuXG5mdW5jdGlvbiBmb3JtYXRWYWx1ZShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMpIHtcbiAgLy8gUHJvdmlkZSBhIGhvb2sgZm9yIHVzZXItc3BlY2lmaWVkIGluc3BlY3QgZnVuY3Rpb25zLlxuICAvLyBDaGVjayB0aGF0IHZhbHVlIGlzIGFuIG9iamVjdCB3aXRoIGFuIGluc3BlY3QgZnVuY3Rpb24gb24gaXRcbiAgaWYgKHZhbHVlICYmIHR5cGVvZiB2YWx1ZS5pbnNwZWN0ID09PSAnZnVuY3Rpb24nICYmXG4gICAgICAvLyBGaWx0ZXIgb3V0IHRoZSB1dGlsIG1vZHVsZSwgaXQncyBpbnNwZWN0IGZ1bmN0aW9uIGlzIHNwZWNpYWxcbiAgICAgIHZhbHVlLmluc3BlY3QgIT09IGV4cG9ydHMuaW5zcGVjdCAmJlxuICAgICAgLy8gQWxzbyBmaWx0ZXIgb3V0IGFueSBwcm90b3R5cGUgb2JqZWN0cyB1c2luZyB0aGUgY2lyY3VsYXIgY2hlY2suXG4gICAgICAhKHZhbHVlLmNvbnN0cnVjdG9yICYmIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZSA9PT0gdmFsdWUpKSB7XG4gICAgdmFyIHJldCA9IHZhbHVlLmluc3BlY3QocmVjdXJzZVRpbWVzKTtcbiAgICBpZiAodHlwZW9mIHJldCAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHJldCA9IGZvcm1hdFZhbHVlKGN0eCwgcmV0LCByZWN1cnNlVGltZXMpO1xuICAgIH1cbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgLy8gUHJpbWl0aXZlIHR5cGVzIGNhbm5vdCBoYXZlIHByb3BlcnRpZXNcbiAgdmFyIHByaW1pdGl2ZSA9IGZvcm1hdFByaW1pdGl2ZShjdHgsIHZhbHVlKTtcbiAgaWYgKHByaW1pdGl2ZSkge1xuICAgIHJldHVybiBwcmltaXRpdmU7XG4gIH1cblxuICAvLyBJZiB0aGlzIGlzIGEgRE9NIGVsZW1lbnQsIHRyeSB0byBnZXQgdGhlIG91dGVyIEhUTUwuXG4gIGlmIChpc0RPTUVsZW1lbnQodmFsdWUpKSB7XG4gICAgaWYgKCdvdXRlckhUTUwnIGluIHZhbHVlKSB7XG4gICAgICByZXR1cm4gdmFsdWUub3V0ZXJIVE1MO1xuICAgICAgLy8gVGhpcyB2YWx1ZSBkb2VzIG5vdCBoYXZlIGFuIG91dGVySFRNTCBhdHRyaWJ1dGUsXG4gICAgICAvLyAgIGl0IGNvdWxkIHN0aWxsIGJlIGFuIFhNTCBlbGVtZW50XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEF0dGVtcHQgdG8gc2VyaWFsaXplIGl0XG4gICAgICB0cnkge1xuICAgICAgICBpZiAoZG9jdW1lbnQueG1sVmVyc2lvbikge1xuICAgICAgICAgIHZhciB4bWxTZXJpYWxpemVyID0gbmV3IFhNTFNlcmlhbGl6ZXIoKTtcbiAgICAgICAgICByZXR1cm4geG1sU2VyaWFsaXplci5zZXJpYWxpemVUb1N0cmluZyh2YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gRmlyZWZveCAxMS0gZG8gbm90IHN1cHBvcnQgb3V0ZXJIVE1MXG4gICAgICAgICAgLy8gICBJdCBkb2VzLCBob3dldmVyLCBzdXBwb3J0IGlubmVySFRNTFxuICAgICAgICAgIC8vICAgVXNlIHRoZSBmb2xsb3dpbmcgdG8gcmVuZGVyIHRoZSBlbGVtZW50XG4gICAgICAgICAgdmFyIG5zID0gXCJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hodG1sXCI7XG4gICAgICAgICAgdmFyIGNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnROUyhucywgJ18nKTtcblxuICAgICAgICAgIGNvbnRhaW5lci5hcHBlbmRDaGlsZCh2YWx1ZS5jbG9uZU5vZGUoZmFsc2UpKTtcbiAgICAgICAgICBodG1sID0gY29udGFpbmVyLmlubmVySFRNTFxuICAgICAgICAgICAgLnJlcGxhY2UoJz48JywgJz4nICsgdmFsdWUuaW5uZXJIVE1MICsgJzwnKTtcbiAgICAgICAgICBjb250YWluZXIuaW5uZXJIVE1MID0gJyc7XG4gICAgICAgICAgcmV0dXJuIGh0bWw7XG4gICAgICAgIH1cbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAvLyBUaGlzIGNvdWxkIGJlIGEgbm9uLW5hdGl2ZSBET00gaW1wbGVtZW50YXRpb24sXG4gICAgICAgIC8vICAgY29udGludWUgd2l0aCB0aGUgbm9ybWFsIGZsb3c6XG4gICAgICAgIC8vICAgcHJpbnRpbmcgdGhlIGVsZW1lbnQgYXMgaWYgaXQgaXMgYW4gb2JqZWN0LlxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIExvb2sgdXAgdGhlIGtleXMgb2YgdGhlIG9iamVjdC5cbiAgdmFyIHZpc2libGVLZXlzID0gZ2V0RW51bWVyYWJsZVByb3BlcnRpZXModmFsdWUpO1xuICB2YXIga2V5cyA9IGN0eC5zaG93SGlkZGVuID8gZ2V0UHJvcGVydGllcyh2YWx1ZSkgOiB2aXNpYmxlS2V5cztcblxuICAvLyBTb21lIHR5cGUgb2Ygb2JqZWN0IHdpdGhvdXQgcHJvcGVydGllcyBjYW4gYmUgc2hvcnRjdXR0ZWQuXG4gIC8vIEluIElFLCBlcnJvcnMgaGF2ZSBhIHNpbmdsZSBgc3RhY2tgIHByb3BlcnR5LCBvciBpZiB0aGV5IGFyZSB2YW5pbGxhIGBFcnJvcmAsXG4gIC8vIGEgYHN0YWNrYCBwbHVzIGBkZXNjcmlwdGlvbmAgcHJvcGVydHk7IGlnbm9yZSB0aG9zZSBmb3IgY29uc2lzdGVuY3kuXG4gIGlmIChrZXlzLmxlbmd0aCA9PT0gMCB8fCAoaXNFcnJvcih2YWx1ZSkgJiYgKFxuICAgICAgKGtleXMubGVuZ3RoID09PSAxICYmIGtleXNbMF0gPT09ICdzdGFjaycpIHx8XG4gICAgICAoa2V5cy5sZW5ndGggPT09IDIgJiYga2V5c1swXSA9PT0gJ2Rlc2NyaXB0aW9uJyAmJiBrZXlzWzFdID09PSAnc3RhY2snKVxuICAgICApKSkge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHZhciBuYW1lID0gZ2V0TmFtZSh2YWx1ZSk7XG4gICAgICB2YXIgbmFtZVN1ZmZpeCA9IG5hbWUgPyAnOiAnICsgbmFtZSA6ICcnO1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbRnVuY3Rpb24nICsgbmFtZVN1ZmZpeCArICddJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9XG4gICAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShEYXRlLnByb3RvdHlwZS50b1VUQ1N0cmluZy5jYWxsKHZhbHVlKSwgJ2RhdGUnKTtcbiAgICB9XG4gICAgaWYgKGlzRXJyb3IodmFsdWUpKSB7XG4gICAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBiYXNlID0gJycsIGFycmF5ID0gZmFsc2UsIGJyYWNlcyA9IFsneycsICd9J107XG5cbiAgLy8gTWFrZSBBcnJheSBzYXkgdGhhdCB0aGV5IGFyZSBBcnJheVxuICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBhcnJheSA9IHRydWU7XG4gICAgYnJhY2VzID0gWydbJywgJ10nXTtcbiAgfVxuXG4gIC8vIE1ha2UgZnVuY3Rpb25zIHNheSB0aGF0IHRoZXkgYXJlIGZ1bmN0aW9uc1xuICBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgdmFyIG5hbWUgPSBnZXROYW1lKHZhbHVlKTtcbiAgICB2YXIgbmFtZVN1ZmZpeCA9IG5hbWUgPyAnOiAnICsgbmFtZSA6ICcnO1xuICAgIGJhc2UgPSAnIFtGdW5jdGlvbicgKyBuYW1lU3VmZml4ICsgJ10nO1xuICB9XG5cbiAgLy8gTWFrZSBSZWdFeHBzIHNheSB0aGF0IHRoZXkgYXJlIFJlZ0V4cHNcbiAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBkYXRlcyB3aXRoIHByb3BlcnRpZXMgZmlyc3Qgc2F5IHRoZSBkYXRlXG4gIGlmIChpc0RhdGUodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIERhdGUucHJvdG90eXBlLnRvVVRDU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBlcnJvciB3aXRoIG1lc3NhZ2UgZmlyc3Qgc2F5IHRoZSBlcnJvclxuICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICB9XG5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwICYmICghYXJyYXkgfHwgdmFsdWUubGVuZ3RoID09IDApKSB7XG4gICAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyBicmFjZXNbMV07XG4gIH1cblxuICBpZiAocmVjdXJzZVRpbWVzIDwgMCkge1xuICAgIGlmIChpc1JlZ0V4cCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAncmVnZXhwJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgnW09iamVjdF0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuXG4gIGN0eC5zZWVuLnB1c2godmFsdWUpO1xuXG4gIHZhciBvdXRwdXQ7XG4gIGlmIChhcnJheSkge1xuICAgIG91dHB1dCA9IGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpO1xuICB9IGVsc2Uge1xuICAgIG91dHB1dCA9IGtleXMubWFwKGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpO1xuICAgIH0pO1xuICB9XG5cbiAgY3R4LnNlZW4ucG9wKCk7XG5cbiAgcmV0dXJuIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRQcmltaXRpdmUoY3R4LCB2YWx1ZSkge1xuICBzd2l0Y2ggKHR5cGVvZiB2YWx1ZSkge1xuICAgIGNhc2UgJ3VuZGVmaW5lZCc6XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJ3VuZGVmaW5lZCcsICd1bmRlZmluZWQnKTtcblxuICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICB2YXIgc2ltcGxlID0gJ1xcJycgKyBKU09OLnN0cmluZ2lmeSh2YWx1ZSkucmVwbGFjZSgvXlwifFwiJC9nLCAnJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnJlcGxhY2UoLycvZywgXCJcXFxcJ1wiKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxcXFwiL2csICdcIicpICsgJ1xcJyc7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoc2ltcGxlLCAnc3RyaW5nJyk7XG5cbiAgICBjYXNlICdudW1iZXInOlxuICAgICAgaWYgKHZhbHVlID09PSAwICYmICgxL3ZhbHVlKSA9PT0gLUluZmluaXR5KSB7XG4gICAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgnLTAnLCAnbnVtYmVyJyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJycgKyB2YWx1ZSwgJ251bWJlcicpO1xuXG4gICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJycgKyB2YWx1ZSwgJ2Jvb2xlYW4nKTtcbiAgfVxuICAvLyBGb3Igc29tZSByZWFzb24gdHlwZW9mIG51bGwgaXMgXCJvYmplY3RcIiwgc28gc3BlY2lhbCBjYXNlIGhlcmUuXG4gIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgIHJldHVybiBjdHguc3R5bGl6ZSgnbnVsbCcsICdudWxsJyk7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRFcnJvcih2YWx1ZSkge1xuICByZXR1cm4gJ1snICsgRXJyb3IucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpICsgJ10nO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpIHtcbiAgdmFyIG91dHB1dCA9IFtdO1xuICBmb3IgKHZhciBpID0gMCwgbCA9IHZhbHVlLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwodmFsdWUsIFN0cmluZyhpKSkpIHtcbiAgICAgIG91dHB1dC5wdXNoKGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsXG4gICAgICAgICAgU3RyaW5nKGkpLCB0cnVlKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG91dHB1dC5wdXNoKCcnKTtcbiAgICB9XG4gIH1cbiAga2V5cy5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgIGlmICgha2V5Lm1hdGNoKC9eXFxkKyQvKSkge1xuICAgICAgb3V0cHV0LnB1c2goZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cyxcbiAgICAgICAgICBrZXksIHRydWUpKTtcbiAgICB9XG4gIH0pO1xuICByZXR1cm4gb3V0cHV0O1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpIHtcbiAgdmFyIG5hbWUsIHN0cjtcbiAgaWYgKHZhbHVlLl9fbG9va3VwR2V0dGVyX18pIHtcbiAgICBpZiAodmFsdWUuX19sb29rdXBHZXR0ZXJfXyhrZXkpKSB7XG4gICAgICBpZiAodmFsdWUuX19sb29rdXBTZXR0ZXJfXyhrZXkpKSB7XG4gICAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbR2V0dGVyL1NldHRlcl0nLCAnc3BlY2lhbCcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHZhbHVlLl9fbG9va3VwU2V0dGVyX18oa2V5KSkge1xuICAgICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW1NldHRlcl0nLCAnc3BlY2lhbCcpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBpZiAodmlzaWJsZUtleXMuaW5kZXhPZihrZXkpIDwgMCkge1xuICAgIG5hbWUgPSAnWycgKyBrZXkgKyAnXSc7XG4gIH1cbiAgaWYgKCFzdHIpIHtcbiAgICBpZiAoY3R4LnNlZW4uaW5kZXhPZih2YWx1ZVtrZXldKSA8IDApIHtcbiAgICAgIGlmIChyZWN1cnNlVGltZXMgPT09IG51bGwpIHtcbiAgICAgICAgc3RyID0gZm9ybWF0VmFsdWUoY3R4LCB2YWx1ZVtrZXldLCBudWxsKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0ciA9IGZvcm1hdFZhbHVlKGN0eCwgdmFsdWVba2V5XSwgcmVjdXJzZVRpbWVzIC0gMSk7XG4gICAgICB9XG4gICAgICBpZiAoc3RyLmluZGV4T2YoJ1xcbicpID4gLTEpIHtcbiAgICAgICAgaWYgKGFycmF5KSB7XG4gICAgICAgICAgc3RyID0gc3RyLnNwbGl0KCdcXG4nKS5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgcmV0dXJuICcgICcgKyBsaW5lO1xuICAgICAgICAgIH0pLmpvaW4oJ1xcbicpLnN1YnN0cigyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzdHIgPSAnXFxuJyArIHN0ci5zcGxpdCgnXFxuJykubWFwKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgICAgICAgIHJldHVybiAnICAgJyArIGxpbmU7XG4gICAgICAgICAgfSkuam9pbignXFxuJyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tDaXJjdWxhcl0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuICBpZiAodHlwZW9mIG5hbWUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKGFycmF5ICYmIGtleS5tYXRjaCgvXlxcZCskLykpIHtcbiAgICAgIHJldHVybiBzdHI7XG4gICAgfVxuICAgIG5hbWUgPSBKU09OLnN0cmluZ2lmeSgnJyArIGtleSk7XG4gICAgaWYgKG5hbWUubWF0Y2goL15cIihbYS16QS1aX11bYS16QS1aXzAtOV0qKVwiJC8pKSB7XG4gICAgICBuYW1lID0gbmFtZS5zdWJzdHIoMSwgbmFtZS5sZW5ndGggLSAyKTtcbiAgICAgIG5hbWUgPSBjdHguc3R5bGl6ZShuYW1lLCAnbmFtZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuYW1lID0gbmFtZS5yZXBsYWNlKC8nL2csIFwiXFxcXCdcIilcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcXFxcIi9nLCAnXCInKVxuICAgICAgICAgICAgICAgICAucmVwbGFjZSgvKF5cInxcIiQpL2csIFwiJ1wiKTtcbiAgICAgIG5hbWUgPSBjdHguc3R5bGl6ZShuYW1lLCAnc3RyaW5nJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5hbWUgKyAnOiAnICsgc3RyO1xufVxuXG5cbmZ1bmN0aW9uIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKSB7XG4gIHZhciBudW1MaW5lc0VzdCA9IDA7XG4gIHZhciBsZW5ndGggPSBvdXRwdXQucmVkdWNlKGZ1bmN0aW9uKHByZXYsIGN1cikge1xuICAgIG51bUxpbmVzRXN0Kys7XG4gICAgaWYgKGN1ci5pbmRleE9mKCdcXG4nKSA+PSAwKSBudW1MaW5lc0VzdCsrO1xuICAgIHJldHVybiBwcmV2ICsgY3VyLmxlbmd0aCArIDE7XG4gIH0sIDApO1xuXG4gIGlmIChsZW5ndGggPiA2MCkge1xuICAgIHJldHVybiBicmFjZXNbMF0gK1xuICAgICAgICAgICAoYmFzZSA9PT0gJycgPyAnJyA6IGJhc2UgKyAnXFxuICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgb3V0cHV0LmpvaW4oJyxcXG4gICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgYnJhY2VzWzFdO1xuICB9XG5cbiAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyAnICcgKyBvdXRwdXQuam9pbignLCAnKSArICcgJyArIGJyYWNlc1sxXTtcbn1cblxuZnVuY3Rpb24gaXNBcnJheShhcikge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShhcikgfHxcbiAgICAgICAgICh0eXBlb2YgYXIgPT09ICdvYmplY3QnICYmIG9iamVjdFRvU3RyaW5nKGFyKSA9PT0gJ1tvYmplY3QgQXJyYXldJyk7XG59XG5cbmZ1bmN0aW9uIGlzUmVnRXhwKHJlKSB7XG4gIHJldHVybiB0eXBlb2YgcmUgPT09ICdvYmplY3QnICYmIG9iamVjdFRvU3RyaW5nKHJlKSA9PT0gJ1tvYmplY3QgUmVnRXhwXSc7XG59XG5cbmZ1bmN0aW9uIGlzRGF0ZShkKSB7XG4gIHJldHVybiB0eXBlb2YgZCA9PT0gJ29iamVjdCcgJiYgb2JqZWN0VG9TdHJpbmcoZCkgPT09ICdbb2JqZWN0IERhdGVdJztcbn1cblxuZnVuY3Rpb24gaXNFcnJvcihlKSB7XG4gIHJldHVybiB0eXBlb2YgZSA9PT0gJ29iamVjdCcgJiYgb2JqZWN0VG9TdHJpbmcoZSkgPT09ICdbb2JqZWN0IEVycm9yXSc7XG59XG5cbmZ1bmN0aW9uIG9iamVjdFRvU3RyaW5nKG8pIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTtcbn1cbiIsIi8qIVxuICogQ2hhaSAtIGZsYWcgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qIVxuICogTW9kdWxlIGRlcGVuZGFuY2llc1xuICovXG5cbnZhciBpbnNwZWN0ID0gcmVxdWlyZSgnLi9pbnNwZWN0Jyk7XG52YXIgY29uZmlnID0gcmVxdWlyZSgnLi4vY29uZmlnJyk7XG5cbi8qKlxuICogIyMjIC5vYmpEaXNwbGF5IChvYmplY3QpXG4gKlxuICogRGV0ZXJtaW5lcyBpZiBhbiBvYmplY3Qgb3IgYW4gYXJyYXkgbWF0Y2hlc1xuICogY3JpdGVyaWEgdG8gYmUgaW5zcGVjdGVkIGluLWxpbmUgZm9yIGVycm9yXG4gKiBtZXNzYWdlcyBvciBzaG91bGQgYmUgdHJ1bmNhdGVkLlxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IGphdmFzY3JpcHQgb2JqZWN0IHRvIGluc3BlY3RcbiAqIEBuYW1lIG9iakRpc3BsYXlcbiAqIEBhcGkgcHVibGljXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAob2JqKSB7XG4gIHZhciBzdHIgPSBpbnNwZWN0KG9iailcbiAgICAsIHR5cGUgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKTtcblxuICBpZiAoY29uZmlnLnRydW5jYXRlVGhyZXNob2xkICYmIHN0ci5sZW5ndGggPj0gY29uZmlnLnRydW5jYXRlVGhyZXNob2xkKSB7XG4gICAgaWYgKHR5cGUgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXScpIHtcbiAgICAgIHJldHVybiAhb2JqLm5hbWUgfHwgb2JqLm5hbWUgPT09ICcnXG4gICAgICAgID8gJ1tGdW5jdGlvbl0nXG4gICAgICAgIDogJ1tGdW5jdGlvbjogJyArIG9iai5uYW1lICsgJ10nO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ1tvYmplY3QgQXJyYXldJykge1xuICAgICAgcmV0dXJuICdbIEFycmF5KCcgKyBvYmoubGVuZ3RoICsgJykgXSc7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnW29iamVjdCBPYmplY3RdJykge1xuICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhvYmopXG4gICAgICAgICwga3N0ciA9IGtleXMubGVuZ3RoID4gMlxuICAgICAgICAgID8ga2V5cy5zcGxpY2UoMCwgMikuam9pbignLCAnKSArICcsIC4uLidcbiAgICAgICAgICA6IGtleXMuam9pbignLCAnKTtcbiAgICAgIHJldHVybiAneyBPYmplY3QgKCcgKyBrc3RyICsgJykgfSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBzdHI7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBzdHI7XG4gIH1cbn07XG4iLCIvKiFcbiAqIENoYWkgLSBvdmVyd3JpdGVDaGFpbmFibGVNZXRob2QgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIG92ZXJ3cml0ZUNoYWluYWJsZU1ldGhvZCAoY3R4LCBuYW1lLCBtZXRob2QsIGNoYWluaW5nQmVoYXZpb3IpXG4gKlxuICogT3ZlcndpdGVzIGFuIGFscmVhZHkgZXhpc3RpbmcgY2hhaW5hYmxlIG1ldGhvZFxuICogYW5kIHByb3ZpZGVzIGFjY2VzcyB0byB0aGUgcHJldmlvdXMgZnVuY3Rpb24gb3JcbiAqIHByb3BlcnR5LiAgTXVzdCByZXR1cm4gZnVuY3Rpb25zIHRvIGJlIHVzZWQgZm9yXG4gKiBuYW1lLlxuICpcbiAqICAgICB1dGlscy5vdmVyd3JpdGVDaGFpbmFibGVNZXRob2QoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCAnbGVuZ3RoJyxcbiAqICAgICAgIGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAqICAgICAgIH1cbiAqICAgICAsIGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAqICAgICAgIH1cbiAqICAgICApO1xuICpcbiAqIENhbiBhbHNvIGJlIGFjY2Vzc2VkIGRpcmVjdGx5IGZyb20gYGNoYWkuQXNzZXJ0aW9uYC5cbiAqXG4gKiAgICAgY2hhaS5Bc3NlcnRpb24ub3ZlcndyaXRlQ2hhaW5hYmxlTWV0aG9kKCdmb28nLCBmbiwgZm4pO1xuICpcbiAqIFRoZW4gY2FuIGJlIHVzZWQgYXMgYW55IG90aGVyIGFzc2VydGlvbi5cbiAqXG4gKiAgICAgZXhwZWN0KG15Rm9vKS50by5oYXZlLmxlbmd0aCgzKTtcbiAqICAgICBleHBlY3QobXlGb28pLnRvLmhhdmUubGVuZ3RoLmFib3ZlKDMpO1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjdHggb2JqZWN0IHdob3NlIG1ldGhvZCAvIHByb3BlcnR5IGlzIHRvIGJlIG92ZXJ3cml0dGVuXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiBtZXRob2QgLyBwcm9wZXJ0eSB0byBvdmVyd3JpdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IG1ldGhvZCBmdW5jdGlvbiB0aGF0IHJldHVybnMgYSBmdW5jdGlvbiB0byBiZSB1c2VkIGZvciBuYW1lXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjaGFpbmluZ0JlaGF2aW9yIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIGZ1bmN0aW9uIHRvIGJlIHVzZWQgZm9yIHByb3BlcnR5XG4gKiBAbmFtZSBvdmVyd3JpdGVDaGFpbmFibGVNZXRob2RcbiAqIEBhcGkgcHVibGljXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoY3R4LCBuYW1lLCBtZXRob2QsIGNoYWluaW5nQmVoYXZpb3IpIHtcbiAgdmFyIGNoYWluYWJsZUJlaGF2aW9yID0gY3R4Ll9fbWV0aG9kc1tuYW1lXTtcblxuICB2YXIgX2NoYWluaW5nQmVoYXZpb3IgPSBjaGFpbmFibGVCZWhhdmlvci5jaGFpbmluZ0JlaGF2aW9yO1xuICBjaGFpbmFibGVCZWhhdmlvci5jaGFpbmluZ0JlaGF2aW9yID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciByZXN1bHQgPSBjaGFpbmluZ0JlaGF2aW9yKF9jaGFpbmluZ0JlaGF2aW9yKS5jYWxsKHRoaXMpO1xuICAgIHJldHVybiByZXN1bHQgPT09IHVuZGVmaW5lZCA/IHRoaXMgOiByZXN1bHQ7XG4gIH07XG5cbiAgdmFyIF9tZXRob2QgPSBjaGFpbmFibGVCZWhhdmlvci5tZXRob2Q7XG4gIGNoYWluYWJsZUJlaGF2aW9yLm1ldGhvZCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmVzdWx0ID0gbWV0aG9kKF9tZXRob2QpLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gdGhpcyA6IHJlc3VsdDtcbiAgfTtcbn07XG4iLCIvKiFcbiAqIENoYWkgLSBvdmVyd3JpdGVNZXRob2QgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIG92ZXJ3cml0ZU1ldGhvZCAoY3R4LCBuYW1lLCBmbilcbiAqXG4gKiBPdmVyd2l0ZXMgYW4gYWxyZWFkeSBleGlzdGluZyBtZXRob2QgYW5kIHByb3ZpZGVzXG4gKiBhY2Nlc3MgdG8gcHJldmlvdXMgZnVuY3Rpb24uIE11c3QgcmV0dXJuIGZ1bmN0aW9uXG4gKiB0byBiZSB1c2VkIGZvciBuYW1lLlxuICpcbiAqICAgICB1dGlscy5vdmVyd3JpdGVNZXRob2QoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCAnZXF1YWwnLCBmdW5jdGlvbiAoX3N1cGVyKSB7XG4gKiAgICAgICByZXR1cm4gZnVuY3Rpb24gKHN0cikge1xuICogICAgICAgICB2YXIgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gKiAgICAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBGb28pIHtcbiAqICAgICAgICAgICBuZXcgY2hhaS5Bc3NlcnRpb24ob2JqLnZhbHVlKS50by5lcXVhbChzdHIpO1xuICogICAgICAgICB9IGVsc2Uge1xuICogICAgICAgICAgIF9zdXBlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICogICAgICAgICB9XG4gKiAgICAgICB9XG4gKiAgICAgfSk7XG4gKlxuICogQ2FuIGFsc28gYmUgYWNjZXNzZWQgZGlyZWN0bHkgZnJvbSBgY2hhaS5Bc3NlcnRpb25gLlxuICpcbiAqICAgICBjaGFpLkFzc2VydGlvbi5vdmVyd3JpdGVNZXRob2QoJ2ZvbycsIGZuKTtcbiAqXG4gKiBUaGVuIGNhbiBiZSB1c2VkIGFzIGFueSBvdGhlciBhc3NlcnRpb24uXG4gKlxuICogICAgIGV4cGVjdChteUZvbykudG8uZXF1YWwoJ2JhcicpO1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjdHggb2JqZWN0IHdob3NlIG1ldGhvZCBpcyB0byBiZSBvdmVyd3JpdHRlblxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgb2YgbWV0aG9kIHRvIG92ZXJ3cml0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gbWV0aG9kIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhIGZ1bmN0aW9uIHRvIGJlIHVzZWQgZm9yIG5hbWVcbiAqIEBuYW1lIG92ZXJ3cml0ZU1ldGhvZFxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChjdHgsIG5hbWUsIG1ldGhvZCkge1xuICB2YXIgX21ldGhvZCA9IGN0eFtuYW1lXVxuICAgICwgX3N1cGVyID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfTtcblxuICBpZiAoX21ldGhvZCAmJiAnZnVuY3Rpb24nID09PSB0eXBlb2YgX21ldGhvZClcbiAgICBfc3VwZXIgPSBfbWV0aG9kO1xuXG4gIGN0eFtuYW1lXSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcmVzdWx0ID0gbWV0aG9kKF9zdXBlcikuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICByZXR1cm4gcmVzdWx0ID09PSB1bmRlZmluZWQgPyB0aGlzIDogcmVzdWx0O1xuICB9XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gb3ZlcndyaXRlUHJvcGVydHkgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIG92ZXJ3cml0ZVByb3BlcnR5IChjdHgsIG5hbWUsIGZuKVxuICpcbiAqIE92ZXJ3aXRlcyBhbiBhbHJlYWR5IGV4aXN0aW5nIHByb3BlcnR5IGdldHRlciBhbmQgcHJvdmlkZXNcbiAqIGFjY2VzcyB0byBwcmV2aW91cyB2YWx1ZS4gTXVzdCByZXR1cm4gZnVuY3Rpb24gdG8gdXNlIGFzIGdldHRlci5cbiAqXG4gKiAgICAgdXRpbHMub3ZlcndyaXRlUHJvcGVydHkoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCAnb2snLCBmdW5jdGlvbiAoX3N1cGVyKSB7XG4gKiAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICogICAgICAgICB2YXIgb2JqID0gdXRpbHMuZmxhZyh0aGlzLCAnb2JqZWN0Jyk7XG4gKiAgICAgICAgIGlmIChvYmogaW5zdGFuY2VvZiBGb28pIHtcbiAqICAgICAgICAgICBuZXcgY2hhaS5Bc3NlcnRpb24ob2JqLm5hbWUpLnRvLmVxdWFsKCdiYXInKTtcbiAqICAgICAgICAgfSBlbHNlIHtcbiAqICAgICAgICAgICBfc3VwZXIuY2FsbCh0aGlzKTtcbiAqICAgICAgICAgfVxuICogICAgICAgfVxuICogICAgIH0pO1xuICpcbiAqXG4gKiBDYW4gYWxzbyBiZSBhY2Nlc3NlZCBkaXJlY3RseSBmcm9tIGBjaGFpLkFzc2VydGlvbmAuXG4gKlxuICogICAgIGNoYWkuQXNzZXJ0aW9uLm92ZXJ3cml0ZVByb3BlcnR5KCdmb28nLCBmbik7XG4gKlxuICogVGhlbiBjYW4gYmUgdXNlZCBhcyBhbnkgb3RoZXIgYXNzZXJ0aW9uLlxuICpcbiAqICAgICBleHBlY3QobXlGb28pLnRvLmJlLm9rO1xuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBjdHggb2JqZWN0IHdob3NlIHByb3BlcnR5IGlzIHRvIGJlIG92ZXJ3cml0dGVuXG4gKiBAcGFyYW0ge1N0cmluZ30gbmFtZSBvZiBwcm9wZXJ0eSB0byBvdmVyd3JpdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGdldHRlciBmdW5jdGlvbiB0aGF0IHJldHVybnMgYSBnZXR0ZXIgZnVuY3Rpb24gdG8gYmUgdXNlZCBmb3IgbmFtZVxuICogQG5hbWUgb3ZlcndyaXRlUHJvcGVydHlcbiAqIEBhcGkgcHVibGljXG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoY3R4LCBuYW1lLCBnZXR0ZXIpIHtcbiAgdmFyIF9nZXQgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKGN0eCwgbmFtZSlcbiAgICAsIF9zdXBlciA9IGZ1bmN0aW9uICgpIHt9O1xuXG4gIGlmIChfZ2V0ICYmICdmdW5jdGlvbicgPT09IHR5cGVvZiBfZ2V0LmdldClcbiAgICBfc3VwZXIgPSBfZ2V0LmdldFxuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjdHgsIG5hbWUsXG4gICAgeyBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGdldHRlcihfc3VwZXIpLmNhbGwodGhpcyk7XG4gICAgICAgIHJldHVybiByZXN1bHQgPT09IHVuZGVmaW5lZCA/IHRoaXMgOiByZXN1bHQ7XG4gICAgICB9XG4gICAgLCBjb25maWd1cmFibGU6IHRydWVcbiAgfSk7XG59O1xuIiwiLyohXG4gKiBDaGFpIC0gdGVzdCB1dGlsaXR5XG4gKiBDb3B5cmlnaHQoYykgMjAxMi0yMDE0IEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBNb2R1bGUgZGVwZW5kYW5jaWVzXG4gKi9cblxudmFyIGZsYWcgPSByZXF1aXJlKCcuL2ZsYWcnKTtcblxuLyoqXG4gKiAjIHRlc3Qob2JqZWN0LCBleHByZXNzaW9uKVxuICpcbiAqIFRlc3QgYW5kIG9iamVjdCBmb3IgZXhwcmVzc2lvbi5cbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IChjb25zdHJ1Y3RlZCBBc3NlcnRpb24pXG4gKiBAcGFyYW0ge0FyZ3VtZW50c30gY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLmFzc2VydCBhcmd1bWVudHNcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmosIGFyZ3MpIHtcbiAgdmFyIG5lZ2F0ZSA9IGZsYWcob2JqLCAnbmVnYXRlJylcbiAgICAsIGV4cHIgPSBhcmdzWzBdO1xuICByZXR1cm4gbmVnYXRlID8gIWV4cHIgOiBleHByO1xufTtcbiIsIi8qIVxuICogQ2hhaSAtIHRyYW5zZmVyRmxhZ3MgdXRpbGl0eVxuICogQ29weXJpZ2h0KGMpIDIwMTItMjAxNCBKYWtlIEx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qKlxuICogIyMjIHRyYW5zZmVyRmxhZ3MoYXNzZXJ0aW9uLCBvYmplY3QsIGluY2x1ZGVBbGwgPSB0cnVlKVxuICpcbiAqIFRyYW5zZmVyIGFsbCB0aGUgZmxhZ3MgZm9yIGBhc3NlcnRpb25gIHRvIGBvYmplY3RgLiBJZlxuICogYGluY2x1ZGVBbGxgIGlzIHNldCB0byBgZmFsc2VgLCB0aGVuIHRoZSBiYXNlIENoYWlcbiAqIGFzc2VydGlvbiBmbGFncyAobmFtZWx5IGBvYmplY3RgLCBgc3NmaWAsIGFuZCBgbWVzc2FnZWApXG4gKiB3aWxsIG5vdCBiZSB0cmFuc2ZlcnJlZC5cbiAqXG4gKlxuICogICAgIHZhciBuZXdBc3NlcnRpb24gPSBuZXcgQXNzZXJ0aW9uKCk7XG4gKiAgICAgdXRpbHMudHJhbnNmZXJGbGFncyhhc3NlcnRpb24sIG5ld0Fzc2VydGlvbik7XG4gKlxuICogICAgIHZhciBhbm90aGVyQXNzZXJpdG9uID0gbmV3IEFzc2VydGlvbihteU9iaik7XG4gKiAgICAgdXRpbHMudHJhbnNmZXJGbGFncyhhc3NlcnRpb24sIGFub3RoZXJBc3NlcnRpb24sIGZhbHNlKTtcbiAqXG4gKiBAcGFyYW0ge0Fzc2VydGlvbn0gYXNzZXJ0aW9uIHRoZSBhc3NlcnRpb24gdG8gdHJhbnNmZXIgdGhlIGZsYWdzIGZyb21cbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgdGhlIG9iamVjdCB0byB0cmFuc2ZlciB0aGUgZmxhZ3MgdG87IHVzdWFsbHkgYSBuZXcgYXNzZXJ0aW9uXG4gKiBAcGFyYW0ge0Jvb2xlYW59IGluY2x1ZGVBbGxcbiAqIEBuYW1lIHRyYW5zZmVyRmxhZ3NcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFzc2VydGlvbiwgb2JqZWN0LCBpbmNsdWRlQWxsKSB7XG4gIHZhciBmbGFncyA9IGFzc2VydGlvbi5fX2ZsYWdzIHx8IChhc3NlcnRpb24uX19mbGFncyA9IE9iamVjdC5jcmVhdGUobnVsbCkpO1xuXG4gIGlmICghb2JqZWN0Ll9fZmxhZ3MpIHtcbiAgICBvYmplY3QuX19mbGFncyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gIH1cblxuICBpbmNsdWRlQWxsID0gYXJndW1lbnRzLmxlbmd0aCA9PT0gMyA/IGluY2x1ZGVBbGwgOiB0cnVlO1xuXG4gIGZvciAodmFyIGZsYWcgaW4gZmxhZ3MpIHtcbiAgICBpZiAoaW5jbHVkZUFsbCB8fFxuICAgICAgICAoZmxhZyAhPT0gJ29iamVjdCcgJiYgZmxhZyAhPT0gJ3NzZmknICYmIGZsYWcgIT0gJ21lc3NhZ2UnKSkge1xuICAgICAgb2JqZWN0Ll9fZmxhZ3NbZmxhZ10gPSBmbGFnc1tmbGFnXTtcbiAgICB9XG4gIH1cbn07XG4iLCIvKiFcbiAqIENoYWkgLSB0eXBlIHV0aWxpdHlcbiAqIENvcHlyaWdodChjKSAyMDEyLTIwMTQgSmFrZSBMdWVyIDxqYWtlQGFsb2dpY2FscGFyYWRveC5jb20+XG4gKiBNSVQgTGljZW5zZWRcbiAqL1xuXG4vKiFcbiAqIERldGVjdGFibGUgamF2YXNjcmlwdCBuYXRpdmVzXG4gKi9cblxudmFyIG5hdGl2ZXMgPSB7XG4gICAgJ1tvYmplY3QgQXJndW1lbnRzXSc6ICdhcmd1bWVudHMnXG4gICwgJ1tvYmplY3QgQXJyYXldJzogJ2FycmF5J1xuICAsICdbb2JqZWN0IERhdGVdJzogJ2RhdGUnXG4gICwgJ1tvYmplY3QgRnVuY3Rpb25dJzogJ2Z1bmN0aW9uJ1xuICAsICdbb2JqZWN0IE51bWJlcl0nOiAnbnVtYmVyJ1xuICAsICdbb2JqZWN0IFJlZ0V4cF0nOiAncmVnZXhwJ1xuICAsICdbb2JqZWN0IFN0cmluZ10nOiAnc3RyaW5nJ1xufTtcblxuLyoqXG4gKiAjIyMgdHlwZShvYmplY3QpXG4gKlxuICogQmV0dGVyIGltcGxlbWVudGF0aW9uIG9mIGB0eXBlb2ZgIGRldGVjdGlvbiB0aGF0IGNhblxuICogYmUgdXNlZCBjcm9zcy1icm93c2VyLiBIYW5kbGVzIHRoZSBpbmNvbnNpc3RlbmNpZXMgb2ZcbiAqIEFycmF5LCBgbnVsbGAsIGFuZCBgdW5kZWZpbmVkYCBkZXRlY3Rpb24uXG4gKlxuICogICAgIHV0aWxzLnR5cGUoe30pIC8vICdvYmplY3QnXG4gKiAgICAgdXRpbHMudHlwZShudWxsKSAvLyBgbnVsbCdcbiAqICAgICB1dGlscy50eXBlKHVuZGVmaW5lZCkgLy8gYHVuZGVmaW5lZGBcbiAqICAgICB1dGlscy50eXBlKFtdKSAvLyBgYXJyYXlgXG4gKlxuICogQHBhcmFtIHtNaXhlZH0gb2JqZWN0IHRvIGRldGVjdCB0eXBlIG9mXG4gKiBAbmFtZSB0eXBlXG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmopIHtcbiAgdmFyIHN0ciA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopO1xuICBpZiAobmF0aXZlc1tzdHJdKSByZXR1cm4gbmF0aXZlc1tzdHJdO1xuICBpZiAob2JqID09PSBudWxsKSByZXR1cm4gJ251bGwnO1xuICBpZiAob2JqID09PSB1bmRlZmluZWQpIHJldHVybiAndW5kZWZpbmVkJztcbiAgaWYgKG9iaiA9PT0gT2JqZWN0KG9iaikpIHJldHVybiAnb2JqZWN0JztcbiAgcmV0dXJuIHR5cGVvZiBvYmo7XG59O1xuIiwiLyohXG4gKiBhc3NlcnRpb24tZXJyb3JcbiAqIENvcHlyaWdodChjKSAyMDEzIEpha2UgTHVlciA8amFrZUBxdWFsaWFuY3kuY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBSZXR1cm4gYSBmdW5jdGlvbiB0aGF0IHdpbGwgY29weSBwcm9wZXJ0aWVzIGZyb21cbiAqIG9uZSBvYmplY3QgdG8gYW5vdGhlciBleGNsdWRpbmcgYW55IG9yaWdpbmFsbHlcbiAqIGxpc3RlZC4gUmV0dXJuZWQgZnVuY3Rpb24gd2lsbCBjcmVhdGUgYSBuZXcgYHt9YC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gZXhjbHVkZWQgcHJvcGVydGllcyAuLi5cbiAqIEByZXR1cm4ge0Z1bmN0aW9ufVxuICovXG5cbmZ1bmN0aW9uIGV4Y2x1ZGUgKCkge1xuICB2YXIgZXhjbHVkZXMgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG5cbiAgZnVuY3Rpb24gZXhjbHVkZVByb3BzIChyZXMsIG9iaikge1xuICAgIE9iamVjdC5rZXlzKG9iaikuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICBpZiAoIX5leGNsdWRlcy5pbmRleE9mKGtleSkpIHJlc1trZXldID0gb2JqW2tleV07XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gZXh0ZW5kRXhjbHVkZSAoKSB7XG4gICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cylcbiAgICAgICwgaSA9IDBcbiAgICAgICwgcmVzID0ge307XG5cbiAgICBmb3IgKDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgIGV4Y2x1ZGVQcm9wcyhyZXMsIGFyZ3NbaV0pO1xuICAgIH1cblxuICAgIHJldHVybiByZXM7XG4gIH07XG59O1xuXG4vKiFcbiAqIFByaW1hcnkgRXhwb3J0c1xuICovXG5cbm1vZHVsZS5leHBvcnRzID0gQXNzZXJ0aW9uRXJyb3I7XG5cbi8qKlxuICogIyMjIEFzc2VydGlvbkVycm9yXG4gKlxuICogQW4gZXh0ZW5zaW9uIG9mIHRoZSBKYXZhU2NyaXB0IGBFcnJvcmAgY29uc3RydWN0b3IgZm9yXG4gKiBhc3NlcnRpb24gYW5kIHZhbGlkYXRpb24gc2NlbmFyaW9zLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtZXNzYWdlXG4gKiBAcGFyYW0ge09iamVjdH0gcHJvcGVydGllcyB0byBpbmNsdWRlIChvcHRpb25hbClcbiAqIEBwYXJhbSB7Y2FsbGVlfSBzdGFydCBzdGFjayBmdW5jdGlvbiAob3B0aW9uYWwpXG4gKi9cblxuZnVuY3Rpb24gQXNzZXJ0aW9uRXJyb3IgKG1lc3NhZ2UsIF9wcm9wcywgc3NmKSB7XG4gIHZhciBleHRlbmQgPSBleGNsdWRlKCduYW1lJywgJ21lc3NhZ2UnLCAnc3RhY2snLCAnY29uc3RydWN0b3InLCAndG9KU09OJylcbiAgICAsIHByb3BzID0gZXh0ZW5kKF9wcm9wcyB8fCB7fSk7XG5cbiAgLy8gZGVmYXVsdCB2YWx1ZXNcbiAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZSB8fCAnVW5zcGVjaWZpZWQgQXNzZXJ0aW9uRXJyb3InO1xuICB0aGlzLnNob3dEaWZmID0gZmFsc2U7XG5cbiAgLy8gY29weSBmcm9tIHByb3BlcnRpZXNcbiAgZm9yICh2YXIga2V5IGluIHByb3BzKSB7XG4gICAgdGhpc1trZXldID0gcHJvcHNba2V5XTtcbiAgfVxuXG4gIC8vIGNhcHR1cmUgc3RhY2sgdHJhY2VcbiAgc3NmID0gc3NmIHx8IGFyZ3VtZW50cy5jYWxsZWU7XG4gIGlmIChzc2YgJiYgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UpIHtcbiAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBzc2YpO1xuICB9XG59XG5cbi8qIVxuICogSW5oZXJpdCBmcm9tIEVycm9yLnByb3RvdHlwZVxuICovXG5cbkFzc2VydGlvbkVycm9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXJyb3IucHJvdG90eXBlKTtcblxuLyohXG4gKiBTdGF0aWNhbGx5IHNldCBuYW1lXG4gKi9cblxuQXNzZXJ0aW9uRXJyb3IucHJvdG90eXBlLm5hbWUgPSAnQXNzZXJ0aW9uRXJyb3InO1xuXG4vKiFcbiAqIEVuc3VyZSBjb3JyZWN0IGNvbnN0cnVjdG9yXG4gKi9cblxuQXNzZXJ0aW9uRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gQXNzZXJ0aW9uRXJyb3I7XG5cbi8qKlxuICogQWxsb3cgZXJyb3JzIHRvIGJlIGNvbnZlcnRlZCB0byBKU09OIGZvciBzdGF0aWMgdHJhbnNmZXIuXG4gKlxuICogQHBhcmFtIHtCb29sZWFufSBpbmNsdWRlIHN0YWNrIChkZWZhdWx0OiBgdHJ1ZWApXG4gKiBAcmV0dXJuIHtPYmplY3R9IG9iamVjdCB0aGF0IGNhbiBiZSBgSlNPTi5zdHJpbmdpZnlgXG4gKi9cblxuQXNzZXJ0aW9uRXJyb3IucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIChzdGFjaykge1xuICB2YXIgZXh0ZW5kID0gZXhjbHVkZSgnY29uc3RydWN0b3InLCAndG9KU09OJywgJ3N0YWNrJylcbiAgICAsIHByb3BzID0gZXh0ZW5kKHsgbmFtZTogdGhpcy5uYW1lIH0sIHRoaXMpO1xuXG4gIC8vIGluY2x1ZGUgc3RhY2sgaWYgZXhpc3RzIGFuZCBub3QgdHVybmVkIG9mZlxuICBpZiAoZmFsc2UgIT09IHN0YWNrICYmIHRoaXMuc3RhY2spIHtcbiAgICBwcm9wcy5zdGFjayA9IHRoaXMuc3RhY2s7XG4gIH1cblxuICByZXR1cm4gcHJvcHM7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL2xpYi9lcWwnKTtcbiIsIi8qIVxuICogZGVlcC1lcWxcbiAqIENvcHlyaWdodChjKSAyMDEzIEpha2UgTHVlciA8amFrZUBhbG9naWNhbHBhcmFkb3guY29tPlxuICogTUlUIExpY2Vuc2VkXG4gKi9cblxuLyohXG4gKiBNb2R1bGUgZGVwZW5kZW5jaWVzXG4gKi9cblxudmFyIHR5cGUgPSByZXF1aXJlKCd0eXBlLWRldGVjdCcpO1xuXG4vKiFcbiAqIEJ1ZmZlci5pc0J1ZmZlciBicm93c2VyIHNoaW1cbiAqL1xuXG52YXIgQnVmZmVyO1xudHJ5IHsgQnVmZmVyID0gcmVxdWlyZSgnYnVmZmVyJykuQnVmZmVyOyB9XG5jYXRjaChleCkge1xuICBCdWZmZXIgPSB7fTtcbiAgQnVmZmVyLmlzQnVmZmVyID0gZnVuY3Rpb24oKSB7IHJldHVybiBmYWxzZTsgfVxufVxuXG4vKiFcbiAqIFByaW1hcnkgRXhwb3J0XG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBkZWVwRXF1YWw7XG5cbi8qKlxuICogQXNzZXJ0IHN1cGVyLXN0cmljdCAoZWdhbCkgZXF1YWxpdHkgYmV0d2VlblxuICogdHdvIG9iamVjdHMgb2YgYW55IHR5cGUuXG4gKlxuICogQHBhcmFtIHtNaXhlZH0gYVxuICogQHBhcmFtIHtNaXhlZH0gYlxuICogQHBhcmFtIHtBcnJheX0gbWVtb2lzZWQgKG9wdGlvbmFsKVxuICogQHJldHVybiB7Qm9vbGVhbn0gZXF1YWwgbWF0Y2hcbiAqL1xuXG5mdW5jdGlvbiBkZWVwRXF1YWwoYSwgYiwgbSkge1xuICBpZiAoc2FtZVZhbHVlKGEsIGIpKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSBpZiAoJ2RhdGUnID09PSB0eXBlKGEpKSB7XG4gICAgcmV0dXJuIGRhdGVFcXVhbChhLCBiKTtcbiAgfSBlbHNlIGlmICgncmVnZXhwJyA9PT0gdHlwZShhKSkge1xuICAgIHJldHVybiByZWdleHBFcXVhbChhLCBiKTtcbiAgfSBlbHNlIGlmIChCdWZmZXIuaXNCdWZmZXIoYSkpIHtcbiAgICByZXR1cm4gYnVmZmVyRXF1YWwoYSwgYik7XG4gIH0gZWxzZSBpZiAoJ2FyZ3VtZW50cycgPT09IHR5cGUoYSkpIHtcbiAgICByZXR1cm4gYXJndW1lbnRzRXF1YWwoYSwgYiwgbSk7XG4gIH0gZWxzZSBpZiAoIXR5cGVFcXVhbChhLCBiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfSBlbHNlIGlmICgoJ29iamVjdCcgIT09IHR5cGUoYSkgJiYgJ29iamVjdCcgIT09IHR5cGUoYikpXG4gICYmICgnYXJyYXknICE9PSB0eXBlKGEpICYmICdhcnJheScgIT09IHR5cGUoYikpKSB7XG4gICAgcmV0dXJuIHNhbWVWYWx1ZShhLCBiKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gb2JqZWN0RXF1YWwoYSwgYiwgbSk7XG4gIH1cbn1cblxuLyohXG4gKiBTdHJpY3QgKGVnYWwpIGVxdWFsaXR5IHRlc3QuIEVuc3VyZXMgdGhhdCBOYU4gYWx3YXlzXG4gKiBlcXVhbHMgTmFOIGFuZCBgLTBgIGRvZXMgbm90IGVxdWFsIGArMGAuXG4gKlxuICogQHBhcmFtIHtNaXhlZH0gYVxuICogQHBhcmFtIHtNaXhlZH0gYlxuICogQHJldHVybiB7Qm9vbGVhbn0gZXF1YWwgbWF0Y2hcbiAqL1xuXG5mdW5jdGlvbiBzYW1lVmFsdWUoYSwgYikge1xuICBpZiAoYSA9PT0gYikgcmV0dXJuIGEgIT09IDAgfHwgMSAvIGEgPT09IDEgLyBiO1xuICByZXR1cm4gYSAhPT0gYSAmJiBiICE9PSBiO1xufVxuXG4vKiFcbiAqIENvbXBhcmUgdGhlIHR5cGVzIG9mIHR3byBnaXZlbiBvYmplY3RzIGFuZFxuICogcmV0dXJuIGlmIHRoZXkgYXJlIGVxdWFsLiBOb3RlIHRoYXQgYW4gQXJyYXlcbiAqIGhhcyBhIHR5cGUgb2YgYGFycmF5YCAobm90IGBvYmplY3RgKSBhbmQgYXJndW1lbnRzXG4gKiBoYXZlIGEgdHlwZSBvZiBgYXJndW1lbnRzYCAobm90IGBhcnJheWAvYG9iamVjdGApLlxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IGFcbiAqIEBwYXJhbSB7TWl4ZWR9IGJcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHJlc3VsdFxuICovXG5cbmZ1bmN0aW9uIHR5cGVFcXVhbChhLCBiKSB7XG4gIHJldHVybiB0eXBlKGEpID09PSB0eXBlKGIpO1xufVxuXG4vKiFcbiAqIENvbXBhcmUgdHdvIERhdGUgb2JqZWN0cyBieSBhc3NlcnRpbmcgdGhhdFxuICogdGhlIHRpbWUgdmFsdWVzIGFyZSBlcXVhbCB1c2luZyBgc2F2ZVZhbHVlYC5cbiAqXG4gKiBAcGFyYW0ge0RhdGV9IGFcbiAqIEBwYXJhbSB7RGF0ZX0gYlxuICogQHJldHVybiB7Qm9vbGVhbn0gcmVzdWx0XG4gKi9cblxuZnVuY3Rpb24gZGF0ZUVxdWFsKGEsIGIpIHtcbiAgaWYgKCdkYXRlJyAhPT0gdHlwZShiKSkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gc2FtZVZhbHVlKGEuZ2V0VGltZSgpLCBiLmdldFRpbWUoKSk7XG59XG5cbi8qIVxuICogQ29tcGFyZSB0d28gcmVndWxhciBleHByZXNzaW9ucyBieSBjb252ZXJ0aW5nIHRoZW1cbiAqIHRvIHN0cmluZyBhbmQgY2hlY2tpbmcgZm9yIGBzYW1lVmFsdWVgLlxuICpcbiAqIEBwYXJhbSB7UmVnRXhwfSBhXG4gKiBAcGFyYW0ge1JlZ0V4cH0gYlxuICogQHJldHVybiB7Qm9vbGVhbn0gcmVzdWx0XG4gKi9cblxuZnVuY3Rpb24gcmVnZXhwRXF1YWwoYSwgYikge1xuICBpZiAoJ3JlZ2V4cCcgIT09IHR5cGUoYikpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHNhbWVWYWx1ZShhLnRvU3RyaW5nKCksIGIudG9TdHJpbmcoKSk7XG59XG5cbi8qIVxuICogQXNzZXJ0IGRlZXAgZXF1YWxpdHkgb2YgdHdvIGBhcmd1bWVudHNgIG9iamVjdHMuXG4gKiBVbmZvcnR1bmF0ZWx5LCB0aGVzZSBtdXN0IGJlIHNsaWNlZCB0byBhcnJheXNcbiAqIHByaW9yIHRvIHRlc3QgdG8gZW5zdXJlIG5vIGJhZCBiZWhhdmlvci5cbiAqXG4gKiBAcGFyYW0ge0FyZ3VtZW50c30gYVxuICogQHBhcmFtIHtBcmd1bWVudHN9IGJcbiAqIEBwYXJhbSB7QXJyYXl9IG1lbW9pemUgKG9wdGlvbmFsKVxuICogQHJldHVybiB7Qm9vbGVhbn0gcmVzdWx0XG4gKi9cblxuZnVuY3Rpb24gYXJndW1lbnRzRXF1YWwoYSwgYiwgbSkge1xuICBpZiAoJ2FyZ3VtZW50cycgIT09IHR5cGUoYikpIHJldHVybiBmYWxzZTtcbiAgYSA9IFtdLnNsaWNlLmNhbGwoYSk7XG4gIGIgPSBbXS5zbGljZS5jYWxsKGIpO1xuICByZXR1cm4gZGVlcEVxdWFsKGEsIGIsIG0pO1xufVxuXG4vKiFcbiAqIEdldCBlbnVtZXJhYmxlIHByb3BlcnRpZXMgb2YgYSBnaXZlbiBvYmplY3QuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IGFcbiAqIEByZXR1cm4ge0FycmF5fSBwcm9wZXJ0eSBuYW1lc1xuICovXG5cbmZ1bmN0aW9uIGVudW1lcmFibGUoYSkge1xuICB2YXIgcmVzID0gW107XG4gIGZvciAodmFyIGtleSBpbiBhKSByZXMucHVzaChrZXkpO1xuICByZXR1cm4gcmVzO1xufVxuXG4vKiFcbiAqIFNpbXBsZSBlcXVhbGl0eSBmb3IgZmxhdCBpdGVyYWJsZSBvYmplY3RzXG4gKiBzdWNoIGFzIEFycmF5cyBvciBOb2RlLmpzIGJ1ZmZlcnMuXG4gKlxuICogQHBhcmFtIHtJdGVyYWJsZX0gYVxuICogQHBhcmFtIHtJdGVyYWJsZX0gYlxuICogQHJldHVybiB7Qm9vbGVhbn0gcmVzdWx0XG4gKi9cblxuZnVuY3Rpb24gaXRlcmFibGVFcXVhbChhLCBiKSB7XG4gIGlmIChhLmxlbmd0aCAhPT0gIGIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG5cbiAgdmFyIGkgPSAwO1xuICB2YXIgbWF0Y2ggPSB0cnVlO1xuXG4gIGZvciAoOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgIGlmIChhW2ldICE9PSBiW2ldKSB7XG4gICAgICBtYXRjaCA9IGZhbHNlO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG1hdGNoO1xufVxuXG4vKiFcbiAqIEV4dGVuc2lvbiB0byBgaXRlcmFibGVFcXVhbGAgc3BlY2lmaWNhbGx5XG4gKiBmb3IgTm9kZS5qcyBCdWZmZXJzLlxuICpcbiAqIEBwYXJhbSB7QnVmZmVyfSBhXG4gKiBAcGFyYW0ge01peGVkfSBiXG4gKiBAcmV0dXJuIHtCb29sZWFufSByZXN1bHRcbiAqL1xuXG5mdW5jdGlvbiBidWZmZXJFcXVhbChhLCBiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGIpKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiBpdGVyYWJsZUVxdWFsKGEsIGIpO1xufVxuXG4vKiFcbiAqIEJsb2NrIGZvciBgb2JqZWN0RXF1YWxgIGVuc3VyaW5nIG5vbi1leGlzdGluZ1xuICogdmFsdWVzIGRvbid0IGdldCBpbi5cbiAqXG4gKiBAcGFyYW0ge01peGVkfSBvYmplY3RcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHJlc3VsdFxuICovXG5cbmZ1bmN0aW9uIGlzVmFsdWUoYSkge1xuICByZXR1cm4gYSAhPT0gbnVsbCAmJiBhICE9PSB1bmRlZmluZWQ7XG59XG5cbi8qIVxuICogUmVjdXJzaXZlbHkgY2hlY2sgdGhlIGVxdWFsaXR5IG9mIHR3byBvYmplY3RzLlxuICogT25jZSBiYXNpYyBzYW1lbmVzcyBoYXMgYmVlbiBlc3RhYmxpc2hlZCBpdCB3aWxsXG4gKiBkZWZlciB0byBgZGVlcEVxdWFsYCBmb3IgZWFjaCBlbnVtZXJhYmxlIGtleVxuICogaW4gdGhlIG9iamVjdC5cbiAqXG4gKiBAcGFyYW0ge01peGVkfSBhXG4gKiBAcGFyYW0ge01peGVkfSBiXG4gKiBAcmV0dXJuIHtCb29sZWFufSByZXN1bHRcbiAqL1xuXG5mdW5jdGlvbiBvYmplY3RFcXVhbChhLCBiLCBtKSB7XG4gIGlmICghaXNWYWx1ZShhKSB8fCAhaXNWYWx1ZShiKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChhLnByb3RvdHlwZSAhPT0gYi5wcm90b3R5cGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB2YXIgaTtcbiAgaWYgKG0pIHtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbS5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKChtW2ldWzBdID09PSBhICYmIG1baV1bMV0gPT09IGIpXG4gICAgICB8fCAgKG1baV1bMF0gPT09IGIgJiYgbVtpXVsxXSA9PT0gYSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIG0gPSBbXTtcbiAgfVxuXG4gIHRyeSB7XG4gICAgdmFyIGthID0gZW51bWVyYWJsZShhKTtcbiAgICB2YXIga2IgPSBlbnVtZXJhYmxlKGIpO1xuICB9IGNhdGNoIChleCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGthLnNvcnQoKTtcbiAga2Iuc29ydCgpO1xuXG4gIGlmICghaXRlcmFibGVFcXVhbChrYSwga2IpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbS5wdXNoKFsgYSwgYiBdKTtcblxuICB2YXIga2V5O1xuICBmb3IgKGkgPSBrYS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGtleSA9IGthW2ldO1xuICAgIGlmICghZGVlcEVxdWFsKGFba2V5XSwgYltrZXldLCBtKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL2xpYi90eXBlJyk7XG4iLCIvKiFcbiAqIHR5cGUtZGV0ZWN0XG4gKiBDb3B5cmlnaHQoYykgMjAxMyBqYWtlIGx1ZXIgPGpha2VAYWxvZ2ljYWxwYXJhZG94LmNvbT5cbiAqIE1JVCBMaWNlbnNlZFxuICovXG5cbi8qIVxuICogUHJpbWFyeSBFeHBvcnRzXG4gKi9cblxudmFyIGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IGdldFR5cGU7XG5cbi8qIVxuICogRGV0ZWN0YWJsZSBqYXZhc2NyaXB0IG5hdGl2ZXNcbiAqL1xuXG52YXIgbmF0aXZlcyA9IHtcbiAgICAnW29iamVjdCBBcnJheV0nOiAnYXJyYXknXG4gICwgJ1tvYmplY3QgUmVnRXhwXSc6ICdyZWdleHAnXG4gICwgJ1tvYmplY3QgRnVuY3Rpb25dJzogJ2Z1bmN0aW9uJ1xuICAsICdbb2JqZWN0IEFyZ3VtZW50c10nOiAnYXJndW1lbnRzJ1xuICAsICdbb2JqZWN0IERhdGVdJzogJ2RhdGUnXG59O1xuXG4vKipcbiAqICMjIyB0eXBlT2YgKG9iailcbiAqXG4gKiBVc2Ugc2V2ZXJhbCBkaWZmZXJlbnQgdGVjaG5pcXVlcyB0byBkZXRlcm1pbmVcbiAqIHRoZSB0eXBlIG9mIG9iamVjdCBiZWluZyB0ZXN0ZWQuXG4gKlxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IG9iamVjdFxuICogQHJldHVybiB7U3RyaW5nfSBvYmplY3QgdHlwZVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5mdW5jdGlvbiBnZXRUeXBlIChvYmopIHtcbiAgdmFyIHN0ciA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmopO1xuICBpZiAobmF0aXZlc1tzdHJdKSByZXR1cm4gbmF0aXZlc1tzdHJdO1xuICBpZiAob2JqID09PSBudWxsKSByZXR1cm4gJ251bGwnO1xuICBpZiAob2JqID09PSB1bmRlZmluZWQpIHJldHVybiAndW5kZWZpbmVkJztcbiAgaWYgKG9iaiA9PT0gT2JqZWN0KG9iaikpIHJldHVybiAnb2JqZWN0JztcbiAgcmV0dXJuIHR5cGVvZiBvYmo7XG59XG5cbmV4cG9ydHMuTGlicmFyeSA9IExpYnJhcnk7XG5cbi8qKlxuICogIyMjIExpYnJhcnlcbiAqXG4gKiBDcmVhdGUgYSByZXBvc2l0b3J5IGZvciBjdXN0b20gdHlwZSBkZXRlY3Rpb24uXG4gKlxuICogYGBganNcbiAqIHZhciBsaWIgPSBuZXcgdHlwZS5MaWJyYXJ5O1xuICogYGBgXG4gKlxuICovXG5cbmZ1bmN0aW9uIExpYnJhcnkgKCkge1xuICB0aGlzLnRlc3RzID0ge307XG59XG5cbi8qKlxuICogIyMjIyAub2YgKG9iailcbiAqXG4gKiBFeHBvc2UgcmVwbGFjZW1lbnQgYHR5cGVvZmAgZGV0ZWN0aW9uIHRvIHRoZSBsaWJyYXJ5LlxuICpcbiAqIGBgYGpzXG4gKiBpZiAoJ3N0cmluZycgPT09IGxpYi5vZignaGVsbG8gd29ybGQnKSkge1xuICogICAvLyAuLi5cbiAqIH1cbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IG9iamVjdCB0byB0ZXN0XG4gKiBAcmV0dXJuIHtTdHJpbmd9IHR5cGVcbiAqL1xuXG5MaWJyYXJ5LnByb3RvdHlwZS5vZiA9IGdldFR5cGU7XG5cbi8qKlxuICogIyMjIyAuZGVmaW5lICh0eXBlLCB0ZXN0KVxuICpcbiAqIEFkZCBhIHRlc3QgdG8gZm9yIHRoZSBgLnRlc3QoKWAgYXNzZXJ0aW9uLlxuICpcbiAqIENhbiBiZSBkZWZpbmVkIGFzIGEgcmVndWxhciBleHByZXNzaW9uOlxuICpcbiAqIGBgYGpzXG4gKiBsaWIuZGVmaW5lKCdpbnQnLCAvXlswLTldKyQvKTtcbiAqIGBgYFxuICpcbiAqIC4uLiBvciBhcyBhIGZ1bmN0aW9uOlxuICpcbiAqIGBgYGpzXG4gKiBsaWIuZGVmaW5lKCdibG4nLCBmdW5jdGlvbiAob2JqKSB7XG4gKiAgIGlmICgnYm9vbGVhbicgPT09IGxpYi5vZihvYmopKSByZXR1cm4gdHJ1ZTtcbiAqICAgdmFyIGJsbnMgPSBbICd5ZXMnLCAnbm8nLCAndHJ1ZScsICdmYWxzZScsIDEsIDAgXTtcbiAqICAgaWYgKCdzdHJpbmcnID09PSBsaWIub2Yob2JqKSkgb2JqID0gb2JqLnRvTG93ZXJDYXNlKCk7XG4gKiAgIHJldHVybiAhISB+Ymxucy5pbmRleE9mKG9iaik7XG4gKiB9KTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gKiBAcGFyYW0ge1JlZ0V4cHxGdW5jdGlvbn0gdGVzdFxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5MaWJyYXJ5LnByb3RvdHlwZS5kZWZpbmUgPSBmdW5jdGlvbiAodHlwZSwgdGVzdCkge1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgcmV0dXJuIHRoaXMudGVzdHNbdHlwZV07XG4gIHRoaXMudGVzdHNbdHlwZV0gPSB0ZXN0O1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogIyMjIyAudGVzdCAob2JqLCB0ZXN0KVxuICpcbiAqIEFzc2VydCB0aGF0IGFuIG9iamVjdCBpcyBvZiB0eXBlLiBXaWxsIGZpcnN0XG4gKiBjaGVjayBuYXRpdmVzLCBhbmQgaWYgdGhhdCBkb2VzIG5vdCBwYXNzIGl0IHdpbGxcbiAqIHVzZSB0aGUgdXNlciBkZWZpbmVkIGN1c3RvbSB0ZXN0cy5cbiAqXG4gKiBgYGBqc1xuICogYXNzZXJ0KGxpYi50ZXN0KCcxJywgJ2ludCcpKTtcbiAqIGFzc2VydChsaWIudGVzdCgneWVzJywgJ2JsbicpKTtcbiAqIGBgYFxuICpcbiAqIEBwYXJhbSB7TWl4ZWR9IG9iamVjdFxuICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAqIEByZXR1cm4ge0Jvb2xlYW59IHJlc3VsdFxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5MaWJyYXJ5LnByb3RvdHlwZS50ZXN0ID0gZnVuY3Rpb24gKG9iaiwgdHlwZSkge1xuICBpZiAodHlwZSA9PT0gZ2V0VHlwZShvYmopKSByZXR1cm4gdHJ1ZTtcbiAgdmFyIHRlc3QgPSB0aGlzLnRlc3RzW3R5cGVdO1xuXG4gIGlmICh0ZXN0ICYmICdyZWdleHAnID09PSBnZXRUeXBlKHRlc3QpKSB7XG4gICAgcmV0dXJuIHRlc3QudGVzdChvYmopO1xuICB9IGVsc2UgaWYgKHRlc3QgJiYgJ2Z1bmN0aW9uJyA9PT0gZ2V0VHlwZSh0ZXN0KSkge1xuICAgIHJldHVybiB0ZXN0KG9iaik7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IFJlZmVyZW5jZUVycm9yKCdUeXBlIHRlc3QgXCInICsgdHlwZSArICdcIiBub3QgZGVmaW5lZCBvciBpbnZhbGlkLicpO1xuICB9XG59O1xuIiwiLyohXG4gKiBUaGUgYnVmZmVyIG1vZHVsZSBmcm9tIG5vZGUuanMsIGZvciB0aGUgYnJvd3Nlci5cbiAqXG4gKiBAYXV0aG9yICAgRmVyb3NzIEFib3VraGFkaWplaCA8ZmVyb3NzQGZlcm9zcy5vcmc+IDxodHRwOi8vZmVyb3NzLm9yZz5cbiAqIEBsaWNlbnNlICBNSVRcbiAqL1xuXG52YXIgYmFzZTY0ID0gcmVxdWlyZSgnYmFzZTY0LWpzJylcbnZhciBpZWVlNzU0ID0gcmVxdWlyZSgnaWVlZTc1NCcpXG5cbmV4cG9ydHMuQnVmZmVyID0gQnVmZmVyXG5leHBvcnRzLlNsb3dCdWZmZXIgPSBCdWZmZXJcbmV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVMgPSA1MFxuQnVmZmVyLnBvb2xTaXplID0gODE5MlxuXG4vKipcbiAqIElmIGBCdWZmZXIuX3VzZVR5cGVkQXJyYXlzYDpcbiAqICAgPT09IHRydWUgICAgVXNlIFVpbnQ4QXJyYXkgaW1wbGVtZW50YXRpb24gKGZhc3Rlc3QpXG4gKiAgID09PSBmYWxzZSAgIFVzZSBPYmplY3QgaW1wbGVtZW50YXRpb24gKGNvbXBhdGlibGUgZG93biB0byBJRTYpXG4gKi9cbkJ1ZmZlci5fdXNlVHlwZWRBcnJheXMgPSAoZnVuY3Rpb24gKCkge1xuICAvLyBEZXRlY3QgaWYgYnJvd3NlciBzdXBwb3J0cyBUeXBlZCBBcnJheXMuIFN1cHBvcnRlZCBicm93c2VycyBhcmUgSUUgMTArLCBGaXJlZm94IDQrLFxuICAvLyBDaHJvbWUgNyssIFNhZmFyaSA1LjErLCBPcGVyYSAxMS42KywgaU9TIDQuMisuIElmIHRoZSBicm93c2VyIGRvZXMgbm90IHN1cHBvcnQgYWRkaW5nXG4gIC8vIHByb3BlcnRpZXMgdG8gYFVpbnQ4QXJyYXlgIGluc3RhbmNlcywgdGhlbiB0aGF0J3MgdGhlIHNhbWUgYXMgbm8gYFVpbnQ4QXJyYXlgIHN1cHBvcnRcbiAgLy8gYmVjYXVzZSB3ZSBuZWVkIHRvIGJlIGFibGUgdG8gYWRkIGFsbCB0aGUgbm9kZSBCdWZmZXIgQVBJIG1ldGhvZHMuIFRoaXMgaXMgYW4gaXNzdWVcbiAgLy8gaW4gRmlyZWZveCA0LTI5LiBOb3cgZml4ZWQ6IGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY5NTQzOFxuICB0cnkge1xuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoMClcbiAgICB2YXIgYXJyID0gbmV3IFVpbnQ4QXJyYXkoYnVmKVxuICAgIGFyci5mb28gPSBmdW5jdGlvbiAoKSB7IHJldHVybiA0MiB9XG4gICAgcmV0dXJuIDQyID09PSBhcnIuZm9vKCkgJiZcbiAgICAgICAgdHlwZW9mIGFyci5zdWJhcnJheSA9PT0gJ2Z1bmN0aW9uJyAvLyBDaHJvbWUgOS0xMCBsYWNrIGBzdWJhcnJheWBcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZVxuICB9XG59KSgpXG5cbi8qKlxuICogQ2xhc3M6IEJ1ZmZlclxuICogPT09PT09PT09PT09PVxuICpcbiAqIFRoZSBCdWZmZXIgY29uc3RydWN0b3IgcmV0dXJucyBpbnN0YW5jZXMgb2YgYFVpbnQ4QXJyYXlgIHRoYXQgYXJlIGF1Z21lbnRlZFxuICogd2l0aCBmdW5jdGlvbiBwcm9wZXJ0aWVzIGZvciBhbGwgdGhlIG5vZGUgYEJ1ZmZlcmAgQVBJIGZ1bmN0aW9ucy4gV2UgdXNlXG4gKiBgVWludDhBcnJheWAgc28gdGhhdCBzcXVhcmUgYnJhY2tldCBub3RhdGlvbiB3b3JrcyBhcyBleHBlY3RlZCAtLSBpdCByZXR1cm5zXG4gKiBhIHNpbmdsZSBvY3RldC5cbiAqXG4gKiBCeSBhdWdtZW50aW5nIHRoZSBpbnN0YW5jZXMsIHdlIGNhbiBhdm9pZCBtb2RpZnlpbmcgdGhlIGBVaW50OEFycmF5YFxuICogcHJvdG90eXBlLlxuICovXG5mdW5jdGlvbiBCdWZmZXIgKHN1YmplY3QsIGVuY29kaW5nLCBub1plcm8pIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEJ1ZmZlcikpXG4gICAgcmV0dXJuIG5ldyBCdWZmZXIoc3ViamVjdCwgZW5jb2RpbmcsIG5vWmVybylcblxuICB2YXIgdHlwZSA9IHR5cGVvZiBzdWJqZWN0XG5cbiAgLy8gV29ya2Fyb3VuZDogbm9kZSdzIGJhc2U2NCBpbXBsZW1lbnRhdGlvbiBhbGxvd3MgZm9yIG5vbi1wYWRkZWQgc3RyaW5nc1xuICAvLyB3aGlsZSBiYXNlNjQtanMgZG9lcyBub3QuXG4gIGlmIChlbmNvZGluZyA9PT0gJ2Jhc2U2NCcgJiYgdHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICBzdWJqZWN0ID0gc3RyaW5ndHJpbShzdWJqZWN0KVxuICAgIHdoaWxlIChzdWJqZWN0Lmxlbmd0aCAlIDQgIT09IDApIHtcbiAgICAgIHN1YmplY3QgPSBzdWJqZWN0ICsgJz0nXG4gICAgfVxuICB9XG5cbiAgLy8gRmluZCB0aGUgbGVuZ3RoXG4gIHZhciBsZW5ndGhcbiAgaWYgKHR5cGUgPT09ICdudW1iZXInKVxuICAgIGxlbmd0aCA9IGNvZXJjZShzdWJqZWN0KVxuICBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJylcbiAgICBsZW5ndGggPSBCdWZmZXIuYnl0ZUxlbmd0aChzdWJqZWN0LCBlbmNvZGluZylcbiAgZWxzZSBpZiAodHlwZSA9PT0gJ29iamVjdCcpXG4gICAgbGVuZ3RoID0gY29lcmNlKHN1YmplY3QubGVuZ3RoKSAvLyBhc3N1bWUgdGhhdCBvYmplY3QgaXMgYXJyYXktbGlrZVxuICBlbHNlXG4gICAgdGhyb3cgbmV3IEVycm9yKCdGaXJzdCBhcmd1bWVudCBuZWVkcyB0byBiZSBhIG51bWJlciwgYXJyYXkgb3Igc3RyaW5nLicpXG5cbiAgdmFyIGJ1ZlxuICBpZiAoQnVmZmVyLl91c2VUeXBlZEFycmF5cykge1xuICAgIC8vIFByZWZlcnJlZDogUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2UgZm9yIGJlc3QgcGVyZm9ybWFuY2VcbiAgICBidWYgPSBCdWZmZXIuX2F1Z21lbnQobmV3IFVpbnQ4QXJyYXkobGVuZ3RoKSlcbiAgfSBlbHNlIHtcbiAgICAvLyBGYWxsYmFjazogUmV0dXJuIFRISVMgaW5zdGFuY2Ugb2YgQnVmZmVyIChjcmVhdGVkIGJ5IGBuZXdgKVxuICAgIGJ1ZiA9IHRoaXNcbiAgICBidWYubGVuZ3RoID0gbGVuZ3RoXG4gICAgYnVmLl9pc0J1ZmZlciA9IHRydWVcbiAgfVxuXG4gIHZhciBpXG4gIGlmIChCdWZmZXIuX3VzZVR5cGVkQXJyYXlzICYmIHR5cGVvZiBzdWJqZWN0LmJ5dGVMZW5ndGggPT09ICdudW1iZXInKSB7XG4gICAgLy8gU3BlZWQgb3B0aW1pemF0aW9uIC0tIHVzZSBzZXQgaWYgd2UncmUgY29weWluZyBmcm9tIGEgdHlwZWQgYXJyYXlcbiAgICBidWYuX3NldChzdWJqZWN0KVxuICB9IGVsc2UgaWYgKGlzQXJyYXlpc2goc3ViamVjdCkpIHtcbiAgICAvLyBUcmVhdCBhcnJheS1pc2ggb2JqZWN0cyBhcyBhIGJ5dGUgYXJyYXlcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChCdWZmZXIuaXNCdWZmZXIoc3ViamVjdCkpXG4gICAgICAgIGJ1ZltpXSA9IHN1YmplY3QucmVhZFVJbnQ4KGkpXG4gICAgICBlbHNlXG4gICAgICAgIGJ1ZltpXSA9IHN1YmplY3RbaV1cbiAgICB9XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICBidWYud3JpdGUoc3ViamVjdCwgMCwgZW5jb2RpbmcpXG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ251bWJlcicgJiYgIUJ1ZmZlci5fdXNlVHlwZWRBcnJheXMgJiYgIW5vWmVybykge1xuICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgYnVmW2ldID0gMFxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBidWZcbn1cblxuLy8gU1RBVElDIE1FVEhPRFNcbi8vID09PT09PT09PT09PT09XG5cbkJ1ZmZlci5pc0VuY29kaW5nID0gZnVuY3Rpb24gKGVuY29kaW5nKSB7XG4gIHN3aXRjaCAoU3RyaW5nKGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpKSB7XG4gICAgY2FzZSAnaGV4JzpcbiAgICBjYXNlICd1dGY4JzpcbiAgICBjYXNlICd1dGYtOCc6XG4gICAgY2FzZSAnYXNjaWknOlxuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgY2FzZSAnYmFzZTY0JzpcbiAgICBjYXNlICdyYXcnOlxuICAgIGNhc2UgJ3VjczInOlxuICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICBjYXNlICd1dGYxNmxlJzpcbiAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5CdWZmZXIuaXNCdWZmZXIgPSBmdW5jdGlvbiAoYikge1xuICByZXR1cm4gISEoYiAhPT0gbnVsbCAmJiBiICE9PSB1bmRlZmluZWQgJiYgYi5faXNCdWZmZXIpXG59XG5cbkJ1ZmZlci5ieXRlTGVuZ3RoID0gZnVuY3Rpb24gKHN0ciwgZW5jb2RpbmcpIHtcbiAgdmFyIHJldFxuICBzdHIgPSBzdHIgKyAnJ1xuICBzd2l0Y2ggKGVuY29kaW5nIHx8ICd1dGY4Jykge1xuICAgIGNhc2UgJ2hleCc6XG4gICAgICByZXQgPSBzdHIubGVuZ3RoIC8gMlxuICAgICAgYnJlYWtcbiAgICBjYXNlICd1dGY4JzpcbiAgICBjYXNlICd1dGYtOCc6XG4gICAgICByZXQgPSB1dGY4VG9CeXRlcyhzdHIpLmxlbmd0aFxuICAgICAgYnJlYWtcbiAgICBjYXNlICdhc2NpaSc6XG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICBjYXNlICdyYXcnOlxuICAgICAgcmV0ID0gc3RyLmxlbmd0aFxuICAgICAgYnJlYWtcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgcmV0ID0gYmFzZTY0VG9CeXRlcyhzdHIpLmxlbmd0aFxuICAgICAgYnJlYWtcbiAgICBjYXNlICd1Y3MyJzpcbiAgICBjYXNlICd1Y3MtMic6XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgcmV0ID0gc3RyLmxlbmd0aCAqIDJcbiAgICAgIGJyZWFrXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcignVW5rbm93biBlbmNvZGluZycpXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5CdWZmZXIuY29uY2F0ID0gZnVuY3Rpb24gKGxpc3QsIHRvdGFsTGVuZ3RoKSB7XG4gIGFzc2VydChpc0FycmF5KGxpc3QpLCAnVXNhZ2U6IEJ1ZmZlci5jb25jYXQobGlzdCwgW3RvdGFsTGVuZ3RoXSlcXG4nICtcbiAgICAgICdsaXN0IHNob3VsZCBiZSBhbiBBcnJheS4nKVxuXG4gIGlmIChsaXN0Lmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBuZXcgQnVmZmVyKDApXG4gIH0gZWxzZSBpZiAobGlzdC5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gbGlzdFswXVxuICB9XG5cbiAgdmFyIGlcbiAgaWYgKHR5cGVvZiB0b3RhbExlbmd0aCAhPT0gJ251bWJlcicpIHtcbiAgICB0b3RhbExlbmd0aCA9IDBcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgdG90YWxMZW5ndGggKz0gbGlzdFtpXS5sZW5ndGhcbiAgICB9XG4gIH1cblxuICB2YXIgYnVmID0gbmV3IEJ1ZmZlcih0b3RhbExlbmd0aClcbiAgdmFyIHBvcyA9IDBcbiAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgaXRlbSA9IGxpc3RbaV1cbiAgICBpdGVtLmNvcHkoYnVmLCBwb3MpXG4gICAgcG9zICs9IGl0ZW0ubGVuZ3RoXG4gIH1cbiAgcmV0dXJuIGJ1ZlxufVxuXG4vLyBCVUZGRVIgSU5TVEFOQ0UgTUVUSE9EU1xuLy8gPT09PT09PT09PT09PT09PT09PT09PT1cblxuZnVuY3Rpb24gX2hleFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgb2Zmc2V0ID0gTnVtYmVyKG9mZnNldCkgfHwgMFxuICB2YXIgcmVtYWluaW5nID0gYnVmLmxlbmd0aCAtIG9mZnNldFxuICBpZiAoIWxlbmd0aCkge1xuICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICB9IGVsc2Uge1xuICAgIGxlbmd0aCA9IE51bWJlcihsZW5ndGgpXG4gICAgaWYgKGxlbmd0aCA+IHJlbWFpbmluZykge1xuICAgICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gICAgfVxuICB9XG5cbiAgLy8gbXVzdCBiZSBhbiBldmVuIG51bWJlciBvZiBkaWdpdHNcbiAgdmFyIHN0ckxlbiA9IHN0cmluZy5sZW5ndGhcbiAgYXNzZXJ0KHN0ckxlbiAlIDIgPT09IDAsICdJbnZhbGlkIGhleCBzdHJpbmcnKVxuXG4gIGlmIChsZW5ndGggPiBzdHJMZW4gLyAyKSB7XG4gICAgbGVuZ3RoID0gc3RyTGVuIC8gMlxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgYnl0ZSA9IHBhcnNlSW50KHN0cmluZy5zdWJzdHIoaSAqIDIsIDIpLCAxNilcbiAgICBhc3NlcnQoIWlzTmFOKGJ5dGUpLCAnSW52YWxpZCBoZXggc3RyaW5nJylcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSBieXRlXG4gIH1cbiAgQnVmZmVyLl9jaGFyc1dyaXR0ZW4gPSBpICogMlxuICByZXR1cm4gaVxufVxuXG5mdW5jdGlvbiBfdXRmOFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgdmFyIGNoYXJzV3JpdHRlbiA9IEJ1ZmZlci5fY2hhcnNXcml0dGVuID1cbiAgICBibGl0QnVmZmVyKHV0ZjhUb0J5dGVzKHN0cmluZyksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG4gIHJldHVybiBjaGFyc1dyaXR0ZW5cbn1cblxuZnVuY3Rpb24gX2FzY2lpV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICB2YXIgY2hhcnNXcml0dGVuID0gQnVmZmVyLl9jaGFyc1dyaXR0ZW4gPVxuICAgIGJsaXRCdWZmZXIoYXNjaWlUb0J5dGVzKHN0cmluZyksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG4gIHJldHVybiBjaGFyc1dyaXR0ZW5cbn1cblxuZnVuY3Rpb24gX2JpbmFyeVdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIF9hc2NpaVdyaXRlKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gX2Jhc2U2NFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgdmFyIGNoYXJzV3JpdHRlbiA9IEJ1ZmZlci5fY2hhcnNXcml0dGVuID1cbiAgICBibGl0QnVmZmVyKGJhc2U2NFRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbiAgcmV0dXJuIGNoYXJzV3JpdHRlblxufVxuXG5mdW5jdGlvbiBfdXRmMTZsZVdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgdmFyIGNoYXJzV3JpdHRlbiA9IEJ1ZmZlci5fY2hhcnNXcml0dGVuID1cbiAgICBibGl0QnVmZmVyKHV0ZjE2bGVUb0J5dGVzKHN0cmluZyksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG4gIHJldHVybiBjaGFyc1dyaXR0ZW5cbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZSA9IGZ1bmN0aW9uIChzdHJpbmcsIG9mZnNldCwgbGVuZ3RoLCBlbmNvZGluZykge1xuICAvLyBTdXBwb3J0IGJvdGggKHN0cmluZywgb2Zmc2V0LCBsZW5ndGgsIGVuY29kaW5nKVxuICAvLyBhbmQgdGhlIGxlZ2FjeSAoc3RyaW5nLCBlbmNvZGluZywgb2Zmc2V0LCBsZW5ndGgpXG4gIGlmIChpc0Zpbml0ZShvZmZzZXQpKSB7XG4gICAgaWYgKCFpc0Zpbml0ZShsZW5ndGgpKSB7XG4gICAgICBlbmNvZGluZyA9IGxlbmd0aFxuICAgICAgbGVuZ3RoID0gdW5kZWZpbmVkXG4gICAgfVxuICB9IGVsc2UgeyAgLy8gbGVnYWN5XG4gICAgdmFyIHN3YXAgPSBlbmNvZGluZ1xuICAgIGVuY29kaW5nID0gb2Zmc2V0XG4gICAgb2Zmc2V0ID0gbGVuZ3RoXG4gICAgbGVuZ3RoID0gc3dhcFxuICB9XG5cbiAgb2Zmc2V0ID0gTnVtYmVyKG9mZnNldCkgfHwgMFxuICB2YXIgcmVtYWluaW5nID0gdGhpcy5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKCFsZW5ndGgpIHtcbiAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgfSBlbHNlIHtcbiAgICBsZW5ndGggPSBOdW1iZXIobGVuZ3RoKVxuICAgIGlmIChsZW5ndGggPiByZW1haW5pbmcpIHtcbiAgICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICAgIH1cbiAgfVxuICBlbmNvZGluZyA9IFN0cmluZyhlbmNvZGluZyB8fCAndXRmOCcpLnRvTG93ZXJDYXNlKClcblxuICB2YXIgcmV0XG4gIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgICAgcmV0ID0gX2hleFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgIHJldCA9IF91dGY4V3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnYXNjaWknOlxuICAgICAgcmV0ID0gX2FzY2lpV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgIHJldCA9IF9iaW5hcnlXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgcmV0ID0gX2Jhc2U2NFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ3VjczInOlxuICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICBjYXNlICd1dGYxNmxlJzpcbiAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICByZXQgPSBfdXRmMTZsZVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG4gICAgICBicmVha1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gZW5jb2RpbmcnKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIChlbmNvZGluZywgc3RhcnQsIGVuZCkge1xuICB2YXIgc2VsZiA9IHRoaXNcblxuICBlbmNvZGluZyA9IFN0cmluZyhlbmNvZGluZyB8fCAndXRmOCcpLnRvTG93ZXJDYXNlKClcbiAgc3RhcnQgPSBOdW1iZXIoc3RhcnQpIHx8IDBcbiAgZW5kID0gKGVuZCAhPT0gdW5kZWZpbmVkKVxuICAgID8gTnVtYmVyKGVuZClcbiAgICA6IGVuZCA9IHNlbGYubGVuZ3RoXG5cbiAgLy8gRmFzdHBhdGggZW1wdHkgc3RyaW5nc1xuICBpZiAoZW5kID09PSBzdGFydClcbiAgICByZXR1cm4gJydcblxuICB2YXIgcmV0XG4gIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICBjYXNlICdoZXgnOlxuICAgICAgcmV0ID0gX2hleFNsaWNlKHNlbGYsIHN0YXJ0LCBlbmQpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ3V0ZjgnOlxuICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgIHJldCA9IF91dGY4U2xpY2Uoc2VsZiwgc3RhcnQsIGVuZClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnYXNjaWknOlxuICAgICAgcmV0ID0gX2FzY2lpU2xpY2Uoc2VsZiwgc3RhcnQsIGVuZClcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgIHJldCA9IF9iaW5hcnlTbGljZShzZWxmLCBzdGFydCwgZW5kKVxuICAgICAgYnJlYWtcbiAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgcmV0ID0gX2Jhc2U2NFNsaWNlKHNlbGYsIHN0YXJ0LCBlbmQpXG4gICAgICBicmVha1xuICAgIGNhc2UgJ3VjczInOlxuICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICBjYXNlICd1dGYxNmxlJzpcbiAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICByZXQgPSBfdXRmMTZsZVNsaWNlKHNlbGYsIHN0YXJ0LCBlbmQpXG4gICAgICBicmVha1xuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gZW5jb2RpbmcnKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0J1ZmZlcicsXG4gICAgZGF0YTogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5fYXJyIHx8IHRoaXMsIDApXG4gIH1cbn1cblxuLy8gY29weSh0YXJnZXRCdWZmZXIsIHRhcmdldFN0YXJ0PTAsIHNvdXJjZVN0YXJ0PTAsIHNvdXJjZUVuZD1idWZmZXIubGVuZ3RoKVxuQnVmZmVyLnByb3RvdHlwZS5jb3B5ID0gZnVuY3Rpb24gKHRhcmdldCwgdGFyZ2V0X3N0YXJ0LCBzdGFydCwgZW5kKSB7XG4gIHZhciBzb3VyY2UgPSB0aGlzXG5cbiAgaWYgKCFzdGFydCkgc3RhcnQgPSAwXG4gIGlmICghZW5kICYmIGVuZCAhPT0gMCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKCF0YXJnZXRfc3RhcnQpIHRhcmdldF9zdGFydCA9IDBcblxuICAvLyBDb3B5IDAgYnl0ZXM7IHdlJ3JlIGRvbmVcbiAgaWYgKGVuZCA9PT0gc3RhcnQpIHJldHVyblxuICBpZiAodGFyZ2V0Lmxlbmd0aCA9PT0gMCB8fCBzb3VyY2UubGVuZ3RoID09PSAwKSByZXR1cm5cblxuICAvLyBGYXRhbCBlcnJvciBjb25kaXRpb25zXG4gIGFzc2VydChlbmQgPj0gc3RhcnQsICdzb3VyY2VFbmQgPCBzb3VyY2VTdGFydCcpXG4gIGFzc2VydCh0YXJnZXRfc3RhcnQgPj0gMCAmJiB0YXJnZXRfc3RhcnQgPCB0YXJnZXQubGVuZ3RoLFxuICAgICAgJ3RhcmdldFN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICBhc3NlcnQoc3RhcnQgPj0gMCAmJiBzdGFydCA8IHNvdXJjZS5sZW5ndGgsICdzb3VyY2VTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgYXNzZXJ0KGVuZCA+PSAwICYmIGVuZCA8PSBzb3VyY2UubGVuZ3RoLCAnc291cmNlRW5kIG91dCBvZiBib3VuZHMnKVxuXG4gIC8vIEFyZSB3ZSBvb2I/XG4gIGlmIChlbmQgPiB0aGlzLmxlbmd0aClcbiAgICBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0Lmxlbmd0aCAtIHRhcmdldF9zdGFydCA8IGVuZCAtIHN0YXJ0KVxuICAgIGVuZCA9IHRhcmdldC5sZW5ndGggLSB0YXJnZXRfc3RhcnQgKyBzdGFydFxuXG4gIHZhciBsZW4gPSBlbmQgLSBzdGFydFxuXG4gIGlmIChsZW4gPCAxMDAgfHwgIUJ1ZmZlci5fdXNlVHlwZWRBcnJheXMpIHtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKVxuICAgICAgdGFyZ2V0W2kgKyB0YXJnZXRfc3RhcnRdID0gdGhpc1tpICsgc3RhcnRdXG4gIH0gZWxzZSB7XG4gICAgdGFyZ2V0Ll9zZXQodGhpcy5zdWJhcnJheShzdGFydCwgc3RhcnQgKyBsZW4pLCB0YXJnZXRfc3RhcnQpXG4gIH1cbn1cblxuZnVuY3Rpb24gX2Jhc2U2NFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgaWYgKHN0YXJ0ID09PSAwICYmIGVuZCA9PT0gYnVmLmxlbmd0aCkge1xuICAgIHJldHVybiBiYXNlNjQuZnJvbUJ5dGVBcnJheShidWYpXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1Zi5zbGljZShzdGFydCwgZW5kKSlcbiAgfVxufVxuXG5mdW5jdGlvbiBfdXRmOFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJlcyA9ICcnXG4gIHZhciB0bXAgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICBpZiAoYnVmW2ldIDw9IDB4N0YpIHtcbiAgICAgIHJlcyArPSBkZWNvZGVVdGY4Q2hhcih0bXApICsgU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0pXG4gICAgICB0bXAgPSAnJ1xuICAgIH0gZWxzZSB7XG4gICAgICB0bXAgKz0gJyUnICsgYnVmW2ldLnRvU3RyaW5nKDE2KVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXMgKyBkZWNvZGVVdGY4Q2hhcih0bXApXG59XG5cbmZ1bmN0aW9uIF9hc2NpaVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJldCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKylcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0pXG4gIHJldHVybiByZXRcbn1cblxuZnVuY3Rpb24gX2JpbmFyeVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgcmV0dXJuIF9hc2NpaVNsaWNlKGJ1Ziwgc3RhcnQsIGVuZClcbn1cblxuZnVuY3Rpb24gX2hleFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcblxuICBpZiAoIXN0YXJ0IHx8IHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIGlmICghZW5kIHx8IGVuZCA8IDAgfHwgZW5kID4gbGVuKSBlbmQgPSBsZW5cblxuICB2YXIgb3V0ID0gJydcbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICBvdXQgKz0gdG9IZXgoYnVmW2ldKVxuICB9XG4gIHJldHVybiBvdXRcbn1cblxuZnVuY3Rpb24gX3V0ZjE2bGVTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBieXRlcyA9IGJ1Zi5zbGljZShzdGFydCwgZW5kKVxuICB2YXIgcmVzID0gJydcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkgKz0gMikge1xuICAgIHJlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ5dGVzW2ldICsgYnl0ZXNbaSsxXSAqIDI1NilcbiAgfVxuICByZXR1cm4gcmVzXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuc2xpY2UgPSBmdW5jdGlvbiAoc3RhcnQsIGVuZCkge1xuICB2YXIgbGVuID0gdGhpcy5sZW5ndGhcbiAgc3RhcnQgPSBjbGFtcChzdGFydCwgbGVuLCAwKVxuICBlbmQgPSBjbGFtcChlbmQsIGxlbiwgbGVuKVxuXG4gIGlmIChCdWZmZXIuX3VzZVR5cGVkQXJyYXlzKSB7XG4gICAgcmV0dXJuIEJ1ZmZlci5fYXVnbWVudCh0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpKVxuICB9IGVsc2Uge1xuICAgIHZhciBzbGljZUxlbiA9IGVuZCAtIHN0YXJ0XG4gICAgdmFyIG5ld0J1ZiA9IG5ldyBCdWZmZXIoc2xpY2VMZW4sIHVuZGVmaW5lZCwgdHJ1ZSlcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNsaWNlTGVuOyBpKyspIHtcbiAgICAgIG5ld0J1ZltpXSA9IHRoaXNbaSArIHN0YXJ0XVxuICAgIH1cbiAgICByZXR1cm4gbmV3QnVmXG4gIH1cbn1cblxuLy8gYGdldGAgd2lsbCBiZSByZW1vdmVkIGluIE5vZGUgMC4xMytcbkJ1ZmZlci5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24gKG9mZnNldCkge1xuICBjb25zb2xlLmxvZygnLmdldCgpIGlzIGRlcHJlY2F0ZWQuIEFjY2VzcyB1c2luZyBhcnJheSBpbmRleGVzIGluc3RlYWQuJylcbiAgcmV0dXJuIHRoaXMucmVhZFVJbnQ4KG9mZnNldClcbn1cblxuLy8gYHNldGAgd2lsbCBiZSByZW1vdmVkIGluIE5vZGUgMC4xMytcbkJ1ZmZlci5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKHYsIG9mZnNldCkge1xuICBjb25zb2xlLmxvZygnLnNldCgpIGlzIGRlcHJlY2F0ZWQuIEFjY2VzcyB1c2luZyBhcnJheSBpbmRleGVzIGluc3RlYWQuJylcbiAgcmV0dXJuIHRoaXMud3JpdGVVSW50OCh2LCBvZmZzZXQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQ4ID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCA8IHRoaXMubGVuZ3RoLCAnVHJ5aW5nIHRvIHJlYWQgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICB9XG5cbiAgaWYgKG9mZnNldCA+PSB0aGlzLmxlbmd0aClcbiAgICByZXR1cm5cblxuICByZXR1cm4gdGhpc1tvZmZzZXRdXG59XG5cbmZ1bmN0aW9uIF9yZWFkVUludDE2IChidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDEgPCBidWYubGVuZ3RoLCAnVHJ5aW5nIHRvIHJlYWQgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICB9XG5cbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcbiAgaWYgKG9mZnNldCA+PSBsZW4pXG4gICAgcmV0dXJuXG5cbiAgdmFyIHZhbFxuICBpZiAobGl0dGxlRW5kaWFuKSB7XG4gICAgdmFsID0gYnVmW29mZnNldF1cbiAgICBpZiAob2Zmc2V0ICsgMSA8IGxlbilcbiAgICAgIHZhbCB8PSBidWZbb2Zmc2V0ICsgMV0gPDwgOFxuICB9IGVsc2Uge1xuICAgIHZhbCA9IGJ1ZltvZmZzZXRdIDw8IDhcbiAgICBpZiAob2Zmc2V0ICsgMSA8IGxlbilcbiAgICAgIHZhbCB8PSBidWZbb2Zmc2V0ICsgMV1cbiAgfVxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkxFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIF9yZWFkVUludDE2KHRoaXMsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkJFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIF9yZWFkVUludDE2KHRoaXMsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiBfcmVhZFVJbnQzMiAoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAzIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIHZhciB2YWxcbiAgaWYgKGxpdHRsZUVuZGlhbikge1xuICAgIGlmIChvZmZzZXQgKyAyIDwgbGVuKVxuICAgICAgdmFsID0gYnVmW29mZnNldCArIDJdIDw8IDE2XG4gICAgaWYgKG9mZnNldCArIDEgPCBsZW4pXG4gICAgICB2YWwgfD0gYnVmW29mZnNldCArIDFdIDw8IDhcbiAgICB2YWwgfD0gYnVmW29mZnNldF1cbiAgICBpZiAob2Zmc2V0ICsgMyA8IGxlbilcbiAgICAgIHZhbCA9IHZhbCArIChidWZbb2Zmc2V0ICsgM10gPDwgMjQgPj4+IDApXG4gIH0gZWxzZSB7XG4gICAgaWYgKG9mZnNldCArIDEgPCBsZW4pXG4gICAgICB2YWwgPSBidWZbb2Zmc2V0ICsgMV0gPDwgMTZcbiAgICBpZiAob2Zmc2V0ICsgMiA8IGxlbilcbiAgICAgIHZhbCB8PSBidWZbb2Zmc2V0ICsgMl0gPDwgOFxuICAgIGlmIChvZmZzZXQgKyAzIDwgbGVuKVxuICAgICAgdmFsIHw9IGJ1ZltvZmZzZXQgKyAzXVxuICAgIHZhbCA9IHZhbCArIChidWZbb2Zmc2V0XSA8PCAyNCA+Pj4gMClcbiAgfVxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkxFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIF9yZWFkVUludDMyKHRoaXMsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkJFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIF9yZWFkVUludDMyKHRoaXMsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQ4ID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsXG4gICAgICAgICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCA8IHRoaXMubGVuZ3RoLCAnVHJ5aW5nIHRvIHJlYWQgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICB9XG5cbiAgaWYgKG9mZnNldCA+PSB0aGlzLmxlbmd0aClcbiAgICByZXR1cm5cblxuICB2YXIgbmVnID0gdGhpc1tvZmZzZXRdICYgMHg4MFxuICBpZiAobmVnKVxuICAgIHJldHVybiAoMHhmZiAtIHRoaXNbb2Zmc2V0XSArIDEpICogLTFcbiAgZWxzZVxuICAgIHJldHVybiB0aGlzW29mZnNldF1cbn1cblxuZnVuY3Rpb24gX3JlYWRJbnQxNiAoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAxIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byByZWFkIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIHZhciB2YWwgPSBfcmVhZFVJbnQxNihidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCB0cnVlKVxuICB2YXIgbmVnID0gdmFsICYgMHg4MDAwXG4gIGlmIChuZWcpXG4gICAgcmV0dXJuICgweGZmZmYgLSB2YWwgKyAxKSAqIC0xXG4gIGVsc2VcbiAgICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2TEUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gX3JlYWRJbnQxNih0aGlzLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkJFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIF9yZWFkSW50MTYodGhpcywgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIF9yZWFkSW50MzIgKGJ1Ziwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0ICsgMyA8IGJ1Zi5sZW5ndGgsICdUcnlpbmcgdG8gcmVhZCBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICB2YXIgdmFsID0gX3JlYWRVSW50MzIoYnVmLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgdHJ1ZSlcbiAgdmFyIG5lZyA9IHZhbCAmIDB4ODAwMDAwMDBcbiAgaWYgKG5lZylcbiAgICByZXR1cm4gKDB4ZmZmZmZmZmYgLSB2YWwgKyAxKSAqIC0xXG4gIGVsc2VcbiAgICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDMyTEUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gX3JlYWRJbnQzMih0aGlzLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkJFID0gZnVuY3Rpb24gKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIF9yZWFkSW50MzIodGhpcywgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIF9yZWFkRmxvYXQgKGJ1Ziwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCArIDMgPCBidWYubGVuZ3RoLCAnVHJ5aW5nIHRvIHJlYWQgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICB9XG5cbiAgcmV0dXJuIGllZWU3NTQucmVhZChidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRMRSA9IGZ1bmN0aW9uIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiBfcmVhZEZsb2F0KHRoaXMsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0QkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gX3JlYWRGbG9hdCh0aGlzLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gX3JlYWREb3VibGUgKGJ1Ziwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCArIDcgPCBidWYubGVuZ3RoLCAnVHJ5aW5nIHRvIHJlYWQgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICB9XG5cbiAgcmV0dXJuIGllZWU3NTQucmVhZChidWYsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCA1MiwgOClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlTEUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gX3JlYWREb3VibGUodGhpcywgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlQkUgPSBmdW5jdGlvbiAob2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gX3JlYWREb3VibGUodGhpcywgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50OCA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwsICdtaXNzaW5nIHZhbHVlJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgPCB0aGlzLmxlbmd0aCwgJ3RyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gICAgdmVyaWZ1aW50KHZhbHVlLCAweGZmKVxuICB9XG5cbiAgaWYgKG9mZnNldCA+PSB0aGlzLmxlbmd0aCkgcmV0dXJuXG5cbiAgdGhpc1tvZmZzZXRdID0gdmFsdWVcbn1cblxuZnVuY3Rpb24gX3dyaXRlVUludDE2IChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsLCAnbWlzc2luZyB2YWx1ZScpXG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDEgPCBidWYubGVuZ3RoLCAndHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgICB2ZXJpZnVpbnQodmFsdWUsIDB4ZmZmZilcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIGZvciAodmFyIGkgPSAwLCBqID0gTWF0aC5taW4obGVuIC0gb2Zmc2V0LCAyKTsgaSA8IGo7IGkrKykge1xuICAgIGJ1ZltvZmZzZXQgKyBpXSA9XG4gICAgICAgICh2YWx1ZSAmICgweGZmIDw8ICg4ICogKGxpdHRsZUVuZGlhbiA/IGkgOiAxIC0gaSkpKSkgPj4+XG4gICAgICAgICAgICAobGl0dGxlRW5kaWFuID8gaSA6IDEgLSBpKSAqIDhcbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDE2TEUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgX3dyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDE2QkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgX3dyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gX3dyaXRlVUludDMyIChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsLCAnbWlzc2luZyB2YWx1ZScpXG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDMgPCBidWYubGVuZ3RoLCAndHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgICB2ZXJpZnVpbnQodmFsdWUsIDB4ZmZmZmZmZmYpXG4gIH1cblxuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuICBpZiAob2Zmc2V0ID49IGxlbilcbiAgICByZXR1cm5cblxuICBmb3IgKHZhciBpID0gMCwgaiA9IE1hdGgubWluKGxlbiAtIG9mZnNldCwgNCk7IGkgPCBqOyBpKyspIHtcbiAgICBidWZbb2Zmc2V0ICsgaV0gPVxuICAgICAgICAodmFsdWUgPj4+IChsaXR0bGVFbmRpYW4gPyBpIDogMyAtIGkpICogOCkgJiAweGZmXG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkxFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIF93cml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkJFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIF93cml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQ4ID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCwgJ21pc3NpbmcgdmFsdWUnKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCA8IHRoaXMubGVuZ3RoLCAnVHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgICB2ZXJpZnNpbnQodmFsdWUsIDB4N2YsIC0weDgwKVxuICB9XG5cbiAgaWYgKG9mZnNldCA+PSB0aGlzLmxlbmd0aClcbiAgICByZXR1cm5cblxuICBpZiAodmFsdWUgPj0gMClcbiAgICB0aGlzLndyaXRlVUludDgodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpXG4gIGVsc2VcbiAgICB0aGlzLndyaXRlVUludDgoMHhmZiArIHZhbHVlICsgMSwgb2Zmc2V0LCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gX3dyaXRlSW50MTYgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgYXNzZXJ0KHZhbHVlICE9PSB1bmRlZmluZWQgJiYgdmFsdWUgIT09IG51bGwsICdtaXNzaW5nIHZhbHVlJylcbiAgICBhc3NlcnQodHlwZW9mIGxpdHRsZUVuZGlhbiA9PT0gJ2Jvb2xlYW4nLCAnbWlzc2luZyBvciBpbnZhbGlkIGVuZGlhbicpXG4gICAgYXNzZXJ0KG9mZnNldCAhPT0gdW5kZWZpbmVkICYmIG9mZnNldCAhPT0gbnVsbCwgJ21pc3Npbmcgb2Zmc2V0JylcbiAgICBhc3NlcnQob2Zmc2V0ICsgMSA8IGJ1Zi5sZW5ndGgsICdUcnlpbmcgdG8gd3JpdGUgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxuICAgIHZlcmlmc2ludCh2YWx1ZSwgMHg3ZmZmLCAtMHg4MDAwKVxuICB9XG5cbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcbiAgaWYgKG9mZnNldCA+PSBsZW4pXG4gICAgcmV0dXJuXG5cbiAgaWYgKHZhbHVlID49IDApXG4gICAgX3dyaXRlVUludDE2KGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydClcbiAgZWxzZVxuICAgIF93cml0ZVVJbnQxNihidWYsIDB4ZmZmZiArIHZhbHVlICsgMSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZMRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBfd3JpdGVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDE2QkUgPSBmdW5jdGlvbiAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgX3dyaXRlSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG5mdW5jdGlvbiBfd3JpdGVJbnQzMiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCwgJ21pc3NpbmcgdmFsdWUnKVxuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyAzIDwgYnVmLmxlbmd0aCwgJ1RyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gICAgdmVyaWZzaW50KHZhbHVlLCAweDdmZmZmZmZmLCAtMHg4MDAwMDAwMClcbiAgfVxuXG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG4gIGlmIChvZmZzZXQgPj0gbGVuKVxuICAgIHJldHVyblxuXG4gIGlmICh2YWx1ZSA+PSAwKVxuICAgIF93cml0ZVVJbnQzMihidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpXG4gIGVsc2VcbiAgICBfd3JpdGVVSW50MzIoYnVmLCAweGZmZmZmZmZmICsgdmFsdWUgKyAxLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkxFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIF93cml0ZUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJCRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBfd3JpdGVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIF93cml0ZUZsb2F0IChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGFzc2VydCh2YWx1ZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlICE9PSBudWxsLCAnbWlzc2luZyB2YWx1ZScpXG4gICAgYXNzZXJ0KHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICdib29sZWFuJywgJ21pc3Npbmcgb3IgaW52YWxpZCBlbmRpYW4nKVxuICAgIGFzc2VydChvZmZzZXQgIT09IHVuZGVmaW5lZCAmJiBvZmZzZXQgIT09IG51bGwsICdtaXNzaW5nIG9mZnNldCcpXG4gICAgYXNzZXJ0KG9mZnNldCArIDMgPCBidWYubGVuZ3RoLCAnVHJ5aW5nIHRvIHdyaXRlIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbiAgICB2ZXJpZklFRUU3NTQodmFsdWUsIDMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgsIC0zLjQwMjgyMzQ2NjM4NTI4ODZlKzM4KVxuICB9XG5cbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcbiAgaWYgKG9mZnNldCA+PSBsZW4pXG4gICAgcmV0dXJuXG5cbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdExFID0gZnVuY3Rpb24gKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIF93cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXRCRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBfd3JpdGVGbG9hdCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIF93cml0ZURvdWJsZSAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBhc3NlcnQodmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCwgJ21pc3NpbmcgdmFsdWUnKVxuICAgIGFzc2VydCh0eXBlb2YgbGl0dGxlRW5kaWFuID09PSAnYm9vbGVhbicsICdtaXNzaW5nIG9yIGludmFsaWQgZW5kaWFuJylcbiAgICBhc3NlcnQob2Zmc2V0ICE9PSB1bmRlZmluZWQgJiYgb2Zmc2V0ICE9PSBudWxsLCAnbWlzc2luZyBvZmZzZXQnKVxuICAgIGFzc2VydChvZmZzZXQgKyA3IDwgYnVmLmxlbmd0aCxcbiAgICAgICAgJ1RyeWluZyB0byB3cml0ZSBiZXlvbmQgYnVmZmVyIGxlbmd0aCcpXG4gICAgdmVyaWZJRUVFNzU0KHZhbHVlLCAxLjc5NzY5MzEzNDg2MjMxNTdFKzMwOCwgLTEuNzk3NjkzMTM0ODYyMzE1N0UrMzA4KVxuICB9XG5cbiAgdmFyIGxlbiA9IGJ1Zi5sZW5ndGhcbiAgaWYgKG9mZnNldCA+PSBsZW4pXG4gICAgcmV0dXJuXG5cbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgNTIsIDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVEb3VibGVMRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBfd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVEb3VibGVCRSA9IGZ1bmN0aW9uICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICBfd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG4vLyBmaWxsKHZhbHVlLCBzdGFydD0wLCBlbmQ9YnVmZmVyLmxlbmd0aClcbkJ1ZmZlci5wcm90b3R5cGUuZmlsbCA9IGZ1bmN0aW9uICh2YWx1ZSwgc3RhcnQsIGVuZCkge1xuICBpZiAoIXZhbHVlKSB2YWx1ZSA9IDBcbiAgaWYgKCFzdGFydCkgc3RhcnQgPSAwXG4gIGlmICghZW5kKSBlbmQgPSB0aGlzLmxlbmd0aFxuXG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgdmFsdWUgPSB2YWx1ZS5jaGFyQ29kZUF0KDApXG4gIH1cblxuICBhc3NlcnQodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJyAmJiAhaXNOYU4odmFsdWUpLCAndmFsdWUgaXMgbm90IGEgbnVtYmVyJylcbiAgYXNzZXJ0KGVuZCA+PSBzdGFydCwgJ2VuZCA8IHN0YXJ0JylcblxuICAvLyBGaWxsIDAgYnl0ZXM7IHdlJ3JlIGRvbmVcbiAgaWYgKGVuZCA9PT0gc3RhcnQpIHJldHVyblxuICBpZiAodGhpcy5sZW5ndGggPT09IDApIHJldHVyblxuXG4gIGFzc2VydChzdGFydCA+PSAwICYmIHN0YXJ0IDwgdGhpcy5sZW5ndGgsICdzdGFydCBvdXQgb2YgYm91bmRzJylcbiAgYXNzZXJ0KGVuZCA+PSAwICYmIGVuZCA8PSB0aGlzLmxlbmd0aCwgJ2VuZCBvdXQgb2YgYm91bmRzJylcblxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgIHRoaXNbaV0gPSB2YWx1ZVxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5zcGVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIG91dCA9IFtdXG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgb3V0W2ldID0gdG9IZXgodGhpc1tpXSlcbiAgICBpZiAoaSA9PT0gZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFUykge1xuICAgICAgb3V0W2kgKyAxXSA9ICcuLi4nXG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuICByZXR1cm4gJzxCdWZmZXIgJyArIG91dC5qb2luKCcgJykgKyAnPidcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGBBcnJheUJ1ZmZlcmAgd2l0aCB0aGUgKmNvcGllZCogbWVtb3J5IG9mIHRoZSBidWZmZXIgaW5zdGFuY2UuXG4gKiBBZGRlZCBpbiBOb2RlIDAuMTIuIE9ubHkgYXZhaWxhYmxlIGluIGJyb3dzZXJzIHRoYXQgc3VwcG9ydCBBcnJheUJ1ZmZlci5cbiAqL1xuQnVmZmVyLnByb3RvdHlwZS50b0FycmF5QnVmZmVyID0gZnVuY3Rpb24gKCkge1xuICBpZiAodHlwZW9mIFVpbnQ4QXJyYXkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKEJ1ZmZlci5fdXNlVHlwZWRBcnJheXMpIHtcbiAgICAgIHJldHVybiAobmV3IEJ1ZmZlcih0aGlzKSkuYnVmZmVyXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBidWYgPSBuZXcgVWludDhBcnJheSh0aGlzLmxlbmd0aClcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBidWYubGVuZ3RoOyBpIDwgbGVuOyBpICs9IDEpXG4gICAgICAgIGJ1ZltpXSA9IHRoaXNbaV1cbiAgICAgIHJldHVybiBidWYuYnVmZmVyXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcignQnVmZmVyLnRvQXJyYXlCdWZmZXIgbm90IHN1cHBvcnRlZCBpbiB0aGlzIGJyb3dzZXInKVxuICB9XG59XG5cbi8vIEhFTFBFUiBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT1cblxuZnVuY3Rpb24gc3RyaW5ndHJpbSAoc3RyKSB7XG4gIGlmIChzdHIudHJpbSkgcmV0dXJuIHN0ci50cmltKClcbiAgcmV0dXJuIHN0ci5yZXBsYWNlKC9eXFxzK3xcXHMrJC9nLCAnJylcbn1cblxudmFyIEJQID0gQnVmZmVyLnByb3RvdHlwZVxuXG4vKipcbiAqIEF1Z21lbnQgYSBVaW50OEFycmF5ICppbnN0YW5jZSogKG5vdCB0aGUgVWludDhBcnJheSBjbGFzcyEpIHdpdGggQnVmZmVyIG1ldGhvZHNcbiAqL1xuQnVmZmVyLl9hdWdtZW50ID0gZnVuY3Rpb24gKGFycikge1xuICBhcnIuX2lzQnVmZmVyID0gdHJ1ZVxuXG4gIC8vIHNhdmUgcmVmZXJlbmNlIHRvIG9yaWdpbmFsIFVpbnQ4QXJyYXkgZ2V0L3NldCBtZXRob2RzIGJlZm9yZSBvdmVyd3JpdGluZ1xuICBhcnIuX2dldCA9IGFyci5nZXRcbiAgYXJyLl9zZXQgPSBhcnIuc2V0XG5cbiAgLy8gZGVwcmVjYXRlZCwgd2lsbCBiZSByZW1vdmVkIGluIG5vZGUgMC4xMytcbiAgYXJyLmdldCA9IEJQLmdldFxuICBhcnIuc2V0ID0gQlAuc2V0XG5cbiAgYXJyLndyaXRlID0gQlAud3JpdGVcbiAgYXJyLnRvU3RyaW5nID0gQlAudG9TdHJpbmdcbiAgYXJyLnRvTG9jYWxlU3RyaW5nID0gQlAudG9TdHJpbmdcbiAgYXJyLnRvSlNPTiA9IEJQLnRvSlNPTlxuICBhcnIuY29weSA9IEJQLmNvcHlcbiAgYXJyLnNsaWNlID0gQlAuc2xpY2VcbiAgYXJyLnJlYWRVSW50OCA9IEJQLnJlYWRVSW50OFxuICBhcnIucmVhZFVJbnQxNkxFID0gQlAucmVhZFVJbnQxNkxFXG4gIGFyci5yZWFkVUludDE2QkUgPSBCUC5yZWFkVUludDE2QkVcbiAgYXJyLnJlYWRVSW50MzJMRSA9IEJQLnJlYWRVSW50MzJMRVxuICBhcnIucmVhZFVJbnQzMkJFID0gQlAucmVhZFVJbnQzMkJFXG4gIGFyci5yZWFkSW50OCA9IEJQLnJlYWRJbnQ4XG4gIGFyci5yZWFkSW50MTZMRSA9IEJQLnJlYWRJbnQxNkxFXG4gIGFyci5yZWFkSW50MTZCRSA9IEJQLnJlYWRJbnQxNkJFXG4gIGFyci5yZWFkSW50MzJMRSA9IEJQLnJlYWRJbnQzMkxFXG4gIGFyci5yZWFkSW50MzJCRSA9IEJQLnJlYWRJbnQzMkJFXG4gIGFyci5yZWFkRmxvYXRMRSA9IEJQLnJlYWRGbG9hdExFXG4gIGFyci5yZWFkRmxvYXRCRSA9IEJQLnJlYWRGbG9hdEJFXG4gIGFyci5yZWFkRG91YmxlTEUgPSBCUC5yZWFkRG91YmxlTEVcbiAgYXJyLnJlYWREb3VibGVCRSA9IEJQLnJlYWREb3VibGVCRVxuICBhcnIud3JpdGVVSW50OCA9IEJQLndyaXRlVUludDhcbiAgYXJyLndyaXRlVUludDE2TEUgPSBCUC53cml0ZVVJbnQxNkxFXG4gIGFyci53cml0ZVVJbnQxNkJFID0gQlAud3JpdGVVSW50MTZCRVxuICBhcnIud3JpdGVVSW50MzJMRSA9IEJQLndyaXRlVUludDMyTEVcbiAgYXJyLndyaXRlVUludDMyQkUgPSBCUC53cml0ZVVJbnQzMkJFXG4gIGFyci53cml0ZUludDggPSBCUC53cml0ZUludDhcbiAgYXJyLndyaXRlSW50MTZMRSA9IEJQLndyaXRlSW50MTZMRVxuICBhcnIud3JpdGVJbnQxNkJFID0gQlAud3JpdGVJbnQxNkJFXG4gIGFyci53cml0ZUludDMyTEUgPSBCUC53cml0ZUludDMyTEVcbiAgYXJyLndyaXRlSW50MzJCRSA9IEJQLndyaXRlSW50MzJCRVxuICBhcnIud3JpdGVGbG9hdExFID0gQlAud3JpdGVGbG9hdExFXG4gIGFyci53cml0ZUZsb2F0QkUgPSBCUC53cml0ZUZsb2F0QkVcbiAgYXJyLndyaXRlRG91YmxlTEUgPSBCUC53cml0ZURvdWJsZUxFXG4gIGFyci53cml0ZURvdWJsZUJFID0gQlAud3JpdGVEb3VibGVCRVxuICBhcnIuZmlsbCA9IEJQLmZpbGxcbiAgYXJyLmluc3BlY3QgPSBCUC5pbnNwZWN0XG4gIGFyci50b0FycmF5QnVmZmVyID0gQlAudG9BcnJheUJ1ZmZlclxuXG4gIHJldHVybiBhcnJcbn1cblxuLy8gc2xpY2Uoc3RhcnQsIGVuZClcbmZ1bmN0aW9uIGNsYW1wIChpbmRleCwgbGVuLCBkZWZhdWx0VmFsdWUpIHtcbiAgaWYgKHR5cGVvZiBpbmRleCAhPT0gJ251bWJlcicpIHJldHVybiBkZWZhdWx0VmFsdWVcbiAgaW5kZXggPSB+fmluZGV4OyAgLy8gQ29lcmNlIHRvIGludGVnZXIuXG4gIGlmIChpbmRleCA+PSBsZW4pIHJldHVybiBsZW5cbiAgaWYgKGluZGV4ID49IDApIHJldHVybiBpbmRleFxuICBpbmRleCArPSBsZW5cbiAgaWYgKGluZGV4ID49IDApIHJldHVybiBpbmRleFxuICByZXR1cm4gMFxufVxuXG5mdW5jdGlvbiBjb2VyY2UgKGxlbmd0aCkge1xuICAvLyBDb2VyY2UgbGVuZ3RoIHRvIGEgbnVtYmVyIChwb3NzaWJseSBOYU4pLCByb3VuZCB1cFxuICAvLyBpbiBjYXNlIGl0J3MgZnJhY3Rpb25hbCAoZS5nLiAxMjMuNDU2KSB0aGVuIGRvIGFcbiAgLy8gZG91YmxlIG5lZ2F0ZSB0byBjb2VyY2UgYSBOYU4gdG8gMC4gRWFzeSwgcmlnaHQ/XG4gIGxlbmd0aCA9IH5+TWF0aC5jZWlsKCtsZW5ndGgpXG4gIHJldHVybiBsZW5ndGggPCAwID8gMCA6IGxlbmd0aFxufVxuXG5mdW5jdGlvbiBpc0FycmF5IChzdWJqZWN0KSB7XG4gIHJldHVybiAoQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiAoc3ViamVjdCkge1xuICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc3ViamVjdCkgPT09ICdbb2JqZWN0IEFycmF5XSdcbiAgfSkoc3ViamVjdClcbn1cblxuZnVuY3Rpb24gaXNBcnJheWlzaCAoc3ViamVjdCkge1xuICByZXR1cm4gaXNBcnJheShzdWJqZWN0KSB8fCBCdWZmZXIuaXNCdWZmZXIoc3ViamVjdCkgfHxcbiAgICAgIHN1YmplY3QgJiYgdHlwZW9mIHN1YmplY3QgPT09ICdvYmplY3QnICYmXG4gICAgICB0eXBlb2Ygc3ViamVjdC5sZW5ndGggPT09ICdudW1iZXInXG59XG5cbmZ1bmN0aW9uIHRvSGV4IChuKSB7XG4gIGlmIChuIDwgMTYpIHJldHVybiAnMCcgKyBuLnRvU3RyaW5nKDE2KVxuICByZXR1cm4gbi50b1N0cmluZygxNilcbn1cblxuZnVuY3Rpb24gdXRmOFRvQnl0ZXMgKHN0cikge1xuICB2YXIgYnl0ZUFycmF5ID0gW11cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgYiA9IHN0ci5jaGFyQ29kZUF0KGkpXG4gICAgaWYgKGIgPD0gMHg3RilcbiAgICAgIGJ5dGVBcnJheS5wdXNoKHN0ci5jaGFyQ29kZUF0KGkpKVxuICAgIGVsc2Uge1xuICAgICAgdmFyIHN0YXJ0ID0gaVxuICAgICAgaWYgKGIgPj0gMHhEODAwICYmIGIgPD0gMHhERkZGKSBpKytcbiAgICAgIHZhciBoID0gZW5jb2RlVVJJQ29tcG9uZW50KHN0ci5zbGljZShzdGFydCwgaSsxKSkuc3Vic3RyKDEpLnNwbGl0KCclJylcbiAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgaC5sZW5ndGg7IGorKylcbiAgICAgICAgYnl0ZUFycmF5LnB1c2gocGFyc2VJbnQoaFtqXSwgMTYpKVxuICAgIH1cbiAgfVxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIGFzY2lpVG9CeXRlcyAoc3RyKSB7XG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIC8vIE5vZGUncyBjb2RlIHNlZW1zIHRvIGJlIGRvaW5nIHRoaXMgYW5kIG5vdCAmIDB4N0YuLlxuICAgIGJ5dGVBcnJheS5wdXNoKHN0ci5jaGFyQ29kZUF0KGkpICYgMHhGRilcbiAgfVxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVUb0J5dGVzIChzdHIpIHtcbiAgdmFyIGMsIGhpLCBsb1xuICB2YXIgYnl0ZUFycmF5ID0gW11cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICBjID0gc3RyLmNoYXJDb2RlQXQoaSlcbiAgICBoaSA9IGMgPj4gOFxuICAgIGxvID0gYyAlIDI1NlxuICAgIGJ5dGVBcnJheS5wdXNoKGxvKVxuICAgIGJ5dGVBcnJheS5wdXNoKGhpKVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiBiYXNlNjRUb0J5dGVzIChzdHIpIHtcbiAgcmV0dXJuIGJhc2U2NC50b0J5dGVBcnJheShzdHIpXG59XG5cbmZ1bmN0aW9uIGJsaXRCdWZmZXIgKHNyYywgZHN0LCBvZmZzZXQsIGxlbmd0aCkge1xuICB2YXIgcG9zXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoKGkgKyBvZmZzZXQgPj0gZHN0Lmxlbmd0aCkgfHwgKGkgPj0gc3JjLmxlbmd0aCkpXG4gICAgICBicmVha1xuICAgIGRzdFtpICsgb2Zmc2V0XSA9IHNyY1tpXVxuICB9XG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIGRlY29kZVV0ZjhDaGFyIChzdHIpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KHN0cilcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoMHhGRkZEKSAvLyBVVEYgOCBpbnZhbGlkIGNoYXJcbiAgfVxufVxuXG4vKlxuICogV2UgaGF2ZSB0byBtYWtlIHN1cmUgdGhhdCB0aGUgdmFsdWUgaXMgYSB2YWxpZCBpbnRlZ2VyLiBUaGlzIG1lYW5zIHRoYXQgaXRcbiAqIGlzIG5vbi1uZWdhdGl2ZS4gSXQgaGFzIG5vIGZyYWN0aW9uYWwgY29tcG9uZW50IGFuZCB0aGF0IGl0IGRvZXMgbm90XG4gKiBleGNlZWQgdGhlIG1heGltdW0gYWxsb3dlZCB2YWx1ZS5cbiAqL1xuZnVuY3Rpb24gdmVyaWZ1aW50ICh2YWx1ZSwgbWF4KSB7XG4gIGFzc2VydCh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInLCAnY2Fubm90IHdyaXRlIGEgbm9uLW51bWJlciBhcyBhIG51bWJlcicpXG4gIGFzc2VydCh2YWx1ZSA+PSAwLCAnc3BlY2lmaWVkIGEgbmVnYXRpdmUgdmFsdWUgZm9yIHdyaXRpbmcgYW4gdW5zaWduZWQgdmFsdWUnKVxuICBhc3NlcnQodmFsdWUgPD0gbWF4LCAndmFsdWUgaXMgbGFyZ2VyIHRoYW4gbWF4aW11bSB2YWx1ZSBmb3IgdHlwZScpXG4gIGFzc2VydChNYXRoLmZsb29yKHZhbHVlKSA9PT0gdmFsdWUsICd2YWx1ZSBoYXMgYSBmcmFjdGlvbmFsIGNvbXBvbmVudCcpXG59XG5cbmZ1bmN0aW9uIHZlcmlmc2ludCAodmFsdWUsIG1heCwgbWluKSB7XG4gIGFzc2VydCh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInLCAnY2Fubm90IHdyaXRlIGEgbm9uLW51bWJlciBhcyBhIG51bWJlcicpXG4gIGFzc2VydCh2YWx1ZSA8PSBtYXgsICd2YWx1ZSBsYXJnZXIgdGhhbiBtYXhpbXVtIGFsbG93ZWQgdmFsdWUnKVxuICBhc3NlcnQodmFsdWUgPj0gbWluLCAndmFsdWUgc21hbGxlciB0aGFuIG1pbmltdW0gYWxsb3dlZCB2YWx1ZScpXG4gIGFzc2VydChNYXRoLmZsb29yKHZhbHVlKSA9PT0gdmFsdWUsICd2YWx1ZSBoYXMgYSBmcmFjdGlvbmFsIGNvbXBvbmVudCcpXG59XG5cbmZ1bmN0aW9uIHZlcmlmSUVFRTc1NCAodmFsdWUsIG1heCwgbWluKSB7XG4gIGFzc2VydCh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInLCAnY2Fubm90IHdyaXRlIGEgbm9uLW51bWJlciBhcyBhIG51bWJlcicpXG4gIGFzc2VydCh2YWx1ZSA8PSBtYXgsICd2YWx1ZSBsYXJnZXIgdGhhbiBtYXhpbXVtIGFsbG93ZWQgdmFsdWUnKVxuICBhc3NlcnQodmFsdWUgPj0gbWluLCAndmFsdWUgc21hbGxlciB0aGFuIG1pbmltdW0gYWxsb3dlZCB2YWx1ZScpXG59XG5cbmZ1bmN0aW9uIGFzc2VydCAodGVzdCwgbWVzc2FnZSkge1xuICBpZiAoIXRlc3QpIHRocm93IG5ldyBFcnJvcihtZXNzYWdlIHx8ICdGYWlsZWQgYXNzZXJ0aW9uJylcbn1cbiIsInZhciBsb29rdXAgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLyc7XG5cbjsoZnVuY3Rpb24gKGV4cG9ydHMpIHtcblx0J3VzZSBzdHJpY3QnO1xuXG4gIHZhciBBcnIgPSAodHlwZW9mIFVpbnQ4QXJyYXkgIT09ICd1bmRlZmluZWQnKVxuICAgID8gVWludDhBcnJheVxuICAgIDogQXJyYXlcblxuXHR2YXIgUExVUyAgID0gJysnLmNoYXJDb2RlQXQoMClcblx0dmFyIFNMQVNIICA9ICcvJy5jaGFyQ29kZUF0KDApXG5cdHZhciBOVU1CRVIgPSAnMCcuY2hhckNvZGVBdCgwKVxuXHR2YXIgTE9XRVIgID0gJ2EnLmNoYXJDb2RlQXQoMClcblx0dmFyIFVQUEVSICA9ICdBJy5jaGFyQ29kZUF0KDApXG5cdHZhciBQTFVTX1VSTF9TQUZFID0gJy0nLmNoYXJDb2RlQXQoMClcblx0dmFyIFNMQVNIX1VSTF9TQUZFID0gJ18nLmNoYXJDb2RlQXQoMClcblxuXHRmdW5jdGlvbiBkZWNvZGUgKGVsdCkge1xuXHRcdHZhciBjb2RlID0gZWx0LmNoYXJDb2RlQXQoMClcblx0XHRpZiAoY29kZSA9PT0gUExVUyB8fFxuXHRcdCAgICBjb2RlID09PSBQTFVTX1VSTF9TQUZFKVxuXHRcdFx0cmV0dXJuIDYyIC8vICcrJ1xuXHRcdGlmIChjb2RlID09PSBTTEFTSCB8fFxuXHRcdCAgICBjb2RlID09PSBTTEFTSF9VUkxfU0FGRSlcblx0XHRcdHJldHVybiA2MyAvLyAnLydcblx0XHRpZiAoY29kZSA8IE5VTUJFUilcblx0XHRcdHJldHVybiAtMSAvL25vIG1hdGNoXG5cdFx0aWYgKGNvZGUgPCBOVU1CRVIgKyAxMClcblx0XHRcdHJldHVybiBjb2RlIC0gTlVNQkVSICsgMjYgKyAyNlxuXHRcdGlmIChjb2RlIDwgVVBQRVIgKyAyNilcblx0XHRcdHJldHVybiBjb2RlIC0gVVBQRVJcblx0XHRpZiAoY29kZSA8IExPV0VSICsgMjYpXG5cdFx0XHRyZXR1cm4gY29kZSAtIExPV0VSICsgMjZcblx0fVxuXG5cdGZ1bmN0aW9uIGI2NFRvQnl0ZUFycmF5IChiNjQpIHtcblx0XHR2YXIgaSwgaiwgbCwgdG1wLCBwbGFjZUhvbGRlcnMsIGFyclxuXG5cdFx0aWYgKGI2NC5sZW5ndGggJSA0ID4gMCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHN0cmluZy4gTGVuZ3RoIG11c3QgYmUgYSBtdWx0aXBsZSBvZiA0Jylcblx0XHR9XG5cblx0XHQvLyB0aGUgbnVtYmVyIG9mIGVxdWFsIHNpZ25zIChwbGFjZSBob2xkZXJzKVxuXHRcdC8vIGlmIHRoZXJlIGFyZSB0d28gcGxhY2Vob2xkZXJzLCB0aGFuIHRoZSB0d28gY2hhcmFjdGVycyBiZWZvcmUgaXRcblx0XHQvLyByZXByZXNlbnQgb25lIGJ5dGVcblx0XHQvLyBpZiB0aGVyZSBpcyBvbmx5IG9uZSwgdGhlbiB0aGUgdGhyZWUgY2hhcmFjdGVycyBiZWZvcmUgaXQgcmVwcmVzZW50IDIgYnl0ZXNcblx0XHQvLyB0aGlzIGlzIGp1c3QgYSBjaGVhcCBoYWNrIHRvIG5vdCBkbyBpbmRleE9mIHR3aWNlXG5cdFx0dmFyIGxlbiA9IGI2NC5sZW5ndGhcblx0XHRwbGFjZUhvbGRlcnMgPSAnPScgPT09IGI2NC5jaGFyQXQobGVuIC0gMikgPyAyIDogJz0nID09PSBiNjQuY2hhckF0KGxlbiAtIDEpID8gMSA6IDBcblxuXHRcdC8vIGJhc2U2NCBpcyA0LzMgKyB1cCB0byB0d28gY2hhcmFjdGVycyBvZiB0aGUgb3JpZ2luYWwgZGF0YVxuXHRcdGFyciA9IG5ldyBBcnIoYjY0Lmxlbmd0aCAqIDMgLyA0IC0gcGxhY2VIb2xkZXJzKVxuXG5cdFx0Ly8gaWYgdGhlcmUgYXJlIHBsYWNlaG9sZGVycywgb25seSBnZXQgdXAgdG8gdGhlIGxhc3QgY29tcGxldGUgNCBjaGFyc1xuXHRcdGwgPSBwbGFjZUhvbGRlcnMgPiAwID8gYjY0Lmxlbmd0aCAtIDQgOiBiNjQubGVuZ3RoXG5cblx0XHR2YXIgTCA9IDBcblxuXHRcdGZ1bmN0aW9uIHB1c2ggKHYpIHtcblx0XHRcdGFycltMKytdID0gdlxuXHRcdH1cblxuXHRcdGZvciAoaSA9IDAsIGogPSAwOyBpIDwgbDsgaSArPSA0LCBqICs9IDMpIHtcblx0XHRcdHRtcCA9IChkZWNvZGUoYjY0LmNoYXJBdChpKSkgPDwgMTgpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPDwgMTIpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAyKSkgPDwgNikgfCBkZWNvZGUoYjY0LmNoYXJBdChpICsgMykpXG5cdFx0XHRwdXNoKCh0bXAgJiAweEZGMDAwMCkgPj4gMTYpXG5cdFx0XHRwdXNoKCh0bXAgJiAweEZGMDApID4+IDgpXG5cdFx0XHRwdXNoKHRtcCAmIDB4RkYpXG5cdFx0fVxuXG5cdFx0aWYgKHBsYWNlSG9sZGVycyA9PT0gMikge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAyKSB8IChkZWNvZGUoYjY0LmNoYXJBdChpICsgMSkpID4+IDQpXG5cdFx0XHRwdXNoKHRtcCAmIDB4RkYpXG5cdFx0fSBlbHNlIGlmIChwbGFjZUhvbGRlcnMgPT09IDEpIHtcblx0XHRcdHRtcCA9IChkZWNvZGUoYjY0LmNoYXJBdChpKSkgPDwgMTApIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPDwgNCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDIpKSA+PiAyKVxuXHRcdFx0cHVzaCgodG1wID4+IDgpICYgMHhGRilcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9XG5cblx0XHRyZXR1cm4gYXJyXG5cdH1cblxuXHRmdW5jdGlvbiB1aW50OFRvQmFzZTY0ICh1aW50OCkge1xuXHRcdHZhciBpLFxuXHRcdFx0ZXh0cmFCeXRlcyA9IHVpbnQ4Lmxlbmd0aCAlIDMsIC8vIGlmIHdlIGhhdmUgMSBieXRlIGxlZnQsIHBhZCAyIGJ5dGVzXG5cdFx0XHRvdXRwdXQgPSBcIlwiLFxuXHRcdFx0dGVtcCwgbGVuZ3RoXG5cblx0XHRmdW5jdGlvbiBlbmNvZGUgKG51bSkge1xuXHRcdFx0cmV0dXJuIGxvb2t1cC5jaGFyQXQobnVtKVxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHRyaXBsZXRUb0Jhc2U2NCAobnVtKSB7XG5cdFx0XHRyZXR1cm4gZW5jb2RlKG51bSA+PiAxOCAmIDB4M0YpICsgZW5jb2RlKG51bSA+PiAxMiAmIDB4M0YpICsgZW5jb2RlKG51bSA+PiA2ICYgMHgzRikgKyBlbmNvZGUobnVtICYgMHgzRilcblx0XHR9XG5cblx0XHQvLyBnbyB0aHJvdWdoIHRoZSBhcnJheSBldmVyeSB0aHJlZSBieXRlcywgd2UnbGwgZGVhbCB3aXRoIHRyYWlsaW5nIHN0dWZmIGxhdGVyXG5cdFx0Zm9yIChpID0gMCwgbGVuZ3RoID0gdWludDgubGVuZ3RoIC0gZXh0cmFCeXRlczsgaSA8IGxlbmd0aDsgaSArPSAzKSB7XG5cdFx0XHR0ZW1wID0gKHVpbnQ4W2ldIDw8IDE2KSArICh1aW50OFtpICsgMV0gPDwgOCkgKyAodWludDhbaSArIDJdKVxuXHRcdFx0b3V0cHV0ICs9IHRyaXBsZXRUb0Jhc2U2NCh0ZW1wKVxuXHRcdH1cblxuXHRcdC8vIHBhZCB0aGUgZW5kIHdpdGggemVyb3MsIGJ1dCBtYWtlIHN1cmUgdG8gbm90IGZvcmdldCB0aGUgZXh0cmEgYnl0ZXNcblx0XHRzd2l0Y2ggKGV4dHJhQnl0ZXMpIHtcblx0XHRcdGNhc2UgMTpcblx0XHRcdFx0dGVtcCA9IHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDFdXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUodGVtcCA+PiAyKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wIDw8IDQpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9ICc9PSdcblx0XHRcdFx0YnJlYWtcblx0XHRcdGNhc2UgMjpcblx0XHRcdFx0dGVtcCA9ICh1aW50OFt1aW50OC5sZW5ndGggLSAyXSA8PCA4KSArICh1aW50OFt1aW50OC5sZW5ndGggLSAxXSlcblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSh0ZW1wID4+IDEwKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wID4+IDQpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSgodGVtcCA8PCAyKSAmIDB4M0YpXG5cdFx0XHRcdG91dHB1dCArPSAnPSdcblx0XHRcdFx0YnJlYWtcblx0XHR9XG5cblx0XHRyZXR1cm4gb3V0cHV0XG5cdH1cblxuXHRleHBvcnRzLnRvQnl0ZUFycmF5ID0gYjY0VG9CeXRlQXJyYXlcblx0ZXhwb3J0cy5mcm9tQnl0ZUFycmF5ID0gdWludDhUb0Jhc2U2NFxufSh0eXBlb2YgZXhwb3J0cyA9PT0gJ3VuZGVmaW5lZCcgPyAodGhpcy5iYXNlNjRqcyA9IHt9KSA6IGV4cG9ydHMpKVxuIiwiZXhwb3J0cy5yZWFkID0gZnVuY3Rpb24gKGJ1ZmZlciwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG1cbiAgdmFyIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDFcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDFcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxXG4gIHZhciBuQml0cyA9IC03XG4gIHZhciBpID0gaXNMRSA/IChuQnl0ZXMgLSAxKSA6IDBcbiAgdmFyIGQgPSBpc0xFID8gLTEgOiAxXG4gIHZhciBzID0gYnVmZmVyW29mZnNldCArIGldXG5cbiAgaSArPSBkXG5cbiAgZSA9IHMgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgcyA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gZUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBlID0gZSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIG0gPSBlICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpXG4gIGUgPj49ICgtbkJpdHMpXG4gIG5CaXRzICs9IG1MZW5cbiAgZm9yICg7IG5CaXRzID4gMDsgbSA9IG0gKiAyNTYgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cblxuICBpZiAoZSA9PT0gMCkge1xuICAgIGUgPSAxIC0gZUJpYXNcbiAgfSBlbHNlIGlmIChlID09PSBlTWF4KSB7XG4gICAgcmV0dXJuIG0gPyBOYU4gOiAoKHMgPyAtMSA6IDEpICogSW5maW5pdHkpXG4gIH0gZWxzZSB7XG4gICAgbSA9IG0gKyBNYXRoLnBvdygyLCBtTGVuKVxuICAgIGUgPSBlIC0gZUJpYXNcbiAgfVxuICByZXR1cm4gKHMgPyAtMSA6IDEpICogbSAqIE1hdGgucG93KDIsIGUgLSBtTGVuKVxufVxuXG5leHBvcnRzLndyaXRlID0gZnVuY3Rpb24gKGJ1ZmZlciwgdmFsdWUsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtLCBjXG4gIHZhciBlTGVuID0gbkJ5dGVzICogOCAtIG1MZW4gLSAxXG4gIHZhciBlTWF4ID0gKDEgPDwgZUxlbikgLSAxXG4gIHZhciBlQmlhcyA9IGVNYXggPj4gMVxuICB2YXIgcnQgPSAobUxlbiA9PT0gMjMgPyBNYXRoLnBvdygyLCAtMjQpIC0gTWF0aC5wb3coMiwgLTc3KSA6IDApXG4gIHZhciBpID0gaXNMRSA/IDAgOiAobkJ5dGVzIC0gMSlcbiAgdmFyIGQgPSBpc0xFID8gMSA6IC0xXG4gIHZhciBzID0gdmFsdWUgPCAwIHx8ICh2YWx1ZSA9PT0gMCAmJiAxIC8gdmFsdWUgPCAwKSA/IDEgOiAwXG5cbiAgdmFsdWUgPSBNYXRoLmFicyh2YWx1ZSlcblxuICBpZiAoaXNOYU4odmFsdWUpIHx8IHZhbHVlID09PSBJbmZpbml0eSkge1xuICAgIG0gPSBpc05hTih2YWx1ZSkgPyAxIDogMFxuICAgIGUgPSBlTWF4XG4gIH0gZWxzZSB7XG4gICAgZSA9IE1hdGguZmxvb3IoTWF0aC5sb2codmFsdWUpIC8gTWF0aC5MTjIpXG4gICAgaWYgKHZhbHVlICogKGMgPSBNYXRoLnBvdygyLCAtZSkpIDwgMSkge1xuICAgICAgZS0tXG4gICAgICBjICo9IDJcbiAgICB9XG4gICAgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICB2YWx1ZSArPSBydCAvIGNcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsdWUgKz0gcnQgKiBNYXRoLnBvdygyLCAxIC0gZUJpYXMpXG4gICAgfVxuICAgIGlmICh2YWx1ZSAqIGMgPj0gMikge1xuICAgICAgZSsrXG4gICAgICBjIC89IDJcbiAgICB9XG5cbiAgICBpZiAoZSArIGVCaWFzID49IGVNYXgpIHtcbiAgICAgIG0gPSAwXG4gICAgICBlID0gZU1heFxuICAgIH0gZWxzZSBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIG0gPSAodmFsdWUgKiBjIC0gMSkgKiBNYXRoLnBvdygyLCBtTGVuKVxuICAgICAgZSA9IGUgKyBlQmlhc1xuICAgIH0gZWxzZSB7XG4gICAgICBtID0gdmFsdWUgKiBNYXRoLnBvdygyLCBlQmlhcyAtIDEpICogTWF0aC5wb3coMiwgbUxlbilcbiAgICAgIGUgPSAwXG4gICAgfVxuICB9XG5cbiAgZm9yICg7IG1MZW4gPj0gODsgYnVmZmVyW29mZnNldCArIGldID0gbSAmIDB4ZmYsIGkgKz0gZCwgbSAvPSAyNTYsIG1MZW4gLT0gOCkge31cblxuICBlID0gKGUgPDwgbUxlbikgfCBtXG4gIGVMZW4gKz0gbUxlblxuICBmb3IgKDsgZUxlbiA+IDA7IGJ1ZmZlcltvZmZzZXQgKyBpXSA9IGUgJiAweGZmLCBpICs9IGQsIGUgLz0gMjU2LCBlTGVuIC09IDgpIHt9XG5cbiAgYnVmZmVyW29mZnNldCArIGkgLSBkXSB8PSBzICogMTI4XG59XG4iLCJpZiAodHlwZW9mIE9iamVjdC5jcmVhdGUgPT09ICdmdW5jdGlvbicpIHtcbiAgLy8gaW1wbGVtZW50YXRpb24gZnJvbSBzdGFuZGFyZCBub2RlLmpzICd1dGlsJyBtb2R1bGVcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIGN0b3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLCB7XG4gICAgICBjb25zdHJ1Y3Rvcjoge1xuICAgICAgICB2YWx1ZTogY3RvcixcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICBjb25maWd1cmFibGU6IHRydWVcbiAgICAgIH1cbiAgICB9KTtcbiAgfTtcbn0gZWxzZSB7XG4gIC8vIG9sZCBzY2hvb2wgc2hpbSBmb3Igb2xkIGJyb3dzZXJzXG4gIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaW5oZXJpdHMoY3Rvciwgc3VwZXJDdG9yKSB7XG4gICAgY3Rvci5zdXBlcl8gPSBzdXBlckN0b3JcbiAgICB2YXIgVGVtcEN0b3IgPSBmdW5jdGlvbiAoKSB7fVxuICAgIFRlbXBDdG9yLnByb3RvdHlwZSA9IHN1cGVyQ3Rvci5wcm90b3R5cGVcbiAgICBjdG9yLnByb3RvdHlwZSA9IG5ldyBUZW1wQ3RvcigpXG4gICAgY3Rvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBjdG9yXG4gIH1cbn1cbiIsIi8vIHNoaW0gZm9yIHVzaW5nIHByb2Nlc3MgaW4gYnJvd3NlclxuXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbnByb2Nlc3MubmV4dFRpY2sgPSAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBjYW5TZXRJbW1lZGlhdGUgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJ1xuICAgICYmIHdpbmRvdy5zZXRJbW1lZGlhdGU7XG4gICAgdmFyIGNhblBvc3QgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJ1xuICAgICYmIHdpbmRvdy5wb3N0TWVzc2FnZSAmJiB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lclxuICAgIDtcblxuICAgIGlmIChjYW5TZXRJbW1lZGlhdGUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChmKSB7IHJldHVybiB3aW5kb3cuc2V0SW1tZWRpYXRlKGYpIH07XG4gICAgfVxuXG4gICAgaWYgKGNhblBvc3QpIHtcbiAgICAgICAgdmFyIHF1ZXVlID0gW107XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgZnVuY3Rpb24gKGV2KSB7XG4gICAgICAgICAgICB2YXIgc291cmNlID0gZXYuc291cmNlO1xuICAgICAgICAgICAgaWYgKChzb3VyY2UgPT09IHdpbmRvdyB8fCBzb3VyY2UgPT09IG51bGwpICYmIGV2LmRhdGEgPT09ICdwcm9jZXNzLXRpY2snKSB7XG4gICAgICAgICAgICAgICAgZXYuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICAgICAgaWYgKHF1ZXVlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZuID0gcXVldWUuc2hpZnQoKTtcbiAgICAgICAgICAgICAgICAgICAgZm4oKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHRydWUpO1xuXG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBuZXh0VGljayhmbikge1xuICAgICAgICAgICAgcXVldWUucHVzaChmbik7XG4gICAgICAgICAgICB3aW5kb3cucG9zdE1lc3NhZ2UoJ3Byb2Nlc3MtdGljaycsICcqJyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIGZ1bmN0aW9uIG5leHRUaWNrKGZuKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZm4sIDApO1xuICAgIH07XG59KSgpO1xuXG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn1cblxuLy8gVE9ETyhzaHR5bG1hbilcbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc0J1ZmZlcihhcmcpIHtcbiAgcmV0dXJuIGFyZyAmJiB0eXBlb2YgYXJnID09PSAnb2JqZWN0J1xuICAgICYmIHR5cGVvZiBhcmcuY29weSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcuZmlsbCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcucmVhZFVJbnQ4ID09PSAnZnVuY3Rpb24nO1xufSIsIihmdW5jdGlvbiAocHJvY2VzcyxnbG9iYWwpe1xuLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbnZhciBmb3JtYXRSZWdFeHAgPSAvJVtzZGolXS9nO1xuZXhwb3J0cy5mb3JtYXQgPSBmdW5jdGlvbihmKSB7XG4gIGlmICghaXNTdHJpbmcoZikpIHtcbiAgICB2YXIgb2JqZWN0cyA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBvYmplY3RzLnB1c2goaW5zcGVjdChhcmd1bWVudHNbaV0pKTtcbiAgICB9XG4gICAgcmV0dXJuIG9iamVjdHMuam9pbignICcpO1xuICB9XG5cbiAgdmFyIGkgPSAxO1xuICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgdmFyIGxlbiA9IGFyZ3MubGVuZ3RoO1xuICB2YXIgc3RyID0gU3RyaW5nKGYpLnJlcGxhY2UoZm9ybWF0UmVnRXhwLCBmdW5jdGlvbih4KSB7XG4gICAgaWYgKHggPT09ICclJScpIHJldHVybiAnJSc7XG4gICAgaWYgKGkgPj0gbGVuKSByZXR1cm4geDtcbiAgICBzd2l0Y2ggKHgpIHtcbiAgICAgIGNhc2UgJyVzJzogcmV0dXJuIFN0cmluZyhhcmdzW2krK10pO1xuICAgICAgY2FzZSAnJWQnOiByZXR1cm4gTnVtYmVyKGFyZ3NbaSsrXSk7XG4gICAgICBjYXNlICclaic6XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGFyZ3NbaSsrXSk7XG4gICAgICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgICAgICByZXR1cm4gJ1tDaXJjdWxhcl0nO1xuICAgICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm4geDtcbiAgICB9XG4gIH0pO1xuICBmb3IgKHZhciB4ID0gYXJnc1tpXTsgaSA8IGxlbjsgeCA9IGFyZ3NbKytpXSkge1xuICAgIGlmIChpc051bGwoeCkgfHwgIWlzT2JqZWN0KHgpKSB7XG4gICAgICBzdHIgKz0gJyAnICsgeDtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyICs9ICcgJyArIGluc3BlY3QoeCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBzdHI7XG59O1xuXG5cbi8vIE1hcmsgdGhhdCBhIG1ldGhvZCBzaG91bGQgbm90IGJlIHVzZWQuXG4vLyBSZXR1cm5zIGEgbW9kaWZpZWQgZnVuY3Rpb24gd2hpY2ggd2FybnMgb25jZSBieSBkZWZhdWx0LlxuLy8gSWYgLS1uby1kZXByZWNhdGlvbiBpcyBzZXQsIHRoZW4gaXQgaXMgYSBuby1vcC5cbmV4cG9ydHMuZGVwcmVjYXRlID0gZnVuY3Rpb24oZm4sIG1zZykge1xuICAvLyBBbGxvdyBmb3IgZGVwcmVjYXRpbmcgdGhpbmdzIGluIHRoZSBwcm9jZXNzIG9mIHN0YXJ0aW5nIHVwLlxuICBpZiAoaXNVbmRlZmluZWQoZ2xvYmFsLnByb2Nlc3MpKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGV4cG9ydHMuZGVwcmVjYXRlKGZuLCBtc2cpLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfVxuXG4gIGlmIChwcm9jZXNzLm5vRGVwcmVjYXRpb24gPT09IHRydWUpIHtcbiAgICByZXR1cm4gZm47XG4gIH1cblxuICB2YXIgd2FybmVkID0gZmFsc2U7XG4gIGZ1bmN0aW9uIGRlcHJlY2F0ZWQoKSB7XG4gICAgaWYgKCF3YXJuZWQpIHtcbiAgICAgIGlmIChwcm9jZXNzLnRocm93RGVwcmVjYXRpb24pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7XG4gICAgICB9IGVsc2UgaWYgKHByb2Nlc3MudHJhY2VEZXByZWNhdGlvbikge1xuICAgICAgICBjb25zb2xlLnRyYWNlKG1zZyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zb2xlLmVycm9yKG1zZyk7XG4gICAgICB9XG4gICAgICB3YXJuZWQgPSB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIHJldHVybiBkZXByZWNhdGVkO1xufTtcblxuXG52YXIgZGVidWdzID0ge307XG52YXIgZGVidWdFbnZpcm9uO1xuZXhwb3J0cy5kZWJ1Z2xvZyA9IGZ1bmN0aW9uKHNldCkge1xuICBpZiAoaXNVbmRlZmluZWQoZGVidWdFbnZpcm9uKSlcbiAgICBkZWJ1Z0Vudmlyb24gPSBwcm9jZXNzLmVudi5OT0RFX0RFQlVHIHx8ICcnO1xuICBzZXQgPSBzZXQudG9VcHBlckNhc2UoKTtcbiAgaWYgKCFkZWJ1Z3Nbc2V0XSkge1xuICAgIGlmIChuZXcgUmVnRXhwKCdcXFxcYicgKyBzZXQgKyAnXFxcXGInLCAnaScpLnRlc3QoZGVidWdFbnZpcm9uKSkge1xuICAgICAgdmFyIHBpZCA9IHByb2Nlc3MucGlkO1xuICAgICAgZGVidWdzW3NldF0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG1zZyA9IGV4cG9ydHMuZm9ybWF0LmFwcGx5KGV4cG9ydHMsIGFyZ3VtZW50cyk7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJyVzICVkOiAlcycsIHNldCwgcGlkLCBtc2cpO1xuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVidWdzW3NldF0gPSBmdW5jdGlvbigpIHt9O1xuICAgIH1cbiAgfVxuICByZXR1cm4gZGVidWdzW3NldF07XG59O1xuXG5cbi8qKlxuICogRWNob3MgdGhlIHZhbHVlIG9mIGEgdmFsdWUuIFRyeXMgdG8gcHJpbnQgdGhlIHZhbHVlIG91dFxuICogaW4gdGhlIGJlc3Qgd2F5IHBvc3NpYmxlIGdpdmVuIHRoZSBkaWZmZXJlbnQgdHlwZXMuXG4gKlxuICogQHBhcmFtIHtPYmplY3R9IG9iaiBUaGUgb2JqZWN0IHRvIHByaW50IG91dC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIE9wdGlvbmFsIG9wdGlvbnMgb2JqZWN0IHRoYXQgYWx0ZXJzIHRoZSBvdXRwdXQuXG4gKi9cbi8qIGxlZ2FjeTogb2JqLCBzaG93SGlkZGVuLCBkZXB0aCwgY29sb3JzKi9cbmZ1bmN0aW9uIGluc3BlY3Qob2JqLCBvcHRzKSB7XG4gIC8vIGRlZmF1bHQgb3B0aW9uc1xuICB2YXIgY3R4ID0ge1xuICAgIHNlZW46IFtdLFxuICAgIHN0eWxpemU6IHN0eWxpemVOb0NvbG9yXG4gIH07XG4gIC8vIGxlZ2FjeS4uLlxuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+PSAzKSBjdHguZGVwdGggPSBhcmd1bWVudHNbMl07XG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID49IDQpIGN0eC5jb2xvcnMgPSBhcmd1bWVudHNbM107XG4gIGlmIChpc0Jvb2xlYW4ob3B0cykpIHtcbiAgICAvLyBsZWdhY3kuLi5cbiAgICBjdHguc2hvd0hpZGRlbiA9IG9wdHM7XG4gIH0gZWxzZSBpZiAob3B0cykge1xuICAgIC8vIGdvdCBhbiBcIm9wdGlvbnNcIiBvYmplY3RcbiAgICBleHBvcnRzLl9leHRlbmQoY3R4LCBvcHRzKTtcbiAgfVxuICAvLyBzZXQgZGVmYXVsdCBvcHRpb25zXG4gIGlmIChpc1VuZGVmaW5lZChjdHguc2hvd0hpZGRlbikpIGN0eC5zaG93SGlkZGVuID0gZmFsc2U7XG4gIGlmIChpc1VuZGVmaW5lZChjdHguZGVwdGgpKSBjdHguZGVwdGggPSAyO1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LmNvbG9ycykpIGN0eC5jb2xvcnMgPSBmYWxzZTtcbiAgaWYgKGlzVW5kZWZpbmVkKGN0eC5jdXN0b21JbnNwZWN0KSkgY3R4LmN1c3RvbUluc3BlY3QgPSB0cnVlO1xuICBpZiAoY3R4LmNvbG9ycykgY3R4LnN0eWxpemUgPSBzdHlsaXplV2l0aENvbG9yO1xuICByZXR1cm4gZm9ybWF0VmFsdWUoY3R4LCBvYmosIGN0eC5kZXB0aCk7XG59XG5leHBvcnRzLmluc3BlY3QgPSBpbnNwZWN0O1xuXG5cbi8vIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQU5TSV9lc2NhcGVfY29kZSNncmFwaGljc1xuaW5zcGVjdC5jb2xvcnMgPSB7XG4gICdib2xkJyA6IFsxLCAyMl0sXG4gICdpdGFsaWMnIDogWzMsIDIzXSxcbiAgJ3VuZGVybGluZScgOiBbNCwgMjRdLFxuICAnaW52ZXJzZScgOiBbNywgMjddLFxuICAnd2hpdGUnIDogWzM3LCAzOV0sXG4gICdncmV5JyA6IFs5MCwgMzldLFxuICAnYmxhY2snIDogWzMwLCAzOV0sXG4gICdibHVlJyA6IFszNCwgMzldLFxuICAnY3lhbicgOiBbMzYsIDM5XSxcbiAgJ2dyZWVuJyA6IFszMiwgMzldLFxuICAnbWFnZW50YScgOiBbMzUsIDM5XSxcbiAgJ3JlZCcgOiBbMzEsIDM5XSxcbiAgJ3llbGxvdycgOiBbMzMsIDM5XVxufTtcblxuLy8gRG9uJ3QgdXNlICdibHVlJyBub3QgdmlzaWJsZSBvbiBjbWQuZXhlXG5pbnNwZWN0LnN0eWxlcyA9IHtcbiAgJ3NwZWNpYWwnOiAnY3lhbicsXG4gICdudW1iZXInOiAneWVsbG93JyxcbiAgJ2Jvb2xlYW4nOiAneWVsbG93JyxcbiAgJ3VuZGVmaW5lZCc6ICdncmV5JyxcbiAgJ251bGwnOiAnYm9sZCcsXG4gICdzdHJpbmcnOiAnZ3JlZW4nLFxuICAnZGF0ZSc6ICdtYWdlbnRhJyxcbiAgLy8gXCJuYW1lXCI6IGludGVudGlvbmFsbHkgbm90IHN0eWxpbmdcbiAgJ3JlZ2V4cCc6ICdyZWQnXG59O1xuXG5cbmZ1bmN0aW9uIHN0eWxpemVXaXRoQ29sb3Ioc3RyLCBzdHlsZVR5cGUpIHtcbiAgdmFyIHN0eWxlID0gaW5zcGVjdC5zdHlsZXNbc3R5bGVUeXBlXTtcblxuICBpZiAoc3R5bGUpIHtcbiAgICByZXR1cm4gJ1xcdTAwMWJbJyArIGluc3BlY3QuY29sb3JzW3N0eWxlXVswXSArICdtJyArIHN0ciArXG4gICAgICAgICAgICdcXHUwMDFiWycgKyBpbnNwZWN0LmNvbG9yc1tzdHlsZV1bMV0gKyAnbSc7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHN0cjtcbiAgfVxufVxuXG5cbmZ1bmN0aW9uIHN0eWxpemVOb0NvbG9yKHN0ciwgc3R5bGVUeXBlKSB7XG4gIHJldHVybiBzdHI7XG59XG5cblxuZnVuY3Rpb24gYXJyYXlUb0hhc2goYXJyYXkpIHtcbiAgdmFyIGhhc2ggPSB7fTtcblxuICBhcnJheS5mb3JFYWNoKGZ1bmN0aW9uKHZhbCwgaWR4KSB7XG4gICAgaGFzaFt2YWxdID0gdHJ1ZTtcbiAgfSk7XG5cbiAgcmV0dXJuIGhhc2g7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0VmFsdWUoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzKSB7XG4gIC8vIFByb3ZpZGUgYSBob29rIGZvciB1c2VyLXNwZWNpZmllZCBpbnNwZWN0IGZ1bmN0aW9ucy5cbiAgLy8gQ2hlY2sgdGhhdCB2YWx1ZSBpcyBhbiBvYmplY3Qgd2l0aCBhbiBpbnNwZWN0IGZ1bmN0aW9uIG9uIGl0XG4gIGlmIChjdHguY3VzdG9tSW5zcGVjdCAmJlxuICAgICAgdmFsdWUgJiZcbiAgICAgIGlzRnVuY3Rpb24odmFsdWUuaW5zcGVjdCkgJiZcbiAgICAgIC8vIEZpbHRlciBvdXQgdGhlIHV0aWwgbW9kdWxlLCBpdCdzIGluc3BlY3QgZnVuY3Rpb24gaXMgc3BlY2lhbFxuICAgICAgdmFsdWUuaW5zcGVjdCAhPT0gZXhwb3J0cy5pbnNwZWN0ICYmXG4gICAgICAvLyBBbHNvIGZpbHRlciBvdXQgYW55IHByb3RvdHlwZSBvYmplY3RzIHVzaW5nIHRoZSBjaXJjdWxhciBjaGVjay5cbiAgICAgICEodmFsdWUuY29uc3RydWN0b3IgJiYgdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlID09PSB2YWx1ZSkpIHtcbiAgICB2YXIgcmV0ID0gdmFsdWUuaW5zcGVjdChyZWN1cnNlVGltZXMsIGN0eCk7XG4gICAgaWYgKCFpc1N0cmluZyhyZXQpKSB7XG4gICAgICByZXQgPSBmb3JtYXRWYWx1ZShjdHgsIHJldCwgcmVjdXJzZVRpbWVzKTtcbiAgICB9XG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIC8vIFByaW1pdGl2ZSB0eXBlcyBjYW5ub3QgaGF2ZSBwcm9wZXJ0aWVzXG4gIHZhciBwcmltaXRpdmUgPSBmb3JtYXRQcmltaXRpdmUoY3R4LCB2YWx1ZSk7XG4gIGlmIChwcmltaXRpdmUpIHtcbiAgICByZXR1cm4gcHJpbWl0aXZlO1xuICB9XG5cbiAgLy8gTG9vayB1cCB0aGUga2V5cyBvZiB0aGUgb2JqZWN0LlxuICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKHZhbHVlKTtcbiAgdmFyIHZpc2libGVLZXlzID0gYXJyYXlUb0hhc2goa2V5cyk7XG5cbiAgaWYgKGN0eC5zaG93SGlkZGVuKSB7XG4gICAga2V5cyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKHZhbHVlKTtcbiAgfVxuXG4gIC8vIElFIGRvZXNuJ3QgbWFrZSBlcnJvciBmaWVsZHMgbm9uLWVudW1lcmFibGVcbiAgLy8gaHR0cDovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L2llL2R3dzUyc2J0KHY9dnMuOTQpLmFzcHhcbiAgaWYgKGlzRXJyb3IodmFsdWUpXG4gICAgICAmJiAoa2V5cy5pbmRleE9mKCdtZXNzYWdlJykgPj0gMCB8fCBrZXlzLmluZGV4T2YoJ2Rlc2NyaXB0aW9uJykgPj0gMCkpIHtcbiAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICB9XG5cbiAgLy8gU29tZSB0eXBlIG9mIG9iamVjdCB3aXRob3V0IHByb3BlcnRpZXMgY2FuIGJlIHNob3J0Y3V0dGVkLlxuICBpZiAoa2V5cy5sZW5ndGggPT09IDApIHtcbiAgICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICAgIHZhciBuYW1lID0gdmFsdWUubmFtZSA/ICc6ICcgKyB2YWx1ZS5uYW1lIDogJyc7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoJ1tGdW5jdGlvbicgKyBuYW1lICsgJ10nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgICBpZiAoaXNSZWdFeHAodmFsdWUpKSB7XG4gICAgICByZXR1cm4gY3R4LnN0eWxpemUoUmVnRXhwLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSwgJ3JlZ2V4cCcpO1xuICAgIH1cbiAgICBpZiAoaXNEYXRlKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKERhdGUucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAnZGF0ZScpO1xuICAgIH1cbiAgICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBmb3JtYXRFcnJvcih2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgdmFyIGJhc2UgPSAnJywgYXJyYXkgPSBmYWxzZSwgYnJhY2VzID0gWyd7JywgJ30nXTtcblxuICAvLyBNYWtlIEFycmF5IHNheSB0aGF0IHRoZXkgYXJlIEFycmF5XG4gIGlmIChpc0FycmF5KHZhbHVlKSkge1xuICAgIGFycmF5ID0gdHJ1ZTtcbiAgICBicmFjZXMgPSBbJ1snLCAnXSddO1xuICB9XG5cbiAgLy8gTWFrZSBmdW5jdGlvbnMgc2F5IHRoYXQgdGhleSBhcmUgZnVuY3Rpb25zXG4gIGlmIChpc0Z1bmN0aW9uKHZhbHVlKSkge1xuICAgIHZhciBuID0gdmFsdWUubmFtZSA/ICc6ICcgKyB2YWx1ZS5uYW1lIDogJyc7XG4gICAgYmFzZSA9ICcgW0Z1bmN0aW9uJyArIG4gKyAnXSc7XG4gIH1cblxuICAvLyBNYWtlIFJlZ0V4cHMgc2F5IHRoYXQgdGhleSBhcmUgUmVnRXhwc1xuICBpZiAoaXNSZWdFeHAodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gIH1cblxuICAvLyBNYWtlIGRhdGVzIHdpdGggcHJvcGVydGllcyBmaXJzdCBzYXkgdGhlIGRhdGVcbiAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICBiYXNlID0gJyAnICsgRGF0ZS5wcm90b3R5cGUudG9VVENTdHJpbmcuY2FsbCh2YWx1ZSk7XG4gIH1cblxuICAvLyBNYWtlIGVycm9yIHdpdGggbWVzc2FnZSBmaXJzdCBzYXkgdGhlIGVycm9yXG4gIGlmIChpc0Vycm9yKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBmb3JtYXRFcnJvcih2YWx1ZSk7XG4gIH1cblxuICBpZiAoa2V5cy5sZW5ndGggPT09IDAgJiYgKCFhcnJheSB8fCB2YWx1ZS5sZW5ndGggPT0gMCkpIHtcbiAgICByZXR1cm4gYnJhY2VzWzBdICsgYmFzZSArIGJyYWNlc1sxXTtcbiAgfVxuXG4gIGlmIChyZWN1cnNlVGltZXMgPCAwKSB7XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbT2JqZWN0XScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9XG5cbiAgY3R4LnNlZW4ucHVzaCh2YWx1ZSk7XG5cbiAgdmFyIG91dHB1dDtcbiAgaWYgKGFycmF5KSB7XG4gICAgb3V0cHV0ID0gZm9ybWF0QXJyYXkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5cyk7XG4gIH0gZWxzZSB7XG4gICAgb3V0cHV0ID0ga2V5cy5tYXAoZnVuY3Rpb24oa2V5KSB7XG4gICAgICByZXR1cm4gZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5LCBhcnJheSk7XG4gICAgfSk7XG4gIH1cblxuICBjdHguc2Vlbi5wb3AoKTtcblxuICByZXR1cm4gcmVkdWNlVG9TaW5nbGVTdHJpbmcob3V0cHV0LCBiYXNlLCBicmFjZXMpO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFByaW1pdGl2ZShjdHgsIHZhbHVlKSB7XG4gIGlmIChpc1VuZGVmaW5lZCh2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCd1bmRlZmluZWQnLCAndW5kZWZpbmVkJyk7XG4gIGlmIChpc1N0cmluZyh2YWx1ZSkpIHtcbiAgICB2YXIgc2ltcGxlID0gJ1xcJycgKyBKU09OLnN0cmluZ2lmeSh2YWx1ZSkucmVwbGFjZSgvXlwifFwiJC9nLCAnJylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKC8nL2csIFwiXFxcXCdcIilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXCIvZywgJ1wiJykgKyAnXFwnJztcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoc2ltcGxlLCAnc3RyaW5nJyk7XG4gIH1cbiAgaWYgKGlzTnVtYmVyKHZhbHVlKSlcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoJycgKyB2YWx1ZSwgJ251bWJlcicpO1xuICBpZiAoaXNCb29sZWFuKHZhbHVlKSlcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoJycgKyB2YWx1ZSwgJ2Jvb2xlYW4nKTtcbiAgLy8gRm9yIHNvbWUgcmVhc29uIHR5cGVvZiBudWxsIGlzIFwib2JqZWN0XCIsIHNvIHNwZWNpYWwgY2FzZSBoZXJlLlxuICBpZiAoaXNOdWxsKHZhbHVlKSlcbiAgICByZXR1cm4gY3R4LnN0eWxpemUoJ251bGwnLCAnbnVsbCcpO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEVycm9yKHZhbHVlKSB7XG4gIHJldHVybiAnWycgKyBFcnJvci5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgKyAnXSc7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0QXJyYXkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5cykge1xuICB2YXIgb3V0cHV0ID0gW107XG4gIGZvciAodmFyIGkgPSAwLCBsID0gdmFsdWUubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgaWYgKGhhc093blByb3BlcnR5KHZhbHVlLCBTdHJpbmcoaSkpKSB7XG4gICAgICBvdXRwdXQucHVzaChmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLFxuICAgICAgICAgIFN0cmluZyhpKSwgdHJ1ZSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBvdXRwdXQucHVzaCgnJyk7XG4gICAgfVxuICB9XG4gIGtleXMuZm9yRWFjaChmdW5jdGlvbihrZXkpIHtcbiAgICBpZiAoIWtleS5tYXRjaCgvXlxcZCskLykpIHtcbiAgICAgIG91dHB1dC5wdXNoKGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsXG4gICAgICAgICAga2V5LCB0cnVlKSk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIG91dHB1dDtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLCBrZXksIGFycmF5KSB7XG4gIHZhciBuYW1lLCBzdHIsIGRlc2M7XG4gIGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHZhbHVlLCBrZXkpIHx8IHsgdmFsdWU6IHZhbHVlW2tleV0gfTtcbiAgaWYgKGRlc2MuZ2V0KSB7XG4gICAgaWYgKGRlc2Muc2V0KSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW0dldHRlci9TZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKGRlc2Muc2V0KSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW1NldHRlcl0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuICBpZiAoIWhhc093blByb3BlcnR5KHZpc2libGVLZXlzLCBrZXkpKSB7XG4gICAgbmFtZSA9ICdbJyArIGtleSArICddJztcbiAgfVxuICBpZiAoIXN0cikge1xuICAgIGlmIChjdHguc2Vlbi5pbmRleE9mKGRlc2MudmFsdWUpIDwgMCkge1xuICAgICAgaWYgKGlzTnVsbChyZWN1cnNlVGltZXMpKSB7XG4gICAgICAgIHN0ciA9IGZvcm1hdFZhbHVlKGN0eCwgZGVzYy52YWx1ZSwgbnVsbCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdHIgPSBmb3JtYXRWYWx1ZShjdHgsIGRlc2MudmFsdWUsIHJlY3Vyc2VUaW1lcyAtIDEpO1xuICAgICAgfVxuICAgICAgaWYgKHN0ci5pbmRleE9mKCdcXG4nKSA+IC0xKSB7XG4gICAgICAgIGlmIChhcnJheSkge1xuICAgICAgICAgIHN0ciA9IHN0ci5zcGxpdCgnXFxuJykubWFwKGZ1bmN0aW9uKGxpbmUpIHtcbiAgICAgICAgICAgIHJldHVybiAnICAnICsgbGluZTtcbiAgICAgICAgICB9KS5qb2luKCdcXG4nKS5zdWJzdHIoMik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc3RyID0gJ1xcbicgKyBzdHIuc3BsaXQoJ1xcbicpLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICByZXR1cm4gJyAgICcgKyBsaW5lO1xuICAgICAgICAgIH0pLmpvaW4oJ1xcbicpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbQ2lyY3VsYXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH1cbiAgaWYgKGlzVW5kZWZpbmVkKG5hbWUpKSB7XG4gICAgaWYgKGFycmF5ICYmIGtleS5tYXRjaCgvXlxcZCskLykpIHtcbiAgICAgIHJldHVybiBzdHI7XG4gICAgfVxuICAgIG5hbWUgPSBKU09OLnN0cmluZ2lmeSgnJyArIGtleSk7XG4gICAgaWYgKG5hbWUubWF0Y2goL15cIihbYS16QS1aX11bYS16QS1aXzAtOV0qKVwiJC8pKSB7XG4gICAgICBuYW1lID0gbmFtZS5zdWJzdHIoMSwgbmFtZS5sZW5ndGggLSAyKTtcbiAgICAgIG5hbWUgPSBjdHguc3R5bGl6ZShuYW1lLCAnbmFtZScpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuYW1lID0gbmFtZS5yZXBsYWNlKC8nL2csIFwiXFxcXCdcIilcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoL1xcXFxcIi9nLCAnXCInKVxuICAgICAgICAgICAgICAgICAucmVwbGFjZSgvKF5cInxcIiQpL2csIFwiJ1wiKTtcbiAgICAgIG5hbWUgPSBjdHguc3R5bGl6ZShuYW1lLCAnc3RyaW5nJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5hbWUgKyAnOiAnICsgc3RyO1xufVxuXG5cbmZ1bmN0aW9uIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKSB7XG4gIHZhciBudW1MaW5lc0VzdCA9IDA7XG4gIHZhciBsZW5ndGggPSBvdXRwdXQucmVkdWNlKGZ1bmN0aW9uKHByZXYsIGN1cikge1xuICAgIG51bUxpbmVzRXN0Kys7XG4gICAgaWYgKGN1ci5pbmRleE9mKCdcXG4nKSA+PSAwKSBudW1MaW5lc0VzdCsrO1xuICAgIHJldHVybiBwcmV2ICsgY3VyLnJlcGxhY2UoL1xcdTAwMWJcXFtcXGRcXGQ/bS9nLCAnJykubGVuZ3RoICsgMTtcbiAgfSwgMCk7XG5cbiAgaWYgKGxlbmd0aCA+IDYwKSB7XG4gICAgcmV0dXJuIGJyYWNlc1swXSArXG4gICAgICAgICAgIChiYXNlID09PSAnJyA/ICcnIDogYmFzZSArICdcXG4gJykgK1xuICAgICAgICAgICAnICcgK1xuICAgICAgICAgICBvdXRwdXQuam9pbignLFxcbiAgJykgK1xuICAgICAgICAgICAnICcgK1xuICAgICAgICAgICBicmFjZXNbMV07XG4gIH1cblxuICByZXR1cm4gYnJhY2VzWzBdICsgYmFzZSArICcgJyArIG91dHB1dC5qb2luKCcsICcpICsgJyAnICsgYnJhY2VzWzFdO1xufVxuXG5cbi8vIE5PVEU6IFRoZXNlIHR5cGUgY2hlY2tpbmcgZnVuY3Rpb25zIGludGVudGlvbmFsbHkgZG9uJ3QgdXNlIGBpbnN0YW5jZW9mYFxuLy8gYmVjYXVzZSBpdCBpcyBmcmFnaWxlIGFuZCBjYW4gYmUgZWFzaWx5IGZha2VkIHdpdGggYE9iamVjdC5jcmVhdGUoKWAuXG5mdW5jdGlvbiBpc0FycmF5KGFyKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KGFyKTtcbn1cbmV4cG9ydHMuaXNBcnJheSA9IGlzQXJyYXk7XG5cbmZ1bmN0aW9uIGlzQm9vbGVhbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdib29sZWFuJztcbn1cbmV4cG9ydHMuaXNCb29sZWFuID0gaXNCb29sZWFuO1xuXG5mdW5jdGlvbiBpc051bGwoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IG51bGw7XG59XG5leHBvcnRzLmlzTnVsbCA9IGlzTnVsbDtcblxuZnVuY3Rpb24gaXNOdWxsT3JVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT0gbnVsbDtcbn1cbmV4cG9ydHMuaXNOdWxsT3JVbmRlZmluZWQgPSBpc051bGxPclVuZGVmaW5lZDtcblxuZnVuY3Rpb24gaXNOdW1iZXIoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnbnVtYmVyJztcbn1cbmV4cG9ydHMuaXNOdW1iZXIgPSBpc051bWJlcjtcblxuZnVuY3Rpb24gaXNTdHJpbmcoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnc3RyaW5nJztcbn1cbmV4cG9ydHMuaXNTdHJpbmcgPSBpc1N0cmluZztcblxuZnVuY3Rpb24gaXNTeW1ib2woYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnc3ltYm9sJztcbn1cbmV4cG9ydHMuaXNTeW1ib2wgPSBpc1N5bWJvbDtcblxuZnVuY3Rpb24gaXNVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IHZvaWQgMDtcbn1cbmV4cG9ydHMuaXNVbmRlZmluZWQgPSBpc1VuZGVmaW5lZDtcblxuZnVuY3Rpb24gaXNSZWdFeHAocmUpIHtcbiAgcmV0dXJuIGlzT2JqZWN0KHJlKSAmJiBvYmplY3RUb1N0cmluZyhyZSkgPT09ICdbb2JqZWN0IFJlZ0V4cF0nO1xufVxuZXhwb3J0cy5pc1JlZ0V4cCA9IGlzUmVnRXhwO1xuXG5mdW5jdGlvbiBpc09iamVjdChhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdvYmplY3QnICYmIGFyZyAhPT0gbnVsbDtcbn1cbmV4cG9ydHMuaXNPYmplY3QgPSBpc09iamVjdDtcblxuZnVuY3Rpb24gaXNEYXRlKGQpIHtcbiAgcmV0dXJuIGlzT2JqZWN0KGQpICYmIG9iamVjdFRvU3RyaW5nKGQpID09PSAnW29iamVjdCBEYXRlXSc7XG59XG5leHBvcnRzLmlzRGF0ZSA9IGlzRGF0ZTtcblxuZnVuY3Rpb24gaXNFcnJvcihlKSB7XG4gIHJldHVybiBpc09iamVjdChlKSAmJlxuICAgICAgKG9iamVjdFRvU3RyaW5nKGUpID09PSAnW29iamVjdCBFcnJvcl0nIHx8IGUgaW5zdGFuY2VvZiBFcnJvcik7XG59XG5leHBvcnRzLmlzRXJyb3IgPSBpc0Vycm9yO1xuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ2Z1bmN0aW9uJztcbn1cbmV4cG9ydHMuaXNGdW5jdGlvbiA9IGlzRnVuY3Rpb247XG5cbmZ1bmN0aW9uIGlzUHJpbWl0aXZlKGFyZykge1xuICByZXR1cm4gYXJnID09PSBudWxsIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnYm9vbGVhbicgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdudW1iZXInIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnc3RyaW5nJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcgfHwgIC8vIEVTNiBzeW1ib2xcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICd1bmRlZmluZWQnO1xufVxuZXhwb3J0cy5pc1ByaW1pdGl2ZSA9IGlzUHJpbWl0aXZlO1xuXG5leHBvcnRzLmlzQnVmZmVyID0gcmVxdWlyZSgnLi9zdXBwb3J0L2lzQnVmZmVyJyk7XG5cbmZ1bmN0aW9uIG9iamVjdFRvU3RyaW5nKG8pIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKTtcbn1cblxuXG5mdW5jdGlvbiBwYWQobikge1xuICByZXR1cm4gbiA8IDEwID8gJzAnICsgbi50b1N0cmluZygxMCkgOiBuLnRvU3RyaW5nKDEwKTtcbn1cblxuXG52YXIgbW9udGhzID0gWydKYW4nLCAnRmViJywgJ01hcicsICdBcHInLCAnTWF5JywgJ0p1bicsICdKdWwnLCAnQXVnJywgJ1NlcCcsXG4gICAgICAgICAgICAgICdPY3QnLCAnTm92JywgJ0RlYyddO1xuXG4vLyAyNiBGZWIgMTY6MTk6MzRcbmZ1bmN0aW9uIHRpbWVzdGFtcCgpIHtcbiAgdmFyIGQgPSBuZXcgRGF0ZSgpO1xuICB2YXIgdGltZSA9IFtwYWQoZC5nZXRIb3VycygpKSxcbiAgICAgICAgICAgICAgcGFkKGQuZ2V0TWludXRlcygpKSxcbiAgICAgICAgICAgICAgcGFkKGQuZ2V0U2Vjb25kcygpKV0uam9pbignOicpO1xuICByZXR1cm4gW2QuZ2V0RGF0ZSgpLCBtb250aHNbZC5nZXRNb250aCgpXSwgdGltZV0uam9pbignICcpO1xufVxuXG5cbi8vIGxvZyBpcyBqdXN0IGEgdGhpbiB3cmFwcGVyIHRvIGNvbnNvbGUubG9nIHRoYXQgcHJlcGVuZHMgYSB0aW1lc3RhbXBcbmV4cG9ydHMubG9nID0gZnVuY3Rpb24oKSB7XG4gIGNvbnNvbGUubG9nKCclcyAtICVzJywgdGltZXN0YW1wKCksIGV4cG9ydHMuZm9ybWF0LmFwcGx5KGV4cG9ydHMsIGFyZ3VtZW50cykpO1xufTtcblxuXG4vKipcbiAqIEluaGVyaXQgdGhlIHByb3RvdHlwZSBtZXRob2RzIGZyb20gb25lIGNvbnN0cnVjdG9yIGludG8gYW5vdGhlci5cbiAqXG4gKiBUaGUgRnVuY3Rpb24ucHJvdG90eXBlLmluaGVyaXRzIGZyb20gbGFuZy5qcyByZXdyaXR0ZW4gYXMgYSBzdGFuZGFsb25lXG4gKiBmdW5jdGlvbiAobm90IG9uIEZ1bmN0aW9uLnByb3RvdHlwZSkuIE5PVEU6IElmIHRoaXMgZmlsZSBpcyB0byBiZSBsb2FkZWRcbiAqIGR1cmluZyBib290c3RyYXBwaW5nIHRoaXMgZnVuY3Rpb24gbmVlZHMgdG8gYmUgcmV3cml0dGVuIHVzaW5nIHNvbWUgbmF0aXZlXG4gKiBmdW5jdGlvbnMgYXMgcHJvdG90eXBlIHNldHVwIHVzaW5nIG5vcm1hbCBKYXZhU2NyaXB0IGRvZXMgbm90IHdvcmsgYXNcbiAqIGV4cGVjdGVkIGR1cmluZyBib290c3RyYXBwaW5nIChzZWUgbWlycm9yLmpzIGluIHIxMTQ5MDMpLlxuICpcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGN0b3IgQ29uc3RydWN0b3IgZnVuY3Rpb24gd2hpY2ggbmVlZHMgdG8gaW5oZXJpdCB0aGVcbiAqICAgICBwcm90b3R5cGUuXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBzdXBlckN0b3IgQ29uc3RydWN0b3IgZnVuY3Rpb24gdG8gaW5oZXJpdCBwcm90b3R5cGUgZnJvbS5cbiAqL1xuZXhwb3J0cy5pbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG5cbmV4cG9ydHMuX2V4dGVuZCA9IGZ1bmN0aW9uKG9yaWdpbiwgYWRkKSB7XG4gIC8vIERvbid0IGRvIGFueXRoaW5nIGlmIGFkZCBpc24ndCBhbiBvYmplY3RcbiAgaWYgKCFhZGQgfHwgIWlzT2JqZWN0KGFkZCkpIHJldHVybiBvcmlnaW47XG5cbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyhhZGQpO1xuICB2YXIgaSA9IGtleXMubGVuZ3RoO1xuICB3aGlsZSAoaS0tKSB7XG4gICAgb3JpZ2luW2tleXNbaV1dID0gYWRkW2tleXNbaV1dO1xuICB9XG4gIHJldHVybiBvcmlnaW47XG59O1xuXG5mdW5jdGlvbiBoYXNPd25Qcm9wZXJ0eShvYmosIHByb3ApIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3ApO1xufVxuXG59KS5jYWxsKHRoaXMscmVxdWlyZShcIjFZaVo1U1wiKSx0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pIiwiKGZ1bmN0aW9uIChzaW5vbkNoYWkpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIC8vIE1vZHVsZSBzeXN0ZW1zIG1hZ2ljIGRhbmNlLlxuXG4gICAgLyogaXN0YW5idWwgaWdub3JlIGVsc2UgKi9cbiAgICBpZiAodHlwZW9mIHJlcXVpcmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZXhwb3J0cyA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIC8vIE5vZGVKU1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHNpbm9uQ2hhaTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIC8vIEFNRFxuICAgICAgICBkZWZpbmUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHNpbm9uQ2hhaTtcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gT3RoZXIgZW52aXJvbm1lbnQgKHVzdWFsbHkgPHNjcmlwdD4gdGFnKTogcGx1ZyBpbiB0byBnbG9iYWwgY2hhaSBpbnN0YW5jZSBkaXJlY3RseS5cbiAgICAgICAgY2hhaS51c2Uoc2lub25DaGFpKTtcbiAgICB9XG59KGZ1bmN0aW9uIHNpbm9uQ2hhaShjaGFpLCB1dGlscykge1xuICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgdmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xuXG4gICAgZnVuY3Rpb24gaXNTcHkocHV0YXRpdmVTcHkpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBwdXRhdGl2ZVNweSA9PT0gXCJmdW5jdGlvblwiICYmXG4gICAgICAgICAgICAgICB0eXBlb2YgcHV0YXRpdmVTcHkuZ2V0Q2FsbCA9PT0gXCJmdW5jdGlvblwiICYmXG4gICAgICAgICAgICAgICB0eXBlb2YgcHV0YXRpdmVTcHkuY2FsbGVkV2l0aEV4YWN0bHkgPT09IFwiZnVuY3Rpb25cIjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0aW1lc0luV29yZHMoY291bnQpIHtcbiAgICAgICAgcmV0dXJuIGNvdW50ID09PSAxID8gXCJvbmNlXCIgOlxuICAgICAgICAgICAgICAgY291bnQgPT09IDIgPyBcInR3aWNlXCIgOlxuICAgICAgICAgICAgICAgY291bnQgPT09IDMgPyBcInRocmljZVwiIDpcbiAgICAgICAgICAgICAgIChjb3VudCB8fCAwKSArIFwiIHRpbWVzXCI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNDYWxsKHB1dGF0aXZlQ2FsbCkge1xuICAgICAgICByZXR1cm4gcHV0YXRpdmVDYWxsICYmIGlzU3B5KHB1dGF0aXZlQ2FsbC5wcm94eSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXNzZXJ0Q2FuV29ya1dpdGgoYXNzZXJ0aW9uKSB7XG4gICAgICAgIGlmICghaXNTcHkoYXNzZXJ0aW9uLl9vYmopICYmICFpc0NhbGwoYXNzZXJ0aW9uLl9vYmopKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKHV0aWxzLmluc3BlY3QoYXNzZXJ0aW9uLl9vYmopICsgXCIgaXMgbm90IGEgc3B5IG9yIGEgY2FsbCB0byBhIHNweSFcIik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRNZXNzYWdlcyhzcHksIGFjdGlvbiwgbm9uTmVnYXRlZFN1ZmZpeCwgYWx3YXlzLCBhcmdzKSB7XG4gICAgICAgIHZhciB2ZXJiUGhyYXNlID0gYWx3YXlzID8gXCJhbHdheXMgaGF2ZSBcIiA6IFwiaGF2ZSBcIjtcbiAgICAgICAgbm9uTmVnYXRlZFN1ZmZpeCA9IG5vbk5lZ2F0ZWRTdWZmaXggfHwgXCJcIjtcbiAgICAgICAgaWYgKGlzU3B5KHNweS5wcm94eSkpIHtcbiAgICAgICAgICAgIHNweSA9IHNweS5wcm94eTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHByaW50ZkFycmF5KGFycmF5KSB7XG4gICAgICAgICAgICByZXR1cm4gc3B5LnByaW50Zi5hcHBseShzcHksIGFycmF5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBhZmZpcm1hdGl2ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBwcmludGZBcnJheShbXCJleHBlY3RlZCAlbiB0byBcIiArIHZlcmJQaHJhc2UgKyBhY3Rpb24gKyBub25OZWdhdGVkU3VmZml4XS5jb25jYXQoYXJncykpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5lZ2F0aXZlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByaW50ZkFycmF5KFtcImV4cGVjdGVkICVuIHRvIG5vdCBcIiArIHZlcmJQaHJhc2UgKyBhY3Rpb25dLmNvbmNhdChhcmdzKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2lub25Qcm9wZXJ0eShuYW1lLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgpIHtcbiAgICAgICAgdXRpbHMuYWRkUHJvcGVydHkoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCBuYW1lLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBhc3NlcnRDYW5Xb3JrV2l0aCh0aGlzKTtcblxuICAgICAgICAgICAgdmFyIG1lc3NhZ2VzID0gZ2V0TWVzc2FnZXModGhpcy5fb2JqLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgsIGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMuYXNzZXJ0KHRoaXMuX29ialtuYW1lXSwgbWVzc2FnZXMuYWZmaXJtYXRpdmUsIG1lc3NhZ2VzLm5lZ2F0aXZlKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2lub25Qcm9wZXJ0eUFzQm9vbGVhbk1ldGhvZChuYW1lLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgpIHtcbiAgICAgICAgdXRpbHMuYWRkTWV0aG9kKGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZSwgbmFtZSwgZnVuY3Rpb24gKGFyZykge1xuICAgICAgICAgICAgYXNzZXJ0Q2FuV29ya1dpdGgodGhpcyk7XG5cbiAgICAgICAgICAgIHZhciBtZXNzYWdlcyA9IGdldE1lc3NhZ2VzKHRoaXMuX29iaiwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4LCBmYWxzZSwgW3RpbWVzSW5Xb3JkcyhhcmcpXSk7XG4gICAgICAgICAgICB0aGlzLmFzc2VydCh0aGlzLl9vYmpbbmFtZV0gPT09IGFyZywgbWVzc2FnZXMuYWZmaXJtYXRpdmUsIG1lc3NhZ2VzLm5lZ2F0aXZlKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlU2lub25NZXRob2RIYW5kbGVyKHNpbm9uTmFtZSwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4KSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBhc3NlcnRDYW5Xb3JrV2l0aCh0aGlzKTtcblxuICAgICAgICAgICAgdmFyIGFsd2F5c1Npbm9uTWV0aG9kID0gXCJhbHdheXNcIiArIHNpbm9uTmFtZVswXS50b1VwcGVyQ2FzZSgpICsgc2lub25OYW1lLnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgIHZhciBzaG91bGRCZUFsd2F5cyA9IHV0aWxzLmZsYWcodGhpcywgXCJhbHdheXNcIikgJiYgdHlwZW9mIHRoaXMuX29ialthbHdheXNTaW5vbk1ldGhvZF0gPT09IFwiZnVuY3Rpb25cIjtcbiAgICAgICAgICAgIHZhciBzaW5vbk1ldGhvZCA9IHNob3VsZEJlQWx3YXlzID8gYWx3YXlzU2lub25NZXRob2QgOiBzaW5vbk5hbWU7XG5cbiAgICAgICAgICAgIHZhciBtZXNzYWdlcyA9IGdldE1lc3NhZ2VzKHRoaXMuX29iaiwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4LCBzaG91bGRCZUFsd2F5cywgc2xpY2UuY2FsbChhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIHRoaXMuYXNzZXJ0KHRoaXMuX29ialtzaW5vbk1ldGhvZF0uYXBwbHkodGhpcy5fb2JqLCBhcmd1bWVudHMpLCBtZXNzYWdlcy5hZmZpcm1hdGl2ZSwgbWVzc2FnZXMubmVnYXRpdmUpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNpbm9uTWV0aG9kQXNQcm9wZXJ0eShuYW1lLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgpIHtcbiAgICAgICAgdmFyIGhhbmRsZXIgPSBjcmVhdGVTaW5vbk1ldGhvZEhhbmRsZXIobmFtZSwgYWN0aW9uLCBub25OZWdhdGVkU3VmZml4KTtcbiAgICAgICAgdXRpbHMuYWRkUHJvcGVydHkoY2hhaS5Bc3NlcnRpb24ucHJvdG90eXBlLCBuYW1lLCBoYW5kbGVyKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBleGNlcHRpb25hbFNpbm9uTWV0aG9kKGNoYWlOYW1lLCBzaW5vbk5hbWUsIGFjdGlvbiwgbm9uTmVnYXRlZFN1ZmZpeCkge1xuICAgICAgICB2YXIgaGFuZGxlciA9IGNyZWF0ZVNpbm9uTWV0aG9kSGFuZGxlcihzaW5vbk5hbWUsIGFjdGlvbiwgbm9uTmVnYXRlZFN1ZmZpeCk7XG4gICAgICAgIHV0aWxzLmFkZE1ldGhvZChjaGFpLkFzc2VydGlvbi5wcm90b3R5cGUsIGNoYWlOYW1lLCBoYW5kbGVyKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzaW5vbk1ldGhvZChuYW1lLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgpIHtcbiAgICAgICAgZXhjZXB0aW9uYWxTaW5vbk1ldGhvZChuYW1lLCBuYW1lLCBhY3Rpb24sIG5vbk5lZ2F0ZWRTdWZmaXgpO1xuICAgIH1cblxuICAgIHV0aWxzLmFkZFByb3BlcnR5KGNoYWkuQXNzZXJ0aW9uLnByb3RvdHlwZSwgXCJhbHdheXNcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICB1dGlscy5mbGFnKHRoaXMsIFwiYWx3YXlzXCIsIHRydWUpO1xuICAgIH0pO1xuXG4gICAgc2lub25Qcm9wZXJ0eShcImNhbGxlZFwiLCBcImJlZW4gY2FsbGVkXCIsIFwiIGF0IGxlYXN0IG9uY2UsIGJ1dCBpdCB3YXMgbmV2ZXIgY2FsbGVkXCIpO1xuICAgIHNpbm9uUHJvcGVydHlBc0Jvb2xlYW5NZXRob2QoXCJjYWxsQ291bnRcIiwgXCJiZWVuIGNhbGxlZCBleGFjdGx5ICUxXCIsIFwiLCBidXQgaXQgd2FzIGNhbGxlZCAlYyVDXCIpO1xuICAgIHNpbm9uUHJvcGVydHkoXCJjYWxsZWRPbmNlXCIsIFwiYmVlbiBjYWxsZWQgZXhhY3RseSBvbmNlXCIsIFwiLCBidXQgaXQgd2FzIGNhbGxlZCAlYyVDXCIpO1xuICAgIHNpbm9uUHJvcGVydHkoXCJjYWxsZWRUd2ljZVwiLCBcImJlZW4gY2FsbGVkIGV4YWN0bHkgdHdpY2VcIiwgXCIsIGJ1dCBpdCB3YXMgY2FsbGVkICVjJUNcIik7XG4gICAgc2lub25Qcm9wZXJ0eShcImNhbGxlZFRocmljZVwiLCBcImJlZW4gY2FsbGVkIGV4YWN0bHkgdGhyaWNlXCIsIFwiLCBidXQgaXQgd2FzIGNhbGxlZCAlYyVDXCIpO1xuICAgIHNpbm9uTWV0aG9kQXNQcm9wZXJ0eShcImNhbGxlZFdpdGhOZXdcIiwgXCJiZWVuIGNhbGxlZCB3aXRoIG5ld1wiKTtcbiAgICBzaW5vbk1ldGhvZChcImNhbGxlZEJlZm9yZVwiLCBcImJlZW4gY2FsbGVkIGJlZm9yZSAlMVwiKTtcbiAgICBzaW5vbk1ldGhvZChcImNhbGxlZEFmdGVyXCIsIFwiYmVlbiBjYWxsZWQgYWZ0ZXIgJTFcIik7XG4gICAgc2lub25NZXRob2QoXCJjYWxsZWRPblwiLCBcImJlZW4gY2FsbGVkIHdpdGggJTEgYXMgdGhpc1wiLCBcIiwgYnV0IGl0IHdhcyBjYWxsZWQgd2l0aCAldCBpbnN0ZWFkXCIpO1xuICAgIHNpbm9uTWV0aG9kKFwiY2FsbGVkV2l0aFwiLCBcImJlZW4gY2FsbGVkIHdpdGggYXJndW1lbnRzICUqXCIsIFwiJUNcIik7XG4gICAgc2lub25NZXRob2QoXCJjYWxsZWRXaXRoRXhhY3RseVwiLCBcImJlZW4gY2FsbGVkIHdpdGggZXhhY3QgYXJndW1lbnRzICUqXCIsIFwiJUNcIik7XG4gICAgc2lub25NZXRob2QoXCJjYWxsZWRXaXRoTWF0Y2hcIiwgXCJiZWVuIGNhbGxlZCB3aXRoIGFyZ3VtZW50cyBtYXRjaGluZyAlKlwiLCBcIiVDXCIpO1xuICAgIHNpbm9uTWV0aG9kKFwicmV0dXJuZWRcIiwgXCJyZXR1cm5lZCAlMVwiKTtcbiAgICBleGNlcHRpb25hbFNpbm9uTWV0aG9kKFwidGhyb3duXCIsIFwidGhyZXdcIiwgXCJ0aHJvd24gJTFcIik7XG59KSk7XG4iLCIvKipcbiAqIFNpbm9uIGNvcmUgdXRpbGl0aWVzLiBGb3IgaW50ZXJuYWwgdXNlIG9ubHkuXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciBzaW5vbiA9IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNpbm9uO1xuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICBzaW5vbiA9IG1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcIi4vc2lub24vdXRpbC9jb3JlXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9zaW5vbi9leHRlbmRcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3Npbm9uL3R5cGVPZlwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vdGltZXNfaW5fd29yZHNcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3Npbm9uL3NweVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vY2FsbFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vYmVoYXZpb3JcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3Npbm9uL3N0dWJcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3Npbm9uL21vY2tcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3Npbm9uL2NvbGxlY3Rpb25cIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3Npbm9uL2Fzc2VydFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vc2FuZGJveFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vdGVzdFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vdGVzdF9jYXNlXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9zaW5vbi9tYXRjaFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc2lub24vZm9ybWF0XCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9zaW5vbi9sb2dfZXJyb3JcIik7XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgICAgICBzaW5vbiA9IG1vZHVsZS5leHBvcnRzO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHNpbm9uID0ge307XG4gICAgfVxuXG4gICAgcmV0dXJuIHNpbm9uO1xufSgpKTtcbiIsIihmdW5jdGlvbiAoZ2xvYmFsKXtcbi8qKlxuICogQGRlcGVuZCB0aW1lc19pbl93b3Jkcy5qc1xuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqIEBkZXBlbmQgbWF0Y2guanNcbiAqIEBkZXBlbmQgZm9ybWF0LmpzXG4gKi9cbi8qKlxuICogQXNzZXJ0aW9ucyBtYXRjaGluZyB0aGUgdGVzdCBzcHkgcmV0cmlldmFsIGludGVyZmFjZS5cbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbiwgZ2xvYmFsKSB7XG4gICAgdmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xuXG4gICAgZnVuY3Rpb24gbWFrZUFwaShzaW5vbikge1xuICAgICAgICB2YXIgYXNzZXJ0O1xuXG4gICAgICAgIGZ1bmN0aW9uIHZlcmlmeUlzU3R1YigpIHtcbiAgICAgICAgICAgIHZhciBtZXRob2Q7XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gYXJndW1lbnRzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgICAgIG1ldGhvZCA9IGFyZ3VtZW50c1tpXTtcblxuICAgICAgICAgICAgICAgIGlmICghbWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5mYWlsKFwiZmFrZSBpcyBub3QgYSBzcHlcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG1ldGhvZC5wcm94eSAmJiBtZXRob2QucHJveHkuaXNTaW5vblByb3h5KSB7XG4gICAgICAgICAgICAgICAgICAgIHZlcmlmeUlzU3R1YihtZXRob2QucHJveHkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgbWV0aG9kICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmZhaWwobWV0aG9kICsgXCIgaXMgbm90IGEgZnVuY3Rpb25cIik7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG1ldGhvZC5nZXRDYWxsICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LmZhaWwobWV0aG9kICsgXCIgaXMgbm90IHN0dWJiZWRcIik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGZhaWxBc3NlcnRpb24ob2JqZWN0LCBtc2cpIHtcbiAgICAgICAgICAgIG9iamVjdCA9IG9iamVjdCB8fCBnbG9iYWw7XG4gICAgICAgICAgICB2YXIgZmFpbE1ldGhvZCA9IG9iamVjdC5mYWlsIHx8IGFzc2VydC5mYWlsO1xuICAgICAgICAgICAgZmFpbE1ldGhvZC5jYWxsKG9iamVjdCwgbXNnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIG1pcnJvclByb3BBc0Fzc2VydGlvbihuYW1lLCBtZXRob2QsIG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09IDIpIHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlID0gbWV0aG9kO1xuICAgICAgICAgICAgICAgIG1ldGhvZCA9IG5hbWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGFzc2VydFtuYW1lXSA9IGZ1bmN0aW9uIChmYWtlKSB7XG4gICAgICAgICAgICAgICAgdmVyaWZ5SXNTdHViKGZha2UpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgICAgICAgICAgdmFyIGZhaWxlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBtZXRob2QgPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZhaWxlZCA9ICFtZXRob2QoZmFrZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZmFpbGVkID0gdHlwZW9mIGZha2VbbWV0aG9kXSA9PSBcImZ1bmN0aW9uXCIgP1xuICAgICAgICAgICAgICAgICAgICAgICAgIWZha2VbbWV0aG9kXS5hcHBseShmYWtlLCBhcmdzKSA6ICFmYWtlW21ldGhvZF07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGZhaWxlZCkge1xuICAgICAgICAgICAgICAgICAgICBmYWlsQXNzZXJ0aW9uKHRoaXMsIChmYWtlLnByaW50ZiB8fCBmYWtlLnByb3h5LnByaW50ZikuYXBwbHkoZmFrZSwgW21lc3NhZ2VdLmNvbmNhdChhcmdzKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydC5wYXNzKG5hbWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBleHBvc2VkTmFtZShwcmVmaXgsIHByb3ApIHtcbiAgICAgICAgICAgIHJldHVybiAhcHJlZml4IHx8IC9eZmFpbC8udGVzdChwcm9wKSA/IHByb3AgOlxuICAgICAgICAgICAgICAgIHByZWZpeCArIHByb3Auc2xpY2UoMCwgMSkudG9VcHBlckNhc2UoKSArIHByb3Auc2xpY2UoMSk7XG4gICAgICAgIH1cblxuICAgICAgICBhc3NlcnQgPSB7XG4gICAgICAgICAgICBmYWlsRXhjZXB0aW9uOiBcIkFzc2VydEVycm9yXCIsXG5cbiAgICAgICAgICAgIGZhaWw6IGZ1bmN0aW9uIGZhaWwobWVzc2FnZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnJvciA9IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgICAgICAgICAgICAgICBlcnJvci5uYW1lID0gdGhpcy5mYWlsRXhjZXB0aW9uIHx8IGFzc2VydC5mYWlsRXhjZXB0aW9uO1xuXG4gICAgICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBwYXNzOiBmdW5jdGlvbiBwYXNzKGFzc2VydGlvbikge30sXG5cbiAgICAgICAgICAgIGNhbGxPcmRlcjogZnVuY3Rpb24gYXNzZXJ0Q2FsbE9yZGVyKCkge1xuICAgICAgICAgICAgICAgIHZlcmlmeUlzU3R1Yi5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIHZhciBleHBlY3RlZCA9IFwiXCIsIGFjdHVhbCA9IFwiXCI7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXNpbm9uLmNhbGxlZEluT3JkZXIoYXJndW1lbnRzKSkge1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhwZWN0ZWQgPSBbXS5qb2luLmNhbGwoYXJndW1lbnRzLCBcIiwgXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNhbGxzID0gc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGkgPSBjYWxscy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoaSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY2FsbHNbLS1pXS5jYWxsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FsbHMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGFjdHVhbCA9IHNpbm9uLm9yZGVyQnlGaXJzdENhbGwoY2FsbHMpLmpvaW4oXCIsIFwiKTtcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhpcyBmYWlscywgd2UnbGwganVzdCBmYWxsIGJhY2sgdG8gdGhlIGJsYW5rIHN0cmluZ1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgZmFpbEFzc2VydGlvbih0aGlzLCBcImV4cGVjdGVkIFwiICsgZXhwZWN0ZWQgKyBcIiB0byBiZSBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiY2FsbGVkIGluIG9yZGVyIGJ1dCB3ZXJlIGNhbGxlZCBhcyBcIiArIGFjdHVhbCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0LnBhc3MoXCJjYWxsT3JkZXJcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgY2FsbENvdW50OiBmdW5jdGlvbiBhc3NlcnRDYWxsQ291bnQobWV0aG9kLCBjb3VudCkge1xuICAgICAgICAgICAgICAgIHZlcmlmeUlzU3R1YihtZXRob2QpO1xuXG4gICAgICAgICAgICAgICAgaWYgKG1ldGhvZC5jYWxsQ291bnQgIT0gY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1zZyA9IFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIFwiICsgc2lub24udGltZXNJbldvcmRzKGNvdW50KSArXG4gICAgICAgICAgICAgICAgICAgICAgICBcIiBidXQgd2FzIGNhbGxlZCAlYyVDXCI7XG4gICAgICAgICAgICAgICAgICAgIGZhaWxBc3NlcnRpb24odGhpcywgbWV0aG9kLnByaW50Zihtc2cpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQucGFzcyhcImNhbGxDb3VudFwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBleHBvc2U6IGZ1bmN0aW9uIGV4cG9zZSh0YXJnZXQsIG9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwidGFyZ2V0IGlzIG51bGwgb3IgdW5kZWZpbmVkXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBvID0gb3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICB2YXIgcHJlZml4ID0gdHlwZW9mIG8ucHJlZml4ID09IFwidW5kZWZpbmVkXCIgJiYgXCJhc3NlcnRcIiB8fCBvLnByZWZpeDtcbiAgICAgICAgICAgICAgICB2YXIgaW5jbHVkZUZhaWwgPSB0eXBlb2Ygby5pbmNsdWRlRmFpbCA9PSBcInVuZGVmaW5lZFwiIHx8ICEhby5pbmNsdWRlRmFpbDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIG1ldGhvZCBpbiB0aGlzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtZXRob2QgIT0gXCJleHBvc2VcIiAmJiAoaW5jbHVkZUZhaWwgfHwgIS9eKGZhaWwpLy50ZXN0KG1ldGhvZCkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRbZXhwb3NlZE5hbWUocHJlZml4LCBtZXRob2QpXSA9IHRoaXNbbWV0aG9kXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB0YXJnZXQ7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBtYXRjaDogZnVuY3Rpb24gbWF0Y2goYWN0dWFsLCBleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgICAgIHZhciBtYXRjaGVyID0gc2lub24ubWF0Y2goZXhwZWN0YXRpb24pO1xuICAgICAgICAgICAgICAgIGlmIChtYXRjaGVyLnRlc3QoYWN0dWFsKSkge1xuICAgICAgICAgICAgICAgICAgICBhc3NlcnQucGFzcyhcIm1hdGNoXCIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmb3JtYXR0ZWQgPSBbXG4gICAgICAgICAgICAgICAgICAgICAgICBcImV4cGVjdGVkIHZhbHVlIHRvIG1hdGNoXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBcIiAgICBleHBlY3RlZCA9IFwiICsgc2lub24uZm9ybWF0KGV4cGVjdGF0aW9uKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiICAgIGFjdHVhbCA9IFwiICsgc2lub24uZm9ybWF0KGFjdHVhbClcbiAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICAgICBmYWlsQXNzZXJ0aW9uKHRoaXMsIGZvcm1hdHRlZC5qb2luKFwiXFxuXCIpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwiY2FsbGVkXCIsIFwiZXhwZWN0ZWQgJW4gdG8gaGF2ZSBiZWVuIGNhbGxlZCBhdCBsZWFzdCBvbmNlIGJ1dCB3YXMgbmV2ZXIgY2FsbGVkXCIpO1xuICAgICAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJub3RDYWxsZWRcIiwgZnVuY3Rpb24gKHNweSkge1xuICAgICAgICAgICAgcmV0dXJuICFzcHkuY2FsbGVkO1xuICAgICAgICB9LCBcImV4cGVjdGVkICVuIHRvIG5vdCBoYXZlIGJlZW4gY2FsbGVkIGJ1dCB3YXMgY2FsbGVkICVjJUNcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZE9uY2VcIiwgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgb25jZSBidXQgd2FzIGNhbGxlZCAlYyVDXCIpO1xuICAgICAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJjYWxsZWRUd2ljZVwiLCBcImV4cGVjdGVkICVuIHRvIGJlIGNhbGxlZCB0d2ljZSBidXQgd2FzIGNhbGxlZCAlYyVDXCIpO1xuICAgICAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJjYWxsZWRUaHJpY2VcIiwgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgdGhyaWNlIGJ1dCB3YXMgY2FsbGVkICVjJUNcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZE9uXCIsIFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIHdpdGggJTEgYXMgdGhpcyBidXQgd2FzIGNhbGxlZCB3aXRoICV0XCIpO1xuICAgICAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJhbHdheXNDYWxsZWRPblwiLCBcImV4cGVjdGVkICVuIHRvIGFsd2F5cyBiZSBjYWxsZWQgd2l0aCAlMSBhcyB0aGlzIGJ1dCB3YXMgY2FsbGVkIHdpdGggJXRcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZFdpdGhOZXdcIiwgXCJleHBlY3RlZCAlbiB0byBiZSBjYWxsZWQgd2l0aCBuZXdcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImFsd2F5c0NhbGxlZFdpdGhOZXdcIiwgXCJleHBlY3RlZCAlbiB0byBhbHdheXMgYmUgY2FsbGVkIHdpdGggbmV3XCIpO1xuICAgICAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJjYWxsZWRXaXRoXCIsIFwiZXhwZWN0ZWQgJW4gdG8gYmUgY2FsbGVkIHdpdGggYXJndW1lbnRzICUqJUNcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImNhbGxlZFdpdGhNYXRjaFwiLCBcImV4cGVjdGVkICVuIHRvIGJlIGNhbGxlZCB3aXRoIG1hdGNoICUqJUNcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImFsd2F5c0NhbGxlZFdpdGhcIiwgXCJleHBlY3RlZCAlbiB0byBhbHdheXMgYmUgY2FsbGVkIHdpdGggYXJndW1lbnRzICUqJUNcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcImFsd2F5c0NhbGxlZFdpdGhNYXRjaFwiLCBcImV4cGVjdGVkICVuIHRvIGFsd2F5cyBiZSBjYWxsZWQgd2l0aCBtYXRjaCAlKiVDXCIpO1xuICAgICAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJjYWxsZWRXaXRoRXhhY3RseVwiLCBcImV4cGVjdGVkICVuIHRvIGJlIGNhbGxlZCB3aXRoIGV4YWN0IGFyZ3VtZW50cyAlKiVDXCIpO1xuICAgICAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJhbHdheXNDYWxsZWRXaXRoRXhhY3RseVwiLCBcImV4cGVjdGVkICVuIHRvIGFsd2F5cyBiZSBjYWxsZWQgd2l0aCBleGFjdCBhcmd1bWVudHMgJSolQ1wiKTtcbiAgICAgICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwibmV2ZXJDYWxsZWRXaXRoXCIsIFwiZXhwZWN0ZWQgJW4gdG8gbmV2ZXIgYmUgY2FsbGVkIHdpdGggYXJndW1lbnRzICUqJUNcIik7XG4gICAgICAgIG1pcnJvclByb3BBc0Fzc2VydGlvbihcIm5ldmVyQ2FsbGVkV2l0aE1hdGNoXCIsIFwiZXhwZWN0ZWQgJW4gdG8gbmV2ZXIgYmUgY2FsbGVkIHdpdGggbWF0Y2ggJSolQ1wiKTtcbiAgICAgICAgbWlycm9yUHJvcEFzQXNzZXJ0aW9uKFwidGhyZXdcIiwgXCIlbiBkaWQgbm90IHRocm93IGV4Y2VwdGlvbiVDXCIpO1xuICAgICAgICBtaXJyb3JQcm9wQXNBc3NlcnRpb24oXCJhbHdheXNUaHJld1wiLCBcIiVuIGRpZCBub3QgYWx3YXlzIHRocm93IGV4Y2VwdGlvbiVDXCIpO1xuXG4gICAgICAgIHNpbm9uLmFzc2VydCA9IGFzc2VydDtcbiAgICAgICAgcmV0dXJuIGFzc2VydDtcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL21hdGNoXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9mb3JtYXRcIik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCwgdHlwZW9mIHdpbmRvdyAhPSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogKHR5cGVvZiBzZWxmICE9IFwidW5kZWZpbmVkXCIpID8gc2VsZiA6IGdsb2JhbCkpO1xuXG59KS5jYWxsKHRoaXMsdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KSIsIihmdW5jdGlvbiAocHJvY2Vzcyl7XG4vKipcbiAqIEBkZXBlbmQgdXRpbC9jb3JlLmpzXG4gKiBAZGVwZW5kIGV4dGVuZC5qc1xuICovXG4vKipcbiAqIFN0dWIgYmVoYXZpb3JcbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBhdXRob3IgVGltIEZpc2NoYmFjaCAobWFpbEB0aW1maXNjaGJhY2guZGUpXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiAoc2lub24pIHtcbiAgICB2YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG4gICAgdmFyIGpvaW4gPSBBcnJheS5wcm90b3R5cGUuam9pbjtcbiAgICB2YXIgdXNlTGVmdE1vc3RDYWxsYmFjayA9IC0xO1xuICAgIHZhciB1c2VSaWdodE1vc3RDYWxsYmFjayA9IC0yO1xuXG4gICAgdmFyIG5leHRUaWNrID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBwcm9jZXNzID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBwcm9jZXNzLm5leHRUaWNrID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBwcm9jZXNzLm5leHRUaWNrO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBzZXRJbW1lZGlhdGUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgcmV0dXJuIHNldEltbWVkaWF0ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGNhbGxiYWNrLCAwKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9KSgpO1xuXG4gICAgZnVuY3Rpb24gdGhyb3dzRXhjZXB0aW9uKGVycm9yLCBtZXNzYWdlKSB7XG4gICAgICAgIGlmICh0eXBlb2YgZXJyb3IgPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgdGhpcy5leGNlcHRpb24gPSBuZXcgRXJyb3IobWVzc2FnZSB8fCBcIlwiKTtcbiAgICAgICAgICAgIHRoaXMuZXhjZXB0aW9uLm5hbWUgPSBlcnJvcjtcbiAgICAgICAgfSBlbHNlIGlmICghZXJyb3IpIHtcbiAgICAgICAgICAgIHRoaXMuZXhjZXB0aW9uID0gbmV3IEVycm9yKFwiRXJyb3JcIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLmV4Y2VwdGlvbiA9IGVycm9yO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Q2FsbGJhY2soYmVoYXZpb3IsIGFyZ3MpIHtcbiAgICAgICAgdmFyIGNhbGxBcmdBdCA9IGJlaGF2aW9yLmNhbGxBcmdBdDtcblxuICAgICAgICBpZiAoY2FsbEFyZ0F0ID49IDApIHtcbiAgICAgICAgICAgIHJldHVybiBhcmdzW2NhbGxBcmdBdF07XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYXJndW1lbnRMaXN0O1xuXG4gICAgICAgIGlmIChjYWxsQXJnQXQgPT09IHVzZUxlZnRNb3N0Q2FsbGJhY2spIHtcbiAgICAgICAgICAgIGFyZ3VtZW50TGlzdCA9IGFyZ3M7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2FsbEFyZ0F0ID09PSB1c2VSaWdodE1vc3RDYWxsYmFjaykge1xuICAgICAgICAgICAgYXJndW1lbnRMaXN0ID0gc2xpY2UuY2FsbChhcmdzKS5yZXZlcnNlKCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgY2FsbEFyZ1Byb3AgPSBiZWhhdmlvci5jYWxsQXJnUHJvcDtcblxuICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGFyZ3VtZW50TGlzdC5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgIGlmICghY2FsbEFyZ1Byb3AgJiYgdHlwZW9mIGFyZ3VtZW50TGlzdFtpXSA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXJndW1lbnRMaXN0W2ldO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoY2FsbEFyZ1Byb3AgJiYgYXJndW1lbnRMaXN0W2ldICYmXG4gICAgICAgICAgICAgICAgdHlwZW9mIGFyZ3VtZW50TGlzdFtpXVtjYWxsQXJnUHJvcF0gPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFyZ3VtZW50TGlzdFtpXVtjYWxsQXJnUHJvcF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYWtlQXBpKHNpbm9uKSB7XG4gICAgICAgIGZ1bmN0aW9uIGdldENhbGxiYWNrRXJyb3IoYmVoYXZpb3IsIGZ1bmMsIGFyZ3MpIHtcbiAgICAgICAgICAgIGlmIChiZWhhdmlvci5jYWxsQXJnQXQgPCAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1zZztcblxuICAgICAgICAgICAgICAgIGlmIChiZWhhdmlvci5jYWxsQXJnUHJvcCkge1xuICAgICAgICAgICAgICAgICAgICBtc2cgPSBzaW5vbi5mdW5jdGlvbk5hbWUoYmVoYXZpb3Iuc3R1YikgK1xuICAgICAgICAgICAgICAgICAgICAgICAgXCIgZXhwZWN0ZWQgdG8geWllbGQgdG8gJ1wiICsgYmVoYXZpb3IuY2FsbEFyZ1Byb3AgK1xuICAgICAgICAgICAgICAgICAgICAgICAgXCInLCBidXQgbm8gb2JqZWN0IHdpdGggc3VjaCBhIHByb3BlcnR5IHdhcyBwYXNzZWQuXCI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbXNnID0gc2lub24uZnVuY3Rpb25OYW1lKGJlaGF2aW9yLnN0dWIpICtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiIGV4cGVjdGVkIHRvIHlpZWxkLCBidXQgbm8gY2FsbGJhY2sgd2FzIHBhc3NlZC5cIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG1zZyArPSBcIiBSZWNlaXZlZCBbXCIgKyBqb2luLmNhbGwoYXJncywgXCIsIFwiKSArIFwiXVwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBtc2c7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBcImFyZ3VtZW50IGF0IGluZGV4IFwiICsgYmVoYXZpb3IuY2FsbEFyZ0F0ICsgXCIgaXMgbm90IGEgZnVuY3Rpb246IFwiICsgZnVuYztcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGNhbGxDYWxsYmFjayhiZWhhdmlvciwgYXJncykge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBiZWhhdmlvci5jYWxsQXJnQXQgPT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgIHZhciBmdW5jID0gZ2V0Q2FsbGJhY2soYmVoYXZpb3IsIGFyZ3MpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBmdW5jICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGdldENhbGxiYWNrRXJyb3IoYmVoYXZpb3IsIGZ1bmMsIGFyZ3MpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYmVoYXZpb3IuY2FsbGJhY2tBc3luYykge1xuICAgICAgICAgICAgICAgICAgICBuZXh0VGljayhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmdW5jLmFwcGx5KGJlaGF2aW9yLmNhbGxiYWNrQ29udGV4dCwgYmVoYXZpb3IuY2FsbGJhY2tBcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBmdW5jLmFwcGx5KGJlaGF2aW9yLmNhbGxiYWNrQ29udGV4dCwgYmVoYXZpb3IuY2FsbGJhY2tBcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwcm90byA9IHtcbiAgICAgICAgICAgIGNyZWF0ZTogZnVuY3Rpb24gY3JlYXRlKHN0dWIpIHtcbiAgICAgICAgICAgICAgICB2YXIgYmVoYXZpb3IgPSBzaW5vbi5leHRlbmQoe30sIHNpbm9uLmJlaGF2aW9yKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgYmVoYXZpb3IuY3JlYXRlO1xuICAgICAgICAgICAgICAgIGJlaGF2aW9yLnN0dWIgPSBzdHViO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGJlaGF2aW9yO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgaXNQcmVzZW50OiBmdW5jdGlvbiBpc1ByZXNlbnQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICh0eXBlb2YgdGhpcy5jYWxsQXJnQXQgPT0gXCJudW1iZXJcIiB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5leGNlcHRpb24gfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVvZiB0aGlzLnJldHVybkFyZ0F0ID09IFwibnVtYmVyXCIgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmV0dXJuVGhpcyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXR1cm5WYWx1ZURlZmluZWQpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgaW52b2tlOiBmdW5jdGlvbiBpbnZva2UoY29udGV4dCwgYXJncykge1xuICAgICAgICAgICAgICAgIGNhbGxDYWxsYmFjayh0aGlzLCBhcmdzKTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmV4Y2VwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyB0aGlzLmV4Y2VwdGlvbjtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLnJldHVybkFyZ0F0ID09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFyZ3NbdGhpcy5yZXR1cm5BcmdBdF07XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnJldHVyblRoaXMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbnRleHQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmV0dXJuVmFsdWU7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBvbkNhbGw6IGZ1bmN0aW9uIG9uQ2FsbChpbmRleCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnN0dWIub25DYWxsKGluZGV4KTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uRmlyc3RDYWxsOiBmdW5jdGlvbiBvbkZpcnN0Q2FsbCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zdHViLm9uRmlyc3RDYWxsKCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBvblNlY29uZENhbGw6IGZ1bmN0aW9uIG9uU2Vjb25kQ2FsbCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zdHViLm9uU2Vjb25kQ2FsbCgpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb25UaGlyZENhbGw6IGZ1bmN0aW9uIG9uVGhpcmRDYWxsKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnN0dWIub25UaGlyZENhbGwoKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHdpdGhBcmdzOiBmdW5jdGlvbiB3aXRoQXJncygvKiBhcmd1bWVudHMgKi8pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJEZWZpbmluZyBhIHN0dWIgYnkgaW52b2tpbmcgXFxcInN0dWIub25DYWxsKC4uLikud2l0aEFyZ3MoLi4uKVxcXCIgaXMgbm90IHN1cHBvcnRlZC4gXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlVzZSBcXFwic3R1Yi53aXRoQXJncyguLi4pLm9uQ2FsbCguLi4pXFxcIiB0byBkZWZpbmUgc2VxdWVudGlhbCBiZWhhdmlvciBmb3IgY2FsbHMgd2l0aCBjZXJ0YWluIGFyZ3VtZW50cy5cIik7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsc0FyZzogZnVuY3Rpb24gY2FsbHNBcmcocG9zKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwb3MgIT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgaW5kZXggaXMgbm90IG51bWJlclwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdBdCA9IHBvcztcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXJndW1lbnRzID0gW107XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0NvbnRleHQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsQXJnUHJvcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXN5bmMgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgY2FsbHNBcmdPbjogZnVuY3Rpb24gY2FsbHNBcmdPbihwb3MsIGNvbnRleHQpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHBvcyAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcmd1bWVudCBpbmRleCBpcyBub3QgbnVtYmVyXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNvbnRleHQgIT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgY29udGV4dCBpcyBub3QgYW4gb2JqZWN0XCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ0F0ID0gcG9zO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBcmd1bWVudHMgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQ29udGV4dCA9IGNvbnRleHQ7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsQXJnUHJvcCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXN5bmMgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgY2FsbHNBcmdXaXRoOiBmdW5jdGlvbiBjYWxsc0FyZ1dpdGgocG9zKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwb3MgIT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgaW5kZXggaXMgbm90IG51bWJlclwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdBdCA9IHBvcztcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXJndW1lbnRzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tDb250ZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ1Byb3AgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FzeW5jID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGNhbGxzQXJnT25XaXRoOiBmdW5jdGlvbiBjYWxsc0FyZ1dpdGgocG9zLCBjb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwb3MgIT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgaW5kZXggaXMgbm90IG51bWJlclwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjb250ZXh0ICE9IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcImFyZ3VtZW50IGNvbnRleHQgaXMgbm90IGFuIG9iamVjdFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdBdCA9IHBvcztcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXJndW1lbnRzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tDb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdQcm9wID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB5aWVsZHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdBdCA9IHVzZUxlZnRNb3N0Q2FsbGJhY2s7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FyZ3VtZW50cyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQ29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdQcm9wID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB5aWVsZHNSaWdodDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ0F0ID0gdXNlUmlnaHRNb3N0Q2FsbGJhY2s7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FyZ3VtZW50cyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQ29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdQcm9wID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB5aWVsZHNPbjogZnVuY3Rpb24gKGNvbnRleHQpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNvbnRleHQgIT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgY29udGV4dCBpcyBub3QgYW4gb2JqZWN0XCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ0F0ID0gdXNlTGVmdE1vc3RDYWxsYmFjaztcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXJndW1lbnRzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tDb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdQcm9wID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tBc3luYyA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB5aWVsZHNUbzogZnVuY3Rpb24gKHByb3ApIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdBdCA9IHVzZUxlZnRNb3N0Q2FsbGJhY2s7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsYmFja0FyZ3VtZW50cyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQ29udGV4dCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdQcm9wID0gcHJvcDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXN5bmMgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgeWllbGRzVG9PbjogZnVuY3Rpb24gKHByb3AsIGNvbnRleHQpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNvbnRleHQgIT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgY29udGV4dCBpcyBub3QgYW4gb2JqZWN0XCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ0F0ID0gdXNlTGVmdE1vc3RDYWxsYmFjaztcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXJndW1lbnRzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGJhY2tDb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxBcmdQcm9wID0gcHJvcDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXN5bmMgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgdGhyb3dzOiB0aHJvd3NFeGNlcHRpb24sXG4gICAgICAgICAgICB0aHJvd3NFeGNlcHRpb246IHRocm93c0V4Y2VwdGlvbixcblxuICAgICAgICAgICAgcmV0dXJuczogZnVuY3Rpb24gcmV0dXJucyh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMucmV0dXJuVmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnJldHVyblZhbHVlRGVmaW5lZCA9IHRydWU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJldHVybnNBcmc6IGZ1bmN0aW9uIHJldHVybnNBcmcocG9zKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwb3MgIT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiYXJndW1lbnQgaW5kZXggaXMgbm90IG51bWJlclwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnJldHVybkFyZ0F0ID0gcG9zO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICByZXR1cm5zVGhpczogZnVuY3Rpb24gcmV0dXJuc1RoaXMoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXR1cm5UaGlzID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIGNyZWF0ZSBhc3luY2hyb25vdXMgdmVyc2lvbnMgb2YgY2FsbHNBcmcqIGFuZCB5aWVsZHMqIG1ldGhvZHNcbiAgICAgICAgZm9yICh2YXIgbWV0aG9kIGluIHByb3RvKSB7XG4gICAgICAgICAgICAvLyBuZWVkIHRvIGF2b2lkIGNyZWF0aW5nIGFub3RoZXJhc3luYyB2ZXJzaW9ucyBvZiB0aGUgbmV3bHkgYWRkZWQgYXN5bmMgbWV0aG9kc1xuICAgICAgICAgICAgaWYgKHByb3RvLmhhc093blByb3BlcnR5KG1ldGhvZCkgJiZcbiAgICAgICAgICAgICAgICBtZXRob2QubWF0Y2goL14oY2FsbHNBcmd8eWllbGRzKS8pICYmXG4gICAgICAgICAgICAgICAgIW1ldGhvZC5tYXRjaCgvQXN5bmMvKSkge1xuICAgICAgICAgICAgICAgIHByb3RvW21ldGhvZCArIFwiQXN5bmNcIl0gPSAoZnVuY3Rpb24gKHN5bmNGbk5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB0aGlzW3N5bmNGbk5hbWVdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGxiYWNrQXN5bmMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9KShtZXRob2QpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2lub24uYmVoYXZpb3IgPSBwcm90bztcbiAgICAgICAgcmV0dXJuIHByb3RvO1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vZXh0ZW5kXCIpO1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG1ha2VBcGkoc2lub24pO1xuICAgIH1cblxuICAgIGlmIChpc0FNRCkge1xuICAgICAgICBkZWZpbmUobG9hZERlcGVuZGVuY2llcyk7XG4gICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBtb2R1bGUuZXhwb3J0cywgbW9kdWxlKTtcbiAgICB9IGVsc2UgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufSh0eXBlb2Ygc2lub24gPT0gXCJvYmplY3RcIiAmJiBzaW5vbiB8fCBudWxsKSk7XG5cbn0pLmNhbGwodGhpcyxyZXF1aXJlKFwiMVlpWjVTXCIpKSIsIi8qKlxuICAqIEBkZXBlbmQgdXRpbC9jb3JlLmpzXG4gICogQGRlcGVuZCBtYXRjaC5qc1xuICAqIEBkZXBlbmQgZm9ybWF0LmpzXG4gICovXG4vKipcbiAgKiBTcHkgY2FsbHNcbiAgKlxuICAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICAqIEBhdXRob3IgTWF4aW1pbGlhbiBBbnRvbmkgKG1haWxAbWF4YW50b25pLmRlKVxuICAqIEBsaWNlbnNlIEJTRFxuICAqXG4gICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gICogQ29weXJpZ2h0IChjKSAyMDEzIE1heGltaWxpYW4gQW50b25pXG4gICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgZnVuY3Rpb24gdGhyb3dZaWVsZEVycm9yKHByb3h5LCB0ZXh0LCBhcmdzKSB7XG4gICAgICAgICAgICB2YXIgbXNnID0gc2lub24uZnVuY3Rpb25OYW1lKHByb3h5KSArIHRleHQ7XG4gICAgICAgICAgICBpZiAoYXJncy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBtc2cgKz0gXCIgUmVjZWl2ZWQgW1wiICsgc2xpY2UuY2FsbChhcmdzKS5qb2luKFwiLCBcIikgKyBcIl1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xuXG4gICAgICAgIHZhciBjYWxsUHJvdG8gPSB7XG4gICAgICAgICAgICBjYWxsZWRPbjogZnVuY3Rpb24gY2FsbGVkT24odGhpc1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHNpbm9uLm1hdGNoICYmIHNpbm9uLm1hdGNoLmlzTWF0Y2hlcih0aGlzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzVmFsdWUudGVzdCh0aGlzLnRoaXNWYWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnRoaXNWYWx1ZSA9PT0gdGhpc1ZhbHVlO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgY2FsbGVkV2l0aDogZnVuY3Rpb24gY2FsbGVkV2l0aCgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgaWYgKGwgPiB0aGlzLmFyZ3MubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsOyBpICs9IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW5vbi5kZWVwRXF1YWwoYXJndW1lbnRzW2ldLCB0aGlzLmFyZ3NbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGNhbGxlZFdpdGhNYXRjaDogZnVuY3Rpb24gY2FsbGVkV2l0aE1hdGNoKCkge1xuICAgICAgICAgICAgICAgIHZhciBsID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBpZiAobCA+IHRoaXMuYXJncy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGw7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYWN0dWFsID0gdGhpcy5hcmdzW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXhwZWN0YXRpb24gPSBhcmd1bWVudHNbaV07XG4gICAgICAgICAgICAgICAgICAgIGlmICghc2lub24ubWF0Y2ggfHwgIXNpbm9uLm1hdGNoKGV4cGVjdGF0aW9uKS50ZXN0KGFjdHVhbCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGNhbGxlZFdpdGhFeGFjdGx5OiBmdW5jdGlvbiBjYWxsZWRXaXRoRXhhY3RseSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA9PSB0aGlzLmFyZ3MubGVuZ3RoICYmXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2FsbGVkV2l0aC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgbm90Q2FsbGVkV2l0aDogZnVuY3Rpb24gbm90Q2FsbGVkV2l0aCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gIXRoaXMuY2FsbGVkV2l0aC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgbm90Q2FsbGVkV2l0aE1hdGNoOiBmdW5jdGlvbiBub3RDYWxsZWRXaXRoTWF0Y2goKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICF0aGlzLmNhbGxlZFdpdGhNYXRjaC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgcmV0dXJuZWQ6IGZ1bmN0aW9uIHJldHVybmVkKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNpbm9uLmRlZXBFcXVhbCh2YWx1ZSwgdGhpcy5yZXR1cm5WYWx1ZSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB0aHJldzogZnVuY3Rpb24gdGhyZXcoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGVycm9yID09PSBcInVuZGVmaW5lZFwiIHx8ICF0aGlzLmV4Y2VwdGlvbikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gISF0aGlzLmV4Y2VwdGlvbjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5leGNlcHRpb24gPT09IGVycm9yIHx8IHRoaXMuZXhjZXB0aW9uLm5hbWUgPT09IGVycm9yO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgY2FsbGVkV2l0aE5ldzogZnVuY3Rpb24gY2FsbGVkV2l0aE5ldygpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wcm94eS5wcm90b3R5cGUgJiYgdGhpcy50aGlzVmFsdWUgaW5zdGFuY2VvZiB0aGlzLnByb3h5O1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgY2FsbGVkQmVmb3JlOiBmdW5jdGlvbiAob3RoZXIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5jYWxsSWQgPCBvdGhlci5jYWxsSWQ7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsZWRBZnRlcjogZnVuY3Rpb24gKG90aGVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2FsbElkID4gb3RoZXIuY2FsbElkO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgY2FsbEFyZzogZnVuY3Rpb24gKHBvcykge1xuICAgICAgICAgICAgICAgIHRoaXMuYXJnc1twb3NdKCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsQXJnT246IGZ1bmN0aW9uIChwb3MsIHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuYXJnc1twb3NdLmFwcGx5KHRoaXNWYWx1ZSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsQXJnV2l0aDogZnVuY3Rpb24gKHBvcykge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbEFyZ09uV2l0aC5hcHBseSh0aGlzLCBbcG9zLCBudWxsXS5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsQXJnT25XaXRoOiBmdW5jdGlvbiAocG9zLCB0aGlzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICAgICAgICAgICAgICB0aGlzLmFyZ3NbcG9zXS5hcHBseSh0aGlzVmFsdWUsIGFyZ3MpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgeWllbGQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnlpZWxkT24uYXBwbHkodGhpcywgW251bGxdLmNvbmNhdChzbGljZS5jYWxsKGFyZ3VtZW50cywgMCkpKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHlpZWxkT246IGZ1bmN0aW9uICh0aGlzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXJncyA9IHRoaXMuYXJncztcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGFyZ3MubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYXJnc1tpXSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmdzW2ldLmFwcGx5KHRoaXNWYWx1ZSwgc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aHJvd1lpZWxkRXJyb3IodGhpcy5wcm94eSwgXCIgY2Fubm90IHlpZWxkIHNpbmNlIG5vIGNhbGxiYWNrIHdhcyBwYXNzZWQuXCIsIGFyZ3MpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgeWllbGRUbzogZnVuY3Rpb24gKHByb3ApIHtcbiAgICAgICAgICAgICAgICB0aGlzLnlpZWxkVG9Pbi5hcHBseSh0aGlzLCBbcHJvcCwgbnVsbF0uY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSkpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgeWllbGRUb09uOiBmdW5jdGlvbiAocHJvcCwgdGhpc1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSB0aGlzLmFyZ3M7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBhcmdzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoYXJnc1tpXSAmJiB0eXBlb2YgYXJnc1tpXVtwcm9wXSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmdzW2ldW3Byb3BdLmFwcGx5KHRoaXNWYWx1ZSwgc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aHJvd1lpZWxkRXJyb3IodGhpcy5wcm94eSwgXCIgY2Fubm90IHlpZWxkIHRvICdcIiArIHByb3AgK1xuICAgICAgICAgICAgICAgICAgICBcIicgc2luY2Ugbm8gY2FsbGJhY2sgd2FzIHBhc3NlZC5cIiwgYXJncyk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB0b1N0cmluZzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBjYWxsU3RyID0gdGhpcy5wcm94eS50b1N0cmluZygpICsgXCIoXCI7XG4gICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBbXTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gdGhpcy5hcmdzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBhcmdzLnB1c2goc2lub24uZm9ybWF0KHRoaXMuYXJnc1tpXSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGNhbGxTdHIgPSBjYWxsU3RyICsgYXJncy5qb2luKFwiLCBcIikgKyBcIilcIjtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5yZXR1cm5WYWx1ZSAhPSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxTdHIgKz0gXCIgPT4gXCIgKyBzaW5vbi5mb3JtYXQodGhpcy5yZXR1cm5WYWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxTdHIgKz0gXCIgIVwiICsgdGhpcy5leGNlcHRpb24ubmFtZTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5leGNlcHRpb24ubWVzc2FnZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FsbFN0ciArPSBcIihcIiArIHRoaXMuZXhjZXB0aW9uLm1lc3NhZ2UgKyBcIilcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBjYWxsU3RyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGNhbGxQcm90by5pbnZva2VDYWxsYmFjayA9IGNhbGxQcm90by55aWVsZDtcblxuICAgICAgICBmdW5jdGlvbiBjcmVhdGVTcHlDYWxsKHNweSwgdGhpc1ZhbHVlLCBhcmdzLCByZXR1cm5WYWx1ZSwgZXhjZXB0aW9uLCBpZCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBpZCAhPT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYWxsIGlkIGlzIG5vdCBhIG51bWJlclwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBwcm94eUNhbGwgPSBzaW5vbi5jcmVhdGUoY2FsbFByb3RvKTtcbiAgICAgICAgICAgIHByb3h5Q2FsbC5wcm94eSA9IHNweTtcbiAgICAgICAgICAgIHByb3h5Q2FsbC50aGlzVmFsdWUgPSB0aGlzVmFsdWU7XG4gICAgICAgICAgICBwcm94eUNhbGwuYXJncyA9IGFyZ3M7XG4gICAgICAgICAgICBwcm94eUNhbGwucmV0dXJuVmFsdWUgPSByZXR1cm5WYWx1ZTtcbiAgICAgICAgICAgIHByb3h5Q2FsbC5leGNlcHRpb24gPSBleGNlcHRpb247XG4gICAgICAgICAgICBwcm94eUNhbGwuY2FsbElkID0gaWQ7XG5cbiAgICAgICAgICAgIHJldHVybiBwcm94eUNhbGw7XG4gICAgICAgIH1cbiAgICAgICAgY3JlYXRlU3B5Q2FsbC50b1N0cmluZyA9IGNhbGxQcm90by50b1N0cmluZzsgLy8gdXNlZCBieSBtb2Nrc1xuXG4gICAgICAgIHNpbm9uLnNweUNhbGwgPSBjcmVhdGVTcHlDYWxsO1xuICAgICAgICByZXR1cm4gY3JlYXRlU3B5Q2FsbDtcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL21hdGNoXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9mb3JtYXRcIik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KHR5cGVvZiBzaW5vbiA9PSBcIm9iamVjdFwiICYmIHNpbm9uIHx8IG51bGwpKTtcbiIsIi8qKlxuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqIEBkZXBlbmQgc3B5LmpzXG4gKiBAZGVwZW5kIHN0dWIuanNcbiAqIEBkZXBlbmQgbW9jay5qc1xuICovXG4vKipcbiAqIENvbGxlY3Rpb25zIG9mIHN0dWJzLCBzcGllcyBhbmQgbW9ja3MuXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiAoc2lub24pIHtcbiAgICB2YXIgcHVzaCA9IFtdLnB1c2g7XG4gICAgdmFyIGhhc093blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcblxuICAgIGZ1bmN0aW9uIGdldEZha2VzKGZha2VDb2xsZWN0aW9uKSB7XG4gICAgICAgIGlmICghZmFrZUNvbGxlY3Rpb24uZmFrZXMpIHtcbiAgICAgICAgICAgIGZha2VDb2xsZWN0aW9uLmZha2VzID0gW107XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFrZUNvbGxlY3Rpb24uZmFrZXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZWFjaChmYWtlQ29sbGVjdGlvbiwgbWV0aG9kKSB7XG4gICAgICAgIHZhciBmYWtlcyA9IGdldEZha2VzKGZha2VDb2xsZWN0aW9uKTtcblxuICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGZha2VzLmxlbmd0aDsgaSA8IGw7IGkgKz0gMSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBmYWtlc1tpXVttZXRob2RdID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIGZha2VzW2ldW21ldGhvZF0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbXBhY3QoZmFrZUNvbGxlY3Rpb24pIHtcbiAgICAgICAgdmFyIGZha2VzID0gZ2V0RmFrZXMoZmFrZUNvbGxlY3Rpb24pO1xuICAgICAgICB2YXIgaSA9IDA7XG4gICAgICAgIHdoaWxlIChpIDwgZmFrZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBmYWtlcy5zcGxpY2UoaSwgMSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYWtlQXBpKHNpbm9uKSB7XG4gICAgICAgIHZhciBjb2xsZWN0aW9uID0ge1xuICAgICAgICAgICAgdmVyaWZ5OiBmdW5jdGlvbiByZXNvbHZlKCkge1xuICAgICAgICAgICAgICAgIGVhY2godGhpcywgXCJ2ZXJpZnlcIik7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICByZXN0b3JlOiBmdW5jdGlvbiByZXN0b3JlKCkge1xuICAgICAgICAgICAgICAgIGVhY2godGhpcywgXCJyZXN0b3JlXCIpO1xuICAgICAgICAgICAgICAgIGNvbXBhY3QodGhpcyk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICByZXNldDogZnVuY3Rpb24gcmVzdG9yZSgpIHtcbiAgICAgICAgICAgICAgICBlYWNoKHRoaXMsIFwicmVzZXRcIik7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB2ZXJpZnlBbmRSZXN0b3JlOiBmdW5jdGlvbiB2ZXJpZnlBbmRSZXN0b3JlKCkge1xuICAgICAgICAgICAgICAgIHZhciBleGNlcHRpb247XG5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnZlcmlmeSgpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgZXhjZXB0aW9uID0gZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnJlc3RvcmUoKTtcblxuICAgICAgICAgICAgICAgIGlmIChleGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXhjZXB0aW9uO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGFkZDogZnVuY3Rpb24gYWRkKGZha2UpIHtcbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwoZ2V0RmFrZXModGhpcyksIGZha2UpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWtlO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgc3B5OiBmdW5jdGlvbiBzcHkoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRkKHNpbm9uLnNweS5hcHBseShzaW5vbiwgYXJndW1lbnRzKSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBzdHViOiBmdW5jdGlvbiBzdHViKG9iamVjdCwgcHJvcGVydHksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByb3BlcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBvcmlnaW5hbCA9IG9iamVjdFtwcm9wZXJ0eV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvcmlnaW5hbCAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3Qgc3R1YiBub24tZXhpc3RlbnQgb3duIHByb3BlcnR5IFwiICsgcHJvcGVydHkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3RbcHJvcGVydHldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFkZCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdG9yZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYmplY3RbcHJvcGVydHldID0gb3JpZ2luYWw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCFwcm9wZXJ0eSAmJiAhIW9iamVjdCAmJiB0eXBlb2Ygb2JqZWN0ID09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHN0dWJiZWRPYmogPSBzaW5vbi5zdHViLmFwcGx5KHNpbm9uLCBhcmd1bWVudHMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3AgaW4gc3R1YmJlZE9iaikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzdHViYmVkT2JqW3Byb3BdID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFkZChzdHViYmVkT2JqW3Byb3BdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHViYmVkT2JqO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFkZChzaW5vbi5zdHViLmFwcGx5KHNpbm9uLCBhcmd1bWVudHMpKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG1vY2s6IGZ1bmN0aW9uIG1vY2soKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRkKHNpbm9uLm1vY2suYXBwbHkoc2lub24sIGFyZ3VtZW50cykpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgaW5qZWN0OiBmdW5jdGlvbiBpbmplY3Qob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbCA9IHRoaXM7XG5cbiAgICAgICAgICAgICAgICBvYmouc3B5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29sLnNweS5hcHBseShjb2wsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIG9iai5zdHViID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29sLnN0dWIuYXBwbHkoY29sLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBvYmoubW9jayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNvbC5tb2NrLmFwcGx5KGNvbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5jb2xsZWN0aW9uID0gY29sbGVjdGlvbjtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgICAgICAgdmFyIHNpbm9uID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9tb2NrXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9zcHlcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3N0dWJcIik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KHR5cGVvZiBzaW5vbiA9PSBcIm9iamVjdFwiICYmIHNpbm9uIHx8IG51bGwpKTtcbiIsIi8qKlxuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiAoc2lub24pIHtcbiAgICBmdW5jdGlvbiBtYWtlQXBpKHNpbm9uKSB7XG5cbiAgICAgICAgLy8gQWRhcHRlZCBmcm9tIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL2RvY3MvRUNNQVNjcmlwdF9Eb250RW51bV9hdHRyaWJ1dGUjSlNjcmlwdF9Eb250RW51bV9CdWdcbiAgICAgICAgdmFyIGhhc0RvbnRFbnVtQnVnID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBvYmogPSB7XG4gICAgICAgICAgICAgICAgY29uc3RydWN0b3I6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiMFwiO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiMVwiO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgdmFsdWVPZjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCIyXCI7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB0b0xvY2FsZVN0cmluZzogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCIzXCI7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwcm90b3R5cGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiNFwiO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgaXNQcm90b3R5cGVPZjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCI1XCI7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBwcm9wZXJ0eUlzRW51bWVyYWJsZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCI2XCI7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBoYXNPd25Qcm9wZXJ0eTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCI3XCI7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBsZW5ndGg6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiOFwiO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgdW5pcXVlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIjlcIlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIHByb3AgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2gob2JqW3Byb3BdKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdC5qb2luKFwiXCIpICE9PSBcIjAxMjM0NTY3ODlcIjtcbiAgICAgICAgfSkoKTtcblxuICAgICAgICAvKiBQdWJsaWM6IEV4dGVuZCB0YXJnZXQgaW4gcGxhY2Ugd2l0aCBhbGwgKG93bikgcHJvcGVydGllcyBmcm9tIHNvdXJjZXMgaW4tb3JkZXIuIFRodXMsIGxhc3Qgc291cmNlIHdpbGxcbiAgICAgICAgICogICAgICAgICBvdmVycmlkZSBwcm9wZXJ0aWVzIGluIHByZXZpb3VzIHNvdXJjZXMuXG4gICAgICAgICAqXG4gICAgICAgICAqIHRhcmdldCAtIFRoZSBPYmplY3QgdG8gZXh0ZW5kXG4gICAgICAgICAqIHNvdXJjZXMgLSBPYmplY3RzIHRvIGNvcHkgcHJvcGVydGllcyBmcm9tLlxuICAgICAgICAgKlxuICAgICAgICAgKiBSZXR1cm5zIHRoZSBleHRlbmRlZCB0YXJnZXRcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIGV4dGVuZCh0YXJnZXQgLyosIHNvdXJjZXMgKi8pIHtcbiAgICAgICAgICAgIHZhciBzb3VyY2VzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcbiAgICAgICAgICAgICAgICBzb3VyY2UsIGksIHByb3A7XG5cbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBzb3VyY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgc291cmNlID0gc291cmNlc1tpXTtcblxuICAgICAgICAgICAgICAgIGZvciAocHJvcCBpbiBzb3VyY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNvdXJjZS5oYXNPd25Qcm9wZXJ0eShwcm9wKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0W3Byb3BdID0gc291cmNlW3Byb3BdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHdlIGNvcHkgKG93bikgdG9TdHJpbmcgbWV0aG9kIGV2ZW4gd2hlbiBpbiBKU2NyaXB0IHdpdGggRG9udEVudW0gYnVnXG4gICAgICAgICAgICAgICAgLy8gU2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL2RvY3MvRUNNQVNjcmlwdF9Eb250RW51bV9hdHRyaWJ1dGUjSlNjcmlwdF9Eb250RW51bV9CdWdcbiAgICAgICAgICAgICAgICBpZiAoaGFzRG9udEVudW1CdWcgJiYgc291cmNlLmhhc093blByb3BlcnR5KFwidG9TdHJpbmdcIikgJiYgc291cmNlLnRvU3RyaW5nICE9PSB0YXJnZXQudG9TdHJpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LnRvU3RyaW5nID0gc291cmNlLnRvU3RyaW5nO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRhcmdldDtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5leHRlbmQgPSBleHRlbmQ7XG4gICAgICAgIHJldHVybiBzaW5vbi5leHRlbmQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgICAgICAgdmFyIHNpbm9uID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlXCIpO1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG1ha2VBcGkoc2lub24pO1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGlmIChpc0FNRCkge1xuICAgICAgICBkZWZpbmUobG9hZERlcGVuZGVuY2llcyk7XG4gICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBtb2R1bGUuZXhwb3J0cywgbW9kdWxlKTtcbiAgICB9IGVsc2UgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufSh0eXBlb2Ygc2lub24gPT0gXCJvYmplY3RcIiAmJiBzaW5vbiB8fCBudWxsKSk7XG4iLCIvKipcbiAqIEBkZXBlbmQgdXRpbC9jb3JlLmpzXG4gKi9cbi8qKlxuICogRm9ybWF0IGZ1bmN0aW9uc1xuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTQgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKHNpbm9uLCBmb3JtYXRpbykge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgZnVuY3Rpb24gdmFsdWVGb3JtYXR0ZXIodmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiBcIlwiICsgdmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBnZXRGb3JtYXRpb0Zvcm1hdHRlcigpIHtcbiAgICAgICAgICAgIHZhciBmb3JtYXR0ZXIgPSBmb3JtYXRpby5jb25maWd1cmUoe1xuICAgICAgICAgICAgICAgICAgICBxdW90ZVN0cmluZ3M6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBsaW1pdENoaWxkcmVuQ291bnQ6IDI1MFxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBmb3JtYXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZvcm1hdHRlci5hc2NpaS5hcHBseShmb3JtYXR0ZXIsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0O1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gZ2V0Tm9kZUZvcm1hdHRlcih2YWx1ZSkge1xuICAgICAgICAgICAgZnVuY3Rpb24gZm9ybWF0KHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSBcIm9iamVjdFwiICYmIHZhbHVlLnRvU3RyaW5nID09PSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nID8gdXRpbC5pbnNwZWN0KHZhbHVlKSA6IHZhbHVlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgdXRpbCA9IHJlcXVpcmUoXCJ1dGlsXCIpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIC8qIE5vZGUsIGJ1dCBubyB1dGlsIG1vZHVsZSAtIHdvdWxkIGJlIHZlcnkgb2xkLCBidXQgYmV0dGVyIHNhZmUgdGhhbiBzb3JyeSAqL1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdXRpbCA/IGZvcm1hdCA6IHZhbHVlRm9ybWF0dGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiLFxuICAgICAgICAgICAgZm9ybWF0dGVyO1xuXG4gICAgICAgIGlmIChpc05vZGUpIHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgZm9ybWF0aW8gPSByZXF1aXJlKFwiZm9ybWF0aW9cIik7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZvcm1hdGlvKSB7XG4gICAgICAgICAgICBmb3JtYXR0ZXIgPSBnZXRGb3JtYXRpb0Zvcm1hdHRlcigpXG4gICAgICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgICAgICBmb3JtYXR0ZXIgPSBnZXROb2RlRm9ybWF0dGVyKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3JtYXR0ZXIgPSB2YWx1ZUZvcm1hdHRlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHNpbm9uLmZvcm1hdCA9IGZvcm1hdHRlcjtcbiAgICAgICAgcmV0dXJuIHNpbm9uLmZvcm1hdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KFxuICAgICh0eXBlb2Ygc2lub24gPT0gXCJvYmplY3RcIiAmJiBzaW5vbiB8fCBudWxsKSxcbiAgICAodHlwZW9mIGZvcm1hdGlvID09IFwib2JqZWN0XCIgJiYgZm9ybWF0aW8pXG4pKTtcbiIsIi8qKlxuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqL1xuLyoqXG4gKiBMb2dzIGVycm9yc1xuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTQgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKHNpbm9uKSB7XG4gICAgLy8gY2FjaGUgYSByZWZlcmVuY2UgdG8gc2V0VGltZW91dCwgc28gdGhhdCBvdXIgcmVmZXJlbmNlIHdvbid0IGJlIHN0dWJiZWQgb3V0XG4gICAgLy8gd2hlbiB1c2luZyBmYWtlIHRpbWVycyBhbmQgZXJyb3JzIHdpbGwgc3RpbGwgZ2V0IGxvZ2dlZFxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9jam9oYW5zZW4vU2lub24uSlMvaXNzdWVzLzM4MVxuICAgIHZhciByZWFsU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG5cbiAgICBmdW5jdGlvbiBtYWtlQXBpKHNpbm9uKSB7XG5cbiAgICAgICAgZnVuY3Rpb24gbG9nKCkge31cblxuICAgICAgICBmdW5jdGlvbiBsb2dFcnJvcihsYWJlbCwgZXJyKSB7XG4gICAgICAgICAgICB2YXIgbXNnID0gbGFiZWwgKyBcIiB0aHJldyBleGNlcHRpb246IFwiO1xuXG4gICAgICAgICAgICBzaW5vbi5sb2cobXNnICsgXCJbXCIgKyBlcnIubmFtZSArIFwiXSBcIiArIGVyci5tZXNzYWdlKTtcblxuICAgICAgICAgICAgaWYgKGVyci5zdGFjaykge1xuICAgICAgICAgICAgICAgIHNpbm9uLmxvZyhlcnIuc3RhY2spO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsb2dFcnJvci5zZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IG1zZyArIGVyci5tZXNzYWdlO1xuICAgICAgICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgICAgIH0sIDApO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIHdyYXAgcmVhbFNldFRpbWVvdXQgd2l0aCBzb21ldGhpbmcgd2UgY2FuIHN0dWIgaW4gdGVzdHNcbiAgICAgICAgbG9nRXJyb3Iuc2V0VGltZW91dCA9IGZ1bmN0aW9uIChmdW5jLCB0aW1lb3V0KSB7XG4gICAgICAgICAgICByZWFsU2V0VGltZW91dChmdW5jLCB0aW1lb3V0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBleHBvcnRzID0ge307XG4gICAgICAgIGV4cG9ydHMubG9nID0gc2lub24ubG9nID0gbG9nO1xuICAgICAgICBleHBvcnRzLmxvZ0Vycm9yID0gc2lub24ubG9nRXJyb3IgPSBsb2dFcnJvcjtcblxuICAgICAgICByZXR1cm4gZXhwb3J0cztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KHR5cGVvZiBzaW5vbiA9PSBcIm9iamVjdFwiICYmIHNpbm9uIHx8IG51bGwpKTtcbiIsIi8qKlxuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqIEBkZXBlbmQgdHlwZU9mLmpzXG4gKi9cbi8qanNsaW50IGVxZXFlcTogZmFsc2UsIG9uZXZhcjogZmFsc2UsIHBsdXNwbHVzOiBmYWxzZSovXG4vKmdsb2JhbCBtb2R1bGUsIHJlcXVpcmUsIHNpbm9uKi9cbi8qKlxuICogTWF0Y2ggZnVuY3Rpb25zXG4gKlxuICogQGF1dGhvciBNYXhpbWlsaWFuIEFudG9uaSAobWFpbEBtYXhhbnRvbmkuZGUpXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTIgTWF4aW1pbGlhbiBBbnRvbmlcbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiAoc2lub24pIHtcbiAgICBmdW5jdGlvbiBtYWtlQXBpKHNpbm9uKSB7XG4gICAgICAgIGZ1bmN0aW9uIGFzc2VydFR5cGUodmFsdWUsIHR5cGUsIG5hbWUpIHtcbiAgICAgICAgICAgIHZhciBhY3R1YWwgPSBzaW5vbi50eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgaWYgKGFjdHVhbCAhPT0gdHlwZSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJFeHBlY3RlZCB0eXBlIG9mIFwiICsgbmFtZSArIFwiIHRvIGJlIFwiICtcbiAgICAgICAgICAgICAgICAgICAgdHlwZSArIFwiLCBidXQgd2FzIFwiICsgYWN0dWFsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBtYXRjaGVyID0ge1xuICAgICAgICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tZXNzYWdlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGZ1bmN0aW9uIGlzTWF0Y2hlcihvYmplY3QpIHtcbiAgICAgICAgICAgIHJldHVybiBtYXRjaGVyLmlzUHJvdG90eXBlT2Yob2JqZWN0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIG1hdGNoT2JqZWN0KGV4cGVjdGF0aW9uLCBhY3R1YWwpIHtcbiAgICAgICAgICAgIGlmIChhY3R1YWwgPT09IG51bGwgfHwgYWN0dWFsID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gZXhwZWN0YXRpb24pIHtcbiAgICAgICAgICAgICAgICBpZiAoZXhwZWN0YXRpb24uaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXhwID0gZXhwZWN0YXRpb25ba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFjdCA9IGFjdHVhbFtrZXldO1xuICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2guaXNNYXRjaGVyKGV4cCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZXhwLnRlc3QoYWN0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzaW5vbi50eXBlT2YoZXhwKSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFtYXRjaE9iamVjdChleHAsIGFjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIXNpbm9uLmRlZXBFcXVhbChleHAsIGFjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgbWF0Y2hlci5vciA9IGZ1bmN0aW9uIChtMikge1xuICAgICAgICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk1hdGNoZXIgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFpc01hdGNoZXIobTIpKSB7XG4gICAgICAgICAgICAgICAgbTIgPSBtYXRjaChtMik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgbTEgPSB0aGlzO1xuICAgICAgICAgICAgdmFyIG9yID0gc2lub24uY3JlYXRlKG1hdGNoZXIpO1xuICAgICAgICAgICAgb3IudGVzdCA9IGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbTEudGVzdChhY3R1YWwpIHx8IG0yLnRlc3QoYWN0dWFsKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBvci5tZXNzYWdlID0gbTEubWVzc2FnZSArIFwiLm9yKFwiICsgbTIubWVzc2FnZSArIFwiKVwiO1xuICAgICAgICAgICAgcmV0dXJuIG9yO1xuICAgICAgICB9O1xuXG4gICAgICAgIG1hdGNoZXIuYW5kID0gZnVuY3Rpb24gKG0yKSB7XG4gICAgICAgICAgICBpZiAoIWFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWF0Y2hlciBleHBlY3RlZFwiKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzTWF0Y2hlcihtMikpIHtcbiAgICAgICAgICAgICAgICBtMiA9IG1hdGNoKG0yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBtMSA9IHRoaXM7XG4gICAgICAgICAgICB2YXIgYW5kID0gc2lub24uY3JlYXRlKG1hdGNoZXIpO1xuICAgICAgICAgICAgYW5kLnRlc3QgPSBmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG0xLnRlc3QoYWN0dWFsKSAmJiBtMi50ZXN0KGFjdHVhbCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgYW5kLm1lc3NhZ2UgPSBtMS5tZXNzYWdlICsgXCIuYW5kKFwiICsgbTIubWVzc2FnZSArIFwiKVwiO1xuICAgICAgICAgICAgcmV0dXJuIGFuZDtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgbWF0Y2ggPSBmdW5jdGlvbiAoZXhwZWN0YXRpb24sIG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIHZhciBtID0gc2lub24uY3JlYXRlKG1hdGNoZXIpO1xuICAgICAgICAgICAgdmFyIHR5cGUgPSBzaW5vbi50eXBlT2YoZXhwZWN0YXRpb24pO1xuICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICBjYXNlIFwib2JqZWN0XCI6XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBleHBlY3RhdGlvbi50ZXN0ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbS50ZXN0ID0gZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV4cGVjdGF0aW9uLnRlc3QoYWN0dWFsKSA9PT0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgbS5tZXNzYWdlID0gXCJtYXRjaChcIiArIHNpbm9uLmZ1bmN0aW9uTmFtZShleHBlY3RhdGlvbi50ZXN0KSArIFwiKVwiO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIHN0ciA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXhwZWN0YXRpb24uaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc3RyLnB1c2goa2V5ICsgXCI6IFwiICsgZXhwZWN0YXRpb25ba2V5XSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbS50ZXN0ID0gZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWF0Y2hPYmplY3QoZXhwZWN0YXRpb24sIGFjdHVhbCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBtLm1lc3NhZ2UgPSBcIm1hdGNoKFwiICsgc3RyLmpvaW4oXCIsIFwiKSArIFwiKVwiO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcIm51bWJlclwiOlxuICAgICAgICAgICAgICAgIG0udGVzdCA9IGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGV4cGVjdGF0aW9uID09IGFjdHVhbDtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBcInN0cmluZ1wiOlxuICAgICAgICAgICAgICAgIG0udGVzdCA9IGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhY3R1YWwgIT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWN0dWFsLmluZGV4T2YoZXhwZWN0YXRpb24pICE9PSAtMTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIG0ubWVzc2FnZSA9IFwibWF0Y2goXFxcIlwiICsgZXhwZWN0YXRpb24gKyBcIlxcXCIpXCI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIFwicmVnZXhwXCI6XG4gICAgICAgICAgICAgICAgbS50ZXN0ID0gZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGFjdHVhbCAhPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBleHBlY3RhdGlvbi50ZXN0KGFjdHVhbCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgXCJmdW5jdGlvblwiOlxuICAgICAgICAgICAgICAgIG0udGVzdCA9IGV4cGVjdGF0aW9uO1xuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIG0ubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbS5tZXNzYWdlID0gXCJtYXRjaChcIiArIHNpbm9uLmZ1bmN0aW9uTmFtZShleHBlY3RhdGlvbikgKyBcIilcIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIG0udGVzdCA9IGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHNpbm9uLmRlZXBFcXVhbChleHBlY3RhdGlvbiwgYWN0dWFsKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFtLm1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICBtLm1lc3NhZ2UgPSBcIm1hdGNoKFwiICsgZXhwZWN0YXRpb24gKyBcIilcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBtO1xuICAgICAgICB9O1xuXG4gICAgICAgIG1hdGNoLmlzTWF0Y2hlciA9IGlzTWF0Y2hlcjtcblxuICAgICAgICBtYXRjaC5hbnkgPSBtYXRjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSwgXCJhbnlcIik7XG5cbiAgICAgICAgbWF0Y2guZGVmaW5lZCA9IG1hdGNoKGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgIHJldHVybiBhY3R1YWwgIT09IG51bGwgJiYgYWN0dWFsICE9PSB1bmRlZmluZWQ7XG4gICAgICAgIH0sIFwiZGVmaW5lZFwiKTtcblxuICAgICAgICBtYXRjaC50cnV0aHkgPSBtYXRjaChmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICByZXR1cm4gISFhY3R1YWw7XG4gICAgICAgIH0sIFwidHJ1dGh5XCIpO1xuXG4gICAgICAgIG1hdGNoLmZhbHN5ID0gbWF0Y2goZnVuY3Rpb24gKGFjdHVhbCkge1xuICAgICAgICAgICAgcmV0dXJuICFhY3R1YWw7XG4gICAgICAgIH0sIFwiZmFsc3lcIik7XG5cbiAgICAgICAgbWF0Y2guc2FtZSA9IGZ1bmN0aW9uIChleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgcmV0dXJuIG1hdGNoKGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXhwZWN0YXRpb24gPT09IGFjdHVhbDtcbiAgICAgICAgICAgIH0sIFwic2FtZShcIiArIGV4cGVjdGF0aW9uICsgXCIpXCIpO1xuICAgICAgICB9O1xuXG4gICAgICAgIG1hdGNoLnR5cGVPZiA9IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgICAgICBhc3NlcnRUeXBlKHR5cGUsIFwic3RyaW5nXCIsIFwidHlwZVwiKTtcbiAgICAgICAgICAgIHJldHVybiBtYXRjaChmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNpbm9uLnR5cGVPZihhY3R1YWwpID09PSB0eXBlO1xuICAgICAgICAgICAgfSwgXCJ0eXBlT2YoXFxcIlwiICsgdHlwZSArIFwiXFxcIilcIik7XG4gICAgICAgIH07XG5cbiAgICAgICAgbWF0Y2guaW5zdGFuY2VPZiA9IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgICAgICBhc3NlcnRUeXBlKHR5cGUsIFwiZnVuY3Rpb25cIiwgXCJ0eXBlXCIpO1xuICAgICAgICAgICAgcmV0dXJuIG1hdGNoKGZ1bmN0aW9uIChhY3R1YWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWN0dWFsIGluc3RhbmNlb2YgdHlwZTtcbiAgICAgICAgICAgIH0sIFwiaW5zdGFuY2VPZihcIiArIHNpbm9uLmZ1bmN0aW9uTmFtZSh0eXBlKSArIFwiKVwiKTtcbiAgICAgICAgfTtcblxuICAgICAgICBmdW5jdGlvbiBjcmVhdGVQcm9wZXJ0eU1hdGNoZXIocHJvcGVydHlUZXN0LCBtZXNzYWdlUHJlZml4KSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHByb3BlcnR5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGFzc2VydFR5cGUocHJvcGVydHksIFwic3RyaW5nXCIsIFwicHJvcGVydHlcIik7XG4gICAgICAgICAgICAgICAgdmFyIG9ubHlQcm9wZXJ0eSA9IGFyZ3VtZW50cy5sZW5ndGggPT09IDE7XG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBtZXNzYWdlUHJlZml4ICsgXCIoXFxcIlwiICsgcHJvcGVydHkgKyBcIlxcXCJcIjtcbiAgICAgICAgICAgICAgICBpZiAoIW9ubHlQcm9wZXJ0eSkge1xuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlICs9IFwiLCBcIiArIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBtZXNzYWdlICs9IFwiKVwiO1xuICAgICAgICAgICAgICAgIHJldHVybiBtYXRjaChmdW5jdGlvbiAoYWN0dWFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhY3R1YWwgPT09IHVuZGVmaW5lZCB8fCBhY3R1YWwgPT09IG51bGwgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAhcHJvcGVydHlUZXN0KGFjdHVhbCwgcHJvcGVydHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9ubHlQcm9wZXJ0eSB8fCBzaW5vbi5kZWVwRXF1YWwodmFsdWUsIGFjdHVhbFtwcm9wZXJ0eV0pO1xuICAgICAgICAgICAgICAgIH0sIG1lc3NhZ2UpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIG1hdGNoLmhhcyA9IGNyZWF0ZVByb3BlcnR5TWF0Y2hlcihmdW5jdGlvbiAoYWN0dWFsLCBwcm9wZXJ0eSkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBhY3R1YWwgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcGVydHkgaW4gYWN0dWFsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGFjdHVhbFtwcm9wZXJ0eV0gIT09IHVuZGVmaW5lZDtcbiAgICAgICAgfSwgXCJoYXNcIik7XG5cbiAgICAgICAgbWF0Y2guaGFzT3duID0gY3JlYXRlUHJvcGVydHlNYXRjaGVyKGZ1bmN0aW9uIChhY3R1YWwsIHByb3BlcnR5KSB7XG4gICAgICAgICAgICByZXR1cm4gYWN0dWFsLmhhc093blByb3BlcnR5KHByb3BlcnR5KTtcbiAgICAgICAgfSwgXCJoYXNPd25cIik7XG5cbiAgICAgICAgbWF0Y2guYm9vbCA9IG1hdGNoLnR5cGVPZihcImJvb2xlYW5cIik7XG4gICAgICAgIG1hdGNoLm51bWJlciA9IG1hdGNoLnR5cGVPZihcIm51bWJlclwiKTtcbiAgICAgICAgbWF0Y2guc3RyaW5nID0gbWF0Y2gudHlwZU9mKFwic3RyaW5nXCIpO1xuICAgICAgICBtYXRjaC5vYmplY3QgPSBtYXRjaC50eXBlT2YoXCJvYmplY3RcIik7XG4gICAgICAgIG1hdGNoLmZ1bmMgPSBtYXRjaC50eXBlT2YoXCJmdW5jdGlvblwiKTtcbiAgICAgICAgbWF0Y2guYXJyYXkgPSBtYXRjaC50eXBlT2YoXCJhcnJheVwiKTtcbiAgICAgICAgbWF0Y2gucmVnZXhwID0gbWF0Y2gudHlwZU9mKFwicmVnZXhwXCIpO1xuICAgICAgICBtYXRjaC5kYXRlID0gbWF0Y2gudHlwZU9mKFwiZGF0ZVwiKTtcblxuICAgICAgICBzaW5vbi5tYXRjaCA9IG1hdGNoO1xuICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgICAgICAgdmFyIHNpbm9uID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi90eXBlT2ZcIik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KHR5cGVvZiBzaW5vbiA9PSBcIm9iamVjdFwiICYmIHNpbm9uIHx8IG51bGwpKTtcbiIsIi8qKlxuICogQGRlcGVuZCB0aW1lc19pbl93b3Jkcy5qc1xuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqIEBkZXBlbmQgY2FsbC5qc1xuICogQGRlcGVuZCBleHRlbmQuanNcbiAqIEBkZXBlbmQgbWF0Y2guanNcbiAqIEBkZXBlbmQgc3B5LmpzXG4gKiBAZGVwZW5kIHN0dWIuanNcbiAqIEBkZXBlbmQgZm9ybWF0LmpzXG4gKi9cbi8qKlxuICogTW9jayBmdW5jdGlvbnMuXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiAoc2lub24pIHtcbiAgICBmdW5jdGlvbiBtYWtlQXBpKHNpbm9uKSB7XG4gICAgICAgIHZhciBwdXNoID0gW10ucHVzaDtcbiAgICAgICAgdmFyIG1hdGNoID0gc2lub24ubWF0Y2g7XG5cbiAgICAgICAgZnVuY3Rpb24gbW9jayhvYmplY3QpIHtcbiAgICAgICAgICAgIC8vIGlmICh0eXBlb2YgY29uc29sZSAhPT0gdW5kZWZpbmVkICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgICAgLy8gICAgIGNvbnNvbGUud2FybihcIm1vY2sgd2lsbCBiZSByZW1vdmVkIGZyb20gU2lub24uSlMgdjIuMFwiKTtcbiAgICAgICAgICAgIC8vIH1cblxuICAgICAgICAgICAgaWYgKCFvYmplY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2lub24uZXhwZWN0YXRpb24uY3JlYXRlKFwiQW5vbnltb3VzIG1vY2tcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBtb2NrLmNyZWF0ZShvYmplY3QpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gZWFjaChjb2xsZWN0aW9uLCBjYWxsYmFjaykge1xuICAgICAgICAgICAgaWYgKCFjb2xsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGNvbGxlY3Rpb24ubGVuZ3RoOyBpIDwgbDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2soY29sbGVjdGlvbltpXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzaW5vbi5leHRlbmQobW9jaywge1xuICAgICAgICAgICAgY3JlYXRlOiBmdW5jdGlvbiBjcmVhdGUob2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgaWYgKCFvYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIm9iamVjdCBpcyBudWxsXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtb2NrT2JqZWN0ID0gc2lub24uZXh0ZW5kKHt9LCBtb2NrKTtcbiAgICAgICAgICAgICAgICBtb2NrT2JqZWN0Lm9iamVjdCA9IG9iamVjdDtcbiAgICAgICAgICAgICAgICBkZWxldGUgbW9ja09iamVjdC5jcmVhdGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbW9ja09iamVjdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGV4cGVjdHM6IGZ1bmN0aW9uIGV4cGVjdHMobWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFtZXRob2QpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIm1ldGhvZCBpcyBmYWxzeVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuZXhwZWN0YXRpb25zKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXhwZWN0YXRpb25zID0ge307XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJveGllcyA9IFtdO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5leHBlY3RhdGlvbnNbbWV0aG9kXSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV4cGVjdGF0aW9uc1ttZXRob2RdID0gW107XG4gICAgICAgICAgICAgICAgICAgIHZhciBtb2NrT2JqZWN0ID0gdGhpcztcblxuICAgICAgICAgICAgICAgICAgICBzaW5vbi53cmFwTWV0aG9kKHRoaXMub2JqZWN0LCBtZXRob2QsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtb2NrT2JqZWN0Lmludm9rZU1ldGhvZChtZXRob2QsIHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbCh0aGlzLnByb3hpZXMsIG1ldGhvZCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGV4cGVjdGF0aW9uID0gc2lub24uZXhwZWN0YXRpb24uY3JlYXRlKG1ldGhvZCk7XG4gICAgICAgICAgICAgICAgcHVzaC5jYWxsKHRoaXMuZXhwZWN0YXRpb25zW21ldGhvZF0sIGV4cGVjdGF0aW9uKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBleHBlY3RhdGlvbjtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlc3RvcmU6IGZ1bmN0aW9uIHJlc3RvcmUoKSB7XG4gICAgICAgICAgICAgICAgdmFyIG9iamVjdCA9IHRoaXMub2JqZWN0O1xuXG4gICAgICAgICAgICAgICAgZWFjaCh0aGlzLnByb3hpZXMsIGZ1bmN0aW9uIChwcm94eSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdFtwcm94eV0ucmVzdG9yZSA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9iamVjdFtwcm94eV0ucmVzdG9yZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB2ZXJpZnk6IGZ1bmN0aW9uIHZlcmlmeSgpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXhwZWN0YXRpb25zID0gdGhpcy5leHBlY3RhdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2VzID0gW10sIG1ldCA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZWFjaCh0aGlzLnByb3hpZXMsIGZ1bmN0aW9uIChwcm94eSkge1xuICAgICAgICAgICAgICAgICAgICBlYWNoKGV4cGVjdGF0aW9uc1twcm94eV0sIGZ1bmN0aW9uIChleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFleHBlY3RhdGlvbi5tZXQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbChtZXNzYWdlcywgZXhwZWN0YXRpb24udG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbChtZXQsIGV4cGVjdGF0aW9uLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIHRoaXMucmVzdG9yZSgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2VzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbChtZXNzYWdlcy5jb25jYXQobWV0KS5qb2luKFwiXFxuXCIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1ldC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbm9uLmV4cGVjdGF0aW9uLnBhc3MobWVzc2FnZXMuY29uY2F0KG1ldCkuam9pbihcIlxcblwiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBpbnZva2VNZXRob2Q6IGZ1bmN0aW9uIGludm9rZU1ldGhvZChtZXRob2QsIHRoaXNWYWx1ZSwgYXJncykge1xuICAgICAgICAgICAgICAgIHZhciBleHBlY3RhdGlvbnMgPSB0aGlzLmV4cGVjdGF0aW9ucyAmJiB0aGlzLmV4cGVjdGF0aW9uc1ttZXRob2RdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBleHBlY3RhdGlvbnMgJiYgZXhwZWN0YXRpb25zLmxlbmd0aCB8fCAwLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghZXhwZWN0YXRpb25zW2ldLm1ldCgpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBleHBlY3RhdGlvbnNbaV0uYWxsb3dzQ2FsbCh0aGlzVmFsdWUsIGFyZ3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXhwZWN0YXRpb25zW2ldLmFwcGx5KHRoaXNWYWx1ZSwgYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbWVzc2FnZXMgPSBbXSwgYXZhaWxhYmxlLCBleGhhdXN0ZWQgPSAwO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleHBlY3RhdGlvbnNbaV0uYWxsb3dzQ2FsbCh0aGlzVmFsdWUsIGFyZ3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhdmFpbGFibGUgPSBhdmFpbGFibGUgfHwgZXhwZWN0YXRpb25zW2ldO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXhoYXVzdGVkICs9IDE7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcHVzaC5jYWxsKG1lc3NhZ2VzLCBcIiAgICBcIiArIGV4cGVjdGF0aW9uc1tpXS50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoZXhoYXVzdGVkID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhdmFpbGFibGUuYXBwbHkodGhpc1ZhbHVlLCBhcmdzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBtZXNzYWdlcy51bnNoaWZ0KFwiVW5leHBlY3RlZCBjYWxsOiBcIiArIHNpbm9uLnNweUNhbGwudG9TdHJpbmcuY2FsbCh7XG4gICAgICAgICAgICAgICAgICAgIHByb3h5OiBtZXRob2QsXG4gICAgICAgICAgICAgICAgICAgIGFyZ3M6IGFyZ3NcbiAgICAgICAgICAgICAgICB9KSk7XG5cbiAgICAgICAgICAgICAgICBzaW5vbi5leHBlY3RhdGlvbi5mYWlsKG1lc3NhZ2VzLmpvaW4oXCJcXG5cIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgdGltZXMgPSBzaW5vbi50aW1lc0luV29yZHM7XG4gICAgICAgIHZhciBzbGljZSA9IEFycmF5LnByb3RvdHlwZS5zbGljZTtcblxuICAgICAgICBmdW5jdGlvbiBjYWxsQ291bnRJbldvcmRzKGNhbGxDb3VudCkge1xuICAgICAgICAgICAgaWYgKGNhbGxDb3VudCA9PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwibmV2ZXIgY2FsbGVkXCI7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBcImNhbGxlZCBcIiArIHRpbWVzKGNhbGxDb3VudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBleHBlY3RlZENhbGxDb3VudEluV29yZHMoZXhwZWN0YXRpb24pIHtcbiAgICAgICAgICAgIHZhciBtaW4gPSBleHBlY3RhdGlvbi5taW5DYWxscztcbiAgICAgICAgICAgIHZhciBtYXggPSBleHBlY3RhdGlvbi5tYXhDYWxscztcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBtaW4gPT0gXCJudW1iZXJcIiAmJiB0eXBlb2YgbWF4ID09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICB2YXIgc3RyID0gdGltZXMobWluKTtcblxuICAgICAgICAgICAgICAgIGlmIChtaW4gIT0gbWF4KSB7XG4gICAgICAgICAgICAgICAgICAgIHN0ciA9IFwiYXQgbGVhc3QgXCIgKyBzdHIgKyBcIiBhbmQgYXQgbW9zdCBcIiArIHRpbWVzKG1heCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHN0cjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBtaW4gPT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgIHJldHVybiBcImF0IGxlYXN0IFwiICsgdGltZXMobWluKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIFwiYXQgbW9zdCBcIiArIHRpbWVzKG1heCk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiByZWNlaXZlZE1pbkNhbGxzKGV4cGVjdGF0aW9uKSB7XG4gICAgICAgICAgICB2YXIgaGFzTWluTGltaXQgPSB0eXBlb2YgZXhwZWN0YXRpb24ubWluQ2FsbHMgPT0gXCJudW1iZXJcIjtcbiAgICAgICAgICAgIHJldHVybiAhaGFzTWluTGltaXQgfHwgZXhwZWN0YXRpb24uY2FsbENvdW50ID49IGV4cGVjdGF0aW9uLm1pbkNhbGxzO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcmVjZWl2ZWRNYXhDYWxscyhleHBlY3RhdGlvbikge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBleHBlY3RhdGlvbi5tYXhDYWxscyAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZXhwZWN0YXRpb24uY2FsbENvdW50ID09IGV4cGVjdGF0aW9uLm1heENhbGxzO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gdmVyaWZ5TWF0Y2hlcihwb3NzaWJsZU1hdGNoZXIsIGFyZykge1xuICAgICAgICAgICAgaWYgKG1hdGNoICYmIG1hdGNoLmlzTWF0Y2hlcihwb3NzaWJsZU1hdGNoZXIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBvc3NpYmxlTWF0Y2hlci50ZXN0KGFyZyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2lub24uZXhwZWN0YXRpb24gPSB7XG4gICAgICAgICAgICBtaW5DYWxsczogMSxcbiAgICAgICAgICAgIG1heENhbGxzOiAxLFxuXG4gICAgICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShtZXRob2ROYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGV4cGVjdGF0aW9uID0gc2lub24uZXh0ZW5kKHNpbm9uLnN0dWIuY3JlYXRlKCksIHNpbm9uLmV4cGVjdGF0aW9uKTtcbiAgICAgICAgICAgICAgICBkZWxldGUgZXhwZWN0YXRpb24uY3JlYXRlO1xuICAgICAgICAgICAgICAgIGV4cGVjdGF0aW9uLm1ldGhvZCA9IG1ldGhvZE5hbWU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXhwZWN0YXRpb247XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBpbnZva2U6IGZ1bmN0aW9uIGludm9rZShmdW5jLCB0aGlzVmFsdWUsIGFyZ3MpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnZlcmlmeUNhbGxBbGxvd2VkKHRoaXNWYWx1ZSwgYXJncyk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2lub24uc3B5Lmludm9rZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgYXRMZWFzdDogZnVuY3Rpb24gYXRMZWFzdChudW0pIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG51bSAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInXCIgKyBudW0gKyBcIicgaXMgbm90IG51bWJlclwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMubGltaXRzU2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubWF4Q2FsbHMgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxpbWl0c1NldCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5taW5DYWxscyA9IG51bTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgYXRNb3N0OiBmdW5jdGlvbiBhdE1vc3QobnVtKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBudW0gIT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiJ1wiICsgbnVtICsgXCInIGlzIG5vdCBudW1iZXJcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmxpbWl0c1NldCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1pbkNhbGxzID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5saW1pdHNTZXQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMubWF4Q2FsbHMgPSBudW07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG5ldmVyOiBmdW5jdGlvbiBuZXZlcigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5leGFjdGx5KDApO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb25jZTogZnVuY3Rpb24gb25jZSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5leGFjdGx5KDEpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgdHdpY2U6IGZ1bmN0aW9uIHR3aWNlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmV4YWN0bHkoMik7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB0aHJpY2U6IGZ1bmN0aW9uIHRocmljZSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5leGFjdGx5KDMpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZXhhY3RseTogZnVuY3Rpb24gZXhhY3RseShudW0pIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG51bSAhPSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCInXCIgKyBudW0gKyBcIicgaXMgbm90IGEgbnVtYmVyXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuYXRMZWFzdChudW0pO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmF0TW9zdChudW0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgbWV0OiBmdW5jdGlvbiBtZXQoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICF0aGlzLmZhaWxlZCAmJiByZWNlaXZlZE1pbkNhbGxzKHRoaXMpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgdmVyaWZ5Q2FsbEFsbG93ZWQ6IGZ1bmN0aW9uIHZlcmlmeUNhbGxBbGxvd2VkKHRoaXNWYWx1ZSwgYXJncykge1xuICAgICAgICAgICAgICAgIGlmIChyZWNlaXZlZE1heENhbGxzKHRoaXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZmFpbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbCh0aGlzLm1ldGhvZCArIFwiIGFscmVhZHkgY2FsbGVkIFwiICsgdGltZXModGhpcy5tYXhDYWxscykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChcImV4cGVjdGVkVGhpc1wiIGluIHRoaXMgJiYgdGhpcy5leHBlY3RlZFRoaXMgIT09IHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBzaW5vbi5leHBlY3RhdGlvbi5mYWlsKHRoaXMubWV0aG9kICsgXCIgY2FsbGVkIHdpdGggXCIgKyB0aGlzVmFsdWUgKyBcIiBhcyB0aGlzVmFsdWUsIGV4cGVjdGVkIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZXhwZWN0ZWRUaGlzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShcImV4cGVjdGVkQXJndW1lbnRzXCIgaW4gdGhpcykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghYXJncykge1xuICAgICAgICAgICAgICAgICAgICBzaW5vbi5leHBlY3RhdGlvbi5mYWlsKHRoaXMubWV0aG9kICsgXCIgcmVjZWl2ZWQgbm8gYXJndW1lbnRzLCBleHBlY3RlZCBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICBzaW5vbi5mb3JtYXQodGhpcy5leHBlY3RlZEFyZ3VtZW50cykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcmdzLmxlbmd0aCA8IHRoaXMuZXhwZWN0ZWRBcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbm9uLmV4cGVjdGF0aW9uLmZhaWwodGhpcy5tZXRob2QgKyBcIiByZWNlaXZlZCB0b28gZmV3IGFyZ3VtZW50cyAoXCIgKyBzaW5vbi5mb3JtYXQoYXJncykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgXCIpLCBleHBlY3RlZCBcIiArIHNpbm9uLmZvcm1hdCh0aGlzLmV4cGVjdGVkQXJndW1lbnRzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZXhwZWN0c0V4YWN0QXJnQ291bnQgJiZcbiAgICAgICAgICAgICAgICAgICAgYXJncy5sZW5ndGggIT0gdGhpcy5leHBlY3RlZEFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbCh0aGlzLm1ldGhvZCArIFwiIHJlY2VpdmVkIHRvbyBtYW55IGFyZ3VtZW50cyAoXCIgKyBzaW5vbi5mb3JtYXQoYXJncykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgXCIpLCBleHBlY3RlZCBcIiArIHNpbm9uLmZvcm1hdCh0aGlzLmV4cGVjdGVkQXJndW1lbnRzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSB0aGlzLmV4cGVjdGVkQXJndW1lbnRzLmxlbmd0aDsgaSA8IGw7IGkgKz0gMSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdmVyaWZ5TWF0Y2hlcih0aGlzLmV4cGVjdGVkQXJndW1lbnRzW2ldLCBhcmdzW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbCh0aGlzLm1ldGhvZCArIFwiIHJlY2VpdmVkIHdyb25nIGFyZ3VtZW50cyBcIiArIHNpbm9uLmZvcm1hdChhcmdzKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCIsIGRpZG4ndCBtYXRjaCBcIiArIHRoaXMuZXhwZWN0ZWRBcmd1bWVudHMudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbm9uLmRlZXBFcXVhbCh0aGlzLmV4cGVjdGVkQXJndW1lbnRzW2ldLCBhcmdzW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbCh0aGlzLm1ldGhvZCArIFwiIHJlY2VpdmVkIHdyb25nIGFyZ3VtZW50cyBcIiArIHNpbm9uLmZvcm1hdChhcmdzKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCIsIGV4cGVjdGVkIFwiICsgc2lub24uZm9ybWF0KHRoaXMuZXhwZWN0ZWRBcmd1bWVudHMpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGFsbG93c0NhbGw6IGZ1bmN0aW9uIGFsbG93c0NhbGwodGhpc1ZhbHVlLCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubWV0KCkgJiYgcmVjZWl2ZWRNYXhDYWxscyh0aGlzKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKFwiZXhwZWN0ZWRUaGlzXCIgaW4gdGhpcyAmJiB0aGlzLmV4cGVjdGVkVGhpcyAhPT0gdGhpc1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShcImV4cGVjdGVkQXJndW1lbnRzXCIgaW4gdGhpcykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgYXJncyA9IGFyZ3MgfHwgW107XG5cbiAgICAgICAgICAgICAgICBpZiAoYXJncy5sZW5ndGggPCB0aGlzLmV4cGVjdGVkQXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZXhwZWN0c0V4YWN0QXJnQ291bnQgJiZcbiAgICAgICAgICAgICAgICAgICAgYXJncy5sZW5ndGggIT0gdGhpcy5leHBlY3RlZEFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gdGhpcy5leHBlY3RlZEFyZ3VtZW50cy5sZW5ndGg7IGkgPCBsOyBpICs9IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF2ZXJpZnlNYXRjaGVyKHRoaXMuZXhwZWN0ZWRBcmd1bWVudHNbaV0sIGFyZ3NbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbm9uLmRlZXBFcXVhbCh0aGlzLmV4cGVjdGVkQXJndW1lbnRzW2ldLCBhcmdzW2ldKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB3aXRoQXJnczogZnVuY3Rpb24gd2l0aEFyZ3MoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5leHBlY3RlZEFyZ3VtZW50cyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHdpdGhFeGFjdEFyZ3M6IGZ1bmN0aW9uIHdpdGhFeGFjdEFyZ3MoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53aXRoQXJncy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIHRoaXMuZXhwZWN0c0V4YWN0QXJnQ291bnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb246IGZ1bmN0aW9uIG9uKHRoaXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZXhwZWN0ZWRUaGlzID0gdGhpc1ZhbHVlO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgdG9TdHJpbmc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXJncyA9ICh0aGlzLmV4cGVjdGVkQXJndW1lbnRzIHx8IFtdKS5zbGljZSgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmV4cGVjdHNFeGFjdEFyZ0NvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbChhcmdzLCBcIlsuLi5dXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjYWxsU3RyID0gc2lub24uc3B5Q2FsbC50b1N0cmluZy5jYWxsKHtcbiAgICAgICAgICAgICAgICAgICAgcHJveHk6IHRoaXMubWV0aG9kIHx8IFwiYW5vbnltb3VzIG1vY2sgZXhwZWN0YXRpb25cIixcbiAgICAgICAgICAgICAgICAgICAgYXJnczogYXJnc1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBjYWxsU3RyLnJlcGxhY2UoXCIsIFsuLi5cIiwgXCJbLCAuLi5cIikgKyBcIiBcIiArXG4gICAgICAgICAgICAgICAgICAgIGV4cGVjdGVkQ2FsbENvdW50SW5Xb3Jkcyh0aGlzKTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLm1ldCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkV4cGVjdGF0aW9uIG1ldDogXCIgKyBtZXNzYWdlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBcIkV4cGVjdGVkIFwiICsgbWVzc2FnZSArIFwiIChcIiArXG4gICAgICAgICAgICAgICAgICAgIGNhbGxDb3VudEluV29yZHModGhpcy5jYWxsQ291bnQpICsgXCIpXCI7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB2ZXJpZnk6IGZ1bmN0aW9uIHZlcmlmeSgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMubWV0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgc2lub24uZXhwZWN0YXRpb24uZmFpbCh0aGlzLnRvU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbm9uLmV4cGVjdGF0aW9uLnBhc3ModGhpcy50b1N0cmluZygpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHBhc3M6IGZ1bmN0aW9uIHBhc3MobWVzc2FnZSkge1xuICAgICAgICAgICAgICAgIHNpbm9uLmFzc2VydC5wYXNzKG1lc3NhZ2UpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZmFpbDogZnVuY3Rpb24gZmFpbChtZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGV4Y2VwdGlvbiA9IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgICAgICAgICAgICAgICBleGNlcHRpb24ubmFtZSA9IFwiRXhwZWN0YXRpb25FcnJvclwiO1xuXG4gICAgICAgICAgICAgICAgdGhyb3cgZXhjZXB0aW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLm1vY2sgPSBtb2NrO1xuICAgICAgICByZXR1cm4gbW9jaztcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3RpbWVzX2luX3dvcmRzXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9jYWxsXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9leHRlbmRcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL21hdGNoXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9zcHlcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL3N0dWJcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2Zvcm1hdFwiKTtcblxuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG1ha2VBcGkoc2lub24pO1xuICAgIH1cblxuICAgIGlmIChpc0FNRCkge1xuICAgICAgICBkZWZpbmUobG9hZERlcGVuZGVuY2llcyk7XG4gICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBtb2R1bGUuZXhwb3J0cywgbW9kdWxlKTtcbiAgICB9IGVsc2UgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufSh0eXBlb2Ygc2lub24gPT0gXCJvYmplY3RcIiAmJiBzaW5vbiB8fCBudWxsKSk7XG4iLCIvKipcbiAqIEBkZXBlbmQgdXRpbC9jb3JlLmpzXG4gKiBAZGVwZW5kIGV4dGVuZC5qc1xuICogQGRlcGVuZCBjb2xsZWN0aW9uLmpzXG4gKiBAZGVwZW5kIHV0aWwvZmFrZV90aW1lcnMuanNcbiAqIEBkZXBlbmQgdXRpbC9mYWtlX3NlcnZlcl93aXRoX2Nsb2NrLmpzXG4gKi9cbi8qKlxuICogTWFuYWdlcyBmYWtlIGNvbGxlY3Rpb25zIGFzIHdlbGwgYXMgZmFrZSB1dGlsaXRpZXMgc3VjaCBhcyBTaW5vbidzXG4gKiB0aW1lcnMgYW5kIGZha2UgWEhSIGltcGxlbWVudGF0aW9uIGluIG9uZSBjb252ZW5pZW50IG9iamVjdC5cbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBtYWtlQXBpKHNpbm9uKSB7XG4gICAgICAgIHZhciBwdXNoID0gW10ucHVzaDtcblxuICAgICAgICBmdW5jdGlvbiBleHBvc2VWYWx1ZShzYW5kYm94LCBjb25maWcsIGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgIGlmICghdmFsdWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcuaW5qZWN0SW50byAmJiAhKGtleSBpbiBjb25maWcuaW5qZWN0SW50bykpIHtcbiAgICAgICAgICAgICAgICBjb25maWcuaW5qZWN0SW50b1trZXldID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgc2FuZGJveC5pbmplY3RlZEtleXMucHVzaChrZXkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwoc2FuZGJveC5hcmdzLCB2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBwcmVwYXJlU2FuZGJveEZyb21Db25maWcoY29uZmlnKSB7XG4gICAgICAgICAgICB2YXIgc2FuZGJveCA9IHNpbm9uLmNyZWF0ZShzaW5vbi5zYW5kYm94KTtcblxuICAgICAgICAgICAgaWYgKGNvbmZpZy51c2VGYWtlU2VydmVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjb25maWcudXNlRmFrZVNlcnZlciA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHNhbmRib3guc2VydmVyUHJvdG90eXBlID0gY29uZmlnLnVzZUZha2VTZXJ2ZXI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgc2FuZGJveC51c2VGYWtlU2VydmVyKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjb25maWcudXNlRmFrZVRpbWVycykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY29uZmlnLnVzZUZha2VUaW1lcnMgPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICBzYW5kYm94LnVzZUZha2VUaW1lcnMuYXBwbHkoc2FuZGJveCwgY29uZmlnLnVzZUZha2VUaW1lcnMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHNhbmRib3gudXNlRmFrZVRpbWVycygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHNhbmRib3g7XG4gICAgICAgIH1cblxuICAgICAgICBzaW5vbi5zYW5kYm94ID0gc2lub24uZXh0ZW5kKHNpbm9uLmNyZWF0ZShzaW5vbi5jb2xsZWN0aW9uKSwge1xuICAgICAgICAgICAgdXNlRmFrZVRpbWVyczogZnVuY3Rpb24gdXNlRmFrZVRpbWVycygpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNsb2NrID0gc2lub24udXNlRmFrZVRpbWVycy5hcHBseShzaW5vbiwgYXJndW1lbnRzKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmFkZCh0aGlzLmNsb2NrKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHNlcnZlclByb3RvdHlwZTogc2lub24uZmFrZVNlcnZlcixcblxuICAgICAgICAgICAgdXNlRmFrZVNlcnZlcjogZnVuY3Rpb24gdXNlRmFrZVNlcnZlcigpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJvdG8gPSB0aGlzLnNlcnZlclByb3RvdHlwZSB8fCBzaW5vbi5mYWtlU2VydmVyO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFwcm90byB8fCAhcHJvdG8uY3JlYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuc2VydmVyID0gcHJvdG8uY3JlYXRlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYWRkKHRoaXMuc2VydmVyKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGluamVjdDogZnVuY3Rpb24gKG9iaikge1xuICAgICAgICAgICAgICAgIHNpbm9uLmNvbGxlY3Rpb24uaW5qZWN0LmNhbGwodGhpcywgb2JqKTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNsb2NrKSB7XG4gICAgICAgICAgICAgICAgICAgIG9iai5jbG9jayA9IHRoaXMuY2xvY2s7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2VydmVyKSB7XG4gICAgICAgICAgICAgICAgICAgIG9iai5zZXJ2ZXIgPSB0aGlzLnNlcnZlcjtcbiAgICAgICAgICAgICAgICAgICAgb2JqLnJlcXVlc3RzID0gdGhpcy5zZXJ2ZXIucmVxdWVzdHM7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgb2JqLm1hdGNoID0gc2lub24ubWF0Y2g7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgcmVzdG9yZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNpbm9uLmNvbGxlY3Rpb24ucmVzdG9yZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIHRoaXMucmVzdG9yZUNvbnRleHQoKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlc3RvcmVDb250ZXh0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaW5qZWN0ZWRLZXlzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBqID0gdGhpcy5pbmplY3RlZEtleXMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgdGhpcy5pbmplY3RJbnRvW3RoaXMuaW5qZWN0ZWRLZXlzW2ldXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGlzLmluamVjdGVkS2V5cyA9IFtdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGNyZWF0ZTogZnVuY3Rpb24gKGNvbmZpZykge1xuICAgICAgICAgICAgICAgIGlmICghY29uZmlnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzaW5vbi5jcmVhdGUoc2lub24uc2FuZGJveCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNhbmRib3ggPSBwcmVwYXJlU2FuZGJveEZyb21Db25maWcoY29uZmlnKTtcbiAgICAgICAgICAgICAgICBzYW5kYm94LmFyZ3MgPSBzYW5kYm94LmFyZ3MgfHwgW107XG4gICAgICAgICAgICAgICAgc2FuZGJveC5pbmplY3RlZEtleXMgPSBbXTtcbiAgICAgICAgICAgICAgICBzYW5kYm94LmluamVjdEludG8gPSBjb25maWcuaW5qZWN0SW50bztcbiAgICAgICAgICAgICAgICB2YXIgcHJvcCwgdmFsdWUsIGV4cG9zZWQgPSBzYW5kYm94LmluamVjdCh7fSk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY29uZmlnLnByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBjb25maWcucHJvcGVydGllcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3AgPSBjb25maWcucHJvcGVydGllc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gZXhwb3NlZFtwcm9wXSB8fCBwcm9wID09IFwic2FuZGJveFwiICYmIHNhbmRib3g7XG4gICAgICAgICAgICAgICAgICAgICAgICBleHBvc2VWYWx1ZShzYW5kYm94LCBjb25maWcsIHByb3AsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9zZVZhbHVlKHNhbmRib3gsIGNvbmZpZywgXCJzYW5kYm94XCIsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2FuZGJveDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG1hdGNoOiBzaW5vbi5tYXRjaFxuICAgICAgICB9KTtcblxuICAgICAgICBzaW5vbi5zYW5kYm94LnVzZUZha2VYTUxIdHRwUmVxdWVzdCA9IHNpbm9uLnNhbmRib3gudXNlRmFrZVNlcnZlcjtcblxuICAgICAgICByZXR1cm4gc2lub24uc2FuZGJveDtcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2V4dGVuZFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vdXRpbC9mYWtlX3NlcnZlcl93aXRoX2Nsb2NrXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi91dGlsL2Zha2VfdGltZXJzXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9jb2xsZWN0aW9uXCIpO1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG1ha2VBcGkoc2lub24pO1xuICAgIH1cblxuICAgIGlmIChpc0FNRCkge1xuICAgICAgICBkZWZpbmUobG9hZERlcGVuZGVuY2llcyk7XG4gICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBtb2R1bGUuZXhwb3J0cywgbW9kdWxlKTtcbiAgICB9IGVsc2UgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufSgpKTtcbiIsIi8qKlxuICAqIEBkZXBlbmQgdGltZXNfaW5fd29yZHMuanNcbiAgKiBAZGVwZW5kIHV0aWwvY29yZS5qc1xuICAqIEBkZXBlbmQgZXh0ZW5kLmpzXG4gICogQGRlcGVuZCBjYWxsLmpzXG4gICogQGRlcGVuZCBmb3JtYXQuanNcbiAgKi9cbi8qKlxuICAqIFNweSBmdW5jdGlvbnNcbiAgKlxuICAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICAqIEBsaWNlbnNlIEJTRFxuICAqXG4gICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuXG4gICAgZnVuY3Rpb24gbWFrZUFwaShzaW5vbikge1xuICAgICAgICB2YXIgcHVzaCA9IEFycmF5LnByb3RvdHlwZS5wdXNoO1xuICAgICAgICB2YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG4gICAgICAgIHZhciBjYWxsSWQgPSAwO1xuXG4gICAgICAgIGZ1bmN0aW9uIHNweShvYmplY3QsIHByb3BlcnR5LCB0eXBlcykge1xuICAgICAgICAgICAgaWYgKCFwcm9wZXJ0eSAmJiB0eXBlb2Ygb2JqZWN0ID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIHJldHVybiBzcHkuY3JlYXRlKG9iamVjdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghb2JqZWN0ICYmICFwcm9wZXJ0eSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzcHkuY3JlYXRlKGZ1bmN0aW9uICgpIHsgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlcykge1xuICAgICAgICAgICAgICAgIHZhciBtZXRob2REZXNjID0gc2lub24uZ2V0UHJvcGVydHlEZXNjcmlwdG9yKG9iamVjdCwgcHJvcGVydHkpO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHlwZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kRGVzY1t0eXBlc1tpXV0gPSBzcHkuY3JlYXRlKG1ldGhvZERlc2NbdHlwZXNbaV1dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNpbm9uLndyYXBNZXRob2Qob2JqZWN0LCBwcm9wZXJ0eSwgbWV0aG9kRGVzYyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBtZXRob2QgPSBvYmplY3RbcHJvcGVydHldO1xuICAgICAgICAgICAgICAgIHJldHVybiBzaW5vbi53cmFwTWV0aG9kKG9iamVjdCwgcHJvcGVydHksIHNweS5jcmVhdGUobWV0aG9kKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBtYXRjaGluZ0Zha2UoZmFrZXMsIGFyZ3MsIHN0cmljdCkge1xuICAgICAgICAgICAgaWYgKCFmYWtlcykge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBmYWtlcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoZmFrZXNbaV0ubWF0Y2hlcyhhcmdzLCBzdHJpY3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWtlc1tpXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBpbmNyZW1lbnRDYWxsQ291bnQoKSB7XG4gICAgICAgICAgICB0aGlzLmNhbGxlZCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmNhbGxDb3VudCArPSAxO1xuICAgICAgICAgICAgdGhpcy5ub3RDYWxsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuY2FsbGVkT25jZSA9IHRoaXMuY2FsbENvdW50ID09IDE7XG4gICAgICAgICAgICB0aGlzLmNhbGxlZFR3aWNlID0gdGhpcy5jYWxsQ291bnQgPT0gMjtcbiAgICAgICAgICAgIHRoaXMuY2FsbGVkVGhyaWNlID0gdGhpcy5jYWxsQ291bnQgPT0gMztcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUNhbGxQcm9wZXJ0aWVzKCkge1xuICAgICAgICAgICAgdGhpcy5maXJzdENhbGwgPSB0aGlzLmdldENhbGwoMCk7XG4gICAgICAgICAgICB0aGlzLnNlY29uZENhbGwgPSB0aGlzLmdldENhbGwoMSk7XG4gICAgICAgICAgICB0aGlzLnRoaXJkQ2FsbCA9IHRoaXMuZ2V0Q2FsbCgyKTtcbiAgICAgICAgICAgIHRoaXMubGFzdENhbGwgPSB0aGlzLmdldENhbGwodGhpcy5jYWxsQ291bnQgLSAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB2YXJzID0gXCJhLGIsYyxkLGUsZixnLGgsaSxqLGssbFwiO1xuICAgICAgICBmdW5jdGlvbiBjcmVhdGVQcm94eShmdW5jLCBwcm94eUxlbmd0aCkge1xuICAgICAgICAgICAgLy8gUmV0YWluIHRoZSBmdW5jdGlvbiBsZW5ndGg6XG4gICAgICAgICAgICB2YXIgcDtcbiAgICAgICAgICAgIGlmIChwcm94eUxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGV2YWwoXCJwID0gKGZ1bmN0aW9uIHByb3h5KFwiICsgdmFycy5zdWJzdHJpbmcoMCwgcHJveHlMZW5ndGggKiAyIC0gMSkgK1xuICAgICAgICAgICAgICAgICAgICBcIikgeyByZXR1cm4gcC5pbnZva2UoZnVuYywgdGhpcywgc2xpY2UuY2FsbChhcmd1bWVudHMpKTsgfSk7XCIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwID0gZnVuY3Rpb24gcHJveHkoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwLmludm9rZShmdW5jLCB0aGlzLCBzbGljZS5jYWxsKGFyZ3VtZW50cykpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwLmlzU2lub25Qcm94eSA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm4gcDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB1dWlkID0gMDtcblxuICAgICAgICAvLyBQdWJsaWMgQVBJXG4gICAgICAgIHZhciBzcHlBcGkgPSB7XG4gICAgICAgICAgICByZXNldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmludm9raW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoXCJDYW5ub3QgcmVzZXQgU2lub24gZnVuY3Rpb24gd2hpbGUgaW52b2tpbmcgaXQuIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIk1vdmUgdGhlIGNhbGwgdG8gLnJlc2V0IG91dHNpZGUgb2YgdGhlIGNhbGxiYWNrLlwiKTtcbiAgICAgICAgICAgICAgICAgICAgZXJyLm5hbWUgPSBcIkludmFsaWRSZXNldEV4Y2VwdGlvblwiO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB0aGlzLm5vdENhbGxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsZWRPbmNlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsZWRUd2ljZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbGVkVGhyaWNlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5jYWxsQ291bnQgPSAwO1xuICAgICAgICAgICAgICAgIHRoaXMuZmlyc3RDYWxsID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLnNlY29uZENhbGwgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMudGhpcmRDYWxsID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLmxhc3RDYWxsID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLmFyZ3MgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLnJldHVyblZhbHVlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMudGhpc1ZhbHVlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMuZXhjZXB0aW9ucyA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FsbElkcyA9IFtdO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmZha2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5mYWtlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mYWtlc1tpXS5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShmdW5jLCBzcHlMZW5ndGgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmFtZTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZnVuYyAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZnVuYyA9IGZ1bmN0aW9uICgpIHsgfTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuYW1lID0gc2lub24uZnVuY3Rpb25OYW1lKGZ1bmMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghc3B5TGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNweUxlbmd0aCA9IGZ1bmMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwcm94eSA9IGNyZWF0ZVByb3h5KGZ1bmMsIHNweUxlbmd0aCk7XG5cbiAgICAgICAgICAgICAgICBzaW5vbi5leHRlbmQocHJveHksIHNweSk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHByb3h5LmNyZWF0ZTtcbiAgICAgICAgICAgICAgICBzaW5vbi5leHRlbmQocHJveHksIGZ1bmMpO1xuXG4gICAgICAgICAgICAgICAgcHJveHkucmVzZXQoKTtcbiAgICAgICAgICAgICAgICBwcm94eS5wcm90b3R5cGUgPSBmdW5jLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICBwcm94eS5kaXNwbGF5TmFtZSA9IG5hbWUgfHwgXCJzcHlcIjtcbiAgICAgICAgICAgICAgICBwcm94eS50b1N0cmluZyA9IHNpbm9uLmZ1bmN0aW9uVG9TdHJpbmc7XG4gICAgICAgICAgICAgICAgcHJveHkuaW5zdGFudGlhdGVGYWtlID0gc2lub24uc3B5LmNyZWF0ZTtcbiAgICAgICAgICAgICAgICBwcm94eS5pZCA9IFwic3B5I1wiICsgdXVpZCsrO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3h5O1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgaW52b2tlOiBmdW5jdGlvbiBpbnZva2UoZnVuYywgdGhpc1ZhbHVlLCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hdGNoaW5nID0gbWF0Y2hpbmdGYWtlKHRoaXMuZmFrZXMsIGFyZ3MpO1xuICAgICAgICAgICAgICAgIHZhciBleGNlcHRpb24sIHJldHVyblZhbHVlO1xuXG4gICAgICAgICAgICAgICAgaW5jcmVtZW50Q2FsbENvdW50LmNhbGwodGhpcyk7XG4gICAgICAgICAgICAgICAgcHVzaC5jYWxsKHRoaXMudGhpc1ZhbHVlcywgdGhpc1ZhbHVlKTtcbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwodGhpcy5hcmdzLCBhcmdzKTtcbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwodGhpcy5jYWxsSWRzLCBjYWxsSWQrKyk7XG5cbiAgICAgICAgICAgICAgICAvLyBNYWtlIGNhbGwgcHJvcGVydGllcyBhdmFpbGFibGUgZnJvbSB3aXRoaW4gdGhlIHNwaWVkIGZ1bmN0aW9uOlxuICAgICAgICAgICAgICAgIGNyZWF0ZUNhbGxQcm9wZXJ0aWVzLmNhbGwodGhpcyk7XG5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmludm9raW5nID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2hpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVyblZhbHVlID0gbWF0Y2hpbmcuaW52b2tlKGZ1bmMsIHRoaXNWYWx1ZSwgYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm5WYWx1ZSA9ICh0aGlzLmZ1bmMgfHwgZnVuYykuYXBwbHkodGhpc1ZhbHVlLCBhcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB0aGlzQ2FsbCA9IHRoaXMuZ2V0Q2FsbCh0aGlzLmNhbGxDb3VudCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpc0NhbGwuY2FsbGVkV2l0aE5ldygpICYmIHR5cGVvZiByZXR1cm5WYWx1ZSAhPT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuVmFsdWUgPSB0aGlzVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGV4Y2VwdGlvbiA9IGU7XG4gICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuaW52b2tpbmc7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHVzaC5jYWxsKHRoaXMuZXhjZXB0aW9ucywgZXhjZXB0aW9uKTtcbiAgICAgICAgICAgICAgICBwdXNoLmNhbGwodGhpcy5yZXR1cm5WYWx1ZXMsIHJldHVyblZhbHVlKTtcblxuICAgICAgICAgICAgICAgIC8vIE1ha2UgcmV0dXJuIHZhbHVlIGFuZCBleGNlcHRpb24gYXZhaWxhYmxlIGluIHRoZSBjYWxsczpcbiAgICAgICAgICAgICAgICBjcmVhdGVDYWxsUHJvcGVydGllcy5jYWxsKHRoaXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGV4Y2VwdGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IGV4Y2VwdGlvbjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmV0dXJuVmFsdWU7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBuYW1lZDogZnVuY3Rpb24gbmFtZWQobmFtZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZGlzcGxheU5hbWUgPSBuYW1lO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZ2V0Q2FsbDogZnVuY3Rpb24gZ2V0Q2FsbChpKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgPCAwIHx8IGkgPj0gdGhpcy5jYWxsQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNpbm9uLnNweUNhbGwodGhpcywgdGhpcy50aGlzVmFsdWVzW2ldLCB0aGlzLmFyZ3NbaV0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXR1cm5WYWx1ZXNbaV0sIHRoaXMuZXhjZXB0aW9uc1tpXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhbGxJZHNbaV0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZ2V0Q2FsbHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2FsbHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNhbGxDb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhbGxzLnB1c2godGhpcy5nZXRDYWxsKGkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gY2FsbHM7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsZWRCZWZvcmU6IGZ1bmN0aW9uIGNhbGxlZEJlZm9yZShzcHlGbikge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5jYWxsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghc3B5Rm4uY2FsbGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNhbGxJZHNbMF0gPCBzcHlGbi5jYWxsSWRzW3NweUZuLmNhbGxJZHMubGVuZ3RoIC0gMV07XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjYWxsZWRBZnRlcjogZnVuY3Rpb24gY2FsbGVkQWZ0ZXIoc3B5Rm4pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY2FsbGVkIHx8ICFzcHlGbi5jYWxsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmNhbGxJZHNbdGhpcy5jYWxsQ291bnQgLSAxXSA+IHNweUZuLmNhbGxJZHNbc3B5Rm4uY2FsbENvdW50IC0gMV07XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB3aXRoQXJnczogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZmFrZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG1hdGNoID0gbWF0Y2hpbmdGYWtlKHRoaXMuZmFrZXMsIGFyZ3MsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mYWtlcyA9IFtdO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBvcmlnaW5hbCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgdmFyIGZha2UgPSB0aGlzLmluc3RhbnRpYXRlRmFrZSgpO1xuICAgICAgICAgICAgICAgIGZha2UubWF0Y2hpbmdBZ3VtZW50cyA9IGFyZ3M7XG4gICAgICAgICAgICAgICAgZmFrZS5wYXJlbnQgPSB0aGlzO1xuICAgICAgICAgICAgICAgIHB1c2guY2FsbCh0aGlzLmZha2VzLCBmYWtlKTtcblxuICAgICAgICAgICAgICAgIGZha2Uud2l0aEFyZ3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbC53aXRoQXJncy5hcHBseShvcmlnaW5hbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZha2UubWF0Y2hlcyh0aGlzLmFyZ3NbaV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmNyZW1lbnRDYWxsQ291bnQuY2FsbChmYWtlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1c2guY2FsbChmYWtlLnRoaXNWYWx1ZXMsIHRoaXMudGhpc1ZhbHVlc1tpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdXNoLmNhbGwoZmFrZS5hcmdzLCB0aGlzLmFyZ3NbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVzaC5jYWxsKGZha2UucmV0dXJuVmFsdWVzLCB0aGlzLnJldHVyblZhbHVlc1tpXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdXNoLmNhbGwoZmFrZS5leGNlcHRpb25zLCB0aGlzLmV4Y2VwdGlvbnNbaV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVzaC5jYWxsKGZha2UuY2FsbElkcywgdGhpcy5jYWxsSWRzW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjcmVhdGVDYWxsUHJvcGVydGllcy5jYWxsKGZha2UpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZha2U7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBtYXRjaGVzOiBmdW5jdGlvbiAoYXJncywgc3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hcmdzID0gdGhpcy5tYXRjaGluZ0FndW1lbnRzO1xuXG4gICAgICAgICAgICAgICAgaWYgKG1hcmdzLmxlbmd0aCA8PSBhcmdzLmxlbmd0aCAmJlxuICAgICAgICAgICAgICAgICAgICBzaW5vbi5kZWVwRXF1YWwobWFyZ3MsIGFyZ3Muc2xpY2UoMCwgbWFyZ3MubGVuZ3RoKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICFzdHJpY3QgfHwgbWFyZ3MubGVuZ3RoID09IGFyZ3MubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHByaW50ZjogZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICAgICAgICAgIHZhciBzcHkgPSB0aGlzO1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgICAgIHZhciBmb3JtYXR0ZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gKGZvcm1hdCB8fCBcIlwiKS5yZXBsYWNlKC8lKC4pL2csIGZ1bmN0aW9uIChtYXRjaCwgc3BlY2lmeWVyKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcm1hdHRlciA9IHNweUFwaS5mb3JtYXR0ZXJzW3NwZWNpZnllcl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBmb3JtYXR0ZXIgPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZm9ybWF0dGVyLmNhbGwobnVsbCwgc3B5LCBhcmdzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNOYU4ocGFyc2VJbnQoc3BlY2lmeWVyLCAxMCkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2lub24uZm9ybWF0KGFyZ3Nbc3BlY2lmeWVyIC0gMV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiJVwiICsgc3BlY2lmeWVyO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGZ1bmN0aW9uIGRlbGVnYXRlVG9DYWxscyhtZXRob2QsIG1hdGNoQW55LCBhY3R1YWwsIG5vdENhbGxlZCkge1xuICAgICAgICAgICAgc3B5QXBpW21ldGhvZF0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNhbGxlZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobm90Q2FsbGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbm90Q2FsbGVkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50Q2FsbDtcbiAgICAgICAgICAgICAgICB2YXIgbWF0Y2hlcyA9IDA7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHRoaXMuY2FsbENvdW50OyBpIDwgbDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRDYWxsID0gdGhpcy5nZXRDYWxsKGkpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50Q2FsbFthY3R1YWwgfHwgbWV0aG9kXS5hcHBseShjdXJyZW50Q2FsbCwgYXJndW1lbnRzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2hBbnkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBtYXRjaGVzID09PSB0aGlzLmNhbGxDb3VudDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICBkZWxlZ2F0ZVRvQ2FsbHMoXCJjYWxsZWRPblwiLCB0cnVlKTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwiYWx3YXlzQ2FsbGVkT25cIiwgZmFsc2UsIFwiY2FsbGVkT25cIik7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcImNhbGxlZFdpdGhcIiwgdHJ1ZSk7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcImNhbGxlZFdpdGhNYXRjaFwiLCB0cnVlKTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwiYWx3YXlzQ2FsbGVkV2l0aFwiLCBmYWxzZSwgXCJjYWxsZWRXaXRoXCIpO1xuICAgICAgICBkZWxlZ2F0ZVRvQ2FsbHMoXCJhbHdheXNDYWxsZWRXaXRoTWF0Y2hcIiwgZmFsc2UsIFwiY2FsbGVkV2l0aE1hdGNoXCIpO1xuICAgICAgICBkZWxlZ2F0ZVRvQ2FsbHMoXCJjYWxsZWRXaXRoRXhhY3RseVwiLCB0cnVlKTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwiYWx3YXlzQ2FsbGVkV2l0aEV4YWN0bHlcIiwgZmFsc2UsIFwiY2FsbGVkV2l0aEV4YWN0bHlcIik7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcIm5ldmVyQ2FsbGVkV2l0aFwiLCBmYWxzZSwgXCJub3RDYWxsZWRXaXRoXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwibmV2ZXJDYWxsZWRXaXRoTWF0Y2hcIiwgZmFsc2UsIFwibm90Q2FsbGVkV2l0aE1hdGNoXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9KTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwidGhyZXdcIiwgdHJ1ZSk7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcImFsd2F5c1RocmV3XCIsIGZhbHNlLCBcInRocmV3XCIpO1xuICAgICAgICBkZWxlZ2F0ZVRvQ2FsbHMoXCJyZXR1cm5lZFwiLCB0cnVlKTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwiYWx3YXlzUmV0dXJuZWRcIiwgZmFsc2UsIFwicmV0dXJuZWRcIik7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcImNhbGxlZFdpdGhOZXdcIiwgdHJ1ZSk7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcImFsd2F5c0NhbGxlZFdpdGhOZXdcIiwgZmFsc2UsIFwiY2FsbGVkV2l0aE5ld1wiKTtcbiAgICAgICAgZGVsZWdhdGVUb0NhbGxzKFwiY2FsbEFyZ1wiLCBmYWxzZSwgXCJjYWxsQXJnV2l0aFwiLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy50b1N0cmluZygpICsgXCIgY2Fubm90IGNhbGwgYXJnIHNpbmNlIGl0IHdhcyBub3QgeWV0IGludm9rZWQuXCIpO1xuICAgICAgICB9KTtcbiAgICAgICAgc3B5QXBpLmNhbGxBcmdXaXRoID0gc3B5QXBpLmNhbGxBcmc7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcImNhbGxBcmdPblwiLCBmYWxzZSwgXCJjYWxsQXJnT25XaXRoXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLnRvU3RyaW5nKCkgKyBcIiBjYW5ub3QgY2FsbCBhcmcgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5cIik7XG4gICAgICAgIH0pO1xuICAgICAgICBzcHlBcGkuY2FsbEFyZ09uV2l0aCA9IHNweUFwaS5jYWxsQXJnT247XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcInlpZWxkXCIsIGZhbHNlLCBcInlpZWxkXCIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLnRvU3RyaW5nKCkgKyBcIiBjYW5ub3QgeWllbGQgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5cIik7XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBcImludm9rZUNhbGxiYWNrXCIgaXMgYW4gYWxpYXMgZm9yIFwieWllbGRcIiBzaW5jZSBcInlpZWxkXCIgaXMgaW52YWxpZCBpbiBzdHJpY3QgbW9kZS5cbiAgICAgICAgc3B5QXBpLmludm9rZUNhbGxiYWNrID0gc3B5QXBpLnlpZWxkO1xuICAgICAgICBkZWxlZ2F0ZVRvQ2FsbHMoXCJ5aWVsZE9uXCIsIGZhbHNlLCBcInlpZWxkT25cIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHRoaXMudG9TdHJpbmcoKSArIFwiIGNhbm5vdCB5aWVsZCBzaW5jZSBpdCB3YXMgbm90IHlldCBpbnZva2VkLlwiKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcInlpZWxkVG9cIiwgZmFsc2UsIFwieWllbGRUb1wiLCBmdW5jdGlvbiAocHJvcGVydHkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcih0aGlzLnRvU3RyaW5nKCkgKyBcIiBjYW5ub3QgeWllbGQgdG8gJ1wiICsgcHJvcGVydHkgK1xuICAgICAgICAgICAgICAgIFwiJyBzaW5jZSBpdCB3YXMgbm90IHlldCBpbnZva2VkLlwiKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGRlbGVnYXRlVG9DYWxscyhcInlpZWxkVG9PblwiLCBmYWxzZSwgXCJ5aWVsZFRvT25cIiwgZnVuY3Rpb24gKHByb3BlcnR5KSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IodGhpcy50b1N0cmluZygpICsgXCIgY2Fubm90IHlpZWxkIHRvICdcIiArIHByb3BlcnR5ICtcbiAgICAgICAgICAgICAgICBcIicgc2luY2UgaXQgd2FzIG5vdCB5ZXQgaW52b2tlZC5cIik7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHNweUFwaS5mb3JtYXR0ZXJzID0ge1xuICAgICAgICAgICAgYzogZnVuY3Rpb24gKHNweSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzaW5vbi50aW1lc0luV29yZHMoc3B5LmNhbGxDb3VudCk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBuOiBmdW5jdGlvbiAoc3B5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNweS50b1N0cmluZygpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgQzogZnVuY3Rpb24gKHNweSkge1xuICAgICAgICAgICAgICAgIHZhciBjYWxscyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBzcHkuY2FsbENvdW50OyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzdHJpbmdpZmllZENhbGwgPSBcIiAgICBcIiArIHNweS5nZXRDYWxsKGkpLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICgvXFxuLy50ZXN0KGNhbGxzW2kgLSAxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ2lmaWVkQ2FsbCA9IFwiXFxuXCIgKyBzdHJpbmdpZmllZENhbGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcHVzaC5jYWxsKGNhbGxzLCBzdHJpbmdpZmllZENhbGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBjYWxscy5sZW5ndGggPiAwID8gXCJcXG5cIiArIGNhbGxzLmpvaW4oXCJcXG5cIikgOiBcIlwiO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgdDogZnVuY3Rpb24gKHNweSkge1xuICAgICAgICAgICAgICAgIHZhciBvYmplY3RzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbCA9IHNweS5jYWxsQ291bnQ7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgcHVzaC5jYWxsKG9iamVjdHMsIHNpbm9uLmZvcm1hdChzcHkudGhpc1ZhbHVlc1tpXSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBvYmplY3RzLmpvaW4oXCIsIFwiKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIFwiKlwiOiBmdW5jdGlvbiAoc3B5LCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZvcm1hdHRlZCA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBhcmdzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBwdXNoLmNhbGwoZm9ybWF0dGVkLCBzaW5vbi5mb3JtYXQoYXJnc1tpXSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmb3JtYXR0ZWQuam9pbihcIiwgXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLmV4dGVuZChzcHksIHNweUFwaSk7XG5cbiAgICAgICAgc3B5LnNweUNhbGwgPSBzaW5vbi5zcHlDYWxsO1xuICAgICAgICBzaW5vbi5zcHkgPSBzcHk7XG5cbiAgICAgICAgcmV0dXJuIHNweTtcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2NhbGxcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2V4dGVuZFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vdGltZXNfaW5fd29yZHNcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2Zvcm1hdFwiKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIHV0aWwvY29yZS5qc1xuICogQGRlcGVuZCBleHRlbmQuanNcbiAqIEBkZXBlbmQgc3B5LmpzXG4gKiBAZGVwZW5kIGJlaGF2aW9yLmpzXG4gKi9cbi8qKlxuICogU3R1YiBmdW5jdGlvbnNcbiAqXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMC0yMDEzIENocmlzdGlhbiBKb2hhbnNlblxuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgZnVuY3Rpb24gc3R1YihvYmplY3QsIHByb3BlcnR5LCBmdW5jKSB7XG4gICAgICAgICAgICBpZiAoISFmdW5jICYmIHR5cGVvZiBmdW5jICE9IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZnVuYyAhPSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkN1c3RvbSBzdHViIHNob3VsZCBiZSBhIGZ1bmN0aW9uIG9yIGEgcHJvcGVydHkgZGVzY3JpcHRvclwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHdyYXBwZXI7XG5cbiAgICAgICAgICAgIGlmIChmdW5jKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBmdW5jID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICB3cmFwcGVyID0gc2lub24uc3B5ICYmIHNpbm9uLnNweS5jcmVhdGUgPyBzaW5vbi5zcHkuY3JlYXRlKGZ1bmMpIDogZnVuYztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB3cmFwcGVyID0gZnVuYztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNpbm9uLnNweSAmJiBzaW5vbi5zcHkuY3JlYXRlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZXMgPSBzaW5vbi5vYmplY3RLZXlzKHdyYXBwZXIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0eXBlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdyYXBwZXJbdHlwZXNbaV1dID0gc2lub24uc3B5LmNyZWF0ZSh3cmFwcGVyW3R5cGVzW2ldXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBzdHViTGVuZ3RoID0gMDtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9iamVjdCA9PSBcIm9iamVjdFwiICYmIHR5cGVvZiBvYmplY3RbcHJvcGVydHldID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICBzdHViTGVuZ3RoID0gb2JqZWN0W3Byb3BlcnR5XS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHdyYXBwZXIgPSBzdHViLmNyZWF0ZShzdHViTGVuZ3RoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFvYmplY3QgJiYgdHlwZW9mIHByb3BlcnR5ID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNpbm9uLnN0dWIuY3JlYXRlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgcHJvcGVydHkgPT09IFwidW5kZWZpbmVkXCIgJiYgdHlwZW9mIG9iamVjdCA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiBvYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzaW5vbi5nZXRQcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wKS52YWx1ZSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdHViKG9iamVjdCwgcHJvcCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gc2lub24ud3JhcE1ldGhvZChvYmplY3QsIHByb3BlcnR5LCB3cmFwcGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGdldERlZmF1bHRCZWhhdmlvcihzdHViKSB7XG4gICAgICAgICAgICByZXR1cm4gc3R1Yi5kZWZhdWx0QmVoYXZpb3IgfHwgZ2V0UGFyZW50QmVoYXZpb3VyKHN0dWIpIHx8IHNpbm9uLmJlaGF2aW9yLmNyZWF0ZShzdHViKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGdldFBhcmVudEJlaGF2aW91cihzdHViKSB7XG4gICAgICAgICAgICByZXR1cm4gKHN0dWIucGFyZW50ICYmIGdldEN1cnJlbnRCZWhhdmlvcihzdHViLnBhcmVudCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gZ2V0Q3VycmVudEJlaGF2aW9yKHN0dWIpIHtcbiAgICAgICAgICAgIHZhciBiZWhhdmlvciA9IHN0dWIuYmVoYXZpb3JzW3N0dWIuY2FsbENvdW50IC0gMV07XG4gICAgICAgICAgICByZXR1cm4gYmVoYXZpb3IgJiYgYmVoYXZpb3IuaXNQcmVzZW50KCkgPyBiZWhhdmlvciA6IGdldERlZmF1bHRCZWhhdmlvcihzdHViKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciB1dWlkID0gMDtcblxuICAgICAgICB2YXIgcHJvdG8gPSB7XG4gICAgICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uIGNyZWF0ZShzdHViTGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGZ1bmN0aW9uU3R1YiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGdldEN1cnJlbnRCZWhhdmlvcihmdW5jdGlvblN0dWIpLmludm9rZSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvblN0dWIuaWQgPSBcInN0dWIjXCIgKyB1dWlkKys7XG4gICAgICAgICAgICAgICAgdmFyIG9yaWcgPSBmdW5jdGlvblN0dWI7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb25TdHViID0gc2lub24uc3B5LmNyZWF0ZShmdW5jdGlvblN0dWIsIHN0dWJMZW5ndGgpO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uU3R1Yi5mdW5jID0gb3JpZztcblxuICAgICAgICAgICAgICAgIHNpbm9uLmV4dGVuZChmdW5jdGlvblN0dWIsIHN0dWIpO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uU3R1Yi5pbnN0YW50aWF0ZUZha2UgPSBzaW5vbi5zdHViLmNyZWF0ZTtcbiAgICAgICAgICAgICAgICBmdW5jdGlvblN0dWIuZGlzcGxheU5hbWUgPSBcInN0dWJcIjtcbiAgICAgICAgICAgICAgICBmdW5jdGlvblN0dWIudG9TdHJpbmcgPSBzaW5vbi5mdW5jdGlvblRvU3RyaW5nO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb25TdHViLmRlZmF1bHRCZWhhdmlvciA9IG51bGw7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb25TdHViLmJlaGF2aW9ycyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uU3R1YjtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlc2V0QmVoYXZpb3I6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgaTtcblxuICAgICAgICAgICAgICAgIHRoaXMuZGVmYXVsdEJlaGF2aW9yID0gbnVsbDtcbiAgICAgICAgICAgICAgICB0aGlzLmJlaGF2aW9ycyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmV0dXJuVmFsdWU7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMucmV0dXJuQXJnQXQ7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXR1cm5UaGlzID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5mYWtlcykge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5mYWtlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mYWtlc1tpXS5yZXNldEJlaGF2aW9yKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBvbkNhbGw6IGZ1bmN0aW9uIG9uQ2FsbChpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5iZWhhdmlvcnNbaW5kZXhdKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYmVoYXZpb3JzW2luZGV4XSA9IHNpbm9uLmJlaGF2aW9yLmNyZWF0ZSh0aGlzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5iZWhhdmlvcnNbaW5kZXhdO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb25GaXJzdENhbGw6IGZ1bmN0aW9uIG9uRmlyc3RDYWxsKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9uQ2FsbCgwKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uU2Vjb25kQ2FsbDogZnVuY3Rpb24gb25TZWNvbmRDYWxsKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm9uQ2FsbCgxKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uVGhpcmRDYWxsOiBmdW5jdGlvbiBvblRoaXJkQ2FsbCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5vbkNhbGwoMik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgZm9yICh2YXIgbWV0aG9kIGluIHNpbm9uLmJlaGF2aW9yKSB7XG4gICAgICAgICAgICBpZiAoc2lub24uYmVoYXZpb3IuaGFzT3duUHJvcGVydHkobWV0aG9kKSAmJlxuICAgICAgICAgICAgICAgICFwcm90by5oYXNPd25Qcm9wZXJ0eShtZXRob2QpICYmXG4gICAgICAgICAgICAgICAgbWV0aG9kICE9IFwiY3JlYXRlXCIgJiZcbiAgICAgICAgICAgICAgICBtZXRob2QgIT0gXCJ3aXRoQXJnc1wiICYmXG4gICAgICAgICAgICAgICAgbWV0aG9kICE9IFwiaW52b2tlXCIpIHtcbiAgICAgICAgICAgICAgICBwcm90b1ttZXRob2RdID0gKGZ1bmN0aW9uIChiZWhhdmlvck1ldGhvZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kZWZhdWx0QmVoYXZpb3IgPSB0aGlzLmRlZmF1bHRCZWhhdmlvciB8fCBzaW5vbi5iZWhhdmlvci5jcmVhdGUodGhpcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRlZmF1bHRCZWhhdmlvcltiZWhhdmlvck1ldGhvZF0uYXBwbHkodGhpcy5kZWZhdWx0QmVoYXZpb3IsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9KG1ldGhvZCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2lub24uZXh0ZW5kKHN0dWIsIHByb3RvKTtcbiAgICAgICAgc2lub24uc3R1YiA9IHN0dWI7XG5cbiAgICAgICAgcmV0dXJuIHN0dWI7XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgICAgICAgdmFyIHNpbm9uID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9iZWhhdmlvclwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vc3B5XCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9leHRlbmRcIik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KHR5cGVvZiBzaW5vbiA9PSBcIm9iamVjdFwiICYmIHNpbm9uIHx8IG51bGwpKTtcbiIsIi8qKlxuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqIEBkZXBlbmQgc2FuZGJveC5qc1xuICovXG4vKipcbiAqIFRlc3QgZnVuY3Rpb24sIHNhbmRib3hlcyBmYWtlc1xuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKHNpbm9uKSB7XG4gICAgZnVuY3Rpb24gbWFrZUFwaShzaW5vbikge1xuICAgICAgICB2YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG5cbiAgICAgICAgZnVuY3Rpb24gdGVzdChjYWxsYmFjaykge1xuICAgICAgICAgICAgdmFyIHR5cGUgPSB0eXBlb2YgY2FsbGJhY2s7XG5cbiAgICAgICAgICAgIGlmICh0eXBlICE9IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJzaW5vbi50ZXN0IG5lZWRzIHRvIHdyYXAgYSB0ZXN0IGZ1bmN0aW9uLCBnb3QgXCIgKyB0eXBlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc2lub25TYW5kYm94ZWRUZXN0KCkge1xuICAgICAgICAgICAgICAgIHZhciBjb25maWcgPSBzaW5vbi5nZXRDb25maWcoc2lub24uY29uZmlnKTtcbiAgICAgICAgICAgICAgICBjb25maWcuaW5qZWN0SW50byA9IGNvbmZpZy5pbmplY3RJbnRvVGhpcyAmJiB0aGlzIHx8IGNvbmZpZy5pbmplY3RJbnRvO1xuICAgICAgICAgICAgICAgIHZhciBzYW5kYm94ID0gc2lub24uc2FuZGJveC5jcmVhdGUoY29uZmlnKTtcbiAgICAgICAgICAgICAgICB2YXIgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICB2YXIgb2xkRG9uZSA9IGFyZ3MubGVuZ3RoICYmIGFyZ3NbYXJncy5sZW5ndGggLSAxXTtcbiAgICAgICAgICAgICAgICB2YXIgZXhjZXB0aW9uLCByZXN1bHQ7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9sZERvbmUgPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGFyZ3NbYXJncy5sZW5ndGggLSAxXSA9IGZ1bmN0aW9uIHNpbm9uRG9uZShyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzYW5kYm94LnJlc3RvcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBleGNlcHRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhbmRib3gudmVyaWZ5QW5kUmVzdG9yZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgb2xkRG9uZShyZXN1bHQpO1xuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGNhbGxiYWNrLmFwcGx5KHRoaXMsIGFyZ3MuY29uY2F0KHNhbmRib3guYXJncykpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgZXhjZXB0aW9uID0gZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9sZERvbmUgIT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZXhjZXB0aW9uICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzYW5kYm94LnJlc3RvcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGV4Y2VwdGlvbjtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNhbmRib3gudmVyaWZ5QW5kUmVzdG9yZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNhbGxiYWNrLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBzaW5vbkFzeW5jU2FuZGJveGVkVGVzdChjYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2lub25TYW5kYm94ZWRUZXN0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHNpbm9uU2FuZGJveGVkVGVzdDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRlc3QuY29uZmlnID0ge1xuICAgICAgICAgICAgaW5qZWN0SW50b1RoaXM6IHRydWUsXG4gICAgICAgICAgICBpbmplY3RJbnRvOiBudWxsLFxuICAgICAgICAgICAgcHJvcGVydGllczogW1wic3B5XCIsIFwic3R1YlwiLCBcIm1vY2tcIiwgXCJjbG9ja1wiLCBcInNlcnZlclwiLCBcInJlcXVlc3RzXCJdLFxuICAgICAgICAgICAgdXNlRmFrZVRpbWVyczogdHJ1ZSxcbiAgICAgICAgICAgIHVzZUZha2VTZXJ2ZXI6IHRydWVcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi50ZXN0ID0gdGVzdDtcbiAgICAgICAgcmV0dXJuIHRlc3Q7XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgICAgICAgdmFyIHNpbm9uID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9zYW5kYm94XCIpO1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG1ha2VBcGkoc2lub24pO1xuICAgIH1cblxuICAgIGlmIChpc0FNRCkge1xuICAgICAgICBkZWZpbmUobG9hZERlcGVuZGVuY2llcyk7XG4gICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBtb2R1bGUuZXhwb3J0cywgbW9kdWxlKTtcbiAgICB9IGVsc2UgaWYgKHNpbm9uKSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIHV0aWwvY29yZS5qc1xuICogQGRlcGVuZCB0ZXN0LmpzXG4gKi9cbi8qKlxuICogVGVzdCBjYXNlLCBzYW5kYm94ZXMgYWxsIHRlc3QgZnVuY3Rpb25zXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiAoc2lub24pIHtcbiAgICBmdW5jdGlvbiBjcmVhdGVUZXN0KHByb3BlcnR5LCBzZXRVcCwgdGVhckRvd24pIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChzZXRVcCkge1xuICAgICAgICAgICAgICAgIHNldFVwLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBleGNlcHRpb24sIHJlc3VsdDtcblxuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBwcm9wZXJ0eS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgIGV4Y2VwdGlvbiA9IGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0ZWFyRG93bikge1xuICAgICAgICAgICAgICAgIHRlYXJEb3duLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChleGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBleGNlcHRpb247XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFrZUFwaShzaW5vbikge1xuICAgICAgICBmdW5jdGlvbiB0ZXN0Q2FzZSh0ZXN0cywgcHJlZml4KSB7XG4gICAgICAgICAgICBpZiAoIXRlc3RzIHx8IHR5cGVvZiB0ZXN0cyAhPSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcInNpbm9uLnRlc3RDYXNlIG5lZWRzIGFuIG9iamVjdCB3aXRoIHRlc3QgZnVuY3Rpb25zXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBwcmVmaXggPSBwcmVmaXggfHwgXCJ0ZXN0XCI7XG4gICAgICAgICAgICB2YXIgclByZWZpeCA9IG5ldyBSZWdFeHAoXCJeXCIgKyBwcmVmaXgpO1xuICAgICAgICAgICAgdmFyIG1ldGhvZHMgPSB7fSwgdGVzdE5hbWUsIHByb3BlcnR5LCBtZXRob2Q7XG4gICAgICAgICAgICB2YXIgc2V0VXAgPSB0ZXN0cy5zZXRVcDtcbiAgICAgICAgICAgIHZhciB0ZWFyRG93biA9IHRlc3RzLnRlYXJEb3duO1xuXG4gICAgICAgICAgICBmb3IgKHRlc3ROYW1lIGluIHRlc3RzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRlc3RzLmhhc093blByb3BlcnR5KHRlc3ROYW1lKSAmJiAhL14oc2V0VXB8dGVhckRvd24pJC8udGVzdCh0ZXN0TmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcGVydHkgPSB0ZXN0c1t0ZXN0TmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBwcm9wZXJ0eSA9PSBcImZ1bmN0aW9uXCIgJiYgclByZWZpeC50ZXN0KHRlc3ROYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gcHJvcGVydHk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXRVcCB8fCB0ZWFyRG93bikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9IGNyZWF0ZVRlc3QocHJvcGVydHksIHNldFVwLCB0ZWFyRG93bik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZHNbdGVzdE5hbWVdID0gc2lub24udGVzdChtZXRob2QpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kc1t0ZXN0TmFtZV0gPSB0ZXN0c1t0ZXN0TmFtZV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBtZXRob2RzO1xuICAgICAgICB9XG5cbiAgICAgICAgc2lub24udGVzdENhc2UgPSB0ZXN0Q2FzZTtcbiAgICAgICAgcmV0dXJuIHRlc3RDYXNlO1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL3V0aWwvY29yZVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vdGVzdFwiKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBAZGVwZW5kIHV0aWwvY29yZS5qc1xuICovXG5cInVzZSBzdHJpY3RcIjtcblxuKGZ1bmN0aW9uIChzaW5vbikge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcblxuICAgICAgICBmdW5jdGlvbiB0aW1lc0luV29yZHMoY291bnQpIHtcbiAgICAgICAgICAgIHN3aXRjaCAoY291bnQpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIm9uY2VcIjtcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcInR3aWNlXCI7XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJ0aHJpY2VcIjtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gKGNvdW50IHx8IDApICsgXCIgdGltZXNcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNpbm9uLnRpbWVzSW5Xb3JkcyA9IHRpbWVzSW5Xb3JkcztcbiAgICAgICAgcmV0dXJuIHNpbm9uLnRpbWVzSW5Xb3JkcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICB2YXIgc2lub24gPSByZXF1aXJlKFwiLi91dGlsL2NvcmVcIik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSBpZiAoIXNpbm9uKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KHR5cGVvZiBzaW5vbiA9PSBcIm9iamVjdFwiICYmIHNpbm9uIHx8IG51bGwpKTtcbiIsIi8qKlxuICogQGRlcGVuZCB1dGlsL2NvcmUuanNcbiAqL1xuLyoqXG4gKiBGb3JtYXQgZnVuY3Rpb25zXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxNCBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbihmdW5jdGlvbiAoc2lub24sIGZvcm1hdGlvKSB7XG4gICAgZnVuY3Rpb24gbWFrZUFwaShzaW5vbikge1xuICAgICAgICBmdW5jdGlvbiB0eXBlT2YodmFsdWUpIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBcIm51bGxcIjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBcInVuZGVmaW5lZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHN0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSk7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nLnN1YnN0cmluZyg4LCBzdHJpbmcubGVuZ3RoIC0gMSkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi50eXBlT2YgPSB0eXBlT2Y7XG4gICAgICAgIHJldHVybiBzaW5vbi50eXBlT2Y7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgICAgICAgdmFyIHNpbm9uID0gcmVxdWlyZShcIi4vdXRpbC9jb3JlXCIpO1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG1ha2VBcGkoc2lub24pO1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGlmIChpc0FNRCkge1xuICAgICAgICBkZWZpbmUobG9hZERlcGVuZGVuY2llcyk7XG4gICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBtb2R1bGUuZXhwb3J0cywgbW9kdWxlKTtcbiAgICB9IGVsc2UgaWYgKCFzaW5vbikge1xuICAgICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufShcbiAgICAodHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCksXG4gICAgKHR5cGVvZiBmb3JtYXRpbyA9PSBcIm9iamVjdFwiICYmIGZvcm1hdGlvKVxuKSk7XG4iLCIvKipcbiAqIEBkZXBlbmQgLi4vLi4vc2lub24uanNcbiAqL1xuLyoqXG4gKiBTaW5vbiBjb3JlIHV0aWxpdGllcy4gRm9yIGludGVybmFsIHVzZSBvbmx5LlxuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKHNpbm9uKSB7XG4gICAgdmFyIGRpdiA9IHR5cGVvZiBkb2N1bWVudCAhPSBcInVuZGVmaW5lZFwiICYmIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgdmFyIGhhc093biA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG5cbiAgICBmdW5jdGlvbiBpc0RPTU5vZGUob2JqKSB7XG4gICAgICAgIHZhciBzdWNjZXNzID0gZmFsc2U7XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG9iai5hcHBlbmRDaGlsZChkaXYpO1xuICAgICAgICAgICAgc3VjY2VzcyA9IGRpdi5wYXJlbnROb2RlID09IG9iajtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBvYmoucmVtb3ZlQ2hpbGQoZGl2KTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgZmFpbGVkLCBub3QgbXVjaCB3ZSBjYW4gZG8gYWJvdXQgdGhhdFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHN1Y2Nlc3M7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNFbGVtZW50KG9iaikge1xuICAgICAgICByZXR1cm4gZGl2ICYmIG9iaiAmJiBvYmoubm9kZVR5cGUgPT09IDEgJiYgaXNET01Ob2RlKG9iaik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNGdW5jdGlvbihvYmopIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBvYmogPT09IFwiZnVuY3Rpb25cIiB8fCAhIShvYmogJiYgb2JqLmNvbnN0cnVjdG9yICYmIG9iai5jYWxsICYmIG9iai5hcHBseSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNSZWFsbHlOYU4odmFsKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgdmFsID09PSBcIm51bWJlclwiICYmIGlzTmFOKHZhbCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWlycm9yUHJvcGVydGllcyh0YXJnZXQsIHNvdXJjZSkge1xuICAgICAgICBmb3IgKHZhciBwcm9wIGluIHNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKCFoYXNPd24uY2FsbCh0YXJnZXQsIHByb3ApKSB7XG4gICAgICAgICAgICAgICAgdGFyZ2V0W3Byb3BdID0gc291cmNlW3Byb3BdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNSZXN0b3JhYmxlKG9iaikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBvYmoucmVzdG9yZSA9PT0gXCJmdW5jdGlvblwiICYmIG9iai5yZXN0b3JlLnNpbm9uO1xuICAgIH1cblxuICAgIC8vIENoZWFwIHdheSB0byBkZXRlY3QgaWYgd2UgaGF2ZSBFUzUgc3VwcG9ydC5cbiAgICB2YXIgaGFzRVM1U3VwcG9ydCA9IFwia2V5c1wiIGluIE9iamVjdDtcblxuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgc2lub24ud3JhcE1ldGhvZCA9IGZ1bmN0aW9uIHdyYXBNZXRob2Qob2JqZWN0LCBwcm9wZXJ0eSwgbWV0aG9kKSB7XG4gICAgICAgICAgICBpZiAoIW9iamVjdCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTaG91bGQgd3JhcCBwcm9wZXJ0eSBvZiBvYmplY3RcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgbWV0aG9kICE9IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgbWV0aG9kICE9IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiTWV0aG9kIHdyYXBwZXIgc2hvdWxkIGJlIGEgZnVuY3Rpb24gb3IgYSBwcm9wZXJ0eSBkZXNjcmlwdG9yXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjaGVja1dyYXBwZWRNZXRob2Qod3JhcHBlZE1ldGhvZCkge1xuICAgICAgICAgICAgICAgIGlmICghaXNGdW5jdGlvbih3cmFwcGVkTWV0aG9kKSkge1xuICAgICAgICAgICAgICAgICAgICBlcnJvciA9IG5ldyBUeXBlRXJyb3IoXCJBdHRlbXB0ZWQgdG8gd3JhcCBcIiArICh0eXBlb2Ygd3JhcHBlZE1ldGhvZCkgKyBcIiBwcm9wZXJ0eSBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydHkgKyBcIiBhcyBmdW5jdGlvblwiKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHdyYXBwZWRNZXRob2QucmVzdG9yZSAmJiB3cmFwcGVkTWV0aG9kLnJlc3RvcmUuc2lub24pIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBuZXcgVHlwZUVycm9yKFwiQXR0ZW1wdGVkIHRvIHdyYXAgXCIgKyBwcm9wZXJ0eSArIFwiIHdoaWNoIGlzIGFscmVhZHkgd3JhcHBlZFwiKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHdyYXBwZWRNZXRob2QuY2FsbGVkQmVmb3JlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2ZXJiID0gISF3cmFwcGVkTWV0aG9kLnJldHVybnMgPyBcInN0dWJiZWRcIiA6IFwic3BpZWQgb25cIjtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBuZXcgVHlwZUVycm9yKFwiQXR0ZW1wdGVkIHRvIHdyYXAgXCIgKyBwcm9wZXJ0eSArIFwiIHdoaWNoIGlzIGFscmVhZHkgXCIgKyB2ZXJiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdyYXBwZWRNZXRob2QgJiYgd3JhcHBlZE1ldGhvZC5zdGFja1RyYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5zdGFjayArPSBcIlxcbi0tLS0tLS0tLS0tLS0tXFxuXCIgKyB3cmFwcGVkTWV0aG9kLnN0YWNrVHJhY2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgZXJyb3IsIHdyYXBwZWRNZXRob2Q7XG5cbiAgICAgICAgICAgIC8vIElFIDggZG9lcyBub3Qgc3VwcG9ydCBoYXNPd25Qcm9wZXJ0eSBvbiB0aGUgd2luZG93IG9iamVjdCBhbmQgRmlyZWZveCBoYXMgYSBwcm9ibGVtXG4gICAgICAgICAgICAvLyB3aGVuIHVzaW5nIGhhc093bi5jYWxsIG9uIG9iamVjdHMgZnJvbSBvdGhlciBmcmFtZXMuXG4gICAgICAgICAgICB2YXIgb3duZWQgPSBvYmplY3QuaGFzT3duUHJvcGVydHkgPyBvYmplY3QuaGFzT3duUHJvcGVydHkocHJvcGVydHkpIDogaGFzT3duLmNhbGwob2JqZWN0LCBwcm9wZXJ0eSk7XG5cbiAgICAgICAgICAgIGlmIChoYXNFUzVTdXBwb3J0KSB7XG4gICAgICAgICAgICAgICAgdmFyIG1ldGhvZERlc2MgPSAodHlwZW9mIG1ldGhvZCA9PSBcImZ1bmN0aW9uXCIpID8ge3ZhbHVlOiBtZXRob2R9IDogbWV0aG9kLFxuICAgICAgICAgICAgICAgICAgICB3cmFwcGVkTWV0aG9kRGVzYyA9IHNpbm9uLmdldFByb3BlcnR5RGVzY3JpcHRvcihvYmplY3QsIHByb3BlcnR5KSxcbiAgICAgICAgICAgICAgICAgICAgaTtcblxuICAgICAgICAgICAgICAgIGlmICghd3JhcHBlZE1ldGhvZERlc2MpIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBuZXcgVHlwZUVycm9yKFwiQXR0ZW1wdGVkIHRvIHdyYXAgXCIgKyAodHlwZW9mIHdyYXBwZWRNZXRob2QpICsgXCIgcHJvcGVydHkgXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnR5ICsgXCIgYXMgZnVuY3Rpb25cIik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh3cmFwcGVkTWV0aG9kRGVzYy5yZXN0b3JlICYmIHdyYXBwZWRNZXRob2REZXNjLnJlc3RvcmUuc2lub24pIHtcbiAgICAgICAgICAgICAgICAgICAgZXJyb3IgPSBuZXcgVHlwZUVycm9yKFwiQXR0ZW1wdGVkIHRvIHdyYXAgXCIgKyBwcm9wZXJ0eSArIFwiIHdoaWNoIGlzIGFscmVhZHkgd3JhcHBlZFwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3cmFwcGVkTWV0aG9kRGVzYyAmJiB3cmFwcGVkTWV0aG9kRGVzYy5zdGFja1RyYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvci5zdGFjayArPSBcIlxcbi0tLS0tLS0tLS0tLS0tXFxuXCIgKyB3cmFwcGVkTWV0aG9kRGVzYy5zdGFja1RyYWNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciB0eXBlcyA9IHNpbm9uLm9iamVjdEtleXMobWV0aG9kRGVzYyk7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHR5cGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHdyYXBwZWRNZXRob2QgPSB3cmFwcGVkTWV0aG9kRGVzY1t0eXBlc1tpXV07XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrV3JhcHBlZE1ldGhvZCh3cmFwcGVkTWV0aG9kKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBtaXJyb3JQcm9wZXJ0aWVzKG1ldGhvZERlc2MsIHdyYXBwZWRNZXRob2REZXNjKTtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdHlwZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgbWlycm9yUHJvcGVydGllcyhtZXRob2REZXNjW3R5cGVzW2ldXSwgd3JhcHBlZE1ldGhvZERlc2NbdHlwZXNbaV1dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcGVydHksIG1ldGhvZERlc2MpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB3cmFwcGVkTWV0aG9kID0gb2JqZWN0W3Byb3BlcnR5XTtcbiAgICAgICAgICAgICAgICBjaGVja1dyYXBwZWRNZXRob2Qod3JhcHBlZE1ldGhvZCk7XG4gICAgICAgICAgICAgICAgb2JqZWN0W3Byb3BlcnR5XSA9IG1ldGhvZDtcbiAgICAgICAgICAgICAgICBtZXRob2QuZGlzcGxheU5hbWUgPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbWV0aG9kLmRpc3BsYXlOYW1lID0gcHJvcGVydHk7XG5cbiAgICAgICAgICAgIC8vIFNldCB1cCBhIHN0YWNrIHRyYWNlIHdoaWNoIGNhbiBiZSB1c2VkIGxhdGVyIHRvIGZpbmQgd2hhdCBsaW5lIG9mXG4gICAgICAgICAgICAvLyBjb2RlIHRoZSBvcmlnaW5hbCBtZXRob2Qgd2FzIGNyZWF0ZWQgb24uXG4gICAgICAgICAgICBtZXRob2Quc3RhY2tUcmFjZSA9IChuZXcgRXJyb3IoXCJTdGFjayBUcmFjZSBmb3Igb3JpZ2luYWxcIikpLnN0YWNrO1xuXG4gICAgICAgICAgICBtZXRob2QucmVzdG9yZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAvLyBGb3IgcHJvdG90eXBlIHByb3BlcnRpZXMgdHJ5IHRvIHJlc2V0IGJ5IGRlbGV0ZSBmaXJzdC5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGlzIGZhaWxzIChleDogbG9jYWxTdG9yYWdlIG9uIG1vYmlsZSBzYWZhcmkpIHRoZW4gZm9yY2UgYSByZXNldFxuICAgICAgICAgICAgICAgIC8vIHZpYSBkaXJlY3QgYXNzaWdubWVudC5cbiAgICAgICAgICAgICAgICBpZiAoIW93bmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEluIHNvbWUgY2FzZXMgYGRlbGV0ZWAgbWF5IHRocm93IGFuIGVycm9yXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgb2JqZWN0W3Byb3BlcnR5XTtcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgICAgICAgICAgICAgLy8gRm9yIG5hdGl2ZSBjb2RlIGZ1bmN0aW9ucyBgZGVsZXRlYCBmYWlscyB3aXRob3V0IHRocm93aW5nIGFuIGVycm9yXG4gICAgICAgICAgICAgICAgICAgIC8vIG9uIENocm9tZSA8IDQzLCBQaGFudG9tSlMsIGV0Yy5cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGhhc0VTNVN1cHBvcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iamVjdCwgcHJvcGVydHksIHdyYXBwZWRNZXRob2REZXNjKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBVc2Ugc3RyaWN0IGVxdWFsaXR5IGNvbXBhcmlzb24gdG8gY2hlY2sgZmFpbHVyZXMgdGhlbiBmb3JjZSBhIHJlc2V0XG4gICAgICAgICAgICAgICAgLy8gdmlhIGRpcmVjdCBhc3NpZ25tZW50LlxuICAgICAgICAgICAgICAgIGlmIChvYmplY3RbcHJvcGVydHldID09PSBtZXRob2QpIHtcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0W3Byb3BlcnR5XSA9IHdyYXBwZWRNZXRob2Q7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgbWV0aG9kLnJlc3RvcmUuc2lub24gPSB0cnVlO1xuXG4gICAgICAgICAgICBpZiAoIWhhc0VTNVN1cHBvcnQpIHtcbiAgICAgICAgICAgICAgICBtaXJyb3JQcm9wZXJ0aWVzKG1ldGhvZCwgd3JhcHBlZE1ldGhvZCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBtZXRob2Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlKHByb3RvKSB7XG4gICAgICAgICAgICB2YXIgRiA9IGZ1bmN0aW9uICgpIHt9O1xuICAgICAgICAgICAgRi5wcm90b3R5cGUgPSBwcm90bztcbiAgICAgICAgICAgIHJldHVybiBuZXcgRigpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLmRlZXBFcXVhbCA9IGZ1bmN0aW9uIGRlZXBFcXVhbChhLCBiKSB7XG4gICAgICAgICAgICBpZiAoc2lub24ubWF0Y2ggJiYgc2lub24ubWF0Y2guaXNNYXRjaGVyKGEpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEudGVzdChiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHR5cGVvZiBhICE9IFwib2JqZWN0XCIgfHwgdHlwZW9mIGIgIT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgIGlmIChpc1JlYWxseU5hTihhKSAmJiBpc1JlYWxseU5hTihiKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYSA9PT0gYjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChpc0VsZW1lbnQoYSkgfHwgaXNFbGVtZW50KGIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPT09IGI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICgoYSA9PT0gbnVsbCAmJiBiICE9PSBudWxsKSB8fCAoYSAhPT0gbnVsbCAmJiBiID09PSBudWxsKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGEgaW5zdGFuY2VvZiBSZWdFeHAgJiYgYiBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoYS5zb3VyY2UgPT09IGIuc291cmNlKSAmJiAoYS5nbG9iYWwgPT09IGIuZ2xvYmFsKSAmJlxuICAgICAgICAgICAgICAgICAgICAoYS5pZ25vcmVDYXNlID09PSBiLmlnbm9yZUNhc2UpICYmIChhLm11bHRpbGluZSA9PT0gYi5tdWx0aWxpbmUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgYVN0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhKTtcbiAgICAgICAgICAgIGlmIChhU3RyaW5nICE9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChiKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGFTdHJpbmcgPT0gXCJbb2JqZWN0IERhdGVdXCIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYS52YWx1ZU9mKCkgPT09IGIudmFsdWVPZigpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcHJvcCwgYUxlbmd0aCA9IDAsIGJMZW5ndGggPSAwO1xuXG4gICAgICAgICAgICBpZiAoYVN0cmluZyA9PSBcIltvYmplY3QgQXJyYXldXCIgJiYgYS5sZW5ndGggIT09IGIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKHByb3AgaW4gYSkge1xuICAgICAgICAgICAgICAgIGFMZW5ndGggKz0gMTtcblxuICAgICAgICAgICAgICAgIGlmICghKHByb3AgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghZGVlcEVxdWFsKGFbcHJvcF0sIGJbcHJvcF0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAocHJvcCBpbiBiKSB7XG4gICAgICAgICAgICAgICAgYkxlbmd0aCArPSAxO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gYUxlbmd0aCA9PSBiTGVuZ3RoO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLmZ1bmN0aW9uTmFtZSA9IGZ1bmN0aW9uIGZ1bmN0aW9uTmFtZShmdW5jKSB7XG4gICAgICAgICAgICB2YXIgbmFtZSA9IGZ1bmMuZGlzcGxheU5hbWUgfHwgZnVuYy5uYW1lO1xuXG4gICAgICAgICAgICAvLyBVc2UgZnVuY3Rpb24gZGVjb21wb3NpdGlvbiBhcyBhIGxhc3QgcmVzb3J0IHRvIGdldCBmdW5jdGlvblxuICAgICAgICAgICAgLy8gbmFtZS4gRG9lcyBub3QgcmVseSBvbiBmdW5jdGlvbiBkZWNvbXBvc2l0aW9uIHRvIHdvcmsgLSBpZiBpdFxuICAgICAgICAgICAgLy8gZG9lc24ndCBkZWJ1Z2dpbmcgd2lsbCBiZSBzbGlnaHRseSBsZXNzIGluZm9ybWF0aXZlXG4gICAgICAgICAgICAvLyAoaS5lLiB0b1N0cmluZyB3aWxsIHNheSAnc3B5JyByYXRoZXIgdGhhbiAnbXlGdW5jJykuXG4gICAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgbWF0Y2hlcyA9IGZ1bmMudG9TdHJpbmcoKS5tYXRjaCgvZnVuY3Rpb24gKFteXFxzXFwoXSspLyk7XG4gICAgICAgICAgICAgICAgbmFtZSA9IG1hdGNoZXMgJiYgbWF0Y2hlc1sxXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIG5hbWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uZnVuY3Rpb25Ub1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2V0Q2FsbCAmJiB0aGlzLmNhbGxDb3VudCkge1xuICAgICAgICAgICAgICAgIHZhciB0aGlzVmFsdWUsIHByb3AsIGkgPSB0aGlzLmNhbGxDb3VudDtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChpLS0pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpc1ZhbHVlID0gdGhpcy5nZXRDYWxsKGkpLnRoaXNWYWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICBmb3IgKHByb3AgaW4gdGhpc1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpc1ZhbHVlW3Byb3BdID09PSB0aGlzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByb3A7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRpc3BsYXlOYW1lIHx8IFwic2lub24gZmFrZVwiO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLm9iamVjdEtleXMgPSBmdW5jdGlvbiBvYmplY3RLZXlzKG9iaikge1xuICAgICAgICAgICAgaWYgKG9iaiAhPT0gT2JqZWN0KG9iaikpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwic2lub24ub2JqZWN0S2V5cyBjYWxsZWQgb24gYSBub24tb2JqZWN0XCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIga2V5cyA9IFtdO1xuICAgICAgICAgICAgdmFyIGtleTtcbiAgICAgICAgICAgIGZvciAoa2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgIGlmIChoYXNPd24uY2FsbChvYmosIGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5cy5wdXNoKGtleSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4ga2V5cztcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5nZXRQcm9wZXJ0eURlc2NyaXB0b3IgPSBmdW5jdGlvbiBnZXRQcm9wZXJ0eURlc2NyaXB0b3Iob2JqZWN0LCBwcm9wZXJ0eSkge1xuICAgICAgICAgICAgdmFyIHByb3RvID0gb2JqZWN0LCBkZXNjcmlwdG9yO1xuICAgICAgICAgICAgd2hpbGUgKHByb3RvICYmICEoZGVzY3JpcHRvciA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IocHJvdG8sIHByb3BlcnR5KSkpIHtcbiAgICAgICAgICAgICAgICBwcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZihwcm90byk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZGVzY3JpcHRvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHNpbm9uLmdldENvbmZpZyA9IGZ1bmN0aW9uIChjdXN0b20pIHtcbiAgICAgICAgICAgIHZhciBjb25maWcgPSB7fTtcbiAgICAgICAgICAgIGN1c3RvbSA9IGN1c3RvbSB8fCB7fTtcbiAgICAgICAgICAgIHZhciBkZWZhdWx0cyA9IHNpbm9uLmRlZmF1bHRDb25maWc7XG5cbiAgICAgICAgICAgIGZvciAodmFyIHByb3AgaW4gZGVmYXVsdHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGVmYXVsdHMuaGFzT3duUHJvcGVydHkocHJvcCkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnW3Byb3BdID0gY3VzdG9tLmhhc093blByb3BlcnR5KHByb3ApID8gY3VzdG9tW3Byb3BdIDogZGVmYXVsdHNbcHJvcF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLmRlZmF1bHRDb25maWcgPSB7XG4gICAgICAgICAgICBpbmplY3RJbnRvVGhpczogdHJ1ZSxcbiAgICAgICAgICAgIGluamVjdEludG86IG51bGwsXG4gICAgICAgICAgICBwcm9wZXJ0aWVzOiBbXCJzcHlcIiwgXCJzdHViXCIsIFwibW9ja1wiLCBcImNsb2NrXCIsIFwic2VydmVyXCIsIFwicmVxdWVzdHNcIl0sXG4gICAgICAgICAgICB1c2VGYWtlVGltZXJzOiB0cnVlLFxuICAgICAgICAgICAgdXNlRmFrZVNlcnZlcjogdHJ1ZVxuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLnRpbWVzSW5Xb3JkcyA9IGZ1bmN0aW9uIHRpbWVzSW5Xb3Jkcyhjb3VudCkge1xuICAgICAgICAgICAgcmV0dXJuIGNvdW50ID09IDEgJiYgXCJvbmNlXCIgfHxcbiAgICAgICAgICAgICAgICBjb3VudCA9PSAyICYmIFwidHdpY2VcIiB8fFxuICAgICAgICAgICAgICAgIGNvdW50ID09IDMgJiYgXCJ0aHJpY2VcIiB8fFxuICAgICAgICAgICAgICAgIChjb3VudCB8fCAwKSArIFwiIHRpbWVzXCI7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uY2FsbGVkSW5PcmRlciA9IGZ1bmN0aW9uIChzcGllcykge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDEsIGwgPSBzcGllcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoIXNwaWVzW2kgLSAxXS5jYWxsZWRCZWZvcmUoc3BpZXNbaV0pIHx8ICFzcGllc1tpXS5jYWxsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24ub3JkZXJCeUZpcnN0Q2FsbCA9IGZ1bmN0aW9uIChzcGllcykge1xuICAgICAgICAgICAgcmV0dXJuIHNwaWVzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgICAgICAgICAvLyB1dWlkLCB3b24ndCBldmVyIGJlIGVxdWFsXG4gICAgICAgICAgICAgICAgdmFyIGFDYWxsID0gYS5nZXRDYWxsKDApO1xuICAgICAgICAgICAgICAgIHZhciBiQ2FsbCA9IGIuZ2V0Q2FsbCgwKTtcbiAgICAgICAgICAgICAgICB2YXIgYUlkID0gYUNhbGwgJiYgYUNhbGwuY2FsbElkIHx8IC0xO1xuICAgICAgICAgICAgICAgIHZhciBiSWQgPSBiQ2FsbCAmJiBiQ2FsbC5jYWxsSWQgfHwgLTE7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYUlkIDwgYklkID8gLTEgOiAxO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uY3JlYXRlU3R1Ykluc3RhbmNlID0gZnVuY3Rpb24gKGNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGNvbnN0cnVjdG9yICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiVGhlIGNvbnN0cnVjdG9yIHNob3VsZCBiZSBhIGZ1bmN0aW9uLlwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzaW5vbi5zdHViKHNpbm9uLmNyZWF0ZShjb25zdHJ1Y3Rvci5wcm90b3R5cGUpKTtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5yZXN0b3JlID0gZnVuY3Rpb24gKG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKG9iamVjdCAhPT0gbnVsbCAmJiB0eXBlb2Ygb2JqZWN0ID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcCBpbiBvYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzUmVzdG9yYWJsZShvYmplY3RbcHJvcF0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3RbcHJvcF0ucmVzdG9yZSgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChpc1Jlc3RvcmFibGUob2JqZWN0KSkge1xuICAgICAgICAgICAgICAgIG9iamVjdC5yZXN0b3JlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgcmV0dXJuIHNpbm9uO1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cykge1xuICAgICAgICBtYWtlQXBpKGV4cG9ydHMpO1xuICAgIH1cblxuICAgIGlmIChpc0FNRCkge1xuICAgICAgICBkZWZpbmUobG9hZERlcGVuZGVuY2llcyk7XG4gICAgfSBlbHNlIGlmIChpc05vZGUpIHtcbiAgICAgICAgbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBtb2R1bGUuZXhwb3J0cyk7XG4gICAgfSBlbHNlIGlmICghc2lub24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0odHlwZW9mIHNpbm9uID09IFwib2JqZWN0XCIgJiYgc2lub24gfHwgbnVsbCkpO1xuIiwiLyoqXG4gKiBNaW5pbWFsIEV2ZW50IGludGVyZmFjZSBpbXBsZW1lbnRhdGlvblxuICpcbiAqIE9yaWdpbmFsIGltcGxlbWVudGF0aW9uIGJ5IFN2ZW4gRnVjaHM6IGh0dHBzOi8vZ2lzdC5naXRodWIuY29tLzk5NTAyOFxuICogTW9kaWZpY2F0aW9ucyBhbmQgdGVzdHMgYnkgQ2hyaXN0aWFuIEpvaGFuc2VuLlxuICpcbiAqIEBhdXRob3IgU3ZlbiBGdWNocyAoc3ZlbmZ1Y2hzQGFydHdlYi1kZXNpZ24uZGUpXG4gKiBAYXV0aG9yIENocmlzdGlhbiBKb2hhbnNlbiAoY2hyaXN0aWFuQGNqb2hhbnNlbi5ubylcbiAqIEBsaWNlbnNlIEJTRFxuICpcbiAqIENvcHlyaWdodCAoYykgMjAxMSBTdmVuIEZ1Y2hzLCBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbmlmICh0eXBlb2Ygc2lub24gPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHRoaXMuc2lub24gPSB7fTtcbn1cblxuKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcHVzaCA9IFtdLnB1c2g7XG5cbiAgICBmdW5jdGlvbiBtYWtlQXBpKHNpbm9uKSB7XG4gICAgICAgIHNpbm9uLkV2ZW50ID0gZnVuY3Rpb24gRXZlbnQodHlwZSwgYnViYmxlcywgY2FuY2VsYWJsZSwgdGFyZ2V0KSB7XG4gICAgICAgICAgICB0aGlzLmluaXRFdmVudCh0eXBlLCBidWJibGVzLCBjYW5jZWxhYmxlLCB0YXJnZXQpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLkV2ZW50LnByb3RvdHlwZSA9IHtcbiAgICAgICAgICAgIGluaXRFdmVudDogZnVuY3Rpb24gKHR5cGUsIGJ1YmJsZXMsIGNhbmNlbGFibGUsIHRhcmdldCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgICAgICAgICAgICAgdGhpcy5idWJibGVzID0gYnViYmxlcztcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmNlbGFibGUgPSBjYW5jZWxhYmxlO1xuICAgICAgICAgICAgICAgIHRoaXMudGFyZ2V0ID0gdGFyZ2V0O1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgc3RvcFByb3BhZ2F0aW9uOiBmdW5jdGlvbiAoKSB7fSxcblxuICAgICAgICAgICAgcHJldmVudERlZmF1bHQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRlZmF1bHRQcmV2ZW50ZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLlByb2dyZXNzRXZlbnQgPSBmdW5jdGlvbiBQcm9ncmVzc0V2ZW50KHR5cGUsIHByb2dyZXNzRXZlbnRSYXcsIHRhcmdldCkge1xuICAgICAgICAgICAgdGhpcy5pbml0RXZlbnQodHlwZSwgZmFsc2UsIGZhbHNlLCB0YXJnZXQpO1xuICAgICAgICAgICAgdGhpcy5sb2FkZWQgPSBwcm9ncmVzc0V2ZW50UmF3LmxvYWRlZCB8fCBudWxsO1xuICAgICAgICAgICAgdGhpcy50b3RhbCA9IHByb2dyZXNzRXZlbnRSYXcudG90YWwgfHwgbnVsbDtcbiAgICAgICAgICAgIHRoaXMubGVuZ3RoQ29tcHV0YWJsZSA9ICEhcHJvZ3Jlc3NFdmVudFJhdy50b3RhbDtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5Qcm9ncmVzc0V2ZW50LnByb3RvdHlwZSA9IG5ldyBzaW5vbi5FdmVudCgpO1xuXG4gICAgICAgIHNpbm9uLlByb2dyZXNzRXZlbnQucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gIHNpbm9uLlByb2dyZXNzRXZlbnQ7XG5cbiAgICAgICAgc2lub24uQ3VzdG9tRXZlbnQgPSBmdW5jdGlvbiBDdXN0b21FdmVudCh0eXBlLCBjdXN0b21EYXRhLCB0YXJnZXQpIHtcbiAgICAgICAgICAgIHRoaXMuaW5pdEV2ZW50KHR5cGUsIGZhbHNlLCBmYWxzZSwgdGFyZ2V0KTtcbiAgICAgICAgICAgIHRoaXMuZGV0YWlsID0gY3VzdG9tRGF0YS5kZXRhaWwgfHwgbnVsbDtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5DdXN0b21FdmVudC5wcm90b3R5cGUgPSBuZXcgc2lub24uRXZlbnQoKTtcblxuICAgICAgICBzaW5vbi5DdXN0b21FdmVudC5wcm90b3R5cGUuY29uc3RydWN0b3IgPSAgc2lub24uQ3VzdG9tRXZlbnQ7XG5cbiAgICAgICAgc2lub24uRXZlbnRUYXJnZXQgPSB7XG4gICAgICAgICAgICBhZGRFdmVudExpc3RlbmVyOiBmdW5jdGlvbiBhZGRFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcikge1xuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRMaXN0ZW5lcnMgPSB0aGlzLmV2ZW50TGlzdGVuZXJzIHx8IHt9O1xuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRMaXN0ZW5lcnNbZXZlbnRdID0gdGhpcy5ldmVudExpc3RlbmVyc1tldmVudF0gfHwgW107XG4gICAgICAgICAgICAgICAgcHVzaC5jYWxsKHRoaXMuZXZlbnRMaXN0ZW5lcnNbZXZlbnRdLCBsaXN0ZW5lcik7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICByZW1vdmVFdmVudExpc3RlbmVyOiBmdW5jdGlvbiByZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcikge1xuICAgICAgICAgICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmV2ZW50TGlzdGVuZXJzICYmIHRoaXMuZXZlbnRMaXN0ZW5lcnNbZXZlbnRdIHx8IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChsaXN0ZW5lcnNbaV0gPT0gbGlzdGVuZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBsaXN0ZW5lcnMuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZGlzcGF0Y2hFdmVudDogZnVuY3Rpb24gZGlzcGF0Y2hFdmVudChldmVudCkge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gZXZlbnQudHlwZTtcbiAgICAgICAgICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5ldmVudExpc3RlbmVycyAmJiB0aGlzLmV2ZW50TGlzdGVuZXJzW3R5cGVdIHx8IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaXN0ZW5lcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBsaXN0ZW5lcnNbaV0gPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uY2FsbCh0aGlzLCBldmVudCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsaXN0ZW5lcnNbaV0uaGFuZGxlRXZlbnQoZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuICEhZXZlbnQuZGVmYXVsdFByZXZlbnRlZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgaXNOb2RlID0gdHlwZW9mIG1vZHVsZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBtb2R1bGUuZXhwb3J0cyAmJiB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCI7XG4gICAgdmFyIGlzQU1EID0gdHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBkZWZpbmUuYW1kID09PSBcIm9iamVjdFwiICYmIGRlZmluZS5hbWQ7XG5cbiAgICBmdW5jdGlvbiBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUpIHtcbiAgICAgICAgdmFyIHNpbm9uID0gcmVxdWlyZShcIi4vY29yZVwiKTtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0oKSk7XG4iLCIvKipcbiAqIEBkZXBlbmQgZmFrZV94ZG9tYWluX3JlcXVlc3QuanNcbiAqIEBkZXBlbmQgZmFrZV94bWxfaHR0cF9yZXF1ZXN0LmpzXG4gKiBAZGVwZW5kIC4uL2Zvcm1hdC5qc1xuICogQGRlcGVuZCAuLi9sb2dfZXJyb3IuanNcbiAqL1xuLyoqXG4gKiBUaGUgU2lub24gXCJzZXJ2ZXJcIiBtaW1pY3MgYSB3ZWIgc2VydmVyIHRoYXQgcmVjZWl2ZXMgcmVxdWVzdHMgZnJvbVxuICogc2lub24uRmFrZVhNTEh0dHBSZXF1ZXN0IGFuZCBwcm92aWRlcyBhbiBBUEkgdG8gcmVzcG9uZCB0byB0aG9zZSByZXF1ZXN0cyxcbiAqIGJvdGggc3luY2hyb25vdXNseSBhbmQgYXN5bmNocm9ub3VzbHkuIFRvIHJlc3BvbmQgc3luY2hyb251b3VzbHksIGNhbm5lZFxuICogYW5zd2VycyBoYXZlIHRvIGJlIHByb3ZpZGVkIHVwZnJvbnQuXG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbmlmICh0eXBlb2Ygc2lub24gPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHZhciBzaW5vbiA9IHt9O1xufVxuXG4oZnVuY3Rpb24gKCkge1xuICAgIHZhciBwdXNoID0gW10ucHVzaDtcbiAgICBmdW5jdGlvbiBGKCkge31cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZShwcm90bykge1xuICAgICAgICBGLnByb3RvdHlwZSA9IHByb3RvO1xuICAgICAgICByZXR1cm4gbmV3IEYoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNwb25zZUFycmF5KGhhbmRsZXIpIHtcbiAgICAgICAgdmFyIHJlc3BvbnNlID0gaGFuZGxlcjtcblxuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGhhbmRsZXIpICE9IFwiW29iamVjdCBBcnJheV1cIikge1xuICAgICAgICAgICAgcmVzcG9uc2UgPSBbMjAwLCB7fSwgaGFuZGxlcl07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHJlc3BvbnNlWzJdICE9IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJGYWtlIHNlcnZlciByZXNwb25zZSBib2R5IHNob3VsZCBiZSBzdHJpbmcsIGJ1dCB3YXMgXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlb2YgcmVzcG9uc2VbMl0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlO1xuICAgIH1cblxuICAgIHZhciB3bG9jID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdy5sb2NhdGlvbiA6IHt9O1xuICAgIHZhciByQ3VyckxvYyA9IG5ldyBSZWdFeHAoXCJeXCIgKyB3bG9jLnByb3RvY29sICsgXCIvL1wiICsgd2xvYy5ob3N0KTtcblxuICAgIGZ1bmN0aW9uIG1hdGNoT25lKHJlc3BvbnNlLCByZXFNZXRob2QsIHJlcVVybCkge1xuICAgICAgICB2YXIgcm1ldGggPSByZXNwb25zZS5tZXRob2Q7XG4gICAgICAgIHZhciBtYXRjaE1ldGhvZCA9ICFybWV0aCB8fCBybWV0aC50b0xvd2VyQ2FzZSgpID09IHJlcU1ldGhvZC50b0xvd2VyQ2FzZSgpO1xuICAgICAgICB2YXIgdXJsID0gcmVzcG9uc2UudXJsO1xuICAgICAgICB2YXIgbWF0Y2hVcmwgPSAhdXJsIHx8IHVybCA9PSByZXFVcmwgfHwgKHR5cGVvZiB1cmwudGVzdCA9PSBcImZ1bmN0aW9uXCIgJiYgdXJsLnRlc3QocmVxVXJsKSk7XG5cbiAgICAgICAgcmV0dXJuIG1hdGNoTWV0aG9kICYmIG1hdGNoVXJsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1hdGNoKHJlc3BvbnNlLCByZXF1ZXN0KSB7XG4gICAgICAgIHZhciByZXF1ZXN0VXJsID0gcmVxdWVzdC51cmw7XG5cbiAgICAgICAgaWYgKCEvXmh0dHBzPzpcXC9cXC8vLnRlc3QocmVxdWVzdFVybCkgfHwgckN1cnJMb2MudGVzdChyZXF1ZXN0VXJsKSkge1xuICAgICAgICAgICAgcmVxdWVzdFVybCA9IHJlcXVlc3RVcmwucmVwbGFjZShyQ3VyckxvYywgXCJcIik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWF0Y2hPbmUocmVzcG9uc2UsIHRoaXMuZ2V0SFRUUE1ldGhvZChyZXF1ZXN0KSwgcmVxdWVzdFVybCkpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcmVzcG9uc2UucmVzcG9uc2UgPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJ1ID0gcmVzcG9uc2UudXJsO1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gW3JlcXVlc3RdLmNvbmNhdChydSAmJiB0eXBlb2YgcnUuZXhlYyA9PSBcImZ1bmN0aW9uXCIgPyBydS5leGVjKHJlcXVlc3RVcmwpLnNsaWNlKDEpIDogW10pO1xuICAgICAgICAgICAgICAgIHJldHVybiByZXNwb25zZS5yZXNwb25zZS5hcHBseShyZXNwb25zZSwgYXJncyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgc2lub24uZmFrZVNlcnZlciA9IHtcbiAgICAgICAgICAgIGNyZWF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBzZXJ2ZXIgPSBjcmVhdGUodGhpcyk7XG4gICAgICAgICAgICAgICAgaWYgKCFzaW5vbi54aHIuc3VwcG9ydHNDT1JTKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMueGhyID0gc2lub24udXNlRmFrZVhEb21haW5SZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy54aHIgPSBzaW5vbi51c2VGYWtlWE1MSHR0cFJlcXVlc3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2VydmVyLnJlcXVlc3RzID0gW107XG5cbiAgICAgICAgICAgICAgICB0aGlzLnhoci5vbkNyZWF0ZSA9IGZ1bmN0aW9uICh4aHJPYmopIHtcbiAgICAgICAgICAgICAgICAgICAgc2VydmVyLmFkZFJlcXVlc3QoeGhyT2JqKTtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlcnZlcjtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGFkZFJlcXVlc3Q6IGZ1bmN0aW9uIGFkZFJlcXVlc3QoeGhyT2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlcnZlciA9IHRoaXM7XG4gICAgICAgICAgICAgICAgcHVzaC5jYWxsKHRoaXMucmVxdWVzdHMsIHhock9iaik7XG5cbiAgICAgICAgICAgICAgICB4aHJPYmoub25TZW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICBzZXJ2ZXIuaGFuZGxlUmVxdWVzdCh0aGlzKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoc2VydmVyLnJlc3BvbmRJbW1lZGlhdGVseSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VydmVyLnJlc3BvbmQoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzZXJ2ZXIuYXV0b1Jlc3BvbmQgJiYgIXNlcnZlci5yZXNwb25kaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXJ2ZXIucmVzcG9uZGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcnZlci5yZXNwb25kKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCBzZXJ2ZXIuYXV0b1Jlc3BvbmRBZnRlciB8fCAxMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcnZlci5yZXNwb25kaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBnZXRIVFRQTWV0aG9kOiBmdW5jdGlvbiBnZXRIVFRQTWV0aG9kKHJlcXVlc3QpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5mYWtlSFRUUE1ldGhvZHMgJiYgL3Bvc3QvaS50ZXN0KHJlcXVlc3QubWV0aG9kKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWF0Y2hlcyA9IChyZXF1ZXN0LnJlcXVlc3RCb2R5IHx8IFwiXCIpLm1hdGNoKC9fbWV0aG9kPShbXlxcYjtdKykvKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEhbWF0Y2hlcyA/IG1hdGNoZXNbMV0gOiByZXF1ZXN0Lm1ldGhvZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVxdWVzdC5tZXRob2Q7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBoYW5kbGVSZXF1ZXN0OiBmdW5jdGlvbiBoYW5kbGVSZXF1ZXN0KHhocikge1xuICAgICAgICAgICAgICAgIGlmICh4aHIuYXN5bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLnF1ZXVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnF1ZXVlID0gW107XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwdXNoLmNhbGwodGhpcy5xdWV1ZSwgeGhyKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NSZXF1ZXN0KHhocik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgbG9nOiBmdW5jdGlvbiBsb2cocmVzcG9uc2UsIHJlcXVlc3QpIHtcbiAgICAgICAgICAgICAgICB2YXIgc3RyO1xuXG4gICAgICAgICAgICAgICAgc3RyID0gIFwiUmVxdWVzdDpcXG5cIiAgKyBzaW5vbi5mb3JtYXQocmVxdWVzdCkgICsgXCJcXG5cXG5cIjtcbiAgICAgICAgICAgICAgICBzdHIgKz0gXCJSZXNwb25zZTpcXG5cIiArIHNpbm9uLmZvcm1hdChyZXNwb25zZSkgKyBcIlxcblxcblwiO1xuXG4gICAgICAgICAgICAgICAgc2lub24ubG9nKHN0cik7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICByZXNwb25kV2l0aDogZnVuY3Rpb24gcmVzcG9uZFdpdGgobWV0aG9kLCB1cmwsIGJvZHkpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PSAxICYmIHR5cGVvZiBtZXRob2QgIT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVzcG9uc2UgPSByZXNwb25zZUFycmF5KG1ldGhvZCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMucmVzcG9uc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVzcG9uc2VzID0gW107XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT0gMSkge1xuICAgICAgICAgICAgICAgICAgICBib2R5ID0gbWV0aG9kO1xuICAgICAgICAgICAgICAgICAgICB1cmwgPSBtZXRob2QgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgYm9keSA9IHVybDtcbiAgICAgICAgICAgICAgICAgICAgdXJsID0gbWV0aG9kO1xuICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHB1c2guY2FsbCh0aGlzLnJlc3BvbnNlcywge1xuICAgICAgICAgICAgICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgICAgICAgICAgICAgdXJsOiB1cmwsXG4gICAgICAgICAgICAgICAgICAgIHJlc3BvbnNlOiB0eXBlb2YgYm9keSA9PSBcImZ1bmN0aW9uXCIgPyBib2R5IDogcmVzcG9uc2VBcnJheShib2R5KVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgcmVzcG9uZDogZnVuY3Rpb24gcmVzcG9uZCgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNwb25kV2l0aC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBxdWV1ZSA9IHRoaXMucXVldWUgfHwgW107XG4gICAgICAgICAgICAgICAgdmFyIHJlcXVlc3RzID0gcXVldWUuc3BsaWNlKDAsIHF1ZXVlLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgdmFyIHJlcXVlc3Q7XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAocmVxdWVzdCA9IHJlcXVlc3RzLnNoaWZ0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzUmVxdWVzdChyZXF1ZXN0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBwcm9jZXNzUmVxdWVzdDogZnVuY3Rpb24gcHJvY2Vzc1JlcXVlc3QocmVxdWVzdCkge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXF1ZXN0LmFib3J0ZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciByZXNwb25zZSA9IHRoaXMucmVzcG9uc2UgfHwgWzQwNCwge30sIFwiXCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlc3BvbnNlcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgbCA9IHRoaXMucmVzcG9uc2VzLmxlbmd0aCwgaSA9IGwgLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5jYWxsKHRoaXMsIHRoaXMucmVzcG9uc2VzW2ldLCByZXF1ZXN0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNwb25zZSA9IHRoaXMucmVzcG9uc2VzW2ldLnJlc3BvbnNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAocmVxdWVzdC5yZWFkeVN0YXRlICE9IDQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubG9nKHJlc3BvbnNlLCByZXF1ZXN0KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWVzdC5yZXNwb25kKHJlc3BvbnNlWzBdLCByZXNwb25zZVsxXSwgcmVzcG9uc2VbMl0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBzaW5vbi5sb2dFcnJvcihcIkZha2Ugc2VydmVyIHJlcXVlc3QgcHJvY2Vzc2luZ1wiLCBlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICByZXN0b3JlOiBmdW5jdGlvbiByZXN0b3JlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnhoci5yZXN0b3JlICYmIHRoaXMueGhyLnJlc3RvcmUuYXBwbHkodGhpcy54aHIsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBleHBvcnRzLCBtb2R1bGUpIHtcbiAgICAgICAgdmFyIHNpbm9uID0gcmVxdWlyZShcIi4vY29yZVwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4vZmFrZV94ZG9tYWluX3JlcXVlc3RcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2Zha2VfeG1sX2h0dHBfcmVxdWVzdFwiKTtcbiAgICAgICAgcmVxdWlyZShcIi4uL2Zvcm1hdFwiKTtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gc2lub247XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUsIG1vZHVsZS5leHBvcnRzLCBtb2R1bGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0oKSk7XG4iLCIvKipcbiAqIEBkZXBlbmQgZmFrZV9zZXJ2ZXIuanNcbiAqIEBkZXBlbmQgZmFrZV90aW1lcnMuanNcbiAqL1xuLyoqXG4gKiBBZGQtb24gZm9yIHNpbm9uLmZha2VTZXJ2ZXIgdGhhdCBhdXRvbWF0aWNhbGx5IGhhbmRsZXMgYSBmYWtlIHRpbWVyIGFsb25nIHdpdGhcbiAqIHRoZSBGYWtlWE1MSHR0cFJlcXVlc3QuIFRoZSBkaXJlY3QgaW5zcGlyYXRpb24gZm9yIHRoaXMgYWRkLW9uIGlzIGpRdWVyeVxuICogMS4zLngsIHdoaWNoIGRvZXMgbm90IHVzZSB4aHIgb2JqZWN0J3Mgb25yZWFkeXN0YXRlaGFuZGxlciBhdCBhbGwgLSBpbnN0ZWFkLFxuICogaXQgcG9sbHMgdGhlIG9iamVjdCBmb3IgY29tcGxldGlvbiB3aXRoIHNldEludGVydmFsLiBEaXNwaXRlIHRoZSBkaXJlY3RcbiAqIG1vdGl2YXRpb24sIHRoZXJlIGlzIG5vdGhpbmcgalF1ZXJ5LXNwZWNpZmljIGluIHRoaXMgZmlsZSwgc28gaXQgY2FuIGJlIHVzZWRcbiAqIGluIGFueSBlbnZpcm9ubWVudCB3aGVyZSB0aGUgYWpheCBpbXBsZW1lbnRhdGlvbiBkZXBlbmRzIG9uIHNldEludGVydmFsIG9yXG4gKiBzZXRUaW1lb3V0LlxuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgZnVuY3Rpb24gU2VydmVyKCkge31cbiAgICAgICAgU2VydmVyLnByb3RvdHlwZSA9IHNpbm9uLmZha2VTZXJ2ZXI7XG5cbiAgICAgICAgc2lub24uZmFrZVNlcnZlcldpdGhDbG9jayA9IG5ldyBTZXJ2ZXIoKTtcblxuICAgICAgICBzaW5vbi5mYWtlU2VydmVyV2l0aENsb2NrLmFkZFJlcXVlc3QgPSBmdW5jdGlvbiBhZGRSZXF1ZXN0KHhocikge1xuICAgICAgICAgICAgaWYgKHhoci5hc3luYykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc2V0VGltZW91dC5jbG9jayA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2xvY2sgPSBzZXRUaW1lb3V0LmNsb2NrO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2xvY2sgPSBzaW5vbi51c2VGYWtlVGltZXJzKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVzZXRDbG9jayA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmxvbmdlc3RUaW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjbG9ja1NldFRpbWVvdXQgPSB0aGlzLmNsb2NrLnNldFRpbWVvdXQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjbG9ja1NldEludGVydmFsID0gdGhpcy5jbG9jay5zZXRJbnRlcnZhbDtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNlcnZlciA9IHRoaXM7XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jbG9jay5zZXRUaW1lb3V0ID0gZnVuY3Rpb24gKGZuLCB0aW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXJ2ZXIubG9uZ2VzdFRpbWVvdXQgPSBNYXRoLm1heCh0aW1lb3V0LCBzZXJ2ZXIubG9uZ2VzdFRpbWVvdXQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjbG9ja1NldFRpbWVvdXQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLmNsb2NrLnNldEludGVydmFsID0gZnVuY3Rpb24gKGZuLCB0aW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXJ2ZXIubG9uZ2VzdFRpbWVvdXQgPSBNYXRoLm1heCh0aW1lb3V0LCBzZXJ2ZXIubG9uZ2VzdFRpbWVvdXQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjbG9ja1NldEludGVydmFsLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gc2lub24uZmFrZVNlcnZlci5hZGRSZXF1ZXN0LmNhbGwodGhpcywgeGhyKTtcbiAgICAgICAgfTtcblxuICAgICAgICBzaW5vbi5mYWtlU2VydmVyV2l0aENsb2NrLnJlc3BvbmQgPSBmdW5jdGlvbiByZXNwb25kKCkge1xuICAgICAgICAgICAgdmFyIHJldHVyblZhbCA9IHNpbm9uLmZha2VTZXJ2ZXIucmVzcG9uZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5jbG9jaykge1xuICAgICAgICAgICAgICAgIHRoaXMuY2xvY2sudGljayh0aGlzLmxvbmdlc3RUaW1lb3V0IHx8IDApO1xuICAgICAgICAgICAgICAgIHRoaXMubG9uZ2VzdFRpbWVvdXQgPSAwO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucmVzZXRDbG9jaykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNsb2NrLnJlc3RvcmUoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNldENsb2NrID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmV0dXJuVmFsO1xuICAgICAgICB9O1xuXG4gICAgICAgIHNpbm9uLmZha2VTZXJ2ZXJXaXRoQ2xvY2sucmVzdG9yZSA9IGZ1bmN0aW9uIHJlc3RvcmUoKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5jbG9jaykge1xuICAgICAgICAgICAgICAgIHRoaXMuY2xvY2sucmVzdG9yZSgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gc2lub24uZmFrZVNlcnZlci5yZXN0b3JlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2Zha2Vfc2VydmVyXCIpO1xuICAgICAgICByZXF1aXJlKFwiLi9mYWtlX3RpbWVyc1wiKTtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxuXG4gICAgaWYgKGlzQU1EKSB7XG4gICAgICAgIGRlZmluZShsb2FkRGVwZW5kZW5jaWVzKTtcbiAgICB9IGVsc2UgaWYgKGlzTm9kZSkge1xuICAgICAgICBsb2FkRGVwZW5kZW5jaWVzKHJlcXVpcmUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cbn0oKSk7XG4iLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG4vKmdsb2JhbCBsb2xleCAqL1xuXG4vKipcbiAqIEZha2UgdGltZXIgQVBJXG4gKiBzZXRUaW1lb3V0XG4gKiBzZXRJbnRlcnZhbFxuICogY2xlYXJUaW1lb3V0XG4gKiBjbGVhckludGVydmFsXG4gKiB0aWNrXG4gKiByZXNldFxuICogRGF0ZVxuICpcbiAqIEluc3BpcmVkIGJ5IGpzVW5pdE1vY2tUaW1lT3V0IGZyb20gSnNVbml0XG4gKlxuICogQGF1dGhvciBDaHJpc3RpYW4gSm9oYW5zZW4gKGNocmlzdGlhbkBjam9oYW5zZW4ubm8pXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxMyBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbmlmICh0eXBlb2Ygc2lub24gPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHZhciBzaW5vbiA9IHt9O1xufVxuXG4oZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24sIGxvbCkge1xuICAgICAgICB2YXIgbGx4ID0gdHlwZW9mIGxvbGV4ICE9PSBcInVuZGVmaW5lZFwiID8gbG9sZXggOiBsb2w7XG5cbiAgICAgICAgc2lub24udXNlRmFrZVRpbWVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBub3csIG1ldGhvZHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIG1ldGhvZHNbMF0gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBub3cgPSAwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBub3cgPSBtZXRob2RzLnNoaWZ0KCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBjbG9jayA9IGxseC5pbnN0YWxsKG5vdyB8fCAwLCBtZXRob2RzKTtcbiAgICAgICAgICAgIGNsb2NrLnJlc3RvcmUgPSBjbG9jay51bmluc3RhbGw7XG4gICAgICAgICAgICByZXR1cm4gY2xvY2s7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uY2xvY2sgPSB7XG4gICAgICAgICAgICBjcmVhdGU6IGZ1bmN0aW9uIChub3cpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGx4LmNyZWF0ZUNsb2NrKG5vdyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24udGltZXJzID0ge1xuICAgICAgICAgICAgc2V0VGltZW91dDogc2V0VGltZW91dCxcbiAgICAgICAgICAgIGNsZWFyVGltZW91dDogY2xlYXJUaW1lb3V0LFxuICAgICAgICAgICAgc2V0SW1tZWRpYXRlOiAodHlwZW9mIHNldEltbWVkaWF0ZSAhPT0gXCJ1bmRlZmluZWRcIiA/IHNldEltbWVkaWF0ZSA6IHVuZGVmaW5lZCksXG4gICAgICAgICAgICBjbGVhckltbWVkaWF0ZTogKHR5cGVvZiBjbGVhckltbWVkaWF0ZSAhPT0gXCJ1bmRlZmluZWRcIiA/IGNsZWFySW1tZWRpYXRlIDogdW5kZWZpbmVkKSxcbiAgICAgICAgICAgIHNldEludGVydmFsOiBzZXRJbnRlcnZhbCxcbiAgICAgICAgICAgIGNsZWFySW50ZXJ2YWw6IGNsZWFySW50ZXJ2YWwsXG4gICAgICAgICAgICBEYXRlOiBEYXRlXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGlzTm9kZSA9IHR5cGVvZiBtb2R1bGUgIT09IFwidW5kZWZpbmVkXCIgJiYgbW9kdWxlLmV4cG9ydHMgJiYgdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiO1xuICAgIHZhciBpc0FNRCA9IHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgZGVmaW5lLmFtZCA9PT0gXCJvYmplY3RcIiAmJiBkZWZpbmUuYW1kO1xuXG4gICAgZnVuY3Rpb24gbG9hZERlcGVuZGVuY2llcyhyZXF1aXJlLCBlcHhvcnRzLCBtb2R1bGUsIGxvbGV4KSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL2NvcmVcIik7XG4gICAgICAgIG1ha2VBcGkoc2lub24sIGxvbGV4KTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBzaW5vbjtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgcmVxdWlyZShcImxvbGV4XCIpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICB9XG59KHR5cGVvZiBnbG9iYWwgIT0gXCJ1bmRlZmluZWRcIiAmJiB0eXBlb2YgZ2xvYmFsICE9PSBcImZ1bmN0aW9uXCIgPyBnbG9iYWwgOiB0aGlzKSk7XG5cbn0pLmNhbGwodGhpcyx0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pIiwiKGZ1bmN0aW9uIChnbG9iYWwpe1xuLyoqXG4gKiBAZGVwZW5kIGNvcmUuanNcbiAqIEBkZXBlbmQgLi4vZXh0ZW5kLmpzXG4gKiBAZGVwZW5kIGV2ZW50LmpzXG4gKiBAZGVwZW5kIC4uL2xvZ19lcnJvci5qc1xuICovXG4vKipcbiAqIEZha2UgWERvbWFpblJlcXVlc3Qgb2JqZWN0XG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG5pZiAodHlwZW9mIHNpbm9uID09IFwidW5kZWZpbmVkXCIpIHtcbiAgICB0aGlzLnNpbm9uID0ge307XG59XG5cbi8vIHdyYXBwZXIgZm9yIGdsb2JhbFxuKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICB2YXIgeGRyID0geyBYRG9tYWluUmVxdWVzdDogZ2xvYmFsLlhEb21haW5SZXF1ZXN0IH07XG4gICAgeGRyLkdsb2JhbFhEb21haW5SZXF1ZXN0ID0gZ2xvYmFsLlhEb21haW5SZXF1ZXN0O1xuICAgIHhkci5zdXBwb3J0c1hEUiA9IHR5cGVvZiB4ZHIuR2xvYmFsWERvbWFpblJlcXVlc3QgIT0gXCJ1bmRlZmluZWRcIjtcbiAgICB4ZHIud29ya2luZ1hEUiA9IHhkci5zdXBwb3J0c1hEUiA/IHhkci5HbG9iYWxYRG9tYWluUmVxdWVzdCA6ICBmYWxzZTtcblxuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgc2lub24ueGRyID0geGRyO1xuXG4gICAgICAgIGZ1bmN0aW9uIEZha2VYRG9tYWluUmVxdWVzdCgpIHtcbiAgICAgICAgICAgIHRoaXMucmVhZHlTdGF0ZSA9IEZha2VYRG9tYWluUmVxdWVzdC5VTlNFTlQ7XG4gICAgICAgICAgICB0aGlzLnJlcXVlc3RCb2R5ID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMucmVxdWVzdEhlYWRlcnMgPSB7fTtcbiAgICAgICAgICAgIHRoaXMuc3RhdHVzID0gMDtcbiAgICAgICAgICAgIHRoaXMudGltZW91dCA9IG51bGw7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgRmFrZVhEb21haW5SZXF1ZXN0Lm9uQ3JlYXRlID09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgIEZha2VYRG9tYWluUmVxdWVzdC5vbkNyZWF0ZSh0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHZlcmlmeVN0YXRlKHhkcikge1xuICAgICAgICAgICAgaWYgKHhkci5yZWFkeVN0YXRlICE9PSBGYWtlWERvbWFpblJlcXVlc3QuT1BFTkVEKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSU5WQUxJRF9TVEFURV9FUlJcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh4ZHIuc2VuZEZsYWcpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJTlZBTElEX1NUQVRFX0VSUlwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHZlcmlmeVJlcXVlc3RTZW50KHhkcikge1xuICAgICAgICAgICAgaWYgKHhkci5yZWFkeVN0YXRlID09IEZha2VYRG9tYWluUmVxdWVzdC5VTlNFTlQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJSZXF1ZXN0IG5vdCBzZW50XCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHhkci5yZWFkeVN0YXRlID09IEZha2VYRG9tYWluUmVxdWVzdC5ET05FKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVxdWVzdCBkb25lXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gdmVyaWZ5UmVzcG9uc2VCb2R5VHlwZShib2R5KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGJvZHkgIT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgIHZhciBlcnJvciA9IG5ldyBFcnJvcihcIkF0dGVtcHRlZCB0byByZXNwb25kIHRvIGZha2UgWERvbWFpblJlcXVlc3Qgd2l0aCBcIiArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBib2R5ICsgXCIsIHdoaWNoIGlzIG5vdCBhIHN0cmluZy5cIik7XG4gICAgICAgICAgICAgICAgZXJyb3IubmFtZSA9IFwiSW52YWxpZEJvZHlFeGNlcHRpb25cIjtcbiAgICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNpbm9uLmV4dGVuZChGYWtlWERvbWFpblJlcXVlc3QucHJvdG90eXBlLCBzaW5vbi5FdmVudFRhcmdldCwge1xuICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gb3BlbihtZXRob2QsIHVybCkge1xuICAgICAgICAgICAgICAgIHRoaXMubWV0aG9kID0gbWV0aG9kO1xuICAgICAgICAgICAgICAgIHRoaXMudXJsID0gdXJsO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZVRleHQgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMuc2VuZEZsYWcgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIHRoaXMucmVhZHlTdGF0ZUNoYW5nZShGYWtlWERvbWFpblJlcXVlc3QuT1BFTkVEKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlYWR5U3RhdGVDaGFuZ2U6IGZ1bmN0aW9uIHJlYWR5U3RhdGVDaGFuZ2Uoc3RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGUgPSBzdGF0ZTtcbiAgICAgICAgICAgICAgICB2YXIgZXZlbnROYW1lID0gXCJcIjtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMucmVhZHlTdGF0ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgRmFrZVhEb21haW5SZXF1ZXN0LlVOU0VOVDpcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBGYWtlWERvbWFpblJlcXVlc3QuT1BFTkVEOlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEZha2VYRG9tYWluUmVxdWVzdC5MT0FESU5HOlxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZW5kRmxhZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy9yYWlzZSB0aGUgcHJvZ3Jlc3MgZXZlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TmFtZSA9IFwib25wcm9ncmVzc1wiO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgRmFrZVhEb21haW5SZXF1ZXN0LkRPTkU6XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzVGltZW91dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnROYW1lID0gXCJvbnRpbWVvdXRcIlxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZXJyb3JGbGFnIHx8ICh0aGlzLnN0YXR1cyA8IDIwMCB8fCB0aGlzLnN0YXR1cyA+IDI5OSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50TmFtZSA9IFwib25lcnJvclwiO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnROYW1lID0gXCJvbmxvYWRcIlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJhaXNpbmcgZXZlbnQgKGlmIGRlZmluZWQpXG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50TmFtZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHRoaXNbZXZlbnROYW1lXSA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpc1tldmVudE5hbWVdKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2lub24ubG9nRXJyb3IoXCJGYWtlIFhIUiBcIiArIGV2ZW50TmFtZSArIFwiIGhhbmRsZXJcIiwgZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBzZW5kOiBmdW5jdGlvbiBzZW5kKGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2ZXJpZnlTdGF0ZSh0aGlzKTtcblxuICAgICAgICAgICAgICAgIGlmICghL14oZ2V0fGhlYWQpJC9pLnRlc3QodGhpcy5tZXRob2QpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVxdWVzdEJvZHkgPSBkYXRhO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnJlcXVlc3RIZWFkZXJzW1wiQ29udGVudC1UeXBlXCJdID0gXCJ0ZXh0L3BsYWluO2NoYXJzZXQ9dXRmLThcIjtcblxuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JGbGFnID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kRmxhZyA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkeVN0YXRlQ2hhbmdlKEZha2VYRG9tYWluUmVxdWVzdC5PUEVORUQpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm9uU2VuZCA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblNlbmQodGhpcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgYWJvcnQ6IGZ1bmN0aW9uIGFib3J0KCkge1xuICAgICAgICAgICAgICAgIHRoaXMuYWJvcnRlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZVRleHQgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JGbGFnID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlYWR5U3RhdGUgPiBzaW5vbi5GYWtlWERvbWFpblJlcXVlc3QuVU5TRU5UICYmIHRoaXMuc2VuZEZsYWcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWFkeVN0YXRlQ2hhbmdlKHNpbm9uLkZha2VYRG9tYWluUmVxdWVzdC5ET05FKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZW5kRmxhZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHNldFJlc3BvbnNlQm9keTogZnVuY3Rpb24gc2V0UmVzcG9uc2VCb2R5KGJvZHkpIHtcbiAgICAgICAgICAgICAgICB2ZXJpZnlSZXF1ZXN0U2VudCh0aGlzKTtcbiAgICAgICAgICAgICAgICB2ZXJpZnlSZXNwb25zZUJvZHlUeXBlKGJvZHkpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNodW5rU2l6ZSA9IHRoaXMuY2h1bmtTaXplIHx8IDEwO1xuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZVRleHQgPSBcIlwiO1xuXG4gICAgICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGVDaGFuZ2UoRmFrZVhEb21haW5SZXF1ZXN0LkxPQURJTkcpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlVGV4dCArPSBib2R5LnN1YnN0cmluZyhpbmRleCwgaW5kZXggKyBjaHVua1NpemUpO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaHVua1NpemU7XG4gICAgICAgICAgICAgICAgfSB3aGlsZSAoaW5kZXggPCBib2R5Lmxlbmd0aCk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGVDaGFuZ2UoRmFrZVhEb21haW5SZXF1ZXN0LkRPTkUpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgcmVzcG9uZDogZnVuY3Rpb24gcmVzcG9uZChzdGF0dXMsIGNvbnRlbnRUeXBlLCBib2R5KSB7XG4gICAgICAgICAgICAgICAgLy8gY29udGVudC10eXBlIGlnbm9yZWQsIHNpbmNlIFhEb21haW5SZXF1ZXN0IGRvZXMgbm90IGNhcnJ5IHRoaXNcbiAgICAgICAgICAgICAgICAvLyB3ZSBrZWVwIHRoZSBzYW1lIHN5bnRheCBmb3IgcmVzcG9uZCguLi4pIGFzIGZvciBGYWtlWE1MSHR0cFJlcXVlc3QgdG8gZWFzZVxuICAgICAgICAgICAgICAgIC8vIHRlc3QgaW50ZWdyYXRpb24gYWNyb3NzIGJyb3dzZXJzXG4gICAgICAgICAgICAgICAgdGhpcy5zdGF0dXMgPSB0eXBlb2Ygc3RhdHVzID09IFwibnVtYmVyXCIgPyBzdGF0dXMgOiAyMDA7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXRSZXNwb25zZUJvZHkoYm9keSB8fCBcIlwiKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHNpbXVsYXRldGltZW91dDogZnVuY3Rpb24gc2ltdWxhdGV0aW1lb3V0KCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RhdHVzID0gMDtcbiAgICAgICAgICAgICAgICB0aGlzLmlzVGltZW91dCA9IHRydWU7XG4gICAgICAgICAgICAgICAgLy8gQWNjZXNzIHRvIHRoaXMgc2hvdWxkIGFjdHVhbGx5IHRocm93IGFuIGVycm9yXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZVRleHQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5yZWFkeVN0YXRlQ2hhbmdlKEZha2VYRG9tYWluUmVxdWVzdC5ET05FKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2lub24uZXh0ZW5kKEZha2VYRG9tYWluUmVxdWVzdCwge1xuICAgICAgICAgICAgVU5TRU5UOiAwLFxuICAgICAgICAgICAgT1BFTkVEOiAxLFxuICAgICAgICAgICAgTE9BRElORzogMyxcbiAgICAgICAgICAgIERPTkU6IDRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2lub24udXNlRmFrZVhEb21haW5SZXF1ZXN0ID0gZnVuY3Rpb24gdXNlRmFrZVhEb21haW5SZXF1ZXN0KCkge1xuICAgICAgICAgICAgc2lub24uRmFrZVhEb21haW5SZXF1ZXN0LnJlc3RvcmUgPSBmdW5jdGlvbiByZXN0b3JlKGtlZXBPbkNyZWF0ZSkge1xuICAgICAgICAgICAgICAgIGlmICh4ZHIuc3VwcG9ydHNYRFIpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2xvYmFsLlhEb21haW5SZXF1ZXN0ID0geGRyLkdsb2JhbFhEb21haW5SZXF1ZXN0O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlbGV0ZSBzaW5vbi5GYWtlWERvbWFpblJlcXVlc3QucmVzdG9yZTtcblxuICAgICAgICAgICAgICAgIGlmIChrZWVwT25DcmVhdGUgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHNpbm9uLkZha2VYRG9tYWluUmVxdWVzdC5vbkNyZWF0ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKHhkci5zdXBwb3J0c1hEUikge1xuICAgICAgICAgICAgICAgIGdsb2JhbC5YRG9tYWluUmVxdWVzdCA9IHNpbm9uLkZha2VYRG9tYWluUmVxdWVzdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzaW5vbi5GYWtlWERvbWFpblJlcXVlc3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uRmFrZVhEb21haW5SZXF1ZXN0ID0gRmFrZVhEb21haW5SZXF1ZXN0O1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuLi9leHRlbmRcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2V2ZW50XCIpO1xuICAgICAgICByZXF1aXJlKFwiLi4vbG9nX2Vycm9yXCIpO1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBzaW5vbjtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUFwaShzaW5vbik7XG4gICAgfVxufSkodHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHNlbGYpO1xuXG59KS5jYWxsKHRoaXMsdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KSIsIihmdW5jdGlvbiAoZ2xvYmFsKXtcbi8qKlxuICogQGRlcGVuZCBjb3JlLmpzXG4gKiBAZGVwZW5kIC4uL2V4dGVuZC5qc1xuICogQGRlcGVuZCBldmVudC5qc1xuICogQGRlcGVuZCAuLi9sb2dfZXJyb3IuanNcbiAqL1xuLyoqXG4gKiBGYWtlIFhNTEh0dHBSZXF1ZXN0IG9iamVjdFxuICpcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKVxuICogQGxpY2Vuc2UgQlNEXG4gKlxuICogQ29weXJpZ2h0IChjKSAyMDEwLTIwMTMgQ2hyaXN0aWFuIEpvaGFuc2VuXG4gKi9cblwidXNlIHN0cmljdFwiO1xuXG4oZnVuY3Rpb24gKGdsb2JhbCkge1xuXG4gICAgdmFyIHN1cHBvcnRzUHJvZ3Jlc3MgPSB0eXBlb2YgUHJvZ3Jlc3NFdmVudCAhPT0gXCJ1bmRlZmluZWRcIjtcbiAgICB2YXIgc3VwcG9ydHNDdXN0b21FdmVudCA9IHR5cGVvZiBDdXN0b21FdmVudCAhPT0gXCJ1bmRlZmluZWRcIjtcbiAgICB2YXIgc3VwcG9ydHNGb3JtRGF0YSA9IHR5cGVvZiBGb3JtRGF0YSAhPT0gXCJ1bmRlZmluZWRcIjtcbiAgICB2YXIgc2lub25YaHIgPSB7IFhNTEh0dHBSZXF1ZXN0OiBnbG9iYWwuWE1MSHR0cFJlcXVlc3QgfTtcbiAgICBzaW5vblhoci5HbG9iYWxYTUxIdHRwUmVxdWVzdCA9IGdsb2JhbC5YTUxIdHRwUmVxdWVzdDtcbiAgICBzaW5vblhoci5HbG9iYWxBY3RpdmVYT2JqZWN0ID0gZ2xvYmFsLkFjdGl2ZVhPYmplY3Q7XG4gICAgc2lub25YaHIuc3VwcG9ydHNBY3RpdmVYID0gdHlwZW9mIHNpbm9uWGhyLkdsb2JhbEFjdGl2ZVhPYmplY3QgIT0gXCJ1bmRlZmluZWRcIjtcbiAgICBzaW5vblhoci5zdXBwb3J0c1hIUiA9IHR5cGVvZiBzaW5vblhoci5HbG9iYWxYTUxIdHRwUmVxdWVzdCAhPSBcInVuZGVmaW5lZFwiO1xuICAgIHNpbm9uWGhyLndvcmtpbmdYSFIgPSBzaW5vblhoci5zdXBwb3J0c1hIUiA/IHNpbm9uWGhyLkdsb2JhbFhNTEh0dHBSZXF1ZXN0IDogc2lub25YaHIuc3VwcG9ydHNBY3RpdmVYXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBzaW5vblhoci5HbG9iYWxBY3RpdmVYT2JqZWN0KFwiTVNYTUwyLlhNTEhUVFAuMy4wXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IDogZmFsc2U7XG4gICAgc2lub25YaHIuc3VwcG9ydHNDT1JTID0gc2lub25YaHIuc3VwcG9ydHNYSFIgJiYgXCJ3aXRoQ3JlZGVudGlhbHNcIiBpbiAobmV3IHNpbm9uWGhyLkdsb2JhbFhNTEh0dHBSZXF1ZXN0KCkpO1xuXG4gICAgLypqc2w6aWdub3JlKi9cbiAgICB2YXIgdW5zYWZlSGVhZGVycyA9IHtcbiAgICAgICAgXCJBY2NlcHQtQ2hhcnNldFwiOiB0cnVlLFxuICAgICAgICBcIkFjY2VwdC1FbmNvZGluZ1wiOiB0cnVlLFxuICAgICAgICBDb25uZWN0aW9uOiB0cnVlLFxuICAgICAgICBcIkNvbnRlbnQtTGVuZ3RoXCI6IHRydWUsXG4gICAgICAgIENvb2tpZTogdHJ1ZSxcbiAgICAgICAgQ29va2llMjogdHJ1ZSxcbiAgICAgICAgXCJDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nXCI6IHRydWUsXG4gICAgICAgIERhdGU6IHRydWUsXG4gICAgICAgIEV4cGVjdDogdHJ1ZSxcbiAgICAgICAgSG9zdDogdHJ1ZSxcbiAgICAgICAgXCJLZWVwLUFsaXZlXCI6IHRydWUsXG4gICAgICAgIFJlZmVyZXI6IHRydWUsXG4gICAgICAgIFRFOiB0cnVlLFxuICAgICAgICBUcmFpbGVyOiB0cnVlLFxuICAgICAgICBcIlRyYW5zZmVyLUVuY29kaW5nXCI6IHRydWUsXG4gICAgICAgIFVwZ3JhZGU6IHRydWUsXG4gICAgICAgIFwiVXNlci1BZ2VudFwiOiB0cnVlLFxuICAgICAgICBWaWE6IHRydWVcbiAgICB9O1xuICAgIC8qanNsOmVuZCovXG5cbiAgICAvLyBOb3RlIHRoYXQgZm9yIEZha2VYTUxIdHRwUmVxdWVzdCB0byB3b3JrIHByZSBFUzVcbiAgICAvLyB3ZSBsb3NlIHNvbWUgb2YgdGhlIGFsaWdubWVudCB3aXRoIHRoZSBzcGVjLlxuICAgIC8vIFRvIGVuc3VyZSBhcyBjbG9zZSBhIG1hdGNoIGFzIHBvc3NpYmxlLFxuICAgIC8vIHNldCByZXNwb25zZVR5cGUgYmVmb3JlIGNhbGxpbmcgb3Blbiwgc2VuZCBvciByZXNwb25kO1xuICAgIGZ1bmN0aW9uIEZha2VYTUxIdHRwUmVxdWVzdCgpIHtcbiAgICAgICAgdGhpcy5yZWFkeVN0YXRlID0gRmFrZVhNTEh0dHBSZXF1ZXN0LlVOU0VOVDtcbiAgICAgICAgdGhpcy5yZXF1ZXN0SGVhZGVycyA9IHt9O1xuICAgICAgICB0aGlzLnJlcXVlc3RCb2R5ID0gbnVsbDtcbiAgICAgICAgdGhpcy5zdGF0dXMgPSAwO1xuICAgICAgICB0aGlzLnN0YXR1c1RleHQgPSBcIlwiO1xuICAgICAgICB0aGlzLnVwbG9hZCA9IG5ldyBVcGxvYWRQcm9ncmVzcygpO1xuICAgICAgICB0aGlzLnJlc3BvbnNlVHlwZSA9IFwiXCI7XG4gICAgICAgIHRoaXMucmVzcG9uc2UgPSBcIlwiO1xuICAgICAgICBpZiAoc2lub25YaHIuc3VwcG9ydHNDT1JTKSB7XG4gICAgICAgICAgICB0aGlzLndpdGhDcmVkZW50aWFscyA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHhociA9IHRoaXM7XG4gICAgICAgIHZhciBldmVudHMgPSBbXCJsb2Fkc3RhcnRcIiwgXCJsb2FkXCIsIFwiYWJvcnRcIiwgXCJsb2FkZW5kXCJdO1xuXG4gICAgICAgIGZ1bmN0aW9uIGFkZEV2ZW50TGlzdGVuZXIoZXZlbnROYW1lKSB7XG4gICAgICAgICAgICB4aHIuYWRkRXZlbnRMaXN0ZW5lcihldmVudE5hbWUsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgICAgIHZhciBsaXN0ZW5lciA9IHhocltcIm9uXCIgKyBldmVudE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgaWYgKGxpc3RlbmVyICYmIHR5cGVvZiBsaXN0ZW5lciA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXIuY2FsbCh0aGlzLCBldmVudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciBpID0gZXZlbnRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgICAgICBhZGRFdmVudExpc3RlbmVyKGV2ZW50c1tpXSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIEZha2VYTUxIdHRwUmVxdWVzdC5vbkNyZWF0ZSA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIEZha2VYTUxIdHRwUmVxdWVzdC5vbkNyZWF0ZSh0aGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIEFuIHVwbG9hZCBvYmplY3QgaXMgY3JlYXRlZCBmb3IgZWFjaFxuICAgIC8vIEZha2VYTUxIdHRwUmVxdWVzdCBhbmQgYWxsb3dzIHVwbG9hZFxuICAgIC8vIGV2ZW50cyB0byBiZSBzaW11bGF0ZWQgdXNpbmcgdXBsb2FkUHJvZ3Jlc3NcbiAgICAvLyBhbmQgdXBsb2FkRXJyb3IuXG4gICAgZnVuY3Rpb24gVXBsb2FkUHJvZ3Jlc3MoKSB7XG4gICAgICAgIHRoaXMuZXZlbnRMaXN0ZW5lcnMgPSB7XG4gICAgICAgICAgICBwcm9ncmVzczogW10sXG4gICAgICAgICAgICBsb2FkOiBbXSxcbiAgICAgICAgICAgIGFib3J0OiBbXSxcbiAgICAgICAgICAgIGVycm9yOiBbXVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgVXBsb2FkUHJvZ3Jlc3MucHJvdG90eXBlLmFkZEV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiBhZGRFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcikge1xuICAgICAgICB0aGlzLmV2ZW50TGlzdGVuZXJzW2V2ZW50XS5wdXNoKGxpc3RlbmVyKTtcbiAgICB9O1xuXG4gICAgVXBsb2FkUHJvZ3Jlc3MucHJvdG90eXBlLnJlbW92ZUV2ZW50TGlzdGVuZXIgPSBmdW5jdGlvbiByZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBsaXN0ZW5lcikge1xuICAgICAgICB2YXIgbGlzdGVuZXJzID0gdGhpcy5ldmVudExpc3RlbmVyc1tldmVudF0gfHwgW107XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDAsIGwgPSBsaXN0ZW5lcnMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICBpZiAobGlzdGVuZXJzW2ldID09IGxpc3RlbmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxpc3RlbmVycy5zcGxpY2UoaSwgMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgVXBsb2FkUHJvZ3Jlc3MucHJvdG90eXBlLmRpc3BhdGNoRXZlbnQgPSBmdW5jdGlvbiBkaXNwYXRjaEV2ZW50KGV2ZW50KSB7XG4gICAgICAgIHZhciBsaXN0ZW5lcnMgPSB0aGlzLmV2ZW50TGlzdGVuZXJzW2V2ZW50LnR5cGVdIHx8IFtdO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBsaXN0ZW5lcjsgKGxpc3RlbmVyID0gbGlzdGVuZXJzW2ldKSAhPSBudWxsOyBpKyspIHtcbiAgICAgICAgICAgIGxpc3RlbmVyKGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBmdW5jdGlvbiB2ZXJpZnlTdGF0ZSh4aHIpIHtcbiAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlICE9PSBGYWtlWE1MSHR0cFJlcXVlc3QuT1BFTkVEKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJTlZBTElEX1NUQVRFX0VSUlwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh4aHIuc2VuZEZsYWcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIklOVkFMSURfU1RBVEVfRVJSXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0SGVhZGVyKGhlYWRlcnMsIGhlYWRlcikge1xuICAgICAgICBoZWFkZXIgPSBoZWFkZXIudG9Mb3dlckNhc2UoKTtcblxuICAgICAgICBmb3IgKHZhciBoIGluIGhlYWRlcnMpIHtcbiAgICAgICAgICAgIGlmIChoLnRvTG93ZXJDYXNlKCkgPT0gaGVhZGVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBmaWx0ZXJpbmcgdG8gZW5hYmxlIGEgd2hpdGUtbGlzdCB2ZXJzaW9uIG9mIFNpbm9uIEZha2VYaHIsXG4gICAgLy8gd2hlcmUgd2hpdGVsaXN0ZWQgcmVxdWVzdHMgYXJlIHBhc3NlZCB0aHJvdWdoIHRvIHJlYWwgWEhSXG4gICAgZnVuY3Rpb24gZWFjaChjb2xsZWN0aW9uLCBjYWxsYmFjaykge1xuICAgICAgICBpZiAoIWNvbGxlY3Rpb24pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBsID0gY29sbGVjdGlvbi5sZW5ndGg7IGkgPCBsOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKGNvbGxlY3Rpb25baV0pO1xuICAgICAgICB9XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNvbWUoY29sbGVjdGlvbiwgY2FsbGJhY2spIHtcbiAgICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGNvbGxlY3Rpb24ubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICAgICAgICBpZiAoY2FsbGJhY2soY29sbGVjdGlvbltpbmRleF0pID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvLyBsYXJnZXN0IGFyaXR5IGluIFhIUiBpcyA1IC0gWEhSI29wZW5cbiAgICB2YXIgYXBwbHkgPSBmdW5jdGlvbiAob2JqLCBtZXRob2QsIGFyZ3MpIHtcbiAgICAgICAgc3dpdGNoIChhcmdzLmxlbmd0aCkge1xuICAgICAgICBjYXNlIDA6IHJldHVybiBvYmpbbWV0aG9kXSgpO1xuICAgICAgICBjYXNlIDE6IHJldHVybiBvYmpbbWV0aG9kXShhcmdzWzBdKTtcbiAgICAgICAgY2FzZSAyOiByZXR1cm4gb2JqW21ldGhvZF0oYXJnc1swXSwgYXJnc1sxXSk7XG4gICAgICAgIGNhc2UgMzogcmV0dXJuIG9ialttZXRob2RdKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0pO1xuICAgICAgICBjYXNlIDQ6IHJldHVybiBvYmpbbWV0aG9kXShhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdLCBhcmdzWzNdKTtcbiAgICAgICAgY2FzZSA1OiByZXR1cm4gb2JqW21ldGhvZF0oYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSwgYXJnc1s0XSk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgRmFrZVhNTEh0dHBSZXF1ZXN0LmZpbHRlcnMgPSBbXTtcbiAgICBGYWtlWE1MSHR0cFJlcXVlc3QuYWRkRmlsdGVyID0gZnVuY3Rpb24gYWRkRmlsdGVyKGZuKSB7XG4gICAgICAgIHRoaXMuZmlsdGVycy5wdXNoKGZuKVxuICAgIH07XG4gICAgdmFyIElFNlJlID0gL01TSUUgNi87XG4gICAgRmFrZVhNTEh0dHBSZXF1ZXN0LmRlZmFrZSA9IGZ1bmN0aW9uIGRlZmFrZShmYWtlWGhyLCB4aHJBcmdzKSB7XG4gICAgICAgIHZhciB4aHIgPSBuZXcgc2lub25YaHIud29ya2luZ1hIUigpO1xuICAgICAgICBlYWNoKFtcbiAgICAgICAgICAgIFwib3BlblwiLFxuICAgICAgICAgICAgXCJzZXRSZXF1ZXN0SGVhZGVyXCIsXG4gICAgICAgICAgICBcInNlbmRcIixcbiAgICAgICAgICAgIFwiYWJvcnRcIixcbiAgICAgICAgICAgIFwiZ2V0UmVzcG9uc2VIZWFkZXJcIixcbiAgICAgICAgICAgIFwiZ2V0QWxsUmVzcG9uc2VIZWFkZXJzXCIsXG4gICAgICAgICAgICBcImFkZEV2ZW50TGlzdGVuZXJcIixcbiAgICAgICAgICAgIFwib3ZlcnJpZGVNaW1lVHlwZVwiLFxuICAgICAgICAgICAgXCJyZW1vdmVFdmVudExpc3RlbmVyXCJcbiAgICAgICAgXSwgZnVuY3Rpb24gKG1ldGhvZCkge1xuICAgICAgICAgICAgZmFrZVhoclttZXRob2RdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseSh4aHIsIG1ldGhvZCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBjb3B5QXR0cnMgPSBmdW5jdGlvbiAoYXJncykge1xuICAgICAgICAgICAgZWFjaChhcmdzLCBmdW5jdGlvbiAoYXR0cikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGZha2VYaHJbYXR0cl0gPSB4aHJbYXR0cl1cbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghSUU2UmUudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuXG4gICAgICAgIHZhciBzdGF0ZUNoYW5nZSA9IGZ1bmN0aW9uIHN0YXRlQ2hhbmdlKCkge1xuICAgICAgICAgICAgZmFrZVhoci5yZWFkeVN0YXRlID0geGhyLnJlYWR5U3RhdGU7XG4gICAgICAgICAgICBpZiAoeGhyLnJlYWR5U3RhdGUgPj0gRmFrZVhNTEh0dHBSZXF1ZXN0LkhFQURFUlNfUkVDRUlWRUQpIHtcbiAgICAgICAgICAgICAgICBjb3B5QXR0cnMoW1wic3RhdHVzXCIsIFwic3RhdHVzVGV4dFwiXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoeGhyLnJlYWR5U3RhdGUgPj0gRmFrZVhNTEh0dHBSZXF1ZXN0LkxPQURJTkcpIHtcbiAgICAgICAgICAgICAgICBjb3B5QXR0cnMoW1wicmVzcG9uc2VUZXh0XCIsIFwicmVzcG9uc2VcIl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHhoci5yZWFkeVN0YXRlID09PSBGYWtlWE1MSHR0cFJlcXVlc3QuRE9ORSkge1xuICAgICAgICAgICAgICAgIGNvcHlBdHRycyhbXCJyZXNwb25zZVhNTFwiXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmFrZVhoci5vbnJlYWR5c3RhdGVjaGFuZ2UpIHtcbiAgICAgICAgICAgICAgICBmYWtlWGhyLm9ucmVhZHlzdGF0ZWNoYW5nZS5jYWxsKGZha2VYaHIsIHsgdGFyZ2V0OiBmYWtlWGhyIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICh4aHIuYWRkRXZlbnRMaXN0ZW5lcikge1xuICAgICAgICAgICAgZm9yICh2YXIgZXZlbnQgaW4gZmFrZVhoci5ldmVudExpc3RlbmVycykge1xuICAgICAgICAgICAgICAgIGlmIChmYWtlWGhyLmV2ZW50TGlzdGVuZXJzLmhhc093blByb3BlcnR5KGV2ZW50KSkge1xuICAgICAgICAgICAgICAgICAgICBlYWNoKGZha2VYaHIuZXZlbnRMaXN0ZW5lcnNbZXZlbnRdLCBmdW5jdGlvbiAoaGFuZGxlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgeGhyLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGhhbmRsZXIpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB4aHIuYWRkRXZlbnRMaXN0ZW5lcihcInJlYWR5c3RhdGVjaGFuZ2VcIiwgc3RhdGVDaGFuZ2UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IHN0YXRlQ2hhbmdlO1xuICAgICAgICB9XG4gICAgICAgIGFwcGx5KHhociwgXCJvcGVuXCIsIHhockFyZ3MpO1xuICAgIH07XG4gICAgRmFrZVhNTEh0dHBSZXF1ZXN0LnVzZUZpbHRlcnMgPSBmYWxzZTtcblxuICAgIGZ1bmN0aW9uIHZlcmlmeVJlcXVlc3RPcGVuZWQoeGhyKSB7XG4gICAgICAgIGlmICh4aHIucmVhZHlTdGF0ZSAhPSBGYWtlWE1MSHR0cFJlcXVlc3QuT1BFTkVEKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJTlZBTElEX1NUQVRFX0VSUiAtIFwiICsgeGhyLnJlYWR5U3RhdGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdmVyaWZ5UmVxdWVzdFNlbnQoeGhyKSB7XG4gICAgICAgIGlmICh4aHIucmVhZHlTdGF0ZSA9PSBGYWtlWE1MSHR0cFJlcXVlc3QuRE9ORSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiUmVxdWVzdCBkb25lXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdmVyaWZ5SGVhZGVyc1JlY2VpdmVkKHhocikge1xuICAgICAgICBpZiAoeGhyLmFzeW5jICYmIHhoci5yZWFkeVN0YXRlICE9IEZha2VYTUxIdHRwUmVxdWVzdC5IRUFERVJTX1JFQ0VJVkVEKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBoZWFkZXJzIHJlY2VpdmVkXCIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdmVyaWZ5UmVzcG9uc2VCb2R5VHlwZShib2R5KSB7XG4gICAgICAgIGlmICh0eXBlb2YgYm9keSAhPSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoXCJBdHRlbXB0ZWQgdG8gcmVzcG9uZCB0byBmYWtlIFhNTEh0dHBSZXF1ZXN0IHdpdGggXCIgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYm9keSArIFwiLCB3aGljaCBpcyBub3QgYSBzdHJpbmcuXCIpO1xuICAgICAgICAgICAgZXJyb3IubmFtZSA9IFwiSW52YWxpZEJvZHlFeGNlcHRpb25cIjtcbiAgICAgICAgICAgIHRocm93IGVycm9yO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgRmFrZVhNTEh0dHBSZXF1ZXN0LnBhcnNlWE1MID0gZnVuY3Rpb24gcGFyc2VYTUwodGV4dCkge1xuICAgICAgICB2YXIgeG1sRG9jO1xuXG4gICAgICAgIGlmICh0eXBlb2YgRE9NUGFyc2VyICE9IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgIHZhciBwYXJzZXIgPSBuZXcgRE9NUGFyc2VyKCk7XG4gICAgICAgICAgICB4bWxEb2MgPSBwYXJzZXIucGFyc2VGcm9tU3RyaW5nKHRleHQsIFwidGV4dC94bWxcIik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB4bWxEb2MgPSBuZXcgQWN0aXZlWE9iamVjdChcIk1pY3Jvc29mdC5YTUxET01cIik7XG4gICAgICAgICAgICB4bWxEb2MuYXN5bmMgPSBcImZhbHNlXCI7XG4gICAgICAgICAgICB4bWxEb2MubG9hZFhNTCh0ZXh0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB4bWxEb2M7XG4gICAgfTtcblxuICAgIEZha2VYTUxIdHRwUmVxdWVzdC5zdGF0dXNDb2RlcyA9IHtcbiAgICAgICAgMTAwOiBcIkNvbnRpbnVlXCIsXG4gICAgICAgIDEwMTogXCJTd2l0Y2hpbmcgUHJvdG9jb2xzXCIsXG4gICAgICAgIDIwMDogXCJPS1wiLFxuICAgICAgICAyMDE6IFwiQ3JlYXRlZFwiLFxuICAgICAgICAyMDI6IFwiQWNjZXB0ZWRcIixcbiAgICAgICAgMjAzOiBcIk5vbi1BdXRob3JpdGF0aXZlIEluZm9ybWF0aW9uXCIsXG4gICAgICAgIDIwNDogXCJObyBDb250ZW50XCIsXG4gICAgICAgIDIwNTogXCJSZXNldCBDb250ZW50XCIsXG4gICAgICAgIDIwNjogXCJQYXJ0aWFsIENvbnRlbnRcIixcbiAgICAgICAgMjA3OiBcIk11bHRpLVN0YXR1c1wiLFxuICAgICAgICAzMDA6IFwiTXVsdGlwbGUgQ2hvaWNlXCIsXG4gICAgICAgIDMwMTogXCJNb3ZlZCBQZXJtYW5lbnRseVwiLFxuICAgICAgICAzMDI6IFwiRm91bmRcIixcbiAgICAgICAgMzAzOiBcIlNlZSBPdGhlclwiLFxuICAgICAgICAzMDQ6IFwiTm90IE1vZGlmaWVkXCIsXG4gICAgICAgIDMwNTogXCJVc2UgUHJveHlcIixcbiAgICAgICAgMzA3OiBcIlRlbXBvcmFyeSBSZWRpcmVjdFwiLFxuICAgICAgICA0MDA6IFwiQmFkIFJlcXVlc3RcIixcbiAgICAgICAgNDAxOiBcIlVuYXV0aG9yaXplZFwiLFxuICAgICAgICA0MDI6IFwiUGF5bWVudCBSZXF1aXJlZFwiLFxuICAgICAgICA0MDM6IFwiRm9yYmlkZGVuXCIsXG4gICAgICAgIDQwNDogXCJOb3QgRm91bmRcIixcbiAgICAgICAgNDA1OiBcIk1ldGhvZCBOb3QgQWxsb3dlZFwiLFxuICAgICAgICA0MDY6IFwiTm90IEFjY2VwdGFibGVcIixcbiAgICAgICAgNDA3OiBcIlByb3h5IEF1dGhlbnRpY2F0aW9uIFJlcXVpcmVkXCIsXG4gICAgICAgIDQwODogXCJSZXF1ZXN0IFRpbWVvdXRcIixcbiAgICAgICAgNDA5OiBcIkNvbmZsaWN0XCIsXG4gICAgICAgIDQxMDogXCJHb25lXCIsXG4gICAgICAgIDQxMTogXCJMZW5ndGggUmVxdWlyZWRcIixcbiAgICAgICAgNDEyOiBcIlByZWNvbmRpdGlvbiBGYWlsZWRcIixcbiAgICAgICAgNDEzOiBcIlJlcXVlc3QgRW50aXR5IFRvbyBMYXJnZVwiLFxuICAgICAgICA0MTQ6IFwiUmVxdWVzdC1VUkkgVG9vIExvbmdcIixcbiAgICAgICAgNDE1OiBcIlVuc3VwcG9ydGVkIE1lZGlhIFR5cGVcIixcbiAgICAgICAgNDE2OiBcIlJlcXVlc3RlZCBSYW5nZSBOb3QgU2F0aXNmaWFibGVcIixcbiAgICAgICAgNDE3OiBcIkV4cGVjdGF0aW9uIEZhaWxlZFwiLFxuICAgICAgICA0MjI6IFwiVW5wcm9jZXNzYWJsZSBFbnRpdHlcIixcbiAgICAgICAgNTAwOiBcIkludGVybmFsIFNlcnZlciBFcnJvclwiLFxuICAgICAgICA1MDE6IFwiTm90IEltcGxlbWVudGVkXCIsXG4gICAgICAgIDUwMjogXCJCYWQgR2F0ZXdheVwiLFxuICAgICAgICA1MDM6IFwiU2VydmljZSBVbmF2YWlsYWJsZVwiLFxuICAgICAgICA1MDQ6IFwiR2F0ZXdheSBUaW1lb3V0XCIsXG4gICAgICAgIDUwNTogXCJIVFRQIFZlcnNpb24gTm90IFN1cHBvcnRlZFwiXG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIG1ha2VBcGkoc2lub24pIHtcbiAgICAgICAgc2lub24ueGhyID0gc2lub25YaHI7XG5cbiAgICAgICAgc2lub24uZXh0ZW5kKEZha2VYTUxIdHRwUmVxdWVzdC5wcm90b3R5cGUsIHNpbm9uLkV2ZW50VGFyZ2V0LCB7XG4gICAgICAgICAgICBhc3luYzogdHJ1ZSxcblxuICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gb3BlbihtZXRob2QsIHVybCwgYXN5bmMsIHVzZXJuYW1lLCBwYXNzd29yZCkge1xuICAgICAgICAgICAgICAgIHRoaXMubWV0aG9kID0gbWV0aG9kO1xuICAgICAgICAgICAgICAgIHRoaXMudXJsID0gdXJsO1xuICAgICAgICAgICAgICAgIHRoaXMuYXN5bmMgPSB0eXBlb2YgYXN5bmMgPT0gXCJib29sZWFuXCIgPyBhc3luYyA6IHRydWU7XG4gICAgICAgICAgICAgICAgdGhpcy51c2VybmFtZSA9IHVzZXJuYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucGFzc3dvcmQgPSBwYXNzd29yZDtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlVGV4dCA9IG51bGw7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZSA9IHRoaXMucmVzcG9uc2VUeXBlID09PSBcImpzb25cIiA/IG51bGwgOiBcIlwiO1xuICAgICAgICAgICAgICAgIHRoaXMucmVzcG9uc2VYTUwgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMucmVxdWVzdEhlYWRlcnMgPSB7fTtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRGbGFnID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoRmFrZVhNTEh0dHBSZXF1ZXN0LnVzZUZpbHRlcnMgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHhockFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkZWZha2UgPSBzb21lKEZha2VYTUxIdHRwUmVxdWVzdC5maWx0ZXJzLCBmdW5jdGlvbiAoZmlsdGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmlsdGVyLmFwcGx5KHRoaXMsIHhockFyZ3MpXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZGVmYWtlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gRmFrZVhNTEh0dHBSZXF1ZXN0LmRlZmFrZSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMucmVhZHlTdGF0ZUNoYW5nZShGYWtlWE1MSHR0cFJlcXVlc3QuT1BFTkVEKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHJlYWR5U3RhdGVDaGFuZ2U6IGZ1bmN0aW9uIHJlYWR5U3RhdGVDaGFuZ2Uoc3RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGUgPSBzdGF0ZTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5vbnJlYWR5c3RhdGVjaGFuZ2UgPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9ucmVhZHlzdGF0ZWNoYW5nZSgpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW5vbi5sb2dFcnJvcihcIkZha2UgWEhSIG9ucmVhZHlzdGF0ZWNoYW5nZSBoYW5kbGVyXCIsIGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnJlYWR5U3RhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBGYWtlWE1MSHR0cFJlcXVlc3QuRE9ORTpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzdXBwb3J0c1Byb2dyZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy51cGxvYWQuZGlzcGF0Y2hFdmVudChuZXcgc2lub24uUHJvZ3Jlc3NFdmVudChcInByb2dyZXNzXCIsIHtsb2FkZWQ6IDEwMCwgdG90YWw6IDEwMH0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IHNpbm9uLlByb2dyZXNzRXZlbnQoXCJwcm9ncmVzc1wiLCB7bG9hZGVkOiAxMDAsIHRvdGFsOiAxMDB9KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnVwbG9hZC5kaXNwYXRjaEV2ZW50KG5ldyBzaW5vbi5FdmVudChcImxvYWRcIiwgZmFsc2UsIGZhbHNlLCB0aGlzKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IHNpbm9uLkV2ZW50KFwibG9hZFwiLCBmYWxzZSwgZmFsc2UsIHRoaXMpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgc2lub24uRXZlbnQoXCJsb2FkZW5kXCIsIGZhbHNlLCBmYWxzZSwgdGhpcykpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBzaW5vbi5FdmVudChcInJlYWR5c3RhdGVjaGFuZ2VcIikpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgc2V0UmVxdWVzdEhlYWRlcjogZnVuY3Rpb24gc2V0UmVxdWVzdEhlYWRlcihoZWFkZXIsIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmVyaWZ5U3RhdGUodGhpcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAodW5zYWZlSGVhZGVyc1toZWFkZXJdIHx8IC9eKFNlYy18UHJveHktKS8udGVzdChoZWFkZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlJlZnVzZWQgdG8gc2V0IHVuc2FmZSBoZWFkZXIgXFxcIlwiICsgaGVhZGVyICsgXCJcXFwiXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlcXVlc3RIZWFkZXJzW2hlYWRlcl0pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXF1ZXN0SGVhZGVyc1toZWFkZXJdICs9IFwiLFwiICsgdmFsdWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXF1ZXN0SGVhZGVyc1toZWFkZXJdID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLy8gSGVscHMgdGVzdGluZ1xuICAgICAgICAgICAgc2V0UmVzcG9uc2VIZWFkZXJzOiBmdW5jdGlvbiBzZXRSZXNwb25zZUhlYWRlcnMoaGVhZGVycykge1xuICAgICAgICAgICAgICAgIHZlcmlmeVJlcXVlc3RPcGVuZWQodGhpcyk7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZUhlYWRlcnMgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGhlYWRlciBpbiBoZWFkZXJzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChoZWFkZXJzLmhhc093blByb3BlcnR5KGhlYWRlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzcG9uc2VIZWFkZXJzW2hlYWRlcl0gPSBoZWFkZXJzW2hlYWRlcl07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5hc3luYykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGVDaGFuZ2UoRmFrZVhNTEh0dHBSZXF1ZXN0LkhFQURFUlNfUkVDRUlWRUQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVhZHlTdGF0ZSA9IEZha2VYTUxIdHRwUmVxdWVzdC5IRUFERVJTX1JFQ0VJVkVEO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8vIEN1cnJlbnRseSB0cmVhdHMgQUxMIGRhdGEgYXMgYSBET01TdHJpbmcgKGkuZS4gbm8gRG9jdW1lbnQpXG4gICAgICAgICAgICBzZW5kOiBmdW5jdGlvbiBzZW5kKGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2ZXJpZnlTdGF0ZSh0aGlzKTtcblxuICAgICAgICAgICAgICAgIGlmICghL14oZ2V0fGhlYWQpJC9pLnRlc3QodGhpcy5tZXRob2QpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb250ZW50VHlwZSA9IGdldEhlYWRlcih0aGlzLnJlcXVlc3RIZWFkZXJzLCBcIkNvbnRlbnQtVHlwZVwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucmVxdWVzdEhlYWRlcnNbY29udGVudFR5cGVdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSB0aGlzLnJlcXVlc3RIZWFkZXJzW2NvbnRlbnRUeXBlXS5zcGxpdChcIjtcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlcXVlc3RIZWFkZXJzW2NvbnRlbnRUeXBlXSA9IHZhbHVlWzBdICsgXCI7Y2hhcnNldD11dGYtOFwiO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHN1cHBvcnRzRm9ybURhdGEgJiYgIShkYXRhIGluc3RhbmNlb2YgRm9ybURhdGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlcXVlc3RIZWFkZXJzW1wiQ29udGVudC1UeXBlXCJdID0gXCJ0ZXh0L3BsYWluO2NoYXJzZXQ9dXRmLThcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVxdWVzdEJvZHkgPSBkYXRhO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JGbGFnID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kRmxhZyA9IHRoaXMuYXN5bmM7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZSA9IHRoaXMucmVzcG9uc2VUeXBlID09PSBcImpzb25cIiA/IG51bGwgOiBcIlwiO1xuICAgICAgICAgICAgICAgIHRoaXMucmVhZHlTdGF0ZUNoYW5nZShGYWtlWE1MSHR0cFJlcXVlc3QuT1BFTkVEKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5vblNlbmQgPT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25TZW5kKHRoaXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgc2lub24uRXZlbnQoXCJsb2Fkc3RhcnRcIiwgZmFsc2UsIGZhbHNlLCB0aGlzKSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBhYm9ydDogZnVuY3Rpb24gYWJvcnQoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5hYm9ydGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlVGV4dCA9IG51bGw7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZSA9IHRoaXMucmVzcG9uc2VUeXBlID09PSBcImpzb25cIiA/IG51bGwgOiBcIlwiO1xuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JGbGFnID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlcXVlc3RIZWFkZXJzID0ge307XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNwb25zZUhlYWRlcnMgPSB7fTtcblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlYWR5U3RhdGUgPiBGYWtlWE1MSHR0cFJlcXVlc3QuVU5TRU5UICYmIHRoaXMuc2VuZEZsYWcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWFkeVN0YXRlQ2hhbmdlKEZha2VYTUxIdHRwUmVxdWVzdC5ET05FKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZW5kRmxhZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMucmVhZHlTdGF0ZSA9IEZha2VYTUxIdHRwUmVxdWVzdC5VTlNFTlQ7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IHNpbm9uLkV2ZW50KFwiYWJvcnRcIiwgZmFsc2UsIGZhbHNlLCB0aGlzKSk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLnVwbG9hZC5kaXNwYXRjaEV2ZW50KG5ldyBzaW5vbi5FdmVudChcImFib3J0XCIsIGZhbHNlLCBmYWxzZSwgdGhpcykpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLm9uZXJyb3IgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uZXJyb3IoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBnZXRSZXNwb25zZUhlYWRlcjogZnVuY3Rpb24gZ2V0UmVzcG9uc2VIZWFkZXIoaGVhZGVyKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucmVhZHlTdGF0ZSA8IEZha2VYTUxIdHRwUmVxdWVzdC5IRUFERVJTX1JFQ0VJVkVEKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICgvXlNldC1Db29raWUyPyQvaS50ZXN0KGhlYWRlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaGVhZGVyID0gZ2V0SGVhZGVyKHRoaXMucmVzcG9uc2VIZWFkZXJzLCBoZWFkZXIpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVzcG9uc2VIZWFkZXJzW2hlYWRlcl0gfHwgbnVsbDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIGdldEFsbFJlc3BvbnNlSGVhZGVyczogZnVuY3Rpb24gZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlYWR5U3RhdGUgPCBGYWtlWE1MSHR0cFJlcXVlc3QuSEVBREVSU19SRUNFSVZFRCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaGVhZGVycyA9IFwiXCI7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBoZWFkZXIgaW4gdGhpcy5yZXNwb25zZUhlYWRlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMucmVzcG9uc2VIZWFkZXJzLmhhc093blByb3BlcnR5KGhlYWRlcikgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICEvXlNldC1Db29raWUyPyQvaS50ZXN0KGhlYWRlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhlYWRlcnMgKz0gaGVhZGVyICsgXCI6IFwiICsgdGhpcy5yZXNwb25zZUhlYWRlcnNbaGVhZGVyXSArIFwiXFxyXFxuXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGVhZGVycztcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHNldFJlc3BvbnNlQm9keTogZnVuY3Rpb24gc2V0UmVzcG9uc2VCb2R5KGJvZHkpIHtcbiAgICAgICAgICAgICAgICB2ZXJpZnlSZXF1ZXN0U2VudCh0aGlzKTtcbiAgICAgICAgICAgICAgICB2ZXJpZnlIZWFkZXJzUmVjZWl2ZWQodGhpcyk7XG4gICAgICAgICAgICAgICAgdmVyaWZ5UmVzcG9uc2VCb2R5VHlwZShib2R5KTtcblxuICAgICAgICAgICAgICAgIHZhciBjaHVua1NpemUgPSB0aGlzLmNodW5rU2l6ZSB8fCAxMDtcbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHRoaXMucmVzcG9uc2VUZXh0ID0gXCJcIjtcblxuICAgICAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuYXN5bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVhZHlTdGF0ZUNoYW5nZShGYWtlWE1MSHR0cFJlcXVlc3QuTE9BRElORyk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlVGV4dCArPSBib2R5LnN1YnN0cmluZyhpbmRleCwgaW5kZXggKyBjaHVua1NpemUpO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaHVua1NpemU7XG4gICAgICAgICAgICAgICAgfSB3aGlsZSAoaW5kZXggPCBib2R5Lmxlbmd0aCk7XG5cbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHRoaXMuZ2V0UmVzcG9uc2VIZWFkZXIoXCJDb250ZW50LVR5cGVcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yZXNwb25zZVRleHQgJiZcbiAgICAgICAgICAgICAgICAgICAgKCF0eXBlIHx8IC8odGV4dFxcL3htbCl8KGFwcGxpY2F0aW9uXFwveG1sKXwoXFwreG1sKS8udGVzdCh0eXBlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVzcG9uc2VYTUwgPSBGYWtlWE1MSHR0cFJlcXVlc3QucGFyc2VYTUwodGhpcy5yZXNwb25zZVRleHQpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBVbmFibGUgdG8gcGFyc2UgWE1MIC0gbm8gYmlnZ2llXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnJlc3BvbnNlID0gdGhpcy5yZXNwb25zZVR5cGUgPT09IFwianNvblwiID8gSlNPTi5wYXJzZSh0aGlzLnJlc3BvbnNlVGV4dCkgOiB0aGlzLnJlc3BvbnNlVGV4dDtcbiAgICAgICAgICAgICAgICB0aGlzLnJlYWR5U3RhdGVDaGFuZ2UoRmFrZVhNTEh0dHBSZXF1ZXN0LkRPTkUpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgcmVzcG9uZDogZnVuY3Rpb24gcmVzcG9uZChzdGF0dXMsIGhlYWRlcnMsIGJvZHkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXR1cyA9IHR5cGVvZiBzdGF0dXMgPT0gXCJudW1iZXJcIiA/IHN0YXR1cyA6IDIwMDtcbiAgICAgICAgICAgICAgICB0aGlzLnN0YXR1c1RleHQgPSBGYWtlWE1MSHR0cFJlcXVlc3Quc3RhdHVzQ29kZXNbdGhpcy5zdGF0dXNdO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0UmVzcG9uc2VIZWFkZXJzKGhlYWRlcnMgfHwge30pO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0UmVzcG9uc2VCb2R5KGJvZHkgfHwgXCJcIik7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICB1cGxvYWRQcm9ncmVzczogZnVuY3Rpb24gdXBsb2FkUHJvZ3Jlc3MocHJvZ3Jlc3NFdmVudFJhdykge1xuICAgICAgICAgICAgICAgIGlmIChzdXBwb3J0c1Byb2dyZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudXBsb2FkLmRpc3BhdGNoRXZlbnQobmV3IHNpbm9uLlByb2dyZXNzRXZlbnQoXCJwcm9ncmVzc1wiLCBwcm9ncmVzc0V2ZW50UmF3KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgZG93bmxvYWRQcm9ncmVzczogZnVuY3Rpb24gZG93bmxvYWRQcm9ncmVzcyhwcm9ncmVzc0V2ZW50UmF3KSB7XG4gICAgICAgICAgICAgICAgaWYgKHN1cHBvcnRzUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBzaW5vbi5Qcm9ncmVzc0V2ZW50KFwicHJvZ3Jlc3NcIiwgcHJvZ3Jlc3NFdmVudFJhdykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIHVwbG9hZEVycm9yOiBmdW5jdGlvbiB1cGxvYWRFcnJvcihlcnJvcikge1xuICAgICAgICAgICAgICAgIGlmIChzdXBwb3J0c0N1c3RvbUV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudXBsb2FkLmRpc3BhdGNoRXZlbnQobmV3IHNpbm9uLkN1c3RvbUV2ZW50KFwiZXJyb3JcIiwge2RldGFpbDogZXJyb3J9KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBzaW5vbi5leHRlbmQoRmFrZVhNTEh0dHBSZXF1ZXN0LCB7XG4gICAgICAgICAgICBVTlNFTlQ6IDAsXG4gICAgICAgICAgICBPUEVORUQ6IDEsXG4gICAgICAgICAgICBIRUFERVJTX1JFQ0VJVkVEOiAyLFxuICAgICAgICAgICAgTE9BRElORzogMyxcbiAgICAgICAgICAgIERPTkU6IDRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgc2lub24udXNlRmFrZVhNTEh0dHBSZXF1ZXN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgRmFrZVhNTEh0dHBSZXF1ZXN0LnJlc3RvcmUgPSBmdW5jdGlvbiByZXN0b3JlKGtlZXBPbkNyZWF0ZSkge1xuICAgICAgICAgICAgICAgIGlmIChzaW5vblhoci5zdXBwb3J0c1hIUikge1xuICAgICAgICAgICAgICAgICAgICBnbG9iYWwuWE1MSHR0cFJlcXVlc3QgPSBzaW5vblhoci5HbG9iYWxYTUxIdHRwUmVxdWVzdDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoc2lub25YaHIuc3VwcG9ydHNBY3RpdmVYKSB7XG4gICAgICAgICAgICAgICAgICAgIGdsb2JhbC5BY3RpdmVYT2JqZWN0ID0gc2lub25YaHIuR2xvYmFsQWN0aXZlWE9iamVjdDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkZWxldGUgRmFrZVhNTEh0dHBSZXF1ZXN0LnJlc3RvcmU7XG5cbiAgICAgICAgICAgICAgICBpZiAoa2VlcE9uQ3JlYXRlICE9PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBGYWtlWE1MSHR0cFJlcXVlc3Qub25DcmVhdGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChzaW5vblhoci5zdXBwb3J0c1hIUikge1xuICAgICAgICAgICAgICAgIGdsb2JhbC5YTUxIdHRwUmVxdWVzdCA9IEZha2VYTUxIdHRwUmVxdWVzdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHNpbm9uWGhyLnN1cHBvcnRzQWN0aXZlWCkge1xuICAgICAgICAgICAgICAgIGdsb2JhbC5BY3RpdmVYT2JqZWN0ID0gZnVuY3Rpb24gQWN0aXZlWE9iamVjdChvYmpJZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAob2JqSWQgPT0gXCJNaWNyb3NvZnQuWE1MSFRUUFwiIHx8IC9eTXN4bWwyXFwuWE1MSFRUUC9pLnRlc3Qob2JqSWQpKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRmFrZVhNTEh0dHBSZXF1ZXN0KCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IHNpbm9uWGhyLkdsb2JhbEFjdGl2ZVhPYmplY3Qob2JqSWQpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBGYWtlWE1MSHR0cFJlcXVlc3Q7XG4gICAgICAgIH07XG5cbiAgICAgICAgc2lub24uRmFrZVhNTEh0dHBSZXF1ZXN0ID0gRmFrZVhNTEh0dHBSZXF1ZXN0O1xuICAgIH1cblxuICAgIHZhciBpc05vZGUgPSB0eXBlb2YgbW9kdWxlICE9PSBcInVuZGVmaW5lZFwiICYmIG1vZHVsZS5leHBvcnRzICYmIHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIjtcbiAgICB2YXIgaXNBTUQgPSB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIGRlZmluZS5hbWQgPT09IFwib2JqZWN0XCIgJiYgZGVmaW5lLmFtZDtcblxuICAgIGZ1bmN0aW9uIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlKSB7XG4gICAgICAgIHZhciBzaW5vbiA9IHJlcXVpcmUoXCIuL2NvcmVcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuLi9leHRlbmRcIik7XG4gICAgICAgIHJlcXVpcmUoXCIuL2V2ZW50XCIpO1xuICAgICAgICByZXF1aXJlKFwiLi4vbG9nX2Vycm9yXCIpO1xuICAgICAgICBtYWtlQXBpKHNpbm9uKTtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBzaW5vbjtcbiAgICB9XG5cbiAgICBpZiAoaXNBTUQpIHtcbiAgICAgICAgZGVmaW5lKGxvYWREZXBlbmRlbmNpZXMpO1xuICAgIH0gZWxzZSBpZiAoaXNOb2RlKSB7XG4gICAgICAgIGxvYWREZXBlbmRlbmNpZXMocmVxdWlyZSwgbW9kdWxlLmV4cG9ydHMsIG1vZHVsZSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2Ygc2lub24gPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIG1ha2VBcGkoc2lub24pO1xuICAgIH1cblxufSkodHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHNlbGYpO1xuXG59KS5jYWxsKHRoaXMsdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KSIsIihmdW5jdGlvbiAoZ2xvYmFsKXtcbigodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQgJiYgZnVuY3Rpb24gKG0pIHtcbiAgICBkZWZpbmUoXCJmb3JtYXRpb1wiLCBbXCJzYW1zYW1cIl0sIG0pO1xufSkgfHwgKHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgZnVuY3Rpb24gKG0pIHtcbiAgICBtb2R1bGUuZXhwb3J0cyA9IG0ocmVxdWlyZShcInNhbXNhbVwiKSk7XG59KSB8fCBmdW5jdGlvbiAobSkgeyB0aGlzLmZvcm1hdGlvID0gbSh0aGlzLnNhbXNhbSk7IH1cbikoZnVuY3Rpb24gKHNhbXNhbSkge1xuICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgdmFyIGZvcm1hdGlvID0ge1xuICAgICAgICBleGNsdWRlQ29uc3RydWN0b3JzOiBbXCJPYmplY3RcIiwgL14uJC9dLFxuICAgICAgICBxdW90ZVN0cmluZ3M6IHRydWUsXG4gICAgICAgIGxpbWl0Q2hpbGRyZW5Db3VudDogMFxuICAgIH07XG5cbiAgICB2YXIgaGFzT3duID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcblxuICAgIHZhciBzcGVjaWFsT2JqZWN0cyA9IFtdO1xuICAgIGlmICh0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIHNwZWNpYWxPYmplY3RzLnB1c2goeyBvYmplY3Q6IGdsb2JhbCwgdmFsdWU6IFwiW29iamVjdCBnbG9iYWxdXCIgfSk7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgc3BlY2lhbE9iamVjdHMucHVzaCh7XG4gICAgICAgICAgICBvYmplY3Q6IGRvY3VtZW50LFxuICAgICAgICAgICAgdmFsdWU6IFwiW29iamVjdCBIVE1MRG9jdW1lbnRdXCJcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIHNwZWNpYWxPYmplY3RzLnB1c2goeyBvYmplY3Q6IHdpbmRvdywgdmFsdWU6IFwiW29iamVjdCBXaW5kb3ddXCIgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZnVuY3Rpb25OYW1lKGZ1bmMpIHtcbiAgICAgICAgaWYgKCFmdW5jKSB7IHJldHVybiBcIlwiOyB9XG4gICAgICAgIGlmIChmdW5jLmRpc3BsYXlOYW1lKSB7IHJldHVybiBmdW5jLmRpc3BsYXlOYW1lOyB9XG4gICAgICAgIGlmIChmdW5jLm5hbWUpIHsgcmV0dXJuIGZ1bmMubmFtZTsgfVxuICAgICAgICB2YXIgbWF0Y2hlcyA9IGZ1bmMudG9TdHJpbmcoKS5tYXRjaCgvZnVuY3Rpb25cXHMrKFteXFwoXSspL20pO1xuICAgICAgICByZXR1cm4gKG1hdGNoZXMgJiYgbWF0Y2hlc1sxXSkgfHwgXCJcIjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb25zdHJ1Y3Rvck5hbWUoZiwgb2JqZWN0KSB7XG4gICAgICAgIHZhciBuYW1lID0gZnVuY3Rpb25OYW1lKG9iamVjdCAmJiBvYmplY3QuY29uc3RydWN0b3IpO1xuICAgICAgICB2YXIgZXhjbHVkZXMgPSBmLmV4Y2x1ZGVDb25zdHJ1Y3RvcnMgfHxcbiAgICAgICAgICAgICAgICBmb3JtYXRpby5leGNsdWRlQ29uc3RydWN0b3JzIHx8IFtdO1xuXG4gICAgICAgIHZhciBpLCBsO1xuICAgICAgICBmb3IgKGkgPSAwLCBsID0gZXhjbHVkZXMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGV4Y2x1ZGVzW2ldID09PSBcInN0cmluZ1wiICYmIGV4Y2x1ZGVzW2ldID09PSBuYW1lKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFwiXCI7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGV4Y2x1ZGVzW2ldLnRlc3QgJiYgZXhjbHVkZXNbaV0udGVzdChuYW1lKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBcIlwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNDaXJjdWxhcihvYmplY3QsIG9iamVjdHMpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QgIT09IFwib2JqZWN0XCIpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgICAgIHZhciBpLCBsO1xuICAgICAgICBmb3IgKGkgPSAwLCBsID0gb2JqZWN0cy5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgIGlmIChvYmplY3RzW2ldID09PSBvYmplY3QpIHsgcmV0dXJuIHRydWU7IH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYXNjaWkoZiwgb2JqZWN0LCBwcm9jZXNzZWQsIGluZGVudCkge1xuICAgICAgICBpZiAodHlwZW9mIG9iamVjdCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgdmFyIHFzID0gZi5xdW90ZVN0cmluZ3M7XG4gICAgICAgICAgICB2YXIgcXVvdGUgPSB0eXBlb2YgcXMgIT09IFwiYm9vbGVhblwiIHx8IHFzO1xuICAgICAgICAgICAgcmV0dXJuIHByb2Nlc3NlZCB8fCBxdW90ZSA/ICdcIicgKyBvYmplY3QgKyAnXCInIDogb2JqZWN0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QgPT09IFwiZnVuY3Rpb25cIiAmJiAhKG9iamVjdCBpbnN0YW5jZW9mIFJlZ0V4cCkpIHtcbiAgICAgICAgICAgIHJldHVybiBhc2NpaS5mdW5jKG9iamVjdCk7XG4gICAgICAgIH1cblxuICAgICAgICBwcm9jZXNzZWQgPSBwcm9jZXNzZWQgfHwgW107XG5cbiAgICAgICAgaWYgKGlzQ2lyY3VsYXIob2JqZWN0LCBwcm9jZXNzZWQpKSB7IHJldHVybiBcIltDaXJjdWxhcl1cIjsgfVxuXG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqZWN0KSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiKSB7XG4gICAgICAgICAgICByZXR1cm4gYXNjaWkuYXJyYXkuY2FsbChmLCBvYmplY3QsIHByb2Nlc3NlZCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIW9iamVjdCkgeyByZXR1cm4gU3RyaW5nKCgxL29iamVjdCkgPT09IC1JbmZpbml0eSA/IFwiLTBcIiA6IG9iamVjdCk7IH1cbiAgICAgICAgaWYgKHNhbXNhbS5pc0VsZW1lbnQob2JqZWN0KSkgeyByZXR1cm4gYXNjaWkuZWxlbWVudChvYmplY3QpOyB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QudG9TdHJpbmcgPT09IFwiZnVuY3Rpb25cIiAmJlxuICAgICAgICAgICAgICAgIG9iamVjdC50b1N0cmluZyAhPT0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdC50b1N0cmluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGksIGw7XG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBzcGVjaWFsT2JqZWN0cy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgIGlmIChvYmplY3QgPT09IHNwZWNpYWxPYmplY3RzW2ldLm9iamVjdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBzcGVjaWFsT2JqZWN0c1tpXS52YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhc2NpaS5vYmplY3QuY2FsbChmLCBvYmplY3QsIHByb2Nlc3NlZCwgaW5kZW50KTtcbiAgICB9XG5cbiAgICBhc2NpaS5mdW5jID0gZnVuY3Rpb24gKGZ1bmMpIHtcbiAgICAgICAgcmV0dXJuIFwiZnVuY3Rpb24gXCIgKyBmdW5jdGlvbk5hbWUoZnVuYykgKyBcIigpIHt9XCI7XG4gICAgfTtcblxuICAgIGFzY2lpLmFycmF5ID0gZnVuY3Rpb24gKGFycmF5LCBwcm9jZXNzZWQpIHtcbiAgICAgICAgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkIHx8IFtdO1xuICAgICAgICBwcm9jZXNzZWQucHVzaChhcnJheSk7XG4gICAgICAgIHZhciBwaWVjZXMgPSBbXTtcbiAgICAgICAgdmFyIGksIGw7XG4gICAgICAgIGwgPSAodGhpcy5saW1pdENoaWxkcmVuQ291bnQgPiAwKSA/IFxuICAgICAgICAgICAgTWF0aC5taW4odGhpcy5saW1pdENoaWxkcmVuQ291bnQsIGFycmF5Lmxlbmd0aCkgOiBhcnJheS5sZW5ndGg7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgcGllY2VzLnB1c2goYXNjaWkodGhpcywgYXJyYXlbaV0sIHByb2Nlc3NlZCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYobCA8IGFycmF5Lmxlbmd0aClcbiAgICAgICAgICAgIHBpZWNlcy5wdXNoKFwiWy4uLiBcIiArIChhcnJheS5sZW5ndGggLSBsKSArIFwiIG1vcmUgZWxlbWVudHNdXCIpO1xuXG4gICAgICAgIHJldHVybiBcIltcIiArIHBpZWNlcy5qb2luKFwiLCBcIikgKyBcIl1cIjtcbiAgICB9O1xuXG4gICAgYXNjaWkub2JqZWN0ID0gZnVuY3Rpb24gKG9iamVjdCwgcHJvY2Vzc2VkLCBpbmRlbnQpIHtcbiAgICAgICAgcHJvY2Vzc2VkID0gcHJvY2Vzc2VkIHx8IFtdO1xuICAgICAgICBwcm9jZXNzZWQucHVzaChvYmplY3QpO1xuICAgICAgICBpbmRlbnQgPSBpbmRlbnQgfHwgMDtcbiAgICAgICAgdmFyIHBpZWNlcyA9IFtdLCBwcm9wZXJ0aWVzID0gc2Ftc2FtLmtleXMob2JqZWN0KS5zb3J0KCk7XG4gICAgICAgIHZhciBsZW5ndGggPSAzO1xuICAgICAgICB2YXIgcHJvcCwgc3RyLCBvYmosIGksIGssIGw7XG4gICAgICAgIGwgPSAodGhpcy5saW1pdENoaWxkcmVuQ291bnQgPiAwKSA/IFxuICAgICAgICAgICAgTWF0aC5taW4odGhpcy5saW1pdENoaWxkcmVuQ291bnQsIHByb3BlcnRpZXMubGVuZ3RoKSA6IHByb3BlcnRpZXMubGVuZ3RoO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgIHByb3AgPSBwcm9wZXJ0aWVzW2ldO1xuICAgICAgICAgICAgb2JqID0gb2JqZWN0W3Byb3BdO1xuXG4gICAgICAgICAgICBpZiAoaXNDaXJjdWxhcihvYmosIHByb2Nlc3NlZCkpIHtcbiAgICAgICAgICAgICAgICBzdHIgPSBcIltDaXJjdWxhcl1cIjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc3RyID0gYXNjaWkodGhpcywgb2JqLCBwcm9jZXNzZWQsIGluZGVudCArIDIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzdHIgPSAoL1xccy8udGVzdChwcm9wKSA/ICdcIicgKyBwcm9wICsgJ1wiJyA6IHByb3ApICsgXCI6IFwiICsgc3RyO1xuICAgICAgICAgICAgbGVuZ3RoICs9IHN0ci5sZW5ndGg7XG4gICAgICAgICAgICBwaWVjZXMucHVzaChzdHIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNvbnMgPSBjb25zdHJ1Y3Rvck5hbWUodGhpcywgb2JqZWN0KTtcbiAgICAgICAgdmFyIHByZWZpeCA9IGNvbnMgPyBcIltcIiArIGNvbnMgKyBcIl0gXCIgOiBcIlwiO1xuICAgICAgICB2YXIgaXMgPSBcIlwiO1xuICAgICAgICBmb3IgKGkgPSAwLCBrID0gaW5kZW50OyBpIDwgazsgKytpKSB7IGlzICs9IFwiIFwiOyB9XG5cbiAgICAgICAgaWYobCA8IHByb3BlcnRpZXMubGVuZ3RoKVxuICAgICAgICAgICAgcGllY2VzLnB1c2goXCJbLi4uIFwiICsgKHByb3BlcnRpZXMubGVuZ3RoIC0gbCkgKyBcIiBtb3JlIGVsZW1lbnRzXVwiKTtcblxuICAgICAgICBpZiAobGVuZ3RoICsgaW5kZW50ID4gODApIHtcbiAgICAgICAgICAgIHJldHVybiBwcmVmaXggKyBcIntcXG4gIFwiICsgaXMgKyBwaWVjZXMuam9pbihcIixcXG4gIFwiICsgaXMpICsgXCJcXG5cIiArXG4gICAgICAgICAgICAgICAgaXMgKyBcIn1cIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcHJlZml4ICsgXCJ7IFwiICsgcGllY2VzLmpvaW4oXCIsIFwiKSArIFwiIH1cIjtcbiAgICB9O1xuXG4gICAgYXNjaWkuZWxlbWVudCA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgICAgIHZhciB0YWdOYW1lID0gZWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgIHZhciBhdHRycyA9IGVsZW1lbnQuYXR0cmlidXRlcywgYXR0ciwgcGFpcnMgPSBbXSwgYXR0ck5hbWUsIGksIGwsIHZhbDtcblxuICAgICAgICBmb3IgKGkgPSAwLCBsID0gYXR0cnMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICBhdHRyID0gYXR0cnMuaXRlbShpKTtcbiAgICAgICAgICAgIGF0dHJOYW1lID0gYXR0ci5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoXCJodG1sOlwiLCBcIlwiKTtcbiAgICAgICAgICAgIHZhbCA9IGF0dHIubm9kZVZhbHVlO1xuICAgICAgICAgICAgaWYgKGF0dHJOYW1lICE9PSBcImNvbnRlbnRlZGl0YWJsZVwiIHx8IHZhbCAhPT0gXCJpbmhlcml0XCIpIHtcbiAgICAgICAgICAgICAgICBpZiAoISF2YWwpIHsgcGFpcnMucHVzaChhdHRyTmFtZSArIFwiPVxcXCJcIiArIHZhbCArIFwiXFxcIlwiKTsgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGZvcm1hdHRlZCA9IFwiPFwiICsgdGFnTmFtZSArIChwYWlycy5sZW5ndGggPiAwID8gXCIgXCIgOiBcIlwiKTtcbiAgICAgICAgdmFyIGNvbnRlbnQgPSBlbGVtZW50LmlubmVySFRNTDtcblxuICAgICAgICBpZiAoY29udGVudC5sZW5ndGggPiAyMCkge1xuICAgICAgICAgICAgY29udGVudCA9IGNvbnRlbnQuc3Vic3RyKDAsIDIwKSArIFwiWy4uLl1cIjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciByZXMgPSBmb3JtYXR0ZWQgKyBwYWlycy5qb2luKFwiIFwiKSArIFwiPlwiICsgY29udGVudCArXG4gICAgICAgICAgICAgICAgXCI8L1wiICsgdGFnTmFtZSArIFwiPlwiO1xuXG4gICAgICAgIHJldHVybiByZXMucmVwbGFjZSgvIGNvbnRlbnRFZGl0YWJsZT1cImluaGVyaXRcIi8sIFwiXCIpO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBGb3JtYXRpbyhvcHRpb25zKSB7XG4gICAgICAgIGZvciAodmFyIG9wdCBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICB0aGlzW29wdF0gPSBvcHRpb25zW29wdF07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBGb3JtYXRpby5wcm90b3R5cGUgPSB7XG4gICAgICAgIGZ1bmN0aW9uTmFtZTogZnVuY3Rpb25OYW1lLFxuXG4gICAgICAgIGNvbmZpZ3VyZTogZnVuY3Rpb24gKG9wdGlvbnMpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRm9ybWF0aW8ob3B0aW9ucyk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgY29uc3RydWN0b3JOYW1lOiBmdW5jdGlvbiAob2JqZWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gY29uc3RydWN0b3JOYW1lKHRoaXMsIG9iamVjdCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgYXNjaWk6IGZ1bmN0aW9uIChvYmplY3QsIHByb2Nlc3NlZCwgaW5kZW50KSB7XG4gICAgICAgICAgICByZXR1cm4gYXNjaWkodGhpcywgb2JqZWN0LCBwcm9jZXNzZWQsIGluZGVudCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIEZvcm1hdGlvLnByb3RvdHlwZTtcbn0pO1xuXG59KS5jYWxsKHRoaXMsdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KSIsIihmdW5jdGlvbiAoZ2xvYmFsKXtcbi8qanNsaW50IGVxZXFlcTogZmFsc2UsIHBsdXNwbHVzOiBmYWxzZSwgZXZpbDogdHJ1ZSwgb25ldmFyOiBmYWxzZSwgYnJvd3NlcjogdHJ1ZSwgZm9yaW46IGZhbHNlKi9cbi8qZ2xvYmFsIGdsb2JhbCovXG4vKipcbiAqIEBhdXRob3IgQ2hyaXN0aWFuIEpvaGFuc2VuIChjaHJpc3RpYW5AY2pvaGFuc2VuLm5vKSBhbmQgY29udHJpYnV0b3JzXG4gKiBAbGljZW5zZSBCU0RcbiAqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTAtMjAxNCBDaHJpc3RpYW4gSm9oYW5zZW5cbiAqL1xuXCJ1c2Ugc3RyaWN0XCI7XG5cbi8vIG5vZGUgZXhwZWN0cyBzZXRUaW1lb3V0L3NldEludGVydmFsIHRvIHJldHVybiBhIGZuIG9iamVjdCB3LyAucmVmKCkvLnVucmVmKClcbi8vIGJyb3dzZXJzLCBhIG51bWJlci5cbi8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vY2pvaGFuc2VuL1Npbm9uLkpTL3B1bGwvNDM2XG52YXIgdGltZW91dFJlc3VsdCA9IHNldFRpbWVvdXQoZnVuY3Rpb24oKSB7fSwgMCk7XG52YXIgYWRkVGltZXJSZXR1cm5zT2JqZWN0ID0gdHlwZW9mIHRpbWVvdXRSZXN1bHQgPT09IFwib2JqZWN0XCI7XG5jbGVhclRpbWVvdXQodGltZW91dFJlc3VsdCk7XG5cbnZhciBOYXRpdmVEYXRlID0gRGF0ZTtcbnZhciBpZCA9IDE7XG5cbi8qKlxuICogUGFyc2Ugc3RyaW5ncyBsaWtlIFwiMDE6MTA6MDBcIiAobWVhbmluZyAxIGhvdXIsIDEwIG1pbnV0ZXMsIDAgc2Vjb25kcykgaW50b1xuICogbnVtYmVyIG9mIG1pbGxpc2Vjb25kcy4gVGhpcyBpcyB1c2VkIHRvIHN1cHBvcnQgaHVtYW4tcmVhZGFibGUgc3RyaW5ncyBwYXNzZWRcbiAqIHRvIGNsb2NrLnRpY2soKVxuICovXG5mdW5jdGlvbiBwYXJzZVRpbWUoc3RyKSB7XG4gICAgaWYgKCFzdHIpIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgdmFyIHN0cmluZ3MgPSBzdHIuc3BsaXQoXCI6XCIpO1xuICAgIHZhciBsID0gc3RyaW5ncy5sZW5ndGgsIGkgPSBsO1xuICAgIHZhciBtcyA9IDAsIHBhcnNlZDtcblxuICAgIGlmIChsID4gMyB8fCAhL14oXFxkXFxkOil7MCwyfVxcZFxcZD8kLy50ZXN0KHN0cikpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGljayBvbmx5IHVuZGVyc3RhbmRzIG51bWJlcnMgYW5kICdoOm06cydcIik7XG4gICAgfVxuXG4gICAgd2hpbGUgKGktLSkge1xuICAgICAgICBwYXJzZWQgPSBwYXJzZUludChzdHJpbmdzW2ldLCAxMCk7XG5cbiAgICAgICAgaWYgKHBhcnNlZCA+PSA2MCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCB0aW1lIFwiICsgc3RyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG1zICs9IHBhcnNlZCAqIE1hdGgucG93KDYwLCAobCAtIGkgLSAxKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1zICogMTAwMDtcbn1cblxuLyoqXG4gKiBVc2VkIHRvIGdyb2sgdGhlIGBub3dgIHBhcmFtZXRlciB0byBjcmVhdGVDbG9jay5cbiAqL1xuZnVuY3Rpb24gZ2V0RXBvY2goZXBvY2gpIHtcbiAgICBpZiAoIWVwb2NoKSB7IHJldHVybiAwOyB9XG4gICAgaWYgKHR5cGVvZiBlcG9jaC5nZXRUaW1lID09PSBcImZ1bmN0aW9uXCIpIHsgcmV0dXJuIGVwb2NoLmdldFRpbWUoKTsgfVxuICAgIGlmICh0eXBlb2YgZXBvY2ggPT09IFwibnVtYmVyXCIpIHsgcmV0dXJuIGVwb2NoOyB9XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIm5vdyBzaG91bGQgYmUgbWlsbGlzZWNvbmRzIHNpbmNlIFVOSVggZXBvY2hcIik7XG59XG5cbmZ1bmN0aW9uIGluUmFuZ2UoZnJvbSwgdG8sIHRpbWVyKSB7XG4gICAgcmV0dXJuIHRpbWVyICYmIHRpbWVyLmNhbGxBdCA+PSBmcm9tICYmIHRpbWVyLmNhbGxBdCA8PSB0bztcbn1cblxuZnVuY3Rpb24gbWlycm9yRGF0ZVByb3BlcnRpZXModGFyZ2V0LCBzb3VyY2UpIHtcbiAgICBpZiAoc291cmNlLm5vdykge1xuICAgICAgICB0YXJnZXQubm93ID0gZnVuY3Rpb24gbm93KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRhcmdldC5jbG9jay5ub3c7XG4gICAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZGVsZXRlIHRhcmdldC5ub3c7XG4gICAgfVxuXG4gICAgaWYgKHNvdXJjZS50b1NvdXJjZSkge1xuICAgICAgICB0YXJnZXQudG9Tb3VyY2UgPSBmdW5jdGlvbiB0b1NvdXJjZSgpIHtcbiAgICAgICAgICAgIHJldHVybiBzb3VyY2UudG9Tb3VyY2UoKTtcbiAgICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBkZWxldGUgdGFyZ2V0LnRvU291cmNlO1xuICAgIH1cblxuICAgIHRhcmdldC50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gc291cmNlLnRvU3RyaW5nKCk7XG4gICAgfTtcblxuICAgIHRhcmdldC5wcm90b3R5cGUgPSBzb3VyY2UucHJvdG90eXBlO1xuICAgIHRhcmdldC5wYXJzZSA9IHNvdXJjZS5wYXJzZTtcbiAgICB0YXJnZXQuVVRDID0gc291cmNlLlVUQztcbiAgICB0YXJnZXQucHJvdG90eXBlLnRvVVRDU3RyaW5nID0gc291cmNlLnByb3RvdHlwZS50b1VUQ1N0cmluZztcblxuICAgIGZvciAodmFyIHByb3AgaW4gc291cmNlKSB7XG4gICAgICAgIGlmIChzb3VyY2UuaGFzT3duUHJvcGVydHkocHJvcCkpIHtcbiAgICAgICAgICAgIHRhcmdldFtwcm9wXSA9IHNvdXJjZVtwcm9wXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0YXJnZXQ7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZURhdGUoKSB7XG4gICAgZnVuY3Rpb24gQ2xvY2tEYXRlKHllYXIsIG1vbnRoLCBkYXRlLCBob3VyLCBtaW51dGUsIHNlY29uZCwgbXMpIHtcbiAgICAgICAgLy8gRGVmZW5zaXZlIGFuZCB2ZXJib3NlIHRvIGF2b2lkIHBvdGVudGlhbCBoYXJtIGluIHBhc3NpbmdcbiAgICAgICAgLy8gZXhwbGljaXQgdW5kZWZpbmVkIHdoZW4gdXNlciBkb2VzIG5vdCBwYXNzIGFyZ3VtZW50XG4gICAgICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICByZXR1cm4gbmV3IE5hdGl2ZURhdGUoQ2xvY2tEYXRlLmNsb2NrLm5vdyk7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIHJldHVybiBuZXcgTmF0aXZlRGF0ZSh5ZWFyKTtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKHllYXIsIG1vbnRoKTtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKHllYXIsIG1vbnRoLCBkYXRlKTtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKHllYXIsIG1vbnRoLCBkYXRlLCBob3VyKTtcbiAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgcmV0dXJuIG5ldyBOYXRpdmVEYXRlKHllYXIsIG1vbnRoLCBkYXRlLCBob3VyLCBtaW51dGUpO1xuICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICByZXR1cm4gbmV3IE5hdGl2ZURhdGUoeWVhciwgbW9udGgsIGRhdGUsIGhvdXIsIG1pbnV0ZSwgc2Vjb25kKTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBuZXcgTmF0aXZlRGF0ZSh5ZWFyLCBtb250aCwgZGF0ZSwgaG91ciwgbWludXRlLCBzZWNvbmQsIG1zKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBtaXJyb3JEYXRlUHJvcGVydGllcyhDbG9ja0RhdGUsIE5hdGl2ZURhdGUpO1xufVxuXG5mdW5jdGlvbiBhZGRUaW1lcihjbG9jaywgdGltZXIpIHtcbiAgICBpZiAodHlwZW9mIHRpbWVyLmZ1bmMgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FsbGJhY2sgbXVzdCBiZSBwcm92aWRlZCB0byB0aW1lciBjYWxsc1wiKTtcbiAgICB9XG5cbiAgICBpZiAoIWNsb2NrLnRpbWVycykge1xuICAgICAgICBjbG9jay50aW1lcnMgPSB7fTtcbiAgICB9XG5cbiAgICB0aW1lci5pZCA9IGlkKys7XG4gICAgdGltZXIuY3JlYXRlZEF0ID0gY2xvY2subm93O1xuICAgIHRpbWVyLmNhbGxBdCA9IGNsb2NrLm5vdyArICh0aW1lci5kZWxheSB8fCAwKTtcblxuICAgIGNsb2NrLnRpbWVyc1t0aW1lci5pZF0gPSB0aW1lcjtcblxuICAgIGlmIChhZGRUaW1lclJldHVybnNPYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGlkOiB0aW1lci5pZCxcbiAgICAgICAgICAgIHJlZjogZnVuY3Rpb24oKSB7fSxcbiAgICAgICAgICAgIHVucmVmOiBmdW5jdGlvbigpIHt9XG4gICAgICAgIH07XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gdGltZXIuaWQ7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBmaXJzdFRpbWVySW5SYW5nZShjbG9jaywgZnJvbSwgdG8pIHtcbiAgICB2YXIgdGltZXJzID0gY2xvY2sudGltZXJzLCB0aW1lciA9IG51bGw7XG5cbiAgICBmb3IgKHZhciBpZCBpbiB0aW1lcnMpIHtcbiAgICAgICAgaWYgKCFpblJhbmdlKGZyb20sIHRvLCB0aW1lcnNbaWRdKSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRpbWVyIHx8IH5jb21wYXJlVGltZXJzKHRpbWVyLCB0aW1lcnNbaWRdKSkge1xuICAgICAgICAgICAgdGltZXIgPSB0aW1lcnNbaWRdO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRpbWVyO1xufVxuXG5mdW5jdGlvbiBjb21wYXJlVGltZXJzKGEsIGIpIHtcbiAgICAvLyBTb3J0IGZpcnN0IGJ5IGFic29sdXRlIHRpbWluZ1xuICAgIGlmIChhLmNhbGxBdCA8IGIuY2FsbEF0KSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG4gICAgaWYgKGEuY2FsbEF0ID4gYi5jYWxsQXQpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgfVxuXG4gICAgLy8gU29ydCBuZXh0IGJ5IGltbWVkaWF0ZSwgaW1tZWRpYXRlIHRpbWVycyB0YWtlIHByZWNlZGVuY2VcbiAgICBpZiAoYS5pbW1lZGlhdGUgJiYgIWIuaW1tZWRpYXRlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG4gICAgaWYgKCFhLmltbWVkaWF0ZSAmJiBiLmltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICB9XG5cbiAgICAvLyBTb3J0IG5leHQgYnkgY3JlYXRpb24gdGltZSwgZWFybGllci1jcmVhdGVkIHRpbWVycyB0YWtlIHByZWNlZGVuY2VcbiAgICBpZiAoYS5jcmVhdGVkQXQgPCBiLmNyZWF0ZWRBdCkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuICAgIGlmIChhLmNyZWF0ZWRBdCA+IGIuY3JlYXRlZEF0KSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH1cblxuICAgIC8vIFNvcnQgbmV4dCBieSBpZCwgbG93ZXItaWQgdGltZXJzIHRha2UgcHJlY2VkZW5jZVxuICAgIGlmIChhLmlkIDwgYi5pZCkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgfVxuICAgIGlmIChhLmlkID4gYi5pZCkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICB9XG5cbiAgICAvLyBBcyB0aW1lciBpZHMgYXJlIHVuaXF1ZSwgbm8gZmFsbGJhY2sgYDBgIGlzIG5lY2Vzc2FyeVxufVxuXG5mdW5jdGlvbiBjYWxsVGltZXIoY2xvY2ssIHRpbWVyKSB7XG4gICAgaWYgKHR5cGVvZiB0aW1lci5pbnRlcnZhbCA9PSBcIm51bWJlclwiKSB7XG4gICAgICAgIGNsb2NrLnRpbWVyc1t0aW1lci5pZF0uY2FsbEF0ICs9IHRpbWVyLmludGVydmFsO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGRlbGV0ZSBjbG9jay50aW1lcnNbdGltZXIuaWRdO1xuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2YgdGltZXIuZnVuYyA9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHRpbWVyLmZ1bmMuYXBwbHkobnVsbCwgdGltZXIuYXJncyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBldmFsKHRpbWVyLmZ1bmMpO1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB2YXIgZXhjZXB0aW9uID0gZTtcbiAgICB9XG5cbiAgICBpZiAoIWNsb2NrLnRpbWVyc1t0aW1lci5pZF0pIHtcbiAgICAgICAgaWYgKGV4Y2VwdGlvbikge1xuICAgICAgICAgICAgdGhyb3cgZXhjZXB0aW9uO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoZXhjZXB0aW9uKSB7XG4gICAgICAgIHRocm93IGV4Y2VwdGlvbjtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHVuaW5zdGFsbChjbG9jaywgdGFyZ2V0KSB7XG4gICAgdmFyIG1ldGhvZDtcblxuICAgIGZvciAodmFyIGkgPSAwLCBsID0gY2xvY2subWV0aG9kcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgbWV0aG9kID0gY2xvY2subWV0aG9kc1tpXTtcblxuICAgICAgICBpZiAodGFyZ2V0W21ldGhvZF0uaGFkT3duUHJvcGVydHkpIHtcbiAgICAgICAgICAgIHRhcmdldFttZXRob2RdID0gY2xvY2tbXCJfXCIgKyBtZXRob2RdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBkZWxldGUgdGFyZ2V0W21ldGhvZF07XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gUHJldmVudCBtdWx0aXBsZSBleGVjdXRpb25zIHdoaWNoIHdpbGwgY29tcGxldGVseSByZW1vdmUgdGhlc2UgcHJvcHNcbiAgICBjbG9jay5tZXRob2RzID0gW107XG59XG5cbmZ1bmN0aW9uIGhpamFja01ldGhvZCh0YXJnZXQsIG1ldGhvZCwgY2xvY2spIHtcbiAgICBjbG9ja1ttZXRob2RdLmhhZE93blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHRhcmdldCwgbWV0aG9kKTtcbiAgICBjbG9ja1tcIl9cIiArIG1ldGhvZF0gPSB0YXJnZXRbbWV0aG9kXTtcblxuICAgIGlmIChtZXRob2QgPT0gXCJEYXRlXCIpIHtcbiAgICAgICAgdmFyIGRhdGUgPSBtaXJyb3JEYXRlUHJvcGVydGllcyhjbG9ja1ttZXRob2RdLCB0YXJnZXRbbWV0aG9kXSk7XG4gICAgICAgIHRhcmdldFttZXRob2RdID0gZGF0ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0YXJnZXRbbWV0aG9kXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBjbG9ja1ttZXRob2RdLmFwcGx5KGNsb2NrLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuXG4gICAgICAgIGZvciAodmFyIHByb3AgaW4gY2xvY2tbbWV0aG9kXSkge1xuICAgICAgICAgICAgaWYgKGNsb2NrW21ldGhvZF0uaGFzT3duUHJvcGVydHkocHJvcCkpIHtcbiAgICAgICAgICAgICAgICB0YXJnZXRbbWV0aG9kXVtwcm9wXSA9IGNsb2NrW21ldGhvZF1bcHJvcF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB0YXJnZXRbbWV0aG9kXS5jbG9jayA9IGNsb2NrO1xufVxuXG52YXIgdGltZXJzID0ge1xuICAgIHNldFRpbWVvdXQ6IHNldFRpbWVvdXQsXG4gICAgY2xlYXJUaW1lb3V0OiBjbGVhclRpbWVvdXQsXG4gICAgc2V0SW1tZWRpYXRlOiAodHlwZW9mIHNldEltbWVkaWF0ZSAhPT0gXCJ1bmRlZmluZWRcIiA/IHNldEltbWVkaWF0ZSA6IHVuZGVmaW5lZCksXG4gICAgY2xlYXJJbW1lZGlhdGU6ICh0eXBlb2YgY2xlYXJJbW1lZGlhdGUgIT09IFwidW5kZWZpbmVkXCIgPyBjbGVhckltbWVkaWF0ZTogdW5kZWZpbmVkKSxcbiAgICBzZXRJbnRlcnZhbDogc2V0SW50ZXJ2YWwsXG4gICAgY2xlYXJJbnRlcnZhbDogY2xlYXJJbnRlcnZhbCxcbiAgICBEYXRlOiBEYXRlXG59O1xuXG52YXIga2V5cyA9IE9iamVjdC5rZXlzIHx8IGZ1bmN0aW9uIChvYmopIHtcbiAgICB2YXIga3MgPSBbXTtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgIGtzLnB1c2goa2V5KTtcbiAgICB9XG4gICAgcmV0dXJuIGtzO1xufTtcblxuZXhwb3J0cy50aW1lcnMgPSB0aW1lcnM7XG5cbnZhciBjcmVhdGVDbG9jayA9IGV4cG9ydHMuY3JlYXRlQ2xvY2sgPSBmdW5jdGlvbiAobm93KSB7XG4gICAgdmFyIGNsb2NrID0ge1xuICAgICAgICBub3c6IGdldEVwb2NoKG5vdyksXG4gICAgICAgIHRpbWVvdXRzOiB7fSxcbiAgICAgICAgRGF0ZTogY3JlYXRlRGF0ZSgpXG4gICAgfTtcblxuICAgIGNsb2NrLkRhdGUuY2xvY2sgPSBjbG9jaztcblxuICAgIGNsb2NrLnNldFRpbWVvdXQgPSBmdW5jdGlvbiBzZXRUaW1lb3V0KGZ1bmMsIHRpbWVvdXQpIHtcbiAgICAgICAgcmV0dXJuIGFkZFRpbWVyKGNsb2NrLCB7XG4gICAgICAgICAgICBmdW5jOiBmdW5jLFxuICAgICAgICAgICAgYXJnczogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKSxcbiAgICAgICAgICAgIGRlbGF5OiB0aW1lb3V0XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBjbG9jay5jbGVhclRpbWVvdXQgPSBmdW5jdGlvbiBjbGVhclRpbWVvdXQodGltZXJJZCkge1xuICAgICAgICBpZiAoIXRpbWVySWQpIHtcbiAgICAgICAgICAgIC8vIG51bGwgYXBwZWFycyB0byBiZSBhbGxvd2VkIGluIG1vc3QgYnJvd3NlcnMsIGFuZCBhcHBlYXJzIHRvIGJlXG4gICAgICAgICAgICAvLyByZWxpZWQgdXBvbiBieSBzb21lIGxpYnJhcmllcywgbGlrZSBCb290c3RyYXAgY2Fyb3VzZWxcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNsb2NrLnRpbWVycykge1xuICAgICAgICAgICAgY2xvY2sudGltZXJzID0gW107XG4gICAgICAgIH1cbiAgICAgICAgLy8gaW4gTm9kZSwgdGltZXJJZCBpcyBhbiBvYmplY3Qgd2l0aCAucmVmKCkvLnVucmVmKCksIGFuZFxuICAgICAgICAvLyBpdHMgLmlkIGZpZWxkIGlzIHRoZSBhY3R1YWwgdGltZXIgaWQuXG4gICAgICAgIGlmICh0eXBlb2YgdGltZXJJZCA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgdGltZXJJZCA9IHRpbWVySWQuaWRcbiAgICAgICAgfVxuICAgICAgICBpZiAodGltZXJJZCBpbiBjbG9jay50aW1lcnMpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBjbG9jay50aW1lcnNbdGltZXJJZF07XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgY2xvY2suc2V0SW50ZXJ2YWwgPSBmdW5jdGlvbiBzZXRJbnRlcnZhbChmdW5jLCB0aW1lb3V0KSB7XG4gICAgICAgIHJldHVybiBhZGRUaW1lcihjbG9jaywge1xuICAgICAgICAgICAgZnVuYzogZnVuYyxcbiAgICAgICAgICAgIGFyZ3M6IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMiksXG4gICAgICAgICAgICBkZWxheTogdGltZW91dCxcbiAgICAgICAgICAgIGludGVydmFsOiB0aW1lb3V0XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICBjbG9jay5jbGVhckludGVydmFsID0gZnVuY3Rpb24gY2xlYXJJbnRlcnZhbCh0aW1lcklkKSB7XG4gICAgICAgIGNsb2NrLmNsZWFyVGltZW91dCh0aW1lcklkKTtcbiAgICB9O1xuXG4gICAgY2xvY2suc2V0SW1tZWRpYXRlID0gZnVuY3Rpb24gc2V0SW1tZWRpYXRlKGZ1bmMpIHtcbiAgICAgICAgcmV0dXJuIGFkZFRpbWVyKGNsb2NrLCB7XG4gICAgICAgICAgICBmdW5jOiBmdW5jLFxuICAgICAgICAgICAgYXJnczogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSxcbiAgICAgICAgICAgIGltbWVkaWF0ZTogdHJ1ZVxuICAgICAgICB9KTtcbiAgICB9O1xuXG4gICAgY2xvY2suY2xlYXJJbW1lZGlhdGUgPSBmdW5jdGlvbiBjbGVhckltbWVkaWF0ZSh0aW1lcklkKSB7XG4gICAgICAgIGNsb2NrLmNsZWFyVGltZW91dCh0aW1lcklkKTtcbiAgICB9O1xuXG4gICAgY2xvY2sudGljayA9IGZ1bmN0aW9uIHRpY2sobXMpIHtcbiAgICAgICAgbXMgPSB0eXBlb2YgbXMgPT0gXCJudW1iZXJcIiA/IG1zIDogcGFyc2VUaW1lKG1zKTtcbiAgICAgICAgdmFyIHRpY2tGcm9tID0gY2xvY2subm93LCB0aWNrVG8gPSBjbG9jay5ub3cgKyBtcywgcHJldmlvdXMgPSBjbG9jay5ub3c7XG4gICAgICAgIHZhciB0aW1lciA9IGZpcnN0VGltZXJJblJhbmdlKGNsb2NrLCB0aWNrRnJvbSwgdGlja1RvKTtcblxuICAgICAgICB2YXIgZmlyc3RFeGNlcHRpb247XG4gICAgICAgIHdoaWxlICh0aW1lciAmJiB0aWNrRnJvbSA8PSB0aWNrVG8pIHtcbiAgICAgICAgICAgIGlmIChjbG9jay50aW1lcnNbdGltZXIuaWRdKSB7XG4gICAgICAgICAgICAgICAgdGlja0Zyb20gPSBjbG9jay5ub3cgPSB0aW1lci5jYWxsQXQ7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgY2FsbFRpbWVyKGNsb2NrLCB0aW1lcik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdEV4Y2VwdGlvbiA9IGZpcnN0RXhjZXB0aW9uIHx8IGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aW1lciA9IGZpcnN0VGltZXJJblJhbmdlKGNsb2NrLCBwcmV2aW91cywgdGlja1RvKTtcbiAgICAgICAgICAgIHByZXZpb3VzID0gdGlja0Zyb207XG4gICAgICAgIH1cblxuICAgICAgICBjbG9jay5ub3cgPSB0aWNrVG87XG5cbiAgICAgICAgaWYgKGZpcnN0RXhjZXB0aW9uKSB7XG4gICAgICAgICAgICB0aHJvdyBmaXJzdEV4Y2VwdGlvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjbG9jay5ub3c7XG4gICAgfTtcblxuICAgIGNsb2NrLnJlc2V0ID0gZnVuY3Rpb24gcmVzZXQoKSB7XG4gICAgICAgIGNsb2NrLnRpbWVycyA9IHt9O1xuICAgIH07XG5cbiAgICByZXR1cm4gY2xvY2s7XG59O1xuXG5leHBvcnRzLmluc3RhbGwgPSBmdW5jdGlvbiBpbnN0YWxsKHRhcmdldCwgbm93LCB0b0Zha2UpIHtcbiAgICBpZiAodHlwZW9mIHRhcmdldCA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICB0b0Zha2UgPSBub3c7XG4gICAgICAgIG5vdyA9IHRhcmdldDtcbiAgICAgICAgdGFyZ2V0ID0gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAoIXRhcmdldCkge1xuICAgICAgICB0YXJnZXQgPSBnbG9iYWw7XG4gICAgfVxuXG4gICAgdmFyIGNsb2NrID0gY3JlYXRlQ2xvY2sobm93KTtcblxuICAgIGNsb2NrLnVuaW5zdGFsbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdW5pbnN0YWxsKGNsb2NrLCB0YXJnZXQpO1xuICAgIH07XG5cbiAgICBjbG9jay5tZXRob2RzID0gdG9GYWtlIHx8IFtdO1xuXG4gICAgaWYgKGNsb2NrLm1ldGhvZHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNsb2NrLm1ldGhvZHMgPSBrZXlzKHRpbWVycyk7XG4gICAgfVxuXG4gICAgZm9yICh2YXIgaSA9IDAsIGwgPSBjbG9jay5tZXRob2RzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICBoaWphY2tNZXRob2QodGFyZ2V0LCBjbG9jay5tZXRob2RzW2ldLCBjbG9jayk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNsb2NrO1xufTtcblxufSkuY2FsbCh0aGlzLHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSkiLCIoKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kICYmIGZ1bmN0aW9uIChtKSB7IGRlZmluZShcInNhbXNhbVwiLCBtKTsgfSkgfHxcbiAodHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJlxuICAgICAgZnVuY3Rpb24gKG0pIHsgbW9kdWxlLmV4cG9ydHMgPSBtKCk7IH0pIHx8IC8vIE5vZGVcbiBmdW5jdGlvbiAobSkgeyB0aGlzLnNhbXNhbSA9IG0oKTsgfSAvLyBCcm93c2VyIGdsb2JhbHNcbikoZnVuY3Rpb24gKCkge1xuICAgIHZhciBvID0gT2JqZWN0LnByb3RvdHlwZTtcbiAgICB2YXIgZGl2ID0gdHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiICYmIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG5cbiAgICBmdW5jdGlvbiBpc05hTih2YWx1ZSkge1xuICAgICAgICAvLyBVbmxpa2UgZ2xvYmFsIGlzTmFOLCB0aGlzIGF2b2lkcyB0eXBlIGNvZXJjaW9uXG4gICAgICAgIC8vIHR5cGVvZiBjaGVjayBhdm9pZHMgSUUgaG9zdCBvYmplY3QgaXNzdWVzLCBoYXQgdGlwIHRvXG4gICAgICAgIC8vIGxvZGFzaFxuICAgICAgICB2YXIgdmFsID0gdmFsdWU7IC8vIEpzTGludCB0aGlua3MgdmFsdWUgIT09IHZhbHVlIGlzIFwid2VpcmRcIlxuICAgICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiICYmIHZhbHVlICE9PSB2YWw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0Q2xhc3ModmFsdWUpIHtcbiAgICAgICAgLy8gUmV0dXJucyB0aGUgaW50ZXJuYWwgW1tDbGFzc11dIGJ5IGNhbGxpbmcgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZ1xuICAgICAgICAvLyB3aXRoIHRoZSBwcm92aWRlZCB2YWx1ZSBhcyB0aGlzLiBSZXR1cm4gdmFsdWUgaXMgYSBzdHJpbmcsIG5hbWluZyB0aGVcbiAgICAgICAgLy8gaW50ZXJuYWwgY2xhc3MsIGUuZy4gXCJBcnJheVwiXG4gICAgICAgIHJldHVybiBvLnRvU3RyaW5nLmNhbGwodmFsdWUpLnNwbGl0KC9bIFxcXV0vKVsxXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAbmFtZSBzYW1zYW0uaXNBcmd1bWVudHNcbiAgICAgKiBAcGFyYW0gT2JqZWN0IG9iamVjdFxuICAgICAqXG4gICAgICogUmV0dXJucyBgYHRydWVgYCBpZiBgYG9iamVjdGBgIGlzIGFuIGBgYXJndW1lbnRzYGAgb2JqZWN0LFxuICAgICAqIGBgZmFsc2VgYCBvdGhlcndpc2UuXG4gICAgICovXG4gICAgZnVuY3Rpb24gaXNBcmd1bWVudHMob2JqZWN0KSB7XG4gICAgICAgIGlmIChnZXRDbGFzcyhvYmplY3QpID09PSAnQXJndW1lbnRzJykgeyByZXR1cm4gdHJ1ZTsgfVxuICAgICAgICBpZiAodHlwZW9mIG9iamVjdCAhPT0gXCJvYmplY3RcIiB8fCB0eXBlb2Ygb2JqZWN0Lmxlbmd0aCAhPT0gXCJudW1iZXJcIiB8fFxuICAgICAgICAgICAgICAgIGdldENsYXNzKG9iamVjdCkgPT09IFwiQXJyYXlcIikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0LmNhbGxlZSA9PSBcImZ1bmN0aW9uXCIpIHsgcmV0dXJuIHRydWU7IH1cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG9iamVjdFtvYmplY3QubGVuZ3RoXSA9IDY7XG4gICAgICAgICAgICBkZWxldGUgb2JqZWN0W29iamVjdC5sZW5ndGhdO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQG5hbWUgc2Ftc2FtLmlzRWxlbWVudFxuICAgICAqIEBwYXJhbSBPYmplY3Qgb2JqZWN0XG4gICAgICpcbiAgICAgKiBSZXR1cm5zIGBgdHJ1ZWBgIGlmIGBgb2JqZWN0YGAgaXMgYSBET00gZWxlbWVudCBub2RlLiBVbmxpa2VcbiAgICAgKiBVbmRlcnNjb3JlLmpzL2xvZGFzaCwgdGhpcyBmdW5jdGlvbiB3aWxsIHJldHVybiBgYGZhbHNlYGAgaWYgYGBvYmplY3RgYFxuICAgICAqIGlzIGFuICplbGVtZW50LWxpa2UqIG9iamVjdCwgaS5lLiBhIHJlZ3VsYXIgb2JqZWN0IHdpdGggYSBgYG5vZGVUeXBlYGBcbiAgICAgKiBwcm9wZXJ0eSB0aGF0IGhvbGRzIHRoZSB2YWx1ZSBgYDFgYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0VsZW1lbnQob2JqZWN0KSB7XG4gICAgICAgIGlmICghb2JqZWN0IHx8IG9iamVjdC5ub2RlVHlwZSAhPT0gMSB8fCAhZGl2KSB7IHJldHVybiBmYWxzZTsgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgb2JqZWN0LmFwcGVuZENoaWxkKGRpdik7XG4gICAgICAgICAgICBvYmplY3QucmVtb3ZlQ2hpbGQoZGl2KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBuYW1lIHNhbXNhbS5rZXlzXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmplY3RcbiAgICAgKlxuICAgICAqIFJldHVybiBhbiBhcnJheSBvZiBvd24gcHJvcGVydHkgbmFtZXMuXG4gICAgICovXG4gICAgZnVuY3Rpb24ga2V5cyhvYmplY3QpIHtcbiAgICAgICAgdmFyIGtzID0gW10sIHByb3A7XG4gICAgICAgIGZvciAocHJvcCBpbiBvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvLmhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBwcm9wKSkgeyBrcy5wdXNoKHByb3ApOyB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGtzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBuYW1lIHNhbXNhbS5pc0RhdGVcbiAgICAgKiBAcGFyYW0gT2JqZWN0IHZhbHVlXG4gICAgICpcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIG9iamVjdCBpcyBhIGBgRGF0ZWBgLCBvciAqZGF0ZS1saWtlKi4gRHVjayB0eXBpbmdcbiAgICAgKiBvZiBkYXRlIG9iamVjdHMgd29yayBieSBjaGVja2luZyB0aGF0IHRoZSBvYmplY3QgaGFzIGEgYGBnZXRUaW1lYGBcbiAgICAgKiBmdW5jdGlvbiB3aG9zZSByZXR1cm4gdmFsdWUgZXF1YWxzIHRoZSByZXR1cm4gdmFsdWUgZnJvbSB0aGUgb2JqZWN0J3NcbiAgICAgKiBgYHZhbHVlT2ZgYC5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc0RhdGUodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZS5nZXRUaW1lID09IFwiZnVuY3Rpb25cIiAmJlxuICAgICAgICAgICAgdmFsdWUuZ2V0VGltZSgpID09IHZhbHVlLnZhbHVlT2YoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAbmFtZSBzYW1zYW0uaXNOZWdaZXJvXG4gICAgICogQHBhcmFtIE9iamVjdCB2YWx1ZVxuICAgICAqXG4gICAgICogUmV0dXJucyBgYHRydWVgYCBpZiBgYHZhbHVlYGAgaXMgYGAtMGBgLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlzTmVnWmVybyh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IDAgJiYgMSAvIHZhbHVlID09PSAtSW5maW5pdHk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQG5hbWUgc2Ftc2FtLmVxdWFsXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmoxXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmoyXG4gICAgICpcbiAgICAgKiBSZXR1cm5zIGBgdHJ1ZWBgIGlmIHR3byBvYmplY3RzIGFyZSBzdHJpY3RseSBlcXVhbC4gQ29tcGFyZWQgdG9cbiAgICAgKiBgYD09PWBgIHRoZXJlIGFyZSB0d28gZXhjZXB0aW9uczpcbiAgICAgKlxuICAgICAqICAgLSBOYU4gaXMgY29uc2lkZXJlZCBlcXVhbCB0byBOYU5cbiAgICAgKiAgIC0gLTAgYW5kICswIGFyZSBub3QgY29uc2lkZXJlZCBlcXVhbFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGlkZW50aWNhbChvYmoxLCBvYmoyKSB7XG4gICAgICAgIGlmIChvYmoxID09PSBvYmoyIHx8IChpc05hTihvYmoxKSAmJiBpc05hTihvYmoyKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmoxICE9PSAwIHx8IGlzTmVnWmVybyhvYmoxKSA9PT0gaXNOZWdaZXJvKG9iajIpO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICAvKipcbiAgICAgKiBAbmFtZSBzYW1zYW0uZGVlcEVxdWFsXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmoxXG4gICAgICogQHBhcmFtIE9iamVjdCBvYmoyXG4gICAgICpcbiAgICAgKiBEZWVwIGVxdWFsIGNvbXBhcmlzb24uIFR3byB2YWx1ZXMgYXJlIFwiZGVlcCBlcXVhbFwiIGlmOlxuICAgICAqXG4gICAgICogICAtIFRoZXkgYXJlIGVxdWFsLCBhY2NvcmRpbmcgdG8gc2Ftc2FtLmlkZW50aWNhbFxuICAgICAqICAgLSBUaGV5IGFyZSBib3RoIGRhdGUgb2JqZWN0cyByZXByZXNlbnRpbmcgdGhlIHNhbWUgdGltZVxuICAgICAqICAgLSBUaGV5IGFyZSBib3RoIGFycmF5cyBjb250YWluaW5nIGVsZW1lbnRzIHRoYXQgYXJlIGFsbCBkZWVwRXF1YWxcbiAgICAgKiAgIC0gVGhleSBhcmUgb2JqZWN0cyB3aXRoIHRoZSBzYW1lIHNldCBvZiBwcm9wZXJ0aWVzLCBhbmQgZWFjaCBwcm9wZXJ0eVxuICAgICAqICAgICBpbiBgYG9iajFgYCBpcyBkZWVwRXF1YWwgdG8gdGhlIGNvcnJlc3BvbmRpbmcgcHJvcGVydHkgaW4gYGBvYmoyYGBcbiAgICAgKlxuICAgICAqIFN1cHBvcnRzIGN5Y2xpYyBvYmplY3RzLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGRlZXBFcXVhbEN5Y2xpYyhvYmoxLCBvYmoyKSB7XG5cbiAgICAgICAgLy8gdXNlZCBmb3IgY3ljbGljIGNvbXBhcmlzb25cbiAgICAgICAgLy8gY29udGFpbiBhbHJlYWR5IHZpc2l0ZWQgb2JqZWN0c1xuICAgICAgICB2YXIgb2JqZWN0czEgPSBbXSxcbiAgICAgICAgICAgIG9iamVjdHMyID0gW10sXG4gICAgICAgIC8vIGNvbnRhaW4gcGF0aGVzIChwb3NpdGlvbiBpbiB0aGUgb2JqZWN0IHN0cnVjdHVyZSlcbiAgICAgICAgLy8gb2YgdGhlIGFscmVhZHkgdmlzaXRlZCBvYmplY3RzXG4gICAgICAgIC8vIGluZGV4ZXMgc2FtZSBhcyBpbiBvYmplY3RzIGFycmF5c1xuICAgICAgICAgICAgcGF0aHMxID0gW10sXG4gICAgICAgICAgICBwYXRoczIgPSBbXSxcbiAgICAgICAgLy8gY29udGFpbnMgY29tYmluYXRpb25zIG9mIGFscmVhZHkgY29tcGFyZWQgb2JqZWN0c1xuICAgICAgICAvLyBpbiB0aGUgbWFubmVyOiB7IFwiJDFbJ3JlZiddJDJbJ3JlZiddXCI6IHRydWUgfVxuICAgICAgICAgICAgY29tcGFyZWQgPSB7fTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogdXNlZCB0byBjaGVjaywgaWYgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkgaXMgYW4gb2JqZWN0XG4gICAgICAgICAqIChjeWNsaWMgbG9naWMgaXMgb25seSBuZWVkZWQgZm9yIG9iamVjdHMpXG4gICAgICAgICAqIG9ubHkgbmVlZGVkIGZvciBjeWNsaWMgbG9naWNcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIGlzT2JqZWN0KHZhbHVlKSB7XG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsICYmXG4gICAgICAgICAgICAgICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBCb29sZWFuKSAmJlxuICAgICAgICAgICAgICAgICAgICAhKHZhbHVlIGluc3RhbmNlb2YgRGF0ZSkgICAgJiZcbiAgICAgICAgICAgICAgICAgICAgISh2YWx1ZSBpbnN0YW5jZW9mIE51bWJlcikgICYmXG4gICAgICAgICAgICAgICAgICAgICEodmFsdWUgaW5zdGFuY2VvZiBSZWdFeHApICAmJlxuICAgICAgICAgICAgICAgICAgICAhKHZhbHVlIGluc3RhbmNlb2YgU3RyaW5nKSkge1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiByZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgZ2l2ZW4gb2JqZWN0IGluIHRoZVxuICAgICAgICAgKiBnaXZlbiBvYmplY3RzIGFycmF5LCAtMSBpZiBub3QgY29udGFpbmVkXG4gICAgICAgICAqIG9ubHkgbmVlZGVkIGZvciBjeWNsaWMgbG9naWNcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIGdldEluZGV4KG9iamVjdHMsIG9iaikge1xuXG4gICAgICAgICAgICB2YXIgaTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBvYmplY3RzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9iamVjdHNbaV0gPT09IG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGRvZXMgdGhlIHJlY3Vyc2lvbiBmb3IgdGhlIGRlZXAgZXF1YWwgY2hlY2tcbiAgICAgICAgcmV0dXJuIChmdW5jdGlvbiBkZWVwRXF1YWwob2JqMSwgb2JqMiwgcGF0aDEsIHBhdGgyKSB7XG4gICAgICAgICAgICB2YXIgdHlwZTEgPSB0eXBlb2Ygb2JqMTtcbiAgICAgICAgICAgIHZhciB0eXBlMiA9IHR5cGVvZiBvYmoyO1xuXG4gICAgICAgICAgICAvLyA9PSBudWxsIGFsc28gbWF0Y2hlcyB1bmRlZmluZWRcbiAgICAgICAgICAgIGlmIChvYmoxID09PSBvYmoyIHx8XG4gICAgICAgICAgICAgICAgICAgIGlzTmFOKG9iajEpIHx8IGlzTmFOKG9iajIpIHx8XG4gICAgICAgICAgICAgICAgICAgIG9iajEgPT0gbnVsbCB8fCBvYmoyID09IG51bGwgfHxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTEgIT09IFwib2JqZWN0XCIgfHwgdHlwZTIgIT09IFwib2JqZWN0XCIpIHtcblxuICAgICAgICAgICAgICAgIHJldHVybiBpZGVudGljYWwob2JqMSwgb2JqMik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEVsZW1lbnRzIGFyZSBvbmx5IGVxdWFsIGlmIGlkZW50aWNhbChleHBlY3RlZCwgYWN0dWFsKVxuICAgICAgICAgICAgaWYgKGlzRWxlbWVudChvYmoxKSB8fCBpc0VsZW1lbnQob2JqMikpIHsgcmV0dXJuIGZhbHNlOyB9XG5cbiAgICAgICAgICAgIHZhciBpc0RhdGUxID0gaXNEYXRlKG9iajEpLCBpc0RhdGUyID0gaXNEYXRlKG9iajIpO1xuICAgICAgICAgICAgaWYgKGlzRGF0ZTEgfHwgaXNEYXRlMikge1xuICAgICAgICAgICAgICAgIGlmICghaXNEYXRlMSB8fCAhaXNEYXRlMiB8fCBvYmoxLmdldFRpbWUoKSAhPT0gb2JqMi5nZXRUaW1lKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9iajEgaW5zdGFuY2VvZiBSZWdFeHAgJiYgb2JqMiBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgICAgICAgICAgICAgIGlmIChvYmoxLnRvU3RyaW5nKCkgIT09IG9iajIudG9TdHJpbmcoKSkgeyByZXR1cm4gZmFsc2U7IH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGNsYXNzMSA9IGdldENsYXNzKG9iajEpO1xuICAgICAgICAgICAgdmFyIGNsYXNzMiA9IGdldENsYXNzKG9iajIpO1xuICAgICAgICAgICAgdmFyIGtleXMxID0ga2V5cyhvYmoxKTtcbiAgICAgICAgICAgIHZhciBrZXlzMiA9IGtleXMob2JqMik7XG5cbiAgICAgICAgICAgIGlmIChpc0FyZ3VtZW50cyhvYmoxKSB8fCBpc0FyZ3VtZW50cyhvYmoyKSkge1xuICAgICAgICAgICAgICAgIGlmIChvYmoxLmxlbmd0aCAhPT0gb2JqMi5sZW5ndGgpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlMSAhPT0gdHlwZTIgfHwgY2xhc3MxICE9PSBjbGFzczIgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXMxLmxlbmd0aCAhPT0ga2V5czIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBrZXksIGksIGwsXG4gICAgICAgICAgICAgICAgLy8gZm9sbG93aW5nIHZhcnMgYXJlIHVzZWQgZm9yIHRoZSBjeWNsaWMgbG9naWNcbiAgICAgICAgICAgICAgICB2YWx1ZTEsIHZhbHVlMixcbiAgICAgICAgICAgICAgICBpc09iamVjdDEsIGlzT2JqZWN0MixcbiAgICAgICAgICAgICAgICBpbmRleDEsIGluZGV4MixcbiAgICAgICAgICAgICAgICBuZXdQYXRoMSwgbmV3UGF0aDI7XG5cbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGwgPSBrZXlzMS5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICBrZXkgPSBrZXlzMVtpXTtcbiAgICAgICAgICAgICAgICBpZiAoIW8uaGFzT3duUHJvcGVydHkuY2FsbChvYmoyLCBrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBTdGFydCBvZiB0aGUgY3ljbGljIGxvZ2ljXG5cbiAgICAgICAgICAgICAgICB2YWx1ZTEgPSBvYmoxW2tleV07XG4gICAgICAgICAgICAgICAgdmFsdWUyID0gb2JqMltrZXldO1xuXG4gICAgICAgICAgICAgICAgaXNPYmplY3QxID0gaXNPYmplY3QodmFsdWUxKTtcbiAgICAgICAgICAgICAgICBpc09iamVjdDIgPSBpc09iamVjdCh2YWx1ZTIpO1xuXG4gICAgICAgICAgICAgICAgLy8gZGV0ZXJtaW5lLCBpZiB0aGUgb2JqZWN0cyB3ZXJlIGFscmVhZHkgdmlzaXRlZFxuICAgICAgICAgICAgICAgIC8vIChpdCdzIGZhc3RlciB0byBjaGVjayBmb3IgaXNPYmplY3QgZmlyc3QsIHRoYW4gdG9cbiAgICAgICAgICAgICAgICAvLyBnZXQgLTEgZnJvbSBnZXRJbmRleCBmb3Igbm9uIG9iamVjdHMpXG4gICAgICAgICAgICAgICAgaW5kZXgxID0gaXNPYmplY3QxID8gZ2V0SW5kZXgob2JqZWN0czEsIHZhbHVlMSkgOiAtMTtcbiAgICAgICAgICAgICAgICBpbmRleDIgPSBpc09iamVjdDIgPyBnZXRJbmRleChvYmplY3RzMiwgdmFsdWUyKSA6IC0xO1xuXG4gICAgICAgICAgICAgICAgLy8gZGV0ZXJtaW5lIHRoZSBuZXcgcGF0aGVzIG9mIHRoZSBvYmplY3RzXG4gICAgICAgICAgICAgICAgLy8gLSBmb3Igbm9uIGN5Y2xpYyBvYmplY3RzIHRoZSBjdXJyZW50IHBhdGggd2lsbCBiZSBleHRlbmRlZFxuICAgICAgICAgICAgICAgIC8vICAgYnkgY3VycmVudCBwcm9wZXJ0eSBuYW1lXG4gICAgICAgICAgICAgICAgLy8gLSBmb3IgY3ljbGljIG9iamVjdHMgdGhlIHN0b3JlZCBwYXRoIGlzIHRha2VuXG4gICAgICAgICAgICAgICAgbmV3UGF0aDEgPSBpbmRleDEgIT09IC0xXG4gICAgICAgICAgICAgICAgICAgID8gcGF0aHMxW2luZGV4MV1cbiAgICAgICAgICAgICAgICAgICAgOiBwYXRoMSArICdbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXSc7XG4gICAgICAgICAgICAgICAgbmV3UGF0aDIgPSBpbmRleDIgIT09IC0xXG4gICAgICAgICAgICAgICAgICAgID8gcGF0aHMyW2luZGV4Ml1cbiAgICAgICAgICAgICAgICAgICAgOiBwYXRoMiArICdbJyArIEpTT04uc3RyaW5naWZ5KGtleSkgKyAnXSc7XG5cbiAgICAgICAgICAgICAgICAvLyBzdG9wIHJlY3Vyc2lvbiBpZiBjdXJyZW50IG9iamVjdHMgYXJlIGFscmVhZHkgY29tcGFyZWRcbiAgICAgICAgICAgICAgICBpZiAoY29tcGFyZWRbbmV3UGF0aDEgKyBuZXdQYXRoMl0pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtZW1iZXIgdGhlIGN1cnJlbnQgb2JqZWN0cyBhbmQgdGhlaXIgcGF0aGVzXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4MSA9PT0gLTEgJiYgaXNPYmplY3QxKSB7XG4gICAgICAgICAgICAgICAgICAgIG9iamVjdHMxLnB1c2godmFsdWUxKTtcbiAgICAgICAgICAgICAgICAgICAgcGF0aHMxLnB1c2gobmV3UGF0aDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaW5kZXgyID09PSAtMSAmJiBpc09iamVjdDIpIHtcbiAgICAgICAgICAgICAgICAgICAgb2JqZWN0czIucHVzaCh2YWx1ZTIpO1xuICAgICAgICAgICAgICAgICAgICBwYXRoczIucHVzaChuZXdQYXRoMik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtZW1iZXIgdGhhdCB0aGUgY3VycmVudCBvYmplY3RzIGFyZSBhbHJlYWR5IGNvbXBhcmVkXG4gICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0MSAmJiBpc09iamVjdDIpIHtcbiAgICAgICAgICAgICAgICAgICAgY29tcGFyZWRbbmV3UGF0aDEgKyBuZXdQYXRoMl0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEVuZCBvZiBjeWNsaWMgbG9naWNcblxuICAgICAgICAgICAgICAgIC8vIG5laXRoZXIgdmFsdWUxIG5vciB2YWx1ZTIgaXMgYSBjeWNsZVxuICAgICAgICAgICAgICAgIC8vIGNvbnRpbnVlIHdpdGggbmV4dCBsZXZlbFxuICAgICAgICAgICAgICAgIGlmICghZGVlcEVxdWFsKHZhbHVlMSwgdmFsdWUyLCBuZXdQYXRoMSwgbmV3UGF0aDIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuXG4gICAgICAgIH0ob2JqMSwgb2JqMiwgJyQxJywgJyQyJykpO1xuICAgIH1cblxuICAgIHZhciBtYXRjaDtcblxuICAgIGZ1bmN0aW9uIGFycmF5Q29udGFpbnMoYXJyYXksIHN1YnNldCkge1xuICAgICAgICBpZiAoc3Vic2V0Lmxlbmd0aCA9PT0gMCkgeyByZXR1cm4gdHJ1ZTsgfVxuICAgICAgICB2YXIgaSwgbCwgaiwgaztcbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGFycmF5Lmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgaWYgKG1hdGNoKGFycmF5W2ldLCBzdWJzZXRbMF0pKSB7XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMCwgayA9IHN1YnNldC5sZW5ndGg7IGogPCBrOyArK2opIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFtYXRjaChhcnJheVtpICsgal0sIHN1YnNldFtqXSkpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAbmFtZSBzYW1zYW0ubWF0Y2hcbiAgICAgKiBAcGFyYW0gT2JqZWN0IG9iamVjdFxuICAgICAqIEBwYXJhbSBPYmplY3QgbWF0Y2hlclxuICAgICAqXG4gICAgICogQ29tcGFyZSBhcmJpdHJhcnkgdmFsdWUgYGBvYmplY3RgYCB3aXRoIG1hdGNoZXIuXG4gICAgICovXG4gICAgbWF0Y2ggPSBmdW5jdGlvbiBtYXRjaChvYmplY3QsIG1hdGNoZXIpIHtcbiAgICAgICAgaWYgKG1hdGNoZXIgJiYgdHlwZW9mIG1hdGNoZXIudGVzdCA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICByZXR1cm4gbWF0Y2hlci50ZXN0KG9iamVjdCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIG1hdGNoZXIgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXIob2JqZWN0KSA9PT0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbWF0Y2hlciA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgbWF0Y2hlciA9IG1hdGNoZXIudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgIHZhciBub3ROdWxsID0gdHlwZW9mIG9iamVjdCA9PT0gXCJzdHJpbmdcIiB8fCAhIW9iamVjdDtcbiAgICAgICAgICAgIHJldHVybiBub3ROdWxsICYmXG4gICAgICAgICAgICAgICAgKFN0cmluZyhvYmplY3QpKS50b0xvd2VyQ2FzZSgpLmluZGV4T2YobWF0Y2hlcikgPj0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbWF0Y2hlciA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXIgPT09IG9iamVjdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgbWF0Y2hlciA9PT0gXCJib29sZWFuXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBtYXRjaGVyID09PSBvYmplY3Q7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mKG1hdGNoZXIpID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICByZXR1cm4gdHlwZW9mKG9iamVjdCkgPT09IFwidW5kZWZpbmVkXCI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobWF0Y2hlciA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdCA9PT0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChnZXRDbGFzcyhvYmplY3QpID09PSBcIkFycmF5XCIgJiYgZ2V0Q2xhc3MobWF0Y2hlcikgPT09IFwiQXJyYXlcIikge1xuICAgICAgICAgICAgcmV0dXJuIGFycmF5Q29udGFpbnMob2JqZWN0LCBtYXRjaGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChtYXRjaGVyICYmIHR5cGVvZiBtYXRjaGVyID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICBpZiAobWF0Y2hlciA9PT0gb2JqZWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcHJvcDtcbiAgICAgICAgICAgIGZvciAocHJvcCBpbiBtYXRjaGVyKSB7XG4gICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gb2JqZWN0W3Byb3BdO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwidW5kZWZpbmVkXCIgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVvZiBvYmplY3QuZ2V0QXR0cmlidXRlID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBvYmplY3QuZ2V0QXR0cmlidXRlKHByb3ApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobWF0Y2hlcltwcm9wXSA9PT0gbnVsbCB8fCB0eXBlb2YgbWF0Y2hlcltwcm9wXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlICE9PSBtYXRjaGVyW3Byb3BdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiAgdmFsdWUgPT09IFwidW5kZWZpbmVkXCIgfHwgIW1hdGNoKHZhbHVlLCBtYXRjaGVyW3Byb3BdKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJNYXRjaGVyIHdhcyBub3QgYSBzdHJpbmcsIGEgbnVtYmVyLCBhIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgIFwiZnVuY3Rpb24sIGEgYm9vbGVhbiBvciBhbiBvYmplY3RcIik7XG4gICAgfTtcblxuICAgIHJldHVybiB7XG4gICAgICAgIGlzQXJndW1lbnRzOiBpc0FyZ3VtZW50cyxcbiAgICAgICAgaXNFbGVtZW50OiBpc0VsZW1lbnQsXG4gICAgICAgIGlzRGF0ZTogaXNEYXRlLFxuICAgICAgICBpc05lZ1plcm86IGlzTmVnWmVybyxcbiAgICAgICAgaWRlbnRpY2FsOiBpZGVudGljYWwsXG4gICAgICAgIGRlZXBFcXVhbDogZGVlcEVxdWFsQ3ljbGljLFxuICAgICAgICBtYXRjaDogbWF0Y2gsXG4gICAgICAgIGtleXM6IGtleXNcbiAgICB9O1xufSk7XG4iLCIvLyAgICAgVW5kZXJzY29yZS5qcyAxLjguM1xuLy8gICAgIGh0dHA6Ly91bmRlcnNjb3JlanMub3JnXG4vLyAgICAgKGMpIDIwMDktMjAxNSBKZXJlbXkgQXNoa2VuYXMsIERvY3VtZW50Q2xvdWQgYW5kIEludmVzdGlnYXRpdmUgUmVwb3J0ZXJzICYgRWRpdG9yc1xuLy8gICAgIFVuZGVyc2NvcmUgbWF5IGJlIGZyZWVseSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UuXG5cbihmdW5jdGlvbigpIHtcblxuICAvLyBCYXNlbGluZSBzZXR1cFxuICAvLyAtLS0tLS0tLS0tLS0tLVxuXG4gIC8vIEVzdGFibGlzaCB0aGUgcm9vdCBvYmplY3QsIGB3aW5kb3dgIGluIHRoZSBicm93c2VyLCBvciBgZXhwb3J0c2Agb24gdGhlIHNlcnZlci5cbiAgdmFyIHJvb3QgPSB0aGlzO1xuXG4gIC8vIFNhdmUgdGhlIHByZXZpb3VzIHZhbHVlIG9mIHRoZSBgX2AgdmFyaWFibGUuXG4gIHZhciBwcmV2aW91c1VuZGVyc2NvcmUgPSByb290Ll87XG5cbiAgLy8gU2F2ZSBieXRlcyBpbiB0aGUgbWluaWZpZWQgKGJ1dCBub3QgZ3ppcHBlZCkgdmVyc2lvbjpcbiAgdmFyIEFycmF5UHJvdG8gPSBBcnJheS5wcm90b3R5cGUsIE9ialByb3RvID0gT2JqZWN0LnByb3RvdHlwZSwgRnVuY1Byb3RvID0gRnVuY3Rpb24ucHJvdG90eXBlO1xuXG4gIC8vIENyZWF0ZSBxdWljayByZWZlcmVuY2UgdmFyaWFibGVzIGZvciBzcGVlZCBhY2Nlc3MgdG8gY29yZSBwcm90b3R5cGVzLlxuICB2YXJcbiAgICBwdXNoICAgICAgICAgICAgID0gQXJyYXlQcm90by5wdXNoLFxuICAgIHNsaWNlICAgICAgICAgICAgPSBBcnJheVByb3RvLnNsaWNlLFxuICAgIHRvU3RyaW5nICAgICAgICAgPSBPYmpQcm90by50b1N0cmluZyxcbiAgICBoYXNPd25Qcm9wZXJ0eSAgID0gT2JqUHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbiAgLy8gQWxsICoqRUNNQVNjcmlwdCA1KiogbmF0aXZlIGZ1bmN0aW9uIGltcGxlbWVudGF0aW9ucyB0aGF0IHdlIGhvcGUgdG8gdXNlXG4gIC8vIGFyZSBkZWNsYXJlZCBoZXJlLlxuICB2YXJcbiAgICBuYXRpdmVJc0FycmF5ICAgICAgPSBBcnJheS5pc0FycmF5LFxuICAgIG5hdGl2ZUtleXMgICAgICAgICA9IE9iamVjdC5rZXlzLFxuICAgIG5hdGl2ZUJpbmQgICAgICAgICA9IEZ1bmNQcm90by5iaW5kLFxuICAgIG5hdGl2ZUNyZWF0ZSAgICAgICA9IE9iamVjdC5jcmVhdGU7XG5cbiAgLy8gTmFrZWQgZnVuY3Rpb24gcmVmZXJlbmNlIGZvciBzdXJyb2dhdGUtcHJvdG90eXBlLXN3YXBwaW5nLlxuICB2YXIgQ3RvciA9IGZ1bmN0aW9uKCl7fTtcblxuICAvLyBDcmVhdGUgYSBzYWZlIHJlZmVyZW5jZSB0byB0aGUgVW5kZXJzY29yZSBvYmplY3QgZm9yIHVzZSBiZWxvdy5cbiAgdmFyIF8gPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAob2JqIGluc3RhbmNlb2YgXykgcmV0dXJuIG9iajtcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgXykpIHJldHVybiBuZXcgXyhvYmopO1xuICAgIHRoaXMuX3dyYXBwZWQgPSBvYmo7XG4gIH07XG5cbiAgLy8gRXhwb3J0IHRoZSBVbmRlcnNjb3JlIG9iamVjdCBmb3IgKipOb2RlLmpzKiosIHdpdGhcbiAgLy8gYmFja3dhcmRzLWNvbXBhdGliaWxpdHkgZm9yIHRoZSBvbGQgYHJlcXVpcmUoKWAgQVBJLiBJZiB3ZSdyZSBpblxuICAvLyB0aGUgYnJvd3NlciwgYWRkIGBfYCBhcyBhIGdsb2JhbCBvYmplY3QuXG4gIGlmICh0eXBlb2YgZXhwb3J0cyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgJiYgbW9kdWxlLmV4cG9ydHMpIHtcbiAgICAgIGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IF87XG4gICAgfVxuICAgIGV4cG9ydHMuXyA9IF87XG4gIH0gZWxzZSB7XG4gICAgcm9vdC5fID0gXztcbiAgfVxuXG4gIC8vIEN1cnJlbnQgdmVyc2lvbi5cbiAgXy5WRVJTSU9OID0gJzEuOC4zJztcblxuICAvLyBJbnRlcm5hbCBmdW5jdGlvbiB0aGF0IHJldHVybnMgYW4gZWZmaWNpZW50IChmb3IgY3VycmVudCBlbmdpbmVzKSB2ZXJzaW9uXG4gIC8vIG9mIHRoZSBwYXNzZWQtaW4gY2FsbGJhY2ssIHRvIGJlIHJlcGVhdGVkbHkgYXBwbGllZCBpbiBvdGhlciBVbmRlcnNjb3JlXG4gIC8vIGZ1bmN0aW9ucy5cbiAgdmFyIG9wdGltaXplQ2IgPSBmdW5jdGlvbihmdW5jLCBjb250ZXh0LCBhcmdDb3VudCkge1xuICAgIGlmIChjb250ZXh0ID09PSB2b2lkIDApIHJldHVybiBmdW5jO1xuICAgIHN3aXRjaCAoYXJnQ291bnQgPT0gbnVsbCA/IDMgOiBhcmdDb3VudCkge1xuICAgICAgY2FzZSAxOiByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmMuY2FsbChjb250ZXh0LCB2YWx1ZSk7XG4gICAgICB9O1xuICAgICAgY2FzZSAyOiByZXR1cm4gZnVuY3Rpb24odmFsdWUsIG90aGVyKSB7XG4gICAgICAgIHJldHVybiBmdW5jLmNhbGwoY29udGV4dCwgdmFsdWUsIG90aGVyKTtcbiAgICAgIH07XG4gICAgICBjYXNlIDM6IHJldHVybiBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuIGZ1bmMuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgICAgfTtcbiAgICAgIGNhc2UgNDogcmV0dXJuIGZ1bmN0aW9uKGFjY3VtdWxhdG9yLCB2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgcmV0dXJuIGZ1bmMuY2FsbChjb250ZXh0LCBhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKTtcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfTtcblxuICAvLyBBIG1vc3RseS1pbnRlcm5hbCBmdW5jdGlvbiB0byBnZW5lcmF0ZSBjYWxsYmFja3MgdGhhdCBjYW4gYmUgYXBwbGllZFxuICAvLyB0byBlYWNoIGVsZW1lbnQgaW4gYSBjb2xsZWN0aW9uLCByZXR1cm5pbmcgdGhlIGRlc2lyZWQgcmVzdWx0IOKAlCBlaXRoZXJcbiAgLy8gaWRlbnRpdHksIGFuIGFyYml0cmFyeSBjYWxsYmFjaywgYSBwcm9wZXJ0eSBtYXRjaGVyLCBvciBhIHByb3BlcnR5IGFjY2Vzc29yLlxuICB2YXIgY2IgPSBmdW5jdGlvbih2YWx1ZSwgY29udGV4dCwgYXJnQ291bnQpIHtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkgcmV0dXJuIF8uaWRlbnRpdHk7XG4gICAgaWYgKF8uaXNGdW5jdGlvbih2YWx1ZSkpIHJldHVybiBvcHRpbWl6ZUNiKHZhbHVlLCBjb250ZXh0LCBhcmdDb3VudCk7XG4gICAgaWYgKF8uaXNPYmplY3QodmFsdWUpKSByZXR1cm4gXy5tYXRjaGVyKHZhbHVlKTtcbiAgICByZXR1cm4gXy5wcm9wZXJ0eSh2YWx1ZSk7XG4gIH07XG4gIF8uaXRlcmF0ZWUgPSBmdW5jdGlvbih2YWx1ZSwgY29udGV4dCkge1xuICAgIHJldHVybiBjYih2YWx1ZSwgY29udGV4dCwgSW5maW5pdHkpO1xuICB9O1xuXG4gIC8vIEFuIGludGVybmFsIGZ1bmN0aW9uIGZvciBjcmVhdGluZyBhc3NpZ25lciBmdW5jdGlvbnMuXG4gIHZhciBjcmVhdGVBc3NpZ25lciA9IGZ1bmN0aW9uKGtleXNGdW5jLCB1bmRlZmluZWRPbmx5KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKG9iaikge1xuICAgICAgdmFyIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgICBpZiAobGVuZ3RoIDwgMiB8fCBvYmogPT0gbnVsbCkgcmV0dXJuIG9iajtcbiAgICAgIGZvciAodmFyIGluZGV4ID0gMTsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpbmRleF0sXG4gICAgICAgICAgICBrZXlzID0ga2V5c0Z1bmMoc291cmNlKSxcbiAgICAgICAgICAgIGwgPSBrZXlzLmxlbmd0aDtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICB2YXIga2V5ID0ga2V5c1tpXTtcbiAgICAgICAgICBpZiAoIXVuZGVmaW5lZE9ubHkgfHwgb2JqW2tleV0gPT09IHZvaWQgMCkgb2JqW2tleV0gPSBzb3VyY2Vba2V5XTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIG9iajtcbiAgICB9O1xuICB9O1xuXG4gIC8vIEFuIGludGVybmFsIGZ1bmN0aW9uIGZvciBjcmVhdGluZyBhIG5ldyBvYmplY3QgdGhhdCBpbmhlcml0cyBmcm9tIGFub3RoZXIuXG4gIHZhciBiYXNlQ3JlYXRlID0gZnVuY3Rpb24ocHJvdG90eXBlKSB7XG4gICAgaWYgKCFfLmlzT2JqZWN0KHByb3RvdHlwZSkpIHJldHVybiB7fTtcbiAgICBpZiAobmF0aXZlQ3JlYXRlKSByZXR1cm4gbmF0aXZlQ3JlYXRlKHByb3RvdHlwZSk7XG4gICAgQ3Rvci5wcm90b3R5cGUgPSBwcm90b3R5cGU7XG4gICAgdmFyIHJlc3VsdCA9IG5ldyBDdG9yO1xuICAgIEN0b3IucHJvdG90eXBlID0gbnVsbDtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIHZhciBwcm9wZXJ0eSA9IGZ1bmN0aW9uKGtleSkge1xuICAgIHJldHVybiBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiBvYmogPT0gbnVsbCA/IHZvaWQgMCA6IG9ialtrZXldO1xuICAgIH07XG4gIH07XG5cbiAgLy8gSGVscGVyIGZvciBjb2xsZWN0aW9uIG1ldGhvZHMgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgYSBjb2xsZWN0aW9uXG4gIC8vIHNob3VsZCBiZSBpdGVyYXRlZCBhcyBhbiBhcnJheSBvciBhcyBhbiBvYmplY3RcbiAgLy8gUmVsYXRlZDogaHR0cDovL3Blb3BsZS5tb3ppbGxhLm9yZy9+am9yZW5kb3JmZi9lczYtZHJhZnQuaHRtbCNzZWMtdG9sZW5ndGhcbiAgLy8gQXZvaWRzIGEgdmVyeSBuYXN0eSBpT1MgOCBKSVQgYnVnIG9uIEFSTS02NC4gIzIwOTRcbiAgdmFyIE1BWF9BUlJBWV9JTkRFWCA9IE1hdGgucG93KDIsIDUzKSAtIDE7XG4gIHZhciBnZXRMZW5ndGggPSBwcm9wZXJ0eSgnbGVuZ3RoJyk7XG4gIHZhciBpc0FycmF5TGlrZSA9IGZ1bmN0aW9uKGNvbGxlY3Rpb24pIHtcbiAgICB2YXIgbGVuZ3RoID0gZ2V0TGVuZ3RoKGNvbGxlY3Rpb24pO1xuICAgIHJldHVybiB0eXBlb2YgbGVuZ3RoID09ICdudW1iZXInICYmIGxlbmd0aCA+PSAwICYmIGxlbmd0aCA8PSBNQVhfQVJSQVlfSU5ERVg7XG4gIH07XG5cbiAgLy8gQ29sbGVjdGlvbiBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBUaGUgY29ybmVyc3RvbmUsIGFuIGBlYWNoYCBpbXBsZW1lbnRhdGlvbiwgYWthIGBmb3JFYWNoYC5cbiAgLy8gSGFuZGxlcyByYXcgb2JqZWN0cyBpbiBhZGRpdGlvbiB0byBhcnJheS1saWtlcy4gVHJlYXRzIGFsbFxuICAvLyBzcGFyc2UgYXJyYXktbGlrZXMgYXMgaWYgdGhleSB3ZXJlIGRlbnNlLlxuICBfLmVhY2ggPSBfLmZvckVhY2ggPSBmdW5jdGlvbihvYmosIGl0ZXJhdGVlLCBjb250ZXh0KSB7XG4gICAgaXRlcmF0ZWUgPSBvcHRpbWl6ZUNiKGl0ZXJhdGVlLCBjb250ZXh0KTtcbiAgICB2YXIgaSwgbGVuZ3RoO1xuICAgIGlmIChpc0FycmF5TGlrZShvYmopKSB7XG4gICAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSBvYmoubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaXRlcmF0ZWUob2JqW2ldLCBpLCBvYmopO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xuICAgICAgZm9yIChpID0gMCwgbGVuZ3RoID0ga2V5cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBpdGVyYXRlZShvYmpba2V5c1tpXV0sIGtleXNbaV0sIG9iaik7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBvYmo7XG4gIH07XG5cbiAgLy8gUmV0dXJuIHRoZSByZXN1bHRzIG9mIGFwcGx5aW5nIHRoZSBpdGVyYXRlZSB0byBlYWNoIGVsZW1lbnQuXG4gIF8ubWFwID0gXy5jb2xsZWN0ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgY29udGV4dCkge1xuICAgIGl0ZXJhdGVlID0gY2IoaXRlcmF0ZWUsIGNvbnRleHQpO1xuICAgIHZhciBrZXlzID0gIWlzQXJyYXlMaWtlKG9iaikgJiYgXy5rZXlzKG9iaiksXG4gICAgICAgIGxlbmd0aCA9IChrZXlzIHx8IG9iaikubGVuZ3RoLFxuICAgICAgICByZXN1bHRzID0gQXJyYXkobGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICB2YXIgY3VycmVudEtleSA9IGtleXMgPyBrZXlzW2luZGV4XSA6IGluZGV4O1xuICAgICAgcmVzdWx0c1tpbmRleF0gPSBpdGVyYXRlZShvYmpbY3VycmVudEtleV0sIGN1cnJlbnRLZXksIG9iaik7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRzO1xuICB9O1xuXG4gIC8vIENyZWF0ZSBhIHJlZHVjaW5nIGZ1bmN0aW9uIGl0ZXJhdGluZyBsZWZ0IG9yIHJpZ2h0LlxuICBmdW5jdGlvbiBjcmVhdGVSZWR1Y2UoZGlyKSB7XG4gICAgLy8gT3B0aW1pemVkIGl0ZXJhdG9yIGZ1bmN0aW9uIGFzIHVzaW5nIGFyZ3VtZW50cy5sZW5ndGhcbiAgICAvLyBpbiB0aGUgbWFpbiBmdW5jdGlvbiB3aWxsIGRlb3B0aW1pemUgdGhlLCBzZWUgIzE5OTEuXG4gICAgZnVuY3Rpb24gaXRlcmF0b3Iob2JqLCBpdGVyYXRlZSwgbWVtbywga2V5cywgaW5kZXgsIGxlbmd0aCkge1xuICAgICAgZm9yICg7IGluZGV4ID49IDAgJiYgaW5kZXggPCBsZW5ndGg7IGluZGV4ICs9IGRpcikge1xuICAgICAgICB2YXIgY3VycmVudEtleSA9IGtleXMgPyBrZXlzW2luZGV4XSA6IGluZGV4O1xuICAgICAgICBtZW1vID0gaXRlcmF0ZWUobWVtbywgb2JqW2N1cnJlbnRLZXldLCBjdXJyZW50S2V5LCBvYmopO1xuICAgICAgfVxuICAgICAgcmV0dXJuIG1lbW87XG4gICAgfVxuXG4gICAgcmV0dXJuIGZ1bmN0aW9uKG9iaiwgaXRlcmF0ZWUsIG1lbW8sIGNvbnRleHQpIHtcbiAgICAgIGl0ZXJhdGVlID0gb3B0aW1pemVDYihpdGVyYXRlZSwgY29udGV4dCwgNCk7XG4gICAgICB2YXIga2V5cyA9ICFpc0FycmF5TGlrZShvYmopICYmIF8ua2V5cyhvYmopLFxuICAgICAgICAgIGxlbmd0aCA9IChrZXlzIHx8IG9iaikubGVuZ3RoLFxuICAgICAgICAgIGluZGV4ID0gZGlyID4gMCA/IDAgOiBsZW5ndGggLSAxO1xuICAgICAgLy8gRGV0ZXJtaW5lIHRoZSBpbml0aWFsIHZhbHVlIGlmIG5vbmUgaXMgcHJvdmlkZWQuXG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDMpIHtcbiAgICAgICAgbWVtbyA9IG9ialtrZXlzID8ga2V5c1tpbmRleF0gOiBpbmRleF07XG4gICAgICAgIGluZGV4ICs9IGRpcjtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpdGVyYXRvcihvYmosIGl0ZXJhdGVlLCBtZW1vLCBrZXlzLCBpbmRleCwgbGVuZ3RoKTtcbiAgICB9O1xuICB9XG5cbiAgLy8gKipSZWR1Y2UqKiBidWlsZHMgdXAgYSBzaW5nbGUgcmVzdWx0IGZyb20gYSBsaXN0IG9mIHZhbHVlcywgYWthIGBpbmplY3RgLFxuICAvLyBvciBgZm9sZGxgLlxuICBfLnJlZHVjZSA9IF8uZm9sZGwgPSBfLmluamVjdCA9IGNyZWF0ZVJlZHVjZSgxKTtcblxuICAvLyBUaGUgcmlnaHQtYXNzb2NpYXRpdmUgdmVyc2lvbiBvZiByZWR1Y2UsIGFsc28ga25vd24gYXMgYGZvbGRyYC5cbiAgXy5yZWR1Y2VSaWdodCA9IF8uZm9sZHIgPSBjcmVhdGVSZWR1Y2UoLTEpO1xuXG4gIC8vIFJldHVybiB0aGUgZmlyc3QgdmFsdWUgd2hpY2ggcGFzc2VzIGEgdHJ1dGggdGVzdC4gQWxpYXNlZCBhcyBgZGV0ZWN0YC5cbiAgXy5maW5kID0gXy5kZXRlY3QgPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkge1xuICAgIHZhciBrZXk7XG4gICAgaWYgKGlzQXJyYXlMaWtlKG9iaikpIHtcbiAgICAgIGtleSA9IF8uZmluZEluZGV4KG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KTtcbiAgICB9IGVsc2Uge1xuICAgICAga2V5ID0gXy5maW5kS2V5KG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KTtcbiAgICB9XG4gICAgaWYgKGtleSAhPT0gdm9pZCAwICYmIGtleSAhPT0gLTEpIHJldHVybiBvYmpba2V5XTtcbiAgfTtcblxuICAvLyBSZXR1cm4gYWxsIHRoZSBlbGVtZW50cyB0aGF0IHBhc3MgYSB0cnV0aCB0ZXN0LlxuICAvLyBBbGlhc2VkIGFzIGBzZWxlY3RgLlxuICBfLmZpbHRlciA9IF8uc2VsZWN0ID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcbiAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgIHByZWRpY2F0ZSA9IGNiKHByZWRpY2F0ZSwgY29udGV4dCk7XG4gICAgXy5lYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICBpZiAocHJlZGljYXRlKHZhbHVlLCBpbmRleCwgbGlzdCkpIHJlc3VsdHMucHVzaCh2YWx1ZSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH07XG5cbiAgLy8gUmV0dXJuIGFsbCB0aGUgZWxlbWVudHMgZm9yIHdoaWNoIGEgdHJ1dGggdGVzdCBmYWlscy5cbiAgXy5yZWplY3QgPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkge1xuICAgIHJldHVybiBfLmZpbHRlcihvYmosIF8ubmVnYXRlKGNiKHByZWRpY2F0ZSkpLCBjb250ZXh0KTtcbiAgfTtcblxuICAvLyBEZXRlcm1pbmUgd2hldGhlciBhbGwgb2YgdGhlIGVsZW1lbnRzIG1hdGNoIGEgdHJ1dGggdGVzdC5cbiAgLy8gQWxpYXNlZCBhcyBgYWxsYC5cbiAgXy5ldmVyeSA9IF8uYWxsID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcbiAgICBwcmVkaWNhdGUgPSBjYihwcmVkaWNhdGUsIGNvbnRleHQpO1xuICAgIHZhciBrZXlzID0gIWlzQXJyYXlMaWtlKG9iaikgJiYgXy5rZXlzKG9iaiksXG4gICAgICAgIGxlbmd0aCA9IChrZXlzIHx8IG9iaikubGVuZ3RoO1xuICAgIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgIHZhciBjdXJyZW50S2V5ID0ga2V5cyA/IGtleXNbaW5kZXhdIDogaW5kZXg7XG4gICAgICBpZiAoIXByZWRpY2F0ZShvYmpbY3VycmVudEtleV0sIGN1cnJlbnRLZXksIG9iaikpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG5cbiAgLy8gRGV0ZXJtaW5lIGlmIGF0IGxlYXN0IG9uZSBlbGVtZW50IGluIHRoZSBvYmplY3QgbWF0Y2hlcyBhIHRydXRoIHRlc3QuXG4gIC8vIEFsaWFzZWQgYXMgYGFueWAuXG4gIF8uc29tZSA9IF8uYW55ID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcbiAgICBwcmVkaWNhdGUgPSBjYihwcmVkaWNhdGUsIGNvbnRleHQpO1xuICAgIHZhciBrZXlzID0gIWlzQXJyYXlMaWtlKG9iaikgJiYgXy5rZXlzKG9iaiksXG4gICAgICAgIGxlbmd0aCA9IChrZXlzIHx8IG9iaikubGVuZ3RoO1xuICAgIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgIHZhciBjdXJyZW50S2V5ID0ga2V5cyA/IGtleXNbaW5kZXhdIDogaW5kZXg7XG4gICAgICBpZiAocHJlZGljYXRlKG9ialtjdXJyZW50S2V5XSwgY3VycmVudEtleSwgb2JqKSkgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcblxuICAvLyBEZXRlcm1pbmUgaWYgdGhlIGFycmF5IG9yIG9iamVjdCBjb250YWlucyBhIGdpdmVuIGl0ZW0gKHVzaW5nIGA9PT1gKS5cbiAgLy8gQWxpYXNlZCBhcyBgaW5jbHVkZXNgIGFuZCBgaW5jbHVkZWAuXG4gIF8uY29udGFpbnMgPSBfLmluY2x1ZGVzID0gXy5pbmNsdWRlID0gZnVuY3Rpb24ob2JqLCBpdGVtLCBmcm9tSW5kZXgsIGd1YXJkKSB7XG4gICAgaWYgKCFpc0FycmF5TGlrZShvYmopKSBvYmogPSBfLnZhbHVlcyhvYmopO1xuICAgIGlmICh0eXBlb2YgZnJvbUluZGV4ICE9ICdudW1iZXInIHx8IGd1YXJkKSBmcm9tSW5kZXggPSAwO1xuICAgIHJldHVybiBfLmluZGV4T2Yob2JqLCBpdGVtLCBmcm9tSW5kZXgpID49IDA7XG4gIH07XG5cbiAgLy8gSW52b2tlIGEgbWV0aG9kICh3aXRoIGFyZ3VtZW50cykgb24gZXZlcnkgaXRlbSBpbiBhIGNvbGxlY3Rpb24uXG4gIF8uaW52b2tlID0gZnVuY3Rpb24ob2JqLCBtZXRob2QpIHtcbiAgICB2YXIgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICB2YXIgaXNGdW5jID0gXy5pc0Z1bmN0aW9uKG1ldGhvZCk7XG4gICAgcmV0dXJuIF8ubWFwKG9iaiwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHZhciBmdW5jID0gaXNGdW5jID8gbWV0aG9kIDogdmFsdWVbbWV0aG9kXTtcbiAgICAgIHJldHVybiBmdW5jID09IG51bGwgPyBmdW5jIDogZnVuYy5hcHBseSh2YWx1ZSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gQ29udmVuaWVuY2UgdmVyc2lvbiBvZiBhIGNvbW1vbiB1c2UgY2FzZSBvZiBgbWFwYDogZmV0Y2hpbmcgYSBwcm9wZXJ0eS5cbiAgXy5wbHVjayA9IGZ1bmN0aW9uKG9iaiwga2V5KSB7XG4gICAgcmV0dXJuIF8ubWFwKG9iaiwgXy5wcm9wZXJ0eShrZXkpKTtcbiAgfTtcblxuICAvLyBDb252ZW5pZW5jZSB2ZXJzaW9uIG9mIGEgY29tbW9uIHVzZSBjYXNlIG9mIGBmaWx0ZXJgOiBzZWxlY3Rpbmcgb25seSBvYmplY3RzXG4gIC8vIGNvbnRhaW5pbmcgc3BlY2lmaWMgYGtleTp2YWx1ZWAgcGFpcnMuXG4gIF8ud2hlcmUgPSBmdW5jdGlvbihvYmosIGF0dHJzKSB7XG4gICAgcmV0dXJuIF8uZmlsdGVyKG9iaiwgXy5tYXRjaGVyKGF0dHJzKSk7XG4gIH07XG5cbiAgLy8gQ29udmVuaWVuY2UgdmVyc2lvbiBvZiBhIGNvbW1vbiB1c2UgY2FzZSBvZiBgZmluZGA6IGdldHRpbmcgdGhlIGZpcnN0IG9iamVjdFxuICAvLyBjb250YWluaW5nIHNwZWNpZmljIGBrZXk6dmFsdWVgIHBhaXJzLlxuICBfLmZpbmRXaGVyZSA9IGZ1bmN0aW9uKG9iaiwgYXR0cnMpIHtcbiAgICByZXR1cm4gXy5maW5kKG9iaiwgXy5tYXRjaGVyKGF0dHJzKSk7XG4gIH07XG5cbiAgLy8gUmV0dXJuIHRoZSBtYXhpbXVtIGVsZW1lbnQgKG9yIGVsZW1lbnQtYmFzZWQgY29tcHV0YXRpb24pLlxuICBfLm1heCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpIHtcbiAgICB2YXIgcmVzdWx0ID0gLUluZmluaXR5LCBsYXN0Q29tcHV0ZWQgPSAtSW5maW5pdHksXG4gICAgICAgIHZhbHVlLCBjb21wdXRlZDtcbiAgICBpZiAoaXRlcmF0ZWUgPT0gbnVsbCAmJiBvYmogIT0gbnVsbCkge1xuICAgICAgb2JqID0gaXNBcnJheUxpa2Uob2JqKSA/IG9iaiA6IF8udmFsdWVzKG9iaik7XG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gb2JqLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhbHVlID0gb2JqW2ldO1xuICAgICAgICBpZiAodmFsdWUgPiByZXN1bHQpIHtcbiAgICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBpdGVyYXRlZSA9IGNiKGl0ZXJhdGVlLCBjb250ZXh0KTtcbiAgICAgIF8uZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlKHZhbHVlLCBpbmRleCwgbGlzdCk7XG4gICAgICAgIGlmIChjb21wdXRlZCA+IGxhc3RDb21wdXRlZCB8fCBjb21wdXRlZCA9PT0gLUluZmluaXR5ICYmIHJlc3VsdCA9PT0gLUluZmluaXR5KSB7XG4gICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgICAgbGFzdENvbXB1dGVkID0gY29tcHV0ZWQ7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFJldHVybiB0aGUgbWluaW11bSBlbGVtZW50IChvciBlbGVtZW50LWJhc2VkIGNvbXB1dGF0aW9uKS5cbiAgXy5taW4gPSBmdW5jdGlvbihvYmosIGl0ZXJhdGVlLCBjb250ZXh0KSB7XG4gICAgdmFyIHJlc3VsdCA9IEluZmluaXR5LCBsYXN0Q29tcHV0ZWQgPSBJbmZpbml0eSxcbiAgICAgICAgdmFsdWUsIGNvbXB1dGVkO1xuICAgIGlmIChpdGVyYXRlZSA9PSBudWxsICYmIG9iaiAhPSBudWxsKSB7XG4gICAgICBvYmogPSBpc0FycmF5TGlrZShvYmopID8gb2JqIDogXy52YWx1ZXMob2JqKTtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBvYmoubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFsdWUgPSBvYmpbaV07XG4gICAgICAgIGlmICh2YWx1ZSA8IHJlc3VsdCkge1xuICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGl0ZXJhdGVlID0gY2IoaXRlcmF0ZWUsIGNvbnRleHQpO1xuICAgICAgXy5lYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUodmFsdWUsIGluZGV4LCBsaXN0KTtcbiAgICAgICAgaWYgKGNvbXB1dGVkIDwgbGFzdENvbXB1dGVkIHx8IGNvbXB1dGVkID09PSBJbmZpbml0eSAmJiByZXN1bHQgPT09IEluZmluaXR5KSB7XG4gICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgICAgbGFzdENvbXB1dGVkID0gY29tcHV0ZWQ7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFNodWZmbGUgYSBjb2xsZWN0aW9uLCB1c2luZyB0aGUgbW9kZXJuIHZlcnNpb24gb2YgdGhlXG4gIC8vIFtGaXNoZXItWWF0ZXMgc2h1ZmZsZV0oaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GaXNoZXLigJNZYXRlc19zaHVmZmxlKS5cbiAgXy5zaHVmZmxlID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIHNldCA9IGlzQXJyYXlMaWtlKG9iaikgPyBvYmogOiBfLnZhbHVlcyhvYmopO1xuICAgIHZhciBsZW5ndGggPSBzZXQubGVuZ3RoO1xuICAgIHZhciBzaHVmZmxlZCA9IEFycmF5KGxlbmd0aCk7XG4gICAgZm9yICh2YXIgaW5kZXggPSAwLCByYW5kOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgcmFuZCA9IF8ucmFuZG9tKDAsIGluZGV4KTtcbiAgICAgIGlmIChyYW5kICE9PSBpbmRleCkgc2h1ZmZsZWRbaW5kZXhdID0gc2h1ZmZsZWRbcmFuZF07XG4gICAgICBzaHVmZmxlZFtyYW5kXSA9IHNldFtpbmRleF07XG4gICAgfVxuICAgIHJldHVybiBzaHVmZmxlZDtcbiAgfTtcblxuICAvLyBTYW1wbGUgKipuKiogcmFuZG9tIHZhbHVlcyBmcm9tIGEgY29sbGVjdGlvbi5cbiAgLy8gSWYgKipuKiogaXMgbm90IHNwZWNpZmllZCwgcmV0dXJucyBhIHNpbmdsZSByYW5kb20gZWxlbWVudC5cbiAgLy8gVGhlIGludGVybmFsIGBndWFyZGAgYXJndW1lbnQgYWxsb3dzIGl0IHRvIHdvcmsgd2l0aCBgbWFwYC5cbiAgXy5zYW1wbGUgPSBmdW5jdGlvbihvYmosIG4sIGd1YXJkKSB7XG4gICAgaWYgKG4gPT0gbnVsbCB8fCBndWFyZCkge1xuICAgICAgaWYgKCFpc0FycmF5TGlrZShvYmopKSBvYmogPSBfLnZhbHVlcyhvYmopO1xuICAgICAgcmV0dXJuIG9ialtfLnJhbmRvbShvYmoubGVuZ3RoIC0gMSldO1xuICAgIH1cbiAgICByZXR1cm4gXy5zaHVmZmxlKG9iaikuc2xpY2UoMCwgTWF0aC5tYXgoMCwgbikpO1xuICB9O1xuXG4gIC8vIFNvcnQgdGhlIG9iamVjdCdzIHZhbHVlcyBieSBhIGNyaXRlcmlvbiBwcm9kdWNlZCBieSBhbiBpdGVyYXRlZS5cbiAgXy5zb3J0QnkgPSBmdW5jdGlvbihvYmosIGl0ZXJhdGVlLCBjb250ZXh0KSB7XG4gICAgaXRlcmF0ZWUgPSBjYihpdGVyYXRlZSwgY29udGV4dCk7XG4gICAgcmV0dXJuIF8ucGx1Y2soXy5tYXAob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHZhbHVlOiB2YWx1ZSxcbiAgICAgICAgaW5kZXg6IGluZGV4LFxuICAgICAgICBjcml0ZXJpYTogaXRlcmF0ZWUodmFsdWUsIGluZGV4LCBsaXN0KVxuICAgICAgfTtcbiAgICB9KS5zb3J0KGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7XG4gICAgICB2YXIgYSA9IGxlZnQuY3JpdGVyaWE7XG4gICAgICB2YXIgYiA9IHJpZ2h0LmNyaXRlcmlhO1xuICAgICAgaWYgKGEgIT09IGIpIHtcbiAgICAgICAgaWYgKGEgPiBiIHx8IGEgPT09IHZvaWQgMCkgcmV0dXJuIDE7XG4gICAgICAgIGlmIChhIDwgYiB8fCBiID09PSB2b2lkIDApIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBsZWZ0LmluZGV4IC0gcmlnaHQuaW5kZXg7XG4gICAgfSksICd2YWx1ZScpO1xuICB9O1xuXG4gIC8vIEFuIGludGVybmFsIGZ1bmN0aW9uIHVzZWQgZm9yIGFnZ3JlZ2F0ZSBcImdyb3VwIGJ5XCIgb3BlcmF0aW9ucy5cbiAgdmFyIGdyb3VwID0gZnVuY3Rpb24oYmVoYXZpb3IpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgY29udGV4dCkge1xuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgaXRlcmF0ZWUgPSBjYihpdGVyYXRlZSwgY29udGV4dCk7XG4gICAgICBfLmVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgpIHtcbiAgICAgICAgdmFyIGtleSA9IGl0ZXJhdGVlKHZhbHVlLCBpbmRleCwgb2JqKTtcbiAgICAgICAgYmVoYXZpb3IocmVzdWx0LCB2YWx1ZSwga2V5KTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICB9O1xuXG4gIC8vIEdyb3VwcyB0aGUgb2JqZWN0J3MgdmFsdWVzIGJ5IGEgY3JpdGVyaW9uLiBQYXNzIGVpdGhlciBhIHN0cmluZyBhdHRyaWJ1dGVcbiAgLy8gdG8gZ3JvdXAgYnksIG9yIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSBjcml0ZXJpb24uXG4gIF8uZ3JvdXBCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgIGlmIChfLmhhcyhyZXN1bHQsIGtleSkpIHJlc3VsdFtrZXldLnB1c2godmFsdWUpOyBlbHNlIHJlc3VsdFtrZXldID0gW3ZhbHVlXTtcbiAgfSk7XG5cbiAgLy8gSW5kZXhlcyB0aGUgb2JqZWN0J3MgdmFsdWVzIGJ5IGEgY3JpdGVyaW9uLCBzaW1pbGFyIHRvIGBncm91cEJ5YCwgYnV0IGZvclxuICAvLyB3aGVuIHlvdSBrbm93IHRoYXQgeW91ciBpbmRleCB2YWx1ZXMgd2lsbCBiZSB1bmlxdWUuXG4gIF8uaW5kZXhCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkge1xuICAgIHJlc3VsdFtrZXldID0gdmFsdWU7XG4gIH0pO1xuXG4gIC8vIENvdW50cyBpbnN0YW5jZXMgb2YgYW4gb2JqZWN0IHRoYXQgZ3JvdXAgYnkgYSBjZXJ0YWluIGNyaXRlcmlvbi4gUGFzc1xuICAvLyBlaXRoZXIgYSBzdHJpbmcgYXR0cmlidXRlIHRvIGNvdW50IGJ5LCBvciBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGVcbiAgLy8gY3JpdGVyaW9uLlxuICBfLmNvdW50QnkgPSBncm91cChmdW5jdGlvbihyZXN1bHQsIHZhbHVlLCBrZXkpIHtcbiAgICBpZiAoXy5oYXMocmVzdWx0LCBrZXkpKSByZXN1bHRba2V5XSsrOyBlbHNlIHJlc3VsdFtrZXldID0gMTtcbiAgfSk7XG5cbiAgLy8gU2FmZWx5IGNyZWF0ZSBhIHJlYWwsIGxpdmUgYXJyYXkgZnJvbSBhbnl0aGluZyBpdGVyYWJsZS5cbiAgXy50b0FycmF5ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYgKCFvYmopIHJldHVybiBbXTtcbiAgICBpZiAoXy5pc0FycmF5KG9iaikpIHJldHVybiBzbGljZS5jYWxsKG9iaik7XG4gICAgaWYgKGlzQXJyYXlMaWtlKG9iaikpIHJldHVybiBfLm1hcChvYmosIF8uaWRlbnRpdHkpO1xuICAgIHJldHVybiBfLnZhbHVlcyhvYmopO1xuICB9O1xuXG4gIC8vIFJldHVybiB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIGluIGFuIG9iamVjdC5cbiAgXy5zaXplID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gMDtcbiAgICByZXR1cm4gaXNBcnJheUxpa2Uob2JqKSA/IG9iai5sZW5ndGggOiBfLmtleXMob2JqKS5sZW5ndGg7XG4gIH07XG5cbiAgLy8gU3BsaXQgYSBjb2xsZWN0aW9uIGludG8gdHdvIGFycmF5czogb25lIHdob3NlIGVsZW1lbnRzIGFsbCBzYXRpc2Z5IHRoZSBnaXZlblxuICAvLyBwcmVkaWNhdGUsIGFuZCBvbmUgd2hvc2UgZWxlbWVudHMgYWxsIGRvIG5vdCBzYXRpc2Z5IHRoZSBwcmVkaWNhdGUuXG4gIF8ucGFydGl0aW9uID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcbiAgICBwcmVkaWNhdGUgPSBjYihwcmVkaWNhdGUsIGNvbnRleHQpO1xuICAgIHZhciBwYXNzID0gW10sIGZhaWwgPSBbXTtcbiAgICBfLmVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwga2V5LCBvYmopIHtcbiAgICAgIChwcmVkaWNhdGUodmFsdWUsIGtleSwgb2JqKSA/IHBhc3MgOiBmYWlsKS5wdXNoKHZhbHVlKTtcbiAgICB9KTtcbiAgICByZXR1cm4gW3Bhc3MsIGZhaWxdO1xuICB9O1xuXG4gIC8vIEFycmF5IEZ1bmN0aW9uc1xuICAvLyAtLS0tLS0tLS0tLS0tLS1cblxuICAvLyBHZXQgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYW4gYXJyYXkuIFBhc3NpbmcgKipuKiogd2lsbCByZXR1cm4gdGhlIGZpcnN0IE5cbiAgLy8gdmFsdWVzIGluIHRoZSBhcnJheS4gQWxpYXNlZCBhcyBgaGVhZGAgYW5kIGB0YWtlYC4gVGhlICoqZ3VhcmQqKiBjaGVja1xuICAvLyBhbGxvd3MgaXQgdG8gd29yayB3aXRoIGBfLm1hcGAuXG4gIF8uZmlyc3QgPSBfLmhlYWQgPSBfLnRha2UgPSBmdW5jdGlvbihhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICBpZiAoYXJyYXkgPT0gbnVsbCkgcmV0dXJuIHZvaWQgMDtcbiAgICBpZiAobiA9PSBudWxsIHx8IGd1YXJkKSByZXR1cm4gYXJyYXlbMF07XG4gICAgcmV0dXJuIF8uaW5pdGlhbChhcnJheSwgYXJyYXkubGVuZ3RoIC0gbik7XG4gIH07XG5cbiAgLy8gUmV0dXJucyBldmVyeXRoaW5nIGJ1dCB0aGUgbGFzdCBlbnRyeSBvZiB0aGUgYXJyYXkuIEVzcGVjaWFsbHkgdXNlZnVsIG9uXG4gIC8vIHRoZSBhcmd1bWVudHMgb2JqZWN0LiBQYXNzaW5nICoqbioqIHdpbGwgcmV0dXJuIGFsbCB0aGUgdmFsdWVzIGluXG4gIC8vIHRoZSBhcnJheSwgZXhjbHVkaW5nIHRoZSBsYXN0IE4uXG4gIF8uaW5pdGlhbCA9IGZ1bmN0aW9uKGFycmF5LCBuLCBndWFyZCkge1xuICAgIHJldHVybiBzbGljZS5jYWxsKGFycmF5LCAwLCBNYXRoLm1heCgwLCBhcnJheS5sZW5ndGggLSAobiA9PSBudWxsIHx8IGd1YXJkID8gMSA6IG4pKSk7XG4gIH07XG5cbiAgLy8gR2V0IHRoZSBsYXN0IGVsZW1lbnQgb2YgYW4gYXJyYXkuIFBhc3NpbmcgKipuKiogd2lsbCByZXR1cm4gdGhlIGxhc3QgTlxuICAvLyB2YWx1ZXMgaW4gdGhlIGFycmF5LlxuICBfLmxhc3QgPSBmdW5jdGlvbihhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICBpZiAoYXJyYXkgPT0gbnVsbCkgcmV0dXJuIHZvaWQgMDtcbiAgICBpZiAobiA9PSBudWxsIHx8IGd1YXJkKSByZXR1cm4gYXJyYXlbYXJyYXkubGVuZ3RoIC0gMV07XG4gICAgcmV0dXJuIF8ucmVzdChhcnJheSwgTWF0aC5tYXgoMCwgYXJyYXkubGVuZ3RoIC0gbikpO1xuICB9O1xuXG4gIC8vIFJldHVybnMgZXZlcnl0aGluZyBidXQgdGhlIGZpcnN0IGVudHJ5IG9mIHRoZSBhcnJheS4gQWxpYXNlZCBhcyBgdGFpbGAgYW5kIGBkcm9wYC5cbiAgLy8gRXNwZWNpYWxseSB1c2VmdWwgb24gdGhlIGFyZ3VtZW50cyBvYmplY3QuIFBhc3NpbmcgYW4gKipuKiogd2lsbCByZXR1cm5cbiAgLy8gdGhlIHJlc3QgTiB2YWx1ZXMgaW4gdGhlIGFycmF5LlxuICBfLnJlc3QgPSBfLnRhaWwgPSBfLmRyb3AgPSBmdW5jdGlvbihhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICByZXR1cm4gc2xpY2UuY2FsbChhcnJheSwgbiA9PSBudWxsIHx8IGd1YXJkID8gMSA6IG4pO1xuICB9O1xuXG4gIC8vIFRyaW0gb3V0IGFsbCBmYWxzeSB2YWx1ZXMgZnJvbSBhbiBhcnJheS5cbiAgXy5jb21wYWN0ID0gZnVuY3Rpb24oYXJyYXkpIHtcbiAgICByZXR1cm4gXy5maWx0ZXIoYXJyYXksIF8uaWRlbnRpdHkpO1xuICB9O1xuXG4gIC8vIEludGVybmFsIGltcGxlbWVudGF0aW9uIG9mIGEgcmVjdXJzaXZlIGBmbGF0dGVuYCBmdW5jdGlvbi5cbiAgdmFyIGZsYXR0ZW4gPSBmdW5jdGlvbihpbnB1dCwgc2hhbGxvdywgc3RyaWN0LCBzdGFydEluZGV4KSB7XG4gICAgdmFyIG91dHB1dCA9IFtdLCBpZHggPSAwO1xuICAgIGZvciAodmFyIGkgPSBzdGFydEluZGV4IHx8IDAsIGxlbmd0aCA9IGdldExlbmd0aChpbnB1dCk7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHZhbHVlID0gaW5wdXRbaV07XG4gICAgICBpZiAoaXNBcnJheUxpa2UodmFsdWUpICYmIChfLmlzQXJyYXkodmFsdWUpIHx8IF8uaXNBcmd1bWVudHModmFsdWUpKSkge1xuICAgICAgICAvL2ZsYXR0ZW4gY3VycmVudCBsZXZlbCBvZiBhcnJheSBvciBhcmd1bWVudHMgb2JqZWN0XG4gICAgICAgIGlmICghc2hhbGxvdykgdmFsdWUgPSBmbGF0dGVuKHZhbHVlLCBzaGFsbG93LCBzdHJpY3QpO1xuICAgICAgICB2YXIgaiA9IDAsIGxlbiA9IHZhbHVlLmxlbmd0aDtcbiAgICAgICAgb3V0cHV0Lmxlbmd0aCArPSBsZW47XG4gICAgICAgIHdoaWxlIChqIDwgbGVuKSB7XG4gICAgICAgICAgb3V0cHV0W2lkeCsrXSA9IHZhbHVlW2orK107XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoIXN0cmljdCkge1xuICAgICAgICBvdXRwdXRbaWR4KytdID0gdmFsdWU7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBvdXRwdXQ7XG4gIH07XG5cbiAgLy8gRmxhdHRlbiBvdXQgYW4gYXJyYXksIGVpdGhlciByZWN1cnNpdmVseSAoYnkgZGVmYXVsdCksIG9yIGp1c3Qgb25lIGxldmVsLlxuICBfLmZsYXR0ZW4gPSBmdW5jdGlvbihhcnJheSwgc2hhbGxvdykge1xuICAgIHJldHVybiBmbGF0dGVuKGFycmF5LCBzaGFsbG93LCBmYWxzZSk7XG4gIH07XG5cbiAgLy8gUmV0dXJuIGEgdmVyc2lvbiBvZiB0aGUgYXJyYXkgdGhhdCBkb2VzIG5vdCBjb250YWluIHRoZSBzcGVjaWZpZWQgdmFsdWUocykuXG4gIF8ud2l0aG91dCA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgcmV0dXJuIF8uZGlmZmVyZW5jZShhcnJheSwgc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgfTtcblxuICAvLyBQcm9kdWNlIGEgZHVwbGljYXRlLWZyZWUgdmVyc2lvbiBvZiB0aGUgYXJyYXkuIElmIHRoZSBhcnJheSBoYXMgYWxyZWFkeVxuICAvLyBiZWVuIHNvcnRlZCwgeW91IGhhdmUgdGhlIG9wdGlvbiBvZiB1c2luZyBhIGZhc3RlciBhbGdvcml0aG0uXG4gIC8vIEFsaWFzZWQgYXMgYHVuaXF1ZWAuXG4gIF8udW5pcSA9IF8udW5pcXVlID0gZnVuY3Rpb24oYXJyYXksIGlzU29ydGVkLCBpdGVyYXRlZSwgY29udGV4dCkge1xuICAgIGlmICghXy5pc0Jvb2xlYW4oaXNTb3J0ZWQpKSB7XG4gICAgICBjb250ZXh0ID0gaXRlcmF0ZWU7XG4gICAgICBpdGVyYXRlZSA9IGlzU29ydGVkO1xuICAgICAgaXNTb3J0ZWQgPSBmYWxzZTtcbiAgICB9XG4gICAgaWYgKGl0ZXJhdGVlICE9IG51bGwpIGl0ZXJhdGVlID0gY2IoaXRlcmF0ZWUsIGNvbnRleHQpO1xuICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICB2YXIgc2VlbiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBnZXRMZW5ndGgoYXJyYXkpOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciB2YWx1ZSA9IGFycmF5W2ldLFxuICAgICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUgPyBpdGVyYXRlZSh2YWx1ZSwgaSwgYXJyYXkpIDogdmFsdWU7XG4gICAgICBpZiAoaXNTb3J0ZWQpIHtcbiAgICAgICAgaWYgKCFpIHx8IHNlZW4gIT09IGNvbXB1dGVkKSByZXN1bHQucHVzaCh2YWx1ZSk7XG4gICAgICAgIHNlZW4gPSBjb21wdXRlZDtcbiAgICAgIH0gZWxzZSBpZiAoaXRlcmF0ZWUpIHtcbiAgICAgICAgaWYgKCFfLmNvbnRhaW5zKHNlZW4sIGNvbXB1dGVkKSkge1xuICAgICAgICAgIHNlZW4ucHVzaChjb21wdXRlZCk7XG4gICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKCFfLmNvbnRhaW5zKHJlc3VsdCwgdmFsdWUpKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBQcm9kdWNlIGFuIGFycmF5IHRoYXQgY29udGFpbnMgdGhlIHVuaW9uOiBlYWNoIGRpc3RpbmN0IGVsZW1lbnQgZnJvbSBhbGwgb2ZcbiAgLy8gdGhlIHBhc3NlZC1pbiBhcnJheXMuXG4gIF8udW5pb24gPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gXy51bmlxKGZsYXR0ZW4oYXJndW1lbnRzLCB0cnVlLCB0cnVlKSk7XG4gIH07XG5cbiAgLy8gUHJvZHVjZSBhbiBhcnJheSB0aGF0IGNvbnRhaW5zIGV2ZXJ5IGl0ZW0gc2hhcmVkIGJldHdlZW4gYWxsIHRoZVxuICAvLyBwYXNzZWQtaW4gYXJyYXlzLlxuICBfLmludGVyc2VjdGlvbiA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgIHZhciBhcmdzTGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gZ2V0TGVuZ3RoKGFycmF5KTsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgaXRlbSA9IGFycmF5W2ldO1xuICAgICAgaWYgKF8uY29udGFpbnMocmVzdWx0LCBpdGVtKSkgY29udGludWU7XG4gICAgICBmb3IgKHZhciBqID0gMTsgaiA8IGFyZ3NMZW5ndGg7IGorKykge1xuICAgICAgICBpZiAoIV8uY29udGFpbnMoYXJndW1lbnRzW2pdLCBpdGVtKSkgYnJlYWs7XG4gICAgICB9XG4gICAgICBpZiAoaiA9PT0gYXJnc0xlbmd0aCkgcmVzdWx0LnB1c2goaXRlbSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gVGFrZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIG9uZSBhcnJheSBhbmQgYSBudW1iZXIgb2Ygb3RoZXIgYXJyYXlzLlxuICAvLyBPbmx5IHRoZSBlbGVtZW50cyBwcmVzZW50IGluIGp1c3QgdGhlIGZpcnN0IGFycmF5IHdpbGwgcmVtYWluLlxuICBfLmRpZmZlcmVuY2UgPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHZhciByZXN0ID0gZmxhdHRlbihhcmd1bWVudHMsIHRydWUsIHRydWUsIDEpO1xuICAgIHJldHVybiBfLmZpbHRlcihhcnJheSwgZnVuY3Rpb24odmFsdWUpe1xuICAgICAgcmV0dXJuICFfLmNvbnRhaW5zKHJlc3QsIHZhbHVlKTtcbiAgICB9KTtcbiAgfTtcblxuICAvLyBaaXAgdG9nZXRoZXIgbXVsdGlwbGUgbGlzdHMgaW50byBhIHNpbmdsZSBhcnJheSAtLSBlbGVtZW50cyB0aGF0IHNoYXJlXG4gIC8vIGFuIGluZGV4IGdvIHRvZ2V0aGVyLlxuICBfLnppcCA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBfLnVuemlwKGFyZ3VtZW50cyk7XG4gIH07XG5cbiAgLy8gQ29tcGxlbWVudCBvZiBfLnppcC4gVW56aXAgYWNjZXB0cyBhbiBhcnJheSBvZiBhcnJheXMgYW5kIGdyb3Vwc1xuICAvLyBlYWNoIGFycmF5J3MgZWxlbWVudHMgb24gc2hhcmVkIGluZGljZXNcbiAgXy51bnppcCA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgdmFyIGxlbmd0aCA9IGFycmF5ICYmIF8ubWF4KGFycmF5LCBnZXRMZW5ndGgpLmxlbmd0aCB8fCAwO1xuICAgIHZhciByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgcmVzdWx0W2luZGV4XSA9IF8ucGx1Y2soYXJyYXksIGluZGV4KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBDb252ZXJ0cyBsaXN0cyBpbnRvIG9iamVjdHMuIFBhc3MgZWl0aGVyIGEgc2luZ2xlIGFycmF5IG9mIGBba2V5LCB2YWx1ZV1gXG4gIC8vIHBhaXJzLCBvciB0d28gcGFyYWxsZWwgYXJyYXlzIG9mIHRoZSBzYW1lIGxlbmd0aCAtLSBvbmUgb2Yga2V5cywgYW5kIG9uZSBvZlxuICAvLyB0aGUgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gIF8ub2JqZWN0ID0gZnVuY3Rpb24obGlzdCwgdmFsdWVzKSB7XG4gICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBnZXRMZW5ndGgobGlzdCk7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHZhbHVlcykge1xuICAgICAgICByZXN1bHRbbGlzdFtpXV0gPSB2YWx1ZXNbaV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHRbbGlzdFtpXVswXV0gPSBsaXN0W2ldWzFdO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIEdlbmVyYXRvciBmdW5jdGlvbiB0byBjcmVhdGUgdGhlIGZpbmRJbmRleCBhbmQgZmluZExhc3RJbmRleCBmdW5jdGlvbnNcbiAgZnVuY3Rpb24gY3JlYXRlUHJlZGljYXRlSW5kZXhGaW5kZXIoZGlyKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5LCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcbiAgICAgIHByZWRpY2F0ZSA9IGNiKHByZWRpY2F0ZSwgY29udGV4dCk7XG4gICAgICB2YXIgbGVuZ3RoID0gZ2V0TGVuZ3RoKGFycmF5KTtcbiAgICAgIHZhciBpbmRleCA9IGRpciA+IDAgPyAwIDogbGVuZ3RoIC0gMTtcbiAgICAgIGZvciAoOyBpbmRleCA+PSAwICYmIGluZGV4IDwgbGVuZ3RoOyBpbmRleCArPSBkaXIpIHtcbiAgICAgICAgaWYgKHByZWRpY2F0ZShhcnJheVtpbmRleF0sIGluZGV4LCBhcnJheSkpIHJldHVybiBpbmRleDtcbiAgICAgIH1cbiAgICAgIHJldHVybiAtMTtcbiAgICB9O1xuICB9XG5cbiAgLy8gUmV0dXJucyB0aGUgZmlyc3QgaW5kZXggb24gYW4gYXJyYXktbGlrZSB0aGF0IHBhc3NlcyBhIHByZWRpY2F0ZSB0ZXN0XG4gIF8uZmluZEluZGV4ID0gY3JlYXRlUHJlZGljYXRlSW5kZXhGaW5kZXIoMSk7XG4gIF8uZmluZExhc3RJbmRleCA9IGNyZWF0ZVByZWRpY2F0ZUluZGV4RmluZGVyKC0xKTtcblxuICAvLyBVc2UgYSBjb21wYXJhdG9yIGZ1bmN0aW9uIHRvIGZpZ3VyZSBvdXQgdGhlIHNtYWxsZXN0IGluZGV4IGF0IHdoaWNoXG4gIC8vIGFuIG9iamVjdCBzaG91bGQgYmUgaW5zZXJ0ZWQgc28gYXMgdG8gbWFpbnRhaW4gb3JkZXIuIFVzZXMgYmluYXJ5IHNlYXJjaC5cbiAgXy5zb3J0ZWRJbmRleCA9IGZ1bmN0aW9uKGFycmF5LCBvYmosIGl0ZXJhdGVlLCBjb250ZXh0KSB7XG4gICAgaXRlcmF0ZWUgPSBjYihpdGVyYXRlZSwgY29udGV4dCwgMSk7XG4gICAgdmFyIHZhbHVlID0gaXRlcmF0ZWUob2JqKTtcbiAgICB2YXIgbG93ID0gMCwgaGlnaCA9IGdldExlbmd0aChhcnJheSk7XG4gICAgd2hpbGUgKGxvdyA8IGhpZ2gpIHtcbiAgICAgIHZhciBtaWQgPSBNYXRoLmZsb29yKChsb3cgKyBoaWdoKSAvIDIpO1xuICAgICAgaWYgKGl0ZXJhdGVlKGFycmF5W21pZF0pIDwgdmFsdWUpIGxvdyA9IG1pZCArIDE7IGVsc2UgaGlnaCA9IG1pZDtcbiAgICB9XG4gICAgcmV0dXJuIGxvdztcbiAgfTtcblxuICAvLyBHZW5lcmF0b3IgZnVuY3Rpb24gdG8gY3JlYXRlIHRoZSBpbmRleE9mIGFuZCBsYXN0SW5kZXhPZiBmdW5jdGlvbnNcbiAgZnVuY3Rpb24gY3JlYXRlSW5kZXhGaW5kZXIoZGlyLCBwcmVkaWNhdGVGaW5kLCBzb3J0ZWRJbmRleCkge1xuICAgIHJldHVybiBmdW5jdGlvbihhcnJheSwgaXRlbSwgaWR4KSB7XG4gICAgICB2YXIgaSA9IDAsIGxlbmd0aCA9IGdldExlbmd0aChhcnJheSk7XG4gICAgICBpZiAodHlwZW9mIGlkeCA9PSAnbnVtYmVyJykge1xuICAgICAgICBpZiAoZGlyID4gMCkge1xuICAgICAgICAgICAgaSA9IGlkeCA+PSAwID8gaWR4IDogTWF0aC5tYXgoaWR4ICsgbGVuZ3RoLCBpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxlbmd0aCA9IGlkeCA+PSAwID8gTWF0aC5taW4oaWR4ICsgMSwgbGVuZ3RoKSA6IGlkeCArIGxlbmd0aCArIDE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoc29ydGVkSW5kZXggJiYgaWR4ICYmIGxlbmd0aCkge1xuICAgICAgICBpZHggPSBzb3J0ZWRJbmRleChhcnJheSwgaXRlbSk7XG4gICAgICAgIHJldHVybiBhcnJheVtpZHhdID09PSBpdGVtID8gaWR4IDogLTE7XG4gICAgICB9XG4gICAgICBpZiAoaXRlbSAhPT0gaXRlbSkge1xuICAgICAgICBpZHggPSBwcmVkaWNhdGVGaW5kKHNsaWNlLmNhbGwoYXJyYXksIGksIGxlbmd0aCksIF8uaXNOYU4pO1xuICAgICAgICByZXR1cm4gaWR4ID49IDAgPyBpZHggKyBpIDogLTE7XG4gICAgICB9XG4gICAgICBmb3IgKGlkeCA9IGRpciA+IDAgPyBpIDogbGVuZ3RoIC0gMTsgaWR4ID49IDAgJiYgaWR4IDwgbGVuZ3RoOyBpZHggKz0gZGlyKSB7XG4gICAgICAgIGlmIChhcnJheVtpZHhdID09PSBpdGVtKSByZXR1cm4gaWR4O1xuICAgICAgfVxuICAgICAgcmV0dXJuIC0xO1xuICAgIH07XG4gIH1cblxuICAvLyBSZXR1cm4gdGhlIHBvc2l0aW9uIG9mIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIGFuIGl0ZW0gaW4gYW4gYXJyYXksXG4gIC8vIG9yIC0xIGlmIHRoZSBpdGVtIGlzIG5vdCBpbmNsdWRlZCBpbiB0aGUgYXJyYXkuXG4gIC8vIElmIHRoZSBhcnJheSBpcyBsYXJnZSBhbmQgYWxyZWFkeSBpbiBzb3J0IG9yZGVyLCBwYXNzIGB0cnVlYFxuICAvLyBmb3IgKippc1NvcnRlZCoqIHRvIHVzZSBiaW5hcnkgc2VhcmNoLlxuICBfLmluZGV4T2YgPSBjcmVhdGVJbmRleEZpbmRlcigxLCBfLmZpbmRJbmRleCwgXy5zb3J0ZWRJbmRleCk7XG4gIF8ubGFzdEluZGV4T2YgPSBjcmVhdGVJbmRleEZpbmRlcigtMSwgXy5maW5kTGFzdEluZGV4KTtcblxuICAvLyBHZW5lcmF0ZSBhbiBpbnRlZ2VyIEFycmF5IGNvbnRhaW5pbmcgYW4gYXJpdGhtZXRpYyBwcm9ncmVzc2lvbi4gQSBwb3J0IG9mXG4gIC8vIHRoZSBuYXRpdmUgUHl0aG9uIGByYW5nZSgpYCBmdW5jdGlvbi4gU2VlXG4gIC8vIFt0aGUgUHl0aG9uIGRvY3VtZW50YXRpb25dKGh0dHA6Ly9kb2NzLnB5dGhvbi5vcmcvbGlicmFyeS9mdW5jdGlvbnMuaHRtbCNyYW5nZSkuXG4gIF8ucmFuZ2UgPSBmdW5jdGlvbihzdGFydCwgc3RvcCwgc3RlcCkge1xuICAgIGlmIChzdG9wID09IG51bGwpIHtcbiAgICAgIHN0b3AgPSBzdGFydCB8fCAwO1xuICAgICAgc3RhcnQgPSAwO1xuICAgIH1cbiAgICBzdGVwID0gc3RlcCB8fCAxO1xuXG4gICAgdmFyIGxlbmd0aCA9IE1hdGgubWF4KE1hdGguY2VpbCgoc3RvcCAtIHN0YXJ0KSAvIHN0ZXApLCAwKTtcbiAgICB2YXIgcmFuZ2UgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgZm9yICh2YXIgaWR4ID0gMDsgaWR4IDwgbGVuZ3RoOyBpZHgrKywgc3RhcnQgKz0gc3RlcCkge1xuICAgICAgcmFuZ2VbaWR4XSA9IHN0YXJ0O1xuICAgIH1cblxuICAgIHJldHVybiByYW5nZTtcbiAgfTtcblxuICAvLyBGdW5jdGlvbiAoYWhlbSkgRnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIERldGVybWluZXMgd2hldGhlciB0byBleGVjdXRlIGEgZnVuY3Rpb24gYXMgYSBjb25zdHJ1Y3RvclxuICAvLyBvciBhIG5vcm1hbCBmdW5jdGlvbiB3aXRoIHRoZSBwcm92aWRlZCBhcmd1bWVudHNcbiAgdmFyIGV4ZWN1dGVCb3VuZCA9IGZ1bmN0aW9uKHNvdXJjZUZ1bmMsIGJvdW5kRnVuYywgY29udGV4dCwgY2FsbGluZ0NvbnRleHQsIGFyZ3MpIHtcbiAgICBpZiAoIShjYWxsaW5nQ29udGV4dCBpbnN0YW5jZW9mIGJvdW5kRnVuYykpIHJldHVybiBzb3VyY2VGdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgIHZhciBzZWxmID0gYmFzZUNyZWF0ZShzb3VyY2VGdW5jLnByb3RvdHlwZSk7XG4gICAgdmFyIHJlc3VsdCA9IHNvdXJjZUZ1bmMuYXBwbHkoc2VsZiwgYXJncyk7XG4gICAgaWYgKF8uaXNPYmplY3QocmVzdWx0KSkgcmV0dXJuIHJlc3VsdDtcbiAgICByZXR1cm4gc2VsZjtcbiAgfTtcblxuICAvLyBDcmVhdGUgYSBmdW5jdGlvbiBib3VuZCB0byBhIGdpdmVuIG9iamVjdCAoYXNzaWduaW5nIGB0aGlzYCwgYW5kIGFyZ3VtZW50cyxcbiAgLy8gb3B0aW9uYWxseSkuIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBGdW5jdGlvbi5iaW5kYCBpZlxuICAvLyBhdmFpbGFibGUuXG4gIF8uYmluZCA9IGZ1bmN0aW9uKGZ1bmMsIGNvbnRleHQpIHtcbiAgICBpZiAobmF0aXZlQmluZCAmJiBmdW5jLmJpbmQgPT09IG5hdGl2ZUJpbmQpIHJldHVybiBuYXRpdmVCaW5kLmFwcGx5KGZ1bmMsIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgaWYgKCFfLmlzRnVuY3Rpb24oZnVuYykpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0JpbmQgbXVzdCBiZSBjYWxsZWQgb24gYSBmdW5jdGlvbicpO1xuICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgIHZhciBib3VuZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIGV4ZWN1dGVCb3VuZChmdW5jLCBib3VuZCwgY29udGV4dCwgdGhpcywgYXJncy5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7XG4gICAgfTtcbiAgICByZXR1cm4gYm91bmQ7XG4gIH07XG5cbiAgLy8gUGFydGlhbGx5IGFwcGx5IGEgZnVuY3Rpb24gYnkgY3JlYXRpbmcgYSB2ZXJzaW9uIHRoYXQgaGFzIGhhZCBzb21lIG9mIGl0c1xuICAvLyBhcmd1bWVudHMgcHJlLWZpbGxlZCwgd2l0aG91dCBjaGFuZ2luZyBpdHMgZHluYW1pYyBgdGhpc2AgY29udGV4dC4gXyBhY3RzXG4gIC8vIGFzIGEgcGxhY2Vob2xkZXIsIGFsbG93aW5nIGFueSBjb21iaW5hdGlvbiBvZiBhcmd1bWVudHMgdG8gYmUgcHJlLWZpbGxlZC5cbiAgXy5wYXJ0aWFsID0gZnVuY3Rpb24oZnVuYykge1xuICAgIHZhciBib3VuZEFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgdmFyIGJvdW5kID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcG9zaXRpb24gPSAwLCBsZW5ndGggPSBib3VuZEFyZ3MubGVuZ3RoO1xuICAgICAgdmFyIGFyZ3MgPSBBcnJheShsZW5ndGgpO1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBhcmdzW2ldID0gYm91bmRBcmdzW2ldID09PSBfID8gYXJndW1lbnRzW3Bvc2l0aW9uKytdIDogYm91bmRBcmdzW2ldO1xuICAgICAgfVxuICAgICAgd2hpbGUgKHBvc2l0aW9uIDwgYXJndW1lbnRzLmxlbmd0aCkgYXJncy5wdXNoKGFyZ3VtZW50c1twb3NpdGlvbisrXSk7XG4gICAgICByZXR1cm4gZXhlY3V0ZUJvdW5kKGZ1bmMsIGJvdW5kLCB0aGlzLCB0aGlzLCBhcmdzKTtcbiAgICB9O1xuICAgIHJldHVybiBib3VuZDtcbiAgfTtcblxuICAvLyBCaW5kIGEgbnVtYmVyIG9mIGFuIG9iamVjdCdzIG1ldGhvZHMgdG8gdGhhdCBvYmplY3QuIFJlbWFpbmluZyBhcmd1bWVudHNcbiAgLy8gYXJlIHRoZSBtZXRob2QgbmFtZXMgdG8gYmUgYm91bmQuIFVzZWZ1bCBmb3IgZW5zdXJpbmcgdGhhdCBhbGwgY2FsbGJhY2tzXG4gIC8vIGRlZmluZWQgb24gYW4gb2JqZWN0IGJlbG9uZyB0byBpdC5cbiAgXy5iaW5kQWxsID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIGksIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsIGtleTtcbiAgICBpZiAobGVuZ3RoIDw9IDEpIHRocm93IG5ldyBFcnJvcignYmluZEFsbCBtdXN0IGJlIHBhc3NlZCBmdW5jdGlvbiBuYW1lcycpO1xuICAgIGZvciAoaSA9IDE7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAga2V5ID0gYXJndW1lbnRzW2ldO1xuICAgICAgb2JqW2tleV0gPSBfLmJpbmQob2JqW2tleV0sIG9iaik7XG4gICAgfVxuICAgIHJldHVybiBvYmo7XG4gIH07XG5cbiAgLy8gTWVtb2l6ZSBhbiBleHBlbnNpdmUgZnVuY3Rpb24gYnkgc3RvcmluZyBpdHMgcmVzdWx0cy5cbiAgXy5tZW1vaXplID0gZnVuY3Rpb24oZnVuYywgaGFzaGVyKSB7XG4gICAgdmFyIG1lbW9pemUgPSBmdW5jdGlvbihrZXkpIHtcbiAgICAgIHZhciBjYWNoZSA9IG1lbW9pemUuY2FjaGU7XG4gICAgICB2YXIgYWRkcmVzcyA9ICcnICsgKGhhc2hlciA/IGhhc2hlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpIDoga2V5KTtcbiAgICAgIGlmICghXy5oYXMoY2FjaGUsIGFkZHJlc3MpKSBjYWNoZVthZGRyZXNzXSA9IGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIHJldHVybiBjYWNoZVthZGRyZXNzXTtcbiAgICB9O1xuICAgIG1lbW9pemUuY2FjaGUgPSB7fTtcbiAgICByZXR1cm4gbWVtb2l6ZTtcbiAgfTtcblxuICAvLyBEZWxheXMgYSBmdW5jdGlvbiBmb3IgdGhlIGdpdmVuIG51bWJlciBvZiBtaWxsaXNlY29uZHMsIGFuZCB0aGVuIGNhbGxzXG4gIC8vIGl0IHdpdGggdGhlIGFyZ3VtZW50cyBzdXBwbGllZC5cbiAgXy5kZWxheSA9IGZ1bmN0aW9uKGZ1bmMsIHdhaXQpIHtcbiAgICB2YXIgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICByZXR1cm4gc2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkobnVsbCwgYXJncyk7XG4gICAgfSwgd2FpdCk7XG4gIH07XG5cbiAgLy8gRGVmZXJzIGEgZnVuY3Rpb24sIHNjaGVkdWxpbmcgaXQgdG8gcnVuIGFmdGVyIHRoZSBjdXJyZW50IGNhbGwgc3RhY2sgaGFzXG4gIC8vIGNsZWFyZWQuXG4gIF8uZGVmZXIgPSBfLnBhcnRpYWwoXy5kZWxheSwgXywgMSk7XG5cbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uLCB0aGF0LCB3aGVuIGludm9rZWQsIHdpbGwgb25seSBiZSB0cmlnZ2VyZWQgYXQgbW9zdCBvbmNlXG4gIC8vIGR1cmluZyBhIGdpdmVuIHdpbmRvdyBvZiB0aW1lLiBOb3JtYWxseSwgdGhlIHRocm90dGxlZCBmdW5jdGlvbiB3aWxsIHJ1blxuICAvLyBhcyBtdWNoIGFzIGl0IGNhbiwgd2l0aG91dCBldmVyIGdvaW5nIG1vcmUgdGhhbiBvbmNlIHBlciBgd2FpdGAgZHVyYXRpb247XG4gIC8vIGJ1dCBpZiB5b3UnZCBsaWtlIHRvIGRpc2FibGUgdGhlIGV4ZWN1dGlvbiBvbiB0aGUgbGVhZGluZyBlZGdlLCBwYXNzXG4gIC8vIGB7bGVhZGluZzogZmFsc2V9YC4gVG8gZGlzYWJsZSBleGVjdXRpb24gb24gdGhlIHRyYWlsaW5nIGVkZ2UsIGRpdHRvLlxuICBfLnRocm90dGxlID0gZnVuY3Rpb24oZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICAgIHZhciBjb250ZXh0LCBhcmdzLCByZXN1bHQ7XG4gICAgdmFyIHRpbWVvdXQgPSBudWxsO1xuICAgIHZhciBwcmV2aW91cyA9IDA7XG4gICAgaWYgKCFvcHRpb25zKSBvcHRpb25zID0ge307XG4gICAgdmFyIGxhdGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICBwcmV2aW91cyA9IG9wdGlvbnMubGVhZGluZyA9PT0gZmFsc2UgPyAwIDogXy5ub3coKTtcbiAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgIGlmICghdGltZW91dCkgY29udGV4dCA9IGFyZ3MgPSBudWxsO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIG5vdyA9IF8ubm93KCk7XG4gICAgICBpZiAoIXByZXZpb3VzICYmIG9wdGlvbnMubGVhZGluZyA9PT0gZmFsc2UpIHByZXZpb3VzID0gbm93O1xuICAgICAgdmFyIHJlbWFpbmluZyA9IHdhaXQgLSAobm93IC0gcHJldmlvdXMpO1xuICAgICAgY29udGV4dCA9IHRoaXM7XG4gICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgaWYgKHJlbWFpbmluZyA8PSAwIHx8IHJlbWFpbmluZyA+IHdhaXQpIHtcbiAgICAgICAgaWYgKHRpbWVvdXQpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgICAgdGltZW91dCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgcHJldmlvdXMgPSBub3c7XG4gICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgIGlmICghdGltZW91dCkgY29udGV4dCA9IGFyZ3MgPSBudWxsO1xuICAgICAgfSBlbHNlIGlmICghdGltZW91dCAmJiBvcHRpb25zLnRyYWlsaW5nICE9PSBmYWxzZSkge1xuICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgcmVtYWluaW5nKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24sIHRoYXQsIGFzIGxvbmcgYXMgaXQgY29udGludWVzIHRvIGJlIGludm9rZWQsIHdpbGwgbm90XG4gIC8vIGJlIHRyaWdnZXJlZC4gVGhlIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIGFmdGVyIGl0IHN0b3BzIGJlaW5nIGNhbGxlZCBmb3JcbiAgLy8gTiBtaWxsaXNlY29uZHMuIElmIGBpbW1lZGlhdGVgIGlzIHBhc3NlZCwgdHJpZ2dlciB0aGUgZnVuY3Rpb24gb24gdGhlXG4gIC8vIGxlYWRpbmcgZWRnZSwgaW5zdGVhZCBvZiB0aGUgdHJhaWxpbmcuXG4gIF8uZGVib3VuY2UgPSBmdW5jdGlvbihmdW5jLCB3YWl0LCBpbW1lZGlhdGUpIHtcbiAgICB2YXIgdGltZW91dCwgYXJncywgY29udGV4dCwgdGltZXN0YW1wLCByZXN1bHQ7XG5cbiAgICB2YXIgbGF0ZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBsYXN0ID0gXy5ub3coKSAtIHRpbWVzdGFtcDtcblxuICAgICAgaWYgKGxhc3QgPCB3YWl0ICYmIGxhc3QgPj0gMCkge1xuICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgd2FpdCAtIGxhc3QpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGltZW91dCA9IG51bGw7XG4gICAgICAgIGlmICghaW1tZWRpYXRlKSB7XG4gICAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgICBpZiAoIXRpbWVvdXQpIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBjb250ZXh0ID0gdGhpcztcbiAgICAgIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICB0aW1lc3RhbXAgPSBfLm5vdygpO1xuICAgICAgdmFyIGNhbGxOb3cgPSBpbW1lZGlhdGUgJiYgIXRpbWVvdXQ7XG4gICAgICBpZiAoIXRpbWVvdXQpIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCB3YWl0KTtcbiAgICAgIGlmIChjYWxsTm93KSB7XG4gICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgdGhlIGZpcnN0IGZ1bmN0aW9uIHBhc3NlZCBhcyBhbiBhcmd1bWVudCB0byB0aGUgc2Vjb25kLFxuICAvLyBhbGxvd2luZyB5b3UgdG8gYWRqdXN0IGFyZ3VtZW50cywgcnVuIGNvZGUgYmVmb3JlIGFuZCBhZnRlciwgYW5kXG4gIC8vIGNvbmRpdGlvbmFsbHkgZXhlY3V0ZSB0aGUgb3JpZ2luYWwgZnVuY3Rpb24uXG4gIF8ud3JhcCA9IGZ1bmN0aW9uKGZ1bmMsIHdyYXBwZXIpIHtcbiAgICByZXR1cm4gXy5wYXJ0aWFsKHdyYXBwZXIsIGZ1bmMpO1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBuZWdhdGVkIHZlcnNpb24gb2YgdGhlIHBhc3NlZC1pbiBwcmVkaWNhdGUuXG4gIF8ubmVnYXRlID0gZnVuY3Rpb24ocHJlZGljYXRlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuICFwcmVkaWNhdGUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiB0aGF0IGlzIHRoZSBjb21wb3NpdGlvbiBvZiBhIGxpc3Qgb2YgZnVuY3Rpb25zLCBlYWNoXG4gIC8vIGNvbnN1bWluZyB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBmdW5jdGlvbiB0aGF0IGZvbGxvd3MuXG4gIF8uY29tcG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgIHZhciBzdGFydCA9IGFyZ3MubGVuZ3RoIC0gMTtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgaSA9IHN0YXJ0O1xuICAgICAgdmFyIHJlc3VsdCA9IGFyZ3Nbc3RhcnRdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB3aGlsZSAoaS0tKSByZXN1bHQgPSBhcmdzW2ldLmNhbGwodGhpcywgcmVzdWx0KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCB3aWxsIG9ubHkgYmUgZXhlY3V0ZWQgb24gYW5kIGFmdGVyIHRoZSBOdGggY2FsbC5cbiAgXy5hZnRlciA9IGZ1bmN0aW9uKHRpbWVzLCBmdW5jKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKC0tdGltZXMgPCAxKSB7XG4gICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB9XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCB3aWxsIG9ubHkgYmUgZXhlY3V0ZWQgdXAgdG8gKGJ1dCBub3QgaW5jbHVkaW5nKSB0aGUgTnRoIGNhbGwuXG4gIF8uYmVmb3JlID0gZnVuY3Rpb24odGltZXMsIGZ1bmMpIHtcbiAgICB2YXIgbWVtbztcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoLS10aW1lcyA+IDApIHtcbiAgICAgICAgbWVtbyA9IGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIH1cbiAgICAgIGlmICh0aW1lcyA8PSAxKSBmdW5jID0gbnVsbDtcbiAgICAgIHJldHVybiBtZW1vO1xuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBleGVjdXRlZCBhdCBtb3N0IG9uZSB0aW1lLCBubyBtYXR0ZXIgaG93XG4gIC8vIG9mdGVuIHlvdSBjYWxsIGl0LiBVc2VmdWwgZm9yIGxhenkgaW5pdGlhbGl6YXRpb24uXG4gIF8ub25jZSA9IF8ucGFydGlhbChfLmJlZm9yZSwgMik7XG5cbiAgLy8gT2JqZWN0IEZ1bmN0aW9uc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tXG5cbiAgLy8gS2V5cyBpbiBJRSA8IDkgdGhhdCB3b24ndCBiZSBpdGVyYXRlZCBieSBgZm9yIGtleSBpbiAuLi5gIGFuZCB0aHVzIG1pc3NlZC5cbiAgdmFyIGhhc0VudW1CdWcgPSAhe3RvU3RyaW5nOiBudWxsfS5wcm9wZXJ0eUlzRW51bWVyYWJsZSgndG9TdHJpbmcnKTtcbiAgdmFyIG5vbkVudW1lcmFibGVQcm9wcyA9IFsndmFsdWVPZicsICdpc1Byb3RvdHlwZU9mJywgJ3RvU3RyaW5nJyxcbiAgICAgICAgICAgICAgICAgICAgICAncHJvcGVydHlJc0VudW1lcmFibGUnLCAnaGFzT3duUHJvcGVydHknLCAndG9Mb2NhbGVTdHJpbmcnXTtcblxuICBmdW5jdGlvbiBjb2xsZWN0Tm9uRW51bVByb3BzKG9iaiwga2V5cykge1xuICAgIHZhciBub25FbnVtSWR4ID0gbm9uRW51bWVyYWJsZVByb3BzLmxlbmd0aDtcbiAgICB2YXIgY29uc3RydWN0b3IgPSBvYmouY29uc3RydWN0b3I7XG4gICAgdmFyIHByb3RvID0gKF8uaXNGdW5jdGlvbihjb25zdHJ1Y3RvcikgJiYgY29uc3RydWN0b3IucHJvdG90eXBlKSB8fCBPYmpQcm90bztcblxuICAgIC8vIENvbnN0cnVjdG9yIGlzIGEgc3BlY2lhbCBjYXNlLlxuICAgIHZhciBwcm9wID0gJ2NvbnN0cnVjdG9yJztcbiAgICBpZiAoXy5oYXMob2JqLCBwcm9wKSAmJiAhXy5jb250YWlucyhrZXlzLCBwcm9wKSkga2V5cy5wdXNoKHByb3ApO1xuXG4gICAgd2hpbGUgKG5vbkVudW1JZHgtLSkge1xuICAgICAgcHJvcCA9IG5vbkVudW1lcmFibGVQcm9wc1tub25FbnVtSWR4XTtcbiAgICAgIGlmIChwcm9wIGluIG9iaiAmJiBvYmpbcHJvcF0gIT09IHByb3RvW3Byb3BdICYmICFfLmNvbnRhaW5zKGtleXMsIHByb3ApKSB7XG4gICAgICAgIGtleXMucHVzaChwcm9wKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBSZXRyaWV2ZSB0aGUgbmFtZXMgb2YgYW4gb2JqZWN0J3Mgb3duIHByb3BlcnRpZXMuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBPYmplY3Qua2V5c2BcbiAgXy5rZXlzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYgKCFfLmlzT2JqZWN0KG9iaikpIHJldHVybiBbXTtcbiAgICBpZiAobmF0aXZlS2V5cykgcmV0dXJuIG5hdGl2ZUtleXMob2JqKTtcbiAgICB2YXIga2V5cyA9IFtdO1xuICAgIGZvciAodmFyIGtleSBpbiBvYmopIGlmIChfLmhhcyhvYmosIGtleSkpIGtleXMucHVzaChrZXkpO1xuICAgIC8vIEFoZW0sIElFIDwgOS5cbiAgICBpZiAoaGFzRW51bUJ1ZykgY29sbGVjdE5vbkVudW1Qcm9wcyhvYmosIGtleXMpO1xuICAgIHJldHVybiBrZXlzO1xuICB9O1xuXG4gIC8vIFJldHJpZXZlIGFsbCB0aGUgcHJvcGVydHkgbmFtZXMgb2YgYW4gb2JqZWN0LlxuICBfLmFsbEtleXMgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAoIV8uaXNPYmplY3Qob2JqKSkgcmV0dXJuIFtdO1xuICAgIHZhciBrZXlzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikga2V5cy5wdXNoKGtleSk7XG4gICAgLy8gQWhlbSwgSUUgPCA5LlxuICAgIGlmIChoYXNFbnVtQnVnKSBjb2xsZWN0Tm9uRW51bVByb3BzKG9iaiwga2V5cyk7XG4gICAgcmV0dXJuIGtleXM7XG4gIH07XG5cbiAgLy8gUmV0cmlldmUgdGhlIHZhbHVlcyBvZiBhbiBvYmplY3QncyBwcm9wZXJ0aWVzLlxuICBfLnZhbHVlcyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgIHZhciB2YWx1ZXMgPSBBcnJheShsZW5ndGgpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhbHVlc1tpXSA9IG9ialtrZXlzW2ldXTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlcztcbiAgfTtcblxuICAvLyBSZXR1cm5zIHRoZSByZXN1bHRzIG9mIGFwcGx5aW5nIHRoZSBpdGVyYXRlZSB0byBlYWNoIGVsZW1lbnQgb2YgdGhlIG9iamVjdFxuICAvLyBJbiBjb250cmFzdCB0byBfLm1hcCBpdCByZXR1cm5zIGFuIG9iamVjdFxuICBfLm1hcE9iamVjdCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpIHtcbiAgICBpdGVyYXRlZSA9IGNiKGl0ZXJhdGVlLCBjb250ZXh0KTtcbiAgICB2YXIga2V5cyA9ICBfLmtleXMob2JqKSxcbiAgICAgICAgICBsZW5ndGggPSBrZXlzLmxlbmd0aCxcbiAgICAgICAgICByZXN1bHRzID0ge30sXG4gICAgICAgICAgY3VycmVudEtleTtcbiAgICAgIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICAgICAgY3VycmVudEtleSA9IGtleXNbaW5kZXhdO1xuICAgICAgICByZXN1bHRzW2N1cnJlbnRLZXldID0gaXRlcmF0ZWUob2JqW2N1cnJlbnRLZXldLCBjdXJyZW50S2V5LCBvYmopO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gIH07XG5cbiAgLy8gQ29udmVydCBhbiBvYmplY3QgaW50byBhIGxpc3Qgb2YgYFtrZXksIHZhbHVlXWAgcGFpcnMuXG4gIF8ucGFpcnMgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xuICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgICB2YXIgcGFpcnMgPSBBcnJheShsZW5ndGgpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHBhaXJzW2ldID0gW2tleXNbaV0sIG9ialtrZXlzW2ldXV07XG4gICAgfVxuICAgIHJldHVybiBwYWlycztcbiAgfTtcblxuICAvLyBJbnZlcnQgdGhlIGtleXMgYW5kIHZhbHVlcyBvZiBhbiBvYmplY3QuIFRoZSB2YWx1ZXMgbXVzdCBiZSBzZXJpYWxpemFibGUuXG4gIF8uaW52ZXJ0ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHJlc3VsdFtvYmpba2V5c1tpXV1dID0ga2V5c1tpXTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBSZXR1cm4gYSBzb3J0ZWQgbGlzdCBvZiB0aGUgZnVuY3Rpb24gbmFtZXMgYXZhaWxhYmxlIG9uIHRoZSBvYmplY3QuXG4gIC8vIEFsaWFzZWQgYXMgYG1ldGhvZHNgXG4gIF8uZnVuY3Rpb25zID0gXy5tZXRob2RzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIG5hbWVzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgaWYgKF8uaXNGdW5jdGlvbihvYmpba2V5XSkpIG5hbWVzLnB1c2goa2V5KTtcbiAgICB9XG4gICAgcmV0dXJuIG5hbWVzLnNvcnQoKTtcbiAgfTtcblxuICAvLyBFeHRlbmQgYSBnaXZlbiBvYmplY3Qgd2l0aCBhbGwgdGhlIHByb3BlcnRpZXMgaW4gcGFzc2VkLWluIG9iamVjdChzKS5cbiAgXy5leHRlbmQgPSBjcmVhdGVBc3NpZ25lcihfLmFsbEtleXMpO1xuXG4gIC8vIEFzc2lnbnMgYSBnaXZlbiBvYmplY3Qgd2l0aCBhbGwgdGhlIG93biBwcm9wZXJ0aWVzIGluIHRoZSBwYXNzZWQtaW4gb2JqZWN0KHMpXG4gIC8vIChodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9PYmplY3QvYXNzaWduKVxuICBfLmV4dGVuZE93biA9IF8uYXNzaWduID0gY3JlYXRlQXNzaWduZXIoXy5rZXlzKTtcblxuICAvLyBSZXR1cm5zIHRoZSBmaXJzdCBrZXkgb24gYW4gb2JqZWN0IHRoYXQgcGFzc2VzIGEgcHJlZGljYXRlIHRlc3RcbiAgXy5maW5kS2V5ID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcbiAgICBwcmVkaWNhdGUgPSBjYihwcmVkaWNhdGUsIGNvbnRleHQpO1xuICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaiksIGtleTtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0ga2V5cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAga2V5ID0ga2V5c1tpXTtcbiAgICAgIGlmIChwcmVkaWNhdGUob2JqW2tleV0sIGtleSwgb2JqKSkgcmV0dXJuIGtleTtcbiAgICB9XG4gIH07XG5cbiAgLy8gUmV0dXJuIGEgY29weSBvZiB0aGUgb2JqZWN0IG9ubHkgY29udGFpbmluZyB0aGUgd2hpdGVsaXN0ZWQgcHJvcGVydGllcy5cbiAgXy5waWNrID0gZnVuY3Rpb24ob2JqZWN0LCBvaXRlcmF0ZWUsIGNvbnRleHQpIHtcbiAgICB2YXIgcmVzdWx0ID0ge30sIG9iaiA9IG9iamVjdCwgaXRlcmF0ZWUsIGtleXM7XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gcmVzdWx0O1xuICAgIGlmIChfLmlzRnVuY3Rpb24ob2l0ZXJhdGVlKSkge1xuICAgICAga2V5cyA9IF8uYWxsS2V5cyhvYmopO1xuICAgICAgaXRlcmF0ZWUgPSBvcHRpbWl6ZUNiKG9pdGVyYXRlZSwgY29udGV4dCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGtleXMgPSBmbGF0dGVuKGFyZ3VtZW50cywgZmFsc2UsIGZhbHNlLCAxKTtcbiAgICAgIGl0ZXJhdGVlID0gZnVuY3Rpb24odmFsdWUsIGtleSwgb2JqKSB7IHJldHVybiBrZXkgaW4gb2JqOyB9O1xuICAgICAgb2JqID0gT2JqZWN0KG9iaik7XG4gICAgfVxuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBrZXlzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIga2V5ID0ga2V5c1tpXTtcbiAgICAgIHZhciB2YWx1ZSA9IG9ialtrZXldO1xuICAgICAgaWYgKGl0ZXJhdGVlKHZhbHVlLCBrZXksIG9iaikpIHJlc3VsdFtrZXldID0gdmFsdWU7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgIC8vIFJldHVybiBhIGNvcHkgb2YgdGhlIG9iamVjdCB3aXRob3V0IHRoZSBibGFja2xpc3RlZCBwcm9wZXJ0aWVzLlxuICBfLm9taXQgPSBmdW5jdGlvbihvYmosIGl0ZXJhdGVlLCBjb250ZXh0KSB7XG4gICAgaWYgKF8uaXNGdW5jdGlvbihpdGVyYXRlZSkpIHtcbiAgICAgIGl0ZXJhdGVlID0gXy5uZWdhdGUoaXRlcmF0ZWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIga2V5cyA9IF8ubWFwKGZsYXR0ZW4oYXJndW1lbnRzLCBmYWxzZSwgZmFsc2UsIDEpLCBTdHJpbmcpO1xuICAgICAgaXRlcmF0ZWUgPSBmdW5jdGlvbih2YWx1ZSwga2V5KSB7XG4gICAgICAgIHJldHVybiAhXy5jb250YWlucyhrZXlzLCBrZXkpO1xuICAgICAgfTtcbiAgICB9XG4gICAgcmV0dXJuIF8ucGljayhvYmosIGl0ZXJhdGVlLCBjb250ZXh0KTtcbiAgfTtcblxuICAvLyBGaWxsIGluIGEgZ2l2ZW4gb2JqZWN0IHdpdGggZGVmYXVsdCBwcm9wZXJ0aWVzLlxuICBfLmRlZmF1bHRzID0gY3JlYXRlQXNzaWduZXIoXy5hbGxLZXlzLCB0cnVlKTtcblxuICAvLyBDcmVhdGVzIGFuIG9iamVjdCB0aGF0IGluaGVyaXRzIGZyb20gdGhlIGdpdmVuIHByb3RvdHlwZSBvYmplY3QuXG4gIC8vIElmIGFkZGl0aW9uYWwgcHJvcGVydGllcyBhcmUgcHJvdmlkZWQgdGhlbiB0aGV5IHdpbGwgYmUgYWRkZWQgdG8gdGhlXG4gIC8vIGNyZWF0ZWQgb2JqZWN0LlxuICBfLmNyZWF0ZSA9IGZ1bmN0aW9uKHByb3RvdHlwZSwgcHJvcHMpIHtcbiAgICB2YXIgcmVzdWx0ID0gYmFzZUNyZWF0ZShwcm90b3R5cGUpO1xuICAgIGlmIChwcm9wcykgXy5leHRlbmRPd24ocmVzdWx0LCBwcm9wcyk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBDcmVhdGUgYSAoc2hhbGxvdy1jbG9uZWQpIGR1cGxpY2F0ZSBvZiBhbiBvYmplY3QuXG4gIF8uY2xvbmUgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAoIV8uaXNPYmplY3Qob2JqKSkgcmV0dXJuIG9iajtcbiAgICByZXR1cm4gXy5pc0FycmF5KG9iaikgPyBvYmouc2xpY2UoKSA6IF8uZXh0ZW5kKHt9LCBvYmopO1xuICB9O1xuXG4gIC8vIEludm9rZXMgaW50ZXJjZXB0b3Igd2l0aCB0aGUgb2JqLCBhbmQgdGhlbiByZXR1cm5zIG9iai5cbiAgLy8gVGhlIHByaW1hcnkgcHVycG9zZSBvZiB0aGlzIG1ldGhvZCBpcyB0byBcInRhcCBpbnRvXCIgYSBtZXRob2QgY2hhaW4sIGluXG4gIC8vIG9yZGVyIHRvIHBlcmZvcm0gb3BlcmF0aW9ucyBvbiBpbnRlcm1lZGlhdGUgcmVzdWx0cyB3aXRoaW4gdGhlIGNoYWluLlxuICBfLnRhcCA9IGZ1bmN0aW9uKG9iaiwgaW50ZXJjZXB0b3IpIHtcbiAgICBpbnRlcmNlcHRvcihvYmopO1xuICAgIHJldHVybiBvYmo7XG4gIH07XG5cbiAgLy8gUmV0dXJucyB3aGV0aGVyIGFuIG9iamVjdCBoYXMgYSBnaXZlbiBzZXQgb2YgYGtleTp2YWx1ZWAgcGFpcnMuXG4gIF8uaXNNYXRjaCA9IGZ1bmN0aW9uKG9iamVjdCwgYXR0cnMpIHtcbiAgICB2YXIga2V5cyA9IF8ua2V5cyhhdHRycyksIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgIGlmIChvYmplY3QgPT0gbnVsbCkgcmV0dXJuICFsZW5ndGg7XG4gICAgdmFyIG9iaiA9IE9iamVjdChvYmplY3QpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBrZXkgPSBrZXlzW2ldO1xuICAgICAgaWYgKGF0dHJzW2tleV0gIT09IG9ialtrZXldIHx8ICEoa2V5IGluIG9iaikpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG5cblxuICAvLyBJbnRlcm5hbCByZWN1cnNpdmUgY29tcGFyaXNvbiBmdW5jdGlvbiBmb3IgYGlzRXF1YWxgLlxuICB2YXIgZXEgPSBmdW5jdGlvbihhLCBiLCBhU3RhY2ssIGJTdGFjaykge1xuICAgIC8vIElkZW50aWNhbCBvYmplY3RzIGFyZSBlcXVhbC4gYDAgPT09IC0wYCwgYnV0IHRoZXkgYXJlbid0IGlkZW50aWNhbC5cbiAgICAvLyBTZWUgdGhlIFtIYXJtb255IGBlZ2FsYCBwcm9wb3NhbF0oaHR0cDovL3dpa2kuZWNtYXNjcmlwdC5vcmcvZG9rdS5waHA/aWQ9aGFybW9ueTplZ2FsKS5cbiAgICBpZiAoYSA9PT0gYikgcmV0dXJuIGEgIT09IDAgfHwgMSAvIGEgPT09IDEgLyBiO1xuICAgIC8vIEEgc3RyaWN0IGNvbXBhcmlzb24gaXMgbmVjZXNzYXJ5IGJlY2F1c2UgYG51bGwgPT0gdW5kZWZpbmVkYC5cbiAgICBpZiAoYSA9PSBudWxsIHx8IGIgPT0gbnVsbCkgcmV0dXJuIGEgPT09IGI7XG4gICAgLy8gVW53cmFwIGFueSB3cmFwcGVkIG9iamVjdHMuXG4gICAgaWYgKGEgaW5zdGFuY2VvZiBfKSBhID0gYS5fd3JhcHBlZDtcbiAgICBpZiAoYiBpbnN0YW5jZW9mIF8pIGIgPSBiLl93cmFwcGVkO1xuICAgIC8vIENvbXBhcmUgYFtbQ2xhc3NdXWAgbmFtZXMuXG4gICAgdmFyIGNsYXNzTmFtZSA9IHRvU3RyaW5nLmNhbGwoYSk7XG4gICAgaWYgKGNsYXNzTmFtZSAhPT0gdG9TdHJpbmcuY2FsbChiKSkgcmV0dXJuIGZhbHNlO1xuICAgIHN3aXRjaCAoY2xhc3NOYW1lKSB7XG4gICAgICAvLyBTdHJpbmdzLCBudW1iZXJzLCByZWd1bGFyIGV4cHJlc3Npb25zLCBkYXRlcywgYW5kIGJvb2xlYW5zIGFyZSBjb21wYXJlZCBieSB2YWx1ZS5cbiAgICAgIGNhc2UgJ1tvYmplY3QgUmVnRXhwXSc6XG4gICAgICAvLyBSZWdFeHBzIGFyZSBjb2VyY2VkIHRvIHN0cmluZ3MgZm9yIGNvbXBhcmlzb24gKE5vdGU6ICcnICsgL2EvaSA9PT0gJy9hL2knKVxuICAgICAgY2FzZSAnW29iamVjdCBTdHJpbmddJzpcbiAgICAgICAgLy8gUHJpbWl0aXZlcyBhbmQgdGhlaXIgY29ycmVzcG9uZGluZyBvYmplY3Qgd3JhcHBlcnMgYXJlIGVxdWl2YWxlbnQ7IHRodXMsIGBcIjVcImAgaXNcbiAgICAgICAgLy8gZXF1aXZhbGVudCB0byBgbmV3IFN0cmluZyhcIjVcIilgLlxuICAgICAgICByZXR1cm4gJycgKyBhID09PSAnJyArIGI7XG4gICAgICBjYXNlICdbb2JqZWN0IE51bWJlcl0nOlxuICAgICAgICAvLyBgTmFOYHMgYXJlIGVxdWl2YWxlbnQsIGJ1dCBub24tcmVmbGV4aXZlLlxuICAgICAgICAvLyBPYmplY3QoTmFOKSBpcyBlcXVpdmFsZW50IHRvIE5hTlxuICAgICAgICBpZiAoK2EgIT09ICthKSByZXR1cm4gK2IgIT09ICtiO1xuICAgICAgICAvLyBBbiBgZWdhbGAgY29tcGFyaXNvbiBpcyBwZXJmb3JtZWQgZm9yIG90aGVyIG51bWVyaWMgdmFsdWVzLlxuICAgICAgICByZXR1cm4gK2EgPT09IDAgPyAxIC8gK2EgPT09IDEgLyBiIDogK2EgPT09ICtiO1xuICAgICAgY2FzZSAnW29iamVjdCBEYXRlXSc6XG4gICAgICBjYXNlICdbb2JqZWN0IEJvb2xlYW5dJzpcbiAgICAgICAgLy8gQ29lcmNlIGRhdGVzIGFuZCBib29sZWFucyB0byBudW1lcmljIHByaW1pdGl2ZSB2YWx1ZXMuIERhdGVzIGFyZSBjb21wYXJlZCBieSB0aGVpclxuICAgICAgICAvLyBtaWxsaXNlY29uZCByZXByZXNlbnRhdGlvbnMuIE5vdGUgdGhhdCBpbnZhbGlkIGRhdGVzIHdpdGggbWlsbGlzZWNvbmQgcmVwcmVzZW50YXRpb25zXG4gICAgICAgIC8vIG9mIGBOYU5gIGFyZSBub3QgZXF1aXZhbGVudC5cbiAgICAgICAgcmV0dXJuICthID09PSArYjtcbiAgICB9XG5cbiAgICB2YXIgYXJlQXJyYXlzID0gY2xhc3NOYW1lID09PSAnW29iamVjdCBBcnJheV0nO1xuICAgIGlmICghYXJlQXJyYXlzKSB7XG4gICAgICBpZiAodHlwZW9mIGEgIT0gJ29iamVjdCcgfHwgdHlwZW9mIGIgIT0gJ29iamVjdCcpIHJldHVybiBmYWxzZTtcblxuICAgICAgLy8gT2JqZWN0cyB3aXRoIGRpZmZlcmVudCBjb25zdHJ1Y3RvcnMgYXJlIG5vdCBlcXVpdmFsZW50LCBidXQgYE9iamVjdGBzIG9yIGBBcnJheWBzXG4gICAgICAvLyBmcm9tIGRpZmZlcmVudCBmcmFtZXMgYXJlLlxuICAgICAgdmFyIGFDdG9yID0gYS5jb25zdHJ1Y3RvciwgYkN0b3IgPSBiLmNvbnN0cnVjdG9yO1xuICAgICAgaWYgKGFDdG9yICE9PSBiQ3RvciAmJiAhKF8uaXNGdW5jdGlvbihhQ3RvcikgJiYgYUN0b3IgaW5zdGFuY2VvZiBhQ3RvciAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF8uaXNGdW5jdGlvbihiQ3RvcikgJiYgYkN0b3IgaW5zdGFuY2VvZiBiQ3RvcilcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJiYgKCdjb25zdHJ1Y3RvcicgaW4gYSAmJiAnY29uc3RydWN0b3InIGluIGIpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gQXNzdW1lIGVxdWFsaXR5IGZvciBjeWNsaWMgc3RydWN0dXJlcy4gVGhlIGFsZ29yaXRobSBmb3IgZGV0ZWN0aW5nIGN5Y2xpY1xuICAgIC8vIHN0cnVjdHVyZXMgaXMgYWRhcHRlZCBmcm9tIEVTIDUuMSBzZWN0aW9uIDE1LjEyLjMsIGFic3RyYWN0IG9wZXJhdGlvbiBgSk9gLlxuXG4gICAgLy8gSW5pdGlhbGl6aW5nIHN0YWNrIG9mIHRyYXZlcnNlZCBvYmplY3RzLlxuICAgIC8vIEl0J3MgZG9uZSBoZXJlIHNpbmNlIHdlIG9ubHkgbmVlZCB0aGVtIGZvciBvYmplY3RzIGFuZCBhcnJheXMgY29tcGFyaXNvbi5cbiAgICBhU3RhY2sgPSBhU3RhY2sgfHwgW107XG4gICAgYlN0YWNrID0gYlN0YWNrIHx8IFtdO1xuICAgIHZhciBsZW5ndGggPSBhU3RhY2subGVuZ3RoO1xuICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgLy8gTGluZWFyIHNlYXJjaC4gUGVyZm9ybWFuY2UgaXMgaW52ZXJzZWx5IHByb3BvcnRpb25hbCB0byB0aGUgbnVtYmVyIG9mXG4gICAgICAvLyB1bmlxdWUgbmVzdGVkIHN0cnVjdHVyZXMuXG4gICAgICBpZiAoYVN0YWNrW2xlbmd0aF0gPT09IGEpIHJldHVybiBiU3RhY2tbbGVuZ3RoXSA9PT0gYjtcbiAgICB9XG5cbiAgICAvLyBBZGQgdGhlIGZpcnN0IG9iamVjdCB0byB0aGUgc3RhY2sgb2YgdHJhdmVyc2VkIG9iamVjdHMuXG4gICAgYVN0YWNrLnB1c2goYSk7XG4gICAgYlN0YWNrLnB1c2goYik7XG5cbiAgICAvLyBSZWN1cnNpdmVseSBjb21wYXJlIG9iamVjdHMgYW5kIGFycmF5cy5cbiAgICBpZiAoYXJlQXJyYXlzKSB7XG4gICAgICAvLyBDb21wYXJlIGFycmF5IGxlbmd0aHMgdG8gZGV0ZXJtaW5lIGlmIGEgZGVlcCBjb21wYXJpc29uIGlzIG5lY2Vzc2FyeS5cbiAgICAgIGxlbmd0aCA9IGEubGVuZ3RoO1xuICAgICAgaWYgKGxlbmd0aCAhPT0gYi5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICAgIC8vIERlZXAgY29tcGFyZSB0aGUgY29udGVudHMsIGlnbm9yaW5nIG5vbi1udW1lcmljIHByb3BlcnRpZXMuXG4gICAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgICAgaWYgKCFlcShhW2xlbmd0aF0sIGJbbGVuZ3RoXSwgYVN0YWNrLCBiU3RhY2spKSByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIERlZXAgY29tcGFyZSBvYmplY3RzLlxuICAgICAgdmFyIGtleXMgPSBfLmtleXMoYSksIGtleTtcbiAgICAgIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgICAgLy8gRW5zdXJlIHRoYXQgYm90aCBvYmplY3RzIGNvbnRhaW4gdGhlIHNhbWUgbnVtYmVyIG9mIHByb3BlcnRpZXMgYmVmb3JlIGNvbXBhcmluZyBkZWVwIGVxdWFsaXR5LlxuICAgICAgaWYgKF8ua2V5cyhiKS5sZW5ndGggIT09IGxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAgIC8vIERlZXAgY29tcGFyZSBlYWNoIG1lbWJlclxuICAgICAgICBrZXkgPSBrZXlzW2xlbmd0aF07XG4gICAgICAgIGlmICghKF8uaGFzKGIsIGtleSkgJiYgZXEoYVtrZXldLCBiW2tleV0sIGFTdGFjaywgYlN0YWNrKSkpIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gUmVtb3ZlIHRoZSBmaXJzdCBvYmplY3QgZnJvbSB0aGUgc3RhY2sgb2YgdHJhdmVyc2VkIG9iamVjdHMuXG4gICAgYVN0YWNrLnBvcCgpO1xuICAgIGJTdGFjay5wb3AoKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcblxuICAvLyBQZXJmb3JtIGEgZGVlcCBjb21wYXJpc29uIHRvIGNoZWNrIGlmIHR3byBvYmplY3RzIGFyZSBlcXVhbC5cbiAgXy5pc0VxdWFsID0gZnVuY3Rpb24oYSwgYikge1xuICAgIHJldHVybiBlcShhLCBiKTtcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIGFycmF5LCBzdHJpbmcsIG9yIG9iamVjdCBlbXB0eT9cbiAgLy8gQW4gXCJlbXB0eVwiIG9iamVjdCBoYXMgbm8gZW51bWVyYWJsZSBvd24tcHJvcGVydGllcy5cbiAgXy5pc0VtcHR5ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gdHJ1ZTtcbiAgICBpZiAoaXNBcnJheUxpa2Uob2JqKSAmJiAoXy5pc0FycmF5KG9iaikgfHwgXy5pc1N0cmluZyhvYmopIHx8IF8uaXNBcmd1bWVudHMob2JqKSkpIHJldHVybiBvYmoubGVuZ3RoID09PSAwO1xuICAgIHJldHVybiBfLmtleXMob2JqKS5sZW5ndGggPT09IDA7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YWx1ZSBhIERPTSBlbGVtZW50P1xuICBfLmlzRWxlbWVudCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiAhIShvYmogJiYgb2JqLm5vZGVUeXBlID09PSAxKTtcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhbHVlIGFuIGFycmF5P1xuICAvLyBEZWxlZ2F0ZXMgdG8gRUNNQTUncyBuYXRpdmUgQXJyYXkuaXNBcnJheVxuICBfLmlzQXJyYXkgPSBuYXRpdmVJc0FycmF5IHx8IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IEFycmF5XSc7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YXJpYWJsZSBhbiBvYmplY3Q/XG4gIF8uaXNPYmplY3QgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgdHlwZSA9IHR5cGVvZiBvYmo7XG4gICAgcmV0dXJuIHR5cGUgPT09ICdmdW5jdGlvbicgfHwgdHlwZSA9PT0gJ29iamVjdCcgJiYgISFvYmo7XG4gIH07XG5cbiAgLy8gQWRkIHNvbWUgaXNUeXBlIG1ldGhvZHM6IGlzQXJndW1lbnRzLCBpc0Z1bmN0aW9uLCBpc1N0cmluZywgaXNOdW1iZXIsIGlzRGF0ZSwgaXNSZWdFeHAsIGlzRXJyb3IuXG4gIF8uZWFjaChbJ0FyZ3VtZW50cycsICdGdW5jdGlvbicsICdTdHJpbmcnLCAnTnVtYmVyJywgJ0RhdGUnLCAnUmVnRXhwJywgJ0Vycm9yJ10sIGZ1bmN0aW9uKG5hbWUpIHtcbiAgICBfWydpcycgKyBuYW1lXSA9IGZ1bmN0aW9uKG9iaikge1xuICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgJyArIG5hbWUgKyAnXSc7XG4gICAgfTtcbiAgfSk7XG5cbiAgLy8gRGVmaW5lIGEgZmFsbGJhY2sgdmVyc2lvbiBvZiB0aGUgbWV0aG9kIGluIGJyb3dzZXJzIChhaGVtLCBJRSA8IDkpLCB3aGVyZVxuICAvLyB0aGVyZSBpc24ndCBhbnkgaW5zcGVjdGFibGUgXCJBcmd1bWVudHNcIiB0eXBlLlxuICBpZiAoIV8uaXNBcmd1bWVudHMoYXJndW1lbnRzKSkge1xuICAgIF8uaXNBcmd1bWVudHMgPSBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiBfLmhhcyhvYmosICdjYWxsZWUnKTtcbiAgICB9O1xuICB9XG5cbiAgLy8gT3B0aW1pemUgYGlzRnVuY3Rpb25gIGlmIGFwcHJvcHJpYXRlLiBXb3JrIGFyb3VuZCBzb21lIHR5cGVvZiBidWdzIGluIG9sZCB2OCxcbiAgLy8gSUUgMTEgKCMxNjIxKSwgYW5kIGluIFNhZmFyaSA4ICgjMTkyOSkuXG4gIGlmICh0eXBlb2YgLy4vICE9ICdmdW5jdGlvbicgJiYgdHlwZW9mIEludDhBcnJheSAhPSAnb2JqZWN0Jykge1xuICAgIF8uaXNGdW5jdGlvbiA9IGZ1bmN0aW9uKG9iaikge1xuICAgICAgcmV0dXJuIHR5cGVvZiBvYmogPT0gJ2Z1bmN0aW9uJyB8fCBmYWxzZTtcbiAgICB9O1xuICB9XG5cbiAgLy8gSXMgYSBnaXZlbiBvYmplY3QgYSBmaW5pdGUgbnVtYmVyP1xuICBfLmlzRmluaXRlID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIGlzRmluaXRlKG9iaikgJiYgIWlzTmFOKHBhcnNlRmxvYXQob2JqKSk7XG4gIH07XG5cbiAgLy8gSXMgdGhlIGdpdmVuIHZhbHVlIGBOYU5gPyAoTmFOIGlzIHRoZSBvbmx5IG51bWJlciB3aGljaCBkb2VzIG5vdCBlcXVhbCBpdHNlbGYpLlxuICBfLmlzTmFOID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIF8uaXNOdW1iZXIob2JqKSAmJiBvYmogIT09ICtvYmo7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YWx1ZSBhIGJvb2xlYW4/XG4gIF8uaXNCb29sZWFuID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIG9iaiA9PT0gdHJ1ZSB8fCBvYmogPT09IGZhbHNlIHx8IHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgQm9vbGVhbl0nO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFsdWUgZXF1YWwgdG8gbnVsbD9cbiAgXy5pc051bGwgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gb2JqID09PSBudWxsO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFyaWFibGUgdW5kZWZpbmVkP1xuICBfLmlzVW5kZWZpbmVkID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIG9iaiA9PT0gdm9pZCAwO1xuICB9O1xuXG4gIC8vIFNob3J0Y3V0IGZ1bmN0aW9uIGZvciBjaGVja2luZyBpZiBhbiBvYmplY3QgaGFzIGEgZ2l2ZW4gcHJvcGVydHkgZGlyZWN0bHlcbiAgLy8gb24gaXRzZWxmIChpbiBvdGhlciB3b3Jkcywgbm90IG9uIGEgcHJvdG90eXBlKS5cbiAgXy5oYXMgPSBmdW5jdGlvbihvYmosIGtleSkge1xuICAgIHJldHVybiBvYmogIT0gbnVsbCAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KTtcbiAgfTtcblxuICAvLyBVdGlsaXR5IEZ1bmN0aW9uc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIFJ1biBVbmRlcnNjb3JlLmpzIGluICpub0NvbmZsaWN0KiBtb2RlLCByZXR1cm5pbmcgdGhlIGBfYCB2YXJpYWJsZSB0byBpdHNcbiAgLy8gcHJldmlvdXMgb3duZXIuIFJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhlIFVuZGVyc2NvcmUgb2JqZWN0LlxuICBfLm5vQ29uZmxpY3QgPSBmdW5jdGlvbigpIHtcbiAgICByb290Ll8gPSBwcmV2aW91c1VuZGVyc2NvcmU7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgLy8gS2VlcCB0aGUgaWRlbnRpdHkgZnVuY3Rpb24gYXJvdW5kIGZvciBkZWZhdWx0IGl0ZXJhdGVlcy5cbiAgXy5pZGVudGl0eSA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9O1xuXG4gIC8vIFByZWRpY2F0ZS1nZW5lcmF0aW5nIGZ1bmN0aW9ucy4gT2Z0ZW4gdXNlZnVsIG91dHNpZGUgb2YgVW5kZXJzY29yZS5cbiAgXy5jb25zdGFudCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH07XG4gIH07XG5cbiAgXy5ub29wID0gZnVuY3Rpb24oKXt9O1xuXG4gIF8ucHJvcGVydHkgPSBwcm9wZXJ0eTtcblxuICAvLyBHZW5lcmF0ZXMgYSBmdW5jdGlvbiBmb3IgYSBnaXZlbiBvYmplY3QgdGhhdCByZXR1cm5zIGEgZ2l2ZW4gcHJvcGVydHkuXG4gIF8ucHJvcGVydHlPZiA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBvYmogPT0gbnVsbCA/IGZ1bmN0aW9uKCl7fSA6IGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIG9ialtrZXldO1xuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIHByZWRpY2F0ZSBmb3IgY2hlY2tpbmcgd2hldGhlciBhbiBvYmplY3QgaGFzIGEgZ2l2ZW4gc2V0IG9mXG4gIC8vIGBrZXk6dmFsdWVgIHBhaXJzLlxuICBfLm1hdGNoZXIgPSBfLm1hdGNoZXMgPSBmdW5jdGlvbihhdHRycykge1xuICAgIGF0dHJzID0gXy5leHRlbmRPd24oe30sIGF0dHJzKTtcbiAgICByZXR1cm4gZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gXy5pc01hdGNoKG9iaiwgYXR0cnMpO1xuICAgIH07XG4gIH07XG5cbiAgLy8gUnVuIGEgZnVuY3Rpb24gKipuKiogdGltZXMuXG4gIF8udGltZXMgPSBmdW5jdGlvbihuLCBpdGVyYXRlZSwgY29udGV4dCkge1xuICAgIHZhciBhY2N1bSA9IEFycmF5KE1hdGgubWF4KDAsIG4pKTtcbiAgICBpdGVyYXRlZSA9IG9wdGltaXplQ2IoaXRlcmF0ZWUsIGNvbnRleHQsIDEpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSBhY2N1bVtpXSA9IGl0ZXJhdGVlKGkpO1xuICAgIHJldHVybiBhY2N1bTtcbiAgfTtcblxuICAvLyBSZXR1cm4gYSByYW5kb20gaW50ZWdlciBiZXR3ZWVuIG1pbiBhbmQgbWF4IChpbmNsdXNpdmUpLlxuICBfLnJhbmRvbSA9IGZ1bmN0aW9uKG1pbiwgbWF4KSB7XG4gICAgaWYgKG1heCA9PSBudWxsKSB7XG4gICAgICBtYXggPSBtaW47XG4gICAgICBtaW4gPSAwO1xuICAgIH1cbiAgICByZXR1cm4gbWluICsgTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogKG1heCAtIG1pbiArIDEpKTtcbiAgfTtcblxuICAvLyBBIChwb3NzaWJseSBmYXN0ZXIpIHdheSB0byBnZXQgdGhlIGN1cnJlbnQgdGltZXN0YW1wIGFzIGFuIGludGVnZXIuXG4gIF8ubm93ID0gRGF0ZS5ub3cgfHwgZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICB9O1xuXG4gICAvLyBMaXN0IG9mIEhUTUwgZW50aXRpZXMgZm9yIGVzY2FwaW5nLlxuICB2YXIgZXNjYXBlTWFwID0ge1xuICAgICcmJzogJyZhbXA7JyxcbiAgICAnPCc6ICcmbHQ7JyxcbiAgICAnPic6ICcmZ3Q7JyxcbiAgICAnXCInOiAnJnF1b3Q7JyxcbiAgICBcIidcIjogJyYjeDI3OycsXG4gICAgJ2AnOiAnJiN4NjA7J1xuICB9O1xuICB2YXIgdW5lc2NhcGVNYXAgPSBfLmludmVydChlc2NhcGVNYXApO1xuXG4gIC8vIEZ1bmN0aW9ucyBmb3IgZXNjYXBpbmcgYW5kIHVuZXNjYXBpbmcgc3RyaW5ncyB0by9mcm9tIEhUTUwgaW50ZXJwb2xhdGlvbi5cbiAgdmFyIGNyZWF0ZUVzY2FwZXIgPSBmdW5jdGlvbihtYXApIHtcbiAgICB2YXIgZXNjYXBlciA9IGZ1bmN0aW9uKG1hdGNoKSB7XG4gICAgICByZXR1cm4gbWFwW21hdGNoXTtcbiAgICB9O1xuICAgIC8vIFJlZ2V4ZXMgZm9yIGlkZW50aWZ5aW5nIGEga2V5IHRoYXQgbmVlZHMgdG8gYmUgZXNjYXBlZFxuICAgIHZhciBzb3VyY2UgPSAnKD86JyArIF8ua2V5cyhtYXApLmpvaW4oJ3wnKSArICcpJztcbiAgICB2YXIgdGVzdFJlZ2V4cCA9IFJlZ0V4cChzb3VyY2UpO1xuICAgIHZhciByZXBsYWNlUmVnZXhwID0gUmVnRXhwKHNvdXJjZSwgJ2cnKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oc3RyaW5nKSB7XG4gICAgICBzdHJpbmcgPSBzdHJpbmcgPT0gbnVsbCA/ICcnIDogJycgKyBzdHJpbmc7XG4gICAgICByZXR1cm4gdGVzdFJlZ2V4cC50ZXN0KHN0cmluZykgPyBzdHJpbmcucmVwbGFjZShyZXBsYWNlUmVnZXhwLCBlc2NhcGVyKSA6IHN0cmluZztcbiAgICB9O1xuICB9O1xuICBfLmVzY2FwZSA9IGNyZWF0ZUVzY2FwZXIoZXNjYXBlTWFwKTtcbiAgXy51bmVzY2FwZSA9IGNyZWF0ZUVzY2FwZXIodW5lc2NhcGVNYXApO1xuXG4gIC8vIElmIHRoZSB2YWx1ZSBvZiB0aGUgbmFtZWQgYHByb3BlcnR5YCBpcyBhIGZ1bmN0aW9uIHRoZW4gaW52b2tlIGl0IHdpdGggdGhlXG4gIC8vIGBvYmplY3RgIGFzIGNvbnRleHQ7IG90aGVyd2lzZSwgcmV0dXJuIGl0LlxuICBfLnJlc3VsdCA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHksIGZhbGxiYWNrKSB7XG4gICAgdmFyIHZhbHVlID0gb2JqZWN0ID09IG51bGwgPyB2b2lkIDAgOiBvYmplY3RbcHJvcGVydHldO1xuICAgIGlmICh2YWx1ZSA9PT0gdm9pZCAwKSB7XG4gICAgICB2YWx1ZSA9IGZhbGxiYWNrO1xuICAgIH1cbiAgICByZXR1cm4gXy5pc0Z1bmN0aW9uKHZhbHVlKSA/IHZhbHVlLmNhbGwob2JqZWN0KSA6IHZhbHVlO1xuICB9O1xuXG4gIC8vIEdlbmVyYXRlIGEgdW5pcXVlIGludGVnZXIgaWQgKHVuaXF1ZSB3aXRoaW4gdGhlIGVudGlyZSBjbGllbnQgc2Vzc2lvbikuXG4gIC8vIFVzZWZ1bCBmb3IgdGVtcG9yYXJ5IERPTSBpZHMuXG4gIHZhciBpZENvdW50ZXIgPSAwO1xuICBfLnVuaXF1ZUlkID0gZnVuY3Rpb24ocHJlZml4KSB7XG4gICAgdmFyIGlkID0gKytpZENvdW50ZXIgKyAnJztcbiAgICByZXR1cm4gcHJlZml4ID8gcHJlZml4ICsgaWQgOiBpZDtcbiAgfTtcblxuICAvLyBCeSBkZWZhdWx0LCBVbmRlcnNjb3JlIHVzZXMgRVJCLXN0eWxlIHRlbXBsYXRlIGRlbGltaXRlcnMsIGNoYW5nZSB0aGVcbiAgLy8gZm9sbG93aW5nIHRlbXBsYXRlIHNldHRpbmdzIHRvIHVzZSBhbHRlcm5hdGl2ZSBkZWxpbWl0ZXJzLlxuICBfLnRlbXBsYXRlU2V0dGluZ3MgPSB7XG4gICAgZXZhbHVhdGUgICAgOiAvPCUoW1xcc1xcU10rPyklPi9nLFxuICAgIGludGVycG9sYXRlIDogLzwlPShbXFxzXFxTXSs/KSU+L2csXG4gICAgZXNjYXBlICAgICAgOiAvPCUtKFtcXHNcXFNdKz8pJT4vZ1xuICB9O1xuXG4gIC8vIFdoZW4gY3VzdG9taXppbmcgYHRlbXBsYXRlU2V0dGluZ3NgLCBpZiB5b3UgZG9uJ3Qgd2FudCB0byBkZWZpbmUgYW5cbiAgLy8gaW50ZXJwb2xhdGlvbiwgZXZhbHVhdGlvbiBvciBlc2NhcGluZyByZWdleCwgd2UgbmVlZCBvbmUgdGhhdCBpc1xuICAvLyBndWFyYW50ZWVkIG5vdCB0byBtYXRjaC5cbiAgdmFyIG5vTWF0Y2ggPSAvKC4pXi87XG5cbiAgLy8gQ2VydGFpbiBjaGFyYWN0ZXJzIG5lZWQgdG8gYmUgZXNjYXBlZCBzbyB0aGF0IHRoZXkgY2FuIGJlIHB1dCBpbnRvIGFcbiAgLy8gc3RyaW5nIGxpdGVyYWwuXG4gIHZhciBlc2NhcGVzID0ge1xuICAgIFwiJ1wiOiAgICAgIFwiJ1wiLFxuICAgICdcXFxcJzogICAgICdcXFxcJyxcbiAgICAnXFxyJzogICAgICdyJyxcbiAgICAnXFxuJzogICAgICduJyxcbiAgICAnXFx1MjAyOCc6ICd1MjAyOCcsXG4gICAgJ1xcdTIwMjknOiAndTIwMjknXG4gIH07XG5cbiAgdmFyIGVzY2FwZXIgPSAvXFxcXHwnfFxccnxcXG58XFx1MjAyOHxcXHUyMDI5L2c7XG5cbiAgdmFyIGVzY2FwZUNoYXIgPSBmdW5jdGlvbihtYXRjaCkge1xuICAgIHJldHVybiAnXFxcXCcgKyBlc2NhcGVzW21hdGNoXTtcbiAgfTtcblxuICAvLyBKYXZhU2NyaXB0IG1pY3JvLXRlbXBsYXRpbmcsIHNpbWlsYXIgdG8gSm9obiBSZXNpZydzIGltcGxlbWVudGF0aW9uLlxuICAvLyBVbmRlcnNjb3JlIHRlbXBsYXRpbmcgaGFuZGxlcyBhcmJpdHJhcnkgZGVsaW1pdGVycywgcHJlc2VydmVzIHdoaXRlc3BhY2UsXG4gIC8vIGFuZCBjb3JyZWN0bHkgZXNjYXBlcyBxdW90ZXMgd2l0aGluIGludGVycG9sYXRlZCBjb2RlLlxuICAvLyBOQjogYG9sZFNldHRpbmdzYCBvbmx5IGV4aXN0cyBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuXG4gIF8udGVtcGxhdGUgPSBmdW5jdGlvbih0ZXh0LCBzZXR0aW5ncywgb2xkU2V0dGluZ3MpIHtcbiAgICBpZiAoIXNldHRpbmdzICYmIG9sZFNldHRpbmdzKSBzZXR0aW5ncyA9IG9sZFNldHRpbmdzO1xuICAgIHNldHRpbmdzID0gXy5kZWZhdWx0cyh7fSwgc2V0dGluZ3MsIF8udGVtcGxhdGVTZXR0aW5ncyk7XG5cbiAgICAvLyBDb21iaW5lIGRlbGltaXRlcnMgaW50byBvbmUgcmVndWxhciBleHByZXNzaW9uIHZpYSBhbHRlcm5hdGlvbi5cbiAgICB2YXIgbWF0Y2hlciA9IFJlZ0V4cChbXG4gICAgICAoc2V0dGluZ3MuZXNjYXBlIHx8IG5vTWF0Y2gpLnNvdXJjZSxcbiAgICAgIChzZXR0aW5ncy5pbnRlcnBvbGF0ZSB8fCBub01hdGNoKS5zb3VyY2UsXG4gICAgICAoc2V0dGluZ3MuZXZhbHVhdGUgfHwgbm9NYXRjaCkuc291cmNlXG4gICAgXS5qb2luKCd8JykgKyAnfCQnLCAnZycpO1xuXG4gICAgLy8gQ29tcGlsZSB0aGUgdGVtcGxhdGUgc291cmNlLCBlc2NhcGluZyBzdHJpbmcgbGl0ZXJhbHMgYXBwcm9wcmlhdGVseS5cbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHZhciBzb3VyY2UgPSBcIl9fcCs9J1wiO1xuICAgIHRleHQucmVwbGFjZShtYXRjaGVyLCBmdW5jdGlvbihtYXRjaCwgZXNjYXBlLCBpbnRlcnBvbGF0ZSwgZXZhbHVhdGUsIG9mZnNldCkge1xuICAgICAgc291cmNlICs9IHRleHQuc2xpY2UoaW5kZXgsIG9mZnNldCkucmVwbGFjZShlc2NhcGVyLCBlc2NhcGVDaGFyKTtcbiAgICAgIGluZGV4ID0gb2Zmc2V0ICsgbWF0Y2gubGVuZ3RoO1xuXG4gICAgICBpZiAoZXNjYXBlKSB7XG4gICAgICAgIHNvdXJjZSArPSBcIicrXFxuKChfX3Q9KFwiICsgZXNjYXBlICsgXCIpKT09bnVsbD8nJzpfLmVzY2FwZShfX3QpKStcXG4nXCI7XG4gICAgICB9IGVsc2UgaWYgKGludGVycG9sYXRlKSB7XG4gICAgICAgIHNvdXJjZSArPSBcIicrXFxuKChfX3Q9KFwiICsgaW50ZXJwb2xhdGUgKyBcIikpPT1udWxsPycnOl9fdCkrXFxuJ1wiO1xuICAgICAgfSBlbHNlIGlmIChldmFsdWF0ZSkge1xuICAgICAgICBzb3VyY2UgKz0gXCInO1xcblwiICsgZXZhbHVhdGUgKyBcIlxcbl9fcCs9J1wiO1xuICAgICAgfVxuXG4gICAgICAvLyBBZG9iZSBWTXMgbmVlZCB0aGUgbWF0Y2ggcmV0dXJuZWQgdG8gcHJvZHVjZSB0aGUgY29ycmVjdCBvZmZlc3QuXG4gICAgICByZXR1cm4gbWF0Y2g7XG4gICAgfSk7XG4gICAgc291cmNlICs9IFwiJztcXG5cIjtcblxuICAgIC8vIElmIGEgdmFyaWFibGUgaXMgbm90IHNwZWNpZmllZCwgcGxhY2UgZGF0YSB2YWx1ZXMgaW4gbG9jYWwgc2NvcGUuXG4gICAgaWYgKCFzZXR0aW5ncy52YXJpYWJsZSkgc291cmNlID0gJ3dpdGgob2JqfHx7fSl7XFxuJyArIHNvdXJjZSArICd9XFxuJztcblxuICAgIHNvdXJjZSA9IFwidmFyIF9fdCxfX3A9JycsX19qPUFycmF5LnByb3RvdHlwZS5qb2luLFwiICtcbiAgICAgIFwicHJpbnQ9ZnVuY3Rpb24oKXtfX3ArPV9fai5jYWxsKGFyZ3VtZW50cywnJyk7fTtcXG5cIiArXG4gICAgICBzb3VyY2UgKyAncmV0dXJuIF9fcDtcXG4nO1xuXG4gICAgdHJ5IHtcbiAgICAgIHZhciByZW5kZXIgPSBuZXcgRnVuY3Rpb24oc2V0dGluZ3MudmFyaWFibGUgfHwgJ29iaicsICdfJywgc291cmNlKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBlLnNvdXJjZSA9IHNvdXJjZTtcbiAgICAgIHRocm93IGU7XG4gICAgfVxuXG4gICAgdmFyIHRlbXBsYXRlID0gZnVuY3Rpb24oZGF0YSkge1xuICAgICAgcmV0dXJuIHJlbmRlci5jYWxsKHRoaXMsIGRhdGEsIF8pO1xuICAgIH07XG5cbiAgICAvLyBQcm92aWRlIHRoZSBjb21waWxlZCBzb3VyY2UgYXMgYSBjb252ZW5pZW5jZSBmb3IgcHJlY29tcGlsYXRpb24uXG4gICAgdmFyIGFyZ3VtZW50ID0gc2V0dGluZ3MudmFyaWFibGUgfHwgJ29iaic7XG4gICAgdGVtcGxhdGUuc291cmNlID0gJ2Z1bmN0aW9uKCcgKyBhcmd1bWVudCArICcpe1xcbicgKyBzb3VyY2UgKyAnfSc7XG5cbiAgICByZXR1cm4gdGVtcGxhdGU7XG4gIH07XG5cbiAgLy8gQWRkIGEgXCJjaGFpblwiIGZ1bmN0aW9uLiBTdGFydCBjaGFpbmluZyBhIHdyYXBwZWQgVW5kZXJzY29yZSBvYmplY3QuXG4gIF8uY2hhaW4gPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgaW5zdGFuY2UgPSBfKG9iaik7XG4gICAgaW5zdGFuY2UuX2NoYWluID0gdHJ1ZTtcbiAgICByZXR1cm4gaW5zdGFuY2U7XG4gIH07XG5cbiAgLy8gT09QXG4gIC8vIC0tLS0tLS0tLS0tLS0tLVxuICAvLyBJZiBVbmRlcnNjb3JlIGlzIGNhbGxlZCBhcyBhIGZ1bmN0aW9uLCBpdCByZXR1cm5zIGEgd3JhcHBlZCBvYmplY3QgdGhhdFxuICAvLyBjYW4gYmUgdXNlZCBPTy1zdHlsZS4gVGhpcyB3cmFwcGVyIGhvbGRzIGFsdGVyZWQgdmVyc2lvbnMgb2YgYWxsIHRoZVxuICAvLyB1bmRlcnNjb3JlIGZ1bmN0aW9ucy4gV3JhcHBlZCBvYmplY3RzIG1heSBiZSBjaGFpbmVkLlxuXG4gIC8vIEhlbHBlciBmdW5jdGlvbiB0byBjb250aW51ZSBjaGFpbmluZyBpbnRlcm1lZGlhdGUgcmVzdWx0cy5cbiAgdmFyIHJlc3VsdCA9IGZ1bmN0aW9uKGluc3RhbmNlLCBvYmopIHtcbiAgICByZXR1cm4gaW5zdGFuY2UuX2NoYWluID8gXyhvYmopLmNoYWluKCkgOiBvYmo7XG4gIH07XG5cbiAgLy8gQWRkIHlvdXIgb3duIGN1c3RvbSBmdW5jdGlvbnMgdG8gdGhlIFVuZGVyc2NvcmUgb2JqZWN0LlxuICBfLm1peGluID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgXy5lYWNoKF8uZnVuY3Rpb25zKG9iaiksIGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgIHZhciBmdW5jID0gX1tuYW1lXSA9IG9ialtuYW1lXTtcbiAgICAgIF8ucHJvdG90eXBlW25hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBhcmdzID0gW3RoaXMuX3dyYXBwZWRdO1xuICAgICAgICBwdXNoLmFwcGx5KGFyZ3MsIGFyZ3VtZW50cyk7XG4gICAgICAgIHJldHVybiByZXN1bHQodGhpcywgZnVuYy5hcHBseShfLCBhcmdzKSk7XG4gICAgICB9O1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIEFkZCBhbGwgb2YgdGhlIFVuZGVyc2NvcmUgZnVuY3Rpb25zIHRvIHRoZSB3cmFwcGVyIG9iamVjdC5cbiAgXy5taXhpbihfKTtcblxuICAvLyBBZGQgYWxsIG11dGF0b3IgQXJyYXkgZnVuY3Rpb25zIHRvIHRoZSB3cmFwcGVyLlxuICBfLmVhY2goWydwb3AnLCAncHVzaCcsICdyZXZlcnNlJywgJ3NoaWZ0JywgJ3NvcnQnLCAnc3BsaWNlJywgJ3Vuc2hpZnQnXSwgZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBtZXRob2QgPSBBcnJheVByb3RvW25hbWVdO1xuICAgIF8ucHJvdG90eXBlW25hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgb2JqID0gdGhpcy5fd3JhcHBlZDtcbiAgICAgIG1ldGhvZC5hcHBseShvYmosIGFyZ3VtZW50cyk7XG4gICAgICBpZiAoKG5hbWUgPT09ICdzaGlmdCcgfHwgbmFtZSA9PT0gJ3NwbGljZScpICYmIG9iai5sZW5ndGggPT09IDApIGRlbGV0ZSBvYmpbMF07XG4gICAgICByZXR1cm4gcmVzdWx0KHRoaXMsIG9iaik7XG4gICAgfTtcbiAgfSk7XG5cbiAgLy8gQWRkIGFsbCBhY2Nlc3NvciBBcnJheSBmdW5jdGlvbnMgdG8gdGhlIHdyYXBwZXIuXG4gIF8uZWFjaChbJ2NvbmNhdCcsICdqb2luJywgJ3NsaWNlJ10sIGZ1bmN0aW9uKG5hbWUpIHtcbiAgICB2YXIgbWV0aG9kID0gQXJyYXlQcm90b1tuYW1lXTtcbiAgICBfLnByb3RvdHlwZVtuYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHJlc3VsdCh0aGlzLCBtZXRob2QuYXBwbHkodGhpcy5fd3JhcHBlZCwgYXJndW1lbnRzKSk7XG4gICAgfTtcbiAgfSk7XG5cbiAgLy8gRXh0cmFjdHMgdGhlIHJlc3VsdCBmcm9tIGEgd3JhcHBlZCBhbmQgY2hhaW5lZCBvYmplY3QuXG4gIF8ucHJvdG90eXBlLnZhbHVlID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuX3dyYXBwZWQ7XG4gIH07XG5cbiAgLy8gUHJvdmlkZSB1bndyYXBwaW5nIHByb3h5IGZvciBzb21lIG1ldGhvZHMgdXNlZCBpbiBlbmdpbmUgb3BlcmF0aW9uc1xuICAvLyBzdWNoIGFzIGFyaXRobWV0aWMgYW5kIEpTT04gc3RyaW5naWZpY2F0aW9uLlxuICBfLnByb3RvdHlwZS52YWx1ZU9mID0gXy5wcm90b3R5cGUudG9KU09OID0gXy5wcm90b3R5cGUudmFsdWU7XG5cbiAgXy5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gJycgKyB0aGlzLl93cmFwcGVkO1xuICB9O1xuXG4gIC8vIEFNRCByZWdpc3RyYXRpb24gaGFwcGVucyBhdCB0aGUgZW5kIGZvciBjb21wYXRpYmlsaXR5IHdpdGggQU1EIGxvYWRlcnNcbiAgLy8gdGhhdCBtYXkgbm90IGVuZm9yY2UgbmV4dC10dXJuIHNlbWFudGljcyBvbiBtb2R1bGVzLiBFdmVuIHRob3VnaCBnZW5lcmFsXG4gIC8vIHByYWN0aWNlIGZvciBBTUQgcmVnaXN0cmF0aW9uIGlzIHRvIGJlIGFub255bW91cywgdW5kZXJzY29yZSByZWdpc3RlcnNcbiAgLy8gYXMgYSBuYW1lZCBtb2R1bGUgYmVjYXVzZSwgbGlrZSBqUXVlcnksIGl0IGlzIGEgYmFzZSBsaWJyYXJ5IHRoYXQgaXNcbiAgLy8gcG9wdWxhciBlbm91Z2ggdG8gYmUgYnVuZGxlZCBpbiBhIHRoaXJkIHBhcnR5IGxpYiwgYnV0IG5vdCBiZSBwYXJ0IG9mXG4gIC8vIGFuIEFNRCBsb2FkIHJlcXVlc3QuIFRob3NlIGNhc2VzIGNvdWxkIGdlbmVyYXRlIGFuIGVycm9yIHdoZW4gYW5cbiAgLy8gYW5vbnltb3VzIGRlZmluZSgpIGlzIGNhbGxlZCBvdXRzaWRlIG9mIGEgbG9hZGVyIHJlcXVlc3QuXG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICBkZWZpbmUoJ3VuZGVyc2NvcmUnLCBbXSwgZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gXztcbiAgICB9KTtcbiAgfVxufS5jYWxsKHRoaXMpKTtcbiIsImNoYWkgICAgICA9IHJlcXVpcmUoJ2NoYWknKVxuZXhwZWN0ICAgID0gY2hhaS5leHBlY3RcbnNpbm9uICAgICA9IHJlcXVpcmUoJ3Npbm9uJylcbnNpbm9uQ2hhaSA9IHJlcXVpcmUoJ3Npbm9uLWNoYWknKVxuXyAgICAgICAgID0gcmVxdWlyZShcInVuZGVyc2NvcmVcIilcblxuY2hhaS51c2Uoc2lub25DaGFpKVxuXG5Db25uZWN0b3IgPSByZXF1aXJlIFwiLi4vLi4veS10ZXN0L2xpYi95LXRlc3QuY29mZmVlXCJcblkgPSBudWxsICMgbmVlZCBnbG9iYWwgcmVmZXJlbmNlIVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYXNzIFRlc3RcbiAgY29uc3RydWN0b3I6IChAbmFtZV9zdWZmaXggPSBcIlwiLCBZanMpLT5cbiAgICBZID0gWWpzXG4gICAgQG51bWJlcl9vZl90ZXN0X2Nhc2VzX211bHRpcGxpZXIgPSAxXG4gICAgQHJlcGVhdF90aGlzID0gMSAqIEBudW1iZXJfb2ZfdGVzdF9jYXNlc19tdWx0aXBsaWVyXG4gICAgQGRvU29tZXRoaW5nX2Ftb3VudCA9IDEyMyAqIEBudW1iZXJfb2ZfdGVzdF9jYXNlc19tdWx0aXBsaWVyXG4gICAgQG51bWJlcl9vZl9lbmdpbmVzID0gNSArIEBudW1iZXJfb2ZfdGVzdF9jYXNlc19tdWx0aXBsaWVyIC0gMVxuXG4gICAgQHRpbWUgPSAwICMgZGVub3RlcyB0byB0aGUgdGltZSB3aGVuIHJ1biB3YXMgc3RhcnRlZFxuICAgIEBvcHMgPSAwICMgbnVtYmVyIG9mIG9wZXJhdGlvbnMgKHVzZWQgd2l0aCBAdGltZSlcbiAgICBAdGltZV9ub3cgPSAwICMgY3VycmVudCB0aW1lXG4gICAgQG1heF9kZXB0aCA9IDNcblxuICAgIEBkZWJ1ZyA9IGZhbHNlXG5cbiAgICBAcmVpbml0aWFsaXplKClcbiAgICBmb3IgZ2YgaW4gQGdldEdlbmVyYXRpbmdGdW5jdGlvbnMoMClcbiAgICAgIGlmIG5vdCAoZ2YudHlwZXM/IGFuZCBnZi5mPylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiR2VuZXJhdGluZyBGdW5jdGlvbnMgYXJlIG5vdCBpbml0aWFsaXplZCBwcm9wZXJseSFcIlxuICAgICAgZm9yIHQgaW4gZ2YudHlwZXNcbiAgICAgICAgaWYgbm90IHQ/XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IGhhdmVudCBpbmNsdWRlZHQgdGhpcyB0eXBlIGluIFkgKGRvIHJlcXVpcmUgJ3ktd2hhdGV2ZXInKVwiXG5cbiAgcmVpbml0aWFsaXplOiAoKS0+XG4gICAgQHVzZXJzID0gW11cbiAgICBmb3IgaSBpbiBbMC4uLkBudW1iZXJfb2ZfZW5naW5lc11cbiAgICAgIHUgPSBAbWFrZU5ld1VzZXIgKGkrQG5hbWVfc3VmZml4KVxuICAgICAgZm9yIHVzZXIgaW4gQHVzZXJzXG4gICAgICAgIHUuX21vZGVsLmNvbm5lY3Rvci5qb2luKHVzZXIuX21vZGVsLmNvbm5lY3RvcikgIyBUT0RPOiBjaGFuZ2UgdGhlIHRlc3QtY29ubmVjdG9yIHRvIG1ha2UgdGhpcyBtb3JlIGNvbnZlbmllbnRcbiAgICAgIEB1c2Vycy5wdXNoIHVcbiAgICBAaW5pdFVzZXJzPyhAdXNlcnNbMF0pXG4gICAgQGZsdXNoQWxsKClcblxuICAjIGlzIGNhbGxlZCBieSBpbXBsZW1lbnRpbmcgY2xhc3NcbiAgbWFrZU5ld1VzZXI6ICh1c2VyKS0+XG4gICAgdXNlci5fbW9kZWwuSEIuc3RvcEdhcmJhZ2VDb2xsZWN0aW9uKClcbiAgICB1c2VyXG5cbiAgZ2V0U29tZVVzZXI6ICgpLT5cbiAgICBpID0gXy5yYW5kb20gMCwgKEB1c2Vycy5sZW5ndGgtMSlcbiAgICBAdXNlcnNbaV1cblxuICBnZXRSYW5kb21UZXh0OiAoY2hhcnMsIG1pbl9sZW5ndGggPSAwKS0+XG4gICAgY2hhcnMgPz0gXCJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5elwiXG4gICAgbGVuZ3RoID0gXy5yYW5kb20gbWluX2xlbmd0aCwgMTBcbiAgICAjbGVuZ3RoID0gMVxuICAgIG5leHRjaGFyID0gY2hhcnNbKF8ucmFuZG9tIDAsIChjaGFycy5sZW5ndGgtMSkpXVxuICAgIHRleHQgPSBcIlwiXG4gICAgXyhsZW5ndGgpLnRpbWVzICgpLT4gdGV4dCArPSBuZXh0Y2hhclxuICAgIHRleHRcblxuICBnZXRSYW5kb21PYmplY3Q6ICgpLT5cbiAgICByZXN1bHQgPSB7fVxuICAgIGtleTEgPSBAZ2V0UmFuZG9tS2V5KClcbiAgICBrZXkyID0gQGdldFJhbmRvbUtleSgpXG4gICAgdmFsMSA9IEBnZXRSYW5kb21UZXh0KClcbiAgICB2YWwyID0gbnVsbFxuICAgIGlmIF8ucmFuZG9tKDAsMSkgaXMgMVxuICAgICAgdmFsMiA9IEBnZXRSYW5kb21PYmplY3QoKVxuICAgIGVsc2VcbiAgICAgIHZhbDIgPSBAZ2V0UmFuZG9tVGV4dCgpXG4gICAgcmVzdWx0W2tleTFdID0gdmFsMVxuICAgIHJlc3VsdFtrZXkyXSA9IHZhbDJcbiAgICByZXN1bHRcblxuICBnZXRSYW5kb21LZXk6ICgpLT5cbiAgICBAZ2V0UmFuZG9tVGV4dCBbMSwyLCd4JywneSddLCAxICMgb25seSA0IGtleXNcblxuICBnZXRHZW5lcmF0aW5nRnVuY3Rpb25zOiAodXNlcl9udW0pPT5cbiAgICB0eXBlcyA9IEB1c2Vyc1t1c2VyX251bV0uX21vZGVsLm9wZXJhdGlvbnNcbiAgICBbXVxuICBnZXRSYW5kb21Sb290OiAodXNlcl9udW0pLT5cbiAgICB0aHJvdyBuZXcgRXJyb3IgXCJpbXBsZW1lbnQgbWUhXCJcblxuICBjb21wYXJlOiAobzEsIG8yLCBkZXB0aCA9IChAbWF4X2RlcHRoKzEpKS0+XG4gICAgaWYgbzEgaXMgbzIgb3IgZGVwdGggPD0gMFxuICAgICAgdHJ1ZVxuICAgIGVsc2UgaWYgbzEuX25hbWU/IGFuZCBvMS5fbmFtZSBpc250IG8yLl9uYW1lXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJkaWZmZXJlbnQgdHlwZXNcIlxuICAgIGVsc2UgaWYgbzEuX21vZGVsP1xuICAgICAgQGNvbXBhcmUgbzEuX21vZGVsLCBvMi5fbW9kZWwsIGRlcHRoXG4gICAgZWxzZSBpZiBvMS50eXBlIGlzIFwiTWFwTWFuYWdlclwiXG4gICAgICBmb3IgbmFtZSwgdmFsIG9mIG8xLnZhbCgpXG4gICAgICAgIEBjb21wYXJlKHZhbCwgbzIudmFsKG5hbWUpLCBkZXB0aC0xKVxuICAgIGVsc2UgaWYgbzEudHlwZSBpcyBcIkxpc3RNYW5hZ2VyXCJcbiAgICAgIGZvciB2YWwsaSBpbiBvMS52YWwoKVxuICAgICAgICBAY29tcGFyZSh2YWwsIG8yLnZhbChpKSwgZGVwdGgtMSlcbiAgICBlbHNlIGlmIG8xLmNvbnN0cnVjdG9yIGlzIEFycmF5IGFuZCBvMi5jb25zdHJ1Y3RvciBpcyBBcnJheVxuICAgICAgaWYgbzEubGVuZ3RoIGlzbnQgbzIubGVuZ3RoXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcIlRoZSBBcnJheXMgZG8gbm90IGhhdmUgdGhlIHNhbWUgc2l6ZSFcIlxuICAgICAgZm9yIG8saSBpbiBvMVxuICAgICAgICBAY29tcGFyZSBvLCBvMltpXSwgKGRlcHRoLTEpXG4gICAgZWxzZSBpZiBvMSBpc250IG8yXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJkaWZmZXJlbnQgdmFsdWVzXCJcbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJJIGRvbid0IGtub3cgd2hhdCB0byBkbyAuLiBcIlxuXG4gIGdlbmVyYXRlUmFuZG9tT3A6ICh1c2VyX251bSk9PlxuICAgIHkgPSBAZ2V0UmFuZG9tUm9vdCh1c2VyX251bSlcbiAgICBjaG9pY2VzID0gQGdldEdlbmVyYXRpbmdGdW5jdGlvbnModXNlcl9udW0pLmZpbHRlciAoZ2YpLT5cbiAgICAgIF8uc29tZSBnZi50eXBlcywgKHR5cGUpLT5cbiAgICAgICAgeSBpbnN0YW5jZW9mIHR5cGVcblxuICAgIGlmIGNob2ljZXMubGVuZ3RoIGlzIDBcbiAgICAgIGNvbnNvbGUuZGlyKHkpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgZm9yZ290IHRvIHNwZWNpZnkgYSB0ZXN0IGdlbmVyYXRpb24gbWV0aG90IGZvciB0aGlzIE9wZXJhdGlvbiEgKCN7eS50eXBlfSlcIlxuICAgIGkgPSBfLnJhbmRvbSAwLCAoY2hvaWNlcy5sZW5ndGgtMSlcbiAgICBjaG9pY2VzW2ldLmYgeVxuXG4gIGFwcGx5UmFuZG9tT3A6ICh1c2VyX251bSk9PlxuICAgIHVzZXIgPSBAdXNlcnNbdXNlcl9udW1dXG4gICAgdXNlci5fbW9kZWwuY29ubmVjdG9yLmZsdXNoT25lUmFuZG9tKClcblxuICBkb1NvbWV0aGluZzogKCktPlxuICAgIHVzZXJfbnVtID0gXy5yYW5kb20gKEBudW1iZXJfb2ZfZW5naW5lcy0xKVxuICAgIGNob2ljZXMgPSBbQGFwcGx5UmFuZG9tT3AsIEBnZW5lcmF0ZVJhbmRvbU9wXVxuICAgIGNob2ljZSA9IF8ucmFuZG9tIChjaG9pY2VzLmxlbmd0aC0xKVxuICAgIGNob2ljZXNbY2hvaWNlXSh1c2VyX251bSlcblxuICBmbHVzaEFsbDogKGZpbmFsKS0+XG4gICAgIyBUT0RPOiEhXG4gICAgZmluYWwgPSBmYWxzZVxuICAgIGlmIEB1c2Vycy5sZW5ndGggPD0gMSBvciBub3QgZmluYWxcbiAgICAgIGZvciB1c2VyLHVzZXJfbnVtYmVyIGluIEB1c2Vyc1xuICAgICAgICB1c2VyLl9tb2RlbC5jb25uZWN0b3IuZmx1c2hBbGwoKVxuICAgIGVsc2VcbiAgICAgIGZvciB1c2VyLHVzZXJfbnVtYmVyIGluIEB1c2Vyc1sxLi5dXG4gICAgICAgIHVzZXIuX21vZGVsLmNvbm5lY3Rvci5mbHVzaEFsbCgpXG4gICAgICBvcHMgPSBAdXNlcnNbMV0uZ2V0SGlzdG9yeUJ1ZmZlcigpLl9lbmNvZGUgQHVzZXJzWzBdLkhCLmdldE9wZXJhdGlvbkNvdW50ZXIoKVxuICAgICAgQHVzZXJzWzBdLmVuZ2luZS5hcHBseU9wc0NoZWNrRG91YmxlIG9wc1xuXG5cbiAgY29tcGFyZUFsbDogKHRlc3RfbnVtYmVyKS0+XG4gICAgQGZsdXNoQWxsKHRydWUpXG5cbiAgICBAdGltZSArPSAobmV3IERhdGUoKSkuZ2V0VGltZSgpIC0gQHRpbWVfbm93XG5cbiAgICBudW1iZXJfb2ZfY3JlYXRlZF9vcGVyYXRpb25zID0gMFxuICAgIGZvciBpIGluIFswLi4uKEB1c2Vycy5sZW5ndGgpXVxuICAgICAgbnVtYmVyX29mX2NyZWF0ZWRfb3BlcmF0aW9ucyArPSBAdXNlcnNbaV0uX21vZGVsLmNvbm5lY3Rvci5nZXRPcHNJbkV4ZWN1dGlvbk9yZGVyKCkubGVuZ3RoXG4gICAgQG9wcyArPSBudW1iZXJfb2ZfY3JlYXRlZF9vcGVyYXRpb25zKkB1c2Vycy5sZW5ndGhcblxuICAgIG9wc19wZXJfbXNlayA9IE1hdGguZmxvb3IoQG9wcy9AdGltZSlcbiAgICBpZiB0ZXN0X251bWJlcj8gIyBhbmQgQGRlYnVnXG4gICAgICBjb25zb2xlLmxvZyBcIiN7dGVzdF9udW1iZXJ9LyN7QHJlcGVhdF90aGlzfTogI3tudW1iZXJfb2ZfY3JlYXRlZF9vcGVyYXRpb25zfSB3ZXJlIGNyZWF0ZWQgYW5kIGFwcGxpZWQgb24gKCN7QHVzZXJzLmxlbmd0aH0pIHVzZXJzIG9wcyBpbiBhIGRpZmZlcmVudCBvcmRlci5cIiArIFwiIE92ZXIgYWxsIHdlIGNvbnN1bWVkICN7QG9wc30gb3BlcmF0aW9ucyBpbiAje0B0aW1lLzEwMDB9IHNlY29uZHMgKCN7b3BzX3Blcl9tc2VrfSBvcHMvbXNlaykuXCJcblxuICAgIGZvciBpIGluIFswLi4uKEB1c2Vycy5sZW5ndGgtMSldXG4gICAgICBpZiBAZGVidWdcbiAgICAgICAgaWYgbm90IF8uaXNFcXVhbCBAZ2V0Q29udGVudChpKSwgQGdldENvbnRlbnQoaSsxKVxuICAgICAgICAgIHByaW50T3BzSW5FeGVjdXRpb25PcmRlciA9IChvdG51bWJlciwgb3RoZXJvdG51bWJlcik9PlxuICAgICAgICAgICAgb3BzID0gXy5maWx0ZXIgQHVzZXJzW290bnVtYmVyXS5fbW9kZWwuY29ubmVjdG9yLmdldE9wc0luRXhlY3V0aW9uT3JkZXIoKSwgKG8pLT5cbiAgICAgICAgICAgICAgdHlwZW9mIG8udWlkLm9wX25hbWUgaXNudCAnc3RyaW5nJyBhbmQgby51aWQuY3JlYXRvciBpc250ICdfJ1xuICAgICAgICAgICAgZm9yIHMsaiBpbiBvcHNcbiAgICAgICAgICAgICAgY29uc29sZS5sb2cgXCJvcCN7an0gPSBcIiArIChKU09OLnN0cmluZ2lmeSBzKVxuICAgICAgICAgICAgY29uc29sZS5sb2cgXCJcIlxuICAgICAgICAgICAgcyA9IFwib3BzID0gW1wiXG4gICAgICAgICAgICBmb3IgbyxqIGluIG9wc1xuICAgICAgICAgICAgICBpZiBqIGlzbnQgMFxuICAgICAgICAgICAgICAgIHMgKz0gXCIsIFwiXG4gICAgICAgICAgICAgIHMgKz0gXCJvcCN7an1cIlxuICAgICAgICAgICAgcyArPSBcIl1cIlxuICAgICAgICAgICAgY29uc29sZS5sb2cgc1xuICAgICAgICAgICAgY29uc29sZS5sb2cgXCJAdGVzdF91c2VyLmVuZ2luZS5hcHBseU9wcyBvcHNcIlxuICAgICAgICAgICAgY29uc29sZS5sb2cgXCJleHBlY3QoQHRlc3RfdXNlci52YWwoJ25hbWUnKS52YWwoKSkudG8uZXF1YWwoXFxcIiN7QHVzZXJzW290aGVyb3RudW1iZXJdLnZhbCgnbmFtZScpLnZhbCgpfVxcXCIpXCJcbiAgICAgICAgICAgIG9wc1xuICAgICAgICAgIGNvbnNvbGUubG9nIFwiXCJcbiAgICAgICAgICBjb25zb2xlLmxvZyBcIkZvdW5kIGFuIE9UIFB1enpsZSFcIlxuICAgICAgICAgIGNvbnNvbGUubG9nIFwiT1Qgc3RhdGVzOlwiXG4gICAgICAgICAgZm9yIHUsaiBpbiBAdXNlcnNcbiAgICAgICAgICAgIGNvbnNvbGUubG9nIFwiT1Qje2p9OiBcIit1LnZhbCgnbmFtZScpLnZhbCgpXG4gICAgICAgICAgY29uc29sZS5sb2cgXCJcXG5PVCBleGVjdXRpb24gb3JkZXIgKCN7aX0sI3tpKzF9KTpcIlxuICAgICAgICAgIHByaW50T3BzSW5FeGVjdXRpb25PcmRlciBpLCBpKzFcbiAgICAgICAgICBjb25zb2xlLmxvZyBcIlwiXG4gICAgICAgICAgb3BzID0gcHJpbnRPcHNJbkV4ZWN1dGlvbk9yZGVyIGkrMSwgaVxuXG4gICAgICAgICAgY29uc29sZS5sb2cgXCJcIlxuICAgICAgZXhwZWN0KEBjb21wYXJlKEB1c2Vyc1tpXSwgQHVzZXJzW2krMV0pKS50by5ub3QuYmUudW5kZWZpbmVkXG5cbiAgcnVuOiAoKS0+XG4gICAgaWYgQGRlYnVnXG4gICAgICBjb25zb2xlLmxvZyAnJ1xuICAgIGZvciB0aW1lcyBpbiBbMS4uQHJlcGVhdF90aGlzXVxuICAgICAgQHRpbWVfbm93ID0gKG5ldyBEYXRlKS5nZXRUaW1lKClcbiAgICAgIGZvciBpIGluIFsxLi5NYXRoLmZsb29yKEBkb1NvbWV0aGluZ19hbW91bnQvMildXG4gICAgICAgIEBkb1NvbWV0aGluZygpXG4gICAgICBAZmx1c2hBbGwoZmFsc2UpXG4gICAgICBmb3IgdSBpbiBAdXNlcnNcbiAgICAgICAgdS5fbW9kZWwuSEIuZW1wdHlHYXJiYWdlKClcbiAgICAgIGZvciBpIGluIFsxLi5NYXRoLmZsb29yKEBkb1NvbWV0aGluZ19hbW91bnQvMildXG4gICAgICAgIEBkb1NvbWV0aGluZygpXG5cbiAgICAgIEBjb21wYXJlQWxsKHRpbWVzKVxuICAgICAgQHRlc3RIQmVuY29kaW5nKClcbiAgICAgIGlmIHRpbWVzIGlzbnQgQHJlcGVhdF90aGlzXG4gICAgICAgIEByZWluaXRpYWxpemUoKVxuXG4gIHRlc3RIQmVuY29kaW5nOiAoKS0+XG4gICAgIyBpbiBjYXNlIG9mIEpzb25GcmFtZXdvcmssIGV2ZXJ5IHVzZXIgd2lsbCBjcmVhdGUgaXRzIEpTT04gZmlyc3QhIHRoZXJlZm9yZSwgdGhlIHRlc3R1c2VycyBpZCBtdXN0IGJlIHNtYWxsIHRoYW4gYWxsIHRoZSBvdGhlcnMgKHNlZSBJbnNlcnRUeXBlKVxuICAgIEB1c2Vyc1tAdXNlcnMubGVuZ3RoXSA9IEBtYWtlTmV3VXNlciAoLTEpICMgdGhpcyBkb2VzIG5vdCB3YW50IHRvIGpvaW4gd2l0aCBhbnltb2R5XG5cbiAgICBAdXNlcnNbQHVzZXJzLmxlbmd0aC0xXS5fbW9kZWwuSEIucmVuZXdTdGF0ZVZlY3RvciBAdXNlcnNbMF0uX21vZGVsLkhCLmdldE9wZXJhdGlvbkNvdW50ZXIoKVxuICAgIEB1c2Vyc1tAdXNlcnMubGVuZ3RoLTFdLl9tb2RlbC5lbmdpbmUuYXBwbHlPcHMgQHVzZXJzWzBdLl9tb2RlbC5IQi5fZW5jb2RlKClcblxuICAgICNpZiBAZ2V0Q29udGVudChAdXNlcnMubGVuZ3RoLTEpIGlzbnQgQGdldENvbnRlbnQoMClcbiAgICAjICBjb25zb2xlLmxvZyBcInRlc3RIQmVuY29kaW5nOlwiXG4gICAgIyAgY29uc29sZS5sb2cgXCJVbnByb2Nlc3NlZCBvcHMgZmlyc3Q6ICN7QHVzZXJzWzBdLmVuZ2luZS51bnByb2Nlc3NlZF9vcHMubGVuZ3RofVwiXG4gICAgIyAgY29uc29sZS5sb2cgXCJVbnByb2Nlc3NlZCBvcHMgbGFzdDogI3tAdXNlcnNbQHVzZXJzLmxlbmd0aC0xXS5lbmdpbmUudW5wcm9jZXNzZWRfb3BzLmxlbmd0aH1cIlxuICAgIGV4cGVjdChAY29tcGFyZShAdXNlcnNbQHVzZXJzLmxlbmd0aC0xXSwgQHVzZXJzWzBdKSkudG8ubm90LmJlLnVuZGVmaW5lZFxuIiwiY2hhaSAgICAgID0gcmVxdWlyZSgnY2hhaScpXG5leHBlY3QgICAgPSBjaGFpLmV4cGVjdFxuc2hvdWxkICAgID0gY2hhaS5zaG91bGQoKVxuc2lub24gICAgID0gcmVxdWlyZSgnc2lub24nKVxuc2lub25DaGFpID0gcmVxdWlyZSgnc2lub24tY2hhaScpXG5fICAgICAgICAgPSByZXF1aXJlKFwidW5kZXJzY29yZVwiKVxuXG5jaGFpLnVzZShzaW5vbkNoYWkpXG5cblkgPSByZXF1aXJlIFwiLi4vbGliL3kuY29mZmVlXCJcblkuVGVzdCA9IHJlcXVpcmUgXCIuLi8uLi95LXRlc3QvbGliL3ktdGVzdC5jb2ZmZWVcIlxuWS5UZXh0ID0gcmVxdWlyZSBcIi4uLy4uL3ktdGV4dC9saWIveS10ZXh0XCJcblkuTGlzdCA9IHJlcXVpcmUgXCIuLi8uLi95LWxpc3QvbGliL3ktbGlzdFwiXG5cblRlc3RTdWl0ZSA9IHJlcXVpcmUgXCIuL1Rlc3RTdWl0ZVwiXG5jbGFzcyBPYmplY3RUZXN0IGV4dGVuZHMgVGVzdFN1aXRlXG5cbiAgY29uc3RydWN0b3I6IChzdWZmaXgpLT5cbiAgICBzdXBlciBzdWZmaXgsIFlcblxuICBtYWtlTmV3VXNlcjogKHVzZXJJZCktPlxuICAgIGNvbm4gPSBuZXcgWS5UZXN0IHVzZXJJZFxuICAgIHN1cGVyIG5ldyBZIGNvbm5cblxuICB0eXBlOiBcIk9iamVjdFRlc3RcIlxuXG4gIGdldFJhbmRvbVJvb3Q6ICh1c2VyX251bSwgcm9vdCwgZGVwdGggPSBAbWF4X2RlcHRoKS0+XG4gICAgcm9vdCA/PSBAdXNlcnNbdXNlcl9udW1dXG4gICAgaWYgZGVwdGggaXMgMCBvciBfLnJhbmRvbSgwLDEpIGlzIDEgIyB0YWtlIHJvb3RcbiAgICAgIHJvb3RcbiAgICBlbHNlICMgdGFrZSBjaGlsZFxuICAgICAgZGVwdGgtLVxuICAgICAgZWxlbXMgPSBudWxsXG4gICAgICBpZiByb290Ll9uYW1lIGlzIFwiT2JqZWN0XCJcbiAgICAgICAgZWxlbXMgPVxuICAgICAgICAgIGZvciBvbmFtZSx2YWwgb2Ygcm9vdC52YWwoKVxuICAgICAgICAgICAgdmFsXG4gICAgICBlbHNlIGlmIHJvb3QuX25hbWUgaXMgXCJBcnJheVwiXG4gICAgICAgIGVsZW1zID0gcm9vdC52YWwoKVxuICAgICAgZWxzZVxuICAgICAgICByZXR1cm4gcm9vdFxuXG4gICAgICBlbGVtcyA9IGVsZW1zLmZpbHRlciAoZWxlbSktPlxuICAgICAgICBlbGVtPyBhbmQgKChlbGVtLl9uYW1lIGlzIFwiQXJyYXlcIikgb3IgKGVsZW0uX25hbWUgaXMgXCJPYmplY3RcIikpXG4gICAgICBpZiBlbGVtcy5sZW5ndGggaXMgMFxuICAgICAgICByb290XG4gICAgICBlbHNlXG4gICAgICAgIHAgPSBlbGVtc1tfLnJhbmRvbSgwLCBlbGVtcy5sZW5ndGgtMSldXG4gICAgICAgIEBnZXRSYW5kb21Sb290IHVzZXJfbnVtLCBwLCBkZXB0aFxuXG4gIGdldEdlbmVyYXRpbmdGdW5jdGlvbnM6ICh1c2VyX251bSktPlxuICAgIHN1cGVyKHVzZXJfbnVtKS5jb25jYXQgW1xuICAgICAgICBmIDogKHkpPT4gIyBEZWxldGUgT2JqZWN0IFByb3BlcnR5XG4gICAgICAgICAgbGlzdCA9IGZvciBuYW1lLCBvIG9mIHkudmFsKClcbiAgICAgICAgICAgIG5hbWVcbiAgICAgICAgICBpZiBsaXN0Lmxlbmd0aCA+IDBcbiAgICAgICAgICAgIGtleSA9IGxpc3RbXy5yYW5kb20oMCxsaXN0Lmxlbmd0aC0xKV1cbiAgICAgICAgICAgIHkuZGVsZXRlKGtleSlcbiAgICAgICAgdHlwZXM6IFtZLk9iamVjdF1cbiAgICAgICxcbiAgICAgICAgZiA6ICh5KT0+ICMgU0VUIE9iamVjdCBQcm9wZXJ0eVxuICAgICAgICAgIHkudmFsKEBnZXRSYW5kb21LZXkoKSwgbmV3IFkuT2JqZWN0KEBnZXRSYW5kb21PYmplY3QoKSkpXG4gICAgICAgIHR5cGVzOiBbWS5PYmplY3RdXG4gICAgICAsXG4gICAgICAgIGYgOiAoeSk9PiAjIFNFVCBQUk9QRVJUWSBURVhUXG4gICAgICAgICAgeS52YWwoQGdldFJhbmRvbUtleSgpLCBuZXcgWS5UZXh0KEBnZXRSYW5kb21UZXh0KCkpKVxuICAgICAgICB0eXBlczogW1kuT2JqZWN0XVxuICAgICAgLFxuICAgICAgICBmIDogKHkpPT4gIyBTRVQgUFJPUEVSVFkgTGlzdFxuICAgICAgICAgIHkudmFsKEBnZXRSYW5kb21LZXkoKSwgbmV3IFkuTGlzdChAZ2V0UmFuZG9tVGV4dCgpLnNwbGl0KFwiXCIpKSlcbiAgICAgICAgdHlwZXM6IFtZLk9iamVjdF1cbiAgICAgICxcbiAgICAgICAgZiA6ICh5KT0+ICMgRGVsZXRlIEFycmF5IEVsZW1lbnRcbiAgICAgICAgICBsaXN0ID0geS52YWwoKVxuICAgICAgICAgIGlmIGxpc3QubGVuZ3RoID4gMFxuICAgICAgICAgICAgaSA9IF8ucmFuZG9tKDAsbGlzdC5sZW5ndGgtMSlcbiAgICAgICAgICAgIHkuZGVsZXRlKGkpXG4gICAgICAgIHR5cGVzOiBbWS5MaXN0XVxuICAgICAgLFxuICAgICAgICBmIDogKHkpPT4gIyBpbnNlcnQgT2JqZWN0IG11dGFibGVcbiAgICAgICAgICBsID0geS52YWwoKS5sZW5ndGhcbiAgICAgICAgICB5Lmluc2VydChfLnJhbmRvbSgwLCBsLTEpLCBuZXcgWS5PYmplY3QoQGdldFJhbmRvbU9iamVjdCgpKSlcbiAgICAgICAgdHlwZXM6IFtZLkxpc3RdXG4gICAgICAsXG4gICAgICAgIGYgOiAoeSk9PiAjIGluc2VydCBUZXh0IG11dGFibGVcbiAgICAgICAgICBsID0geS52YWwoKS5sZW5ndGhcbiAgICAgICAgICB5Lmluc2VydChfLnJhbmRvbSgwLCBsLTEpLCBuZXcgWS5UZXh0KEBnZXRSYW5kb21UZXh0KCkpKVxuICAgICAgICB0eXBlcyA6IFtZLkxpc3RdXG4gICAgICAsXG4gICAgICAgIGYgOiAoeSk9PiAjIGluc2VydCBMaXN0IG11dGFibGVcbiAgICAgICAgICBsID0geS52YWwoKS5sZW5ndGhcbiAgICAgICAgICB5Lmluc2VydChfLnJhbmRvbSgwLCBsLTEpLCBuZXcgWS5MaXN0KEBnZXRSYW5kb21UZXh0KCkuc3BsaXQoXCJcIikpKVxuICAgICAgICB0eXBlcyA6IFtZLkxpc3RdXG4gICAgICAsXG4gICAgICAgIGYgOiAoeSk9PiAjIGluc2VydCBOdW1iZXIgKHByaW1pdGl2ZSBvYmplY3QpXG4gICAgICAgICAgbCA9IHkudmFsKCkubGVuZ3RoXG4gICAgICAgICAgeS5pbnNlcnQoXy5yYW5kb20oMCxsLTEpLCBfLnJhbmRvbSgwLDQyKSlcbiAgICAgICAgdHlwZXMgOiBbWS5MaXN0XVxuICAgICAgLFxuICAgICAgICBmIDogKHkpPT4gIyBTRVQgT2JqZWN0IFByb3BlcnR5IChjaXJjdWxhcilcbiAgICAgICAgICB5LnZhbChAZ2V0UmFuZG9tS2V5KCksIEBnZXRSYW5kb21Sb290IHVzZXJfbnVtKVxuICAgICAgICB0eXBlczogW1kuT2JqZWN0XVxuICAgICAgLFxuICAgICAgICBmIDogKHkpPT4gIyBpbnNlcnQgT2JqZWN0IG11dGFibGUgKGNpcmN1bGFyKVxuICAgICAgICAgIGwgPSB5LnZhbCgpLmxlbmd0aFxuICAgICAgICAgIHkuaW5zZXJ0KF8ucmFuZG9tKDAsIGwtMSksIEBnZXRSYW5kb21Sb290IHVzZXJfbnVtKVxuICAgICAgICB0eXBlczogW1kuTGlzdF1cbiAgICAgICxcbiAgICAgICAgZiA6ICh5KT0+ICMgSU5TRVJUIFRFWFRcbiAgICAgICAgICB5XG4gICAgICAgICAgcG9zID0gXy5yYW5kb20gMCwgKHkudmFsKCkubGVuZ3RoLTEpXG4gICAgICAgICAgeS5pbnNlcnQgcG9zLCBAZ2V0UmFuZG9tVGV4dCgpXG4gICAgICAgICAgbnVsbFxuICAgICAgICB0eXBlczogW1kuVGV4dF1cbiAgICAgICxcbiAgICAgICAgZiA6ICh5KS0+ICMgREVMRVRFIFRFWFRcbiAgICAgICAgICBpZiB5LnZhbCgpLmxlbmd0aCA+IDBcbiAgICAgICAgICAgIHBvcyA9IF8ucmFuZG9tIDAsICh5LnZhbCgpLmxlbmd0aC0xKSAjIFRPRE86IHB1dCBoZXJlIGFsc28gYXJiaXRyYXJ5IG51bWJlciAodGVzdCBiZWhhdmlvdXIgaW4gZXJyb3IgY2FzZXMpXG4gICAgICAgICAgICBsZW5ndGggPSBfLnJhbmRvbSAwLCAoeS52YWwoKS5sZW5ndGggLSBwb3MpXG4gICAgICAgICAgICBvcHMxID0geS5kZWxldGUgcG9zLCBsZW5ndGhcbiAgICAgICAgICB1bmRlZmluZWRcbiAgICAgICAgdHlwZXMgOiBbWS5UZXh0XVxuICAgICAgXVxuXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdFRlc3RcblxuZGVzY3JpYmUgXCJPYmplY3QgVGVzdFwiLCAtPlxuICBAdGltZW91dCA1MDAwMDBcblxuICBiZWZvcmVFYWNoIChkb25lKS0+XG4gICAgQHlUZXN0ID0gbmV3IE9iamVjdFRlc3QoKVxuICAgIEB1c2VycyA9IEB5VGVzdC51c2Vyc1xuXG4gICAgQHRlc3RfdXNlciA9IEB5VGVzdC5tYWtlTmV3VXNlciBcInRlc3RfdXNlclwiXG4gICAgZG9uZSgpXG5cbiAgaXQgXCJjYW4gaGFuZGxlIG1hbnkgZW5naW5lcywgbWFueSBvcGVyYXRpb25zLCBjb25jdXJyZW50bHkgKHJhbmRvbSlcIiwgLT5cbiAgICBjb25zb2xlLmxvZyBcIlwiICMgVE9ET1xuICAgIEB5VGVzdC5ydW4oKVxuXG4gIGl0IFwiaGFzIGEgd29ya2luZyB0ZXN0IHN1aXRlXCIsIC0+XG4gICAgQHlUZXN0LmNvbXBhcmVBbGwoKVxuXG4gIGl0IFwiaGFuZGxlcyBkb3VibGUtbGF0ZS1qb2luXCIsIC0+XG4gICAgdGVzdCA9IG5ldyBPYmplY3RUZXN0KFwiZG91YmxlXCIpXG4gICAgdGVzdC5ydW4oKVxuICAgIEB5VGVzdC5ydW4oKVxuICAgIHUxID0gdGVzdC51c2Vyc1swXVxuICAgIHUyID0gQHlUZXN0LnVzZXJzWzFdXG4gICAgb3BzMSA9IHUxLl9tb2RlbC5IQi5fZW5jb2RlKClcbiAgICBvcHMyID0gdTIuX21vZGVsLkhCLl9lbmNvZGUoKVxuICAgIHUxLl9tb2RlbC5lbmdpbmUuYXBwbHlPcCBvcHMyLCB0cnVlXG4gICAgdTIuX21vZGVsLmVuZ2luZS5hcHBseU9wIG9wczEsIHRydWVcblxuICAgIGV4cGVjdChAeVRlc3QuY29tcGFyZSh1MSwgdTIpKS50by5ub3QuYmUudW5kZWZpbmVkXG5cbiAgaXQgXCJjYW4gaGFuZGxlIGNyZWF0b24gb2YgY29tcGxleCBqc29uICgxKVwiLCAtPlxuICAgIEB5VGVzdC51c2Vyc1swXS52YWwoJ2EnLCBuZXcgWS5UZXh0KCdxJykpXG4gICAgQHlUZXN0LnVzZXJzWzFdLnZhbCgnYScsIG5ldyBZLlRleHQoJ3QnKSlcbiAgICBAeVRlc3QuY29tcGFyZUFsbCgpXG4gICAgcSA9IEB5VGVzdC51c2Vyc1syXS52YWwoJ2EnKVxuICAgIHEuaW5zZXJ0KDAsJ0EnKVxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKFwiYVwiKS52YWwoKSkudG8uZXF1YWwoXCJBdFwiKVxuXG4gIGl0IFwiY2FuIGhhbmRsZSBjcmVhdG9uIG9mIGNvbXBsZXgganNvbiAoMilcIiwgLT5cbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ3gnLCBuZXcgWS5PYmplY3QoeydhJzonYid9KSlcbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ2EnLCBuZXcgWS5PYmplY3QoeydhJzp7cTogbmV3IFkuVGV4dChcImR0cm5kdHJ0ZHJudGRybnJ0ZG5ydGRucnRkbnJ0ZG5yZG5yZHRcIil9fSkpXG4gICAgQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdiJywgbmV3IFkuT2JqZWN0KHsnYSc6e319KSlcbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ2MnLCBuZXcgWS5PYmplY3QoeydhJzonYyd9KSlcbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ2MnLCBuZXcgWS5PYmplY3QoeydhJzonYid9KSlcbiAgICBAeVRlc3QuY29tcGFyZUFsbCgpXG4gICAgcSA9IEB5VGVzdC5nZXRTb21lVXNlcigpLnZhbChcImFcIikudmFsKFwiYVwiKS52YWwoXCJxXCIpXG4gICAgcS5pbnNlcnQoMCwnQScpXG4gICAgQHlUZXN0LmNvbXBhcmVBbGwoKVxuICAgIGV4cGVjdChAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoXCJhXCIpLnZhbChcImFcIikudmFsKFwicVwiKS52YWwoKSkudG8uZXF1YWwoXCJBZHRybmR0cnRkcm50ZHJucnRkbnJ0ZG5ydGRucnRkbnJkbnJkdFwiKVxuXG4gIGl0IFwiY2FuIGhhbmRsZSBjcmVhdG9uIG9mIGNvbXBsZXgganNvbiAoMylcIiwgLT5cbiAgICBAeVRlc3QudXNlcnNbMF0udmFsKCdsJywgbmV3IFkuTGlzdChbMSwyLDNdKSlcbiAgICBAeVRlc3QudXNlcnNbMV0udmFsKCdsJywgbmV3IFkuTGlzdChbNCw1LDZdKSlcbiAgICBAeVRlc3QuY29tcGFyZUFsbCgpXG4gICAgQHlUZXN0LnVzZXJzWzJdLnZhbCgnbCcpLmluc2VydCgwLCdBJylcbiAgICB3ID0gQHlUZXN0LnVzZXJzWzFdLnZhbCgnbCcpLmluc2VydCgwLG5ldyBZLlRleHQoJ0InKSkudmFsKDApXG4gICAgdy5pbnNlcnQgMSwgXCJDXCJcbiAgICBleHBlY3Qody52YWwoKSkudG8uZXF1YWwoXCJCQ1wiKVxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcblxuICBpdCBcImhhbmRsZXMgaW1tdXRhYmxlcyBhbmQgcHJpbWl0aXZlIGRhdGEgdHlwZXNcIiwgLT5cbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ3N0cmluZycsIFwidGV4dFwiKVxuICAgIEB5VGVzdC5nZXRTb21lVXNlcigpLnZhbCgnbnVtYmVyJywgNClcbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ29iamVjdCcsIG5ldyBZLk9iamVjdCh7cTpcInJyXCJ9KSlcbiAgICBAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ251bGwnLCBudWxsKVxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdzdHJpbmcnKSkudG8uZXF1YWwgXCJ0ZXh0XCJcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdudW1iZXInKSkudG8uZXF1YWwgNFxuICAgIGV4cGVjdChAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ29iamVjdCcpLnZhbCgncScpKS50by5lcXVhbCBcInJyXCJcbiAgICBleHBlY3QoQHlUZXN0LmdldFNvbWVVc2VyKCkudmFsKCdudWxsJykgaXMgbnVsbCkudG8uYmUub2tcblxuICBpdCBcImhhbmRsZXMgaW1tdXRhYmxlcyBhbmQgcHJpbWl0aXZlIGRhdGEgdHlwZXMgKDIpXCIsIC0+XG4gICAgQHlUZXN0LnVzZXJzWzBdLnZhbCgnc3RyaW5nJywgXCJ0ZXh0XCIpXG4gICAgQHlUZXN0LnVzZXJzWzFdLnZhbCgnbnVtYmVyJywgNClcbiAgICBAeVRlc3QudXNlcnNbMl0udmFsKCdvYmplY3QnLCBuZXcgWS5PYmplY3Qoe3E6XCJyclwifSkpXG4gICAgQHlUZXN0LnVzZXJzWzBdLnZhbCgnbnVsbCcsIG51bGwpXG4gICAgQHlUZXN0LmNvbXBhcmVBbGwoKVxuICAgIGV4cGVjdChAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ3N0cmluZycpKS50by5lcXVhbCBcInRleHRcIlxuICAgIGV4cGVjdChAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ251bWJlcicpKS50by5lcXVhbCA0XG4gICAgZXhwZWN0KEB5VGVzdC5nZXRTb21lVXNlcigpLnZhbCgnb2JqZWN0JykudmFsKCdxJykpLnRvLmVxdWFsIFwicnJcIlxuICAgIGV4cGVjdChAeVRlc3QuZ2V0U29tZVVzZXIoKS52YWwoJ251bGwnKSBpcyBudWxsKS50by5iZS5va1xuXG4gIGl0IFwiT2JzZXJ2ZXJzIHdvcmsgb24gSlNPTiBUeXBlc38gKGFkZCB0eXBlIG9ic2VydmVycywgbG9jYWwgYW5kIGZvcmVpZ24pXCIsIC0+XG4gICAgdSA9IEB5VGVzdC51c2Vyc1swXVxuICAgIEB5VGVzdC5mbHVzaEFsbCgpXG4gICAgbGFzdF90YXNrID0gbnVsbFxuICAgIG9ic2VydmVyMSA9IChjaGFuZ2VzKS0+XG4gICAgICBleHBlY3QoY2hhbmdlcy5sZW5ndGgpLnRvLmVxdWFsKDEpXG4gICAgICBjaGFuZ2UgPSBjaGFuZ2VzWzBdXG4gICAgICBleHBlY3QoY2hhbmdlLnR5cGUpLnRvLmVxdWFsKFwiYWRkXCIpXG4gICAgICBleHBlY3QoY2hhbmdlLm9iamVjdCkudG8uZXF1YWwodSlcbiAgICAgIGV4cGVjdChjaGFuZ2UuY2hhbmdlZEJ5KS50by5lcXVhbCgnMCcpXG4gICAgICBleHBlY3QoY2hhbmdlLm5hbWUpLnRvLmVxdWFsKFwibmV3U3R1ZmZcIilcbiAgICAgIGxhc3RfdGFzayA9IFwib2JzZXJ2ZXIxXCJcbiAgICB1Lm9ic2VydmUgb2JzZXJ2ZXIxXG4gICAgdS52YWwoXCJuZXdTdHVmZlwiLG5ldyBZLlRleHQoXCJzb21lU3R1ZmZcIikpXG4gICAgZXhwZWN0KGxhc3RfdGFzaykudG8uZXF1YWwoXCJvYnNlcnZlcjFcIilcbiAgICB1LnVub2JzZXJ2ZSBvYnNlcnZlcjFcblxuICAgIG9ic2VydmVyMiA9IChjaGFuZ2VzKS0+XG4gICAgICBleHBlY3QoY2hhbmdlcy5sZW5ndGgpLnRvLmVxdWFsKDEpXG4gICAgICBjaGFuZ2UgPSBjaGFuZ2VzWzBdXG4gICAgICBleHBlY3QoY2hhbmdlLnR5cGUpLnRvLmVxdWFsKFwiYWRkXCIpXG4gICAgICBleHBlY3QoY2hhbmdlLm9iamVjdCkudG8uZXF1YWwodSlcbiAgICAgIGV4cGVjdChjaGFuZ2UuY2hhbmdlZEJ5KS50by5lcXVhbCgnMScpXG4gICAgICBleHBlY3QoY2hhbmdlLm5hbWUpLnRvLmVxdWFsKFwibW9yZVN0dWZmXCIpXG4gICAgICBsYXN0X3Rhc2sgPSBcIm9ic2VydmVyMlwiXG4gICAgdS5vYnNlcnZlIG9ic2VydmVyMlxuICAgIHYgPSBAeVRlc3QudXNlcnNbMV1cbiAgICB2LnZhbChcIm1vcmVTdHVmZlwiLFwic29tZU1vcmVTdHVmZlwiKVxuICAgIEB5VGVzdC5mbHVzaEFsbCgpXG4gICAgZXhwZWN0KGxhc3RfdGFzaykudG8uZXF1YWwoXCJvYnNlcnZlcjJcIilcbiAgICB1LnVub2JzZXJ2ZSBvYnNlcnZlcjJcblxuICBpdCBcIk9ic2VydmVycyB3b3JrIG9uIEpTT04gVHlwZXN/ICh1cGRhdGUgdHlwZSBvYnNlcnZlcnMsIGxvY2FsIGFuZCBmb3JlaWduKVwiLCAtPlxuICAgIHUgPSBAeVRlc3QudXNlcnNbMF0udmFsKFwibmV3U3R1ZmZcIiwgbmV3IFkuVGV4dChcIm9sZFN0dWZmXCIpKS52YWwoXCJtb3JlU3R1ZmZcIixuZXcgWS5UZXh0KFwibW9yZU9sZFN0dWZmXCIpKVxuICAgIEB5VGVzdC5mbHVzaEFsbCgpXG4gICAgbGFzdF90YXNrID0gbnVsbFxuICAgIG9ic2VydmVyMSA9IChjaGFuZ2VzKS0+XG4gICAgICBleHBlY3QoY2hhbmdlcy5sZW5ndGgpLnRvLmVxdWFsKDEpXG4gICAgICBjaGFuZ2UgPSBjaGFuZ2VzWzBdXG4gICAgICBleHBlY3QoY2hhbmdlLnR5cGUpLnRvLmVxdWFsKFwidXBkYXRlXCIpXG4gICAgICBleHBlY3QoY2hhbmdlLm9iamVjdCkudG8uZXF1YWwodSlcbiAgICAgIGV4cGVjdChjaGFuZ2UuY2hhbmdlZEJ5KS50by5lcXVhbCgnMCcpXG4gICAgICBleHBlY3QoY2hhbmdlLm5hbWUpLnRvLmVxdWFsKFwibmV3U3R1ZmZcIilcbiAgICAgIGV4cGVjdChjaGFuZ2Uub2xkVmFsdWUudmFsKCkpLnRvLmVxdWFsKFwib2xkU3R1ZmZcIilcbiAgICAgIGxhc3RfdGFzayA9IFwib2JzZXJ2ZXIxXCJcbiAgICB1Lm9ic2VydmUgb2JzZXJ2ZXIxXG4gICAgdS52YWwoXCJuZXdTdHVmZlwiLFwic29tZVN0dWZmXCIpXG4gICAgZXhwZWN0KGxhc3RfdGFzaykudG8uZXF1YWwoXCJvYnNlcnZlcjFcIilcbiAgICB1LnVub2JzZXJ2ZSBvYnNlcnZlcjFcblxuICAgIG9ic2VydmVyMiA9IChjaGFuZ2VzKS0+XG4gICAgICBleHBlY3QoY2hhbmdlcy5sZW5ndGgpLnRvLmVxdWFsKDEpXG4gICAgICBjaGFuZ2UgPSBjaGFuZ2VzWzBdXG4gICAgICBleHBlY3QoY2hhbmdlLnR5cGUpLnRvLmVxdWFsKFwidXBkYXRlXCIpXG4gICAgICBleHBlY3QoY2hhbmdlLm9iamVjdCkudG8uZXF1YWwodSlcbiAgICAgIGV4cGVjdChjaGFuZ2UuY2hhbmdlZEJ5KS50by5lcXVhbCgnMScpXG4gICAgICBleHBlY3QoY2hhbmdlLm5hbWUpLnRvLmVxdWFsKFwibW9yZVN0dWZmXCIpXG4gICAgICBleHBlY3QoY2hhbmdlLm9sZFZhbHVlLnZhbCgpKS50by5lcXVhbChcIm1vcmVPbGRTdHVmZlwiKVxuICAgICAgbGFzdF90YXNrID0gXCJvYnNlcnZlcjJcIlxuICAgIHUub2JzZXJ2ZSBvYnNlcnZlcjJcbiAgICB2ID0gQHlUZXN0LnVzZXJzWzFdXG4gICAgdi52YWwoXCJtb3JlU3R1ZmZcIixcInNvbWVNb3JlU3R1ZmZcIilcbiAgICBAeVRlc3QuZmx1c2hBbGwoKVxuICAgIGV4cGVjdChsYXN0X3Rhc2spLnRvLmVxdWFsKFwib2JzZXJ2ZXIyXCIpXG4gICAgdS51bm9ic2VydmUgb2JzZXJ2ZXIyXG5cblxuICBpdCBcIk9ic2VydmVycyB3b3JrIG9uIEpTT04gVHlwZXN/IChkZWxldGUgdHlwZSBvYnNlcnZlcnMsIGxvY2FsIGFuZCBmb3JlaWduKVwiLCAtPlxuICAgIHUgPSBAeVRlc3QudXNlcnNbMF0udmFsKFwibmV3U3R1ZmZcIixuZXcgWS5UZXh0KFwib2xkU3R1ZmZcIikpLnZhbChcIm1vcmVTdHVmZlwiLG5ldyBZLlRleHQoXCJtb3JlT2xkU3R1ZmZcIikpXG4gICAgQHlUZXN0LmZsdXNoQWxsKClcbiAgICBsYXN0X3Rhc2sgPSBudWxsXG4gICAgb2JzZXJ2ZXIxID0gKGNoYW5nZXMpLT5cbiAgICAgIGV4cGVjdChjaGFuZ2VzLmxlbmd0aCkudG8uZXF1YWwoMSlcbiAgICAgIGNoYW5nZSA9IGNoYW5nZXNbMF1cbiAgICAgIGV4cGVjdChjaGFuZ2UudHlwZSkudG8uZXF1YWwoXCJkZWxldGVcIilcbiAgICAgIGV4cGVjdChjaGFuZ2Uub2JqZWN0KS50by5lcXVhbCh1KVxuICAgICAgZXhwZWN0KGNoYW5nZS5jaGFuZ2VkQnkpLnRvLmVxdWFsKCcwJylcbiAgICAgIGV4cGVjdChjaGFuZ2UubmFtZSkudG8uZXF1YWwoXCJuZXdTdHVmZlwiKVxuICAgICAgZXhwZWN0KGNoYW5nZS5vbGRWYWx1ZS52YWwoKSkudG8uZXF1YWwoXCJvbGRTdHVmZlwiKVxuICAgICAgbGFzdF90YXNrID0gXCJvYnNlcnZlcjFcIlxuICAgIHUub2JzZXJ2ZSBvYnNlcnZlcjFcbiAgICB1LmRlbGV0ZShcIm5ld1N0dWZmXCIpXG4gICAgZXhwZWN0KGxhc3RfdGFzaykudG8uZXF1YWwoXCJvYnNlcnZlcjFcIilcbiAgICB1LnVub2JzZXJ2ZSBvYnNlcnZlcjFcblxuICAgIG9ic2VydmVyMiA9IChjaGFuZ2VzKS0+XG4gICAgICBleHBlY3QoY2hhbmdlcy5sZW5ndGgpLnRvLmVxdWFsKDEpXG4gICAgICBjaGFuZ2UgPSBjaGFuZ2VzWzBdXG4gICAgICBleHBlY3QoY2hhbmdlLnR5cGUpLnRvLmVxdWFsKFwiZGVsZXRlXCIpXG4gICAgICBleHBlY3QoY2hhbmdlLm9iamVjdCkudG8uZXF1YWwodSlcbiAgICAgIGV4cGVjdChjaGFuZ2UuY2hhbmdlZEJ5KS50by5lcXVhbCgnMScpXG4gICAgICBleHBlY3QoY2hhbmdlLm5hbWUpLnRvLmVxdWFsKFwibW9yZVN0dWZmXCIpXG4gICAgICBleHBlY3QoY2hhbmdlLm9sZFZhbHVlLnZhbCgpKS50by5lcXVhbChcIm1vcmVPbGRTdHVmZlwiKVxuICAgICAgbGFzdF90YXNrID0gXCJvYnNlcnZlcjJcIlxuICAgIHUub2JzZXJ2ZSBvYnNlcnZlcjJcbiAgICB2ID0gQHlUZXN0LnVzZXJzWzFdXG4gICAgdi5kZWxldGUoXCJtb3JlU3R1ZmZcIilcbiAgICBAeVRlc3QuZmx1c2hBbGwoKVxuICAgIGV4cGVjdChsYXN0X3Rhc2spLnRvLmVxdWFsKFwib2JzZXJ2ZXIyXCIpXG4gICAgdS51bm9ic2VydmUgb2JzZXJ2ZXIyXG5cbiAgaXQgXCJjYW4gaGFuZGxlIGNpcmN1bGFyIEpTT05cIiwgLT5cbiAgICB1ID0gQHlUZXN0LnVzZXJzWzBdXG4gICAgdS52YWwoXCJtZVwiLCB1KVxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcbiAgICB1LnZhbChcInN0dWZmXCIsIG5ldyBZLk9iamVjdCh7eDogdHJ1ZX0pKVxuICAgIHUudmFsKFwic2FtZV9zdHVmZlwiLCB1LnZhbChcInN0dWZmXCIpKVxuICAgIHUudmFsKFwic2FtZV9zdHVmZlwiKS52YWwoXCJ4XCIsIDUpXG4gICAgZXhwZWN0KHUudmFsKFwic2FtZV9zdHVmZlwiKS52YWwoXCJ4XCIpKS50by5lcXVhbCg1KVxuICAgIEB5VGVzdC5jb21wYXJlQWxsKClcbiAgICB1LnZhbChcInN0dWZmXCIpLnZhbChcInlcIiwgdS52YWwoXCJzdHVmZlwiKSlcbiAgICBAeVRlc3QuY29tcGFyZUFsbCgpXG5cblxuXG4iXX0=
|