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.
Files changed (160) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rubyfox/server/data/config/admin/descriptors/config_room.txt +10 -1
  3. data/lib/rubyfox/server/data/config/admin/descriptors/config_server.txt +90 -20
  4. data/lib/rubyfox/server/data/config/admin/descriptors/config_zone.txt +9 -0
  5. data/lib/rubyfox/server/data/config/admin/descriptors/runtime_room.txt +11 -0
  6. data/lib/rubyfox/server/data/config/admin/descriptors/runtime_user.txt +3 -3
  7. data/lib/rubyfox/server/data/config/core.xml +4 -4
  8. data/lib/rubyfox/server/data/config/default.words.txt +11 -0
  9. data/lib/rubyfox/server/data/config/log4j.properties +1 -2
  10. data/lib/rubyfox/server/data/config/server.xml +1 -1
  11. data/lib/rubyfox/server/data/data/GeoLite2-Country.mmdb +0 -0
  12. data/lib/rubyfox/server/data/data/bannedusers/users.bin +0 -0
  13. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/bootstrap.jar +0 -0
  14. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/catalina-tasks.xml +39 -39
  15. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/catalina.sh +0 -0
  16. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/ciphers.sh +0 -0
  17. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/commons-daemon-native.tar.gz +0 -0
  18. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/commons-daemon.jar +0 -0
  19. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/configtest.sh +0 -0
  20. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/daemon.sh +0 -0
  21. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/digest.sh +0 -0
  22. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/makebase.sh +0 -0
  23. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/setclasspath.sh +0 -0
  24. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/shutdown.sh +0 -0
  25. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/startup.sh +0 -0
  26. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tomcat-juli.jar +0 -0
  27. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tomcat-native.tar.gz +0 -0
  28. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tool-wrapper.sh +0 -0
  29. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/version.sh +0 -0
  30. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/Catalina/localhost/rewrite.config +1 -1
  31. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/catalina.policy +263 -263
  32. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/catalina.properties +209 -207
  33. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/context.xml +31 -31
  34. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/jaspic-providers.xml +23 -23
  35. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/jaspic-providers.xsd +52 -52
  36. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/keystore.jks +0 -0
  37. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/server.xml +177 -161
  38. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/tomcat-users.xml +18 -7
  39. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/tomcat-users.xsd +59 -59
  40. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/web.xml +4740 -4737
  41. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/annotations-api.jar +0 -0
  42. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ant.jar +0 -0
  43. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ha.jar +0 -0
  44. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ssi.jar +0 -0
  45. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-storeconfig.jar +0 -0
  46. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-tribes.jar +0 -0
  47. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina.jar +0 -0
  48. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/el-api.jar +0 -0
  49. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jasper-el.jar +0 -0
  50. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jasper.jar +0 -0
  51. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jaspic-api.jar +0 -0
  52. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jsp-api.jar +0 -0
  53. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/servlet-api.jar +0 -0
  54. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/sfs2x-ws-helper.jar +0 -0
  55. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-api.jar +0 -0
  56. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-coyote.jar +0 -0
  57. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-dbcp.jar +0 -0
  58. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-cs.jar +0 -0
  59. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-de.jar +0 -0
  60. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-es.jar +0 -0
  61. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-fr.jar +0 -0
  62. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ja.jar +0 -0
  63. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ko.jar +0 -0
  64. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-pt-BR.jar +0 -0
  65. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ru.jar +0 -0
  66. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-zh-CN.jar +0 -0
  67. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-jdbc.jar +0 -0
  68. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-jni.jar +0 -0
  69. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-util-scan.jar +0 -0
  70. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-util.jar +0 -0
  71. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-websocket.jar +0 -0
  72. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/websocket-api.jar +0 -0
  73. data/lib/rubyfox/server/data/lib/javax.activation-1.2.0.jar +0 -0
  74. data/lib/rubyfox/server/data/lib/javax.mail.jar +0 -0
  75. data/lib/rubyfox/server/data/lib/js/JSApi.js +2 -1
  76. data/lib/rubyfox/server/data/lib/js/LibApi.js +181 -48
  77. data/lib/rubyfox/server/data/lib/sfs2x-admin.jar +0 -0
  78. data/lib/rubyfox/server/data/lib/sfs2x-cluster.jar +0 -0
  79. data/lib/rubyfox/server/data/lib/sfs2x-core.jar +0 -0
  80. data/lib/rubyfox/server/data/lib/sfs2x.jar +0 -0
  81. data/lib/rubyfox/server/data/sfs2x-service +26 -30
  82. data/lib/rubyfox/server/data/www/BlueBox.war +0 -0
  83. data/lib/rubyfox/server/data/www/HelloServlet/WEB-INF/web.xml +1 -3
  84. data/lib/rubyfox/server/data/www/ROOT/_css_/default.css +14 -6
  85. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/style.css +44 -2
  86. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/application.bundle.js +98 -61
  87. 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
  88. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-0.bundle.js +4 -4
  89. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-1.bundle.js +3 -3
  90. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-10.bundle.js +101 -66
  91. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-11.bundle.js +544 -8
  92. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12.bundle.js +915 -1480
  93. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12~module-15~module-16~module-4.bundle.js +2665 -0
  94. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-13.bundle.js +606 -3093
  95. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-13~module-16~module-17~module-4.bundle.js +2665 -0
  96. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-14.bundle.js +764 -0
  97. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-15.bundle.js +71 -0
  98. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-16.bundle.js +1787 -0
  99. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-17.bundle.js +3383 -0
  100. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-4.bundle.js +121 -1009
  101. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-5.bundle.js +1214 -1744
  102. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-6.bundle.js +398 -666
  103. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-7.bundle.js +717 -192
  104. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-8.bundle.js +2117 -665
  105. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-9.bundle.js +613 -690
  106. 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
  107. 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
  108. 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
  109. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-12.bundle.js +807 -0
  110. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-13.bundle.js +807 -0
  111. data/lib/rubyfox/server/data/www/ROOT/admin/modules/cluster-configurator.html +32 -0
  112. data/lib/rubyfox/server/data/www/ROOT/admin/modules/cluster-monitor.html +185 -0
  113. data/lib/rubyfox/server/data/www/ROOT/admin/modules/cluster-updater.html +47 -0
  114. data/lib/rubyfox/server/data/www/ROOT/admin/modules/extension-deployer.html +84 -0
  115. data/lib/rubyfox/server/data/www/ROOT/admin/modules/zone-monitor.html +15 -8
  116. data/lib/rubyfox/server/data/www/ROOT/index.html +13 -23
  117. data/lib/rubyfox/server/data/www/host-manager/META-INF/context.xml +2 -2
  118. data/lib/rubyfox/server/data/www/host-manager/WEB-INF/jsp/404.jsp +2 -2
  119. data/lib/rubyfox/server/data/www/host-manager/{manager.xml → WEB-INF/manager.xml} +5 -1
  120. data/lib/rubyfox/server/data/www/host-manager/WEB-INF/web.xml +17 -0
  121. data/lib/rubyfox/server/data/www/host-manager/css/manager.css +141 -0
  122. data/lib/rubyfox/server/data/www/host-manager/images/tomcat.svg +967 -0
  123. data/lib/rubyfox/server/data/www/manager/META-INF/context.xml +2 -0
  124. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorCerts.jsp +1 -1
  125. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorCiphers.jsp +1 -1
  126. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorTrustedCerts.jsp +1 -1
  127. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/sessionDetail.jsp +3 -3
  128. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/sessionsList.jsp +1 -1
  129. data/lib/rubyfox/server/data/www/manager/WEB-INF/web.xml +17 -0
  130. data/lib/rubyfox/server/data/www/manager/css/manager.css +141 -0
  131. data/lib/rubyfox/server/data/www/manager/images/tomcat.svg +967 -0
  132. data/lib/rubyfox/server/data/www/manager/xform.xsl +74 -59
  133. data/lib/rubyfox/server/version.rb +1 -1
  134. metadata +30 -31
  135. data/lib/rubyfox/server/data/config/admin/icons/Analytics.png +0 -0
  136. data/lib/rubyfox/server/data/config/admin/icons/BanManager.png +0 -0
  137. data/lib/rubyfox/server/data/config/admin/icons/BlueBoxMonitor.png +0 -0
  138. data/lib/rubyfox/server/data/config/admin/icons/Console.png +0 -0
  139. data/lib/rubyfox/server/data/config/admin/icons/Dashboard.png +0 -0
  140. data/lib/rubyfox/server/data/config/admin/icons/ExtensionManager.png +0 -0
  141. data/lib/rubyfox/server/data/config/admin/icons/LicenseManager.png +0 -0
  142. data/lib/rubyfox/server/data/config/admin/icons/LogViewer.png +0 -0
  143. data/lib/rubyfox/server/data/config/admin/icons/ServerConfigurator.png +0 -0
  144. data/lib/rubyfox/server/data/config/admin/icons/ServletManager.png +0 -0
  145. data/lib/rubyfox/server/data/config/admin/icons/ZoneConfigurator.png +0 -0
  146. data/lib/rubyfox/server/data/config/admin/icons/ZoneMonitor.png +0 -0
  147. data/lib/rubyfox/server/data/lib/BlueBox.war +0 -0
  148. data/lib/rubyfox/server/data/lib/apache-tomcat/LICENSE +0 -1061
  149. data/lib/rubyfox/server/data/lib/apache-tomcat/NOTICE +0 -68
  150. data/lib/rubyfox/server/data/lib/apache-tomcat/README.md +0 -81
  151. data/lib/rubyfox/server/data/lib/apache-tomcat/RELEASE-NOTES +0 -174
  152. data/lib/rubyfox/server/data/lib/imap.jar +0 -0
  153. data/lib/rubyfox/server/data/lib/mailapi.jar +0 -0
  154. data/lib/rubyfox/server/data/lib/pop3.jar +0 -0
  155. data/lib/rubyfox/server/data/lib/smtp.jar +0 -0
  156. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12~module-13~module-9.bundle.js +0 -2634
  157. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-9.bundle.js +0 -807
  158. data/lib/rubyfox/server/data/www/host-manager/images/tomcat.gif +0 -0
  159. data/lib/rubyfox/server/data/www/manager/images/tomcat.gif +0 -0
  160. /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
- /***/ "./node_modules/webpack/buildin/global.js":
308
- /*!***********************************!*\
309
- !*** (webpack)/buildin/global.js ***!
310
- \***********************************/
311
- /*! no static exports found */
312
- /***/ (function(module, exports) {
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
- var g;
306
+ this._maxValues = maxValues;
315
307
 
316
- // This works in non-strict mode
317
- g = (function() {
318
- return this;
319
- })();
308
+ // Initialize
309
+ this._initialize();
310
+ }
320
311
 
321
- try {
322
- // This works if eval is allowed (see CSP)
323
- g = g || new Function("return this")();
324
- } catch (e) {
325
- // This works if the window reference is available
326
- if (typeof window === "object") g = window;
327
- }
312
+ // Can be overridden
313
+ _initialize()
314
+ {
315
+ // Create chart html
316
+ let chartHtml = $('<div>');
317
+ $(this).append(chartHtml);
328
318
 
329
- // g can still be undefined, but nothing to do about it...
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
- module.exports = g;
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
- /***/ "./src/data/runtime-log-entry.js":
339
- /*!***************************************!*\
340
- !*** ./src/data/runtime-log-entry.js ***!
341
- \***************************************/
342
- /*! exports provided: RuntimeLogEntry */
343
- /***/ (function(module, __webpack_exports__, __webpack_require__) {
337
+ get paused()
338
+ {
339
+ return this.isPaused;
340
+ }
344
341
 
345
- "use strict";
346
- __webpack_require__.r(__webpack_exports__);
347
- /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RuntimeLogEntry", function() { return RuntimeLogEntry; });
348
- class RuntimeLogEntry
349
- {
350
- constructor(separator)
342
+ reset()
343
+ {
344
+ this._chartWidget.setDataSource([]);
345
+ }
346
+
347
+ redraw()
351
348
  {
352
- this.sep = separator
349
+ this._chartWidget.redraw();
353
350
  }
354
351
 
355
- static fromArray(separator, logEntryData)
352
+ getLastEntry()
356
353
  {
357
- let rle = new RuntimeLogEntry(separator);
354
+ let ds;
358
355
 
359
- rle.date = logEntryData[0];
360
- rle.time = logEntryData[1];
361
- rle.dateTime = rle._getDateTime();
362
- rle.level = logEntryData[2].trim();
363
- rle.thread = logEntryData[3];
364
- rle.clazz = logEntryData[4];
365
- rle.message = logEntryData[6];
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
- return rle;
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
- _getDateTime()
409
+ get _dataSource()
371
410
  {
372
- return this.date + '\n' + this.time;
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/modules/log-viewer.js":
380
- /*!***********************************!*\
381
- !*** ./src/modules/log-viewer.js ***!
382
- \***********************************/
383
- /*! exports provided: default */
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
- /* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return LogViewer; });
389
- /* harmony import */ var _base_module__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-module */ "./src/modules/base-module.js");
390
- /* harmony import */ var _data_runtime_log_entry__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../data/runtime-log-entry */ "./src/data/runtime-log-entry.js");
391
- /* harmony import */ var file_saver__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! file-saver */ "./node_modules/file-saver/dist/FileSaver.min.js");
392
- /* harmony import */ var file_saver__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(file_saver__WEBPACK_IMPORTED_MODULE_2__);
393
- /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! moment */ "./node_modules/moment/moment.js");
394
- /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_3__);
395
- /* harmony import */ var _utils_utilities__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/utilities */ "./src/utils/utilities.js");
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
- class LogViewer extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseModule"]
403
- {
404
- constructor()
405
- {
406
- super('logViewer');
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
- this.COMMANDS_PREFIX = 'logViewer';
409
- this.HELP_URL = '/admintool-LogViewer';
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
- this.ANY_LEVEL = '[any]';
412
- this.LEVELS = ['TRACE','DEBUG','INFO','WARN','ERROR'];
413
- this.ANY_CLASS = '[any]';
549
+ v1 = v2 - 1;
550
+ }
414
551
 
415
- this.LOG_DATA_LABEL = 'lines';
552
+ let start = Math.abs(v1);
553
+ let end = Math.abs(v2);
416
554
 
417
- this.BOOT_LOG_BACKUP_ID = 'SFS2X_BootLog';
418
- this.RUNTIME_LOG_BACKUP_ID = 'SFS2X_RuntimeLog';
419
- this.FULL_BACKUP_ID = 'SFS2X_Logs';
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
- // Outgoing requests
422
- this.REQ_GET_RUNTIME_LOG = 'getRunLog';
423
- this.REQ_GET_BOOT_LOG = 'getBootLog';
424
- this.REQ_GET_BACKUPS_STATUS = 'getBakStatus';
425
- this.REQ_BACKUP_BOOT_LOG = 'bakBootLog';
426
- this.REQ_BACKUP_RUNTIME_LOG = 'bakRunLog';
427
- this.REQ_BACKUP_FULL_LOGS = 'bakFullLogs';
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
- // Incoming responses
431
- this.RESP_INIT_ERROR = 'initErr';
432
- this.RESP_RUNTIME_LOG_ERROR = 'runLogErr';
433
- this.RESP_RUNTIME_LOG_INVALID = 'runLogInv';
434
- this.RESP_RUNTIME_LOG = 'runLog';
435
- this.RESP_BOOT_LOG_ERROR = 'bootLogErr';
436
- this.RESP_BOOT_LOG = 'bootLog';
437
- this.RESP_BACKUPS_STATUS = 'bakStatus';
438
- this.RESP_DELETE_BACKUP_FAILED = 'delBakFail';
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
- // COMMON MODULE INTERFACE METHODS
445
- // This members are used by the main controller
446
- // to communicate with the module's controller.
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
- initialize(idData, shellController)
450
- {
451
- // Call super method
452
- super.initialize(idData, shellController);
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
- // Add listener to tab shown event
465
- $('a[data-toggle="tab"]').on('shown.bs.tab', $.proxy(this._onTabShown, this));
608
+ /***/ }),
466
609
 
467
- // Initialize log lines dropdown
468
- this._logLinesDD = $('#lgv-logLinesDD').kendoDropDownList({
469
- valueTemplate: '<span class="text-muted pr-1">Log entries:</span><span>#:data.text#</span>',
470
- }).data('kendoDropDownList');
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
- // Initialize load button
473
- $('#lgv-loadBt').on('click', $.proxy(this._onRuntimeLogLoadBtClick, this));
474
-
475
- // Initialize progress bars
476
- $('.progress-bar').kendoProgressBar({
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
- // Initialize export button
504
- $('#lgv-exportRuntimeLogBt').on('click', $.proxy(this._onExportRuntimeLogBtClick, this));
626
+ class CpuUsageChart extends _base_chart__WEBPACK_IMPORTED_MODULE_0__["BaseChart"]
627
+ {
628
+ constructor()
629
+ {
630
+ super(120);
631
+ }
505
632
 
506
- // Initialize runtime log grid
507
- this._runtimeLogGrid = $('#lgv-runtimeLogGrid').kendoGrid({
508
- scrollable: true,
509
- sortable: false,
510
- //resizable: true,
511
- selectable: false,
512
- columns:
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
- field: 'dateTime',
516
- width: 150,
517
- title: 'Date/Time',
518
- },
519
- {
520
- field: 'level',
521
- width: 100,
522
- title: 'Level',
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
- field: 'message',
536
- width: 1000,
537
- title: 'Message',
538
- },
662
+ name: 'Process',
663
+ field: 'processLoad',
664
+ categoryField: 'time',
665
+ color: this.processColor,
666
+ line: {
667
+ width: 2
668
+ }
669
+ }
539
670
  ],
540
- noRecords: {
541
- template: 'No log entries to display.'
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
- field: 'name',
579
- width: 300,
580
- title: 'Filename',
675
+ line: {
676
+ visible: false
581
677
  },
582
- {
583
- field: 'size',
584
- width: 100,
585
- title: 'Size',
678
+ min: 0,
679
+ max: 100
680
+ },
681
+ categoryAxis: {
682
+ majorGridLines: {
683
+ visible: false
586
684
  },
587
- ],
588
- noRecords: {
589
- template: 'No backups available.'
590
- },
591
- change: $.proxy(this._onDownloadGridSelectionChange, this),
592
- dataSource: []
593
- }).data('kendoGrid');
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
- // Initialize delete button
596
- $('#lgv-deleteBt').on('click', $.proxy(this._onDeleteBtClick, this));
701
+ get systemColor()
702
+ {
703
+ return '#3399FF';
597
704
  }
598
705
 
599
- destroy()
706
+ get processColor()
600
707
  {
601
- // Call super method
602
- super.destroy();
708
+ return '#0033CC';
709
+ }
603
710
 
604
- // Remove listener to tab shown event
605
- $('a[data-toggle="tab"]').off('shown.bs.tab');
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
- // Destroy scrolling tabs
608
- $('#lgv-tabNavigator #tabs').scrollingTabs('destroy');
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
- $('#lgv-messageIn').off('input');
620
- }
729
+ /***/ }),
621
730
 
622
- onExtensionCommand(command, data)
623
- {
624
- // Error during initialization (unable to access log4j configuration file)
625
- if (command == this.RESP_INIT_ERROR)
626
- {
627
- const error = data.getUtfString('error');
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
- // Show an alert
630
- this.shellCtrl.showSimpleAlert(error, true);
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
- // Error responses
644
- else if (command == this.RESP_BOOT_LOG_ERROR || command == this.RESP_RUNTIME_LOG_ERROR)
645
- {
646
- const error = data.getUtfString('error');
747
+ class MemoryChart extends _base_chart__WEBPACK_IMPORTED_MODULE_0__["BaseChart"]
748
+ {
749
+ constructor()
750
+ {
751
+ super(300);
647
752
 
648
- // Show an alert
649
- this.shellCtrl.showSimpleAlert(error, true);
753
+ // Append text to display elapsed time
754
+ this._elapsedTxt = $('<div>', {class: 'text-center', text: '---'});
755
+ $(this).append(this._elapsedTxt);
756
+ }
650
757
 
651
- if (command == this.RESP_BOOT_LOG_ERROR)
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
- // Set tab to show error
654
- this._switchBootViewStack('lgv-bootLogErrorView');
655
-
656
- // Disable boot log backup generation
657
- this._bootLogBackupUnavailable = true;
658
- this._disableBackupInterface(false);
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
- this._bootLogRequested = true;
661
- }
824
+ get allocatedColor()
825
+ {
826
+ return '#3399FF';
827
+ }
662
828
 
663
- if (command == this.RESP_RUNTIME_LOG_ERROR)
664
- {
665
- // Disable controls
666
- this._enableRuntimeLogControls(false);
829
+ get usedColor()
830
+ {
831
+ return '#0033CC';
832
+ }
667
833
 
668
- // Remove loading bar (runtime log)
669
- this._switchRuntimeViewStack('lgv-runtimeLogErrorView');
834
+ addEntry(allocMem, usedMem)
835
+ {
836
+ let now = new Date();
670
837
 
671
- // Disable runtime log backup download
672
- this._runtimeLogBackupUnavailable = true;
673
- this._disableBackupInterface(false);
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
- // Modified conversion pattern in the log4j properties file: unable to parse the log
678
- else if (command == this.RESP_RUNTIME_LOG_INVALID)
679
- {
680
- // Disable controls
681
- this._enableRuntimeLogControls(false);
845
+ // Add entry to chart
846
+ super._addEntry(newEntry);
682
847
 
683
- // Fill in error message
684
- $('#lgv-convPattName').text(data.getUtfString('param'));
685
- $('#lgv-convPattVal').text(data.getUtfString('value'));
848
+ // Update x axis
849
+ if (!this.isPaused)
850
+ this._updateElapsedText();
851
+ }
686
852
 
687
- // Remove loading bar (runtime log)
688
- this._switchRuntimeViewStack('lgv-invConvPattView');
689
- }
853
+ _updateElapsedText()
854
+ {
855
+ let ds = this._dataSource;
690
856
 
691
- // Runtime log received
692
- else if (command == this.RESP_RUNTIME_LOG)
857
+ if (ds.total() > 1)
693
858
  {
694
- let classes = [];
695
- classes.push(this.ANY_CLASS);
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
- this._totalRuntimeLogEntries = logEntries.length;
863
+ // Set elapsed text
864
+ let seconds = Math.round( (chartMaximum - chartMinimum) / 1000 );
865
+ let title;
703
866
 
704
- // Parse log entries
705
- // We can't use the split method because there could be instances of the separator in the log message too
706
- for (let e = 0; e < logEntries.length; e++)
867
+ if (seconds < 60)
868
+ title = 'Last ' + (seconds != 1 ? seconds + ' seconds' : 'second');
869
+ else
707
870
  {
708
- const logEntry = logEntries[e];
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
- // Show classes list
733
- classes.sort(function (a, b) {
734
- return a.localeCompare(b);
735
- });
736
-
737
- this._classFilterDD.setDataSource(classes);
738
- this._classFilterDD.select(0);
875
+ this._elapsedTxt.text(title);
876
+ }
877
+ }
878
+ }
739
879
 
740
- // Assign data source to grid
741
- let ds = new kendo.data.DataSource({
742
- data: dsArr
743
- })
880
+ // DEFINE COMPONENT
881
+ if (!window.customElements.get('memory-chart'))
882
+ window.customElements.define('memory-chart', MemoryChart);
744
883
 
745
- this._setRuntimeLogDataSource(ds);
884
+ /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! jquery */ "jquery")))
746
885
 
747
- // Re-enable log loading controls
748
- this._enableRuntimeLogControls(true);
886
+ /***/ }),
749
887
 
750
- // Remove loading bar
751
- this._switchRuntimeViewStack('lgv-runtimeLogView');
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
- // Boot log received
755
- else if (command == this.RESP_BOOT_LOG)
756
- {
757
- const bootLogEntries = data.getSFSArray(this.LOG_DATA_LABEL);
758
- let text = '';
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
- // Remove loading bar
766
- this._switchBootViewStack('lgv-bootLogView');
767
- }
904
+ class Network24hChart extends HTMLElement
905
+ {
906
+ constructor()
907
+ {
908
+ super();
768
909
 
769
- // Logs backups status received
770
- else if (command == this.RESP_BACKUPS_STATUS)
771
- {
772
- // Show/hide operation in progress message
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
- // Backup files list
776
- if (data.containsKey('files'))
777
- {
778
- let files = data.getSFSArray('files');
915
+ // Create chart html
916
+ let chartHtml = $('<div>');
917
+ $(this).append(chartHtml);
779
918
 
780
- let lastBootLogBackupFound = false;
781
- let lastRuntimeLogBackupFound = false;
782
- let lastFullBackupFound = false;
919
+ // Initialize chart
920
+ this._chartWidget = this._initChartWidget(chartHtml);
921
+ }
783
922
 
784
- let backupsList = [];
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
- const webServerProtocol = (data.containsKey('protocol') ? data.getUtfString('protocol') : 'http') + '://';
787
- const webServerPort = (data.containsKey('port') ? ':' + data.getInt('port') : '');
995
+ redraw()
996
+ {
997
+ this._chartWidget.redraw();
998
+ }
788
999
 
789
- let totalSize = 0;
1000
+ set range(values)
1001
+ {
1002
+ this._range = values;
790
1003
 
791
- for (let f = 0; f < files.size(); f++)
792
- {
793
- const file = files.getSFSObject(f);
1004
+ this._updateXAxisLimits();
1005
+ }
794
1006
 
795
- const filePath = file.getUtfString('path');
1007
+ get range()
1008
+ {
1009
+ return this._range;
1010
+ }
796
1011
 
797
- const fileObj = {};
798
- fileObj.path = filePath;
799
- fileObj.url = webServerProtocol + this.smartFox.config.host + webServerPort + '/' + filePath;
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
- totalSize += file.getLong('size');
1016
+ let now = new Date();
806
1017
 
807
- // Check if this is a boot log backup
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
- lastBootLogBackupFound = true;
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
- // Check if this is a runtime log backup
819
- if (!lastRuntimeLogBackupFound)
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
- lastRuntimeLogBackupFound = true;
826
- }
827
- }
1029
+ if (outgoingData.length > 1)
1030
+ {
1031
+ let dataSource = new kendo.data.DataSource();
828
1032
 
829
- // Check if this is a full backup
830
- if (!lastFullBackupFound)
831
- {
832
- if (fileObj.name.startsWith(this.FULL_BACKUP_ID))
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
- lastFullBackupFound = true;
837
- }
838
- }
1038
+ let date = start.clone();
1039
+ date.add(i * samplingRateSeconds, 's');
839
1040
 
840
- // Populate logs list
841
- backupsList.push(fileObj);
1041
+ this.addEntry(totalOut, totalIn, dataSource, date.toDate(), false);
842
1042
  }
843
1043
 
844
- // Show total backups size
845
- $('#lgv-logSizeLb').html(`Total size: <strong>${Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_4__["bytesToSize"])(totalSize, 2, 'KB')}</strong>`);
1044
+ // Assign datasource to chart
1045
+ this._chartWidget.setDataSource(dataSource);
846
1046
 
847
- // Assign data source to grid
848
- this._setDownloadGridDataSource(backupsList);
849
- this._onDownloadGridSelectionChange();
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
- // Hide links to latest files if not available
852
- if (!lastBootLogBackupFound)
853
- this._fillBackupCard('#lgv-bootLogBackupCard', null);
1059
+ addEntry(totalOut, totalIn, dataSource = null, date = null, updateAxis = true)
1060
+ {
1061
+ if (date == null)
1062
+ date = new Date();
854
1063
 
855
- if (!lastRuntimeLogBackupFound)
856
- this._fillBackupCard('#lgv-runtimeLogBackupCard', null);
1064
+ const elapsedSecs = Math.round((date.getTime() - this._lastDate.getTime()) / 1000);
857
1065
 
858
- if (!lastFullBackupFound)
859
- this._fillBackupCard('#lgv-fullLogBackupCard', null);
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
- if (data.containsKey('message'))
862
- {
863
- // Display notification
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
- // Set download view to main
869
- this._switchDownloadViewStack('lgv-downloadView');
870
- }
1079
+ dataSource.add(newEntry);
871
1080
 
872
- // Logs backup deletion failed
873
- else if (command == this.RESP_DELETE_BACKUP_FAILED)
874
- {
875
- const error = data.getUtfString('error');
1081
+ this._lastTotalOut = totalOut;
1082
+ this._lastTotalIn = totalIn;
1083
+ this._lastDate = date;
876
1084
 
877
- // Show an alert
878
- this.shellCtrl.showSimpleAlert(error, true);
1085
+ if (updateAxis)
1086
+ this._updateXAxisLimits();
879
1087
  }
1088
+ }
880
1089
 
881
- // A blocking error occurred during backup operation
882
- else if (command == this.RESP_BACKUP_ERROR)
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
- // An non-blocking error occurred during backup operation
891
- else if (command == this.RESP_BACKUP_WARNING)
1094
+ if (ds.total() > 0)
892
1095
  {
893
- let warn = data.getUtfString('warn');
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
- // Display notification
896
- this.shellCtrl.showNotification(`Log backup warning`, warn);
1102
+ this._chartWidget.redraw();
897
1103
  }
898
1104
  }
899
1105
 
900
- //---------------------------------
901
- // UI EVENT LISTENERS
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
- _onTabShown(e)
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
- if (!this._initFailed)
907
- {
908
- // If boot log view was displayed...
909
- if (e.target.id == 'lgv-bootLog-tab')
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
- // Load boot log the first time the tab is selected
912
- if (!this._bootLogRequested)
913
- {
914
- this.sendExtensionRequest(this.REQ_GET_BOOT_LOG);
915
- this._bootLogRequested = true;
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
- // If backup&dowload view was displayed...
920
- else if (e.target.id == 'lgv-logsDownload-tab')
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
- // Request logs backup status the first time the tab is selected
923
- if (!this._backupStatusRequested)
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
- _onRuntimeLogLoadBtClick()
1322
+ _initialize()
933
1323
  {
934
- // Request log
935
- this._loadRuntimeLog();
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
- _onExportBootLogBtClick()
1368
+ _initChartWidget(chartHtml, height)
939
1369
  {
940
- // Export log to file
941
- this._exportLog($('#lgv-bootLogText').text(), this.BOOT_LOG_BACKUP_ID);
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
- _onSwitchBootLogColorBtClick()
1430
+ _initGaugeWidget(gaugeHtml, height)
945
1431
  {
946
- if ($('#lgv-bootLogText').hasClass('invert'))
947
- $('#lgv-bootLogText').removeClass('invert');
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
- $('#lgv-bootLogText').addClass('invert');
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
- _onBootLogGenerateBtClick()
1527
+ _updateElapsedText()
953
1528
  {
954
- // Show/hide operation in progress message
955
- this._disableBackupInterface(true, this.BOOT_LOG_BACKUP_ID);
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
- // Request backup generation
958
- this.sendExtensionRequest(this.REQ_BACKUP_BOOT_LOG);
1549
+ this._elapsedTxt.text(title);
1550
+ }
959
1551
  }
960
1552
 
961
- _onRuntimeLogGenerateBtClick()
1553
+ get load()
962
1554
  {
963
- // Show/hide operation in progress message
964
- this._disableBackupInterface(true, this.RUNTIME_LOG_BACKUP_ID);
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
- // Request backup generation
967
- this.sendExtensionRequest(this.REQ_BACKUP_RUNTIME_LOG);
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
- _onFullLogsGenerateBtClick()
1590
+ _initialize()
971
1591
  {
972
- // Show/hide operation in progress message
973
- this._disableBackupInterface(true, this.FULL_BACKUP_ID);
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
- // Request backup generation
976
- this.sendExtensionRequest(this.REQ_BACKUP_FULL_LOGS);
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
- _onFilterChange()
1636
+ _initChartWidget(chartHtml, height)
980
1637
  {
981
- // Set filters
982
- this._setRuntimeLogDataSource(this._runtimeLogGrid.dataSource);
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
- _onClearFilterClick()
1696
+ _initGaugeWidget(gaugeHtml, height)
986
1697
  {
987
- this._clearRuntimeLogFilters();
988
- this._setRuntimeLogDataSource(this._runtimeLogGrid.dataSource);
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
- _onExportRuntimeLogBtClick()
1749
+ addEntry(load)
992
1750
  {
993
- let log = '';
994
- const entries = this._runtimeLogGrid.dataSource.view();
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
- for (let i = 0; i < entries.length; i++)
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
- const item = entries[i];
999
- log += [item.date, item.time, item.level, item.thread, item.clazz, item.message].join(item.sep) + '\n';
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
- // Export log to file
1003
- this._exportLog(log, this.RUNTIME_LOG_BACKUP_ID);
1783
+ // Set gauge value
1784
+ this._gaugeWidget.value(averageLoad);
1785
+
1786
+ // Set load text
1787
+ this._loadTxt.text(averageLoad + '%')
1004
1788
  }
1005
1789
 
1006
- _onDownloadGridSelectionChange()
1790
+ _updateElapsedText()
1007
1791
  {
1008
- // Enable/disable buttons
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 (selectedRows.length > 0)
1794
+ if (ds.total() > 1)
1014
1795
  {
1015
- let dataItem = this._downloadGrid.dataItem(selectedRows[0]);
1016
- $('#lgv-downloadBt').attr('href', dataItem.url);
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
- _onDeleteBtClick()
1816
+ get load()
1023
1817
  {
1024
- let selectedRows = this._downloadGrid.select();
1818
+ return this._averageLoad;
1819
+ }
1820
+ }
1025
1821
 
1026
- if (selectedRows.length > 0)
1027
- {
1028
- let dataItem = this._downloadGrid.dataItem(selectedRows[0]);
1822
+ // DEFINE COMPONENT
1823
+ if (!window.customElements.get('system-workload-chart'))
1824
+ window.customElements.define('system-workload-chart', SystemWorkloadChart);
1029
1825
 
1030
- // Request backup deletion
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
- this.sendExtensionRequest(this.REQ_DELETE_BACKUP, params);
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
- // PRIVATE METHODS
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
- _switchRuntimeViewStack(viewId)
1995
+ initialize(idData, shellController)
1043
1996
  {
1044
- document.getElementById('lgv-runtime-viewstack').selectedElement = document.getElementById(viewId);
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
- _switchBootViewStack(viewId)
2141
+ destroy()
1048
2142
  {
1049
- document.getElementById('lgv-boot-viewstack').selectedElement = document.getElementById(viewId);
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
- _switchDownloadViewStack(viewId)
2166
+ onExtensionCommand(command, data)
1053
2167
  {
1054
- document.getElementById('lgv-download-viewstack').selectedElement = document.getElementById(viewId);
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
- _enableRuntimeLogControls(enable)
2368
+ onUptimeUpdated(values)
1058
2369
  {
1059
- $('#lgv-loadBt').attr('disabled', !enable);
1060
- $('#lgv-exportRuntimeLogBt').attr('disabled', !enable);
1061
- $('#lgv-filterBt').attr('disabled', !enable);
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
- _loadRuntimeLog()
2381
+ //---------------------------------
2382
+ // UI EVENT LISTENERS
2383
+ //---------------------------------
2384
+
2385
+ _onUpdateIntervalChange()
1065
2386
  {
1066
- // Disable controls to load log, so that impatient users can't send multiple requests
1067
- // (it will be enabled again when a response is received)
1068
- this._enableRuntimeLogControls(false);
2387
+ // Request data to server
2388
+ this._requestData();
2389
+ }
1069
2390
 
1070
- // Clear filters
1071
- this._clearRuntimeLogFilters();
2391
+ _onPauseUpdateClick()
2392
+ {
2393
+ this._setChartUpdatePaused(true);
1072
2394
 
1073
- // Show loading bar
1074
- this._switchRuntimeViewStack('lgv-runtimeLogLoadingView');
2395
+ // Hide pause button and show play button
2396
+ $('#dsh-pauseBt').addClass('hidden');
2397
+ $('#dsh-playBt').removeClass('hidden');
2398
+ }
1075
2399
 
1076
- // Send request
1077
- // (the number of lines to be retrieved is sent)
1078
- let params = new SFS2X.SFSObject();
1079
- params.putInt('numEntries', Number(this._logLinesDD.value()));
2400
+ _onPlayUpdateClick()
2401
+ {
2402
+ this._setChartUpdatePaused(false);
1080
2403
 
1081
- this.sendExtensionRequest(this.REQ_GET_RUNTIME_LOG, params);
2404
+ // Hide play button and show pause button
2405
+ $('#dsh-pauseBt').removeClass('hidden');
2406
+ $('#dsh-playBt').addClass('hidden');
1082
2407
  }
1083
2408
 
1084
- _clearRuntimeLogFilters()
2409
+ _onResetChartsClick()
1085
2410
  {
1086
- this._levelFilterDD.select(0);
1087
- this._classFilterDD.select(0);
1088
- $('#lgv-messageIn').val('');
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
- _exportLog(log, name)
2426
+ _redrawNetworkCharts()
1092
2427
  {
1093
- let blob = new Blob([log], {type: "text/plain;charset=utf-8"});
1094
- let date = moment__WEBPACK_IMPORTED_MODULE_3__().format('YYYYMMDD_HHmmss');
2428
+ // Redraw charts
2429
+ this._networkRTChart.redraw();
2430
+ this._network24hChart.redraw();
1095
2431
 
1096
- file_saver__WEBPACK_IMPORTED_MODULE_2__["saveAs"](blob, `${name}_${date}.log`);
2432
+ // Redraw time range slider
2433
+ this._timeSlider.resize();
1097
2434
  }
1098
2435
 
1099
- _setRuntimeLogDataSource(ds)
2436
+ _redrawOutMsgCharts()
1100
2437
  {
1101
- // Read current horizontal scroll value
1102
- const scrollLeft = $('#lgv-runtimeLogGrid .k-grid-content', this._runtimeLogGrid.wrapper).scrollLeft();
2438
+ // Redraw charts
2439
+ this._outTcpMsgQueueChart.redraw();
2440
+ this._outUdpMsgQueueChart.redraw();
1103
2441
 
1104
- // Assign data source to grid
1105
- this._runtimeLogGrid.setDataSource(ds);
2442
+ this._updateOutMessagesQueueStatus();
2443
+ }
1106
2444
 
1107
- // Set filters
1108
- this._setFilters(ds);
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
- // Set horizontal scroll
1111
- $('#lgv-runtimeLogGrid .k-grid-content', this._runtimeLogGrid.wrapper).scrollLeft(scrollLeft);
2460
+ _onTimeRangeChange()
2461
+ {
2462
+ let values = this._timeSlider.value();
1112
2463
 
1113
- // Update counter
1114
- $('#lgv-runtimeLogEntriesLb').text(`Log entries: ${this._totalRuntimeLogEntries} (${ds.total()} displayed)`);
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
- _setFilters(ds)
2479
+ _onUseHttpsForWsManagerChange()
1118
2480
  {
1119
- let filters = [];
2481
+ const wsMan = this._wsManagerConfig;
1120
2482
 
1121
- // Level filtering
1122
- if (this._levelFilterDD.select() > 0)
1123
- filters.push({
1124
- field: 'level', operator: 'eq', value: this._levelFilterDD.value()
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
- // Class filtering
1128
- if (this._classFilterDD.select() > 0)
1129
- filters.push({
1130
- field: 'clazz', operator: 'eq', value: this._classFilterDD.value()
1131
- });
2488
+ $('#dsh-toWsManagerBt').attr('href', url);
2489
+ }
1132
2490
 
1133
- // Message filtering
1134
- if ($('#lgv-messageIn').val() != '')
1135
- filters.push({
1136
- field: 'message', operator: 'contains', value: $('#lgv-messageIn').val()
1137
- });
2491
+ _onDumpThreadsClick()
2492
+ {
2493
+ // Disable button
2494
+ $('#dsh-dumpThreadsBt').attr('disabled', true);
1138
2495
 
1139
- // Set filters
1140
- ds.filter(filters);
2496
+ // Send request to extension
2497
+ this.sendExtensionRequest(this.REQ_DUMP_THREADS);
1141
2498
  }
1142
2499
 
1143
- _disableBackupInterface(disable, backupId = null)
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
- if (disable)
2524
+ const wsMan = this._wsManagerConfig;
2525
+
2526
+ if (wsMan.hasAccess && (wsMan.httpEnabled || wsMan.httpsEnabled))
1146
2527
  {
1147
- // Show proper progress bar
1148
- if (backupId == this.BOOT_LOG_BACKUP_ID)
1149
- $('#lgv-bootLogBackupCard .progress-bar').show();
1150
- else if (backupId == this.RUNTIME_LOG_BACKUP_ID)
1151
- $('#lgv-runtimeLogBackupCard .progress-bar').show();
1152
- else if (backupId == this.FULL_BACKUP_ID)
1153
- $('#lgv-fullLogBackupCard .progress-bar').show();
1154
-
1155
- // Disable buttons
1156
- $('#lgv-bootLogBackupCard .backup-button').attr('disabled', true);
1157
- $('#lgv-runtimeLogBackupCard .backup-button').attr('disabled', true);
1158
- $('#lgv-fullLogBackupCard .backup-button').attr('disabled', true);
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
- // Hide all progress bar
1163
- $('.card-body .progress-bar').hide();
2543
+ // Show alert
2544
+ $('#dsh-wsManagerAlert').show();
1164
2545
 
1165
- // Enable buttons
1166
- $('#lgv-fullLogBackupCard .backup-button').attr('disabled', false);
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
- if (!this._bootLogBackupUnavailable)
1169
- $('#lgv-bootLogBackupCard .backup-button').attr('disabled', false);
2551
+ // Disable button
2552
+ $('#dsh-toWsManagerBt').attr('disabled', true);
1170
2553
 
1171
- if (!this._runtimeLogBackupUnavailable)
1172
- $('#lgv-runtimeLogBackupCard .backup-button').attr('disabled', false);
2554
+ // Disable checkbox
2555
+ $('#dsh-useHttpsCheck').attr('checked', wsMan.httpsEnabled);
2556
+ $('#dsh-useHttpsCheck').attr('disabled', true);
1173
2557
  }
1174
2558
  }
1175
2559
 
1176
- _initBackupCard(idSelector)
2560
+ /**
2561
+ * Build the polling request to be sent to the server.
2562
+ */
2563
+ _requestData(getHistory = false)
1177
2564
  {
1178
- $(idSelector + ' .backup-details').hide();
1179
- $(idSelector + ' .progress-bar').hide();
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
- _fillBackupCard(idSelector, detailsObj = null)
2585
+ _getMemObject(bytes)
1183
2586
  {
1184
- if (detailsObj == null)
1185
- $(idSelector + ' .backup-details').hide();
1186
- else
1187
- {
1188
- $(idSelector + ' .backup-details').show();
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
- $(idSelector + ' .backup-link').attr('href', detailsObj.url);
1191
- $(idSelector + ' .backup-date').text(detailsObj.date);
1192
- $(idSelector + ' .backup-time').text(detailsObj.time);
1193
- $(idSelector + ' .backup-size').text(detailsObj.size);
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
- _setDownloadGridDataSource(ds)
2640
+ _updateOutMessagesQueueStatus()
1198
2641
  {
1199
- // Read current horizontal scroll value
1200
- const scrollLeft = $('#lgv-downloadGrid .k-grid-content', this._downloadGrid.wrapper).scrollLeft();
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
- // Assign data source to grid
1203
- this._downloadGrid.setDataSource(ds);
2651
+ if ($('#dsh-udpPill').hasClass('active'))
2652
+ {
2653
+ threadsStr = this._getQueueThreadsLabel(this._udpOutThreads);
2654
+ loadStr = this._getQueueLoadLabel(this._udpOutLoad);
2655
+ }
1204
2656
 
1205
- // Set horizontal scroll
1206
- $('#lgv-downloadGrid .k-grid-content', this._downloadGrid.wrapper).scrollLeft(scrollLeft);
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