oncoprintjs
Version:
A data visualization for cancer genomic data.
193 lines (179 loc) • 819 kB
JavaScript
import { __awaiter, __generator, __spreadArrays, __extends } from 'tslib';
import $$1 from 'jquery';
import _, { isNumber } from 'lodash';
import gl_matrix from 'gl-matrix';
/*
* Copyright (c) 2016 Memorial Sloan-Kettering Cancer Center.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS
* FOR A PARTICULAR PURPOSE. The software and documentation provided hereunder
* is on an "as is" basis, and Memorial Sloan-Kettering Cancer Center has no
* obligations to provide maintenance, support, updates, enhancements or
* modifications. In no event shall Memorial Sloan-Kettering Cancer Center be
* liable to any party for direct, indirect, special, incidental or
* consequential damages, including lost profits, arising out of the use of this
* software and its documentation, even if Memorial Sloan-Kettering Cancer
* Center has been advised of the possibility of such damage.
*/
var OMath = Math;
OMath.log2 =
OMath.log2 ||
function (x) {
return Math.log(x) / Math.LN2;
};
function binarysearch(array, target_key, keyFn, return_closest_lower_if_not_found) {
if (!array.length) {
return -1; // return -1 for an empty array
}
var upper_excl = array.length;
var lower_incl = 0;
var middle;
while (lower_incl < upper_excl) {
middle = Math.floor((upper_excl + lower_incl) / 2);
var middle_key = keyFn(array[middle]);
if (middle_key === target_key) {
return middle;
}
else if (target_key > middle_key) {
lower_incl = middle + 1;
}
else if (target_key < middle_key) {
upper_excl = middle;
}
else {
// make sure we don't infinite loop in case anything's wrong
// so that those three cases don't cover everything
return -1;
}
}
if (return_closest_lower_if_not_found) {
return Math.max(0, lower_incl - 1);
}
else {
return -1;
}
}
var CachedProperty = /** @class */ (function () {
function CachedProperty(value, updateFn) {
Object.defineProperty(this, "value", {
enumerable: true,
configurable: true,
writable: true,
value: value
});
Object.defineProperty(this, "updateFn", {
enumerable: true,
configurable: true,
writable: true,
value: updateFn
});
Object.defineProperty(this, "bound_properties", {
enumerable: true,
configurable: true,
writable: true,
value: []
});
}
Object.defineProperty(CachedProperty.prototype, "update", {
enumerable: false,
configurable: true,
writable: true,
value: function () {
var _a;
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
this.value = this.updateFn.apply(null, args);
for (var i = 0; i < this.bound_properties.length; i++) {
(_a = this.bound_properties[i]).update.apply(_a, args);
}
}
});
Object.defineProperty(CachedProperty.prototype, "get", {
enumerable: false,
configurable: true,
writable: true,
value: function () {
return this.value;
}
});
Object.defineProperty(CachedProperty.prototype, "updateAndGet", {
enumerable: false,
configurable: true,
writable: true,
value: function () {
this.update();
return this.get();
}
});
Object.defineProperty(CachedProperty.prototype, "addBoundProperty", {
enumerable: false,
configurable: true,
writable: true,
value: function (cached_property) {
this.bound_properties.push(cached_property);
}
});
return CachedProperty;
}());
var WorkerClass = null;
try {
var WorkerThreads =
typeof module !== 'undefined' && typeof module.require === 'function' && module.require('worker_threads') ||
typeof __non_webpack_require__ === 'function' && __non_webpack_require__('worker_threads') ||
typeof require === 'function' && require('worker_threads');
WorkerClass = WorkerThreads.Worker;
} catch(e) {} // eslint-disable-line
function decodeBase64$1(base64, enableUnicode) {
return Buffer.from(base64, 'base64').toString(enableUnicode ? 'utf16' : 'utf8');
}
function createBase64WorkerFactory$2(base64, sourcemapArg, enableUnicodeArg) {
var sourcemap = sourcemapArg === undefined ? null : sourcemapArg;
var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg;
var source = decodeBase64$1(base64, enableUnicode);
var start = source.indexOf('\n', 10) + 1;
var body = source.substring(start) + (sourcemap ? '\/\/# sourceMappingURL=' + sourcemap : '');
return function WorkerFactory(options) {
return new WorkerClass(body, Object.assign({}, options, { eval: true }));
};
}
function decodeBase64(base64, enableUnicode) {
var binaryString = atob(base64);
if (enableUnicode) {
var binaryView = new Uint8Array(binaryString.length);
for (var i = 0, n = binaryString.length; i < n; ++i) {
binaryView[i] = binaryString.charCodeAt(i);
}
return String.fromCharCode.apply(null, new Uint16Array(binaryView.buffer));
}
return binaryString;
}
function createURL(base64, sourcemapArg, enableUnicodeArg) {
var sourcemap = sourcemapArg === undefined ? null : sourcemapArg;
var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg;
var source = decodeBase64(base64, enableUnicode);
var start = source.indexOf('\n', 10) + 1;
var body = source.substring(start) + (sourcemap ? '\/\/# sourceMappingURL=' + sourcemap : '');
var blob = new Blob([body], { type: 'application/javascript' });
return URL.createObjectURL(blob);
}
function createBase64WorkerFactory$1(base64, sourcemapArg, enableUnicodeArg) {
var url;
return function WorkerFactory(options) {
url = url || createURL(base64, sourcemapArg, enableUnicodeArg);
return new Worker(url, options);
};
}
var kIsNodeJS = Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]';
function isNodeJS() {
return kIsNodeJS;
}
function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {
if (isNodeJS()) {
return createBase64WorkerFactory$2(base64, sourcemapArg, enableUnicodeArg);
}
return createBase64WorkerFactory$1(base64, sourcemapArg, enableUnicodeArg);
}
var WorkerFactory = createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewoJJ3VzZSBzdHJpY3QnOwoKCXZhciBjb21tb25qc0dsb2JhbCA9IHR5cGVvZiBnbG9iYWxUaGlzICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbFRoaXMgOiB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnID8gc2VsZiA6IHt9OwoKCXZhciBkaXN0YW5jZSA9IHsKCSAgZXVjbGlkZWFuOiBmdW5jdGlvbih2MSwgdjIpIHsKCSAgICAgIHZhciB0b3RhbCA9IDA7CgkgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHYxLmxlbmd0aDsgaSsrKSB7CgkgICAgICAgICB0b3RhbCArPSBNYXRoLnBvdyh2MltpXSAtIHYxW2ldLCAyKTsgICAgICAKCSAgICAgIH0KCSAgICAgIHJldHVybiBNYXRoLnNxcnQodG90YWwpOwoJICAgfSwKCSAgIG1hbmhhdHRhbjogZnVuY3Rpb24odjEsIHYyKSB7CgkgICAgIHZhciB0b3RhbCA9IDA7CgkgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdjEubGVuZ3RoIDsgaSsrKSB7CgkgICAgICAgIHRvdGFsICs9IE1hdGguYWJzKHYyW2ldIC0gdjFbaV0pOyAgICAgIAoJICAgICB9CgkgICAgIHJldHVybiB0b3RhbDsKCSAgIH0sCgkgICBtYXg6IGZ1bmN0aW9uKHYxLCB2MikgewoJICAgICB2YXIgbWF4ID0gMDsKCSAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB2MS5sZW5ndGg7IGkrKykgewoJICAgICAgICBtYXggPSBNYXRoLm1heChtYXggLCBNYXRoLmFicyh2MltpXSAtIHYxW2ldKSk7ICAgICAgCgkgICAgIH0KCSAgICAgcmV0dXJuIG1heDsKCSAgIH0KCX07CgoJdmFyIGRpc3RhbmNlcyQxID0gZGlzdGFuY2U7CgoJdmFyIEhpZXJhcmNoaWNhbENsdXN0ZXJpbmcgPSBmdW5jdGlvbihkaXN0YW5jZSwgbGlua2FnZSwgdGhyZXNob2xkKSB7CgkgICB0aGlzLmRpc3RhbmNlID0gZGlzdGFuY2U7CgkgICB0aGlzLmxpbmthZ2UgPSBsaW5rYWdlOwoJICAgdGhpcy50aHJlc2hvbGQgPSB0aHJlc2hvbGQgPT0gdW5kZWZpbmVkID8gSW5maW5pdHkgOiB0aHJlc2hvbGQ7Cgl9OwoKCUhpZXJhcmNoaWNhbENsdXN0ZXJpbmcucHJvdG90eXBlID0gewoJICAgdHJlZTogZnVuY3Rpb24oaXRlbXMsIHNuYXBzaG90UGVyaW9kLCBzbmFwc2hvdENiKSB7CgkgICAgICB0aGlzLnRyZWUgPSBbXTsKCSAgICAgIHRoaXMuZGlzdHMgPSBbXTsgIC8vIGRpc3RhbmNlcyBiZXR3ZWVuIGVhY2ggcGFpciBvZiBjbHVzdGVycwoJICAgICAgdGhpcy5taW5zID0gW107IC8vIGNsb3Nlc3QgY2x1c3RlciBmb3IgZWFjaCBjbHVzdGVyCgkgICAgICB0aGlzLmluZGV4ID0gW107IC8vIGtlZXAgYSBoYXNoIG9mIGFsbCBjbHVzdGVycyBieSBrZXkKCgkgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgaSsrKSB7CgkgICAgICAgICB2YXIgY2x1c3RlciA9IHsKCSAgICAgICAgICAgIHZhbHVlOiBpdGVtc1tpXSwKCSAgICAgICAgICAgIGtleTogaSwKCSAgICAgICAgICAgIGluZGV4OiBpLAoJICAgICAgICAgICAgc2l6ZTogMQoJICAgICAgICAgfTsKCSAgICAgICAgIHRoaXMudHJlZVtpXSA9IGNsdXN0ZXI7CgkgICAgICAgICB0aGlzLmluZGV4W2ldID0gY2x1c3RlcjsKCSAgICAgICAgIHRoaXMuZGlzdHNbaV0gPSBbXTsKCSAgICAgICAgIHRoaXMubWluc1tpXSA9IDA7CgkgICAgICB9CgoJICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnRyZWUubGVuZ3RoOyBpKyspIHsKCSAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDw9IGk7IGorKykgewoJICAgICAgICAgICAgdmFyIGRpc3QgPSAoaSA9PSBqKSA/IEluZmluaXR5IDoKCSAgICAgICAgICAgICAgIHRoaXMuZGlzdGFuY2UodGhpcy50cmVlW2ldLnZhbHVlLCB0aGlzLnRyZWVbal0udmFsdWUpOwoJICAgICAgICAgICAgdGhpcy5kaXN0c1tpXVtqXSA9IGRpc3Q7CgkgICAgICAgICAgICB0aGlzLmRpc3RzW2pdW2ldID0gZGlzdDsKCgkgICAgICAgICAgICBpZiAoZGlzdCA8IHRoaXMuZGlzdHNbaV1bdGhpcy5taW5zW2ldXSkgewoJICAgICAgICAgICAgICAgdGhpcy5taW5zW2ldID0gajsKCSAgICAgICAgICAgIH0KCSAgICAgICAgIH0KCSAgICAgIH0KCgkgICAgICB2YXIgbWVyZ2VkID0gdGhpcy5tZXJnZUNsb3Nlc3QoKTsKCSAgICAgIHZhciBpID0gMDsKCSAgICAgIHdoaWxlIChtZXJnZWQpIHsKCSAgICAgICAgaWYgKHNuYXBzaG90Q2IgJiYgKGkrKyAlIHNuYXBzaG90UGVyaW9kKSA9PSAwKSB7CgkgICAgICAgICAgIHNuYXBzaG90Q2IodGhpcy50cmVlKTsKCSAgICAgICAgfQoJICAgICAgICBtZXJnZWQgPSB0aGlzLm1lcmdlQ2xvc2VzdCgpOwoJICAgICAgfQoKCSAgICAgIHRoaXMudHJlZS5mb3JFYWNoKGZ1bmN0aW9uKGNsdXN0ZXIpIHsKCSAgICAgICAgLy8gY2xlYW4gdXAgbWV0YWRhdGEgdXNlZCBmb3IgY2x1c3RlcmluZwoJICAgICAgICBkZWxldGUgY2x1c3Rlci5rZXk7CgkgICAgICAgIGRlbGV0ZSBjbHVzdGVyLmluZGV4OwoJICAgICAgfSk7CgoJICAgICAgcmV0dXJuIHRoaXMudHJlZTsKCSAgIH0sCgoJICAgbWVyZ2VDbG9zZXN0OiBmdW5jdGlvbigpIHsKCSAgICAgIC8vIGZpbmQgdHdvIGNsb3Nlc3QgY2x1c3RlcnMgZnJvbSBjYWNoZWQgbWlucwoJICAgICAgdmFyIG1pbktleSA9IDAsIG1pbiA9IEluZmluaXR5OwoJICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnRyZWUubGVuZ3RoOyBpKyspIHsKCSAgICAgICAgIHZhciBrZXkgPSB0aGlzLnRyZWVbaV0ua2V5LAoJICAgICAgICAgICAgIGRpc3QgPSB0aGlzLmRpc3RzW2tleV1bdGhpcy5taW5zW2tleV1dOwoJICAgICAgICAgaWYgKGRpc3QgPCBtaW4pIHsKCSAgICAgICAgICAgIG1pbktleSA9IGtleTsKCSAgICAgICAgICAgIG1pbiA9IGRpc3Q7CgkgICAgICAgICB9CgkgICAgICB9CgkgICAgICBpZiAobWluID49IHRoaXMudGhyZXNob2xkKSB7CgkgICAgICAgICByZXR1cm4gZmFsc2U7CgkgICAgICB9CgoJICAgICAgdmFyIGMxID0gdGhpcy5pbmRleFttaW5LZXldLAoJICAgICAgICAgIGMyID0gdGhpcy5pbmRleFt0aGlzLm1pbnNbbWluS2V5XV07CgoJICAgICAgLy8gbWVyZ2UgdHdvIGNsb3Nlc3QgY2x1c3RlcnMKCSAgICAgIHZhciBtZXJnZWQgPSB7CgkgICAgICAgICBkaXN0OiBtaW4sCgkgICAgICAgICBsZWZ0OiBjMSwKCSAgICAgICAgIHJpZ2h0OiBjMiwKCSAgICAgICAgIGtleTogYzEua2V5LAoJICAgICAgICAgc2l6ZTogYzEuc2l6ZSArIGMyLnNpemUKCSAgICAgIH07CgoJICAgICAgdGhpcy50cmVlW2MxLmluZGV4XSA9IG1lcmdlZDsKCSAgICAgIHRoaXMudHJlZS5zcGxpY2UoYzIuaW5kZXgsIDEpOwoJICAgICAgdGhpcy5pbmRleFtjMS5rZXldID0gbWVyZ2VkOwoKCSAgICAgIC8vIHVwZGF0ZSBkaXN0YW5jZXMgd2l0aCBuZXcgbWVyZ2VkIGNsdXN0ZXIKCSAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy50cmVlLmxlbmd0aDsgaSsrKSB7CgkgICAgICAgICB2YXIgY2kgPSB0aGlzLnRyZWVbaV07CgkgICAgICAgICB2YXIgZGlzdDsKCSAgICAgICAgIGlmIChjMS5rZXkgPT0gY2kua2V5KSB7CgkgICAgICAgICAgICBkaXN0ID0gSW5maW5pdHk7CgkgICAgICAgICB9CgkgICAgICAgICBlbHNlIGlmICh0aGlzLmxpbmthZ2UgPT0gInNpbmdsZSIpIHsKCSAgICAgICAgICAgIGRpc3QgPSB0aGlzLmRpc3RzW2MxLmtleV1bY2kua2V5XTsKCSAgICAgICAgICAgIGlmICh0aGlzLmRpc3RzW2MxLmtleV1bY2kua2V5XSA+IHRoaXMuZGlzdHNbYzIua2V5XVtjaS5rZXldKSB7CgkgICAgICAgICAgICAgICBkaXN0ID0gdGhpcy5kaXN0c1tjMi5rZXldW2NpLmtleV07CgkgICAgICAgICAgICB9CgkgICAgICAgICB9CgkgICAgICAgICBlbHNlIGlmICh0aGlzLmxpbmthZ2UgPT0gImNvbXBsZXRlIikgewoJICAgICAgICAgICAgZGlzdCA9IHRoaXMuZGlzdHNbYzEua2V5XVtjaS5rZXldOwoJICAgICAgICAgICAgaWYgKHRoaXMuZGlzdHNbYzEua2V5XVtjaS5rZXldIDwgdGhpcy5kaXN0c1tjMi5rZXldW2NpLmtleV0pIHsKCSAgICAgICAgICAgICAgIGRpc3QgPSB0aGlzLmRpc3RzW2MyLmtleV1bY2kua2V5XTsKCSAgICAgICAgICAgIH0KCSAgICAgICAgIH0KCSAgICAgICAgIGVsc2UgaWYgKHRoaXMubGlua2FnZSA9PSAiYXZlcmFnZSIpIHsKCSAgICAgICAgICAgIGRpc3QgPSAodGhpcy5kaXN0c1tjMS5rZXldW2NpLmtleV0gKiBjMS5zaXplCgkgICAgICAgICAgICAgICAgICAgKyB0aGlzLmRpc3RzW2MyLmtleV1bY2kua2V5XSAqIGMyLnNpemUpIC8gKGMxLnNpemUgKyBjMi5zaXplKTsKCSAgICAgICAgIH0KCSAgICAgICAgIGVsc2UgewoJICAgICAgICAgICAgZGlzdCA9IHRoaXMuZGlzdGFuY2UoY2kudmFsdWUsIGMxLnZhbHVlKTsKCSAgICAgICAgIH0KCgkgICAgICAgICB0aGlzLmRpc3RzW2MxLmtleV1bY2kua2V5XSA9IHRoaXMuZGlzdHNbY2kua2V5XVtjMS5rZXldID0gZGlzdDsKCSAgICAgIH0KCgoJICAgICAgLy8gdXBkYXRlIGNhY2hlZCBtaW5zCgkgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMudHJlZS5sZW5ndGg7IGkrKykgewoJICAgICAgICAgdmFyIGtleTEgPSB0aGlzLnRyZWVbaV0ua2V5OwoJICAgICAgICAgaWYgKHRoaXMubWluc1trZXkxXSA9PSBjMS5rZXkgfHwgdGhpcy5taW5zW2tleTFdID09IGMyLmtleSkgewoJICAgICAgICAgICAgdmFyIG1pbiA9IGtleTE7CgkgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHRoaXMudHJlZS5sZW5ndGg7IGorKykgewoJICAgICAgICAgICAgICAgdmFyIGtleTIgPSB0aGlzLnRyZWVbal0ua2V5OwoJICAgICAgICAgICAgICAgaWYgKHRoaXMuZGlzdHNba2V5MV1ba2V5Ml0gPCB0aGlzLmRpc3RzW2tleTFdW21pbl0pIHsKCSAgICAgICAgICAgICAgICAgIG1pbiA9IGtleTI7CgkgICAgICAgICAgICAgICB9CgkgICAgICAgICAgICB9CgkgICAgICAgICAgICB0aGlzLm1pbnNba2V5MV0gPSBtaW47CgkgICAgICAgICB9CgkgICAgICAgICB0aGlzLnRyZWVbaV0uaW5kZXggPSBpOwoJICAgICAgfQoKCSAgICAgIC8vIGNsZWFuIHVwIG1ldGFkYXRhIHVzZWQgZm9yIGNsdXN0ZXJpbmcKCSAgICAgIGRlbGV0ZSBjMS5rZXk7IGRlbGV0ZSBjMi5rZXk7CgkgICAgICBkZWxldGUgYzEuaW5kZXg7IGRlbGV0ZSBjMi5pbmRleDsKCgkgICAgICByZXR1cm4gdHJ1ZTsKCSAgIH0sCgkgICBjbHVzdGVyczogZnVuY3Rpb24obnVtKXsKCSAgICAgLy8gIFJldHVybiBhbGwgbm9kZXMgaWYgbnVtIGlzIGludmFsaWQKCSAgICAgaWYobnVtID4gdGhpcy50cmVlLnNpemUgfHwgbnVtIDwgMSkgbnVtID0gdGhpcy50cmVlLnNpemU7CgoJICAgICB2YXIgcmVzdWx0ID0gW10sCgkgICAgICAgICBzdWJ0cmVlcyA9IFt0aGlzLnRyZWVdOwoKCSAgICAvLyAgR2V0IGEgbGlzdCBvZiByb290IG5vZGVzIGZvciBudW0gZGlmZmVyZW50IGNsdXN0ZXJzCgkgICAgIHdoaWxlKG51bSA+IDEpewoJICAgICAgIHZhciBmdXJ0aGVzdCA9IF9maW5kTmV4dEZ1cnRoZXN0KHN1YnRyZWVzKTsKCSAgICAgICBzdWJ0cmVlcy5zcGxpY2Uoc3VidHJlZXMuaW5kZXhPZihmdXJ0aGVzdCksIDEpOwoJICAgICAgIHN1YnRyZWVzLnB1c2goZnVydGhlc3QubGVmdCwgZnVydGhlc3QucmlnaHQpOwoJICAgICAgIG51bS0tOwoJICAgICB9CgoJICAgICAvLyAgVHJhbnNmb3JtIHRoZSBzdWJ0cmVlcyBub2RlIGxpc3QgaW50byBhIGxpc3Qgb2YgdGhlIHN1YnRyZWVzIGxlYWYgdmFsdWVzCgkgICAgIHN1YnRyZWVzLmZvckVhY2goZnVuY3Rpb24odHJlZSkgewoJICAgICAgIHJlc3VsdC5wdXNoKF9nZXRWYWx1ZXModHJlZSkpOwoJICAgICB9KTsKCgkgICAgIC8vICBTcGxpdCB0aGUgbmV4dCBmdXJ0aGVzdCBkaXN0YW5jZSByb290IG5vZGUKCSAgICAgZnVuY3Rpb24gX2ZpbmROZXh0RnVydGhlc3Qoc3VidHJlZXMpIHsKCSAgICAgICB2YXIgbWF4ID0gLTEsCgkgICAgICAgICAgIGZ1cnRoZXN0OwoJICAgICAgIHN1YnRyZWVzLmZvckVhY2goZnVuY3Rpb24odHJlZSl7CgkgICAgICAgICBpZih0cmVlLmRpc3QgPiBtYXgpIHsKCSAgICAgICAgICAgbWF4ID0gdHJlZS5kaXN0OwoJICAgICAgICAgICBmdXJ0aGVzdCA9IHRyZWU7CgkgICAgICAgICB9CgkgICAgICAgfSk7CgkgICAgICAgcmV0dXJuIGZ1cnRoZXN0OwoJICAgICB9CgoJICAgICAvLyAgVHJhdmVyc2UgdGhlIHRyZWUgYW5kIHlpZWxkIGEgbGlzdCBvZiB0aGUgbGVhZiBub2RlIHZhbHVlcwoJICAgICBmdW5jdGlvbiBfZ2V0VmFsdWVzKHRyZWUpIHsKCSAgICAgICBpZih0cmVlLnNpemUgPT09IDEpIHJldHVybiBbdHJlZS52YWx1ZV07CgkgICAgICAgcmV0dXJuIF9nZXRWYWx1ZXModHJlZS5sZWZ0KS5jb25jYXQoX2dldFZhbHVlcyh0cmVlLnJpZ2h0KSk7CgkgICAgIH0KCgkgICAgIHJldHVybiByZXN1bHQ7CgkgICB9Cgl9OwoKCXZhciBoY2x1c3RlciA9IGZ1bmN0aW9uKGl0ZW1zLCBkaXN0YW5jZSwgbGlua2FnZSwgdGhyZXNob2xkLCBzbmFwc2hvdCwgc25hcHNob3RDYWxsYmFjaykgewoJICAgZGlzdGFuY2UgPSBkaXN0YW5jZSB8fCAiZXVjbGlkZWFuIjsKCSAgIGxpbmthZ2UgPSBsaW5rYWdlIHx8ICJhdmVyYWdlIjsKCgkgICBpZiAodHlwZW9mIGRpc3RhbmNlID09ICJzdHJpbmciKSB7CgkgICAgIGRpc3RhbmNlID0gZGlzdGFuY2VzJDFbZGlzdGFuY2VdOwoJICAgfQoJICB2YXIgaGMgPSBuZXcgSGllcmFyY2hpY2FsQ2x1c3RlcmluZyhkaXN0YW5jZSwgbGlua2FnZSwgdGhyZXNob2xkKSwKCSAgICAgIHRyZWUgPSBoYy50cmVlKGl0ZW1zLCBzbmFwc2hvdCwgc25hcHNob3RDYWxsYmFjayk7CgoJICAgcmV0dXJuIHsKCSAgICAgdHJlZTogKHRocmVzaG9sZCA9PT0gdW5kZWZpbmVkID8gdHJlZVswXSA6IHRyZWUpLAoJICAgICBjbHVzdGVyczogaGMuY2x1c3RlcnMKCSAgIH07Cgl9OwoKCXZhciBoY2x1c3Rlcl8xID0gaGNsdXN0ZXI7CgoJdmFyIGttZWFucyA9IHtleHBvcnRzOiB7fX07CgoJdmFyIGRpc3RhbmNlcyA9IGRpc3RhbmNlOwoKCWZ1bmN0aW9uIEtNZWFucyhjZW50cm9pZHMpIHsKCSAgIHRoaXMuY2VudHJvaWRzID0gY2VudHJvaWRzIHx8IFtdOwoJfQoKCUtNZWFucy5wcm90b3R5cGUucmFuZG9tQ2VudHJvaWRzID0gZnVuY3Rpb24ocG9pbnRzLCBrKSB7CgkgICB2YXIgY2VudHJvaWRzID0gcG9pbnRzLnNsaWNlKDApOyAvLyBjb3B5CgkgICBjZW50cm9pZHMuc29ydChmdW5jdGlvbigpIHsKCSAgICAgIHJldHVybiAoTWF0aC5yb3VuZChNYXRoLnJhbmRvbSgpKSAtIDAuNSk7CgkgICB9KTsKCSAgIHJldHVybiBjZW50cm9pZHMuc2xpY2UoMCwgayk7Cgl9OwoKCUtNZWFucy5wcm90b3R5cGUuY2xhc3NpZnkgPSBmdW5jdGlvbihwb2ludCwgZGlzdGFuY2UpIHsKCSAgIHZhciBtaW4gPSBJbmZpbml0eSwKCSAgICAgICBpbmRleCA9IDA7CgoJICAgZGlzdGFuY2UgPSBkaXN0YW5jZSB8fCAiZXVjbGlkZWFuIjsKCSAgIGlmICh0eXBlb2YgZGlzdGFuY2UgPT0gInN0cmluZyIpIHsKCSAgICAgIGRpc3RhbmNlID0gZGlzdGFuY2VzW2Rpc3RhbmNlXTsKCSAgIH0KCgkgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY2VudHJvaWRzLmxlbmd0aDsgaSsrKSB7CgkgICAgICB2YXIgZGlzdCA9IGRpc3RhbmNlKHBvaW50LCB0aGlzLmNlbnRyb2lkc1tpXSk7CgkgICAgICBpZiAoZGlzdCA8IG1pbikgewoJICAgICAgICAgbWluID0gZGlzdDsKCSAgICAgICAgIGluZGV4ID0gaTsKCSAgICAgIH0KCSAgIH0KCgkgICByZXR1cm4gaW5kZXg7Cgl9OwoKCUtNZWFucy5wcm90b3R5cGUuY2x1c3RlciA9IGZ1bmN0aW9uKHBvaW50cywgaywgZGlzdGFuY2UsIHNuYXBzaG90UGVyaW9kLCBzbmFwc2hvdENiKSB7CgkgICBrID0gayB8fCBNYXRoLm1heCgyLCBNYXRoLmNlaWwoTWF0aC5zcXJ0KHBvaW50cy5sZW5ndGggLyAyKSkpOwoKCSAgIGRpc3RhbmNlID0gZGlzdGFuY2UgfHwgImV1Y2xpZGVhbiI7CgkgICBpZiAodHlwZW9mIGRpc3RhbmNlID09ICJzdHJpbmciKSB7CgkgICAgICBkaXN0YW5jZSA9IGRpc3RhbmNlc1tkaXN0YW5jZV07CgkgICB9CgoJICAgdGhpcy5jZW50cm9pZHMgPSB0aGlzLnJhbmRvbUNlbnRyb2lkcyhwb2ludHMsIGspOwoKCSAgIHZhciBhc3NpZ25tZW50ID0gbmV3IEFycmF5KHBvaW50cy5sZW5ndGgpOwoJICAgdmFyIGNsdXN0ZXJzID0gbmV3IEFycmF5KGspOwoKCSAgIHZhciBpdGVyYXRpb25zID0gMDsKCSAgIHZhciBtb3ZlbWVudCA9IHRydWU7CgkgICB3aGlsZSAobW92ZW1lbnQpIHsKCSAgICAgIC8vIHVwZGF0ZSBwb2ludC10by1jZW50cm9pZCBhc3NpZ25tZW50cwoJICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHsKCSAgICAgICAgIGFzc2lnbm1lbnRbaV0gPSB0aGlzLmNsYXNzaWZ5KHBvaW50c1tpXSwgZGlzdGFuY2UpOwoJICAgICAgfQoKCSAgICAgIC8vIHVwZGF0ZSBsb2NhdGlvbiBvZiBlYWNoIGNlbnRyb2lkCgkgICAgICBtb3ZlbWVudCA9IGZhbHNlOwoJICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBrOyBqKyspIHsKCSAgICAgICAgIHZhciBhc3NpZ25lZCA9IFtdOwoJICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhc3NpZ25tZW50Lmxlbmd0aDsgaSsrKSB7CgkgICAgICAgICAgICBpZiAoYXNzaWdubWVudFtpXSA9PSBqKSB7CgkgICAgICAgICAgICAgICBhc3NpZ25lZC5wdXNoKHBvaW50c1tpXSk7CgkgICAgICAgICAgICB9CgkgICAgICAgICB9CgoJICAgICAgICAgaWYgKCFhc3NpZ25lZC5sZW5ndGgpIHsKCSAgICAgICAgICAgIGNvbnRpbnVlOwoJICAgICAgICAgfQoKCSAgICAgICAgIHZhciBjZW50cm9pZCA9IHRoaXMuY2VudHJvaWRzW2pdOwoJICAgICAgICAgdmFyIG5ld0NlbnRyb2lkID0gbmV3IEFycmF5KGNlbnRyb2lkLmxlbmd0aCk7CgoJICAgICAgICAgZm9yICh2YXIgZyA9IDA7IGcgPCBjZW50cm9pZC5sZW5ndGg7IGcrKykgewoJICAgICAgICAgICAgdmFyIHN1bSA9IDA7CgkgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFzc2lnbmVkLmxlbmd0aDsgaSsrKSB7CgkgICAgICAgICAgICAgICBzdW0gKz0gYXNzaWduZWRbaV1bZ107CgkgICAgICAgICAgICB9CgkgICAgICAgICAgICBuZXdDZW50cm9pZFtnXSA9IHN1bSAvIGFzc2lnbmVkLmxlbmd0aDsKCgkgICAgICAgICAgICBpZiAobmV3Q2VudHJvaWRbZ10gIT0gY2VudHJvaWRbZ10pIHsKCSAgICAgICAgICAgICAgIG1vdmVtZW50ID0gdHJ1ZTsKCSAgICAgICAgICAgIH0KCSAgICAgICAgIH0KCgkgICAgICAgICB0aGlzLmNlbnRyb2lkc1tqXSA9IG5ld0NlbnRyb2lkOwoJICAgICAgICAgY2x1c3RlcnNbal0gPSBhc3NpZ25lZDsKCSAgICAgIH0KCgkgICAgICBpZiAoc25hcHNob3RDYiAmJiAoaXRlcmF0aW9ucysrICUgc25hcHNob3RQZXJpb2QgPT0gMCkpIHsKCSAgICAgICAgIHNuYXBzaG90Q2IoY2x1c3RlcnMpOwoJICAgICAgfQoJICAgfQoKCSAgIHJldHVybiBjbHVzdGVyczsKCX07CgoJS01lYW5zLnByb3RvdHlwZS50b0pTT04gPSBmdW5jdGlvbigpIHsKCSAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh0aGlzLmNlbnRyb2lkcyk7Cgl9OwoKCUtNZWFucy5wcm90b3R5cGUuZnJvbUpTT04gPSBmdW5jdGlvbihqc29uKSB7CgkgICB0aGlzLmNlbnRyb2lkcyA9IEpTT04ucGFyc2UoanNvbik7CgkgICByZXR1cm4gdGhpczsKCX07CgoJa21lYW5zLmV4cG9ydHMgPSBLTWVhbnM7CgoJa21lYW5zLmV4cG9ydHMua21lYW5zID0gZnVuY3Rpb24odmVjdG9ycywgaykgewoJICAgcmV0dXJuIChuZXcgS01lYW5zKCkpLmNsdXN0ZXIodmVjdG9ycywgayk7Cgl9OwoKCXZhciBjbHVzdGVyZmNrID0gewoJICAgaGNsdXN0ZXI6IGhjbHVzdGVyXzEsCgkgICBLbWVhbnM6IGttZWFucy5leHBvcnRzLAoJICAga21lYW5zOiBrbWVhbnMuZXhwb3J0cy5rbWVhbnMKCX07CgoJdmFyIGpzdGF0ID0ge2V4cG9ydHM6IHt9fTsKCgkoZnVuY3Rpb24gKG1vZHVsZSwgZXhwb3J0cykgewoJCShmdW5jdGlvbiAod2luZG93LCBmYWN0b3J5KSB7CgkJICAgIHsKCQkgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpOwoJCSAgICB9CgkJfSkoY29tbW9uanNHbG9iYWwsIGZ1bmN0aW9uICgpIHsKCQl2YXIgalN0YXQgPSAoZnVuY3Rpb24oTWF0aCwgdW5kZWZpbmVkJDEpIHsKCgkJLy8gRm9yIHF1aWNrIHJlZmVyZW5jZS4KCQl2YXIgY29uY2F0ID0gQXJyYXkucHJvdG90eXBlLmNvbmNhdDsKCQl2YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7CgkJdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZzsKCgkJLy8gQ2FsY3VsYXRlIGNvcnJlY3Rpb24gZm9yIElFRUUgZXJyb3IKCQkvLyBUT0RPOiBUaGlzIGNhbGN1bGF0aW9uIGNhbiBiZSBpbXByb3ZlZC4KCQlmdW5jdGlvbiBjYWxjUmR4KG4sIG0pIHsKCQkgIHZhciB2YWwgPSBuID4gbSA/IG4gOiBtOwoJCSAgcmV0dXJuIE1hdGgucG93KDEwLAoJCSAgICAgICAgICAgICAgICAgIDE3IC0gfn4oTWF0aC5sb2coKCh2YWwgPiAwKSA/IHZhbCA6IC12YWwpKSAqIE1hdGguTE9HMTBFKSk7CgkJfQoKCgkJdmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uIGlzQXJyYXkoYXJnKSB7CgkJICByZXR1cm4gdG9TdHJpbmcuY2FsbChhcmcpID09PSAnW29iamVjdCBBcnJheV0nOwoJCX07CgoKCQlmdW5jdGlvbiBpc0Z1bmN0aW9uKGFyZykgewoJCSAgcmV0dXJuIHRvU3RyaW5nLmNhbGwoYXJnKSA9PT0gJ1tvYmplY3QgRnVuY3Rpb25dJzsKCQl9CgoKCQlmdW5jdGlvbiBpc051bWJlcihhcmcpIHsKCQkgIHJldHVybiB0eXBlb2YgYXJnID09PSAnbnVtYmVyJyAmJiBhcmcgPT09IGFyZzsKCQl9CgoKCQkvLyBDb252ZXJ0cyB0aGUgalN0YXQgbWF0cml4IHRvIHZlY3Rvci4KCQlmdW5jdGlvbiB0b1ZlY3RvcihhcnIpIHsKCQkgIHJldHVybiBjb25jYXQuYXBwbHkoW10sIGFycik7CgkJfQoKCgkJLy8gVGhlIG9uZSBhbmQgb25seSBqU3RhdCBjb25zdHJ1Y3Rvci4KCQlmdW5jdGlvbiBqU3RhdCgpIHsKCQkgIHJldHVybiBuZXcgalN0YXQuX2luaXQoYXJndW1lbnRzKTsKCQl9CgoKCQkvLyBUT0RPOiBSZW1vdmUgYWZ0ZXIgYWxsIHJlZmVyZW5jZXMgaW4gc3JjIGZpbGVzIGhhdmUgYmVlbiByZW1vdmVkLgoJCWpTdGF0LmZuID0galN0YXQucHJvdG90eXBlOwoKCgkJLy8gQnkgc2VwYXJhdGluZyB0aGUgaW5pdGlhbGl6ZXIgZnJvbSB0aGUgY29uc3RydWN0b3IgaXQncyBlYXNpZXIgdG8gaGFuZGxlCgkJLy8gYWx3YXlzIHJldHVybmluZyBhIG5ldyBpbnN0YW5jZSB3aGV0aGVyICJuZXciIHdhcyB1c2VkIG9yIG5vdC4KCQlqU3RhdC5faW5pdCA9IGZ1bmN0aW9uIF9pbml0KGFyZ3MpIHsKCQkgIHZhciBpOwoKCQkgIC8vIElmIGZpcnN0IGFyZ3VtZW50IGlzIGFuIGFycmF5LCBtdXN0IGJlIHZlY3RvciBvciBtYXRyaXguCgkJICBpZiAoaXNBcnJheShhcmdzWzBdKSkgewoJCSAgICAvLyBDaGVjayBpZiBtYXRyaXguCgkJICAgIGlmIChpc0FycmF5KGFyZ3NbMF1bMF0pKSB7CgkJICAgICAgLy8gU2VlIGlmIGEgbWFwcGluZyBmdW5jdGlvbiB3YXMgYWxzbyBwYXNzZWQuCgkJICAgICAgaWYgKGlzRnVuY3Rpb24oYXJnc1sxXSkpCgkJICAgICAgICBhcmdzWzBdID0galN0YXQubWFwKGFyZ3NbMF0sIGFyZ3NbMV0pOwoJCSAgICAgIC8vIEl0ZXJhdGUgb3ZlciBlYWNoIGlzIGZhc3RlciB0aGFuIHRoaXMucHVzaC5hcHBseSh0aGlzLCBhcmdzWzBdLgoJCSAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJnc1swXS5sZW5ndGg7IGkrKykKCQkgICAgICAgIHRoaXNbaV0gPSBhcmdzWzBdW2ldOwoJCSAgICAgIHRoaXMubGVuZ3RoID0gYXJnc1swXS5sZW5ndGg7CgoJCSAgICAvLyBPdGhlcndpc2UgbXVzdCBiZSBhIHZlY3Rvci4KCQkgICAgfSBlbHNlIHsKCQkgICAgICB0aGlzWzBdID0gaXNGdW5jdGlvbihhcmdzWzFdKSA/IGpTdGF0Lm1hcChhcmdzWzBdLCBhcmdzWzFdKSA6IGFyZ3NbMF07CgkJICAgICAgdGhpcy5sZW5ndGggPSAxOwoJCSAgICB9CgoJCSAgLy8gSWYgZmlyc3QgYXJndW1lbnQgaXMgbnVtYmVyLCBhc3N1bWUgY3JlYXRpb24gb2Ygc2VxdWVuY2UuCgkJICB9IGVsc2UgaWYgKGlzTnVtYmVyKGFyZ3NbMF0pKSB7CgkJICAgIHRoaXNbMF0gPSBqU3RhdC5zZXEuYXBwbHkobnVsbCwgYXJncyk7CgkJICAgIHRoaXMubGVuZ3RoID0gMTsKCgkJICAvLyBIYW5kbGUgY2FzZSB3aGVuIGpTdGF0IG9iamVjdCBpcyBwYXNzZWQgdG8galN0YXQuCgkJICB9IGVsc2UgaWYgKGFyZ3NbMF0gaW5zdGFuY2VvZiBqU3RhdCkgewoJCSAgICAvLyBEdXBsaWNhdGUgdGhlIG9iamVjdCBhbmQgcGFzcyBpdCBiYWNrLgoJCSAgICByZXR1cm4galN0YXQoYXJnc1swXS50b0FycmF5KCkpOwoKCQkgIC8vIFVuZXhwZWN0ZWQgYXJndW1lbnQgdmFsdWUsIHJldHVybiBlbXB0eSBqU3RhdCBvYmplY3QuCgkJICAvLyBUT0RPOiBUaGlzIGlzIHN0cmFuZ2UgYmVoYXZpb3IuIFNob3VsZG4ndCB0aGlzIHRocm93IG9yIHNvbWUgc3VjaCB0byBsZXQKCQkgIC8vIHRoZSB1c2VyIGtub3cgdGhleSBoYWQgYmFkIGFyZ3VtZW50cz8KCQkgIH0gZWxzZSB7CgkJICAgIHRoaXNbMF0gPSBbXTsKCQkgICAgdGhpcy5sZW5ndGggPSAxOwoJCSAgfQoKCQkgIHJldHVybiB0aGlzOwoJCX07CgkJalN0YXQuX2luaXQucHJvdG90eXBlID0galN0YXQucHJvdG90eXBlOwoJCWpTdGF0Ll9pbml0LmNvbnN0cnVjdG9yID0galN0YXQ7CgoKCQkvLyBVdGlsaXR5IGZ1bmN0aW9ucy4KCQkvLyBUT0RPOiBmb3IgaW50ZXJuYWwgdXNlIG9ubHk/CgkJalN0YXQudXRpbHMgPSB7CgkJICBjYWxjUmR4OiBjYWxjUmR4LAoJCSAgaXNBcnJheTogaXNBcnJheSwKCQkgIGlzRnVuY3Rpb246IGlzRnVuY3Rpb24sCgkJICBpc051bWJlcjogaXNOdW1iZXIsCgkJICB0b1ZlY3RvcjogdG9WZWN0b3IKCQl9OwoKCgkJLy8gRWFzaWx5IGV4dGVuZCB0aGUgalN0YXQgb2JqZWN0LgoJCS8vIFRPRE86IGlzIHRoaXMgc2VyaW91c2x5IG5lY2Vzc2FyeT8KCQlqU3RhdC5leHRlbmQgPSBmdW5jdGlvbiBleHRlbmQob2JqKSB7CgkJICB2YXIgaSwgajsKCgkJICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkgewoJCSAgICBmb3IgKGogaW4gb2JqKQoJCSAgICAgIGpTdGF0W2pdID0gb2JqW2pdOwoJCSAgICByZXR1cm4gdGhpczsKCQkgIH0KCgkJICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykgewoJCSAgICBmb3IgKGogaW4gYXJndW1lbnRzW2ldKQoJCSAgICAgIG9ialtqXSA9IGFyZ3VtZW50c1tpXVtqXTsKCQkgIH0KCgkJICByZXR1cm4gb2JqOwoJCX07CgoKCQkvLyBSZXR1cm5zIHRoZSBudW1iZXIgb2Ygcm93cyBpbiB0aGUgbWF0cml4LgoJCWpTdGF0LnJvd3MgPSBmdW5jdGlvbiByb3dzKGFycikgewoJCSAgcmV0dXJuIGFyci5sZW5ndGggfHwgMTsKCQl9OwoKCgkJLy8gUmV0dXJucyB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIG1hdHJpeC4KCQlqU3RhdC5jb2xzID0gZnVuY3Rpb24gY29scyhhcnIpIHsKCQkgIHJldHVybiBhcnJbMF0ubGVuZ3RoIHx8IDE7CgkJfTsKCgoJCS8vIFJldHVybnMgdGhlIGRpbWVuc2lvbnMgb2YgdGhlIG9iamVjdCB7IHJvd3M6IGksIGNvbHM6IGogfQoJCWpTdGF0LmRpbWVuc2lvbnMgPSBmdW5jdGlvbiBkaW1lbnNpb25zKGFycikgewoJCSAgcmV0dXJuIHsKCQkgICAgcm93czogalN0YXQucm93cyhhcnIpLAoJCSAgICBjb2xzOiBqU3RhdC5jb2xzKGFycikKCQkgIH07CgkJfTsKCgoJCS8vIFJldHVybnMgYSBzcGVjaWZpZWQgcm93IGFzIGEgdmVjdG9yIG9yIHJldHVybiBhIHN1YiBtYXRyaXggYnkgcGljayBzb21lIHJvd3MKCQlqU3RhdC5yb3cgPSBmdW5jdGlvbiByb3coYXJyLCBpbmRleCkgewoJCSAgaWYgKGlzQXJyYXkoaW5kZXgpKSB7CgkJICAgIHJldHVybiBpbmRleC5tYXAoZnVuY3Rpb24oaSkgewoJCSAgICAgIHJldHVybiBqU3RhdC5yb3coYXJyLCBpKTsKCQkgICAgfSkKCQkgIH0KCQkgIHJldHVybiBhcnJbaW5kZXhdOwoJCX07CgoKCQkvLyByZXR1cm4gcm93IGFzIGFycmF5CgkJLy8gcm93YShbWzEsMl0sWzMsNF1dLDApIC0+IFsxLDJdCgkJalN0YXQucm93YSA9IGZ1bmN0aW9uIHJvd2EoYXJyLCBpKSB7CgkJICByZXR1cm4galN0YXQucm93KGFyciwgaSk7CgkJfTsKCgoJCS8vIFJldHVybnMgdGhlIHNwZWNpZmllZCBjb2x1bW4gYXMgYSB2ZWN0b3Igb3IgcmV0dXJuIGEgc3ViIG1hdHJpeCBieSBwaWNrIHNvbWUKCQkvLyBjb2x1bW5zCgkJalN0YXQuY29sID0gZnVuY3Rpb24gY29sKGFyciwgaW5kZXgpIHsKCQkgIGlmIChpc0FycmF5KGluZGV4KSkgewoJCSAgICB2YXIgc3VibWF0ID0galN0YXQuYXJhbmdlKGFyci5sZW5ndGgpLm1hcChmdW5jdGlvbihpKSB7CgkJICAgICAgcmV0dXJuIG5ldyBBcnJheShpbmRleC5sZW5ndGgpOwoJCSAgICB9KTsKCQkgICAgaW5kZXguZm9yRWFjaChmdW5jdGlvbihpbmQsIGkpewoJCSAgICAgIGpTdGF0LmFyYW5nZShhcnIubGVuZ3RoKS5mb3JFYWNoKGZ1bmN0aW9uKGopIHsKCQkgICAgICAgIHN1Ym1hdFtqXVtpXSA9IGFycltqXVtpbmRdOwoJCSAgICAgIH0pOwoJCSAgICB9KTsKCQkgICAgcmV0dXJuIHN1Ym1hdDsKCQkgIH0KCQkgIHZhciBjb2x1bW4gPSBuZXcgQXJyYXkoYXJyLmxlbmd0aCk7CgkJICBmb3IgKHZhciBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykKCQkgICAgY29sdW1uW2ldID0gW2FycltpXVtpbmRleF1dOwoJCSAgcmV0dXJuIGNvbHVtbjsKCQl9OwoKCgkJLy8gcmV0dXJuIGNvbHVtbiBhcyBhcnJheQoJCS8vIGNvbGEoW1sxLDJdLFszLDRdXSwwKSAtPiBbMSwzXQoJCWpTdGF0LmNvbGEgPSBmdW5jdGlvbiBjb2xhKGFyciwgaSkgewoJCSAgcmV0dXJuIGpTdGF0LmNvbChhcnIsIGkpLm1hcChmdW5jdGlvbihhKXsgcmV0dXJuIGFbMF0gfSk7CgkJfTsKCgoJCS8vIFJldHVybnMgdGhlIGRpYWdvbmFsIG9mIHRoZSBtYXRyaXgKCQlqU3RhdC5kaWFnID0gZnVuY3Rpb24gZGlhZyhhcnIpIHsKCQkgIHZhciBucm93ID0galN0YXQucm93cyhhcnIpOwoJCSAgdmFyIHJlcyA9IG5ldyBBcnJheShucm93KTsKCQkgIGZvciAodmFyIHJvdyA9IDA7IHJvdyA8IG5yb3c7IHJvdysrKQoJCSAgICByZXNbcm93XSA9IFthcnJbcm93XVtyb3ddXTsKCQkgIHJldHVybiByZXM7CgkJfTsKCgoJCS8vIFJldHVybnMgdGhlIGFudGktZGlhZ29uYWwgb2YgdGhlIG1hdHJpeAoJCWpTdGF0LmFudGlkaWFnID0gZnVuY3Rpb24gYW50aWRpYWcoYXJyKSB7CgkJICB2YXIgbnJvdyA9IGpTdGF0LnJvd3MoYXJyKSAtIDE7CgkJICB2YXIgcmVzID0gbmV3IEFycmF5KG5yb3cpOwoJCSAgZm9yICh2YXIgaSA9IDA7IG5yb3cgPj0gMDsgbnJvdy0tLCBpKyspCgkJICAgIHJlc1tpXSA9IFthcnJbaV1bbnJvd11dOwoJCSAgcmV0dXJuIHJlczsKCQl9OwoKCQkvLyBUcmFuc3Bvc2UgYSBtYXRyaXggb3IgYXJyYXkuCgkJalN0YXQudHJhbnNwb3NlID0gZnVuY3Rpb24gdHJhbnNwb3NlKGFycikgewoJCSAgdmFyIG9iaiA9IFtdOwoJCSAgdmFyIG9iakFyciwgcm93cywgY29scywgaiwgaTsKCgkJICAvLyBNYWtlIHN1cmUgYXJyIGlzIGluIG1hdHJpeCBmb3JtYXQuCgkJICBpZiAoIWlzQXJyYXkoYXJyWzBdKSkKCQkgICAgYXJyID0gW2Fycl07CgoJCSAgcm93cyA9IGFyci5sZW5ndGg7CgkJICBjb2xzID0gYXJyWzBdLmxlbmd0aDsKCgkJICBmb3IgKHZhciBpID0gMDsgaSA8IGNvbHM7IGkrKykgewoJCSAgICBvYmpBcnIgPSBuZXcgQXJyYXkocm93cyk7CgkJICAgIGZvciAoaiA9IDA7IGogPCByb3dzOyBqKyspCgkJICAgICAgb2JqQXJyW2pdID0gYXJyW2pdW2ldOwoJCSAgICBvYmoucHVzaChvYmpBcnIpOwoJCSAgfQoKCQkgIC8vIElmIG9iaiBpcyB2ZWN0b3IsIHJldHVybiBvbmx5IHNpbmdsZSBhcnJheS4KCQkgIHJldHVybiBvYmoubGVuZ3RoID09PSAxID8gb2JqWzBdIDogb2JqOwoJCX07CgoKCQkvLyBNYXAgYSBmdW5jdGlvbiB0byBhbiBhcnJheSBvciBhcnJheSBvZiBhcnJheXMuCgkJLy8gInRvQWx0ZXIiIGlzIGFuIGludGVybmFsIHZhcmlhYmxlLgoJCWpTdGF0Lm1hcCA9IGZ1bmN0aW9uIG1hcChhcnIsIGZ1bmMsIHRvQWx0ZXIpIHsKCQkgIHZhciByb3csIG5yb3csIG5jb2wsIHJlcywgY29sOwoKCQkgIGlmICghaXNBcnJheShhcnJbMF0pKQoJCSAgICBhcnIgPSBbYXJyXTsKCgkJICBucm93ID0gYXJyLmxlbmd0aDsKCQkgIG5jb2wgPSBhcnJbMF0ubGVuZ3RoOwoJCSAgcmVzID0gdG9BbHRlciA/IGFyciA6IG5ldyBBcnJheShucm93KTsKCgkJICBmb3IgKHJvdyA9IDA7IHJvdyA8IG5yb3c7IHJvdysrKSB7CgkJICAgIC8vIGlmIHRoZSByb3cgZG9lc24ndCBleGlzdCwgY3JlYXRlIGl0CgkJICAgIGlmICghcmVzW3Jvd10pCgkJICAgICAgcmVzW3Jvd10gPSBuZXcgQXJyYXkobmNvbCk7CgkJICAgIGZvciAoY29sID0gMDsgY29sIDwgbmNvbDsgY29sKyspCgkJICAgICAgcmVzW3Jvd11bY29sXSA9IGZ1bmMoYXJyW3Jvd11bY29sXSwgcm93LCBjb2wpOwoJCSAgfQoKCQkgIHJldHVybiByZXMubGVuZ3RoID09PSAxID8gcmVzWzBdIDogcmVzOwoJCX07CgoKCQkvLyBDdW11bGF0aXZlbHkgY29tYmluZSB0aGUgZWxlbWVudHMgb2YgYW4gYXJyYXkgb3IgYXJyYXkgb2YgYXJyYXlzIHVzaW5nIGEgZnVuY3Rpb24uCgkJalN0YXQuY3VtcmVkdWNlID0gZnVuY3Rpb24gY3VtcmVkdWNlKGFyciwgZnVuYywgdG9BbHRlcikgewoJCSAgdmFyIHJvdywgbnJvdywgbmNvbCwgcmVzLCBjb2w7CgoJCSAgaWYgKCFpc0FycmF5KGFyclswXSkpCgkJICAgIGFyciA9IFthcnJdOwoKCQkgIG5yb3cgPSBhcnIubGVuZ3RoOwoJCSAgbmNvbCA9IGFyclswXS5sZW5ndGg7CgkJICByZXMgPSB0b0FsdGVyID8gYXJyIDogbmV3IEFycmF5KG5yb3cpOwoKCQkgIGZvciAocm93ID0gMDsgcm93IDwgbnJvdzsgcm93KyspIHsKCQkgICAgLy8gaWYgdGhlIHJvdyBkb2Vzbid0IGV4aXN0LCBjcmVhdGUgaXQKCQkgICAgaWYgKCFyZXNbcm93XSkKCQkgICAgICByZXNbcm93XSA9IG5ldyBBcnJheShuY29sKTsKCQkgICAgaWYgKG5jb2wgPiAwKQoJCSAgICAgIHJlc1tyb3ddWzBdID0gYXJyW3Jvd11bMF07CgkJICAgIGZvciAoY29sID0gMTsgY29sIDwgbmNvbDsgY29sKyspCgkJICAgICAgcmVzW3Jvd11bY29sXSA9IGZ1bmMocmVzW3Jvd11bY29sLTFdLCBhcnJbcm93XVtjb2xdKTsKCQkgIH0KCQkgIHJldHVybiByZXMubGVuZ3RoID09PSAxID8gcmVzWzBdIDogcmVzOwoJCX07CgoKCQkvLyBEZXN0cnVjdGl2ZWx5IGFsdGVyIGFuIGFycmF5LgoJCWpTdGF0LmFsdGVyID0gZnVuY3Rpb24gYWx0ZXIoYXJyLCBmdW5jKSB7CgkJICByZXR1cm4galN0YXQubWFwKGFyciwgZnVuYywgdHJ1ZSk7CgkJfTsKCgoJCS8vIEdlbmVyYXRlIGEgcm93cyB4IGNvbHMgbWF0cml4IGFjY29yZGluZyB0byB0aGUgc3VwcGxpZWQgZnVuY3Rpb24uCgkJalN0YXQuY3JlYXRlID0gZnVuY3Rpb24gIGNyZWF0ZShyb3dzLCBjb2xzLCBmdW5jKSB7CgkJICB2YXIgcmVzID0gbmV3IEFycmF5KHJvd3MpOwoJCSAgdmFyIGksIGo7CgoJCSAgaWYgKGlzRnVuY3Rpb24oY29scykpIHsKCQkgICAgZnVuYyA9IGNvbHM7CgkJICAgIGNvbHMgPSByb3dzOwoJCSAgfQoKCQkgIGZvciAodmFyIGkgPSAwOyBpIDwgcm93czsgaSsrKSB7CgkJICAgIHJlc1tpXSA9IG5ldyBBcnJheShjb2xzKTsKCQkgICAgZm9yIChqID0gMDsgaiA8IGNvbHM7IGorKykKCQkgICAgICByZXNbaV1bal0gPSBmdW5jKGksIGopOwoJCSAgfQoKCQkgIHJldHVybiByZXM7CgkJfTsKCgoJCWZ1bmN0aW9uIHJldFplcm8oKSB7IHJldHVybiAwOyB9CgoKCQkvLyBHZW5lcmF0ZSBhIHJvd3MgeCBjb2xzIG1hdHJpeCBvZiB6ZXJvcy4KCQlqU3RhdC56ZXJvcyA9IGZ1bmN0aW9uIHplcm9zKHJvd3MsIGNvbHMpIHsKCQkgIGlmICghaXNOdW1iZXIoY29scykpCgkJICAgIGNvbHMgPSByb3dzOwoJCSAgcmV0dXJuIGpTdGF0LmNyZWF0ZShyb3dzLCBjb2xzLCByZXRaZXJvKTsKCQl9OwoKCgkJZnVuY3Rpb24gcmV0T25lKCkgeyByZXR1cm4gMTsgfQoKCgkJLy8gR2VuZXJhdGUgYSByb3dzIHggY29scyBtYXRyaXggb2Ygb25lcy4KCQlqU3RhdC5vbmVzID0gZnVuY3Rpb24gb25lcyhyb3dzLCBjb2xzKSB7CgkJICBpZiAoIWlzTnVtYmVyKGNvbHMpKQoJCSAgICBjb2xzID0gcm93czsKCQkgIHJldHVybiBqU3RhdC5jcmVhdGUocm93cywgY29scywgcmV0T25lKTsKCQl9OwoKCgkJLy8gR2VuZXJhdGUgYSByb3dzIHggY29scyBtYXRyaXggb2YgdW5pZm9ybWx5IHJhbmRvbSBudW1iZXJzLgoJCWpTdGF0LnJhbmQgPSBmdW5jdGlvbiByYW5kKHJvd3MsIGNvbHMpIHsKCQkgIGlmICghaXNOdW1iZXIoY29scykpCgkJICAgIGNvbHMgPSByb3dzOwoJCSAgcmV0dXJuIGpTdGF0LmNyZWF0ZShyb3dzLCBjb2xzLCBNYXRoLnJhbmRvbSk7CgkJfTsKCgoJCWZ1bmN0aW9uIHJldElkZW50KGksIGopIHsgcmV0dXJuIGkgPT09IGogPyAxIDogMDsgfQoKCgkJLy8gR2VuZXJhdGUgYW4gaWRlbnRpdHkgbWF0cml4IG9mIHNpemUgcm93IHggY29scy4KCQlqU3RhdC5pZGVudGl0eSA9IGZ1bmN0aW9uIGlkZW50aXR5KHJvd3MsIGNvbHMpIHsKCQkgIGlmICghaXNOdW1iZXIoY29scykpCgkJICAgIGNvbHMgPSByb3dzOwoJCSAgcmV0dXJuIGpTdGF0LmNyZWF0ZShyb3dzLCBjb2xzLCByZXRJZGVudCk7CgkJfTsKCgoJCS8vIFRlc3RzIHdoZXRoZXIgYSBtYXRyaXggaXMgc3ltbWV0cmljCgkJalN0YXQuc3ltbWV0cmljID0gZnVuY3Rpb24gc3ltbWV0cmljKGFycikgewoJCSAgdmFyIHNpemUgPSBhcnIubGVuZ3RoOwoJCSAgdmFyIHJvdywgY29sOwoKCQkgIGlmIChhcnIubGVuZ3RoICE9PSBhcnJbMF0ubGVuZ3RoKQoJCSAgICByZXR1cm4gZmFsc2U7CgoJCSAgZm9yIChyb3cgPSAwOyByb3cgPCBzaXplOyByb3crKykgewoJCSAgICBmb3IgKGNvbCA9IDA7IGNvbCA8IHNpemU7IGNvbCsrKQoJCSAgICAgIGlmIChhcnJbY29sXVtyb3ddICE9PSBhcnJbcm93XVtjb2xdKQoJCSAgICAgICAgcmV0dXJuIGZhbHNlOwoJCSAgfQoKCQkgIHJldHVybiB0cnVlOwoJCX07CgoKCQkvLyBTZXQgYWxsIHZhbHVlcyB0byB6ZXJvLgoJCWpTdGF0LmNsZWFyID0gZnVuY3Rpb24gY2xlYXIoYXJyKSB7CgkJICByZXR1cm4galN0YXQuYWx0ZXIoYXJyLCByZXRaZXJvKTsKCQl9OwoKCgkJLy8gR2VuZXJhdGUgc2VxdWVuY2UuCgkJalN0YXQuc2VxID0gZnVuY3Rpb24gc2VxKG1pbiwgbWF4LCBsZW5ndGgsIGZ1bmMpIHsKCQkgIGlmICghaXNGdW5jdGlvbihmdW5jKSkKCQkgICAgZnVuYyA9IGZhbHNlOwoKCQkgIHZhciBhcnIgPSBbXTsKCQkgIHZhciBoaXZhbCA9IGNhbGNSZHgobWluLCBtYXgpOwoJCSAgdmFyIHN0ZXAgPSAobWF4ICogaGl2YWwgLSBtaW4gKiBoaXZhbCkgLyAoKGxlbmd0aCAtIDEpICogaGl2YWwpOwoJCSAgdmFyIGN1cnJlbnQgPSBtaW47CgkJICB2YXIgY250OwoKCQkgIC8vIEN1cnJlbnQgaXMgYXNzaWduZWQgdXNpbmcgYSB0ZWNobmlxdWUgdG8gY29tcGVuc2F0ZSBmb3IgSUVFRSBlcnJvci4KCQkgIC8vIFRPRE86IE5lZWRzIGJldHRlciBpbXBsZW1lbnRhdGlvbi4KCQkgIGZvciAoY250ID0gMDsKCQkgICAgICAgY3VycmVudCA8PSBtYXggJiYgY250IDwgbGVuZ3RoOwoJCSAgICAgICBjbnQrKywgY3VycmVudCA9IChtaW4gKiBoaXZhbCArIHN0ZXAgKiBoaXZhbCAqIGNudCkgLyBoaXZhbCkgewoJCSAgICBhcnIucHVzaCgoZnVuYyA/IGZ1bmMoY3VycmVudCwgY250KSA6IGN1cnJlbnQpKTsKCQkgIH0KCgkJICByZXR1cm4gYXJyOwoJCX07CgoKCQkvLyBhcmFuZ2UoNSkgLT4gWzAsMSwyLDMsNF0KCQkvLyBhcmFuZ2UoMSw1KSAtPiBbMSwyLDMsNF0KCQkvLyBhcmFuZ2UoNSwxLC0xKSAtPiBbNSw0LDMsMl0KCQlqU3RhdC5hcmFuZ2UgPSBmdW5jdGlvbiBhcmFuZ2Uoc3RhcnQsIGVuZCwgc3RlcCkgewoJCSAgdmFyIHJsID0gW107CgkJICBzdGVwID0gc3RlcCB8fCAxOwoJCSAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkJDEpIHsKCQkgICAgZW5kID0gc3RhcnQ7CgkJICAgIHN0YXJ0ID0gMDsKCQkgIH0KCQkgIGlmIChzdGFydCA9PT0gZW5kIHx8IHN0ZXAgPT09IDApIHsKCQkgICAgcmV0dXJuIFtdOwoJCSAgfQoJCSAgaWYgKHN0YXJ0IDwgZW5kICYmIHN0ZXAgPCAwKSB7CgkJICAgIHJldHVybiBbXTsKCQkgIH0KCQkgIGlmIChzdGFydCA+IGVuZCAmJiBzdGVwID4gMCkgewoJCSAgICByZXR1cm4gW107CgkJICB9CgkJICBpZiAoc3RlcCA+IDApIHsKCQkgICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7IGkgKz0gc3RlcCkgewoJCSAgICAgIHJsLnB1c2goaSk7CgkJICAgIH0KCQkgIH0gZWxzZSB7CgkJICAgIGZvciAoaSA9IHN0YXJ0OyBpID4gZW5kOyBpICs9IHN0ZXApIHsKCQkgICAgICBybC5wdXNoKGkpOwoJCSAgICB9CgkJICB9CgkJICByZXR1cm4gcmw7CgkJfTsKCgoJCS8vIEE9W1sxLDIsM10sWzQsNSw2XSxbNyw4LDldXQoJCS8vIHNsaWNlKEEse3Jvdzp7ZW5kOjJ9LGNvbDp7c3RhcnQ6MX19KSAtPiBbWzIsM10sWzUsNl1dCgkJLy8gc2xpY2UoQSwxLHtzdGFydDoxfSkgLT4gWzUsNl0KCQkvLyBhcyBudW1weSBjb2RlIEFbOjIsMTpdCgkJalN0YXQuc2xpY2UgPSAoZnVuY3Rpb24oKXsKCQkgIGZ1bmN0aW9uIF9zbGljZShsaXN0LCBzdGFydCwgZW5kLCBzdGVwKSB7CgkJICAgIC8vIG5vdGUgaXQncyBub3QgZXF1YWwgdG8gcmFuZ2UubWFwIG1vZGUgaXQncyBhIGJ1ZwoJCSAgICB2YXIgaTsKCQkgICAgdmFyIHJsID0gW107CgkJICAgIHZhciBsZW5ndGggPSBsaXN0Lmxlbmd0aDsKCQkgICAgaWYgKHN0YXJ0ID09PSB1bmRlZmluZWQkMSAmJiBlbmQgPT09IHVuZGVmaW5lZCQxICYmIHN0ZXAgPT09IHVuZGVmaW5lZCQxKSB7CgkJICAgICAgcmV0dXJuIGpTdGF0LmNvcHkobGlzdCk7CgkJICAgIH0KCgkJICAgIHN0YXJ0ID0gc3RhcnQgfHwgMDsKCQkgICAgZW5kID0gZW5kIHx8IGxpc3QubGVuZ3RoOwoJCSAgICBzdGFydCA9IHN0YXJ0ID49IDAgPyBzdGFydCA6IGxlbmd0aCArIHN0YXJ0OwoJCSAgICBlbmQgPSBlbmQgPj0gMCA/IGVuZCA6IGxlbmd0aCArIGVuZDsKCQkgICAgc3RlcCA9IHN0ZXAgfHwgMTsKCQkgICAgaWYgKHN0YXJ0ID09PSBlbmQgfHwgc3RlcCA9PT0gMCkgewoJCSAgICAgIHJldHVybiBbXTsKCQkgICAgfQoJCSAgICBpZiAoc3RhcnQgPCBlbmQgJiYgc3RlcCA8IDApIHsKCQkgICAgICByZXR1cm4gW107CgkJICAgIH0KCQkgICAgaWYgKHN0YXJ0ID4gZW5kICYmIHN0ZXAgPiAwKSB7CgkJICAgICAgcmV0dXJuIFtdOwoJCSAgICB9CgkJICAgIGlmIChzdGVwID4gMCkgewoJCSAgICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgZW5kOyBpICs9IHN0ZXApIHsKCQkgICAgICAgIHJsLnB1c2gobGlzdFtpXSk7CgkJICAgICAgfQoJCSAgICB9IGVsc2UgewoJCSAgICAgIGZvciAoaSA9IHN0YXJ0OyBpID4gZW5kO2kgKz0gc3RlcCkgewoJCSAgICAgICAgcmwucHVzaChsaXN0W2ldKTsKCQkgICAgICB9CgkJICAgIH0KCQkgICAgcmV0dXJuIHJsOwoJCSAgfQoKCQkgIGZ1bmN0aW9uIHNsaWNlKGxpc3QsIHJjU2xpY2UpIHsKCQkgICAgcmNTbGljZSA9IHJjU2xpY2UgfHwge307CgkJICAgIGlmIChpc051bWJlcihyY1NsaWNlLnJvdykpIHsKCQkgICAgICBpZiAoaXNOdW1iZXIocmNTbGljZS5jb2wpKQoJCSAgICAgICAgcmV0dXJuIGxpc3RbcmNTbGljZS5yb3ddW3JjU2xpY2UuY29sXTsKCQkgICAgICB2YXIgcm93ID0galN0YXQucm93YShsaXN0LCByY1NsaWNlLnJvdyk7CgkJICAgICAgdmFyIGNvbFNsaWNlID0gcmNTbGljZS5jb2wgfHwge307CgkJICAgICAgcmV0dXJuIF9zbGljZShyb3csIGNvbFNsaWNlLnN0YXJ0LCBjb2xTbGljZS5lbmQsIGNvbFNsaWNlLnN0ZXApOwoJCSAgICB9CgoJCSAgICBpZiAoaXNOdW1iZXIocmNTbGljZS5jb2wpKSB7CgkJICAgICAgdmFyIGNvbCA9IGpTdGF0LmNvbGEobGlzdCwgcmNTbGljZS5jb2wpOwoJCSAgICAgIHZhciByb3dTbGljZSA9IHJjU2xpY2Uucm93IHx8IHt9OwoJCSAgICAgIHJldHVybiBfc2xpY2UoY29sLCByb3dTbGljZS5zdGFydCwgcm93U2xpY2UuZW5kLCByb3dTbGljZS5zdGVwKTsKCQkgICAgfQoKCQkgICAgdmFyIHJvd1NsaWNlID0gcmNTbGljZS5yb3cgfHwge307CgkJICAgIHZhciBjb2xTbGljZSA9IHJjU2xpY2UuY29sIHx8IHt9OwoJCSAgICB2YXIgcm93cyA9IF9zbGljZShsaXN0LCByb3dTbGljZS5zdGFydCwgcm93U2xpY2UuZW5kLCByb3dTbGljZS5zdGVwKTsKCQkgICAgcmV0dXJuIHJvd3MubWFwKGZ1bmN0aW9uKHJvdykgewoJCSAgICAgIHJldHVybiBfc2xpY2Uocm93LCBjb2xTbGljZS5zdGFydCwgY29sU2xpY2UuZW5kLCBjb2xTbGljZS5zdGVwKTsKCQkgICAgfSk7CgkJICB9CgoJCSAgcmV0dXJuIHNsaWNlOwoJCX0oKSk7CgoKCQkvLyBBPVtbMSwyLDNdLFs0LDUsNl0sWzcsOCw5XV0KCQkvLyBzbGljZUFzc2lnbihBLHtyb3c6e3N0YXJ0OjF9LGNvbDp7c3RhcnQ6MX19LFtbMCwwXSxbMCwwXV0pCgkJLy8gQT1bWzEsMiwzXSxbNCwwLDBdLFs3LDAsMF1dCgkJalN0YXQuc2xpY2VBc3NpZ24gPSBmdW5jdGlvbiBzbGljZUFzc2lnbihBLCByY1NsaWNlLCBCKSB7CgkJICBpZiAoaXNOdW1iZXIocmNTbGljZS5yb3cpKSB7CgkJICAgIGlmIChpc051bWJlcihyY1NsaWNlLmNvbCkpCgkJICAgICAgcmV0dXJuIEFbcmNTbGljZS5yb3ddW3JjU2xpY2UuY29sXSA9IEI7CgkJICAgIHJjU2xpY2UuY29sID0gcmNTbGljZS5jb2wgfHwge307CgkJICAgIHJjU2xpY2UuY29sLnN0YXJ0ID0gcmNTbGljZS5jb2wuc3RhcnQgfHwgMDsKCQkgICAgcmNTbGljZS5jb2wuZW5kID0gcmNTbGljZS5jb2wuZW5kIHx8IEFbMF0ubGVuZ3RoOwoJCSAgICByY1NsaWNlLmNvbC5zdGVwID0gcmNTbGljZS5jb2wuc3RlcCB8fCAxOwoJCSAgICB2YXIgbmwgPSBqU3RhdC5hcmFuZ2UocmNTbGljZS5jb2wuc3RhcnQsCgkJICAgICAgICAgICAgICAgICAgICAgICAgICBNYXRoLm1pbihBLmxlbmd0aCwgcmNTbGljZS5jb2wuZW5kKSwKCQkgICAgICAgICAgICAgICAgICAgICAgICAgIHJjU2xpY2UuY29sLnN0ZXApOwoJCSAgICB2YXIgbSA9IHJjU2xpY2Uucm93OwoJCSAgICBubC5mb3JFYWNoKGZ1bmN0aW9uKG4sIGkpIHsKCQkgICAgICBBW21dW25dID0gQltpXTsKCQkgICAgfSk7CgkJICAgIHJldHVybiBBOwoJCSAgfQoKCQkgIGlmIChpc051bWJlcihyY1NsaWNlLmNvbCkpIHsKCQkgICAgcmNTbGljZS5yb3cgPSByY1NsaWNlLnJvdyB8fCB7fTsKCQkgICAgcmNTbGljZS5yb3cuc3RhcnQgPSByY1NsaWNlLnJvdy5zdGFydCB8fCAwOwoJCSAgICByY1NsaWNlLnJvdy5lbmQgPSByY1NsaWNlLnJvdy5lbmQgfHwgQS5sZW5ndGg7CgkJICAgIHJjU2xpY2Uucm93LnN0ZXAgPSByY1NsaWNlLnJvdy5zdGVwIHx8IDE7CgkJICAgIHZhciBtbCA9IGpTdGF0LmFyYW5nZShyY1NsaWNlLnJvdy5zdGFydCwKCQkgICAgICAgICAgICAgICAgICAgICAgICAgIE1hdGgubWluKEFbMF0ubGVuZ3RoLCByY1NsaWNlLnJvdy5lbmQpLAoJCSAgICAgICAgICAgICAgICAgICAgICAgICAgcmNTbGljZS5yb3cuc3RlcCk7CgkJICAgIHZhciBuID0gcmNTbGljZS5jb2w7CgkJICAgIG1sLmZvckVhY2goZnVuY3Rpb24obSwgaikgewoJCSAgICAgIEFbbV1bbl0gPSBCW2pdOwoJCSAgICB9KTsKCQkgICAgcmV0dXJuIEE7CgkJICB9CgoJCSAgaWYgKEJbMF0ubGVuZ3RoID09PSB1bmRlZmluZWQkMSkgewoJCSAgICBCID0gW0JdOwoJCSAgfQoJCSAgcmNTbGljZS5yb3cuc3RhcnQgPSByY1NsaWNlLnJvdy5zdGFydCB8fCAwOwoJCSAgcmNTbGljZS5yb3cuZW5kID0gcmNTbGljZS5yb3cuZW5kIHx8IEEubGVuZ3RoOwoJCSAgcmNTbGljZS5yb3cuc3RlcCA9IHJjU2xpY2Uucm93LnN0ZXAgfHwgMTsKCQkgIHJjU2xpY2UuY29sLnN0YXJ0ID0gcmNTbGljZS5jb2wuc3RhcnQgfHwgMDsKCQkgIHJjU2xpY2UuY29sLmVuZCA9IHJjU2xpY2UuY29sLmVuZCB8fCBBWzBdLmxlbmd0aDsKCQkgIHJjU2xpY2UuY29sLnN0ZXAgPSByY1NsaWNlLmNvbC5zdGVwIHx8IDE7CgkJICB2YXIgbWwgPSBqU3RhdC5hcmFuZ2UocmNTbGljZS5yb3cuc3RhcnQsCgkJICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5taW4oQS5sZW5ndGgsIHJjU2xpY2Uucm93LmVuZCksCgkJICAgICAgICAgICAgICAgICAgICAgICAgcmNTbGljZS5yb3cuc3RlcCk7CgkJICB2YXIgbmwgPSBqU3RhdC5hcmFuZ2UocmNTbGljZS5jb2wuc3RhcnQsCgkJICAgICAgICAgICAgICAgICAgICAgICAgTWF0aC5taW4oQVswXS5sZW5ndGgsIHJjU2xpY2UuY29sLmVuZCksCgkJICAgICAgICAgICAgICAgICAgICAgICAgcmNTbGljZS5jb2wuc3RlcCk7CgkJICBtbC5mb3JFYWNoKGZ1bmN0aW9uKG0sIGkpIHsKCQkgICAgbmwuZm9yRWFjaChmdW5jdGlvbihuLCBqKSB7CgkJICAgICAgQVttXVtuXSA9IEJbaV1bal07CgkJICAgIH0pOwoJCSAgfSk7CgkJICByZXR1cm4gQTsKCQl9OwoKCgkJLy8gWzEsMiwzXSAtPgoJCS8vIFtbMSwwLDBdLFswLDIsMF0sWzAsMCwzXV0KCQlqU3RhdC5kaWFnb25hbCA9IGZ1bmN0aW9uIGRpYWdvbmFsKGRpYWdBcnJheSkgewoJCSAgdmFyIG1hdCA9IGpTdGF0Lnplcm9zKGRpYWdBcnJheS5sZW5ndGgsIGRpYWdBcnJheS5sZW5ndGgpOwoJCSAgZGlhZ0FycmF5LmZvckVhY2goZnVuY3Rpb24odCwgaSkgewoJCSAgICBtYXRbaV1baV0gPSB0OwoJCSAgfSk7CgkJICByZXR1cm4gbWF0OwoJCX07CgoKCQkvLyByZXR1cm4gY29weSBvZiBBCgkJalN0YXQuY29weSA9IGZ1bmN0aW9uIGNvcHkoQSkgewoJCSAgcmV0dXJuIEEubWFwKGZ1bmN0aW9uKHJvdykgewoJCSAgICBpZiAoaXNOdW1iZXIocm93KSkKCQkgICAgICByZXR1cm4gcm93OwoJCSAgICByZXR1cm4gcm93Lm1hcChmdW5jdGlvbih0KSB7CgkJICAgICAgcmV0dXJuIHQ7CgkJICAgIH0pOwoJCSAgfSk7CgkJfTsKCgoJCS8vIFRPRE86IEdvIG92ZXIgdGhpcyBlbnRpcmUgaW1wbGVtZW50YXRpb24uIFNlZW1zIGEgdHJhZ2ljIHdhc3RlIG9mIHJlc291cmNlcwoJCS8vIGRvaW5nIGFsbCB0aGlzIHdvcmsuIEluc3RlYWQsIGFuZCB3aGlsZSB1Z2x5LCB1c2UgbmV3IEZ1bmN0aW9uKCkgdG8gZ2VuZXJhdGUKCQkvLyBhIGN1c3RvbSBmdW5jdGlvbiBmb3IgZWFjaCBzdGF0aWMgbWV0aG9kLgoKCQkvLyBRdWljayByZWZlcmVuY2UuCgkJdmFyIGpQcm90byA9IGpTdGF0LnByb3RvdHlwZTsKCgkJLy8gRGVmYXVsdCBsZW5ndGguCgkJalByb3RvLmxlbmd0aCA9IDA7CgoJCS8vIEZvciBpbnRlcm5hbCB1c2Ugb25seS4KCQkvLyBUT0RPOiBDaGVjayBpZiB0aGV5J3JlIGFjdHVhbGx5IHVzZWQsIGFuZCBpZiB0aGV5IGFyZSB0aGVuIHJlbmFtZSB0aGVtCgkJLy8gdG8gXyoKCQlqUHJvdG8ucHVzaCA9IEFycmF5LnByb3RvdHlwZS5wdXNoOwoJCWpQcm90by5zb3J0ID0gQXJyYXkucHJvdG90eXBlLnNvcnQ7CgkJalByb3RvLnNwbGljZSA9IEFycmF5LnByb3RvdHlwZS5zcGxpY2U7CgkJalByb3RvLnNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlOwoKCgkJLy8gUmV0dXJuIGEgY2xlYW4gYXJyYXkuCgkJalByb3RvLnRvQXJyYXkgPSBmdW5jdGlvbiB0b0FycmF5KCkgewoJCSAgcmV0dXJuIHRoaXMubGVuZ3RoID4gMSA/IHNsaWNlLmNhbGwodGhpcykgOiBzbGljZS5jYWxsKHRoaXMpWzBdOwoJCX07CgoKCQkvLyBNYXAgYSBmdW5jdGlvbiB0byBhIG1hdHJpeCBvciB2ZWN0b3IuCgkJalByb3RvLm1hcCA9IGZ1bmN0aW9uIG1hcChmdW5jLCB0b0FsdGVyKSB7CgkJICByZXR1cm4galN0YXQoalN0YXQubWFwKHRoaXMsIGZ1bmMsIHRvQWx0ZXIpKTsKCQl9OwoKCgkJLy8gQ3VtdWxhdGl2ZWx5IGNvbWJpbmUgdGhlIGVsZW1lbnRzIG9mIGEgbWF0cml4IG9yIHZlY3RvciB1c2luZyBhIGZ1bmN0aW9uLgoJCWpQcm90by5jdW1yZWR1Y2UgPSBmdW5jdGlvbiBjdW1yZWR1Y2UoZnVuYywgdG9BbHRlcikgewoJCSAgcmV0dXJuIGpTdGF0KGpTdGF0LmN1bXJlZHVjZSh0aGlzLCBmdW5jLCB0b0FsdGVyKSk7CgkJfTsKCgoJCS8vIERlc3RydWN0aXZlbHkgYWx0ZXIgYW4gYXJyYXkuCgkJalByb3RvLmFsdGVyID0gZnVuY3Rpb24gYWx0ZXIoZnVuYykgewoJCSAgalN0YXQuYWx0ZXIodGhpcywgZnVuYyk7CgkJICByZXR1cm4gdGhpczsKCQl9OwoKCgkJLy8gRXh0ZW5kIHByb3RvdHlwZSB3aXRoIG1ldGhvZHMgdGhhdCBoYXZlIG5vIGFyZ3VtZW50LgoJCShmdW5jdGlvbihmdW5jcykgewoJCSAgZm9yICh2YXIgaSA9IDA7IGkgPCBmdW5jcy5sZW5ndGg7IGkrKykgKGZ1bmN0aW9uKHBhc3NmdW5jKSB7CgkJICAgIGpQcm90b1twYXNzZnVuY10gPSBmdW5jdGlvbihmdW5jKSB7CgkJICAgICAgdmFyIHNlbGYgPSB0aGlzLAoJCSAgICAgIHJlc3VsdHM7CgkJICAgICAgLy8gQ2hlY2sgZm9yIGNhbGxiYWNrLgoJCSAgICAgIGlmIChmdW5jKSB7CgkJICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkgewoJCSAgICAgICAgICBmdW5jLmNhbGwoc2VsZiwgalByb3RvW3Bhc3NmdW5jXS5jYWxsKHNlbGYpKTsKCQkgICAgICAgIH0pOwoJCSAgICAgICAgcmV0dXJuIHRoaXM7CgkJICAgICAgfQoJCSAgICAgIHJlc3VsdHMgPSBqU3RhdFtwYXNzZnVuY10odGhpcyk7CgkJICAgICAgcmV0dXJuIGlzQXJyYXkocmVzdWx0cykgPyBqU3RhdChyZXN1bHRzKSA6IHJlc3VsdHM7CgkJICAgIH07CgkJICB9KShmdW5jc1tpXSk7CgkJfSkoJ3RyYW5zcG9zZSBjbGVhciBzeW1tZXRyaWMgcm93cyBjb2xzIGRpbWVuc2lvbnMgZGlhZyBhbnRpZGlhZycuc3BsaXQoJyAnKSk7CgoKCQkvLyBFeHRlbmQgcHJvdG90eXBlIHdpdGggbWV0aG9kcyB0aGF0IGhhdmUgb25lIGFyZ3VtZW50LgoJCShmdW5jdGlvbihmdW5jcykgewoJCSAgZm9yICh2YXIgaSA9IDA7IGkgPCBmdW5jcy5sZW5ndGg7IGkrKykgKGZ1bmN0aW9uKHBhc3NmdW5jKSB7CgkJICAgIGpQcm90b1twYXNzZnVuY10gPSBmdW5jdGlvbihpbmRleCwgZnVuYykgewoJCSAgICAgIHZhciBzZWxmID0gdGhpczsKCQkgICAgICAvLyBjaGVjayBmb3IgY2FsbGJhY2sKCQkgICAgICBpZiAoZnVuYykgewoJCSAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHsKCQkgICAgICAgICAgZnVuYy5jYWxsKHNlbGYsIGpQcm90b1twYXNzZnVuY10uY2FsbChzZWxmLCBpbmRleCkpOwoJCSAgICAgICAgfSk7CgkJICAgICAgICByZXR1cm4gdGhpczsKCQkgICAgICB9CgkJICAgICAgcmV0dXJuIGpTdGF0KGpTdGF0W3Bhc3NmdW5jXSh0aGlzLCBpbmRleCkpOwoJCSAgICB9OwoJCSAgfSkoZnVuY3NbaV0pOwoJCX0pKCdyb3cgY29sJy5zcGxpdCgnICcpKTsKCgoJCS8vIEV4dGVuZCBwcm90b3R5cGUgd2l0aCBzaW1wbGUgc2hvcnRjdXQgbWV0aG9kcy4KCQkoZnVuY3Rpb24oZnVuY3MpIHsKCQkgIGZvciAodmFyIGkgPSAwOyBpIDwgZnVuY3MubGVuZ3RoOyBpKyspIChmdW5jdGlvbihwYXNzZnVuYykgewoJCSAgICBqUHJvdG9bcGFzc2Z1bmNdID0gbmV3IEZ1bmN0aW9uKAoJCSAgICAgICAgJ3JldHVybiBqU3RhdChqU3RhdC4nICsgcGFzc2Z1bmMgKyAnLmFwcGx5KG51bGwsIGFyZ3VtZW50cykpOycpOwoJCSAgfSkoZnVuY3NbaV0pOwoJCX0pKCdjcmVhdGUgemVyb3Mgb25lcyByYW5kIGlkZW50aXR5Jy5zcGxpdCgnICcpKTsKCgoJCS8vIEV4cG9zaW5nIGpTdGF0LgoJCXJldHVybiBqU3RhdDsKCgkJfShNYXRoKSk7CgkJKGZ1bmN0aW9uKGpTdGF0LCBNYXRoKSB7CgoJCXZhciBpc0Z1bmN0aW9uID0galN0YXQudXRpbHMuaXNGdW5jdGlvbjsKCgkJLy8gQXNjZW5kaW5nIGZ1bmN0aW9ucyBmb3Igc29ydAoJCWZ1bmN0aW9uIGFzY051bShhLCBiKSB7IHJldHVybiBhIC0gYjsgfQoKCQlmdW5jdGlvbiBjbGlwKGFyZywgbWluLCBtYXgpIHsKCQkgIHJldHVybiBNYXRoLm1heChtaW4sIE1hdGgubWluKGFyZywgbWF4KSk7CgkJfQoKCgkJLy8gc3VtIG9mIGFuIGFycmF5CgkJalN0YXQuc3VtID0gZnVuY3Rpb24gc3VtKGFycikgewoJCSAgdmFyIHN1bSA9IDA7CgkJICB2YXIgaSA9IGFyci5sZW5ndGg7CgkJICB3aGlsZSAoLS1pID49IDApCgkJICAgIHN1bSArPSBhcnJbaV07CgkJICByZXR1cm4gc3VtOwoJCX07CgoKCQkvLyBzdW0gc3F1YXJlZAoJCWpTdGF0LnN1bXNxcmQgPSBmdW5jdGlvbiBzdW1zcXJkKGFycikgewoJCSAgdmFyIHN1bSA9IDA7CgkJICB2YXIgaSA9IGFyci5sZW5ndGg7CgkJICB3aGlsZSAoLS1pID49IDApCgkJICAgIHN1bSArPSBhcnJbaV0gKiBhcnJbaV07CgkJICByZXR1cm4gc3VtOwoJCX07CgoKCQkvLyBzdW0gb2Ygc3F1YXJlZCBlcnJvcnMgb2YgcHJlZGljdGlvbiAoU1NFKQoJCWpTdGF0LnN1bXNxZXJyID0gZnVuY3Rpb24gc3Vtc3FlcnIoYXJyKSB7CgkJICB2YXIgbWVhbiA9IGpTdGF0Lm1lYW4oYXJyKTsKCQkgIHZhciBzdW0gPSAwOwoJCSAgdmFyIGkgPSBhcnIubGVuZ3RoOwoJCSAgdmFyIHRtcDsKCQkgIHdoaWxlICgtLWkgPj0gMCkgewoJCSAgICB0bXAgPSBhcnJbaV0gLSBtZWFuOwoJCSAgICBzdW0gKz0gdG1wICogdG1wOwoJCSAgfQoJCSAgcmV0dXJuIHN1bTsKCQl9OwoKCQkvLyBzdW0gb2YgYW4gYXJyYXkgaW4gZWFjaCByb3cKCQlqU3RhdC5zdW1yb3cgPSBmdW5jdGlvbiBzdW1yb3coYXJyKSB7CgkJICB2YXIgc3VtID0gMDsKCQkgIHZhciBpID0gYXJyLmxlbmd0aDsKCQkgIHdoaWxlICgtLWkgPj0gMCkKCQkgICAgc3VtICs9IGFycltpXTsKCQkgIHJldHVybiBzdW07CgkJfTsKCgkJLy8gcHJvZHVjdCBvZiBhbiBhcnJheQoJCWpTdGF0LnByb2R1Y3QgPSBmdW5jdGlvbiBwcm9kdWN0KGFycikgewoJCSAgdmFyIHByb2QgPSAxOwoJCSAgdmFyIGkgPSBhcnIubGVuZ3RoOwoJCSAgd2hpbGUgKC0taSA+PSAwKQoJCSAgICBwcm9kICo9IGFycltpXTsKCQkgIHJldHVybiBwcm9kOwoJCX07CgoKCQkvLyBtaW5pbXVtIHZhbHVlIG9mIGFuIGFycmF5CgkJalN0YXQubWluID0gZnVuY3Rpb24gbWluKGFycikgewoJCSAgdmFyIGxvdyA9IGFyclswXTsKCQkgIHZhciBpID0gMDsKCQkgIHdoaWxlICgrK2kgPCBhcnIubGVuZ3RoKQoJCSAgICBpZiAoYXJyW2ldIDwgbG93KQoJCSAgICAgIGxvdyA9IGFycltpXTsKCQkgIHJldHVybiBsb3c7CgkJfTsKCgoJCS8vIG1heGltdW0gdmFsdWUgb2YgYW4gYXJyYXkKCQlqU3RhdC5tYXggPSBmdW5jdGlvbiBtYXgoYXJyKSB7CgkJICB2YXIgaGlnaCA9IGFyclswXTsKCQkgIHZhciBpID0gMDsKCQkgIHdoaWxlICgrK2kgPCBhcnIubGVuZ3RoKQoJCSAgICBpZiAoYXJyW2ldID4gaGlnaCkKCQkgICAgICBoaWdoID0gYXJyW2ldOwoJCSAgcmV0dXJuIGhpZ2g7CgkJfTsKCgoJCS8vIHVuaXF1ZSB2YWx1ZXMgb2YgYW4gYXJyYXkKCQlqU3RhdC51bmlxdWUgPSBmdW5jdGlvbiB1bmlxdWUoYXJyKSB7CgkJICB2YXIgaGFzaCA9IHt9LCBfYXJyID0gW107CgkJICBmb3IodmFyIGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7CgkJICAgIGlmICghaGFzaFthcnJbaV1dKSB7CgkJICAgICAgaGFzaFthcnJbaV1dID0gdHJ1ZTsKCQkgICAgICBfYXJyLnB1c2goYXJyW2ldKTsKCQkgICAgfQoJCSAgfQoJCSAgcmV0dXJuIF9hcnI7CgkJfTsKCgoJCS8vIG1lYW4gdmFsdWUgb2YgYW4gYXJyYXkKCQlqU3RhdC5tZWFuID0gZnVuY3Rpb24gbWVhbihhcnIpIHsKCQkgIHJldHVybiBqU3RhdC5zdW0oYXJyKSAvIGFyci5sZW5ndGg7CgkJfTsKCgoJCS8vIG1lYW4gc3F1YXJlZCBlcnJvciAoTVNFKQoJCWpTdGF0Lm1lYW5zcWVyciA9IGZ1bmN0aW9uIG1lYW5zcWVycihhcnIpIHsKCQkgIHJldHVybiBqU3RhdC5zdW1zcWVycihhcnIpIC8gYXJyLmxlbmd0aDsKCQl9OwoKCgkJLy8gZ2VvbWV0cmljIG1lYW4gb2YgYW4gYXJyYXkKCQlqU3RhdC5nZW9tZWFuID0gZnVuY3Rpb24gZ2VvbWVhbihhcnIpIHsKCQkgIHJldHVybiBNYXRoLnBvdyhqU3RhdC5wcm9kdWN0KGFyciksIDEgLyBhcnIubGVuZ3RoKTsKCQl9OwoKCgkJLy8gbWVkaWFuIG9mIGFuIGFycmF5CgkJalN0YXQubWVkaWFuID0gZnVuY3Rpb24gbWVkaWFuKGFycikgewoJCSAgdmFyIGFycmxlbiA9IGFyci5sZW5ndGg7CgkJICB2YXIgX2FyciA9IGFyci5zbGljZSgpLnNvcnQoYXNjTnVtKTsKCQkgIC8vIGNoZWNrIGlmIGFycmF5IGlzIGV2ZW4gb3Igb2RkLCB0aGVuIHJldHVybiB0aGUgYXBwcm9wcmlhdGUKCQkgIHJldHVybiAhKGFycmxlbiAmIDEpCgkJICAgID8gKF9hcnJbKGFycmxlbiAvIDIpIC0gMSBdICsgX2FyclsoYXJybGVuIC8gMildKSAvIDIKCQkgICAgOiBfYXJyWyhhcnJsZW4gLyAyKSB8IDAgXTsKCQl9OwoKCgkJLy8gY3VtdWxhdGl2ZSBzdW0gb2YgYW4gYXJyYXkKCQlqU3RhdC5jdW1zdW0gPSBmdW5jdGlvbiBjdW1zdW0oYXJyKSB7CgkJICByZXR1cm4galN0YXQuY3VtcmVkdWNlKGFyciwgZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEgKyBiOyB9KTsKCQl9OwoKCgkJLy8gY3VtdWxhdGl2ZSBwcm9kdWN0IG9mIGFuIGFycmF5CgkJalN0YXQuY3VtcHJvZCA9IGZ1bmN0aW9uIGN1bXByb2QoYXJyKSB7CgkJICByZXR1cm4galN0YXQuY3VtcmVkdWNlKGFyciwgZnVuY3Rpb24gKGEsIGIpIHsgcmV0dXJuIGEgKiBiOyB9KTsKCQl9OwoKCgkJLy8gc3VjY2Vzc2l2ZSBkaWZmZXJlbmNlcyBvZiBhIHNlcXVlbmNlCgkJalN0YXQuZGlmZiA9IGZ1bmN0aW9uIGRpZmYoYXJyKSB7CgkJICB2YXIgZGlmZnMgPSBbXTsKCQkgIHZhciBhcnJMZW4gPSBhcnIubGVuZ3RoOwoJCSAgdmFyIGk7CgkJICBmb3IgKHZhciBpID0gMTsgaSA8IGFyckxlbjsgaSsrKQoJCSAgICBkaWZmcy5wdXNoKGFycltpXSAtIGFycltpIC0gMV0pOwoJCSAgcmV0dXJuIGRpZmZzOwoJCX07CgoKCQkvLyByYW5rcyBvZiBhbiBhcnJheQoJCWpTdGF0LnJhbmsgPSBmdW5jdGlvbiAoYXJyKSB7CgkJICB2YXIgYXJybGVuID0gYXJyLmxlbmd0aDsKCQkgIHZhciBzb3J0ZWQgPSBhcnIuc2xpY2UoKS5zb3J0KGFzY051bSk7CgkJICB2YXIgcmFua3MgPSBuZXcgQXJyYXkoYXJybGVuKTsKCQkgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJybGVuOyBpKyspIHsKCQkgICAgdmFyIGZpcnN0ID0gc29ydGVkLmluZGV4T2YoYXJyW2ldKTsKCQkgICAgdmFyIGxhc3QgPSBzb3J0ZWQubGFzdEluZGV4T2YoYXJyW2ldKTsKCQkgICAgaWYgKGZpcnN0ID09PSBsYXN0KSB7CgkJICAgICAgdmFyIHZhbCA9IGZpcnN0OwoJCSAgICB9IGVsc2UgewoJCSAgICAgIHZhciB2YWwgPSAoZmlyc3QgKyBsYXN0KSAvIDI7CgkJICAgIH0KCQkgICAgcmFua3NbaV0gPSB2YWwgKyAxOwoJCSAgfQoJCSAgcmV0dXJuIHJhbmtzOwoJCX07CgoKCQkvLyBtb2RlIG9mIGFuIGFycmF5CgkJLy8gaWYgdGhlcmUgYXJlIG11bHRpcGxlIG1vZGVzIG9mIGFuIGFycmF5LCByZXR1cm4gYWxsIG9mIHRoZW0KCQkvLyBpcyB0aGlzIHRoZSBhcHByb3ByaWF0ZSB3YXkgb2YgaGFuZGxpbmcgaXQ/CgkJalN0YXQubW9kZSA9IGZ1bmN0aW9uIG1vZGUoYXJyKSB7CgkJICB2YXIgYXJyTGVuID0gYXJyLmxlbmd0aDsKCQkgIHZhciBfYXJyID0gYXJyLnNsaWNlKCkuc29ydChhc2NOdW0pOwoJCSAgdmFyIGNvdW50ID0gMTsKCQkgIHZhciBtYXhDb3VudCA9IDA7CgkJICB2YXIgbnVtTWF4Q291bnQgPSAwOwoJCSAgdmFyIG1vZGVfYXJyID0gW107CgkJICB2YXIgaTsKCgkJICBmb3IgKHZhciBpID0gMDsgaSA8IGFyckxlbjsgaSsrKSB7CgkJICAgIGlmIChfYXJyW2ldID09PSBfYXJyW2kgKyAxXSkgewoJCSAgICAgIGNvdW50Kys7CgkJICAgIH0gZWxzZSB7CgkJICAgICAgaWYgKGNvdW50ID4gbWF4Q291bnQpIHsKCQkgICAgICAgIG1vZGVfYXJyID0gW19hcnJbaV1dOwoJCSAgICAgICAgbWF4Q291bnQgPSBjb3VudDsKCQkgICAgICAgIG51bU1heENvdW50ID0gMDsKCQkgICAgICB9CgkJICAgICAgLy8gYXJlIHRoZXJlIG11bHRpcGxlIG1heCBjb3VudHMKCQkgICAgICBlbHNlIGlmIChjb3VudCA9PT0gbWF4Q291bnQpIHsKCQkgICAgICAgIG1vZGVfYXJyLnB1c2goX2FycltpXSk7CgkJICAgICAgICBudW1NYXhDb3VudCsrOwoJCSAgICAgIH0KCQkgICAgICAvLyByZXNldHRpbmcgY291bnQgZm9yIG5ldyB2YWx1ZSBpbiBhcnJheQoJCSAgICAgIGNvdW50ID0gMTsKCQkgICAgfQoJCSAgfQoKCQkgIHJldHVybiBudW1NYXhDb3VudCA9PT0gMCA/IG1vZGVfYXJyWzBdIDogbW9kZV9hcnI7CgkJfTsKCgoJCS8vIHJhbmdlIG9mIGFuIGFycmF5CgkJalN0YXQucmFuZ2UgPSBmdW5jdGlvbiByYW5nZShhcnIpIHsKCQkgIHJldHVybiBqU3RhdC5tYXgoYXJyKSAtIGpTdGF0Lm1pbihhcnIpOwoJCX07CgoJCS8vIHZhcmlhbmNlIG9mIGFuIGFycmF5CgkJLy8gZmxhZyA9IHRydWUgaW5kaWNhdGVzIHNhbXBsZSBpbnN0ZWFkIG9mIHBvcHVsYXRpb24KCQlqU3RhdC52YXJpYW5jZSA9I