rubyfox-server 2.17.3.2 → 2.19.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/rubyfox/server/data/config/admin/descriptors/config_room.txt +10 -1
- data/lib/rubyfox/server/data/config/admin/descriptors/config_server.txt +90 -20
- data/lib/rubyfox/server/data/config/admin/descriptors/config_zone.txt +9 -0
- data/lib/rubyfox/server/data/config/admin/descriptors/runtime_room.txt +11 -0
- data/lib/rubyfox/server/data/config/admin/descriptors/runtime_user.txt +3 -3
- data/lib/rubyfox/server/data/config/core.xml +4 -4
- data/lib/rubyfox/server/data/config/default.words.txt +11 -0
- data/lib/rubyfox/server/data/config/log4j.properties +1 -2
- data/lib/rubyfox/server/data/config/server.xml +1 -1
- data/lib/rubyfox/server/data/data/GeoLite2-Country.mmdb +0 -0
- data/lib/rubyfox/server/data/data/bannedusers/users.bin +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/bootstrap.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/catalina-tasks.xml +39 -39
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/catalina.sh +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/ciphers.sh +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/commons-daemon-native.tar.gz +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/commons-daemon.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/configtest.sh +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/daemon.sh +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/digest.sh +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/makebase.sh +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/setclasspath.sh +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/shutdown.sh +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/startup.sh +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tomcat-juli.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tomcat-native.tar.gz +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tool-wrapper.sh +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/version.sh +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/Catalina/localhost/rewrite.config +1 -1
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/catalina.policy +263 -263
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/catalina.properties +209 -207
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/context.xml +31 -31
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/jaspic-providers.xml +23 -23
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/jaspic-providers.xsd +52 -52
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/keystore.jks +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/server.xml +177 -161
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/tomcat-users.xml +18 -7
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/tomcat-users.xsd +59 -59
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/web.xml +4740 -4737
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/annotations-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ant.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ha.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ssi.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-storeconfig.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-tribes.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/el-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jasper-el.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jasper.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jaspic-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jsp-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/servlet-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/sfs2x-ws-helper.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-coyote.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-dbcp.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-cs.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-de.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-es.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-fr.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ja.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ko.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-pt-BR.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ru.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-zh-CN.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-jdbc.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-jni.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-util-scan.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-util.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-websocket.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/websocket-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/javax.activation-1.2.0.jar +0 -0
- data/lib/rubyfox/server/data/lib/javax.mail.jar +0 -0
- data/lib/rubyfox/server/data/lib/js/JSApi.js +2 -1
- data/lib/rubyfox/server/data/lib/js/LibApi.js +181 -48
- data/lib/rubyfox/server/data/lib/sfs2x-admin.jar +0 -0
- data/lib/rubyfox/server/data/lib/sfs2x-cluster.jar +0 -0
- data/lib/rubyfox/server/data/lib/sfs2x-core.jar +0 -0
- data/lib/rubyfox/server/data/lib/sfs2x.jar +0 -0
- data/lib/rubyfox/server/data/sfs2x-service +26 -30
- data/lib/rubyfox/server/data/www/BlueBox.war +0 -0
- data/lib/rubyfox/server/data/www/HelloServlet/WEB-INF/web.xml +1 -3
- data/lib/rubyfox/server/data/www/ROOT/_css_/default.css +14 -6
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/style.css +44 -2
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/application.bundle.js +98 -61
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/endors~mod-0~mod-1~mod-11~mod-12~mod-17~mod-6~mod-7~mod-8~mod-9.bundle.js +17357 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-0.bundle.js +4 -4
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-1.bundle.js +3 -3
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-10.bundle.js +101 -66
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-11.bundle.js +544 -8
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12.bundle.js +915 -1480
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12~module-15~module-16~module-4.bundle.js +2665 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-13.bundle.js +606 -3093
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-13~module-16~module-17~module-4.bundle.js +2665 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-14.bundle.js +764 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-15.bundle.js +71 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-16.bundle.js +1787 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-17.bundle.js +3383 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-4.bundle.js +121 -1009
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-5.bundle.js +1214 -1744
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-6.bundle.js +398 -666
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-7.bundle.js +717 -192
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-8.bundle.js +2117 -665
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-9.bundle.js +613 -690
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~mod-0~mod-1~mod-10~mod-11~mod-16~mod-5~mod-6~mod-7~mod-8.bundle.js +17357 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~mod-0~mod-1~mod-11~mod-12~mod-17~mod-5~mod-6~mod-7~mod-8~mod-9.bundle.js +17357 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/{vendors~module-0~module-1~module-13~module-4~module-5~module-7~module-8.bundle.js → vendors~mod-0~mod-1~mod-11~mod-12~mod-17~mod-5~mod-7~mod-8~mod-9.bundle.js} +2 -2
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-12.bundle.js +807 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-13.bundle.js +807 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/cluster-configurator.html +32 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/cluster-monitor.html +185 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/cluster-updater.html +47 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/extension-deployer.html +84 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/zone-monitor.html +15 -8
- data/lib/rubyfox/server/data/www/ROOT/index.html +13 -23
- data/lib/rubyfox/server/data/www/host-manager/META-INF/context.xml +2 -2
- data/lib/rubyfox/server/data/www/host-manager/WEB-INF/jsp/404.jsp +2 -2
- data/lib/rubyfox/server/data/www/host-manager/{manager.xml → WEB-INF/manager.xml} +5 -1
- data/lib/rubyfox/server/data/www/host-manager/WEB-INF/web.xml +17 -0
- data/lib/rubyfox/server/data/www/host-manager/css/manager.css +141 -0
- data/lib/rubyfox/server/data/www/host-manager/images/tomcat.svg +967 -0
- data/lib/rubyfox/server/data/www/manager/META-INF/context.xml +2 -0
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorCerts.jsp +1 -1
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorCiphers.jsp +1 -1
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorTrustedCerts.jsp +1 -1
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/sessionDetail.jsp +3 -3
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/sessionsList.jsp +1 -1
- data/lib/rubyfox/server/data/www/manager/WEB-INF/web.xml +17 -0
- data/lib/rubyfox/server/data/www/manager/css/manager.css +141 -0
- data/lib/rubyfox/server/data/www/manager/images/tomcat.svg +967 -0
- data/lib/rubyfox/server/data/www/manager/xform.xsl +74 -59
- data/lib/rubyfox/server/version.rb +1 -1
- metadata +30 -31
- data/lib/rubyfox/server/data/config/admin/icons/Analytics.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/BanManager.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/BlueBoxMonitor.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/Console.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/Dashboard.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/ExtensionManager.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/LicenseManager.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/LogViewer.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/ServerConfigurator.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/ServletManager.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/ZoneConfigurator.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/ZoneMonitor.png +0 -0
- data/lib/rubyfox/server/data/lib/BlueBox.war +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/LICENSE +0 -1061
- data/lib/rubyfox/server/data/lib/apache-tomcat/NOTICE +0 -68
- data/lib/rubyfox/server/data/lib/apache-tomcat/README.md +0 -81
- data/lib/rubyfox/server/data/lib/apache-tomcat/RELEASE-NOTES +0 -174
- data/lib/rubyfox/server/data/lib/imap.jar +0 -0
- data/lib/rubyfox/server/data/lib/mailapi.jar +0 -0
- data/lib/rubyfox/server/data/lib/pop3.jar +0 -0
- data/lib/rubyfox/server/data/lib/smtp.jar +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12~module-13~module-9.bundle.js +0 -2634
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-9.bundle.js +0 -807
- data/lib/rubyfox/server/data/www/host-manager/images/tomcat.gif +0 -0
- data/lib/rubyfox/server/data/www/manager/images/tomcat.gif +0 -0
- /data/lib/rubyfox/server/data/data/buddylists/{BasicExamples/.keep → .keep} +0 -0
@@ -1,23 +1,6 @@
|
|
1
1
|
/*! (c) gotoAndPlay | All rights reserved */
|
2
2
|
(window["webpackJsonpapplication"] = window["webpackJsonpapplication"] || []).push([["module-8"],{
|
3
3
|
|
4
|
-
/***/ "./node_modules/file-saver/dist/FileSaver.min.js":
|
5
|
-
/*!*******************************************************!*\
|
6
|
-
!*** ./node_modules/file-saver/dist/FileSaver.min.js ***!
|
7
|
-
\*******************************************************/
|
8
|
-
/*! no static exports found */
|
9
|
-
/***/ (function(module, exports, __webpack_require__) {
|
10
|
-
|
11
|
-
/* WEBPACK VAR INJECTION */(function(global) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function(a,b){if(true)!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (b),
|
12
|
-
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
|
13
|
-
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
|
14
|
-
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));else {}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Deprecated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(b,c,d){var e=new XMLHttpRequest;e.open("GET",b),e.responseType="blob",e.onload=function(){a(e.response,c,d)},e.onerror=function(){console.error("could not download file")},e.send()}function d(a){var b=new XMLHttpRequest;b.open("HEAD",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=f.saveAs||("object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(a,b,d,e){if(e=e||open("","_blank"),e&&(e.document.title=e.document.body.innerText="downloading..."),"string"==typeof a)return c(a,b,d);var g="application/octet-stream"===a.type,h=/constructor/i.test(f.HTMLElement)||f.safari,i=/CriOS\/[\d]+/.test(navigator.userAgent);if((i||g&&h)&&"object"==typeof FileReader){var j=new FileReader;j.onloadend=function(){var a=j.result;a=i?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),e?e.location.href=a:location=a,e=null},j.readAsDataURL(a)}else{var k=f.URL||f.webkitURL,l=k.createObjectURL(a);e?e.location=l:location.href=l,e=null,setTimeout(function(){k.revokeObjectURL(l)},4E4)}});f.saveAs=a.saveAs=a, true&&(module.exports=a)});
|
15
|
-
|
16
|
-
//# sourceMappingURL=FileSaver.min.js.map
|
17
|
-
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../webpack/buildin/global.js */ "./node_modules/webpack/buildin/global.js")))
|
18
|
-
|
19
|
-
/***/ }),
|
20
|
-
|
21
4
|
/***/ "./node_modules/moment/locale sync recursive ^\\.\\/.*$":
|
22
5
|
/*!**************************************************!*\
|
23
6
|
!*** ./node_modules/moment/locale sync ^\.\/.*$ ***!
|
@@ -304,906 +287,2375 @@ webpackContext.id = "./node_modules/moment/locale sync recursive ^\\.\\/.*$";
|
|
304
287
|
|
305
288
|
/***/ }),
|
306
289
|
|
307
|
-
/***/ "./
|
308
|
-
|
309
|
-
!***
|
310
|
-
|
311
|
-
/*!
|
312
|
-
/***/ (function(module,
|
290
|
+
/***/ "./src/components/charts/base-chart.js":
|
291
|
+
/*!*********************************************!*\
|
292
|
+
!*** ./src/components/charts/base-chart.js ***!
|
293
|
+
\*********************************************/
|
294
|
+
/*! exports provided: BaseChart */
|
295
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
296
|
+
|
297
|
+
"use strict";
|
298
|
+
__webpack_require__.r(__webpack_exports__);
|
299
|
+
/* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "BaseChart", function() { return BaseChart; });
|
300
|
+
class BaseChart extends HTMLElement
|
301
|
+
{
|
302
|
+
constructor(maxValues)
|
303
|
+
{
|
304
|
+
super();
|
313
305
|
|
314
|
-
|
306
|
+
this._maxValues = maxValues;
|
315
307
|
|
316
|
-
//
|
317
|
-
|
318
|
-
|
319
|
-
})();
|
308
|
+
// Initialize
|
309
|
+
this._initialize();
|
310
|
+
}
|
320
311
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
}
|
312
|
+
// Can be overridden
|
313
|
+
_initialize()
|
314
|
+
{
|
315
|
+
// Create chart html
|
316
|
+
let chartHtml = $('<div>');
|
317
|
+
$(this).append(chartHtml);
|
328
318
|
|
329
|
-
|
330
|
-
// We return undefined, instead of nothing here, so it's
|
331
|
-
// easier to handle this case. if(!global) { ...}
|
319
|
+
this._chartWidget = this._initChartWidget(chartHtml);
|
332
320
|
|
333
|
-
|
321
|
+
// Reset data source
|
322
|
+
this.reset();
|
323
|
+
}
|
334
324
|
|
325
|
+
// MUST BE OVERRIDDEN
|
326
|
+
_initChartWidget()
|
327
|
+
{
|
328
|
+
throw new Error('Chart widget must be initialized!')
|
329
|
+
}
|
335
330
|
|
336
|
-
|
331
|
+
set paused(value)
|
332
|
+
{
|
333
|
+
this.isPaused = value;
|
334
|
+
this._onPauseChange();
|
335
|
+
}
|
337
336
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
/*! exports provided: RuntimeLogEntry */
|
343
|
-
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
337
|
+
get paused()
|
338
|
+
{
|
339
|
+
return this.isPaused;
|
340
|
+
}
|
344
341
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
342
|
+
reset()
|
343
|
+
{
|
344
|
+
this._chartWidget.setDataSource([]);
|
345
|
+
}
|
346
|
+
|
347
|
+
redraw()
|
351
348
|
{
|
352
|
-
this.
|
349
|
+
this._chartWidget.redraw();
|
353
350
|
}
|
354
351
|
|
355
|
-
|
352
|
+
getLastEntry()
|
356
353
|
{
|
357
|
-
let
|
354
|
+
let ds;
|
358
355
|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
356
|
+
if (this.isPaused)
|
357
|
+
ds = this._tempDS;
|
358
|
+
else
|
359
|
+
ds = this._dataSource;
|
360
|
+
|
361
|
+
if (ds != null && ds.total() > 0)
|
362
|
+
return ds.at(ds.total() - 1);
|
363
|
+
else
|
364
|
+
return null;
|
365
|
+
}
|
366
|
+
|
367
|
+
_addEntry(newEntry)
|
368
|
+
{
|
369
|
+
if (this.isPaused)
|
370
|
+
{
|
371
|
+
if (this._tempDS == null)
|
372
|
+
this._tempDS = new kendo.data.DataSource();
|
373
|
+
|
374
|
+
// Store new value in a temporary array
|
375
|
+
this._tempDS.add(newEntry);
|
376
|
+
}
|
377
|
+
else
|
378
|
+
{
|
379
|
+
let ds = this._dataSource;
|
380
|
+
|
381
|
+
if (this._tempDS != null)
|
382
|
+
{
|
383
|
+
// Concatenate temporary entries to actual data source
|
384
|
+
let newArr = $.merge(ds.data(), this._tempDS.data());
|
385
|
+
|
386
|
+
// Remove values exceeding MAX_VALUES
|
387
|
+
if (newArr.length > this._maxValues)
|
388
|
+
newArr.splice(0, newArr.length - this._maxValues)
|
389
|
+
|
390
|
+
// Create new datasource
|
391
|
+
let newDS = new kendo.data.DataSource({data: newArr})
|
392
|
+
|
393
|
+
// Assign new data source to chart
|
394
|
+
this._chartWidget.setDataSource(newDS);
|
366
395
|
|
367
|
-
|
396
|
+
// Remove temporary array
|
397
|
+
this._tempDS = null;
|
398
|
+
}
|
399
|
+
|
400
|
+
// Add new entry
|
401
|
+
ds.add(newEntry);
|
402
|
+
|
403
|
+
// Remove first item if needed
|
404
|
+
if (ds.total() > this._maxValues)
|
405
|
+
ds.remove(ds.at(0));
|
406
|
+
}
|
368
407
|
}
|
369
408
|
|
370
|
-
|
409
|
+
get _dataSource()
|
371
410
|
{
|
372
|
-
return this.
|
411
|
+
return this._chartWidget.dataSource;
|
412
|
+
}
|
413
|
+
|
414
|
+
_onPauseChange()
|
415
|
+
{
|
416
|
+
// Nothing to do, should be overridden
|
373
417
|
}
|
374
418
|
}
|
375
419
|
|
420
|
+
// DEFINE COMPONENT
|
421
|
+
if (!window.customElements.get('base-chart'))
|
422
|
+
window.customElements.define('base-chart', BaseChart);
|
423
|
+
|
424
|
+
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! jquery */ "jquery")))
|
376
425
|
|
377
426
|
/***/ }),
|
378
427
|
|
379
|
-
/***/ "./src/
|
380
|
-
|
381
|
-
!*** ./src/
|
382
|
-
|
383
|
-
/*! exports provided:
|
428
|
+
/***/ "./src/components/charts/chart-utils.js":
|
429
|
+
/*!**********************************************!*\
|
430
|
+
!*** ./src/components/charts/chart-utils.js ***!
|
431
|
+
\**********************************************/
|
432
|
+
/*! exports provided: getFormattedDateTime, getBasicSharedTemplate, getMemorySharedTemplate, getMemoryValueAxisLabelTemplate, getNetworkSharedTemplate, getNetworkValueAxisLabelTemplate, getNetworkValueAxisLabelTemplateB, getUserCountSharedTemplate, getTimeRangeTooltipTemplate, getWRBytesLabelTemplate, getBasicTemplate, getMemoryTemplate, getNetworkTemplate */
|
384
433
|
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
385
434
|
|
386
435
|
"use strict";
|
387
436
|
__webpack_require__.r(__webpack_exports__);
|
388
|
-
/*
|
389
|
-
/* harmony
|
390
|
-
/* harmony
|
391
|
-
/* harmony
|
392
|
-
/* harmony
|
393
|
-
/* harmony
|
394
|
-
/* harmony
|
395
|
-
/* harmony
|
437
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getFormattedDateTime", function() { return getFormattedDateTime; });
|
438
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBasicSharedTemplate", function() { return getBasicSharedTemplate; });
|
439
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getMemorySharedTemplate", function() { return getMemorySharedTemplate; });
|
440
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getMemoryValueAxisLabelTemplate", function() { return getMemoryValueAxisLabelTemplate; });
|
441
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNetworkSharedTemplate", function() { return getNetworkSharedTemplate; });
|
442
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNetworkValueAxisLabelTemplate", function() { return getNetworkValueAxisLabelTemplate; });
|
443
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNetworkValueAxisLabelTemplateB", function() { return getNetworkValueAxisLabelTemplateB; });
|
444
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getUserCountSharedTemplate", function() { return getUserCountSharedTemplate; });
|
445
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getTimeRangeTooltipTemplate", function() { return getTimeRangeTooltipTemplate; });
|
446
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getWRBytesLabelTemplate", function() { return getWRBytesLabelTemplate; });
|
447
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBasicTemplate", function() { return getBasicTemplate; });
|
448
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getMemoryTemplate", function() { return getMemoryTemplate; });
|
449
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNetworkTemplate", function() { return getNetworkTemplate; });
|
450
|
+
/* harmony import */ var _utils_utilities__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/utilities */ "./src/utils/utilities.js");
|
451
|
+
|
452
|
+
|
453
|
+
function getFormattedDateTime(date, format = 'dd MMM HH:mm:ss')
|
454
|
+
{
|
455
|
+
return kendo.toString(date, format);
|
456
|
+
}
|
457
|
+
|
458
|
+
function getBasicSharedTemplate(valueFormat = '{0}') {
|
459
|
+
return kendo.template(`
|
460
|
+
<div class="chart-tooltip-category"><strong>#: category #</strong></div>
|
461
|
+
# for (var i = 0; i < points.length; i++) { #
|
462
|
+
<div>
|
463
|
+
<i class="fas fa-square" style="color: #: points[i].color # "></i>
|
464
|
+
#: points[i].series.name# : #: kendo.format('${valueFormat}', points[i].value) #
|
465
|
+
</div>
|
466
|
+
# } #
|
467
|
+
`);
|
468
|
+
}
|
396
469
|
|
470
|
+
function getMemorySharedTemplate() {
|
471
|
+
return function(dataItem) {
|
472
|
+
dataItem.bytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_0__["bytesToSize"]; // Pass bytesToSize utility function to template
|
473
|
+
return kendo.template(`
|
474
|
+
<div class="chart-tooltip-category"><strong>#: category #</strong></div>
|
475
|
+
# for (var i = 0; i < points.length; i++) { #
|
476
|
+
<div>
|
477
|
+
<i class="fas fa-square" style="color: #: points[i].color # "></i>
|
478
|
+
#: points[i].series.name# : #: bytesToSize(points[i].value) #
|
479
|
+
</div>
|
480
|
+
# } #
|
481
|
+
`)(dataItem);
|
482
|
+
};
|
483
|
+
}
|
397
484
|
|
485
|
+
function getMemoryValueAxisLabelTemplate() {
|
486
|
+
return function(dataItem) {
|
487
|
+
dataItem.bytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_0__["bytesToSize"]; // Pass bytesToSize utility function to template
|
488
|
+
return kendo.template(`
|
489
|
+
#: bytesToSize(value) #
|
490
|
+
`)(dataItem);
|
491
|
+
};
|
492
|
+
}
|
398
493
|
|
494
|
+
function getNetworkSharedTemplate(categoryFormat = 'dd MMM HH:mm:ss') {
|
495
|
+
return function(dataItem) {
|
496
|
+
dataItem.kBytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_0__["kBytesToSize"]; // Pass kBytesToSize utility function to template
|
497
|
+
return kendo.template(`
|
498
|
+
<div class="chart-tooltip-category"><strong>#: kendo.toString(category, '${categoryFormat}') #</strong></div>
|
499
|
+
# for (var i = 0; i < points.length; i++) { #
|
500
|
+
<div>
|
501
|
+
<i class="fas fa-square" style="color: #: points[i].color # "></i>
|
502
|
+
#: points[i].series.name# : #: kBytesToSize(points[i].value, 1, '', '/s') #
|
503
|
+
</div>
|
504
|
+
# } #
|
505
|
+
`)(dataItem);
|
506
|
+
};
|
507
|
+
}
|
399
508
|
|
509
|
+
function getNetworkValueAxisLabelTemplate() {
|
510
|
+
return function(dataItem) {
|
511
|
+
dataItem.kBytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_0__["kBytesToSize"]; // Pass kBytesToSize utility function to template
|
512
|
+
return kendo.template(`
|
513
|
+
#: kBytesToSize(value, 1, '', '/s') #
|
514
|
+
`)(dataItem);
|
515
|
+
};
|
516
|
+
}
|
400
517
|
|
518
|
+
function getNetworkValueAxisLabelTemplateB() {
|
519
|
+
return function(dataItem) {
|
520
|
+
dataItem.bytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_0__["bytesToSize"]; // Pass bytesToSize utility function to template
|
521
|
+
return kendo.template(`
|
522
|
+
#: bytesToSize(value, 1, '', '/s') #
|
523
|
+
`)(dataItem);
|
524
|
+
};
|
525
|
+
}
|
401
526
|
|
402
|
-
|
403
|
-
{
|
404
|
-
|
405
|
-
|
406
|
-
|
527
|
+
function getUserCountSharedTemplate(categoryFormat = 'dd MMM HH:mm:ss') {
|
528
|
+
return function(dataItem) {
|
529
|
+
return kendo.template(`
|
530
|
+
<div class="chart-tooltip-category"><strong>#: kendo.toString(category, '${categoryFormat}') #</strong></div>
|
531
|
+
# for (var i = 0; i < points.length; i++) { #
|
532
|
+
<div>
|
533
|
+
<i class="fas fa-square" style="color: #: points[i].color # "></i>
|
534
|
+
#: points[i].series.name# : #: points[i].value #
|
535
|
+
</div>
|
536
|
+
# } #
|
537
|
+
`)(dataItem);
|
538
|
+
};
|
539
|
+
}
|
407
540
|
|
408
|
-
|
409
|
-
|
541
|
+
function getTimeRangeTooltipTemplate() {
|
542
|
+
return function(dataItem) {
|
543
|
+
dataItem.getTooltipString = function(v1, v2) {
|
544
|
+
if (v1 == v2)
|
545
|
+
{
|
546
|
+
if (v2 == -24)
|
547
|
+
v2 = -23;
|
410
548
|
|
411
|
-
|
412
|
-
|
413
|
-
this.ANY_CLASS = '[any]';
|
549
|
+
v1 = v2 - 1;
|
550
|
+
}
|
414
551
|
|
415
|
-
|
552
|
+
let start = Math.abs(v1);
|
553
|
+
let end = Math.abs(v2);
|
416
554
|
|
417
|
-
|
418
|
-
|
419
|
-
|
555
|
+
return `From ${start} hour${start != 1 ? 's' : ''} ago to ${end > 0 ? ('to ' + end + ' hour' + (end != 1 ? 's' : '') + ' ago') : 'now'}`;
|
556
|
+
}; // Pass utility function to template
|
557
|
+
return kendo.template(`
|
558
|
+
#: getTooltipString(selectionStart, selectionEnd) #
|
559
|
+
`)(dataItem);
|
560
|
+
};
|
561
|
+
}
|
420
562
|
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
this.REQ_DELETE_BACKUP = 'delBackup';
|
563
|
+
function getWRBytesLabelTemplate() {
|
564
|
+
return function(dataItem) {
|
565
|
+
return kendo.template(`
|
566
|
+
#: value # #: dataItem.unit #
|
567
|
+
`)(dataItem);
|
568
|
+
};
|
569
|
+
}
|
429
570
|
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
this.RESP_BACKUP_ERROR = 'bakError';
|
440
|
-
this.RESP_BACKUP_WARNING = 'bakWarn';
|
441
|
-
}
|
571
|
+
function getBasicTemplate(valueFormat = '{0}') {
|
572
|
+
return kendo.template(`
|
573
|
+
<div>
|
574
|
+
<span class="text-nowrap">#: kendo.toString(new Date(value.x), "dd/MM/yy HH:mm") #</span>
|
575
|
+
<br>
|
576
|
+
<strong class="text-nowrap">#: series.name #: #: kendo.format('${valueFormat}', value.y) # </strong>
|
577
|
+
</div>
|
578
|
+
`);
|
579
|
+
}
|
442
580
|
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
581
|
+
function getMemoryTemplate() {
|
582
|
+
return function(dataItem) {
|
583
|
+
dataItem.bytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_0__["bytesToSize"]; // Pass bytesToSize utility function to template
|
584
|
+
return kendo.template(`
|
585
|
+
<div>
|
586
|
+
<span class="text-nowrap">#: kendo.toString(new Date(value.x), "dd/MM/yy HH:mm") #</span>
|
587
|
+
<br>
|
588
|
+
<strong class="text-nowrap">#: series.name #: #: bytesToSize(value.y) # </strong>
|
589
|
+
</div>
|
590
|
+
`)(dataItem);
|
591
|
+
};
|
592
|
+
}
|
448
593
|
|
449
|
-
|
450
|
-
{
|
451
|
-
//
|
452
|
-
|
594
|
+
function getNetworkTemplate() {
|
595
|
+
return function(dataItem) {
|
596
|
+
dataItem.bytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_0__["bytesToSize"]; // Pass bytesToSize utility function to template
|
597
|
+
return kendo.template(`
|
598
|
+
<div>
|
599
|
+
<span class="text-nowrap">#: kendo.toString(new Date(value.x), "dd/MM/yy HH:mm") #</span>
|
600
|
+
<br>
|
601
|
+
<strong class="text-nowrap">#: series.name #: #: bytesToSize(value.y, 1, '', '/s') # </strong>
|
602
|
+
</div>
|
603
|
+
`)(dataItem);
|
604
|
+
};
|
605
|
+
}
|
453
606
|
|
454
|
-
// Initialize scrolling tabs
|
455
|
-
$('#lgv-tabNavigator > #tabs').scrollingTabs({
|
456
|
-
bootstrapVersion: 4,
|
457
|
-
scrollToTabEdge: true,
|
458
|
-
enableSwiping: true,
|
459
|
-
disableScrollArrowsOnFullyScrolled: true,
|
460
|
-
cssClassLeftArrow: 'fa fa-chevron-left',
|
461
|
-
cssClassRightArrow: 'fa fa-chevron-right'
|
462
|
-
});
|
463
607
|
|
464
|
-
|
465
|
-
$('a[data-toggle="tab"]').on('shown.bs.tab', $.proxy(this._onTabShown, this));
|
608
|
+
/***/ }),
|
466
609
|
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
610
|
+
/***/ "./src/components/charts/cpu-usage-chart.js":
|
611
|
+
/*!**************************************************!*\
|
612
|
+
!*** ./src/components/charts/cpu-usage-chart.js ***!
|
613
|
+
\**************************************************/
|
614
|
+
/*! exports provided: CpuUsageChart */
|
615
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
471
616
|
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
min: 0,
|
478
|
-
max: 100,
|
479
|
-
value: false,
|
480
|
-
type: 'value',
|
481
|
-
animation: {
|
482
|
-
duration: 400
|
483
|
-
}
|
484
|
-
});
|
485
|
-
|
486
|
-
// Initialize level filter dropdown
|
487
|
-
this._levelFilterDD = $('#lgv-levelDD').kendoDropDownList({
|
488
|
-
dataSource: [this.ANY_LEVEL].concat(this.LEVELS),
|
489
|
-
change: $.proxy(this._onFilterChange, this)
|
490
|
-
}).data('kendoDropDownList');
|
617
|
+
"use strict";
|
618
|
+
__webpack_require__.r(__webpack_exports__);
|
619
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CpuUsageChart", function() { return CpuUsageChart; });
|
620
|
+
/* harmony import */ var _base_chart__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-chart */ "./src/components/charts/base-chart.js");
|
621
|
+
/* harmony import */ var _chart_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./chart-utils */ "./src/components/charts/chart-utils.js");
|
491
622
|
|
492
|
-
// Initialize class filter dropdown
|
493
|
-
this._classFilterDD = $('#lgv-classDD').kendoDropDownList({
|
494
|
-
change: $.proxy(this._onFilterChange, this)
|
495
|
-
}).data('kendoDropDownList');
|
496
623
|
|
497
|
-
// Initialize message filter input
|
498
|
-
$('#lgv-messageIn').on('input', $.proxy(this._onFilterChange, this));
|
499
624
|
|
500
|
-
// Initialize clear button
|
501
|
-
$('#lgv-clearFilterBt').on('click', $.proxy(this._onClearFilterClick, this));
|
502
625
|
|
503
|
-
|
504
|
-
|
626
|
+
class CpuUsageChart extends _base_chart__WEBPACK_IMPORTED_MODULE_0__["BaseChart"]
|
627
|
+
{
|
628
|
+
constructor()
|
629
|
+
{
|
630
|
+
super(120);
|
631
|
+
}
|
505
632
|
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
633
|
+
_initChartWidget(chartHtml)
|
634
|
+
{
|
635
|
+
return chartHtml.kendoChart({
|
636
|
+
transitions: false,
|
637
|
+
chartArea: {
|
638
|
+
height: 120
|
639
|
+
},
|
640
|
+
legend: {
|
641
|
+
visible: false
|
642
|
+
},
|
643
|
+
seriesDefaults: {
|
644
|
+
type: 'area',
|
645
|
+
labels: {
|
646
|
+
visible: false,
|
647
|
+
format: '{0}%',
|
648
|
+
background: 'transparent'
|
649
|
+
}
|
650
|
+
},
|
651
|
+
series: [
|
514
652
|
{
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
},
|
524
|
-
{
|
525
|
-
field: 'thread',
|
526
|
-
width: 150,
|
527
|
-
title: 'Thread',
|
528
|
-
},
|
529
|
-
{
|
530
|
-
field: 'clazz',
|
531
|
-
width: 250,
|
532
|
-
title: 'Class',
|
533
|
-
},
|
653
|
+
name: 'System',
|
654
|
+
field: 'systemLoad',
|
655
|
+
categoryField: 'time',
|
656
|
+
color: this.systemColor,
|
657
|
+
line: {
|
658
|
+
width: 2
|
659
|
+
}
|
660
|
+
},
|
534
661
|
{
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
662
|
+
name: 'Process',
|
663
|
+
field: 'processLoad',
|
664
|
+
categoryField: 'time',
|
665
|
+
color: this.processColor,
|
666
|
+
line: {
|
667
|
+
width: 2
|
668
|
+
}
|
669
|
+
}
|
539
670
|
],
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
dataSource: []
|
544
|
-
}).data('kendoGrid');
|
545
|
-
|
546
|
-
// Initialize boot log view buttons
|
547
|
-
$('#lgv-exportBootLogBt').on('click', $.proxy(this._onExportBootLogBtClick, this));
|
548
|
-
$('#lgv-switchBootLogColorBt').on('click', $.proxy(this._onSwitchBootLogColorBtClick, this));
|
549
|
-
|
550
|
-
// Initialize generate backup buttons
|
551
|
-
$('#lgv-bootLogBackupCard .backup-button').on('click', $.proxy(this._onBootLogGenerateBtClick, this));
|
552
|
-
$('#lgv-runtimeLogBackupCard .backup-button').on('click', $.proxy(this._onRuntimeLogGenerateBtClick, this));
|
553
|
-
$('#lgv-fullLogBackupCard .backup-button').on('click', $.proxy(this._onFullLogsGenerateBtClick, this));
|
554
|
-
|
555
|
-
this._initBackupCard('#lgv-bootLogBackupCard');
|
556
|
-
this._initBackupCard('#lgv-runtimeLogBackupCard');
|
557
|
-
this._initBackupCard('#lgv-fullLogBackupCard');
|
558
|
-
|
559
|
-
// Initialize download grid
|
560
|
-
this._downloadGrid = $('#lgv-downloadGrid').kendoGrid({
|
561
|
-
scrollable: true,
|
562
|
-
sortable: true,
|
563
|
-
//resizable: true,
|
564
|
-
selectable: 'row',
|
565
|
-
columns:
|
566
|
-
[
|
567
|
-
{
|
568
|
-
field: 'date',
|
569
|
-
width: 100,
|
570
|
-
title: 'Date',
|
571
|
-
},
|
572
|
-
{
|
573
|
-
field: 'time',
|
574
|
-
width: 100,
|
575
|
-
title: 'Time',
|
671
|
+
valueAxis: {
|
672
|
+
labels: {
|
673
|
+
format: '{0}%'
|
576
674
|
},
|
577
|
-
{
|
578
|
-
|
579
|
-
width: 300,
|
580
|
-
title: 'Filename',
|
675
|
+
line: {
|
676
|
+
visible: false
|
581
677
|
},
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
678
|
+
min: 0,
|
679
|
+
max: 100
|
680
|
+
},
|
681
|
+
categoryAxis: {
|
682
|
+
majorGridLines: {
|
683
|
+
visible: false
|
586
684
|
},
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
685
|
+
majorTicks: {
|
686
|
+
visible: false
|
687
|
+
},
|
688
|
+
labels: {
|
689
|
+
visible: false
|
690
|
+
}
|
691
|
+
},
|
692
|
+
tooltip: {
|
693
|
+
shared: true,
|
694
|
+
visible: true,
|
695
|
+
sharedTemplate: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getBasicSharedTemplate"])('{0}%'),
|
696
|
+
background: '#e4e4e4'
|
697
|
+
}
|
698
|
+
}).data('kendoChart');
|
699
|
+
}
|
594
700
|
|
595
|
-
|
596
|
-
|
701
|
+
get systemColor()
|
702
|
+
{
|
703
|
+
return '#3399FF';
|
597
704
|
}
|
598
705
|
|
599
|
-
|
706
|
+
get processColor()
|
600
707
|
{
|
601
|
-
|
602
|
-
|
708
|
+
return '#0033CC';
|
709
|
+
}
|
603
710
|
|
604
|
-
|
605
|
-
|
711
|
+
addEntry(processLoad, systemLoad)
|
712
|
+
{
|
713
|
+
let newEntry = {
|
714
|
+
time: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getFormattedDateTime"])(new Date()),
|
715
|
+
processLoad: processLoad,
|
716
|
+
systemLoad: systemLoad
|
717
|
+
};
|
718
|
+
|
719
|
+
// Add entry to chart
|
720
|
+
super._addEntry(newEntry);
|
721
|
+
}
|
722
|
+
}
|
606
723
|
|
607
|
-
|
608
|
-
|
724
|
+
// DEFINE COMPONENT
|
725
|
+
if (!window.customElements.get('cpu-usage-chart'))
|
726
|
+
window.customElements.define('cpu-usage-chart', CpuUsageChart);
|
609
727
|
|
610
|
-
// Remove click listeners
|
611
|
-
$('#lgv-loadBt').off('click');
|
612
|
-
$('#lgv-exportBootLogBt').off('click');
|
613
|
-
$('#lgv-switchBootLogColorBt').off('click');
|
614
|
-
$('#lgv-bootLogBackupCard .backup-button').off('click');
|
615
|
-
$('#lgv-runtimeLogBackupCard .backup-button').off('click');
|
616
|
-
$('#lgv-clearFilterBt').off('click');
|
617
|
-
$('#lgv-deleteBt').off('click');
|
618
728
|
|
619
|
-
|
620
|
-
}
|
729
|
+
/***/ }),
|
621
730
|
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
731
|
+
/***/ "./src/components/charts/memory-chart.js":
|
732
|
+
/*!***********************************************!*\
|
733
|
+
!*** ./src/components/charts/memory-chart.js ***!
|
734
|
+
\***********************************************/
|
735
|
+
/*! exports provided: MemoryChart */
|
736
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
628
737
|
|
629
|
-
|
630
|
-
|
738
|
+
"use strict";
|
739
|
+
__webpack_require__.r(__webpack_exports__);
|
740
|
+
/* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MemoryChart", function() { return MemoryChart; });
|
741
|
+
/* harmony import */ var _base_chart__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-chart */ "./src/components/charts/base-chart.js");
|
742
|
+
/* harmony import */ var _chart_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./chart-utils */ "./src/components/charts/chart-utils.js");
|
631
743
|
|
632
|
-
// Set all tabs to show errors
|
633
|
-
this._switchBootViewStack('lgv-bootLogErrorView');
|
634
|
-
this._switchRuntimeViewStack('lgv-runtimeLogErrorView');
|
635
|
-
this._switchDownloadViewStack('lgv-downloadErrorView');
|
636
744
|
|
637
|
-
// Disable runtime log controls
|
638
|
-
this._enableRuntimeLogControls(false);
|
639
745
|
|
640
|
-
this._initFailed = true;
|
641
|
-
}
|
642
746
|
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
747
|
+
class MemoryChart extends _base_chart__WEBPACK_IMPORTED_MODULE_0__["BaseChart"]
|
748
|
+
{
|
749
|
+
constructor()
|
750
|
+
{
|
751
|
+
super(300);
|
647
752
|
|
648
|
-
|
649
|
-
|
753
|
+
// Append text to display elapsed time
|
754
|
+
this._elapsedTxt = $('<div>', {class: 'text-center', text: '---'});
|
755
|
+
$(this).append(this._elapsedTxt);
|
756
|
+
}
|
650
757
|
|
651
|
-
|
758
|
+
_initChartWidget(chartHtml)
|
759
|
+
{
|
760
|
+
return chartHtml.kendoChart({
|
761
|
+
transitions: false,
|
762
|
+
chartArea: {
|
763
|
+
height: 240
|
764
|
+
},
|
765
|
+
legend: {
|
766
|
+
visible: false
|
767
|
+
},
|
768
|
+
seriesDefaults: {
|
769
|
+
type: 'area',
|
770
|
+
labels: {
|
771
|
+
visible: false,
|
772
|
+
format: '{0}',
|
773
|
+
background: 'transparent'
|
774
|
+
},
|
775
|
+
},
|
776
|
+
series: [{
|
777
|
+
name: 'Allocated',
|
778
|
+
field: 'allocMem',
|
779
|
+
categoryField: 'time',
|
780
|
+
color: this.allocatedColor,
|
781
|
+
line: {
|
782
|
+
width: 2
|
783
|
+
}
|
784
|
+
},
|
652
785
|
{
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
786
|
+
name: 'Used',
|
787
|
+
field: 'usedMem',
|
788
|
+
categoryField: 'time',
|
789
|
+
color: this.usedColor,
|
790
|
+
line: {
|
791
|
+
width: 2
|
792
|
+
}
|
793
|
+
}],
|
794
|
+
valueAxis: {
|
795
|
+
labels: {
|
796
|
+
format: '{0}',
|
797
|
+
template: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getMemoryValueAxisLabelTemplate"])()
|
798
|
+
},
|
799
|
+
line: {
|
800
|
+
visible: false
|
801
|
+
},
|
802
|
+
min: 0
|
803
|
+
},
|
804
|
+
categoryAxis: {
|
805
|
+
majorGridLines: {
|
806
|
+
visible: false
|
807
|
+
},
|
808
|
+
majorTicks: {
|
809
|
+
visible: false
|
810
|
+
},
|
811
|
+
labels: {
|
812
|
+
visible: false
|
813
|
+
}
|
814
|
+
},
|
815
|
+
tooltip: {
|
816
|
+
shared: true,
|
817
|
+
visible: true,
|
818
|
+
sharedTemplate: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getMemorySharedTemplate"])(),
|
819
|
+
background: '#e4e4e4'
|
820
|
+
}
|
821
|
+
}).data('kendoChart');
|
822
|
+
}
|
659
823
|
|
660
|
-
|
661
|
-
|
824
|
+
get allocatedColor()
|
825
|
+
{
|
826
|
+
return '#3399FF';
|
827
|
+
}
|
662
828
|
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
829
|
+
get usedColor()
|
830
|
+
{
|
831
|
+
return '#0033CC';
|
832
|
+
}
|
667
833
|
|
668
|
-
|
669
|
-
|
834
|
+
addEntry(allocMem, usedMem)
|
835
|
+
{
|
836
|
+
let now = new Date();
|
670
837
|
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
838
|
+
let newEntry = {
|
839
|
+
time: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getFormattedDateTime"])(now),
|
840
|
+
timestamp: now.getTime(),
|
841
|
+
allocMem: allocMem,
|
842
|
+
usedMem: usedMem
|
843
|
+
};
|
676
844
|
|
677
|
-
//
|
678
|
-
|
679
|
-
{
|
680
|
-
// Disable controls
|
681
|
-
this._enableRuntimeLogControls(false);
|
845
|
+
// Add entry to chart
|
846
|
+
super._addEntry(newEntry);
|
682
847
|
|
683
|
-
|
684
|
-
|
685
|
-
|
848
|
+
// Update x axis
|
849
|
+
if (!this.isPaused)
|
850
|
+
this._updateElapsedText();
|
851
|
+
}
|
686
852
|
|
687
|
-
|
688
|
-
|
689
|
-
|
853
|
+
_updateElapsedText()
|
854
|
+
{
|
855
|
+
let ds = this._dataSource;
|
690
856
|
|
691
|
-
|
692
|
-
else if (command == this.RESP_RUNTIME_LOG)
|
857
|
+
if (ds.total() > 1)
|
693
858
|
{
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
let logEntries = data.getUtfStringArray(this.LOG_DATA_LABEL);
|
698
|
-
let separator = data.getUtfString('sep');
|
699
|
-
let columns = data.getInt('cols');
|
700
|
-
let dsArr = [];
|
859
|
+
// Get axis limits
|
860
|
+
const chartMinimum = ds.at(0).timestamp;
|
861
|
+
const chartMaximum = ds.at(ds.total() - 1).timestamp;
|
701
862
|
|
702
|
-
|
863
|
+
// Set elapsed text
|
864
|
+
let seconds = Math.round( (chartMaximum - chartMinimum) / 1000 );
|
865
|
+
let title;
|
703
866
|
|
704
|
-
|
705
|
-
|
706
|
-
|
867
|
+
if (seconds < 60)
|
868
|
+
title = 'Last ' + (seconds != 1 ? seconds + ' seconds' : 'second');
|
869
|
+
else
|
707
870
|
{
|
708
|
-
const
|
709
|
-
|
710
|
-
let logEntryData = [];
|
711
|
-
let startIndex = 0;
|
712
|
-
|
713
|
-
for (let c = 0; c < columns - 1; c++)
|
714
|
-
{
|
715
|
-
let endIndex = logEntry.indexOf(separator, startIndex);
|
716
|
-
logEntryData.push(logEntry.substring(startIndex, endIndex));
|
717
|
-
startIndex = endIndex + separator.length;
|
718
|
-
}
|
719
|
-
|
720
|
-
if (startIndex < logEntry.length)
|
721
|
-
logEntryData.push(logEntry.substring(startIndex));
|
722
|
-
|
723
|
-
// Fill datagrid's dataprovider
|
724
|
-
let rle = _data_runtime_log_entry__WEBPACK_IMPORTED_MODULE_1__["RuntimeLogEntry"].fromArray(separator, logEntryData);
|
725
|
-
dsArr.push(rle);
|
726
|
-
|
727
|
-
// Add class to filtering dropdown
|
728
|
-
if (classes.indexOf(rle.clazz) < 0)
|
729
|
-
classes.push(rle.clazz);
|
871
|
+
const minutes = Math.floor(seconds / 60);
|
872
|
+
title = 'Last ' + (minutes != 1 ? minutes + ' minutes' : 'minute');
|
730
873
|
}
|
731
874
|
|
732
|
-
|
733
|
-
|
734
|
-
|
735
|
-
|
736
|
-
|
737
|
-
this._classFilterDD.setDataSource(classes);
|
738
|
-
this._classFilterDD.select(0);
|
875
|
+
this._elapsedTxt.text(title);
|
876
|
+
}
|
877
|
+
}
|
878
|
+
}
|
739
879
|
|
740
|
-
|
741
|
-
|
742
|
-
|
743
|
-
})
|
880
|
+
// DEFINE COMPONENT
|
881
|
+
if (!window.customElements.get('memory-chart'))
|
882
|
+
window.customElements.define('memory-chart', MemoryChart);
|
744
883
|
|
745
|
-
|
884
|
+
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! jquery */ "jquery")))
|
746
885
|
|
747
|
-
|
748
|
-
this._enableRuntimeLogControls(true);
|
886
|
+
/***/ }),
|
749
887
|
|
750
|
-
|
751
|
-
|
752
|
-
|
888
|
+
/***/ "./src/components/charts/network-24h-chart.js":
|
889
|
+
/*!****************************************************!*\
|
890
|
+
!*** ./src/components/charts/network-24h-chart.js ***!
|
891
|
+
\****************************************************/
|
892
|
+
/*! exports provided: Network24hChart */
|
893
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
753
894
|
|
754
|
-
|
755
|
-
|
756
|
-
|
757
|
-
|
758
|
-
|
895
|
+
"use strict";
|
896
|
+
__webpack_require__.r(__webpack_exports__);
|
897
|
+
/* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Network24hChart", function() { return Network24hChart; });
|
898
|
+
/* harmony import */ var _chart_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./chart-utils */ "./src/components/charts/chart-utils.js");
|
899
|
+
/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! moment */ "./node_modules/moment/moment.js");
|
900
|
+
/* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_1__);
|
759
901
|
|
760
|
-
for (let i = 0; i < bootLogEntries.size(); i++)
|
761
|
-
text += bootLogEntries.getUtfString(i) + '\n';
|
762
902
|
|
763
|
-
$('#lgv-bootLogText').text(text);
|
764
903
|
|
765
|
-
|
766
|
-
|
767
|
-
|
904
|
+
class Network24hChart extends HTMLElement
|
905
|
+
{
|
906
|
+
constructor()
|
907
|
+
{
|
908
|
+
super();
|
768
909
|
|
769
|
-
|
770
|
-
|
771
|
-
|
772
|
-
|
773
|
-
this._disableBackupInterface(data.getBool('running'), data.getUtfString('type'));
|
910
|
+
this._lastTotalOut = 0;
|
911
|
+
this._lastTotalIn = 0;
|
912
|
+
this._lastDate = new Date();
|
913
|
+
this._samplingRateSeconds = 0;
|
774
914
|
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
let files = data.getSFSArray('files');
|
915
|
+
// Create chart html
|
916
|
+
let chartHtml = $('<div>');
|
917
|
+
$(this).append(chartHtml);
|
779
918
|
|
780
|
-
|
781
|
-
|
782
|
-
|
919
|
+
// Initialize chart
|
920
|
+
this._chartWidget = this._initChartWidget(chartHtml);
|
921
|
+
}
|
783
922
|
|
784
|
-
|
923
|
+
_initChartWidget(chartHtml)
|
924
|
+
{
|
925
|
+
return chartHtml.kendoChart({
|
926
|
+
transitions: false,
|
927
|
+
chartArea: {
|
928
|
+
height: 270,
|
929
|
+
background: 'transparent'
|
930
|
+
},
|
931
|
+
legend: {
|
932
|
+
visible: false
|
933
|
+
},
|
934
|
+
seriesDefaults: {
|
935
|
+
type: 'area',
|
936
|
+
labels: {
|
937
|
+
visible: false,
|
938
|
+
format: '{0}',
|
939
|
+
background: 'transparent'
|
940
|
+
},
|
941
|
+
},
|
942
|
+
series: [{
|
943
|
+
name: 'Outgoing',
|
944
|
+
field: 'outgoing',
|
945
|
+
categoryField: 'time',
|
946
|
+
color: '#CC0000',
|
947
|
+
line: {
|
948
|
+
width: 2
|
949
|
+
}
|
950
|
+
},
|
951
|
+
{
|
952
|
+
name: 'Incoming',
|
953
|
+
field: 'incoming',
|
954
|
+
categoryField: 'time',
|
955
|
+
color: '#009900',
|
956
|
+
line: {
|
957
|
+
width: 2
|
958
|
+
}
|
959
|
+
}],
|
960
|
+
valueAxis: {
|
961
|
+
labels: {
|
962
|
+
format: '{0}',
|
963
|
+
template: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_0__["getNetworkValueAxisLabelTemplate"])()
|
964
|
+
},
|
965
|
+
line: {
|
966
|
+
visible: false
|
967
|
+
},
|
968
|
+
min: 0
|
969
|
+
},
|
970
|
+
categoryAxis: {
|
971
|
+
majorGridLines: {
|
972
|
+
visible: true,
|
973
|
+
step: 60
|
974
|
+
},
|
975
|
+
majorTicks: {
|
976
|
+
visible: true,
|
977
|
+
step: 60
|
978
|
+
},
|
979
|
+
labels: {
|
980
|
+
visible: true,
|
981
|
+
step: 60
|
982
|
+
},
|
983
|
+
baseUnit: 'minutes',
|
984
|
+
type: 'date',
|
985
|
+
},
|
986
|
+
tooltip: {
|
987
|
+
shared: true,
|
988
|
+
visible: true,
|
989
|
+
sharedTemplate: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_0__["getNetworkSharedTemplate"])('dd MMM HH:mm'),
|
990
|
+
background: '#e4e4e4'
|
991
|
+
}
|
992
|
+
}).data('kendoChart');
|
993
|
+
}
|
785
994
|
|
786
|
-
|
787
|
-
|
995
|
+
redraw()
|
996
|
+
{
|
997
|
+
this._chartWidget.redraw();
|
998
|
+
}
|
788
999
|
|
789
|
-
|
1000
|
+
set range(values)
|
1001
|
+
{
|
1002
|
+
this._range = values;
|
790
1003
|
|
791
|
-
|
792
|
-
|
793
|
-
const file = files.getSFSObject(f);
|
1004
|
+
this._updateXAxisLimits();
|
1005
|
+
}
|
794
1006
|
|
795
|
-
|
1007
|
+
get range()
|
1008
|
+
{
|
1009
|
+
return this._range;
|
1010
|
+
}
|
796
1011
|
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
fileObj.name = filePath.substr(filePath.lastIndexOf('/') + 1);
|
801
|
-
fileObj.date = file.getUtfString('date');
|
802
|
-
fileObj.time = file.getUtfString('time');
|
803
|
-
fileObj.size = Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_4__["bytesToSize"])(file.getLong('size'), 2);
|
1012
|
+
addHistoryEntries(outgoingData, incomingData, samplingRateSeconds, shiftSeconds)
|
1013
|
+
{
|
1014
|
+
this._samplingRateSeconds = samplingRateSeconds;
|
804
1015
|
|
805
|
-
|
1016
|
+
let now = new Date();
|
806
1017
|
|
807
|
-
|
808
|
-
if (!lastBootLogBackupFound)
|
809
|
-
{
|
810
|
-
if (fileObj.name.startsWith(this.BOOT_LOG_BACKUP_ID))
|
811
|
-
{
|
812
|
-
this._fillBackupCard('#lgv-bootLogBackupCard', fileObj);
|
1018
|
+
// NOTE: outgoingData and incominData are supposed to have the same size!!!
|
813
1019
|
|
814
|
-
|
815
|
-
|
816
|
-
|
1020
|
+
if (outgoingData.length > 0)
|
1021
|
+
{
|
1022
|
+
let start = moment__WEBPACK_IMPORTED_MODULE_1__(now);
|
1023
|
+
start.subtract((samplingRateSeconds * outgoingData.length) + shiftSeconds, 's')
|
817
1024
|
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
if (fileObj.name.startsWith(this.RUNTIME_LOG_BACKUP_ID))
|
822
|
-
{
|
823
|
-
this._fillBackupCard('#lgv-runtimeLogBackupCard', fileObj);
|
1025
|
+
this._lastTotalOut = outgoingData[0];
|
1026
|
+
this._lastTotalIn = incomingData[0];
|
1027
|
+
this._lastDate = start.toDate();
|
824
1028
|
|
825
|
-
|
826
|
-
|
827
|
-
|
1029
|
+
if (outgoingData.length > 1)
|
1030
|
+
{
|
1031
|
+
let dataSource = new kendo.data.DataSource();
|
828
1032
|
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
{
|
834
|
-
this._fillBackupCard('#lgv-fullLogBackupCard', fileObj);
|
1033
|
+
for (let i = 1; i < outgoingData.length; i++)
|
1034
|
+
{
|
1035
|
+
const totalOut = outgoingData[i];
|
1036
|
+
const totalIn = incomingData[i];
|
835
1037
|
|
836
|
-
|
837
|
-
|
838
|
-
}
|
1038
|
+
let date = start.clone();
|
1039
|
+
date.add(i * samplingRateSeconds, 's');
|
839
1040
|
|
840
|
-
|
841
|
-
backupsList.push(fileObj);
|
1041
|
+
this.addEntry(totalOut, totalIn, dataSource, date.toDate(), false);
|
842
1042
|
}
|
843
1043
|
|
844
|
-
//
|
845
|
-
|
1044
|
+
// Assign datasource to chart
|
1045
|
+
this._chartWidget.setDataSource(dataSource);
|
846
1046
|
|
847
|
-
|
848
|
-
this.
|
849
|
-
|
1047
|
+
// Update axis
|
1048
|
+
this._updateXAxisLimits();
|
1049
|
+
}
|
1050
|
+
}
|
1051
|
+
else
|
1052
|
+
{
|
1053
|
+
this._lastTotalOut = 0;
|
1054
|
+
this._lastTotalIn = 0;
|
1055
|
+
this._lastDate = now;
|
1056
|
+
}
|
1057
|
+
}
|
850
1058
|
|
851
|
-
|
852
|
-
|
853
|
-
|
1059
|
+
addEntry(totalOut, totalIn, dataSource = null, date = null, updateAxis = true)
|
1060
|
+
{
|
1061
|
+
if (date == null)
|
1062
|
+
date = new Date();
|
854
1063
|
|
855
|
-
|
856
|
-
this._fillBackupCard('#lgv-runtimeLogBackupCard', null);
|
1064
|
+
const elapsedSecs = Math.round((date.getTime() - this._lastDate.getTime()) / 1000);
|
857
1065
|
|
858
|
-
|
859
|
-
|
1066
|
+
// The 24h chart is updated at the same sampling rate used by the server to save the traffic history
|
1067
|
+
if (elapsedSecs >= this._samplingRateSeconds)
|
1068
|
+
{
|
1069
|
+
let newEntry = {
|
1070
|
+
time: date,
|
1071
|
+
outgoing: Math.round((totalOut - this._lastTotalOut) / elapsedSecs),
|
1072
|
+
incoming: Math.round((totalIn - this._lastTotalIn) / elapsedSecs)
|
1073
|
+
};
|
860
1074
|
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
this.shellCtrl.showNotification(`Log backup warning`, data.getUtfString('message'));
|
865
|
-
}
|
866
|
-
}
|
1075
|
+
// Add entry to data source
|
1076
|
+
if (dataSource == null)
|
1077
|
+
dataSource = this._dataSource;
|
867
1078
|
|
868
|
-
|
869
|
-
this._switchDownloadViewStack('lgv-downloadView');
|
870
|
-
}
|
1079
|
+
dataSource.add(newEntry);
|
871
1080
|
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
const error = data.getUtfString('error');
|
1081
|
+
this._lastTotalOut = totalOut;
|
1082
|
+
this._lastTotalIn = totalIn;
|
1083
|
+
this._lastDate = date;
|
876
1084
|
|
877
|
-
|
878
|
-
|
1085
|
+
if (updateAxis)
|
1086
|
+
this._updateXAxisLimits();
|
879
1087
|
}
|
1088
|
+
}
|
880
1089
|
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
const error = data.getUtfString('error');
|
885
|
-
|
886
|
-
// Show an alert
|
887
|
-
this.shellCtrl.showSimpleAlert(error, true);
|
888
|
-
}
|
1090
|
+
_updateXAxisLimits()
|
1091
|
+
{
|
1092
|
+
let ds = this._dataSource;
|
889
1093
|
|
890
|
-
|
891
|
-
else if (command == this.RESP_BACKUP_WARNING)
|
1094
|
+
if (ds.total() > 0)
|
892
1095
|
{
|
893
|
-
|
1096
|
+
const chartMinimum = moment__WEBPACK_IMPORTED_MODULE_1__(this._lastDate).add(this._range[0], 'h');
|
1097
|
+
const chartMaximum = moment__WEBPACK_IMPORTED_MODULE_1__(this._lastDate).add(this._range[1], 'h');
|
1098
|
+
|
1099
|
+
this._chartWidget.options.categoryAxis.min = chartMinimum.toDate();
|
1100
|
+
this._chartWidget.options.categoryAxis.max = chartMaximum.toDate();
|
894
1101
|
|
895
|
-
|
896
|
-
this.shellCtrl.showNotification(`Log backup warning`, warn);
|
1102
|
+
this._chartWidget.redraw();
|
897
1103
|
}
|
898
1104
|
}
|
899
1105
|
|
900
|
-
|
901
|
-
|
902
|
-
|
1106
|
+
get _dataSource()
|
1107
|
+
{
|
1108
|
+
return this._chartWidget.dataSource;
|
1109
|
+
}
|
1110
|
+
}
|
1111
|
+
|
1112
|
+
// DEFINE COMPONENT
|
1113
|
+
if (!window.customElements.get('network-24h-chart'))
|
1114
|
+
window.customElements.define('network-24h-chart', Network24hChart);
|
1115
|
+
|
1116
|
+
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! jquery */ "jquery")))
|
1117
|
+
|
1118
|
+
/***/ }),
|
1119
|
+
|
1120
|
+
/***/ "./src/components/charts/network-realtime-chart.js":
|
1121
|
+
/*!*********************************************************!*\
|
1122
|
+
!*** ./src/components/charts/network-realtime-chart.js ***!
|
1123
|
+
\*********************************************************/
|
1124
|
+
/*! exports provided: NetworkRealtimeChart */
|
1125
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
903
1126
|
|
904
|
-
|
1127
|
+
"use strict";
|
1128
|
+
__webpack_require__.r(__webpack_exports__);
|
1129
|
+
/* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "NetworkRealtimeChart", function() { return NetworkRealtimeChart; });
|
1130
|
+
/* harmony import */ var _base_chart__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-chart */ "./src/components/charts/base-chart.js");
|
1131
|
+
/* harmony import */ var _chart_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./chart-utils */ "./src/components/charts/chart-utils.js");
|
1132
|
+
|
1133
|
+
|
1134
|
+
|
1135
|
+
|
1136
|
+
class NetworkRealtimeChart extends _base_chart__WEBPACK_IMPORTED_MODULE_0__["BaseChart"]
|
1137
|
+
{
|
1138
|
+
constructor()
|
905
1139
|
{
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
1140
|
+
super(300);
|
1141
|
+
|
1142
|
+
this._lastTotalKbOut = 0;
|
1143
|
+
this._lastTotalKbIn = 0;
|
1144
|
+
this._lastTime = 0;
|
1145
|
+
|
1146
|
+
// Append text to display elapsed time
|
1147
|
+
this._elapsedTxt = $('<div>', {class: 'text-center', text: '---'});
|
1148
|
+
$(this).append(this._elapsedTxt);
|
1149
|
+
}
|
1150
|
+
|
1151
|
+
_initChartWidget(chartHtml)
|
1152
|
+
{
|
1153
|
+
return chartHtml.kendoChart({
|
1154
|
+
transitions: false,
|
1155
|
+
chartArea: {
|
1156
|
+
height: 270,
|
1157
|
+
background: 'transparent'
|
1158
|
+
},
|
1159
|
+
legend: {
|
1160
|
+
visible: false
|
1161
|
+
},
|
1162
|
+
seriesDefaults: {
|
1163
|
+
type: 'area',
|
1164
|
+
labels: {
|
1165
|
+
visible: false,
|
1166
|
+
format: '{0}',
|
1167
|
+
background: 'transparent'
|
1168
|
+
},
|
1169
|
+
},
|
1170
|
+
series: [{
|
1171
|
+
name: 'Outgoing',
|
1172
|
+
field: 'outgoing',
|
1173
|
+
categoryField: 'time',
|
1174
|
+
color: this.outgoingColor,
|
1175
|
+
line: {
|
1176
|
+
width: 2
|
1177
|
+
}
|
1178
|
+
},
|
910
1179
|
{
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
1180
|
+
name: 'Incoming',
|
1181
|
+
field: 'incoming',
|
1182
|
+
categoryField: 'time',
|
1183
|
+
color: this.incomingColor,
|
1184
|
+
line: {
|
1185
|
+
width: 2
|
916
1186
|
}
|
917
|
-
}
|
1187
|
+
}],
|
1188
|
+
valueAxis: {
|
1189
|
+
labels: {
|
1190
|
+
format: '{0}',
|
1191
|
+
template: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getNetworkValueAxisLabelTemplate"])()
|
1192
|
+
},
|
1193
|
+
line: {
|
1194
|
+
visible: false
|
1195
|
+
},
|
1196
|
+
min: 0,
|
1197
|
+
},
|
1198
|
+
categoryAxis: {
|
1199
|
+
majorGridLines: {
|
1200
|
+
visible: false
|
1201
|
+
},
|
1202
|
+
majorTicks: {
|
1203
|
+
visible: false
|
1204
|
+
},
|
1205
|
+
labels: {
|
1206
|
+
visible: false
|
1207
|
+
}
|
1208
|
+
},
|
1209
|
+
tooltip: {
|
1210
|
+
shared: true,
|
1211
|
+
visible: true,
|
1212
|
+
sharedTemplate: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getNetworkSharedTemplate"])(),
|
1213
|
+
background: '#e4e4e4'
|
1214
|
+
}
|
1215
|
+
}).data('kendoChart');
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
get outgoingColor()
|
1219
|
+
{
|
1220
|
+
return '#CC0000';
|
1221
|
+
}
|
1222
|
+
|
1223
|
+
get incomingColor()
|
1224
|
+
{
|
1225
|
+
return '#009900';
|
1226
|
+
}
|
1227
|
+
|
1228
|
+
addEntry(totalOutKb, totalInKb)
|
1229
|
+
{
|
1230
|
+
let now = new Date()
|
1231
|
+
let time = now.getTime();
|
1232
|
+
|
1233
|
+
// The first value sent by the server is not plotted: it would be a worng value because
|
1234
|
+
// we have to calculate it as the difference between two total values, but we don't have the previous one
|
1235
|
+
if (this._lastTime > 0)
|
1236
|
+
{
|
1237
|
+
let elapsedSecs = (time - this._lastTime) / 1000;
|
1238
|
+
|
1239
|
+
const valueOut = Math.round((totalOutKb - this._lastTotalKbOut) / elapsedSecs);
|
1240
|
+
const valueIn = Math.round((totalInKb - this._lastTotalKbIn) / elapsedSecs);
|
1241
|
+
|
1242
|
+
let newEntry = {
|
1243
|
+
time: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getFormattedDateTime"])(now),
|
1244
|
+
timestamp: time,
|
1245
|
+
outgoing: valueOut,
|
1246
|
+
incoming: valueIn
|
1247
|
+
};
|
1248
|
+
|
1249
|
+
// Add entry to chart
|
1250
|
+
super._addEntry(newEntry);
|
1251
|
+
|
1252
|
+
// Update x axis
|
1253
|
+
if (!this.isPaused)
|
1254
|
+
this._updateElapsedText();
|
1255
|
+
}
|
918
1256
|
|
919
|
-
|
920
|
-
|
1257
|
+
this._lastTotalKbOut = totalOutKb;
|
1258
|
+
this._lastTotalKbIn = totalInKb;
|
1259
|
+
this._lastTime = time;
|
1260
|
+
}
|
1261
|
+
|
1262
|
+
_updateElapsedText()
|
1263
|
+
{
|
1264
|
+
let ds = this._dataSource;
|
1265
|
+
|
1266
|
+
if (ds.total() > 1)
|
1267
|
+
{
|
1268
|
+
// Get axis limits
|
1269
|
+
const chartMinimum = ds.at(0).timestamp;
|
1270
|
+
const chartMaximum = ds.at(ds.total() - 1).timestamp;
|
1271
|
+
|
1272
|
+
// Set elapsed text
|
1273
|
+
let title;
|
1274
|
+
let seconds = Math.round( (chartMaximum - chartMinimum) / 1000 );
|
1275
|
+
|
1276
|
+
if (seconds < 60)
|
1277
|
+
title = 'Last ' + (seconds != 1 ? seconds + ' seconds' : 'second');
|
1278
|
+
else
|
921
1279
|
{
|
922
|
-
|
923
|
-
|
924
|
-
{
|
925
|
-
this.sendExtensionRequest(this.REQ_GET_BACKUPS_STATUS);
|
926
|
-
this._backupStatusRequested = true;
|
927
|
-
}
|
1280
|
+
const minutes = Math.floor(seconds / 60);
|
1281
|
+
title = 'Last ' + (minutes != 1 ? minutes + ' minutes' : 'minute');
|
928
1282
|
}
|
1283
|
+
|
1284
|
+
this._elapsedTxt.text(title);
|
929
1285
|
}
|
930
1286
|
}
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
// DEFINE COMPONENT
|
1290
|
+
if (!window.customElements.get('network-realtime-chart'))
|
1291
|
+
window.customElements.define('network-realtime-chart', NetworkRealtimeChart);
|
1292
|
+
|
1293
|
+
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! jquery */ "jquery")))
|
1294
|
+
|
1295
|
+
/***/ }),
|
1296
|
+
|
1297
|
+
/***/ "./src/components/charts/system-queue-chart.js":
|
1298
|
+
/*!*****************************************************!*\
|
1299
|
+
!*** ./src/components/charts/system-queue-chart.js ***!
|
1300
|
+
\*****************************************************/
|
1301
|
+
/*! exports provided: SystemQueueChart */
|
1302
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
1303
|
+
|
1304
|
+
"use strict";
|
1305
|
+
__webpack_require__.r(__webpack_exports__);
|
1306
|
+
/* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SystemQueueChart", function() { return SystemQueueChart; });
|
1307
|
+
/* harmony import */ var _base_chart__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-chart */ "./src/components/charts/base-chart.js");
|
1308
|
+
/* harmony import */ var _chart_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./chart-utils */ "./src/components/charts/chart-utils.js");
|
1309
|
+
|
1310
|
+
|
1311
|
+
|
1312
|
+
|
1313
|
+
class SystemQueueChart extends _base_chart__WEBPACK_IMPORTED_MODULE_0__["BaseChart"]
|
1314
|
+
{
|
1315
|
+
constructor()
|
1316
|
+
{
|
1317
|
+
super(240);
|
1318
|
+
|
1319
|
+
this._averageLoad = 0;
|
1320
|
+
}
|
931
1321
|
|
932
|
-
|
1322
|
+
_initialize()
|
933
1323
|
{
|
934
|
-
|
935
|
-
|
1324
|
+
const chartHeight = 240;
|
1325
|
+
|
1326
|
+
// Append container for chart & gauge
|
1327
|
+
let container = $('<div>', {class: 'd-flex flex-row'});
|
1328
|
+
$(this).append(container);
|
1329
|
+
|
1330
|
+
// CHART
|
1331
|
+
|
1332
|
+
let chartContainer = $('<div>', {class: 'flex-grow-1'});
|
1333
|
+
container.append(chartContainer);
|
1334
|
+
|
1335
|
+
// Create chart html
|
1336
|
+
let chartHtml = $('<div>');
|
1337
|
+
chartContainer.append(chartHtml);
|
1338
|
+
|
1339
|
+
// Initialize chart
|
1340
|
+
this._chartWidget = this._initChartWidget(chartHtml, chartHeight);
|
1341
|
+
|
1342
|
+
// Append text to display elapsed time
|
1343
|
+
this._elapsedTxt = $('<div>', {class: 'text-center', text: '---'});
|
1344
|
+
chartContainer.append(this._elapsedTxt);
|
1345
|
+
|
1346
|
+
// GAUGE
|
1347
|
+
|
1348
|
+
let gaugeContainer = $('<div>');
|
1349
|
+
container.append(gaugeContainer);
|
1350
|
+
|
1351
|
+
// Create gauge html
|
1352
|
+
let gaugeHtml = $('<div>');
|
1353
|
+
gaugeContainer.append(gaugeHtml);
|
1354
|
+
|
1355
|
+
// Initialize gauge
|
1356
|
+
this._gaugeWidget = this._initGaugeWidget(gaugeHtml, chartHeight);
|
1357
|
+
|
1358
|
+
// Append text to display load
|
1359
|
+
this._loadTxt = $('<div>', {class: 'text-center font-weight-bold', text: '---'});
|
1360
|
+
gaugeContainer.append(this._loadTxt);
|
1361
|
+
|
1362
|
+
//------------------------------
|
1363
|
+
|
1364
|
+
// Reset data source
|
1365
|
+
this.reset();
|
936
1366
|
}
|
937
1367
|
|
938
|
-
|
1368
|
+
_initChartWidget(chartHtml, height)
|
939
1369
|
{
|
940
|
-
|
941
|
-
|
1370
|
+
return chartHtml.kendoChart({
|
1371
|
+
transitions: false,
|
1372
|
+
chartArea: {
|
1373
|
+
height: height,
|
1374
|
+
background: 'transparent'
|
1375
|
+
},
|
1376
|
+
legend: {
|
1377
|
+
visible: false
|
1378
|
+
},
|
1379
|
+
seriesDefaults: {
|
1380
|
+
type: 'area',
|
1381
|
+
labels: {
|
1382
|
+
visible: false,
|
1383
|
+
format: '{0}',
|
1384
|
+
background: 'transparent'
|
1385
|
+
}
|
1386
|
+
},
|
1387
|
+
series: [
|
1388
|
+
{
|
1389
|
+
name: 'Messages',
|
1390
|
+
field: 'load',
|
1391
|
+
categoryField: 'time',
|
1392
|
+
color: '#3399ff',
|
1393
|
+
line: {
|
1394
|
+
width: 2
|
1395
|
+
}
|
1396
|
+
}
|
1397
|
+
],
|
1398
|
+
valueAxis: {
|
1399
|
+
title: {
|
1400
|
+
text: 'Messages'
|
1401
|
+
},
|
1402
|
+
labels: {
|
1403
|
+
format: '{0}'
|
1404
|
+
},
|
1405
|
+
line: {
|
1406
|
+
visible: false
|
1407
|
+
},
|
1408
|
+
min: 0
|
1409
|
+
},
|
1410
|
+
categoryAxis: {
|
1411
|
+
majorGridLines: {
|
1412
|
+
visible: false
|
1413
|
+
},
|
1414
|
+
majorTicks: {
|
1415
|
+
visible: false
|
1416
|
+
},
|
1417
|
+
labels: {
|
1418
|
+
visible: false
|
1419
|
+
}
|
1420
|
+
},
|
1421
|
+
tooltip: {
|
1422
|
+
shared: true,
|
1423
|
+
visible: true,
|
1424
|
+
sharedTemplate: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getBasicSharedTemplate"])(),
|
1425
|
+
background: '#e4e4e4'
|
1426
|
+
}
|
1427
|
+
}).data('kendoChart');
|
942
1428
|
}
|
943
1429
|
|
944
|
-
|
1430
|
+
_initGaugeWidget(gaugeHtml, height)
|
945
1431
|
{
|
946
|
-
|
947
|
-
|
1432
|
+
return gaugeHtml.kendoLinearGauge({
|
1433
|
+
pointer: {
|
1434
|
+
value: 0,
|
1435
|
+
shape: 'arrow',
|
1436
|
+
size: 10,
|
1437
|
+
color: '#212529'
|
1438
|
+
},
|
1439
|
+
gaugeArea: {
|
1440
|
+
height: height
|
1441
|
+
},
|
1442
|
+
scale: {
|
1443
|
+
majorUnit: 10,
|
1444
|
+
minorUnit: 1,
|
1445
|
+
min: 0,
|
1446
|
+
max: 100,
|
1447
|
+
ranges: [
|
1448
|
+
{
|
1449
|
+
from: 0,
|
1450
|
+
to: 50,
|
1451
|
+
color: '#00cc00',
|
1452
|
+
opacity: .5
|
1453
|
+
}, {
|
1454
|
+
from: 50,
|
1455
|
+
to: 75,
|
1456
|
+
color: '#ffe106',
|
1457
|
+
opacity: .5
|
1458
|
+
}, {
|
1459
|
+
from: 75,
|
1460
|
+
to: 100,
|
1461
|
+
color: '#ed1601',
|
1462
|
+
opacity: .5
|
1463
|
+
}
|
1464
|
+
],
|
1465
|
+
majorTicks: {
|
1466
|
+
visible: true,
|
1467
|
+
size: 10
|
1468
|
+
},
|
1469
|
+
minorTicks: {
|
1470
|
+
visible: false
|
1471
|
+
},
|
1472
|
+
labels: {
|
1473
|
+
visible: false
|
1474
|
+
},
|
1475
|
+
line: {
|
1476
|
+
visible: false
|
1477
|
+
},
|
1478
|
+
rangeSize: 10
|
1479
|
+
}
|
1480
|
+
}).data('kendoLinearGauge');
|
1481
|
+
}
|
1482
|
+
|
1483
|
+
addEntry(load, queueMsgLimit)
|
1484
|
+
{
|
1485
|
+
// CHART
|
1486
|
+
|
1487
|
+
let now = new Date();
|
1488
|
+
|
1489
|
+
let newEntry = {
|
1490
|
+
time: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getFormattedDateTime"])(now),
|
1491
|
+
timestamp: now.getTime(),
|
1492
|
+
load: load
|
1493
|
+
};
|
1494
|
+
|
1495
|
+
// Add entry to chart
|
1496
|
+
super._addEntry(newEntry);
|
1497
|
+
|
1498
|
+
// Update x axis
|
1499
|
+
if (!this.isPaused)
|
1500
|
+
this._updateElapsedText();
|
1501
|
+
|
1502
|
+
// GAUGE
|
1503
|
+
|
1504
|
+
// Evaluate average
|
1505
|
+
let numValues = this._dataSource.total();
|
1506
|
+
|
1507
|
+
if (numValues > 0)
|
1508
|
+
{
|
1509
|
+
let total = 0;
|
1510
|
+
for (let i = 0; i < numValues; i++)
|
1511
|
+
total += this._dataSource.at(i).load;
|
1512
|
+
|
1513
|
+
this._averageLoad = Math.round(total / numValues);
|
1514
|
+
}
|
948
1515
|
else
|
949
|
-
|
1516
|
+
this._averageLoad = 0;
|
1517
|
+
|
1518
|
+
const avgLoadPerc = Math.round(this._averageLoad / queueMsgLimit * 1000) / 10;
|
1519
|
+
|
1520
|
+
// Set gauge value
|
1521
|
+
this._gaugeWidget.value(avgLoadPerc);
|
1522
|
+
|
1523
|
+
// Set load text
|
1524
|
+
this._loadTxt.text(avgLoadPerc + '%')
|
950
1525
|
}
|
951
1526
|
|
952
|
-
|
1527
|
+
_updateElapsedText()
|
953
1528
|
{
|
954
|
-
|
955
|
-
|
1529
|
+
let ds = this._dataSource;
|
1530
|
+
|
1531
|
+
if (ds.total() > 1)
|
1532
|
+
{
|
1533
|
+
// Get axis limits
|
1534
|
+
const chartMinimum = ds.at(0).timestamp;
|
1535
|
+
const chartMaximum = ds.at(ds.total() - 1).timestamp;
|
1536
|
+
|
1537
|
+
// Set elapsed text
|
1538
|
+
let seconds = Math.round( (chartMaximum - chartMinimum) / 1000 );
|
1539
|
+
let title;
|
1540
|
+
|
1541
|
+
if (seconds < 60)
|
1542
|
+
title = 'Last ' + (seconds != 1 ? seconds + ' seconds' : 'second');
|
1543
|
+
else
|
1544
|
+
{
|
1545
|
+
const minutes = Math.floor(seconds / 60);
|
1546
|
+
title = 'Last ' + (minutes != 1 ? minutes + ' minutes' : 'minute');
|
1547
|
+
}
|
956
1548
|
|
957
|
-
|
958
|
-
|
1549
|
+
this._elapsedTxt.text(title);
|
1550
|
+
}
|
959
1551
|
}
|
960
1552
|
|
961
|
-
|
1553
|
+
get load()
|
962
1554
|
{
|
963
|
-
|
964
|
-
|
1555
|
+
return this._averageLoad;
|
1556
|
+
}
|
1557
|
+
}
|
1558
|
+
|
1559
|
+
// DEFINE COMPONENT
|
1560
|
+
if (!window.customElements.get('system-queue-chart'))
|
1561
|
+
window.customElements.define('system-queue-chart', SystemQueueChart);
|
1562
|
+
|
1563
|
+
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! jquery */ "jquery")))
|
1564
|
+
|
1565
|
+
/***/ }),
|
1566
|
+
|
1567
|
+
/***/ "./src/components/charts/system-workload-chart.js":
|
1568
|
+
/*!********************************************************!*\
|
1569
|
+
!*** ./src/components/charts/system-workload-chart.js ***!
|
1570
|
+
\********************************************************/
|
1571
|
+
/*! exports provided: SystemWorkloadChart */
|
1572
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
1573
|
+
|
1574
|
+
"use strict";
|
1575
|
+
__webpack_require__.r(__webpack_exports__);
|
1576
|
+
/* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SystemWorkloadChart", function() { return SystemWorkloadChart; });
|
1577
|
+
/* harmony import */ var _base_chart__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-chart */ "./src/components/charts/base-chart.js");
|
1578
|
+
/* harmony import */ var _chart_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./chart-utils */ "./src/components/charts/chart-utils.js");
|
965
1579
|
|
966
|
-
|
967
|
-
|
1580
|
+
|
1581
|
+
|
1582
|
+
|
1583
|
+
class SystemWorkloadChart extends _base_chart__WEBPACK_IMPORTED_MODULE_0__["BaseChart"]
|
1584
|
+
{
|
1585
|
+
constructor()
|
1586
|
+
{
|
1587
|
+
super(240);
|
968
1588
|
}
|
969
1589
|
|
970
|
-
|
1590
|
+
_initialize()
|
971
1591
|
{
|
972
|
-
|
973
|
-
|
1592
|
+
const chartHeight = 240;
|
1593
|
+
|
1594
|
+
// Append container for chart & gauge
|
1595
|
+
let container = $('<div>', {class: 'd-flex flex-row'});
|
1596
|
+
$(this).append(container);
|
1597
|
+
|
1598
|
+
// CHART
|
1599
|
+
|
1600
|
+
let chartContainer = $('<div>', {class: 'flex-grow-1'});
|
1601
|
+
container.append(chartContainer);
|
1602
|
+
|
1603
|
+
// Create chart html
|
1604
|
+
let chartHtml = $('<div>');
|
1605
|
+
chartContainer.append(chartHtml);
|
1606
|
+
|
1607
|
+
// Initialize chart
|
1608
|
+
this._chartWidget = this._initChartWidget(chartHtml, chartHeight);
|
1609
|
+
|
1610
|
+
// Append text to display elapsed time
|
1611
|
+
this._elapsedTxt = $('<div>', {class: 'text-center', text: '---'});
|
1612
|
+
chartContainer.append(this._elapsedTxt);
|
1613
|
+
|
1614
|
+
// GAUGE
|
974
1615
|
|
975
|
-
|
976
|
-
|
1616
|
+
let gaugeContainer = $('<div>');
|
1617
|
+
container.append(gaugeContainer);
|
1618
|
+
|
1619
|
+
// Create gauge html
|
1620
|
+
let gaugeHtml = $('<div>');
|
1621
|
+
gaugeContainer.append(gaugeHtml);
|
1622
|
+
|
1623
|
+
// Initialize gauge
|
1624
|
+
this._gaugeWidget = this._initGaugeWidget(gaugeHtml, chartHeight);
|
1625
|
+
|
1626
|
+
// Append text to display load
|
1627
|
+
this._loadTxt = $('<div>', {class: 'text-center font-weight-bold', text: '---'});
|
1628
|
+
gaugeContainer.append(this._loadTxt);
|
1629
|
+
|
1630
|
+
//------------------------------
|
1631
|
+
|
1632
|
+
// Reset data source
|
1633
|
+
this.reset();
|
977
1634
|
}
|
978
1635
|
|
979
|
-
|
1636
|
+
_initChartWidget(chartHtml, height)
|
980
1637
|
{
|
981
|
-
|
982
|
-
|
1638
|
+
return chartHtml.kendoChart({
|
1639
|
+
transitions: false,
|
1640
|
+
chartArea: {
|
1641
|
+
height: height,
|
1642
|
+
background: 'transparent'
|
1643
|
+
},
|
1644
|
+
legend: {
|
1645
|
+
visible: false
|
1646
|
+
},
|
1647
|
+
seriesDefaults: {
|
1648
|
+
type: 'area',
|
1649
|
+
labels: {
|
1650
|
+
visible: false,
|
1651
|
+
format: '{0}%',
|
1652
|
+
background: 'transparent'
|
1653
|
+
}
|
1654
|
+
},
|
1655
|
+
series: [
|
1656
|
+
{
|
1657
|
+
name: 'Workload',
|
1658
|
+
field: 'load',
|
1659
|
+
categoryField: 'time',
|
1660
|
+
color: '#3399ff',
|
1661
|
+
line: {
|
1662
|
+
width: 2
|
1663
|
+
}
|
1664
|
+
}
|
1665
|
+
],
|
1666
|
+
valueAxis: {
|
1667
|
+
labels: {
|
1668
|
+
format: '{0}%'
|
1669
|
+
},
|
1670
|
+
line: {
|
1671
|
+
visible: false
|
1672
|
+
},
|
1673
|
+
min: 0,
|
1674
|
+
max: 100
|
1675
|
+
},
|
1676
|
+
categoryAxis: {
|
1677
|
+
majorGridLines: {
|
1678
|
+
visible: false
|
1679
|
+
},
|
1680
|
+
majorTicks: {
|
1681
|
+
visible: false
|
1682
|
+
},
|
1683
|
+
labels: {
|
1684
|
+
visible: false
|
1685
|
+
}
|
1686
|
+
},
|
1687
|
+
tooltip: {
|
1688
|
+
shared: true,
|
1689
|
+
visible: true,
|
1690
|
+
sharedTemplate: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getBasicSharedTemplate"])('{0}%'),
|
1691
|
+
background: '#e4e4e4'
|
1692
|
+
}
|
1693
|
+
}).data('kendoChart');
|
983
1694
|
}
|
984
1695
|
|
985
|
-
|
1696
|
+
_initGaugeWidget(gaugeHtml, height)
|
986
1697
|
{
|
987
|
-
|
988
|
-
|
1698
|
+
return gaugeHtml.kendoLinearGauge({
|
1699
|
+
pointer: {
|
1700
|
+
value: 0,
|
1701
|
+
shape: 'arrow',
|
1702
|
+
size: 10,
|
1703
|
+
color: '#212529'
|
1704
|
+
},
|
1705
|
+
gaugeArea: {
|
1706
|
+
height: height
|
1707
|
+
},
|
1708
|
+
scale: {
|
1709
|
+
majorUnit: 10,
|
1710
|
+
minorUnit: 1,
|
1711
|
+
max: 100,
|
1712
|
+
min: 0,
|
1713
|
+
ranges: [
|
1714
|
+
{
|
1715
|
+
from: 0,
|
1716
|
+
to: 50,
|
1717
|
+
color: '#00cc00',
|
1718
|
+
opacity: .5
|
1719
|
+
}, {
|
1720
|
+
from: 50,
|
1721
|
+
to: 75,
|
1722
|
+
color: '#ffe106',
|
1723
|
+
opacity: .5
|
1724
|
+
}, {
|
1725
|
+
from: 75,
|
1726
|
+
to: 100,
|
1727
|
+
color: '#ed1601',
|
1728
|
+
opacity: .5
|
1729
|
+
}
|
1730
|
+
],
|
1731
|
+
majorTicks: {
|
1732
|
+
visible: true,
|
1733
|
+
size: 10
|
1734
|
+
},
|
1735
|
+
minorTicks: {
|
1736
|
+
visible: false
|
1737
|
+
},
|
1738
|
+
labels: {
|
1739
|
+
visible: false
|
1740
|
+
},
|
1741
|
+
line: {
|
1742
|
+
visible: false
|
1743
|
+
},
|
1744
|
+
rangeSize: 10
|
1745
|
+
}
|
1746
|
+
}).data('kendoLinearGauge');
|
989
1747
|
}
|
990
1748
|
|
991
|
-
|
1749
|
+
addEntry(load)
|
992
1750
|
{
|
993
|
-
|
994
|
-
|
1751
|
+
// CHART
|
1752
|
+
|
1753
|
+
let now = new Date();
|
1754
|
+
|
1755
|
+
let newEntry = {
|
1756
|
+
time: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getFormattedDateTime"])(now),
|
1757
|
+
timestamp: now.getTime(),
|
1758
|
+
load: load
|
1759
|
+
};
|
995
1760
|
|
996
|
-
|
1761
|
+
// Add entry to chart
|
1762
|
+
super._addEntry(newEntry);
|
1763
|
+
|
1764
|
+
// Update x axis
|
1765
|
+
if (!this.isPaused)
|
1766
|
+
this._updateElapsedText();
|
1767
|
+
|
1768
|
+
// GAUGE
|
1769
|
+
|
1770
|
+
// Evaluate average
|
1771
|
+
let numValues = this._dataSource.total();
|
1772
|
+
let averageLoad = 0;
|
1773
|
+
|
1774
|
+
if (numValues > 0)
|
997
1775
|
{
|
998
|
-
|
999
|
-
|
1776
|
+
let total = 0;
|
1777
|
+
for (let i = 0; i < numValues; i++)
|
1778
|
+
total += this._dataSource.at(i).load;
|
1779
|
+
|
1780
|
+
averageLoad = Math.round(total / numValues);
|
1000
1781
|
}
|
1001
1782
|
|
1002
|
-
//
|
1003
|
-
this.
|
1783
|
+
// Set gauge value
|
1784
|
+
this._gaugeWidget.value(averageLoad);
|
1785
|
+
|
1786
|
+
// Set load text
|
1787
|
+
this._loadTxt.text(averageLoad + '%')
|
1004
1788
|
}
|
1005
1789
|
|
1006
|
-
|
1790
|
+
_updateElapsedText()
|
1007
1791
|
{
|
1008
|
-
|
1009
|
-
const selectedRows = this._downloadGrid.select();
|
1010
|
-
$('#lgv-downloadBt').attr('disabled', selectedRows.length == 0);
|
1011
|
-
$('#lgv-deleteBt').attr('disabled', selectedRows.length == 0);
|
1792
|
+
let ds = this._dataSource;
|
1012
1793
|
|
1013
|
-
if (
|
1794
|
+
if (ds.total() > 1)
|
1014
1795
|
{
|
1015
|
-
|
1016
|
-
|
1796
|
+
// Get axis limits
|
1797
|
+
const chartMinimum = ds.at(0).timestamp;
|
1798
|
+
const chartMaximum = ds.at(ds.total() - 1).timestamp;
|
1799
|
+
|
1800
|
+
// Set elapsed text
|
1801
|
+
let seconds = Math.round( (chartMaximum - chartMinimum) / 1000 );
|
1802
|
+
let title;
|
1803
|
+
|
1804
|
+
if (seconds < 60)
|
1805
|
+
title = 'Last ' + (seconds != 1 ? seconds + ' seconds' : 'second');
|
1806
|
+
else
|
1807
|
+
{
|
1808
|
+
const minutes = Math.floor(seconds / 60);
|
1809
|
+
title = 'Last ' + (minutes != 1 ? minutes + ' minutes' : 'minute');
|
1810
|
+
}
|
1811
|
+
|
1812
|
+
this._elapsedTxt.text(title);
|
1017
1813
|
}
|
1018
|
-
else
|
1019
|
-
$('#lgv-downloadBt').attr('href', '#');
|
1020
1814
|
}
|
1021
1815
|
|
1022
|
-
|
1816
|
+
get load()
|
1023
1817
|
{
|
1024
|
-
|
1818
|
+
return this._averageLoad;
|
1819
|
+
}
|
1820
|
+
}
|
1025
1821
|
|
1026
|
-
|
1027
|
-
|
1028
|
-
|
1822
|
+
// DEFINE COMPONENT
|
1823
|
+
if (!window.customElements.get('system-workload-chart'))
|
1824
|
+
window.customElements.define('system-workload-chart', SystemWorkloadChart);
|
1029
1825
|
|
1030
|
-
|
1031
|
-
let params = new SFS2X.SFSObject();
|
1032
|
-
params.putUtfString('file', dataItem.name);
|
1826
|
+
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! jquery */ "jquery")))
|
1033
1827
|
|
1034
|
-
|
1035
|
-
|
1828
|
+
/***/ }),
|
1829
|
+
|
1830
|
+
/***/ "./src/components/charts/thread-count-chart.js":
|
1831
|
+
/*!*****************************************************!*\
|
1832
|
+
!*** ./src/components/charts/thread-count-chart.js ***!
|
1833
|
+
\*****************************************************/
|
1834
|
+
/*! exports provided: ThreadCountChart */
|
1835
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
1836
|
+
|
1837
|
+
"use strict";
|
1838
|
+
__webpack_require__.r(__webpack_exports__);
|
1839
|
+
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ThreadCountChart", function() { return ThreadCountChart; });
|
1840
|
+
/* harmony import */ var _base_chart__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-chart */ "./src/components/charts/base-chart.js");
|
1841
|
+
/* harmony import */ var _chart_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./chart-utils */ "./src/components/charts/chart-utils.js");
|
1842
|
+
|
1843
|
+
|
1844
|
+
|
1845
|
+
|
1846
|
+
class ThreadCountChart extends _base_chart__WEBPACK_IMPORTED_MODULE_0__["BaseChart"]
|
1847
|
+
{
|
1848
|
+
constructor()
|
1849
|
+
{
|
1850
|
+
super(120);
|
1851
|
+
}
|
1852
|
+
|
1853
|
+
_initChartWidget(chartHtml)
|
1854
|
+
{
|
1855
|
+
return chartHtml.kendoChart({
|
1856
|
+
transitions: false,
|
1857
|
+
chartArea: {
|
1858
|
+
height: 120,
|
1859
|
+
background: 'transparent'
|
1860
|
+
},
|
1861
|
+
legend: {
|
1862
|
+
visible: false
|
1863
|
+
},
|
1864
|
+
seriesDefaults: {
|
1865
|
+
type: 'area',
|
1866
|
+
labels: {
|
1867
|
+
visible: false,
|
1868
|
+
format: '{0}',
|
1869
|
+
background: 'transparent'
|
1870
|
+
},
|
1871
|
+
},
|
1872
|
+
series: [
|
1873
|
+
{
|
1874
|
+
name: 'Threads',
|
1875
|
+
field: 'threads',
|
1876
|
+
categoryField: 'time',
|
1877
|
+
color: this.threadsColor,
|
1878
|
+
line: {
|
1879
|
+
width: 2
|
1880
|
+
}
|
1881
|
+
}
|
1882
|
+
],
|
1883
|
+
valueAxis: {
|
1884
|
+
min: 0,
|
1885
|
+
labels: {
|
1886
|
+
format: '{0}'
|
1887
|
+
},
|
1888
|
+
line: {
|
1889
|
+
visible: false
|
1890
|
+
},
|
1891
|
+
},
|
1892
|
+
categoryAxis: {
|
1893
|
+
majorGridLines: {
|
1894
|
+
visible: false
|
1895
|
+
},
|
1896
|
+
majorTicks: {
|
1897
|
+
visible: false
|
1898
|
+
},
|
1899
|
+
labels: {
|
1900
|
+
visible: false
|
1901
|
+
}
|
1902
|
+
},
|
1903
|
+
tooltip: {
|
1904
|
+
shared: true,
|
1905
|
+
visible: true,
|
1906
|
+
sharedTemplate: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getBasicSharedTemplate"])(),
|
1907
|
+
background: '#e4e4e4'
|
1908
|
+
}
|
1909
|
+
}).data('kendoChart');
|
1910
|
+
}
|
1911
|
+
|
1912
|
+
get threadsColor()
|
1913
|
+
{
|
1914
|
+
return '#3399FF';
|
1915
|
+
}
|
1916
|
+
|
1917
|
+
addEntry(threads)
|
1918
|
+
{
|
1919
|
+
let newEntry = {
|
1920
|
+
time: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_1__["getFormattedDateTime"])(new Date()),
|
1921
|
+
threads: threads
|
1922
|
+
};
|
1923
|
+
|
1924
|
+
// Add entry to chart
|
1925
|
+
super._addEntry(newEntry);
|
1926
|
+
}
|
1927
|
+
}
|
1928
|
+
|
1929
|
+
// DEFINE COMPONENT
|
1930
|
+
if (!window.customElements.get('thread-count-chart'))
|
1931
|
+
window.customElements.define('thread-count-chart', ThreadCountChart);
|
1932
|
+
|
1933
|
+
|
1934
|
+
/***/ }),
|
1935
|
+
|
1936
|
+
/***/ "./src/modules/dashboard.js":
|
1937
|
+
/*!**********************************!*\
|
1938
|
+
!*** ./src/modules/dashboard.js ***!
|
1939
|
+
\**********************************/
|
1940
|
+
/*! exports provided: default */
|
1941
|
+
/***/ (function(module, __webpack_exports__, __webpack_require__) {
|
1942
|
+
|
1943
|
+
"use strict";
|
1944
|
+
__webpack_require__.r(__webpack_exports__);
|
1945
|
+
/* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return Dashboard; });
|
1946
|
+
/* harmony import */ var _base_module__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-module */ "./src/modules/base-module.js");
|
1947
|
+
/* harmony import */ var _utils_utilities__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../utils/utilities */ "./src/utils/utilities.js");
|
1948
|
+
/* harmony import */ var _components_charts_chart_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../components/charts/chart-utils */ "./src/components/charts/chart-utils.js");
|
1949
|
+
/* harmony import */ var _components_charts_cpu_usage_chart__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../components/charts/cpu-usage-chart */ "./src/components/charts/cpu-usage-chart.js");
|
1950
|
+
/* harmony import */ var _components_charts_thread_count_chart__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../components/charts/thread-count-chart */ "./src/components/charts/thread-count-chart.js");
|
1951
|
+
/* harmony import */ var _components_charts_memory_chart__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../components/charts/memory-chart */ "./src/components/charts/memory-chart.js");
|
1952
|
+
/* harmony import */ var _components_charts_network_realtime_chart__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../components/charts/network-realtime-chart */ "./src/components/charts/network-realtime-chart.js");
|
1953
|
+
/* harmony import */ var _components_charts_network_24h_chart__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../components/charts/network-24h-chart */ "./src/components/charts/network-24h-chart.js");
|
1954
|
+
/* harmony import */ var _components_charts_system_workload_chart__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../components/charts/system-workload-chart */ "./src/components/charts/system-workload-chart.js");
|
1955
|
+
/* harmony import */ var _components_charts_system_queue_chart__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../components/charts/system-queue-chart */ "./src/components/charts/system-queue-chart.js");
|
1956
|
+
|
1957
|
+
|
1958
|
+
|
1959
|
+
|
1960
|
+
|
1961
|
+
|
1962
|
+
|
1963
|
+
|
1964
|
+
|
1965
|
+
|
1966
|
+
|
1967
|
+
class Dashboard extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseModule"]
|
1968
|
+
{
|
1969
|
+
constructor()
|
1970
|
+
{
|
1971
|
+
super('dashboard');
|
1972
|
+
|
1973
|
+
// Outgoing requests
|
1974
|
+
this.REQ_INIT = 'init';
|
1975
|
+
this.REQ_GET_DATA = 'getData';
|
1976
|
+
this.REQ_DUMP_THREADS = 'getThDump';
|
1977
|
+
|
1978
|
+
// Incoming responses
|
1979
|
+
this.RESP_INIT = 'init';
|
1980
|
+
this.RESP_DATA = 'data';
|
1981
|
+
this.RESP_THREAD_DUMP = 'thDump';
|
1982
|
+
|
1983
|
+
this._tcpOutThreads = 0;
|
1984
|
+
this._tcpOutLoad = 0;
|
1985
|
+
this._udpOutThreads = 0;
|
1986
|
+
this._udpOutLoad = 0;
|
1036
1987
|
}
|
1037
1988
|
|
1038
1989
|
//------------------------------------
|
1039
|
-
//
|
1990
|
+
// COMMON MODULE INTERFACE METHODS
|
1991
|
+
// This members are used by the main controller
|
1992
|
+
// to communicate with the module's controller.
|
1040
1993
|
//------------------------------------
|
1041
1994
|
|
1042
|
-
|
1995
|
+
initialize(idData, shellController)
|
1043
1996
|
{
|
1044
|
-
|
1997
|
+
// Call super method
|
1998
|
+
super.initialize(idData, shellController);
|
1999
|
+
|
2000
|
+
// Initialize scrolling tabs
|
2001
|
+
$('#dsh-tabNavigator > #tabs').scrollingTabs({
|
2002
|
+
bootstrapVersion: 4,
|
2003
|
+
scrollToTabEdge: true,
|
2004
|
+
enableSwiping: true,
|
2005
|
+
disableScrollArrowsOnFullyScrolled: true,
|
2006
|
+
cssClassLeftArrow: 'fa fa-chevron-left',
|
2007
|
+
cssClassRightArrow: 'fa fa-chevron-right'
|
2008
|
+
});
|
2009
|
+
|
2010
|
+
// Initialize interval dropdown
|
2011
|
+
this._intervalDropDown = $('#dsh-intervalDD').kendoDropDownList({
|
2012
|
+
valueTemplate: '<span class="text-muted pr-1">Interval:</span><span>#:data.text#</span>',
|
2013
|
+
change: $.proxy(this._onUpdateIntervalChange, this)
|
2014
|
+
}).data('kendoDropDownList');
|
2015
|
+
|
2016
|
+
// Initialize threads grid
|
2017
|
+
this._threadsGrid = $('#dsh-threadsGrid').kendoGrid({
|
2018
|
+
dataSource: this._getThreadsGridDataSource(),
|
2019
|
+
scrollable: true,
|
2020
|
+
sortable: true,
|
2021
|
+
filterable: false,
|
2022
|
+
resizable: true,
|
2023
|
+
selectable: false,
|
2024
|
+
columns: [
|
2025
|
+
{
|
2026
|
+
field: 'id',
|
2027
|
+
title: 'Id',
|
2028
|
+
width: 60
|
2029
|
+
},
|
2030
|
+
{
|
2031
|
+
field: 'name',
|
2032
|
+
title: 'Name',
|
2033
|
+
width: '65%'
|
2034
|
+
},
|
2035
|
+
{
|
2036
|
+
field: 'cpuTime',
|
2037
|
+
title: 'CPU Time',
|
2038
|
+
format: '{0}%',
|
2039
|
+
width: '35%'
|
2040
|
+
},
|
2041
|
+
],
|
2042
|
+
noRecords: {
|
2043
|
+
template: 'No threads.'
|
2044
|
+
},
|
2045
|
+
height: 'calc(240px - .75rem + 1rem)'
|
2046
|
+
}).data('kendoGrid');
|
2047
|
+
|
2048
|
+
// Add click listener to threads dump button
|
2049
|
+
$('#dsh-dumpThreadsBt').on('click', $.proxy(this._onDumpThreadsClick, this));
|
2050
|
+
|
2051
|
+
// Configure thread dump panel
|
2052
|
+
$('#dsh-threadDumpModal').modal({
|
2053
|
+
backdrop: 'static',
|
2054
|
+
keyboard: false,
|
2055
|
+
show: false,
|
2056
|
+
});
|
2057
|
+
|
2058
|
+
// Add listener for threads dump panel hide
|
2059
|
+
$('#dsh-threadDumpModal').on('hidden.bs.modal', $.proxy(this._onThreadDumpModalHidden, this));
|
2060
|
+
|
2061
|
+
// Add click listener to threads dump copy button
|
2062
|
+
$('#dsh-copyThreadDumpBt').on('click', $.proxy(this._onCopyThreadDumpClick, this));
|
2063
|
+
|
2064
|
+
// Initialize time range slider
|
2065
|
+
this._timeSlider = $('#dsh-timeSlider').kendoRangeSlider({
|
2066
|
+
min: -24,
|
2067
|
+
max: 0,
|
2068
|
+
smallStep: 1,
|
2069
|
+
largeStep: 0,
|
2070
|
+
change: $.proxy(this._onTimeRangeChange, this),
|
2071
|
+
tooltip: {
|
2072
|
+
template: Object(_components_charts_chart_utils__WEBPACK_IMPORTED_MODULE_2__["getTimeRangeTooltipTemplate"])()
|
2073
|
+
},
|
2074
|
+
leftDragHandleTitle: 'Drag',
|
2075
|
+
rightDragHandleTitle: 'Drag',
|
2076
|
+
}).data('kendoRangeSlider');
|
2077
|
+
|
2078
|
+
// Add click listener to reset charts button
|
2079
|
+
$('#dsh-resetBt').on('click', $.proxy(this._onResetChartsClick, this));
|
2080
|
+
|
2081
|
+
// Add click listener to play & pause chart update buttons
|
2082
|
+
$('#dsh-pauseBt').on('click', $.proxy(this._onPauseUpdateClick, this));
|
2083
|
+
$('#dsh-playBt').on('click', $.proxy(this._onPlayUpdateClick, this));
|
2084
|
+
|
2085
|
+
// Set reference to charts
|
2086
|
+
this._cpuUsageChart = document.getElementById('dsh-cpuUsageChart');
|
2087
|
+
this._threadCountChart = document.getElementById('dsh-threadCountChart');
|
2088
|
+
this._memoryChart = document.getElementById('dsh-memoryChart');
|
2089
|
+
this._networkRTChart = document.getElementById('dsh-networkRTChart');
|
2090
|
+
this._network24hChart = document.getElementById('dsh-network24hChart');
|
2091
|
+
this._sysWorkloadChart = document.getElementById('dsh-systemWorkloadChart');
|
2092
|
+
this._outTcpMsgQueueChart = document.getElementById('dsh-outgoingTcpMessagesQueueChart');
|
2093
|
+
this._outUdpMsgQueueChart = document.getElementById('dsh-outgoingUdpMessagesQueueChart');
|
2094
|
+
this._sysQueueChart = document.getElementById('dsh-systemQueueChart');
|
2095
|
+
this._extQueueChart = document.getElementById('dsh-extensionQueueChart');
|
2096
|
+
|
2097
|
+
// Set colors in chart legends
|
2098
|
+
$('#dsh-systemLoadColor').css('color', this._cpuUsageChart.systemColor);
|
2099
|
+
$('#dsh-processLoadColor').css('color', this._cpuUsageChart.processColor);
|
2100
|
+
$('#dsh-allocMemColor').css('color', this._memoryChart.allocatedColor);
|
2101
|
+
$('#dsh-usedMemColor').css('color', this._memoryChart.usedColor);
|
2102
|
+
$('#dsh-incomingNetColor').css('color', this._networkRTChart.incomingColor);
|
2103
|
+
$('#dsh-outgoingNetColor').css('color', this._networkRTChart.outgoingColor);
|
2104
|
+
|
2105
|
+
// Reset time range on 24h network chart
|
2106
|
+
this._onTimeRangeChange();
|
2107
|
+
|
2108
|
+
// Add listener to redraw all charts on main tab change
|
2109
|
+
// (to work around an issue with the chart resizing to default width when pane is hidden)
|
2110
|
+
$('a[data-toggle="tab"]').on('shown.bs.tab', $.proxy(this._onWindowResize, this));
|
2111
|
+
|
2112
|
+
// Add listener to redraw network charts on network tab change
|
2113
|
+
// (to work around an issue with the chart resizing to default width when pane is hidden)
|
2114
|
+
$('#dsh-networkPills a[data-toggle="pill"]').on('shown.bs.tab', $.proxy(this._redrawNetworkCharts, this));
|
2115
|
+
|
2116
|
+
// Add listener to redraw outgoing messages queue charts on tab change
|
2117
|
+
// (to work around an issue with the chart resizing to default width when pane is hidden)
|
2118
|
+
$('#dsh-msgQueuePills a[data-toggle="pill"]').on('shown.bs.tab', $.proxy(this._redrawOutMsgCharts, this));
|
2119
|
+
|
2120
|
+
// Add listener to redraw all charts in case of window resize
|
2121
|
+
$(window).on('resize', $.proxy(this._onWindowResize, this));
|
2122
|
+
this._onWindowResize(); // Also do it immediately
|
2123
|
+
|
2124
|
+
// Add listener to show help tooltips in queues status tab
|
2125
|
+
$('#dsh-queues').kendoTooltip({
|
2126
|
+
filter: 'i[title].help',
|
2127
|
+
position: 'right',
|
2128
|
+
width: '250px',
|
2129
|
+
content: function(e) {
|
2130
|
+
return `<div class="help-tooltip">${e.target.data('title')}</div>`;
|
2131
|
+
}
|
2132
|
+
});
|
2133
|
+
|
2134
|
+
// Add listener to regenerate link to open web server external manager console
|
2135
|
+
$('#dsh-useHttpsCheck').on('change', $.proxy(this._onUseHttpsForWsManagerChange, this));
|
2136
|
+
|
2137
|
+
// Send initialization request
|
2138
|
+
this.sendExtensionRequest(this.REQ_INIT);
|
1045
2139
|
}
|
1046
2140
|
|
1047
|
-
|
2141
|
+
destroy()
|
1048
2142
|
{
|
1049
|
-
|
2143
|
+
// Call super method
|
2144
|
+
super.destroy();
|
2145
|
+
|
2146
|
+
// Destroy scrolling tabs
|
2147
|
+
$('#dsh-tabNavigator #tabs').scrollingTabs('destroy');
|
2148
|
+
|
2149
|
+
// Remove other listeners
|
2150
|
+
$('#dsh-resetBt').off('click');
|
2151
|
+
$('#dsh-pauseBt').off('click');
|
2152
|
+
$('#dsh-playBt').off('click');
|
2153
|
+
$('#dsh-dumpThreadsBt').off('click');
|
2154
|
+
$('a[data-toggle="tab"]').off('shown.bs.tab');
|
2155
|
+
$('a[data-toggle="pill"]').off('shown.bs.tab');
|
2156
|
+
$(window).off('resize');
|
2157
|
+
$('#dsh-useHttpsCheck').off('change');
|
2158
|
+
|
2159
|
+
// Remove thread dump panel listener
|
2160
|
+
$('#dsh-threadDumpModal').off('hidden.bs.modal');
|
2161
|
+
|
2162
|
+
// Clear request scheduling
|
2163
|
+
clearTimeout(this._requestTimer);
|
1050
2164
|
}
|
1051
2165
|
|
1052
|
-
|
2166
|
+
onExtensionCommand(command, data)
|
1053
2167
|
{
|
1054
|
-
|
2168
|
+
// Initialization data received
|
2169
|
+
if (command == this.RESP_INIT)
|
2170
|
+
{
|
2171
|
+
// Server sends flags indicating if web server's internal manager is accessible and how
|
2172
|
+
this._wsManagerConfig = {
|
2173
|
+
hasAccess: data.getBool('hasWsManager'),
|
2174
|
+
httpEnabled: data.getBool('httpEnabled'),
|
2175
|
+
httpsEnabled: data.getBool('httpsEnabled'),
|
2176
|
+
httpPort: data.getInt('httpPort'),
|
2177
|
+
httpsPort: data.getInt('httpsPort'),
|
2178
|
+
}
|
2179
|
+
|
2180
|
+
// Enable access to web server manager console
|
2181
|
+
this._enableWebServerManagerAccess();
|
2182
|
+
|
2183
|
+
// Request data to server
|
2184
|
+
this._requestData(true);
|
2185
|
+
}
|
2186
|
+
|
2187
|
+
// Data received
|
2188
|
+
else if (command == this.RESP_DATA)
|
2189
|
+
{
|
2190
|
+
// CPU LOAD CHART
|
2191
|
+
|
2192
|
+
this._cpuUsageChart.addEntry(data.getDouble('pCpu'), data.getDouble('sCpu'));
|
2193
|
+
$('#dsh-systemLoadLabel').text(data.getDouble('sCpu'));
|
2194
|
+
$('#dsh-processLoadLabel').text(data.getDouble('pCpu'));
|
2195
|
+
|
2196
|
+
// As system cpu load is not always available (for example on MacOS X), let's hide it in case it isn't
|
2197
|
+
if (data.getDouble('sCpu') < 0)
|
2198
|
+
$('#dsh-systemLoadLegend').hide();
|
2199
|
+
|
2200
|
+
// THREADS COUNT CHART
|
2201
|
+
|
2202
|
+
const threadCount = data.getSFSArray('thList').size();
|
2203
|
+
this._threadCountChart.addEntry(threadCount);
|
2204
|
+
$('#dsh-threadsCountLabel').text(threadCount);
|
2205
|
+
|
2206
|
+
// MEMORY USAGE CHART
|
2207
|
+
// NOTE: memory data is sent as Bytes by the server
|
2208
|
+
|
2209
|
+
const freeMem = data.getLong('freeMem');
|
2210
|
+
const maxMem = data.getLong('maxMem');
|
2211
|
+
const totalMem = data.getLong('totalMem');
|
2212
|
+
const usedMem = totalMem - freeMem;
|
2213
|
+
|
2214
|
+
this._memoryChart.addEntry(totalMem, usedMem);
|
2215
|
+
$('#dsh-maxMemoryLabel').text(this._getMemObject(maxMem).label);
|
2216
|
+
$('#dsh-freeMemoryLabel').text(this._getMemObject(freeMem).label);
|
2217
|
+
|
2218
|
+
// THREADS LIST
|
2219
|
+
|
2220
|
+
const totalThreadCpuTime = data.getLong('thCpu');
|
2221
|
+
let threads = [];
|
2222
|
+
|
2223
|
+
for (let i = 0; i < data.getSFSArray('thList').size(); i++)
|
2224
|
+
{
|
2225
|
+
let threadData = data.getSFSArray('thList').getSFSObject(i);
|
2226
|
+
|
2227
|
+
threads.push({
|
2228
|
+
id: threadData.getLong('id'),
|
2229
|
+
name: threadData.getUtfString('name'),
|
2230
|
+
cpuTime: Math.round(threadData.getLong('cpu') / totalThreadCpuTime * 1000) / 10
|
2231
|
+
});
|
2232
|
+
}
|
2233
|
+
|
2234
|
+
// Substitute grid's data source, retaining current sorting
|
2235
|
+
let currSort = this._threadsGrid.dataSource.sort();
|
2236
|
+
this._threadsGrid.setDataSource(this._getThreadsGridDataSource(threads, currSort));
|
2237
|
+
|
2238
|
+
// NETWORK TRAFFIC
|
2239
|
+
// NOTE: network traffic data is sent as KBytes by the server
|
2240
|
+
|
2241
|
+
if (data.containsKey('ntOutHistory'))
|
2242
|
+
{
|
2243
|
+
const outgoingData = data.getLongArray('ntOutHistory');
|
2244
|
+
const incomingData = data.getLongArray('ntInHistory');
|
2245
|
+
const samplingRateMins = data.getInt('ntRate');
|
2246
|
+
const shiftSeconds = data.getInt('ntShift');
|
2247
|
+
|
2248
|
+
this._network24hChart.addHistoryEntries(outgoingData, incomingData, samplingRateMins * 60, shiftSeconds);
|
2249
|
+
}
|
2250
|
+
|
2251
|
+
// Add current values
|
2252
|
+
this._network24hChart.addEntry(data.getLong('ntOut'), data.getLong('ntIn'));
|
2253
|
+
this._networkRTChart.addEntry(data.getLong('ntOut'), data.getLong('ntIn'));
|
2254
|
+
|
2255
|
+
// TRAFFIC DETAILS
|
2256
|
+
|
2257
|
+
// Sessions
|
2258
|
+
$('#dsh-detSessionsCurrent').text('Current: ' + (data.getInt('sSocket') + data.getInt('sHttp')));
|
2259
|
+
$('#dsh-detSessionsMax').text('Max: ' + data.getInt('ccsMax'));
|
2260
|
+
$('#dsh-detSessionsSocket').text('Socket: ' + data.getInt('sSocket'));
|
2261
|
+
$('#dsh-detSessionsHttp').text('Http: ' + data.getInt('sHttp'));
|
2262
|
+
|
2263
|
+
// Users
|
2264
|
+
$('#dsh-detUsersCurrent').text('Current: ' + (data.getInt('uSocket') + data.getInt('uHttp') + data.getInt('uNpc')));
|
2265
|
+
$('#dsh-detUsersMax').text('Max: ' + data.getInt('ccuMax'));
|
2266
|
+
$('#dsh-detUsersSocket').text('Socket: ' + data.getInt('uSocket'));
|
2267
|
+
$('#dsh-detUsersHttp').text('Http: ' + data.getInt('uHttp'));
|
2268
|
+
$('#dsh-detUsersNpc').text('Npc: ' + data.getInt('uNpc'));
|
2269
|
+
|
2270
|
+
// Rooms
|
2271
|
+
$('#dsh-detRooms').text(data.getInt('rTotal'));
|
2272
|
+
$('#dsh-detRoomsRegular').text('Regular: ' + (data.getInt('rTotal') - data.getInt('rGame')));
|
2273
|
+
$('#dsh-detRoomsGame').text('Game: ' + data.getInt('rGame'));
|
2274
|
+
|
2275
|
+
// Total data transfer
|
2276
|
+
$('#dsh-detDataTransferOut').text('Out: ' + Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_1__["kBytesToSize"])(data.getLong('ntOut')));
|
2277
|
+
$('#dsh-detDataTransferIn').text('In: ' + Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_1__["kBytesToSize"])(data.getLong('ntIn')));
|
2278
|
+
|
2279
|
+
// Current data transfer rate
|
2280
|
+
let obj = this._networkRTChart.getLastEntry();
|
2281
|
+
|
2282
|
+
if (obj == null)
|
2283
|
+
obj = {outgoing: 0, incoming: 0};
|
2284
|
+
|
2285
|
+
$('#dsh-detTransferRateOut').text('Out: ' + Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_1__["kBytesToSize"])(obj.outgoing, 2, 'KB', '/s'));
|
2286
|
+
$('#dsh-detTransferRateIn').text('In: ' + Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_1__["kBytesToSize"])(obj.incoming, 2, 'KB', '/s'));
|
2287
|
+
|
2288
|
+
// Average data transfer rate over whole uptime
|
2289
|
+
if (this._uptimeSecs > 0)
|
2290
|
+
{
|
2291
|
+
const avgOut = Math.round(data.getLong('ntOut') / this._uptimeSecs * 100) / 100;
|
2292
|
+
const avgIn = Math.round(data.getLong('ntIn') / this._uptimeSecs * 100) / 100;
|
2293
|
+
|
2294
|
+
$('#dsh-detAvgTransferRateOut').text('Out: ' + Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_1__["kBytesToSize"])(avgOut, 2, 'KB', '/s'));
|
2295
|
+
$('#dsh-detAvgTransferRateIn').text('In: ' + Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_1__["kBytesToSize"])(avgIn, 2, 'KB', '/s'));
|
2296
|
+
}
|
2297
|
+
|
2298
|
+
// Dropped packets
|
2299
|
+
const totalPacketsOut = data.getLong('pktOut');
|
2300
|
+
|
2301
|
+
const totalDroppedTcpPacketsOut = data.getLong('pktOutDrop');
|
2302
|
+
$('#dsh-detDroppedTcpPacketsOut').text(`Out TCP: ${totalDroppedTcpPacketsOut} (${Math.round(totalDroppedTcpPacketsOut / totalPacketsOut * 100)}%)`);
|
2303
|
+
|
2304
|
+
const totalDroppedUdpPacketsOut = data.getLong('pktOutUdpDrop');
|
2305
|
+
$('#dsh-detDroppedUdpPacketsOut').text(`Out UDP: ${totalDroppedUdpPacketsOut} (${Math.round(totalDroppedUdpPacketsOut / totalPacketsOut * 100)}%)`);
|
2306
|
+
|
2307
|
+
const totalPacketsIn = data.getLong('pktIn');
|
2308
|
+
const totalDroppedPacketsIn = data.getLong('pktInDrop');
|
2309
|
+
$('#dsh-detDroppedPacketsIn').text(`In: ${totalDroppedPacketsIn} (${Math.round(totalDroppedPacketsIn / totalPacketsIn * 100)}%)`);
|
2310
|
+
|
2311
|
+
// SYSTEM STATUS
|
2312
|
+
|
2313
|
+
// Outgoing TCP messages queue
|
2314
|
+
const outMsgQueue = data.getInt('outMsgQueue');
|
2315
|
+
const outMsgQueueMax = data.getInt('outMsgQueueMax');
|
2316
|
+
this._outTcpMsgQueueChart.addEntry(outMsgQueue, outMsgQueueMax);
|
2317
|
+
this._tcpOutThreads = data.getInt('outMsgTh');
|
2318
|
+
this._tcpOutLoad = this._outTcpMsgQueueChart.load;
|
2319
|
+
|
2320
|
+
// Outgoing UDP messages queue
|
2321
|
+
const outUdpMsgQueue = data.getInt('outUdpMsgQueue');
|
2322
|
+
const outUdpMsgQueueMax = data.getInt('outUdpMsgQueueMax');
|
2323
|
+
this._outUdpMsgQueueChart.addEntry(outUdpMsgQueue, outUdpMsgQueueMax);
|
2324
|
+
this._udpOutThreads = data.getInt('outUdpMsgTh');
|
2325
|
+
this._udpOutLoad = this._outUdpMsgQueueChart.load;
|
2326
|
+
|
2327
|
+
this._updateOutMessagesQueueStatus();
|
2328
|
+
|
2329
|
+
// System Controller requests queue
|
2330
|
+
const sysCtrlQueue = data.getInt('sysCtrlQueue');
|
2331
|
+
const sysCtrlQueueMax = data.getInt('sysCtrlQueueMax');
|
2332
|
+
this._sysQueueChart.addEntry(sysCtrlQueue, sysCtrlQueueMax);
|
2333
|
+
$('#dsh-systemQueueThreads').text(this._getQueueThreadsLabel(data.getInt('sysCtrlTh')));
|
2334
|
+
$('#dsh-systemQueueLoad').text(this._getQueueLoadLabel(this._sysQueueChart.load));
|
2335
|
+
|
2336
|
+
// Extension Controller requests queue
|
2337
|
+
const extCtrlQueue = data.getInt('extCtrlQueue');
|
2338
|
+
const extCtrlQueueMax = data.getInt('extCtrlQueueMax');
|
2339
|
+
this._extQueueChart.addEntry(extCtrlQueue, extCtrlQueueMax);
|
2340
|
+
$('#dsh-extensionQueueThreads').text(this._getQueueThreadsLabel(data.getInt('extCtrlTh')));
|
2341
|
+
$('#dsh-extensionQueueLoad').text(this._getQueueLoadLabel(this._sysQueueChart.load));
|
2342
|
+
|
2343
|
+
// Evaluate overall system workload
|
2344
|
+
let sysWorkload = Math.round((outMsgQueue / outMsgQueueMax +
|
2345
|
+
outUdpMsgQueue / outUdpMsgQueueMax +
|
2346
|
+
sysCtrlQueue / sysCtrlQueueMax +
|
2347
|
+
extCtrlQueue / extCtrlQueueMax) * 100 / 4);
|
2348
|
+
if (sysWorkload > 100)
|
2349
|
+
sysWorkload = 100;
|
2350
|
+
|
2351
|
+
this._sysWorkloadChart.addEntry(sysWorkload);
|
2352
|
+
}
|
2353
|
+
|
2354
|
+
// Thread dump received
|
2355
|
+
else if (command == this.RESP_THREAD_DUMP)
|
2356
|
+
{
|
2357
|
+
// Enable button
|
2358
|
+
$('#dsh-dumpThreadsBt').attr('disabled', false);
|
2359
|
+
|
2360
|
+
// Set result
|
2361
|
+
$('#dsh-threadDumpResult').text(data.getText('dump'));
|
2362
|
+
|
2363
|
+
// Display modal
|
2364
|
+
$('#dsh-threadDumpModal').modal('show');
|
2365
|
+
}
|
1055
2366
|
}
|
1056
2367
|
|
1057
|
-
|
2368
|
+
onUptimeUpdated(values)
|
1058
2369
|
{
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
2370
|
+
this._uptimeSecs = values[3];
|
2371
|
+
this._uptimeSecs += (values[2] * 60);
|
2372
|
+
this._uptimeSecs += (values[1] * 60 * 60);
|
2373
|
+
this._uptimeSecs += (values[0] * 24 * 60 * 60);
|
2374
|
+
|
2375
|
+
$('#dsh-uptimeDays').text( (values[0] <= 9 ? '00' : (values[0] <= 99 ? '0' : '')) + values[0] );
|
2376
|
+
$('#dsh-uptimeHours').text( (values[1] <= 9 ? '0' : '') + values[1] );
|
2377
|
+
$('#dsh-uptimeMinutes').text( (values[2] <= 9 ? '0' : '') + values[2] );
|
2378
|
+
$('#dsh-uptimeSeconds').text( (values[3] <= 9 ? '0' : '') + values[3] );
|
1062
2379
|
}
|
1063
2380
|
|
1064
|
-
|
2381
|
+
//---------------------------------
|
2382
|
+
// UI EVENT LISTENERS
|
2383
|
+
//---------------------------------
|
2384
|
+
|
2385
|
+
_onUpdateIntervalChange()
|
1065
2386
|
{
|
1066
|
-
//
|
1067
|
-
|
1068
|
-
|
2387
|
+
// Request data to server
|
2388
|
+
this._requestData();
|
2389
|
+
}
|
1069
2390
|
|
1070
|
-
|
1071
|
-
|
2391
|
+
_onPauseUpdateClick()
|
2392
|
+
{
|
2393
|
+
this._setChartUpdatePaused(true);
|
1072
2394
|
|
1073
|
-
//
|
1074
|
-
|
2395
|
+
// Hide pause button and show play button
|
2396
|
+
$('#dsh-pauseBt').addClass('hidden');
|
2397
|
+
$('#dsh-playBt').removeClass('hidden');
|
2398
|
+
}
|
1075
2399
|
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
1079
|
-
params.putInt('numEntries', Number(this._logLinesDD.value()));
|
2400
|
+
_onPlayUpdateClick()
|
2401
|
+
{
|
2402
|
+
this._setChartUpdatePaused(false);
|
1080
2403
|
|
1081
|
-
|
2404
|
+
// Hide play button and show pause button
|
2405
|
+
$('#dsh-pauseBt').removeClass('hidden');
|
2406
|
+
$('#dsh-playBt').addClass('hidden');
|
1082
2407
|
}
|
1083
2408
|
|
1084
|
-
|
2409
|
+
_onResetChartsClick()
|
1085
2410
|
{
|
1086
|
-
|
1087
|
-
this.
|
1088
|
-
|
2411
|
+
// Reactivate realtime charts update
|
2412
|
+
this._onPlayUpdateClick();
|
2413
|
+
|
2414
|
+
// Reset realtime charts
|
2415
|
+
this._cpuUsageChart.reset();
|
2416
|
+
this._threadCountChart.reset();
|
2417
|
+
this._memoryChart.reset();
|
2418
|
+
this._networkRTChart.reset();
|
2419
|
+
this._sysWorkloadChart.reset();
|
2420
|
+
this._outTcpMsgQueueChart.reset();
|
2421
|
+
this._outUdpMsgQueueChart.reset();
|
2422
|
+
this._sysQueueChart.reset();
|
2423
|
+
this._extQueueChart.reset();
|
1089
2424
|
}
|
1090
2425
|
|
1091
|
-
|
2426
|
+
_redrawNetworkCharts()
|
1092
2427
|
{
|
1093
|
-
|
1094
|
-
|
2428
|
+
// Redraw charts
|
2429
|
+
this._networkRTChart.redraw();
|
2430
|
+
this._network24hChart.redraw();
|
1095
2431
|
|
1096
|
-
|
2432
|
+
// Redraw time range slider
|
2433
|
+
this._timeSlider.resize();
|
1097
2434
|
}
|
1098
2435
|
|
1099
|
-
|
2436
|
+
_redrawOutMsgCharts()
|
1100
2437
|
{
|
1101
|
-
//
|
1102
|
-
|
2438
|
+
// Redraw charts
|
2439
|
+
this._outTcpMsgQueueChart.redraw();
|
2440
|
+
this._outUdpMsgQueueChart.redraw();
|
1103
2441
|
|
1104
|
-
|
1105
|
-
|
2442
|
+
this._updateOutMessagesQueueStatus();
|
2443
|
+
}
|
1106
2444
|
|
1107
|
-
|
1108
|
-
|
2445
|
+
_onWindowResize()
|
2446
|
+
{
|
2447
|
+
// Redraw all global charts
|
2448
|
+
this._cpuUsageChart.redraw();
|
2449
|
+
this._threadCountChart.redraw();
|
2450
|
+
this._memoryChart.redraw();
|
2451
|
+
this._redrawNetworkCharts();
|
2452
|
+
|
2453
|
+
// Redraw all queue charts
|
2454
|
+
this._sysWorkloadChart.redraw();
|
2455
|
+
this._sysQueueChart.redraw();
|
2456
|
+
this._extQueueChart.redraw();
|
2457
|
+
this._redrawOutMsgCharts();
|
2458
|
+
}
|
1109
2459
|
|
1110
|
-
|
1111
|
-
|
2460
|
+
_onTimeRangeChange()
|
2461
|
+
{
|
2462
|
+
let values = this._timeSlider.value();
|
1112
2463
|
|
1113
|
-
|
1114
|
-
|
2464
|
+
if (values[0] == values[1])
|
2465
|
+
{
|
2466
|
+
if (values[1] == -24)
|
2467
|
+
values[1] = -23;
|
2468
|
+
|
2469
|
+
values[0] = values[1] - 1;
|
2470
|
+
|
2471
|
+
// Reset the time range slider value (we need to use setTimeout
|
2472
|
+
// bacause doing it in the change event listener doesn't redraw the slider)
|
2473
|
+
setTimeout($.proxy( function(values) { this._timeSlider.value(values); }, this), 10, values);
|
2474
|
+
}
|
2475
|
+
|
2476
|
+
this._network24hChart.range = values;
|
1115
2477
|
}
|
1116
2478
|
|
1117
|
-
|
2479
|
+
_onUseHttpsForWsManagerChange()
|
1118
2480
|
{
|
1119
|
-
|
2481
|
+
const wsMan = this._wsManagerConfig;
|
1120
2482
|
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
});
|
2483
|
+
let url = ($('#dsh-useHttpsCheck').prop('checked') ? 'https' : 'http') + '://';
|
2484
|
+
url += this.smartFox.config.host;
|
2485
|
+
url += ':' + ($('#dsh-useHttpsCheck').prop('checked') ? wsMan.httpsPort : wsMan.httpPort);
|
2486
|
+
url += '/manager/status';
|
1126
2487
|
|
1127
|
-
|
1128
|
-
|
1129
|
-
filters.push({
|
1130
|
-
field: 'clazz', operator: 'eq', value: this._classFilterDD.value()
|
1131
|
-
});
|
2488
|
+
$('#dsh-toWsManagerBt').attr('href', url);
|
2489
|
+
}
|
1132
2490
|
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
-
|
1137
|
-
});
|
2491
|
+
_onDumpThreadsClick()
|
2492
|
+
{
|
2493
|
+
// Disable button
|
2494
|
+
$('#dsh-dumpThreadsBt').attr('disabled', true);
|
1138
2495
|
|
1139
|
-
//
|
1140
|
-
|
2496
|
+
// Send request to extension
|
2497
|
+
this.sendExtensionRequest(this.REQ_DUMP_THREADS);
|
1141
2498
|
}
|
1142
2499
|
|
1143
|
-
|
2500
|
+
_onCopyThreadDumpClick()
|
2501
|
+
{
|
2502
|
+
$('#dsh-threadDumpResult').attr('contenteditable', true);
|
2503
|
+
$('#dsh-threadDumpResult').attr('spellcheck', false);
|
2504
|
+
$('#dsh-threadDumpResult').focus();
|
2505
|
+
document.execCommand('selectAll');
|
2506
|
+
document.execCommand('copy');
|
2507
|
+
window.getSelection().removeAllRanges();
|
2508
|
+
$('#dsh-threadDumpResult').blur();
|
2509
|
+
$('#dsh-threadDumpResult').attr('contenteditable', false);
|
2510
|
+
}
|
2511
|
+
|
2512
|
+
_onThreadDumpModalHidden()
|
2513
|
+
{
|
2514
|
+
// Clear modal content
|
2515
|
+
$('#dsh-threadDumpResult').text('');
|
2516
|
+
}
|
2517
|
+
|
2518
|
+
//------------------------------------
|
2519
|
+
// PRIVATE METHODS
|
2520
|
+
//------------------------------------
|
2521
|
+
|
2522
|
+
_enableWebServerManagerAccess()
|
1144
2523
|
{
|
1145
|
-
|
2524
|
+
const wsMan = this._wsManagerConfig;
|
2525
|
+
|
2526
|
+
if (wsMan.hasAccess && (wsMan.httpEnabled || wsMan.httpsEnabled))
|
1146
2527
|
{
|
1147
|
-
//
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
2528
|
+
// Hide alert
|
2529
|
+
$('#dsh-wsManagerAlert').hide();
|
2530
|
+
|
2531
|
+
// Enable button
|
2532
|
+
$('#dsh-toWsManagerBt').attr('disabled', false);
|
2533
|
+
|
2534
|
+
// Set checkbox
|
2535
|
+
$('#dsh-useHttpsCheck').prop('checked', wsMan.httpsEnabled);
|
2536
|
+
$('#dsh-useHttpsCheck').attr('disabled', !wsMan.httpEnabled || !wsMan.httpsEnabled);
|
2537
|
+
|
2538
|
+
// Generate link
|
2539
|
+
this._onUseHttpsForWsManagerChange();
|
1159
2540
|
}
|
1160
2541
|
else
|
1161
2542
|
{
|
1162
|
-
//
|
1163
|
-
$('
|
2543
|
+
// Show alert
|
2544
|
+
$('#dsh-wsManagerAlert').show();
|
1164
2545
|
|
1165
|
-
|
1166
|
-
|
2546
|
+
if (!wsMan.hasAccess)
|
2547
|
+
$('#dsh-wsManagerAlert').html('Access to Tomcat Manager console requires at least one user to be defined in <em>Web Server</em> tab of <strong>Server Configurator</strong> module.');
|
2548
|
+
else
|
2549
|
+
$('#dsh-wsManagerAlert').html('Access to Tomcat Manager console requires either HTTP or HTTPS to be enabled in <em>Web Server</em> tab of <strong>Server Configurator</strong> module.');
|
1167
2550
|
|
1168
|
-
|
1169
|
-
|
2551
|
+
// Disable button
|
2552
|
+
$('#dsh-toWsManagerBt').attr('disabled', true);
|
1170
2553
|
|
1171
|
-
|
1172
|
-
|
2554
|
+
// Disable checkbox
|
2555
|
+
$('#dsh-useHttpsCheck').attr('checked', wsMan.httpsEnabled);
|
2556
|
+
$('#dsh-useHttpsCheck').attr('disabled', true);
|
1173
2557
|
}
|
1174
2558
|
}
|
1175
2559
|
|
1176
|
-
|
2560
|
+
/**
|
2561
|
+
* Build the polling request to be sent to the server.
|
2562
|
+
*/
|
2563
|
+
_requestData(getHistory = false)
|
1177
2564
|
{
|
1178
|
-
|
1179
|
-
|
2565
|
+
// Clear previous request scheduling
|
2566
|
+
clearTimeout(this._requestTimer);
|
2567
|
+
|
2568
|
+
// Check if connection is still available
|
2569
|
+
if (this.smartFox.isConnected)
|
2570
|
+
{
|
2571
|
+
// Build request parameters
|
2572
|
+
let params = new SFS2X.SFSObject();
|
2573
|
+
|
2574
|
+
if (getHistory)
|
2575
|
+
params.putBool('history', true);
|
2576
|
+
|
2577
|
+
// Send request to extension
|
2578
|
+
this.sendExtensionRequest(this.REQ_GET_DATA, params);
|
2579
|
+
|
2580
|
+
// Schedule next request
|
2581
|
+
this._requestTimer = setTimeout($.proxy(this._requestData, this), Number(this._intervalDropDown.value()) * 1000);
|
2582
|
+
}
|
1180
2583
|
}
|
1181
2584
|
|
1182
|
-
|
2585
|
+
_getMemObject(bytes)
|
1183
2586
|
{
|
1184
|
-
|
1185
|
-
|
1186
|
-
|
1187
|
-
|
1188
|
-
|
2587
|
+
return {
|
2588
|
+
data: bytes,
|
2589
|
+
label: Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_1__["bytesToSize"])(bytes)
|
2590
|
+
};
|
2591
|
+
}
|
2592
|
+
|
2593
|
+
_setChartUpdatePaused(paused)
|
2594
|
+
{
|
2595
|
+
// Pause/reactivate realtime charts
|
2596
|
+
this._cpuUsageChart.paused = paused;
|
2597
|
+
this._threadCountChart.paused = paused;
|
2598
|
+
this._memoryChart.paused = paused;
|
2599
|
+
this._networkRTChart.paused = paused;
|
2600
|
+
this._sysWorkloadChart.paused = paused;
|
2601
|
+
this._outTcpMsgQueueChart.paused = paused;
|
2602
|
+
this._sysQueueChart.paused = paused;
|
2603
|
+
this._extQueueChart.paused = paused;
|
2604
|
+
}
|
1189
2605
|
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
2606
|
+
_getThreadsGridDataSource(items, sort)
|
2607
|
+
{
|
2608
|
+
if (!items)
|
2609
|
+
items = '';
|
2610
|
+
|
2611
|
+
if (!sort)
|
2612
|
+
{
|
2613
|
+
sort = {
|
2614
|
+
field: 'cpuTime',
|
2615
|
+
dir: 'desc'
|
2616
|
+
};
|
1194
2617
|
}
|
2618
|
+
|
2619
|
+
return new kendo.data.DataSource({
|
2620
|
+
schema: {
|
2621
|
+
model: {
|
2622
|
+
id: 'id'
|
2623
|
+
}
|
2624
|
+
},
|
2625
|
+
sort: sort,
|
2626
|
+
data: items
|
2627
|
+
});
|
2628
|
+
}
|
2629
|
+
|
2630
|
+
_getQueueThreadsLabel(threadsNum)
|
2631
|
+
{
|
2632
|
+
return `Threads: ${threadsNum}`;
|
2633
|
+
}
|
2634
|
+
|
2635
|
+
_getQueueLoadLabel(load)
|
2636
|
+
{
|
2637
|
+
return `Avg. messages: ${load}`;
|
1195
2638
|
}
|
1196
2639
|
|
1197
|
-
|
2640
|
+
_updateOutMessagesQueueStatus()
|
1198
2641
|
{
|
1199
|
-
|
1200
|
-
|
2642
|
+
let threadsStr = this._getQueueThreadsLabel('--');
|
2643
|
+
let loadStr = this._getQueueLoadLabel('--');
|
2644
|
+
|
2645
|
+
if ($('#dsh-tcpPill').hasClass('active'))
|
2646
|
+
{
|
2647
|
+
threadsStr = this._getQueueThreadsLabel(this._tcpOutThreads);
|
2648
|
+
loadStr = this._getQueueLoadLabel(this._tcpOutLoad);
|
2649
|
+
}
|
1201
2650
|
|
1202
|
-
|
1203
|
-
|
2651
|
+
if ($('#dsh-udpPill').hasClass('active'))
|
2652
|
+
{
|
2653
|
+
threadsStr = this._getQueueThreadsLabel(this._udpOutThreads);
|
2654
|
+
loadStr = this._getQueueLoadLabel(this._udpOutLoad);
|
2655
|
+
}
|
1204
2656
|
|
1205
|
-
|
1206
|
-
|
2657
|
+
$('#dsh-outgoingMessagesQueueThreads').text(threadsStr);
|
2658
|
+
$('#dsh-outgoingMessagesQueueLoad').text(loadStr);
|
1207
2659
|
}
|
1208
2660
|
|
1209
2661
|
//---------------------------------
|
@@ -1218,4 +2670,4 @@ class LogViewer extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseModule"]
|
|
1218
2670
|
/***/ })
|
1219
2671
|
|
1220
2672
|
}]);
|
1221
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXRzL2pzL2NvcmUvbW9kdWxlcy9tb2R1bGUtOC5idW5kbGUuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL25vZGVfbW9kdWxlcy9maWxlLXNhdmVyL2Rpc3QvRmlsZVNhdmVyLm1pbi5qcyIsIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8od2VicGFjaykvYnVpbGRpbi9nbG9iYWwuanMiLCJ3ZWJwYWNrOi8vYXBwbGljYXRpb24vLi9zcmMvZGF0YS9ydW50aW1lLWxvZy1lbnRyeS5qcyIsIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9tb2R1bGVzL2xvZy12aWV3ZXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKGEsYil7aWYoXCJmdW5jdGlvblwiPT10eXBlb2YgZGVmaW5lJiZkZWZpbmUuYW1kKWRlZmluZShbXSxiKTtlbHNlIGlmKFwidW5kZWZpbmVkXCIhPXR5cGVvZiBleHBvcnRzKWIoKTtlbHNle2IoKSxhLkZpbGVTYXZlcj17ZXhwb3J0czp7fX0uZXhwb3J0c319KSh0aGlzLGZ1bmN0aW9uKCl7XCJ1c2Ugc3RyaWN0XCI7ZnVuY3Rpb24gYihhLGIpe3JldHVyblwidW5kZWZpbmVkXCI9PXR5cGVvZiBiP2I9e2F1dG9Cb206ITF9Olwib2JqZWN0XCIhPXR5cGVvZiBiJiYoY29uc29sZS53YXJuKFwiRGVwcmVjYXRlZDogRXhwZWN0ZWQgdGhpcmQgYXJndW1lbnQgdG8gYmUgYSBvYmplY3RcIiksYj17YXV0b0JvbTohYn0pLGIuYXV0b0JvbSYmL15cXHMqKD86dGV4dFxcL1xcUyp8YXBwbGljYXRpb25cXC94bWx8XFxTKlxcL1xcUypcXCt4bWwpXFxzKjsuKmNoYXJzZXRcXHMqPVxccyp1dGYtOC9pLnRlc3QoYS50eXBlKT9uZXcgQmxvYihbXCJcXHVGRUZGXCIsYV0se3R5cGU6YS50eXBlfSk6YX1mdW5jdGlvbiBjKGIsYyxkKXt2YXIgZT1uZXcgWE1MSHR0cFJlcXVlc3Q7ZS5vcGVuKFwiR0VUXCIsYiksZS5yZXNwb25zZVR5cGU9XCJibG9iXCIsZS5vbmxvYWQ9ZnVuY3Rpb24oKXthKGUucmVzcG9uc2UsYyxkKX0sZS5vbmVycm9yPWZ1bmN0aW9uKCl7Y29uc29sZS5lcnJvcihcImNvdWxkIG5vdCBkb3dubG9hZCBmaWxlXCIpfSxlLnNlbmQoKX1mdW5jdGlvbiBkKGEpe3ZhciBiPW5ldyBYTUxIdHRwUmVxdWVzdDtiLm9wZW4oXCJIRUFEXCIsYSwhMSk7dHJ5e2Iuc2VuZCgpfWNhdGNoKGEpe31yZXR1cm4gMjAwPD1iLnN0YXR1cyYmMjk5Pj1iLnN0YXR1c31mdW5jdGlvbiBlKGEpe3RyeXthLmRpc3BhdGNoRXZlbnQobmV3IE1vdXNlRXZlbnQoXCJjbGlja1wiKSl9Y2F0Y2goYyl7dmFyIGI9ZG9jdW1lbnQuY3JlYXRlRXZlbnQoXCJNb3VzZUV2ZW50c1wiKTtiLmluaXRNb3VzZUV2ZW50KFwiY2xpY2tcIiwhMCwhMCx3aW5kb3csMCwwLDAsODAsMjAsITEsITEsITEsITEsMCxudWxsKSxhLmRpc3BhdGNoRXZlbnQoYil9fXZhciBmPVwib2JqZWN0XCI9PXR5cGVvZiB3aW5kb3cmJndpbmRvdy53aW5kb3c9PT13aW5kb3c/d2luZG93Olwib2JqZWN0XCI9PXR5cGVvZiBzZWxmJiZzZWxmLnNlbGY9PT1zZWxmP3NlbGY6XCJvYmplY3RcIj09dHlwZW9mIGdsb2JhbCYmZ2xvYmFsLmdsb2JhbD09PWdsb2JhbD9nbG9iYWw6dm9pZCAwLGE9Zi5zYXZlQXN8fChcIm9iamVjdFwiIT10eXBlb2Ygd2luZG93fHx3aW5kb3chPT1mP2Z1bmN0aW9uKCl7fTpcImRvd25sb2FkXCJpbiBIVE1MQW5jaG9yRWxlbWVudC5wcm90b3R5cGU/ZnVuY3Rpb24oYixnLGgpe3ZhciBpPWYuVVJMfHxmLndlYmtpdFVSTCxqPWRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpO2c9Z3x8Yi5uYW1lfHxcImRvd25sb2FkXCIsai5kb3dubG9hZD1nLGoucmVsPVwibm9vcGVuZXJcIixcInN0cmluZ1wiPT10eXBlb2YgYj8oai5ocmVmPWIsai5vcmlnaW49PT1sb2NhdGlvbi5vcmlnaW4/ZShqKTpkKGouaHJlZik/YyhiLGcsaCk6ZShqLGoudGFyZ2V0PVwiX2JsYW5rXCIpKTooai5ocmVmPWkuY3JlYXRlT2JqZWN0VVJMKGIpLHNldFRpbWVvdXQoZnVuY3Rpb24oKXtpLnJldm9rZU9iamVjdFVSTChqLmhyZWYpfSw0RTQpLHNldFRpbWVvdXQoZnVuY3Rpb24oKXtlKGopfSwwKSl9OlwibXNTYXZlT3JPcGVuQmxvYlwiaW4gbmF2aWdhdG9yP2Z1bmN0aW9uKGYsZyxoKXtpZihnPWd8fGYubmFtZXx8XCJkb3dubG9hZFwiLFwic3RyaW5nXCIhPXR5cGVvZiBmKW5hdmlnYXRvci5tc1NhdmVPck9wZW5CbG9iKGIoZixoKSxnKTtlbHNlIGlmKGQoZikpYyhmLGcsaCk7ZWxzZXt2YXIgaT1kb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYVwiKTtpLmhyZWY9ZixpLnRhcmdldD1cIl9ibGFua1wiLHNldFRpbWVvdXQoZnVuY3Rpb24oKXtlKGkpfSl9fTpmdW5jdGlvbihhLGIsZCxlKXtpZihlPWV8fG9wZW4oXCJcIixcIl9ibGFua1wiKSxlJiYoZS5kb2N1bWVudC50aXRsZT1lLmRvY3VtZW50LmJvZHkuaW5uZXJUZXh0PVwiZG93bmxvYWRpbmcuLi5cIiksXCJzdHJpbmdcIj09dHlwZW9mIGEpcmV0dXJuIGMoYSxiLGQpO3ZhciBnPVwiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtXCI9PT1hLnR5cGUsaD0vY29uc3RydWN0b3IvaS50ZXN0KGYuSFRNTEVsZW1lbnQpfHxmLnNhZmFyaSxpPS9DcmlPU1xcL1tcXGRdKy8udGVzdChuYXZpZ2F0b3IudXNlckFnZW50KTtpZigoaXx8ZyYmaCkmJlwib2JqZWN0XCI9PXR5cGVvZiBGaWxlUmVhZGVyKXt2YXIgaj1uZXcgRmlsZVJlYWRlcjtqLm9ubG9hZGVuZD1mdW5jdGlvbigpe3ZhciBhPWoucmVzdWx0O2E9aT9hOmEucmVwbGFjZSgvXmRhdGE6W147XSo7LyxcImRhdGE6YXR0YWNobWVudC9maWxlO1wiKSxlP2UubG9jYXRpb24uaHJlZj1hOmxvY2F0aW9uPWEsZT1udWxsfSxqLnJlYWRBc0RhdGFVUkwoYSl9ZWxzZXt2YXIgaz1mLlVSTHx8Zi53ZWJraXRVUkwsbD1rLmNyZWF0ZU9iamVjdFVSTChhKTtlP2UubG9jYXRpb249bDpsb2NhdGlvbi5ocmVmPWwsZT1udWxsLHNldFRpbWVvdXQoZnVuY3Rpb24oKXtrLnJldm9rZU9iamVjdFVSTChsKX0sNEU0KX19KTtmLnNhdmVBcz1hLnNhdmVBcz1hLFwidW5kZWZpbmVkXCIhPXR5cGVvZiBtb2R1bGUmJihtb2R1bGUuZXhwb3J0cz1hKX0pO1xuXG4vLyMgc291cmNlTWFwcGluZ1VSTD1GaWxlU2F2ZXIubWluLmpzLm1hcCIsInZhciBnO1xuXG4vLyBUaGlzIHdvcmtzIGluIG5vbi1zdHJpY3QgbW9kZVxuZyA9IChmdW5jdGlvbigpIHtcblx0cmV0dXJuIHRoaXM7XG59KSgpO1xuXG50cnkge1xuXHQvLyBUaGlzIHdvcmtzIGlmIGV2YWwgaXMgYWxsb3dlZCAoc2VlIENTUClcblx0ZyA9IGcgfHwgbmV3IEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKTtcbn0gY2F0Y2ggKGUpIHtcblx0Ly8gVGhpcyB3b3JrcyBpZiB0aGUgd2luZG93IHJlZmVyZW5jZSBpcyBhdmFpbGFibGVcblx0aWYgKHR5cGVvZiB3aW5kb3cgPT09IFwib2JqZWN0XCIpIGcgPSB3aW5kb3c7XG59XG5cbi8vIGcgY2FuIHN0aWxsIGJlIHVuZGVmaW5lZCwgYnV0IG5vdGhpbmcgdG8gZG8gYWJvdXQgaXQuLi5cbi8vIFdlIHJldHVybiB1bmRlZmluZWQsIGluc3RlYWQgb2Ygbm90aGluZyBoZXJlLCBzbyBpdCdzXG4vLyBlYXNpZXIgdG8gaGFuZGxlIHRoaXMgY2FzZS4gaWYoIWdsb2JhbCkgeyAuLi59XG5cbm1vZHVsZS5leHBvcnRzID0gZztcbiIsImV4cG9ydCBjbGFzcyBSdW50aW1lTG9nRW50cnlcbntcblx0Y29uc3RydWN0b3Ioc2VwYXJhdG9yKVxuXHR7XG5cdFx0dGhpcy5zZXAgPSBzZXBhcmF0b3Jcblx0fVxuXG5cdHN0YXRpYyBmcm9tQXJyYXkoc2VwYXJhdG9yLCBsb2dFbnRyeURhdGEpXG5cdHtcblx0XHRsZXQgcmxlID0gbmV3IFJ1bnRpbWVMb2dFbnRyeShzZXBhcmF0b3IpO1xuXG5cdFx0cmxlLmRhdGUgPSBsb2dFbnRyeURhdGFbMF07XG5cdFx0cmxlLnRpbWUgPSBsb2dFbnRyeURhdGFbMV07XG5cdFx0cmxlLmRhdGVUaW1lID0gcmxlLl9nZXREYXRlVGltZSgpO1xuXHRcdHJsZS5sZXZlbCA9IGxvZ0VudHJ5RGF0YVsyXS50cmltKCk7XG5cdFx0cmxlLnRocmVhZCA9IGxvZ0VudHJ5RGF0YVszXTtcblx0XHRybGUuY2xhenogPSBsb2dFbnRyeURhdGFbNF07XG5cdFx0cmxlLm1lc3NhZ2UgPSBsb2dFbnRyeURhdGFbNl07XG5cblx0XHRyZXR1cm4gcmxlO1xuXHR9XG5cblx0X2dldERhdGVUaW1lKClcblx0e1xuXHRcdHJldHVybiB0aGlzLmRhdGUgKyAnXFxuJyArIHRoaXMudGltZTtcblx0fVxufVxuIiwiaW1wb3J0IHtCYXNlTW9kdWxlfSBmcm9tICcuL2Jhc2UtbW9kdWxlJztcbmltcG9ydCB7UnVudGltZUxvZ0VudHJ5fSBmcm9tICcuLi9kYXRhL3J1bnRpbWUtbG9nLWVudHJ5JztcbmltcG9ydCAqIGFzIEZpbGVTYXZlciBmcm9tICdmaWxlLXNhdmVyJztcbmltcG9ydCAqIGFzIG1vbWVudCBmcm9tICdtb21lbnQnO1xuaW1wb3J0IHtieXRlc1RvU2l6ZX0gZnJvbSAnLi4vdXRpbHMvdXRpbGl0aWVzJztcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTG9nVmlld2VyIGV4dGVuZHMgQmFzZU1vZHVsZVxue1xuXHRjb25zdHJ1Y3RvcigpXG5cdHtcblx0ICAgIHN1cGVyKCdsb2dWaWV3ZXInKTtcblxuXHRcdHRoaXMuQ09NTUFORFNfUFJFRklYID0gJ2xvZ1ZpZXdlcic7XG5cdFx0dGhpcy5IRUxQX1VSTCA9ICcvYWRtaW50b29sLUxvZ1ZpZXdlcic7XG5cblx0XHR0aGlzLkFOWV9MRVZFTCA9ICdbYW55XSc7XG5cdFx0dGhpcy5MRVZFTFMgPSBbJ1RSQUNFJywnREVCVUcnLCdJTkZPJywnV0FSTicsJ0VSUk9SJ107XG5cdFx0dGhpcy5BTllfQ0xBU1MgPSAnW2FueV0nO1xuXG5cdFx0dGhpcy5MT0dfREFUQV9MQUJFTCA9ICdsaW5lcyc7XG5cblx0XHR0aGlzLkJPT1RfTE9HX0JBQ0tVUF9JRCA9ICdTRlMyWF9Cb290TG9nJztcblx0XHR0aGlzLlJVTlRJTUVfTE9HX0JBQ0tVUF9JRCA9ICdTRlMyWF9SdW50aW1lTG9nJztcblx0XHR0aGlzLkZVTExfQkFDS1VQX0lEID0gJ1NGUzJYX0xvZ3MnO1xuXG5cdFx0Ly8gT3V0Z29pbmcgcmVxdWVzdHNcblx0XHR0aGlzLlJFUV9HRVRfUlVOVElNRV9MT0cgPSAnZ2V0UnVuTG9nJztcblx0XHR0aGlzLlJFUV9HRVRfQk9PVF9MT0cgPSAnZ2V0Qm9vdExvZyc7XG5cdFx0dGhpcy5SRVFfR0VUX0JBQ0tVUFNfU1RBVFVTID0gJ2dldEJha1N0YXR1cyc7XG5cdFx0dGhpcy5SRVFfQkFDS1VQX0JPT1RfTE9HID0gJ2Jha0Jvb3RMb2cnO1xuXHRcdHRoaXMuUkVRX0JBQ0tVUF9SVU5USU1FX0xPRyA9ICdiYWtSdW5Mb2cnO1xuXHRcdHRoaXMuUkVRX0JBQ0tVUF9GVUxMX0xPR1MgPSAnYmFrRnVsbExvZ3MnO1xuXHRcdHRoaXMuUkVRX0RFTEVURV9CQUNLVVAgPSAnZGVsQmFja3VwJztcblxuXHRcdC8vIEluY29taW5nIHJlc3BvbnNlc1xuXHRcdHRoaXMuUkVTUF9JTklUX0VSUk9SID0gJ2luaXRFcnInO1xuXHRcdHRoaXMuUkVTUF9SVU5USU1FX0xPR19FUlJPUiA9ICdydW5Mb2dFcnInO1xuXHRcdHRoaXMuUkVTUF9SVU5USU1FX0xPR19JTlZBTElEID0gJ3J1bkxvZ0ludic7XG5cdFx0dGhpcy5SRVNQX1JVTlRJTUVfTE9HID0gJ3J1bkxvZyc7XG5cdFx0dGhpcy5SRVNQX0JPT1RfTE9HX0VSUk9SID0gJ2Jvb3RMb2dFcnInO1xuXHRcdHRoaXMuUkVTUF9CT09UX0xPRyA9ICdib290TG9nJztcblx0XHR0aGlzLlJFU1BfQkFDS1VQU19TVEFUVVMgPSAnYmFrU3RhdHVzJztcblx0XHR0aGlzLlJFU1BfREVMRVRFX0JBQ0tVUF9GQUlMRUQgPSAnZGVsQmFrRmFpbCc7XG5cdFx0dGhpcy5SRVNQX0JBQ0tVUF9FUlJPUiA9ICdiYWtFcnJvcic7XG5cdFx0dGhpcy5SRVNQX0JBQ0tVUF9XQVJOSU5HID0gJ2Jha1dhcm4nO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8gQ09NTU9OIE1PRFVMRSBJTlRFUkZBQ0UgTUVUSE9EU1xuXHQvLyBUaGlzIG1lbWJlcnMgYXJlIHVzZWQgYnkgdGhlIG1haW4gY29udHJvbGxlclxuXHQvLyB0byBjb21tdW5pY2F0ZSB3aXRoIHRoZSBtb2R1bGUncyBjb250cm9sbGVyLlxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdGluaXRpYWxpemUoaWREYXRhLCBzaGVsbENvbnRyb2xsZXIpXG5cdHtcblx0XHQvLyBDYWxsIHN1cGVyIG1ldGhvZFxuXHRcdHN1cGVyLmluaXRpYWxpemUoaWREYXRhLCBzaGVsbENvbnRyb2xsZXIpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBzY3JvbGxpbmcgdGFic1xuXHRcdCQoJyNsZ3YtdGFiTmF2aWdhdG9yID4gI3RhYnMnKS5zY3JvbGxpbmdUYWJzKHtcblx0XHRcdGJvb3RzdHJhcFZlcnNpb246IDQsXG5cdFx0XHRzY3JvbGxUb1RhYkVkZ2U6IHRydWUsXG5cdFx0XHRlbmFibGVTd2lwaW5nOiB0cnVlLFxuXHRcdFx0ZGlzYWJsZVNjcm9sbEFycm93c09uRnVsbHlTY3JvbGxlZDogdHJ1ZSxcblx0XHRcdGNzc0NsYXNzTGVmdEFycm93OiAnZmEgZmEtY2hldnJvbi1sZWZ0Jyxcblx0XHRcdGNzc0NsYXNzUmlnaHRBcnJvdzogJ2ZhIGZhLWNoZXZyb24tcmlnaHQnXG5cdFx0fSk7XG5cblx0XHQvLyBBZGQgbGlzdGVuZXIgdG8gdGFiIHNob3duIGV2ZW50XG5cdFx0JCgnYVtkYXRhLXRvZ2dsZT1cInRhYlwiXScpLm9uKCdzaG93bi5icy50YWInLCAkLnByb3h5KHRoaXMuX29uVGFiU2hvd24sIHRoaXMpKTtcblxuXHRcdC8vIEluaXRpYWxpemUgbG9nIGxpbmVzIGRyb3Bkb3duXG5cdFx0dGhpcy5fbG9nTGluZXNERCA9ICQoJyNsZ3YtbG9nTGluZXNERCcpLmtlbmRvRHJvcERvd25MaXN0KHtcblx0XHRcdHZhbHVlVGVtcGxhdGU6ICc8c3BhbiBjbGFzcz1cInRleHQtbXV0ZWQgcHItMVwiPkxvZyBlbnRyaWVzOjwvc3Bhbj48c3Bhbj4jOmRhdGEudGV4dCM8L3NwYW4+Jyxcblx0XHR9KS5kYXRhKCdrZW5kb0Ryb3BEb3duTGlzdCcpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBsb2FkIGJ1dHRvblxuXHRcdCQoJyNsZ3YtbG9hZEJ0Jykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vblJ1bnRpbWVMb2dMb2FkQnRDbGljaywgdGhpcykpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBwcm9ncmVzcyBiYXJzXG5cdFx0JCgnLnByb2dyZXNzLWJhcicpLmtlbmRvUHJvZ3Jlc3NCYXIoe1xuXHRcdFx0bWluOiAwLFxuICAgICAgICAgICAgbWF4OiAxMDAsXG5cdFx0XHR2YWx1ZTogZmFsc2UsXG4gICAgICAgICAgICB0eXBlOiAndmFsdWUnLFxuICAgICAgICAgICAgYW5pbWF0aW9uOiB7XG4gICAgICAgICAgICAgICAgZHVyYXRpb246IDQwMFxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuXHRcdC8vIEluaXRpYWxpemUgbGV2ZWwgZmlsdGVyIGRyb3Bkb3duXG5cdFx0dGhpcy5fbGV2ZWxGaWx0ZXJERCA9ICQoJyNsZ3YtbGV2ZWxERCcpLmtlbmRvRHJvcERvd25MaXN0KHtcblx0XHRcdGRhdGFTb3VyY2U6IFt0aGlzLkFOWV9MRVZFTF0uY29uY2F0KHRoaXMuTEVWRUxTKSxcblx0XHRcdGNoYW5nZTogJC5wcm94eSh0aGlzLl9vbkZpbHRlckNoYW5nZSwgdGhpcylcblx0XHR9KS5kYXRhKCdrZW5kb0Ryb3BEb3duTGlzdCcpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBjbGFzcyBmaWx0ZXIgZHJvcGRvd25cblx0XHR0aGlzLl9jbGFzc0ZpbHRlckREID0gJCgnI2xndi1jbGFzc0REJykua2VuZG9Ecm9wRG93bkxpc3Qoe1xuXHRcdFx0Y2hhbmdlOiAkLnByb3h5KHRoaXMuX29uRmlsdGVyQ2hhbmdlLCB0aGlzKVxuXHRcdH0pLmRhdGEoJ2tlbmRvRHJvcERvd25MaXN0Jyk7XG5cblx0XHQvLyBJbml0aWFsaXplIG1lc3NhZ2UgZmlsdGVyIGlucHV0XG5cdFx0JCgnI2xndi1tZXNzYWdlSW4nKS5vbignaW5wdXQnLCAkLnByb3h5KHRoaXMuX29uRmlsdGVyQ2hhbmdlLCB0aGlzKSk7XG5cblx0XHQvLyBJbml0aWFsaXplIGNsZWFyIGJ1dHRvblxuXHRcdCQoJyNsZ3YtY2xlYXJGaWx0ZXJCdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25DbGVhckZpbHRlckNsaWNrLCB0aGlzKSk7XG5cblx0XHQvLyBJbml0aWFsaXplIGV4cG9ydCBidXR0b25cblx0XHQkKCcjbGd2LWV4cG9ydFJ1bnRpbWVMb2dCdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25FeHBvcnRSdW50aW1lTG9nQnRDbGljaywgdGhpcykpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBydW50aW1lIGxvZyBncmlkXG5cdFx0dGhpcy5fcnVudGltZUxvZ0dyaWQgPSAkKCcjbGd2LXJ1bnRpbWVMb2dHcmlkJykua2VuZG9HcmlkKHtcblx0XHRcdHNjcm9sbGFibGU6IHRydWUsXG4gICAgICAgICAgICBzb3J0YWJsZTogZmFsc2UsXG5cdFx0XHQvL3Jlc2l6YWJsZTogdHJ1ZSxcblx0XHRcdHNlbGVjdGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgY29sdW1uczpcbiAgICAgICAgICAgIFtcblx0XHRcdFx0e1xuXHQgICAgICAgICAgICAgICAgZmllbGQ6ICdkYXRlVGltZScsXG5cdCAgICAgICAgICAgICAgICB3aWR0aDogMTUwLFxuXHRcdFx0XHRcdHRpdGxlOiAnRGF0ZS9UaW1lJyxcblx0ICAgICAgICAgICAgfSxcblx0ICAgICAgICAgICAge1xuXHQgICAgICAgICAgICAgICAgZmllbGQ6ICdsZXZlbCcsXG5cdCAgICAgICAgICAgICAgICB3aWR0aDogMTAwLFxuXHQgICAgICAgICAgICAgICAgdGl0bGU6ICdMZXZlbCcsXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICAgIHtcblx0ICAgICAgICAgICAgICAgIGZpZWxkOiAndGhyZWFkJyxcblx0ICAgICAgICAgICAgICAgIHdpZHRoOiAxNTAsXG5cdCAgICAgICAgICAgICAgICB0aXRsZTogJ1RocmVhZCcsXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICAgIHtcblx0ICAgICAgICAgICAgICAgIGZpZWxkOiAnY2xhenonLFxuXHQgICAgICAgICAgICAgICAgd2lkdGg6IDI1MCxcblx0ICAgICAgICAgICAgICAgIHRpdGxlOiAnQ2xhc3MnLFxuXHQgICAgICAgICAgICB9LFxuXHRcdFx0XHR7XG5cdCAgICAgICAgICAgICAgICBmaWVsZDogJ21lc3NhZ2UnLFxuXHQgICAgICAgICAgICAgICAgd2lkdGg6IDEwMDAsXG5cdFx0XHRcdFx0dGl0bGU6ICdNZXNzYWdlJyxcblx0ICAgICAgICAgICAgfSxcblx0XHRcdF0sXG5cdFx0XHRub1JlY29yZHM6IHtcblx0XHRcdFx0dGVtcGxhdGU6ICdObyBsb2cgZW50cmllcyB0byBkaXNwbGF5Lidcblx0XHRcdH0sXG5cdFx0XHRkYXRhU291cmNlOiBbXVxuICAgICAgICB9KS5kYXRhKCdrZW5kb0dyaWQnKTtcblxuXHRcdC8vIEluaXRpYWxpemUgYm9vdCBsb2cgdmlldyBidXR0b25zXG5cdFx0JCgnI2xndi1leHBvcnRCb290TG9nQnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uRXhwb3J0Qm9vdExvZ0J0Q2xpY2ssIHRoaXMpKTtcblx0XHQkKCcjbGd2LXN3aXRjaEJvb3RMb2dDb2xvckJ0Jykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vblN3aXRjaEJvb3RMb2dDb2xvckJ0Q2xpY2ssIHRoaXMpKTtcblxuXHRcdC8vIEluaXRpYWxpemUgZ2VuZXJhdGUgYmFja3VwIGJ1dHRvbnNcblx0XHQkKCcjbGd2LWJvb3RMb2dCYWNrdXBDYXJkIC5iYWNrdXAtYnV0dG9uJykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vbkJvb3RMb2dHZW5lcmF0ZUJ0Q2xpY2ssIHRoaXMpKTtcblx0XHQkKCcjbGd2LXJ1bnRpbWVMb2dCYWNrdXBDYXJkIC5iYWNrdXAtYnV0dG9uJykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vblJ1bnRpbWVMb2dHZW5lcmF0ZUJ0Q2xpY2ssIHRoaXMpKTtcblx0XHQkKCcjbGd2LWZ1bGxMb2dCYWNrdXBDYXJkIC5iYWNrdXAtYnV0dG9uJykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vbkZ1bGxMb2dzR2VuZXJhdGVCdENsaWNrLCB0aGlzKSk7XG5cblx0XHR0aGlzLl9pbml0QmFja3VwQ2FyZCgnI2xndi1ib290TG9nQmFja3VwQ2FyZCcpO1xuXHRcdHRoaXMuX2luaXRCYWNrdXBDYXJkKCcjbGd2LXJ1bnRpbWVMb2dCYWNrdXBDYXJkJyk7XG5cdFx0dGhpcy5faW5pdEJhY2t1cENhcmQoJyNsZ3YtZnVsbExvZ0JhY2t1cENhcmQnKTtcblxuXHRcdC8vIEluaXRpYWxpemUgZG93bmxvYWQgZ3JpZFxuXHRcdHRoaXMuX2Rvd25sb2FkR3JpZCA9ICQoJyNsZ3YtZG93bmxvYWRHcmlkJykua2VuZG9HcmlkKHtcblx0XHRcdHNjcm9sbGFibGU6IHRydWUsXG4gICAgICAgICAgICBzb3J0YWJsZTogdHJ1ZSxcblx0XHRcdC8vcmVzaXphYmxlOiB0cnVlLFxuXHRcdFx0c2VsZWN0YWJsZTogJ3JvdycsXG4gICAgICAgICAgICBjb2x1bW5zOlxuICAgICAgICAgICAgW1xuXHRcdFx0XHR7XG5cdCAgICAgICAgICAgICAgICBmaWVsZDogJ2RhdGUnLFxuXHQgICAgICAgICAgICAgICAgd2lkdGg6IDEwMCxcblx0XHRcdFx0XHR0aXRsZTogJ0RhdGUnLFxuXHQgICAgICAgICAgICB9LFxuXHQgICAgICAgICAgICB7XG5cdCAgICAgICAgICAgICAgICBmaWVsZDogJ3RpbWUnLFxuXHQgICAgICAgICAgICAgICAgd2lkdGg6IDEwMCxcblx0ICAgICAgICAgICAgICAgIHRpdGxlOiAnVGltZScsXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICAgIHtcblx0ICAgICAgICAgICAgICAgIGZpZWxkOiAnbmFtZScsXG5cdCAgICAgICAgICAgICAgICB3aWR0aDogMzAwLFxuXHQgICAgICAgICAgICAgICAgdGl0bGU6ICdGaWxlbmFtZScsXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICAgIHtcblx0ICAgICAgICAgICAgICAgIGZpZWxkOiAnc2l6ZScsXG5cdCAgICAgICAgICAgICAgICB3aWR0aDogMTAwLFxuXHQgICAgICAgICAgICAgICAgdGl0bGU6ICdTaXplJyxcblx0ICAgICAgICAgICAgfSxcblx0XHRcdF0sXG5cdFx0XHRub1JlY29yZHM6IHtcblx0XHRcdFx0dGVtcGxhdGU6ICdObyBiYWNrdXBzIGF2YWlsYWJsZS4nXG5cdFx0XHR9LFxuXHRcdFx0Y2hhbmdlOiAkLnByb3h5KHRoaXMuX29uRG93bmxvYWRHcmlkU2VsZWN0aW9uQ2hhbmdlLCB0aGlzKSxcblx0XHRcdGRhdGFTb3VyY2U6IFtdXG4gICAgICAgIH0pLmRhdGEoJ2tlbmRvR3JpZCcpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBkZWxldGUgYnV0dG9uXG5cdFx0JCgnI2xndi1kZWxldGVCdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25EZWxldGVCdENsaWNrLCB0aGlzKSk7XG5cdH1cblxuXHRkZXN0cm95KClcblx0e1xuXHRcdC8vIENhbGwgc3VwZXIgbWV0aG9kXG5cdFx0c3VwZXIuZGVzdHJveSgpO1xuXG5cdFx0Ly8gUmVtb3ZlIGxpc3RlbmVyIHRvIHRhYiBzaG93biBldmVudFxuXHRcdCQoJ2FbZGF0YS10b2dnbGU9XCJ0YWJcIl0nKS5vZmYoJ3Nob3duLmJzLnRhYicpO1xuXG5cdFx0Ly8gRGVzdHJveSBzY3JvbGxpbmcgdGFic1xuXHRcdCQoJyNsZ3YtdGFiTmF2aWdhdG9yICN0YWJzJykuc2Nyb2xsaW5nVGFicygnZGVzdHJveScpO1xuXG5cdFx0Ly8gUmVtb3ZlIGNsaWNrIGxpc3RlbmVyc1xuXHRcdCQoJyNsZ3YtbG9hZEJ0Jykub2ZmKCdjbGljaycpO1xuXHRcdCQoJyNsZ3YtZXhwb3J0Qm9vdExvZ0J0Jykub2ZmKCdjbGljaycpO1xuXHRcdCQoJyNsZ3Ytc3dpdGNoQm9vdExvZ0NvbG9yQnQnKS5vZmYoJ2NsaWNrJyk7XG5cdFx0JCgnI2xndi1ib290TG9nQmFja3VwQ2FyZCAuYmFja3VwLWJ1dHRvbicpLm9mZignY2xpY2snKTtcblx0XHQkKCcjbGd2LXJ1bnRpbWVMb2dCYWNrdXBDYXJkIC5iYWNrdXAtYnV0dG9uJykub2ZmKCdjbGljaycpO1xuXHRcdCQoJyNsZ3YtY2xlYXJGaWx0ZXJCdCcpLm9mZignY2xpY2snKTtcblx0XHQkKCcjbGd2LWRlbGV0ZUJ0Jykub2ZmKCdjbGljaycpO1xuXG5cdFx0JCgnI2xndi1tZXNzYWdlSW4nKS5vZmYoJ2lucHV0Jyk7XG5cdH1cblxuXHRvbkV4dGVuc2lvbkNvbW1hbmQoY29tbWFuZCwgZGF0YSlcblx0e1xuXHRcdC8vIEVycm9yIGR1cmluZyBpbml0aWFsaXphdGlvbiAodW5hYmxlIHRvIGFjY2VzcyBsb2c0aiBjb25maWd1cmF0aW9uIGZpbGUpXG5cdFx0aWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0lOSVRfRVJST1IpXG5cdFx0e1xuXHRcdFx0Y29uc3QgZXJyb3IgPSBkYXRhLmdldFV0ZlN0cmluZygnZXJyb3InKTtcblxuXHRcdFx0Ly8gU2hvdyBhbiBhbGVydFxuXHRcdFx0dGhpcy5zaGVsbEN0cmwuc2hvd1NpbXBsZUFsZXJ0KGVycm9yLCB0cnVlKTtcblxuXHRcdFx0Ly8gU2V0IGFsbCB0YWJzIHRvIHNob3cgZXJyb3JzXG5cdFx0XHR0aGlzLl9zd2l0Y2hCb290Vmlld1N0YWNrKCdsZ3YtYm9vdExvZ0Vycm9yVmlldycpO1xuXHRcdFx0dGhpcy5fc3dpdGNoUnVudGltZVZpZXdTdGFjaygnbGd2LXJ1bnRpbWVMb2dFcnJvclZpZXcnKTtcblx0XHRcdHRoaXMuX3N3aXRjaERvd25sb2FkVmlld1N0YWNrKCdsZ3YtZG93bmxvYWRFcnJvclZpZXcnKTtcblxuXHRcdFx0Ly8gRGlzYWJsZSBydW50aW1lIGxvZyBjb250cm9sc1xuXHRcdFx0dGhpcy5fZW5hYmxlUnVudGltZUxvZ0NvbnRyb2xzKGZhbHNlKTtcblxuXHRcdFx0dGhpcy5faW5pdEZhaWxlZCA9IHRydWU7XG5cdFx0fVxuXG5cdFx0Ly8gRXJyb3IgcmVzcG9uc2VzXG5cdFx0ZWxzZSBpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfQk9PVF9MT0dfRVJST1IgfHwgY29tbWFuZCA9PSB0aGlzLlJFU1BfUlVOVElNRV9MT0dfRVJST1IpXG5cdFx0e1xuXHRcdFx0Y29uc3QgZXJyb3IgPSBkYXRhLmdldFV0ZlN0cmluZygnZXJyb3InKTtcblxuXHRcdFx0Ly8gU2hvdyBhbiBhbGVydFxuXHRcdFx0dGhpcy5zaGVsbEN0cmwuc2hvd1NpbXBsZUFsZXJ0KGVycm9yLCB0cnVlKTtcblxuXHRcdFx0aWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0JPT1RfTE9HX0VSUk9SKVxuXHRcdFx0e1xuXHRcdFx0XHQvLyBTZXQgdGFiIHRvIHNob3cgZXJyb3Jcblx0XHRcdFx0dGhpcy5fc3dpdGNoQm9vdFZpZXdTdGFjaygnbGd2LWJvb3RMb2dFcnJvclZpZXcnKTtcblxuXHRcdFx0XHQvLyBEaXNhYmxlIGJvb3QgbG9nIGJhY2t1cCBnZW5lcmF0aW9uXG5cdFx0XHRcdHRoaXMuX2Jvb3RMb2dCYWNrdXBVbmF2YWlsYWJsZSA9IHRydWU7XG5cdFx0XHRcdHRoaXMuX2Rpc2FibGVCYWNrdXBJbnRlcmZhY2UoZmFsc2UpO1xuXG5cdFx0XHRcdHRoaXMuX2Jvb3RMb2dSZXF1ZXN0ZWQgPSB0cnVlO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfUlVOVElNRV9MT0dfRVJST1IpXG5cdFx0XHR7XG5cdFx0XHRcdC8vIERpc2FibGUgY29udHJvbHNcblx0XHRcdFx0dGhpcy5fZW5hYmxlUnVudGltZUxvZ0NvbnRyb2xzKGZhbHNlKTtcblxuXHRcdFx0XHQvLyBSZW1vdmUgbG9hZGluZyBiYXIgKHJ1bnRpbWUgbG9nKVxuXHRcdFx0XHR0aGlzLl9zd2l0Y2hSdW50aW1lVmlld1N0YWNrKCdsZ3YtcnVudGltZUxvZ0Vycm9yVmlldycpO1xuXG5cdFx0XHRcdC8vIERpc2FibGUgcnVudGltZSBsb2cgYmFja3VwIGRvd25sb2FkXG5cdFx0XHRcdHRoaXMuX3J1bnRpbWVMb2dCYWNrdXBVbmF2YWlsYWJsZSA9IHRydWU7XG5cdFx0XHRcdHRoaXMuX2Rpc2FibGVCYWNrdXBJbnRlcmZhY2UoZmFsc2UpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIE1vZGlmaWVkIGNvbnZlcnNpb24gcGF0dGVybiBpbiB0aGUgbG9nNGogcHJvcGVydGllcyBmaWxlOiB1bmFibGUgdG8gcGFyc2UgdGhlIGxvZ1xuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX1JVTlRJTUVfTE9HX0lOVkFMSUQpXG5cdFx0e1xuXHRcdFx0Ly8gRGlzYWJsZSBjb250cm9sc1xuXHRcdFx0dGhpcy5fZW5hYmxlUnVudGltZUxvZ0NvbnRyb2xzKGZhbHNlKTtcblxuXHRcdFx0Ly8gRmlsbCBpbiBlcnJvciBtZXNzYWdlXG5cdFx0XHQkKCcjbGd2LWNvbnZQYXR0TmFtZScpLnRleHQoZGF0YS5nZXRVdGZTdHJpbmcoJ3BhcmFtJykpO1xuXHRcdFx0JCgnI2xndi1jb252UGF0dFZhbCcpLnRleHQoZGF0YS5nZXRVdGZTdHJpbmcoJ3ZhbHVlJykpO1xuXG5cdFx0XHQvLyBSZW1vdmUgbG9hZGluZyBiYXIgKHJ1bnRpbWUgbG9nKVxuXHRcdFx0dGhpcy5fc3dpdGNoUnVudGltZVZpZXdTdGFjaygnbGd2LWludkNvbnZQYXR0VmlldycpO1xuXHRcdH1cblxuXHRcdC8vIFJ1bnRpbWUgbG9nIHJlY2VpdmVkXG5cdFx0ZWxzZSBpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfUlVOVElNRV9MT0cpXG5cdFx0e1xuXHRcdFx0bGV0IGNsYXNzZXMgPSBbXTtcblx0XHRcdGNsYXNzZXMucHVzaCh0aGlzLkFOWV9DTEFTUyk7XG5cblx0XHRcdGxldCBsb2dFbnRyaWVzID0gZGF0YS5nZXRVdGZTdHJpbmdBcnJheSh0aGlzLkxPR19EQVRBX0xBQkVMKTtcblx0XHRcdGxldCBzZXBhcmF0b3IgPSBkYXRhLmdldFV0ZlN0cmluZygnc2VwJyk7XG5cdFx0XHRsZXQgY29sdW1ucyA9IGRhdGEuZ2V0SW50KCdjb2xzJyk7XG5cdFx0XHRsZXQgZHNBcnIgPSBbXTtcblxuXHRcdFx0dGhpcy5fdG90YWxSdW50aW1lTG9nRW50cmllcyA9IGxvZ0VudHJpZXMubGVuZ3RoO1xuXG5cdFx0XHQvLyBQYXJzZSBsb2cgZW50cmllc1xuXHRcdFx0Ly8gV2UgY2FuJ3QgdXNlIHRoZSBzcGxpdCBtZXRob2QgYmVjYXVzZSB0aGVyZSBjb3VsZCBiZSBpbnN0YW5jZXMgb2YgdGhlIHNlcGFyYXRvciBpbiB0aGUgbG9nIG1lc3NhZ2UgdG9vXG5cdFx0XHRmb3IgKGxldCBlID0gMDsgZSA8IGxvZ0VudHJpZXMubGVuZ3RoOyBlKyspXG5cdFx0XHR7XG5cdFx0XHRcdGNvbnN0IGxvZ0VudHJ5ID0gbG9nRW50cmllc1tlXTtcblxuXHRcdFx0XHRsZXQgbG9nRW50cnlEYXRhID0gW107XG5cdFx0XHRcdGxldCBzdGFydEluZGV4ID0gMDtcblxuXHRcdFx0XHRmb3IgKGxldCBjID0gMDsgYyA8IGNvbHVtbnMgLSAxOyBjKyspXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRsZXQgZW5kSW5kZXggPSBsb2dFbnRyeS5pbmRleE9mKHNlcGFyYXRvciwgc3RhcnRJbmRleCk7XG5cdFx0XHRcdFx0bG9nRW50cnlEYXRhLnB1c2gobG9nRW50cnkuc3Vic3RyaW5nKHN0YXJ0SW5kZXgsIGVuZEluZGV4KSk7XG5cdFx0XHRcdFx0c3RhcnRJbmRleCA9IGVuZEluZGV4ICsgc2VwYXJhdG9yLmxlbmd0aDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChzdGFydEluZGV4IDwgbG9nRW50cnkubGVuZ3RoKVxuXHRcdFx0XHRcdGxvZ0VudHJ5RGF0YS5wdXNoKGxvZ0VudHJ5LnN1YnN0cmluZyhzdGFydEluZGV4KSk7XG5cblx0XHRcdFx0Ly8gRmlsbCBkYXRhZ3JpZCdzIGRhdGFwcm92aWRlclxuXHRcdFx0XHRsZXQgcmxlID0gUnVudGltZUxvZ0VudHJ5LmZyb21BcnJheShzZXBhcmF0b3IsIGxvZ0VudHJ5RGF0YSk7XG5cdFx0XHRcdGRzQXJyLnB1c2gocmxlKTtcblxuXHRcdFx0XHQvLyBBZGQgY2xhc3MgdG8gZmlsdGVyaW5nIGRyb3Bkb3duXG5cdFx0XHRcdGlmIChjbGFzc2VzLmluZGV4T2YocmxlLmNsYXp6KSA8IDApXG5cdFx0XHRcdFx0Y2xhc3Nlcy5wdXNoKHJsZS5jbGF6eik7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFNob3cgY2xhc3NlcyBsaXN0XG5cdFx0XHRjbGFzc2VzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcblx0XHRcdFx0cmV0dXJuIGEubG9jYWxlQ29tcGFyZShiKTtcblx0XHRcdH0pO1xuXG5cdFx0XHR0aGlzLl9jbGFzc0ZpbHRlckRELnNldERhdGFTb3VyY2UoY2xhc3Nlcyk7XG5cdFx0XHR0aGlzLl9jbGFzc0ZpbHRlckRELnNlbGVjdCgwKTtcblxuXHRcdFx0Ly8gQXNzaWduIGRhdGEgc291cmNlIHRvIGdyaWRcblx0XHRcdGxldCBkcyA9IG5ldyBrZW5kby5kYXRhLkRhdGFTb3VyY2Uoe1xuXHRcdFx0XHRkYXRhOiBkc0FyclxuXHRcdFx0fSlcblxuXHRcdFx0dGhpcy5fc2V0UnVudGltZUxvZ0RhdGFTb3VyY2UoZHMpO1xuXG5cdFx0XHQvLyBSZS1lbmFibGUgbG9nIGxvYWRpbmcgY29udHJvbHNcblx0XHRcdHRoaXMuX2VuYWJsZVJ1bnRpbWVMb2dDb250cm9scyh0cnVlKTtcblxuXHRcdFx0Ly8gUmVtb3ZlIGxvYWRpbmcgYmFyXG5cdFx0XHR0aGlzLl9zd2l0Y2hSdW50aW1lVmlld1N0YWNrKCdsZ3YtcnVudGltZUxvZ1ZpZXcnKTtcblx0XHR9XG5cblx0XHQvLyBCb290IGxvZyByZWNlaXZlZFxuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0JPT1RfTE9HKVxuXHRcdHtcblx0XHRcdGNvbnN0IGJvb3RMb2dFbnRyaWVzID0gZGF0YS5nZXRTRlNBcnJheSh0aGlzLkxPR19EQVRBX0xBQkVMKTtcblx0XHRcdGxldCB0ZXh0ID0gJyc7XG5cblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgYm9vdExvZ0VudHJpZXMuc2l6ZSgpOyBpKyspXG5cdFx0XHRcdHRleHQgKz0gYm9vdExvZ0VudHJpZXMuZ2V0VXRmU3RyaW5nKGkpICsgJ1xcbic7XG5cblx0XHRcdCQoJyNsZ3YtYm9vdExvZ1RleHQnKS50ZXh0KHRleHQpO1xuXG5cdFx0XHQvLyBSZW1vdmUgbG9hZGluZyBiYXJcblx0XHRcdHRoaXMuX3N3aXRjaEJvb3RWaWV3U3RhY2soJ2xndi1ib290TG9nVmlldycpO1xuXHRcdH1cblxuXHRcdC8vIExvZ3MgYmFja3VwcyBzdGF0dXMgcmVjZWl2ZWRcblx0XHRlbHNlIGlmIChjb21tYW5kID09IHRoaXMuUkVTUF9CQUNLVVBTX1NUQVRVUylcblx0XHR7XG5cdFx0XHQvLyBTaG93L2hpZGUgb3BlcmF0aW9uIGluIHByb2dyZXNzIG1lc3NhZ2Vcblx0XHRcdHRoaXMuX2Rpc2FibGVCYWNrdXBJbnRlcmZhY2UoZGF0YS5nZXRCb29sKCdydW5uaW5nJyksIGRhdGEuZ2V0VXRmU3RyaW5nKCd0eXBlJykpO1xuXG5cdFx0XHQvLyBCYWNrdXAgZmlsZXMgbGlzdFxuXHRcdFx0aWYgKGRhdGEuY29udGFpbnNLZXkoJ2ZpbGVzJykpXG5cdFx0XHR7XG5cdFx0XHRcdGxldCBmaWxlcyA9IGRhdGEuZ2V0U0ZTQXJyYXkoJ2ZpbGVzJyk7XG5cblx0XHRcdFx0bGV0IGxhc3RCb290TG9nQmFja3VwRm91bmQgPSBmYWxzZTtcblx0XHRcdFx0bGV0IGxhc3RSdW50aW1lTG9nQmFja3VwRm91bmQgPSBmYWxzZTtcblx0XHRcdFx0bGV0IGxhc3RGdWxsQmFja3VwRm91bmQgPSBmYWxzZTtcblxuXHRcdFx0XHRsZXQgYmFja3Vwc0xpc3QgPSBbXTtcblxuXHRcdFx0XHRjb25zdCB3ZWJTZXJ2ZXJQcm90b2NvbCA9IChkYXRhLmNvbnRhaW5zS2V5KCdwcm90b2NvbCcpID8gZGF0YS5nZXRVdGZTdHJpbmcoJ3Byb3RvY29sJykgOiAnaHR0cCcpICsgJzovLyc7XG5cdFx0XHRcdGNvbnN0IHdlYlNlcnZlclBvcnQgPSAoZGF0YS5jb250YWluc0tleSgncG9ydCcpID8gJzonICsgZGF0YS5nZXRJbnQoJ3BvcnQnKSA6ICcnKTtcblxuXHRcdFx0XHRsZXQgdG90YWxTaXplID0gMDtcblxuXHRcdFx0XHRmb3IgKGxldCBmID0gMDsgZiA8IGZpbGVzLnNpemUoKTsgZisrKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0Y29uc3QgZmlsZSA9IGZpbGVzLmdldFNGU09iamVjdChmKTtcblxuXHRcdFx0XHRcdGNvbnN0IGZpbGVQYXRoID0gZmlsZS5nZXRVdGZTdHJpbmcoJ3BhdGgnKTtcblxuXHRcdFx0XHRcdGNvbnN0IGZpbGVPYmogPSB7fTtcblx0XHRcdFx0XHRmaWxlT2JqLnBhdGggPSBmaWxlUGF0aDtcblx0XHRcdFx0XHRmaWxlT2JqLnVybCA9IHdlYlNlcnZlclByb3RvY29sICsgdGhpcy5zbWFydEZveC5jb25maWcuaG9zdCArIHdlYlNlcnZlclBvcnQgKyAnLycgKyBmaWxlUGF0aDtcblx0XHRcdFx0XHRmaWxlT2JqLm5hbWUgPSBmaWxlUGF0aC5zdWJzdHIoZmlsZVBhdGgubGFzdEluZGV4T2YoJy8nKSArIDEpO1xuXHRcdFx0XHRcdGZpbGVPYmouZGF0ZSA9IGZpbGUuZ2V0VXRmU3RyaW5nKCdkYXRlJyk7XG5cdFx0XHRcdFx0ZmlsZU9iai50aW1lID0gZmlsZS5nZXRVdGZTdHJpbmcoJ3RpbWUnKTtcblx0XHRcdFx0XHRmaWxlT2JqLnNpemUgPSBieXRlc1RvU2l6ZShmaWxlLmdldExvbmcoJ3NpemUnKSwgMik7XG5cblx0XHRcdFx0XHR0b3RhbFNpemUgKz0gZmlsZS5nZXRMb25nKCdzaXplJyk7XG5cblx0XHRcdFx0XHQvLyBDaGVjayBpZiB0aGlzIGlzIGEgYm9vdCBsb2cgYmFja3VwXG5cdFx0XHRcdFx0aWYgKCFsYXN0Qm9vdExvZ0JhY2t1cEZvdW5kKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGlmIChmaWxlT2JqLm5hbWUuc3RhcnRzV2l0aCh0aGlzLkJPT1RfTE9HX0JBQ0tVUF9JRCkpXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdHRoaXMuX2ZpbGxCYWNrdXBDYXJkKCcjbGd2LWJvb3RMb2dCYWNrdXBDYXJkJywgZmlsZU9iaik7XG5cblx0XHRcdFx0XHRcdFx0bGFzdEJvb3RMb2dCYWNrdXBGb3VuZCA9IHRydWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gQ2hlY2sgaWYgdGhpcyBpcyBhIHJ1bnRpbWUgbG9nIGJhY2t1cFxuXHRcdFx0XHRcdGlmICghbGFzdFJ1bnRpbWVMb2dCYWNrdXBGb3VuZClcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRpZiAoZmlsZU9iai5uYW1lLnN0YXJ0c1dpdGgodGhpcy5SVU5USU1FX0xPR19CQUNLVVBfSUQpKVxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHR0aGlzLl9maWxsQmFja3VwQ2FyZCgnI2xndi1ydW50aW1lTG9nQmFja3VwQ2FyZCcsIGZpbGVPYmopO1xuXG5cdFx0XHRcdFx0XHRcdGxhc3RSdW50aW1lTG9nQmFja3VwRm91bmQgPSB0cnVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIENoZWNrIGlmIHRoaXMgaXMgYSBmdWxsIGJhY2t1cFxuXHRcdFx0XHRcdGlmICghbGFzdEZ1bGxCYWNrdXBGb3VuZClcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRpZiAoZmlsZU9iai5uYW1lLnN0YXJ0c1dpdGgodGhpcy5GVUxMX0JBQ0tVUF9JRCkpXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdHRoaXMuX2ZpbGxCYWNrdXBDYXJkKCcjbGd2LWZ1bGxMb2dCYWNrdXBDYXJkJywgZmlsZU9iaik7XG5cblx0XHRcdFx0XHRcdFx0bGFzdEZ1bGxCYWNrdXBGb3VuZCA9IHRydWU7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gUG9wdWxhdGUgbG9ncyBsaXN0XG5cdFx0XHRcdFx0YmFja3Vwc0xpc3QucHVzaChmaWxlT2JqKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFNob3cgdG90YWwgYmFja3VwcyBzaXplXG5cdFx0XHRcdCQoJyNsZ3YtbG9nU2l6ZUxiJykuaHRtbChgVG90YWwgc2l6ZTogPHN0cm9uZz4ke2J5dGVzVG9TaXplKHRvdGFsU2l6ZSwgMiwgJ0tCJyl9PC9zdHJvbmc+YCk7XG5cblx0XHQgICBcdFx0Ly8gQXNzaWduIGRhdGEgc291cmNlIHRvIGdyaWRcblx0XHRcdFx0dGhpcy5fc2V0RG93bmxvYWRHcmlkRGF0YVNvdXJjZShiYWNrdXBzTGlzdCk7XG5cdFx0XHRcdHRoaXMuX29uRG93bmxvYWRHcmlkU2VsZWN0aW9uQ2hhbmdlKCk7XG5cblx0XHRcdFx0Ly8gSGlkZSBsaW5rcyB0byBsYXRlc3QgZmlsZXMgaWYgbm90IGF2YWlsYWJsZVxuXHRcdFx0XHRpZiAoIWxhc3RCb290TG9nQmFja3VwRm91bmQpXG5cdFx0XHRcdFx0dGhpcy5fZmlsbEJhY2t1cENhcmQoJyNsZ3YtYm9vdExvZ0JhY2t1cENhcmQnLCBudWxsKTtcblxuXHRcdFx0XHRpZiAoIWxhc3RSdW50aW1lTG9nQmFja3VwRm91bmQpXG5cdFx0XHRcdFx0dGhpcy5fZmlsbEJhY2t1cENhcmQoJyNsZ3YtcnVudGltZUxvZ0JhY2t1cENhcmQnLCBudWxsKTtcblxuXHRcdFx0XHRpZiAoIWxhc3RGdWxsQmFja3VwRm91bmQpXG5cdFx0XHRcdFx0dGhpcy5fZmlsbEJhY2t1cENhcmQoJyNsZ3YtZnVsbExvZ0JhY2t1cENhcmQnLCBudWxsKTtcblxuXHRcdFx0XHRpZiAoZGF0YS5jb250YWluc0tleSgnbWVzc2FnZScpKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0Ly8gRGlzcGxheSBub3RpZmljYXRpb25cblx0XHRcdFx0XHR0aGlzLnNoZWxsQ3RybC5zaG93Tm90aWZpY2F0aW9uKGBMb2cgYmFja3VwIHdhcm5pbmdgLCBkYXRhLmdldFV0ZlN0cmluZygnbWVzc2FnZScpKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBTZXQgZG93bmxvYWQgdmlldyB0byBtYWluXG5cdFx0XHR0aGlzLl9zd2l0Y2hEb3dubG9hZFZpZXdTdGFjaygnbGd2LWRvd25sb2FkVmlldycpO1xuXHRcdH1cblxuXHRcdC8vIExvZ3MgYmFja3VwIGRlbGV0aW9uIGZhaWxlZFxuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0RFTEVURV9CQUNLVVBfRkFJTEVEKVxuXHRcdHtcblx0XHRcdGNvbnN0IGVycm9yID0gZGF0YS5nZXRVdGZTdHJpbmcoJ2Vycm9yJyk7XG5cblx0XHRcdC8vIFNob3cgYW4gYWxlcnRcblx0XHRcdHRoaXMuc2hlbGxDdHJsLnNob3dTaW1wbGVBbGVydChlcnJvciwgdHJ1ZSk7XG5cdFx0fVxuXG5cdFx0Ly8gQSBibG9ja2luZyBlcnJvciBvY2N1cnJlZCBkdXJpbmcgYmFja3VwIG9wZXJhdGlvblxuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0JBQ0tVUF9FUlJPUilcblx0XHR7XG5cdFx0XHRjb25zdCBlcnJvciA9IGRhdGEuZ2V0VXRmU3RyaW5nKCdlcnJvcicpO1xuXG5cdFx0XHQvLyBTaG93IGFuIGFsZXJ0XG5cdFx0XHR0aGlzLnNoZWxsQ3RybC5zaG93U2ltcGxlQWxlcnQoZXJyb3IsIHRydWUpO1xuXHRcdH1cblxuXHRcdC8vIEFuIG5vbi1ibG9ja2luZyBlcnJvciBvY2N1cnJlZCBkdXJpbmcgYmFja3VwIG9wZXJhdGlvblxuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0JBQ0tVUF9XQVJOSU5HKVxuXHRcdHtcblx0XHRcdGxldCB3YXJuID0gZGF0YS5nZXRVdGZTdHJpbmcoJ3dhcm4nKTtcblxuXHRcdFx0Ly8gRGlzcGxheSBub3RpZmljYXRpb25cblx0XHRcdHRoaXMuc2hlbGxDdHJsLnNob3dOb3RpZmljYXRpb24oYExvZyBiYWNrdXAgd2FybmluZ2AsIHdhcm4pO1xuXHRcdH1cblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIFVJIEVWRU5UIExJU1RFTkVSU1xuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdF9vblRhYlNob3duKGUpXG5cdHtcblx0XHRpZiAoIXRoaXMuX2luaXRGYWlsZWQpXG5cdFx0e1xuXHRcdFx0Ly8gSWYgYm9vdCBsb2cgdmlldyB3YXMgZGlzcGxheWVkLi4uXG5cdFx0XHRpZiAoZS50YXJnZXQuaWQgPT0gJ2xndi1ib290TG9nLXRhYicpXG5cdFx0XHR7XG5cdFx0XHRcdC8vIExvYWQgYm9vdCBsb2cgdGhlIGZpcnN0IHRpbWUgdGhlIHRhYiBpcyBzZWxlY3RlZFxuXHRcdFx0XHRpZiAoIXRoaXMuX2Jvb3RMb2dSZXF1ZXN0ZWQpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX0dFVF9CT09UX0xPRyk7XG5cdFx0XHRcdFx0dGhpcy5fYm9vdExvZ1JlcXVlc3RlZCA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gSWYgYmFja3VwJmRvd2xvYWQgdmlldyB3YXMgZGlzcGxheWVkLi4uXG5cdFx0XHRlbHNlIGlmIChlLnRhcmdldC5pZCA9PSAnbGd2LWxvZ3NEb3dubG9hZC10YWInKVxuXHRcdFx0e1xuXHRcdFx0XHQvLyBSZXF1ZXN0IGxvZ3MgYmFja3VwIHN0YXR1cyB0aGUgZmlyc3QgdGltZSB0aGUgdGFiIGlzIHNlbGVjdGVkXG5cdFx0XHRcdGlmICghdGhpcy5fYmFja3VwU3RhdHVzUmVxdWVzdGVkKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9HRVRfQkFDS1VQU19TVEFUVVMpO1xuXHRcdFx0XHRcdHRoaXMuX2JhY2t1cFN0YXR1c1JlcXVlc3RlZCA9IHRydWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRfb25SdW50aW1lTG9nTG9hZEJ0Q2xpY2soKVxuXHR7XG5cdFx0Ly8gUmVxdWVzdCBsb2dcblx0XHR0aGlzLl9sb2FkUnVudGltZUxvZygpO1xuXHR9XG5cblx0X29uRXhwb3J0Qm9vdExvZ0J0Q2xpY2soKVxuXHR7XG5cdFx0Ly8gRXhwb3J0IGxvZyB0byBmaWxlXG5cdFx0dGhpcy5fZXhwb3J0TG9nKCQoJyNsZ3YtYm9vdExvZ1RleHQnKS50ZXh0KCksIHRoaXMuQk9PVF9MT0dfQkFDS1VQX0lEKTtcblx0fVxuXG5cdF9vblN3aXRjaEJvb3RMb2dDb2xvckJ0Q2xpY2soKVxuXHR7XG5cdFx0aWYgKCQoJyNsZ3YtYm9vdExvZ1RleHQnKS5oYXNDbGFzcygnaW52ZXJ0JykpXG5cdFx0XHQkKCcjbGd2LWJvb3RMb2dUZXh0JykucmVtb3ZlQ2xhc3MoJ2ludmVydCcpO1xuXHRcdGVsc2Vcblx0XHRcdCQoJyNsZ3YtYm9vdExvZ1RleHQnKS5hZGRDbGFzcygnaW52ZXJ0Jyk7XG5cdH1cblxuXHRfb25Cb290TG9nR2VuZXJhdGVCdENsaWNrKClcblx0e1xuXHRcdC8vIFNob3cvaGlkZSBvcGVyYXRpb24gaW4gcHJvZ3Jlc3MgbWVzc2FnZVxuXHRcdHRoaXMuX2Rpc2FibGVCYWNrdXBJbnRlcmZhY2UodHJ1ZSwgdGhpcy5CT09UX0xPR19CQUNLVVBfSUQpO1xuXG5cdFx0Ly8gUmVxdWVzdCBiYWNrdXAgZ2VuZXJhdGlvblxuXHRcdHRoaXMuc2VuZEV4dGVuc2lvblJlcXVlc3QodGhpcy5SRVFfQkFDS1VQX0JPT1RfTE9HKTtcblx0fVxuXG5cdF9vblJ1bnRpbWVMb2dHZW5lcmF0ZUJ0Q2xpY2soKVxuXHR7XG5cdFx0Ly8gU2hvdy9oaWRlIG9wZXJhdGlvbiBpbiBwcm9ncmVzcyBtZXNzYWdlXG5cdFx0dGhpcy5fZGlzYWJsZUJhY2t1cEludGVyZmFjZSh0cnVlLCB0aGlzLlJVTlRJTUVfTE9HX0JBQ0tVUF9JRCk7XG5cblx0XHQvLyBSZXF1ZXN0IGJhY2t1cCBnZW5lcmF0aW9uXG5cdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9CQUNLVVBfUlVOVElNRV9MT0cpO1xuXHR9XG5cblx0X29uRnVsbExvZ3NHZW5lcmF0ZUJ0Q2xpY2soKVxuXHR7XG5cdFx0Ly8gU2hvdy9oaWRlIG9wZXJhdGlvbiBpbiBwcm9ncmVzcyBtZXNzYWdlXG5cdFx0dGhpcy5fZGlzYWJsZUJhY2t1cEludGVyZmFjZSh0cnVlLCB0aGlzLkZVTExfQkFDS1VQX0lEKTtcblxuXHRcdC8vIFJlcXVlc3QgYmFja3VwIGdlbmVyYXRpb25cblx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX0JBQ0tVUF9GVUxMX0xPR1MpO1xuXHR9XG5cblx0X29uRmlsdGVyQ2hhbmdlKClcblx0e1xuXHRcdC8vIFNldCBmaWx0ZXJzXG5cdFx0dGhpcy5fc2V0UnVudGltZUxvZ0RhdGFTb3VyY2UodGhpcy5fcnVudGltZUxvZ0dyaWQuZGF0YVNvdXJjZSk7XG5cdH1cblxuXHRfb25DbGVhckZpbHRlckNsaWNrKClcblx0e1xuXHRcdHRoaXMuX2NsZWFyUnVudGltZUxvZ0ZpbHRlcnMoKTtcblx0XHR0aGlzLl9zZXRSdW50aW1lTG9nRGF0YVNvdXJjZSh0aGlzLl9ydW50aW1lTG9nR3JpZC5kYXRhU291cmNlKTtcblx0fVxuXG5cdF9vbkV4cG9ydFJ1bnRpbWVMb2dCdENsaWNrKClcblx0e1xuXHRcdGxldCBsb2cgPSAnJztcblx0XHRjb25zdCBlbnRyaWVzID0gdGhpcy5fcnVudGltZUxvZ0dyaWQuZGF0YVNvdXJjZS52aWV3KCk7XG5cblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGVudHJpZXMubGVuZ3RoOyBpKyspXG5cdFx0e1xuXHRcdFx0Y29uc3QgaXRlbSA9IGVudHJpZXNbaV07XG5cdFx0XHRsb2cgKz0gW2l0ZW0uZGF0ZSwgaXRlbS50aW1lLCBpdGVtLmxldmVsLCBpdGVtLnRocmVhZCwgaXRlbS5jbGF6eiwgaXRlbS5tZXNzYWdlXS5qb2luKGl0ZW0uc2VwKSArICdcXG4nO1xuXHRcdH1cblxuXHRcdC8vIEV4cG9ydCBsb2cgdG8gZmlsZVxuXHRcdHRoaXMuX2V4cG9ydExvZyhsb2csIHRoaXMuUlVOVElNRV9MT0dfQkFDS1VQX0lEKTtcblx0fVxuXG5cdF9vbkRvd25sb2FkR3JpZFNlbGVjdGlvbkNoYW5nZSgpXG5cdHtcblx0XHQvLyBFbmFibGUvZGlzYWJsZSBidXR0b25zXG5cdFx0Y29uc3Qgc2VsZWN0ZWRSb3dzID0gdGhpcy5fZG93bmxvYWRHcmlkLnNlbGVjdCgpO1xuXHRcdCQoJyNsZ3YtZG93bmxvYWRCdCcpLmF0dHIoJ2Rpc2FibGVkJywgc2VsZWN0ZWRSb3dzLmxlbmd0aCA9PSAwKTtcblx0XHQkKCcjbGd2LWRlbGV0ZUJ0JykuYXR0cignZGlzYWJsZWQnLCBzZWxlY3RlZFJvd3MubGVuZ3RoID09IDApO1xuXG5cdFx0aWYgKHNlbGVjdGVkUm93cy5sZW5ndGggPiAwKVxuXHRcdHtcblx0XHRcdGxldCBkYXRhSXRlbSA9IHRoaXMuX2Rvd25sb2FkR3JpZC5kYXRhSXRlbShzZWxlY3RlZFJvd3NbMF0pO1xuXHRcdFx0JCgnI2xndi1kb3dubG9hZEJ0JykuYXR0cignaHJlZicsIGRhdGFJdGVtLnVybCk7XG5cdFx0fVxuXHRcdGVsc2Vcblx0XHRcdCQoJyNsZ3YtZG93bmxvYWRCdCcpLmF0dHIoJ2hyZWYnLCAnIycpO1xuXHR9XG5cblx0X29uRGVsZXRlQnRDbGljaygpXG5cdHtcblx0XHRsZXQgc2VsZWN0ZWRSb3dzID0gdGhpcy5fZG93bmxvYWRHcmlkLnNlbGVjdCgpO1xuXG5cdFx0aWYgKHNlbGVjdGVkUm93cy5sZW5ndGggPiAwKVxuXHRcdHtcblx0XHRcdGxldCBkYXRhSXRlbSA9IHRoaXMuX2Rvd25sb2FkR3JpZC5kYXRhSXRlbShzZWxlY3RlZFJvd3NbMF0pO1xuXG5cdFx0XHQvLyBSZXF1ZXN0IGJhY2t1cCBkZWxldGlvblxuXHRcdFx0bGV0IHBhcmFtcyA9IG5ldyBTRlMyWC5TRlNPYmplY3QoKTtcblx0XHRcdHBhcmFtcy5wdXRVdGZTdHJpbmcoJ2ZpbGUnLCBkYXRhSXRlbS5uYW1lKTtcblxuXHRcdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9ERUxFVEVfQkFDS1VQLCBwYXJhbXMpO1xuXHRcdH1cblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIFBSSVZBVEUgTUVUSE9EU1xuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdF9zd2l0Y2hSdW50aW1lVmlld1N0YWNrKHZpZXdJZClcblx0e1xuXHRcdGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdsZ3YtcnVudGltZS12aWV3c3RhY2snKS5zZWxlY3RlZEVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh2aWV3SWQpO1xuXHR9XG5cblx0X3N3aXRjaEJvb3RWaWV3U3RhY2sodmlld0lkKVxuXHR7XG5cdFx0ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2xndi1ib290LXZpZXdzdGFjaycpLnNlbGVjdGVkRWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHZpZXdJZCk7XG5cdH1cblxuXHRfc3dpdGNoRG93bmxvYWRWaWV3U3RhY2sodmlld0lkKVxuXHR7XG5cdFx0ZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2xndi1kb3dubG9hZC12aWV3c3RhY2snKS5zZWxlY3RlZEVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh2aWV3SWQpO1xuXHR9XG5cblx0X2VuYWJsZVJ1bnRpbWVMb2dDb250cm9scyhlbmFibGUpXG5cdHtcblx0XHQkKCcjbGd2LWxvYWRCdCcpLmF0dHIoJ2Rpc2FibGVkJywgIWVuYWJsZSk7XG5cdFx0JCgnI2xndi1leHBvcnRSdW50aW1lTG9nQnQnKS5hdHRyKCdkaXNhYmxlZCcsICFlbmFibGUpO1xuXHRcdCQoJyNsZ3YtZmlsdGVyQnQnKS5hdHRyKCdkaXNhYmxlZCcsICFlbmFibGUpO1xuXHR9XG5cblx0X2xvYWRSdW50aW1lTG9nKClcblx0e1xuXHRcdC8vIERpc2FibGUgY29udHJvbHMgdG8gbG9hZCBsb2csIHNvIHRoYXQgaW1wYXRpZW50IHVzZXJzIGNhbid0IHNlbmQgbXVsdGlwbGUgcmVxdWVzdHNcblx0XHQvLyAoaXQgd2lsbCBiZSBlbmFibGVkIGFnYWluIHdoZW4gYSByZXNwb25zZSBpcyByZWNlaXZlZClcblx0XHR0aGlzLl9lbmFibGVSdW50aW1lTG9nQ29udHJvbHMoZmFsc2UpO1xuXG5cdFx0Ly8gQ2xlYXIgZmlsdGVyc1xuXHRcdHRoaXMuX2NsZWFyUnVudGltZUxvZ0ZpbHRlcnMoKTtcblxuXHRcdC8vIFNob3cgbG9hZGluZyBiYXJcblx0XHR0aGlzLl9zd2l0Y2hSdW50aW1lVmlld1N0YWNrKCdsZ3YtcnVudGltZUxvZ0xvYWRpbmdWaWV3Jyk7XG5cblx0XHQvLyBTZW5kIHJlcXVlc3Rcblx0XHQvLyAodGhlIG51bWJlciBvZiBsaW5lcyB0byBiZSByZXRyaWV2ZWQgaXMgc2VudClcblx0XHRsZXQgcGFyYW1zID0gbmV3IFNGUzJYLlNGU09iamVjdCgpO1xuXHRcdHBhcmFtcy5wdXRJbnQoJ251bUVudHJpZXMnLCBOdW1iZXIodGhpcy5fbG9nTGluZXNERC52YWx1ZSgpKSk7XG5cblx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX0dFVF9SVU5USU1FX0xPRywgcGFyYW1zKTtcblx0fVxuXG5cdF9jbGVhclJ1bnRpbWVMb2dGaWx0ZXJzKClcblx0e1xuXHRcdHRoaXMuX2xldmVsRmlsdGVyREQuc2VsZWN0KDApO1xuXHRcdHRoaXMuX2NsYXNzRmlsdGVyREQuc2VsZWN0KDApO1xuXHRcdCQoJyNsZ3YtbWVzc2FnZUluJykudmFsKCcnKTtcblx0fVxuXG5cdF9leHBvcnRMb2cobG9nLCBuYW1lKVxuXHR7XG5cdFx0bGV0IGJsb2IgPSBuZXcgQmxvYihbbG9nXSwge3R5cGU6IFwidGV4dC9wbGFpbjtjaGFyc2V0PXV0Zi04XCJ9KTtcblx0XHRsZXQgZGF0ZSA9IG1vbWVudCgpLmZvcm1hdCgnWVlZWU1NRERfSEhtbXNzJyk7XG5cblx0XHRGaWxlU2F2ZXIuc2F2ZUFzKGJsb2IsIGAke25hbWV9XyR7ZGF0ZX0ubG9nYCk7XG5cdH1cblxuXHRfc2V0UnVudGltZUxvZ0RhdGFTb3VyY2UoZHMpXG5cdHtcblx0XHQvLyBSZWFkIGN1cnJlbnQgaG9yaXpvbnRhbCBzY3JvbGwgdmFsdWVcblx0XHRjb25zdCBzY3JvbGxMZWZ0ID0gJCgnI2xndi1ydW50aW1lTG9nR3JpZCAuay1ncmlkLWNvbnRlbnQnLCB0aGlzLl9ydW50aW1lTG9nR3JpZC53cmFwcGVyKS5zY3JvbGxMZWZ0KCk7XG5cblx0XHQvLyBBc3NpZ24gZGF0YSBzb3VyY2UgdG8gZ3JpZFxuXHRcdHRoaXMuX3J1bnRpbWVMb2dHcmlkLnNldERhdGFTb3VyY2UoZHMpO1xuXG5cdFx0Ly8gU2V0IGZpbHRlcnNcblx0XHR0aGlzLl9zZXRGaWx0ZXJzKGRzKTtcblxuXHRcdC8vIFNldCBob3Jpem9udGFsIHNjcm9sbFxuXHRcdCQoJyNsZ3YtcnVudGltZUxvZ0dyaWQgLmstZ3JpZC1jb250ZW50JywgdGhpcy5fcnVudGltZUxvZ0dyaWQud3JhcHBlcikuc2Nyb2xsTGVmdChzY3JvbGxMZWZ0KTtcblxuXHRcdC8vIFVwZGF0ZSBjb3VudGVyXG5cdFx0JCgnI2xndi1ydW50aW1lTG9nRW50cmllc0xiJykudGV4dChgTG9nIGVudHJpZXM6ICR7dGhpcy5fdG90YWxSdW50aW1lTG9nRW50cmllc30gKCR7ZHMudG90YWwoKX0gZGlzcGxheWVkKWApO1xuXHR9XG5cblx0X3NldEZpbHRlcnMoZHMpXG5cdHtcblx0XHRsZXQgZmlsdGVycyA9IFtdO1xuXG5cdFx0Ly8gTGV2ZWwgZmlsdGVyaW5nXG5cdFx0aWYgKHRoaXMuX2xldmVsRmlsdGVyREQuc2VsZWN0KCkgPiAwKVxuXHRcdFx0ZmlsdGVycy5wdXNoKHtcblx0XHRcdFx0ZmllbGQ6ICdsZXZlbCcsIG9wZXJhdG9yOiAnZXEnLCB2YWx1ZTogdGhpcy5fbGV2ZWxGaWx0ZXJERC52YWx1ZSgpXG5cdFx0XHR9KTtcblxuXHRcdC8vIENsYXNzIGZpbHRlcmluZ1xuXHRcdGlmICh0aGlzLl9jbGFzc0ZpbHRlckRELnNlbGVjdCgpID4gMClcblx0XHRcdGZpbHRlcnMucHVzaCh7XG5cdFx0XHRcdGZpZWxkOiAnY2xhenonLCBvcGVyYXRvcjogJ2VxJywgdmFsdWU6IHRoaXMuX2NsYXNzRmlsdGVyREQudmFsdWUoKVxuXHRcdFx0fSk7XG5cblx0XHQvLyBNZXNzYWdlIGZpbHRlcmluZ1xuXHRcdGlmICgkKCcjbGd2LW1lc3NhZ2VJbicpLnZhbCgpICE9ICcnKVxuXHRcdFx0ZmlsdGVycy5wdXNoKHtcblx0XHRcdFx0ZmllbGQ6ICdtZXNzYWdlJywgb3BlcmF0b3I6ICdjb250YWlucycsIHZhbHVlOiAkKCcjbGd2LW1lc3NhZ2VJbicpLnZhbCgpXG5cdFx0XHR9KTtcblxuXHRcdC8vIFNldCBmaWx0ZXJzXG5cdFx0ZHMuZmlsdGVyKGZpbHRlcnMpO1xuXHR9XG5cblx0X2Rpc2FibGVCYWNrdXBJbnRlcmZhY2UoZGlzYWJsZSwgYmFja3VwSWQgPSBudWxsKVxuXHR7XG5cdFx0aWYgKGRpc2FibGUpXG5cdFx0e1xuXHRcdFx0Ly8gU2hvdyBwcm9wZXIgcHJvZ3Jlc3MgYmFyXG5cdFx0XHRpZiAoYmFja3VwSWQgPT0gdGhpcy5CT09UX0xPR19CQUNLVVBfSUQpXG5cdFx0XHRcdCQoJyNsZ3YtYm9vdExvZ0JhY2t1cENhcmQgLnByb2dyZXNzLWJhcicpLnNob3coKTtcblx0XHRcdGVsc2UgaWYgKGJhY2t1cElkID09IHRoaXMuUlVOVElNRV9MT0dfQkFDS1VQX0lEKVxuXHRcdFx0XHQkKCcjbGd2LXJ1bnRpbWVMb2dCYWNrdXBDYXJkIC5wcm9ncmVzcy1iYXInKS5zaG93KCk7XG5cdFx0XHRlbHNlIGlmIChiYWNrdXBJZCA9PSB0aGlzLkZVTExfQkFDS1VQX0lEKVxuXHRcdFx0XHQkKCcjbGd2LWZ1bGxMb2dCYWNrdXBDYXJkIC5wcm9ncmVzcy1iYXInKS5zaG93KCk7XG5cblx0XHRcdC8vIERpc2FibGUgYnV0dG9uc1xuXHRcdFx0JCgnI2xndi1ib290TG9nQmFja3VwQ2FyZCAuYmFja3VwLWJ1dHRvbicpLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cdFx0XHQkKCcjbGd2LXJ1bnRpbWVMb2dCYWNrdXBDYXJkIC5iYWNrdXAtYnV0dG9uJykuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcblx0XHRcdCQoJyNsZ3YtZnVsbExvZ0JhY2t1cENhcmQgLmJhY2t1cC1idXR0b24nKS5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuXHRcdH1cblx0XHRlbHNlXG5cdFx0e1xuXHRcdFx0Ly8gSGlkZSBhbGwgcHJvZ3Jlc3MgYmFyXG5cdFx0XHQkKCcuY2FyZC1ib2R5IC5wcm9ncmVzcy1iYXInKS5oaWRlKCk7XG5cblx0XHRcdC8vIEVuYWJsZSBidXR0b25zXG5cdFx0XHQkKCcjbGd2LWZ1bGxMb2dCYWNrdXBDYXJkIC5iYWNrdXAtYnV0dG9uJykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cblx0XHRcdGlmICghdGhpcy5fYm9vdExvZ0JhY2t1cFVuYXZhaWxhYmxlKVxuXHRcdFx0XHQkKCcjbGd2LWJvb3RMb2dCYWNrdXBDYXJkIC5iYWNrdXAtYnV0dG9uJykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cblx0XHRcdGlmICghdGhpcy5fcnVudGltZUxvZ0JhY2t1cFVuYXZhaWxhYmxlKVxuXHRcdFx0XHQkKCcjbGd2LXJ1bnRpbWVMb2dCYWNrdXBDYXJkIC5iYWNrdXAtYnV0dG9uJykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cdFx0fVxuXHR9XG5cblx0X2luaXRCYWNrdXBDYXJkKGlkU2VsZWN0b3IpXG5cdHtcblx0XHQkKGlkU2VsZWN0b3IgKyAnIC5iYWNrdXAtZGV0YWlscycpLmhpZGUoKTtcblx0XHQkKGlkU2VsZWN0b3IgKyAnIC5wcm9ncmVzcy1iYXInKS5oaWRlKCk7XG5cdH1cblxuXHRfZmlsbEJhY2t1cENhcmQoaWRTZWxlY3RvciwgZGV0YWlsc09iaiA9IG51bGwpXG5cdHtcblx0XHRpZiAoZGV0YWlsc09iaiA9PSBudWxsKVxuXHRcdFx0JChpZFNlbGVjdG9yICsgJyAuYmFja3VwLWRldGFpbHMnKS5oaWRlKCk7XG5cdFx0ZWxzZVxuXHRcdHtcblx0XHRcdCQoaWRTZWxlY3RvciArICcgLmJhY2t1cC1kZXRhaWxzJykuc2hvdygpO1xuXG5cdFx0XHQkKGlkU2VsZWN0b3IgKyAnIC5iYWNrdXAtbGluaycpLmF0dHIoJ2hyZWYnLCBkZXRhaWxzT2JqLnVybCk7XG5cdFx0XHQkKGlkU2VsZWN0b3IgKyAnIC5iYWNrdXAtZGF0ZScpLnRleHQoZGV0YWlsc09iai5kYXRlKTtcblx0XHRcdCQoaWRTZWxlY3RvciArICcgLmJhY2t1cC10aW1lJykudGV4dChkZXRhaWxzT2JqLnRpbWUpO1xuXHRcdFx0JChpZFNlbGVjdG9yICsgJyAuYmFja3VwLXNpemUnKS50ZXh0KGRldGFpbHNPYmouc2l6ZSk7XG5cdFx0fVxuXHR9XG5cblx0X3NldERvd25sb2FkR3JpZERhdGFTb3VyY2UoZHMpXG5cdHtcblx0XHQvLyBSZWFkIGN1cnJlbnQgaG9yaXpvbnRhbCBzY3JvbGwgdmFsdWVcblx0ICAgY29uc3Qgc2Nyb2xsTGVmdCA9ICQoJyNsZ3YtZG93bmxvYWRHcmlkIC5rLWdyaWQtY29udGVudCcsIHRoaXMuX2Rvd25sb2FkR3JpZC53cmFwcGVyKS5zY3JvbGxMZWZ0KCk7XG5cblx0ICAgLy8gQXNzaWduIGRhdGEgc291cmNlIHRvIGdyaWRcblx0ICAgdGhpcy5fZG93bmxvYWRHcmlkLnNldERhdGFTb3VyY2UoZHMpO1xuXG5cdCAgIC8vIFNldCBob3Jpem9udGFsIHNjcm9sbFxuXHQgICAkKCcjbGd2LWRvd25sb2FkR3JpZCAuay1ncmlkLWNvbnRlbnQnLCB0aGlzLl9kb3dubG9hZEdyaWQud3JhcHBlcikuc2Nyb2xsTGVmdChzY3JvbGxMZWZ0KTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIFBSSVZBVEUgR0VUVEVSU1xuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cbn1cbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUNuQkE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQzFCQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBIiwic291cmNlUm9vdCI6IiJ9
|
2673
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXRzL2pzL2NvcmUvbW9kdWxlcy9tb2R1bGUtOC5idW5kbGUuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9jb21wb25lbnRzL2NoYXJ0cy9iYXNlLWNoYXJ0LmpzIiwid2VicGFjazovL2FwcGxpY2F0aW9uLy4vc3JjL2NvbXBvbmVudHMvY2hhcnRzL2NoYXJ0LXV0aWxzLmpzIiwid2VicGFjazovL2FwcGxpY2F0aW9uLy4vc3JjL2NvbXBvbmVudHMvY2hhcnRzL2NwdS11c2FnZS1jaGFydC5qcyIsIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9jb21wb25lbnRzL2NoYXJ0cy9tZW1vcnktY2hhcnQuanMiLCJ3ZWJwYWNrOi8vYXBwbGljYXRpb24vLi9zcmMvY29tcG9uZW50cy9jaGFydHMvbmV0d29yay0yNGgtY2hhcnQuanMiLCJ3ZWJwYWNrOi8vYXBwbGljYXRpb24vLi9zcmMvY29tcG9uZW50cy9jaGFydHMvbmV0d29yay1yZWFsdGltZS1jaGFydC5qcyIsIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9jb21wb25lbnRzL2NoYXJ0cy9zeXN0ZW0tcXVldWUtY2hhcnQuanMiLCJ3ZWJwYWNrOi8vYXBwbGljYXRpb24vLi9zcmMvY29tcG9uZW50cy9jaGFydHMvc3lzdGVtLXdvcmtsb2FkLWNoYXJ0LmpzIiwid2VicGFjazovL2FwcGxpY2F0aW9uLy4vc3JjL2NvbXBvbmVudHMvY2hhcnRzL3RocmVhZC1jb3VudC1jaGFydC5qcyIsIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9tb2R1bGVzL2Rhc2hib2FyZC5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgY2xhc3MgQmFzZUNoYXJ0IGV4dGVuZHMgSFRNTEVsZW1lbnRcbntcblx0Y29uc3RydWN0b3IobWF4VmFsdWVzKVxuXHR7XG5cdCAgICBzdXBlcigpO1xuXG5cdFx0dGhpcy5fbWF4VmFsdWVzID0gbWF4VmFsdWVzO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZVxuXHRcdHRoaXMuX2luaXRpYWxpemUoKTtcblx0fVxuXG5cdC8vIENhbiBiZSBvdmVycmlkZGVuXG5cdF9pbml0aWFsaXplKClcblx0e1xuXHRcdC8vIENyZWF0ZSBjaGFydCBodG1sXG5cdFx0bGV0IGNoYXJ0SHRtbCA9ICQoJzxkaXY+Jyk7XG5cdFx0JCh0aGlzKS5hcHBlbmQoY2hhcnRIdG1sKTtcblxuXHRcdHRoaXMuX2NoYXJ0V2lkZ2V0ID0gdGhpcy5faW5pdENoYXJ0V2lkZ2V0KGNoYXJ0SHRtbCk7XG5cblx0XHQvLyBSZXNldCBkYXRhIHNvdXJjZVxuXHRcdHRoaXMucmVzZXQoKTtcblx0fVxuXG5cdC8vIE1VU1QgQkUgT1ZFUlJJRERFTlxuXHRfaW5pdENoYXJ0V2lkZ2V0KClcblx0e1xuXHRcdHRocm93IG5ldyBFcnJvcignQ2hhcnQgd2lkZ2V0IG11c3QgYmUgaW5pdGlhbGl6ZWQhJylcblx0fVxuXG5cdHNldCBwYXVzZWQodmFsdWUpXG5cdHtcblx0XHR0aGlzLmlzUGF1c2VkID0gdmFsdWU7XG5cdFx0dGhpcy5fb25QYXVzZUNoYW5nZSgpO1xuXHR9XG5cblx0Z2V0IHBhdXNlZCgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5pc1BhdXNlZDtcblx0fVxuXG5cdHJlc2V0KClcblx0e1xuXHRcdHRoaXMuX2NoYXJ0V2lkZ2V0LnNldERhdGFTb3VyY2UoW10pO1xuXHR9XG5cblx0cmVkcmF3KClcblx0e1xuXHRcdHRoaXMuX2NoYXJ0V2lkZ2V0LnJlZHJhdygpO1xuXHR9XG5cblx0Z2V0TGFzdEVudHJ5KClcblx0e1xuXHRcdGxldCBkcztcblxuXHRcdGlmICh0aGlzLmlzUGF1c2VkKVxuXHRcdFx0ZHMgPSB0aGlzLl90ZW1wRFM7XG5cdFx0ZWxzZVxuXHRcdFx0ZHMgPSB0aGlzLl9kYXRhU291cmNlO1xuXG5cdFx0aWYgKGRzICE9IG51bGwgJiYgZHMudG90YWwoKSA+IDApXG5cdFx0XHRyZXR1cm4gZHMuYXQoZHMudG90YWwoKSAtIDEpO1xuXHRcdGVsc2Vcblx0XHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0X2FkZEVudHJ5KG5ld0VudHJ5KVxuXHR7XG5cdFx0aWYgKHRoaXMuaXNQYXVzZWQpXG5cdFx0e1xuXHRcdFx0aWYgKHRoaXMuX3RlbXBEUyA9PSBudWxsKVxuXHRcdFx0XHR0aGlzLl90ZW1wRFMgPSBuZXcga2VuZG8uZGF0YS5EYXRhU291cmNlKCk7XG5cblx0XHRcdC8vIFN0b3JlIG5ldyB2YWx1ZSBpbiBhIHRlbXBvcmFyeSBhcnJheVxuXHRcdFx0dGhpcy5fdGVtcERTLmFkZChuZXdFbnRyeSk7XG5cdFx0fVxuXHRcdGVsc2Vcblx0XHR7XG5cdFx0XHRsZXQgZHMgPSB0aGlzLl9kYXRhU291cmNlO1xuXG5cdFx0XHRpZiAodGhpcy5fdGVtcERTICE9IG51bGwpXG5cdFx0XHR7XG5cdFx0XHRcdC8vIENvbmNhdGVuYXRlIHRlbXBvcmFyeSBlbnRyaWVzIHRvIGFjdHVhbCBkYXRhIHNvdXJjZVxuXHRcdFx0XHRsZXQgbmV3QXJyID0gJC5tZXJnZShkcy5kYXRhKCksIHRoaXMuX3RlbXBEUy5kYXRhKCkpO1xuXG5cdFx0XHRcdC8vIFJlbW92ZSB2YWx1ZXMgZXhjZWVkaW5nIE1BWF9WQUxVRVNcblx0XHRcdFx0aWYgKG5ld0Fyci5sZW5ndGggPiB0aGlzLl9tYXhWYWx1ZXMpXG5cdFx0XHRcdFx0bmV3QXJyLnNwbGljZSgwLCBuZXdBcnIubGVuZ3RoIC0gdGhpcy5fbWF4VmFsdWVzKVxuXG5cdFx0XHRcdC8vIENyZWF0ZSBuZXcgZGF0YXNvdXJjZVxuXHRcdFx0XHRsZXQgbmV3RFMgPSBuZXcga2VuZG8uZGF0YS5EYXRhU291cmNlKHtkYXRhOiBuZXdBcnJ9KVxuXG5cdFx0XHRcdC8vIEFzc2lnbiBuZXcgZGF0YSBzb3VyY2UgdG8gY2hhcnRcblx0XHRcdFx0dGhpcy5fY2hhcnRXaWRnZXQuc2V0RGF0YVNvdXJjZShuZXdEUyk7XG5cblx0XHRcdFx0Ly8gUmVtb3ZlIHRlbXBvcmFyeSBhcnJheVxuXHRcdFx0XHR0aGlzLl90ZW1wRFMgPSBudWxsO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBZGQgbmV3IGVudHJ5XG5cdFx0XHRkcy5hZGQobmV3RW50cnkpO1xuXG5cdFx0XHQvLyBSZW1vdmUgZmlyc3QgaXRlbSBpZiBuZWVkZWRcblx0XHRcdGlmIChkcy50b3RhbCgpID4gdGhpcy5fbWF4VmFsdWVzKVxuXHRcdFx0XHRkcy5yZW1vdmUoZHMuYXQoMCkpO1xuXHRcdH1cblx0fVxuXG5cdGdldCBfZGF0YVNvdXJjZSgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fY2hhcnRXaWRnZXQuZGF0YVNvdXJjZTtcblx0fVxuXG5cdF9vblBhdXNlQ2hhbmdlKClcblx0e1xuXHRcdC8vIE5vdGhpbmcgdG8gZG8sIHNob3VsZCBiZSBvdmVycmlkZGVuXG5cdH1cbn1cblxuLy8gREVGSU5FIENPTVBPTkVOVFxuaWYgKCF3aW5kb3cuY3VzdG9tRWxlbWVudHMuZ2V0KCdiYXNlLWNoYXJ0JykpXG5cdHdpbmRvdy5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ2Jhc2UtY2hhcnQnLCBCYXNlQ2hhcnQpO1xuIiwiaW1wb3J0IHtieXRlc1RvU2l6ZSwga0J5dGVzVG9TaXplfSBmcm9tICcuLi8uLi91dGlscy91dGlsaXRpZXMnO1xuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Rm9ybWF0dGVkRGF0ZVRpbWUoZGF0ZSwgZm9ybWF0ID0gJ2RkIE1NTSBISDptbTpzcycpXG57XG5cdHJldHVybiBrZW5kby50b1N0cmluZyhkYXRlLCBmb3JtYXQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QmFzaWNTaGFyZWRUZW1wbGF0ZSh2YWx1ZUZvcm1hdCA9ICd7MH0nKSB7XG5cdHJldHVybiBrZW5kby50ZW1wbGF0ZShgXG5cdFx0PGRpdiBjbGFzcz1cImNoYXJ0LXRvb2x0aXAtY2F0ZWdvcnlcIj48c3Ryb25nPiM6IGNhdGVnb3J5ICM8L3N0cm9uZz48L2Rpdj5cblx0XHQjIGZvciAodmFyIGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7ICNcblx0XHQ8ZGl2PlxuXHRcdFx0PGkgY2xhc3M9XCJmYXMgZmEtc3F1YXJlXCIgc3R5bGU9XCJjb2xvcjogIzogcG9pbnRzW2ldLmNvbG9yICMgXCI+PC9pPlxuXHRcdFx0IzogcG9pbnRzW2ldLnNlcmllcy5uYW1lIyA6ICM6IGtlbmRvLmZvcm1hdCgnJHt2YWx1ZUZvcm1hdH0nLCBwb2ludHNbaV0udmFsdWUpICNcblx0XHQ8L2Rpdj5cblx0XHQjIH0gI1xuXHRgKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE1lbW9yeVNoYXJlZFRlbXBsYXRlKCkge1xuXHRyZXR1cm4gZnVuY3Rpb24oZGF0YUl0ZW0pIHtcblx0XHRkYXRhSXRlbS5ieXRlc1RvU2l6ZSA9IGJ5dGVzVG9TaXplOyAvLyBQYXNzIGJ5dGVzVG9TaXplIHV0aWxpdHkgZnVuY3Rpb24gdG8gdGVtcGxhdGVcblx0XHRyZXR1cm4ga2VuZG8udGVtcGxhdGUoYFxuXHRcdFx0PGRpdiBjbGFzcz1cImNoYXJ0LXRvb2x0aXAtY2F0ZWdvcnlcIj48c3Ryb25nPiM6IGNhdGVnb3J5ICM8L3N0cm9uZz48L2Rpdj5cblx0XHRcdCMgZm9yICh2YXIgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHsgI1xuXHRcdFx0PGRpdj5cblx0XHRcdFx0PGkgY2xhc3M9XCJmYXMgZmEtc3F1YXJlXCIgc3R5bGU9XCJjb2xvcjogIzogcG9pbnRzW2ldLmNvbG9yICMgXCI+PC9pPlxuXHRcdFx0XHQjOiBwb2ludHNbaV0uc2VyaWVzLm5hbWUjIDogIzogYnl0ZXNUb1NpemUocG9pbnRzW2ldLnZhbHVlKSAjXG5cdFx0XHQ8L2Rpdj5cblx0XHRcdCMgfSAjXG5cdFx0YCkoZGF0YUl0ZW0pO1xuXHR9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TWVtb3J5VmFsdWVBeGlzTGFiZWxUZW1wbGF0ZSgpIHtcblx0cmV0dXJuIGZ1bmN0aW9uKGRhdGFJdGVtKSB7XG5cdFx0ZGF0YUl0ZW0uYnl0ZXNUb1NpemUgPSBieXRlc1RvU2l6ZTsgLy8gUGFzcyBieXRlc1RvU2l6ZSB1dGlsaXR5IGZ1bmN0aW9uIHRvIHRlbXBsYXRlXG5cdFx0cmV0dXJuIGtlbmRvLnRlbXBsYXRlKGBcblx0XHRcdCM6IGJ5dGVzVG9TaXplKHZhbHVlKSAjXG5cdFx0YCkoZGF0YUl0ZW0pO1xuXHR9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TmV0d29ya1NoYXJlZFRlbXBsYXRlKGNhdGVnb3J5Rm9ybWF0ID0gJ2RkIE1NTSBISDptbTpzcycpIHtcblx0cmV0dXJuIGZ1bmN0aW9uKGRhdGFJdGVtKSB7XG5cdFx0ZGF0YUl0ZW0ua0J5dGVzVG9TaXplID0ga0J5dGVzVG9TaXplOyAvLyBQYXNzIGtCeXRlc1RvU2l6ZSB1dGlsaXR5IGZ1bmN0aW9uIHRvIHRlbXBsYXRlXG5cdFx0cmV0dXJuIGtlbmRvLnRlbXBsYXRlKGBcblx0XHRcdDxkaXYgY2xhc3M9XCJjaGFydC10b29sdGlwLWNhdGVnb3J5XCI+PHN0cm9uZz4jOiBrZW5kby50b1N0cmluZyhjYXRlZ29yeSwgJyR7Y2F0ZWdvcnlGb3JtYXR9JykgIzwvc3Ryb25nPjwvZGl2PlxuXHRcdFx0IyBmb3IgKHZhciBpID0gMDsgaSA8IHBvaW50cy5sZW5ndGg7IGkrKykgeyAjXG5cdFx0XHQ8ZGl2PlxuXHRcdFx0XHQ8aSBjbGFzcz1cImZhcyBmYS1zcXVhcmVcIiBzdHlsZT1cImNvbG9yOiAjOiBwb2ludHNbaV0uY29sb3IgIyBcIj48L2k+XG5cdFx0XHRcdCM6IHBvaW50c1tpXS5zZXJpZXMubmFtZSMgOiAjOiBrQnl0ZXNUb1NpemUocG9pbnRzW2ldLnZhbHVlLCAxLCAnJywgJy9zJykgI1xuXHRcdFx0PC9kaXY+XG5cdFx0XHQjIH0gI1xuXHRcdGApKGRhdGFJdGVtKTtcblx0fTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE5ldHdvcmtWYWx1ZUF4aXNMYWJlbFRlbXBsYXRlKCkge1xuXHRyZXR1cm4gZnVuY3Rpb24oZGF0YUl0ZW0pIHtcblx0XHRkYXRhSXRlbS5rQnl0ZXNUb1NpemUgPSBrQnl0ZXNUb1NpemU7IC8vIFBhc3Mga0J5dGVzVG9TaXplIHV0aWxpdHkgZnVuY3Rpb24gdG8gdGVtcGxhdGVcblx0XHRyZXR1cm4ga2VuZG8udGVtcGxhdGUoYFxuXHRcdFx0Izoga0J5dGVzVG9TaXplKHZhbHVlLCAxLCAnJywgJy9zJykgI1xuXHRcdGApKGRhdGFJdGVtKTtcblx0fTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE5ldHdvcmtWYWx1ZUF4aXNMYWJlbFRlbXBsYXRlQigpIHtcblx0cmV0dXJuIGZ1bmN0aW9uKGRhdGFJdGVtKSB7XG5cdFx0ZGF0YUl0ZW0uYnl0ZXNUb1NpemUgPSBieXRlc1RvU2l6ZTsgLy8gUGFzcyBieXRlc1RvU2l6ZSB1dGlsaXR5IGZ1bmN0aW9uIHRvIHRlbXBsYXRlXG5cdFx0cmV0dXJuIGtlbmRvLnRlbXBsYXRlKGBcblx0XHRcdCM6IGJ5dGVzVG9TaXplKHZhbHVlLCAxLCAnJywgJy9zJykgI1xuXHRcdGApKGRhdGFJdGVtKTtcblx0fTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFVzZXJDb3VudFNoYXJlZFRlbXBsYXRlKGNhdGVnb3J5Rm9ybWF0ID0gJ2RkIE1NTSBISDptbTpzcycpIHtcblx0cmV0dXJuIGZ1bmN0aW9uKGRhdGFJdGVtKSB7XG5cdFx0cmV0dXJuIGtlbmRvLnRlbXBsYXRlKGBcblx0XHRcdDxkaXYgY2xhc3M9XCJjaGFydC10b29sdGlwLWNhdGVnb3J5XCI+PHN0cm9uZz4jOiBrZW5kby50b1N0cmluZyhjYXRlZ29yeSwgJyR7Y2F0ZWdvcnlGb3JtYXR9JykgIzwvc3Ryb25nPjwvZGl2PlxuXHRcdFx0IyBmb3IgKHZhciBpID0gMDsgaSA8IHBvaW50cy5sZW5ndGg7IGkrKykgeyAjXG5cdFx0XHQ8ZGl2PlxuXHRcdFx0XHQ8aSBjbGFzcz1cImZhcyBmYS1zcXVhcmVcIiBzdHlsZT1cImNvbG9yOiAjOiBwb2ludHNbaV0uY29sb3IgIyBcIj48L2k+XG5cdFx0XHRcdCM6IHBvaW50c1tpXS5zZXJpZXMubmFtZSMgOiAjOiBwb2ludHNbaV0udmFsdWUgI1xuXHRcdFx0PC9kaXY+XG5cdFx0XHQjIH0gI1xuXHRcdGApKGRhdGFJdGVtKTtcblx0fTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFRpbWVSYW5nZVRvb2x0aXBUZW1wbGF0ZSgpIHtcblx0cmV0dXJuIGZ1bmN0aW9uKGRhdGFJdGVtKSB7XG5cdFx0ZGF0YUl0ZW0uZ2V0VG9vbHRpcFN0cmluZyA9IGZ1bmN0aW9uKHYxLCB2Mikge1xuXHRcdFx0aWYgKHYxID09IHYyKVxuXHRcdFx0e1xuXHRcdFx0XHRpZiAodjIgPT0gLTI0KVxuXHRcdFx0XHRcdHYyID0gLTIzO1xuXG5cdFx0XHRcdHYxID0gdjIgLSAxO1xuXHRcdFx0fVxuXG5cdFx0XHRsZXQgc3RhcnQgPSBNYXRoLmFicyh2MSk7XG5cdFx0XHRsZXQgZW5kID0gTWF0aC5hYnModjIpO1xuXG5cdFx0XHRyZXR1cm4gYEZyb20gJHtzdGFydH0gaG91ciR7c3RhcnQgIT0gMSA/ICdzJyA6ICcnfSBhZ28gdG8gJHtlbmQgPiAwID8gKCd0byAnICsgZW5kICsgJyBob3VyJyArIChlbmQgIT0gMSA/ICdzJyA6ICcnKSArICcgYWdvJykgOiAnbm93J31gO1xuXHRcdH07IC8vIFBhc3MgdXRpbGl0eSBmdW5jdGlvbiB0byB0ZW1wbGF0ZVxuXHRcdHJldHVybiBrZW5kby50ZW1wbGF0ZShgXG5cdFx0XHQjOiBnZXRUb29sdGlwU3RyaW5nKHNlbGVjdGlvblN0YXJ0LCBzZWxlY3Rpb25FbmQpICNcblx0XHRgKShkYXRhSXRlbSk7XG5cdH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRXUkJ5dGVzTGFiZWxUZW1wbGF0ZSgpIHtcblx0cmV0dXJuIGZ1bmN0aW9uKGRhdGFJdGVtKSB7XG5cdFx0cmV0dXJuIGtlbmRvLnRlbXBsYXRlKGBcblx0XHRcdCM6IHZhbHVlICMgIzogZGF0YUl0ZW0udW5pdCAjXG5cdFx0YCkoZGF0YUl0ZW0pO1xuXHR9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0QmFzaWNUZW1wbGF0ZSh2YWx1ZUZvcm1hdCA9ICd7MH0nKSB7XG5cdHJldHVybiBrZW5kby50ZW1wbGF0ZShgXG5cdFx0PGRpdj5cblx0XHRcdDxzcGFuIGNsYXNzPVwidGV4dC1ub3dyYXBcIj4jOiBrZW5kby50b1N0cmluZyhuZXcgRGF0ZSh2YWx1ZS54KSwgXCJkZC9NTS95eSBISDptbVwiKSAjPC9zcGFuPlxuXHRcdFx0PGJyPlxuXHRcdFx0PHN0cm9uZyBjbGFzcz1cInRleHQtbm93cmFwXCI+Izogc2VyaWVzLm5hbWUgIzogIzoga2VuZG8uZm9ybWF0KCcke3ZhbHVlRm9ybWF0fScsIHZhbHVlLnkpICMgPC9zdHJvbmc+XG5cdFx0PC9kaXY+XG5cdGApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TWVtb3J5VGVtcGxhdGUoKSB7XG5cdHJldHVybiBmdW5jdGlvbihkYXRhSXRlbSkge1xuXHRcdGRhdGFJdGVtLmJ5dGVzVG9TaXplID0gYnl0ZXNUb1NpemU7IC8vIFBhc3MgYnl0ZXNUb1NpemUgdXRpbGl0eSBmdW5jdGlvbiB0byB0ZW1wbGF0ZVxuXHRcdHJldHVybiBrZW5kby50ZW1wbGF0ZShgXG5cdFx0XHQ8ZGl2PlxuXHRcdFx0XHQ8c3BhbiBjbGFzcz1cInRleHQtbm93cmFwXCI+Izoga2VuZG8udG9TdHJpbmcobmV3IERhdGUodmFsdWUueCksIFwiZGQvTU0veXkgSEg6bW1cIikgIzwvc3Bhbj5cblx0XHRcdFx0PGJyPlxuXHRcdFx0XHQ8c3Ryb25nIGNsYXNzPVwidGV4dC1ub3dyYXBcIj4jOiBzZXJpZXMubmFtZSAjOiAjOiBieXRlc1RvU2l6ZSh2YWx1ZS55KSAjIDwvc3Ryb25nPlxuXHRcdFx0PC9kaXY+XG5cdFx0YCkoZGF0YUl0ZW0pO1xuXHR9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TmV0d29ya1RlbXBsYXRlKCkge1xuXHRyZXR1cm4gZnVuY3Rpb24oZGF0YUl0ZW0pIHtcblx0XHRkYXRhSXRlbS5ieXRlc1RvU2l6ZSA9IGJ5dGVzVG9TaXplOyAvLyBQYXNzIGJ5dGVzVG9TaXplIHV0aWxpdHkgZnVuY3Rpb24gdG8gdGVtcGxhdGVcblx0XHRyZXR1cm4ga2VuZG8udGVtcGxhdGUoYFxuXHRcdFx0PGRpdj5cblx0XHRcdFx0PHNwYW4gY2xhc3M9XCJ0ZXh0LW5vd3JhcFwiPiM6IGtlbmRvLnRvU3RyaW5nKG5ldyBEYXRlKHZhbHVlLngpLCBcImRkL01NL3l5IEhIOm1tXCIpICM8L3NwYW4+XG5cdFx0XHRcdDxicj5cblx0XHRcdFx0PHN0cm9uZyBjbGFzcz1cInRleHQtbm93cmFwXCI+Izogc2VyaWVzLm5hbWUgIzogIzogYnl0ZXNUb1NpemUodmFsdWUueSwgMSwgJycsICcvcycpICMgPC9zdHJvbmc+XG5cdFx0XHQ8L2Rpdj5cblx0XHRgKShkYXRhSXRlbSk7XG5cdH07XG59XG4iLCJpbXBvcnQge0Jhc2VDaGFydH0gZnJvbSAnLi9iYXNlLWNoYXJ0JztcblxuaW1wb3J0IHtnZXRCYXNpY1NoYXJlZFRlbXBsYXRlLCBnZXRGb3JtYXR0ZWREYXRlVGltZX0gZnJvbSAnLi9jaGFydC11dGlscyc7XG5cbmV4cG9ydCBjbGFzcyBDcHVVc2FnZUNoYXJ0IGV4dGVuZHMgQmFzZUNoYXJ0XG57XG5cdGNvbnN0cnVjdG9yKClcblx0e1xuXHQgICAgc3VwZXIoMTIwKTtcblx0fVxuXG5cdF9pbml0Q2hhcnRXaWRnZXQoY2hhcnRIdG1sKVxuXHR7XG5cdFx0cmV0dXJuIGNoYXJ0SHRtbC5rZW5kb0NoYXJ0KHtcblx0XHRcdHRyYW5zaXRpb25zOiBmYWxzZSxcblx0XHRcdGNoYXJ0QXJlYToge1xuXHRcdFx0XHRoZWlnaHQ6IDEyMFxuXHRcdFx0fSxcblx0ICAgICAgICBsZWdlbmQ6IHtcblx0ICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHNlcmllc0RlZmF1bHRzOiB7XG5cdCAgICAgICAgICAgIHR5cGU6ICdhcmVhJyxcblx0ICAgICAgICAgICAgbGFiZWxzOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZSxcblx0ICAgICAgICAgICAgICAgIGZvcm1hdDogJ3swfSUnLFxuXHQgICAgICAgICAgICAgICAgYmFja2dyb3VuZDogJ3RyYW5zcGFyZW50J1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBzZXJpZXM6IFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdG5hbWU6ICdTeXN0ZW0nLFxuXHRcdCAgICAgICAgICAgIGZpZWxkOiAnc3lzdGVtTG9hZCcsXG5cdFx0ICAgICAgICAgICAgY2F0ZWdvcnlGaWVsZDogJ3RpbWUnLFxuXHRcdFx0XHRcdGNvbG9yOiB0aGlzLnN5c3RlbUNvbG9yLFxuXHRcdFx0XHRcdGxpbmU6IHtcblx0XHRcdFx0XHRcdHdpZHRoOiAyXG5cdFx0XHRcdFx0fVxuXHRcdCAgICAgICAgfSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdG5hbWU6ICdQcm9jZXNzJyxcblx0XHRcdFx0XHRmaWVsZDogJ3Byb2Nlc3NMb2FkJyxcblx0XHRcdFx0XHRjYXRlZ29yeUZpZWxkOiAndGltZScsXG5cdFx0XHRcdFx0Y29sb3I6IHRoaXMucHJvY2Vzc0NvbG9yLFxuXHRcdFx0XHRcdGxpbmU6IHtcblx0XHRcdFx0XHRcdHdpZHRoOiAyXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRdLFxuXHQgICAgICAgIHZhbHVlQXhpczoge1xuXHQgICAgICAgICAgICBsYWJlbHM6IHtcblx0ICAgICAgICAgICAgICAgIGZvcm1hdDogJ3swfSUnXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICAgIGxpbmU6IHtcblx0ICAgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlXG5cdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdG1pbjogMCxcblx0ICAgIFx0XHRtYXg6IDEwMFxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgY2F0ZWdvcnlBeGlzOiB7XG5cdCAgICAgICAgICAgIG1ham9yR3JpZExpbmVzOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHRcdFx0XHRtYWpvclRpY2tzOiB7XG5cdFx0XHRcdFx0dmlzaWJsZTogZmFsc2Vcblx0XHRcdFx0fSxcblx0XHRcdFx0bGFiZWxzOiB7XG5cdFx0XHRcdFx0dmlzaWJsZTogZmFsc2Vcblx0XHRcdFx0fVxuXHQgICAgICAgIH0sXG5cdFx0XHR0b29sdGlwOiB7XG5cdFx0XHRcdHNoYXJlZDogdHJ1ZSxcblx0ICAgICAgICAgICAgdmlzaWJsZTogdHJ1ZSxcblx0XHRcdFx0c2hhcmVkVGVtcGxhdGU6IGdldEJhc2ljU2hhcmVkVGVtcGxhdGUoJ3swfSUnKSxcblx0XHRcdFx0YmFja2dyb3VuZDogJyNlNGU0ZTQnXG5cdCAgICAgICAgfVxuXHQgICAgfSkuZGF0YSgna2VuZG9DaGFydCcpO1xuXHR9XG5cblx0Z2V0IHN5c3RlbUNvbG9yKClcblx0e1xuXHRcdHJldHVybiAnIzMzOTlGRic7XG5cdH1cblxuXHRnZXQgcHJvY2Vzc0NvbG9yKClcblx0e1xuXHRcdHJldHVybiAnIzAwMzNDQyc7XG5cdH1cblxuXHRhZGRFbnRyeShwcm9jZXNzTG9hZCwgc3lzdGVtTG9hZClcblx0e1xuXHRcdGxldCBuZXdFbnRyeSA9IHtcblx0XHRcdHRpbWU6IGdldEZvcm1hdHRlZERhdGVUaW1lKG5ldyBEYXRlKCkpLFxuXHRcdFx0cHJvY2Vzc0xvYWQ6IHByb2Nlc3NMb2FkLFxuXHRcdFx0c3lzdGVtTG9hZDogc3lzdGVtTG9hZFxuXHRcdH07XG5cblx0XHQvLyBBZGQgZW50cnkgdG8gY2hhcnRcblx0XHRzdXBlci5fYWRkRW50cnkobmV3RW50cnkpO1xuXHR9XG59XG5cbi8vIERFRklORSBDT01QT05FTlRcbmlmICghd2luZG93LmN1c3RvbUVsZW1lbnRzLmdldCgnY3B1LXVzYWdlLWNoYXJ0JykpXG5cdHdpbmRvdy5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ2NwdS11c2FnZS1jaGFydCcsIENwdVVzYWdlQ2hhcnQpO1xuIiwiaW1wb3J0IHtCYXNlQ2hhcnR9IGZyb20gJy4vYmFzZS1jaGFydCc7XG5cbmltcG9ydCB7Z2V0TWVtb3J5U2hhcmVkVGVtcGxhdGUsIGdldE1lbW9yeVZhbHVlQXhpc0xhYmVsVGVtcGxhdGUsIGdldEZvcm1hdHRlZERhdGVUaW1lfSBmcm9tICcuL2NoYXJ0LXV0aWxzJztcblxuZXhwb3J0IGNsYXNzIE1lbW9yeUNoYXJ0IGV4dGVuZHMgQmFzZUNoYXJ0XG57XG5cdGNvbnN0cnVjdG9yKClcblx0e1xuXHQgICAgc3VwZXIoMzAwKTtcblxuXHRcdC8vIEFwcGVuZCB0ZXh0IHRvIGRpc3BsYXkgZWxhcHNlZCB0aW1lXG5cdFx0dGhpcy5fZWxhcHNlZFR4dCA9ICQoJzxkaXY+Jywge2NsYXNzOiAndGV4dC1jZW50ZXInLCB0ZXh0OiAnLS0tJ30pO1xuXHRcdCQodGhpcykuYXBwZW5kKHRoaXMuX2VsYXBzZWRUeHQpO1xuXHR9XG5cblx0X2luaXRDaGFydFdpZGdldChjaGFydEh0bWwpXG5cdHtcblx0XHRyZXR1cm4gY2hhcnRIdG1sLmtlbmRvQ2hhcnQoe1xuXHRcdFx0dHJhbnNpdGlvbnM6IGZhbHNlLFxuXHRcdFx0Y2hhcnRBcmVhOiB7XG5cdFx0XHRcdGhlaWdodDogMjQwXG5cdFx0XHR9LFxuXHQgICAgICAgIGxlZ2VuZDoge1xuXHQgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgc2VyaWVzRGVmYXVsdHM6IHtcblx0ICAgICAgICAgICAgdHlwZTogJ2FyZWEnLFxuXHQgICAgICAgICAgICBsYWJlbHM6IHtcblx0ICAgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlLFxuXHQgICAgICAgICAgICAgICAgZm9ybWF0OiAnezB9Jyxcblx0ICAgICAgICAgICAgICAgIGJhY2tncm91bmQ6ICd0cmFuc3BhcmVudCdcblx0ICAgICAgICAgICAgfSxcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHNlcmllczogW3tcblx0XHRcdFx0bmFtZTogJ0FsbG9jYXRlZCcsXG5cdCAgICAgICAgICAgIGZpZWxkOiAnYWxsb2NNZW0nLFxuXHQgICAgICAgICAgICBjYXRlZ29yeUZpZWxkOiAndGltZScsXG5cdFx0XHRcdGNvbG9yOiB0aGlzLmFsbG9jYXRlZENvbG9yLFxuXHRcdFx0XHRsaW5lOiB7XG5cdFx0XHRcdFx0d2lkdGg6IDJcblx0XHRcdFx0fVxuXHQgICAgICAgIH0sXG5cdFx0XHR7XG5cdFx0XHRcdG5hbWU6ICdVc2VkJyxcblx0XHRcdFx0ZmllbGQ6ICd1c2VkTWVtJyxcblx0XHRcdFx0Y2F0ZWdvcnlGaWVsZDogJ3RpbWUnLFxuXHRcdFx0XHRjb2xvcjogdGhpcy51c2VkQ29sb3IsXG5cdFx0XHRcdGxpbmU6IHtcblx0XHRcdFx0XHR3aWR0aDogMlxuXHRcdFx0XHR9XG5cdFx0XHR9XSxcblx0ICAgICAgICB2YWx1ZUF4aXM6IHtcblx0ICAgICAgICAgICAgbGFiZWxzOiB7XG5cdCAgICAgICAgICAgICAgICBmb3JtYXQ6ICd7MH0nLFxuICAgICAgXHRcdFx0XHR0ZW1wbGF0ZTogZ2V0TWVtb3J5VmFsdWVBeGlzTGFiZWxUZW1wbGF0ZSgpXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICAgIGxpbmU6IHtcblx0ICAgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlXG5cdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdG1pbjogMFxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgY2F0ZWdvcnlBeGlzOiB7XG5cdFx0XHRcdG1ham9yR3JpZExpbmVzOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHRcdFx0XHRtYWpvclRpY2tzOiB7XG5cdFx0XHRcdFx0dmlzaWJsZTogZmFsc2Vcblx0XHRcdFx0fSxcblx0XHRcdFx0bGFiZWxzOiB7XG5cdFx0XHRcdFx0dmlzaWJsZTogZmFsc2Vcblx0XHRcdFx0fVxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgdG9vbHRpcDoge1xuXHRcdFx0XHRzaGFyZWQ6IHRydWUsXG5cdCAgICAgICAgICAgIHZpc2libGU6IHRydWUsXG5cdFx0XHRcdHNoYXJlZFRlbXBsYXRlOiBnZXRNZW1vcnlTaGFyZWRUZW1wbGF0ZSgpLFxuXHRcdFx0XHRiYWNrZ3JvdW5kOiAnI2U0ZTRlNCdcblx0ICAgICAgICB9XG5cdCAgICB9KS5kYXRhKCdrZW5kb0NoYXJ0Jyk7XG5cdH1cblxuXHRnZXQgYWxsb2NhdGVkQ29sb3IoKVxuXHR7XG5cdFx0cmV0dXJuICcjMzM5OUZGJztcblx0fVxuXG5cdGdldCB1c2VkQ29sb3IoKVxuXHR7XG5cdFx0cmV0dXJuICcjMDAzM0NDJztcblx0fVxuXG5cdGFkZEVudHJ5KGFsbG9jTWVtLCB1c2VkTWVtKVxuXHR7XG5cdFx0bGV0IG5vdyA9IG5ldyBEYXRlKCk7XG5cblx0XHRsZXQgbmV3RW50cnkgPSB7XG5cdFx0XHR0aW1lOiBnZXRGb3JtYXR0ZWREYXRlVGltZShub3cpLFxuXHRcdFx0dGltZXN0YW1wOiBub3cuZ2V0VGltZSgpLFxuXHRcdFx0YWxsb2NNZW06IGFsbG9jTWVtLFxuXHRcdFx0dXNlZE1lbTogdXNlZE1lbVxuXHRcdH07XG5cblx0XHQvLyBBZGQgZW50cnkgdG8gY2hhcnRcblx0XHRzdXBlci5fYWRkRW50cnkobmV3RW50cnkpO1xuXG5cdFx0Ly8gVXBkYXRlIHggYXhpc1xuXHRcdGlmICghdGhpcy5pc1BhdXNlZClcblx0XHRcdHRoaXMuX3VwZGF0ZUVsYXBzZWRUZXh0KCk7XG5cdH1cblxuXHRfdXBkYXRlRWxhcHNlZFRleHQoKVxuXHR7XG5cdFx0bGV0IGRzID0gdGhpcy5fZGF0YVNvdXJjZTtcblxuXHRcdGlmIChkcy50b3RhbCgpID4gMSlcblx0XHR7XG5cdFx0XHQvLyBHZXQgYXhpcyBsaW1pdHNcblx0XHRcdGNvbnN0IGNoYXJ0TWluaW11bSA9IGRzLmF0KDApLnRpbWVzdGFtcDtcblx0XHRcdGNvbnN0IGNoYXJ0TWF4aW11bSA9IGRzLmF0KGRzLnRvdGFsKCkgLSAxKS50aW1lc3RhbXA7XG5cblx0XHRcdC8vIFNldCBlbGFwc2VkIHRleHRcblx0XHRcdGxldCBzZWNvbmRzID0gTWF0aC5yb3VuZCggKGNoYXJ0TWF4aW11bSAtIGNoYXJ0TWluaW11bSkgLyAxMDAwICk7XG5cdFx0XHRsZXQgdGl0bGU7XG5cblx0XHRcdGlmIChzZWNvbmRzIDwgNjApXG5cdFx0XHRcdHRpdGxlID0gJ0xhc3QgJyArIChzZWNvbmRzICE9IDEgPyBzZWNvbmRzICsgJyBzZWNvbmRzJyA6ICdzZWNvbmQnKTtcblx0XHRcdGVsc2Vcblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgbWludXRlcyA9IE1hdGguZmxvb3Ioc2Vjb25kcyAvIDYwKTtcblx0XHRcdFx0dGl0bGUgPSAnTGFzdCAnICsgKG1pbnV0ZXMgIT0gMSA/IG1pbnV0ZXMgKyAnIG1pbnV0ZXMnIDogJ21pbnV0ZScpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLl9lbGFwc2VkVHh0LnRleHQodGl0bGUpO1xuXHRcdH1cblx0fVxufVxuXG4vLyBERUZJTkUgQ09NUE9ORU5UXG5pZiAoIXdpbmRvdy5jdXN0b21FbGVtZW50cy5nZXQoJ21lbW9yeS1jaGFydCcpKVxuXHR3aW5kb3cuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdtZW1vcnktY2hhcnQnLCBNZW1vcnlDaGFydCk7XG4iLCJpbXBvcnQge2dldE5ldHdvcmtTaGFyZWRUZW1wbGF0ZSwgZ2V0TmV0d29ya1ZhbHVlQXhpc0xhYmVsVGVtcGxhdGV9IGZyb20gJy4vY2hhcnQtdXRpbHMnO1xuaW1wb3J0ICogYXMgbW9tZW50IGZyb20gJ21vbWVudCc7XG5cbmV4cG9ydCBjbGFzcyBOZXR3b3JrMjRoQ2hhcnQgZXh0ZW5kcyBIVE1MRWxlbWVudFxue1xuXHRjb25zdHJ1Y3RvcigpXG5cdHtcblx0ICAgIHN1cGVyKCk7XG5cblx0XHR0aGlzLl9sYXN0VG90YWxPdXQgPSAwO1xuXHRcdHRoaXMuX2xhc3RUb3RhbEluID0gMDtcblx0XHR0aGlzLl9sYXN0RGF0ZSA9IG5ldyBEYXRlKCk7XG5cdFx0dGhpcy5fc2FtcGxpbmdSYXRlU2Vjb25kcyA9IDA7XG5cblx0XHQvLyBDcmVhdGUgY2hhcnQgaHRtbFxuXHRcdGxldCBjaGFydEh0bWwgPSAkKCc8ZGl2PicpO1xuXHRcdCQodGhpcykuYXBwZW5kKGNoYXJ0SHRtbCk7XG5cblx0XHQvLyBJbml0aWFsaXplIGNoYXJ0XG5cdFx0dGhpcy5fY2hhcnRXaWRnZXQgPSB0aGlzLl9pbml0Q2hhcnRXaWRnZXQoY2hhcnRIdG1sKTtcblx0fVxuXG5cdF9pbml0Q2hhcnRXaWRnZXQoY2hhcnRIdG1sKVxuXHR7XG5cdFx0cmV0dXJuIGNoYXJ0SHRtbC5rZW5kb0NoYXJ0KHtcblx0XHRcdHRyYW5zaXRpb25zOiBmYWxzZSxcblx0XHRcdGNoYXJ0QXJlYToge1xuXHRcdFx0XHRoZWlnaHQ6IDI3MCxcblx0XHRcdFx0YmFja2dyb3VuZDogJ3RyYW5zcGFyZW50J1xuXHRcdFx0fSxcblx0ICAgICAgICBsZWdlbmQ6IHtcblx0ICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHNlcmllc0RlZmF1bHRzOiB7XG5cdCAgICAgICAgICAgIHR5cGU6ICdhcmVhJyxcblx0ICAgICAgICAgICAgbGFiZWxzOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZSxcblx0ICAgICAgICAgICAgICAgIGZvcm1hdDogJ3swfScsXG5cdCAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kOiAndHJhbnNwYXJlbnQnXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgfSxcblx0ICAgICAgICBzZXJpZXM6IFt7XG5cdFx0XHRcdG5hbWU6ICdPdXRnb2luZycsXG5cdCAgICAgICAgICAgIGZpZWxkOiAnb3V0Z29pbmcnLFxuXHQgICAgICAgICAgICBjYXRlZ29yeUZpZWxkOiAndGltZScsXG5cdFx0XHRcdGNvbG9yOiAnI0NDMDAwMCcsXG5cdFx0XHRcdGxpbmU6IHtcblx0XHRcdFx0XHR3aWR0aDogMlxuXHRcdFx0XHR9XG5cdCAgICAgICAgfSxcblx0XHRcdHtcblx0XHRcdFx0bmFtZTogJ0luY29taW5nJyxcblx0XHRcdFx0ZmllbGQ6ICdpbmNvbWluZycsXG5cdFx0XHRcdGNhdGVnb3J5RmllbGQ6ICd0aW1lJyxcblx0XHRcdFx0Y29sb3I6ICcjMDA5OTAwJyxcblx0XHRcdFx0bGluZToge1xuXHRcdFx0XHRcdHdpZHRoOiAyXG5cdFx0XHRcdH1cblx0XHRcdH1dLFxuXHQgICAgICAgIHZhbHVlQXhpczoge1xuXHQgICAgICAgICAgICBsYWJlbHM6IHtcblx0ICAgICAgICAgICAgICAgIGZvcm1hdDogJ3swfScsXG4gICAgICBcdFx0XHRcdHRlbXBsYXRlOiBnZXROZXR3b3JrVmFsdWVBeGlzTGFiZWxUZW1wbGF0ZSgpXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICAgIGxpbmU6IHtcblx0ICAgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlXG5cdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdG1pbjogMFxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgY2F0ZWdvcnlBeGlzOiB7XG5cdFx0XHRcdG1ham9yR3JpZExpbmVzOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiB0cnVlLFxuXHRcdFx0XHRcdHN0ZXA6IDYwXG5cdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdG1ham9yVGlja3M6IHtcblx0XHRcdFx0XHR2aXNpYmxlOiB0cnVlLFxuXHRcdFx0XHRcdHN0ZXA6IDYwXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGxhYmVsczoge1xuXHRcdFx0XHRcdHZpc2libGU6IHRydWUsXG5cdFx0XHRcdFx0c3RlcDogNjBcblx0XHRcdFx0fSxcblx0XHRcdFx0YmFzZVVuaXQ6ICdtaW51dGVzJyxcblx0XHRcdFx0dHlwZTogJ2RhdGUnLFxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgdG9vbHRpcDoge1xuXHRcdFx0XHRzaGFyZWQ6IHRydWUsXG5cdCAgICAgICAgICAgIHZpc2libGU6IHRydWUsXG5cdFx0XHRcdHNoYXJlZFRlbXBsYXRlOiBnZXROZXR3b3JrU2hhcmVkVGVtcGxhdGUoJ2RkIE1NTSBISDptbScpLFxuXHRcdFx0XHRiYWNrZ3JvdW5kOiAnI2U0ZTRlNCdcblx0ICAgICAgICB9XG5cdCAgICB9KS5kYXRhKCdrZW5kb0NoYXJ0Jyk7XG5cdH1cblxuXHRyZWRyYXcoKVxuXHR7XG5cdFx0dGhpcy5fY2hhcnRXaWRnZXQucmVkcmF3KCk7XG5cdH1cblxuXHRzZXQgcmFuZ2UodmFsdWVzKVxuXHR7XG5cdFx0dGhpcy5fcmFuZ2UgPSB2YWx1ZXM7XG5cblx0XHR0aGlzLl91cGRhdGVYQXhpc0xpbWl0cygpO1xuXHR9XG5cblx0Z2V0IHJhbmdlKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9yYW5nZTtcblx0fVxuXG5cdGFkZEhpc3RvcnlFbnRyaWVzKG91dGdvaW5nRGF0YSwgaW5jb21pbmdEYXRhLCBzYW1wbGluZ1JhdGVTZWNvbmRzLCBzaGlmdFNlY29uZHMpXG5cdHtcblx0XHR0aGlzLl9zYW1wbGluZ1JhdGVTZWNvbmRzID0gc2FtcGxpbmdSYXRlU2Vjb25kcztcblxuXHRcdGxldCBub3cgPSBuZXcgRGF0ZSgpO1xuXG5cdFx0Ly8gTk9URTogb3V0Z29pbmdEYXRhIGFuZCBpbmNvbWluRGF0YSBhcmUgc3VwcG9zZWQgdG8gaGF2ZSB0aGUgc2FtZSBzaXplISEhXG5cblx0XHRpZiAob3V0Z29pbmdEYXRhLmxlbmd0aCA+IDApXG5cdFx0e1xuXHRcdFx0bGV0IHN0YXJ0ID0gbW9tZW50KG5vdyk7XG5cdFx0XHRzdGFydC5zdWJ0cmFjdCgoc2FtcGxpbmdSYXRlU2Vjb25kcyAqIG91dGdvaW5nRGF0YS5sZW5ndGgpICsgc2hpZnRTZWNvbmRzLCAncycpXG5cblx0XHRcdHRoaXMuX2xhc3RUb3RhbE91dCA9IG91dGdvaW5nRGF0YVswXTtcblx0XHRcdHRoaXMuX2xhc3RUb3RhbEluID0gaW5jb21pbmdEYXRhWzBdO1xuXHRcdFx0dGhpcy5fbGFzdERhdGUgPSBzdGFydC50b0RhdGUoKTtcblxuXHRcdFx0aWYgKG91dGdvaW5nRGF0YS5sZW5ndGggPiAxKVxuXHRcdFx0e1xuXHRcdFx0XHRsZXQgZGF0YVNvdXJjZSA9IG5ldyBrZW5kby5kYXRhLkRhdGFTb3VyY2UoKTtcblxuXHRcdFx0XHRmb3IgKGxldCBpID0gMTsgaSA8IG91dGdvaW5nRGF0YS5sZW5ndGg7IGkrKylcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGNvbnN0IHRvdGFsT3V0ID0gb3V0Z29pbmdEYXRhW2ldO1xuXHRcdFx0XHRcdGNvbnN0IHRvdGFsSW4gPSBpbmNvbWluZ0RhdGFbaV07XG5cblx0XHRcdFx0XHRsZXQgZGF0ZSA9IHN0YXJ0LmNsb25lKCk7XG5cdFx0XHRcdFx0ZGF0ZS5hZGQoaSAqIHNhbXBsaW5nUmF0ZVNlY29uZHMsICdzJyk7XG5cblx0XHRcdFx0XHR0aGlzLmFkZEVudHJ5KHRvdGFsT3V0LCB0b3RhbEluLCBkYXRhU291cmNlLCBkYXRlLnRvRGF0ZSgpLCBmYWxzZSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBBc3NpZ24gZGF0YXNvdXJjZSB0byBjaGFydFxuXHRcdFx0XHR0aGlzLl9jaGFydFdpZGdldC5zZXREYXRhU291cmNlKGRhdGFTb3VyY2UpO1xuXG5cdFx0XHRcdC8vIFVwZGF0ZSBheGlzXG5cdFx0XHRcdHRoaXMuX3VwZGF0ZVhBeGlzTGltaXRzKCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGVsc2Vcblx0XHR7XG5cdFx0XHR0aGlzLl9sYXN0VG90YWxPdXQgPSAwO1xuXHRcdFx0dGhpcy5fbGFzdFRvdGFsSW4gPSAwO1xuXHRcdFx0dGhpcy5fbGFzdERhdGUgPSBub3c7XG5cdFx0fVxuXHR9XG5cblx0YWRkRW50cnkodG90YWxPdXQsIHRvdGFsSW4sIGRhdGFTb3VyY2UgPSBudWxsLCBkYXRlID0gbnVsbCwgdXBkYXRlQXhpcyA9IHRydWUpXG5cdHtcblx0XHRpZiAoZGF0ZSA9PSBudWxsKVxuXHRcdFx0ZGF0ZSA9IG5ldyBEYXRlKCk7XG5cblx0XHRjb25zdCBlbGFwc2VkU2VjcyA9IE1hdGgucm91bmQoKGRhdGUuZ2V0VGltZSgpIC0gdGhpcy5fbGFzdERhdGUuZ2V0VGltZSgpKSAvIDEwMDApO1xuXG5cdFx0Ly8gVGhlIDI0aCBjaGFydCBpcyB1cGRhdGVkIGF0IHRoZSBzYW1lIHNhbXBsaW5nIHJhdGUgdXNlZCBieSB0aGUgc2VydmVyIHRvIHNhdmUgdGhlIHRyYWZmaWMgaGlzdG9yeVxuXHRcdGlmIChlbGFwc2VkU2VjcyA+PSB0aGlzLl9zYW1wbGluZ1JhdGVTZWNvbmRzKVxuXHRcdHtcblx0XHRcdGxldCBuZXdFbnRyeSA9IHtcblx0XHRcdFx0dGltZTogZGF0ZSxcblx0XHRcdFx0b3V0Z29pbmc6IE1hdGgucm91bmQoKHRvdGFsT3V0IC0gdGhpcy5fbGFzdFRvdGFsT3V0KSAvIGVsYXBzZWRTZWNzKSxcblx0XHRcdFx0aW5jb21pbmc6IE1hdGgucm91bmQoKHRvdGFsSW4gLSB0aGlzLl9sYXN0VG90YWxJbikgLyBlbGFwc2VkU2Vjcylcblx0XHRcdH07XG5cblx0XHRcdC8vIEFkZCBlbnRyeSB0byBkYXRhIHNvdXJjZVxuXHRcdFx0aWYgKGRhdGFTb3VyY2UgPT0gbnVsbClcblx0XHRcdFx0ZGF0YVNvdXJjZSA9IHRoaXMuX2RhdGFTb3VyY2U7XG5cblx0XHRcdGRhdGFTb3VyY2UuYWRkKG5ld0VudHJ5KTtcblxuXHRcdFx0dGhpcy5fbGFzdFRvdGFsT3V0ID0gdG90YWxPdXQ7XG5cdFx0XHR0aGlzLl9sYXN0VG90YWxJbiA9IHRvdGFsSW47XG5cdFx0XHR0aGlzLl9sYXN0RGF0ZSA9IGRhdGU7XG5cblx0XHRcdGlmICh1cGRhdGVBeGlzKVxuXHRcdFx0XHR0aGlzLl91cGRhdGVYQXhpc0xpbWl0cygpO1xuXHRcdH1cblx0fVxuXG5cdF91cGRhdGVYQXhpc0xpbWl0cygpXG5cdHtcblx0XHRsZXQgZHMgPSB0aGlzLl9kYXRhU291cmNlO1xuXG5cdFx0aWYgKGRzLnRvdGFsKCkgPiAwKVxuXHRcdHtcblx0XHRcdGNvbnN0IGNoYXJ0TWluaW11bSA9IG1vbWVudCh0aGlzLl9sYXN0RGF0ZSkuYWRkKHRoaXMuX3JhbmdlWzBdLCAnaCcpO1xuXHRcdFx0Y29uc3QgY2hhcnRNYXhpbXVtID0gbW9tZW50KHRoaXMuX2xhc3REYXRlKS5hZGQodGhpcy5fcmFuZ2VbMV0sICdoJyk7XG5cblx0XHRcdHRoaXMuX2NoYXJ0V2lkZ2V0Lm9wdGlvbnMuY2F0ZWdvcnlBeGlzLm1pbiA9IGNoYXJ0TWluaW11bS50b0RhdGUoKTtcblx0XHRcdHRoaXMuX2NoYXJ0V2lkZ2V0Lm9wdGlvbnMuY2F0ZWdvcnlBeGlzLm1heCA9IGNoYXJ0TWF4aW11bS50b0RhdGUoKTtcblxuXHRcdFx0dGhpcy5fY2hhcnRXaWRnZXQucmVkcmF3KCk7XG5cdFx0fVxuXHR9XG5cblx0Z2V0IF9kYXRhU291cmNlKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9jaGFydFdpZGdldC5kYXRhU291cmNlO1xuXHR9XG59XG5cbi8vIERFRklORSBDT01QT05FTlRcbmlmICghd2luZG93LmN1c3RvbUVsZW1lbnRzLmdldCgnbmV0d29yay0yNGgtY2hhcnQnKSlcblx0d2luZG93LmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnbmV0d29yay0yNGgtY2hhcnQnLCBOZXR3b3JrMjRoQ2hhcnQpO1xuIiwiaW1wb3J0IHtCYXNlQ2hhcnR9IGZyb20gJy4vYmFzZS1jaGFydCc7XG5cbmltcG9ydCB7Z2V0TmV0d29ya1NoYXJlZFRlbXBsYXRlLCBnZXROZXR3b3JrVmFsdWVBeGlzTGFiZWxUZW1wbGF0ZSwgZ2V0Rm9ybWF0dGVkRGF0ZVRpbWV9IGZyb20gJy4vY2hhcnQtdXRpbHMnO1xuXG5leHBvcnQgY2xhc3MgTmV0d29ya1JlYWx0aW1lQ2hhcnQgZXh0ZW5kcyBCYXNlQ2hhcnRcbntcblx0Y29uc3RydWN0b3IoKVxuXHR7XG5cdCAgICBzdXBlcigzMDApO1xuXG5cdFx0dGhpcy5fbGFzdFRvdGFsS2JPdXQgPSAwO1xuXHRcdHRoaXMuX2xhc3RUb3RhbEtiSW4gPSAwO1xuXHRcdHRoaXMuX2xhc3RUaW1lID0gMDtcblxuXHRcdC8vIEFwcGVuZCB0ZXh0IHRvIGRpc3BsYXkgZWxhcHNlZCB0aW1lXG5cdFx0dGhpcy5fZWxhcHNlZFR4dCA9ICQoJzxkaXY+Jywge2NsYXNzOiAndGV4dC1jZW50ZXInLCB0ZXh0OiAnLS0tJ30pO1xuXHRcdCQodGhpcykuYXBwZW5kKHRoaXMuX2VsYXBzZWRUeHQpO1xuXHR9XG5cblx0X2luaXRDaGFydFdpZGdldChjaGFydEh0bWwpXG5cdHtcblx0XHRyZXR1cm4gY2hhcnRIdG1sLmtlbmRvQ2hhcnQoe1xuXHRcdFx0dHJhbnNpdGlvbnM6IGZhbHNlLFxuXHRcdFx0Y2hhcnRBcmVhOiB7XG5cdFx0XHRcdGhlaWdodDogMjcwLFxuXHRcdFx0XHRiYWNrZ3JvdW5kOiAndHJhbnNwYXJlbnQnXG5cdFx0XHR9LFxuXHQgICAgICAgIGxlZ2VuZDoge1xuXHQgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgc2VyaWVzRGVmYXVsdHM6IHtcblx0ICAgICAgICAgICAgdHlwZTogJ2FyZWEnLFxuXHQgICAgICAgICAgICBsYWJlbHM6IHtcblx0ICAgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlLFxuXHQgICAgICAgICAgICAgICAgZm9ybWF0OiAnezB9Jyxcblx0ICAgICAgICAgICAgICAgIGJhY2tncm91bmQ6ICd0cmFuc3BhcmVudCdcblx0ICAgICAgICAgICAgfSxcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHNlcmllczogW3tcblx0XHRcdFx0bmFtZTogJ091dGdvaW5nJyxcblx0ICAgICAgICAgICAgZmllbGQ6ICdvdXRnb2luZycsXG5cdCAgICAgICAgICAgIGNhdGVnb3J5RmllbGQ6ICd0aW1lJyxcblx0XHRcdFx0Y29sb3I6IHRoaXMub3V0Z29pbmdDb2xvcixcblx0XHRcdFx0bGluZToge1xuXHRcdFx0XHRcdHdpZHRoOiAyXG5cdFx0XHRcdH1cblx0ICAgICAgICB9LFxuXHRcdFx0e1xuXHRcdFx0XHRuYW1lOiAnSW5jb21pbmcnLFxuXHRcdFx0XHRmaWVsZDogJ2luY29taW5nJyxcblx0XHRcdFx0Y2F0ZWdvcnlGaWVsZDogJ3RpbWUnLFxuXHRcdFx0XHRjb2xvcjogdGhpcy5pbmNvbWluZ0NvbG9yLFxuXHRcdFx0XHRsaW5lOiB7XG5cdFx0XHRcdFx0d2lkdGg6IDJcblx0XHRcdFx0fVxuXHRcdFx0fV0sXG5cdCAgICAgICAgdmFsdWVBeGlzOiB7XG5cdCAgICAgICAgICAgIGxhYmVsczoge1xuXHQgICAgICAgICAgICAgICAgZm9ybWF0OiAnezB9JyxcbiAgICAgIFx0XHRcdFx0dGVtcGxhdGU6IGdldE5ldHdvcmtWYWx1ZUF4aXNMYWJlbFRlbXBsYXRlKClcblx0ICAgICAgICAgICAgfSxcblx0ICAgICAgICAgICAgbGluZToge1xuXHQgICAgICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICAgICAgfSxcblx0XHRcdFx0bWluOiAwLFxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgY2F0ZWdvcnlBeGlzOiB7XG5cdFx0XHRcdG1ham9yR3JpZExpbmVzOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHRcdFx0XHRtYWpvclRpY2tzOiB7XG5cdFx0XHRcdFx0dmlzaWJsZTogZmFsc2Vcblx0XHRcdFx0fSxcblx0XHRcdFx0bGFiZWxzOiB7XG5cdFx0XHRcdFx0dmlzaWJsZTogZmFsc2Vcblx0XHRcdFx0fVxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgdG9vbHRpcDoge1xuXHRcdFx0XHRzaGFyZWQ6IHRydWUsXG5cdCAgICAgICAgICAgIHZpc2libGU6IHRydWUsXG5cdFx0XHRcdHNoYXJlZFRlbXBsYXRlOiBnZXROZXR3b3JrU2hhcmVkVGVtcGxhdGUoKSxcblx0XHRcdFx0YmFja2dyb3VuZDogJyNlNGU0ZTQnXG5cdCAgICAgICAgfVxuXHQgICAgfSkuZGF0YSgna2VuZG9DaGFydCcpO1xuXHR9XG5cblx0Z2V0IG91dGdvaW5nQ29sb3IoKVxuXHR7XG5cdFx0cmV0dXJuICcjQ0MwMDAwJztcblx0fVxuXG5cdGdldCBpbmNvbWluZ0NvbG9yKClcblx0e1xuXHRcdHJldHVybiAnIzAwOTkwMCc7XG5cdH1cblxuXHRhZGRFbnRyeSh0b3RhbE91dEtiLCB0b3RhbEluS2IpXG5cdHtcblx0XHRsZXQgbm93ID0gbmV3IERhdGUoKVxuXHRcdGxldCB0aW1lID0gbm93LmdldFRpbWUoKTtcblxuXHRcdC8vIFRoZSBmaXJzdCB2YWx1ZSBzZW50IGJ5IHRoZSBzZXJ2ZXIgaXMgbm90IHBsb3R0ZWQ6IGl0IHdvdWxkIGJlIGEgd29ybmcgdmFsdWUgYmVjYXVzZVxuXHRcdC8vIHdlIGhhdmUgdG8gY2FsY3VsYXRlIGl0IGFzIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdHdvIHRvdGFsIHZhbHVlcywgYnV0IHdlIGRvbid0IGhhdmUgdGhlIHByZXZpb3VzIG9uZVxuXHRcdGlmICh0aGlzLl9sYXN0VGltZSA+IDApXG5cdFx0e1xuXHRcdFx0bGV0IGVsYXBzZWRTZWNzID0gKHRpbWUgLSB0aGlzLl9sYXN0VGltZSkgLyAxMDAwO1xuXG5cdFx0XHRjb25zdCB2YWx1ZU91dCA9IE1hdGgucm91bmQoKHRvdGFsT3V0S2IgLSB0aGlzLl9sYXN0VG90YWxLYk91dCkgLyBlbGFwc2VkU2Vjcyk7XG5cdFx0XHRjb25zdCB2YWx1ZUluID0gTWF0aC5yb3VuZCgodG90YWxJbktiIC0gdGhpcy5fbGFzdFRvdGFsS2JJbikgLyBlbGFwc2VkU2Vjcyk7XG5cblx0XHRcdGxldCBuZXdFbnRyeSA9IHtcblx0XHRcdFx0dGltZTogZ2V0Rm9ybWF0dGVkRGF0ZVRpbWUobm93KSxcblx0XHRcdFx0dGltZXN0YW1wOiB0aW1lLFxuXHRcdFx0XHRvdXRnb2luZzogdmFsdWVPdXQsXG5cdFx0XHRcdGluY29taW5nOiB2YWx1ZUluXG5cdFx0XHR9O1xuXG5cdFx0XHQvLyBBZGQgZW50cnkgdG8gY2hhcnRcblx0XHRcdHN1cGVyLl9hZGRFbnRyeShuZXdFbnRyeSk7XG5cblx0XHRcdC8vIFVwZGF0ZSB4IGF4aXNcblx0XHRcdGlmICghdGhpcy5pc1BhdXNlZClcblx0XHRcdFx0dGhpcy5fdXBkYXRlRWxhcHNlZFRleHQoKTtcblx0XHR9XG5cblx0XHR0aGlzLl9sYXN0VG90YWxLYk91dCA9IHRvdGFsT3V0S2I7XG5cdFx0dGhpcy5fbGFzdFRvdGFsS2JJbiA9IHRvdGFsSW5LYjtcblx0XHR0aGlzLl9sYXN0VGltZSA9IHRpbWU7XG5cdH1cblxuXHRfdXBkYXRlRWxhcHNlZFRleHQoKVxuXHR7XG5cdFx0bGV0IGRzID0gdGhpcy5fZGF0YVNvdXJjZTtcblxuXHRcdGlmIChkcy50b3RhbCgpID4gMSlcblx0XHR7XG5cdFx0XHQvLyBHZXQgYXhpcyBsaW1pdHNcblx0XHRcdGNvbnN0IGNoYXJ0TWluaW11bSA9IGRzLmF0KDApLnRpbWVzdGFtcDtcblx0XHRcdGNvbnN0IGNoYXJ0TWF4aW11bSA9IGRzLmF0KGRzLnRvdGFsKCkgLSAxKS50aW1lc3RhbXA7XG5cblx0XHRcdC8vIFNldCBlbGFwc2VkIHRleHRcblx0XHRcdGxldCB0aXRsZTtcblx0XHRcdGxldCBzZWNvbmRzID0gTWF0aC5yb3VuZCggKGNoYXJ0TWF4aW11bSAtIGNoYXJ0TWluaW11bSkgLyAxMDAwICk7XG5cblx0XHRcdGlmIChzZWNvbmRzIDwgNjApXG5cdFx0XHRcdHRpdGxlID0gJ0xhc3QgJyArIChzZWNvbmRzICE9IDEgPyBzZWNvbmRzICsgJyBzZWNvbmRzJyA6ICdzZWNvbmQnKTtcblx0XHRcdGVsc2Vcblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgbWludXRlcyA9IE1hdGguZmxvb3Ioc2Vjb25kcyAvIDYwKTtcblx0XHRcdFx0dGl0bGUgPSAnTGFzdCAnICsgKG1pbnV0ZXMgIT0gMSA/IG1pbnV0ZXMgKyAnIG1pbnV0ZXMnIDogJ21pbnV0ZScpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLl9lbGFwc2VkVHh0LnRleHQodGl0bGUpO1xuXHRcdH1cblx0fVxufVxuXG4vLyBERUZJTkUgQ09NUE9ORU5UXG5pZiAoIXdpbmRvdy5jdXN0b21FbGVtZW50cy5nZXQoJ25ldHdvcmstcmVhbHRpbWUtY2hhcnQnKSlcblx0d2luZG93LmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnbmV0d29yay1yZWFsdGltZS1jaGFydCcsIE5ldHdvcmtSZWFsdGltZUNoYXJ0KTtcbiIsImltcG9ydCB7QmFzZUNoYXJ0fSBmcm9tICcuL2Jhc2UtY2hhcnQnO1xuXG5pbXBvcnQge2dldEJhc2ljU2hhcmVkVGVtcGxhdGUsIGdldEZvcm1hdHRlZERhdGVUaW1lfSBmcm9tICcuL2NoYXJ0LXV0aWxzJztcblxuZXhwb3J0IGNsYXNzIFN5c3RlbVF1ZXVlQ2hhcnQgZXh0ZW5kcyBCYXNlQ2hhcnRcbntcblx0Y29uc3RydWN0b3IoKVxuXHR7XG5cdCAgICBzdXBlcigyNDApO1xuXG5cdFx0dGhpcy5fYXZlcmFnZUxvYWQgPSAwO1xuXHR9XG5cblx0X2luaXRpYWxpemUoKVxuXHR7XG5cdFx0Y29uc3QgY2hhcnRIZWlnaHQgPSAyNDA7XG5cblx0XHQvLyBBcHBlbmQgY29udGFpbmVyIGZvciBjaGFydCAmIGdhdWdlXG5cdFx0bGV0IGNvbnRhaW5lciA9ICQoJzxkaXY+Jywge2NsYXNzOiAnZC1mbGV4IGZsZXgtcm93J30pO1xuXHRcdCQodGhpcykuYXBwZW5kKGNvbnRhaW5lcik7XG5cblx0XHQvLyBDSEFSVFxuXG5cdFx0bGV0IGNoYXJ0Q29udGFpbmVyID0gJCgnPGRpdj4nLCB7Y2xhc3M6ICdmbGV4LWdyb3ctMSd9KTtcblx0XHRjb250YWluZXIuYXBwZW5kKGNoYXJ0Q29udGFpbmVyKTtcblxuXHRcdC8vIENyZWF0ZSBjaGFydCBodG1sXG5cdFx0bGV0IGNoYXJ0SHRtbCA9ICQoJzxkaXY+Jyk7XG5cdFx0Y2hhcnRDb250YWluZXIuYXBwZW5kKGNoYXJ0SHRtbCk7XG5cblx0XHQvLyBJbml0aWFsaXplIGNoYXJ0XG5cdFx0dGhpcy5fY2hhcnRXaWRnZXQgPSB0aGlzLl9pbml0Q2hhcnRXaWRnZXQoY2hhcnRIdG1sLCBjaGFydEhlaWdodCk7XG5cblx0XHQvLyBBcHBlbmQgdGV4dCB0byBkaXNwbGF5IGVsYXBzZWQgdGltZVxuXHRcdHRoaXMuX2VsYXBzZWRUeHQgPSAkKCc8ZGl2PicsIHtjbGFzczogJ3RleHQtY2VudGVyJywgdGV4dDogJy0tLSd9KTtcblx0XHRjaGFydENvbnRhaW5lci5hcHBlbmQodGhpcy5fZWxhcHNlZFR4dCk7XG5cblx0XHQvLyBHQVVHRVxuXG5cdFx0bGV0IGdhdWdlQ29udGFpbmVyID0gJCgnPGRpdj4nKTtcblx0XHRjb250YWluZXIuYXBwZW5kKGdhdWdlQ29udGFpbmVyKTtcblxuXHRcdC8vIENyZWF0ZSBnYXVnZSBodG1sXG5cdFx0bGV0IGdhdWdlSHRtbCA9ICQoJzxkaXY+Jyk7XG5cdFx0Z2F1Z2VDb250YWluZXIuYXBwZW5kKGdhdWdlSHRtbCk7XG5cblx0XHQvLyBJbml0aWFsaXplIGdhdWdlXG5cdFx0dGhpcy5fZ2F1Z2VXaWRnZXQgPSB0aGlzLl9pbml0R2F1Z2VXaWRnZXQoZ2F1Z2VIdG1sLCBjaGFydEhlaWdodCk7XG5cblx0XHQvLyBBcHBlbmQgdGV4dCB0byBkaXNwbGF5IGxvYWRcblx0XHR0aGlzLl9sb2FkVHh0ID0gJCgnPGRpdj4nLCB7Y2xhc3M6ICd0ZXh0LWNlbnRlciBmb250LXdlaWdodC1ib2xkJywgdGV4dDogJy0tLSd9KTtcblx0XHRnYXVnZUNvbnRhaW5lci5hcHBlbmQodGhpcy5fbG9hZFR4dCk7XG5cblx0XHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdFx0Ly8gUmVzZXQgZGF0YSBzb3VyY2Vcblx0XHR0aGlzLnJlc2V0KCk7XG5cdH1cblxuXHRfaW5pdENoYXJ0V2lkZ2V0KGNoYXJ0SHRtbCwgaGVpZ2h0KVxuXHR7XG5cdFx0cmV0dXJuIGNoYXJ0SHRtbC5rZW5kb0NoYXJ0KHtcblx0XHRcdHRyYW5zaXRpb25zOiBmYWxzZSxcblx0XHRcdGNoYXJ0QXJlYToge1xuXHRcdFx0XHRoZWlnaHQ6IGhlaWdodCxcblx0XHRcdFx0YmFja2dyb3VuZDogJ3RyYW5zcGFyZW50J1xuXHRcdFx0fSxcblx0ICAgICAgICBsZWdlbmQ6IHtcblx0ICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHNlcmllc0RlZmF1bHRzOiB7XG5cdCAgICAgICAgICAgIHR5cGU6ICdhcmVhJyxcblx0ICAgICAgICAgICAgbGFiZWxzOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZSxcblx0ICAgICAgICAgICAgICAgIGZvcm1hdDogJ3swfScsXG5cdCAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kOiAndHJhbnNwYXJlbnQnXG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9LFxuXHQgICAgICAgIHNlcmllczogW1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bmFtZTogJ01lc3NhZ2VzJyxcblx0XHQgICAgICAgICAgICBmaWVsZDogJ2xvYWQnLFxuXHRcdCAgICAgICAgICAgIGNhdGVnb3J5RmllbGQ6ICd0aW1lJyxcblx0XHRcdFx0XHRjb2xvcjogJyMzMzk5ZmYnLFxuXHRcdFx0XHRcdGxpbmU6IHtcblx0XHRcdFx0XHRcdHdpZHRoOiAyXG5cdFx0XHRcdFx0fVxuXHRcdCAgICAgICAgfVxuXHRcdFx0XSxcblx0ICAgICAgICB2YWx1ZUF4aXM6IHtcblx0XHRcdFx0dGl0bGU6IHtcblx0XHRcdFx0XHR0ZXh0OiAnTWVzc2FnZXMnXG5cdFx0XHRcdH0sXG5cdCAgICAgICAgICAgIGxhYmVsczoge1xuXHQgICAgICAgICAgICAgICAgZm9ybWF0OiAnezB9J1xuXHQgICAgICAgICAgICB9LFxuXHQgICAgICAgICAgICBsaW5lOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHRcdFx0XHRtaW46IDBcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGNhdGVnb3J5QXhpczoge1xuXHQgICAgICAgICAgICBtYWpvckdyaWRMaW5lczoge1xuXHQgICAgICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICAgICAgfSxcblx0XHRcdFx0bWFqb3JUaWNrczoge1xuXHRcdFx0XHRcdHZpc2libGU6IGZhbHNlXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGxhYmVsczoge1xuXHRcdFx0XHRcdHZpc2libGU6IGZhbHNlXG5cdFx0XHRcdH1cblx0ICAgICAgICB9LFxuXHRcdFx0dG9vbHRpcDoge1xuXHRcdFx0XHRzaGFyZWQ6IHRydWUsXG5cdCAgICAgICAgICAgIHZpc2libGU6IHRydWUsXG5cdFx0XHRcdHNoYXJlZFRlbXBsYXRlOiBnZXRCYXNpY1NoYXJlZFRlbXBsYXRlKCksXG5cdFx0XHRcdGJhY2tncm91bmQ6ICcjZTRlNGU0J1xuXHQgICAgICAgIH1cblx0ICAgIH0pLmRhdGEoJ2tlbmRvQ2hhcnQnKTtcblx0fVxuXG5cdF9pbml0R2F1Z2VXaWRnZXQoZ2F1Z2VIdG1sLCBoZWlnaHQpXG5cdHtcblx0XHRyZXR1cm4gZ2F1Z2VIdG1sLmtlbmRvTGluZWFyR2F1Z2Uoe1xuXHRcdFx0cG9pbnRlcjoge1xuXHQgICAgICAgICAgICB2YWx1ZTogMCxcblx0ICAgICAgICAgICAgc2hhcGU6ICdhcnJvdycsXG5cdCAgICAgICAgICBcdHNpemU6IDEwLFxuXHRcdFx0XHRjb2xvcjogJyMyMTI1MjknXG5cdCAgICAgICAgfSxcblx0XHRcdGdhdWdlQXJlYToge1xuXHRcdFx0XHRoZWlnaHQ6IGhlaWdodFxuXHRcdFx0fSxcblx0ICAgICAgICBzY2FsZToge1xuXHQgICAgICAgICAgICBtYWpvclVuaXQ6IDEwLFxuXHQgICAgICAgICAgICBtaW5vclVuaXQ6IDEsXG5cdFx0XHRcdG1pbjogMCxcblx0XHRcdFx0bWF4OiAxMDAsXG5cdCAgICAgICAgICAgIHJhbmdlczogW1xuXHQgICAgICAgICAgICAgICAge1xuXHRcdFx0XHRcdFx0ZnJvbTogMCxcblx0ICAgICAgICAgICAgICAgICAgICB0bzogNTAsXG5cdCAgICAgICAgICAgICAgICAgICAgY29sb3I6ICcjMDBjYzAwJyxcblx0ICAgICAgICAgICAgICAgICAgXHRvcGFjaXR5OiAuNVxuXHQgICAgICAgICAgICAgICAgfSwge1xuXHQgICAgICAgICAgICAgICAgICAgIGZyb206IDUwLFxuXHQgICAgICAgICAgICAgICAgICAgIHRvOiA3NSxcblx0ICAgICAgICAgICAgICAgICAgICBjb2xvcjogJyNmZmUxMDYnLFxuXHQgICAgICAgICAgICAgICAgICBcdG9wYWNpdHk6IC41XG5cdCAgICAgICAgICAgICAgICB9LCB7XG5cdCAgICAgICAgICAgICAgICAgICAgZnJvbTogNzUsXG5cdCAgICAgICAgICAgICAgICAgICAgdG86IDEwMCxcblx0ICAgICAgICAgICAgICAgICAgICBjb2xvcjogJyNlZDE2MDEnLFxuXHQgICAgICAgICAgICAgICAgICBcdG9wYWNpdHk6IC41XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIF0sXG5cdCAgICAgICAgICBcdG1ham9yVGlja3M6IHtcblx0ICAgICAgICAgICAgICB2aXNpYmxlOiB0cnVlLFxuXHQgICAgICAgICAgICAgIHNpemU6IDEwXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICBcdG1pbm9yVGlja3M6IHtcblx0ICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHQgICAgICAgICAgXHRsYWJlbHM6IHtcblx0ICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHQgICAgICAgICAgXHRsaW5lOiB7XG5cdCAgICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICAgICAgfSxcblx0ICAgICAgICAgIFx0cmFuZ2VTaXplOiAxMFxuXHQgICAgICAgIH1cblx0ICAgIH0pLmRhdGEoJ2tlbmRvTGluZWFyR2F1Z2UnKTtcblx0fVxuXG5cdGFkZEVudHJ5KGxvYWQsIHF1ZXVlTXNnTGltaXQpXG5cdHtcblx0XHQvLyBDSEFSVFxuXG5cdFx0bGV0IG5vdyA9IG5ldyBEYXRlKCk7XG5cblx0XHRsZXQgbmV3RW50cnkgPSB7XG5cdFx0XHR0aW1lOiBnZXRGb3JtYXR0ZWREYXRlVGltZShub3cpLFxuXHRcdFx0dGltZXN0YW1wOiBub3cuZ2V0VGltZSgpLFxuXHRcdFx0bG9hZDogbG9hZFxuXHRcdH07XG5cblx0XHQvLyBBZGQgZW50cnkgdG8gY2hhcnRcblx0XHRzdXBlci5fYWRkRW50cnkobmV3RW50cnkpO1xuXG5cdFx0Ly8gVXBkYXRlIHggYXhpc1xuXHRcdGlmICghdGhpcy5pc1BhdXNlZClcblx0XHRcdHRoaXMuX3VwZGF0ZUVsYXBzZWRUZXh0KCk7XG5cblx0XHQvLyBHQVVHRVxuXG5cdFx0Ly8gRXZhbHVhdGUgYXZlcmFnZVxuXHRcdGxldCBudW1WYWx1ZXMgPSB0aGlzLl9kYXRhU291cmNlLnRvdGFsKCk7XG5cblx0XHRpZiAobnVtVmFsdWVzID4gMClcblx0XHR7XG5cdFx0XHRsZXQgdG90YWwgPSAwO1xuXHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBudW1WYWx1ZXM7IGkrKylcblx0XHRcdFx0dG90YWwgKz0gdGhpcy5fZGF0YVNvdXJjZS5hdChpKS5sb2FkO1xuXG5cdFx0XHR0aGlzLl9hdmVyYWdlTG9hZCA9IE1hdGgucm91bmQodG90YWwgLyBudW1WYWx1ZXMpO1xuXHRcdH1cblx0XHRlbHNlXG5cdFx0XHR0aGlzLl9hdmVyYWdlTG9hZCA9IDA7XG5cblx0XHRjb25zdCBhdmdMb2FkUGVyYyA9IE1hdGgucm91bmQodGhpcy5fYXZlcmFnZUxvYWQgLyBxdWV1ZU1zZ0xpbWl0ICogMTAwMCkgLyAxMDtcblxuXHRcdC8vIFNldCBnYXVnZSB2YWx1ZVxuXHRcdHRoaXMuX2dhdWdlV2lkZ2V0LnZhbHVlKGF2Z0xvYWRQZXJjKTtcblxuXHRcdC8vIFNldCBsb2FkIHRleHRcblx0XHR0aGlzLl9sb2FkVHh0LnRleHQoYXZnTG9hZFBlcmMgKyAnJScpXG5cdH1cblxuXHRfdXBkYXRlRWxhcHNlZFRleHQoKVxuXHR7XG5cdFx0bGV0IGRzID0gdGhpcy5fZGF0YVNvdXJjZTtcblxuXHRcdGlmIChkcy50b3RhbCgpID4gMSlcblx0XHR7XG5cdFx0XHQvLyBHZXQgYXhpcyBsaW1pdHNcblx0XHRcdGNvbnN0IGNoYXJ0TWluaW11bSA9IGRzLmF0KDApLnRpbWVzdGFtcDtcblx0XHRcdGNvbnN0IGNoYXJ0TWF4aW11bSA9IGRzLmF0KGRzLnRvdGFsKCkgLSAxKS50aW1lc3RhbXA7XG5cblx0XHRcdC8vIFNldCBlbGFwc2VkIHRleHRcblx0XHRcdGxldCBzZWNvbmRzID0gTWF0aC5yb3VuZCggKGNoYXJ0TWF4aW11bSAtIGNoYXJ0TWluaW11bSkgLyAxMDAwICk7XG5cdFx0XHRsZXQgdGl0bGU7XG5cblx0XHRcdGlmIChzZWNvbmRzIDwgNjApXG5cdFx0XHRcdHRpdGxlID0gJ0xhc3QgJyArIChzZWNvbmRzICE9IDEgPyBzZWNvbmRzICsgJyBzZWNvbmRzJyA6ICdzZWNvbmQnKTtcblx0XHRcdGVsc2Vcblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgbWludXRlcyA9IE1hdGguZmxvb3Ioc2Vjb25kcyAvIDYwKTtcblx0XHRcdFx0dGl0bGUgPSAnTGFzdCAnICsgKG1pbnV0ZXMgIT0gMSA/IG1pbnV0ZXMgKyAnIG1pbnV0ZXMnIDogJ21pbnV0ZScpO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLl9lbGFwc2VkVHh0LnRleHQodGl0bGUpO1xuXHRcdH1cblx0fVxuXG5cdGdldCBsb2FkKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9hdmVyYWdlTG9hZDtcblx0fVxufVxuXG4vLyBERUZJTkUgQ09NUE9ORU5UXG5pZiAoIXdpbmRvdy5jdXN0b21FbGVtZW50cy5nZXQoJ3N5c3RlbS1xdWV1ZS1jaGFydCcpKVxuXHR3aW5kb3cuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCdzeXN0ZW0tcXVldWUtY2hhcnQnLCBTeXN0ZW1RdWV1ZUNoYXJ0KTtcbiIsImltcG9ydCB7QmFzZUNoYXJ0fSBmcm9tICcuL2Jhc2UtY2hhcnQnO1xuXG5pbXBvcnQge2dldEJhc2ljU2hhcmVkVGVtcGxhdGUsIGdldEZvcm1hdHRlZERhdGVUaW1lfSBmcm9tICcuL2NoYXJ0LXV0aWxzJztcblxuZXhwb3J0IGNsYXNzIFN5c3RlbVdvcmtsb2FkQ2hhcnQgZXh0ZW5kcyBCYXNlQ2hhcnRcbntcblx0Y29uc3RydWN0b3IoKVxuXHR7XG5cdCAgICBzdXBlcigyNDApO1xuXHR9XG5cblx0X2luaXRpYWxpemUoKVxuXHR7XG5cdFx0Y29uc3QgY2hhcnRIZWlnaHQgPSAyNDA7XG5cblx0XHQvLyBBcHBlbmQgY29udGFpbmVyIGZvciBjaGFydCAmIGdhdWdlXG5cdFx0bGV0IGNvbnRhaW5lciA9ICQoJzxkaXY+Jywge2NsYXNzOiAnZC1mbGV4IGZsZXgtcm93J30pO1xuXHRcdCQodGhpcykuYXBwZW5kKGNvbnRhaW5lcik7XG5cblx0XHQvLyBDSEFSVFxuXG5cdFx0bGV0IGNoYXJ0Q29udGFpbmVyID0gJCgnPGRpdj4nLCB7Y2xhc3M6ICdmbGV4LWdyb3ctMSd9KTtcblx0XHRjb250YWluZXIuYXBwZW5kKGNoYXJ0Q29udGFpbmVyKTtcblxuXHRcdC8vIENyZWF0ZSBjaGFydCBodG1sXG5cdFx0bGV0IGNoYXJ0SHRtbCA9ICQoJzxkaXY+Jyk7XG5cdFx0Y2hhcnRDb250YWluZXIuYXBwZW5kKGNoYXJ0SHRtbCk7XG5cblx0XHQvLyBJbml0aWFsaXplIGNoYXJ0XG5cdFx0dGhpcy5fY2hhcnRXaWRnZXQgPSB0aGlzLl9pbml0Q2hhcnRXaWRnZXQoY2hhcnRIdG1sLCBjaGFydEhlaWdodCk7XG5cblx0XHQvLyBBcHBlbmQgdGV4dCB0byBkaXNwbGF5IGVsYXBzZWQgdGltZVxuXHRcdHRoaXMuX2VsYXBzZWRUeHQgPSAkKCc8ZGl2PicsIHtjbGFzczogJ3RleHQtY2VudGVyJywgdGV4dDogJy0tLSd9KTtcblx0XHRjaGFydENvbnRhaW5lci5hcHBlbmQodGhpcy5fZWxhcHNlZFR4dCk7XG5cblx0XHQvLyBHQVVHRVxuXG5cdFx0bGV0IGdhdWdlQ29udGFpbmVyID0gJCgnPGRpdj4nKTtcblx0XHRjb250YWluZXIuYXBwZW5kKGdhdWdlQ29udGFpbmVyKTtcblxuXHRcdC8vIENyZWF0ZSBnYXVnZSBodG1sXG5cdFx0bGV0IGdhdWdlSHRtbCA9ICQoJzxkaXY+Jyk7XG5cdFx0Z2F1Z2VDb250YWluZXIuYXBwZW5kKGdhdWdlSHRtbCk7XG5cblx0XHQvLyBJbml0aWFsaXplIGdhdWdlXG5cdFx0dGhpcy5fZ2F1Z2VXaWRnZXQgPSB0aGlzLl9pbml0R2F1Z2VXaWRnZXQoZ2F1Z2VIdG1sLCBjaGFydEhlaWdodCk7XG5cblx0XHQvLyBBcHBlbmQgdGV4dCB0byBkaXNwbGF5IGxvYWRcblx0XHR0aGlzLl9sb2FkVHh0ID0gJCgnPGRpdj4nLCB7Y2xhc3M6ICd0ZXh0LWNlbnRlciBmb250LXdlaWdodC1ib2xkJywgdGV4dDogJy0tLSd9KTtcblx0XHRnYXVnZUNvbnRhaW5lci5hcHBlbmQodGhpcy5fbG9hZFR4dCk7XG5cblx0XHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdFx0Ly8gUmVzZXQgZGF0YSBzb3VyY2Vcblx0XHR0aGlzLnJlc2V0KCk7XG5cdH1cblxuXHRfaW5pdENoYXJ0V2lkZ2V0KGNoYXJ0SHRtbCwgaGVpZ2h0KVxuXHR7XG5cdFx0cmV0dXJuIGNoYXJ0SHRtbC5rZW5kb0NoYXJ0KHtcblx0XHRcdHRyYW5zaXRpb25zOiBmYWxzZSxcblx0XHRcdGNoYXJ0QXJlYToge1xuXHRcdFx0XHRoZWlnaHQ6IGhlaWdodCxcblx0XHRcdFx0YmFja2dyb3VuZDogJ3RyYW5zcGFyZW50J1xuXHRcdFx0fSxcblx0ICAgICAgICBsZWdlbmQ6IHtcblx0ICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHNlcmllc0RlZmF1bHRzOiB7XG5cdCAgICAgICAgICAgIHR5cGU6ICdhcmVhJyxcblx0ICAgICAgICAgICAgbGFiZWxzOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZSxcblx0ICAgICAgICAgICAgICAgIGZvcm1hdDogJ3swfSUnLFxuXHQgICAgICAgICAgICAgICAgYmFja2dyb3VuZDogJ3RyYW5zcGFyZW50J1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBzZXJpZXM6IFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdG5hbWU6ICdXb3JrbG9hZCcsXG5cdFx0ICAgICAgICAgICAgZmllbGQ6ICdsb2FkJyxcblx0XHQgICAgICAgICAgICBjYXRlZ29yeUZpZWxkOiAndGltZScsXG5cdFx0XHRcdFx0Y29sb3I6ICcjMzM5OWZmJyxcblx0XHRcdFx0XHRsaW5lOiB7XG5cdFx0XHRcdFx0XHR3aWR0aDogMlxuXHRcdFx0XHRcdH1cblx0XHQgICAgICAgIH1cblx0XHRcdF0sXG5cdCAgICAgICAgdmFsdWVBeGlzOiB7XG5cdCAgICAgICAgICAgIGxhYmVsczoge1xuXHQgICAgICAgICAgICAgICAgZm9ybWF0OiAnezB9JSdcblx0ICAgICAgICAgICAgfSxcblx0ICAgICAgICAgICAgbGluZToge1xuXHQgICAgICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICAgICAgfSxcblx0XHRcdFx0bWluOiAwLFxuXHQgICAgXHRcdG1heDogMTAwXG5cdCAgICAgICAgfSxcblx0ICAgICAgICBjYXRlZ29yeUF4aXM6IHtcblx0ICAgICAgICAgICAgbWFqb3JHcmlkTGluZXM6IHtcblx0ICAgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlXG5cdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdG1ham9yVGlja3M6IHtcblx0XHRcdFx0XHR2aXNpYmxlOiBmYWxzZVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRsYWJlbHM6IHtcblx0XHRcdFx0XHR2aXNpYmxlOiBmYWxzZVxuXHRcdFx0XHR9XG5cdCAgICAgICAgfSxcblx0XHRcdHRvb2x0aXA6IHtcblx0XHRcdFx0c2hhcmVkOiB0cnVlLFxuXHQgICAgICAgICAgICB2aXNpYmxlOiB0cnVlLFxuXHRcdFx0XHRzaGFyZWRUZW1wbGF0ZTogZ2V0QmFzaWNTaGFyZWRUZW1wbGF0ZSgnezB9JScpLFxuXHRcdFx0XHRiYWNrZ3JvdW5kOiAnI2U0ZTRlNCdcblx0ICAgICAgICB9XG5cdCAgICB9KS5kYXRhKCdrZW5kb0NoYXJ0Jyk7XG5cdH1cblxuXHRfaW5pdEdhdWdlV2lkZ2V0KGdhdWdlSHRtbCwgaGVpZ2h0KVxuXHR7XG5cdFx0cmV0dXJuIGdhdWdlSHRtbC5rZW5kb0xpbmVhckdhdWdlKHtcblx0XHRcdHBvaW50ZXI6IHtcblx0ICAgICAgICAgICAgdmFsdWU6IDAsXG5cdCAgICAgICAgICAgIHNoYXBlOiAnYXJyb3cnLFxuXHQgICAgICAgICAgXHRzaXplOiAxMCxcblx0XHRcdFx0Y29sb3I6ICcjMjEyNTI5J1xuXHQgICAgICAgIH0sXG5cdFx0XHRnYXVnZUFyZWE6IHtcblx0XHRcdFx0aGVpZ2h0OiBoZWlnaHRcblx0XHRcdH0sXG5cdCAgICAgICAgc2NhbGU6IHtcblx0ICAgICAgICAgICAgbWFqb3JVbml0OiAxMCxcblx0ICAgICAgICAgICAgbWlub3JVbml0OiAxLFxuXHQgICAgICAgICAgICBtYXg6IDEwMCxcblx0XHRcdFx0bWluOiAwLFxuXHQgICAgICAgICAgICByYW5nZXM6IFtcblx0ICAgICAgICAgICAgICAgIHtcblx0ICAgICAgICAgICAgICAgICAgICBmcm9tOiAwLFxuXHQgICAgICAgICAgICAgICAgICAgIHRvOiA1MCxcblx0ICAgICAgICAgICAgICAgICAgICBjb2xvcjogJyMwMGNjMDAnLFxuXHQgICAgICAgICAgICAgICAgICBcdG9wYWNpdHk6IC41XG5cdCAgICAgICAgICAgICAgICB9LCB7XG5cdCAgICAgICAgICAgICAgICAgICAgZnJvbTogNTAsXG5cdCAgICAgICAgICAgICAgICAgICAgdG86IDc1LFxuXHQgICAgICAgICAgICAgICAgICAgIGNvbG9yOiAnI2ZmZTEwNicsXG5cdCAgICAgICAgICAgICAgICAgIFx0b3BhY2l0eTogLjVcblx0ICAgICAgICAgICAgICAgIH0sIHtcblx0ICAgICAgICAgICAgICAgICAgICBmcm9tOiA3NSxcblx0ICAgICAgICAgICAgICAgICAgICB0bzogMTAwLFxuXHQgICAgICAgICAgICAgICAgICAgIGNvbG9yOiAnI2VkMTYwMScsXG5cdCAgICAgICAgICAgICAgICAgIFx0b3BhY2l0eTogLjVcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgXSxcblx0ICAgICAgICAgIFx0bWFqb3JUaWNrczoge1xuXHQgICAgICAgICAgICAgIHZpc2libGU6IHRydWUsXG5cdCAgICAgICAgICAgICAgc2l6ZTogMTBcblx0ICAgICAgICAgICAgfSxcblx0ICAgICAgICAgIFx0bWlub3JUaWNrczoge1xuXHQgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICBcdGxhYmVsczoge1xuXHQgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICBcdGxpbmU6IHtcblx0ICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHQgICAgICAgICAgXHRyYW5nZVNpemU6IDEwXG5cdCAgICAgICAgfVxuXHQgICAgfSkuZGF0YSgna2VuZG9MaW5lYXJHYXVnZScpO1xuXHR9XG5cblx0YWRkRW50cnkobG9hZClcblx0e1xuXHRcdC8vIENIQVJUXG5cblx0XHRsZXQgbm93ID0gbmV3IERhdGUoKTtcblxuXHRcdGxldCBuZXdFbnRyeSA9IHtcblx0XHRcdHRpbWU6IGdldEZvcm1hdHRlZERhdGVUaW1lKG5vdyksXG5cdFx0XHR0aW1lc3RhbXA6IG5vdy5nZXRUaW1lKCksXG5cdFx0XHRsb2FkOiBsb2FkXG5cdFx0fTtcblxuXHRcdC8vIEFkZCBlbnRyeSB0byBjaGFydFxuXHRcdHN1cGVyLl9hZGRFbnRyeShuZXdFbnRyeSk7XG5cblx0XHQvLyBVcGRhdGUgeCBheGlzXG5cdFx0aWYgKCF0aGlzLmlzUGF1c2VkKVxuXHRcdFx0dGhpcy5fdXBkYXRlRWxhcHNlZFRleHQoKTtcblxuXHRcdC8vIEdBVUdFXG5cblx0XHQvLyBFdmFsdWF0ZSBhdmVyYWdlXG5cdFx0bGV0IG51bVZhbHVlcyA9IHRoaXMuX2RhdGFTb3VyY2UudG90YWwoKTtcblx0XHRsZXQgYXZlcmFnZUxvYWQgPSAwO1xuXG5cdFx0aWYgKG51bVZhbHVlcyA+IDApXG5cdFx0e1xuXHRcdFx0bGV0IHRvdGFsID0gMDtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgbnVtVmFsdWVzOyBpKyspXG5cdFx0XHRcdHRvdGFsICs9IHRoaXMuX2RhdGFTb3VyY2UuYXQoaSkubG9hZDtcblxuXHRcdFx0YXZlcmFnZUxvYWQgPSBNYXRoLnJvdW5kKHRvdGFsIC8gbnVtVmFsdWVzKTtcblx0XHR9XG5cblx0XHQvLyBTZXQgZ2F1Z2UgdmFsdWVcblx0XHR0aGlzLl9nYXVnZVdpZGdldC52YWx1ZShhdmVyYWdlTG9hZCk7XG5cblx0XHQvLyBTZXQgbG9hZCB0ZXh0XG5cdFx0dGhpcy5fbG9hZFR4dC50ZXh0KGF2ZXJhZ2VMb2FkICsgJyUnKVxuXHR9XG5cblx0X3VwZGF0ZUVsYXBzZWRUZXh0KClcblx0e1xuXHRcdGxldCBkcyA9IHRoaXMuX2RhdGFTb3VyY2U7XG5cblx0XHRpZiAoZHMudG90YWwoKSA+IDEpXG5cdFx0e1xuXHRcdFx0Ly8gR2V0IGF4aXMgbGltaXRzXG5cdFx0XHRjb25zdCBjaGFydE1pbmltdW0gPSBkcy5hdCgwKS50aW1lc3RhbXA7XG5cdFx0XHRjb25zdCBjaGFydE1heGltdW0gPSBkcy5hdChkcy50b3RhbCgpIC0gMSkudGltZXN0YW1wO1xuXG5cdFx0XHQvLyBTZXQgZWxhcHNlZCB0ZXh0XG5cdFx0XHRsZXQgc2Vjb25kcyA9IE1hdGgucm91bmQoIChjaGFydE1heGltdW0gLSBjaGFydE1pbmltdW0pIC8gMTAwMCApO1xuXHRcdFx0bGV0IHRpdGxlO1xuXG5cdFx0XHRpZiAoc2Vjb25kcyA8IDYwKVxuXHRcdFx0XHR0aXRsZSA9ICdMYXN0ICcgKyAoc2Vjb25kcyAhPSAxID8gc2Vjb25kcyArICcgc2Vjb25kcycgOiAnc2Vjb25kJyk7XG5cdFx0XHRlbHNlXG5cdFx0XHR7XG5cdFx0XHRcdGNvbnN0IG1pbnV0ZXMgPSBNYXRoLmZsb29yKHNlY29uZHMgLyA2MCk7XG5cdFx0XHRcdHRpdGxlID0gJ0xhc3QgJyArIChtaW51dGVzICE9IDEgPyBtaW51dGVzICsgJyBtaW51dGVzJyA6ICdtaW51dGUnKTtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5fZWxhcHNlZFR4dC50ZXh0KHRpdGxlKTtcblx0XHR9XG5cdH1cblxuXHRnZXQgbG9hZCgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fYXZlcmFnZUxvYWQ7XG5cdH1cbn1cblxuLy8gREVGSU5FIENPTVBPTkVOVFxuaWYgKCF3aW5kb3cuY3VzdG9tRWxlbWVudHMuZ2V0KCdzeXN0ZW0td29ya2xvYWQtY2hhcnQnKSlcblx0d2luZG93LmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnc3lzdGVtLXdvcmtsb2FkLWNoYXJ0JywgU3lzdGVtV29ya2xvYWRDaGFydCk7XG4iLCJpbXBvcnQge0Jhc2VDaGFydH0gZnJvbSAnLi9iYXNlLWNoYXJ0JztcblxuaW1wb3J0IHtnZXRCYXNpY1NoYXJlZFRlbXBsYXRlLCBnZXRGb3JtYXR0ZWREYXRlVGltZX0gZnJvbSAnLi9jaGFydC11dGlscyc7XG5cbmV4cG9ydCBjbGFzcyBUaHJlYWRDb3VudENoYXJ0IGV4dGVuZHMgQmFzZUNoYXJ0XG57XG5cdGNvbnN0cnVjdG9yKClcblx0e1xuXHQgICAgc3VwZXIoMTIwKTtcblx0fVxuXG5cdF9pbml0Q2hhcnRXaWRnZXQoY2hhcnRIdG1sKVxuXHR7XG5cdFx0cmV0dXJuIGNoYXJ0SHRtbC5rZW5kb0NoYXJ0KHtcblx0XHRcdHRyYW5zaXRpb25zOiBmYWxzZSxcblx0XHRcdGNoYXJ0QXJlYToge1xuXHRcdFx0XHRoZWlnaHQ6IDEyMCxcblx0XHRcdFx0YmFja2dyb3VuZDogJ3RyYW5zcGFyZW50J1xuXHRcdFx0fSxcblx0ICAgICAgICBsZWdlbmQ6IHtcblx0ICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHNlcmllc0RlZmF1bHRzOiB7XG5cdCAgICAgICAgICAgIHR5cGU6ICdhcmVhJyxcblx0ICAgICAgICAgICAgbGFiZWxzOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZSxcblx0ICAgICAgICAgICAgICAgIGZvcm1hdDogJ3swfScsXG5cdCAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kOiAndHJhbnNwYXJlbnQnXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgfSxcblx0ICAgICAgICBzZXJpZXM6IFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdG5hbWU6ICdUaHJlYWRzJyxcblx0XHQgICAgICAgICAgICBmaWVsZDogJ3RocmVhZHMnLFxuXHRcdCAgICAgICAgICAgIGNhdGVnb3J5RmllbGQ6ICd0aW1lJyxcblx0XHRcdFx0XHRjb2xvcjogdGhpcy50aHJlYWRzQ29sb3IsXG5cdFx0XHRcdFx0bGluZToge1xuXHRcdFx0XHRcdFx0d2lkdGg6IDJcblx0XHRcdFx0XHR9XG5cdFx0ICAgICAgICB9XG5cdFx0XHRdLFxuXHQgICAgICAgIHZhbHVlQXhpczoge1xuXHRcdFx0XHRtaW46IDAsXG5cdCAgICAgICAgICAgIGxhYmVsczoge1xuXHQgICAgICAgICAgICAgICAgZm9ybWF0OiAnezB9J1xuXHQgICAgICAgICAgICB9LFxuXHQgICAgICAgICAgICBsaW5lOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgY2F0ZWdvcnlBeGlzOiB7XG5cdCAgICAgICAgICAgIG1ham9yR3JpZExpbmVzOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHRcdFx0XHRtYWpvclRpY2tzOiB7XG5cdFx0XHRcdFx0dmlzaWJsZTogZmFsc2Vcblx0XHRcdFx0fSxcblx0XHRcdFx0bGFiZWxzOiB7XG5cdFx0XHRcdFx0dmlzaWJsZTogZmFsc2Vcblx0XHRcdFx0fVxuXHQgICAgICAgIH0sXG5cdFx0XHR0b29sdGlwOiB7XG5cdFx0XHRcdHNoYXJlZDogdHJ1ZSxcblx0ICAgICAgICAgICAgdmlzaWJsZTogdHJ1ZSxcblx0XHRcdFx0c2hhcmVkVGVtcGxhdGU6IGdldEJhc2ljU2hhcmVkVGVtcGxhdGUoKSxcblx0XHRcdFx0YmFja2dyb3VuZDogJyNlNGU0ZTQnXG5cdCAgICAgICAgfVxuXHQgICAgfSkuZGF0YSgna2VuZG9DaGFydCcpO1xuXHR9XG5cblx0Z2V0IHRocmVhZHNDb2xvcigpXG5cdHtcblx0XHRyZXR1cm4gJyMzMzk5RkYnO1xuXHR9XG5cblx0YWRkRW50cnkodGhyZWFkcylcblx0e1xuXHRcdGxldCBuZXdFbnRyeSA9IHtcblx0XHRcdHRpbWU6IGdldEZvcm1hdHRlZERhdGVUaW1lKG5ldyBEYXRlKCkpLFxuXHRcdFx0dGhyZWFkczogdGhyZWFkc1xuXHRcdH07XG5cblx0XHQvLyBBZGQgZW50cnkgdG8gY2hhcnRcblx0XHRzdXBlci5fYWRkRW50cnkobmV3RW50cnkpO1xuXHR9XG59XG5cbi8vIERFRklORSBDT01QT05FTlRcbmlmICghd2luZG93LmN1c3RvbUVsZW1lbnRzLmdldCgndGhyZWFkLWNvdW50LWNoYXJ0JykpXG5cdHdpbmRvdy5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ3RocmVhZC1jb3VudC1jaGFydCcsIFRocmVhZENvdW50Q2hhcnQpO1xuIiwiaW1wb3J0IHtCYXNlTW9kdWxlfSBmcm9tICcuL2Jhc2UtbW9kdWxlJztcbmltcG9ydCB7Ynl0ZXNUb1NpemUsIGtCeXRlc1RvU2l6ZX0gZnJvbSAnLi4vdXRpbHMvdXRpbGl0aWVzJztcbmltcG9ydCB7Z2V0VGltZVJhbmdlVG9vbHRpcFRlbXBsYXRlfSBmcm9tICcuLi9jb21wb25lbnRzL2NoYXJ0cy9jaGFydC11dGlscyc7XG5pbXBvcnQge0NwdVVzYWdlQ2hhcnR9IGZyb20gJy4uL2NvbXBvbmVudHMvY2hhcnRzL2NwdS11c2FnZS1jaGFydCc7XG5pbXBvcnQge1RocmVhZENvdW50Q2hhcnR9IGZyb20gJy4uL2NvbXBvbmVudHMvY2hhcnRzL3RocmVhZC1jb3VudC1jaGFydCc7XG5pbXBvcnQge01lbW9yeUNoYXJ0fSBmcm9tICcuLi9jb21wb25lbnRzL2NoYXJ0cy9tZW1vcnktY2hhcnQnO1xuaW1wb3J0IHtOZXR3b3JrUmVhbHRpbWVDaGFydH0gZnJvbSAnLi4vY29tcG9uZW50cy9jaGFydHMvbmV0d29yay1yZWFsdGltZS1jaGFydCc7XG5pbXBvcnQge05ldHdvcmsyNGhDaGFydH0gZnJvbSAnLi4vY29tcG9uZW50cy9jaGFydHMvbmV0d29yay0yNGgtY2hhcnQnO1xuaW1wb3J0IHtTeXN0ZW1Xb3JrbG9hZENoYXJ0fSBmcm9tICcuLi9jb21wb25lbnRzL2NoYXJ0cy9zeXN0ZW0td29ya2xvYWQtY2hhcnQnO1xuaW1wb3J0IHtTeXN0ZW1RdWV1ZUNoYXJ0fSBmcm9tICcuLi9jb21wb25lbnRzL2NoYXJ0cy9zeXN0ZW0tcXVldWUtY2hhcnQnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBEYXNoYm9hcmQgZXh0ZW5kcyBCYXNlTW9kdWxlXG57XG5cdGNvbnN0cnVjdG9yKClcblx0e1xuXHQgICAgc3VwZXIoJ2Rhc2hib2FyZCcpO1xuXG5cdFx0Ly8gT3V0Z29pbmcgcmVxdWVzdHNcblx0XHR0aGlzLlJFUV9JTklUID0gJ2luaXQnO1xuXHRcdHRoaXMuUkVRX0dFVF9EQVRBID0gJ2dldERhdGEnO1xuXHRcdHRoaXMuUkVRX0RVTVBfVEhSRUFEUyA9ICdnZXRUaER1bXAnO1xuXG5cdFx0Ly8gSW5jb21pbmcgcmVzcG9uc2VzXG5cdFx0dGhpcy5SRVNQX0lOSVQgPSAnaW5pdCc7XG5cdFx0dGhpcy5SRVNQX0RBVEEgPSAnZGF0YSc7XG5cdFx0dGhpcy5SRVNQX1RIUkVBRF9EVU1QID0gJ3RoRHVtcCc7XG5cblx0XHR0aGlzLl90Y3BPdXRUaHJlYWRzID0gMDtcblx0XHR0aGlzLl90Y3BPdXRMb2FkID0gMDtcblx0XHR0aGlzLl91ZHBPdXRUaHJlYWRzID0gMDtcblx0XHR0aGlzLl91ZHBPdXRMb2FkID0gMDtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIENPTU1PTiBNT0RVTEUgSU5URVJGQUNFIE1FVEhPRFNcblx0Ly8gVGhpcyBtZW1iZXJzIGFyZSB1c2VkIGJ5IHRoZSBtYWluIGNvbnRyb2xsZXJcblx0Ly8gdG8gY29tbXVuaWNhdGUgd2l0aCB0aGUgbW9kdWxlJ3MgY29udHJvbGxlci5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRpbml0aWFsaXplKGlkRGF0YSwgc2hlbGxDb250cm9sbGVyKVxuXHR7XG5cdFx0Ly8gQ2FsbCBzdXBlciBtZXRob2Rcblx0XHRzdXBlci5pbml0aWFsaXplKGlkRGF0YSwgc2hlbGxDb250cm9sbGVyKTtcblxuXHRcdC8vIEluaXRpYWxpemUgc2Nyb2xsaW5nIHRhYnNcblx0XHQkKCcjZHNoLXRhYk5hdmlnYXRvciA+ICN0YWJzJykuc2Nyb2xsaW5nVGFicyh7XG5cdFx0XHRib290c3RyYXBWZXJzaW9uOiA0LFxuXHRcdFx0c2Nyb2xsVG9UYWJFZGdlOiB0cnVlLFxuXHRcdFx0ZW5hYmxlU3dpcGluZzogdHJ1ZSxcblx0XHRcdGRpc2FibGVTY3JvbGxBcnJvd3NPbkZ1bGx5U2Nyb2xsZWQ6IHRydWUsXG5cdFx0XHRjc3NDbGFzc0xlZnRBcnJvdzogJ2ZhIGZhLWNoZXZyb24tbGVmdCcsXG5cdFx0XHRjc3NDbGFzc1JpZ2h0QXJyb3c6ICdmYSBmYS1jaGV2cm9uLXJpZ2h0J1xuXHRcdH0pO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBpbnRlcnZhbCBkcm9wZG93blxuXHRcdHRoaXMuX2ludGVydmFsRHJvcERvd24gPSAkKCcjZHNoLWludGVydmFsREQnKS5rZW5kb0Ryb3BEb3duTGlzdCh7XG5cdFx0XHR2YWx1ZVRlbXBsYXRlOiAnPHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkIHByLTFcIj5JbnRlcnZhbDo8L3NwYW4+PHNwYW4+IzpkYXRhLnRleHQjPC9zcGFuPicsXG5cdFx0XHRjaGFuZ2U6ICQucHJveHkodGhpcy5fb25VcGRhdGVJbnRlcnZhbENoYW5nZSwgdGhpcylcblx0XHR9KS5kYXRhKCdrZW5kb0Ryb3BEb3duTGlzdCcpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSB0aHJlYWRzIGdyaWRcblx0XHR0aGlzLl90aHJlYWRzR3JpZCA9ICQoJyNkc2gtdGhyZWFkc0dyaWQnKS5rZW5kb0dyaWQoe1xuXHRcdFx0ZGF0YVNvdXJjZTogdGhpcy5fZ2V0VGhyZWFkc0dyaWREYXRhU291cmNlKCksXG5cdFx0XHRzY3JvbGxhYmxlOiB0cnVlLFxuICAgICAgICAgICAgc29ydGFibGU6IHRydWUsXG4gICAgICAgICAgICBmaWx0ZXJhYmxlOiBmYWxzZSxcblx0XHRcdHJlc2l6YWJsZTogdHJ1ZSxcblx0XHRcdHNlbGVjdGFibGU6IGZhbHNlLFxuXHRcdFx0Y29sdW1uczogW1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0ZmllbGQ6ICdpZCcsXG5cdFx0XHRcdFx0dGl0bGU6ICdJZCcsXG5cdFx0XHRcdFx0d2lkdGg6IDYwXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRmaWVsZDogJ25hbWUnLFxuXHRcdFx0XHRcdHRpdGxlOiAnTmFtZScsXG5cdFx0XHRcdFx0d2lkdGg6ICc2NSUnXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRmaWVsZDogJ2NwdVRpbWUnLFxuXHRcdFx0XHRcdHRpdGxlOiAnQ1BVIFRpbWUnLFxuXHRcdFx0XHRcdGZvcm1hdDogJ3swfSUnLFxuXHRcdFx0XHRcdHdpZHRoOiAnMzUlJ1xuXHRcdFx0XHR9LFxuXHRcdFx0XSxcblx0XHRcdG5vUmVjb3Jkczoge1xuXHRcdFx0XHR0ZW1wbGF0ZTogJ05vIHRocmVhZHMuJ1xuXHRcdFx0fSxcblx0XHRcdGhlaWdodDogJ2NhbGMoMjQwcHggLSAuNzVyZW0gKyAxcmVtKSdcblx0XHR9KS5kYXRhKCdrZW5kb0dyaWQnKTtcblxuXHRcdC8vIEFkZCBjbGljayBsaXN0ZW5lciB0byB0aHJlYWRzIGR1bXAgYnV0dG9uXG5cdFx0JCgnI2RzaC1kdW1wVGhyZWFkc0J0Jykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vbkR1bXBUaHJlYWRzQ2xpY2ssIHRoaXMpKTtcblxuXHRcdC8vIENvbmZpZ3VyZSB0aHJlYWQgZHVtcCBwYW5lbFxuXHRcdCQoJyNkc2gtdGhyZWFkRHVtcE1vZGFsJykubW9kYWwoe1xuXHRcdFx0YmFja2Ryb3A6ICdzdGF0aWMnLFxuXHRcdFx0a2V5Ym9hcmQ6IGZhbHNlLFxuXHRcdFx0c2hvdzogZmFsc2UsXG5cdFx0fSk7XG5cblx0XHQvLyBBZGQgbGlzdGVuZXIgZm9yIHRocmVhZHMgZHVtcCBwYW5lbCBoaWRlXG5cdFx0JCgnI2RzaC10aHJlYWREdW1wTW9kYWwnKS5vbignaGlkZGVuLmJzLm1vZGFsJywgJC5wcm94eSh0aGlzLl9vblRocmVhZER1bXBNb2RhbEhpZGRlbiwgdGhpcykpO1xuXG5cdFx0Ly8gQWRkIGNsaWNrIGxpc3RlbmVyIHRvIHRocmVhZHMgZHVtcCBjb3B5IGJ1dHRvblxuXHRcdCQoJyNkc2gtY29weVRocmVhZER1bXBCdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25Db3B5VGhyZWFkRHVtcENsaWNrLCB0aGlzKSk7XG5cblx0XHQvLyBJbml0aWFsaXplIHRpbWUgcmFuZ2Ugc2xpZGVyXG5cdFx0dGhpcy5fdGltZVNsaWRlciA9ICQoJyNkc2gtdGltZVNsaWRlcicpLmtlbmRvUmFuZ2VTbGlkZXIoe1xuXHRcdFx0bWluOiAtMjQsXG4gICAgICAgICAgICBtYXg6IDAsXG4gICAgICAgICAgICBzbWFsbFN0ZXA6IDEsXG4gICAgICAgICAgICBsYXJnZVN0ZXA6IDAsXG5cdFx0XHRjaGFuZ2U6ICQucHJveHkodGhpcy5fb25UaW1lUmFuZ2VDaGFuZ2UsIHRoaXMpLFxuXHRcdFx0dG9vbHRpcDoge1xuXHRcdFx0XHR0ZW1wbGF0ZTogZ2V0VGltZVJhbmdlVG9vbHRpcFRlbXBsYXRlKClcblx0XHRcdH0sXG5cdFx0XHRsZWZ0RHJhZ0hhbmRsZVRpdGxlOiAnRHJhZycsXG5cdFx0XHRyaWdodERyYWdIYW5kbGVUaXRsZTogJ0RyYWcnLFxuXHRcdH0pLmRhdGEoJ2tlbmRvUmFuZ2VTbGlkZXInKTtcblxuXHRcdC8vIEFkZCBjbGljayBsaXN0ZW5lciB0byByZXNldCBjaGFydHMgYnV0dG9uXG5cdFx0JCgnI2RzaC1yZXNldEJ0Jykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vblJlc2V0Q2hhcnRzQ2xpY2ssIHRoaXMpKTtcblxuXHRcdC8vIEFkZCBjbGljayBsaXN0ZW5lciB0byBwbGF5ICYgcGF1c2UgY2hhcnQgdXBkYXRlIGJ1dHRvbnNcblx0XHQkKCcjZHNoLXBhdXNlQnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uUGF1c2VVcGRhdGVDbGljaywgdGhpcykpO1xuXHRcdCQoJyNkc2gtcGxheUJ0Jykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vblBsYXlVcGRhdGVDbGljaywgdGhpcykpO1xuXG5cdFx0Ly8gU2V0IHJlZmVyZW5jZSB0byBjaGFydHNcblx0XHR0aGlzLl9jcHVVc2FnZUNoYXJ0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RzaC1jcHVVc2FnZUNoYXJ0Jyk7XG5cdFx0dGhpcy5fdGhyZWFkQ291bnRDaGFydCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkc2gtdGhyZWFkQ291bnRDaGFydCcpO1xuXHRcdHRoaXMuX21lbW9yeUNoYXJ0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RzaC1tZW1vcnlDaGFydCcpO1xuXHRcdHRoaXMuX25ldHdvcmtSVENoYXJ0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RzaC1uZXR3b3JrUlRDaGFydCcpO1xuXHRcdHRoaXMuX25ldHdvcmsyNGhDaGFydCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkc2gtbmV0d29yazI0aENoYXJ0Jyk7XG5cdFx0dGhpcy5fc3lzV29ya2xvYWRDaGFydCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkc2gtc3lzdGVtV29ya2xvYWRDaGFydCcpO1xuXHRcdHRoaXMuX291dFRjcE1zZ1F1ZXVlQ2hhcnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZHNoLW91dGdvaW5nVGNwTWVzc2FnZXNRdWV1ZUNoYXJ0Jyk7XG5cdFx0dGhpcy5fb3V0VWRwTXNnUXVldWVDaGFydCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkc2gtb3V0Z29pbmdVZHBNZXNzYWdlc1F1ZXVlQ2hhcnQnKTtcblx0XHR0aGlzLl9zeXNRdWV1ZUNoYXJ0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2RzaC1zeXN0ZW1RdWV1ZUNoYXJ0Jyk7XG5cdFx0dGhpcy5fZXh0UXVldWVDaGFydCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkc2gtZXh0ZW5zaW9uUXVldWVDaGFydCcpO1xuXG5cdFx0Ly8gU2V0IGNvbG9ycyBpbiBjaGFydCBsZWdlbmRzXG5cdFx0JCgnI2RzaC1zeXN0ZW1Mb2FkQ29sb3InKS5jc3MoJ2NvbG9yJywgdGhpcy5fY3B1VXNhZ2VDaGFydC5zeXN0ZW1Db2xvcik7XG5cdFx0JCgnI2RzaC1wcm9jZXNzTG9hZENvbG9yJykuY3NzKCdjb2xvcicsIHRoaXMuX2NwdVVzYWdlQ2hhcnQucHJvY2Vzc0NvbG9yKTtcblx0XHQkKCcjZHNoLWFsbG9jTWVtQ29sb3InKS5jc3MoJ2NvbG9yJywgdGhpcy5fbWVtb3J5Q2hhcnQuYWxsb2NhdGVkQ29sb3IpO1xuXHRcdCQoJyNkc2gtdXNlZE1lbUNvbG9yJykuY3NzKCdjb2xvcicsIHRoaXMuX21lbW9yeUNoYXJ0LnVzZWRDb2xvcik7XG5cdFx0JCgnI2RzaC1pbmNvbWluZ05ldENvbG9yJykuY3NzKCdjb2xvcicsIHRoaXMuX25ldHdvcmtSVENoYXJ0LmluY29taW5nQ29sb3IpO1xuXHRcdCQoJyNkc2gtb3V0Z29pbmdOZXRDb2xvcicpLmNzcygnY29sb3InLCB0aGlzLl9uZXR3b3JrUlRDaGFydC5vdXRnb2luZ0NvbG9yKTtcblxuXHRcdC8vIFJlc2V0IHRpbWUgcmFuZ2Ugb24gMjRoIG5ldHdvcmsgY2hhcnRcblx0XHR0aGlzLl9vblRpbWVSYW5nZUNoYW5nZSgpO1xuXG5cdFx0Ly8gQWRkIGxpc3RlbmVyIHRvIHJlZHJhdyBhbGwgY2hhcnRzIG9uIG1haW4gdGFiIGNoYW5nZVxuXHRcdC8vICh0byB3b3JrIGFyb3VuZCBhbiBpc3N1ZSB3aXRoIHRoZSBjaGFydCByZXNpemluZyB0byBkZWZhdWx0IHdpZHRoIHdoZW4gcGFuZSBpcyBoaWRkZW4pXG5cdFx0JCgnYVtkYXRhLXRvZ2dsZT1cInRhYlwiXScpLm9uKCdzaG93bi5icy50YWInLCAkLnByb3h5KHRoaXMuX29uV2luZG93UmVzaXplLCB0aGlzKSk7XG5cblx0XHQvLyBBZGQgbGlzdGVuZXIgdG8gcmVkcmF3IG5ldHdvcmsgY2hhcnRzIG9uIG5ldHdvcmsgdGFiIGNoYW5nZVxuXHRcdC8vICh0byB3b3JrIGFyb3VuZCBhbiBpc3N1ZSB3aXRoIHRoZSBjaGFydCByZXNpemluZyB0byBkZWZhdWx0IHdpZHRoIHdoZW4gcGFuZSBpcyBoaWRkZW4pXG5cdFx0JCgnI2RzaC1uZXR3b3JrUGlsbHMgYVtkYXRhLXRvZ2dsZT1cInBpbGxcIl0nKS5vbignc2hvd24uYnMudGFiJywgJC5wcm94eSh0aGlzLl9yZWRyYXdOZXR3b3JrQ2hhcnRzLCB0aGlzKSk7XG5cblx0XHQvLyBBZGQgbGlzdGVuZXIgdG8gcmVkcmF3IG91dGdvaW5nIG1lc3NhZ2VzIHF1ZXVlIGNoYXJ0cyBvbiB0YWIgY2hhbmdlXG5cdFx0Ly8gKHRvIHdvcmsgYXJvdW5kIGFuIGlzc3VlIHdpdGggdGhlIGNoYXJ0IHJlc2l6aW5nIHRvIGRlZmF1bHQgd2lkdGggd2hlbiBwYW5lIGlzIGhpZGRlbilcblx0XHQkKCcjZHNoLW1zZ1F1ZXVlUGlsbHMgYVtkYXRhLXRvZ2dsZT1cInBpbGxcIl0nKS5vbignc2hvd24uYnMudGFiJywgJC5wcm94eSh0aGlzLl9yZWRyYXdPdXRNc2dDaGFydHMsIHRoaXMpKTtcblxuXHRcdC8vIEFkZCBsaXN0ZW5lciB0byByZWRyYXcgYWxsIGNoYXJ0cyBpbiBjYXNlIG9mIHdpbmRvdyByZXNpemVcblx0XHQkKHdpbmRvdykub24oJ3Jlc2l6ZScsICQucHJveHkodGhpcy5fb25XaW5kb3dSZXNpemUsIHRoaXMpKTtcblx0XHR0aGlzLl9vbldpbmRvd1Jlc2l6ZSgpOyAvLyBBbHNvIGRvIGl0IGltbWVkaWF0ZWx5XG5cblx0XHQvLyBBZGQgbGlzdGVuZXIgdG8gc2hvdyBoZWxwIHRvb2x0aXBzIGluIHF1ZXVlcyBzdGF0dXMgdGFiXG5cdFx0JCgnI2RzaC1xdWV1ZXMnKS5rZW5kb1Rvb2x0aXAoe1xuXHRcdFx0ZmlsdGVyOiAnaVt0aXRsZV0uaGVscCcsXG5cdFx0XHRwb3NpdGlvbjogJ3JpZ2h0Jyxcblx0XHRcdHdpZHRoOiAnMjUwcHgnLFxuXHRcdFx0Y29udGVudDogZnVuY3Rpb24oZSkge1xuXHRcdFx0XHRyZXR1cm4gYDxkaXYgY2xhc3M9XCJoZWxwLXRvb2x0aXBcIj4ke2UudGFyZ2V0LmRhdGEoJ3RpdGxlJyl9PC9kaXY+YDtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdC8vIEFkZCBsaXN0ZW5lciB0byByZWdlbmVyYXRlIGxpbmsgdG8gb3BlbiB3ZWIgc2VydmVyIGV4dGVybmFsIG1hbmFnZXIgY29uc29sZVxuXHRcdCQoJyNkc2gtdXNlSHR0cHNDaGVjaycpLm9uKCdjaGFuZ2UnLCAkLnByb3h5KHRoaXMuX29uVXNlSHR0cHNGb3JXc01hbmFnZXJDaGFuZ2UsIHRoaXMpKTtcblxuXHRcdC8vIFNlbmQgaW5pdGlhbGl6YXRpb24gcmVxdWVzdFxuXHRcdHRoaXMuc2VuZEV4dGVuc2lvblJlcXVlc3QodGhpcy5SRVFfSU5JVCk7XG5cdH1cblxuXHRkZXN0cm95KClcblx0e1xuXHRcdC8vIENhbGwgc3VwZXIgbWV0aG9kXG5cdFx0c3VwZXIuZGVzdHJveSgpO1xuXG5cdFx0Ly8gRGVzdHJveSBzY3JvbGxpbmcgdGFic1xuXHRcdCQoJyNkc2gtdGFiTmF2aWdhdG9yICN0YWJzJykuc2Nyb2xsaW5nVGFicygnZGVzdHJveScpO1xuXG5cdFx0Ly8gUmVtb3ZlIG90aGVyIGxpc3RlbmVyc1xuXHRcdCQoJyNkc2gtcmVzZXRCdCcpLm9mZignY2xpY2snKTtcblx0XHQkKCcjZHNoLXBhdXNlQnQnKS5vZmYoJ2NsaWNrJyk7XG5cdFx0JCgnI2RzaC1wbGF5QnQnKS5vZmYoJ2NsaWNrJyk7XG5cdFx0JCgnI2RzaC1kdW1wVGhyZWFkc0J0Jykub2ZmKCdjbGljaycpO1xuXHRcdCQoJ2FbZGF0YS10b2dnbGU9XCJ0YWJcIl0nKS5vZmYoJ3Nob3duLmJzLnRhYicpO1xuXHRcdCQoJ2FbZGF0YS10b2dnbGU9XCJwaWxsXCJdJykub2ZmKCdzaG93bi5icy50YWInKTtcblx0XHQkKHdpbmRvdykub2ZmKCdyZXNpemUnKTtcblx0XHQkKCcjZHNoLXVzZUh0dHBzQ2hlY2snKS5vZmYoJ2NoYW5nZScpO1xuXG5cdFx0Ly8gUmVtb3ZlIHRocmVhZCBkdW1wIHBhbmVsIGxpc3RlbmVyXG5cdFx0JCgnI2RzaC10aHJlYWREdW1wTW9kYWwnKS5vZmYoJ2hpZGRlbi5icy5tb2RhbCcpO1xuXG5cdFx0Ly8gQ2xlYXIgcmVxdWVzdCBzY2hlZHVsaW5nXG5cdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX3JlcXVlc3RUaW1lcik7XG5cdH1cblxuXHRvbkV4dGVuc2lvbkNvbW1hbmQoY29tbWFuZCwgZGF0YSlcblx0e1xuXHRcdC8vIEluaXRpYWxpemF0aW9uIGRhdGEgcmVjZWl2ZWRcblx0XHRpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfSU5JVClcblx0XHR7XG5cdFx0XHQvLyBTZXJ2ZXIgc2VuZHMgZmxhZ3MgaW5kaWNhdGluZyBpZiB3ZWIgc2VydmVyJ3MgaW50ZXJuYWwgbWFuYWdlciBpcyBhY2Nlc3NpYmxlIGFuZCBob3dcblx0XHRcdHRoaXMuX3dzTWFuYWdlckNvbmZpZyA9IHtcblx0XHRcdFx0aGFzQWNjZXNzOiBkYXRhLmdldEJvb2woJ2hhc1dzTWFuYWdlcicpLFxuXHRcdFx0XHRodHRwRW5hYmxlZDogZGF0YS5nZXRCb29sKCdodHRwRW5hYmxlZCcpLFxuXHRcdFx0XHRodHRwc0VuYWJsZWQ6IGRhdGEuZ2V0Qm9vbCgnaHR0cHNFbmFibGVkJyksXG5cdFx0XHRcdGh0dHBQb3J0OiBkYXRhLmdldEludCgnaHR0cFBvcnQnKSxcblx0XHRcdFx0aHR0cHNQb3J0OiBkYXRhLmdldEludCgnaHR0cHNQb3J0JyksXG5cdFx0XHR9XG5cblx0XHRcdC8vIEVuYWJsZSBhY2Nlc3MgdG8gd2ViIHNlcnZlciBtYW5hZ2VyIGNvbnNvbGVcblx0XHRcdHRoaXMuX2VuYWJsZVdlYlNlcnZlck1hbmFnZXJBY2Nlc3MoKTtcblxuXHRcdFx0Ly8gUmVxdWVzdCBkYXRhIHRvIHNlcnZlclxuXHRcdFx0dGhpcy5fcmVxdWVzdERhdGEodHJ1ZSk7XG5cdFx0fVxuXG5cdFx0Ly8gRGF0YSByZWNlaXZlZFxuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0RBVEEpXG5cdFx0e1xuXHRcdFx0Ly8gQ1BVIExPQUQgQ0hBUlRcblxuXHRcdFx0dGhpcy5fY3B1VXNhZ2VDaGFydC5hZGRFbnRyeShkYXRhLmdldERvdWJsZSgncENwdScpLCBkYXRhLmdldERvdWJsZSgnc0NwdScpKTtcblx0XHRcdCQoJyNkc2gtc3lzdGVtTG9hZExhYmVsJykudGV4dChkYXRhLmdldERvdWJsZSgnc0NwdScpKTtcblx0XHRcdCQoJyNkc2gtcHJvY2Vzc0xvYWRMYWJlbCcpLnRleHQoZGF0YS5nZXREb3VibGUoJ3BDcHUnKSk7XG5cblx0XHRcdC8vIEFzIHN5c3RlbSBjcHUgbG9hZCBpcyBub3QgYWx3YXlzIGF2YWlsYWJsZSAoZm9yIGV4YW1wbGUgb24gTWFjT1MgWCksIGxldCdzIGhpZGUgaXQgaW4gY2FzZSBpdCBpc24ndFxuXHRcdFx0aWYgKGRhdGEuZ2V0RG91YmxlKCdzQ3B1JykgPCAwKVxuXHRcdFx0XHQkKCcjZHNoLXN5c3RlbUxvYWRMZWdlbmQnKS5oaWRlKCk7XG5cblx0XHRcdC8vIFRIUkVBRFMgQ09VTlQgQ0hBUlRcblxuXHRcdFx0Y29uc3QgdGhyZWFkQ291bnQgPSBkYXRhLmdldFNGU0FycmF5KCd0aExpc3QnKS5zaXplKCk7XG5cdFx0XHR0aGlzLl90aHJlYWRDb3VudENoYXJ0LmFkZEVudHJ5KHRocmVhZENvdW50KTtcblx0XHRcdCQoJyNkc2gtdGhyZWFkc0NvdW50TGFiZWwnKS50ZXh0KHRocmVhZENvdW50KTtcblxuXHRcdFx0Ly8gTUVNT1JZIFVTQUdFIENIQVJUXG5cdFx0XHQvLyBOT1RFOiBtZW1vcnkgZGF0YSBpcyBzZW50IGFzIEJ5dGVzIGJ5IHRoZSBzZXJ2ZXJcblxuXHRcdFx0Y29uc3QgZnJlZU1lbSA9IGRhdGEuZ2V0TG9uZygnZnJlZU1lbScpO1xuXHRcdFx0Y29uc3QgbWF4TWVtID0gZGF0YS5nZXRMb25nKCdtYXhNZW0nKTtcblx0XHRcdGNvbnN0IHRvdGFsTWVtID0gZGF0YS5nZXRMb25nKCd0b3RhbE1lbScpO1xuXHRcdFx0Y29uc3QgdXNlZE1lbSA9IHRvdGFsTWVtIC0gZnJlZU1lbTtcblxuXHRcdFx0dGhpcy5fbWVtb3J5Q2hhcnQuYWRkRW50cnkodG90YWxNZW0sIHVzZWRNZW0pO1xuXHRcdFx0JCgnI2RzaC1tYXhNZW1vcnlMYWJlbCcpLnRleHQodGhpcy5fZ2V0TWVtT2JqZWN0KG1heE1lbSkubGFiZWwpO1xuXHRcdFx0JCgnI2RzaC1mcmVlTWVtb3J5TGFiZWwnKS50ZXh0KHRoaXMuX2dldE1lbU9iamVjdChmcmVlTWVtKS5sYWJlbCk7XG5cblx0XHRcdC8vIFRIUkVBRFMgTElTVFxuXG5cdFx0XHRjb25zdCB0b3RhbFRocmVhZENwdVRpbWUgPSBkYXRhLmdldExvbmcoJ3RoQ3B1Jyk7XG5cdFx0XHRsZXQgdGhyZWFkcyA9IFtdO1xuXG5cdFx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGRhdGEuZ2V0U0ZTQXJyYXkoJ3RoTGlzdCcpLnNpemUoKTsgaSsrKVxuXHRcdFx0e1xuXHRcdFx0XHRsZXQgdGhyZWFkRGF0YSA9IGRhdGEuZ2V0U0ZTQXJyYXkoJ3RoTGlzdCcpLmdldFNGU09iamVjdChpKTtcblxuXHRcdFx0XHR0aHJlYWRzLnB1c2goe1xuXHRcdFx0XHRcdGlkOiB0aHJlYWREYXRhLmdldExvbmcoJ2lkJyksXG5cdFx0XHRcdFx0bmFtZTogdGhyZWFkRGF0YS5nZXRVdGZTdHJpbmcoJ25hbWUnKSxcblx0XHRcdFx0XHRjcHVUaW1lOiBNYXRoLnJvdW5kKHRocmVhZERhdGEuZ2V0TG9uZygnY3B1JykgLyB0b3RhbFRocmVhZENwdVRpbWUgKiAxMDAwKSAvIDEwXG5cdFx0XHRcdH0pO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTdWJzdGl0dXRlIGdyaWQncyBkYXRhIHNvdXJjZSwgcmV0YWluaW5nIGN1cnJlbnQgc29ydGluZ1xuXHRcdFx0bGV0IGN1cnJTb3J0ID0gdGhpcy5fdGhyZWFkc0dyaWQuZGF0YVNvdXJjZS5zb3J0KCk7XG5cdFx0XHR0aGlzLl90aHJlYWRzR3JpZC5zZXREYXRhU291cmNlKHRoaXMuX2dldFRocmVhZHNHcmlkRGF0YVNvdXJjZSh0aHJlYWRzLCBjdXJyU29ydCkpO1xuXG5cdFx0XHQvLyBORVRXT1JLIFRSQUZGSUNcblx0XHRcdC8vIE5PVEU6IG5ldHdvcmsgdHJhZmZpYyBkYXRhIGlzIHNlbnQgYXMgS0J5dGVzIGJ5IHRoZSBzZXJ2ZXJcblxuXHRcdFx0aWYgKGRhdGEuY29udGFpbnNLZXkoJ250T3V0SGlzdG9yeScpKVxuXHRcdFx0e1xuXHRcdFx0XHRjb25zdCBvdXRnb2luZ0RhdGEgPSBkYXRhLmdldExvbmdBcnJheSgnbnRPdXRIaXN0b3J5Jyk7XG5cdFx0XHRcdGNvbnN0IGluY29taW5nRGF0YSA9IGRhdGEuZ2V0TG9uZ0FycmF5KCdudEluSGlzdG9yeScpO1xuXHRcdFx0XHRjb25zdCBzYW1wbGluZ1JhdGVNaW5zID0gZGF0YS5nZXRJbnQoJ250UmF0ZScpO1xuXHRcdFx0XHRjb25zdCBzaGlmdFNlY29uZHMgPSBkYXRhLmdldEludCgnbnRTaGlmdCcpO1xuXG5cdFx0XHRcdHRoaXMuX25ldHdvcmsyNGhDaGFydC5hZGRIaXN0b3J5RW50cmllcyhvdXRnb2luZ0RhdGEsIGluY29taW5nRGF0YSwgc2FtcGxpbmdSYXRlTWlucyAqIDYwLCBzaGlmdFNlY29uZHMpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBZGQgY3VycmVudCB2YWx1ZXNcblx0XHRcdHRoaXMuX25ldHdvcmsyNGhDaGFydC5hZGRFbnRyeShkYXRhLmdldExvbmcoJ250T3V0JyksIGRhdGEuZ2V0TG9uZygnbnRJbicpKTtcblx0XHRcdHRoaXMuX25ldHdvcmtSVENoYXJ0LmFkZEVudHJ5KGRhdGEuZ2V0TG9uZygnbnRPdXQnKSwgZGF0YS5nZXRMb25nKCdudEluJykpO1xuXG5cdFx0XHQvLyBUUkFGRklDIERFVEFJTFNcblxuXHRcdFx0Ly8gU2Vzc2lvbnNcblx0XHRcdCQoJyNkc2gtZGV0U2Vzc2lvbnNDdXJyZW50JykudGV4dCgnQ3VycmVudDogJyArIChkYXRhLmdldEludCgnc1NvY2tldCcpICsgZGF0YS5nZXRJbnQoJ3NIdHRwJykpKTtcblx0XHRcdCQoJyNkc2gtZGV0U2Vzc2lvbnNNYXgnKS50ZXh0KCdNYXg6ICcgKyBkYXRhLmdldEludCgnY2NzTWF4JykpO1xuXHRcdFx0JCgnI2RzaC1kZXRTZXNzaW9uc1NvY2tldCcpLnRleHQoJ1NvY2tldDogJyArIGRhdGEuZ2V0SW50KCdzU29ja2V0JykpO1xuXHRcdFx0JCgnI2RzaC1kZXRTZXNzaW9uc0h0dHAnKS50ZXh0KCdIdHRwOiAnICsgZGF0YS5nZXRJbnQoJ3NIdHRwJykpO1xuXG5cdFx0XHQvLyBVc2Vyc1xuXHRcdFx0JCgnI2RzaC1kZXRVc2Vyc0N1cnJlbnQnKS50ZXh0KCdDdXJyZW50OiAnICsgKGRhdGEuZ2V0SW50KCd1U29ja2V0JykgKyBkYXRhLmdldEludCgndUh0dHAnKSArIGRhdGEuZ2V0SW50KCd1TnBjJykpKTtcblx0XHRcdCQoJyNkc2gtZGV0VXNlcnNNYXgnKS50ZXh0KCdNYXg6ICcgKyBkYXRhLmdldEludCgnY2N1TWF4JykpO1xuXHRcdFx0JCgnI2RzaC1kZXRVc2Vyc1NvY2tldCcpLnRleHQoJ1NvY2tldDogJyArIGRhdGEuZ2V0SW50KCd1U29ja2V0JykpO1xuXHRcdFx0JCgnI2RzaC1kZXRVc2Vyc0h0dHAnKS50ZXh0KCdIdHRwOiAnICsgZGF0YS5nZXRJbnQoJ3VIdHRwJykpO1xuXHRcdFx0JCgnI2RzaC1kZXRVc2Vyc05wYycpLnRleHQoJ05wYzogJyArIGRhdGEuZ2V0SW50KCd1TnBjJykpO1xuXG5cdFx0XHQvLyBSb29tc1xuXHRcdFx0JCgnI2RzaC1kZXRSb29tcycpLnRleHQoZGF0YS5nZXRJbnQoJ3JUb3RhbCcpKTtcblx0XHRcdCQoJyNkc2gtZGV0Um9vbXNSZWd1bGFyJykudGV4dCgnUmVndWxhcjogJyArIChkYXRhLmdldEludCgnclRvdGFsJykgLSBkYXRhLmdldEludCgnckdhbWUnKSkpO1xuXHRcdFx0JCgnI2RzaC1kZXRSb29tc0dhbWUnKS50ZXh0KCdHYW1lOiAnICsgZGF0YS5nZXRJbnQoJ3JHYW1lJykpO1xuXG5cdFx0XHQvLyBUb3RhbCBkYXRhIHRyYW5zZmVyXG5cdFx0XHQkKCcjZHNoLWRldERhdGFUcmFuc2Zlck91dCcpLnRleHQoJ091dDogJyArIGtCeXRlc1RvU2l6ZShkYXRhLmdldExvbmcoJ250T3V0JykpKTtcblx0XHRcdCQoJyNkc2gtZGV0RGF0YVRyYW5zZmVySW4nKS50ZXh0KCdJbjogJyArIGtCeXRlc1RvU2l6ZShkYXRhLmdldExvbmcoJ250SW4nKSkpO1xuXG5cdFx0XHQvLyBDdXJyZW50IGRhdGEgdHJhbnNmZXIgcmF0ZVxuXHRcdFx0bGV0IG9iaiA9IHRoaXMuX25ldHdvcmtSVENoYXJ0LmdldExhc3RFbnRyeSgpO1xuXG5cdFx0XHRpZiAob2JqID09IG51bGwpXG5cdFx0XHRcdG9iaiA9IHtvdXRnb2luZzogMCwgaW5jb21pbmc6IDB9O1xuXG5cdFx0XHQkKCcjZHNoLWRldFRyYW5zZmVyUmF0ZU91dCcpLnRleHQoJ091dDogJyArIGtCeXRlc1RvU2l6ZShvYmoub3V0Z29pbmcsIDIsICdLQicsICcvcycpKTtcblx0XHRcdCQoJyNkc2gtZGV0VHJhbnNmZXJSYXRlSW4nKS50ZXh0KCdJbjogJyArIGtCeXRlc1RvU2l6ZShvYmouaW5jb21pbmcsIDIsICdLQicsICcvcycpKTtcblxuXHRcdFx0Ly8gQXZlcmFnZSBkYXRhIHRyYW5zZmVyIHJhdGUgb3ZlciB3aG9sZSB1cHRpbWVcblx0XHRcdGlmICh0aGlzLl91cHRpbWVTZWNzID4gMClcblx0XHRcdHtcblx0XHRcdFx0Y29uc3QgYXZnT3V0ID0gTWF0aC5yb3VuZChkYXRhLmdldExvbmcoJ250T3V0JykgLyB0aGlzLl91cHRpbWVTZWNzICogMTAwKSAvIDEwMDtcblx0XHRcdFx0Y29uc3QgYXZnSW4gPSBNYXRoLnJvdW5kKGRhdGEuZ2V0TG9uZygnbnRJbicpIC8gdGhpcy5fdXB0aW1lU2VjcyAqIDEwMCkgLyAxMDA7XG5cblx0XHRcdFx0JCgnI2RzaC1kZXRBdmdUcmFuc2ZlclJhdGVPdXQnKS50ZXh0KCdPdXQ6ICcgKyBrQnl0ZXNUb1NpemUoYXZnT3V0LCAyLCAnS0InLCAnL3MnKSk7XG5cdFx0XHRcdCQoJyNkc2gtZGV0QXZnVHJhbnNmZXJSYXRlSW4nKS50ZXh0KCdJbjogJyArIGtCeXRlc1RvU2l6ZShhdmdJbiwgMiwgJ0tCJywgJy9zJykpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBEcm9wcGVkIHBhY2tldHNcblx0XHRcdGNvbnN0IHRvdGFsUGFja2V0c091dCA9IGRhdGEuZ2V0TG9uZygncGt0T3V0Jyk7XG5cblx0XHRcdGNvbnN0IHRvdGFsRHJvcHBlZFRjcFBhY2tldHNPdXQgPSBkYXRhLmdldExvbmcoJ3BrdE91dERyb3AnKTtcblx0XHRcdCQoJyNkc2gtZGV0RHJvcHBlZFRjcFBhY2tldHNPdXQnKS50ZXh0KGBPdXQgVENQOiAke3RvdGFsRHJvcHBlZFRjcFBhY2tldHNPdXR9ICgke01hdGgucm91bmQodG90YWxEcm9wcGVkVGNwUGFja2V0c091dCAvIHRvdGFsUGFja2V0c091dCAqIDEwMCl9JSlgKTtcblxuXHRcdFx0Y29uc3QgdG90YWxEcm9wcGVkVWRwUGFja2V0c091dCA9IGRhdGEuZ2V0TG9uZygncGt0T3V0VWRwRHJvcCcpO1xuXHRcdFx0JCgnI2RzaC1kZXREcm9wcGVkVWRwUGFja2V0c091dCcpLnRleHQoYE91dCBVRFA6ICR7dG90YWxEcm9wcGVkVWRwUGFja2V0c091dH0gKCR7TWF0aC5yb3VuZCh0b3RhbERyb3BwZWRVZHBQYWNrZXRzT3V0IC8gdG90YWxQYWNrZXRzT3V0ICogMTAwKX0lKWApO1xuXG5cdFx0XHRjb25zdCB0b3RhbFBhY2tldHNJbiA9IGRhdGEuZ2V0TG9uZygncGt0SW4nKTtcblx0XHRcdGNvbnN0IHRvdGFsRHJvcHBlZFBhY2tldHNJbiA9IGRhdGEuZ2V0TG9uZygncGt0SW5Ecm9wJyk7XG5cdFx0XHQkKCcjZHNoLWRldERyb3BwZWRQYWNrZXRzSW4nKS50ZXh0KGBJbjogJHt0b3RhbERyb3BwZWRQYWNrZXRzSW59ICgke01hdGgucm91bmQodG90YWxEcm9wcGVkUGFja2V0c0luIC8gdG90YWxQYWNrZXRzSW4gKiAxMDApfSUpYCk7XG5cblx0XHRcdC8vIFNZU1RFTSBTVEFUVVNcblxuXHRcdFx0Ly8gT3V0Z29pbmcgVENQIG1lc3NhZ2VzIHF1ZXVlXG5cdFx0XHRjb25zdCBvdXRNc2dRdWV1ZSA9IGRhdGEuZ2V0SW50KCdvdXRNc2dRdWV1ZScpO1xuXHRcdFx0Y29uc3Qgb3V0TXNnUXVldWVNYXggPSBkYXRhLmdldEludCgnb3V0TXNnUXVldWVNYXgnKTtcblx0XHRcdHRoaXMuX291dFRjcE1zZ1F1ZXVlQ2hhcnQuYWRkRW50cnkob3V0TXNnUXVldWUsIG91dE1zZ1F1ZXVlTWF4KTtcblx0XHRcdHRoaXMuX3RjcE91dFRocmVhZHMgPSBkYXRhLmdldEludCgnb3V0TXNnVGgnKTtcblx0XHRcdHRoaXMuX3RjcE91dExvYWQgPSB0aGlzLl9vdXRUY3BNc2dRdWV1ZUNoYXJ0LmxvYWQ7XG5cblx0XHRcdC8vIE91dGdvaW5nIFVEUCBtZXNzYWdlcyBxdWV1ZVxuXHRcdFx0Y29uc3Qgb3V0VWRwTXNnUXVldWUgPSBkYXRhLmdldEludCgnb3V0VWRwTXNnUXVldWUnKTtcblx0XHRcdGNvbnN0IG91dFVkcE1zZ1F1ZXVlTWF4ID0gZGF0YS5nZXRJbnQoJ291dFVkcE1zZ1F1ZXVlTWF4Jyk7XG5cdFx0XHR0aGlzLl9vdXRVZHBNc2dRdWV1ZUNoYXJ0LmFkZEVudHJ5KG91dFVkcE1zZ1F1ZXVlLCBvdXRVZHBNc2dRdWV1ZU1heCk7XG5cdFx0XHR0aGlzLl91ZHBPdXRUaHJlYWRzID0gZGF0YS5nZXRJbnQoJ291dFVkcE1zZ1RoJyk7XG5cdFx0XHR0aGlzLl91ZHBPdXRMb2FkID0gdGhpcy5fb3V0VWRwTXNnUXVldWVDaGFydC5sb2FkO1xuXG5cdFx0XHR0aGlzLl91cGRhdGVPdXRNZXNzYWdlc1F1ZXVlU3RhdHVzKCk7XG5cblx0XHRcdC8vIFN5c3RlbSBDb250cm9sbGVyIHJlcXVlc3RzIHF1ZXVlXG5cdFx0XHRjb25zdCBzeXNDdHJsUXVldWUgPSBkYXRhLmdldEludCgnc3lzQ3RybFF1ZXVlJyk7XG5cdFx0XHRjb25zdCBzeXNDdHJsUXVldWVNYXggPSBkYXRhLmdldEludCgnc3lzQ3RybFF1ZXVlTWF4Jyk7XG5cdFx0XHR0aGlzLl9zeXNRdWV1ZUNoYXJ0LmFkZEVudHJ5KHN5c0N0cmxRdWV1ZSwgc3lzQ3RybFF1ZXVlTWF4KTtcblx0XHRcdCQoJyNkc2gtc3lzdGVtUXVldWVUaHJlYWRzJykudGV4dCh0aGlzLl9nZXRRdWV1ZVRocmVhZHNMYWJlbChkYXRhLmdldEludCgnc3lzQ3RybFRoJykpKTtcblx0XHRcdCQoJyNkc2gtc3lzdGVtUXVldWVMb2FkJykudGV4dCh0aGlzLl9nZXRRdWV1ZUxvYWRMYWJlbCh0aGlzLl9zeXNRdWV1ZUNoYXJ0LmxvYWQpKTtcblxuXHRcdFx0Ly8gRXh0ZW5zaW9uIENvbnRyb2xsZXIgcmVxdWVzdHMgcXVldWVcblx0XHRcdGNvbnN0IGV4dEN0cmxRdWV1ZSA9IGRhdGEuZ2V0SW50KCdleHRDdHJsUXVldWUnKTtcblx0XHRcdGNvbnN0IGV4dEN0cmxRdWV1ZU1heCA9IGRhdGEuZ2V0SW50KCdleHRDdHJsUXVldWVNYXgnKTtcblx0XHRcdHRoaXMuX2V4dFF1ZXVlQ2hhcnQuYWRkRW50cnkoZXh0Q3RybFF1ZXVlLCBleHRDdHJsUXVldWVNYXgpO1xuXHRcdFx0JCgnI2RzaC1leHRlbnNpb25RdWV1ZVRocmVhZHMnKS50ZXh0KHRoaXMuX2dldFF1ZXVlVGhyZWFkc0xhYmVsKGRhdGEuZ2V0SW50KCdleHRDdHJsVGgnKSkpO1xuXHRcdFx0JCgnI2RzaC1leHRlbnNpb25RdWV1ZUxvYWQnKS50ZXh0KHRoaXMuX2dldFF1ZXVlTG9hZExhYmVsKHRoaXMuX3N5c1F1ZXVlQ2hhcnQubG9hZCkpO1xuXG5cdFx0XHQvLyBFdmFsdWF0ZSBvdmVyYWxsIHN5c3RlbSB3b3JrbG9hZFxuXHRcdFx0bGV0IHN5c1dvcmtsb2FkID0gTWF0aC5yb3VuZCgob3V0TXNnUXVldWUgLyBvdXRNc2dRdWV1ZU1heCArXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCAgb3V0VWRwTXNnUXVldWUgLyBvdXRVZHBNc2dRdWV1ZU1heCArXG5cdFx0XHRcdCBcdFx0XHRcdFx0XHQgIHN5c0N0cmxRdWV1ZSAvIHN5c0N0cmxRdWV1ZU1heCArXG5cdFx0XHRcdCBcdFx0XHRcdFx0ICBcdCAgZXh0Q3RybFF1ZXVlIC8gZXh0Q3RybFF1ZXVlTWF4KSAqIDEwMCAvIDQpO1xuXHRcdFx0aWYgKHN5c1dvcmtsb2FkID4gMTAwKVxuXHRcdFx0XHRzeXNXb3JrbG9hZCA9IDEwMDtcblxuXHRcdFx0dGhpcy5fc3lzV29ya2xvYWRDaGFydC5hZGRFbnRyeShzeXNXb3JrbG9hZCk7XG5cdFx0fVxuXG5cdFx0Ly8gVGhyZWFkIGR1bXAgcmVjZWl2ZWRcblx0XHRlbHNlIGlmIChjb21tYW5kID09IHRoaXMuUkVTUF9USFJFQURfRFVNUClcblx0XHR7XG5cdFx0XHQvLyBFbmFibGUgYnV0dG9uXG5cdFx0XHQkKCcjZHNoLWR1bXBUaHJlYWRzQnQnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblxuXHRcdFx0Ly8gU2V0IHJlc3VsdFxuXHRcdFx0JCgnI2RzaC10aHJlYWREdW1wUmVzdWx0JykudGV4dChkYXRhLmdldFRleHQoJ2R1bXAnKSk7XG5cblx0XHRcdC8vIERpc3BsYXkgbW9kYWxcblx0XHRcdCQoJyNkc2gtdGhyZWFkRHVtcE1vZGFsJykubW9kYWwoJ3Nob3cnKTtcblx0XHR9XG5cdH1cblxuXHRvblVwdGltZVVwZGF0ZWQodmFsdWVzKVxuXHR7XG5cdFx0dGhpcy5fdXB0aW1lU2VjcyA9IHZhbHVlc1szXTtcblx0XHR0aGlzLl91cHRpbWVTZWNzICs9ICh2YWx1ZXNbMl0gKiA2MCk7XG5cdFx0dGhpcy5fdXB0aW1lU2VjcyArPSAodmFsdWVzWzFdICogNjAgKiA2MCk7XG5cdFx0dGhpcy5fdXB0aW1lU2VjcyArPSAodmFsdWVzWzBdICogMjQgKiA2MCAqIDYwKTtcblxuXHRcdCQoJyNkc2gtdXB0aW1lRGF5cycpLnRleHQoICh2YWx1ZXNbMF0gPD0gOSA/ICcwMCcgOiAodmFsdWVzWzBdIDw9IDk5ID8gJzAnIDogJycpKSArIHZhbHVlc1swXSApO1xuXHRcdCQoJyNkc2gtdXB0aW1lSG91cnMnKS50ZXh0KCAodmFsdWVzWzFdIDw9IDkgPyAnMCcgOiAnJykgKyB2YWx1ZXNbMV0gKTtcblx0XHQkKCcjZHNoLXVwdGltZU1pbnV0ZXMnKS50ZXh0KCAodmFsdWVzWzJdIDw9IDkgPyAnMCcgOiAnJykgKyB2YWx1ZXNbMl0gKTtcblx0XHQkKCcjZHNoLXVwdGltZVNlY29uZHMnKS50ZXh0KCAodmFsdWVzWzNdIDw9IDkgPyAnMCcgOiAnJykgKyB2YWx1ZXNbM10gKTtcblx0fVxuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdC8vIFVJIEVWRU5UIExJU1RFTkVSU1xuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdF9vblVwZGF0ZUludGVydmFsQ2hhbmdlKClcblx0e1xuXHRcdC8vIFJlcXVlc3QgZGF0YSB0byBzZXJ2ZXJcblx0XHR0aGlzLl9yZXF1ZXN0RGF0YSgpO1xuXHR9XG5cblx0X29uUGF1c2VVcGRhdGVDbGljaygpXG5cdHtcblx0XHR0aGlzLl9zZXRDaGFydFVwZGF0ZVBhdXNlZCh0cnVlKTtcblxuXHRcdC8vIEhpZGUgcGF1c2UgYnV0dG9uIGFuZCBzaG93IHBsYXkgYnV0dG9uXG5cdFx0JCgnI2RzaC1wYXVzZUJ0JykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdCQoJyNkc2gtcGxheUJ0JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHR9XG5cblx0X29uUGxheVVwZGF0ZUNsaWNrKClcblx0e1xuXHRcdHRoaXMuX3NldENoYXJ0VXBkYXRlUGF1c2VkKGZhbHNlKTtcblxuXHRcdC8vIEhpZGUgcGxheSBidXR0b24gYW5kIHNob3cgcGF1c2UgYnV0dG9uXG5cdFx0JCgnI2RzaC1wYXVzZUJ0JykucmVtb3ZlQ2xhc3MoJ2hpZGRlbicpO1xuXHRcdCQoJyNkc2gtcGxheUJ0JykuYWRkQ2xhc3MoJ2hpZGRlbicpO1xuXHR9XG5cblx0X29uUmVzZXRDaGFydHNDbGljaygpXG5cdHtcblx0XHQvLyBSZWFjdGl2YXRlIHJlYWx0aW1lIGNoYXJ0cyB1cGRhdGVcblx0XHR0aGlzLl9vblBsYXlVcGRhdGVDbGljaygpO1xuXG5cdFx0Ly8gUmVzZXQgcmVhbHRpbWUgY2hhcnRzXG5cdFx0dGhpcy5fY3B1VXNhZ2VDaGFydC5yZXNldCgpO1xuXHRcdHRoaXMuX3RocmVhZENvdW50Q2hhcnQucmVzZXQoKTtcblx0XHR0aGlzLl9tZW1vcnlDaGFydC5yZXNldCgpO1xuXHRcdHRoaXMuX25ldHdvcmtSVENoYXJ0LnJlc2V0KCk7XG5cdFx0dGhpcy5fc3lzV29ya2xvYWRDaGFydC5yZXNldCgpO1xuXHRcdHRoaXMuX291dFRjcE1zZ1F1ZXVlQ2hhcnQucmVzZXQoKTtcblx0XHR0aGlzLl9vdXRVZHBNc2dRdWV1ZUNoYXJ0LnJlc2V0KCk7XG5cdFx0dGhpcy5fc3lzUXVldWVDaGFydC5yZXNldCgpO1xuXHRcdHRoaXMuX2V4dFF1ZXVlQ2hhcnQucmVzZXQoKTtcblx0fVxuXG5cdF9yZWRyYXdOZXR3b3JrQ2hhcnRzKClcblx0e1xuXHRcdC8vIFJlZHJhdyBjaGFydHNcblx0XHR0aGlzLl9uZXR3b3JrUlRDaGFydC5yZWRyYXcoKTtcblx0XHR0aGlzLl9uZXR3b3JrMjRoQ2hhcnQucmVkcmF3KCk7XG5cblx0XHQvLyBSZWRyYXcgdGltZSByYW5nZSBzbGlkZXJcblx0XHR0aGlzLl90aW1lU2xpZGVyLnJlc2l6ZSgpO1xuXHR9XG5cblx0X3JlZHJhd091dE1zZ0NoYXJ0cygpXG5cdHtcblx0XHQvLyBSZWRyYXcgY2hhcnRzXG5cdFx0dGhpcy5fb3V0VGNwTXNnUXVldWVDaGFydC5yZWRyYXcoKTtcblx0XHR0aGlzLl9vdXRVZHBNc2dRdWV1ZUNoYXJ0LnJlZHJhdygpO1xuXG5cdFx0dGhpcy5fdXBkYXRlT3V0TWVzc2FnZXNRdWV1ZVN0YXR1cygpO1xuXHR9XG5cblx0X29uV2luZG93UmVzaXplKClcblx0e1xuXHRcdC8vIFJlZHJhdyBhbGwgZ2xvYmFsIGNoYXJ0c1xuXHRcdHRoaXMuX2NwdVVzYWdlQ2hhcnQucmVkcmF3KCk7XG5cdFx0dGhpcy5fdGhyZWFkQ291bnRDaGFydC5yZWRyYXcoKTtcblx0XHR0aGlzLl9tZW1vcnlDaGFydC5yZWRyYXcoKTtcblx0XHR0aGlzLl9yZWRyYXdOZXR3b3JrQ2hhcnRzKCk7XG5cblx0XHQvLyBSZWRyYXcgYWxsIHF1ZXVlIGNoYXJ0c1xuXHRcdHRoaXMuX3N5c1dvcmtsb2FkQ2hhcnQucmVkcmF3KCk7XG5cdFx0dGhpcy5fc3lzUXVldWVDaGFydC5yZWRyYXcoKTtcblx0XHR0aGlzLl9leHRRdWV1ZUNoYXJ0LnJlZHJhdygpO1xuXHRcdHRoaXMuX3JlZHJhd091dE1zZ0NoYXJ0cygpO1xuXHR9XG5cblx0X29uVGltZVJhbmdlQ2hhbmdlKClcblx0e1xuXHRcdGxldCB2YWx1ZXMgPSB0aGlzLl90aW1lU2xpZGVyLnZhbHVlKCk7XG5cblx0XHRpZiAodmFsdWVzWzBdID09IHZhbHVlc1sxXSlcblx0XHR7XG5cdFx0XHRpZiAodmFsdWVzWzFdID09IC0yNClcblx0XHRcdFx0dmFsdWVzWzFdID0gLTIzO1xuXG5cdFx0XHR2YWx1ZXNbMF0gPSB2YWx1ZXNbMV0gLSAxO1xuXG5cdFx0XHQvLyBSZXNldCB0aGUgdGltZSByYW5nZSBzbGlkZXIgdmFsdWUgKHdlIG5lZWQgdG8gdXNlIHNldFRpbWVvdXRcblx0XHRcdC8vIGJhY2F1c2UgZG9pbmcgaXQgaW4gdGhlIGNoYW5nZSBldmVudCBsaXN0ZW5lciBkb2Vzbid0IHJlZHJhdyB0aGUgc2xpZGVyKVxuXHRcdFx0c2V0VGltZW91dCgkLnByb3h5KCBmdW5jdGlvbih2YWx1ZXMpIHsgdGhpcy5fdGltZVNsaWRlci52YWx1ZSh2YWx1ZXMpOyB9LCB0aGlzKSwgMTAsIHZhbHVlcyk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fbmV0d29yazI0aENoYXJ0LnJhbmdlID0gdmFsdWVzO1xuXHR9XG5cblx0X29uVXNlSHR0cHNGb3JXc01hbmFnZXJDaGFuZ2UoKVxuXHR7XG5cdFx0Y29uc3Qgd3NNYW4gPSB0aGlzLl93c01hbmFnZXJDb25maWc7XG5cblx0XHRsZXQgdXJsID0gKCQoJyNkc2gtdXNlSHR0cHNDaGVjaycpLnByb3AoJ2NoZWNrZWQnKSA/ICdodHRwcycgOiAnaHR0cCcpICsgJzovLyc7XG5cdFx0dXJsICs9IHRoaXMuc21hcnRGb3guY29uZmlnLmhvc3Q7XG5cdFx0dXJsICs9ICc6JyArICgkKCcjZHNoLXVzZUh0dHBzQ2hlY2snKS5wcm9wKCdjaGVja2VkJykgPyB3c01hbi5odHRwc1BvcnQgOiB3c01hbi5odHRwUG9ydCk7XG5cdFx0dXJsICs9ICcvbWFuYWdlci9zdGF0dXMnO1xuXG5cdFx0JCgnI2RzaC10b1dzTWFuYWdlckJ0JykuYXR0cignaHJlZicsIHVybCk7XG5cdH1cblxuXHRfb25EdW1wVGhyZWFkc0NsaWNrKClcblx0e1xuXHRcdC8vIERpc2FibGUgYnV0dG9uXG5cdFx0JCgnI2RzaC1kdW1wVGhyZWFkc0J0JykuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcblxuXHRcdC8vIFNlbmQgcmVxdWVzdCB0byBleHRlbnNpb25cblx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX0RVTVBfVEhSRUFEUyk7XG5cdH1cblxuXHRfb25Db3B5VGhyZWFkRHVtcENsaWNrKClcblx0e1xuXHRcdCQoJyNkc2gtdGhyZWFkRHVtcFJlc3VsdCcpLmF0dHIoJ2NvbnRlbnRlZGl0YWJsZScsIHRydWUpO1xuXHRcdCQoJyNkc2gtdGhyZWFkRHVtcFJlc3VsdCcpLmF0dHIoJ3NwZWxsY2hlY2snLCBmYWxzZSk7XG5cdFx0JCgnI2RzaC10aHJlYWREdW1wUmVzdWx0JykuZm9jdXMoKTtcblx0XHRkb2N1bWVudC5leGVjQ29tbWFuZCgnc2VsZWN0QWxsJyk7XG5cdFx0ZG9jdW1lbnQuZXhlY0NvbW1hbmQoJ2NvcHknKTtcblx0XHR3aW5kb3cuZ2V0U2VsZWN0aW9uKCkucmVtb3ZlQWxsUmFuZ2VzKCk7XG5cdFx0JCgnI2RzaC10aHJlYWREdW1wUmVzdWx0JykuYmx1cigpO1xuXHRcdCQoJyNkc2gtdGhyZWFkRHVtcFJlc3VsdCcpLmF0dHIoJ2NvbnRlbnRlZGl0YWJsZScsIGZhbHNlKTtcblx0fVxuXG5cdF9vblRocmVhZER1bXBNb2RhbEhpZGRlbigpXG5cdHtcblx0XHQvLyBDbGVhciBtb2RhbCBjb250ZW50XG5cdFx0JCgnI2RzaC10aHJlYWREdW1wUmVzdWx0JykudGV4dCgnJyk7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLyBQUklWQVRFIE1FVEhPRFNcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRfZW5hYmxlV2ViU2VydmVyTWFuYWdlckFjY2VzcygpXG5cdHtcblx0XHRjb25zdCB3c01hbiA9IHRoaXMuX3dzTWFuYWdlckNvbmZpZztcblxuXHRcdGlmICh3c01hbi5oYXNBY2Nlc3MgJiYgKHdzTWFuLmh0dHBFbmFibGVkIHx8IHdzTWFuLmh0dHBzRW5hYmxlZCkpXG5cdFx0e1xuXHRcdFx0Ly8gSGlkZSBhbGVydFxuXHRcdFx0JCgnI2RzaC13c01hbmFnZXJBbGVydCcpLmhpZGUoKTtcblxuXHRcdFx0Ly8gRW5hYmxlIGJ1dHRvblxuXHRcdFx0JCgnI2RzaC10b1dzTWFuYWdlckJ0JykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cblx0XHRcdC8vIFNldCBjaGVja2JveFxuXHRcdFx0JCgnI2RzaC11c2VIdHRwc0NoZWNrJykucHJvcCgnY2hlY2tlZCcsIHdzTWFuLmh0dHBzRW5hYmxlZCk7XG5cdFx0XHQkKCcjZHNoLXVzZUh0dHBzQ2hlY2snKS5hdHRyKCdkaXNhYmxlZCcsICF3c01hbi5odHRwRW5hYmxlZCB8fCAhd3NNYW4uaHR0cHNFbmFibGVkKTtcblxuXHRcdFx0Ly8gR2VuZXJhdGUgbGlua1xuXHRcdFx0dGhpcy5fb25Vc2VIdHRwc0ZvcldzTWFuYWdlckNoYW5nZSgpO1xuXHRcdH1cblx0XHRlbHNlXG5cdFx0e1xuXHRcdFx0Ly8gU2hvdyBhbGVydFxuXHRcdFx0JCgnI2RzaC13c01hbmFnZXJBbGVydCcpLnNob3coKTtcblxuXHRcdFx0aWYgKCF3c01hbi5oYXNBY2Nlc3MpXG5cdFx0XHRcdCQoJyNkc2gtd3NNYW5hZ2VyQWxlcnQnKS5odG1sKCdBY2Nlc3MgdG8gVG9tY2F0IE1hbmFnZXIgY29uc29sZSByZXF1aXJlcyBhdCBsZWFzdCBvbmUgdXNlciB0byBiZSBkZWZpbmVkIGluIDxlbT5XZWIgU2VydmVyPC9lbT4gdGFiIG9mIDxzdHJvbmc+U2VydmVyIENvbmZpZ3VyYXRvcjwvc3Ryb25nPiBtb2R1bGUuJyk7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdCQoJyNkc2gtd3NNYW5hZ2VyQWxlcnQnKS5odG1sKCdBY2Nlc3MgdG8gVG9tY2F0IE1hbmFnZXIgY29uc29sZSByZXF1aXJlcyBlaXRoZXIgSFRUUCBvciBIVFRQUyB0byBiZSBlbmFibGVkIGluIDxlbT5XZWIgU2VydmVyPC9lbT4gdGFiIG9mIDxzdHJvbmc+U2VydmVyIENvbmZpZ3VyYXRvcjwvc3Ryb25nPiBtb2R1bGUuJyk7XG5cblx0XHRcdC8vIERpc2FibGUgYnV0dG9uXG5cdFx0XHQkKCcjZHNoLXRvV3NNYW5hZ2VyQnQnKS5hdHRyKCdkaXNhYmxlZCcsIHRydWUpO1xuXG5cdFx0XHQvLyBEaXNhYmxlIGNoZWNrYm94XG5cdFx0XHQkKCcjZHNoLXVzZUh0dHBzQ2hlY2snKS5hdHRyKCdjaGVja2VkJywgd3NNYW4uaHR0cHNFbmFibGVkKTtcblx0XHRcdCQoJyNkc2gtdXNlSHR0cHNDaGVjaycpLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIEJ1aWxkIHRoZSBwb2xsaW5nIHJlcXVlc3QgdG8gYmUgc2VudCB0byB0aGUgc2VydmVyLlxuXHQgKi9cblx0X3JlcXVlc3REYXRhKGdldEhpc3RvcnkgPSBmYWxzZSlcblx0e1xuXHRcdC8vIENsZWFyIHByZXZpb3VzIHJlcXVlc3Qgc2NoZWR1bGluZ1xuXHRcdGNsZWFyVGltZW91dCh0aGlzLl9yZXF1ZXN0VGltZXIpO1xuXG5cdFx0Ly8gQ2hlY2sgaWYgY29ubmVjdGlvbiBpcyBzdGlsbCBhdmFpbGFibGVcblx0XHRpZiAodGhpcy5zbWFydEZveC5pc0Nvbm5lY3RlZClcblx0XHR7XG5cdFx0XHQvLyBCdWlsZCByZXF1ZXN0IHBhcmFtZXRlcnNcblx0XHRcdGxldCBwYXJhbXMgPSBuZXcgU0ZTMlguU0ZTT2JqZWN0KCk7XG5cblx0XHRcdGlmIChnZXRIaXN0b3J5KVxuXHRcdFx0XHRwYXJhbXMucHV0Qm9vbCgnaGlzdG9yeScsIHRydWUpO1xuXG5cdFx0XHQvLyBTZW5kIHJlcXVlc3QgdG8gZXh0ZW5zaW9uXG5cdFx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX0dFVF9EQVRBLCBwYXJhbXMpO1xuXG5cdFx0XHQvLyBTY2hlZHVsZSBuZXh0IHJlcXVlc3Rcblx0XHRcdHRoaXMuX3JlcXVlc3RUaW1lciA9IHNldFRpbWVvdXQoJC5wcm94eSh0aGlzLl9yZXF1ZXN0RGF0YSwgdGhpcyksIE51bWJlcih0aGlzLl9pbnRlcnZhbERyb3BEb3duLnZhbHVlKCkpICogMTAwMCk7XG5cdFx0fVxuXHR9XG5cblx0X2dldE1lbU9iamVjdChieXRlcylcblx0e1xuXHRcdHJldHVybiB7XG5cdFx0XHRkYXRhOiBieXRlcyxcblx0XHRcdGxhYmVsOiBieXRlc1RvU2l6ZShieXRlcylcblx0XHR9O1xuXHR9XG5cblx0X3NldENoYXJ0VXBkYXRlUGF1c2VkKHBhdXNlZClcblx0e1xuXHRcdC8vIFBhdXNlL3JlYWN0aXZhdGUgcmVhbHRpbWUgY2hhcnRzXG5cdFx0dGhpcy5fY3B1VXNhZ2VDaGFydC5wYXVzZWQgPSBwYXVzZWQ7XG5cdFx0dGhpcy5fdGhyZWFkQ291bnRDaGFydC5wYXVzZWQgPSBwYXVzZWQ7XG5cdFx0dGhpcy5fbWVtb3J5Q2hhcnQucGF1c2VkID0gcGF1c2VkO1xuXHRcdHRoaXMuX25ldHdvcmtSVENoYXJ0LnBhdXNlZCA9IHBhdXNlZDtcblx0XHR0aGlzLl9zeXNXb3JrbG9hZENoYXJ0LnBhdXNlZCA9IHBhdXNlZDtcblx0XHR0aGlzLl9vdXRUY3BNc2dRdWV1ZUNoYXJ0LnBhdXNlZCA9IHBhdXNlZDtcblx0XHR0aGlzLl9zeXNRdWV1ZUNoYXJ0LnBhdXNlZCA9IHBhdXNlZDtcblx0XHR0aGlzLl9leHRRdWV1ZUNoYXJ0LnBhdXNlZCA9IHBhdXNlZDtcblx0fVxuXG5cdF9nZXRUaHJlYWRzR3JpZERhdGFTb3VyY2UoaXRlbXMsIHNvcnQpXG5cdHtcblx0XHRpZiAoIWl0ZW1zKVxuXHRcdFx0aXRlbXMgPSAnJztcblxuXHRcdGlmICghc29ydClcblx0XHR7XG5cdFx0XHRzb3J0ID0ge1xuXHRcdFx0XHRmaWVsZDogJ2NwdVRpbWUnLFxuXHRcdFx0XHRkaXI6ICdkZXNjJ1xuXHRcdFx0fTtcblx0XHR9XG5cblx0XHRyZXR1cm4gbmV3IGtlbmRvLmRhdGEuRGF0YVNvdXJjZSh7XG5cdFx0XHRzY2hlbWE6IHtcblx0XHRcdFx0bW9kZWw6IHtcblx0XHRcdFx0XHRpZDogJ2lkJ1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0c29ydDogc29ydCxcblx0XHRcdGRhdGE6IGl0ZW1zXG5cdFx0fSk7XG5cdH1cblxuXHRfZ2V0UXVldWVUaHJlYWRzTGFiZWwodGhyZWFkc051bSlcblx0e1xuXHRcdHJldHVybiBgVGhyZWFkczogJHt0aHJlYWRzTnVtfWA7XG5cdH1cblxuXHRfZ2V0UXVldWVMb2FkTGFiZWwobG9hZClcblx0e1xuXHRcdHJldHVybiBgQXZnLiBtZXNzYWdlczogJHtsb2FkfWA7XG5cdH1cblxuXHRfdXBkYXRlT3V0TWVzc2FnZXNRdWV1ZVN0YXR1cygpXG5cdHtcblx0XHRsZXQgdGhyZWFkc1N0ciA9IHRoaXMuX2dldFF1ZXVlVGhyZWFkc0xhYmVsKCctLScpO1xuXHRcdGxldCBsb2FkU3RyID0gdGhpcy5fZ2V0UXVldWVMb2FkTGFiZWwoJy0tJyk7XG5cblx0XHRpZiAoJCgnI2RzaC10Y3BQaWxsJykuaGFzQ2xhc3MoJ2FjdGl2ZScpKVxuXHRcdHtcblx0XHRcdHRocmVhZHNTdHIgPSB0aGlzLl9nZXRRdWV1ZVRocmVhZHNMYWJlbCh0aGlzLl90Y3BPdXRUaHJlYWRzKTtcblx0XHRcdGxvYWRTdHIgPSB0aGlzLl9nZXRRdWV1ZUxvYWRMYWJlbCh0aGlzLl90Y3BPdXRMb2FkKTtcblx0XHR9XG5cblx0XHRpZiAoJCgnI2RzaC11ZHBQaWxsJykuaGFzQ2xhc3MoJ2FjdGl2ZScpKVxuXHRcdHtcblx0XHRcdHRocmVhZHNTdHIgPSB0aGlzLl9nZXRRdWV1ZVRocmVhZHNMYWJlbCh0aGlzLl91ZHBPdXRUaHJlYWRzKTtcblx0XHRcdGxvYWRTdHIgPSB0aGlzLl9nZXRRdWV1ZUxvYWRMYWJlbCh0aGlzLl91ZHBPdXRMb2FkKTtcblx0XHR9XG5cblx0XHQkKCcjZHNoLW91dGdvaW5nTWVzc2FnZXNRdWV1ZVRocmVhZHMnKS50ZXh0KHRocmVhZHNTdHIpO1xuXHRcdCQoJyNkc2gtb3V0Z29pbmdNZXNzYWdlc1F1ZXVlTG9hZCcpLnRleHQobG9hZFN0cik7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLyBQUklWQVRFIEdFVFRFUlNcblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXG59XG4iXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FDMUhBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUMxSkE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUN4R0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7OztBQzNJQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FDck5BO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FDL0pBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FDNVBBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7OztBQ3JQQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQ3pGQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBIiwic291cmNlUm9vdCI6IiJ9
|