You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2674 lines
220 KiB
2674 lines
220 KiB
/******/ (() => { // webpackBootstrap
|
|
/******/ var __webpack_modules__ = ({
|
|
|
|
/***/ "./node_modules/nosleep.js/src/index.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/nosleep.js/src/index.js ***!
|
|
\**********************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
const { webm, mp4 } = __webpack_require__(/*! ./media.js */ "./node_modules/nosleep.js/src/media.js");
|
|
|
|
// Detect iOS browsers < version 10
|
|
const oldIOS = () =>
|
|
typeof navigator !== "undefined" &&
|
|
parseFloat(
|
|
(
|
|
"" +
|
|
(/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec(
|
|
navigator.userAgent
|
|
) || [0, ""])[1]
|
|
)
|
|
.replace("undefined", "3_2")
|
|
.replace("_", ".")
|
|
.replace("_", "")
|
|
) < 10 &&
|
|
!window.MSStream;
|
|
|
|
// Detect native Wake Lock API support
|
|
const nativeWakeLock = () => "wakeLock" in navigator;
|
|
|
|
class NoSleep {
|
|
constructor() {
|
|
this.enabled = false;
|
|
if (nativeWakeLock()) {
|
|
this._wakeLock = null;
|
|
const handleVisibilityChange = () => {
|
|
if (this._wakeLock !== null && document.visibilityState === "visible") {
|
|
this.enable();
|
|
}
|
|
};
|
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
document.addEventListener("fullscreenchange", handleVisibilityChange);
|
|
} else if (oldIOS()) {
|
|
this.noSleepTimer = null;
|
|
} else {
|
|
// Set up no sleep video element
|
|
this.noSleepVideo = document.createElement("video");
|
|
|
|
this.noSleepVideo.setAttribute("title", "No Sleep");
|
|
this.noSleepVideo.setAttribute("playsinline", "");
|
|
|
|
this._addSourceToVideo(this.noSleepVideo, "webm", webm);
|
|
this._addSourceToVideo(this.noSleepVideo, "mp4", mp4);
|
|
|
|
this.noSleepVideo.addEventListener("loadedmetadata", () => {
|
|
if (this.noSleepVideo.duration <= 1) {
|
|
// webm source
|
|
this.noSleepVideo.setAttribute("loop", "");
|
|
} else {
|
|
// mp4 source
|
|
this.noSleepVideo.addEventListener("timeupdate", () => {
|
|
if (this.noSleepVideo.currentTime > 0.5) {
|
|
this.noSleepVideo.currentTime = Math.random();
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
_addSourceToVideo(element, type, dataURI) {
|
|
var source = document.createElement("source");
|
|
source.src = dataURI;
|
|
source.type = `video/${type}`;
|
|
element.appendChild(source);
|
|
}
|
|
|
|
get isEnabled() {
|
|
return this.enabled;
|
|
}
|
|
|
|
enable() {
|
|
if (nativeWakeLock()) {
|
|
return navigator.wakeLock
|
|
.request("screen")
|
|
.then((wakeLock) => {
|
|
this._wakeLock = wakeLock;
|
|
this.enabled = true;
|
|
console.log("Wake Lock active.");
|
|
this._wakeLock.addEventListener("release", () => {
|
|
// ToDo: Potentially emit an event for the page to observe since
|
|
// Wake Lock releases happen when page visibility changes.
|
|
// (https://web.dev/wakelock/#wake-lock-lifecycle)
|
|
console.log("Wake Lock released.");
|
|
});
|
|
})
|
|
.catch((err) => {
|
|
this.enabled = false;
|
|
console.error(`${err.name}, ${err.message}`);
|
|
throw err;
|
|
});
|
|
} else if (oldIOS()) {
|
|
this.disable();
|
|
console.warn(`
|
|
NoSleep enabled for older iOS devices. This can interrupt
|
|
active or long-running network requests from completing successfully.
|
|
See https://github.com/richtr/NoSleep.js/issues/15 for more details.
|
|
`);
|
|
this.noSleepTimer = window.setInterval(() => {
|
|
if (!document.hidden) {
|
|
window.location.href = window.location.href.split("#")[0];
|
|
window.setTimeout(window.stop, 0);
|
|
}
|
|
}, 15000);
|
|
this.enabled = true;
|
|
return Promise.resolve();
|
|
} else {
|
|
let playPromise = this.noSleepVideo.play();
|
|
return playPromise
|
|
.then((res) => {
|
|
this.enabled = true;
|
|
return res;
|
|
})
|
|
.catch((err) => {
|
|
this.enabled = false;
|
|
throw err;
|
|
});
|
|
}
|
|
}
|
|
|
|
disable() {
|
|
if (nativeWakeLock()) {
|
|
if (this._wakeLock) {
|
|
this._wakeLock.release();
|
|
}
|
|
this._wakeLock = null;
|
|
} else if (oldIOS()) {
|
|
if (this.noSleepTimer) {
|
|
console.warn(`
|
|
NoSleep now disabled for older iOS devices.
|
|
`);
|
|
window.clearInterval(this.noSleepTimer);
|
|
this.noSleepTimer = null;
|
|
}
|
|
} else {
|
|
this.noSleepVideo.pause();
|
|
}
|
|
this.enabled = false;
|
|
}
|
|
}
|
|
|
|
module.exports = NoSleep;
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./node_modules/nosleep.js/src/media.js":
|
|
/*!**********************************************!*\
|
|
!*** ./node_modules/nosleep.js/src/media.js ***!
|
|
\**********************************************/
|
|
/***/ ((module) => {
|
|
|
|
module.exports = {
|
|
webm:
|
|
"data:video/webm;base64,GkXfowEAAAAAAAAfQoaBAUL3gQFC8oEEQvOBCEKChHdlYm1Ch4EEQoWBAhhTgGcBAAAAAAAVkhFNm3RALE27i1OrhBVJqWZTrIHfTbuMU6uEFlSua1OsggEwTbuMU6uEHFO7a1OsghV17AEAAAAAAACkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmAQAAAAAAAEUq17GDD0JATYCNTGF2ZjU1LjMzLjEwMFdBjUxhdmY1NS4zMy4xMDBzpJBlrrXf3DCDVB8KcgbMpcr+RImIQJBgAAAAAAAWVK5rAQAAAAAAD++uAQAAAAAAADLXgQFzxYEBnIEAIrWcg3VuZIaFVl9WUDiDgQEj44OEAmJaAOABAAAAAAAABrCBsLqBkK4BAAAAAAAPq9eBAnPFgQKcgQAitZyDdW5khohBX1ZPUkJJU4OBAuEBAAAAAAAAEZ+BArWIQOdwAAAAAABiZIEgY6JPbwIeVgF2b3JiaXMAAAAAAoC7AAAAAAAAgLUBAAAAAAC4AQN2b3JiaXMtAAAAWGlwaC5PcmcgbGliVm9yYmlzIEkgMjAxMDExMDEgKFNjaGF1ZmVudWdnZXQpAQAAABUAAABlbmNvZGVyPUxhdmM1NS41Mi4xMDIBBXZvcmJpcyVCQ1YBAEAAACRzGCpGpXMWhBAaQlAZ4xxCzmvsGUJMEYIcMkxbyyVzkCGkoEKIWyiB0JBVAABAAACHQXgUhIpBCCGEJT1YkoMnPQghhIg5eBSEaUEIIYQQQgghhBBCCCGERTlokoMnQQgdhOMwOAyD5Tj4HIRFOVgQgydB6CCED0K4moOsOQghhCQ1SFCDBjnoHITCLCiKgsQwuBaEBDUojILkMMjUgwtCiJqDSTX4GoRnQXgWhGlBCCGEJEFIkIMGQcgYhEZBWJKDBjm4FITLQagahCo5CB+EIDRkFQCQAACgoiiKoigKEBqyCgDIAAAQQFEUx3EcyZEcybEcCwgNWQUAAAEACAAAoEiKpEiO5EiSJFmSJVmSJVmS5omqLMuyLMuyLMsyEBqyCgBIAABQUQxFcRQHCA1ZBQBkAAAIoDiKpViKpWiK54iOCISGrAIAgAAABAAAEDRDUzxHlETPVFXXtm3btm3btm3btm3btm1blmUZCA1ZBQBAAAAQ0mlmqQaIMAMZBkJDVgEACAAAgBGKMMSA0JBVAABAAACAGEoOogmtOd+c46BZDppKsTkdnEi1eZKbirk555xzzsnmnDHOOeecopxZDJoJrTnnnMSgWQqaCa0555wnsXnQmiqtOeeccc7pYJwRxjnnnCateZCajbU555wFrWmOmkuxOeecSLl5UptLtTnnnHPOOeecc84555zqxekcnBPOOeecqL25lpvQxTnnnE/G6d6cEM4555xzzjnnnHPOOeecIDRkFQAABABAEIaNYdwpCNLnaCBGEWIaMulB9+gwCRqDnELq0ehopJQ6CCWVcVJKJwgNWQUAAAIAQAghhRRSSCGFFFJIIYUUYoghhhhyyimnoIJKKqmooowyyyyzzDLLLLPMOuyssw47DDHEEEMrrcRSU2011lhr7jnnmoO0VlprrbVSSimllFIKQkNWAQAgAAAEQgYZZJBRSCGFFGKIKaeccgoqqIDQkFUAACAAgAAAAABP8hzRER3RER3RER3RER3R8RzPESVREiVREi3TMjXTU0VVdWXXlnVZt31b2IVd933d933d+HVhWJZlWZZlWZZlWZZlWZZlWZYgNGQVAAACAAAghBBCSCGFFFJIKcYYc8w56CSUEAgNWQUAAAIACAAAAHAUR3EcyZEcSbIkS9IkzdIsT/M0TxM9URRF0zRV0RVdUTdtUTZl0zVdUzZdVVZtV5ZtW7Z125dl2/d93/d93/d93/d93/d9XQdCQ1YBABIAADqSIymSIimS4ziOJElAaMgqAEAGAEAAAIriKI7jOJIkSZIlaZJneZaomZrpmZ4qqkBoyCoAABAAQAAAAAAAAIqmeIqpeIqoeI7oiJJomZaoqZoryqbsuq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq7ruq4LhIasAgAkAAB0JEdyJEdSJEVSJEdygNCQVQCADACAAAAcwzEkRXIsy9I0T/M0TxM90RM901NFV3SB0JBVAAAgAIAAAAAAAAAMybAUy9EcTRIl1VItVVMt1VJF1VNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVN0zRNEwgNWQkAkAEAkBBTLS3GmgmLJGLSaqugYwxS7KWxSCpntbfKMYUYtV4ah5RREHupJGOKQcwtpNApJq3WVEKFFKSYYyoVUg5SIDRkhQAQmgHgcBxAsixAsiwAAAAAAAAAkDQN0DwPsDQPAAAAAAAAACRNAyxPAzTPAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA0jRA8zxA8zwAAAAAAAAA0DwP8DwR8EQRAAAAAAAAACzPAzTRAzxRBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABA0jRA8zxA8zwAAAAAAAAAsDwP8EQR0DwRAAAAAAAAACzPAzxRBDzRAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAEOAAABBgIRQasiIAiBMAcEgSJAmSBM0DSJYFTYOmwTQBkmVB06BpME0AAAAAAAAAAAAAJE2DpkHTIIoASdOgadA0iCIAAAAAAAAAAAAAkqZB06BpEEWApGnQNGgaRBEAAAAAAAAAAAAAzzQhihBFmCbAM02IIkQRpgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAGHAAAAgwoQwUGrIiAIgTAHA4imUBAIDjOJYFAACO41gWAABYliWKAABgWZooAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAYcAAACDChDBQashIAiAIAcCiKZQHHsSzgOJYFJMmyAJYF0DyApgFEEQAIAAAocAAACLBBU2JxgEJDVgIAUQAABsWxLE0TRZKkaZoniiRJ0zxPFGma53meacLzPM80IYqiaJoQRVE0TZimaaoqME1VFQAAUOAAABBgg6bE4gCFhqwEAEICAByKYlma5nmeJ4qmqZokSdM8TxRF0TRNU1VJkqZ5niiKommapqqyLE3zPFEURdNUVVWFpnmeKIqiaaqq6sLzPE8URdE0VdV14XmeJ4qiaJqq6roQRVE0TdNUTVV1XSCKpmmaqqqqrgtETxRNU1Vd13WB54miaaqqq7ouEE3TVFVVdV1ZBpimaaqq68oyQFVV1XVdV5YBqqqqruu6sgxQVdd1XVmWZQCu67qyLMsCAAAOHAAAAoygk4wqi7DRhAsPQKEhKwKAKAAAwBimFFPKMCYhpBAaxiSEFEImJaXSUqogpFJSKRWEVEoqJaOUUmopVRBSKamUCkIqJZVSAADYgQMA2IGFUGjISgAgDwCAMEYpxhhzTiKkFGPOOScRUoox55yTSjHmnHPOSSkZc8w556SUzjnnnHNSSuacc845KaVzzjnnnJRSSuecc05KKSWEzkEnpZTSOeecEwAAVOAAABBgo8jmBCNBhYasBABSAQAMjmNZmuZ5omialiRpmud5niiapiZJmuZ5nieKqsnzPE8URdE0VZXneZ4oiqJpqirXFUXTNE1VVV2yLIqmaZqq6rowTdNUVdd1XZimaaqq67oubFtVVdV1ZRm2raqq6rqyDFzXdWXZloEsu67s2rIAAPAEBwCgAhtWRzgpGgssNGQlAJABAEAYg5BCCCFlEEIKIYSUUggJAAAYcAAACDChDBQashIASAUAAIyx1lprrbXWQGettdZaa62AzFprrbXWWmuttdZaa6211lJrrbXWWmuttdZaa6211lprrbXWWmuttdZaa6211lprrbXWWmuttdZaa6211lprrbXWWmstpZRSSimllFJKKaWUUkoppZRSSgUA+lU4APg/2LA6wknRWGChISsBgHAAAMAYpRhzDEIppVQIMeacdFRai7FCiDHnJKTUWmzFc85BKCGV1mIsnnMOQikpxVZjUSmEUlJKLbZYi0qho5JSSq3VWIwxqaTWWoutxmKMSSm01FqLMRYjbE2ptdhqq7EYY2sqLbQYY4zFCF9kbC2m2moNxggjWywt1VprMMYY3VuLpbaaizE++NpSLDHWXAAAd4MDAESCjTOsJJ0VjgYXGrISAAgJACAQUooxxhhzzjnnpFKMOeaccw5CCKFUijHGnHMOQgghlIwx5pxzEEIIIYRSSsaccxBCCCGEkFLqnHMQQgghhBBKKZ1zDkIIIYQQQimlgxBCCCGEEEoopaQUQgghhBBCCKmklEIIIYRSQighlZRSCCGEEEIpJaSUUgohhFJCCKGElFJKKYUQQgillJJSSimlEkoJJYQSUikppRRKCCGUUkpKKaVUSgmhhBJKKSWllFJKIYQQSikFAAAcOAAABBhBJxlVFmGjCRcegEJDVgIAZAAAkKKUUiktRYIipRikGEtGFXNQWoqocgxSzalSziDmJJaIMYSUk1Qy5hRCDELqHHVMKQYtlRhCxhik2HJLoXMOAAAAQQCAgJAAAAMEBTMAwOAA4XMQdAIERxsAgCBEZohEw0JweFAJEBFTAUBigkIuAFRYXKRdXECXAS7o4q4DIQQhCEEsDqCABByccMMTb3jCDU7QKSp1IAAAAAAADADwAACQXAAREdHMYWRobHB0eHyAhIiMkAgAAAAAABcAfAAAJCVAREQ0cxgZGhscHR4fICEiIyQBAIAAAgAAAAAggAAEBAQAAAAAAAIAAAAEBB9DtnUBAAAAAAAEPueBAKOFggAAgACjzoEAA4BwBwCdASqwAJAAAEcIhYWIhYSIAgIABhwJ7kPfbJyHvtk5D32ych77ZOQ99snIe+2TkPfbJyHvtk5D32ych77ZOQ99YAD+/6tQgKOFggADgAqjhYIAD4AOo4WCACSADqOZgQArADECAAEQEAAYABhYL/QACIBDmAYAAKOFggA6gA6jhYIAT4AOo5mBAFMAMQIAARAQABgAGFgv9AAIgEOYBgAAo4WCAGSADqOFggB6gA6jmYEAewAxAgABEBAAGAAYWC/0AAiAQ5gGAACjhYIAj4AOo5mBAKMAMQIAARAQABgAGFgv9AAIgEOYBgAAo4WCAKSADqOFggC6gA6jmYEAywAxAgABEBAAGAAYWC/0AAiAQ5gGAACjhYIAz4AOo4WCAOSADqOZgQDzADECAAEQEAAYABhYL/QACIBDmAYAAKOFggD6gA6jhYIBD4AOo5iBARsAEQIAARAQFGAAYWC/0AAiAQ5gGACjhYIBJIAOo4WCATqADqOZgQFDADECAAEQEAAYABhYL/QACIBDmAYAAKOFggFPgA6jhYIBZIAOo5mBAWsAMQIAARAQABgAGFgv9AAIgEOYBgAAo4WCAXqADqOFggGPgA6jmYEBkwAxAgABEBAAGAAYWC/0AAiAQ5gGAACjhYIBpIAOo4WCAbqADqOZgQG7ADECAAEQEAAYABhYL/QACIBDmAYAAKOFggHPgA6jmYEB4wAxAgABEBAAGAAYWC/0AAiAQ5gGAACjhYIB5IAOo4WCAfqADqOZgQILADECAAEQEAAYABhYL/QACIBDmAYAAKOFggIPgA6jhYICJIAOo5mBAjMAMQIAARAQABgAGFgv9AAIgEOYBgAAo4WCAjqADqOFggJPgA6jmYECWwAxAgABEBAAGAAYWC/0AAiAQ5gGAACjhYICZIAOo4WCAnqADqOZgQKDADECAAEQEAAYABhYL/QACIBDmAYAAKOFggKPgA6jhYICpIAOo5mBAqsAMQIAARAQABgAGFgv9AAIgEOYBgAAo4WCArqADqOFggLPgA6jmIEC0wARAgABEBAUYABhYL/QACIBDmAYAKOFggLkgA6jhYIC+oAOo5mBAvsAMQIAARAQABgAGFgv9AAIgEOYBgAAo4WCAw+ADqOZgQMjADECAAEQEAAYABhYL/QACIBDmAYAAKOFggMkgA6jhYIDOoAOo5mBA0sAMQIAARAQABgAGFgv9AAIgEOYBgAAo4WCA0+ADqOFggNkgA6jmYEDcwAxAgABEBAAGAAYWC/0AAiAQ5gGAACjhYIDeoAOo4WCA4+ADqOZgQObADECAAEQEAAYABhYL/QACIBDmAYAAKOFggOkgA6jhYIDuoAOo5mBA8MAMQIAARAQABgAGFgv9AAIgEOYBgAAo4WCA8+ADqOFggPkgA6jhYID+oAOo4WCBA+ADhxTu2sBAAAAAAAAEbuPs4EDt4r3gQHxghEr8IEK",
|
|
mp4:
|
|
"data:video/mp4;base64,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",
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./src/room/activities.js":
|
|
/*!********************************!*\
|
|
!*** ./src/room/activities.js ***!
|
|
\********************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
const OmUtil = __webpack_require__(/*! ../main/omutils */ "../main/omutils");
|
|
const Settings = __webpack_require__(/*! ../main/settings */ "../main/settings");
|
|
|
|
const closedHeight = 20, timeout = 10000;
|
|
let activities, aclean, modArea, area, openedHeight = 345
|
|
, openedHeightPx = openedHeight + 'px', inited = false
|
|
, newActNotification;
|
|
|
|
function _load() {
|
|
const s = Settings.load();
|
|
if (typeof(s.activity) === 'undefined') {
|
|
s.activity = {};
|
|
}
|
|
return s;
|
|
}
|
|
function _updateClean(s, a) {
|
|
const clean = s.activity.clean === true;
|
|
a.prop('checked', clean);
|
|
if (clean) {
|
|
activities.find('.auto-clean').each(function() {
|
|
setTimeout(_clearItem.bind(null, $(this).data().id), timeout);
|
|
});
|
|
}
|
|
}
|
|
function isClosed() {
|
|
return activities.height() < 24;
|
|
}
|
|
function _updateHeightVar(h) {
|
|
Room.setCssVar('--activities-height', h);
|
|
}
|
|
function _open() {
|
|
if (isClosed()) {
|
|
$('.control.block i', activities).removeClass('fa-angle-up').addClass('fa-angle-down');
|
|
$('.control.block', activities).removeClass('bg-warning');
|
|
activities.animate(
|
|
{
|
|
height: openedHeightPx
|
|
, top: '-' + openedHeightPx
|
|
}
|
|
, 1000
|
|
, function() {
|
|
activities.css({'top': ''});
|
|
_updateHeightVar(openedHeightPx);
|
|
activities.resizable('option', 'disabled', false);
|
|
}
|
|
);
|
|
}
|
|
}
|
|
function _close() {
|
|
if (!isClosed()) {
|
|
$('.control.block i', activities).removeClass('fa-angle-down').addClass('fa-angle-up');
|
|
activities.animate(
|
|
{
|
|
height: closedHeight
|
|
, top: (openedHeight - closedHeight) + 'px'
|
|
}
|
|
, 1000
|
|
, function() {
|
|
activities.css({'top': ''});
|
|
_updateHeightVar(closedHeight + 'px');
|
|
}
|
|
);
|
|
activities.resizable('option', 'disabled', true);
|
|
}
|
|
}
|
|
function _findUser(uid) {
|
|
const m = '5px', t = 50, u = $('#user' + uid);
|
|
if (u.length === 1) {
|
|
u[0].scrollIntoView();
|
|
u.addClass('bg-warning');
|
|
for(let i = 0; i < 10; i++) {
|
|
u.animate({marginTop: '-='+m}, t)
|
|
.animate({marginTop: '+='+m}, t);
|
|
}
|
|
u.removeClass('bg-warning', 1500);
|
|
}
|
|
}
|
|
function _hightlight(notify) {
|
|
if (!inited) {
|
|
return;
|
|
}
|
|
if (isClosed()) {
|
|
$('.control.block', activities).addClass('bg-warning');
|
|
if (notify) {
|
|
OmUtil.notify(newActNotification, 'new_aa_item');
|
|
}
|
|
}
|
|
}
|
|
function _getId(id) {
|
|
return 'activity-' + id;
|
|
}
|
|
function _action(name, val) {
|
|
activityAction($('.room-block .room-container').data('room-id'), name, val);
|
|
}
|
|
function _remove(ids) {
|
|
for (let i = 0; i < ids.length; ++i) {
|
|
$('#' + _getId(ids[i])).remove();
|
|
}
|
|
_updateCount();
|
|
}
|
|
function _clearItem(id) {
|
|
if (aclean.prop('checked')) {
|
|
_remove([id]);
|
|
}
|
|
}
|
|
function _updateCount() {
|
|
if (!inited) {
|
|
return;
|
|
}
|
|
$('.control.block .badge', activities).text(modArea.find('.activity').length);
|
|
}
|
|
|
|
module.exports = {
|
|
init: function() {
|
|
if ($('#activities').resizable("instance") !== undefined) {
|
|
return;
|
|
}
|
|
activities = $('#activities');
|
|
const ctrlBlk = activities.find('.control.block');
|
|
ctrlBlk.off().click(Activities.toggle);
|
|
newActNotification = ctrlBlk.data('new-aa');
|
|
activities.resizable({
|
|
handles: 'n'
|
|
, disabled: isClosed()
|
|
, minHeight: 195
|
|
, stop: function(_, ui) {
|
|
openedHeight = ui.size.height;
|
|
openedHeightPx = openedHeight + 'px';
|
|
_updateHeightVar(openedHeightPx);
|
|
activities.css({'top': ''});
|
|
}
|
|
});
|
|
modArea = activities.find('.area .actions');
|
|
area = activities.find('.area .activities');
|
|
aclean = $('#activity-auto-clean');
|
|
aclean.change(function() {
|
|
const s = _load();
|
|
s.activity.clean = $(this).prop('checked');
|
|
Settings.save(s);
|
|
_updateClean(s, $(this));
|
|
});
|
|
_updateClean(_load(), aclean);
|
|
inited = true;
|
|
_updateCount();
|
|
}
|
|
, toggle: function() {
|
|
if (!inited) {
|
|
return;
|
|
}
|
|
if (isClosed()) {
|
|
_open();
|
|
} else {
|
|
_close();
|
|
}
|
|
}
|
|
, findUser: _findUser
|
|
, add: function(obj) {
|
|
if (!inited) {
|
|
return;
|
|
}
|
|
const _id = _getId(obj.id);
|
|
(obj.action ? modArea : area).append(OmUtil.tmpl('#activity-stub', _id).data(obj));
|
|
const a = $('#' + _id).addClass(obj.cssClass);
|
|
const acpt = a.find('.activity-accept');
|
|
if (obj.accept) {
|
|
acpt.click(function() { _action('accept', obj.id); });
|
|
} else {
|
|
acpt.remove();
|
|
}
|
|
const dcln = a.find('.activity-decline');
|
|
if (obj.decline) {
|
|
dcln.click(function() { _action('decline', obj.id); });
|
|
} else {
|
|
dcln.remove();
|
|
}
|
|
const fnd = a.find('.activity-find');
|
|
if (obj.find) {
|
|
fnd.click(function() { _findUser(obj.uid); });
|
|
} else {
|
|
fnd.remove();
|
|
}
|
|
a.find('.activity-close').click(function() {
|
|
_action('close', obj.id);
|
|
});
|
|
a.find('.activity-text').text(obj.text);
|
|
_hightlight(obj.action);
|
|
if (aclean.prop('checked') && a.hasClass('auto-clean')) {
|
|
setTimeout(_clearItem.bind(null, obj.id), timeout);
|
|
}
|
|
_updateCount();
|
|
}
|
|
, remove: _remove
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./src/room/quick-poll.js":
|
|
/*!********************************!*\
|
|
!*** ./src/room/quick-poll.js ***!
|
|
\********************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
const OmUtil = __webpack_require__(/*! ../main/omutils */ "../main/omutils");
|
|
const UserListUtil = __webpack_require__(/*! ./user-list-util */ "./src/room/user-list-util.js");
|
|
|
|
function _setQuickPollRights() {
|
|
const close = $('#quick-vote .close-btn');
|
|
if (close.length === 1) {
|
|
if (UserListUtil.hasRight(['PRESENTER'])) {
|
|
close.show();
|
|
if (typeof(close.data('bs.confirmation')) === 'object') {
|
|
return;
|
|
}
|
|
close
|
|
.confirmation({
|
|
confirmationEvent: 'bla'
|
|
, onConfirm: () => quickPollAction('close')
|
|
});
|
|
} else {
|
|
close.hide();
|
|
}
|
|
}
|
|
}
|
|
function _update(obj) {
|
|
if (obj.started) {
|
|
let qv = $('#quick-vote');
|
|
if (qv.length === 0) {
|
|
const wbArea = $('.room-block .wb-block');
|
|
qv = OmUtil.tmpl('#quick-vote-template', 'quick-vote');
|
|
qv.attr('class', 'end-0');
|
|
wbArea.append(qv);
|
|
}
|
|
const pro = qv.find('.control.pro')
|
|
, con = qv.find('.control.con');
|
|
if (obj.voted) {
|
|
pro.removeClass('clickable').off();
|
|
con.removeClass('clickable').off();
|
|
} else {
|
|
pro.addClass('clickable').off().click(function() {
|
|
quickPollAction('vote', true);
|
|
});
|
|
con.addClass('clickable').off().click(function() {
|
|
quickPollAction('vote', false);
|
|
});
|
|
}
|
|
pro.find('.badge').text(obj.pros);
|
|
con.find('.badge').text(obj.cons);
|
|
_setQuickPollRights();
|
|
} else {
|
|
const qv = $('#quick-vote');
|
|
if (qv.length === 1) {
|
|
qv.remove();
|
|
}
|
|
}
|
|
OmUtil.tmpl('#quick-vote-template', 'quick-vote');
|
|
}
|
|
|
|
module.exports = {
|
|
update: _update
|
|
, setRights: _setQuickPollRights
|
|
};
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./src/room/room.js":
|
|
/*!**************************!*\
|
|
!*** ./src/room/room.js ***!
|
|
\**************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
const Settings = __webpack_require__(/*! ../main/settings */ "../main/settings");
|
|
const VideoUtil = __webpack_require__(/*! ../settings/video-util */ "../settings/video-util");
|
|
const VideoSettings = __webpack_require__(/*! ../settings/settings */ "../settings/settings");
|
|
const InterviewWbArea = __webpack_require__(/*! ../wb/interview-area */ "../wb/interview-area");
|
|
const DrawWbArea = __webpack_require__(/*! ../wb/wb-area */ "../wb/wb-area")
|
|
|
|
const NoSleep = __webpack_require__(/*! nosleep.js */ "./node_modules/nosleep.js/src/index.js");
|
|
const VideoManager = __webpack_require__(/*! ./video-manager */ "./src/room/video-manager.js");
|
|
const Sharer = __webpack_require__(/*! ./sharer */ "./src/room/sharer.js");
|
|
const Activities = __webpack_require__(/*! ./activities */ "./src/room/activities.js");
|
|
const SipDialer = __webpack_require__(/*! ./sip-dialer */ "./src/room/sip-dialer.js");
|
|
const UserListUtil = __webpack_require__(/*! ./user-list-util */ "./src/room/user-list-util.js");
|
|
const UserList = __webpack_require__(/*! ./user-list */ "./src/room/user-list.js");
|
|
const QuickPoll = __webpack_require__(/*! ./quick-poll */ "./src/room/quick-poll.js");
|
|
|
|
const sbSide = Settings.isRtl ? 'right' : 'left';
|
|
let options, menuHeight, sb, dock, noSleep;
|
|
|
|
function _init(_options) {
|
|
options = _options;
|
|
window.WbArea = options.interview ? new InterviewWbArea() : new DrawWbArea();
|
|
const menu = $('.room-block .room-container .menu');
|
|
sb = $('.room-block .sidebar');
|
|
sb.width(sb.width()); // this is required to 'fix' the width so it will not depend on CSS var
|
|
dock = sb.find('.btn-dock').click(function() {
|
|
const offset = parseInt(sb.css(sbSide));
|
|
if (offset < 0) {
|
|
sb.removeClass('closed');
|
|
}
|
|
dock.prop('disabled', true);
|
|
const props = {};
|
|
props[sbSide] = offset < 0 ? '0px' : (-sb.width() + 45) + 'px';
|
|
sb.animate(props, 1500
|
|
, function() {
|
|
dock.prop('disabled', false);
|
|
__dockSetMode(offset < 0);
|
|
_setSize();
|
|
});
|
|
});
|
|
__dockSetMode(true);
|
|
menuHeight = menu.length === 0 ? 0 : menu.height();
|
|
VideoManager.init();
|
|
Activities.init();
|
|
Sharer.init();
|
|
UserList.init(options);
|
|
_setSize();
|
|
$(window).on('resize.omwb', window.WbArea.resize);
|
|
}
|
|
function __dockSetMode(mode) {
|
|
const icon = dock.find('i').removeClass('icon-dock icon-undock');
|
|
if (mode) {
|
|
icon.addClass('icon-undock');
|
|
dock.attr('title', dock.data('ttl-undock'))
|
|
.find('.sr-only').text(dock.data('ttl-undock'));
|
|
_sbAddResizable();
|
|
} else {
|
|
icon.addClass('icon-dock');
|
|
dock.attr('title', dock.data('ttl-dock'))
|
|
.find('.sr-only').text(dock.data('ttl-dock'));
|
|
sb.addClass('closed').resizable('destroy');
|
|
}
|
|
}
|
|
function _getSelfAudioClient() {
|
|
const vw = $('.video-container[data-client-type=WEBCAM][data-client-uid=' + Room.getOptions().uid + ']');
|
|
if (vw.length > 0) {
|
|
const v = vw.first().data();
|
|
if (VideoUtil.hasMic(v.stream())) {
|
|
return v;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
function _preventKeydown(e) {
|
|
const base = $(e.target);
|
|
if (e.target.isContentEditable === true || base.is('textarea, input:not([readonly]):not([type=radio]):not([type=checkbox])')) {
|
|
return;
|
|
}
|
|
if (e.which === 8) { // backspace
|
|
e.preventDefault();
|
|
e.stopImmediatePropagation();
|
|
return false;
|
|
}
|
|
}
|
|
function __keyPressed(hotkey, e) {
|
|
const code = e.code;
|
|
return hotkey.alt === e.altKey
|
|
&& hotkey.ctrl === e.ctrlKey
|
|
&& hotkey.shift === e.shiftKey
|
|
&& hotkey.code.toUpperCase() === (code ? code.toUpperCase() : '');
|
|
}
|
|
function _keyHandler(e) {
|
|
if (__keyPressed(options.keycode.arrange, e)) {
|
|
VideoUtil.arrange();
|
|
} else if (__keyPressed(options.keycode.arrangeresize, e)) {
|
|
VideoUtil.arrangeResize(VideoSettings.load());
|
|
} else if (__keyPressed(options.keycode.muteothers, e)) {
|
|
const v = _getSelfAudioClient();
|
|
if (v !== null) {
|
|
VideoManager.clickMuteOthers(Room.getOptions().uid);
|
|
}
|
|
} else if (__keyPressed(options.keycode.mute, e)) {
|
|
const v = _getSelfAudioClient();
|
|
if (v !== null) {
|
|
v.mute(!v.isMuted());
|
|
}
|
|
} else if (__keyPressed(options.keycode.quickpoll, e)) {
|
|
quickPollAction('open');
|
|
}
|
|
if (e.which === 27) {
|
|
$('#wb-rename-menu').hide();
|
|
}
|
|
}
|
|
function _mouseHandler(e) {
|
|
if (e.which === 1) {
|
|
$('#wb-rename-menu').hide();
|
|
}
|
|
}
|
|
function _sbWidth() {
|
|
if (sb === undefined) {
|
|
sb = $('.room-block .sidebar');
|
|
}
|
|
return sb === undefined ? 0 : sb.width() + parseInt(sb.css(sbSide));
|
|
}
|
|
function _setSize() {
|
|
const sbW = _sbWidth()
|
|
, holder = $('.room-block');
|
|
($('.main.room')[0]).style.setProperty('--sidebar-width', sbW + 'px');
|
|
if (sbW > 236) {
|
|
holder.addClass('big').removeClass('narrow');
|
|
} else {
|
|
holder.removeClass('big').addClass('narrow');
|
|
}
|
|
}
|
|
function _reload() {
|
|
if (!!options && !!options.reloadUrl) {
|
|
window.location.href = options.reloadUrl;
|
|
} else {
|
|
window.location.reload();
|
|
}
|
|
}
|
|
function _close() {
|
|
_unload();
|
|
$(".room-block").remove();
|
|
$("#chatPanel").remove();
|
|
$('#disconnected-dlg')
|
|
.modal('show')
|
|
.off('hide.bs.modal')
|
|
.on('hide.bs.modal', _reload);
|
|
}
|
|
function _sbAddResizable() {
|
|
sb.resizable({
|
|
handles: Settings.isRtl ? 'w' : 'e'
|
|
, stop: function() {
|
|
_setSize();
|
|
}
|
|
});
|
|
}
|
|
function _load() {
|
|
$('body').addClass('no-header');
|
|
Wicket.Event.subscribe("/websocket/closed", _close);
|
|
Wicket.Event.subscribe("/websocket/error", _close);
|
|
$(window).on('keydown.openmeetings', _preventKeydown);
|
|
$(window).on('keyup.openmeetings', _keyHandler);
|
|
$(window).on('keydown.om-sip', SipDialer.keyDown);
|
|
$(window).on('keyup.om-sip', SipDialer.keyUp);
|
|
$(document).click(_mouseHandler);
|
|
document.addEventListener('click', _addNoSleep, false);
|
|
SipDialer.init();
|
|
}
|
|
function _addNoSleep() {
|
|
_removeNoSleep();
|
|
noSleep = new NoSleep();
|
|
noSleep.enable();
|
|
}
|
|
function _removeNoSleep() {
|
|
document.removeEventListener('click', _addNoSleep, false);
|
|
if (noSleep) {
|
|
noSleep.disable();
|
|
noSleep = null;
|
|
}
|
|
}
|
|
function _unload() {
|
|
$('body').removeClass('no-header');
|
|
Wicket.Event.unsubscribe("/websocket/closed", _close);
|
|
Wicket.Event.unsubscribe("/websocket/error", _close);
|
|
if (typeof(WbArea) === 'object') {
|
|
WbArea.destroy();
|
|
window.WbArea = undefined;
|
|
}
|
|
if (typeof(VideoSettings) === 'object') {
|
|
VideoSettings.close();
|
|
}
|
|
if (typeof(VideoManager) === 'object') {
|
|
VideoManager.destroy();
|
|
}
|
|
$('.ui-dialog.user-video').remove();
|
|
$(window).off('keyup.openmeetings');
|
|
$(window).off('keydown.openmeetings');
|
|
$(window).off('resize.omwb');
|
|
$(window).off('keydown.om-sip');
|
|
$(window).off('keyup.om-sip');
|
|
$(document).off('click', _mouseHandler);
|
|
sb = undefined;
|
|
Sharer.close();
|
|
_removeNoSleep();
|
|
}
|
|
function _showClipboard(txt) {
|
|
const dlg = $('#clipboard-dialog');
|
|
dlg.find('p .text').text(txt);
|
|
dlg.dialog({
|
|
resizable: false
|
|
, height: "auto"
|
|
, width: 400
|
|
, modal: true
|
|
, buttons: [
|
|
{
|
|
text: dlg.data('btn-ok')
|
|
, click: function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
]
|
|
});
|
|
}
|
|
|
|
module.exports = {
|
|
init: _init
|
|
, getMenuHeight: function() {
|
|
return menuHeight;
|
|
}
|
|
, getOptions: function() {
|
|
return typeof(options) === 'object' ? JSON.parse(JSON.stringify(options)) : {};
|
|
}
|
|
, load: _load
|
|
, unload: _unload
|
|
, showClipboard: _showClipboard
|
|
, quickPoll: QuickPoll.update
|
|
, hasRight: UserListUtil.hasRight
|
|
, setCssVar: function(key, val) {
|
|
($('.main.room')[0]).style.setProperty(key, val);
|
|
}
|
|
, addClient: UserList.addClient
|
|
, updateClient: UserList.updateClient
|
|
, removeClient: UserList.removeClient
|
|
, removeOthers: UserList.removeOthers
|
|
, getClient: UserList.getClient
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./src/room/sharer.js":
|
|
/*!****************************!*\
|
|
!*** ./src/room/sharer.js ***!
|
|
\****************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
const VideoUtil = __webpack_require__(/*! ../settings/video-util */ "../settings/video-util");
|
|
const VideoMgrUtil = __webpack_require__(/*! ./video-manager-util */ "./src/room/video-manager-util.js");
|
|
|
|
const SHARE_STARTING = 'starting'
|
|
, SHARE_STARTED = 'started'
|
|
, SHARE_STOPPED = 'stopped';
|
|
|
|
let sharer, type, fps, sbtn, rbtn
|
|
, shareState = SHARE_STOPPED, recState = SHARE_STOPPED;
|
|
|
|
/**
|
|
* Re-entering the room should reset settings.
|
|
*/
|
|
function reset() {
|
|
shareState = SHARE_STOPPED;
|
|
recState = SHARE_STOPPED;
|
|
}
|
|
|
|
function _init() {
|
|
reset();
|
|
sharer = $('#sharer').dialog({
|
|
appendTo: '.room-block .room-container'
|
|
, classes: {
|
|
'ui-dialog': 'sharer'
|
|
, 'ui-dialog-titlebar': ''
|
|
}
|
|
, width: 450
|
|
, autoOpen: false
|
|
, resizable: false
|
|
});
|
|
const ui = sharer.closest('.ui-dialog');
|
|
const parent = $('.room-block .room-container .sb-wb');
|
|
ui.draggable('option', 'containment', parent);
|
|
fixJQueryUIDialogTouch(sharer);
|
|
|
|
if (!VideoUtil.sharingSupported()) {
|
|
sharer.find('.container').remove();
|
|
sharer.find('.alert').show();
|
|
} else {
|
|
type = sharer.find('select.type');
|
|
fps = sharer.find('select.fps');
|
|
_disable(fps, VideoUtil.isEdge());
|
|
sbtn = sharer.find('.share-start-stop').off().click(function() {
|
|
if (shareState === SHARE_STOPPED) {
|
|
_setShareState(SHARE_STARTING);
|
|
VideoMgrUtil.sendMessage({
|
|
id: 'wannaShare'
|
|
, shareType: type.val()
|
|
, fps: fps.val()
|
|
});
|
|
} else {
|
|
VideoMgrUtil.sendMessage({
|
|
id: 'pauseSharing'
|
|
, uid: _getShareUid()
|
|
});
|
|
}
|
|
});
|
|
rbtn = sharer.find('.record-start-stop').off();
|
|
if (Room.getOptions().allowRecording) {
|
|
rbtn.show().click(function() {
|
|
if (recState === SHARE_STOPPED) {
|
|
_setRecState(SHARE_STARTING);
|
|
VideoMgrUtil.sendMessage({
|
|
id: 'wannaRecord'
|
|
, shareType: type.val()
|
|
, fps: fps.val()
|
|
});
|
|
} else {
|
|
VideoMgrUtil.sendMessage({
|
|
id: 'stopRecord'
|
|
, uid: _getShareUid()
|
|
});
|
|
}
|
|
});
|
|
} else {
|
|
rbtn.hide();
|
|
}
|
|
}
|
|
}
|
|
function _disable(e, state) {
|
|
e.prop('disabled', state);
|
|
if (state) {
|
|
e.addClass('disabled');
|
|
} else {
|
|
e.removeClass('disabled');
|
|
}
|
|
}
|
|
function _typeDisabled() {
|
|
return VideoUtil.isEdge() || VideoUtil.isChrome() || VideoUtil.isEdgeChromium();
|
|
}
|
|
function _setBtnState(btn, state) {
|
|
const dis = SHARE_STOPPED !== state
|
|
, typeDis = _typeDisabled();
|
|
_disable(type, dis);
|
|
_disable(fps, dis || typeDis);
|
|
btn.find('span').text(btn.data(dis ? 'stop' : 'start'));
|
|
if (dis) {
|
|
btn.addClass('stop');
|
|
} else {
|
|
btn.removeClass('stop');
|
|
}
|
|
_disable(btn, state === SHARE_STARTING);
|
|
_disable(btn, state === SHARE_STARTING);
|
|
}
|
|
function _setShareState(state) {
|
|
shareState = state;
|
|
_setBtnState(sbtn, state);
|
|
}
|
|
function _setRecState(state) {
|
|
recState = state;
|
|
_setBtnState(rbtn, state);
|
|
}
|
|
function _getShareUid() {
|
|
const v = $('div[data-client-uid="' + Room.getOptions().uid + '"][data-client-type="SCREEN"]');
|
|
return v && v.data() && v.data().stream() ? v.data().stream().uid : '';
|
|
}
|
|
|
|
module.exports = {
|
|
SHARE_STARTING: SHARE_STARTING
|
|
, SHARE_STARTED: SHARE_STARTED
|
|
, SHARE_STOPPED: SHARE_STOPPED
|
|
|
|
, init: _init
|
|
, open: function() {
|
|
if (sharer && sharer.dialog('instance')) {
|
|
sharer.dialog('open');
|
|
}
|
|
}
|
|
, close: function() {
|
|
if (sharer && sharer.dialog('instance')) {
|
|
sharer.dialog('close');
|
|
}
|
|
}
|
|
, setShareState: _setShareState
|
|
, setRecState: _setRecState
|
|
, baseConstraints: function(sd) {
|
|
return {
|
|
video: {
|
|
frameRate: {
|
|
ideal: sd.fps
|
|
}
|
|
}
|
|
, audio: false
|
|
};
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./src/room/sip-dialer.js":
|
|
/*!********************************!*\
|
|
!*** ./src/room/sip-dialer.js ***!
|
|
\********************************/
|
|
/***/ ((module) => {
|
|
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
function __addSipText(v) {
|
|
const txt = $('.sip-number');
|
|
txt.val(txt.val() + v);
|
|
}
|
|
function __eraseSipText() {
|
|
const txt = $('.sip-number')
|
|
, t = txt.val();
|
|
if (!!t) {
|
|
txt.val(t.substring(0, t.length - 1));
|
|
}
|
|
}
|
|
function _sipGetKey(evt) {
|
|
let k = -1;
|
|
if (evt.keyCode > 47 && evt.keyCode < 58) {
|
|
k = evt.keyCode - 48;
|
|
}
|
|
if (evt.keyCode > 95 && evt.keyCode < 106) {
|
|
k = evt.keyCode - 96;
|
|
}
|
|
return k;
|
|
}
|
|
|
|
module.exports = {
|
|
init: function() {
|
|
$('.sip .button-row button').off().click(function() {
|
|
__addSipText($(this).data('value'));
|
|
});
|
|
$('#sip-dialer-btn-erase').off().click(__eraseSipText);
|
|
}
|
|
, keyDown: function(evt) {
|
|
const k = _sipGetKey(evt);
|
|
if (k > 0) {
|
|
$('#sip-dialer-btn-' + k).addClass('bg-warning');
|
|
}
|
|
}
|
|
, keyUp: function(evt) {
|
|
if (evt.key === 'Backspace') {
|
|
__eraseSipText();
|
|
} else {
|
|
const k = _sipGetKey(evt);
|
|
if (k > 0) {
|
|
$('#sip-dialer-btn-' + k).removeClass('bg-warning');
|
|
__addSipText(k);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./src/room/user-list-util.js":
|
|
/*!************************************!*\
|
|
!*** ./src/room/user-list-util.js ***!
|
|
\************************************/
|
|
/***/ ((module) => {
|
|
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
let options;
|
|
|
|
function _hasRight(_inRights, _ref) {
|
|
const ref = _ref || options.rights;
|
|
let _rights;
|
|
if (Array.isArray(_inRights)) {
|
|
_rights = _inRights;
|
|
} else {
|
|
if ('SUPER_MODERATOR' === _inRights) {
|
|
return ref.includes(_inRights);
|
|
}
|
|
_rights = [_inRights];
|
|
}
|
|
const rights = ['SUPER_MODERATOR', 'MODERATOR', ..._rights];
|
|
for (let i = 0; i < rights.length; ++i) {
|
|
if (ref.includes(rights[i])) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
module.exports = {
|
|
init: function(opts) {
|
|
options = opts;
|
|
}
|
|
, hasRight: _hasRight
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./src/room/user-list.js":
|
|
/*!*******************************!*\
|
|
!*** ./src/room/user-list.js ***!
|
|
\*******************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
const Settings = __webpack_require__(/*! ../main/settings */ "../main/settings");
|
|
const Chat = __webpack_require__(/*! ../chat/chat */ "../chat/chat");
|
|
const VideoUtil = __webpack_require__(/*! ../settings/video-util */ "../settings/video-util");
|
|
const VideoSettings = __webpack_require__(/*! ../settings/settings */ "../settings/settings");
|
|
|
|
const OmUtil = __webpack_require__(/*! ../main/omutils */ "../main/omutils");
|
|
const VideoManager = __webpack_require__(/*! ./video-manager */ "./src/room/video-manager.js");
|
|
const UserListUtil = __webpack_require__(/*! ./user-list-util */ "./src/room/user-list-util.js");
|
|
const QuickPoll = __webpack_require__(/*! ./quick-poll */ "./src/room/quick-poll.js");
|
|
|
|
let options;
|
|
|
|
function __activityAVIcon(elem, selector, predicate, onfunc, disabledfunc) {
|
|
const icon = elem.find(selector);
|
|
if (predicate()) {
|
|
icon.show();
|
|
const on = onfunc()
|
|
, disabled = disabledfunc();
|
|
if (disabled) {
|
|
icon.addClass('disabled');
|
|
} else {
|
|
icon.removeClass('disabled');
|
|
if (on) {
|
|
icon.addClass('enabled');
|
|
} else {
|
|
icon.removeClass('enabled');
|
|
}
|
|
}
|
|
icon.attr('title', icon.data(on ? 'on' :'off'));
|
|
} else {
|
|
icon.hide();
|
|
}
|
|
return icon;
|
|
}
|
|
function __activityIcon(elem, selector, predicate, action, confirm) {
|
|
let icon = elem.find(selector);
|
|
if (predicate()) {
|
|
if (icon.length === 0) {
|
|
icon = OmUtil.tmpl('#user-actions-stub ' + selector);
|
|
elem.append(icon);
|
|
}
|
|
icon.off();
|
|
if (confirm) {
|
|
icon.confirmation(confirm);
|
|
} else {
|
|
icon.click(action);
|
|
}
|
|
} else {
|
|
icon.hide();
|
|
}
|
|
}
|
|
function __rightIcon(c, elem, rights, selector, predicate) {
|
|
const self = c.uid === options.uid
|
|
, hasRight = UserListUtil.hasRight(rights, c.rights);
|
|
let icon = elem.find(selector);
|
|
if (predicate() && !UserListUtil.hasRight('SUPER_MODERATOR', c.rights) && (
|
|
(self && options.questions && !hasRight)
|
|
|| (!self && UserListUtil.hasRight('MODERATOR'))
|
|
)) {
|
|
if (icon.length === 0) {
|
|
icon = OmUtil.tmpl('#user-actions-stub ' + selector);
|
|
elem.append(icon);
|
|
}
|
|
if (hasRight) {
|
|
icon.addClass('granted');
|
|
} else {
|
|
icon.removeClass('granted')
|
|
}
|
|
icon.attr('title', icon.data(self ? 'request' : (hasRight ? 'revoke' : 'grant')));
|
|
icon.off().click(function() {
|
|
OmUtil.roomAction({action: 'toggleRight', right: rights[0], uid: c.uid});
|
|
});
|
|
} else {
|
|
icon.remove();
|
|
}
|
|
}
|
|
function __rightAudioIcon(c, elem) {
|
|
__rightIcon(c, elem, ['AUDIO'], '.right.audio', () => true);
|
|
}
|
|
function __rightVideoIcon(c, elem) {
|
|
__rightIcon(c, elem, ['VIDEO'], '.right.camera', () => !options.audioOnly);
|
|
}
|
|
function __rightOtherIcons(c, elem) {
|
|
__rightIcon(c, elem, ['PRESENTER'], '.right.presenter', () => !options.interview && $('.wb-area').is(':visible'));
|
|
__rightIcon(c, elem, ['WHITEBOARD', 'PRESENTER'], '.right.wb', () => !options.interview && $('.wb-area').is(':visible'));
|
|
__rightIcon(c, elem, ['SHARE'], '.right.screen-share', () => true);
|
|
__rightIcon(c, elem, ['REMOTE_CONTROL'], '.right.remote-control', () => true);
|
|
__rightIcon(c, elem, ['MODERATOR'], '.right.moderator', () => true);
|
|
}
|
|
function __setStatus(c, le) {
|
|
const status = le.find('.user-status')
|
|
, mode = c.level == 5 ? 'mod' : (c.level == 3 ? 'wb' : 'user');
|
|
status.removeClass('mod wb user');
|
|
status.attr('title', status.data(mode)).addClass(mode);
|
|
le.data('level', c.level);
|
|
}
|
|
function __updateCount() {
|
|
$('#room-sidebar-users-tab .user-count').text($('#room-sidebar-tab-users .user-list .users .user.entry').length);
|
|
}
|
|
function __sortUserList() {
|
|
const container = $('#room-sidebar-tab-users .user-list .users');
|
|
container.find('.user.entry').sort((_u1, _u2) => {
|
|
const u1 = $(_u1)
|
|
, u2 = $(_u2);
|
|
return u2.data('level') - u1.data('level') || u1.attr('title').localeCompare(u2.attr('title'));
|
|
}).appendTo(container);
|
|
}
|
|
|
|
|
|
function _getClient(uid) {
|
|
return $('#user' + uid);
|
|
}
|
|
function _addClient(_clients) {
|
|
if (!options) {
|
|
return; //too early
|
|
}
|
|
const clients = Array.isArray(_clients) ? _clients : [_clients];
|
|
clients.forEach(c => {
|
|
const self = c.uid === options.uid;
|
|
let le = _getClient(c.uid);
|
|
if (le.length === 0) {
|
|
le = OmUtil.tmpl('#user-entry-stub', 'user' + c.uid);
|
|
le.attr('id', 'user' + c.uid)
|
|
.attr('data-userid', c.user.id)
|
|
.attr('data-uid', c.uid);
|
|
if (self) {
|
|
le.addClass('current');
|
|
}
|
|
$('#room-sidebar-tab-users .user-list .users').append(le);
|
|
}
|
|
_updateClient(c);
|
|
});
|
|
__updateCount();
|
|
__sortUserList();
|
|
}
|
|
function _updateClient(c) {
|
|
if (!options) {
|
|
return; //too early
|
|
}
|
|
const self = c.uid === options.uid
|
|
, le = _getClient(c.uid)
|
|
, selfCamStream = c.streams.find(s => s.type === 'WEBCAM')
|
|
, hasAudio = VideoUtil.hasMic(self && selfCamStream ? selfCamStream : c)
|
|
, hasVideo = VideoUtil.hasCam(self && selfCamStream ? selfCamStream : c)
|
|
, speaks = le.find('.audio-activity');
|
|
if (le.length === 0) {
|
|
return;
|
|
}
|
|
__setStatus(c, le);
|
|
if (hasVideo || hasAudio) {
|
|
if (le.find('.restart').length === 0) {
|
|
le.prepend(OmUtil.tmpl('#user-av-restart').click(function () {
|
|
VideoManager.refresh(c.uid);
|
|
}));
|
|
}
|
|
} else {
|
|
le.find('.restart').remove();
|
|
}
|
|
speaks.hide().removeClass('clickable').attr('title', speaks.data('speaks')).off();
|
|
if (hasAudio) {
|
|
speaks.show();
|
|
if(UserListUtil.hasRight('MUTE_OTHERS')) {
|
|
speaks.addClass('clickable').click(function () {
|
|
VideoManager.clickMuteOthers(c.uid);
|
|
}).attr('title', speaks.attr('title') + speaks.data('mute'));
|
|
}
|
|
}
|
|
le.attr('title', c.user.displayName)
|
|
.css('background-image', 'url(' + c.user.pictureUri + ')')
|
|
.find('.user.name').text(c.user.displayName);
|
|
|
|
if (c.user.id !== -1) {
|
|
const actions = le.find('.user.actions');
|
|
__rightVideoIcon(c, actions);
|
|
__rightAudioIcon(c, actions);
|
|
__rightOtherIcons(c, actions);
|
|
__activityIcon(actions, '.kick'
|
|
, () => !self && UserListUtil.hasRight('MODERATOR') && !UserListUtil.hasRight('SUPER_MODERATOR', c.rights)
|
|
, null
|
|
, {
|
|
confirmationEvent: 'om-kick'
|
|
, placement: Settings.isRtl ? 'left' : 'right'
|
|
, onConfirm: () => OmUtil.roomAction({action: 'kick', uid: c.uid})
|
|
});
|
|
__activityIcon(actions, '.private-chat'
|
|
, () => options.userId !== c.user.id && $('#chatPanel').is(':visible')
|
|
, function() {
|
|
Chat.addTab('chatTab-u' + c.user.id, c.user.displayName);
|
|
Chat.open();
|
|
$('#chatMessage .wysiwyg-editor').click();
|
|
});
|
|
}
|
|
if (self) {
|
|
options.rights = c.rights;
|
|
QuickPoll.setRights();
|
|
options.activities = c.activities;
|
|
const header = $('#room-sidebar-tab-users .header');
|
|
header.find('.om-icon.settings').off().click(VideoSettings.open);
|
|
__rightVideoIcon(c, header);
|
|
__activityAVIcon(
|
|
header
|
|
, '.activity.cam'
|
|
, () => !options.audioOnly && UserListUtil.hasRight(VideoUtil.CAM_ACTIVITY)
|
|
, () => hasVideo
|
|
, () => Settings.load().video.cam < 0)
|
|
.off().click(function() {
|
|
VideoManager.toggleActivity(VideoUtil.CAM_ACTIVITY);
|
|
});;
|
|
__rightAudioIcon(c, header);
|
|
__activityAVIcon(
|
|
header
|
|
, '.activity.mic', () => UserListUtil.hasRight(VideoUtil.MIC_ACTIVITY)
|
|
, () => hasAudio
|
|
, () => Settings.load().video.mic < 0)
|
|
.off().click(function() {
|
|
VideoManager.toggleActivity(VideoUtil.MIC_ACTIVITY);
|
|
});
|
|
__rightOtherIcons(c, header);
|
|
}
|
|
VideoManager.update(c)
|
|
}
|
|
|
|
module.exports = {
|
|
init: function(opts) {
|
|
options = opts;
|
|
UserListUtil.init(opts);
|
|
}
|
|
, addClient: _addClient
|
|
, updateClient: function(c) {
|
|
_updateClient(c);
|
|
__sortUserList();
|
|
}
|
|
, removeClient: function(uid) {
|
|
_getClient(uid).remove();
|
|
__updateCount();
|
|
}
|
|
, removeOthers: function() {
|
|
const selfUid = options.uid;
|
|
$('.user-list .user.entry').each(function() {
|
|
const c = $(this);
|
|
if (c.data('uid') !== selfUid) {
|
|
c.remove();
|
|
}
|
|
});
|
|
__updateCount();
|
|
}
|
|
, getClient: _getClient
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./src/room/user-settings.js":
|
|
/*!***********************************!*\
|
|
!*** ./src/room/user-settings.js ***!
|
|
\***********************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
const Settings = __webpack_require__(/*! ../main/settings */ "../main/settings");
|
|
const Chat = __webpack_require__(/*! ../chat/chat */ "../chat/chat");
|
|
const VideoSettings = __webpack_require__(/*! ../settings/settings */ "../settings/settings");
|
|
|
|
function __initMuteOthers() {
|
|
let s = VideoSettings.load();
|
|
$('#muteOthersAsk')
|
|
.prop('checked', s.video.confirmMuteOthers)
|
|
.off().click(function() {
|
|
s = VideoSettings.load();
|
|
s.video.confirmMuteOthers = !$('#muteOthersAsk').prop('checked');
|
|
VideoSettings.save();
|
|
});
|
|
}
|
|
function __initChat() {
|
|
let s = Settings.load();
|
|
$('#chatNotify')
|
|
.prop('checked', s.chat.muted)
|
|
.off().click(function() {
|
|
s = Settings.load();
|
|
s.chat.muted = !$('#chatNotify').prop('checked');
|
|
Settings.save(s);
|
|
Chat.reload();
|
|
});
|
|
$('#sendOnCtrlEnter')
|
|
.prop('checked', s.chat.sendOn === Chat.SEND_CTRL)
|
|
.off().click(function() {
|
|
s = Settings.load();
|
|
s.chat.sendOn = $('#sendOnCtrlEnter').prop('checked') ? Chat.SEND_CTRL : Chat.SEND_ENTER;
|
|
Settings.save(s);
|
|
Chat.reload();
|
|
});
|
|
}
|
|
function __initVideo() {
|
|
const resolutions = $('#video-settings .cam-resolution').clone();
|
|
let s = VideoSettings.load();
|
|
resolutions
|
|
.change(function() {
|
|
const o = resolutions.find('option:selected').data();
|
|
s.fixed.width = o.width;
|
|
s.fixed.height = o.height;
|
|
VideoSettings.save();
|
|
})
|
|
.find('option').each(function() {
|
|
const o = $(this).data();
|
|
if (o.width === s.fixed.width && o.height === s.fixed.height) {
|
|
$(this).prop('selected', true);
|
|
return false;
|
|
}
|
|
});
|
|
$('#video-sizes-container')
|
|
.html('')
|
|
.append(resolutions.prop('disabled', !s.fixed.enabled));
|
|
$('#fixedVideoPod')
|
|
.prop('checked', s.fixed.enabled)
|
|
.off().click(function() {
|
|
s = VideoSettings.load();
|
|
s.fixed.enabled = $('#fixedVideoPod').prop('checked');
|
|
resolutions.prop('disabled', !s.fixed.enabled)
|
|
VideoSettings.save();
|
|
});
|
|
}
|
|
function _open() {
|
|
__initMuteOthers();
|
|
__initChat();
|
|
__initVideo();
|
|
$('#room-local-settings').modal('show');
|
|
}
|
|
|
|
module.exports = {
|
|
open: _open
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./src/room/video-manager-util.js":
|
|
/*!****************************************!*\
|
|
!*** ./src/room/video-manager-util.js ***!
|
|
\****************************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
const OmUtil = __webpack_require__(/*! ../main/omutils */ "../main/omutils");
|
|
const VideoUtil = __webpack_require__(/*! ../settings/video-util */ "../settings/video-util");
|
|
const VideoSettings = __webpack_require__(/*! ../settings/settings */ "../settings/settings");
|
|
|
|
let share;
|
|
|
|
function __savePod(v) {
|
|
const opts = Room.getOptions();
|
|
if (!opts.interview && v && v.find('video').length > 0 && v.data('clientType') === 'WEBCAM' && v.dialog('instance')) {
|
|
const userUI = $(`#user${v.data('clientUid')}`)
|
|
, widget = v.dialog('widget');
|
|
userUI.data('video-pod', {
|
|
x: widget.css('left')
|
|
, y: widget.css('top')
|
|
, w: widget.css('width')
|
|
, h: widget.css('height')
|
|
});
|
|
}
|
|
}
|
|
function _closeV(v) {
|
|
if (!v || v.length < 1) {
|
|
return;
|
|
}
|
|
__savePod(v);
|
|
if (v.dialog('instance') !== undefined) {
|
|
v.dialog('destroy');
|
|
}
|
|
v.parents('.pod').remove();
|
|
v.remove();
|
|
WbArea.updateAreaClass();
|
|
}
|
|
function _clickMuteOthers(uid) {
|
|
const s = VideoSettings.load();
|
|
if (false !== s.video.confirmMuteOthers) {
|
|
const dlg = $('#muteothers-confirm');
|
|
dlg.dialog({
|
|
appendTo: ".room-container"
|
|
, buttons: [
|
|
{
|
|
text: dlg.data('btn-ok')
|
|
, click: function() {
|
|
s.video.confirmMuteOthers = !$('#muteothers-confirm-dont-show').prop('checked');
|
|
VideoSettings.save();
|
|
OmUtil.roomAction({action: 'muteOthers', uid: uid});
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
, {
|
|
text: dlg.data('btn-cancel')
|
|
, click: function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
]
|
|
})
|
|
} else {
|
|
OmUtil.roomAction({action: 'muteOthers', uid: uid});
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
init: (_share) => {
|
|
share = _share;
|
|
}
|
|
, sendMessage: (_m) => {
|
|
OmUtil.sendMessage(_m, {type: 'kurento'});
|
|
}
|
|
, savePod: __savePod
|
|
, closeV: _closeV
|
|
, close: (uid, showShareBtn) => {
|
|
const v = $('#' + VideoUtil.getVid(uid));
|
|
if (v.length === 1) {
|
|
_closeV(v);
|
|
}
|
|
if (!showShareBtn && uid === share.data('uid')) {
|
|
share.off().hide();
|
|
}
|
|
}
|
|
, clickMuteOthers: _clickMuteOthers
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./src/room/video-manager.js":
|
|
/*!***********************************!*\
|
|
!*** ./src/room/video-manager.js ***!
|
|
\***********************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
const OmUtil = __webpack_require__(/*! ../main/omutils */ "../main/omutils");
|
|
const VideoUtil = __webpack_require__(/*! ../settings/video-util */ "../settings/video-util");
|
|
const VideoSettings = __webpack_require__(/*! ../settings/settings */ "../settings/settings");
|
|
|
|
let share, inited = false;
|
|
const VideoMgrUtil = __webpack_require__(/*! ./video-manager-util */ "./src/room/video-manager-util.js");
|
|
const Video = __webpack_require__(/*! ./video */ "./src/room/video.js");
|
|
const Sharer = __webpack_require__(/*! ./sharer */ "./src/room/sharer.js");
|
|
|
|
function _onVideoResponse(m) {
|
|
const w = $('#' + VideoUtil.getVid(m.uid))
|
|
, v = w.data();
|
|
if (v) {
|
|
v.processSdpAnswer(m.sdpAnswer);
|
|
}
|
|
}
|
|
function _onBroadcast(msg) {
|
|
const sd = msg.stream
|
|
, uid = sd.uid;
|
|
if (Array.isArray(msg.cleanup)) {
|
|
msg.cleanup.forEach(function(_cuid) {
|
|
VideoMgrUtil.close(_cuid);
|
|
});
|
|
}
|
|
$('#' + VideoUtil.getVid(uid)).remove();
|
|
new Video(msg);
|
|
OmUtil.log(uid + ' registered in room');
|
|
}
|
|
function _onShareUpdated(msg) {
|
|
const sd = msg.stream
|
|
, uid = sd.uid
|
|
, w = $('#' + VideoUtil.getVid(uid))
|
|
, v = w.data();
|
|
if (v && (VideoUtil.isSharing(sd) || VideoUtil.isRecording(sd))) {
|
|
// Update activities in the current data object
|
|
v.stream().activities = sd.activities;
|
|
}
|
|
Sharer.setShareState(VideoUtil.isSharing(sd) ? Sharer.SHARE_STARTED : Sharer.SHARE_STOPPED);
|
|
Sharer.setRecState(VideoUtil.isRecording(sd) ? Sharer.SHARE_STARTED : Sharer.SHARE_STOPPED);
|
|
}
|
|
function _onReceive(msg) {
|
|
const uid = msg.stream.uid;
|
|
VideoMgrUtil.closeV($('#' + VideoUtil.getVid(uid)));
|
|
new Video(msg);
|
|
OmUtil.log(uid + ' receiving video');
|
|
}
|
|
function _onKMessage(m) {
|
|
switch (m.id) {
|
|
case 'clientLeave':
|
|
$(`${VideoUtil.VID_SEL}[data-client-uid="${m.uid}"]`).each(function() {
|
|
VideoMgrUtil.closeV($(this));
|
|
});
|
|
if (share.data('cuid') === m.uid) {
|
|
share.off().hide();
|
|
}
|
|
break;
|
|
case 'broadcastStopped':
|
|
VideoMgrUtil.close(m.uid, false);
|
|
break;
|
|
case 'broadcast':
|
|
_onBroadcast(m);
|
|
break;
|
|
case 'videoResponse':
|
|
_onVideoResponse(m);
|
|
break;
|
|
case 'iceCandidate':
|
|
{
|
|
const w = $('#' + VideoUtil.getVid(m.uid))
|
|
, v = w.data();
|
|
if (v) {
|
|
v.processIceCandidate(m.candidate);
|
|
}
|
|
}
|
|
break;
|
|
case 'newStream':
|
|
_play([m.stream], m.iceServers);
|
|
break;
|
|
case 'shareUpdated':
|
|
_onShareUpdated(m);
|
|
break;
|
|
case 'error':
|
|
OmUtil.error(m.message);
|
|
break;
|
|
default:
|
|
//no-op
|
|
}
|
|
}
|
|
function _onWsMessage(_, msg) {
|
|
try {
|
|
if (msg instanceof Blob) {
|
|
return; //ping
|
|
}
|
|
const m = JSON.parse(msg);
|
|
if (!m) {
|
|
return;
|
|
}
|
|
if ('kurento' === m.type && 'test' !== m.mode) {
|
|
OmUtil.info('Received message: ' + msg);
|
|
_onKMessage(m);
|
|
} else if ('mic' === m.type) {
|
|
switch (m.id) {
|
|
case 'activity':
|
|
_userSpeaks(m.uid, m.active);
|
|
break;
|
|
default:
|
|
//no-op
|
|
}
|
|
}
|
|
} catch (err) {
|
|
OmUtil.error(err);
|
|
}
|
|
}
|
|
function _init() {
|
|
Wicket.Event.subscribe('/websocket/message', _onWsMessage);
|
|
VideoSettings.init(Room.getOptions());
|
|
share = $('.room-block .room-container').find('.btn.shared');
|
|
VideoMgrUtil.init(share);
|
|
inited = true;
|
|
$(window).on('keydown.push-to-talk', {enable: true}, _onPtt);
|
|
$(window).on('keyup.push-to-talk', {enable: false}, _onPtt);
|
|
}
|
|
function _update(c) {
|
|
if (!inited) {
|
|
return;
|
|
}
|
|
const streamMap = {};
|
|
c.streams.forEach(function(sd) {
|
|
streamMap[sd.uid] = sd.uid;
|
|
sd.self = c.self;
|
|
sd.cam = c.cam;
|
|
sd.mic = c.mic;
|
|
if (VideoUtil.isSharing(sd) || VideoUtil.isRecording(sd)) {
|
|
return;
|
|
}
|
|
const _id = VideoUtil.getVid(sd.uid)
|
|
, av = VideoUtil.hasMic(sd) || VideoUtil.hasCam(sd)
|
|
, v = $('#' + _id);
|
|
if (av && v.length === 1) {
|
|
v.data().update(sd);
|
|
} else if (!av && v.length === 1) {
|
|
VideoMgrUtil.closeV(v);
|
|
}
|
|
});
|
|
if (c.uid === Room.getOptions().uid) {
|
|
$(VideoUtil.VID_SEL).each(function() {
|
|
$(this).data().setRights(c.rights);
|
|
});
|
|
}
|
|
$(`[data-client-uid="${c.cuid}"]`).each(function() {
|
|
const sd = $(this).data().stream();
|
|
if (!streamMap[sd.uid]) {
|
|
//not-inited/invalid video window
|
|
VideoMgrUtil.closeV($(this));
|
|
}
|
|
});
|
|
}
|
|
function _playSharing(sd, iceServers) {
|
|
const m = {stream: sd, iceServers: iceServers}
|
|
, v = $('#' + VideoUtil.getVid(sd.uid))
|
|
if (v.length === 1) {
|
|
v.remove();
|
|
}
|
|
new Video(m);
|
|
VideoUtil.setPos(v, {left: 0, top: 35});
|
|
}
|
|
function _play(streams, iceServers) {
|
|
if (!inited) {
|
|
return;
|
|
}
|
|
streams.forEach(function(sd) {
|
|
const m = {stream: sd, iceServers: iceServers};
|
|
if (VideoUtil.isSharing(sd)) {
|
|
VideoUtil.highlight(share
|
|
.attr('title', share.data('user') + ' ' + sd.user.firstName + ' ' + sd.user.lastName + ' ' + share.data('text'))
|
|
.data('uid', sd.uid)
|
|
.data('cuid', sd.cuid)
|
|
.show()
|
|
, 'btn-outline-warning', 10);
|
|
share.tooltip().off().click(function() {
|
|
_playSharing(sd, iceServers);
|
|
});
|
|
if (Room.getOptions().autoOpenSharing === true) {
|
|
_playSharing(sd, iceServers);
|
|
}
|
|
} else if (VideoUtil.isRecording(sd)) {
|
|
return;
|
|
} else {
|
|
_onReceive(m);
|
|
}
|
|
});
|
|
}
|
|
function _find(uid) {
|
|
return $(`${VideoUtil.VID_SEL}[data-client-uid="${uid}"][data-client-type="WEBCAM"]`);
|
|
}
|
|
function _userSpeaks(uid, active) {
|
|
const u = $(`#user${uid} .audio-activity`)
|
|
, v = _find(uid).parent();
|
|
if (active) {
|
|
u.addClass('speaking');
|
|
v.addClass('user-speaks')
|
|
} else {
|
|
u.removeClass('speaking');
|
|
v.removeClass('user-speaks')
|
|
}
|
|
}
|
|
function _refresh(uid, opts) {
|
|
const v = _find(uid);
|
|
if (v.length > 0) {
|
|
v.data().refresh(opts);
|
|
}
|
|
}
|
|
function _mute(uid, mute) {
|
|
const v = _find(uid);
|
|
if (v.length > 0) {
|
|
v.data().mute(mute);
|
|
}
|
|
}
|
|
function _muteOthers(uid) {
|
|
$(VideoUtil.VID_SEL).each(function() {
|
|
const w = $(this), v = w.data(), v2 = w.data('client-uid');
|
|
if (v && v2) {
|
|
v.mute(uid !== v2);
|
|
}
|
|
});
|
|
}
|
|
function _toggleActivity(activity) {
|
|
VideoMgrUtil.sendMessage({
|
|
id: 'toggleActivity'
|
|
, activity: activity
|
|
});
|
|
}
|
|
function _onPtt(e) {
|
|
if ((e.ctrlKey || e.metaKey) && 'Space' === e.code) {
|
|
const v = _find(Room.getOptions().uid);
|
|
if (v.length > 0 && v.data()) {
|
|
v.data().pushToTalk(e.data.enable);
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
init: _init
|
|
, update: _update
|
|
, play: _play
|
|
, refresh: _refresh
|
|
, mute: _mute
|
|
, muteOthers: _muteOthers
|
|
, toggleActivity: _toggleActivity
|
|
, destroy: function() {
|
|
$(window).off('keydown.push-to-talk');
|
|
$(window).off('keyup.push-to-talk');
|
|
Wicket.Event.unsubscribe('/websocket/message', _onWsMessage);
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./src/room/video.js":
|
|
/*!***************************!*\
|
|
!*** ./src/room/video.js ***!
|
|
\***************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
const OmUtil = __webpack_require__(/*! ../main/omutils */ "../main/omutils");
|
|
const VideoUtil = __webpack_require__(/*! ../settings/video-util */ "../settings/video-util");
|
|
const MicLevel = __webpack_require__(/*! ../settings/mic-level */ "../settings/mic-level");
|
|
const WebRtcPeer = __webpack_require__(/*! ../settings/WebRtcPeer */ "../settings/WebRtcPeer");
|
|
const VideoSettings = __webpack_require__(/*! ../settings/settings */ "../settings/settings");
|
|
|
|
const AudioCtx = window.AudioContext || window.webkitAudioContext;
|
|
const VideoMgrUtil = __webpack_require__(/*! ./video-manager-util */ "./src/room/video-manager-util.js");
|
|
const Sharer = __webpack_require__(/*! ./sharer */ "./src/room/sharer.js");
|
|
const Volume = __webpack_require__(/*! ./volume */ "./src/room/volume.js");
|
|
|
|
module.exports = class Video {
|
|
constructor(msg) {
|
|
const states = [], self = this, vidSize = {};
|
|
let sd, v, vc, t, footer, size, vol, iceServers
|
|
, lm, level, userSpeaks = false, muteOthers
|
|
, hasVideo, isSharing, isRecording;
|
|
|
|
function __getState() {
|
|
const state = states.length > 0 ? states[0] : null;
|
|
if (!state || state.disposed) {
|
|
return null;
|
|
}
|
|
return state;
|
|
}
|
|
function __getVideo(_state) {
|
|
const vid = self.video(_state);
|
|
return vid && vid.length > 0 ? vid[0] : null;
|
|
}
|
|
function _resizeDlgArea(_w, _h) {
|
|
if (Room.getOptions().interview) {
|
|
VideoUtil.setPos(v, VideoUtil.getPos());
|
|
} else if (v.dialog('instance')) {
|
|
v.dialog('option', 'width', _w).dialog('option', 'height', _h);
|
|
}
|
|
}
|
|
function _micActivity(speaks) {
|
|
if (speaks !== userSpeaks) {
|
|
userSpeaks = speaks;
|
|
OmUtil.sendMessage({type: 'mic', id: 'activity', active: speaks});
|
|
}
|
|
}
|
|
function _getScreenStream(msg, state, callback) {
|
|
function __handleScreenError(err) {
|
|
VideoMgrUtil.sendMessage({id: 'errorSharing'});
|
|
Sharer.setShareState(Sharer.SHARE_STOPPED);
|
|
Sharer.setRecState(Sharer.SHARE_STOPPED);
|
|
OmUtil.error(err);
|
|
}
|
|
const b = VideoUtil.browser;
|
|
let promise, cnts;
|
|
if (VideoUtil.isEdge() && b.major > 16) {
|
|
cnts = {
|
|
video: true
|
|
};
|
|
promise = navigator.getDisplayMedia(cnts);
|
|
} else if (VideoUtil.sharingSupported()) {
|
|
cnts = {
|
|
video: true
|
|
};
|
|
if (VideoUtil.isSafari()) {
|
|
promise = new Promise((resolve) => {
|
|
VideoUtil.askPermission(resolve);
|
|
}).then(() => navigator.mediaDevices.getDisplayMedia(cnts));
|
|
} else {
|
|
promise = navigator.mediaDevices.getDisplayMedia(cnts);
|
|
}
|
|
} else {
|
|
promise = new Promise(() => {
|
|
Sharer.close();
|
|
throw 'Screen-sharing is not supported in ' + b.name + '[' + b.major + ']';
|
|
});
|
|
}
|
|
promise.then(stream => {
|
|
if (!state.disposed) {
|
|
__createVideo(state);
|
|
state.stream = stream;
|
|
callback(msg, state, cnts);
|
|
}
|
|
}).catch(__handleScreenError);
|
|
}
|
|
function _getVideoStream(msg, state, callback) {
|
|
VideoSettings.constraints(sd, function(cnts) {
|
|
if (VideoUtil.hasCam(sd) !== cnts.videoEnabled || VideoUtil.hasMic(sd) !== cnts.audioEnabled) {
|
|
VideoMgrUtil.sendMessage({
|
|
id : 'devicesAltered'
|
|
, uid: sd.uid
|
|
, audio: cnts.audioEnabled
|
|
, video: cnts.videoEnabled
|
|
});
|
|
}
|
|
if (!cnts.audio && !cnts.video) {
|
|
OmUtil.error('Requested devices are not available');
|
|
VideoMgrUtil.close(sd.uid)
|
|
return;
|
|
}
|
|
navigator.mediaDevices.getUserMedia(cnts)
|
|
.then(stream => {
|
|
if (state.disposed || msg.instanceUid !== v.data('instance-uid')) {
|
|
return;
|
|
}
|
|
stream.getVideoTracks().forEach(track => track.enabled = cnts.videoEnabled);
|
|
stream.getAudioTracks().forEach(track => track.enabled = cnts.audioEnabled);
|
|
state.localStream = stream;
|
|
if (__pttEnabled(state)) {
|
|
OmUtil.alert('warning', $('#user-video').data('ptt-info'), 10000);
|
|
}
|
|
let _stream = stream;
|
|
const data = {};
|
|
if (stream.getAudioTracks().length !== 0) {
|
|
lm = vc.find('.level-meter');
|
|
lm.show();
|
|
data.aCtx = new AudioCtx();
|
|
data.gainNode = data.aCtx.createGain();
|
|
data.analyser = data.aCtx.createAnalyser();
|
|
data.aSrc = data.aCtx.createMediaStreamSource(stream);
|
|
data.aSrc.connect(data.gainNode);
|
|
data.gainNode.connect(data.analyser);
|
|
if (VideoUtil.isEdge()) {
|
|
data.analyser.connect(data.aCtx.destination);
|
|
} else {
|
|
data.aDest = data.aCtx.createMediaStreamDestination();
|
|
data.analyser.connect(data.aDest);
|
|
_stream = data.aDest.stream;
|
|
stream.getVideoTracks().forEach(track => _stream.addTrack(track));
|
|
}
|
|
}
|
|
state.data = data;
|
|
__createVideo(state);
|
|
state.stream = _stream;
|
|
callback(msg, state, cnts);
|
|
})
|
|
.catch(function(err) {
|
|
VideoMgrUtil.sendMessage({
|
|
id : 'devicesAltered'
|
|
, uid: sd.uid
|
|
, audio: false
|
|
, video: false
|
|
});
|
|
VideoMgrUtil.close(sd.uid);
|
|
if ('NotReadableError' === err.name) {
|
|
OmUtil.error('Camera/Microphone is busy and can\'t be used');
|
|
} else {
|
|
OmUtil.error(err);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
function __connectionStateChangeListener(state) {
|
|
const pc = state.data.rtcPeer.pc;
|
|
console.warn(`!!RTCPeerConnection state changed: ${pc.connectionState}, user: ${sd.user.displayName}, uid: ${sd.uid}`);
|
|
switch(pc.connectionState) {
|
|
case "connected":
|
|
if (sd.self) {
|
|
// The connection has become fully connected
|
|
OmUtil.alert('info', `Connection to Media server has been established`, 3000);//notify user
|
|
}
|
|
break;
|
|
case "disconnected":
|
|
case "failed":
|
|
//connection has been dropped
|
|
OmUtil.alert('warning', `Media server connection for user ${sd.user.displayName} is ${pc.connectionState}, will try to re-connect`, 3000);//notify user
|
|
_refresh();
|
|
break;
|
|
case "closed":
|
|
// The connection has been closed
|
|
break;
|
|
}
|
|
}
|
|
function __createSendPeer(msg, state, cnts) {
|
|
state.options = {
|
|
mediaStream: state.stream
|
|
, mediaConstraints: cnts
|
|
, onIceCandidate: self.onIceCandidate
|
|
, onConnectionStateChange: () => __connectionStateChangeListener(state)
|
|
};
|
|
const vid = __getVideo(state);
|
|
VideoUtil.playSrc(vid, state.stream, true);
|
|
|
|
const data = state.data;
|
|
data.rtcPeer = new WebRtcPeer.Sendonly(VideoUtil.addIceServers(state.options, msg));
|
|
if (data.analyser) {
|
|
level = new MicLevel();
|
|
level.meter(data.analyser, lm, _micActivity, OmUtil.error);
|
|
}
|
|
data.rtcPeer.createOffer()
|
|
.then(sdpOffer => {
|
|
data.rtcPeer.processLocalOffer(sdpOffer);
|
|
OmUtil.log('Invoking Sender SDP offer callback function');
|
|
const bmsg = {
|
|
id : 'broadcastStarted'
|
|
, uid: sd.uid
|
|
, sdpOffer: sdpOffer.sdp
|
|
}, vtracks = state.stream.getVideoTracks();
|
|
if (vtracks && vtracks.length > 0) {
|
|
const vts = vtracks[0].getSettings();
|
|
vidSize.width = vts.width;
|
|
vidSize.height = vts.height;
|
|
bmsg.width = vts.width;
|
|
bmsg.height = vts.height;
|
|
bmsg.fps = vts.frameRate;
|
|
}
|
|
VideoMgrUtil.sendMessage(bmsg);
|
|
if (isSharing) {
|
|
Sharer.setShareState(Sharer.SHARE_STARTED);
|
|
}
|
|
if (isRecording) {
|
|
Sharer.setRecState(Sharer.SHARE_STARTED);
|
|
}
|
|
})
|
|
.catch(error => OmUtil.error(error));
|
|
}
|
|
function _createSendPeer(msg, state) {
|
|
if (isSharing || isRecording) {
|
|
_getScreenStream(msg, state, __createSendPeer);
|
|
} else {
|
|
_getVideoStream(msg, state, __createSendPeer);
|
|
}
|
|
}
|
|
function _createResvPeer(msg, state) {
|
|
__createVideo(state);
|
|
const options = VideoUtil.addIceServers({
|
|
mediaConstraints: {audio: true, video: true}
|
|
, onIceCandidate : self.onIceCandidate
|
|
, onConnectionStateChange: () => __connectionStateChangeListener(state)
|
|
}, msg);
|
|
const data = state.data;
|
|
data.rtcPeer = new WebRtcPeer.Recvonly(options);
|
|
data.rtcPeer.createOffer()
|
|
.then(sdpOffer => {
|
|
data.rtcPeer.processLocalOffer(sdpOffer);
|
|
OmUtil.log('Invoking Receiver SDP offer callback function');
|
|
VideoMgrUtil.sendMessage({
|
|
id : 'addListener'
|
|
, sender: sd.uid
|
|
, sdpOffer: sdpOffer.sdp
|
|
});
|
|
})
|
|
.catch(genErr => OmUtil.error('Receiver sdp offer error ' + genErr));
|
|
}
|
|
function _handleMicStatus(state) {
|
|
if (!footer || !footer.is(':visible')) {
|
|
return;
|
|
}
|
|
if (state) {
|
|
footer.text(footer.data('on'));
|
|
footer.addClass('mic-on');
|
|
t.addClass('mic-on');
|
|
} else {
|
|
footer.text(footer.data('off'));
|
|
footer.removeClass('mic-on');
|
|
t.removeClass('mic-on');
|
|
}
|
|
}
|
|
function _initContainer(_id, name, opts, instanceUid) {
|
|
let contSel = '#user' + sd.cuid;
|
|
const _hasVideo = VideoUtil.hasVideo(sd)
|
|
if (_hasVideo) {
|
|
const s = VideoSettings.load();
|
|
if (s.fixed.enabled && !opts.interview && !isSharing) {
|
|
size = {
|
|
width: s.fixed.width
|
|
, height: s.fixed.height
|
|
};
|
|
} else {
|
|
size = {
|
|
width: sd.width
|
|
, height: sd.height
|
|
};
|
|
}
|
|
} else {
|
|
size = {
|
|
width: 120
|
|
, height: 90
|
|
};
|
|
}
|
|
hasVideo = _hasVideo || $(contSel).length < 1;
|
|
if (hasVideo) {
|
|
if (opts.interview) {
|
|
const area = $('.pod-area');
|
|
const contId = crypto.randomUUID();
|
|
contSel = '#' + contId;
|
|
area.append($('<div class="pod"></div>').attr('id', contId));
|
|
WbArea.updateAreaClass();
|
|
} else {
|
|
contSel = '.room-block .room-container';
|
|
}
|
|
}
|
|
$(contSel).append(OmUtil.tmpl('#user-video', _id)
|
|
.attr('title', name)
|
|
.attr('data-client-uid', sd.cuid)
|
|
.attr('data-client-type', sd.type)
|
|
.attr('data-instance-uid', instanceUid)
|
|
.data(self));
|
|
v = $('#' + _id);
|
|
vc = v.find('.video');
|
|
muteOthers = vc.find('.mute-others');
|
|
_setRights();
|
|
return contSel;
|
|
}
|
|
function _initDialog(v, opts) {
|
|
if (opts.interview) {
|
|
v.dialog('option', 'draggable', false);
|
|
v.dialog('option', 'resizable', false);
|
|
$('.pod-area').sortable('refresh');
|
|
} else {
|
|
v.dialog('option', 'draggable', true);
|
|
v.dialog('option', 'resizable', true);
|
|
if (isSharing) {
|
|
v.on('dialogclose', function() {
|
|
VideoMgrUtil.close(sd.uid, true);
|
|
});
|
|
}
|
|
const ui = v.closest('.ui-dialog');
|
|
const parent = $('.room-block .room-container .sb-wb');
|
|
ui.draggable('option', 'containment', parent);
|
|
ui.resizable('option', 'containment', parent);
|
|
}
|
|
_initDialogBtns(opts);
|
|
}
|
|
function _initDialogBtns(opts) {
|
|
function noDblClick(elem) {
|
|
elem.dblclick(function(e) {
|
|
e.stopImmediatePropagation();
|
|
return false;
|
|
});
|
|
}
|
|
v.parent().find('.ui-dialog-titlebar-close').remove();
|
|
v.parent().append(OmUtil.tmpl('#video-button-bar'));
|
|
const refresh = v.parent().find('.btn-refresh')
|
|
, tgl = v.parent().find('.btn-toggle')
|
|
, cls = v.parent().find('.btn-wclose');
|
|
if (isSharing) {
|
|
cls.click(function (_) {
|
|
v.dialog('close');
|
|
return false;
|
|
});
|
|
noDblClick(cls);
|
|
refresh.remove();
|
|
} else {
|
|
cls.remove();
|
|
refresh.click(function(e) {
|
|
e.stopImmediatePropagation();
|
|
_refresh();
|
|
return false;
|
|
});
|
|
}
|
|
if (opts.interview) {
|
|
tgl.remove();
|
|
} else {
|
|
tgl.click(function (e) {
|
|
e.stopImmediatePropagation();
|
|
$(this).toggleClass('minimized');
|
|
v.toggle();
|
|
return false;
|
|
});
|
|
noDblClick(tgl);
|
|
}
|
|
}
|
|
function _update(_c) {
|
|
const prevA = sd.activities
|
|
, prevW = vidSize.width || sd.width // try to check actual size of video first
|
|
, prevH = vidSize.height || sd.height // try to check actual size of video first
|
|
, prevCam = sd.cam
|
|
, prevMic = sd.mic;
|
|
sd.activities = _c.activities.sort();
|
|
sd.level = _c.level;
|
|
sd.user.firstName = _c.user.firstName;
|
|
sd.user.lastName = _c.user.lastName;
|
|
sd.user.displayName = _c.user.displayName;
|
|
sd.width = _c.width;
|
|
sd.height = _c.height;
|
|
sd.cam = _c.cam;
|
|
sd.mic = _c.mic;
|
|
const name = sd.user.displayName;
|
|
if (hasVideo) {
|
|
v.dialog('option', 'title', name).parent().find('.ui-dialog-titlebar').attr('title', name);
|
|
}
|
|
const same = prevA.length === sd.activities.length
|
|
&& prevA.every(function(value, index) { return value === sd.activities[index]})
|
|
&& prevW === sd.width && prevH === sd.height
|
|
&& prevCam == sd.cam && prevMic === sd.mic;
|
|
const camChanged = sd.camEnabled !== _c.camEnabled
|
|
, micChanged = sd.micEnabled !== _c.micEnabled
|
|
if (sd.self && !same) {
|
|
_cleanup();
|
|
v.remove();
|
|
_init({stream: sd, iceServers: iceServers});
|
|
} else if (camChanged || micChanged) {
|
|
sd.micEnabled = _c.micEnabled;
|
|
sd.camEnabled = _c.camEnabled;
|
|
const state = __getState();
|
|
if (camChanged) {
|
|
VideoMgrUtil.savePod(v);
|
|
v.off();
|
|
if (v.dialog('instance')) {
|
|
v.dialog('destroy');
|
|
}
|
|
v.remove();
|
|
__initUI(v.data('instance-uid'));
|
|
__createVideo(state);
|
|
VideoUtil.playSrc(state.video[0], state.stream || state.rStream, sd.self);
|
|
if (state.data.analyser) {
|
|
lm = vc.find('.level-meter');
|
|
level.setCanvas(lm);
|
|
}
|
|
}
|
|
if (micChanged) {
|
|
__updateVideo(state);
|
|
}
|
|
if (sd.self) {
|
|
state.localStream.getVideoTracks().forEach(track => track.enabled = sd.camEnabled);
|
|
state.localStream.getAudioTracks().forEach(track => track.enabled = sd.micEnabled);
|
|
}
|
|
}
|
|
}
|
|
function __createVideo(state) {
|
|
const _id = VideoUtil.getVid(sd.uid);
|
|
_resizeDlgArea(size.width, size.height);
|
|
if (hasVideo && !isSharing && !isRecording) {
|
|
// let's try to restore size+position
|
|
const opts = Room.getOptions()
|
|
, stored = $(`#user${sd.cuid}`).data('video-pod');
|
|
if (!opts.interview && stored) {
|
|
const widget = v.dialog('widget');
|
|
widget.css('left', stored.x);
|
|
widget.css('top', stored.y)
|
|
widget.css('width', stored.w);
|
|
widget.css('height', stored.h)
|
|
} else {
|
|
VideoUtil.setPos(v, VideoUtil.getPos(VideoUtil.getRects(VideoUtil.VIDWIN_SEL, _id), sd.width, sd.height + 25));
|
|
}
|
|
}
|
|
state.video = $(hasVideo ? '<video>' : '<audio>').attr('id', 'vid' + _id)
|
|
.attr('playsinline', 'playsinline')
|
|
//.attr('autoplay', 'autoplay')
|
|
.prop('controls', false)
|
|
.width(vc.width()).height(vc.height());
|
|
if (state.data) {
|
|
state.video.data(state.data);
|
|
}
|
|
if (hasVideo) {
|
|
vc.removeClass('audio-only').css('background-image', '');
|
|
vc.parents('.ui-dialog').removeClass('audio-only');
|
|
state.video.attr('poster', sd.user.pictureUri);
|
|
} else {
|
|
state.video.attr('poster', null);
|
|
vc.addClass('audio-only');
|
|
}
|
|
vc.append(state.video);
|
|
__updateVideo(state);
|
|
}
|
|
function __updateVideo(state) {
|
|
if (VideoUtil.hasMic(sd)) {
|
|
const volIco = vol.create(self)
|
|
if (hasVideo) {
|
|
v.parent().find('.buttonpane').append(volIco);
|
|
} else {
|
|
volIco.addClass('ulist-small');
|
|
volIco.insertAfter('#user' + sd.cuid + ' .typing-activity');
|
|
}
|
|
} else {
|
|
vol.destroy();
|
|
}
|
|
}
|
|
function _refresh(_msg) {
|
|
const msg = _msg || {
|
|
iceServers: iceServers
|
|
, instanceUid: v.length > 0 ? v.data('instance-uid') : undefined
|
|
};
|
|
if (sd.self) {
|
|
VideoMgrUtil.sendMessage({
|
|
id : 'broadcastRestarted'
|
|
, uid: sd.uid
|
|
});
|
|
}
|
|
_cleanup();
|
|
const hasAudio = VideoUtil.hasMic(sd)
|
|
, state = {
|
|
disposed: false
|
|
, data: {}
|
|
};
|
|
states.push(state);
|
|
if (sd.self) {
|
|
_createSendPeer(msg, state);
|
|
} else {
|
|
_createResvPeer(msg, state);
|
|
}
|
|
_handleMicStatus(hasAudio);
|
|
}
|
|
function _setRights() {
|
|
if (Room.hasRight(['MUTE_OTHERS']) && VideoUtil.hasMic(sd)) {
|
|
muteOthers.addClass('enabled').off().click(function() {
|
|
VideoMgrUtil.clickMuteOthers(sd.cuid);
|
|
});
|
|
} else {
|
|
muteOthers.removeClass('enabled').off();
|
|
}
|
|
}
|
|
function _cleanData(data) {
|
|
if (!data) {
|
|
return;
|
|
}
|
|
if (data.analyser) {
|
|
VideoUtil.disconnect(data.analyser);
|
|
data.analyser = null;
|
|
}
|
|
if (data.gainNode) {
|
|
VideoUtil.disconnect(data.gainNode);
|
|
data.gainNode = null;
|
|
}
|
|
if (data.aSrc) {
|
|
VideoUtil.cleanStream(data.aSrc.mediaStream);
|
|
VideoUtil.disconnect(data.aSrc);
|
|
data.aSrc = null;
|
|
}
|
|
if (data.aDest) {
|
|
VideoUtil.disconnect(data.aDest);
|
|
data.aDest = null;
|
|
}
|
|
if (data.aCtx) {
|
|
if (data.aCtx.destination) {
|
|
VideoUtil.disconnect(data.aCtx.destination);
|
|
}
|
|
if ('closed' !== data.aCtx.state) {
|
|
try {
|
|
data.aCtx.close();
|
|
} catch(e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
data.aCtx = null;
|
|
}
|
|
VideoUtil.cleanPeer(data.rtcPeer);
|
|
data.rtcPeer = null;
|
|
}
|
|
function _cleanup(evt) {
|
|
VideoMgrUtil.savePod(v);
|
|
delete vidSize.width;
|
|
delete vidSize.height;
|
|
OmUtil.log('!!Disposing participant ' + sd.uid);
|
|
let state;
|
|
while(state = states.pop()) {
|
|
state.disposed = true;
|
|
if (state.options) {
|
|
delete state.options.mediaConstraints;
|
|
delete state.options.onIceCandidate;
|
|
state.options = null;
|
|
}
|
|
_cleanData(state.data);
|
|
VideoUtil.cleanStream(state.localStream);
|
|
VideoUtil.cleanStream(state.stream);
|
|
VideoUtil.cleanStream(state.rStream);
|
|
state.data = null;
|
|
state.localStream = null;
|
|
state.stream = null;
|
|
const video = state.video;
|
|
if (video && video.length > 0) {
|
|
video.attr('id', 'dummy');
|
|
const vidNode = video[0];
|
|
VideoUtil.cleanStream(vidNode.srcObject);
|
|
vidNode.srcObject = null;
|
|
vidNode.load();
|
|
vidNode.removeAttribute("src");
|
|
vidNode.removeAttribute("srcObject");
|
|
vidNode.parentNode.removeChild(vidNode);
|
|
state.video.data({});
|
|
state.video = null;
|
|
}
|
|
}
|
|
if (lm && lm.length > 0) {
|
|
_micActivity(false);
|
|
lm.hide();
|
|
muteOthers.removeClass('enabled').off();
|
|
}
|
|
if (level) {
|
|
level.dispose();
|
|
level = null;
|
|
}
|
|
vc.find('audio,video').remove();
|
|
vol.destroy();
|
|
if (evt && evt.target) {
|
|
$(evt).off();
|
|
}
|
|
}
|
|
function _reattachStream() {
|
|
states.forEach(state => {
|
|
if (state.video && state.video.length > 0) {
|
|
const data = state.data
|
|
, videoEl = state.video[0];
|
|
if (data.rtcPeer && (!videoEl.srcObject || !videoEl.srcObject.active)) {
|
|
videoEl.srcObject = data.rtcPeer.stream;
|
|
}
|
|
}
|
|
});
|
|
}
|
|
function _processSdpAnswer(answer) {
|
|
const state = __getState();
|
|
if (!state || !state.data.rtcPeer) {
|
|
return;
|
|
}
|
|
state.data.rtcPeer.processRemoteAnswer(answer)
|
|
.then(() => {
|
|
const video = __getVideo(state);
|
|
state.rStream = state.data.rtcPeer.pc.getRemoteStreams()[0];
|
|
VideoUtil.playSrc(video, state.rStream, false);
|
|
})
|
|
.catch(error => OmUtil.error(error, true));
|
|
}
|
|
function _processIceCandidate(candidate) {
|
|
const state = __getState();
|
|
if (!state || !state.data.rtcPeer) {
|
|
return;
|
|
}
|
|
state.data.rtcPeer.addIceCandidate(candidate)
|
|
.catch(error => OmUtil.error('Error adding candidate: ' + error, true));
|
|
}
|
|
function __initUI(instanceUid) {
|
|
if (!vol) {
|
|
vol = new Volume();
|
|
}
|
|
isSharing = VideoUtil.isSharing(sd);
|
|
isRecording = VideoUtil.isRecording(sd);
|
|
const _id = VideoUtil.getVid(sd.uid)
|
|
, name = sd.user.displayName
|
|
, _w = sd.width
|
|
, _h = sd.height
|
|
, opts = Room.getOptions();
|
|
sd.self = sd.cuid === opts.uid;
|
|
const contSel = _initContainer(_id, name, opts, instanceUid);
|
|
footer = v.find('.footer');
|
|
if (!opts.showMicStatus) {
|
|
footer.hide();
|
|
}
|
|
if (!sd.self && isSharing) {
|
|
Sharer.close();
|
|
}
|
|
if (sd.self && (isSharing || isRecording)) {
|
|
v.hide();
|
|
} else if (hasVideo) {
|
|
v.dialog({
|
|
classes: {
|
|
'ui-dialog': 'video user-video' + (opts.showMicStatus ? ' mic-status' : '')
|
|
, 'ui-dialog-titlebar': '' + (opts.showMicStatus ? ' ui-state-highlight' : '')
|
|
}
|
|
, width: _w
|
|
, minWidth: 40
|
|
, minHeight: 50
|
|
, autoOpen: true
|
|
, modal: false
|
|
, appendTo: contSel
|
|
});
|
|
_initDialog(v, opts);
|
|
}
|
|
t = v.parent().find('.ui-dialog-titlebar').attr('title', name);
|
|
v.on('remove', _cleanup);
|
|
if (hasVideo) {
|
|
vc.width(_w).height(_h);
|
|
}
|
|
}
|
|
function _init(_msg) {
|
|
sd = _msg.stream;
|
|
sd.activities = sd.activities.sort();
|
|
_msg.instanceUid = crypto.randomUUID();
|
|
iceServers = _msg.iceServers;
|
|
__initUI(_msg.instanceUid);
|
|
_refresh(_msg);
|
|
}
|
|
function __pttEnabled(state) {
|
|
return sd && sd.self && state && state.localStream
|
|
&& VideoUtil.hasActivity(sd, VideoUtil.MIC_ACTIVITY) && !sd.micEnabled;
|
|
}
|
|
|
|
this.update = _update;
|
|
this.refresh = _refresh;
|
|
this.pushToTalk = (enable) => {
|
|
const state = __getState();
|
|
if (__pttEnabled(state)) {
|
|
state.localStream.getAudioTracks().forEach(track => track.enabled = enable);
|
|
const classes = document.querySelector('#room-sidebar-tab-users .header .om-icon.activity.mic.clickable').classList;
|
|
if (enable) {
|
|
classes.add('push-to-talk');
|
|
} else {
|
|
classes.remove('push-to-talk');
|
|
}
|
|
}
|
|
};
|
|
this.mute = function(_mute) {
|
|
vol.mute(_mute);
|
|
};
|
|
this.isMuted = function() {
|
|
return vol.muted();
|
|
};
|
|
this.stream = function() { return sd; };
|
|
this.setRights = _setRights;
|
|
this.processSdpAnswer = _processSdpAnswer;
|
|
this.processIceCandidate = _processIceCandidate;
|
|
this.onIceCandidate = function(candidate) {
|
|
const opts = Room.getOptions();
|
|
OmUtil.log('Local candidate ' + JSON.stringify(candidate));
|
|
VideoMgrUtil.sendMessage({
|
|
id: 'onIceCandidate'
|
|
, candidate: candidate
|
|
, uid: sd.uid
|
|
, luid: sd.self ? sd.uid : opts.uid
|
|
});
|
|
};
|
|
this.reattachStream = _reattachStream;
|
|
this.video = function(_state) {
|
|
const state = _state || __getState();
|
|
if (!state || state.disposed) {
|
|
return null;
|
|
}
|
|
return state.video;
|
|
};
|
|
this.handleMicStatus = _handleMicStatus;
|
|
|
|
_init(msg);
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "./src/room/volume.js":
|
|
/*!****************************!*\
|
|
!*** ./src/room/volume.js ***!
|
|
\****************************/
|
|
/***/ ((module, __unused_webpack_exports, __webpack_require__) => {
|
|
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
const OmUtil = __webpack_require__(/*! ../main/omutils */ "../main/omutils");
|
|
|
|
module.exports = class Volume {
|
|
constructor() {
|
|
const self = this;
|
|
let video, vol, drop, slider, handleEl, hideTimer = null
|
|
, lastVolume = 50, muted = false;
|
|
|
|
function __cancelHide() {
|
|
if (hideTimer) {
|
|
clearTimeout(hideTimer);
|
|
hideTimer = null;
|
|
}
|
|
}
|
|
function __hideDrop() {
|
|
__cancelHide();
|
|
hideTimer = setTimeout(() => {
|
|
drop.hide();
|
|
hideTimer = null;
|
|
}, 3000);
|
|
}
|
|
|
|
this.create = (_video) => {
|
|
video = _video;
|
|
this.destroy();
|
|
const uid = video.stream().uid
|
|
, cuid = video.stream().cuid
|
|
, volId = 'volume-' + uid;
|
|
vol = OmUtil.tmpl('#volume-control-stub', volId)
|
|
slider = vol.find('.slider');
|
|
drop = vol.find('.dropdown-menu');
|
|
vol.on('mouseenter', function(e) {
|
|
e.stopImmediatePropagation();
|
|
drop.show();
|
|
__hideDrop()
|
|
})
|
|
.click(function(e) {
|
|
e.stopImmediatePropagation();
|
|
OmUtil.roomAction({action: 'mute', uid: cuid, mute: !muted});
|
|
self.mute(!muted);
|
|
drop.hide();
|
|
return false;
|
|
}).dblclick(function(e) {
|
|
e.stopImmediatePropagation();
|
|
return false;
|
|
});
|
|
drop.on('mouseenter', function() {
|
|
__cancelHide();
|
|
});
|
|
drop.on('mouseleave', function() {
|
|
__hideDrop();
|
|
});
|
|
handleEl = vol.find('.handle');
|
|
slider.slider({
|
|
orientation: 'vertical'
|
|
, range: 'min'
|
|
, min: 0
|
|
, max: 100
|
|
, value: lastVolume
|
|
, create: function() {
|
|
handleEl.text($(this).slider('value'));
|
|
}
|
|
, slide: function(event, ui) {
|
|
self.handle(ui.value);
|
|
}
|
|
});
|
|
this.handle(lastVolume);
|
|
this.mute(muted);
|
|
return vol;
|
|
};
|
|
this.handle = (val) => {
|
|
handleEl.text(val);
|
|
const vidEl = video.video()
|
|
, data = vidEl.data();
|
|
if (video.stream().self) {
|
|
if (data.gainNode) {
|
|
data.gainNode.gain.value = val / 100;
|
|
}
|
|
} else {
|
|
vidEl[0].volume = val / 100;
|
|
}
|
|
const ico = vol.find('a');
|
|
if (val > 0 && ico.hasClass('volume-off')) {
|
|
ico.toggleClass('volume-off volume-on');
|
|
video.handleMicStatus(true);
|
|
} else if (val === 0 && ico.hasClass('volume-on')) {
|
|
ico.toggleClass('volume-on volume-off');
|
|
video.handleMicStatus(false);
|
|
}
|
|
};
|
|
this.mute = (mute) => {
|
|
if (!slider) {
|
|
return;
|
|
}
|
|
muted = mute;
|
|
if (mute) {
|
|
const val = slider.slider('option', 'value');
|
|
if (val > 0) {
|
|
lastVolume = val;
|
|
}
|
|
slider.slider('option', 'value', 0);
|
|
this.handle(0);
|
|
} else {
|
|
slider.slider('option', 'value', lastVolume);
|
|
this.handle(lastVolume);
|
|
}
|
|
};
|
|
this.destroy = () => {
|
|
if (vol) {
|
|
vol.remove();
|
|
vol = null;
|
|
}
|
|
};
|
|
this.muted = () => {
|
|
return muted;
|
|
};
|
|
}
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../chat/chat":
|
|
/*!***********************!*\
|
|
!*** external "Chat" ***!
|
|
\***********************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = Chat;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../wb/wb-area":
|
|
/*!*****************************!*\
|
|
!*** external "DrawWbArea" ***!
|
|
\*****************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = DrawWbArea;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../wb/interview-area":
|
|
/*!**********************************!*\
|
|
!*** external "InterviewWbArea" ***!
|
|
\**********************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = InterviewWbArea;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../settings/mic-level":
|
|
/*!***************************!*\
|
|
!*** external "MicLevel" ***!
|
|
\***************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = MicLevel;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../main/omutils":
|
|
/*!*************************!*\
|
|
!*** external "OmUtil" ***!
|
|
\*************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = OmUtil;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../main/settings":
|
|
/*!***************************!*\
|
|
!*** external "Settings" ***!
|
|
\***************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = Settings;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../settings/settings":
|
|
/*!********************************!*\
|
|
!*** external "VideoSettings" ***!
|
|
\********************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = VideoSettings;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../settings/video-util":
|
|
/*!****************************!*\
|
|
!*** external "VideoUtil" ***!
|
|
\****************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = VideoUtil;
|
|
|
|
/***/ }),
|
|
|
|
/***/ "../settings/WebRtcPeer":
|
|
/*!*****************************!*\
|
|
!*** external "WebRtcPeer" ***!
|
|
\*****************************/
|
|
/***/ ((module) => {
|
|
|
|
"use strict";
|
|
module.exports = WebRtcPeer;
|
|
|
|
/***/ })
|
|
|
|
/******/ });
|
|
/************************************************************************/
|
|
/******/ // The module cache
|
|
/******/ var __webpack_module_cache__ = {};
|
|
/******/
|
|
/******/ // The require function
|
|
/******/ function __webpack_require__(moduleId) {
|
|
/******/ // Check if module is in cache
|
|
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
|
/******/ if (cachedModule !== undefined) {
|
|
/******/ return cachedModule.exports;
|
|
/******/ }
|
|
/******/ // Create a new module (and put it into the cache)
|
|
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
/******/ // no module.id needed
|
|
/******/ // no module.loaded needed
|
|
/******/ exports: {}
|
|
/******/ };
|
|
/******/
|
|
/******/ // Execute the module function
|
|
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
|
/******/
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
/******/
|
|
/************************************************************************/
|
|
var __webpack_exports__ = {};
|
|
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
|
|
(() => {
|
|
/*!***************************!*\
|
|
!*** ./src/room/index.js ***!
|
|
\***************************/
|
|
/* Licensed under the Apache License, Version 2.0 (the "License") http://www.apache.org/licenses/LICENSE-2.0 */
|
|
|
|
// Let's re-style jquery-ui dialogs and buttons
|
|
$.extend($.ui.dialog.prototype.options.classes, {
|
|
'ui-dialog': 'modal-content'
|
|
, 'ui-dialog-titlebar': 'modal-header'
|
|
, 'ui-dialog-title': 'modal-title'
|
|
, 'ui-dialog-titlebar-close': 'close'
|
|
, 'ui-dialog-content': 'modal-body'
|
|
, 'ui-dialog-buttonpane': 'modal-footer'
|
|
});
|
|
$.extend($.ui.button.prototype.options.classes, {
|
|
'ui-button': 'btn btn-outline-secondary'
|
|
});
|
|
|
|
Object.assign(window, {
|
|
VideoManager: __webpack_require__(/*! ./video-manager */ "./src/room/video-manager.js")
|
|
, Sharer: __webpack_require__(/*! ./sharer */ "./src/room/sharer.js")
|
|
, Room: __webpack_require__(/*! ./room */ "./src/room/room.js")
|
|
, Activities: __webpack_require__(/*! ./activities */ "./src/room/activities.js")
|
|
, UserSettings: __webpack_require__(/*! ./user-settings */ "./src/room/user-settings.js")
|
|
});
|
|
|
|
})();
|
|
|
|
/******/ })()
|
|
;
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QSxLQUFLO0FBQ0w7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxJQUFJO0FBQ0osSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUNsSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FDL0NBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUIsbUJBQW1CO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FB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LHFCQUFxQixLQUFLLG1CQUFtQixpQ0FBaUM7QUFDL0k7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTixLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNENBQTRDLHNDQUFzQztBQUNsRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsbUNBQW1DO0FBQzlDLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsUUFBUTtBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUNodEJBO0FBQ0EsZUFBZSxtQkFBTyxDQUFDLHdDQUFpQjs7QUFFeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSx3QkFBd0Isd0NBQXdDO0FBQ2hFO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDdEhBOzs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7OztBQ0FBOzs7Ozs7Ozs7OztBQ0FBOzs7Ozs7VUNBQTtVQUNBOztVQUVBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBO1VBQ0E7VUFDQTtVQUNBOztVQUVBO1VBQ0E7O1VBRUE7VUFDQTtVQUNBOzs7Ozs7Ozs7QUN0QkE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBLGVBQWUsbUJBQU8sQ0FBQyxvREFBaUI7QUFDeEMsV0FBVyxtQkFBTyxDQUFDLHNDQUFVO0FBQzdCLFNBQVMsbUJBQU8sQ0FBQyxrQ0FBUTtBQUN6QixlQUFlLG1CQUFPLENBQUMsOENBQWM7QUFDckMsaUJBQWlCLG1CQUFPLENBQUMsb0RBQWlCO0FBQzFDLENBQUMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9vbS1mcm9udGVuZC8uL25vZGVfbW9kdWxlcy9ub3NsZWVwLmpzL3NyYy9pbmRleC5qcyIsIndlYnBhY2s6Ly9vbS1mcm9udGVuZC8uL25vZGVfbW9kdWxlcy9ub3NsZWVwLmpzL3NyYy9tZWRpYS5qcyIsIndlYnBhY2s6Ly9vbS1mcm9udGVuZC8uL3NyYy9yb29tL2FjdGl2aXRpZXMuanMiLCJ3ZWJwYWNrOi8vb20tZnJvbnRlbmQvLi9zcmMvcm9vbS9xdWljay1wb2xsLmpzIiwid2VicGFjazovL29tLWZyb250ZW5kLy4vc3JjL3Jvb20vcm9vbS5qcyIsIndlYnBhY2s6Ly9vbS1mcm9udGVuZC8uL3NyYy9yb29tL3NoYXJlci5qcyIsIndlYnBhY2s6Ly9vbS1mcm9udGVuZC8uL3NyYy9yb29tL3NpcC1kaWFsZXIuanMiLCJ3ZWJwYWNrOi8vb20tZnJvbnRlbmQvLi9zcmMvcm9vbS91c2VyLWxpc3QtdXRpbC5qcyIsIndlYnBhY2s6Ly9vbS1mcm9udGVuZC8uL3NyYy9yb29tL3VzZXItbGlzdC5qcyIsIndlYnBhY2s6Ly9vbS1mcm9udGVuZC8uL3NyYy9yb29tL3VzZXItc2V0dGluZ3MuanMiLCJ3ZWJwYWNrOi8vb20tZnJvbnRlbmQvLi9zcmMvcm9vbS92aWRlby1tYW5hZ2VyLXV0aWwuanMiLCJ3ZWJwYWNrOi8vb20tZnJvbnRlbmQvLi9zcmMvcm9vbS92aWRlby1tYW5hZ2VyLmpzIiwid2VicGFjazovL29tLWZyb250ZW5kLy4vc3JjL3Jvb20vdmlkZW8uanMiLCJ3ZWJwYWNrOi8vb20tZnJvbnRlbmQvLi9zcmMvcm9vbS92b2x1bWUuanMiLCJ3ZWJwYWNrOi8vb20tZnJvbnRlbmQvZXh0ZXJuYWwgdmFyIFwiQ2hhdFwiIiwid2VicGFjazovL29tLWZyb250ZW5kL2V4dGVybmFsIHZhciBcIkRyYXdXYkFyZWFcIiIsIndlYnBhY2s6Ly9vbS1mcm9udGVuZC9leHRlcm5hbCB2YXIgXCJJbnRlcnZpZXdXYkFyZWFcIiIsIndlYnBhY2s6Ly9vbS1mcm9udGVuZC9leHRlcm5hbCB2YXIgXCJNaWNMZXZlbFwiIiwid2VicGFjazovL29tLWZyb250ZW5kL2V4dGVybmFsIHZhciBcIk9tVXRpbFwiIiwid2VicGFjazovL29tLWZyb250ZW5kL2V4dGVybmFsIHZhciBcIlNldHRpbmdzXCIiLCJ3ZWJwYWNrOi8vb20tZnJvbnRlbmQvZXh0ZXJuYWwgdmFyIFwiVmlkZW9TZXR0aW5nc1wiIiwid2VicGFjazovL29tLWZyb250ZW5kL2V4dGVybmFsIHZhciBcIlZpZGVvVXRpbFwiIiwid2VicGFjazovL29tLWZyb250ZW5kL2V4dGVybmFsIHZhciBcIldlYlJ0Y1BlZXJcIiIsIndlYnBhY2s6Ly9vbS1mcm9udGVuZC93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly9vbS1mcm9udGVuZC8uL3NyYy9yb29tL2luZGV4LmpzIl0sInNvdXJjZXNDb250ZW50IjpbImNvbnN0IHsgd2VibSwgbXA0IH0gPSByZXF1aXJlKFwiLi9tZWRpYS5qc1wiKTtcblxuLy8gRGV0ZWN0IGlPUyBicm93c2VycyA8IHZlcnNpb24gMTBcbmNvbnN0IG9sZElPUyA9ICgpID0+XG4gIHR5cGVvZiBuYXZpZ2F0b3IgIT09IFwidW5kZWZpbmVkXCIgJiZcbiAgcGFyc2VGbG9hdChcbiAgICAoXG4gICAgICBcIlwiICtcbiAgICAgICgvQ1BVLipPUyAoWzAtOV9dezMsNH0pWzAtOV9dezAsMX18KENQVSBsaWtlKS4qQXBwbGVXZWJLaXQuKk1vYmlsZS9pLmV4ZWMoXG4gICAgICAgIG5hdmlnYXRvci51c2VyQWdlbnRcbiAgICAgICkgfHwgWzAsIFwiXCJdKVsxXVxuICAgIClcbiAgICAgIC5yZXBsYWNlKFwidW5kZWZpbmVkXCIsIFwiM18yXCIpXG4gICAgICAucmVwbGFjZShcIl9cIiwgXCIuXCIpXG4gICAgICAucmVwbGFjZShcIl9cIiwgXCJcIilcbiAgKSA8IDEwICYmXG4gICF3aW5kb3cuTVNTdHJlYW07XG5cbi8vIERldGVjdCBuYXRpdmUgV2FrZSBMb2NrIEFQSSBzdXBwb3J0XG5jb25zdCBuYXRpdmVXYWtlTG9jayA9ICgpID0+IFwid2FrZUxvY2tcIiBpbiBuYXZpZ2F0b3I7XG5cbmNsYXNzIE5vU2xlZXAge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmVuYWJsZWQgPSBmYWxzZTtcbiAgICBpZiAobmF0aXZlV2FrZUxvY2soKSkge1xuICAgICAgdGhpcy5fd2FrZUxvY2sgPSBudWxsO1xuICAgICAgY29uc3QgaGFuZGxlVmlzaWJpbGl0eUNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuX3dha2VMb2NrICE9PSBudWxsICYmIGRvY3VtZW50LnZpc2liaWxpdHlTdGF0ZSA9PT0gXCJ2aXNpYmxlXCIpIHtcbiAgICAgICAgICB0aGlzLmVuYWJsZSgpO1xuICAgICAgICB9XG4gICAgICB9O1xuICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcInZpc2liaWxpdHljaGFuZ2VcIiwgaGFuZGxlVmlzaWJpbGl0eUNoYW5nZSk7XG4gICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFwiZnVsbHNjcmVlbmNoYW5nZVwiLCBoYW5kbGVWaXNpYmlsaXR5Q2hhbmdlKTtcbiAgICB9IGVsc2UgaWYgKG9sZElPUygpKSB7XG4gICAgICB0aGlzLm5vU2xlZXBUaW1lciA9IG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFNldCB1cCBubyBzbGVlcCB2aWRlbyBlbGVtZW50XG4gICAgICB0aGlzLm5vU2xlZXBWaWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJ2aWRlb1wiKTtcblxuICAgICAgdGhpcy5ub1NsZWVwVmlkZW8uc2V0QXR0cmlidXRlKFwidGl0bGVcIiwgXCJObyBTbGVlcFwiKTtcbiAgICAgIHRoaXMubm9TbGVlcFZpZGVvLnNldEF0dHJpYnV0ZShcInBsYXlzaW5saW5lXCIsIFwiXCIpO1xuXG4gICAgICB0aGlzLl9hZGRTb3VyY2VUb1ZpZGVvKHRoaXMubm9TbGVlcFZpZGVvLCBcIndlYm1cIiwgd2VibSk7XG4gICAgICB0aGlzLl9hZGRTb3VyY2VUb1ZpZGVvKHRoaXMubm9TbGVlcFZpZGVvLCBcIm1wNFwiLCBtcDQpO1xuXG4gICAgICB0aGlzLm5vU2xlZXBWaWRlby5hZGRFdmVudExpc3RlbmVyKFwibG9hZGVkbWV0YWRhdGFcIiwgKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5ub1NsZWVwVmlkZW8uZHVyYXRpb24gPD0gMSkge1xuICAgICAgICAgIC8vIHdlYm0gc291cmNlXG4gICAgICAgICAgdGhpcy5ub1NsZWVwVmlkZW8uc2V0QXR0cmlidXRlKFwibG9vcFwiLCBcIlwiKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBtcDQgc291cmNlXG4gICAgICAgICAgdGhpcy5ub1NsZWVwVmlkZW8uYWRkRXZlbnRMaXN0ZW5lcihcInRpbWV1cGRhdGVcIiwgKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMubm9TbGVlcFZpZGVvLmN1cnJlbnRUaW1lID4gMC41KSB7XG4gICAgICAgICAgICAgIHRoaXMubm9TbGVlcFZpZGVvLmN1cnJlbnRUaW1lID0gTWF0aC5yYW5kb20oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgX2FkZFNvdXJjZVRvVmlkZW8oZWxlbWVudCwgdHlwZSwgZGF0YVVSSSkge1xuICAgIHZhciBzb3VyY2UgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic291cmNlXCIpO1xuICAgIHNvdXJjZS5zcmMgPSBkYXRhVVJJO1xuICAgIHNvdXJjZS50eXBlID0gYHZpZGVvLyR7dHlwZX1gO1xuICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoc291cmNlKTtcbiAgfVxuXG4gIGdldCBpc0VuYWJsZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuZW5hYmxlZDtcbiAgfVxuXG4gIGVuYWJsZSgpIHtcbiAgICBpZiAobmF0aXZlV2FrZUxvY2soKSkge1xuICAgICAgcmV0dXJuIG5hdmlnYXRvci53YWtlTG9ja1xuICAgICAgICAucmVxdWVzdChcInNjcmVlblwiKVxuICAgICAgICAudGhlbigod2FrZUxvY2spID0+IHtcbiAgICAgICAgICB0aGlzLl93YWtlTG9jayA9IHdha2VMb2NrO1xuICAgICAgICAgIHRoaXMuZW5hYmxlZCA9IHRydWU7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJXYWtlIExvY2sgYWN0aXZlLlwiKTtcbiAgICAgICAgICB0aGlzLl93YWtlTG9jay5hZGRFdmVudExpc3RlbmVyKFwicmVsZWFzZVwiLCAoKSA9PiB7XG4gICAgICAgICAgICAvLyBUb0RvOiBQb3RlbnRpYWxseSBlbWl0IGFuIGV2ZW50IGZvciB0aGUgcGFnZSB0byBvYnNlcnZlIHNpbmNlXG4gICAgICAgICAgICAvLyBXYWtlIExvY2sgcmVsZWFzZXMgaGFwcGVuIHdoZW4gcGFnZSB2aXNpYmlsaXR5IGNoYW5nZXMuXG4gICAgICAgICAgICAvLyAoaHR0cHM6Ly93ZWIuZGV2L3dha2Vsb2NrLyN3YWtlLWxvY2stbGlmZWN5Y2xlKVxuICAgICAgICAgICAgY29uc29sZS5sb2coXCJXYWtlIExvY2sgcmVsZWFzZWQuXCIpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgIHRoaXMuZW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYCR7ZXJyLm5hbWV9LCAke2Vyci5tZXNzYWdlfWApO1xuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChvbGRJT1MoKSkge1xuICAgICAgdGhpcy5kaXNhYmxlKCk7XG4gICAgICBjb25zb2xlLndhcm4oYFxuICAgICAgICBOb1NsZWVwIGVuYWJsZWQgZm9yIG9sZGVyIGlPUyBkZXZpY2VzLiBUaGlzIGNhbiBpbnRlcnJ1cHRcbiAgICAgICAgYWN0aXZlIG9yIGxvbmctcnVubmluZyBuZXR3b3JrIHJlcXVlc3RzIGZyb20gY29tcGxldGluZyBzdWNjZXNzZnVsbHkuXG4gICAgICAgIFNlZSBodHRwczovL2dpdGh1Yi5jb20vcmljaHRyL05vU2xlZXAuanMvaXNzdWVzLzE1IGZvciBtb3JlIGRldGFpbHMuXG4gICAgICBgKTtcbiAgICAgIHRoaXMubm9TbGVlcFRpbWVyID0gd2luZG93LnNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgaWYgKCFkb2N1bWVudC5oaWRkZW4pIHtcbiAgICAgICAgICB3aW5kb3cubG9jYXRpb24uaHJlZiA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmLnNwbGl0KFwiI1wiKVswXTtcbiAgICAgICAgICB3aW5kb3cuc2V0VGltZW91dCh3aW5kb3cuc3RvcCwgMCk7XG4gICAgICAgIH1cbiAgICAgIH0sIDE1MDAwKTtcbiAgICAgIHRoaXMuZW5hYmxlZCA9IHRydWU7XG4gICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBwbGF5UHJvbWlzZSA9IHRoaXMubm9TbGVlcFZpZGVvLnBsYXkoKTtcbiAgICAgIHJldHVybiBwbGF5UHJvbWlzZVxuICAgICAgICAudGhlbigocmVzKSA9PiB7XG4gICAgICAgICAgdGhpcy5lbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgIHRoaXMuZW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICAgIHRocm93IGVycjtcbiAgICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgZGlzYWJsZSgpIHtcbiAgICBpZiAobmF0aXZlV2FrZUxvY2soKSkge1xuICAgICAgaWYgKHRoaXMuX3dha2VMb2NrKSB7XG4gICAgICAgIHRoaXMuX3dha2VMb2NrLnJlbGVhc2UoKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuX3dha2VMb2NrID0gbnVsbDtcbiAgICB9IGVsc2UgaWYgKG9sZElPUygpKSB7XG4gICAgICBpZiAodGhpcy5ub1NsZWVwVGltZXIpIHtcbiAgICAgICAgY29uc29sZS53YXJuKGBcbiAgICAgICAgICBOb1NsZWVwIG5vdyBkaXNhYmxlZCBmb3Igb2xkZXIgaU9TIGRldmljZXMuXG4gICAgICAgIGApO1xuICAgICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbCh0aGlzLm5vU2xlZXBUaW1lcik7XG4gICAgICAgIHRoaXMubm9TbGVlcFRpbWVyID0gbnVsbDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5ub1NsZWVwVmlkZW8ucGF1c2UoKTtcbiAgICB9XG4gICAgdGhpcy5lbmFibGVkID0gZmFsc2U7XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBOb1NsZWVwO1xuIiwibW9kdWxlLmV4cG9ydHMgPSB7XG4gIHdlYm06XG4gICAgXCJkYXRhOnZpZGVvL3dlYm07YmFzZTY0LEdrWGZvd0VBQUFBQUFBQWZRb2FCQVVMM2dRRkM4b0VFUXZPQkNFS0NoSGRsWW0xQ2g0RUVRb1dCQWhoVGdHY0JBQUFBQUFBVmtoRk5tM1JBTEUyN2kxT3JoQlZKcVdaVHJJSGZUYnVNVTZ1RUZsU3VhMU9zZ2dFd1RidU1VNnVFSEZPN2ExT3NnaFYxN0FFQUFBQUFBQUNrQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBVlNhbG1BUUFBQUFBQUFFVXExN0dERDBKQVRZQ05UR0YyWmpVMUxqTXpMakV3TUZkQmpVeGhkbVkxTlM0ek15NHhNREJ6cEpCbHJyWGYzRENEVkI4S2NnYk1wY3IrUkltSVFKQmdBQUFBQUFBV1ZLNXJBUUFBQUFBQUQrK3VBUUFBQUFBQUFETFhnUUZ6eFlFQm5JRUFJcldjZzNWdVpJYUZWbDlXVURpRGdRRWo0NE9FQW1KYUFPQUJBQUFBQUFBQUJyQ0JzTHFCa0s0QkFBQUFBQUFQcTllQkFuUEZnUUtjZ1FBaXRaeURkVzVraG9oQlgxWlBVa0pKVTRPQkF1RUJBQUFBQUFBQUVaK0JBcldJUU9kd0FBQUFBQUJpWklFZ1k2SlBid0llVmdGMmIzSmlhWE1BQUFBQUFvQzdBQUFBQUFBQWdMVUJBQUFBQUFDNEFRTjJiM0ppYVhNdEFBQUFXR2x3YUM1UGNtY2diR2xpVm05eVltbHpJRWtnTWpBeE1ERXhNREVnS0ZOamFHRjFabVZ1ZFdkblpYUXBBUUFBQUJVQUFBQmxibU52WkdWeVBVeGhkbU0xTlM0MU1pNHhNRElCQlhadmNtSnBjeVZDUTFZQkFFQUFBQ1J6R0NwR3BYTVdoQkFhUWxBWjR4eEN6bXZzR1VKTUVZSWNNa3hieXlWemtDR2tvRUtJV3lpQjBKQlZBQUJBQUFDSFFYZ1VoSXBCQ0NHRUpUMVlrb01uUFFnaGhJZzVlQlNFYVVFSUlZUVFRZ2doaEJCQ0NDR0VSVGxva29NblFRZ2RoT013T0F5RDVUajRISVJGT1ZnUWd5ZEI2Q0NFRDBLNG1vT3NPUWdoaENRMVNGQ0RCam5vSElUQ0xDaUtnc1F3dUJhRUJEVW9qSUxrTU1qVWd3dENpSnFEU1RYNEdvUm5RWGdXaEdsQkNDR0VKRUZJa0lNR1FjZ1loRVpCV0pLREJqbTRGSVRMUWFnYWhDbzVDQitFSURSa0ZRQ1FBQUNnb2lpS29pZ0tFQnF5Q2dESUFBQVFRRkVVeDNFY3laRWN5YkVjQ3dnTldRVUFBQUVBQ0FBQW9FaUtwRWlPNUVpU0pGbVNKVm1TSlZtUzVvbXFMTXV5TE11eUxNc3lFQnF5Q2dCSUFBQlFVUXhGY1JRSENBMVpCUUJrQUFBSW9EaUtwVmlLcFdpSzU0aU9DSVNHckFJQWdBQUFCQUFBRURSRFV6eEhsRVRQVkZYWHRtM2J0bTNidG0zYnRtM2J0bTFibG1VWkNBMVpCUUJBQUFBUTBtbG1xUWFJTUFNWkJrSkRWZ0VBQ0FBQWdCR0tNTVNBMEpCVkFBQkFBQUNBR0VvT29nbXRPZCtjNDZCWkRwcEtzVGtkbkVpMWVaS2Jpcms1NTV4enpzbm1uREhPT2VlY29weFpESm9KclRubm5NU2dXUXFhQ2EwNTU1d25zWG5RbWlxdE9lZWNjYzdwWUp3Unhqbm5uQ2F0ZVpDYWpiVTU1NXdGcldtT21rdXhPZWVjU0xsNVVwdEx0VG5ubkhQT09lZWNjODQ1NTV6cXhla2NuQlBPT2VlY3FMMjVscHZReFRubm5FL0c2ZDZjRU00NTU1eHp6am5ubkhQT09lZWNJRFJrRlFBQUJBQkFFSWFOWWR3cENOTG5hQ0JHRVdJYU11bEI5K2d3Q1JxRG5FTHEwZWhvcEpRNkNDV1ZjVkpLSndnTldRVUFBQUlBUUFnaGhSUlNTQ0dGRkZKSUlZVVVZb2doaGhoeXlpbW5vSUpLS3Ftb29vd3l5eXl6ekRMTExMUE1PdXlzc3c0N0RESEVFRU1ycmNSU1UyMDExbGhyN2pubm1vTzBWbHBycmJWU1NpbWxsRklLUWtOV0FRQWdBQUFFUWdZWlpKQlJTQ0dGRkdLSUthZWNjZ29xcUlEUWtGVUFBQ0FBZ0FBQUFBQlA4aHpSRVIzUkVSM1JFUjNSRVIzUjhSelBFU1ZSRWlWUkVpM1RNalhUVTBWVmRXWFhsblZadDMxYjJJVmQ5MzNkOTMzZCtIVmhXSlpsV1pabFdaWmxXWlpsV1pabFdaWWdOR1FWQUFBQ0FBQWdoQkJDU0NHRkZGSklLY1lZYzh3NTZDU1VFQWdOV1FVQUFBSUFDQUFBQUhBVVIzRWN5WkVjU2JJa1M5SWt6ZElzVC9NMFR4TTlVUlJGMHpSVjBSVmRVVGR0VVRabDB6VmRVelpkVlZadFY1WnRXN1oxMjVkbDIvZDkzL2Q5My9kOTMvZDkzL2Q5WFFkQ1ExWUJBQklBQURxU0l5bVNJaW1TNHppT0pFbEFhTWdxQUVBR0FFQUFBSXJpS0k3ak9KSWtTWklsYVpKbmVaYW9tWnJwbVo0cXFrQm95Q29BQUJBQVFBQUFBQUFBQUlxbWVJcXBlSXFvZUk3b2lKSm9tWmFvcVpvcnlxYnN1cTdydXE3cnVxN3J1cTdydXE3cnVxN3J1cTdydXE3cnVxN3J1cTdydXE3cnVxNExoSWFzQWdBa0FBQjBKRWR5SkVkU0pFVlNKRWR5Z05DUVZRQ0FEQUNBQUFBY3d6RWtSWElzeTlJMFQvTTBUeE05MFJNOTAxTkZWM1NCMEpCVkFBQWdBSUFBQUFBQUFBQU15YkFVeTlFY1RSSWwxVkl0VlZNdDFWSkYxVk5WVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVk4welJORXdnTldRa0FrQUVBa0JCVExTM0dtZ21MSkdMU2FxdWdZd3hTN0tXeFNDcG50YmZLTVlVWXRWNGFoNVJSRUh1cEpHT0tRY3d0cE5BcEpxM1dWRUtGRktTWVl5b1ZVZzVTSURSa2hRQVFtZ0hnY0J4QXNpeEFzaXdBQUFBQUFBQUFrRFFOMER3UHNEUVBBQUFBQUFBQUFDUk5BeXhQQXpUUEF3QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUJBMGpSQTh6eEE4endBQUFBQUFBQUEwRHdQOER3UjhFUVJBQUFBQUFBQUFDelBBelRSQXp4UkJBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUJBMGpSQTh6eEE4endBQUFBQUFBQUFzRHdQOEVRUjBEd1JBQUFBQUFBQUFDelBBenhSQkR6UkF3QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFFQUFBRU9BQUFCQmdJUlFhc2lJQWlCTUFjRWdTSkFtU0JNMERTSllGVFlPbXdUUUJrbVZCMDZCcE1FMEFBQUFBQUFBQUFBQUFKRTJEcGtIVElJb0FTZE9nYWRBMGlDSUFBQUFBQUFBQUFBQUFrcVpCMDZCcEVFV0FwR25RTkdnYVJCRUFBQUFBQUFBQUFBQUF6elFoaWhCRm1DYkFNMDJJSWtRUnBna0FBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQ0FBQUdIQUFBQWd3b1F3VUdySWlBSWdUQUhBNGltVUJBSURqT0pZRkFBQ080MWdXQUFCWWxpV0tBQUJnV1pvb0FnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUlBQUFZY0FBQUNEQ2hEQlFhc2hJQWlBSUFjQ2lLWlFISHNTemdPSllGSk1teUFKWUYwRHlBcGdGRUVRQUlBQUFvY0FBQUNMQkJVMkp4Z0VKRFZnSUFVUUFBQnNXeExFMFRSWktrYVpvbmlpUkowenhQRkdtYTUzbWVhY0x6UE04MElZcWlhSm9RUlZFMFRaaW1hYW9xTUUxVkZRQUFVT0FBQUJCZ2c2YkU0Z0NGaHF3RUFFSUNBQnlLWWxtYTVubWVKNHFtcVpva1NkTThUeFJGMFRSTlUxVkprcVo1bmlpS29tbWFwcXF5TEUzelBGRVVSZE5VVlZXRnBubWVLSXFpYWFxcTZzTHpQRThVUmRFMFZkVjE0WG1lSjRxaWFKcXE2cm9RUlZFMFRkTlVUVlYxWFNDS3BtbWFxcXFxcmd0RVR4Uk5VMVZkMTNXQjU0bWlhYXFxcTdvdUVFM1RWRlZWZFYxWkJwaW1hYXFxNjhveVFGVlYxWFZkVjVZQnFxcXFydXU2c2d4UVZkZDFYVm1XWlFDdTY3cXlMTXNDQUFBT0hBQUFBb3lnazR3cWk3RFJoQXNQUUtFaEt3S0FLQUFBd0JpbUZGUEtNQ1locEJBYXhpU0VGRUltSmFYU1Vxb2dwRkpTS1JXRVZFb3FKYU9VVW1vcFZSQlNLYW1VQ2tJcUpaVlNBQURZZ1FNQTJJR0ZVR2pJU2dBZ0R3Q0FNRVlweGhoelRpS2tGR1BPT1NjUlVvb3g1NXlUU2pIbW5IUE9TU2taYzh3NTU2U1V6am5ubkhOU1N1YWNjODQ1S2FWenpqbm5uSlJTU3VlY2MwNUtLU1dFemtFbnBaVFNPZWVjRXdBQVZPQUFBQkJnbzhqbUJDTkJoWWFzQkFCU0FRQU1qbU5abXVaNW9taWFsaVJwbXVkNW5paWFwaVpKbXVaNW5pZUtxc256UEU4VVJkRTBWWlhuZVo0b2lxSnBxaXJYRlVYVE5FMVZWVjJ5TElxbWFacXE2cm93VGROVVZkZDFYWmltYWFxcTY3b3ViRnRWVmRWMVpSbTJyYXFxNnJxeURGelhkV1habG9Fc3U2N3MycklBQVBBRUJ3Q2dBaHRXUnpncEdnc3NOR1FsQUpBQkFFQVlnNUJDQ0NGbEVFSUtJWVNVVWdnSkFBQVljQUFBQ0RDaERCUWFzaElBU0FVQUFJeXgxbHBycmJYV1FHZXR0ZFphYTYyQXpGcHJyYlhXV211dHRkWmFhNjIxMWxKcnJiWFdXbXV0dGRaYWE2MjExbHBycmJYV1dtdXR0ZFphYTYyMTFscHJyYlhXV211dHRkWmFhNjIxMWxwcnJiWFdXbXN0cFpSU1NpbWxsRkpLS2FXVVVrb3BwWlJTU2dVQStsVTRBUGcvMkxBNndrblJXR0NoSVNzQmdIQUFBTUFZcFJoekRFSXBwVlFJTWVhY2RGUmFpN0ZDaURIbkpLVFVXbXpGYzg1QktDR1YxbUlzbm5NT1Fpa3B4VlpqVVNtRVVsSktMYlpZaTBxaG81SlNTcTNWV0l3eHFhVFdXb3V0eG1LTVNTbTAxRnFMTVJZamJFMnB0ZGhxcTdFWVkyc3FMYlFZWTR6RkNGOWtiQzJtMm1vTnhnZ2pXeXd0MVZwck1NWVkzVnVMcGJhYWl6RSsrTnBTTERIV1hBQUFkNE1EQUVTQ2pUT3NKSjBWamdZWEdySVNBQWdKQUNBUVVvb3h4aGh6empubnBGS01PZWFjY3c1Q0NLRlVpakhHbkhNT1FnZ2hsSXd4NXB4ekVFSUlJWVJTU3NhY2N4QkNDQ0dFa0ZMcW5ITVFRZ2doaEJCS0taMXpEa0lJSVlRUVFpbWxneEJDQ0NHRUVFb29wYVFVUWdnaGhCQkNDS21rbEVJSUlZUlNRaWdobFpSU0NDR0VFRUlwSmFTVVVnb2hoRkpDQ0tHRWxGSktLWVVRUWdpbGxKSlNTaW1sRWtvSkpZUVNVaWtwcFJSS0NDR1VVa3BLS2FWVVNnbWhoQkpLS1NXbGxGSktJWVFRU2lrRkFBQWNPQUFBQkJoQkp4bFZGbUdqQ1JjZWdFSkRWZ0lBWkFBQWtLS1VVaWt0UllJaXBSaWtHRXRHRlhOUVdvcW9jZ3hTemFsU3ppRG1KSmFJTVlTVWsxUXk1aFJDREVMcUhIVk1LUVl0bFJoQ3hoaWsySEpMb1hNT0FBQUFRUUNBZ0pBQUFBTUVCVE1Bd09BQTRYTVFkQUlFUnhzQWdDQkVab2hFdzBKd2VGQUpFQkZUQVVCaWdrSXVBRlJZWEtSZFhFQ1hBUzdvNHE0RElRUWhDRUVzRHFDQUJCeWNjTU1UYjNqQ0RVN1FLU3AxSUFBQUFBQUFEQUR3QUFDUVhBQVJFZEhNWVdSb2JIQjBlSHlBaElpTWtBZ0FBQUFBQUJjQWZBQUFKQ1ZBUkVRMGN4Z1pHaHNjSFI0ZklDRWlJeVFCQUlBQUFnQUFBQUFnZ0FBRUJBUUFBQUFBQUFJQUFBQUVCQjlEdG5VQkFBQUFBQUFFUHVlQkFLT0ZnZ0FBZ0FDanpvRUFBNEJ3QndDZEFTcXdBSkFBQUVjSWhZV0loWVNJQWdJQUJod0o3a1BmYkp5SHZ0azVEMzJ5Y2g3N1pPUTk5c25JZSsyVGtQZmJKeUh2dGs1RDMyeWNoNzdaT1E5OVlBRCsvNnRRZ0tPRmdnQURnQXFqaFlJQUQ0QU9vNFdDQUNTQURxT1pnUUFyQURFQ0FBRVFFQUFZQUJoWUwvUUFDSUJEbUFZQUFLT0ZnZ0E2Z0E2amhZSUFUNEFPbzVtQkFGTUFNUUlBQVJBUUFCZ0FHRmd2OUFBSWdFT1lCZ0FBbzRXQ0FHU0FEcU9GZ2dCNmdBNmptWUVBZXdBeEFnQUJFQkFBR0FBWVdDLzBBQWlBUTVnR0FBQ2poWUlBajRBT281bUJBS01BTVFJQUFSQVFBQmdBR0ZndjlBQUlnRU9ZQmdBQW80V0NBS1NBRHFPRmdnQzZnQTZqbVlFQXl3QXhBZ0FCRUJBQUdBQVlXQy8wQUFpQVE1Z0dBQUNqaFlJQXo0QU9vNFdDQU9TQURxT1pnUUR6QURFQ0FBRVFFQUFZQUJoWUwvUUFDSUJEbUFZQUFLT0ZnZ0Q2Z0E2amhZSUJENEFPbzVpQkFSc0FFUUlBQVJBUUZHQUFZV0MvMEFBaUFRNWdHQUNqaFlJQkpJQU9vNFdDQVRxQURxT1pnUUZEQURFQ0FBRVFFQUFZQUJoWUwvUUFDSUJEbUFZQUFLT0ZnZ0ZQZ0E2amhZSUJaSUFPbzVtQkFXc0FNUUlBQVJBUUFCZ0FHRmd2OUFBSWdFT1lCZ0FBbzRXQ0FYcUFEcU9GZ2dHUGdBNmptWUVCa3dBeEFnQUJFQkFBR0FBWVdDLzBBQWlBUTVnR0FBQ2poWUlCcElBT280V0NBYnFBRHFPWmdRRzdBREVDQUFFUUVBQVlBQmhZTC9RQUNJQkRtQVlBQUtPRmdnSFBnQTZqbVlFQjR3QXhBZ0FCRUJBQUdBQVlXQy8wQUFpQVE1Z0dBQUNqaFlJQjVJQU9vNFdDQWZxQURxT1pnUUlMQURFQ0FBRVFFQUFZQUJoWUwvUUFDSUJEbUFZQUFLT0ZnZ0lQZ0E2amhZSUNKSUFPbzVtQkFqTUFNUUlBQVJBUUFCZ0FHRmd2OUFBSWdFT1lCZ0FBbzRXQ0FqcUFEcU9GZ2dKUGdBNmptWUVDV3dBeEFnQUJFQkFBR0FBWVdDLzBBQWlBUTVnR0FBQ2poWUlDWklBT280V0NBbnFBRHFPWmdRS0RBREVDQUFFUUVBQVlBQmhZTC9RQUNJQkRtQVlBQUtPRmdnS1BnQTZqaFlJQ3BJQU9vNW1CQXFzQU1RSUFBUkFRQUJnQUdGZ3Y5QUFJZ0VPWUJnQUFvNFdDQXJxQURxT0ZnZ0xQZ0E2am1JRUMwd0FSQWdBQkVCQVVZQUJoWUwvUUFDSUJEbUFZQUtPRmdnTGtnQTZqaFlJQytvQU9vNW1CQXZzQU1RSUFBUkFRQUJnQUdGZ3Y5QUFJZ0VPWUJnQUFvNFdDQXcrQURxT1pnUU1qQURFQ0FBRVFFQUFZQUJoWUwvUUFDSUJEbUFZQUFLT0ZnZ01rZ0E2amhZSURPb0FPbzVtQkEwc0FNUUlBQVJBUUFCZ0FHRmd2OUFBSWdFT1lCZ0FBbzRXQ0EwK0FEcU9GZ2dOa2dBNmptWUVEY3dBeEFnQUJFQkFBR0FBWVdDLzBBQWlBUTVnR0FBQ2poWUlEZW9BT280V0NBNCtBRHFPWmdRT2JBREVDQUFFUUVBQVlBQmhZTC9RQUNJQkRtQVlBQUtPRmdnT2tnQTZqaFlJRHVvQU9vNW1CQThNQU1RSUFBUkFRQUJnQUdGZ3Y5QUFJZ0VPWUJnQUFvNFdDQTgrQURxT0ZnZ1BrZ0E2amhZSUQrb0FPbzRXQ0JBK0FEaHhUdTJzQkFBQUFBQUFBRWJ1UHM0RUR0NHIzZ1FIeGdoRXI4SUVLXCIsXG4gIG1wNDpcbiAgICBcImRhdGE6dmlkZW8vbXA0O2Jhc2U2NCxBQUFBSEdaMGVYQk5ORllnQUFBQ0FHbHpiMjFwYzI4eVlYWmpNUUFBQUFobWNtVmxBQUFHRjIxa1lYVGVCQUFBYkdsaVptRmhZeUF4TGpJNEFBQkNBSk1nQkRJQVJ3QUFBckVHQmYvL3JkeEY2YjNtMlVpM2xpellJTmtqN3U5NE1qWTBJQzBnWTI5eVpTQXhORElnY2pJZ09UVTJZemhrT0NBdElFZ3VNalkwTDAxUVJVY3ROQ0JCVmtNZ1kyOWtaV01nTFNCRGIzQjViR1ZtZENBeU1EQXpMVEl3TVRRZ0xTQm9kSFJ3T2k4dmQzZDNMblpwWkdWdmJHRnVMbTl5Wnk5NE1qWTBMbWgwYld3Z0xTQnZjSFJwYjI1ek9pQmpZV0poWXowd0lISmxaajB6SUdSbFlteHZZMnM5TVRvd09qQWdZVzVoYkhselpUMHdlREU2TUhneE1URWdiV1U5YUdWNElITjFZbTFsUFRjZ2NITjVQVEVnY0hONVgzSmtQVEV1TURBNk1DNHdNQ0J0YVhobFpGOXlaV1k5TVNCdFpWOXlZVzVuWlQweE5pQmphSEp2YldGZmJXVTlNU0IwY21Wc2JHbHpQVEVnT0hnNFpHTjBQVEFnWTNGdFBUQWdaR1ZoWkhwdmJtVTlNakVzTVRFZ1ptRnpkRjl3YzJ0cGNEMHhJR05vY205dFlWOXhjRjl2Wm1aelpYUTlMVElnZEdoeVpXRmtjejAySUd4dmIydGhhR1ZoWkY5MGFISmxZV1J6UFRFZ2MyeHBZMlZrWDNSb2NtVmhaSE05TUNCdWNqMHdJR1JsWTJsdFlYUmxQVEVnYVc1MFpYSnNZV05sWkQwd0lHSnNkWEpoZVY5amIyMXdZWFE5TUNCamIyNXpkSEpoYVc1bFpGOXBiblJ5WVQwd0lHSm1jbUZ0WlhNOU1DQjNaV2xuYUhSd1BUQWdhMlY1YVc1MFBUSTFNQ0JyWlhscGJuUmZiV2x1UFRJMUlITmpaVzVsWTNWMFBUUXdJR2x1ZEhKaFgzSmxabkpsYzJnOU1DQnlZMTlzYjI5cllXaGxZV1E5TkRBZ2NtTTlZM0ptSUcxaWRISmxaVDB4SUdOeVpqMHlNeTR3SUhGamIyMXdQVEF1TmpBZ2NYQnRhVzQ5TUNCeGNHMWhlRDAyT1NCeGNITjBaWEE5TkNCMlluWmZiV0Y0Y21GMFpUMDNOamdnZG1KMlgySjFabk5wZW1VOU16QXdNQ0JqY21aZmJXRjRQVEF1TUNCdVlXeGZhSEprUFc1dmJtVWdabWxzYkdWeVBUQWdhWEJmY21GMGFXODlNUzQwTUNCaGNUMHhPakV1TURBQWdBQUFBRlpsaUlRTDhtS0FBS3ZNbkp5Y25KeWNuSnljblhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhpRUFTWkFDR1FBamdDRUFTWkFDR1FBamdBQUFBQWRCbWpnWDRHU0FJUUJKa0FJWkFDT0FBQUFBQjBHYVZBWDRHU0FoQUVtUUFoa0FJNEFoQUVtUUFoa0FJNEFBQUFBR1FacGdMOERKSVFCSmtBSVpBQ09BSVFCSmtBSVpBQ09BQUFBQUJrR2FnQy9BeVNFQVNaQUNHUUFqZ0FBQUFBWkJtcUF2d01raEFFbVFBaGtBSTRBaEFFbVFBaGtBSTRBQUFBQUdRWnJBTDhESklRQkprQUlaQUNPQUFBQUFCa0dhNEMvQXlTRUFTWkFDR1FBamdDRUFTWkFDR1FBamdBQUFBQVpCbXdBdndNa2hBRW1RQWhrQUk0QUFBQUFHUVpzZ0w4REpJUUJKa0FJWkFDT0FJUUJKa0FJWkFDT0FBQUFBQmtHYlFDL0F5U0VBU1pBQ0dRQWpnQ0VBU1pBQ0dRQWpnQUFBQUFaQm0yQXZ3TWtoQUVtUUFoa0FJNEFBQUFBR1FadUFMOERKSVFCSmtBSVpBQ09BSVFCSmtBSVpBQ09BQUFBQUJrR2JvQy9BeVNFQVNaQUNHUUFqZ0FBQUFBWkJtOEF2d01raEFFbVFBaGtBSTRBaEFFbVFBaGtBSTRBQUFBQUdRWnZnTDhESklRQkprQUlaQUNPQUFBQUFCa0dhQUMvQXlTRUFTWkFDR1FBamdDRUFTWkFDR1FBamdBQUFBQVpCbWlBdndNa2hBRW1RQWhrQUk0QWhBRW1RQWhrQUk0QUFBQUFHUVpwQUw4REpJUUJKa0FJWkFDT0FBQUFBQmtHYVlDL0F5U0VBU1pBQ0dRQWpnQ0VBU1pBQ0dRQWpnQUFBQUFaQm1vQXZ3TWtoQUVtUUFoa0FJNEFBQUFBR1FacWdMOERKSVFCSmtBSVpBQ09BSVFCSmtBSVpBQ09BQUFBQUJrR2F3Qy9BeVNFQVNaQUNHUUFqZ0FBQUFBWkJtdUF2d01raEFFbVFBaGtBSTRBaEFFbVFBaGtBSTRBQUFBQUdRWnNBTDhESklRQkprQUlaQUNPQUFBQUFCa0diSUMvQXlTRUFTWkFDR1FBamdDRUFTWkFDR1FBamdBQUFBQVpCbTBBdndNa2hBRW1RQWhrQUk0QWhBRW1RQWhrQUk0QUFBQUFHUVp0Z0w4REpJUUJKa0FJWkFDT0FBQUFBQmtHYmdDdkF5U0VBU1pBQ0dRQWpnQ0VBU1pBQ0dRQWpnQUFBQUFaQm02QW53TWtoQUVtUUFoa0FJNEFoQUVtUUFoa0FJNEFoQUVtUUFoa0FJNEFoQUVtUUFoa0FJNEFBQUFodWJXOXZkZ0FBQUd4dGRtaGtBQUFBQUFBQUFBQUFBQUFBQUFBRDZBQUFCRGNBQVFBQUFRQUFBQUFBQUFBQUFBQUFBQUVBQUFBQUFBQUFBQUFBQUFBQUFBQUJBQUFBQUFBQUFBQUFBQUFBQUFCQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBd0FBQXpCMGNtRnJBQUFBWEhScmFHUUFBQUFEQUFBQUFBQUFBQUFBQUFBQkFBQUFBQUFBQStrQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFFQUFBQUFBQUFBQUFBQUFBQUFBQUFCQUFBQUFBQUFBQUFBQUFBQUFBQkFBQUFBQUxBQUFBQ1FBQUFBQUFBa1pXUjBjd0FBQUJ4bGJITjBBQUFBQUFBQUFBRUFBQVBwQUFBQUFBQUJBQUFBQUFLb2JXUnBZUUFBQUNCdFpHaGtBQUFBQUFBQUFBQUFBQUFBQUFCMU1BQUFkVTVWeEFBQUFBQUFMV2hrYkhJQUFBQUFBQUFBQUhacFpHVUFBQUFBQUFBQUFBQUFBQUJXYVdSbGIwaGhibVJzWlhJQUFBQUNVMjFwYm1ZQUFBQVVkbTFvWkFBQUFBRUFBQUFBQUFBQUFBQUFBQ1JrYVc1bUFBQUFIR1J5WldZQUFBQUFBQUFBQVFBQUFBeDFjbXdnQUFBQUFRQUFBaE56ZEdKc0FBQUFyM04wYzJRQUFBQUFBQUFBQVFBQUFKOWhkbU14QUFBQUFBQUFBQUVBQUFBQUFBQUFBQUFBQUFBQUFBQUFBTEFBa0FCSUFBQUFTQUFBQUFBQUFBQUJBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUdQLy9BQUFBTFdGMlkwTUJRc0FOLytFQUZXZEN3QTNaQXNUc0JFQUFBUHBBQURxWUE4VUtrZ0VBQldqTGc4c2dBQUFBSEhWMWFXUnJhRUR5WHlSUHhibzVwUnZQQXlQekFBQUFBQUFBQUJoemRIUnpBQUFBQUFBQUFBRUFBQUFlQUFBRDZRQUFBQlJ6ZEhOekFBQUFBQUFBQUFFQUFBQUJBQUFBSEhOMGMyTUFBQUFBQUFBQUFRQUFBQUVBQUFBQkFBQUFBUUFBQUl4emRITjZBQUFBQUFBQUFBQUFBQUFlQUFBRER3QUFBQXNBQUFBTEFBQUFDZ0FBQUFvQUFBQUtBQUFBQ2dBQUFBb0FBQUFLQUFBQUNnQUFBQW9BQUFBS0FBQUFDZ0FBQUFvQUFBQUtBQUFBQ2dBQUFBb0FBQUFLQUFBQUNnQUFBQW9BQUFBS0FBQUFDZ0FBQUFvQUFBQUtBQUFBQ2dBQUFBb0FBQUFLQUFBQUNnQUFBQW9BQUFBS0FBQUFpSE4wWTI4QUFBQUFBQUFBSGdBQUFFWUFBQU5uQUFBRGV3QUFBNWdBQUFPMEFBQUR4d0FBQStNQUFBUDJBQUFFRWdBQUJDVUFBQVJCQUFBRVhRQUFCSEFBQUFTTUFBQUVud0FBQkxzQUFBVE9BQUFFNmdBQUJRWUFBQVVaQUFBRk5RQUFCVWdBQUFWa0FBQUZkd0FBQlpNQUFBV21BQUFGd2dBQUJkNEFBQVh4QUFBR0RRQUFCR2gwY21GckFBQUFYSFJyYUdRQUFBQURBQUFBQUFBQUFBQUFBQUFDQUFBQUFBQUFCRGNBQUFBQUFBQUFBQUFBQUFFQkFBQUFBQUVBQUFBQUFBQUFBQUFBQUFBQUFBQUJBQUFBQUFBQUFBQUFBQUFBQUFCQUFBQUFBQUFBQUFBQUFBQUFBQUFrWldSMGN3QUFBQnhsYkhOMEFBQUFBQUFBQUFFQUFBUWtBQUFEY0FBQkFBQUFBQVBnYldScFlRQUFBQ0J0Wkdoa0FBQUFBQUFBQUFBQUFBQUFBQUM3Z0FBQXlrQlZ4QUFBQUFBQUxXaGtiSElBQUFBQUFBQUFBSE52ZFc0QUFBQUFBQUFBQUFBQUFBQlRiM1Z1WkVoaGJtUnNaWElBQUFBRGkyMXBibVlBQUFBUWMyMW9aQUFBQUFBQUFBQUFBQUFBSkdScGJtWUFBQUFjWkhKbFpnQUFBQUFBQUFBQkFBQUFESFZ5YkNBQUFBQUJBQUFEVDNOMFltd0FBQUJuYzNSelpBQUFBQUFBQUFBQkFBQUFWMjF3TkdFQUFBQUFBQUFBQVFBQUFBQUFBQUFBQUFJQUVBQUFBQUM3Z0FBQUFBQUFNMlZ6WkhNQUFBQUFBNENBZ0NJQUFnQUVnSUNBRkVBVkJiallBQXU0QUFBQURjb0ZnSUNBQWhHUUJvQ0FnQUVDQUFBQUlITjBkSE1BQUFBQUFBQUFBZ0FBQURJQUFBUUFBQUFBQVFBQUFrQUFBQUZVYzNSell3QUFBQUFBQUFBYkFBQUFBUUFBQUFFQUFBQUJBQUFBQWdBQUFBSUFBQUFCQUFBQUF3QUFBQUVBQUFBQkFBQUFCQUFBQUFJQUFBQUJBQUFBQmdBQUFBRUFBQUFCQUFBQUJ3QUFBQUlBQUFBQkFBQUFDQUFBQUFFQUFBQUJBQUFBQ1FBQUFBSUFBQUFCQUFBQUNnQUFBQUVBQUFBQkFBQUFDd0FBQUFJQUFBQUJBQUFBRFFBQUFBRUFBQUFCQUFBQURnQUFBQUlBQUFBQkFBQUFEd0FBQUFFQUFBQUJBQUFBRUFBQUFBSUFBQUFCQUFBQUVRQUFBQUVBQUFBQkFBQUFFZ0FBQUFJQUFBQUJBQUFBRkFBQUFBRUFBQUFCQUFBQUZRQUFBQUlBQUFBQkFBQUFGZ0FBQUFFQUFBQUJBQUFBRndBQUFBSUFBQUFCQUFBQUdBQUFBQUVBQUFBQkFBQUFHUUFBQUFJQUFBQUJBQUFBR2dBQUFBRUFBQUFCQUFBQUd3QUFBQUlBQUFBQkFBQUFIUUFBQUFFQUFBQUJBQUFBSGdBQUFBSUFBQUFCQUFBQUh3QUFBQVFBQUFBQkFBQUE0SE4wYzNvQUFBQUFBQUFBQUFBQUFETUFBQUFhQUFBQUNRQUFBQWtBQUFBSkFBQUFDUUFBQUFrQUFBQUpBQUFBQ1FBQUFBa0FBQUFKQUFBQUNRQUFBQWtBQUFBSkFBQUFDUUFBQUFrQUFBQUpBQUFBQ1FBQUFBa0FBQUFKQUFBQUNRQUFBQWtBQUFBSkFBQUFDUUFBQUFrQUFBQUpBQUFBQ1FBQUFBa0FBQUFKQUFBQUNRQUFBQWtBQUFBSkFBQUFDUUFBQUFrQUFBQUpBQUFBQ1FBQUFBa0FBQUFKQUFBQUNRQUFBQWtBQUFBSkFBQUFDUUFBQUFrQUFBQUpBQUFBQ1FBQUFBa0FBQUFKQUFBQUNRQUFBQWtBQUFBSkFBQUFDUUFBQUFrQUFBQ01jM1JqYndBQUFBQUFBQUFmQUFBQUxBQUFBMVVBQUFOeUFBQURoZ0FBQTZJQUFBTytBQUFEMFFBQUErMEFBQVFBQUFBRUhBQUFCQzhBQUFSTEFBQUVad0FBQkhvQUFBU1dBQUFFcVFBQUJNVUFBQVRZQUFBRTlBQUFCUkFBQUFVakFBQUZQd0FBQlZJQUFBVnVBQUFGZ1FBQUJaMEFBQVd3QUFBRnpBQUFCZWdBQUFYN0FBQUdGd0FBQUdKMVpIUmhBQUFBV20xbGRHRUFBQUFBQUFBQUlXaGtiSElBQUFBQUFBQUFBRzFrYVhKaGNIQnNBQUFBQUFBQUFBQUFBQUFBTFdsc2MzUUFBQUFscVhSdmJ3QUFBQjFrWVhSaEFBQUFBUUFBQUFCTVlYWm1OVFV1TXpNdU1UQXdcIixcbn07XG4iLCIvKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMCAqL1xuY29uc3QgT21VdGlsID0gcmVxdWlyZSgnLi4vbWFpbi9vbXV0aWxzJyk7XG5jb25zdCBTZXR0aW5ncyA9IHJlcXVpcmUoJy4uL21haW4vc2V0dGluZ3MnKTtcblxuY29uc3QgY2xvc2VkSGVpZ2h0ID0gMjAsIHRpbWVvdXQgPSAxMDAwMDtcbmxldCBhY3Rpdml0aWVzLCBhY2xlYW4sIG1vZEFyZWEsIGFyZWEsIG9wZW5lZEhlaWdodCA9IDM0NVxuXHQsIG9wZW5lZEhlaWdodFB4ID0gb3BlbmVkSGVpZ2h0ICsgJ3B4JywgaW5pdGVkID0gZmFsc2Vcblx0LCBuZXdBY3ROb3RpZmljYXRpb247XG5cbmZ1bmN0aW9uIF9sb2FkKCkge1xuXHRjb25zdCBzID0gU2V0dGluZ3MubG9hZCgpO1xuXHRpZiAodHlwZW9mKHMuYWN0aXZpdHkpID09PSAndW5kZWZpbmVkJykge1xuXHRcdHMuYWN0aXZpdHkgPSB7fTtcblx0fVxuXHRyZXR1cm4gcztcbn1cbmZ1bmN0aW9uIF91cGRhdGVDbGVhbihzLCBhKSB7XG5cdGNvbnN0IGNsZWFuID0gcy5hY3Rpdml0eS5jbGVhbiA9PT0gdHJ1ZTtcblx0YS5wcm9wKCdjaGVja2VkJywgY2xlYW4pO1xuXHRpZiAoY2xlYW4pIHtcblx0XHRhY3Rpdml0aWVzLmZpbmQoJy5hdXRvLWNsZWFuJykuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdHNldFRpbWVvdXQoX2NsZWFySXRlbS5iaW5kKG51bGwsICQodGhpcykuZGF0YSgpLmlkKSwgdGltZW91dCk7XG5cdFx0fSk7XG5cdH1cbn1cbmZ1bmN0aW9uIGlzQ2xvc2VkKCkge1xuXHRyZXR1cm4gYWN0aXZpdGllcy5oZWlnaHQoKSA8IDI0O1xufVxuZnVuY3Rpb24gX3VwZGF0ZUhlaWdodFZhcihoKSB7XG5cdFJvb20uc2V0Q3NzVmFyKCctLWFjdGl2aXRpZXMtaGVpZ2h0JywgaCk7XG59XG5mdW5jdGlvbiBfb3BlbigpIHtcblx0aWYgKGlzQ2xvc2VkKCkpIHtcblx0XHQkKCcuY29udHJvbC5ibG9jayBpJywgYWN0aXZpdGllcykucmVtb3ZlQ2xhc3MoJ2ZhLWFuZ2xlLXVwJykuYWRkQ2xhc3MoJ2ZhLWFuZ2xlLWRvd24nKTtcblx0XHQkKCcuY29udHJvbC5ibG9jaycsIGFjdGl2aXRpZXMpLnJlbW92ZUNsYXNzKCdiZy13YXJuaW5nJyk7XG5cdFx0YWN0aXZpdGllcy5hbmltYXRlKFxuXHRcdFx0e1xuXHRcdFx0XHRoZWlnaHQ6IG9wZW5lZEhlaWdodFB4XG5cdFx0XHRcdCwgdG9wOiAnLScgKyBvcGVuZWRIZWlnaHRQeFxuXHRcdFx0fVxuXHRcdFx0LCAxMDAwXG5cdFx0XHQsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRhY3Rpdml0aWVzLmNzcyh7J3RvcCc6ICcnfSk7XG5cdFx0XHRcdF91cGRhdGVIZWlnaHRWYXIob3BlbmVkSGVpZ2h0UHgpO1xuXHRcdFx0XHRhY3Rpdml0aWVzLnJlc2l6YWJsZSgnb3B0aW9uJywgJ2Rpc2FibGVkJywgZmFsc2UpO1xuXHRcdFx0fVxuXHRcdCk7XG5cdH1cbn1cbmZ1bmN0aW9uIF9jbG9zZSgpIHtcblx0aWYgKCFpc0Nsb3NlZCgpKSB7XG5cdFx0JCgnLmNvbnRyb2wuYmxvY2sgaScsIGFjdGl2aXRpZXMpLnJlbW92ZUNsYXNzKCdmYS1hbmdsZS1kb3duJykuYWRkQ2xhc3MoJ2ZhLWFuZ2xlLXVwJyk7XG5cdFx0YWN0aXZpdGllcy5hbmltYXRlKFxuXHRcdFx0e1xuXHRcdFx0XHRoZWlnaHQ6IGNsb3NlZEhlaWdodFxuXHRcdFx0XHQsIHRvcDogKG9wZW5lZEhlaWdodCAtIGNsb3NlZEhlaWdodCkgKyAncHgnXG5cdFx0XHR9XG5cdFx0XHQsIDEwMDBcblx0XHRcdCwgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGFjdGl2aXRpZXMuY3NzKHsndG9wJzogJyd9KTtcblx0XHRcdFx0X3VwZGF0ZUhlaWdodFZhcihjbG9zZWRIZWlnaHQgKyAncHgnKTtcblx0XHRcdH1cblx0XHQpO1xuXHRcdGFjdGl2aXRpZXMucmVzaXphYmxlKCdvcHRpb24nLCAnZGlzYWJsZWQnLCB0cnVlKTtcblx0fVxufVxuZnVuY3Rpb24gX2ZpbmRVc2VyKHVpZCkge1xuXHRjb25zdCBtID0gJzVweCcsIHQgPSA1MCwgdSA9ICQoJyN1c2VyJyArIHVpZCk7XG5cdGlmICh1Lmxlbmd0aCA9PT0gMSkge1xuXHRcdHVbMF0uc2Nyb2xsSW50b1ZpZXcoKTtcblx0XHR1LmFkZENsYXNzKCdiZy13YXJuaW5nJyk7XG5cdFx0Zm9yKGxldCBpID0gMDsgaSA8IDEwOyBpKyspIHtcblx0XHRcdHUuYW5pbWF0ZSh7bWFyZ2luVG9wOiAnLT0nK219LCB0KVxuXHRcdFx0XHQuYW5pbWF0ZSh7bWFyZ2luVG9wOiAnKz0nK219LCB0KTtcblx0XHR9XG5cdFx0dS5yZW1vdmVDbGFzcygnYmctd2FybmluZycsIDE1MDApO1xuXHR9XG59XG5mdW5jdGlvbiBfaGlnaHRsaWdodChub3RpZnkpIHtcblx0aWYgKCFpbml0ZWQpIHtcblx0XHRyZXR1cm47XG5cdH1cblx0aWYgKGlzQ2xvc2VkKCkpIHtcblx0XHQkKCcuY29udHJvbC5ibG9jaycsIGFjdGl2aXRpZXMpLmFkZENsYXNzKCdiZy13YXJuaW5nJyk7XG5cdFx0aWYgKG5vdGlmeSkge1xuXHRcdFx0T21VdGlsLm5vdGlmeShuZXdBY3ROb3RpZmljYXRpb24sICduZXdfYWFfaXRlbScpO1xuXHRcdH1cblx0fVxufVxuZnVuY3Rpb24gX2dldElkKGlkKSB7XG5cdHJldHVybiAnYWN0aXZpdHktJyArIGlkO1xufVxuZnVuY3Rpb24gX2FjdGlvbihuYW1lLCB2YWwpIHtcblx0YWN0aXZpdHlBY3Rpb24oJCgnLnJvb20tYmxvY2sgLnJvb20tY29udGFpbmVyJykuZGF0YSgncm9vbS1pZCcpLCBuYW1lLCB2YWwpO1xufVxuZnVuY3Rpb24gX3JlbW92ZShpZHMpIHtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCBpZHMubGVuZ3RoOyArK2kpIHtcblx0XHQkKCcjJyArIF9nZXRJZChpZHNbaV0pKS5yZW1vdmUoKTtcblx0fVxuXHRfdXBkYXRlQ291bnQoKTtcbn1cbmZ1bmN0aW9uIF9jbGVhckl0ZW0oaWQpIHtcblx0aWYgKGFjbGVhbi5wcm9wKCdjaGVja2VkJykpIHtcblx0XHRfcmVtb3ZlKFtpZF0pO1xuXHR9XG59XG5mdW5jdGlvbiBfdXBkYXRlQ291bnQoKSB7XG5cdGlmICghaW5pdGVkKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdCQoJy5jb250cm9sLmJsb2NrIC5iYWRnZScsIGFjdGl2aXRpZXMpLnRleHQobW9kQXJlYS5maW5kKCcuYWN0aXZpdHknKS5sZW5ndGgpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblx0aW5pdDogZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCQoJyNhY3Rpdml0aWVzJykucmVzaXphYmxlKFwiaW5zdGFuY2VcIikgIT09IHVuZGVmaW5lZCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRhY3Rpdml0aWVzID0gJCgnI2FjdGl2aXRpZXMnKTtcblx0XHRjb25zdCBjdHJsQmxrID0gYWN0aXZpdGllcy5maW5kKCcuY29udHJvbC5ibG9jaycpO1xuXHRcdGN0cmxCbGsub2ZmKCkuY2xpY2soQWN0aXZpdGllcy50b2dnbGUpO1xuXHRcdG5ld0FjdE5vdGlmaWNhdGlvbiA9IGN0cmxCbGsuZGF0YSgnbmV3LWFhJyk7XG5cdFx0YWN0aXZpdGllcy5yZXNpemFibGUoe1xuXHRcdFx0aGFuZGxlczogJ24nXG5cdFx0XHQsIGRpc2FibGVkOiBpc0Nsb3NlZCgpXG5cdFx0XHQsIG1pbkhlaWdodDogMTk1XG5cdFx0XHQsIHN0b3A6IGZ1bmN0aW9uKF8sIHVpKSB7XG5cdFx0XHRcdG9wZW5lZEhlaWdodCA9IHVpLnNpemUuaGVpZ2h0O1xuXHRcdFx0XHRvcGVuZWRIZWlnaHRQeCA9IG9wZW5lZEhlaWdodCArICdweCc7XG5cdFx0XHRcdF91cGRhdGVIZWlnaHRWYXIob3BlbmVkSGVpZ2h0UHgpO1xuXHRcdFx0XHRhY3Rpdml0aWVzLmNzcyh7J3RvcCc6ICcnfSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cdFx0bW9kQXJlYSA9IGFjdGl2aXRpZXMuZmluZCgnLmFyZWEgLmFjdGlvbnMnKTtcblx0XHRhcmVhID0gYWN0aXZpdGllcy5maW5kKCcuYXJlYSAuYWN0aXZpdGllcycpO1xuXHRcdGFjbGVhbiA9ICQoJyNhY3Rpdml0eS1hdXRvLWNsZWFuJyk7XG5cdFx0YWNsZWFuLmNoYW5nZShmdW5jdGlvbigpIHtcblx0XHRcdGNvbnN0IHMgPSBfbG9hZCgpO1xuXHRcdFx0cy5hY3Rpdml0eS5jbGVhbiA9ICQodGhpcykucHJvcCgnY2hlY2tlZCcpO1xuXHRcdFx0U2V0dGluZ3Muc2F2ZShzKTtcblx0XHRcdF91cGRhdGVDbGVhbihzLCAkKHRoaXMpKTtcblx0XHR9KTtcblx0XHRfdXBkYXRlQ2xlYW4oX2xvYWQoKSwgYWNsZWFuKTtcblx0XHRpbml0ZWQgPSB0cnVlO1xuXHRcdF91cGRhdGVDb3VudCgpO1xuXHR9XG5cdCwgdG9nZ2xlOiBmdW5jdGlvbigpIHtcblx0XHRpZiAoIWluaXRlZCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHRpZiAoaXNDbG9zZWQoKSkge1xuXHRcdFx0X29wZW4oKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0X2Nsb3NlKCk7XG5cdFx0fVxuXHR9XG5cdCwgZmluZFVzZXI6IF9maW5kVXNlclxuXHQsIGFkZDogZnVuY3Rpb24ob2JqKSB7XG5cdFx0aWYgKCFpbml0ZWQpIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFx0Y29uc3QgX2lkID0gX2dldElkKG9iai5pZCk7XG5cdFx0KG9iai5hY3Rpb24gPyBtb2RBcmVhIDogYXJlYSkuYXBwZW5kKE9tVXRpbC50bXBsKCcjYWN0aXZpdHktc3R1YicsIF9pZCkuZGF0YShvYmopKTtcblx0XHRjb25zdCBhID0gJCgnIycgKyBfaWQpLmFkZENsYXNzKG9iai5jc3NDbGFzcyk7XG5cdFx0Y29uc3QgYWNwdCA9IGEuZmluZCgnLmFjdGl2aXR5LWFjY2VwdCcpO1xuXHRcdGlmIChvYmouYWNjZXB0KSB7XG5cdFx0XHRhY3B0LmNsaWNrKGZ1bmN0aW9uKCkgeyBfYWN0aW9uKCdhY2NlcHQnLCBvYmouaWQpOyB9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0YWNwdC5yZW1vdmUoKTtcblx0XHR9XG5cdFx0Y29uc3QgZGNsbiA9IGEuZmluZCgnLmFjdGl2aXR5LWRlY2xpbmUnKTtcblx0XHRpZiAob2JqLmRlY2xpbmUpIHtcblx0XHRcdGRjbG4uY2xpY2soZnVuY3Rpb24oKSB7IF9hY3Rpb24oJ2RlY2xpbmUnLCBvYmouaWQpOyB9KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZGNsbi5yZW1vdmUoKTtcblx0XHR9XG5cdFx0Y29uc3QgZm5kID0gYS5maW5kKCcuYWN0aXZpdHktZmluZCcpO1xuXHRcdGlmIChvYmouZmluZCkge1xuXHRcdFx0Zm5kLmNsaWNrKGZ1bmN0aW9uKCkgeyBfZmluZFVzZXIob2JqLnVpZCk7IH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRmbmQucmVtb3ZlKCk7XG5cdFx0fVxuXHRcdGEuZmluZCgnLmFjdGl2aXR5LWNsb3NlJykuY2xpY2soZnVuY3Rpb24oKSB7XG5cdFx0XHRfYWN0aW9uKCdjbG9zZScsIG9iai5pZCk7XG5cdFx0fSk7XG5cdFx0YS5maW5kKCcuYWN0aXZpdHktdGV4dCcpLnRleHQob2JqLnRleHQpO1xuXHRcdF9oaWdodGxpZ2h0KG9iai5hY3Rpb24pO1xuXHRcdGlmIChhY2xlYW4ucHJvcCgnY2hlY2tlZCcpICYmIGEuaGFzQ2xhc3MoJ2F1dG8tY2xlYW4nKSkge1xuXHRcdFx0c2V0VGltZW91dChfY2xlYXJJdGVtLmJpbmQobnVsbCwgb2JqLmlkKSwgdGltZW91dCk7XG5cdFx0fVxuXHRcdF91cGRhdGVDb3VudCgpO1xuXHR9XG5cdCwgcmVtb3ZlOiBfcmVtb3ZlXG59O1xuIiwiLyogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKSBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAgKi9cbmNvbnN0IE9tVXRpbCA9IHJlcXVpcmUoJy4uL21haW4vb211dGlscycpO1xuY29uc3QgVXNlckxpc3RVdGlsID0gcmVxdWlyZSgnLi91c2VyLWxpc3QtdXRpbCcpO1xuXG5mdW5jdGlvbiBfc2V0UXVpY2tQb2xsUmlnaHRzKCkge1xuXHRjb25zdCBjbG9zZSA9ICQoJyNxdWljay12b3RlIC5jbG9zZS1idG4nKTtcblx0aWYgKGNsb3NlLmxlbmd0aCA9PT0gMSkge1xuXHRcdGlmIChVc2VyTGlzdFV0aWwuaGFzUmlnaHQoWydQUkVTRU5URVInXSkpIHtcblx0XHRcdGNsb3NlLnNob3coKTtcblx0XHRcdGlmICh0eXBlb2YoY2xvc2UuZGF0YSgnYnMuY29uZmlybWF0aW9uJykpID09PSAnb2JqZWN0Jykge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFx0XHRjbG9zZVxuXHRcdFx0XHQuY29uZmlybWF0aW9uKHtcblx0XHRcdFx0XHRjb25maXJtYXRpb25FdmVudDogJ2JsYSdcblx0XHRcdFx0XHQsIG9uQ29uZmlybTogKCkgPT4gcXVpY2tQb2xsQWN0aW9uKCdjbG9zZScpXG5cdFx0XHRcdH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjbG9zZS5oaWRlKCk7XG5cdFx0fVxuXHR9XG59XG5mdW5jdGlvbiBfdXBkYXRlKG9iaikge1xuXHRpZiAob2JqLnN0YXJ0ZWQpIHtcblx0XHRsZXQgcXYgPSAkKCcjcXVpY2stdm90ZScpO1xuXHRcdGlmIChxdi5sZW5ndGggPT09IDApIHtcblx0XHRcdGNvbnN0IHdiQXJlYSA9ICQoJy5yb29tLWJsb2NrIC53Yi1ibG9jaycpO1xuXHRcdFx0cXYgPSBPbVV0aWwudG1wbCgnI3F1aWNrLXZvdGUtdGVtcGxhdGUnLCAncXVpY2stdm90ZScpO1xuXHRcdFx0cXYuYXR0cignY2xhc3MnLCAnZW5kLTAnKTtcblx0XHRcdHdiQXJlYS5hcHBlbmQocXYpO1xuXHRcdH1cblx0XHRjb25zdCBwcm8gPSBxdi5maW5kKCcuY29udHJvbC5wcm8nKVxuXHRcdFx0LCBjb24gPSBxdi5maW5kKCcuY29udHJvbC5jb24nKTtcblx0XHRpZiAob2JqLnZvdGVkKSB7XG5cdFx0XHRwcm8ucmVtb3ZlQ2xhc3MoJ2NsaWNrYWJsZScpLm9mZigpO1xuXHRcdFx0Y29uLnJlbW92ZUNsYXNzKCdjbGlja2FibGUnKS5vZmYoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cHJvLmFkZENsYXNzKCdjbGlja2FibGUnKS5vZmYoKS5jbGljayhmdW5jdGlvbigpIHtcblx0XHRcdFx0cXVpY2tQb2xsQWN0aW9uKCd2b3RlJywgdHJ1ZSk7XG5cdFx0XHR9KTtcblx0XHRcdGNvbi5hZGRDbGFzcygnY2xpY2thYmxlJykub2ZmKCkuY2xpY2soZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHF1aWNrUG9sbEFjdGlvbigndm90ZScsIGZhbHNlKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0XHRwcm8uZmluZCgnLmJhZGdlJykudGV4dChvYmoucHJvcyk7XG5cdFx0Y29uLmZpbmQoJy5iYWRnZScpLnRleHQob2JqLmNvbnMpO1xuXHRcdF9zZXRRdWlja1BvbGxSaWdodHMoKTtcblx0fSBlbHNlIHtcblx0XHRjb25zdCBxdiA9ICQoJyNxdWljay12b3RlJyk7XG5cdFx0aWYgKHF2Lmxlbmd0aCA9PT0gMSkge1xuXHRcdFx0cXYucmVtb3ZlKCk7XG5cdFx0fVxuXHR9XG5cdE9tVXRpbC50bXBsKCcjcXVpY2stdm90ZS10ZW1wbGF0ZScsICdxdWljay12b3RlJyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHR1cGRhdGU6IF91cGRhdGVcblx0LCBzZXRSaWdodHM6IF9zZXRRdWlja1BvbGxSaWdodHNcbn07IiwiLyogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKSBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAgKi9cbmNvbnN0IFNldHRpbmdzID0gcmVxdWlyZSgnLi4vbWFpbi9zZXR0aW5ncycpO1xuY29uc3QgVmlkZW9VdGlsID0gcmVxdWlyZSgnLi4vc2V0dGluZ3MvdmlkZW8tdXRpbCcpO1xuY29uc3QgVmlkZW9TZXR0aW5ncyA9IHJlcXVpcmUoJy4uL3NldHRpbmdzL3NldHRpbmdzJyk7XG5jb25zdCBJbnRlcnZpZXdXYkFyZWEgPSByZXF1aXJlKCcuLi93Yi9pbnRlcnZpZXctYXJlYScpO1xuY29uc3QgRHJhd1diQXJlYSA9IHJlcXVpcmUoJy4uL3diL3diLWFyZWEnKVxuXG5jb25zdCBOb1NsZWVwID0gcmVxdWlyZSgnbm9zbGVlcC5qcycpO1xuY29uc3QgVmlkZW9NYW5hZ2VyID0gcmVxdWlyZSgnLi92aWRlby1tYW5hZ2VyJyk7XG5jb25zdCBTaGFyZXIgPSByZXF1aXJlKCcuL3NoYXJlcicpO1xuY29uc3QgQWN0aXZpdGllcyA9IHJlcXVpcmUoJy4vYWN0aXZpdGllcycpO1xuY29uc3QgU2lwRGlhbGVyID0gcmVxdWlyZSgnLi9zaXAtZGlhbGVyJyk7XG5jb25zdCBVc2VyTGlzdFV0aWwgPSByZXF1aXJlKCcuL3VzZXItbGlzdC11dGlsJyk7XG5jb25zdCBVc2VyTGlzdCA9IHJlcXVpcmUoJy4vdXNlci1saXN0Jyk7XG5jb25zdCBRdWlja1BvbGwgPSByZXF1aXJlKCcuL3F1aWNrLXBvbGwnKTtcblxuY29uc3Qgc2JTaWRlID0gU2V0dGluZ3MuaXNSdGwgPyAncmlnaHQnIDogJ2xlZnQnO1xubGV0IG9wdGlvbnMsIG1lbnVIZWlnaHQsIHNiLCBkb2NrLCBub1NsZWVwO1xuXG5mdW5jdGlvbiBfaW5pdChfb3B0aW9ucykge1xuXHRvcHRpb25zID0gX29wdGlvbnM7XG5cdHdpbmRvdy5XYkFyZWEgPSBvcHRpb25zLmludGVydmlldyA/IG5ldyBJbnRlcnZpZXdXYkFyZWEoKSA6IG5ldyBEcmF3V2JBcmVhKCk7XG5cdGNvbnN0IG1lbnUgPSAkKCcucm9vbS1ibG9jayAucm9vbS1jb250YWluZXIgLm1lbnUnKTtcblx0c2IgPSAkKCcucm9vbS1ibG9jayAuc2lkZWJhcicpO1xuXHRzYi53aWR0aChzYi53aWR0aCgpKTsgLy8gdGhpcyBpcyByZXF1aXJlZCB0byAnZml4JyB0aGUgd2lkdGggc28gaXQgd2lsbCBub3QgZGVwZW5kIG9uIENTUyB2YXJcblx0ZG9jayA9IHNiLmZpbmQoJy5idG4tZG9jaycpLmNsaWNrKGZ1bmN0aW9uKCkge1xuXHRcdGNvbnN0IG9mZnNldCA9IHBhcnNlSW50KHNiLmNzcyhzYlNpZGUpKTtcblx0XHRpZiAob2Zmc2V0IDwgMCkge1xuXHRcdFx0c2IucmVtb3ZlQ2xhc3MoJ2Nsb3NlZCcpO1xuXHRcdH1cblx0XHRkb2NrLnByb3AoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cdFx0Y29uc3QgcHJvcHMgPSB7fTtcblx0XHRwcm9wc1tzYlNpZGVdID0gb2Zmc2V0IDwgMCA/ICcwcHgnIDogKC1zYi53aWR0aCgpICsgNDUpICsgJ3B4Jztcblx0XHRzYi5hbmltYXRlKHByb3BzLCAxNTAwXG5cdFx0XHQsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRkb2NrLnByb3AoJ2Rpc2FibGVkJywgZmFsc2UpO1xuXHRcdFx0XHRfX2RvY2tTZXRNb2RlKG9mZnNldCA8IDApO1xuXHRcdFx0XHRfc2V0U2l6ZSgpO1xuXHRcdFx0fSk7XG5cdH0pO1xuXHRfX2RvY2tTZXRNb2RlKHRydWUpO1xuXHRtZW51SGVpZ2h0ID0gbWVudS5sZW5ndGggPT09IDAgPyAwIDogbWVudS5oZWlnaHQoKTtcblx0VmlkZW9NYW5hZ2VyLmluaXQoKTtcblx0QWN0aXZpdGllcy5pbml0KCk7XG5cdFNoYXJlci5pbml0KCk7XG5cdFVzZXJMaXN0LmluaXQob3B0aW9ucyk7XG5cdF9zZXRTaXplKCk7XG5cdCQod2luZG93KS5vbigncmVzaXplLm9td2InLCB3aW5kb3cuV2JBcmVhLnJlc2l6ZSk7XG59XG5mdW5jdGlvbiBfX2RvY2tTZXRNb2RlKG1vZGUpIHtcblx0Y29uc3QgaWNvbiA9IGRvY2suZmluZCgnaScpLnJlbW92ZUNsYXNzKCdpY29uLWRvY2sgaWNvbi11bmRvY2snKTtcblx0aWYgKG1vZGUpIHtcblx0XHRpY29uLmFkZENsYXNzKCdpY29uLXVuZG9jaycpO1xuXHRcdGRvY2suYXR0cigndGl0bGUnLCBkb2NrLmRhdGEoJ3R0bC11bmRvY2snKSlcblx0XHRcdC5maW5kKCcuc3Itb25seScpLnRleHQoZG9jay5kYXRhKCd0dGwtdW5kb2NrJykpO1xuXHRcdF9zYkFkZFJlc2l6YWJsZSgpO1xuXHR9IGVsc2Uge1xuXHRcdGljb24uYWRkQ2xhc3MoJ2ljb24tZG9jaycpO1xuXHRcdGRvY2suYXR0cigndGl0bGUnLCBkb2NrLmRhdGEoJ3R0bC1kb2NrJykpXG5cdFx0XHQuZmluZCgnLnNyLW9ubHknKS50ZXh0KGRvY2suZGF0YSgndHRsLWRvY2snKSk7XG5cdFx0c2IuYWRkQ2xhc3MoJ2Nsb3NlZCcpLnJlc2l6YWJsZSgnZGVzdHJveScpO1xuXHR9XG59XG5mdW5jdGlvbiBfZ2V0U2VsZkF1ZGlvQ2xpZW50KCkge1xuXHRjb25zdCB2dyA9ICQoJy52aWRlby1jb250YWluZXJbZGF0YS1jbGllbnQtdHlwZT1XRUJDQU1dW2RhdGEtY2xpZW50LXVpZD0nICsgUm9vbS5nZXRPcHRpb25zKCkudWlkICsgJ10nKTtcblx0aWYgKHZ3Lmxlbmd0aCA+IDApIHtcblx0XHRjb25zdCB2ID0gdncuZmlyc3QoKS5kYXRhKCk7XG5cdFx0aWYgKFZpZGVvVXRpbC5oYXNNaWModi5zdHJlYW0oKSkpIHtcblx0XHRcdHJldHVybiB2O1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gbnVsbDtcbn1cbmZ1bmN0aW9uIF9wcmV2ZW50S2V5ZG93bihlKSB7XG5cdGNvbnN0IGJhc2UgPSAkKGUudGFyZ2V0KTtcblx0aWYgKGUudGFyZ2V0LmlzQ29udGVudEVkaXRhYmxlID09PSB0cnVlIHx8IGJhc2UuaXMoJ3RleHRhcmVhLCBpbnB1dDpub3QoW3JlYWRvbmx5XSk6bm90KFt0eXBlPXJhZGlvXSk6bm90KFt0eXBlPWNoZWNrYm94XSknKSkge1xuXHRcdHJldHVybjtcblx0fVxuXHRpZiAoZS53aGljaCA9PT0gOCkgeyAvLyBiYWNrc3BhY2Vcblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0ZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cbn1cbmZ1bmN0aW9uIF9fa2V5UHJlc3NlZChob3RrZXksIGUpIHtcblx0Y29uc3QgY29kZSA9IGUuY29kZTtcblx0cmV0dXJuIGhvdGtleS5hbHQgPT09IGUuYWx0S2V5XG5cdFx0JiYgaG90a2V5LmN0cmwgPT09IGUuY3RybEtleVxuXHRcdCYmIGhvdGtleS5zaGlmdCA9PT0gZS5zaGlmdEtleVxuXHRcdCYmIGhvdGtleS5jb2RlLnRvVXBwZXJDYXNlKCkgPT09IChjb2RlID8gY29kZS50b1VwcGVyQ2FzZSgpIDogJycpO1xufVxuZnVuY3Rpb24gX2tleUhhbmRsZXIoZSkge1xuXHRpZiAoX19rZXlQcmVzc2VkKG9wdGlvbnMua2V5Y29kZS5hcnJhbmdlLCBlKSkge1xuXHRcdFZpZGVvVXRpbC5hcnJhbmdlKCk7XG5cdH0gZWxzZSBpZiAoX19rZXlQcmVzc2VkKG9wdGlvbnMua2V5Y29kZS5hcnJhbmdlcmVzaXplLCBlKSkge1xuXHRcdFZpZGVvVXRpbC5hcnJhbmdlUmVzaXplKFZpZGVvU2V0dGluZ3MubG9hZCgpKTtcblx0fSBlbHNlIGlmIChfX2tleVByZXNzZWQob3B0aW9ucy5rZXljb2RlLm11dGVvdGhlcnMsIGUpKSB7XG5cdFx0Y29uc3QgdiA9IF9nZXRTZWxmQXVkaW9DbGllbnQoKTtcblx0XHRpZiAodiAhPT0gbnVsbCkge1xuXHRcdFx0VmlkZW9NYW5hZ2VyLmNsaWNrTXV0ZU90aGVycyhSb29tLmdldE9wdGlvbnMoKS51aWQpO1xuXHRcdH1cblx0fSBlbHNlIGlmIChfX2tleVByZXNzZWQob3B0aW9ucy5rZXljb2RlLm11dGUsIGUpKSB7XG5cdFx0Y29uc3QgdiA9IF9nZXRTZWxmQXVkaW9DbGllbnQoKTtcblx0XHRpZiAodiAhPT0gbnVsbCkge1xuXHRcdFx0di5tdXRlKCF2LmlzTXV0ZWQoKSk7XG5cdFx0fVxuXHR9IGVsc2UgaWYgKF9fa2V5UHJlc3NlZChvcHRpb25zLmtleWNvZGUucXVpY2twb2xsLCBlKSkge1xuXHRcdHF1aWNrUG9sbEFjdGlvbignb3BlbicpO1xuXHR9XG5cdGlmIChlLndoaWNoID09PSAyNykge1xuXHRcdCQoJyN3Yi1yZW5hbWUtbWVudScpLmhpZGUoKTtcblx0fVxufVxuZnVuY3Rpb24gX21vdXNlSGFuZGxlcihlKSB7XG5cdGlmIChlLndoaWNoID09PSAxKSB7XG5cdFx0JCgnI3diLXJlbmFtZS1tZW51JykuaGlkZSgpO1xuXHR9XG59XG5mdW5jdGlvbiBfc2JXaWR0aCgpIHtcblx0aWYgKHNiID09PSB1bmRlZmluZWQpIHtcblx0XHRzYiA9ICQoJy5yb29tLWJsb2NrIC5zaWRlYmFyJyk7XG5cdH1cblx0cmV0dXJuIHNiID09PSB1bmRlZmluZWQgPyAwIDogc2Iud2lkdGgoKSArIHBhcnNlSW50KHNiLmNzcyhzYlNpZGUpKTtcbn1cbmZ1bmN0aW9uIF9zZXRTaXplKCkge1xuXHRjb25zdCBzYlcgPSBfc2JXaWR0aCgpXG5cdFx0LCBob2xkZXIgPSAkKCcucm9vbS1ibG9jaycpO1xuXHQoJCgnLm1haW4ucm9vbScpWzBdKS5zdHlsZS5zZXRQcm9wZXJ0eSgnLS1zaWRlYmFyLXdpZHRoJywgc2JXICsgJ3B4Jyk7XG5cdGlmIChzYlcgPiAyMzYpIHtcblx0XHRob2xkZXIuYWRkQ2xhc3MoJ2JpZycpLnJlbW92ZUNsYXNzKCduYXJyb3cnKTtcblx0fSBlbHNlIHtcblx0XHRob2xkZXIucmVtb3ZlQ2xhc3MoJ2JpZycpLmFkZENsYXNzKCduYXJyb3cnKTtcblx0fVxufVxuZnVuY3Rpb24gX3JlbG9hZCgpIHtcblx0aWYgKCEhb3B0aW9ucyAmJiAhIW9wdGlvbnMucmVsb2FkVXJsKSB7XG5cdFx0d2luZG93LmxvY2F0aW9uLmhyZWYgPSBvcHRpb25zLnJlbG9hZFVybDtcblx0fSBlbHNlIHtcblx0XHR3aW5kb3cubG9jYXRpb24ucmVsb2FkKCk7XG5cdH1cbn1cbmZ1bmN0aW9uIF9jbG9zZSgpIHtcblx0X3VubG9hZCgpO1xuXHQkKFwiLnJvb20tYmxvY2tcIikucmVtb3ZlKCk7XG5cdCQoXCIjY2hhdFBhbmVsXCIpLnJlbW92ZSgpO1xuXHQkKCcjZGlzY29ubmVjdGVkLWRsZycpXG5cdFx0Lm1vZGFsKCdzaG93Jylcblx0XHQub2ZmKCdoaWRlLmJzLm1vZGFsJylcblx0XHQub24oJ2hpZGUuYnMubW9kYWwnLCBfcmVsb2FkKTtcbn1cbmZ1bmN0aW9uIF9zYkFkZFJlc2l6YWJsZSgpIHtcblx0c2IucmVzaXphYmxlKHtcblx0XHRoYW5kbGVzOiBTZXR0aW5ncy5pc1J0bCA/ICd3JyA6ICdlJ1xuXHRcdCwgc3RvcDogZnVuY3Rpb24oKSB7XG5cdFx0XHRfc2V0U2l6ZSgpO1xuXHRcdH1cblx0fSk7XG59XG5mdW5jdGlvbiBfbG9hZCgpIHtcblx0JCgnYm9keScpLmFkZENsYXNzKCduby1oZWFkZXInKTtcblx0V2lja2V0LkV2ZW50LnN1YnNjcmliZShcIi93ZWJzb2NrZXQvY2xvc2VkXCIsIF9jbG9zZSk7XG5cdFdpY2tldC5FdmVudC5zdWJzY3JpYmUoXCIvd2Vic29ja2V0L2Vycm9yXCIsIF9jbG9zZSk7XG5cdCQod2luZG93KS5vbigna2V5ZG93bi5vcGVubWVldGluZ3MnLCBfcHJldmVudEtleWRvd24pO1xuXHQkKHdpbmRvdykub24oJ2tleXVwLm9wZW5tZWV0aW5ncycsIF9rZXlIYW5kbGVyKTtcblx0JCh3aW5kb3cpLm9uKCdrZXlkb3duLm9tLXNpcCcsIFNpcERpYWxlci5rZXlEb3duKTtcblx0JCh3aW5kb3cpLm9uKCdrZXl1cC5vbS1zaXAnLCBTaXBEaWFsZXIua2V5VXApO1xuXHQkKGRvY3VtZW50KS5jbGljayhfbW91c2VIYW5kbGVyKTtcblx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBfYWRkTm9TbGVlcCwgZmFsc2UpO1xuXHRTaXBEaWFsZXIuaW5pdCgpO1xufVxuZnVuY3Rpb24gX2FkZE5vU2xlZXAoKSB7XG5cdF9yZW1vdmVOb1NsZWVwKCk7XG5cdG5vU2xlZXAgPSBuZXcgTm9TbGVlcCgpO1xuXHRub1NsZWVwLmVuYWJsZSgpO1xufVxuZnVuY3Rpb24gX3JlbW92ZU5vU2xlZXAoKSB7XG5cdGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgX2FkZE5vU2xlZXAsIGZhbHNlKTtcblx0aWYgKG5vU2xlZXApIHtcblx0XHRub1NsZWVwLmRpc2FibGUoKTtcblx0XHRub1NsZWVwID0gbnVsbDtcblx0fVxufVxuZnVuY3Rpb24gX3VubG9hZCgpIHtcblx0JCgnYm9keScpLnJlbW92ZUNsYXNzKCduby1oZWFkZXInKTtcblx0V2lja2V0LkV2ZW50LnVuc3Vic2NyaWJlKFwiL3dlYnNvY2tldC9jbG9zZWRcIiwgX2Nsb3NlKTtcblx0V2lja2V0LkV2ZW50LnVuc3Vic2NyaWJlKFwiL3dlYnNvY2tldC9lcnJvclwiLCBfY2xvc2UpO1xuXHRpZiAodHlwZW9mKFdiQXJlYSkgPT09ICdvYmplY3QnKSB7XG5cdFx0V2JBcmVhLmRlc3Ryb3koKTtcblx0XHR3aW5kb3cuV2JBcmVhID0gdW5kZWZpbmVkO1xuXHR9XG5cdGlmICh0eXBlb2YoVmlkZW9TZXR0aW5ncykgPT09ICdvYmplY3QnKSB7XG5cdFx0VmlkZW9TZXR0aW5ncy5jbG9zZSgpO1xuXHR9XG5cdGlmICh0eXBlb2YoVmlkZW9NYW5hZ2VyKSA9PT0gJ29iamVjdCcpIHtcblx0XHRWaWRlb01hbmFnZXIuZGVzdHJveSgpO1xuXHR9XG5cdCQoJy51aS1kaWFsb2cudXNlci12aWRlbycpLnJlbW92ZSgpO1xuXHQkKHdpbmRvdykub2ZmKCdrZXl1cC5vcGVubWVldGluZ3MnKTtcblx0JCh3aW5kb3cpLm9mZigna2V5ZG93bi5vcGVubWVldGluZ3MnKTtcblx0JCh3aW5kb3cpLm9mZigncmVzaXplLm9td2InKTtcblx0JCh3aW5kb3cpLm9mZigna2V5ZG93bi5vbS1zaXAnKTtcblx0JCh3aW5kb3cpLm9mZigna2V5dXAub20tc2lwJyk7XG5cdCQoZG9jdW1lbnQpLm9mZignY2xpY2snLCBfbW91c2VIYW5kbGVyKTtcblx0c2IgPSB1bmRlZmluZWQ7XG5cdFNoYXJlci5jbG9zZSgpO1xuXHRfcmVtb3ZlTm9TbGVlcCgpO1xufVxuZnVuY3Rpb24gX3Nob3dDbGlwYm9hcmQodHh0KSB7XG5cdGNvbnN0IGRsZyA9ICQoJyNjbGlwYm9hcmQtZGlhbG9nJyk7XG5cdGRsZy5maW5kKCdwIC50ZXh0JykudGV4dCh0eHQpO1xuXHRkbGcuZGlhbG9nKHtcblx0XHRyZXNpemFibGU6IGZhbHNlXG5cdFx0LCBoZWlnaHQ6IFwiYXV0b1wiXG5cdFx0LCB3aWR0aDogNDAwXG5cdFx0LCBtb2RhbDogdHJ1ZVxuXHRcdCwgYnV0dG9uczogW1xuXHRcdFx0e1xuXHRcdFx0XHR0ZXh0OiBkbGcuZGF0YSgnYnRuLW9rJylcblx0XHRcdFx0LCBjbGljazogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0JCh0aGlzKS5kaWFsb2coJ2Nsb3NlJyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRdXG5cdH0pO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblx0aW5pdDogX2luaXRcblx0LCBnZXRNZW51SGVpZ2h0OiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gbWVudUhlaWdodDtcblx0fVxuXHQsIGdldE9wdGlvbnM6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0eXBlb2Yob3B0aW9ucykgPT09ICdvYmplY3QnID8gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeShvcHRpb25zKSkgOiB7fTtcblx0fVxuXHQsIGxvYWQ6IF9sb2FkXG5cdCwgdW5sb2FkOiBfdW5sb2FkXG5cdCwgc2hvd0NsaXBib2FyZDogX3Nob3dDbGlwYm9hcmRcblx0LCBxdWlja1BvbGw6IFF1aWNrUG9sbC51cGRhdGVcblx0LCBoYXNSaWdodDogVXNlckxpc3RVdGlsLmhhc1JpZ2h0XG5cdCwgc2V0Q3NzVmFyOiBmdW5jdGlvbihrZXksIHZhbCkge1xuXHRcdCgkKCcubWFpbi5yb29tJylbMF0pLnN0eWxlLnNldFByb3BlcnR5KGtleSwgdmFsKTtcblx0fVxuXHQsIGFkZENsaWVudDogVXNlckxpc3QuYWRkQ2xpZW50XG5cdCwgdXBkYXRlQ2xpZW50OiBVc2VyTGlzdC51cGRhdGVDbGllbnRcblx0LCByZW1vdmVDbGllbnQ6IFVzZXJMaXN0LnJlbW92ZUNsaWVudFxuXHQsIHJlbW92ZU90aGVyczogVXNlckxpc3QucmVtb3ZlT3RoZXJzXG5cdCwgZ2V0Q2xpZW50OiBVc2VyTGlzdC5nZXRDbGllbnRcbn07XG4iLCIvKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMCAqL1xuY29uc3QgVmlkZW9VdGlsID0gcmVxdWlyZSgnLi4vc2V0dGluZ3MvdmlkZW8tdXRpbCcpO1xuY29uc3QgVmlkZW9NZ3JVdGlsID0gcmVxdWlyZSgnLi92aWRlby1tYW5hZ2VyLXV0aWwnKTtcblxuY29uc3QgU0hBUkVfU1RBUlRJTkcgPSAnc3RhcnRpbmcnXG5cdCwgU0hBUkVfU1RBUlRFRCA9ICdzdGFydGVkJ1xuXHQsIFNIQVJFX1NUT1BQRUQgPSAnc3RvcHBlZCc7XG5cbmxldCBzaGFyZXIsIHR5cGUsIGZwcywgc2J0biwgcmJ0blxuXHQsIHNoYXJlU3RhdGUgPSBTSEFSRV9TVE9QUEVELCByZWNTdGF0ZSA9IFNIQVJFX1NUT1BQRUQ7XG5cbi8qKlxuICogUmUtZW50ZXJpbmcgdGhlIHJvb20gc2hvdWxkIHJlc2V0IHNldHRpbmdzLlxuICovXG5mdW5jdGlvbiByZXNldCgpIHtcblx0c2hhcmVTdGF0ZSA9IFNIQVJFX1NUT1BQRUQ7XG5cdHJlY1N0YXRlID0gU0hBUkVfU1RPUFBFRDtcbn1cblxuZnVuY3Rpb24gX2luaXQoKSB7XG5cdHJlc2V0KCk7XG5cdHNoYXJlciA9ICQoJyNzaGFyZXInKS5kaWFsb2coe1xuXHRcdGFwcGVuZFRvOiAnLnJvb20tYmxvY2sgLnJvb20tY29udGFpbmVyJ1xuXHRcdCwgY2xhc3Nlczoge1xuXHRcdFx0J3VpLWRpYWxvZyc6ICdzaGFyZXInXG5cdFx0XHQsICd1aS1kaWFsb2ctdGl0bGViYXInOiAnJ1xuXHRcdH1cblx0XHQsIHdpZHRoOiA0NTBcblx0XHQsIGF1dG9PcGVuOiBmYWxzZVxuXHRcdCwgcmVzaXphYmxlOiBmYWxzZVxuXHR9KTtcblx0Y29uc3QgdWkgPSBzaGFyZXIuY2xvc2VzdCgnLnVpLWRpYWxvZycpO1xuXHRjb25zdCBwYXJlbnQgPSAkKCcucm9vbS1ibG9jayAucm9vbS1jb250YWluZXIgLnNiLXdiJyk7XG5cdHVpLmRyYWdnYWJsZSgnb3B0aW9uJywgJ2NvbnRhaW5tZW50JywgcGFyZW50KTtcblx0Zml4SlF1ZXJ5VUlEaWFsb2dUb3VjaChzaGFyZXIpO1xuXG5cdGlmICghVmlkZW9VdGlsLnNoYXJpbmdTdXBwb3J0ZWQoKSkge1xuXHRcdHNoYXJlci5maW5kKCcuY29udGFpbmVyJykucmVtb3ZlKCk7XG5cdFx0c2hhcmVyLmZpbmQoJy5hbGVydCcpLnNob3coKTtcblx0fSBlbHNlIHtcblx0XHR0eXBlID0gc2hhcmVyLmZpbmQoJ3NlbGVjdC50eXBlJyk7XG5cdFx0ZnBzID0gc2hhcmVyLmZpbmQoJ3NlbGVjdC5mcHMnKTtcblx0XHRfZGlzYWJsZShmcHMsIFZpZGVvVXRpbC5pc0VkZ2UoKSk7XG5cdFx0c2J0biA9IHNoYXJlci5maW5kKCcuc2hhcmUtc3RhcnQtc3RvcCcpLm9mZigpLmNsaWNrKGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKHNoYXJlU3RhdGUgPT09IFNIQVJFX1NUT1BQRUQpIHtcblx0XHRcdFx0X3NldFNoYXJlU3RhdGUoU0hBUkVfU1RBUlRJTkcpO1xuXHRcdFx0XHRWaWRlb01nclV0aWwuc2VuZE1lc3NhZ2Uoe1xuXHRcdFx0XHRcdGlkOiAnd2FubmFTaGFyZSdcblx0XHRcdFx0XHQsIHNoYXJlVHlwZTogdHlwZS52YWwoKVxuXHRcdFx0XHRcdCwgZnBzOiBmcHMudmFsKClcblx0XHRcdFx0fSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRWaWRlb01nclV0aWwuc2VuZE1lc3NhZ2Uoe1xuXHRcdFx0XHRcdGlkOiAncGF1c2VTaGFyaW5nJ1xuXHRcdFx0XHRcdCwgdWlkOiBfZ2V0U2hhcmVVaWQoKVxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHR9KTtcblx0XHRyYnRuID0gc2hhcmVyLmZpbmQoJy5yZWNvcmQtc3RhcnQtc3RvcCcpLm9mZigpO1xuXHRcdGlmIChSb29tLmdldE9wdGlvbnMoKS5hbGxvd1JlY29yZGluZykge1xuXHRcdFx0cmJ0bi5zaG93KCkuY2xpY2soZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmIChyZWNTdGF0ZSA9PT0gU0hBUkVfU1RPUFBFRCkge1xuXHRcdFx0XHRcdF9zZXRSZWNTdGF0ZShTSEFSRV9TVEFSVElORyk7XG5cdFx0XHRcdFx0VmlkZW9NZ3JVdGlsLnNlbmRNZXNzYWdlKHtcblx0XHRcdFx0XHRcdGlkOiAnd2FubmFSZWNvcmQnXG5cdFx0XHRcdFx0XHQsIHNoYXJlVHlwZTogdHlwZS52YWwoKVxuXHRcdFx0XHRcdFx0LCBmcHM6IGZwcy52YWwoKVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFZpZGVvTWdyVXRpbC5zZW5kTWVzc2FnZSh7XG5cdFx0XHRcdFx0XHRpZDogJ3N0b3BSZWNvcmQnXG5cdFx0XHRcdFx0XHQsIHVpZDogX2dldFNoYXJlVWlkKClcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJidG4uaGlkZSgpO1xuXHRcdH1cblx0fVxufVxuZnVuY3Rpb24gX2Rpc2FibGUoZSwgc3RhdGUpIHtcblx0ZS5wcm9wKCdkaXNhYmxlZCcsIHN0YXRlKTtcblx0aWYgKHN0YXRlKSB7XG5cdFx0ZS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcblx0fSBlbHNlIHtcblx0XHRlLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xuXHR9XG59XG5mdW5jdGlvbiBfdHlwZURpc2FibGVkKCkge1xuXHRyZXR1cm4gVmlkZW9VdGlsLmlzRWRnZSgpIHx8IFZpZGVvVXRpbC5pc0Nocm9tZSgpIHx8IFZpZGVvVXRpbC5pc0VkZ2VDaHJvbWl1bSgpO1xufVxuZnVuY3Rpb24gX3NldEJ0blN0YXRlKGJ0biwgc3RhdGUpIHtcblx0Y29uc3QgZGlzID0gU0hBUkVfU1RPUFBFRCAhPT0gc3RhdGVcblx0XHQsIHR5cGVEaXMgPSBfdHlwZURpc2FibGVkKCk7XG5cdF9kaXNhYmxlKHR5cGUsIGRpcyk7XG5cdF9kaXNhYmxlKGZwcywgZGlzIHx8IHR5cGVEaXMpO1xuXHRidG4uZmluZCgnc3BhbicpLnRleHQoYnRuLmRhdGEoZGlzID8gJ3N0b3AnIDogJ3N0YXJ0JykpO1xuXHRpZiAoZGlzKSB7XG5cdFx0YnRuLmFkZENsYXNzKCdzdG9wJyk7XG5cdH0gZWxzZSB7XG5cdFx0YnRuLnJlbW92ZUNsYXNzKCdzdG9wJyk7XG5cdH1cblx0X2Rpc2FibGUoYnRuLCBzdGF0ZSA9PT0gU0hBUkVfU1RBUlRJTkcpO1xuXHRfZGlzYWJsZShidG4sIHN0YXRlID09PSBTSEFSRV9TVEFSVElORyk7XG59XG5mdW5jdGlvbiBfc2V0U2hhcmVTdGF0ZShzdGF0ZSkge1xuXHRzaGFyZVN0YXRlID0gc3RhdGU7XG5cdF9zZXRCdG5TdGF0ZShzYnRuLCBzdGF0ZSk7XG59XG5mdW5jdGlvbiBfc2V0UmVjU3RhdGUoc3RhdGUpIHtcblx0cmVjU3RhdGUgPSBzdGF0ZTtcblx0X3NldEJ0blN0YXRlKHJidG4sIHN0YXRlKTtcbn1cbmZ1bmN0aW9uIF9nZXRTaGFyZVVpZCgpIHtcblx0Y29uc3QgdiA9ICQoJ2RpdltkYXRhLWNsaWVudC11aWQ9XCInICsgUm9vbS5nZXRPcHRpb25zKCkudWlkICsgJ1wiXVtkYXRhLWNsaWVudC10eXBlPVwiU0NSRUVOXCJdJyk7XG5cdHJldHVybiB2ICYmIHYuZGF0YSgpICYmIHYuZGF0YSgpLnN0cmVhbSgpID8gdi5kYXRhKCkuc3RyZWFtKCkudWlkIDogJyc7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRTSEFSRV9TVEFSVElORzogU0hBUkVfU1RBUlRJTkdcblx0LCBTSEFSRV9TVEFSVEVEOiBTSEFSRV9TVEFSVEVEXG5cdCwgU0hBUkVfU1RPUFBFRDogU0hBUkVfU1RPUFBFRFxuXG5cdCwgaW5pdDogX2luaXRcblx0LCBvcGVuOiBmdW5jdGlvbigpIHtcblx0XHRpZiAoc2hhcmVyICYmIHNoYXJlci5kaWFsb2coJ2luc3RhbmNlJykpIHtcblx0XHRcdHNoYXJlci5kaWFsb2coJ29wZW4nKTtcblx0XHR9XG5cdH1cblx0LCBjbG9zZTogZnVuY3Rpb24oKSB7XG5cdFx0aWYgKHNoYXJlciAmJiBzaGFyZXIuZGlhbG9nKCdpbnN0YW5jZScpKSB7XG5cdFx0XHRzaGFyZXIuZGlhbG9nKCdjbG9zZScpO1xuXHRcdH1cblx0fVxuXHQsIHNldFNoYXJlU3RhdGU6IF9zZXRTaGFyZVN0YXRlXG5cdCwgc2V0UmVjU3RhdGU6IF9zZXRSZWNTdGF0ZVxuXHQsIGJhc2VDb25zdHJhaW50czogZnVuY3Rpb24oc2QpIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0dmlkZW86IHtcblx0XHRcdFx0ZnJhbWVSYXRlOiB7XG5cdFx0XHRcdFx0aWRlYWw6IHNkLmZwc1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHQsIGF1ZGlvOiBmYWxzZVxuXHRcdH07XG5cdH1cbn07XG4iLCIvKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMCAqL1xuZnVuY3Rpb24gX19hZGRTaXBUZXh0KHYpIHtcblx0Y29uc3QgdHh0ID0gJCgnLnNpcC1udW1iZXInKTtcblx0dHh0LnZhbCh0eHQudmFsKCkgKyB2KTtcbn1cbmZ1bmN0aW9uIF9fZXJhc2VTaXBUZXh0KCkge1xuXHRjb25zdCB0eHQgPSAkKCcuc2lwLW51bWJlcicpXG5cdFx0LCB0ID0gdHh0LnZhbCgpO1xuXHRpZiAoISF0KSB7XG5cdFx0dHh0LnZhbCh0LnN1YnN0cmluZygwLCB0Lmxlbmd0aCAtIDEpKTtcblx0fVxufVxuZnVuY3Rpb24gX3NpcEdldEtleShldnQpIHtcblx0bGV0IGsgPSAtMTtcblx0aWYgKGV2dC5rZXlDb2RlID4gNDcgJiYgZXZ0LmtleUNvZGUgPCA1OCkge1xuXHRcdGsgPSBldnQua2V5Q29kZSAtIDQ4O1xuXHR9XG5cdGlmIChldnQua2V5Q29kZSA+IDk1ICYmIGV2dC5rZXlDb2RlIDwgMTA2KSB7XG5cdFx0ayA9IGV2dC5rZXlDb2RlIC0gOTY7XG5cdH1cblx0cmV0dXJuIGs7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRpbml0OiBmdW5jdGlvbigpIHtcblx0XHQkKCcuc2lwIC5idXR0b24tcm93IGJ1dHRvbicpLm9mZigpLmNsaWNrKGZ1bmN0aW9uKCkge1xuXHRcdFx0X19hZGRTaXBUZXh0KCQodGhpcykuZGF0YSgndmFsdWUnKSk7XG5cdFx0fSk7XG5cdFx0JCgnI3NpcC1kaWFsZXItYnRuLWVyYXNlJykub2ZmKCkuY2xpY2soX19lcmFzZVNpcFRleHQpO1xuXHR9XG5cdCwga2V5RG93bjogZnVuY3Rpb24oZXZ0KSB7XG5cdFx0Y29uc3QgayA9IF9zaXBHZXRLZXkoZXZ0KTtcblx0XHRpZiAoayA+IDApIHtcblx0XHRcdCQoJyNzaXAtZGlhbGVyLWJ0bi0nICsgaykuYWRkQ2xhc3MoJ2JnLXdhcm5pbmcnKTtcblx0XHR9XG5cdH1cblx0LCBrZXlVcDogZnVuY3Rpb24oZXZ0KSB7XG5cdFx0aWYgKGV2dC5rZXkgPT09ICdCYWNrc3BhY2UnKSB7XG5cdFx0XHRfX2VyYXNlU2lwVGV4dCgpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRjb25zdCBrID0gX3NpcEdldEtleShldnQpO1xuXHRcdFx0aWYgKGsgPiAwKSB7XG5cdFx0XHRcdCQoJyNzaXAtZGlhbGVyLWJ0bi0nICsgaykucmVtb3ZlQ2xhc3MoJ2JnLXdhcm5pbmcnKTtcblx0XHRcdFx0X19hZGRTaXBUZXh0KGspO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufTsiLCIvKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMCAqL1xubGV0IG9wdGlvbnM7XG5cbmZ1bmN0aW9uIF9oYXNSaWdodChfaW5SaWdodHMsIF9yZWYpIHtcblx0Y29uc3QgcmVmID0gX3JlZiB8fCBvcHRpb25zLnJpZ2h0cztcblx0bGV0IF9yaWdodHM7XG5cdGlmIChBcnJheS5pc0FycmF5KF9pblJpZ2h0cykpIHtcblx0XHRfcmlnaHRzID0gX2luUmlnaHRzO1xuXHR9IGVsc2Uge1xuXHRcdGlmICgnU1VQRVJfTU9ERVJBVE9SJyA9PT0gX2luUmlnaHRzKSB7XG5cdFx0XHRyZXR1cm4gcmVmLmluY2x1ZGVzKF9pblJpZ2h0cyk7XG5cdFx0fVxuXHRcdF9yaWdodHMgPSBbX2luUmlnaHRzXTtcblx0fVxuXHRjb25zdCByaWdodHMgPSBbJ1NVUEVSX01PREVSQVRPUicsICdNT0RFUkFUT1InLCAuLi5fcmlnaHRzXTtcblx0Zm9yIChsZXQgaSA9IDA7IGkgPCByaWdodHMubGVuZ3RoOyArK2kpIHtcblx0XHRpZiAocmVmLmluY2x1ZGVzKHJpZ2h0c1tpXSkpIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0fVxuXHRyZXR1cm4gZmFsc2U7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRpbml0OiBmdW5jdGlvbihvcHRzKSB7XG5cdFx0b3B0aW9ucyA9IG9wdHM7XG5cdH1cblx0LCBoYXNSaWdodDogX2hhc1JpZ2h0XG59O1xuIiwiLyogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKSBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAgKi9cbmNvbnN0IFNldHRpbmdzID0gcmVxdWlyZSgnLi4vbWFpbi9zZXR0aW5ncycpO1xuY29uc3QgQ2hhdCA9IHJlcXVpcmUoJy4uL2NoYXQvY2hhdCcpO1xuY29uc3QgVmlkZW9VdGlsID0gcmVxdWlyZSgnLi4vc2V0dGluZ3MvdmlkZW8tdXRpbCcpO1xuY29uc3QgVmlkZW9TZXR0aW5ncyA9IHJlcXVpcmUoJy4uL3NldHRpbmdzL3NldHRpbmdzJyk7XG5cbmNvbnN0IE9tVXRpbCA9IHJlcXVpcmUoJy4uL21haW4vb211dGlscycpO1xuY29uc3QgVmlkZW9NYW5hZ2VyID0gcmVxdWlyZSgnLi92aWRlby1tYW5hZ2VyJyk7XG5jb25zdCBVc2VyTGlzdFV0aWwgPSByZXF1aXJlKCcuL3VzZXItbGlzdC11dGlsJyk7XG5jb25zdCBRdWlja1BvbGwgPSByZXF1aXJlKCcuL3F1aWNrLXBvbGwnKTtcblxubGV0IG9wdGlvbnM7XG5cbmZ1bmN0aW9uIF9fYWN0aXZpdHlBVkljb24oZWxlbSwgc2VsZWN0b3IsIHByZWRpY2F0ZSwgb25mdW5jLCBkaXNhYmxlZGZ1bmMpIHtcblx0Y29uc3QgaWNvbiA9IGVsZW0uZmluZChzZWxlY3Rvcik7XG5cdGlmIChwcmVkaWNhdGUoKSkge1xuXHRcdGljb24uc2hvdygpO1xuXHRcdGNvbnN0IG9uID0gb25mdW5jKClcblx0XHRcdCwgZGlzYWJsZWQgPSBkaXNhYmxlZGZ1bmMoKTtcblx0XHRpZiAoZGlzYWJsZWQpIHtcblx0XHRcdGljb24uYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGljb24ucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XG5cdFx0XHRpZiAob24pIHtcblx0XHRcdFx0aWNvbi5hZGRDbGFzcygnZW5hYmxlZCcpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aWNvbi5yZW1vdmVDbGFzcygnZW5hYmxlZCcpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpY29uLmF0dHIoJ3RpdGxlJywgaWNvbi5kYXRhKG9uID8gJ29uJyA6J29mZicpKTtcblx0fSBlbHNlIHtcblx0XHRpY29uLmhpZGUoKTtcblx0fVxuXHRyZXR1cm4gaWNvbjtcbn1cbmZ1bmN0aW9uIF9fYWN0aXZpdHlJY29uKGVsZW0sIHNlbGVjdG9yLCBwcmVkaWNhdGUsIGFjdGlvbiwgY29uZmlybSkge1xuXHRsZXQgaWNvbiA9IGVsZW0uZmluZChzZWxlY3Rvcik7XG5cdGlmIChwcmVkaWNhdGUoKSkge1xuXHRcdGlmIChpY29uLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0aWNvbiA9IE9tVXRpbC50bXBsKCcjdXNlci1hY3Rpb25zLXN0dWIgJyArIHNlbGVjdG9yKTtcblx0XHRcdGVsZW0uYXBwZW5kKGljb24pO1xuXHRcdH1cblx0XHRpY29uLm9mZigpO1xuXHRcdGlmIChjb25maXJtKSB7XG5cdFx0XHRpY29uLmNvbmZpcm1hdGlvbihjb25maXJtKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWNvbi5jbGljayhhY3Rpb24pO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRpY29uLmhpZGUoKTtcblx0fVxufVxuZnVuY3Rpb24gX19yaWdodEljb24oYywgZWxlbSwgcmlnaHRzLCBzZWxlY3RvciwgcHJlZGljYXRlKSB7XG5cdGNvbnN0IHNlbGYgPSBjLnVpZCA9PT0gb3B0aW9ucy51aWRcblx0XHQsIGhhc1JpZ2h0ID0gVXNlckxpc3RVdGlsLmhhc1JpZ2h0KHJpZ2h0cywgYy5yaWdodHMpO1xuXHRsZXQgaWNvbiA9IGVsZW0uZmluZChzZWxlY3Rvcik7XG5cdGlmIChwcmVkaWNhdGUoKSAmJiAhVXNlckxpc3RVdGlsLmhhc1JpZ2h0KCdTVVBFUl9NT0RFUkFUT1InLCBjLnJpZ2h0cykgJiYgKFxuXHRcdChzZWxmICYmIG9wdGlvbnMucXVlc3Rpb25zICYmICFoYXNSaWdodClcblx0XHR8fCAoIXNlbGYgJiYgVXNlckxpc3RVdGlsLmhhc1JpZ2h0KCdNT0RFUkFUT1InKSlcblx0KSkge1xuXHRcdGlmIChpY29uLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0aWNvbiA9IE9tVXRpbC50bXBsKCcjdXNlci1hY3Rpb25zLXN0dWIgJyArIHNlbGVjdG9yKTtcblx0XHRcdGVsZW0uYXBwZW5kKGljb24pO1xuXHRcdH1cblx0XHRpZiAoaGFzUmlnaHQpIHtcblx0XHRcdGljb24uYWRkQ2xhc3MoJ2dyYW50ZWQnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0aWNvbi5yZW1vdmVDbGFzcygnZ3JhbnRlZCcpXG5cdFx0fVxuXHRcdGljb24uYXR0cigndGl0bGUnLCBpY29uLmRhdGEoc2VsZiA/ICdyZXF1ZXN0JyA6IChoYXNSaWdodCA/ICdyZXZva2UnIDogJ2dyYW50JykpKTtcblx0XHRpY29uLm9mZigpLmNsaWNrKGZ1bmN0aW9uKCkge1xuXHRcdFx0T21VdGlsLnJvb21BY3Rpb24oe2FjdGlvbjogJ3RvZ2dsZVJpZ2h0JywgcmlnaHQ6IHJpZ2h0c1swXSwgdWlkOiBjLnVpZH0pO1xuXHRcdH0pO1xuXHR9IGVsc2Uge1xuXHRcdGljb24ucmVtb3ZlKCk7XG5cdH1cbn1cbmZ1bmN0aW9uIF9fcmlnaHRBdWRpb0ljb24oYywgZWxlbSkge1xuXHRfX3JpZ2h0SWNvbihjLCBlbGVtLCBbJ0FVRElPJ10sICcucmlnaHQuYXVkaW8nLCAoKSA9PiB0cnVlKTtcbn1cbmZ1bmN0aW9uIF9fcmlnaHRWaWRlb0ljb24oYywgZWxlbSkge1xuXHRfX3JpZ2h0SWNvbihjLCBlbGVtLCBbJ1ZJREVPJ10sICcucmlnaHQuY2FtZXJhJywgKCkgPT4gIW9wdGlvbnMuYXVkaW9Pbmx5KTtcbn1cbmZ1bmN0aW9uIF9fcmlnaHRPdGhlckljb25zKGMsIGVsZW0pIHtcblx0X19yaWdodEljb24oYywgZWxlbSwgWydQUkVTRU5URVInXSwgJy5yaWdodC5wcmVzZW50ZXInLCAoKSA9PiAhb3B0aW9ucy5pbnRlcnZpZXcgJiYgJCgnLndiLWFyZWEnKS5pcygnOnZpc2libGUnKSk7XG5cdF9fcmlnaHRJY29uKGMsIGVsZW0sIFsnV0hJVEVCT0FSRCcsICdQUkVTRU5URVInXSwgJy5yaWdodC53YicsICgpID0+ICFvcHRpb25zLmludGVydmlldyAmJiAkKCcud2ItYXJlYScpLmlzKCc6dmlzaWJsZScpKTtcblx0X19yaWdodEljb24oYywgZWxlbSwgWydTSEFSRSddLCAnLnJpZ2h0LnNjcmVlbi1zaGFyZScsICgpID0+IHRydWUpO1xuXHRfX3JpZ2h0SWNvbihjLCBlbGVtLCBbJ1JFTU9URV9DT05UUk9MJ10sICcucmlnaHQucmVtb3RlLWNvbnRyb2wnLCAoKSA9PiB0cnVlKTtcblx0X19yaWdodEljb24oYywgZWxlbSwgWydNT0RFUkFUT1InXSwgJy5yaWdodC5tb2RlcmF0b3InLCAoKSA9PiB0cnVlKTtcbn1cbmZ1bmN0aW9uIF9fc2V0U3RhdHVzKGMsIGxlKSB7XG5cdGNvbnN0IHN0YXR1cyA9IGxlLmZpbmQoJy51c2VyLXN0YXR1cycpXG5cdFx0LCBtb2RlID0gYy5sZXZlbCA9PSA1ID8gJ21vZCcgOiAoYy5sZXZlbCA9PSAzID8gJ3diJyA6ICd1c2VyJyk7XG5cdHN0YXR1cy5yZW1vdmVDbGFzcygnbW9kIHdiIHVzZXInKTtcblx0c3RhdHVzLmF0dHIoJ3RpdGxlJywgc3RhdHVzLmRhdGEobW9kZSkpLmFkZENsYXNzKG1vZGUpO1xuXHRsZS5kYXRhKCdsZXZlbCcsIGMubGV2ZWwpO1xufVxuZnVuY3Rpb24gX191cGRhdGVDb3VudCgpIHtcblx0JCgnI3Jvb20tc2lkZWJhci11c2Vycy10YWIgLnVzZXItY291bnQnKS50ZXh0KCQoJyNyb29tLXNpZGViYXItdGFiLXVzZXJzIC51c2VyLWxpc3QgLnVzZXJzIC51c2VyLmVudHJ5JykubGVuZ3RoKTtcbn1cbmZ1bmN0aW9uIF9fc29ydFVzZXJMaXN0KCkge1xuXHRjb25zdCBjb250YWluZXIgPSAkKCcjcm9vbS1zaWRlYmFyLXRhYi11c2VycyAudXNlci1saXN0IC51c2VycycpO1xuXHRjb250YWluZXIuZmluZCgnLnVzZXIuZW50cnknKS5zb3J0KChfdTEsIF91MikgPT4ge1xuXHRcdGNvbnN0IHUxID0gJChfdTEpXG5cdFx0XHQsIHUyID0gJChfdTIpO1xuXHRcdHJldHVybiB1Mi5kYXRhKCdsZXZlbCcpIC0gdTEuZGF0YSgnbGV2ZWwnKSB8fCB1MS5hdHRyKCd0aXRsZScpLmxvY2FsZUNvbXBhcmUodTIuYXR0cigndGl0bGUnKSk7XG5cdH0pLmFwcGVuZFRvKGNvbnRhaW5lcik7XG59XG5cblxuZnVuY3Rpb24gX2dldENsaWVudCh1aWQpIHtcblx0cmV0dXJuICQoJyN1c2VyJyArIHVpZCk7XG59XG5mdW5jdGlvbiBfYWRkQ2xpZW50KF9jbGllbnRzKSB7XG5cdGlmICghb3B0aW9ucykge1xuXHRcdHJldHVybjsgLy90b28gZWFybHlcblx0fVxuXHRjb25zdCBjbGllbnRzID0gQXJyYXkuaXNBcnJheShfY2xpZW50cykgPyBfY2xpZW50cyA6IFtfY2xpZW50c107XG5cdGNsaWVudHMuZm9yRWFjaChjID0+IHtcblx0XHRjb25zdCBzZWxmID0gYy51aWQgPT09IG9wdGlvbnMudWlkO1xuXHRcdGxldCBsZSA9IF9nZXRDbGllbnQoYy51aWQpO1xuXHRcdGlmIChsZS5sZW5ndGggPT09IDApIHtcblx0XHRcdGxlID0gT21VdGlsLnRtcGwoJyN1c2VyLWVudHJ5LXN0dWInLCAndXNlcicgKyBjLnVpZCk7XG5cdFx0XHRsZS5hdHRyKCdpZCcsICd1c2VyJyArIGMudWlkKVxuXHRcdFx0XHQuYXR0cignZGF0YS11c2VyaWQnLCBjLnVzZXIuaWQpXG5cdFx0XHRcdC5hdHRyKCdkYXRhLXVpZCcsIGMudWlkKTtcblx0XHRcdGlmIChzZWxmKSB7XG5cdFx0XHRcdGxlLmFkZENsYXNzKCdjdXJyZW50Jyk7XG5cdFx0XHR9XG5cdFx0XHQkKCcjcm9vbS1zaWRlYmFyLXRhYi11c2VycyAudXNlci1saXN0IC51c2VycycpLmFwcGVuZChsZSk7XG5cdFx0fVxuXHRcdF91cGRhdGVDbGllbnQoYyk7XG5cdH0pO1xuXHRfX3VwZGF0ZUNvdW50KCk7XG5cdF9fc29ydFVzZXJMaXN0KCk7XG59XG5mdW5jdGlvbiBfdXBkYXRlQ2xpZW50KGMpIHtcblx0aWYgKCFvcHRpb25zKSB7XG5cdFx0cmV0dXJuOyAvL3RvbyBlYXJseVxuXHR9XG5cdGNvbnN0IHNlbGYgPSBjLnVpZCA9PT0gb3B0aW9ucy51aWRcblx0XHQsIGxlID0gX2dldENsaWVudChjLnVpZClcblx0XHQsIHNlbGZDYW1TdHJlYW0gPSBjLnN0cmVhbXMuZmluZChzID0+IHMudHlwZSA9PT0gJ1dFQkNBTScpXG5cdFx0LCBoYXNBdWRpbyA9IFZpZGVvVXRpbC5oYXNNaWMoc2VsZiAmJiBzZWxmQ2FtU3RyZWFtID8gc2VsZkNhbVN0cmVhbSA6IGMpXG5cdFx0LCBoYXNWaWRlbyA9IFZpZGVvVXRpbC5oYXNDYW0oc2VsZiAmJiBzZWxmQ2FtU3RyZWFtID8gc2VsZkNhbVN0cmVhbSA6IGMpXG5cdFx0LCBzcGVha3MgPSBsZS5maW5kKCcuYXVkaW8tYWN0aXZpdHknKTtcblx0aWYgKGxlLmxlbmd0aCA9PT0gMCkge1xuXHRcdHJldHVybjtcblx0fVxuXHRfX3NldFN0YXR1cyhjLCBsZSk7XG5cdGlmIChoYXNWaWRlbyB8fCBoYXNBdWRpbykge1xuXHRcdGlmIChsZS5maW5kKCcucmVzdGFydCcpLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0bGUucHJlcGVuZChPbVV0aWwudG1wbCgnI3VzZXItYXYtcmVzdGFydCcpLmNsaWNrKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0VmlkZW9NYW5hZ2VyLnJlZnJlc2goYy51aWQpO1xuXHRcdFx0fSkpO1xuXHRcdH1cblx0fSBlbHNlIHtcblx0XHRsZS5maW5kKCcucmVzdGFydCcpLnJlbW92ZSgpO1xuXHR9XG5cdHNwZWFrcy5oaWRlKCkucmVtb3ZlQ2xhc3MoJ2NsaWNrYWJsZScpLmF0dHIoJ3RpdGxlJywgc3BlYWtzLmRhdGEoJ3NwZWFrcycpKS5vZmYoKTtcblx0aWYgKGhhc0F1ZGlvKSB7XG5cdFx0c3BlYWtzLnNob3coKTtcblx0XHRpZihVc2VyTGlzdFV0aWwuaGFzUmlnaHQoJ01VVEVfT1RIRVJTJykpIHtcblx0XHRcdHNwZWFrcy5hZGRDbGFzcygnY2xpY2thYmxlJykuY2xpY2soZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRWaWRlb01hbmFnZXIuY2xpY2tNdXRlT3RoZXJzKGMudWlkKTtcblx0XHRcdH0pLmF0dHIoJ3RpdGxlJywgc3BlYWtzLmF0dHIoJ3RpdGxlJykgKyBzcGVha3MuZGF0YSgnbXV0ZScpKTtcblx0XHR9XG5cdH1cblx0bGUuYXR0cigndGl0bGUnLCBjLnVzZXIuZGlzcGxheU5hbWUpXG5cdFx0LmNzcygnYmFja2dyb3VuZC1pbWFnZScsICd1cmwoJyArIGMudXNlci5waWN0dXJlVXJpICsgJyknKVxuXHRcdC5maW5kKCcudXNlci5uYW1lJykudGV4dChjLnVzZXIuZGlzcGxheU5hbWUpO1xuXG5cdGlmIChjLnVzZXIuaWQgIT09IC0xKSB7XG5cdFx0Y29uc3QgYWN0aW9ucyA9IGxlLmZpbmQoJy51c2VyLmFjdGlvbnMnKTtcblx0XHRfX3JpZ2h0VmlkZW9JY29uKGMsIGFjdGlvbnMpO1xuXHRcdF9fcmlnaHRBdWRpb0ljb24oYywgYWN0aW9ucyk7XG5cdFx0X19yaWdodE90aGVySWNvbnMoYywgYWN0aW9ucyk7XG5cdFx0X19hY3Rpdml0eUljb24oYWN0aW9ucywgJy5raWNrJ1xuXHRcdFx0LCAoKSA9PiAhc2VsZiAmJiBVc2VyTGlzdFV0aWwuaGFzUmlnaHQoJ01PREVSQVRPUicpICYmICFVc2VyTGlzdFV0aWwuaGFzUmlnaHQoJ1NVUEVSX01PREVSQVRPUicsIGMucmlnaHRzKVxuXHRcdFx0LCBudWxsXG5cdFx0XHQsIHtcblx0XHRcdFx0Y29uZmlybWF0aW9uRXZlbnQ6ICdvbS1raWNrJ1xuXHRcdFx0XHQsIHBsYWNlbWVudDogU2V0dGluZ3MuaXNSdGwgPyAnbGVmdCcgOiAncmlnaHQnXG5cdFx0XHRcdCwgb25Db25maXJtOiAoKSA9PiBPbVV0aWwucm9vbUFjdGlvbih7YWN0aW9uOiAna2ljaycsIHVpZDogYy51aWR9KVxuXHRcdFx0fSk7XG5cdFx0X19hY3Rpdml0eUljb24oYWN0aW9ucywgJy5wcml2YXRlLWNoYXQnXG5cdFx0XHQsICgpID0+IG9wdGlvbnMudXNlcklkICE9PSBjLnVzZXIuaWQgJiYgJCgnI2NoYXRQYW5lbCcpLmlzKCc6dmlzaWJsZScpXG5cdFx0XHQsIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRDaGF0LmFkZFRhYignY2hhdFRhYi11JyArIGMudXNlci5pZCwgYy51c2VyLmRpc3BsYXlOYW1lKTtcblx0XHRcdFx0Q2hhdC5vcGVuKCk7XG5cdFx0XHRcdCQoJyNjaGF0TWVzc2FnZSAud3lzaXd5Zy1lZGl0b3InKS5jbGljaygpO1xuXHRcdFx0fSk7XG5cdH1cblx0aWYgKHNlbGYpIHtcblx0XHRvcHRpb25zLnJpZ2h0cyA9IGMucmlnaHRzO1xuXHRcdFF1aWNrUG9sbC5zZXRSaWdodHMoKTtcblx0XHRvcHRpb25zLmFjdGl2aXRpZXMgPSBjLmFjdGl2aXRpZXM7XG5cdFx0Y29uc3QgaGVhZGVyID0gJCgnI3Jvb20tc2lkZWJhci10YWItdXNlcnMgLmhlYWRlcicpO1xuXHRcdGhlYWRlci5maW5kKCcub20taWNvbi5zZXR0aW5ncycpLm9mZigpLmNsaWNrKFZpZGVvU2V0dGluZ3Mub3Blbik7XG5cdFx0X19yaWdodFZpZGVvSWNvbihjLCBoZWFkZXIpO1xuXHRcdF9fYWN0aXZpdHlBVkljb24oXG5cdFx0XHRcdGhlYWRlclxuXHRcdFx0XHQsICcuYWN0aXZpdHkuY2FtJ1xuXHRcdFx0XHQsICgpID0+ICFvcHRpb25zLmF1ZGlvT25seSAmJiBVc2VyTGlzdFV0aWwuaGFzUmlnaHQoVmlkZW9VdGlsLkNBTV9BQ1RJVklUWSlcblx0XHRcdFx0LCAoKSA9PiBoYXNWaWRlb1xuXHRcdFx0XHQsICgpID0+IFNldHRpbmdzLmxvYWQoKS52aWRlby5jYW0gPCAwKVxuXHRcdFx0Lm9mZigpLmNsaWNrKGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRWaWRlb01hbmFnZXIudG9nZ2xlQWN0aXZpdHkoVmlkZW9VdGlsLkNBTV9BQ1RJVklUWSk7XG5cdFx0XHR9KTs7XG5cdFx0X19yaWdodEF1ZGlvSWNvbihjLCBoZWFkZXIpO1xuXHRcdF9fYWN0aXZpdHlBVkljb24oXG5cdFx0XHRcdGhlYWRlclxuXHRcdFx0XHQsICcuYWN0aXZpdHkubWljJywgKCkgPT4gVXNlckxpc3RVdGlsLmhhc1JpZ2h0KFZpZGVvVXRpbC5NSUNfQUNUSVZJVFkpXG5cdFx0XHRcdCwgKCkgPT4gaGFzQXVkaW9cblx0XHRcdFx0LCAoKSA9PiBTZXR0aW5ncy5sb2FkKCkudmlkZW8ubWljIDwgMClcblx0XHRcdC5vZmYoKS5jbGljayhmdW5jdGlvbigpIHtcblx0XHRcdFx0VmlkZW9NYW5hZ2VyLnRvZ2dsZUFjdGl2aXR5KFZpZGVvVXRpbC5NSUNfQUNUSVZJVFkpO1xuXHRcdFx0fSk7XG5cdFx0X19yaWdodE90aGVySWNvbnMoYywgaGVhZGVyKTtcblx0fVxuXHRWaWRlb01hbmFnZXIudXBkYXRlKGMpXG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRpbml0OiBmdW5jdGlvbihvcHRzKSB7XG5cdFx0b3B0aW9ucyA9IG9wdHM7XG5cdFx0VXNlckxpc3RVdGlsLmluaXQob3B0cyk7XG5cdH1cblx0LCBhZGRDbGllbnQ6IF9hZGRDbGllbnRcblx0LCB1cGRhdGVDbGllbnQ6IGZ1bmN0aW9uKGMpIHtcblx0XHRfdXBkYXRlQ2xpZW50KGMpO1xuXHRcdF9fc29ydFVzZXJMaXN0KCk7XG5cdH1cblx0LCByZW1vdmVDbGllbnQ6IGZ1bmN0aW9uKHVpZCkge1xuXHRcdF9nZXRDbGllbnQodWlkKS5yZW1vdmUoKTtcblx0XHRfX3VwZGF0ZUNvdW50KCk7XG5cdH1cblx0LCByZW1vdmVPdGhlcnM6IGZ1bmN0aW9uKCkge1xuXHRcdGNvbnN0IHNlbGZVaWQgPSBvcHRpb25zLnVpZDtcblx0XHQkKCcudXNlci1saXN0IC51c2VyLmVudHJ5JykuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdGNvbnN0IGMgPSAkKHRoaXMpO1xuXHRcdFx0aWYgKGMuZGF0YSgndWlkJykgIT09IHNlbGZVaWQpIHtcblx0XHRcdFx0Yy5yZW1vdmUoKTtcblx0XHRcdH1cblx0XHR9KTtcblx0XHRfX3VwZGF0ZUNvdW50KCk7XG5cdH1cblx0LCBnZXRDbGllbnQ6IF9nZXRDbGllbnRcbn07XG4iLCIvKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMCAqL1xuY29uc3QgU2V0dGluZ3MgPSByZXF1aXJlKCcuLi9tYWluL3NldHRpbmdzJyk7XG5jb25zdCBDaGF0ID0gcmVxdWlyZSgnLi4vY2hhdC9jaGF0Jyk7XG5jb25zdCBWaWRlb1NldHRpbmdzID0gcmVxdWlyZSgnLi4vc2V0dGluZ3Mvc2V0dGluZ3MnKTtcblxuZnVuY3Rpb24gX19pbml0TXV0ZU90aGVycygpIHtcblx0bGV0IHMgPSBWaWRlb1NldHRpbmdzLmxvYWQoKTtcblx0JCgnI211dGVPdGhlcnNBc2snKVxuXHRcdC5wcm9wKCdjaGVja2VkJywgcy52aWRlby5jb25maXJtTXV0ZU90aGVycylcblx0XHQub2ZmKCkuY2xpY2soZnVuY3Rpb24oKSB7XG5cdFx0XHRzID0gVmlkZW9TZXR0aW5ncy5sb2FkKCk7XG5cdFx0XHRzLnZpZGVvLmNvbmZpcm1NdXRlT3RoZXJzID0gISQoJyNtdXRlT3RoZXJzQXNrJykucHJvcCgnY2hlY2tlZCcpO1xuXHRcdFx0VmlkZW9TZXR0aW5ncy5zYXZlKCk7XG5cdFx0fSk7XG59XG5mdW5jdGlvbiBfX2luaXRDaGF0KCkge1xuXHRsZXQgcyA9IFNldHRpbmdzLmxvYWQoKTtcblx0JCgnI2NoYXROb3RpZnknKVxuXHRcdC5wcm9wKCdjaGVja2VkJywgcy5jaGF0Lm11dGVkKVxuXHRcdC5vZmYoKS5jbGljayhmdW5jdGlvbigpIHtcblx0XHRcdHMgPSBTZXR0aW5ncy5sb2FkKCk7XG5cdFx0XHRzLmNoYXQubXV0ZWQgPSAhJCgnI2NoYXROb3RpZnknKS5wcm9wKCdjaGVja2VkJyk7XG5cdFx0XHRTZXR0aW5ncy5zYXZlKHMpO1xuXHRcdFx0Q2hhdC5yZWxvYWQoKTtcblx0XHR9KTtcblx0JCgnI3NlbmRPbkN0cmxFbnRlcicpXG5cdFx0LnByb3AoJ2NoZWNrZWQnLCBzLmNoYXQuc2VuZE9uID09PSBDaGF0LlNFTkRfQ1RSTClcblx0XHQub2ZmKCkuY2xpY2soZnVuY3Rpb24oKSB7XG5cdFx0XHRzID0gU2V0dGluZ3MubG9hZCgpO1xuXHRcdFx0cy5jaGF0LnNlbmRPbiA9ICQoJyNzZW5kT25DdHJsRW50ZXInKS5wcm9wKCdjaGVja2VkJykgPyBDaGF0LlNFTkRfQ1RSTCA6IENoYXQuU0VORF9FTlRFUjtcblx0XHRcdFNldHRpbmdzLnNhdmUocyk7XG5cdFx0XHRDaGF0LnJlbG9hZCgpO1xuXHRcdH0pO1xufVxuZnVuY3Rpb24gX19pbml0VmlkZW8oKSB7XG5cdGNvbnN0IHJlc29sdXRpb25zID0gJCgnI3ZpZGVvLXNldHRpbmdzIC5jYW0tcmVzb2x1dGlvbicpLmNsb25lKCk7XG5cdGxldCBzID0gVmlkZW9TZXR0aW5ncy5sb2FkKCk7XG5cdHJlc29sdXRpb25zXG5cdFx0LmNoYW5nZShmdW5jdGlvbigpIHtcblx0XHRcdGNvbnN0IG8gPSByZXNvbHV0aW9ucy5maW5kKCdvcHRpb246c2VsZWN0ZWQnKS5kYXRhKCk7XG5cdFx0XHRzLmZpeGVkLndpZHRoID0gby53aWR0aDtcblx0XHRcdHMuZml4ZWQuaGVpZ2h0ID0gby5oZWlnaHQ7XG5cdFx0XHRWaWRlb1NldHRpbmdzLnNhdmUoKTtcblx0XHR9KVxuXHRcdC5maW5kKCdvcHRpb24nKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0Y29uc3QgbyA9ICQodGhpcykuZGF0YSgpO1xuXHRcdFx0aWYgKG8ud2lkdGggPT09IHMuZml4ZWQud2lkdGggJiYgby5oZWlnaHQgPT09IHMuZml4ZWQuaGVpZ2h0KSB7XG5cdFx0XHRcdCQodGhpcykucHJvcCgnc2VsZWN0ZWQnLCB0cnVlKTtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdH0pO1xuXHQkKCcjdmlkZW8tc2l6ZXMtY29udGFpbmVyJylcblx0XHQuaHRtbCgnJylcblx0XHQuYXBwZW5kKHJlc29sdXRpb25zLnByb3AoJ2Rpc2FibGVkJywgIXMuZml4ZWQuZW5hYmxlZCkpO1xuXHQkKCcjZml4ZWRWaWRlb1BvZCcpXG5cdFx0LnByb3AoJ2NoZWNrZWQnLCBzLmZpeGVkLmVuYWJsZWQpXG5cdFx0Lm9mZigpLmNsaWNrKGZ1bmN0aW9uKCkge1xuXHRcdFx0cyA9IFZpZGVvU2V0dGluZ3MubG9hZCgpO1xuXHRcdFx0cy5maXhlZC5lbmFibGVkID0gJCgnI2ZpeGVkVmlkZW9Qb2QnKS5wcm9wKCdjaGVja2VkJyk7XG5cdFx0XHRyZXNvbHV0aW9ucy5wcm9wKCdkaXNhYmxlZCcsICFzLmZpeGVkLmVuYWJsZWQpXG5cdFx0XHRWaWRlb1NldHRpbmdzLnNhdmUoKTtcblx0XHR9KTtcbn1cbmZ1bmN0aW9uIF9vcGVuKCkge1xuXHRfX2luaXRNdXRlT3RoZXJzKCk7XG5cdF9faW5pdENoYXQoKTtcblx0X19pbml0VmlkZW8oKTtcblx0JCgnI3Jvb20tbG9jYWwtc2V0dGluZ3MnKS5tb2RhbCgnc2hvdycpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcblx0b3BlbjogX29wZW5cbn07XG4iLCIvKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMCAqL1xuY29uc3QgT21VdGlsID0gcmVxdWlyZSgnLi4vbWFpbi9vbXV0aWxzJyk7XG5jb25zdCBWaWRlb1V0aWwgPSByZXF1aXJlKCcuLi9zZXR0aW5ncy92aWRlby11dGlsJyk7XG5jb25zdCBWaWRlb1NldHRpbmdzID0gcmVxdWlyZSgnLi4vc2V0dGluZ3Mvc2V0dGluZ3MnKTtcblxubGV0IHNoYXJlO1xuXG5mdW5jdGlvbiBfX3NhdmVQb2Qodikge1xuXHRjb25zdCBvcHRzID0gUm9vbS5nZXRPcHRpb25zKCk7XG5cdGlmICghb3B0cy5pbnRlcnZpZXcgJiYgdiAmJiB2LmZpbmQoJ3ZpZGVvJykubGVuZ3RoID4gMCAmJiB2LmRhdGEoJ2NsaWVudFR5cGUnKSA9PT0gJ1dFQkNBTScgJiYgdi5kaWFsb2coJ2luc3RhbmNlJykpIHtcblx0XHRjb25zdCB1c2VyVUkgPSAkKGAjdXNlciR7di5kYXRhKCdjbGllbnRVaWQnKX1gKVxuXHRcdFx0LCB3aWRnZXQgPSB2LmRpYWxvZygnd2lkZ2V0Jyk7XG5cdFx0dXNlclVJLmRhdGEoJ3ZpZGVvLXBvZCcsIHtcblx0XHRcdHg6IHdpZGdldC5jc3MoJ2xlZnQnKVxuXHRcdFx0LCB5OiB3aWRnZXQuY3NzKCd0b3AnKVxuXHRcdFx0LCB3OiB3aWRnZXQuY3NzKCd3aWR0aCcpXG5cdFx0XHQsIGg6IHdpZGdldC5jc3MoJ2hlaWdodCcpXG5cdFx0fSk7XG5cdH1cbn1cbmZ1bmN0aW9uIF9jbG9zZVYodikge1xuXHRpZiAoIXYgfHwgdi5sZW5ndGggPCAxKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdF9fc2F2ZVBvZCh2KTtcblx0aWYgKHYuZGlhbG9nKCdpbnN0YW5jZScpICE9PSB1bmRlZmluZWQpIHtcblx0XHR2LmRpYWxvZygnZGVzdHJveScpO1xuXHR9XG5cdHYucGFyZW50cygnLnBvZCcpLnJlbW92ZSgpO1xuXHR2LnJlbW92ZSgpO1xuXHRXYkFyZWEudXBkYXRlQXJlYUNsYXNzKCk7XG59XG5mdW5jdGlvbiBfY2xpY2tNdXRlT3RoZXJzKHVpZCkge1xuXHRjb25zdCBzID0gVmlkZW9TZXR0aW5ncy5sb2FkKCk7XG5cdGlmIChmYWxzZSAhPT0gcy52aWRlby5jb25maXJtTXV0ZU90aGVycykge1xuXHRcdGNvbnN0IGRsZyA9ICQoJyNtdXRlb3RoZXJzLWNvbmZpcm0nKTtcblx0XHRkbGcuZGlhbG9nKHtcblx0XHRcdGFwcGVuZFRvOiBcIi5yb29tLWNvbnRhaW5lclwiXG5cdFx0XHQsIGJ1dHRvbnM6IFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHRleHQ6IGRsZy5kYXRhKCdidG4tb2snKVxuXHRcdFx0XHRcdCwgY2xpY2s6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0cy52aWRlby5jb25maXJtTXV0ZU90aGVycyA9ICEkKCcjbXV0ZW90aGVycy1jb25maXJtLWRvbnQtc2hvdycpLnByb3AoJ2NoZWNrZWQnKTtcblx0XHRcdFx0XHRcdFZpZGVvU2V0dGluZ3Muc2F2ZSgpO1xuXHRcdFx0XHRcdFx0T21VdGlsLnJvb21BY3Rpb24oe2FjdGlvbjogJ211dGVPdGhlcnMnLCB1aWQ6IHVpZH0pO1xuXHRcdFx0XHRcdFx0JCh0aGlzKS5kaWFsb2coJ2Nsb3NlJyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdCwge1xuXHRcdFx0XHRcdHRleHQ6IGRsZy5kYXRhKCdidG4tY2FuY2VsJylcblx0XHRcdFx0XHQsIGNsaWNrOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdCQodGhpcykuZGlhbG9nKCdjbG9zZScpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XVxuXHRcdH0pXG5cdH0gZWxzZSB7XG5cdFx0T21VdGlsLnJvb21BY3Rpb24oe2FjdGlvbjogJ211dGVPdGhlcnMnLCB1aWQ6IHVpZH0pO1xuXHR9XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuXHRpbml0OiAoX3NoYXJlKSA9PiB7XG5cdFx0c2hhcmUgPSBfc2hhcmU7XG5cdH1cblx0LCBzZW5kTWVzc2FnZTogKF9tKSA9PiB7XG5cdFx0T21VdGlsLnNlbmRNZXNzYWdlKF9tLCB7dHlwZTogJ2t1cmVudG8nfSk7XG5cdH1cblx0LCBzYXZlUG9kOiBfX3NhdmVQb2Rcblx0LCBjbG9zZVY6IF9jbG9zZVZcblx0LCBjbG9zZTogKHVpZCwgc2hvd1NoYXJlQnRuKSA9PiB7XG5cdFx0Y29uc3QgdiA9ICQoJyMnICsgVmlkZW9VdGlsLmdldFZpZCh1aWQpKTtcblx0XHRpZiAodi5sZW5ndGggPT09IDEpIHtcblx0XHRcdF9jbG9zZVYodik7XG5cdFx0fVxuXHRcdGlmICghc2hvd1NoYXJlQnRuICYmIHVpZCA9PT0gc2hhcmUuZGF0YSgndWlkJykpIHtcblx0XHRcdHNoYXJlLm9mZigpLmhpZGUoKTtcblx0XHR9XG5cdH1cblx0LCBjbGlja011dGVPdGhlcnM6IF9jbGlja011dGVPdGhlcnNcbn07XG4iLCIvKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMCAqL1xuY29uc3QgT21VdGlsID0gcmVxdWlyZSgnLi4vbWFpbi9vbXV0aWxzJyk7XG5jb25zdCBWaWRlb1V0aWwgPSByZXF1aXJlKCcuLi9zZXR0aW5ncy92aWRlby11dGlsJyk7XG5jb25zdCBWaWRlb1NldHRpbmdzID0gcmVxdWlyZSgnLi4vc2V0dGluZ3Mvc2V0dGluZ3MnKTtcblxubGV0IHNoYXJlLCBpbml0ZWQgPSBmYWxzZTtcbmNvbnN0IFZpZGVvTWdyVXRpbCA9IHJlcXVpcmUoJy4vdmlkZW8tbWFuYWdlci11dGlsJyk7XG5jb25zdCBWaWRlbyA9IHJlcXVpcmUoJy4vdmlkZW8nKTtcbmNvbnN0IFNoYXJlciA9IHJlcXVpcmUoJy4vc2hhcmVyJyk7XG5cbmZ1bmN0aW9uIF9vblZpZGVvUmVzcG9uc2UobSkge1xuXHRjb25zdCB3ID0gJCgnIycgKyBWaWRlb1V0aWwuZ2V0VmlkKG0udWlkKSlcblx0XHQsIHYgPSB3LmRhdGEoKTtcblx0aWYgKHYpIHtcblx0XHR2LnByb2Nlc3NTZHBBbnN3ZXIobS5zZHBBbnN3ZXIpO1xuXHR9XG59XG5mdW5jdGlvbiBfb25Ccm9hZGNhc3QobXNnKSB7XG5cdGNvbnN0IHNkID0gbXNnLnN0cmVhbVxuXHRcdCwgdWlkID0gc2QudWlkO1xuXHRpZiAoQXJyYXkuaXNBcnJheShtc2cuY2xlYW51cCkpIHtcblx0XHRtc2cuY2xlYW51cC5mb3JFYWNoKGZ1bmN0aW9uKF9jdWlkKSB7XG5cdFx0XHRWaWRlb01nclV0aWwuY2xvc2UoX2N1aWQpO1xuXHRcdH0pO1xuXHR9XG5cdCQoJyMnICsgVmlkZW9VdGlsLmdldFZpZCh1aWQpKS5yZW1vdmUoKTtcblx0bmV3IFZpZGVvKG1zZyk7XG5cdE9tVXRpbC5sb2codWlkICsgJyByZWdpc3RlcmVkIGluIHJvb20nKTtcbn1cbmZ1bmN0aW9uIF9vblNoYXJlVXBkYXRlZChtc2cpIHtcblx0Y29uc3Qgc2QgPSBtc2cuc3RyZWFtXG5cdFx0LCB1aWQgPSBzZC51aWRcblx0XHQsIHcgPSAkKCcjJyArIFZpZGVvVXRpbC5nZXRWaWQodWlkKSlcblx0XHQsIHYgPSB3LmRhdGEoKTtcblx0aWYgKHYgJiYgKFZpZGVvVXRpbC5pc1NoYXJpbmcoc2QpIHx8IFZpZGVvVXRpbC5pc1JlY29yZGluZyhzZCkpKSB7XG5cdFx0Ly8gVXBkYXRlIGFjdGl2aXRpZXMgaW4gdGhlIGN1cnJlbnQgZGF0YSBvYmplY3Rcblx0XHR2LnN0cmVhbSgpLmFjdGl2aXRpZXMgPSBzZC5hY3Rpdml0aWVzO1xuXHR9XG5cdFNoYXJlci5zZXRTaGFyZVN0YXRlKFZpZGVvVXRpbC5pc1NoYXJpbmcoc2QpID8gU2hhcmVyLlNIQVJFX1NUQVJURUQgOiBTaGFyZXIuU0hBUkVfU1RPUFBFRCk7XG5cdFNoYXJlci5zZXRSZWNTdGF0ZShWaWRlb1V0aWwuaXNSZWNvcmRpbmcoc2QpID8gU2hhcmVyLlNIQVJFX1NUQVJURUQgOiBTaGFyZXIuU0hBUkVfU1RPUFBFRCk7XG59XG5mdW5jdGlvbiBfb25SZWNlaXZlKG1zZykge1xuXHRjb25zdCB1aWQgPSBtc2cuc3RyZWFtLnVpZDtcblx0VmlkZW9NZ3JVdGlsLmNsb3NlVigkKCcjJyArIFZpZGVvVXRpbC5nZXRWaWQodWlkKSkpO1xuXHRuZXcgVmlkZW8obXNnKTtcblx0T21VdGlsLmxvZyh1aWQgKyAnIHJlY2VpdmluZyB2aWRlbycpO1xufVxuZnVuY3Rpb24gX29uS01lc3NhZ2UobSkge1xuXHRzd2l0Y2ggKG0uaWQpIHtcblx0XHRjYXNlICdjbGllbnRMZWF2ZSc6XG5cdFx0XHQkKGAke1ZpZGVvVXRpbC5WSURfU0VMfVtkYXRhLWNsaWVudC11aWQ9XCIke20udWlkfVwiXWApLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFZpZGVvTWdyVXRpbC5jbG9zZVYoJCh0aGlzKSk7XG5cdFx0XHR9KTtcblx0XHRcdGlmIChzaGFyZS5kYXRhKCdjdWlkJykgPT09IG0udWlkKSB7XG5cdFx0XHRcdHNoYXJlLm9mZigpLmhpZGUoKTtcblx0XHRcdH1cblx0XHRcdGJyZWFrO1xuXHRcdGNhc2UgJ2Jyb2FkY2FzdFN0b3BwZWQnOlxuXHRcdFx0VmlkZW9NZ3JVdGlsLmNsb3NlKG0udWlkLCBmYWxzZSk7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlICdicm9hZGNhc3QnOlxuXHRcdFx0X29uQnJvYWRjYXN0KG0pO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSAndmlkZW9SZXNwb25zZSc6XG5cdFx0XHRfb25WaWRlb1Jlc3BvbnNlKG0pO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSAnaWNlQ2FuZGlkYXRlJzpcblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgdyA9ICQoJyMnICsgVmlkZW9VdGlsLmdldFZpZChtLnVpZCkpXG5cdFx0XHRcdFx0LCB2ID0gdy5kYXRhKCk7XG5cdFx0XHRcdGlmICh2KSB7XG5cdFx0XHRcdFx0di5wcm9jZXNzSWNlQ2FuZGlkYXRlKG0uY2FuZGlkYXRlKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSAnbmV3U3RyZWFtJzpcblx0XHRcdF9wbGF5KFttLnN0cmVhbV0sIG0uaWNlU2VydmVycyk7XG5cdFx0XHRicmVhaztcblx0XHRjYXNlICdzaGFyZVVwZGF0ZWQnOlxuXHRcdFx0X29uU2hhcmVVcGRhdGVkKG0pO1xuXHRcdFx0YnJlYWs7XG5cdFx0Y2FzZSAnZXJyb3InOlxuXHRcdFx0T21VdGlsLmVycm9yKG0ubWVzc2FnZSk7XG5cdFx0XHRicmVhaztcblx0XHRkZWZhdWx0OlxuXHRcdFx0Ly9uby1vcFxuXHR9XG59XG5mdW5jdGlvbiBfb25Xc01lc3NhZ2UoXywgbXNnKSB7XG5cdHRyeSB7XG5cdFx0aWYgKG1zZyBpbnN0YW5jZW9mIEJsb2IpIHtcblx0XHRcdHJldHVybjsgLy9waW5nXG5cdFx0fVxuXHRcdGNvbnN0IG0gPSBKU09OLnBhcnNlKG1zZyk7XG5cdFx0aWYgKCFtKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGlmICgna3VyZW50bycgPT09IG0udHlwZSAmJiAndGVzdCcgIT09IG0ubW9kZSkge1xuXHRcdFx0T21VdGlsLmluZm8oJ1JlY2VpdmVkIG1lc3NhZ2U6ICcgKyBtc2cpO1xuXHRcdFx0X29uS01lc3NhZ2UobSk7XG5cdFx0fSBlbHNlIGlmICgnbWljJyA9PT0gbS50eXBlKSB7XG5cdFx0XHRzd2l0Y2ggKG0uaWQpIHtcblx0XHRcdFx0Y2FzZSAnYWN0aXZpdHknOlxuXHRcdFx0XHRcdF91c2VyU3BlYWtzKG0udWlkLCBtLmFjdGl2ZSk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0Ly9uby1vcFxuXHRcdFx0fVxuXHRcdH1cblx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0T21VdGlsLmVycm9yKGVycik7XG5cdH1cbn1cbmZ1bmN0aW9uIF9pbml0KCkge1xuXHRXaWNrZXQuRXZlbnQuc3Vic2NyaWJlKCcvd2Vic29ja2V0L21lc3NhZ2UnLCBfb25Xc01lc3NhZ2UpO1xuXHRWaWRlb1NldHRpbmdzLmluaXQoUm9vbS5nZXRPcHRpb25zKCkpO1xuXHRzaGFyZSA9ICQoJy5yb29tLWJsb2NrIC5yb29tLWNvbnRhaW5lcicpLmZpbmQoJy5idG4uc2hhcmVkJyk7XG5cdFZpZGVvTWdyVXRpbC5pbml0KHNoYXJlKTtcblx0aW5pdGVkID0gdHJ1ZTtcblx0JCh3aW5kb3cpLm9uKCdrZXlkb3duLnB1c2gtdG8tdGFsaycsIHtlbmFibGU6IHRydWV9LCBfb25QdHQpO1xuXHQkKHdpbmRvdykub24oJ2tleXVwLnB1c2gtdG8tdGFsaycsIHtlbmFibGU6IGZhbHNlfSwgX29uUHR0KTtcbn1cbmZ1bmN0aW9uIF91cGRhdGUoYykge1xuXHRpZiAoIWluaXRlZCkge1xuXHRcdHJldHVybjtcblx0fVxuXHRjb25zdCBzdHJlYW1NYXAgPSB7fTtcblx0Yy5zdHJlYW1zLmZvckVhY2goZnVuY3Rpb24oc2QpIHtcblx0XHRzdHJlYW1NYXBbc2QudWlkXSA9IHNkLnVpZDtcblx0XHRzZC5zZWxmID0gYy5zZWxmO1xuXHRcdHNkLmNhbSA9IGMuY2FtO1xuXHRcdHNkLm1pYyA9IGMubWljO1xuXHRcdGlmIChWaWRlb1V0aWwuaXNTaGFyaW5nKHNkKSB8fCBWaWRlb1V0aWwuaXNSZWNvcmRpbmcoc2QpKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcdGNvbnN0IF9pZCA9IFZpZGVvVXRpbC5nZXRWaWQoc2QudWlkKVxuXHRcdFx0LCBhdiA9IFZpZGVvVXRpbC5oYXNNaWMoc2QpIHx8IFZpZGVvVXRpbC5oYXNDYW0oc2QpXG5cdFx0XHQsIHYgPSAkKCcjJyArIF9pZCk7XG5cdFx0aWYgKGF2ICYmIHYubGVuZ3RoID09PSAxKSB7XG5cdFx0XHR2LmRhdGEoKS51cGRhdGUoc2QpO1xuXHRcdH0gZWxzZSBpZiAoIWF2ICYmIHYubGVuZ3RoID09PSAxKSB7XG5cdFx0XHRWaWRlb01nclV0aWwuY2xvc2VWKHYpO1xuXHRcdH1cblx0fSk7XG5cdGlmIChjLnVpZCA9PT0gUm9vbS5nZXRPcHRpb25zKCkudWlkKSB7XG5cdFx0JChWaWRlb1V0aWwuVklEX1NFTCkuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdCQodGhpcykuZGF0YSgpLnNldFJpZ2h0cyhjLnJpZ2h0cyk7XG5cdFx0fSk7XG5cdH1cblx0JChgW2RhdGEtY2xpZW50LXVpZD1cIiR7Yy5jdWlkfVwiXWApLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0Y29uc3Qgc2QgPSAkKHRoaXMpLmRhdGEoKS5zdHJlYW0oKTtcblx0XHRpZiAoIXN0cmVhbU1hcFtzZC51aWRdKSB7XG5cdFx0XHQvL25vdC1pbml0ZWQvaW52YWxpZCB2aWRlbyB3aW5kb3dcblx0XHRcdFZpZGVvTWdyVXRpbC5jbG9zZVYoJCh0aGlzKSk7XG5cdFx0fVxuXHR9KTtcbn1cbmZ1bmN0aW9uIF9wbGF5U2hhcmluZyhzZCwgaWNlU2VydmVycykge1xuXHRjb25zdCBtID0ge3N0cmVhbTogc2QsIGljZVNlcnZlcnM6IGljZVNlcnZlcnN9XG5cdFx0LCB2ID0gJCgnIycgKyBWaWRlb1V0aWwuZ2V0VmlkKHNkLnVpZCkpXG5cdGlmICh2Lmxlbmd0aCA9PT0gMSkge1xuXHRcdHYucmVtb3ZlKCk7XG5cdH1cblx0bmV3IFZpZGVvKG0pO1xuXHRWaWRlb1V0aWwuc2V0UG9zKHYsIHtsZWZ0OiAwLCB0b3A6IDM1fSk7XG59XG5mdW5jdGlvbiBfcGxheShzdHJlYW1zLCBpY2VTZXJ2ZXJzKSB7XG5cdGlmICghaW5pdGVkKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cdHN0cmVhbXMuZm9yRWFjaChmdW5jdGlvbihzZCkge1xuXHRcdGNvbnN0IG0gPSB7c3RyZWFtOiBzZCwgaWNlU2VydmVyczogaWNlU2VydmVyc307XG5cdFx0aWYgKFZpZGVvVXRpbC5pc1NoYXJpbmcoc2QpKSB7XG5cdFx0XHRWaWRlb1V0aWwuaGlnaGxpZ2h0KHNoYXJlXG5cdFx0XHRcdFx0LmF0dHIoJ3RpdGxlJywgc2hhcmUuZGF0YSgndXNlcicpICsgJyAnICsgc2QudXNlci5maXJzdE5hbWUgKyAnICcgKyBzZC51c2VyLmxhc3ROYW1lICsgJyAnICsgc2hhcmUuZGF0YSgndGV4dCcpKVxuXHRcdFx0XHRcdC5kYXRhKCd1aWQnLCBzZC51aWQpXG5cdFx0XHRcdFx0LmRhdGEoJ2N1aWQnLCBzZC5jdWlkKVxuXHRcdFx0XHRcdC5zaG93KClcblx0XHRcdFx0LCAnYnRuLW91dGxpbmUtd2FybmluZycsIDEwKTtcblx0XHRcdHNoYXJlLnRvb2x0aXAoKS5vZmYoKS5jbGljayhmdW5jdGlvbigpIHtcblx0XHRcdFx0X3BsYXlTaGFyaW5nKHNkLCBpY2VTZXJ2ZXJzKTtcblx0XHRcdH0pO1xuXHRcdFx0aWYgKFJvb20uZ2V0T3B0aW9ucygpLmF1dG9PcGVuU2hhcmluZyA9PT0gdHJ1ZSkge1xuXHRcdFx0XHRfcGxheVNoYXJpbmcoc2QsIGljZVNlcnZlcnMpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSBpZiAoVmlkZW9VdGlsLmlzUmVjb3JkaW5nKHNkKSkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRfb25SZWNlaXZlKG0pO1xuXHRcdH1cblx0fSk7XG59XG5mdW5jdGlvbiBfZmluZCh1aWQpIHtcblx0cmV0dXJuICQoYCR7VmlkZW9VdGlsLlZJRF9TRUx9W2RhdGEtY2xpZW50LXVpZD1cIiR7dWlkfVwiXVtkYXRhLWNsaWVudC10eXBlPVwiV0VCQ0FNXCJdYCk7XG59XG5mdW5jdGlvbiBfdXNlclNwZWFrcyh1aWQsIGFjdGl2ZSkge1xuXHRjb25zdCB1ID0gJChgI3VzZXIke3VpZH0gLmF1ZGlvLWFjdGl2aXR5YClcblx0XHQsIHYgPSBfZmluZCh1aWQpLnBhcmVudCgpO1xuXHRpZiAoYWN0aXZlKSB7XG5cdFx0dS5hZGRDbGFzcygnc3BlYWtpbmcnKTtcblx0XHR2LmFkZENsYXNzKCd1c2VyLXNwZWFrcycpXG5cdH0gZWxzZSB7XG5cdFx0dS5yZW1vdmVDbGFzcygnc3BlYWtpbmcnKTtcblx0XHR2LnJlbW92ZUNsYXNzKCd1c2VyLXNwZWFrcycpXG5cdH1cbn1cbmZ1bmN0aW9uIF9yZWZyZXNoKHVpZCwgb3B0cykge1xuXHRjb25zdCB2ID0gX2ZpbmQodWlkKTtcblx0aWYgKHYubGVuZ3RoID4gMCkge1xuXHRcdHYuZGF0YSgpLnJlZnJlc2gob3B0cyk7XG5cdH1cbn1cbmZ1bmN0aW9uIF9tdXRlKHVpZCwgbXV0ZSkge1xuXHRjb25zdCB2ID0gX2ZpbmQodWlkKTtcblx0aWYgKHYubGVuZ3RoID4gMCkge1xuXHRcdHYuZGF0YSgpLm11dGUobXV0ZSk7XG5cdH1cbn1cbmZ1bmN0aW9uIF9tdXRlT3RoZXJzKHVpZCkge1xuXHQkKFZpZGVvVXRpbC5WSURfU0VMKS5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdGNvbnN0IHcgPSAkKHRoaXMpLCB2ID0gdy5kYXRhKCksIHYyID0gdy5kYXRhKCdjbGllbnQtdWlkJyk7XG5cdFx0aWYgKHYgJiYgdjIpIHtcblx0XHRcdHYubXV0ZSh1aWQgIT09IHYyKTtcblx0XHR9XG5cdH0pO1xufVxuZnVuY3Rpb24gX3RvZ2dsZUFjdGl2aXR5KGFjdGl2aXR5KSB7XG5cdFZpZGVvTWdyVXRpbC5zZW5kTWVzc2FnZSh7XG5cdFx0aWQ6ICd0b2dnbGVBY3Rpdml0eSdcblx0XHQsIGFjdGl2aXR5OiBhY3Rpdml0eVxuXHR9KTtcbn1cbmZ1bmN0aW9uIF9vblB0dChlKSB7XG5cdGlmICgoZS5jdHJsS2V5IHx8IGUubWV0YUtleSkgJiYgJ1NwYWNlJyA9PT0gZS5jb2RlKSB7XG5cdFx0Y29uc3QgdiA9IF9maW5kKFJvb20uZ2V0T3B0aW9ucygpLnVpZCk7XG5cdFx0aWYgKHYubGVuZ3RoID4gMCAmJiB2LmRhdGEoKSkge1xuXHRcdFx0di5kYXRhKCkucHVzaFRvVGFsayhlLmRhdGEuZW5hYmxlKTtcblx0XHR9XG5cdH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG5cdGluaXQ6IF9pbml0XG5cdCwgdXBkYXRlOiBfdXBkYXRlXG5cdCwgcGxheTogX3BsYXlcblx0LCByZWZyZXNoOiBfcmVmcmVzaFxuXHQsIG11dGU6IF9tdXRlXG5cdCwgbXV0ZU90aGVyczogX211dGVPdGhlcnNcblx0LCB0b2dnbGVBY3Rpdml0eTogX3RvZ2dsZUFjdGl2aXR5XG5cdCwgZGVzdHJveTogZnVuY3Rpb24oKSB7XG5cdFx0JCh3aW5kb3cpLm9mZigna2V5ZG93bi5wdXNoLXRvLXRhbGsnKTtcblx0XHQkKHdpbmRvdykub2ZmKCdrZXl1cC5wdXNoLXRvLXRhbGsnKTtcblx0XHRXaWNrZXQuRXZlbnQudW5zdWJzY3JpYmUoJy93ZWJzb2NrZXQvbWVzc2FnZScsIF9vbldzTWVzc2FnZSk7XG5cdH1cbn07XG4iLCIvKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMCAqL1xuY29uc3QgT21VdGlsID0gcmVxdWlyZSgnLi4vbWFpbi9vbXV0aWxzJyk7XG5jb25zdCBWaWRlb1V0aWwgPSByZXF1aXJlKCcuLi9zZXR0aW5ncy92aWRlby11dGlsJyk7XG5jb25zdCBNaWNMZXZlbCA9IHJlcXVpcmUoJy4uL3NldHRpbmdzL21pYy1sZXZlbCcpO1xuY29uc3QgV2ViUnRjUGVlciA9IHJlcXVpcmUoJy4uL3NldHRpbmdzL1dlYlJ0Y1BlZXInKTtcbmNvbnN0IFZpZGVvU2V0dGluZ3MgPSByZXF1aXJlKCcuLi9zZXR0aW5ncy9zZXR0aW5ncycpO1xuXG5jb25zdCBBdWRpb0N0eCA9IHdpbmRvdy5BdWRpb0NvbnRleHQgfHwgd2luZG93LndlYmtpdEF1ZGlvQ29udGV4dDtcbmNvbnN0IFZpZGVvTWdyVXRpbCA9IHJlcXVpcmUoJy4vdmlkZW8tbWFuYWdlci11dGlsJyk7XG5jb25zdCBTaGFyZXIgPSByZXF1aXJlKCcuL3NoYXJlcicpO1xuY29uc3QgVm9sdW1lID0gcmVxdWlyZSgnLi92b2x1bWUnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBjbGFzcyBWaWRlbyB7XG5cdGNvbnN0cnVjdG9yKG1zZykge1xuXHRcdGNvbnN0IHN0YXRlcyA9IFtdLCBzZWxmID0gdGhpcywgdmlkU2l6ZSA9IHt9O1xuXHRcdGxldCBzZCwgdiwgdmMsIHQsIGZvb3Rlciwgc2l6ZSwgdm9sLCBpY2VTZXJ2ZXJzXG5cdFx0XHQsIGxtLCBsZXZlbCwgdXNlclNwZWFrcyA9IGZhbHNlLCBtdXRlT3RoZXJzXG5cdFx0XHQsIGhhc1ZpZGVvLCBpc1NoYXJpbmcsIGlzUmVjb3JkaW5nO1xuXG5cdFx0ZnVuY3Rpb24gX19nZXRTdGF0ZSgpIHtcblx0XHRcdGNvbnN0IHN0YXRlID0gc3RhdGVzLmxlbmd0aCA+IDAgPyBzdGF0ZXNbMF0gOiBudWxsO1xuXHRcdFx0aWYgKCFzdGF0ZSB8fCBzdGF0ZS5kaXNwb3NlZCkge1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblx0XHRcdHJldHVybiBzdGF0ZTtcblx0XHR9XG5cdFx0ZnVuY3Rpb24gX19nZXRWaWRlbyhfc3RhdGUpIHtcblx0XHRcdGNvbnN0IHZpZCA9IHNlbGYudmlkZW8oX3N0YXRlKTtcblx0XHRcdHJldHVybiB2aWQgJiYgdmlkLmxlbmd0aCA+IDAgPyB2aWRbMF0gOiBudWxsO1xuXHRcdH1cblx0XHRmdW5jdGlvbiBfcmVzaXplRGxnQXJlYShfdywgX2gpIHtcblx0XHRcdGlmIChSb29tLmdldE9wdGlvbnMoKS5pbnRlcnZpZXcpIHtcblx0XHRcdFx0VmlkZW9VdGlsLnNldFBvcyh2LCBWaWRlb1V0aWwuZ2V0UG9zKCkpO1xuXHRcdFx0fSBlbHNlIGlmICh2LmRpYWxvZygnaW5zdGFuY2UnKSkge1xuXHRcdFx0XHR2LmRpYWxvZygnb3B0aW9uJywgJ3dpZHRoJywgX3cpLmRpYWxvZygnb3B0aW9uJywgJ2hlaWdodCcsIF9oKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZnVuY3Rpb24gX21pY0FjdGl2aXR5KHNwZWFrcykge1xuXHRcdFx0aWYgKHNwZWFrcyAhPT0gdXNlclNwZWFrcykge1xuXHRcdFx0XHR1c2VyU3BlYWtzID0gc3BlYWtzO1xuXHRcdFx0XHRPbVV0aWwuc2VuZE1lc3NhZ2Uoe3R5cGU6ICdtaWMnLCBpZDogJ2FjdGl2aXR5JywgYWN0aXZlOiBzcGVha3N9KTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZnVuY3Rpb24gX2dldFNjcmVlblN0cmVhbShtc2csIHN0YXRlLCBjYWxsYmFjaykge1xuXHRcdFx0ZnVuY3Rpb24gX19oYW5kbGVTY3JlZW5FcnJvcihlcnIpIHtcblx0XHRcdFx0VmlkZW9NZ3JVdGlsLnNlbmRNZXNzYWdlKHtpZDogJ2Vycm9yU2hhcmluZyd9KTtcblx0XHRcdFx0U2hhcmVyLnNldFNoYXJlU3RhdGUoU2hhcmVyLlNIQVJFX1NUT1BQRUQpO1xuXHRcdFx0XHRTaGFyZXIuc2V0UmVjU3RhdGUoU2hhcmVyLlNIQVJFX1NUT1BQRUQpO1xuXHRcdFx0XHRPbVV0aWwuZXJyb3IoZXJyKTtcblx0XHRcdH1cblx0XHRcdGNvbnN0IGIgPSBWaWRlb1V0aWwuYnJvd3Nlcjtcblx0XHRcdGxldCBwcm9taXNlLCBjbnRzO1xuXHRcdFx0aWYgKFZpZGVvVXRpbC5pc0VkZ2UoKSAmJiBiLm1ham9yID4gMTYpIHtcblx0XHRcdFx0Y250cyA9IHtcblx0XHRcdFx0XHR2aWRlbzogdHJ1ZVxuXHRcdFx0XHR9O1xuXHRcdFx0XHRwcm9taXNlID0gbmF2aWdhdG9yLmdldERpc3BsYXlNZWRpYShjbnRzKTtcblx0XHRcdH0gZWxzZSBpZiAoVmlkZW9VdGlsLnNoYXJpbmdTdXBwb3J0ZWQoKSkge1xuXHRcdFx0XHRjbnRzID0ge1xuXHRcdFx0XHRcdHZpZGVvOiB0cnVlXG5cdFx0XHRcdH07XG5cdFx0XHRcdGlmIChWaWRlb1V0aWwuaXNTYWZhcmkoKSkge1xuXHRcdFx0XHRcdHByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuXHRcdFx0XHRcdFx0VmlkZW9VdGlsLmFza1Blcm1pc3Npb24ocmVzb2x2ZSk7XG5cdFx0XHRcdFx0fSkudGhlbigoKSA9PiBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldERpc3BsYXlNZWRpYShjbnRzKSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cHJvbWlzZSA9IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0RGlzcGxheU1lZGlhKGNudHMpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRwcm9taXNlID0gbmV3IFByb21pc2UoKCkgPT4ge1xuXHRcdFx0XHRcdFNoYXJlci5jbG9zZSgpO1xuXHRcdFx0XHRcdHRocm93ICdTY3JlZW4tc2hhcmluZyBpcyBub3Qgc3VwcG9ydGVkIGluICcgKyBiLm5hbWUgKyAnWycgKyBiLm1ham9yICsgJ10nO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHRcdHByb21pc2UudGhlbihzdHJlYW0gPT4ge1xuXHRcdFx0XHRpZiAoIXN0YXRlLmRpc3Bvc2VkKSB7XG5cdFx0XHRcdFx0X19jcmVhdGVWaWRlbyhzdGF0ZSk7XG5cdFx0XHRcdFx0c3RhdGUuc3RyZWFtID0gc3RyZWFtO1xuXHRcdFx0XHRcdGNhbGxiYWNrKG1zZywgc3RhdGUsIGNudHMpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KS5jYXRjaChfX2hhbmRsZVNjcmVlbkVycm9yKTtcblx0XHR9XG5cdFx0ZnVuY3Rpb24gX2dldFZpZGVvU3RyZWFtKG1zZywgc3RhdGUsIGNhbGxiYWNrKSB7XG5cdFx0XHRWaWRlb1NldHRpbmdzLmNvbnN0cmFpbnRzKHNkLCBmdW5jdGlvbihjbnRzKSB7XG5cdFx0XHRcdGlmIChWaWRlb1V0aWwuaGFzQ2FtKHNkKSAhPT0gY250cy52aWRlb0VuYWJsZWQgfHwgVmlkZW9VdGlsLmhhc01pYyhzZCkgIT09IGNudHMuYXVkaW9FbmFibGVkKSB7XG5cdFx0XHRcdFx0VmlkZW9NZ3JVdGlsLnNlbmRNZXNzYWdlKHtcblx0XHRcdFx0XHRcdGlkIDogJ2RldmljZXNBbHRlcmVkJ1xuXHRcdFx0XHRcdFx0LCB1aWQ6IHNkLnVpZFxuXHRcdFx0XHRcdFx0LCBhdWRpbzogY250cy5hdWRpb0VuYWJsZWRcblx0XHRcdFx0XHRcdCwgdmlkZW86IGNudHMudmlkZW9FbmFibGVkXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCFjbnRzLmF1ZGlvICYmICFjbnRzLnZpZGVvKSB7XG5cdFx0XHRcdFx0T21VdGlsLmVycm9yKCdSZXF1ZXN0ZWQgZGV2aWNlcyBhcmUgbm90IGF2YWlsYWJsZScpO1xuXHRcdFx0XHRcdFZpZGVvTWdyVXRpbC5jbG9zZShzZC51aWQpXG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHRcdG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKGNudHMpXG5cdFx0XHRcdFx0LnRoZW4oc3RyZWFtID0+IHtcblx0XHRcdFx0XHRcdGlmIChzdGF0ZS5kaXNwb3NlZCB8fCBtc2cuaW5zdGFuY2VVaWQgIT09IHYuZGF0YSgnaW5zdGFuY2UtdWlkJykpIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0c3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB0cmFjay5lbmFibGVkID0gY250cy52aWRlb0VuYWJsZWQpO1xuXHRcdFx0XHRcdFx0c3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB0cmFjay5lbmFibGVkID0gY250cy5hdWRpb0VuYWJsZWQpO1xuXHRcdFx0XHRcdFx0c3RhdGUubG9jYWxTdHJlYW0gPSBzdHJlYW07XG5cdFx0XHRcdFx0XHRpZiAoX19wdHRFbmFibGVkKHN0YXRlKSkge1xuXHRcdFx0XHRcdFx0XHRPbVV0aWwuYWxlcnQoJ3dhcm5pbmcnLCAkKCcjdXNlci12aWRlbycpLmRhdGEoJ3B0dC1pbmZvJyksIDEwMDAwKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGxldCBfc3RyZWFtID0gc3RyZWFtO1xuXHRcdFx0XHRcdFx0Y29uc3QgZGF0YSA9IHt9O1xuXHRcdFx0XHRcdFx0aWYgKHN0cmVhbS5nZXRBdWRpb1RyYWNrcygpLmxlbmd0aCAhPT0gMCkge1xuXHRcdFx0XHRcdFx0XHRsbSA9IHZjLmZpbmQoJy5sZXZlbC1tZXRlcicpO1xuXHRcdFx0XHRcdFx0XHRsbS5zaG93KCk7XG5cdFx0XHRcdFx0XHRcdGRhdGEuYUN0eCA9IG5ldyBBdWRpb0N0eCgpO1xuXHRcdFx0XHRcdFx0XHRkYXRhLmdhaW5Ob2RlID0gZGF0YS5hQ3R4LmNyZWF0ZUdhaW4oKTtcblx0XHRcdFx0XHRcdFx0ZGF0YS5hbmFseXNlciA9IGRhdGEuYUN0eC5jcmVhdGVBbmFseXNlcigpO1xuXHRcdFx0XHRcdFx0XHRkYXRhLmFTcmMgPSBkYXRhLmFDdHguY3JlYXRlTWVkaWFTdHJlYW1Tb3VyY2Uoc3RyZWFtKTtcblx0XHRcdFx0XHRcdFx0ZGF0YS5hU3JjLmNvbm5lY3QoZGF0YS5nYWluTm9kZSk7XG5cdFx0XHRcdFx0XHRcdGRhdGEuZ2Fpbk5vZGUuY29ubmVjdChkYXRhLmFuYWx5c2VyKTtcblx0XHRcdFx0XHRcdFx0aWYgKFZpZGVvVXRpbC5pc0VkZ2UoKSkge1xuXHRcdFx0XHRcdFx0XHRcdGRhdGEuYW5hbHlzZXIuY29ubmVjdChkYXRhLmFDdHguZGVzdGluYXRpb24pO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdGRhdGEuYURlc3QgPSBkYXRhLmFDdHguY3JlYXRlTWVkaWFTdHJlYW1EZXN0aW5hdGlvbigpO1xuXHRcdFx0XHRcdFx0XHRcdGRhdGEuYW5hbHlzZXIuY29ubmVjdChkYXRhLmFEZXN0KTtcblx0XHRcdFx0XHRcdFx0XHRfc3RyZWFtID0gZGF0YS5hRGVzdC5zdHJlYW07XG5cdFx0XHRcdFx0XHRcdFx0c3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiBfc3RyZWFtLmFkZFRyYWNrKHRyYWNrKSk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHN0YXRlLmRhdGEgPSBkYXRhO1xuXHRcdFx0XHRcdFx0X19jcmVhdGVWaWRlbyhzdGF0ZSk7XG5cdFx0XHRcdFx0XHRzdGF0ZS5zdHJlYW0gPSBfc3RyZWFtO1xuXHRcdFx0XHRcdFx0Y2FsbGJhY2sobXNnLCBzdGF0ZSwgY250cyk7XG5cdFx0XHRcdFx0fSlcblx0XHRcdFx0XHQuY2F0Y2goZnVuY3Rpb24oZXJyKSB7XG5cdFx0XHRcdFx0XHRWaWRlb01nclV0aWwuc2VuZE1lc3NhZ2Uoe1xuXHRcdFx0XHRcdFx0XHRpZCA6ICdkZXZpY2VzQWx0ZXJlZCdcblx0XHRcdFx0XHRcdFx0LCB1aWQ6IHNkLnVpZFxuXHRcdFx0XHRcdFx0XHQsIGF1ZGlvOiBmYWxzZVxuXHRcdFx0XHRcdFx0XHQsIHZpZGVvOiBmYWxzZVxuXHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRWaWRlb01nclV0aWwuY2xvc2Uoc2QudWlkKTtcblx0XHRcdFx0XHRcdGlmICgnTm90UmVhZGFibGVFcnJvcicgPT09IGVyci5uYW1lKSB7XG5cdFx0XHRcdFx0XHRcdE9tVXRpbC5lcnJvcignQ2FtZXJhL01pY3JvcGhvbmUgaXMgYnVzeSBhbmQgY2FuXFwndCBiZSB1c2VkJyk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRPbVV0aWwuZXJyb3IoZXJyKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblx0XHRcdH0pO1xuXHRcdH1cblx0XHRmdW5jdGlvbiBfX2Nvbm5lY3Rpb25TdGF0ZUNoYW5nZUxpc3RlbmVyKHN0YXRlKSB7XG5cdFx0XHRjb25zdCBwYyA9IHN0YXRlLmRhdGEucnRjUGVlci5wYztcblx0XHRcdGNvbnNvbGUud2FybihgISFSVENQZWVyQ29ubmVjdGlvbiBzdGF0ZSBjaGFuZ2VkOiAke3BjLmNvbm5lY3Rpb25TdGF0ZX0sIHVzZXI6ICR7c2QudXNlci5kaXNwbGF5TmFtZX0sIHVpZDogJHtzZC51aWR9YCk7XG5cdFx0XHRzd2l0Y2gocGMuY29ubmVjdGlvblN0YXRlKSB7XG5cdFx0XHRcdGNhc2UgXCJjb25uZWN0ZWRcIjpcblx0XHRcdFx0XHRpZiAoc2Quc2VsZikge1xuXHRcdFx0XHRcdFx0Ly8gVGhlIGNvbm5lY3Rpb24gaGFzIGJlY29tZSBmdWxseSBjb25uZWN0ZWRcblx0XHRcdFx0XHRcdE9tVXRpbC5hbGVydCgnaW5mbycsIGBDb25uZWN0aW9uIHRvIE1lZGlhIHNlcnZlciBoYXMgYmVlbiBlc3RhYmxpc2hlZGAsIDMwMDApOy8vbm90aWZ5IHVzZXJcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJkaXNjb25uZWN0ZWRcIjpcblx0XHRcdFx0Y2FzZSBcImZhaWxlZFwiOlxuXHRcdFx0XHRcdC8vY29ubmVjdGlvbiBoYXMgYmVlbiBkcm9wcGVkXG5cdFx0XHRcdFx0T21VdGlsLmFsZXJ0KCd3YXJuaW5nJywgYE1lZGlhIHNlcnZlciBjb25uZWN0aW9uIGZvciB1c2VyICR7c2QudXNlci5kaXNwbGF5TmFtZX0gaXMgJHtwYy5jb25uZWN0aW9uU3RhdGV9LCB3aWxsIHRyeSB0byByZS1jb25uZWN0YCwgMzAwMCk7Ly9ub3RpZnkgdXNlclxuXHRcdFx0XHRcdF9yZWZyZXNoKCk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJjbG9zZWRcIjpcblx0XHRcdFx0XHQvLyBUaGUgY29ubmVjdGlvbiBoYXMgYmVlbiBjbG9zZWRcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9XG5cdFx0ZnVuY3Rpb24gX19jcmVhdGVTZW5kUGVlcihtc2csIHN0YXRlLCBjbnRzKSB7XG5cdFx0XHRzdGF0ZS5vcHRpb25zID0ge1xuXHRcdFx0XHRtZWRpYVN0cmVhbTogc3RhdGUuc3RyZWFtXG5cdFx0XHRcdCwgbWVkaWFDb25zdHJhaW50czogY250c1xuXHRcdFx0XHQsIG9uSWNlQ2FuZGlkYXRlOiBzZWxmLm9uSWNlQ2FuZGlkYXRlXG5cdFx0XHRcdCwgb25Db25uZWN0aW9uU3RhdGVDaGFuZ2U6ICgpID0+IF9fY29ubmVjdGlvblN0YXRlQ2hhbmdlTGlzdGVuZXIoc3RhdGUpXG5cdFx0XHR9O1xuXHRcdFx0Y29uc3QgdmlkID0gX19nZXRWaWRlbyhzdGF0ZSk7XG5cdFx0XHRWaWRlb1V0aWwucGxheVNyYyh2aWQsIHN0YXRlLnN0cmVhbSwgdHJ1ZSk7XG5cblx0XHRcdGNvbnN0IGRhdGEgPSBzdGF0ZS5kYXRhO1xuXHRcdFx0ZGF0YS5ydGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXIuU2VuZG9ubHkoVmlkZW9VdGlsLmFkZEljZVNlcnZlcnMoc3RhdGUub3B0aW9ucywgbXNnKSk7XG5cdFx0XHRpZiAoZGF0YS5hbmFseXNlcikge1xuXHRcdFx0XHRsZXZlbCA9IG5ldyBNaWNMZXZlbCgpO1xuXHRcdFx0XHRsZXZlbC5tZXRlcihkYXRhLmFuYWx5c2VyLCBsbSwgX21pY0FjdGl2aXR5LCBPbVV0aWwuZXJyb3IpO1xuXHRcdFx0fVxuXHRcdFx0ZGF0YS5ydGNQZWVyLmNyZWF0ZU9mZmVyKClcblx0XHRcdFx0LnRoZW4oc2RwT2ZmZXIgPT4ge1xuXHRcdFx0XHRcdGRhdGEucnRjUGVlci5wcm9jZXNzTG9jYWxPZmZlcihzZHBPZmZlcik7XG5cdFx0XHRcdFx0T21VdGlsLmxvZygnSW52b2tpbmcgU2VuZGVyIFNEUCBvZmZlciBjYWxsYmFjayBmdW5jdGlvbicpO1xuXHRcdFx0XHRcdGNvbnN0IGJtc2cgPSB7XG5cdFx0XHRcdFx0XHRcdGlkIDogJ2Jyb2FkY2FzdFN0YXJ0ZWQnXG5cdFx0XHRcdFx0XHRcdCwgdWlkOiBzZC51aWRcblx0XHRcdFx0XHRcdFx0LCBzZHBPZmZlcjogc2RwT2ZmZXIuc2RwXG5cdFx0XHRcdFx0XHR9LCB2dHJhY2tzID0gc3RhdGUuc3RyZWFtLmdldFZpZGVvVHJhY2tzKCk7XG5cdFx0XHRcdFx0aWYgKHZ0cmFja3MgJiYgdnRyYWNrcy5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0XHRjb25zdCB2dHMgPSB2dHJhY2tzWzBdLmdldFNldHRpbmdzKCk7XG5cdFx0XHRcdFx0XHR2aWRTaXplLndpZHRoID0gdnRzLndpZHRoO1xuXHRcdFx0XHRcdFx0dmlkU2l6ZS5oZWlnaHQgPSB2dHMuaGVpZ2h0O1xuXHRcdFx0XHRcdFx0Ym1zZy53aWR0aCA9IHZ0cy53aWR0aDtcblx0XHRcdFx0XHRcdGJtc2cuaGVpZ2h0ID0gdnRzLmhlaWdodDtcblx0XHRcdFx0XHRcdGJtc2cuZnBzID0gdnRzLmZyYW1lUmF0ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0VmlkZW9NZ3JVdGlsLnNlbmRNZXNzYWdlKGJtc2cpO1xuXHRcdFx0XHRcdGlmIChpc1NoYXJpbmcpIHtcblx0XHRcdFx0XHRcdFNoYXJlci5zZXRTaGFyZVN0YXRlKFNoYXJlci5TSEFSRV9TVEFSVEVEKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKGlzUmVjb3JkaW5nKSB7XG5cdFx0XHRcdFx0XHRTaGFyZXIuc2V0UmVjU3RhdGUoU2hhcmVyLlNIQVJFX1NUQVJURUQpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSlcblx0XHRcdFx0LmNhdGNoKGVycm9yID0+IE9tVXRpbC5lcnJvcihlcnJvcikpO1xuXHRcdH1cblx0XHRmdW5jdGlvbiBfY3JlYXRlU2VuZFBlZXIobXNnLCBzdGF0ZSkge1xuXHRcdFx0aWYgKGlzU2hhcmluZyB8fCBpc1JlY29yZGluZykge1xuXHRcdFx0XHRfZ2V0U2NyZWVuU3RyZWFtKG1zZywgc3RhdGUsIF9fY3JlYXRlU2VuZFBlZXIpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0X2dldFZpZGVvU3RyZWFtKG1zZywgc3RhdGUsIF9fY3JlYXRlU2VuZFBlZXIpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRmdW5jdGlvbiBfY3JlYXRlUmVzdlBlZXIobXNnLCBzdGF0ZSkge1xuXHRcdFx0X19jcmVhdGVWaWRlbyhzdGF0ZSk7XG5cdFx0XHRjb25zdCBvcHRpb25zID0gVmlkZW9VdGlsLmFkZEljZVNlcnZlcnMoe1xuXHRcdFx0XHRtZWRpYUNvbnN0cmFpbnRzOiB7YXVkaW86IHRydWUsIHZpZGVvOiB0cnVlfVxuXHRcdFx0XHQsIG9uSWNlQ2FuZGlkYXRlIDogc2VsZi5vbkljZUNhbmRpZGF0ZVxuXHRcdFx0XHQsIG9uQ29ubmVjdGlvblN0YXRlQ2hhbmdlOiAoKSA9PiBfX2Nvbm5lY3Rpb25TdGF0ZUNoYW5nZUxpc3RlbmVyKHN0YXRlKVxuXHRcdFx0fSwgbXNnKTtcblx0XHRcdGNvbnN0IGRhdGEgPSBzdGF0ZS5kYXRhO1xuXHRcdFx0ZGF0YS5ydGNQZWVyID0gbmV3IFdlYlJ0Y1BlZXIuUmVjdm9ubHkob3B0aW9ucyk7XG5cdFx0XHRkYXRhLnJ0Y1BlZXIuY3JlYXRlT2ZmZXIoKVxuXHRcdFx0XHQudGhlbihzZHBPZmZlciA9PiB7XG5cdFx0XHRcdFx0ZGF0YS5ydGNQZWVyLnByb2Nlc3NMb2NhbE9mZmVyKHNkcE9mZmVyKTtcblx0XHRcdFx0XHRPbVV0aWwubG9nKCdJbnZva2luZyBSZWNlaXZlciBTRFAgb2ZmZXIgY2FsbGJhY2sgZnVuY3Rpb24nKTtcblx0XHRcdFx0XHRWaWRlb01nclV0aWwuc2VuZE1lc3NhZ2Uoe1xuXHRcdFx0XHRcdFx0aWQgOiAnYWRkTGlzdGVuZXInXG5cdFx0XHRcdFx0XHQsIHNlbmRlcjogc2QudWlkXG5cdFx0XHRcdFx0XHQsIHNkcE9mZmVyOiBzZHBPZmZlci5zZHBcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fSlcblx0XHRcdFx0LmNhdGNoKGdlbkVyciA9PiBPbVV0aWwuZXJyb3IoJ1JlY2VpdmVyIHNkcCBvZmZlciBlcnJvciAnICsgZ2VuRXJyKSk7XG5cdFx0fVxuXHRcdGZ1bmN0aW9uIF9oYW5kbGVNaWNTdGF0dXMoc3RhdGUpIHtcblx0XHRcdGlmICghZm9vdGVyIHx8ICFmb290ZXIuaXMoJzp2aXNpYmxlJykpIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHN0YXRlKSB7XG5cdFx0XHRcdGZvb3Rlci50ZXh0KGZvb3Rlci5kYXRhKCdvbicpKTtcblx0XHRcdFx0Zm9vdGVyLmFkZENsYXNzKCdtaWMtb24nKTtcblx0XHRcdFx0dC5hZGRDbGFzcygnbWljLW9uJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRmb290ZXIudGV4dChmb290ZXIuZGF0YSgnb2ZmJykpO1xuXHRcdFx0XHRmb290ZXIucmVtb3ZlQ2xhc3MoJ21pYy1vbicpO1xuXHRcdFx0XHR0LnJlbW92ZUNsYXNzKCdtaWMtb24nKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZnVuY3Rpb24gX2luaXRDb250YWluZXIoX2lkLCBuYW1lLCBvcHRzLCBpbnN0YW5jZVVpZCkge1xuXHRcdFx0bGV0IGNvbnRTZWwgPSAnI3VzZXInICsgc2QuY3VpZDtcblx0XHRcdGNvbnN0IF9oYXNWaWRlbyA9IFZpZGVvVXRpbC5oYXNWaWRlbyhzZClcblx0XHRcdGlmIChfaGFzVmlkZW8pIHtcblx0XHRcdFx0Y29uc3QgcyA9IFZpZGVvU2V0dGluZ3MubG9hZCgpO1xuXHRcdFx0XHRpZiAocy5maXhlZC5lbmFibGVkICYmICFvcHRzLmludGVydmlldyAmJiAhaXNTaGFyaW5nKSB7XG5cdFx0XHRcdFx0c2l6ZSA9IHtcblx0XHRcdFx0XHRcdHdpZHRoOiBzLmZpeGVkLndpZHRoXG5cdFx0XHRcdFx0XHQsIGhlaWdodDogcy5maXhlZC5oZWlnaHRcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHNpemUgPSB7XG5cdFx0XHRcdFx0XHR3aWR0aDogc2Qud2lkdGhcblx0XHRcdFx0XHRcdCwgaGVpZ2h0OiBzZC5oZWlnaHRcblx0XHRcdFx0XHR9O1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzaXplID0ge1xuXHRcdFx0XHRcdHdpZHRoOiAxMjBcblx0XHRcdFx0XHQsIGhlaWdodDogOTBcblx0XHRcdFx0fTtcblx0XHRcdH1cblx0XHRcdGhhc1ZpZGVvID0gX2hhc1ZpZGVvIHx8ICQoY29udFNlbCkubGVuZ3RoIDwgMTtcblx0XHRcdGlmIChoYXNWaWRlbykge1xuXHRcdFx0XHRpZiAob3B0cy5pbnRlcnZpZXcpIHtcblx0XHRcdFx0XHRjb25zdCBhcmVhID0gJCgnLnBvZC1hcmVhJyk7XG5cdFx0XHRcdFx0Y29uc3QgY29udElkID0gY3J5cHRvLnJhbmRvbVVVSUQoKTtcblx0XHRcdFx0XHRjb250U2VsID0gJyMnICsgY29udElkO1xuXHRcdFx0XHRcdGFyZWEuYXBwZW5kKCQoJzxkaXYgY2xhc3M9XCJwb2RcIj48L2Rpdj4nKS5hdHRyKCdpZCcsIGNvbnRJZCkpO1xuXHRcdFx0XHRcdFdiQXJlYS51cGRhdGVBcmVhQ2xhc3MoKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRjb250U2VsID0gJy5yb29tLWJsb2NrIC5yb29tLWNvbnRhaW5lcic7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdCQoY29udFNlbCkuYXBwZW5kKE9tVXRpbC50bXBsKCcjdXNlci12aWRlbycsIF9pZClcblx0XHRcdFx0XHQuYXR0cigndGl0bGUnLCBuYW1lKVxuXHRcdFx0XHRcdC5hdHRyKCdkYXRhLWNsaWVudC11aWQnLCBzZC5jdWlkKVxuXHRcdFx0XHRcdC5hdHRyKCdkYXRhLWNsaWVudC10eXBlJywgc2QudHlwZSlcblx0XHRcdFx0XHQuYXR0cignZGF0YS1pbnN0YW5jZS11aWQnLCBpbnN0YW5jZVVpZClcblx0XHRcdFx0XHQuZGF0YShzZWxmKSk7XG5cdFx0XHR2ID0gJCgnIycgKyBfaWQpO1xuXHRcdFx0dmMgPSB2LmZpbmQoJy52aWRlbycpO1xuXHRcdFx0bXV0ZU90aGVycyA9IHZjLmZpbmQoJy5tdXRlLW90aGVycycpO1xuXHRcdFx0X3NldFJpZ2h0cygpO1xuXHRcdFx0cmV0dXJuIGNvbnRTZWw7XG5cdFx0fVxuXHRcdGZ1bmN0aW9uIF9pbml0RGlhbG9nKHYsIG9wdHMpIHtcblx0XHRcdGlmIChvcHRzLmludGVydmlldykge1xuXHRcdFx0XHR2LmRpYWxvZygnb3B0aW9uJywgJ2RyYWdnYWJsZScsIGZhbHNlKTtcblx0XHRcdFx0di5kaWFsb2coJ29wdGlvbicsICdyZXNpemFibGUnLCBmYWxzZSk7XG5cdFx0XHRcdCQoJy5wb2QtYXJlYScpLnNvcnRhYmxlKCdyZWZyZXNoJyk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR2LmRpYWxvZygnb3B0aW9uJywgJ2RyYWdnYWJsZScsIHRydWUpO1xuXHRcdFx0XHR2LmRpYWxvZygnb3B0aW9uJywgJ3Jlc2l6YWJsZScsIHRydWUpO1xuXHRcdFx0XHRpZiAoaXNTaGFyaW5nKSB7XG5cdFx0XHRcdFx0di5vbignZGlhbG9nY2xvc2UnLCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFZpZGVvTWdyVXRpbC5jbG9zZShzZC51aWQsIHRydWUpO1xuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGNvbnN0IHVpID0gdi5jbG9zZXN0KCcudWktZGlhbG9nJyk7XG5cdFx0XHRcdGNvbnN0IHBhcmVudCA9ICQoJy5yb29tLWJsb2NrIC5yb29tLWNvbnRhaW5lciAuc2Itd2InKTtcblx0XHRcdFx0dWkuZHJhZ2dhYmxlKCdvcHRpb24nLCAnY29udGFpbm1lbnQnLCBwYXJlbnQpO1xuXHRcdFx0XHR1aS5yZXNpemFibGUoJ29wdGlvbicsICdjb250YWlubWVudCcsIHBhcmVudCk7XG5cdFx0XHR9XG5cdFx0XHRfaW5pdERpYWxvZ0J0bnMob3B0cyk7XG5cdFx0fVxuXHRcdGZ1bmN0aW9uIF9pbml0RGlhbG9nQnRucyhvcHRzKSB7XG5cdFx0XHRmdW5jdGlvbiBub0RibENsaWNrKGVsZW0pIHtcblx0XHRcdFx0ZWxlbS5kYmxjbGljayhmdW5jdGlvbihlKSB7XG5cdFx0XHRcdFx0ZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXHRcdFx0di5wYXJlbnQoKS5maW5kKCcudWktZGlhbG9nLXRpdGxlYmFyLWNsb3NlJykucmVtb3ZlKCk7XG5cdFx0XHR2LnBhcmVudCgpLmFwcGVuZChPbVV0aWwudG1wbCgnI3ZpZGVvLWJ1dHRvbi1iYXInKSk7XG5cdFx0XHRjb25zdCByZWZyZXNoID0gdi5wYXJlbnQoKS5maW5kKCcuYnRuLXJlZnJlc2gnKVxuXHRcdFx0XHQsIHRnbCA9IHYucGFyZW50KCkuZmluZCgnLmJ0bi10b2dnbGUnKVxuXHRcdFx0XHQsIGNscyA9IHYucGFyZW50KCkuZmluZCgnLmJ0bi13Y2xvc2UnKTtcblx0XHRcdGlmIChpc1NoYXJpbmcpIHtcblx0XHRcdFx0Y2xzLmNsaWNrKGZ1bmN0aW9uIChfKSB7XG5cdFx0XHRcdFx0di5kaWFsb2coJ2Nsb3NlJyk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9KTtcblx0XHRcdFx0bm9EYmxDbGljayhjbHMpO1xuXHRcdFx0XHRyZWZyZXNoLnJlbW92ZSgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0Y2xzLnJlbW92ZSgpO1xuXHRcdFx0XHRyZWZyZXNoLmNsaWNrKGZ1bmN0aW9uKGUpIHtcblx0XHRcdFx0XHRlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXHRcdFx0XHRcdF9yZWZyZXNoKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblx0XHRcdGlmIChvcHRzLmludGVydmlldykge1xuXHRcdFx0XHR0Z2wucmVtb3ZlKCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0Z2wuY2xpY2soZnVuY3Rpb24gKGUpIHtcblx0XHRcdFx0XHRlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXHRcdFx0XHRcdCQodGhpcykudG9nZ2xlQ2xhc3MoJ21pbmltaXplZCcpO1xuXHRcdFx0XHRcdHYudG9nZ2xlKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9KTtcblx0XHRcdFx0bm9EYmxDbGljayh0Z2wpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRmdW5jdGlvbiBfdXBkYXRlKF9jKSB7XG5cdFx0XHRjb25zdCBwcmV2QSA9IHNkLmFjdGl2aXRpZXNcblx0XHRcdFx0LCBwcmV2VyA9IHZpZFNpemUud2lkdGggfHwgc2Qud2lkdGggLy8gdHJ5IHRvIGNoZWNrIGFjdHVhbCBzaXplIG9mIHZpZGVvIGZpcnN0XG5cdFx0XHRcdCwgcHJldkggPSB2aWRTaXplLmhlaWdodCB8fCBzZC5oZWlnaHQgLy8gdHJ5IHRvIGNoZWNrIGFjdHVhbCBzaXplIG9mIHZpZGVvIGZpcnN0XG5cdFx0XHRcdCwgcHJldkNhbSA9IHNkLmNhbVxuXHRcdFx0XHQsIHByZXZNaWMgPSBzZC5taWM7XG5cdFx0XHRzZC5hY3Rpdml0aWVzID0gX2MuYWN0aXZpdGllcy5zb3J0KCk7XG5cdFx0XHRzZC5sZXZlbCA9IF9jLmxldmVsO1xuXHRcdFx0c2QudXNlci5maXJzdE5hbWUgPSBfYy51c2VyLmZpcnN0TmFtZTtcblx0XHRcdHNkLnVzZXIubGFzdE5hbWUgPSBfYy51c2VyLmxhc3ROYW1lO1xuXHRcdFx0c2QudXNlci5kaXNwbGF5TmFtZSA9IF9jLnVzZXIuZGlzcGxheU5hbWU7XG5cdFx0XHRzZC53aWR0aCA9IF9jLndpZHRoO1xuXHRcdFx0c2QuaGVpZ2h0ID0gX2MuaGVpZ2h0O1xuXHRcdFx0c2QuY2FtID0gX2MuY2FtO1xuXHRcdFx0c2QubWljID0gX2MubWljO1xuXHRcdFx0Y29uc3QgbmFtZSA9IHNkLnVzZXIuZGlzcGxheU5hbWU7XG5cdFx0XHRpZiAoaGFzVmlkZW8pIHtcblx0XHRcdFx0di5kaWFsb2coJ29wdGlvbicsICd0aXRsZScsIG5hbWUpLnBhcmVudCgpLmZpbmQoJy51aS1kaWFsb2ctdGl0bGViYXInKS5hdHRyKCd0aXRsZScsIG5hbWUpO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3Qgc2FtZSA9IHByZXZBLmxlbmd0aCA9PT0gc2QuYWN0aXZpdGllcy5sZW5ndGhcblx0XHRcdFx0JiYgcHJldkEuZXZlcnkoZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7IHJldHVybiB2YWx1ZSA9PT0gc2QuYWN0aXZpdGllc1tpbmRleF19KVxuXHRcdFx0XHQmJiBwcmV2VyA9PT0gc2Qud2lkdGggJiYgcHJldkggPT09IHNkLmhlaWdodFxuXHRcdFx0XHQmJiBwcmV2Q2FtID09IHNkLmNhbSAmJiBwcmV2TWljID09PSBzZC5taWM7XG5cdFx0XHRjb25zdCBjYW1DaGFuZ2VkID0gc2QuY2FtRW5hYmxlZCAhPT0gX2MuY2FtRW5hYmxlZFxuXHRcdFx0XHQsIG1pY0NoYW5nZWQgPSBzZC5taWNFbmFibGVkICE9PSBfYy5taWNFbmFibGVkXG5cdFx0XHRpZiAoc2Quc2VsZiAmJiAhc2FtZSkge1xuXHRcdFx0XHRfY2xlYW51cCgpO1xuXHRcdFx0XHR2LnJlbW92ZSgpO1xuXHRcdFx0XHRfaW5pdCh7c3RyZWFtOiBzZCwgaWNlU2VydmVyczogaWNlU2VydmVyc30pO1xuXHRcdFx0fSBlbHNlIGlmIChjYW1DaGFuZ2VkIHx8IG1pY0NoYW5nZWQpIHtcblx0XHRcdFx0c2QubWljRW5hYmxlZCA9IF9jLm1pY0VuYWJsZWQ7XG5cdFx0XHRcdHNkLmNhbUVuYWJsZWQgPSBfYy5jYW1FbmFibGVkO1xuXHRcdFx0XHRjb25zdCBzdGF0ZSA9IF9fZ2V0U3RhdGUoKTtcblx0XHRcdFx0aWYgKGNhbUNoYW5nZWQpIHtcblx0XHRcdFx0XHRWaWRlb01nclV0aWwuc2F2ZVBvZCh2KTtcblx0XHRcdFx0XHR2Lm9mZigpO1xuXHRcdFx0XHRcdGlmICh2LmRpYWxvZygnaW5zdGFuY2UnKSkge1xuXHRcdFx0XHRcdFx0di5kaWFsb2coJ2Rlc3Ryb3knKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0di5yZW1vdmUoKTtcblx0XHRcdFx0XHRfX2luaXRVSSh2LmRhdGEoJ2luc3RhbmNlLXVpZCcpKTtcblx0XHRcdFx0XHRfX2NyZWF0ZVZpZGVvKHN0YXRlKTtcblx0XHRcdFx0XHRWaWRlb1V0aWwucGxheVNyYyhzdGF0ZS52aWRlb1swXSwgc3RhdGUuc3RyZWFtIHx8IHN0YXRlLnJTdHJlYW0sIHNkLnNlbGYpO1xuXHRcdFx0XHRcdGlmIChzdGF0ZS5kYXRhLmFuYWx5c2VyKSB7XG5cdFx0XHRcdFx0XHRsbSA9IHZjLmZpbmQoJy5sZXZlbC1tZXRlcicpO1xuXHRcdFx0XHRcdFx0bGV2ZWwuc2V0Q2FudmFzKGxtKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKG1pY0NoYW5nZWQpIHtcblx0XHRcdFx0XHRfX3VwZGF0ZVZpZGVvKHN0YXRlKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoc2Quc2VsZikge1xuXHRcdFx0XHRcdHN0YXRlLmxvY2FsU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB0cmFjay5lbmFibGVkID0gc2QuY2FtRW5hYmxlZCk7XG5cdFx0XHRcdFx0c3RhdGUubG9jYWxTdHJlYW0uZ2V0QXVkaW9UcmFja3MoKS5mb3JFYWNoKHRyYWNrID0+IHRyYWNrLmVuYWJsZWQgPSBzZC5taWNFbmFibGVkKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRmdW5jdGlvbiBfX2NyZWF0ZVZpZGVvKHN0YXRlKSB7XG5cdFx0XHRjb25zdCBfaWQgPSBWaWRlb1V0aWwuZ2V0VmlkKHNkLnVpZCk7XG5cdFx0XHRfcmVzaXplRGxnQXJlYShzaXplLndpZHRoLCBzaXplLmhlaWdodCk7XG5cdFx0XHRpZiAoaGFzVmlkZW8gJiYgIWlzU2hhcmluZyAmJiAhaXNSZWNvcmRpbmcpIHtcblx0XHRcdFx0Ly8gbGV0J3MgdHJ5IHRvIHJlc3RvcmUgc2l6ZStwb3NpdGlvblxuXHRcdFx0XHRjb25zdCBvcHRzID0gUm9vbS5nZXRPcHRpb25zKClcblx0XHRcdFx0XHQsIHN0b3JlZCA9ICQoYCN1c2VyJHtzZC5jdWlkfWApLmRhdGEoJ3ZpZGVvLXBvZCcpO1xuXHRcdFx0XHRpZiAoIW9wdHMuaW50ZXJ2aWV3ICYmIHN0b3JlZCkge1xuXHRcdFx0XHRcdGNvbnN0IHdpZGdldCA9IHYuZGlhbG9nKCd3aWRnZXQnKTtcblx0XHRcdFx0XHR3aWRnZXQuY3NzKCdsZWZ0Jywgc3RvcmVkLngpO1xuXHRcdFx0XHRcdHdpZGdldC5jc3MoJ3RvcCcsIHN0b3JlZC55KVxuXHRcdFx0XHRcdHdpZGdldC5jc3MoJ3dpZHRoJywgc3RvcmVkLncpO1xuXHRcdFx0XHRcdHdpZGdldC5jc3MoJ2hlaWdodCcsIHN0b3JlZC5oKVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFZpZGVvVXRpbC5zZXRQb3ModiwgVmlkZW9VdGlsLmdldFBvcyhWaWRlb1V0aWwuZ2V0UmVjdHMoVmlkZW9VdGlsLlZJRFdJTl9TRUwsIF9pZCksIHNkLndpZHRoLCBzZC5oZWlnaHQgKyAyNSkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRzdGF0ZS52aWRlbyA9ICQoaGFzVmlkZW8gPyAnPHZpZGVvPicgOiAnPGF1ZGlvPicpLmF0dHIoJ2lkJywgJ3ZpZCcgKyBfaWQpXG5cdFx0XHRcdC5hdHRyKCdwbGF5c2lubGluZScsICdwbGF5c2lubGluZScpXG5cdFx0XHRcdC8vLmF0dHIoJ2F1dG9wbGF5JywgJ2F1dG9wbGF5Jylcblx0XHRcdFx0LnByb3AoJ2NvbnRyb2xzJywgZmFsc2UpXG5cdFx0XHRcdC53aWR0aCh2Yy53aWR0aCgpKS5oZWlnaHQodmMuaGVpZ2h0KCkpO1xuXHRcdFx0aWYgKHN0YXRlLmRhdGEpIHtcblx0XHRcdFx0c3RhdGUudmlkZW8uZGF0YShzdGF0ZS5kYXRhKTtcblx0XHRcdH1cblx0XHRcdGlmIChoYXNWaWRlbykge1xuXHRcdFx0XHR2Yy5yZW1vdmVDbGFzcygnYXVkaW8tb25seScpLmNzcygnYmFja2dyb3VuZC1pbWFnZScsICcnKTtcblx0XHRcdFx0dmMucGFyZW50cygnLnVpLWRpYWxvZycpLnJlbW92ZUNsYXNzKCdhdWRpby1vbmx5Jyk7XG5cdFx0XHRcdHN0YXRlLnZpZGVvLmF0dHIoJ3Bvc3RlcicsIHNkLnVzZXIucGljdHVyZVVyaSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzdGF0ZS52aWRlby5hdHRyKCdwb3N0ZXInLCBudWxsKTtcblx0XHRcdFx0dmMuYWRkQ2xhc3MoJ2F1ZGlvLW9ubHknKTtcblx0XHRcdH1cblx0XHRcdHZjLmFwcGVuZChzdGF0ZS52aWRlbyk7XG5cdFx0XHRfX3VwZGF0ZVZpZGVvKHN0YXRlKTtcblx0XHR9XG5cdFx0ZnVuY3Rpb24gX191cGRhdGVWaWRlbyhzdGF0ZSkge1xuXHRcdFx0aWYgKFZpZGVvVXRpbC5oYXNNaWMoc2QpKSB7XG5cdFx0XHRcdGNvbnN0IHZvbEljbyA9IHZvbC5jcmVhdGUoc2VsZilcblx0XHRcdFx0aWYgKGhhc1ZpZGVvKSB7XG5cdFx0XHRcdFx0di5wYXJlbnQoKS5maW5kKCcuYnV0dG9ucGFuZScpLmFwcGVuZCh2b2xJY28pO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHZvbEljby5hZGRDbGFzcygndWxpc3Qtc21hbGwnKTtcblx0XHRcdFx0XHR2b2xJY28uaW5zZXJ0QWZ0ZXIoJyN1c2VyJyArIHNkLmN1aWQgKyAnIC50eXBpbmctYWN0aXZpdHknKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dm9sLmRlc3Ryb3koKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZnVuY3Rpb24gX3JlZnJlc2goX21zZykge1xuXHRcdFx0Y29uc3QgbXNnID0gX21zZyB8fCB7XG5cdFx0XHRcdGljZVNlcnZlcnM6IGljZVNlcnZlcnNcblx0XHRcdFx0LCBpbnN0YW5jZVVpZDogdi5sZW5ndGggPiAwID8gdi5kYXRhKCdpbnN0YW5jZS11aWQnKSA6IHVuZGVmaW5lZFxuXHRcdFx0fTtcblx0XHRcdGlmIChzZC5zZWxmKSB7XG5cdFx0XHRcdFZpZGVvTWdyVXRpbC5zZW5kTWVzc2FnZSh7XG5cdFx0XHRcdFx0aWQgOiAnYnJvYWRjYXN0UmVzdGFydGVkJ1xuXHRcdFx0XHRcdCwgdWlkOiBzZC51aWRcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cdFx0XHRfY2xlYW51cCgpO1xuXHRcdFx0Y29uc3QgaGFzQXVkaW8gPSBWaWRlb1V0aWwuaGFzTWljKHNkKVxuXHRcdFx0XHQsIHN0YXRlID0ge1xuXHRcdFx0XHRcdGRpc3Bvc2VkOiBmYWxzZVxuXHRcdFx0XHRcdCwgZGF0YToge31cblx0XHRcdFx0fTtcblx0XHRcdHN0YXRlcy5wdXNoKHN0YXRlKTtcblx0XHRcdGlmIChzZC5zZWxmKSB7XG5cdFx0XHRcdF9jcmVhdGVTZW5kUGVlcihtc2csIHN0YXRlKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdF9jcmVhdGVSZXN2UGVlcihtc2csIHN0YXRlKTtcblx0XHRcdH1cblx0XHRcdF9oYW5kbGVNaWNTdGF0dXMoaGFzQXVkaW8pO1xuXHRcdH1cblx0XHRmdW5jdGlvbiBfc2V0UmlnaHRzKCkge1xuXHRcdFx0aWYgKFJvb20uaGFzUmlnaHQoWydNVVRFX09USEVSUyddKSAmJiBWaWRlb1V0aWwuaGFzTWljKHNkKSkge1xuXHRcdFx0XHRtdXRlT3RoZXJzLmFkZENsYXNzKCdlbmFibGVkJykub2ZmKCkuY2xpY2soZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0VmlkZW9NZ3JVdGlsLmNsaWNrTXV0ZU90aGVycyhzZC5jdWlkKTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRtdXRlT3RoZXJzLnJlbW92ZUNsYXNzKCdlbmFibGVkJykub2ZmKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGZ1bmN0aW9uIF9jbGVhbkRhdGEoZGF0YSkge1xuXHRcdFx0aWYgKCFkYXRhKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdGlmIChkYXRhLmFuYWx5c2VyKSB7XG5cdFx0XHRcdFZpZGVvVXRpbC5kaXNjb25uZWN0KGRhdGEuYW5hbHlzZXIpO1xuXHRcdFx0XHRkYXRhLmFuYWx5c2VyID0gbnVsbDtcblx0XHRcdH1cblx0XHRcdGlmIChkYXRhLmdhaW5Ob2RlKSB7XG5cdFx0XHRcdFZpZGVvVXRpbC5kaXNjb25uZWN0KGRhdGEuZ2Fpbk5vZGUpO1xuXHRcdFx0XHRkYXRhLmdhaW5Ob2RlID0gbnVsbDtcblx0XHRcdH1cblx0XHRcdGlmIChkYXRhLmFTcmMpIHtcblx0XHRcdFx0VmlkZW9VdGlsLmNsZWFuU3RyZWFtKGRhdGEuYVNyYy5tZWRpYVN0cmVhbSk7XG5cdFx0XHRcdFZpZGVvVXRpbC5kaXNjb25uZWN0KGRhdGEuYVNyYyk7XG5cdFx0XHRcdGRhdGEuYVNyYyA9IG51bGw7XG5cdFx0XHR9XG5cdFx0XHRpZiAoZGF0YS5hRGVzdCkge1xuXHRcdFx0XHRWaWRlb1V0aWwuZGlzY29ubmVjdChkYXRhLmFEZXN0KTtcblx0XHRcdFx0ZGF0YS5hRGVzdCA9IG51bGw7XG5cdFx0XHR9XG5cdFx0XHRpZiAoZGF0YS5hQ3R4KSB7XG5cdFx0XHRcdGlmIChkYXRhLmFDdHguZGVzdGluYXRpb24pIHtcblx0XHRcdFx0XHRWaWRlb1V0aWwuZGlzY29ubmVjdChkYXRhLmFDdHguZGVzdGluYXRpb24pO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmICgnY2xvc2VkJyAhPT0gZGF0YS5hQ3R4LnN0YXRlKSB7XG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdGRhdGEuYUN0eC5jbG9zZSgpO1xuXHRcdFx0XHRcdH0gY2F0Y2goZSkge1xuXHRcdFx0XHRcdFx0Y29uc29sZS5lcnJvcihlKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0ZGF0YS5hQ3R4ID0gbnVsbDtcblx0XHRcdH1cblx0XHRcdFZpZGVvVXRpbC5jbGVhblBlZXIoZGF0YS5ydGNQZWVyKTtcblx0XHRcdGRhdGEucnRjUGVlciA9IG51bGw7XG5cdFx0fVxuXHRcdGZ1bmN0aW9uIF9jbGVhbnVwKGV2dCkge1xuXHRcdFx0VmlkZW9NZ3JVdGlsLnNhdmVQb2Qodik7XG5cdFx0XHRkZWxldGUgdmlkU2l6ZS53aWR0aDtcblx0XHRcdGRlbGV0ZSB2aWRTaXplLmhlaWdodDtcblx0XHRcdE9tVXRpbC5sb2coJyEhRGlzcG9zaW5nIHBhcnRpY2lwYW50ICcgKyBzZC51aWQpO1xuXHRcdFx0bGV0IHN0YXRlO1xuXHRcdFx0d2hpbGUoc3RhdGUgPSBzdGF0ZXMucG9wKCkpIHtcblx0XHRcdFx0c3RhdGUuZGlzcG9zZWQgPSB0cnVlO1xuXHRcdFx0XHRpZiAoc3RhdGUub3B0aW9ucykge1xuXHRcdFx0XHRcdGRlbGV0ZSBzdGF0ZS5vcHRpb25zLm1lZGlhQ29uc3RyYWludHM7XG5cdFx0XHRcdFx0ZGVsZXRlIHN0YXRlLm9wdGlvbnMub25JY2VDYW5kaWRhdGU7XG5cdFx0XHRcdFx0c3RhdGUub3B0aW9ucyA9IG51bGw7XG5cdFx0XHRcdH1cblx0XHRcdFx0X2NsZWFuRGF0YShzdGF0ZS5kYXRhKTtcblx0XHRcdFx0VmlkZW9VdGlsLmNsZWFuU3RyZWFtKHN0YXRlLmxvY2FsU3RyZWFtKTtcblx0XHRcdFx0VmlkZW9VdGlsLmNsZWFuU3RyZWFtKHN0YXRlLnN0cmVhbSk7XG5cdFx0XHRcdFZpZGVvVXRpbC5jbGVhblN0cmVhbShzdGF0ZS5yU3RyZWFtKTtcblx0XHRcdFx0c3RhdGUuZGF0YSA9IG51bGw7XG5cdFx0XHRcdHN0YXRlLmxvY2FsU3RyZWFtID0gbnVsbDtcblx0XHRcdFx0c3RhdGUuc3RyZWFtID0gbnVsbDtcblx0XHRcdFx0Y29uc3QgdmlkZW8gPSBzdGF0ZS52aWRlbztcblx0XHRcdFx0aWYgKHZpZGVvICYmIHZpZGVvLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHR2aWRlby5hdHRyKCdpZCcsICdkdW1teScpO1xuXHRcdFx0XHRcdGNvbnN0IHZpZE5vZGUgPSB2aWRlb1swXTtcblx0XHRcdFx0XHRWaWRlb1V0aWwuY2xlYW5TdHJlYW0odmlkTm9kZS5zcmNPYmplY3QpO1xuXHRcdFx0XHRcdHZpZE5vZGUuc3JjT2JqZWN0ID0gbnVsbDtcblx0XHRcdFx0XHR2aWROb2RlLmxvYWQoKTtcblx0XHRcdFx0XHR2aWROb2RlLnJlbW92ZUF0dHJpYnV0ZShcInNyY1wiKTtcblx0XHRcdFx0XHR2aWROb2RlLnJlbW92ZUF0dHJpYnV0ZShcInNyY09iamVjdFwiKTtcblx0XHRcdFx0XHR2aWROb2RlLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodmlkTm9kZSk7XG5cdFx0XHRcdFx0c3RhdGUudmlkZW8uZGF0YSh7fSk7XG5cdFx0XHRcdFx0c3RhdGUudmlkZW8gPSBudWxsO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAobG0gJiYgbG0ubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRfbWljQWN0aXZpdHkoZmFsc2UpO1xuXHRcdFx0XHRsbS5oaWRlKCk7XG5cdFx0XHRcdG11dGVPdGhlcnMucmVtb3ZlQ2xhc3MoJ2VuYWJsZWQnKS5vZmYoKTtcblx0XHRcdH1cblx0XHRcdGlmIChsZXZlbCkge1xuXHRcdFx0XHRsZXZlbC5kaXNwb3NlKCk7XG5cdFx0XHRcdGxldmVsID0gbnVsbDtcblx0XHRcdH1cblx0XHRcdHZjLmZpbmQoJ2F1ZGlvLHZpZGVvJykucmVtb3ZlKCk7XG5cdFx0XHR2b2wuZGVzdHJveSgpO1xuXHRcdFx0aWYgKGV2dCAmJiBldnQudGFyZ2V0KSB7XG5cdFx0XHRcdCQoZXZ0KS5vZmYoKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZnVuY3Rpb24gX3JlYXR0YWNoU3RyZWFtKCkge1xuXHRcdFx0c3RhdGVzLmZvckVhY2goc3RhdGUgPT4ge1xuXHRcdFx0XHRpZiAoc3RhdGUudmlkZW8gJiYgc3RhdGUudmlkZW8ubGVuZ3RoID4gMCkge1xuXHRcdFx0XHRcdGNvbnN0IGRhdGEgPSBzdGF0ZS5kYXRhXG5cdFx0XHRcdFx0XHQsIHZpZGVvRWwgPSBzdGF0ZS52aWRlb1swXTtcblx0XHRcdFx0XHRpZiAoZGF0YS5ydGNQZWVyICYmICghdmlkZW9FbC5zcmNPYmplY3QgfHwgIXZpZGVvRWwuc3JjT2JqZWN0LmFjdGl2ZSkpIHtcblx0XHRcdFx0XHRcdHZpZGVvRWwuc3JjT2JqZWN0ID0gZGF0YS5ydGNQZWVyLnN0cmVhbTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cblx0XHRmdW5jdGlvbiBfcHJvY2Vzc1NkcEFuc3dlcihhbnN3ZXIpIHtcblx0XHRcdGNvbnN0IHN0YXRlID0gX19nZXRTdGF0ZSgpO1xuXHRcdFx0aWYgKCFzdGF0ZSB8fCAhc3RhdGUuZGF0YS5ydGNQZWVyKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdHN0YXRlLmRhdGEucnRjUGVlci5wcm9jZXNzUmVtb3RlQW5zd2VyKGFuc3dlcilcblx0XHRcdFx0LnRoZW4oKCkgPT4ge1xuXHRcdFx0XHRcdGNvbnN0IHZpZGVvID0gX19nZXRWaWRlbyhzdGF0ZSk7XG5cdFx0XHRcdFx0c3RhdGUuclN0cmVhbSA9IHN0YXRlLmRhdGEucnRjUGVlci5wYy5nZXRSZW1vdGVTdHJlYW1zKClbMF07XG5cdFx0XHRcdFx0VmlkZW9VdGlsLnBsYXlTcmModmlkZW8sIHN0YXRlLnJTdHJlYW0sIGZhbHNlKTtcblx0XHRcdFx0fSlcblx0XHRcdFx0LmNhdGNoKGVycm9yID0+IE9tVXRpbC5lcnJvcihlcnJvciwgdHJ1ZSkpO1xuXHRcdH1cblx0XHRmdW5jdGlvbiBfcHJvY2Vzc0ljZUNhbmRpZGF0ZShjYW5kaWRhdGUpIHtcblx0XHRcdGNvbnN0IHN0YXRlID0gX19nZXRTdGF0ZSgpO1xuXHRcdFx0aWYgKCFzdGF0ZSB8fCAhc3RhdGUuZGF0YS5ydGNQZWVyKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdHN0YXRlLmRhdGEucnRjUGVlci5hZGRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKVxuXHRcdFx0XHQuY2F0Y2goZXJyb3IgPT4gT21VdGlsLmVycm9yKCdFcnJvciBhZGRpbmcgY2FuZGlkYXRlOiAnICsgZXJyb3IsIHRydWUpKTtcblx0XHR9XG5cdFx0ZnVuY3Rpb24gX19pbml0VUkoaW5zdGFuY2VVaWQpIHtcblx0XHRcdGlmICghdm9sKSB7XG5cdFx0XHRcdHZvbCA9IG5ldyBWb2x1bWUoKTtcblx0XHRcdH1cblx0XHRcdGlzU2hhcmluZyA9IFZpZGVvVXRpbC5pc1NoYXJpbmcoc2QpO1xuXHRcdFx0aXNSZWNvcmRpbmcgPSBWaWRlb1V0aWwuaXNSZWNvcmRpbmcoc2QpO1xuXHRcdFx0Y29uc3QgX2lkID0gVmlkZW9VdGlsLmdldFZpZChzZC51aWQpXG5cdFx0XHRcdCwgbmFtZSA9IHNkLnVzZXIuZGlzcGxheU5hbWVcblx0XHRcdFx0LCBfdyA9IHNkLndpZHRoXG5cdFx0XHRcdCwgX2ggPSBzZC5oZWlnaHRcblx0XHRcdFx0LCBvcHRzID0gUm9vbS5nZXRPcHRpb25zKCk7XG5cdFx0XHRzZC5zZWxmID0gc2QuY3VpZCA9PT0gb3B0cy51aWQ7XG5cdFx0XHRjb25zdCBjb250U2VsID0gX2luaXRDb250YWluZXIoX2lkLCBuYW1lLCBvcHRzLCBpbnN0YW5jZVVpZCk7XG5cdFx0XHRmb290ZXIgPSB2LmZpbmQoJy5mb290ZXInKTtcblx0XHRcdGlmICghb3B0cy5zaG93TWljU3RhdHVzKSB7XG5cdFx0XHRcdGZvb3Rlci5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIXNkLnNlbGYgJiYgaXNTaGFyaW5nKSB7XG5cdFx0XHRcdFNoYXJlci5jbG9zZSgpO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHNkLnNlbGYgJiYgKGlzU2hhcmluZyB8fCBpc1JlY29yZGluZykpIHtcblx0XHRcdFx0di5oaWRlKCk7XG5cdFx0XHR9IGVsc2UgaWYgKGhhc1ZpZGVvKSB7XG5cdFx0XHRcdHYuZGlhbG9nKHtcblx0XHRcdFx0XHRjbGFzc2VzOiB7XG5cdFx0XHRcdFx0XHQndWktZGlhbG9nJzogJ3ZpZGVvIHVzZXItdmlkZW8nICsgKG9wdHMuc2hvd01pY1N0YXR1cyA/ICcgbWljLXN0YXR1cycgOiAnJylcblx0XHRcdFx0XHRcdCwgJ3VpLWRpYWxvZy10aXRsZWJhcic6ICcnICsgKG9wdHMuc2hvd01pY1N0YXR1cyA/ICcgdWktc3RhdGUtaGlnaGxpZ2h0JyA6ICcnKVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHQsIHdpZHRoOiBfd1xuXHRcdFx0XHRcdCwgbWluV2lkdGg6IDQwXG5cdFx0XHRcdFx0LCBtaW5IZWlnaHQ6IDUwXG5cdFx0XHRcdFx0LCBhdXRvT3BlbjogdHJ1ZVxuXHRcdFx0XHRcdCwgbW9kYWw6IGZhbHNlXG5cdFx0XHRcdFx0LCBhcHBlbmRUbzogY29udFNlbFxuXHRcdFx0XHR9KTtcblx0XHRcdFx0X2luaXREaWFsb2codiwgb3B0cyk7XG5cdFx0XHR9XG5cdFx0XHR0ID0gdi5wYXJlbnQoKS5maW5kKCcudWktZGlhbG9nLXRpdGxlYmFyJykuYXR0cigndGl0bGUnLCBuYW1lKTtcblx0XHRcdHYub24oJ3JlbW92ZScsIF9jbGVhbnVwKTtcblx0XHRcdGlmIChoYXNWaWRlbykge1xuXHRcdFx0XHR2Yy53aWR0aChfdykuaGVpZ2h0KF9oKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZnVuY3Rpb24gX2luaXQoX21zZykge1xuXHRcdFx0c2QgPSBfbXNnLnN0cmVhbTtcblx0XHRcdHNkLmFjdGl2aXRpZXMgPSBzZC5hY3Rpdml0aWVzLnNvcnQoKTtcblx0XHRcdF9tc2cuaW5zdGFuY2VVaWQgPSBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuXHRcdFx0aWNlU2VydmVycyA9IF9tc2cuaWNlU2VydmVycztcblx0XHRcdF9faW5pdFVJKF9tc2cuaW5zdGFuY2VVaWQpO1xuXHRcdFx0X3JlZnJlc2goX21zZyk7XG5cdFx0fVxuXHRcdGZ1bmN0aW9uIF9fcHR0RW5hYmxlZChzdGF0ZSkge1xuXHRcdFx0cmV0dXJuIHNkICYmIHNkLnNlbGYgJiYgc3RhdGUgJiYgc3RhdGUubG9jYWxTdHJlYW1cblx0XHRcdFx0XHQmJiBWaWRlb1V0aWwuaGFzQWN0aXZpdHkoc2QsIFZpZGVvVXRpbC5NSUNfQUNUSVZJVFkpICYmICFzZC5taWNFbmFibGVkO1xuXHRcdH1cblxuXHRcdHRoaXMudXBkYXRlID0gX3VwZGF0ZTtcblx0XHR0aGlzLnJlZnJlc2ggPSBfcmVmcmVzaDtcblx0XHR0aGlzLnB1c2hUb1RhbGsgPSAoZW5hYmxlKSA9PiB7XG5cdFx0XHRjb25zdCBzdGF0ZSA9IF9fZ2V0U3RhdGUoKTtcblx0XHRcdGlmIChfX3B0dEVuYWJsZWQoc3RhdGUpKSB7XG5cdFx0XHRcdHN0YXRlLmxvY2FsU3RyZWFtLmdldEF1ZGlvVHJhY2tzKCkuZm9yRWFjaCh0cmFjayA9PiB0cmFjay5lbmFibGVkID0gZW5hYmxlKTtcblx0XHRcdFx0Y29uc3QgY2xhc3NlcyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNyb29tLXNpZGViYXItdGFiLXVzZXJzIC5oZWFkZXIgLm9tLWljb24uYWN0aXZpdHkubWljLmNsaWNrYWJsZScpLmNsYXNzTGlzdDtcblx0XHRcdFx0aWYgKGVuYWJsZSkge1xuXHRcdFx0XHRcdGNsYXNzZXMuYWRkKCdwdXNoLXRvLXRhbGsnKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRjbGFzc2VzLnJlbW92ZSgncHVzaC10by10YWxrJyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXHRcdHRoaXMubXV0ZSA9IGZ1bmN0aW9uKF9tdXRlKSB7XG5cdFx0XHR2b2wubXV0ZShfbXV0ZSk7XG5cdFx0fTtcblx0XHR0aGlzLmlzTXV0ZWQgPSBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB2b2wubXV0ZWQoKTtcblx0XHR9O1xuXHRcdHRoaXMuc3RyZWFtID0gZnVuY3Rpb24oKSB7IHJldHVybiBzZDsgfTtcblx0XHR0aGlzLnNldFJpZ2h0cyA9IF9zZXRSaWdodHM7XG5cdFx0dGhpcy5wcm9jZXNzU2RwQW5zd2VyID0gX3Byb2Nlc3NTZHBBbnN3ZXI7XG5cdFx0dGhpcy5wcm9jZXNzSWNlQ2FuZGlkYXRlID0gX3Byb2Nlc3NJY2VDYW5kaWRhdGU7XG5cdFx0dGhpcy5vbkljZUNhbmRpZGF0ZSA9IGZ1bmN0aW9uKGNhbmRpZGF0ZSkge1xuXHRcdFx0Y29uc3Qgb3B0cyA9IFJvb20uZ2V0T3B0aW9ucygpO1xuXHRcdFx0T21VdGlsLmxvZygnTG9jYWwgY2FuZGlkYXRlICcgKyBKU09OLnN0cmluZ2lmeShjYW5kaWRhdGUpKTtcblx0XHRcdFZpZGVvTWdyVXRpbC5zZW5kTWVzc2FnZSh7XG5cdFx0XHRcdGlkOiAnb25JY2VDYW5kaWRhdGUnXG5cdFx0XHRcdCwgY2FuZGlkYXRlOiBjYW5kaWRhdGVcblx0XHRcdFx0LCB1aWQ6IHNkLnVpZFxuXHRcdFx0XHQsIGx1aWQ6IHNkLnNlbGYgPyBzZC51aWQgOiBvcHRzLnVpZFxuXHRcdFx0fSk7XG5cdFx0fTtcblx0XHR0aGlzLnJlYXR0YWNoU3RyZWFtID0gX3JlYXR0YWNoU3RyZWFtO1xuXHRcdHRoaXMudmlkZW8gPSBmdW5jdGlvbihfc3RhdGUpIHtcblx0XHRcdGNvbnN0IHN0YXRlID0gX3N0YXRlIHx8IF9fZ2V0U3RhdGUoKTtcblx0XHRcdGlmICghc3RhdGUgfHwgc3RhdGUuZGlzcG9zZWQpIHtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gc3RhdGUudmlkZW87XG5cdFx0fTtcblx0XHR0aGlzLmhhbmRsZU1pY1N0YXR1cyA9IF9oYW5kbGVNaWNTdGF0dXM7XG5cblx0XHRfaW5pdChtc2cpO1xuXHR9XG59O1xuIiwiLyogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKSBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAgKi9cbmNvbnN0IE9tVXRpbCA9IHJlcXVpcmUoJy4uL21haW4vb211dGlscycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGNsYXNzIFZvbHVtZSB7XG5cdGNvbnN0cnVjdG9yKCkge1xuXHRcdGNvbnN0IHNlbGYgPSB0aGlzO1xuXHRcdGxldCB2aWRlbywgdm9sLCBkcm9wLCBzbGlkZXIsIGhhbmRsZUVsLCBoaWRlVGltZXIgPSBudWxsXG5cdFx0XHQsIGxhc3RWb2x1bWUgPSA1MCwgbXV0ZWQgPSBmYWxzZTtcblxuXHRcdGZ1bmN0aW9uIF9fY2FuY2VsSGlkZSgpIHtcblx0XHRcdGlmIChoaWRlVGltZXIpIHtcblx0XHRcdFx0Y2xlYXJUaW1lb3V0KGhpZGVUaW1lcik7XG5cdFx0XHRcdGhpZGVUaW1lciA9IG51bGw7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGZ1bmN0aW9uIF9faGlkZURyb3AoKSB7XG5cdFx0XHRfX2NhbmNlbEhpZGUoKTtcblx0XHRcdGhpZGVUaW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuXHRcdFx0XHRkcm9wLmhpZGUoKTtcblx0XHRcdFx0aGlkZVRpbWVyID0gbnVsbDtcblx0XHRcdH0sIDMwMDApO1xuXHRcdH1cblxuXHRcdHRoaXMuY3JlYXRlID0gKF92aWRlbykgPT4ge1xuXHRcdFx0dmlkZW8gPSBfdmlkZW87XG5cdFx0XHR0aGlzLmRlc3Ryb3koKTtcblx0XHRcdGNvbnN0IHVpZCA9IHZpZGVvLnN0cmVhbSgpLnVpZFxuXHRcdFx0XHQsIGN1aWQgPSB2aWRlby5zdHJlYW0oKS5jdWlkXG5cdFx0XHRcdCwgdm9sSWQgPSAndm9sdW1lLScgKyB1aWQ7XG5cdFx0XHR2b2wgPSBPbVV0aWwudG1wbCgnI3ZvbHVtZS1jb250cm9sLXN0dWInLCB2b2xJZClcblx0XHRcdHNsaWRlciA9IHZvbC5maW5kKCcuc2xpZGVyJyk7XG5cdFx0XHRkcm9wID0gdm9sLmZpbmQoJy5kcm9wZG93bi1tZW51Jyk7XG5cdFx0XHR2b2wub24oJ21vdXNlZW50ZXInLCBmdW5jdGlvbihlKSB7XG5cdFx0XHRcdFx0ZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcblx0XHRcdFx0XHRkcm9wLnNob3coKTtcblx0XHRcdFx0XHRfX2hpZGVEcm9wKClcblx0XHRcdFx0fSlcblx0XHRcdFx0LmNsaWNrKGZ1bmN0aW9uKGUpIHtcblx0XHRcdFx0XHRlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXHRcdFx0XHRcdE9tVXRpbC5yb29tQWN0aW9uKHthY3Rpb246ICdtdXRlJywgdWlkOiBjdWlkLCBtdXRlOiAhbXV0ZWR9KTtcblx0XHRcdFx0XHRzZWxmLm11dGUoIW11dGVkKTtcblx0XHRcdFx0XHRkcm9wLmhpZGUoKTtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH0pLmRibGNsaWNrKGZ1bmN0aW9uKGUpIHtcblx0XHRcdFx0XHRlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fSk7XG5cdFx0XHRkcm9wLm9uKCdtb3VzZWVudGVyJywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdF9fY2FuY2VsSGlkZSgpO1xuXHRcdFx0fSk7XG5cdFx0XHRkcm9wLm9uKCdtb3VzZWxlYXZlJywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdF9faGlkZURyb3AoKTtcblx0XHRcdH0pO1xuXHRcdFx0aGFuZGxlRWwgPSB2b2wuZmluZCgnLmhhbmRsZScpO1xuXHRcdFx0c2xpZGVyLnNsaWRlcih7XG5cdFx0XHRcdG9yaWVudGF0aW9uOiAndmVydGljYWwnXG5cdFx0XHRcdCwgcmFuZ2U6ICdtaW4nXG5cdFx0XHRcdCwgbWluOiAwXG5cdFx0XHRcdCwgbWF4OiAxMDBcblx0XHRcdFx0LCB2YWx1ZTogbGFzdFZvbHVtZVxuXHRcdFx0XHQsIGNyZWF0ZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aGFuZGxlRWwudGV4dCgkKHRoaXMpLnNsaWRlcigndmFsdWUnKSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0LCBzbGlkZTogZnVuY3Rpb24oZXZlbnQsIHVpKSB7XG5cdFx0XHRcdFx0c2VsZi5oYW5kbGUodWkudmFsdWUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdHRoaXMuaGFuZGxlKGxhc3RWb2x1bWUpO1xuXHRcdFx0dGhpcy5tdXRlKG11dGVkKTtcblx0XHRcdHJldHVybiB2b2w7XG5cdFx0fTtcblx0XHR0aGlzLmhhbmRsZSA9ICh2YWwpID0+IHtcblx0XHRcdGhhbmRsZUVsLnRleHQodmFsKTtcblx0XHRcdGNvbnN0IHZpZEVsID0gdmlkZW8udmlkZW8oKVxuXHRcdFx0XHQsIGRhdGEgPSB2aWRFbC5kYXRhKCk7XG5cdFx0XHRpZiAodmlkZW8uc3RyZWFtKCkuc2VsZikge1xuXHRcdFx0XHRpZiAoZGF0YS5nYWluTm9kZSkge1xuXHRcdFx0XHRcdGRhdGEuZ2Fpbk5vZGUuZ2Fpbi52YWx1ZSA9IHZhbCAvIDEwMDtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dmlkRWxbMF0udm9sdW1lID0gdmFsIC8gMTAwO1xuXHRcdFx0fVxuXHRcdFx0Y29uc3QgaWNvID0gdm9sLmZpbmQoJ2EnKTtcblx0XHRcdGlmICh2YWwgPiAwICYmIGljby5oYXNDbGFzcygndm9sdW1lLW9mZicpKSB7XG5cdFx0XHRcdGljby50b2dnbGVDbGFzcygndm9sdW1lLW9mZiB2b2x1bWUtb24nKTtcblx0XHRcdFx0dmlkZW8uaGFuZGxlTWljU3RhdHVzKHRydWUpO1xuXHRcdFx0fSBlbHNlIGlmICh2YWwgPT09IDAgJiYgaWNvLmhhc0NsYXNzKCd2b2x1bWUtb24nKSkge1xuXHRcdFx0XHRpY28udG9nZ2xlQ2xhc3MoJ3ZvbHVtZS1vbiB2b2x1bWUtb2ZmJyk7XG5cdFx0XHRcdHZpZGVvLmhhbmRsZU1pY1N0YXR1cyhmYWxzZSk7XG5cdFx0XHR9XG5cdFx0fTtcblx0XHR0aGlzLm11dGUgPSAobXV0ZSkgPT4ge1xuXHRcdFx0aWYgKCFzbGlkZXIpIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0bXV0ZWQgPSBtdXRlO1xuXHRcdFx0aWYgKG11dGUpIHtcblx0XHRcdFx0Y29uc3QgdmFsID0gc2xpZGVyLnNsaWRlcignb3B0aW9uJywgJ3ZhbHVlJyk7XG5cdFx0XHRcdGlmICh2YWwgPiAwKSB7XG5cdFx0XHRcdFx0bGFzdFZvbHVtZSA9IHZhbDtcblx0XHRcdFx0fVxuXHRcdFx0XHRzbGlkZXIuc2xpZGVyKCdvcHRpb24nLCAndmFsdWUnLCAwKTtcblx0XHRcdFx0dGhpcy5oYW5kbGUoMCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRzbGlkZXIuc2xpZGVyKCdvcHRpb24nLCAndmFsdWUnLCBsYXN0Vm9sdW1lKTtcblx0XHRcdFx0dGhpcy5oYW5kbGUobGFzdFZvbHVtZSk7XG5cdFx0XHR9XG5cdFx0fTtcblx0XHR0aGlzLmRlc3Ryb3kgPSAoKSA9PiB7XG5cdFx0XHRpZiAodm9sKSB7XG5cdFx0XHRcdHZvbC5yZW1vdmUoKTtcblx0XHRcdFx0dm9sID0gbnVsbDtcblx0XHRcdH1cblx0XHR9O1xuXHRcdHRoaXMubXV0ZWQgPSAoKSA9PiB7XG5cdFx0XHRyZXR1cm4gbXV0ZWQ7XG5cdFx0fTtcblx0fVxufTtcbiIsIm1vZHVsZS5leHBvcnRzID0gQ2hhdDsiLCJtb2R1bGUuZXhwb3J0cyA9IERyYXdXYkFyZWE7IiwibW9kdWxlLmV4cG9ydHMgPSBJbnRlcnZpZXdXYkFyZWE7IiwibW9kdWxlLmV4cG9ydHMgPSBNaWNMZXZlbDsiLCJtb2R1bGUuZXhwb3J0cyA9IE9tVXRpbDsiLCJtb2R1bGUuZXhwb3J0cyA9IFNldHRpbmdzOyIsIm1vZHVsZS5leHBvcnRzID0gVmlkZW9TZXR0aW5nczsiLCJtb2R1bGUuZXhwb3J0cyA9IFZpZGVvVXRpbDsiLCJtb2R1bGUuZXhwb3J0cyA9IFdlYlJ0Y1BlZXI7IiwiLy8gVGhlIG1vZHVsZSBjYWNoZVxudmFyIF9fd2VicGFja19tb2R1bGVfY2FjaGVfXyA9IHt9O1xuXG4vLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcblx0dmFyIGNhY2hlZE1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF07XG5cdGlmIChjYWNoZWRNb2R1bGUgIT09IHVuZGVmaW5lZCkge1xuXHRcdHJldHVybiBjYWNoZWRNb2R1bGUuZXhwb3J0cztcblx0fVxuXHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuXHR2YXIgbW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXSA9IHtcblx0XHQvLyBubyBtb2R1bGUuaWQgbmVlZGVkXG5cdFx0Ly8gbm8gbW9kdWxlLmxvYWRlZCBuZWVkZWRcblx0XHRleHBvcnRzOiB7fVxuXHR9O1xuXG5cdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuXHRfX3dlYnBhY2tfbW9kdWxlc19fW21vZHVsZUlkXShtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuXHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuXHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG59XG5cbiIsIi8qIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIikgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wICovXG5cbi8vIExldCdzIHJlLXN0eWxlIGpxdWVyeS11aSBkaWFsb2dzIGFuZCBidXR0b25zXG4kLmV4dGVuZCgkLnVpLmRpYWxvZy5wcm90b3R5cGUub3B0aW9ucy5jbGFzc2VzLCB7XG5cdCd1aS1kaWFsb2cnOiAnbW9kYWwtY29udGVudCdcblx0LCAndWktZGlhbG9nLXRpdGxlYmFyJzogJ21vZGFsLWhlYWRlcidcblx0LCAndWktZGlhbG9nLXRpdGxlJzogJ21vZGFsLXRpdGxlJ1xuXHQsICd1aS1kaWFsb2ctdGl0bGViYXItY2xvc2UnOiAnY2xvc2UnXG5cdCwgJ3VpLWRpYWxvZy1jb250ZW50JzogJ21vZGFsLWJvZHknXG5cdCwgJ3VpLWRpYWxvZy1idXR0b25wYW5lJzogJ21vZGFsLWZvb3Rlcidcbn0pO1xuJC5leHRlbmQoJC51aS5idXR0b24ucHJvdG90eXBlLm9wdGlvbnMuY2xhc3Nlcywge1xuXHQndWktYnV0dG9uJzogJ2J0biBidG4tb3V0bGluZS1zZWNvbmRhcnknXG59KTtcblxuT2JqZWN0LmFzc2lnbih3aW5kb3csIHtcblx0VmlkZW9NYW5hZ2VyOiByZXF1aXJlKCcuL3ZpZGVvLW1hbmFnZXInKVxuXHQsIFNoYXJlcjogcmVxdWlyZSgnLi9zaGFyZXInKVxuXHQsIFJvb206IHJlcXVpcmUoJy4vcm9vbScpXG5cdCwgQWN0aXZpdGllczogcmVxdWlyZSgnLi9hY3Rpdml0aWVzJylcblx0LCBVc2VyU2V0dGluZ3M6IHJlcXVpcmUoJy4vdXNlci1zZXR0aW5ncycpXG59KTtcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==
|