rubyfox-server 2.13.5.1 → 2.16.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (572) hide show
  1. checksums.yaml +4 -4
  2. data/lib/rubyfox/server/data/config/UploadsLock.txt +3 -0
  3. data/lib/rubyfox/server/data/config/admin/admintool.xml +2 -0
  4. data/lib/rubyfox/server/data/config/admin/descriptors/config_room.txt +97 -43
  5. data/lib/rubyfox/server/data/config/admin/descriptors/config_server.txt +307 -93
  6. data/lib/rubyfox/server/data/config/admin/descriptors/config_zone.txt +311 -95
  7. data/lib/rubyfox/server/data/config/admin/descriptors/runtime_game.txt +5 -5
  8. data/lib/rubyfox/server/data/config/admin/descriptors/runtime_mmo.txt +6 -6
  9. data/lib/rubyfox/server/data/config/admin/descriptors/runtime_room.txt +69 -44
  10. data/lib/rubyfox/server/data/config/admin/descriptors/runtime_user.txt +55 -43
  11. data/lib/rubyfox/server/data/config/admin/descriptors/runtime_zone.txt +81 -36
  12. data/lib/rubyfox/server/data/config/admin/gmc/gmc.py +55 -18
  13. data/lib/rubyfox/server/data/config/admin/icons/Analytics.png +0 -0
  14. data/lib/rubyfox/server/data/config/admin/icons/Analytics.svg +1 -0
  15. data/lib/rubyfox/server/data/config/admin/icons/BanManager.png +0 -0
  16. data/lib/rubyfox/server/data/config/admin/icons/BanManager.svg +1 -0
  17. data/lib/rubyfox/server/data/config/admin/icons/BlueBoxMonitor.png +0 -0
  18. data/lib/rubyfox/server/data/config/admin/icons/BlueBoxMonitor.svg +1 -0
  19. data/lib/rubyfox/server/data/config/admin/icons/Console.png +0 -0
  20. data/lib/rubyfox/server/data/config/admin/icons/Console.svg +9 -0
  21. data/lib/rubyfox/server/data/config/admin/icons/Dashboard.png +0 -0
  22. data/lib/rubyfox/server/data/config/admin/icons/Dashboard.svg +1 -0
  23. data/lib/rubyfox/server/data/config/admin/icons/ExtensionManager.png +0 -0
  24. data/lib/rubyfox/server/data/config/admin/icons/ExtensionManager.svg +1 -0
  25. data/lib/rubyfox/server/data/config/admin/icons/LicenseManager.png +0 -0
  26. data/lib/rubyfox/server/data/config/admin/icons/LicenseManager.svg +1 -0
  27. data/lib/rubyfox/server/data/config/admin/icons/LogViewer.png +0 -0
  28. data/lib/rubyfox/server/data/config/admin/icons/LogViewer.svg +1 -0
  29. data/lib/rubyfox/server/data/config/admin/icons/ServerConfigurator.png +0 -0
  30. data/lib/rubyfox/server/data/config/admin/icons/ServerConfigurator.svg +1 -0
  31. data/lib/rubyfox/server/data/config/admin/icons/ServletManager.png +0 -0
  32. data/lib/rubyfox/server/data/config/admin/icons/ServletManager.svg +1 -0
  33. data/lib/rubyfox/server/data/config/admin/icons/ZoneConfigurator.png +0 -0
  34. data/lib/rubyfox/server/data/config/admin/icons/ZoneConfigurator.svg +1 -0
  35. data/lib/rubyfox/server/data/config/admin/icons/ZoneMonitor.png +0 -0
  36. data/lib/rubyfox/server/data/config/admin/icons/ZoneMonitor.svg +1 -0
  37. data/lib/rubyfox/server/data/config/core.xml +2 -2
  38. data/lib/rubyfox/server/data/config/log4j.properties +7 -7
  39. data/lib/rubyfox/server/data/config/server.xml +9 -10
  40. data/lib/rubyfox/server/data/config/wordsFile.txt +0 -2
  41. data/lib/rubyfox/server/data/data/GeoLite2-Country.mmdb +0 -0
  42. data/lib/rubyfox/server/data/{config → data/buddylists/BasicExamples}/.keep +0 -0
  43. data/lib/rubyfox/server/data/data/{buddylists → uploads}/.keep +0 -0
  44. data/lib/rubyfox/server/data/lib/BlueBox.war +0 -0
  45. data/lib/rubyfox/server/data/lib/apache-tomcat/LICENSE +1061 -0
  46. data/lib/rubyfox/server/data/lib/apache-tomcat/NOTICE +68 -0
  47. data/lib/rubyfox/server/data/lib/apache-tomcat/README.md +79 -0
  48. data/lib/rubyfox/server/data/lib/apache-tomcat/RELEASE-NOTES +174 -0
  49. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/bootstrap.jar +0 -0
  50. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/catalina-tasks.xml +39 -0
  51. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/catalina.bat +386 -0
  52. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/catalina.sh +689 -0
  53. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/ciphers.bat +58 -0
  54. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/ciphers.sh +60 -0
  55. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/commons-daemon-native.tar.gz +0 -0
  56. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/commons-daemon.jar +0 -0
  57. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/configtest.bat +58 -0
  58. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/configtest.sh +60 -0
  59. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/daemon.sh +293 -0
  60. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/digest.bat +58 -0
  61. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/digest.sh +60 -0
  62. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/makebase.bat +114 -0
  63. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/makebase.sh +115 -0
  64. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/setclasspath.bat +94 -0
  65. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/setclasspath.sh +98 -0
  66. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/shutdown.bat +58 -0
  67. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/shutdown.sh +60 -0
  68. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/startup.bat +58 -0
  69. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/startup.sh +60 -0
  70. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tomcat-juli.jar +0 -0
  71. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tomcat-native.tar.gz +0 -0
  72. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tool-wrapper.bat +110 -0
  73. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tool-wrapper.sh +153 -0
  74. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/version.bat +58 -0
  75. data/lib/rubyfox/server/data/lib/apache-tomcat/bin/version.sh +60 -0
  76. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/Catalina/localhost/rewrite.config +1 -0
  77. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/catalina.policy +260 -0
  78. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/catalina.properties +206 -0
  79. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/context.xml +31 -0
  80. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/jaspic-providers.xml +23 -0
  81. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/jaspic-providers.xsd +53 -0
  82. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/keystore.jks +0 -0
  83. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/logging.properties +79 -0
  84. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/server.xml +161 -0
  85. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/tomcat-users.xml +41 -0
  86. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/tomcat-users.xsd +59 -0
  87. data/lib/rubyfox/server/data/lib/apache-tomcat/conf/web.xml +4733 -0
  88. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/annotations-api.jar +0 -0
  89. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ant.jar +0 -0
  90. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ha.jar +0 -0
  91. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ssi.jar +0 -0
  92. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-storeconfig.jar +0 -0
  93. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-tribes.jar +0 -0
  94. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina.jar +0 -0
  95. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/ecj-4.15.jar +0 -0
  96. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/el-api.jar +0 -0
  97. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jasper-el.jar +0 -0
  98. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jasper.jar +0 -0
  99. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jaspic-api.jar +0 -0
  100. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jsp-api.jar +0 -0
  101. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/servlet-api.jar +0 -0
  102. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/sfs2x-ws-helper.jar +0 -0
  103. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-api.jar +0 -0
  104. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-coyote.jar +0 -0
  105. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-dbcp.jar +0 -0
  106. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-cs.jar +0 -0
  107. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-de.jar +0 -0
  108. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-es.jar +0 -0
  109. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-fr.jar +0 -0
  110. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ja.jar +0 -0
  111. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ko.jar +0 -0
  112. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-pt-BR.jar +0 -0
  113. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ru.jar +0 -0
  114. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-zh-CN.jar +0 -0
  115. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-jdbc.jar +0 -0
  116. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-jni.jar +0 -0
  117. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-util-scan.jar +0 -0
  118. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-util.jar +0 -0
  119. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-websocket.jar +0 -0
  120. data/lib/rubyfox/server/data/lib/apache-tomcat/lib/websocket-api.jar +0 -0
  121. data/lib/rubyfox/server/data/{extensions → lib/apache-tomcat/logs}/.keep +0 -0
  122. data/lib/rubyfox/server/data/lib/{jetty/lib/ext/.donotdelete → apache-tomcat/temp/safeToDelete.tmp} +0 -0
  123. data/lib/rubyfox/server/data/lib/{jetty/resources → apache-tomcat/work}/.keep +0 -0
  124. data/lib/rubyfox/server/data/lib/commons-collections-3.2.2.jar +0 -0
  125. data/lib/rubyfox/server/data/lib/commons-compress-1.19.jar +0 -0
  126. data/lib/rubyfox/server/data/lib/js/LibApi.js +48 -181
  127. data/lib/rubyfox/server/data/lib/sfs2x-admin.jar +0 -0
  128. data/lib/rubyfox/server/data/lib/sfs2x-core.jar +0 -0
  129. data/lib/rubyfox/server/data/lib/sfs2x-lib.jar +0 -0
  130. data/lib/rubyfox/server/data/lib/sfs2x-util.jar +0 -0
  131. data/lib/rubyfox/server/data/lib/sfs2x.jar +0 -0
  132. data/lib/rubyfox/server/data/sfs2x-service +6 -6
  133. data/lib/rubyfox/server/data/sfs2x-service.vmoptions +1 -1
  134. data/lib/rubyfox/server/data/sfs2x.sh +1 -1
  135. data/lib/rubyfox/server/data/www/BlueBox.war +0 -0
  136. data/lib/rubyfox/server/data/www/HelloServlet/index.jsp +1 -1
  137. data/lib/rubyfox/server/data/www/{root → ROOT}/_css_/default.css +0 -0
  138. data/lib/rubyfox/server/data/www/{root → ROOT}/_css_/reset.css +0 -0
  139. data/lib/rubyfox/server/data/www/{root → ROOT}/_images_/background_gradient.png +0 -0
  140. data/lib/rubyfox/server/data/www/{root → ROOT}/_images_/background_logo.png +0 -0
  141. data/lib/rubyfox/server/data/www/{root → ROOT}/_images_/favicon.png +0 -0
  142. data/lib/rubyfox/server/data/www/{root → ROOT}/_images_/logo_smartfoxserver.png +0 -0
  143. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/_changes-to-default-themes_.txt +15 -0
  144. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/bootstrap.min.css +7 -0
  145. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/custom-bootstrap.min.css +1 -0
  146. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/css/all.min.css +5 -0
  147. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-brands-400.eot +0 -0
  148. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-brands-400.svg +3459 -0
  149. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-brands-400.ttf +0 -0
  150. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-brands-400.woff +0 -0
  151. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
  152. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-regular-400.eot +0 -0
  153. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-regular-400.svg +803 -0
  154. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-regular-400.ttf +0 -0
  155. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-regular-400.woff +0 -0
  156. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
  157. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-solid-900.eot +0 -0
  158. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-solid-900.svg +4527 -0
  159. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-solid-900.ttf +0 -0
  160. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-solid-900.woff +0 -0
  161. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
  162. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fonts.css +175 -0
  163. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/jquery.scrolling-tabs.min.css +8 -0
  164. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/kendo.custom-bootstrap-v4.css +15280 -0
  165. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/reset.css +54 -0
  166. data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/style.css +1428 -0
  167. data/lib/rubyfox/server/data/www/ROOT/admin/assets/data/countries.geo.json +178 -0
  168. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/FreeMono.otf +0 -0
  169. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/FreeMono.ttf +0 -0
  170. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/FreeMono.woff +0 -0
  171. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/FreeMono.woff2 +0 -0
  172. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-300.ttf +0 -0
  173. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-300.woff +0 -0
  174. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-300.woff2 +0 -0
  175. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-300italic.ttf +0 -0
  176. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-300italic.woff +0 -0
  177. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-300italic.woff2 +0 -0
  178. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-600.ttf +0 -0
  179. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-600.woff +0 -0
  180. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-600.woff2 +0 -0
  181. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-600italic.ttf +0 -0
  182. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-600italic.woff +0 -0
  183. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-600italic.woff2 +0 -0
  184. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-700.ttf +0 -0
  185. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-700.woff +0 -0
  186. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-700.woff2 +0 -0
  187. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-700italic.ttf +0 -0
  188. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-700italic.woff +0 -0
  189. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-700italic.woff2 +0 -0
  190. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-800.ttf +0 -0
  191. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-800.woff +0 -0
  192. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-800.woff2 +0 -0
  193. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-800italic.ttf +0 -0
  194. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-800italic.woff +0 -0
  195. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-800italic.woff2 +0 -0
  196. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-italic.ttf +0 -0
  197. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-italic.woff +0 -0
  198. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-italic.woff2 +0 -0
  199. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-regular.ttf +0 -0
  200. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-regular.woff +0 -0
  201. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/open-sans-v15-cyrillic_greek_cyrillic-ext_vietnamese_latin_latin-ext_greek-ext-regular.woff2 +0 -0
  202. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/roboto-condensed-v16-latin-300.ttf +0 -0
  203. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/roboto-condensed-v16-latin-300.woff +0 -0
  204. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/roboto-condensed-v16-latin-300.woff2 +0 -0
  205. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/roboto-condensed-v16-latin-700.ttf +0 -0
  206. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/roboto-condensed-v16-latin-700.woff +0 -0
  207. data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/roboto-condensed-v16-latin-700.woff2 +0 -0
  208. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/compare.png +0 -0
  209. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/demographicsChart.png +0 -0
  210. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/demographicsCompare.png +0 -0
  211. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/demographicsFilter.png +0 -0
  212. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/demographicsMap.png +0 -0
  213. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/demographicsTable.png +0 -0
  214. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/technologyChart.png +0 -0
  215. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/technologyCompare.png +0 -0
  216. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/technologyFilter.png +0 -0
  217. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/technologyTable.png +0 -0
  218. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/apple-touch-icon-180x180.png +0 -0
  219. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/favicon-16x16.png +0 -0
  220. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/favicon-32x32.png +0 -0
  221. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/favicon-64x64.png +0 -0
  222. data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/logo.png +0 -0
  223. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/application.bundle.js +2208 -0
  224. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-0.bundle.js +7662 -0
  225. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-1.bundle.js +929 -0
  226. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-10.bundle.js +766 -0
  227. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-11.bundle.js +71 -0
  228. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12.bundle.js +1184 -0
  229. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12~module-13~module-9.bundle.js +2618 -0
  230. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-13.bundle.js +3315 -0
  231. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-3.bundle.js +280 -0
  232. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-4.bundle.js +1122 -0
  233. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-5.bundle.js +2624 -0
  234. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-6.bundle.js +801 -0
  235. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-7.bundle.js +607 -0
  236. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-8.bundle.js +1221 -0
  237. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-9.bundle.js +847 -0
  238. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-0.bundle.js +3240 -0
  239. 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 +17357 -0
  240. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-9.bundle.js +807 -0
  241. data/lib/rubyfox/server/data/{lib/jetty/webapps → www/ROOT/admin/assets/js/custom-modules}/.keep +0 -0
  242. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/bootstrap.min.js +7 -0
  243. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/jquery-3.3.1.min.js +2 -0
  244. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/jquery.scrolling-tabs.min.js +8 -0
  245. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/js.cookie.min.js +8 -0
  246. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/kendo.all.min.js +136 -0
  247. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/popper.min.js +5 -0
  248. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/sfs2x-api-1.7.15.js +8 -0
  249. data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/versions-readme.txt +16 -0
  250. data/lib/rubyfox/server/data/www/ROOT/admin/index.html +244 -0
  251. data/lib/rubyfox/server/data/www/ROOT/admin/manifest.json +25 -0
  252. data/lib/rubyfox/server/data/www/ROOT/admin/modules/analytics.html +328 -0
  253. data/lib/rubyfox/server/data/www/ROOT/admin/modules/ban-manager.html +160 -0
  254. data/lib/rubyfox/server/data/www/ROOT/admin/modules/blue-box-monitor.html +37 -0
  255. data/lib/rubyfox/server/data/www/ROOT/admin/modules/console.html +135 -0
  256. data/lib/rubyfox/server/data/www/ROOT/admin/modules/dashboard.html +368 -0
  257. data/lib/rubyfox/server/data/www/ROOT/admin/modules/extension-manager.html +98 -0
  258. data/lib/rubyfox/server/data/www/ROOT/admin/modules/license-manager.html +117 -0
  259. data/lib/rubyfox/server/data/www/ROOT/admin/modules/log-viewer.html +194 -0
  260. data/lib/rubyfox/server/data/www/ROOT/admin/modules/server-configurator.html +55 -0
  261. data/lib/rubyfox/server/data/www/ROOT/admin/modules/servlet-manager.html +98 -0
  262. data/lib/rubyfox/server/data/www/ROOT/admin/modules/zone-configurator.html +62 -0
  263. data/lib/rubyfox/server/data/www/ROOT/admin/modules/zone-monitor.html +346 -0
  264. data/lib/rubyfox/server/data/www/{root → ROOT}/crossdomain.xml +0 -0
  265. data/lib/rubyfox/server/data/www/{root → ROOT}/examples/index.html +0 -0
  266. data/lib/rubyfox/server/data/www/{root → ROOT}/favicon.ico +0 -0
  267. data/lib/rubyfox/server/data/www/{root → ROOT}/favicon.png +0 -0
  268. data/lib/rubyfox/server/data/www/{root → ROOT}/index.html +0 -0
  269. data/lib/rubyfox/server/data/www/host-manager/META-INF/context.xml +24 -0
  270. data/lib/rubyfox/server/data/www/host-manager/WEB-INF/jsp/401.jsp +71 -0
  271. data/lib/rubyfox/server/data/www/host-manager/WEB-INF/jsp/403.jsp +90 -0
  272. data/lib/rubyfox/server/data/www/host-manager/WEB-INF/jsp/404.jsp +62 -0
  273. data/lib/rubyfox/server/data/www/host-manager/WEB-INF/web.xml +131 -0
  274. data/lib/rubyfox/server/data/www/host-manager/images/asf-logo.svg +226 -0
  275. data/lib/rubyfox/server/data/www/host-manager/images/tomcat.gif +0 -0
  276. data/lib/rubyfox/server/data/www/host-manager/index.jsp +18 -0
  277. data/lib/rubyfox/server/data/www/host-manager/manager.xml +26 -0
  278. data/lib/rubyfox/server/data/{logs → www/logsBackup}/.keep +0 -0
  279. data/lib/rubyfox/server/data/www/manager/META-INF/context.xml +24 -0
  280. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/401.jsp +80 -0
  281. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/403.jsp +100 -0
  282. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/404.jsp +63 -0
  283. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorCerts.jsp +92 -0
  284. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorCiphers.jsp +92 -0
  285. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorTrustedCerts.jsp +92 -0
  286. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/sessionDetail.jsp +197 -0
  287. data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/sessionsList.jsp +170 -0
  288. data/lib/rubyfox/server/data/www/manager/WEB-INF/web.xml +195 -0
  289. data/lib/rubyfox/server/data/www/manager/images/asf-logo.svg +226 -0
  290. data/lib/rubyfox/server/data/www/manager/images/tomcat.gif +0 -0
  291. data/lib/rubyfox/server/data/www/manager/index.jsp +18 -0
  292. data/lib/rubyfox/server/data/www/manager/status.xsd +84 -0
  293. data/lib/rubyfox/server/data/www/manager/xform.xsl +125 -0
  294. data/lib/rubyfox/server/version.rb +1 -1
  295. metadata +258 -298
  296. data/lib/rubyfox/server/data/config/ExtensionManagerLock.txt +0 -2
  297. data/lib/rubyfox/server/data/lib/Lib/reindex$py.class +0 -0
  298. data/lib/rubyfox/server/data/lib/jetty/VERSION.txt +0 -9320
  299. data/lib/rubyfox/server/data/lib/jetty/etc/README.spnego +0 -62
  300. data/lib/rubyfox/server/data/lib/jetty/etc/jamon.xml +0 -32
  301. data/lib/rubyfox/server/data/lib/jetty/etc/jdbcRealm.properties +0 -72
  302. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-alpn.xml +0 -32
  303. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-annotations.xml +0 -20
  304. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-cdi.xml +0 -19
  305. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-debug.xml +0 -36
  306. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-debuglog.xml +0 -25
  307. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-deploy.xml +0 -76
  308. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-gcloud-memcached-sessions.xml +0 -27
  309. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-gcloud-session-idmgr.xml +0 -19
  310. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-gcloud-sessions.xml +0 -27
  311. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-gzip.xml +0 -67
  312. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-http-forwarded.xml +0 -17
  313. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-http.xml +0 -47
  314. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-http2.xml +0 -26
  315. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-http2c.xml +0 -18
  316. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-https.xml +0 -29
  317. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-infinispan.xml +0 -39
  318. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-ipaccess.xml +0 -28
  319. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-jaas.xml +0 -16
  320. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-jdbc-sessions.xml +0 -34
  321. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-jmx-remote.xml +0 -40
  322. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-jmx.xml +0 -32
  323. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-logging.xml +0 -36
  324. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-lowresources.xml +0 -22
  325. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-monitor.xml +0 -30
  326. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-nosql.xml +0 -19
  327. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-plus.xml +0 -26
  328. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-proxy-protocol-ssl.xml +0 -10
  329. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-proxy-protocol.xml +0 -10
  330. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-proxy.xml +0 -35
  331. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-requestlog.xml +0 -30
  332. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-rewrite-customizer.xml +0 -17
  333. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-rewrite.xml +0 -31
  334. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-setuid.xml +0 -30
  335. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-spring.xml +0 -61
  336. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-ssl-context.xml +0 -29
  337. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-ssl.xml +0 -58
  338. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-started.xml +0 -15
  339. data/lib/rubyfox/server/data/lib/jetty/etc/jetty-stats.xml +0 -18
  340. data/lib/rubyfox/server/data/lib/jetty/etc/jetty.conf +0 -12
  341. data/lib/rubyfox/server/data/lib/jetty/etc/jetty.xml +0 -195
  342. data/lib/rubyfox/server/data/lib/jetty/etc/jminix.xml +0 -12
  343. data/lib/rubyfox/server/data/lib/jetty/etc/jolokia.xml +0 -16
  344. data/lib/rubyfox/server/data/lib/jetty/etc/keystore +0 -0
  345. data/lib/rubyfox/server/data/lib/jetty/etc/krb5.ini +0 -23
  346. data/lib/rubyfox/server/data/lib/jetty/etc/rewrite-compactpath.xml +0 -10
  347. data/lib/rubyfox/server/data/lib/jetty/etc/spnego.conf +0 -19
  348. data/lib/rubyfox/server/data/lib/jetty/etc/spnego.properties +0 -1
  349. data/lib/rubyfox/server/data/lib/jetty/etc/webdefault.xml +0 -539
  350. data/lib/rubyfox/server/data/lib/jetty/lib/asm-5.0.1.jar +0 -0
  351. data/lib/rubyfox/server/data/lib/jetty/lib/asm-commons-5.0.1.jar +0 -0
  352. data/lib/rubyfox/server/data/lib/jetty/lib/fcgi/fcgi-client-9.3.11.v20160721.jar +0 -0
  353. data/lib/rubyfox/server/data/lib/jetty/lib/fcgi/fcgi-server-9.3.11.v20160721.jar +0 -0
  354. data/lib/rubyfox/server/data/lib/jetty/lib/http2-common-9.3.11.v20160721.jar +0 -0
  355. data/lib/rubyfox/server/data/lib/jetty/lib/http2-hpack-9.3.11.v20160721.jar +0 -0
  356. data/lib/rubyfox/server/data/lib/jetty/lib/http2-server-9.3.11.v20160721.jar +0 -0
  357. data/lib/rubyfox/server/data/lib/jetty/lib/jaspi/javax.security.auth.message-1.0.0.v201108011116.jar +0 -0
  358. data/lib/rubyfox/server/data/lib/jetty/lib/javax-websocket-client-impl-9.3.11.v20160721.jar +0 -0
  359. data/lib/rubyfox/server/data/lib/jetty/lib/javax-websocket-server-impl-9.3.11.v20160721.jar +0 -0
  360. data/lib/rubyfox/server/data/lib/jetty/lib/javax.annotation-api-1.2.jar +0 -0
  361. data/lib/rubyfox/server/data/lib/jetty/lib/javax.websocket-api-1.0.jar +0 -0
  362. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-alpn-server-9.3.11.v20160721.jar +0 -0
  363. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-annotations-9.3.11.v20160721.jar +0 -0
  364. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-client-9.3.11.v20160721.jar +0 -0
  365. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-continuation-9.3.11.v20160721.jar +0 -0
  366. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-deploy-9.3.11.v20160721.jar +0 -0
  367. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-gcloud-memcached-session-manager-9.3.11.v20160721.jar +0 -0
  368. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-gcloud-session-manager-9.3.11.v20160721.jar +0 -0
  369. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-http-9.3.11.v20160721.jar +0 -0
  370. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-infinispan-9.3.11.v20160721.jar +0 -0
  371. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-io-9.3.11.v20160721.jar +0 -0
  372. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-jaas-9.3.11.v20160721.jar +0 -0
  373. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-jaspi-9.3.11.v20160721.jar +0 -0
  374. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-jmx-9.3.11.v20160721.jar +0 -0
  375. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-jndi-9.3.11.v20160721.jar +0 -0
  376. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-nosql-9.3.11.v20160721.jar +0 -0
  377. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-plus-9.3.11.v20160721.jar +0 -0
  378. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-proxy-9.3.11.v20160721.jar +0 -0
  379. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-quickstart-9.3.11.v20160721.jar +0 -0
  380. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-rewrite-9.3.11.v20160721.jar +0 -0
  381. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-schemas-3.1.jar +0 -0
  382. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-security-9.3.11.v20160721.jar +0 -0
  383. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-server-9.3.11.v20160721.jar +0 -0
  384. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-servlet-9.3.11.v20160721.jar +0 -0
  385. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-servlets-9.3.11.v20160721.jar +0 -0
  386. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-util-9.3.11.v20160721.jar +0 -0
  387. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-webapp-9.3.11.v20160721.jar +0 -0
  388. data/lib/rubyfox/server/data/lib/jetty/lib/jetty-xml-9.3.11.v20160721.jar +0 -0
  389. data/lib/rubyfox/server/data/lib/jetty/lib/jndi/javax.mail.glassfish-1.4.1.v201005082020.jar +0 -0
  390. data/lib/rubyfox/server/data/lib/jetty/lib/jndi/javax.transaction-api-1.2.jar +0 -0
  391. data/lib/rubyfox/server/data/lib/jetty/lib/monitor/jetty-monitor-9.3.11.v20160721.jar +0 -0
  392. data/lib/rubyfox/server/data/lib/jetty/lib/org.apache.taglibs.taglibs-standard-impl-1.2.5.jar +0 -0
  393. data/lib/rubyfox/server/data/lib/jetty/lib/org.apache.taglibs.taglibs-standard-spec-1.2.5.jar +0 -0
  394. data/lib/rubyfox/server/data/lib/jetty/lib/org.eclipse.jdt.core.compiler.ecj-4.4.2.jar +0 -0
  395. data/lib/rubyfox/server/data/lib/jetty/lib/org.eclipse.jetty.apache-jsp-9.3.11.v20160721.jar +0 -0
  396. data/lib/rubyfox/server/data/lib/jetty/lib/org.mortbay.jasper.apache-el-8.0.33.jar +0 -0
  397. data/lib/rubyfox/server/data/lib/jetty/lib/org.mortbay.jasper.apache-jsp-8.0.33.jar +0 -0
  398. data/lib/rubyfox/server/data/lib/jetty/lib/servlet-api-3.1.jar +0 -0
  399. data/lib/rubyfox/server/data/lib/jetty/lib/setuid/jetty-setuid-java-1.0.3.jar +0 -0
  400. data/lib/rubyfox/server/data/lib/jetty/lib/setuid/libsetuid-linux.so +0 -0
  401. data/lib/rubyfox/server/data/lib/jetty/lib/setuid/libsetuid-osx.so +0 -0
  402. data/lib/rubyfox/server/data/lib/jetty/lib/spring/jetty-spring-9.3.11.v20160721.jar +0 -0
  403. data/lib/rubyfox/server/data/lib/jetty/lib/start.jar +0 -0
  404. data/lib/rubyfox/server/data/lib/jetty/lib/websocket-api-9.3.11.v20160721.jar +0 -0
  405. data/lib/rubyfox/server/data/lib/jetty/lib/websocket-client-9.3.11.v20160721.jar +0 -0
  406. data/lib/rubyfox/server/data/lib/jetty/lib/websocket-common-9.3.11h.v20160721.jar +0 -0
  407. data/lib/rubyfox/server/data/lib/jetty/lib/websocket-server-9.3.11.v20160721.jar +0 -0
  408. data/lib/rubyfox/server/data/lib/jetty/lib/websocket-servlet-9.3.11.v20160721.jar +0 -0
  409. data/lib/rubyfox/server/data/lib/jetty/license-eplv10-aslv20.html +0 -576
  410. data/lib/rubyfox/server/data/lib/jetty/modules/.donotdelete +0 -0
  411. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0.mod +0 -8
  412. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_05.mod +0 -8
  413. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_101.mod +0 -8
  414. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_102.mod +0 -8
  415. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_11.mod +0 -8
  416. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_20.mod +0 -8
  417. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_25.mod +0 -8
  418. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_31.mod +0 -8
  419. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_40.mod +0 -8
  420. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_45.mod +0 -8
  421. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_51.mod +0 -8
  422. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_60.mod +0 -8
  423. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_65.mod +0 -8
  424. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_66.mod +0 -8
  425. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_71.mod +0 -8
  426. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_72.mod +0 -8
  427. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_73.mod +0 -8
  428. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_74.mod +0 -8
  429. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_77.mod +0 -8
  430. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_91.mod +0 -8
  431. data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_92.mod +0 -8
  432. data/lib/rubyfox/server/data/lib/jetty/modules/alpn.mod +0 -53
  433. data/lib/rubyfox/server/data/lib/jetty/modules/annotations.mod +0 -17
  434. data/lib/rubyfox/server/data/lib/jetty/modules/apache-jsp.mod +0 -10
  435. data/lib/rubyfox/server/data/lib/jetty/modules/apache-jstl.mod +0 -9
  436. data/lib/rubyfox/server/data/lib/jetty/modules/cdi.mod +0 -39
  437. data/lib/rubyfox/server/data/lib/jetty/modules/client.mod +0 -6
  438. data/lib/rubyfox/server/data/lib/jetty/modules/continuation.mod +0 -6
  439. data/lib/rubyfox/server/data/lib/jetty/modules/debug.mod +0 -29
  440. data/lib/rubyfox/server/data/lib/jetty/modules/debuglog.mod +0 -25
  441. data/lib/rubyfox/server/data/lib/jetty/modules/deploy.mod +0 -31
  442. data/lib/rubyfox/server/data/lib/jetty/modules/ext.mod +0 -11
  443. data/lib/rubyfox/server/data/lib/jetty/modules/fcgi.mod +0 -15
  444. data/lib/rubyfox/server/data/lib/jetty/modules/gcloud-memcached-sessions.mod +0 -26
  445. data/lib/rubyfox/server/data/lib/jetty/modules/gcloud-session-idmgr.mod +0 -63
  446. data/lib/rubyfox/server/data/lib/jetty/modules/gcloud-sessions.mod +0 -11
  447. data/lib/rubyfox/server/data/lib/jetty/modules/gzip.mod +0 -23
  448. data/lib/rubyfox/server/data/lib/jetty/modules/hawtio.mod +0 -28
  449. data/lib/rubyfox/server/data/lib/jetty/modules/home-base-warning.mod +0 -7
  450. data/lib/rubyfox/server/data/lib/jetty/modules/http-forwarded.mod +0 -20
  451. data/lib/rubyfox/server/data/lib/jetty/modules/http.mod +0 -39
  452. data/lib/rubyfox/server/data/lib/jetty/modules/http2.mod +0 -20
  453. data/lib/rubyfox/server/data/lib/jetty/modules/http2c.mod +0 -22
  454. data/lib/rubyfox/server/data/lib/jetty/modules/https.mod +0 -14
  455. data/lib/rubyfox/server/data/lib/jetty/modules/infinispan.mod +0 -33
  456. data/lib/rubyfox/server/data/lib/jetty/modules/ipaccess.mod +0 -9
  457. data/lib/rubyfox/server/data/lib/jetty/modules/jaas.mod +0 -17
  458. data/lib/rubyfox/server/data/lib/jetty/modules/jamon.mod +0 -31
  459. data/lib/rubyfox/server/data/lib/jetty/modules/jaspi.mod +0 -10
  460. data/lib/rubyfox/server/data/lib/jetty/modules/jdbc-sessions.mod +0 -27
  461. data/lib/rubyfox/server/data/lib/jetty/modules/jminix.mod +0 -41
  462. data/lib/rubyfox/server/data/lib/jetty/modules/jmx-remote.mod +0 -16
  463. data/lib/rubyfox/server/data/lib/jetty/modules/jmx.mod +0 -13
  464. data/lib/rubyfox/server/data/lib/jetty/modules/jndi.mod +0 -11
  465. data/lib/rubyfox/server/data/lib/jetty/modules/jolokia.mod +0 -19
  466. data/lib/rubyfox/server/data/lib/jetty/modules/jsp.mod +0 -9
  467. data/lib/rubyfox/server/data/lib/jetty/modules/jstl.mod +0 -8
  468. data/lib/rubyfox/server/data/lib/jetty/modules/jvm.mod +0 -22
  469. data/lib/rubyfox/server/data/lib/jetty/modules/logging.mod +0 -36
  470. data/lib/rubyfox/server/data/lib/jetty/modules/lowresources.mod +0 -28
  471. data/lib/rubyfox/server/data/lib/jetty/modules/monitor.mod +0 -13
  472. data/lib/rubyfox/server/data/lib/jetty/modules/nosql.mod +0 -31
  473. data/lib/rubyfox/server/data/lib/jetty/modules/plus.mod +0 -15
  474. data/lib/rubyfox/server/data/lib/jetty/modules/proxy-protocol-ssl.mod +0 -9
  475. data/lib/rubyfox/server/data/lib/jetty/modules/proxy-protocol.mod +0 -9
  476. data/lib/rubyfox/server/data/lib/jetty/modules/proxy.mod +0 -22
  477. data/lib/rubyfox/server/data/lib/jetty/modules/quickstart.mod +0 -11
  478. data/lib/rubyfox/server/data/lib/jetty/modules/requestlog.mod +0 -40
  479. data/lib/rubyfox/server/data/lib/jetty/modules/resources.mod +0 -10
  480. data/lib/rubyfox/server/data/lib/jetty/modules/rewrite-compactpath.mod +0 -10
  481. data/lib/rubyfox/server/data/lib/jetty/modules/rewrite-customizer.mod +0 -24
  482. data/lib/rubyfox/server/data/lib/jetty/modules/rewrite.mod +0 -23
  483. data/lib/rubyfox/server/data/lib/jetty/modules/security.mod +0 -9
  484. data/lib/rubyfox/server/data/lib/jetty/modules/server.mod +0 -79
  485. data/lib/rubyfox/server/data/lib/jetty/modules/servlet.mod +0 -9
  486. data/lib/rubyfox/server/data/lib/jetty/modules/servlets.mod +0 -11
  487. data/lib/rubyfox/server/data/lib/jetty/modules/setuid.mod +0 -19
  488. data/lib/rubyfox/server/data/lib/jetty/modules/spring.mod +0 -17
  489. data/lib/rubyfox/server/data/lib/jetty/modules/ssl.mod +0 -97
  490. data/lib/rubyfox/server/data/lib/jetty/modules/stats.mod +0 -9
  491. data/lib/rubyfox/server/data/lib/jetty/modules/webapp.mod +0 -10
  492. data/lib/rubyfox/server/data/lib/jetty/modules/websocket.mod +0 -12
  493. data/lib/rubyfox/server/data/lib/jetty/notice.html +0 -111
  494. data/lib/rubyfox/server/data/lib/jetty/start.d/README.TXT +0 -24
  495. data/lib/rubyfox/server/data/lib/jetty/start.d/http.ini +0 -7
  496. data/lib/rubyfox/server/data/lib/jetty/start.d/https.ini +0 -10
  497. data/lib/rubyfox/server/data/lib/jetty/start.d/ssl.ini +0 -19
  498. data/lib/rubyfox/server/data/lib/jetty/start.ini +0 -83
  499. data/lib/rubyfox/server/data/www/.keep +0 -0
  500. data/lib/rubyfox/server/data/www/HelloServlet/META-INF/context.xml +0 -2
  501. data/lib/rubyfox/server/data/www/PyServletExample/MyModule$py.class +0 -0
  502. data/lib/rubyfox/server/data/www/PyServletExample/MyModule.py +0 -5
  503. data/lib/rubyfox/server/data/www/PyServletExample/WEB-INF/web.xml +0 -37
  504. data/lib/rubyfox/server/data/www/PyServletExample/errors/404.htm +0 -20
  505. data/lib/rubyfox/server/data/www/PyServletExample/index.py +0 -42
  506. data/lib/rubyfox/server/data/www/root/admin/.keep +0 -0
  507. data/lib/rubyfox/server/data/www/root/admin/AdminTool.swf +0 -0
  508. data/lib/rubyfox/server/data/www/root/admin/ReleaseNotes.txt +0 -192
  509. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/adobeFlashPlayer.png +0 -0
  510. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/advanced.png +0 -0
  511. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/analytics.png +0 -0
  512. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/banManager.png +0 -0
  513. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/bannedIPs.png +0 -0
  514. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/bannedUsernames.png +0 -0
  515. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/bookmarks.png +0 -0
  516. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/bootLog.png +0 -0
  517. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/buddyList.png +0 -0
  518. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/buddyProperties.png +0 -0
  519. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/connection.png +0 -0
  520. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/databaseManager.png +0 -0
  521. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/floodFilter.png +0 -0
  522. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/gameSettings.png +0 -0
  523. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/general.png +0 -0
  524. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/globalServerStatus.png +0 -0
  525. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/hTML5WebSockets.png +0 -0
  526. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/iPDiscovery.png +0 -0
  527. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/iPFilter.png +0 -0
  528. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/jVMSettings.png +0 -0
  529. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/logsDownload.png +0 -0
  530. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/mMOSettings.png +0 -0
  531. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/mailer.png +0 -0
  532. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/permissionsAndEvents.png +0 -0
  533. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/privilegeManager.png +0 -0
  534. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/remoteAdmin.png +0 -0
  535. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/roomExtension.png +0 -0
  536. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/roomVariables.png +0 -0
  537. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/roomsAndGroups.png +0 -0
  538. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/runtimeLog.png +0 -0
  539. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/runtimeRoomSettings.png +0 -0
  540. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/runtimeUserSettings.png +0 -0
  541. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/runtimeZoneSettings.png +0 -0
  542. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/statsApplication.png +0 -0
  543. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/statsDemographics.png +0 -0
  544. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/statsExceptions.png +0 -0
  545. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/statsOverview.png +0 -0
  546. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/statsTechnology.png +0 -0
  547. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/systemQueueStatus.png +0 -0
  548. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/threadPools.png +0 -0
  549. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/userManagement.png +0 -0
  550. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/userVariables.png +0 -0
  551. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/webServer.png +0 -0
  552. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/wordsFilter.png +0 -0
  553. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/zoneExtension.png +0 -0
  554. data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/zoneTraffic.png +0 -0
  555. data/lib/rubyfox/server/data/www/root/admin/expressInstall.swf +0 -0
  556. data/lib/rubyfox/server/data/www/root/admin/index.html +0 -124
  557. data/lib/rubyfox/server/data/www/root/admin/modules/Analytics.swf +0 -0
  558. data/lib/rubyfox/server/data/www/root/admin/modules/BanManager.swf +0 -0
  559. data/lib/rubyfox/server/data/www/root/admin/modules/BlueBoxMonitor.swf +0 -0
  560. data/lib/rubyfox/server/data/www/root/admin/modules/Console.swf +0 -0
  561. data/lib/rubyfox/server/data/www/root/admin/modules/Dashboard.swf +0 -0
  562. data/lib/rubyfox/server/data/www/root/admin/modules/ExtensionManager.swf +0 -0
  563. data/lib/rubyfox/server/data/www/root/admin/modules/LicenseManager.swf +0 -0
  564. data/lib/rubyfox/server/data/www/root/admin/modules/LogViewer.swf +0 -0
  565. data/lib/rubyfox/server/data/www/root/admin/modules/ServerConfigurator.swf +0 -0
  566. data/lib/rubyfox/server/data/www/root/admin/modules/ZoneConfigurator.swf +0 -0
  567. data/lib/rubyfox/server/data/www/root/admin/modules/ZoneMonitor.swf +0 -0
  568. data/lib/rubyfox/server/data/www/root/admin/swfobject.js +0 -4
  569. data/lib/rubyfox/server/data/www/root/examples/.keep +0 -0
  570. data/lib/rubyfox/server/data/www/sfs2x-ws.war +0 -0
  571. data/lib/rubyfox/server/data/www/sfs2x-ws.xml +0 -30
  572. data/lib/rubyfox/server/data/zones/BasicExamples.zone.xml +0 -147
@@ -0,0 +1,3315 @@
1
+ /*! (c) gotoAndPlay | All rights reserved */
2
+ (window["webpackJsonpapplication"] = window["webpackJsonpapplication"] || []).push([["module-13"],{
3
+
4
+ /***/ "./node_modules/moment/locale sync recursive ^\\.\\/.*$":
5
+ /*!**************************************************!*\
6
+ !*** ./node_modules/moment/locale sync ^\.\/.*$ ***!
7
+ \**************************************************/
8
+ /*! no static exports found */
9
+ /***/ (function(module, exports, __webpack_require__) {
10
+
11
+ var map = {
12
+ "./af": "./node_modules/moment/locale/af.js",
13
+ "./af.js": "./node_modules/moment/locale/af.js",
14
+ "./ar": "./node_modules/moment/locale/ar.js",
15
+ "./ar-dz": "./node_modules/moment/locale/ar-dz.js",
16
+ "./ar-dz.js": "./node_modules/moment/locale/ar-dz.js",
17
+ "./ar-kw": "./node_modules/moment/locale/ar-kw.js",
18
+ "./ar-kw.js": "./node_modules/moment/locale/ar-kw.js",
19
+ "./ar-ly": "./node_modules/moment/locale/ar-ly.js",
20
+ "./ar-ly.js": "./node_modules/moment/locale/ar-ly.js",
21
+ "./ar-ma": "./node_modules/moment/locale/ar-ma.js",
22
+ "./ar-ma.js": "./node_modules/moment/locale/ar-ma.js",
23
+ "./ar-sa": "./node_modules/moment/locale/ar-sa.js",
24
+ "./ar-sa.js": "./node_modules/moment/locale/ar-sa.js",
25
+ "./ar-tn": "./node_modules/moment/locale/ar-tn.js",
26
+ "./ar-tn.js": "./node_modules/moment/locale/ar-tn.js",
27
+ "./ar.js": "./node_modules/moment/locale/ar.js",
28
+ "./az": "./node_modules/moment/locale/az.js",
29
+ "./az.js": "./node_modules/moment/locale/az.js",
30
+ "./be": "./node_modules/moment/locale/be.js",
31
+ "./be.js": "./node_modules/moment/locale/be.js",
32
+ "./bg": "./node_modules/moment/locale/bg.js",
33
+ "./bg.js": "./node_modules/moment/locale/bg.js",
34
+ "./bm": "./node_modules/moment/locale/bm.js",
35
+ "./bm.js": "./node_modules/moment/locale/bm.js",
36
+ "./bn": "./node_modules/moment/locale/bn.js",
37
+ "./bn.js": "./node_modules/moment/locale/bn.js",
38
+ "./bo": "./node_modules/moment/locale/bo.js",
39
+ "./bo.js": "./node_modules/moment/locale/bo.js",
40
+ "./br": "./node_modules/moment/locale/br.js",
41
+ "./br.js": "./node_modules/moment/locale/br.js",
42
+ "./bs": "./node_modules/moment/locale/bs.js",
43
+ "./bs.js": "./node_modules/moment/locale/bs.js",
44
+ "./ca": "./node_modules/moment/locale/ca.js",
45
+ "./ca.js": "./node_modules/moment/locale/ca.js",
46
+ "./cs": "./node_modules/moment/locale/cs.js",
47
+ "./cs.js": "./node_modules/moment/locale/cs.js",
48
+ "./cv": "./node_modules/moment/locale/cv.js",
49
+ "./cv.js": "./node_modules/moment/locale/cv.js",
50
+ "./cy": "./node_modules/moment/locale/cy.js",
51
+ "./cy.js": "./node_modules/moment/locale/cy.js",
52
+ "./da": "./node_modules/moment/locale/da.js",
53
+ "./da.js": "./node_modules/moment/locale/da.js",
54
+ "./de": "./node_modules/moment/locale/de.js",
55
+ "./de-at": "./node_modules/moment/locale/de-at.js",
56
+ "./de-at.js": "./node_modules/moment/locale/de-at.js",
57
+ "./de-ch": "./node_modules/moment/locale/de-ch.js",
58
+ "./de-ch.js": "./node_modules/moment/locale/de-ch.js",
59
+ "./de.js": "./node_modules/moment/locale/de.js",
60
+ "./dv": "./node_modules/moment/locale/dv.js",
61
+ "./dv.js": "./node_modules/moment/locale/dv.js",
62
+ "./el": "./node_modules/moment/locale/el.js",
63
+ "./el.js": "./node_modules/moment/locale/el.js",
64
+ "./en-SG": "./node_modules/moment/locale/en-SG.js",
65
+ "./en-SG.js": "./node_modules/moment/locale/en-SG.js",
66
+ "./en-au": "./node_modules/moment/locale/en-au.js",
67
+ "./en-au.js": "./node_modules/moment/locale/en-au.js",
68
+ "./en-ca": "./node_modules/moment/locale/en-ca.js",
69
+ "./en-ca.js": "./node_modules/moment/locale/en-ca.js",
70
+ "./en-gb": "./node_modules/moment/locale/en-gb.js",
71
+ "./en-gb.js": "./node_modules/moment/locale/en-gb.js",
72
+ "./en-ie": "./node_modules/moment/locale/en-ie.js",
73
+ "./en-ie.js": "./node_modules/moment/locale/en-ie.js",
74
+ "./en-il": "./node_modules/moment/locale/en-il.js",
75
+ "./en-il.js": "./node_modules/moment/locale/en-il.js",
76
+ "./en-nz": "./node_modules/moment/locale/en-nz.js",
77
+ "./en-nz.js": "./node_modules/moment/locale/en-nz.js",
78
+ "./eo": "./node_modules/moment/locale/eo.js",
79
+ "./eo.js": "./node_modules/moment/locale/eo.js",
80
+ "./es": "./node_modules/moment/locale/es.js",
81
+ "./es-do": "./node_modules/moment/locale/es-do.js",
82
+ "./es-do.js": "./node_modules/moment/locale/es-do.js",
83
+ "./es-us": "./node_modules/moment/locale/es-us.js",
84
+ "./es-us.js": "./node_modules/moment/locale/es-us.js",
85
+ "./es.js": "./node_modules/moment/locale/es.js",
86
+ "./et": "./node_modules/moment/locale/et.js",
87
+ "./et.js": "./node_modules/moment/locale/et.js",
88
+ "./eu": "./node_modules/moment/locale/eu.js",
89
+ "./eu.js": "./node_modules/moment/locale/eu.js",
90
+ "./fa": "./node_modules/moment/locale/fa.js",
91
+ "./fa.js": "./node_modules/moment/locale/fa.js",
92
+ "./fi": "./node_modules/moment/locale/fi.js",
93
+ "./fi.js": "./node_modules/moment/locale/fi.js",
94
+ "./fo": "./node_modules/moment/locale/fo.js",
95
+ "./fo.js": "./node_modules/moment/locale/fo.js",
96
+ "./fr": "./node_modules/moment/locale/fr.js",
97
+ "./fr-ca": "./node_modules/moment/locale/fr-ca.js",
98
+ "./fr-ca.js": "./node_modules/moment/locale/fr-ca.js",
99
+ "./fr-ch": "./node_modules/moment/locale/fr-ch.js",
100
+ "./fr-ch.js": "./node_modules/moment/locale/fr-ch.js",
101
+ "./fr.js": "./node_modules/moment/locale/fr.js",
102
+ "./fy": "./node_modules/moment/locale/fy.js",
103
+ "./fy.js": "./node_modules/moment/locale/fy.js",
104
+ "./ga": "./node_modules/moment/locale/ga.js",
105
+ "./ga.js": "./node_modules/moment/locale/ga.js",
106
+ "./gd": "./node_modules/moment/locale/gd.js",
107
+ "./gd.js": "./node_modules/moment/locale/gd.js",
108
+ "./gl": "./node_modules/moment/locale/gl.js",
109
+ "./gl.js": "./node_modules/moment/locale/gl.js",
110
+ "./gom-latn": "./node_modules/moment/locale/gom-latn.js",
111
+ "./gom-latn.js": "./node_modules/moment/locale/gom-latn.js",
112
+ "./gu": "./node_modules/moment/locale/gu.js",
113
+ "./gu.js": "./node_modules/moment/locale/gu.js",
114
+ "./he": "./node_modules/moment/locale/he.js",
115
+ "./he.js": "./node_modules/moment/locale/he.js",
116
+ "./hi": "./node_modules/moment/locale/hi.js",
117
+ "./hi.js": "./node_modules/moment/locale/hi.js",
118
+ "./hr": "./node_modules/moment/locale/hr.js",
119
+ "./hr.js": "./node_modules/moment/locale/hr.js",
120
+ "./hu": "./node_modules/moment/locale/hu.js",
121
+ "./hu.js": "./node_modules/moment/locale/hu.js",
122
+ "./hy-am": "./node_modules/moment/locale/hy-am.js",
123
+ "./hy-am.js": "./node_modules/moment/locale/hy-am.js",
124
+ "./id": "./node_modules/moment/locale/id.js",
125
+ "./id.js": "./node_modules/moment/locale/id.js",
126
+ "./is": "./node_modules/moment/locale/is.js",
127
+ "./is.js": "./node_modules/moment/locale/is.js",
128
+ "./it": "./node_modules/moment/locale/it.js",
129
+ "./it-ch": "./node_modules/moment/locale/it-ch.js",
130
+ "./it-ch.js": "./node_modules/moment/locale/it-ch.js",
131
+ "./it.js": "./node_modules/moment/locale/it.js",
132
+ "./ja": "./node_modules/moment/locale/ja.js",
133
+ "./ja.js": "./node_modules/moment/locale/ja.js",
134
+ "./jv": "./node_modules/moment/locale/jv.js",
135
+ "./jv.js": "./node_modules/moment/locale/jv.js",
136
+ "./ka": "./node_modules/moment/locale/ka.js",
137
+ "./ka.js": "./node_modules/moment/locale/ka.js",
138
+ "./kk": "./node_modules/moment/locale/kk.js",
139
+ "./kk.js": "./node_modules/moment/locale/kk.js",
140
+ "./km": "./node_modules/moment/locale/km.js",
141
+ "./km.js": "./node_modules/moment/locale/km.js",
142
+ "./kn": "./node_modules/moment/locale/kn.js",
143
+ "./kn.js": "./node_modules/moment/locale/kn.js",
144
+ "./ko": "./node_modules/moment/locale/ko.js",
145
+ "./ko.js": "./node_modules/moment/locale/ko.js",
146
+ "./ku": "./node_modules/moment/locale/ku.js",
147
+ "./ku.js": "./node_modules/moment/locale/ku.js",
148
+ "./ky": "./node_modules/moment/locale/ky.js",
149
+ "./ky.js": "./node_modules/moment/locale/ky.js",
150
+ "./lb": "./node_modules/moment/locale/lb.js",
151
+ "./lb.js": "./node_modules/moment/locale/lb.js",
152
+ "./lo": "./node_modules/moment/locale/lo.js",
153
+ "./lo.js": "./node_modules/moment/locale/lo.js",
154
+ "./lt": "./node_modules/moment/locale/lt.js",
155
+ "./lt.js": "./node_modules/moment/locale/lt.js",
156
+ "./lv": "./node_modules/moment/locale/lv.js",
157
+ "./lv.js": "./node_modules/moment/locale/lv.js",
158
+ "./me": "./node_modules/moment/locale/me.js",
159
+ "./me.js": "./node_modules/moment/locale/me.js",
160
+ "./mi": "./node_modules/moment/locale/mi.js",
161
+ "./mi.js": "./node_modules/moment/locale/mi.js",
162
+ "./mk": "./node_modules/moment/locale/mk.js",
163
+ "./mk.js": "./node_modules/moment/locale/mk.js",
164
+ "./ml": "./node_modules/moment/locale/ml.js",
165
+ "./ml.js": "./node_modules/moment/locale/ml.js",
166
+ "./mn": "./node_modules/moment/locale/mn.js",
167
+ "./mn.js": "./node_modules/moment/locale/mn.js",
168
+ "./mr": "./node_modules/moment/locale/mr.js",
169
+ "./mr.js": "./node_modules/moment/locale/mr.js",
170
+ "./ms": "./node_modules/moment/locale/ms.js",
171
+ "./ms-my": "./node_modules/moment/locale/ms-my.js",
172
+ "./ms-my.js": "./node_modules/moment/locale/ms-my.js",
173
+ "./ms.js": "./node_modules/moment/locale/ms.js",
174
+ "./mt": "./node_modules/moment/locale/mt.js",
175
+ "./mt.js": "./node_modules/moment/locale/mt.js",
176
+ "./my": "./node_modules/moment/locale/my.js",
177
+ "./my.js": "./node_modules/moment/locale/my.js",
178
+ "./nb": "./node_modules/moment/locale/nb.js",
179
+ "./nb.js": "./node_modules/moment/locale/nb.js",
180
+ "./ne": "./node_modules/moment/locale/ne.js",
181
+ "./ne.js": "./node_modules/moment/locale/ne.js",
182
+ "./nl": "./node_modules/moment/locale/nl.js",
183
+ "./nl-be": "./node_modules/moment/locale/nl-be.js",
184
+ "./nl-be.js": "./node_modules/moment/locale/nl-be.js",
185
+ "./nl.js": "./node_modules/moment/locale/nl.js",
186
+ "./nn": "./node_modules/moment/locale/nn.js",
187
+ "./nn.js": "./node_modules/moment/locale/nn.js",
188
+ "./pa-in": "./node_modules/moment/locale/pa-in.js",
189
+ "./pa-in.js": "./node_modules/moment/locale/pa-in.js",
190
+ "./pl": "./node_modules/moment/locale/pl.js",
191
+ "./pl.js": "./node_modules/moment/locale/pl.js",
192
+ "./pt": "./node_modules/moment/locale/pt.js",
193
+ "./pt-br": "./node_modules/moment/locale/pt-br.js",
194
+ "./pt-br.js": "./node_modules/moment/locale/pt-br.js",
195
+ "./pt.js": "./node_modules/moment/locale/pt.js",
196
+ "./ro": "./node_modules/moment/locale/ro.js",
197
+ "./ro.js": "./node_modules/moment/locale/ro.js",
198
+ "./ru": "./node_modules/moment/locale/ru.js",
199
+ "./ru.js": "./node_modules/moment/locale/ru.js",
200
+ "./sd": "./node_modules/moment/locale/sd.js",
201
+ "./sd.js": "./node_modules/moment/locale/sd.js",
202
+ "./se": "./node_modules/moment/locale/se.js",
203
+ "./se.js": "./node_modules/moment/locale/se.js",
204
+ "./si": "./node_modules/moment/locale/si.js",
205
+ "./si.js": "./node_modules/moment/locale/si.js",
206
+ "./sk": "./node_modules/moment/locale/sk.js",
207
+ "./sk.js": "./node_modules/moment/locale/sk.js",
208
+ "./sl": "./node_modules/moment/locale/sl.js",
209
+ "./sl.js": "./node_modules/moment/locale/sl.js",
210
+ "./sq": "./node_modules/moment/locale/sq.js",
211
+ "./sq.js": "./node_modules/moment/locale/sq.js",
212
+ "./sr": "./node_modules/moment/locale/sr.js",
213
+ "./sr-cyrl": "./node_modules/moment/locale/sr-cyrl.js",
214
+ "./sr-cyrl.js": "./node_modules/moment/locale/sr-cyrl.js",
215
+ "./sr.js": "./node_modules/moment/locale/sr.js",
216
+ "./ss": "./node_modules/moment/locale/ss.js",
217
+ "./ss.js": "./node_modules/moment/locale/ss.js",
218
+ "./sv": "./node_modules/moment/locale/sv.js",
219
+ "./sv.js": "./node_modules/moment/locale/sv.js",
220
+ "./sw": "./node_modules/moment/locale/sw.js",
221
+ "./sw.js": "./node_modules/moment/locale/sw.js",
222
+ "./ta": "./node_modules/moment/locale/ta.js",
223
+ "./ta.js": "./node_modules/moment/locale/ta.js",
224
+ "./te": "./node_modules/moment/locale/te.js",
225
+ "./te.js": "./node_modules/moment/locale/te.js",
226
+ "./tet": "./node_modules/moment/locale/tet.js",
227
+ "./tet.js": "./node_modules/moment/locale/tet.js",
228
+ "./tg": "./node_modules/moment/locale/tg.js",
229
+ "./tg.js": "./node_modules/moment/locale/tg.js",
230
+ "./th": "./node_modules/moment/locale/th.js",
231
+ "./th.js": "./node_modules/moment/locale/th.js",
232
+ "./tl-ph": "./node_modules/moment/locale/tl-ph.js",
233
+ "./tl-ph.js": "./node_modules/moment/locale/tl-ph.js",
234
+ "./tlh": "./node_modules/moment/locale/tlh.js",
235
+ "./tlh.js": "./node_modules/moment/locale/tlh.js",
236
+ "./tr": "./node_modules/moment/locale/tr.js",
237
+ "./tr.js": "./node_modules/moment/locale/tr.js",
238
+ "./tzl": "./node_modules/moment/locale/tzl.js",
239
+ "./tzl.js": "./node_modules/moment/locale/tzl.js",
240
+ "./tzm": "./node_modules/moment/locale/tzm.js",
241
+ "./tzm-latn": "./node_modules/moment/locale/tzm-latn.js",
242
+ "./tzm-latn.js": "./node_modules/moment/locale/tzm-latn.js",
243
+ "./tzm.js": "./node_modules/moment/locale/tzm.js",
244
+ "./ug-cn": "./node_modules/moment/locale/ug-cn.js",
245
+ "./ug-cn.js": "./node_modules/moment/locale/ug-cn.js",
246
+ "./uk": "./node_modules/moment/locale/uk.js",
247
+ "./uk.js": "./node_modules/moment/locale/uk.js",
248
+ "./ur": "./node_modules/moment/locale/ur.js",
249
+ "./ur.js": "./node_modules/moment/locale/ur.js",
250
+ "./uz": "./node_modules/moment/locale/uz.js",
251
+ "./uz-latn": "./node_modules/moment/locale/uz-latn.js",
252
+ "./uz-latn.js": "./node_modules/moment/locale/uz-latn.js",
253
+ "./uz.js": "./node_modules/moment/locale/uz.js",
254
+ "./vi": "./node_modules/moment/locale/vi.js",
255
+ "./vi.js": "./node_modules/moment/locale/vi.js",
256
+ "./x-pseudo": "./node_modules/moment/locale/x-pseudo.js",
257
+ "./x-pseudo.js": "./node_modules/moment/locale/x-pseudo.js",
258
+ "./yo": "./node_modules/moment/locale/yo.js",
259
+ "./yo.js": "./node_modules/moment/locale/yo.js",
260
+ "./zh-cn": "./node_modules/moment/locale/zh-cn.js",
261
+ "./zh-cn.js": "./node_modules/moment/locale/zh-cn.js",
262
+ "./zh-hk": "./node_modules/moment/locale/zh-hk.js",
263
+ "./zh-hk.js": "./node_modules/moment/locale/zh-hk.js",
264
+ "./zh-tw": "./node_modules/moment/locale/zh-tw.js",
265
+ "./zh-tw.js": "./node_modules/moment/locale/zh-tw.js"
266
+ };
267
+
268
+
269
+ function webpackContext(req) {
270
+ var id = webpackContextResolve(req);
271
+ return __webpack_require__(id);
272
+ }
273
+ function webpackContextResolve(req) {
274
+ if(!__webpack_require__.o(map, req)) {
275
+ var e = new Error("Cannot find module '" + req + "'");
276
+ e.code = 'MODULE_NOT_FOUND';
277
+ throw e;
278
+ }
279
+ return map[req];
280
+ }
281
+ webpackContext.keys = function webpackContextKeys() {
282
+ return Object.keys(map);
283
+ };
284
+ webpackContext.resolve = webpackContextResolve;
285
+ module.exports = webpackContext;
286
+ webpackContext.id = "./node_modules/moment/locale sync recursive ^\\.\\/.*$";
287
+
288
+ /***/ }),
289
+
290
+ /***/ "./src/components/charts/chart-utils.js":
291
+ /*!**********************************************!*\
292
+ !*** ./src/components/charts/chart-utils.js ***!
293
+ \**********************************************/
294
+ /*! exports provided: getFormattedDateTime, getBasicSharedTemplate, getMemorySharedTemplate, getMemoryValueAxisLabelTemplate, getNetworkSharedTemplate, getNetworkValueAxisLabelTemplate, getUserCountSharedTemplate, getTimeRangeTooltipTemplate, getWRBytesLabelTemplate */
295
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
296
+
297
+ "use strict";
298
+ __webpack_require__.r(__webpack_exports__);
299
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getFormattedDateTime", function() { return getFormattedDateTime; });
300
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBasicSharedTemplate", function() { return getBasicSharedTemplate; });
301
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getMemorySharedTemplate", function() { return getMemorySharedTemplate; });
302
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getMemoryValueAxisLabelTemplate", function() { return getMemoryValueAxisLabelTemplate; });
303
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNetworkSharedTemplate", function() { return getNetworkSharedTemplate; });
304
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getNetworkValueAxisLabelTemplate", function() { return getNetworkValueAxisLabelTemplate; });
305
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getUserCountSharedTemplate", function() { return getUserCountSharedTemplate; });
306
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getTimeRangeTooltipTemplate", function() { return getTimeRangeTooltipTemplate; });
307
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getWRBytesLabelTemplate", function() { return getWRBytesLabelTemplate; });
308
+ /* harmony import */ var _utils_utilities__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../utils/utilities */ "./src/utils/utilities.js");
309
+
310
+
311
+ function getFormattedDateTime(date, format = 'dd MMM HH:mm:ss')
312
+ {
313
+ return kendo.toString(date, format);
314
+ }
315
+
316
+ function getBasicSharedTemplate(valueFormat = '{0}') {
317
+ return kendo.template(`
318
+ <div class="chart-tooltip-category"><strong>#: category #</strong></div>
319
+ # for (var i = 0; i < points.length; i++) { #
320
+ <div>
321
+ <i class="fas fa-square" style="color: #: points[i].color # "></i>
322
+ #: points[i].series.name# : #: kendo.format('${valueFormat}', points[i].value) #
323
+ </div>
324
+ # } #
325
+ `);
326
+ }
327
+
328
+ function getMemorySharedTemplate() {
329
+ return function(dataItem) {
330
+ dataItem.bytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_0__["bytesToSize"]; // Pass bytesToSize utility function to template
331
+ return kendo.template(`
332
+ <div class="chart-tooltip-category"><strong>#: category #</strong></div>
333
+ # for (var i = 0; i < points.length; i++) { #
334
+ <div>
335
+ <i class="fas fa-square" style="color: #: points[i].color # "></i>
336
+ #: points[i].series.name# : #: bytesToSize(points[i].value) #
337
+ </div>
338
+ # } #
339
+ `)(dataItem);
340
+ };
341
+ }
342
+
343
+ function getMemoryValueAxisLabelTemplate() {
344
+ return function(dataItem) {
345
+ dataItem.bytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_0__["bytesToSize"]; // Pass bytesToSize utility function to template
346
+ return kendo.template(`
347
+ #: bytesToSize(value) #
348
+ `)(dataItem);
349
+ };
350
+ }
351
+
352
+ function getNetworkSharedTemplate(categoryFormat = 'dd MMM HH:mm:ss') {
353
+ return function(dataItem) {
354
+ dataItem.kBytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_0__["kBytesToSize"]; // Pass kBytesToSize utility function to template
355
+ return kendo.template(`
356
+ <div class="chart-tooltip-category"><strong>#: kendo.toString(category, '${categoryFormat}') #</strong></div>
357
+ # for (var i = 0; i < points.length; i++) { #
358
+ <div>
359
+ <i class="fas fa-square" style="color: #: points[i].color # "></i>
360
+ #: points[i].series.name# : #: kBytesToSize(points[i].value, 1, '', '/s') #
361
+ </div>
362
+ # } #
363
+ `)(dataItem);
364
+ };
365
+ }
366
+
367
+ function getNetworkValueAxisLabelTemplate() {
368
+ return function(dataItem) {
369
+ dataItem.kBytesToSize = _utils_utilities__WEBPACK_IMPORTED_MODULE_0__["kBytesToSize"]; // Pass kBytesToSize utility function to template
370
+ return kendo.template(`
371
+ #: kBytesToSize(value, 1, '', '/s') #
372
+ `)(dataItem);
373
+ };
374
+ }
375
+
376
+ function getUserCountSharedTemplate(categoryFormat = 'dd MMM HH:mm:ss') {
377
+ return function(dataItem) {
378
+ return kendo.template(`
379
+ <div class="chart-tooltip-category"><strong>#: kendo.toString(category, '${categoryFormat}') #</strong></div>
380
+ # for (var i = 0; i < points.length; i++) { #
381
+ <div>
382
+ <i class="fas fa-square" style="color: #: points[i].color # "></i>
383
+ #: points[i].series.name# : #: points[i].value #
384
+ </div>
385
+ # } #
386
+ `)(dataItem);
387
+ };
388
+ }
389
+
390
+ function getTimeRangeTooltipTemplate() {
391
+ return function(dataItem) {
392
+ dataItem.getTooltipString = function(v1, v2) {
393
+ if (v1 == v2)
394
+ {
395
+ if (v2 == -24)
396
+ v2 = -23;
397
+
398
+ v1 = v2 - 1;
399
+ }
400
+
401
+ let start = Math.abs(v1);
402
+ let end = Math.abs(v2);
403
+
404
+ return `From ${start} hour${start != 1 ? 's' : ''} ago to ${end > 0 ? ('to ' + end + ' hour' + (end != 1 ? 's' : '') + ' ago') : 'now'}`;
405
+ }; // Pass utility function to template
406
+ return kendo.template(`
407
+ #: getTooltipString(selectionStart, selectionEnd) #
408
+ `)(dataItem);
409
+ };
410
+ }
411
+
412
+ function getWRBytesLabelTemplate() {
413
+ return function(dataItem) {
414
+ return kendo.template(`
415
+ #: value # #: dataItem.unit #
416
+ `)(dataItem);
417
+ };
418
+ }
419
+
420
+
421
+ /***/ }),
422
+
423
+ /***/ "./src/components/charts/user-count-chart.js":
424
+ /*!***************************************************!*\
425
+ !*** ./src/components/charts/user-count-chart.js ***!
426
+ \***************************************************/
427
+ /*! exports provided: UserCountChart */
428
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
429
+
430
+ "use strict";
431
+ __webpack_require__.r(__webpack_exports__);
432
+ /* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UserCountChart", function() { return UserCountChart; });
433
+ /* harmony import */ var _chart_utils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./chart-utils */ "./src/components/charts/chart-utils.js");
434
+ /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! moment */ "./node_modules/moment/moment.js");
435
+ /* harmony import */ var moment__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(moment__WEBPACK_IMPORTED_MODULE_1__);
436
+
437
+
438
+
439
+ class UserCountChart extends HTMLElement
440
+ {
441
+ constructor()
442
+ {
443
+ super();
444
+
445
+ // Create chart html
446
+ let chartHtml = $('<div>');
447
+ $(this).append(chartHtml);
448
+
449
+ // Initialize chart
450
+ this._chartWidget = this._initChartWidget(chartHtml);
451
+ }
452
+
453
+ _initChartWidget(chartHtml)
454
+ {
455
+ return chartHtml.kendoChart({
456
+ transitions: false,
457
+ chartArea: {
458
+ height: 270,
459
+ background: 'transparent'
460
+ },
461
+ legend: {
462
+ visible: false
463
+ },
464
+ seriesDefaults: {
465
+ type: 'area',
466
+ labels: {
467
+ visible: false,
468
+ format: '{0}',
469
+ background: 'transparent'
470
+ },
471
+ },
472
+ series: [{
473
+ name: 'Users',
474
+ field: 'users',
475
+ categoryField: 'time',
476
+ color: '#fd7d24',
477
+ line: {
478
+ width: 2
479
+ }
480
+ }],
481
+ valueAxis: {
482
+ labels: {
483
+ format: '{0}',
484
+ },
485
+ line: {
486
+ visible: false
487
+ },
488
+ min: 0,
489
+ },
490
+ categoryAxis: {
491
+ majorGridLines: {
492
+ visible: true,
493
+ step: 60
494
+ },
495
+ majorTicks: {
496
+ visible: true,
497
+ step: 60
498
+ },
499
+ labels: {
500
+ visible: true,
501
+ step: 60
502
+ },
503
+ baseUnit: 'minutes',
504
+ type: 'date',
505
+ },
506
+ tooltip: {
507
+ shared: true,
508
+ visible: true,
509
+ sharedTemplate: Object(_chart_utils__WEBPACK_IMPORTED_MODULE_0__["getUserCountSharedTemplate"])('dd MMM HH:mm'),
510
+ background: '#e4e4e4'
511
+ }
512
+ }).data('kendoChart');
513
+ }
514
+
515
+ redraw()
516
+ {
517
+ this._chartWidget.redraw();
518
+ }
519
+
520
+ set range(values)
521
+ {
522
+ this._range = values;
523
+
524
+ this._updateXAxisLimits();
525
+ }
526
+
527
+ get range()
528
+ {
529
+ return this._range;
530
+ }
531
+
532
+ addHistoryEntries(userCountData, samplingRateSeconds)
533
+ {
534
+ let date = new Date();
535
+ let start = moment__WEBPACK_IMPORTED_MODULE_1__(date);
536
+ start.subtract((samplingRateSeconds * userCountData.length), 's')
537
+
538
+ let dataSource = new kendo.data.DataSource();
539
+
540
+ for (let i = 1; i < userCountData.length; i++)
541
+ {
542
+ let date = start.clone();
543
+ date.add(i * samplingRateSeconds, 's');
544
+
545
+ this.addEntry(userCountData[i], dataSource, date.toDate(), false);
546
+ }
547
+
548
+ // Assign datasource to chart
549
+ this._chartWidget.setDataSource(dataSource);
550
+
551
+ // Update axis
552
+ this._updateXAxisLimits();
553
+ }
554
+
555
+ addEntry(userCount, dataSource = null, date = null, updateAxis = true)
556
+ {
557
+ if (date == null)
558
+ date = new Date();
559
+
560
+ let newEntry = {
561
+ time: date,
562
+ users: userCount
563
+ };
564
+
565
+ // Add entry to data source
566
+ if (dataSource == null)
567
+ dataSource = this._dataSource;
568
+
569
+ dataSource.add(newEntry);
570
+
571
+ if (updateAxis)
572
+ this._updateXAxisLimits();
573
+ }
574
+
575
+ _updateXAxisLimits()
576
+ {
577
+ let ds = this._dataSource;
578
+
579
+ if (ds.total() > 0)
580
+ {
581
+ const chartMinimum = moment__WEBPACK_IMPORTED_MODULE_1__(this._lastDate).add(this._range[0], 'h');
582
+ const chartMaximum = moment__WEBPACK_IMPORTED_MODULE_1__(this._lastDate).add(this._range[1], 'h');
583
+
584
+ this._chartWidget.options.categoryAxis.min = chartMinimum.toDate();
585
+ this._chartWidget.options.categoryAxis.max = chartMaximum.toDate();
586
+
587
+ this._chartWidget.redraw();
588
+ }
589
+ }
590
+
591
+ get _dataSource()
592
+ {
593
+ return this._chartWidget.dataSource;
594
+ }
595
+ }
596
+
597
+ // DEFINE COMPONENT
598
+ if (!window.customElements.get('user-count-chart'))
599
+ window.customElements.define('user-count-chart', UserCountChart);
600
+
601
+ /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! jquery */ "jquery")))
602
+
603
+ /***/ }),
604
+
605
+ /***/ "./src/components/module-specific/match-expression-builder.js":
606
+ /*!********************************************************************!*\
607
+ !*** ./src/components/module-specific/match-expression-builder.js ***!
608
+ \********************************************************************/
609
+ /*! exports provided: MatchExpressionBuilder */
610
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
611
+
612
+ "use strict";
613
+ __webpack_require__.r(__webpack_exports__);
614
+ /* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "MatchExpressionBuilder", function() { return MatchExpressionBuilder; });
615
+ class MatchExpressionBuilder extends HTMLElement
616
+ {
617
+ constructor()
618
+ {
619
+ super();
620
+
621
+ this.EXPRESSION_UPDATED_EVENT = 'expressionUpdated';
622
+
623
+ this._dialog = $(`
624
+ <div class="modal" id="matchExprBuilderModal" tabindex="-1" role="dialog" aria-labelledby="matchExprBuilderModalTitle" aria-hidden="true">
625
+ <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
626
+ <div class="modal-content">
627
+ <div class="modal-header">
628
+ <h5 class="modal-title text-primary" id="matchExprBuilderModalTitle">...</h5>
629
+ </div>
630
+ <div class="modal-body p-0">
631
+ <form class="bg-color-default p-3">
632
+ <div class="d-inline-flex align-items-center radio-button-group inline-form-groups">
633
+ <div class="custom-control custom-radio custom-control-inline mr-2">
634
+ <input type="radio" id="andOperatorRB" name="operatorRBG" class="custom-control-input" value="AND" checked disabled>
635
+ <label class="custom-control-label" for="andOperatorRB">AND</label>
636
+ </div>
637
+ <div class="custom-control custom-radio custom-control-inline mr-2">
638
+ <input type="radio" id="orOperatorRB" name="operatorRBG" class="custom-control-input" value="OR" disabled>
639
+ <label class="custom-control-label" for="orOperatorRB">OR</label>
640
+ </div>
641
+ </div>
642
+ <div class="d-inline-block">
643
+ <div class="inline-form-groups my-1">
644
+ <input id="varNameCB"/>
645
+ </div>
646
+ <div class="inline-form-groups my-1">
647
+ <input id="typeDD" class="matchTypeDropdown"/>
648
+ <input id="conditionDD" class="matchConditionDropdown"/>
649
+ </div>
650
+ </div>
651
+ <div class="d-inline inline-form-groups">
652
+ <input id="valueIn" class="k-textbox mt-1" placeholder="Value"/>
653
+ <button id="matchExprAddBt" type="button" class="k-button k-secondary mt-1"><i class="fas fa-plus mr-1"></i>Add</button>
654
+ </div>
655
+ </form>
656
+
657
+ <div id="matchExprGrid" class="m-3"></div>
658
+ </div>
659
+ <div class="modal-footer d-flex">
660
+ <div class="flex-grow-1 text-left">
661
+ <button id="matchExprApplyBt" type="button" class="k-button k-primary mr-2"><i class="fas fa-check-circle mr-1"></i>Apply</button>
662
+ </div>
663
+ <div class="flex-grow-1 text-right">
664
+ <button id="matchExprRemoveBt" type="button" class="k-button k-secondary" disabled><i class="fas fa-minus-circle mr-1"></i>Remove selected</button>
665
+ <button id="matchExprClearBt" type="button" class="k-button k-secondary"><i class="fas fa-times-circle mr-1"></i>Clear all</button>
666
+ </div>
667
+ </div>
668
+ </div>
669
+ </div>
670
+ </div>
671
+ `);
672
+
673
+ $('#matchExprAddBt', this._dialog).on('click', $.proxy(this._onAddBtClick, this));
674
+ $('#matchExprApplyBt', this._dialog).on('click', $.proxy(this._onApplyBtClick, this));
675
+ $('#matchExprRemoveBt', this._dialog).on('click', $.proxy(this._onRemoveBtClick, this));
676
+ $('#matchExprClearBt', this._dialog).on('click', $.proxy(this._onClearBtClick, this));
677
+
678
+ // INITIALIZE FORM ITEMS
679
+
680
+ this._varNameCb = $('#varNameCB', this._dialog).kendoComboBox({
681
+ dataTextField: 'label',
682
+ dataValueField: 'value',
683
+ placeholder: 'Variable name',
684
+ }).data('kendoComboBox');
685
+
686
+ // Set types dropdown data source
687
+ // NOTE: in order to avoid XxxMatch objects to be wrapped by Kendo data source, we have to pass them using _ property names
688
+ let typeDS = [];
689
+
690
+ // Boolean ----------------
691
+ typeDS.push({
692
+ label: 'Boolean',
693
+ _value: SFS2X.BoolMatch.EQUALS,
694
+ conditions: [
695
+ {
696
+ label: SFS2X.BoolMatch.EQUALS.symbol,
697
+ _value: SFS2X.BoolMatch.EQUALS,
698
+ },
699
+ {
700
+ label: SFS2X.BoolMatch.NOT_EQUALS.symbol,
701
+ _value: SFS2X.BoolMatch.NOT_EQUALS,
702
+ }
703
+ ]
704
+ });
705
+
706
+ // Number ----------------
707
+ typeDS.push({
708
+ label: 'Number',
709
+ _value: SFS2X.NumberMatch.EQUALS,
710
+ conditions: [
711
+ {
712
+ label: SFS2X.NumberMatch.EQUALS.symbol,
713
+ _value: SFS2X.NumberMatch.EQUALS,
714
+ },
715
+ {
716
+ label: SFS2X.NumberMatch.NOT_EQUALS.symbol,
717
+ _value: SFS2X.NumberMatch.NOT_EQUALS,
718
+ },
719
+ {
720
+ label: SFS2X.NumberMatch.GREATER_THAN.symbol,
721
+ _value: SFS2X.NumberMatch.GREATER_THAN,
722
+ },
723
+ {
724
+ label: SFS2X.NumberMatch.LESS_THAN.symbol,
725
+ _value: SFS2X.NumberMatch.LESS_THAN,
726
+ },
727
+ {
728
+ label: SFS2X.NumberMatch.GREATER_THAN_OR_EQUAL_TO.symbol,
729
+ _value: SFS2X.NumberMatch.GREATER_THAN_OR_EQUAL_TO,
730
+ },
731
+ {
732
+ label: SFS2X.NumberMatch.LESS_THAN_OR_EQUAL_TO.symbol,
733
+ _value: SFS2X.NumberMatch.LESS_THAN_OR_EQUAL_TO,
734
+ }
735
+ ]
736
+ });
737
+
738
+ // String ----------------
739
+ typeDS.push({
740
+ label: 'String',
741
+ _value: SFS2X.StringMatch.EQUALS,
742
+ conditions: [
743
+ {
744
+ label: SFS2X.StringMatch.EQUALS.symbol,
745
+ _value: SFS2X.StringMatch.EQUALS,
746
+ },
747
+ {
748
+ label: SFS2X.StringMatch.NOT_EQUALS.symbol,
749
+ _value: SFS2X.StringMatch.NOT_EQUALS,
750
+ },
751
+ {
752
+ label: SFS2X.StringMatch.CONTAINS.symbol,
753
+ _value: SFS2X.StringMatch.CONTAINS,
754
+ },
755
+ {
756
+ label: SFS2X.StringMatch.STARTS_WITH.symbol,
757
+ _value: SFS2X.StringMatch.STARTS_WITH,
758
+ },
759
+ {
760
+ label: SFS2X.StringMatch.ENDS_WITH.symbol,
761
+ _value: SFS2X.StringMatch.ENDS_WITH,
762
+ }
763
+ ]
764
+ });
765
+
766
+ this._typeDd = $('#typeDD', this._dialog).kendoDropDownList({
767
+ dataSource: typeDS,
768
+ dataTextField: 'label',
769
+ dataValueField: '_value',
770
+ optionLabel: {
771
+ label: 'Type',
772
+ _value: ''
773
+ },
774
+ optionLabelTemplate: '<span class="text-muted">#:label#</span>',
775
+ change: $.proxy(function() {
776
+ if (this._typeDd && this._typeDd.select())
777
+ {
778
+ let selectedType = this._typeDd.dataItem(this._typeDd.select());
779
+ this._conditionDd.setDataSource(selectedType.conditions);
780
+ this._conditionDd.select(1);
781
+ }
782
+ }, this)
783
+ }).data('kendoDropDownList');
784
+
785
+ this._conditionDd = $('#conditionDD', this._dialog).kendoDropDownList({
786
+ dataTextField: 'label',
787
+ dataValueField: '_value',
788
+ optionLabel: {
789
+ label: 'Condition',
790
+ _value: ''
791
+ },
792
+ optionLabelTemplate: '<span class="text-muted">#:label#</span>',
793
+ }).data('kendoDropDownList');
794
+
795
+ this._valueIn = $('#valueIn', this._dialog);
796
+
797
+ // INITIALIZE GRID
798
+
799
+ this._grid = $('#matchExprGrid', this._dialog).kendoGrid({
800
+ dataSource: [],
801
+ resizable: true,
802
+ selectable: 'row',
803
+ change: $.proxy(this._onGridSelectionChange, this),
804
+ noRecords: {
805
+ template: 'No entries.'
806
+ },
807
+ columns: [
808
+ {
809
+ field: 'operator',
810
+ title: 'Operator',
811
+ width: 90
812
+ },
813
+ {
814
+ field: 'label',
815
+ title: 'Name',
816
+ width: 120
817
+ },
818
+ {
819
+ field: 'typeLabel',
820
+ title: 'Type',
821
+ width: 85
822
+ },
823
+ {
824
+ field: 'symbol',
825
+ title: 'Condition',
826
+ width: 95
827
+ },
828
+ {
829
+ field: 'value',
830
+ title: 'Value',
831
+ width: 200
832
+ },
833
+ ]
834
+ }).data('kendoGrid');
835
+ }
836
+
837
+ get title()
838
+ {
839
+ return $('#matchExprBuilderModalTitle', this._dialog).text();
840
+ }
841
+
842
+ set title(value)
843
+ {
844
+ $('#matchExprBuilderModalTitle', this._dialog).text(value);
845
+ }
846
+
847
+ get predefinedVarNames()
848
+ {
849
+ return this._predefinedVarNames;
850
+ }
851
+
852
+ set predefinedVarNames(value)
853
+ {
854
+ this._predefinedVarNames = value;
855
+
856
+ this._varNameCb.setDataSource(value);
857
+ }
858
+
859
+ get filterExpression()
860
+ {
861
+ return this._filterExpression;
862
+ }
863
+
864
+ show()
865
+ {
866
+ this._dialog.modal({
867
+ backdrop: 'static',
868
+ keyboard: false,
869
+ show: true
870
+ });
871
+ }
872
+
873
+ _onGridSelectionChange()
874
+ {
875
+ let selectedRows = this._grid.select();
876
+ let selectedDataItems = [];
877
+
878
+ for (let i = 0; i < selectedRows.length; i++)
879
+ {
880
+ let dataItem = this._grid.dataItem(selectedRows[i]);
881
+ selectedDataItems.push(dataItem);
882
+ }
883
+
884
+ // Enable/disable remove button
885
+ $('#matchExprRemoveBt', this._dialog).attr('disabled', selectedDataItems.length == 0);
886
+ }
887
+
888
+ _onAddBtClick()
889
+ {
890
+ if (this._varNameCb.value() != '' && this._typeDd.select())
891
+ {
892
+ // Variable name and label
893
+ let varName, varLabel;
894
+
895
+ if (this._varNameCb.select() > -1)
896
+ {
897
+ let dataItem = this._varNameCb.dataItem(this._varNameCb.select());
898
+ varName = dataItem.value;
899
+ varLabel = dataItem.label;
900
+ }
901
+ else
902
+ varName = varLabel = this._varNameCb.value();
903
+
904
+ // Variable type's label
905
+ let typeLabel = this._typeDd.dataItem(this._typeDd.select()).label;
906
+
907
+ // Match condition
908
+ let condition = this._conditionDd.dataItem(this._conditionDd.select())._value;
909
+
910
+ // Expression operator
911
+ let operator = this._grid.dataSource.total() > 0 ? $('input[name=operatorRBG]:checked', this._dialog).val() : null;
912
+
913
+ // Variable value
914
+ let val = this._valueIn.val();
915
+ let varValue;
916
+
917
+ if (condition instanceof SFS2X.BoolMatch)
918
+ varValue = (val == 'true' ? true : false);
919
+ else if (condition instanceof SFS2X.NumberMatch)
920
+ varValue = (isNaN(Number(val)) ? 0 : Number(val));
921
+ else
922
+ varValue = val;
923
+
924
+ // Add item to grid
925
+ let exprPart = this._getExpressionPart(varLabel, varName, varValue, typeLabel, condition, operator);
926
+ this._grid.dataSource.add(exprPart);
927
+
928
+ // Reset inputs
929
+ this._varNameCb.value('');
930
+ this._valueIn.val('');
931
+
932
+ // Enable operator radio buttons
933
+ this._enableOperatorRb(true);
934
+ }
935
+ }
936
+
937
+ _onApplyBtClick()
938
+ {
939
+ // Hide dialog
940
+ this._dialog.modal('hide');
941
+
942
+ // Clear grid selection
943
+ this._grid.clearSelection();
944
+
945
+ // Build final match expression
946
+ this._filterExpression = null;
947
+
948
+ if (this._grid.dataSource.total() > 0)
949
+ {
950
+ let expPart = this._grid.dataSource.at(0);
951
+ this._filterExpression = new SFS2X.MatchExpression(expPart.name, expPart._condition, expPart.value);
952
+
953
+ for (let i = 1; i < this._grid.dataSource.total(); i++)
954
+ {
955
+ expPart = this._grid.dataSource.at(i);
956
+
957
+ if (expPart.operator == SFS2X.LogicOperator.AND.id)
958
+ this._filterExpression = this._filterExpression.and(expPart.name, expPart._condition, expPart.value);
959
+ else if (expPart.operator == SFS2X.LogicOperator.OR.id)
960
+ this._filterExpression = this._filterExpression.or(expPart.name, expPart._condition, expPart.value);
961
+ }
962
+ }
963
+
964
+ // Fire event
965
+ let evt = new CustomEvent(this.EXPRESSION_UPDATED_EVENT, {
966
+ detail: null,
967
+ bubbles: false,
968
+ cancelable: false
969
+ });
970
+
971
+ this.dispatchEvent(evt);
972
+ }
973
+
974
+ _onRemoveBtClick()
975
+ {
976
+ let dataItem = this._grid.dataItem(this._grid.select());
977
+ this._grid.dataSource.remove(dataItem);
978
+
979
+ // Clear grid selection
980
+ this._grid.clearSelection();
981
+
982
+ if (this._grid.dataSource.total() == 0)
983
+ {
984
+ // Disable operator radio buttons
985
+ this._enableOperatorRb(false);
986
+ }
987
+ else
988
+ {
989
+ // Reset operator on first entry
990
+ this._grid.dataSource.at(0).operator = null;
991
+ this._grid.refresh();
992
+ }
993
+ }
994
+
995
+ _onClearBtClick()
996
+ {
997
+ // Reset form
998
+ $('#andOperatorRB', this._dialog).attr('checked', true);
999
+ $('#orOperatorRB', this._dialog).attr('checked', false);
1000
+ this._enableOperatorRb(false);
1001
+
1002
+ this._varNameCb.value('');
1003
+ this._typeDd.select(0);
1004
+ this._conditionDd.select(0);
1005
+
1006
+ this._valueIn.val('');
1007
+
1008
+ // Clear grid selection
1009
+ this._grid.clearSelection();
1010
+
1011
+ // Clear table
1012
+ this._grid.setDataSource([]);
1013
+ }
1014
+
1015
+ _getExpressionPart(varLabel, varName, varValue, typeLabel, condition, operator)
1016
+ {
1017
+ return {
1018
+ 'label': varLabel,
1019
+ 'name': varName,
1020
+ 'value': varValue,
1021
+ 'typeLabel': typeLabel,
1022
+ 'symbol': condition.symbol,
1023
+ 'operator': operator,
1024
+ '_condition': condition,
1025
+ };
1026
+ }
1027
+
1028
+ _enableOperatorRb(enable)
1029
+ {
1030
+ $('#andOperatorRB', this._dialog).attr('disabled', !enable);
1031
+ $('#orOperatorRB', this._dialog).attr('disabled', !enable);
1032
+ }
1033
+ }
1034
+
1035
+ // DEFINE COMPONENT
1036
+ if (!window.customElements.get('match-expression-builder'))
1037
+ window.customElements.define('match-expression-builder', MatchExpressionBuilder);
1038
+
1039
+ /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! jquery */ "jquery")))
1040
+
1041
+ /***/ }),
1042
+
1043
+ /***/ "./src/components/sidebar-layout.js":
1044
+ /*!******************************************!*\
1045
+ !*** ./src/components/sidebar-layout.js ***!
1046
+ \******************************************/
1047
+ /*! exports provided: SidebarLayout */
1048
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
1049
+
1050
+ "use strict";
1051
+ __webpack_require__.r(__webpack_exports__);
1052
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "SidebarLayout", function() { return SidebarLayout; });
1053
+ class SidebarLayout extends HTMLElement
1054
+ {
1055
+ constructor()
1056
+ {
1057
+ super();
1058
+
1059
+ // Attach a shadow root
1060
+ const shadowRoot = this.attachShadow({mode: 'open'});
1061
+ shadowRoot.innerHTML = `
1062
+ <style>
1063
+ :host {
1064
+ display: flex;
1065
+ flex-direction: row;
1066
+ }
1067
+
1068
+ @media (max-width: 575.98px) {
1069
+ :host(.split-xs) ::slotted(:not([aria-selected="true"])) {
1070
+ display: none !important;
1071
+ }
1072
+
1073
+ :host(.split-xs) ::slotted([aria-selected="true"]) {
1074
+ flex-grow: 1;
1075
+ }
1076
+ }
1077
+
1078
+ @media (max-width: 767.98px) {
1079
+ :host(.split-sm) ::slotted(:not([aria-selected="true"])) {
1080
+ display: none !important;
1081
+ }
1082
+
1083
+ :host(.split-sm) ::slotted([aria-selected="true"]) {
1084
+ flex-grow: 1;
1085
+ }
1086
+ }
1087
+
1088
+ @media (max-width: 991.98px) {
1089
+ :host(.split-md) ::slotted(:not([aria-selected="true"])) {
1090
+ display: none !important;
1091
+ }
1092
+
1093
+ :host(.split-md) ::slotted([aria-selected="true"]) {
1094
+ flex-grow: 1;
1095
+ }
1096
+ }
1097
+
1098
+ @media (max-width: 1199.98px) {
1099
+ :host(.split-lg) ::slotted(:not([aria-selected="true"])) {
1100
+ display: none !important;
1101
+ }
1102
+
1103
+ :host(.split-lg) ::slotted([aria-selected="true"]) {
1104
+ flex-grow: 1;
1105
+ }
1106
+ }
1107
+
1108
+ .side-col::slotted(*) {
1109
+ }
1110
+
1111
+ .main-col::slotted(*) {
1112
+ flex-grow: 1;
1113
+ }
1114
+ </style>
1115
+
1116
+ <slot class="side-col" name="side-column"></slot>
1117
+ <slot class="main-col" name="main-column"></slot>
1118
+ `;
1119
+
1120
+ // Set initial selection
1121
+ this.selectedIndex = 0;
1122
+ }
1123
+
1124
+ get selectedPanel()
1125
+ {
1126
+ return this._selectedPanel;
1127
+ }
1128
+
1129
+ set selectedPanel(element) // 'side' or 'main'
1130
+ {
1131
+ if (element != null && element.parentNode == this)
1132
+ {
1133
+ this._selectedPanel = element;
1134
+
1135
+ for (let element of this.children)
1136
+ {
1137
+ if (element == this._selectedPanel)
1138
+ element.setAttribute('aria-selected', 'true');
1139
+ else
1140
+ element.removeAttribute('aria-selected');
1141
+ }
1142
+ }
1143
+ else
1144
+ {
1145
+ console.error('Element is not a child of SidebarLayout');
1146
+ }
1147
+ }
1148
+
1149
+ get selectedIndex()
1150
+ {
1151
+ return Array.from(this.children).indexOf(this._selectedPanel);
1152
+ }
1153
+
1154
+ set selectedIndex(index)
1155
+ {
1156
+ if (this.children.length > 0)
1157
+ {
1158
+ if (this.children[index] == null)
1159
+ {
1160
+ console.error('Invalid SidebarLayout index');
1161
+ return;
1162
+ }
1163
+
1164
+ let element = this.children[index];
1165
+ this.selectedPanel = element;
1166
+ }
1167
+ }
1168
+ }
1169
+
1170
+ // DEFINE COMPONENT
1171
+ if (!window.customElements.get('sidebar-layout'))
1172
+ window.customElements.define('sidebar-layout', SidebarLayout);
1173
+
1174
+
1175
+ /***/ }),
1176
+
1177
+ /***/ "./src/modules/zone-monitor.js":
1178
+ /*!*************************************!*\
1179
+ !*** ./src/modules/zone-monitor.js ***!
1180
+ \*************************************/
1181
+ /*! exports provided: default */
1182
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
1183
+
1184
+ "use strict";
1185
+ __webpack_require__.r(__webpack_exports__);
1186
+ /* WEBPACK VAR INJECTION */(function($) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return ZoneMonitor; });
1187
+ /* harmony import */ var _base_module__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./base-module */ "./src/modules/base-module.js");
1188
+ /* harmony import */ var _components_sidebar_layout__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../components/sidebar-layout */ "./src/components/sidebar-layout.js");
1189
+ /* harmony import */ var _components_module_specific_match_expression_builder__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../components/module-specific/match-expression-builder */ "./src/components/module-specific/match-expression-builder.js");
1190
+ /* harmony import */ var _utils_uibuilder_config_interface_builder__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../utils/uibuilder/config-interface-builder */ "./src/utils/uibuilder/config-interface-builder.js");
1191
+ /* harmony import */ var _utils_utilities__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/utilities */ "./src/utils/utilities.js");
1192
+ /* harmony import */ var _utils_match_properties__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../utils/match-properties */ "./src/utils/match-properties.js");
1193
+ /* harmony import */ var _components_charts_user_count_chart__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../components/charts/user-count-chart */ "./src/components/charts/user-count-chart.js");
1194
+ /* harmony import */ var _components_charts_chart_utils__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../components/charts/chart-utils */ "./src/components/charts/chart-utils.js");
1195
+
1196
+
1197
+
1198
+
1199
+
1200
+
1201
+
1202
+
1203
+
1204
+ class ZoneMonitor extends _base_module__WEBPACK_IMPORTED_MODULE_0__["BaseModule"]
1205
+ {
1206
+ constructor()
1207
+ {
1208
+ super('zoneMonitor');
1209
+
1210
+ this.MONITORED_TYPE_ZONE = 'zone';
1211
+ this.MONITORED_TYPE_ROOM = 'room';
1212
+ this.MONITORED_TYPE_USER = 'user';
1213
+
1214
+ this.ANY_LABEL = '[any]';
1215
+ this.DEFAULT_GROUP_NAME = 'default';
1216
+ this.MAX_EXTENSION_LOG_SIZE = 300;
1217
+ this.KICK_BAN_DEFAULT_DELAY = 5;
1218
+
1219
+ // Outgoing requests
1220
+ this.REQ_GET_DATA = 'getData';
1221
+ this.REQ_SET_ZONE_SETTINGS = 'setZoneSettings';
1222
+ this.REQ_SET_ROOM_SETTINGS = 'setRoomSettings';
1223
+ this.REQ_SET_USER_SETTINGS = 'setUserSettings';
1224
+ this.REQ_RELOAD_ZONE_EXT = 'reloadZoneExt';
1225
+ this.REQ_RELOAD_WORDS = 'reloadWords';
1226
+ this.REQ_KICK_USER = 'kickUser';
1227
+ this.REQ_BAN_USER = 'banUser';
1228
+ this.REQ_GET_ROOM_CONFIG = 'getRoomConfig';
1229
+ this.REQ_CREATE_ROOM = 'createRoom';
1230
+ this.REQ_REMOVE_ROOM = 'removeRoom';
1231
+ this.REQ_ADMIN_MSG = 'adminMsg';
1232
+
1233
+ // Incoming responses
1234
+ this.RESP_DATA = 'data';
1235
+ this.RESP_UNEXPECTED_ERROR = 'unexpError';
1236
+ this.RESP_UPDATE_ERROR = 'updateError';
1237
+ this.RESP_ROOM_CONFIG = 'roomConfig';
1238
+ this.RESP_ROOM_CONFIG_ERROR = 'roomConfigErr';
1239
+ this.RESP_ROOM_CREATED = 'roomCreated';
1240
+ this.RESP_ROOM_CREATION_ERROR = 'roomError';
1241
+ this.RESP_LOG_MESSAGES = 'log'; // This response doesn't have a corresponding request because it is managed by a server event listener
1242
+
1243
+ this._currentRequestId = -1;
1244
+ }
1245
+
1246
+ //------------------------------------
1247
+ // COMMON MODULE INTERFACE METHODS
1248
+ // This members are used by the main controller
1249
+ // to communicate with the module's controller.
1250
+ //------------------------------------
1251
+
1252
+ initialize(idData, shellController)
1253
+ {
1254
+ // Call super method
1255
+ super.initialize(idData, shellController);
1256
+
1257
+ // Set monitoring interface
1258
+ this._setMonitoringInterface();
1259
+
1260
+ // Initialize progress bar
1261
+ $('#znm-progressBar').kendoProgressBar({
1262
+ min: 0,
1263
+ max: 100,
1264
+ value: false,
1265
+ type: 'value',
1266
+ animation: {
1267
+ duration: 400
1268
+ }
1269
+ });
1270
+
1271
+ // LISTS
1272
+
1273
+ // Initialize interval dropdown
1274
+ this._intervalDropDown = $('#znm-intervalDD').kendoDropDownList({
1275
+ valueTemplate: '<span class="text-muted pr-1">Interval:</span><span>#:data.text#</span>',
1276
+ change: $.proxy(this._onUpdateIntervalChange, this)
1277
+ }).data('kendoDropDownList');
1278
+
1279
+ // Initialize pane bar
1280
+ this._accordion = $('#znm-panelbar').kendoPanelBar({
1281
+ expandMode: 'single',
1282
+ change: $.proxy(this._onEntitiesPanelChange, this)
1283
+ }).data('kendoPanelBar');
1284
+
1285
+ // Initialize lists
1286
+ this._zoneListBox = $("#znm-zoneList").kendoListBox({
1287
+ template: '<div>#:data.name# (#:data.users#)</div>',
1288
+ change: $.proxy(this._onZoneSelected, this)
1289
+ }).data('kendoListBox');
1290
+
1291
+ this._zoneListBox.wrapper.find('.k-list').on('dblclick', '.k-item', $.proxy(this._onMonitorSelectionBtClick, this));
1292
+
1293
+ this._roomListBox = $("#znm-roomList").kendoListBox({
1294
+ template: '<div>#:data.name# (#:data.users#)</div>',
1295
+ change: $.proxy(this._onRoomSelected, this)
1296
+ }).data('kendoListBox');
1297
+
1298
+ this._roomListBox.wrapper.find('.k-list').on('dblclick', '.k-item', $.proxy(this._onMonitorSelectionBtClick, this));
1299
+
1300
+ this._userListBox = $("#znm-userList").kendoListBox({
1301
+ template: '<div>#:data.name#</div>',
1302
+ change: $.proxy(this._onUserSelected, this)
1303
+ }).data('kendoListBox');
1304
+
1305
+ this._userListBox.wrapper.find('.k-list').on('dblclick', '.k-item', $.proxy(this._onMonitorSelectionBtClick, this));
1306
+
1307
+ // Initialize Room Groups dropdown
1308
+ this._groupsDropDown = $('#znm-roomGroupsDD').kendoDropDownList({
1309
+ dataTextField: 'label',
1310
+ dataValueField: 'name',
1311
+ change: $.proxy(this._onGroupChange, this)
1312
+ }).data('kendoDropDownList');
1313
+
1314
+ // Build initial groups list
1315
+ this._setGroupsDataProvider(null);
1316
+
1317
+ // // Create interface builder instances
1318
+ this._interfaceBuilder = new _utils_uibuilder_config_interface_builder__WEBPACK_IMPORTED_MODULE_3__["ConfigInterfaceBuilder"]();
1319
+ this._roomCreationIBuilder = new _utils_uibuilder_config_interface_builder__WEBPACK_IMPORTED_MODULE_3__["ConfigInterfaceBuilder"]();
1320
+
1321
+ // Add listener to show limit warning tooltips
1322
+ $('#znm-panelbar').kendoTooltip({
1323
+ filter: 'i[title].limit-warning',
1324
+ position: 'right',
1325
+ width: '250px',
1326
+ content: function(e) {
1327
+ return `<div class="help-tooltip">${e.target.data('title')}</div>`;
1328
+ }
1329
+ });
1330
+
1331
+ // ROOM CREATION PANEL
1332
+
1333
+ // Add click listener to Create & Remove Room buttons
1334
+ $('#znm-createRoomBt').on('click', $.proxy(this._onCreateRoomBtClick, this));
1335
+ $('#znm-removeRoomBt').on('click', $.proxy(this._onRemoveRoomBtClick, this));
1336
+
1337
+ // Configure room creation panel
1338
+ $('#znm-createRoomModal').modal({
1339
+ backdrop: 'static',
1340
+ keyboard: false,
1341
+ show: false,
1342
+ });
1343
+
1344
+ // Add listener for room creation panel's create button click
1345
+ $('#znm-roomCreatorCreateBt').on('click', $.proxy(this._onRoomCreatorCreateBtClick, this));
1346
+
1347
+ // Add listener for room creation panel hide
1348
+ $('#znm-createRoomModal').on('hidden.bs.modal', $.proxy(this._onCreateRoomModalHidden, this));
1349
+
1350
+ // ROOM & USER FILTERING PANELS
1351
+
1352
+ // Setup match expression builder panel for rooms
1353
+ this._roomFilter = document.getElementById('znm-roomFilter');
1354
+ this._roomFilter.title = 'Room Filter Expression Builder';
1355
+ this._roomFilter.predefinedVarNames = _utils_match_properties__WEBPACK_IMPORTED_MODULE_5__["RoomPropertiesData"].propertiesArray;
1356
+ $(this._roomFilter).on(this._roomFilter.EXPRESSION_UPDATED_EVENT, $.proxy(this._onRoomFilterUpdated, this));
1357
+
1358
+ $('#znm-filterRoomBt').on('click', $.proxy(this._onShowRoomFilterBtClick, this));
1359
+ $('#znm-applyRoomFilterCB').on('change', $.proxy(this._onApplyBtChange, this));
1360
+
1361
+ // Setup match expression builder panel for users
1362
+ this._userFilter = document.getElementById('znm-userFilter');
1363
+ this._userFilter.title = 'User Filter Expression Builder';
1364
+ this._userFilter.predefinedVarNames = _utils_match_properties__WEBPACK_IMPORTED_MODULE_5__["UserPropertiesData"].propertiesArray;
1365
+ $(this._userFilter).on(this._userFilter.EXPRESSION_UPDATED_EVENT, $.proxy(this._onUserFilterUpdated, this));
1366
+
1367
+ $('#znm-filterUserBt').on('click', $.proxy(this._onShowUserFilterBtClick, this));
1368
+ $('#znm-applyUserFilterCB').on('change', $.proxy(this._onApplyBtChange, this));
1369
+
1370
+ // MAIN CONTROLS
1371
+
1372
+ $('#znm-monitorBt').on('click', $.proxy(this._onMonitorSelectionBtClick, this));
1373
+ $('#znm-sendMessageBt').on('click', $.proxy(this._onSendAdminMsgBtClick, this));
1374
+ $('#znm-messageIn').on('keyup', $.proxy(this._onSendAdminMsgInKeyUp, this));
1375
+
1376
+ // MONITORING CONTROLS
1377
+
1378
+ $('#znm-closeMonitorBt').on('click', $.proxy(this._onCloseMonitorBtClick, this));
1379
+ $('#znm-editBt').on('click', $.proxy(this._onEditBtClick, this));
1380
+ $('#znm-cancelBt').on('click', $.proxy(this._onCancelBtClick, this));
1381
+ $('#znm-submitBt').on('click', $.proxy(this._onSubmitBtClick, this));
1382
+
1383
+ // Hide edit controls
1384
+ $('#znm-editControls').hide();
1385
+
1386
+ // ZONE MONITOR ---------------------
1387
+
1388
+ // Set reference to user count chart
1389
+ this._userCountChart = document.getElementById('znm-userCountChart');
1390
+
1391
+ // Initialize time range slider
1392
+ this._timeSlider = $('#znm-timeSlider').kendoRangeSlider({
1393
+ min: -24,
1394
+ max: 0,
1395
+ smallStep: 1,
1396
+ largeStep: 0,
1397
+ change: $.proxy(this._onTimeRangeChange, this),
1398
+ tooltip: {
1399
+ template: Object(_components_charts_chart_utils__WEBPACK_IMPORTED_MODULE_7__["getTimeRangeTooltipTemplate"])()
1400
+ },
1401
+ leftDragHandleTitle: 'Drag',
1402
+ rightDragHandleTitle: 'Drag',
1403
+ }).data('kendoRangeSlider');
1404
+
1405
+ // Reset time range on user count chart
1406
+ this._onTimeRangeChange();
1407
+
1408
+ // Add button click listeners
1409
+ $('#znm-reloadWordsBt').on('click', $.proxy(this._onWordsReloadBtClick, this));
1410
+ $('#znm-reloadZoneExtBt').on('click', $.proxy(this._onZoneExtReloadBtClick, this));
1411
+
1412
+ // Initialize extension log grid
1413
+ this._zoneExtLogGrid = $('#znm-zoneExtLogGrid').kendoGrid({
1414
+ dataSource: [],
1415
+ resizable: true,
1416
+ selectable: false,
1417
+ noRecords: {
1418
+ template: 'No entries.'
1419
+ },
1420
+ columns: [
1421
+ {
1422
+ field: 'timestamp',
1423
+ title: 'Timestamp',
1424
+ width: 180
1425
+ },
1426
+ {
1427
+ field: 'level',
1428
+ title: 'Level',
1429
+ width: 100
1430
+ },
1431
+ {
1432
+ field: 'message',
1433
+ title: 'Message',
1434
+ width: 400
1435
+ },
1436
+ ],
1437
+ dataBound: function() {
1438
+ this.content.scrollTop(this.tbody.height()); // Scroll to bottom
1439
+ }
1440
+ }).data('kendoGrid');
1441
+
1442
+ // ROOM MONITOR ---------------------
1443
+
1444
+ // Initialize extension log grid
1445
+ this._roomExtLogGrid = $('#znm-roomExtLogGrid').kendoGrid({
1446
+ dataSource: [],
1447
+ resizable: true,
1448
+ selectable: false,
1449
+ noRecords: {
1450
+ template: 'No entries.'
1451
+ },
1452
+ columns: [
1453
+ {
1454
+ field: 'timestamp',
1455
+ title: 'Timestamp',
1456
+ width: 180
1457
+ },
1458
+ {
1459
+ field: 'level',
1460
+ title: 'Level',
1461
+ width: 100
1462
+ },
1463
+ {
1464
+ field: 'message',
1465
+ title: 'Message',
1466
+ width: 400
1467
+ },
1468
+ ],
1469
+ dataBound: function() {
1470
+ this.content.scrollTop(this.tbody.height()); // Scroll to bottom
1471
+ }
1472
+ }).data('kendoGrid');
1473
+
1474
+ // USER MONITOR ---------------------
1475
+
1476
+ this._kickDelayIn = $('#znm-kickDelayNS').kendoNumericTextBox({
1477
+ min: 0,
1478
+ step: 1,
1479
+ format: '#',
1480
+ placeholder: 'Delay (s)'
1481
+ }).data('kendoNumericTextBox');
1482
+
1483
+ this._banModeDd = $('#znm-banModeDD').kendoDropDownList({
1484
+ dataSource: ['IP', 'NAME'],
1485
+ autoWidth: true,
1486
+ optionLabel: {
1487
+ text: 'Mode'
1488
+ },
1489
+ optionLabelTemplate: '<span class="text-muted">#:text#</span>',
1490
+ }).data('kendoDropDownList');
1491
+
1492
+ this._banDurUnitDd = $('#znm-banDurationUnitDD').kendoDropDownList({
1493
+ autoWidth: true,
1494
+ }).data('kendoDropDownList');
1495
+
1496
+ this._banDurationIn = $('#znm-banDurationNS').kendoNumericTextBox({
1497
+ min: 1,
1498
+ step: 1,
1499
+ format: '#',
1500
+ placeholder: 'Duration'
1501
+ }).data('kendoNumericTextBox');
1502
+
1503
+ this._banDelayIn = $('#znm-banDelayNS').kendoNumericTextBox({
1504
+ min: 0,
1505
+ step: 1,
1506
+ format: '#',
1507
+ placeholder: 'Delay (s)'
1508
+ }).data('kendoNumericTextBox');
1509
+
1510
+ // Add button click listeners
1511
+ $('#znm-kickBt').on('click', $.proxy(this._onKickBtClick, this));
1512
+ $('#znm-banBt').on('click', $.proxy(this._onBanBtClick, this));
1513
+
1514
+ // Charts
1515
+
1516
+ this._packetQueueChart = $('#znm-packetQueueChart').kendoChart({
1517
+ transitions: false,
1518
+ chartArea: {
1519
+ height: 100
1520
+ },
1521
+ legend: {
1522
+ visible: false
1523
+ },
1524
+ seriesDefaults: {
1525
+ type: 'bar',
1526
+ labels: {
1527
+ visible: true,
1528
+ format: '{0}%',
1529
+ background: 'transparent',
1530
+ position: 'insideBase'
1531
+ },
1532
+ gap: .5,
1533
+ spacing: 0,
1534
+ overlay: {
1535
+ gradient: 'none'
1536
+ },
1537
+ border: {
1538
+ width: 0
1539
+ }
1540
+ },
1541
+ series: [
1542
+ {
1543
+ name: 'Packet queue',
1544
+ field: 'value',
1545
+ categoryField: 'category',
1546
+ color: '#FB7D33'
1547
+ }
1548
+ ],
1549
+ valueAxis: {
1550
+ labels: {
1551
+ format: '{0}%'
1552
+ },
1553
+ line: {
1554
+ visible: false
1555
+ },
1556
+ min: 0,
1557
+ max: 100
1558
+ },
1559
+ categoryAxis: {
1560
+ majorGridLines: {
1561
+ visible: false
1562
+ },
1563
+ majorTicks: {
1564
+ visible: false
1565
+ },
1566
+ labels: {
1567
+ visible: false
1568
+ }
1569
+ },
1570
+ tooltip: {
1571
+ visible: false,
1572
+ }
1573
+ }).data('kendoChart');
1574
+
1575
+ this._droppedMsgChart = $('#znm-droppedMsgChart').kendoChart({
1576
+ transitions: false,
1577
+ chartArea: {
1578
+ height: 100
1579
+ },
1580
+ legend: {
1581
+ visible: false
1582
+ },
1583
+ seriesDefaults: {
1584
+ type: 'bar',
1585
+ labels: {
1586
+ visible: true,
1587
+ format: '{0}',
1588
+ background: 'transparent',
1589
+ position: 'insideBase',
1590
+ },
1591
+ gap: .5,
1592
+ spacing: 0,
1593
+ overlay: {
1594
+ gradient: 'none'
1595
+ },
1596
+ border: {
1597
+ width: 0
1598
+ }
1599
+ },
1600
+ series: [
1601
+ {
1602
+ name: 'Dropped messages',
1603
+ field: 'value',
1604
+ categoryField: 'category',
1605
+ color: '#FB7D33'
1606
+ }
1607
+ ],
1608
+ valueAxis: {
1609
+ labels: {
1610
+ format: '{0}'
1611
+ },
1612
+ line: {
1613
+ visible: false
1614
+ },
1615
+ min: 0,
1616
+ },
1617
+ categoryAxis: {
1618
+ majorGridLines: {
1619
+ visible: false
1620
+ },
1621
+ majorTicks: {
1622
+ visible: false
1623
+ },
1624
+ labels: {
1625
+ visible: false
1626
+ }
1627
+ },
1628
+ tooltip: {
1629
+ visible: false,
1630
+ }
1631
+ }).data('kendoChart');
1632
+
1633
+ this._writtenDataChart = $('#znm-writtenDataChart').kendoChart({
1634
+ transitions: false,
1635
+ chartArea: {
1636
+ height: 100
1637
+ },
1638
+ legend: {
1639
+ visible: false
1640
+ },
1641
+ seriesDefaults: {
1642
+ type: 'bar',
1643
+ labels: {
1644
+ visible: true,
1645
+ format: '{0}',
1646
+ background: 'transparent',
1647
+ position: 'insideBase',
1648
+ template: Object(_components_charts_chart_utils__WEBPACK_IMPORTED_MODULE_7__["getWRBytesLabelTemplate"])(),
1649
+ },
1650
+ gap: .5,
1651
+ spacing: 0,
1652
+ overlay: {
1653
+ gradient: 'none'
1654
+ },
1655
+ border: {
1656
+ width: 0
1657
+ }
1658
+ },
1659
+ series: [
1660
+ {
1661
+ name: 'Written data',
1662
+ field: 'value',
1663
+ categoryField: 'category',
1664
+ color: '#FB7D33'
1665
+ }
1666
+ ],
1667
+ valueAxis: {
1668
+ labels: {
1669
+ format: '{0}'
1670
+ },
1671
+ line: {
1672
+ visible: false
1673
+ },
1674
+ min: 0,
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
+ visible: false,
1689
+ }
1690
+ }).data('kendoChart');
1691
+
1692
+ this._readDataChart = $('#znm-readDataChart').kendoChart({
1693
+ transitions: false,
1694
+ chartArea: {
1695
+ height: 100
1696
+ },
1697
+ legend: {
1698
+ visible: false
1699
+ },
1700
+ seriesDefaults: {
1701
+ type: 'bar',
1702
+ labels: {
1703
+ visible: true,
1704
+ format: '{0}',
1705
+ background: 'transparent',
1706
+ position: 'insideBase',
1707
+ template: Object(_components_charts_chart_utils__WEBPACK_IMPORTED_MODULE_7__["getWRBytesLabelTemplate"])(),
1708
+ },
1709
+ gap: .5,
1710
+ spacing: 0,
1711
+ overlay: {
1712
+ gradient: 'none'
1713
+ },
1714
+ border: {
1715
+ width: 0
1716
+ }
1717
+ },
1718
+ series: [
1719
+ {
1720
+ name: 'Read data',
1721
+ field: 'value',
1722
+ categoryField: 'category',
1723
+ color: '#FB7D33'
1724
+ }
1725
+ ],
1726
+ valueAxis: {
1727
+ labels: {
1728
+ format: '{0}'
1729
+ },
1730
+ line: {
1731
+ visible: false
1732
+ },
1733
+ min: 0,
1734
+ },
1735
+ categoryAxis: {
1736
+ majorGridLines: {
1737
+ visible: false
1738
+ },
1739
+ majorTicks: {
1740
+ visible: false
1741
+ },
1742
+ labels: {
1743
+ visible: false
1744
+ }
1745
+ },
1746
+ tooltip: {
1747
+ visible: false,
1748
+ }
1749
+ }).data('kendoChart');
1750
+
1751
+ //-------------------------------
1752
+
1753
+ // Add listener to redraw all charts in case of window resize
1754
+ $(window).on('resize', $.proxy(this._onWindowResize, this));
1755
+ this._onWindowResize(); // Also do it immediately
1756
+
1757
+ // Request data to server
1758
+ this._requestData(true);
1759
+ }
1760
+
1761
+ destroy()
1762
+ {
1763
+ // Call super method
1764
+ super.destroy();
1765
+
1766
+ // Close monitoring
1767
+ this._onCloseMonitorBtClick();
1768
+
1769
+ // Remove doubleclick event listeners
1770
+ this._zoneListBox.wrapper.find('.k-list').off('dblclick');
1771
+ this._roomListBox.wrapper.find('.k-list').off('dblclick');
1772
+ this._userListBox.wrapper.find('.k-list').off('dblclick');
1773
+
1774
+ // Remove other event listeners
1775
+ $('#znm-createRoomBt').off('click');
1776
+ $('#znm-removeRoomBt').off('click');
1777
+ $('#znm-roomCreatorCreateBt').off('click');
1778
+ $('#znm-filterRoomBt').off('click');
1779
+ $('#znm-applyRoomFilterCB').off('change');
1780
+ $('#znm-filterUserBt').off('click');
1781
+ $('#znm-applyUserFilterCB').off('change');
1782
+ $('#znm-monitorBt').off('click');
1783
+ $('#znm-sendMessageBt').off('click');
1784
+ $('#znm-messageIn').off('keyup');
1785
+ $('#znm-closeMonitorBt').off('click');
1786
+ $('#znm-editBt').off('click');
1787
+ $('#znm-cancelBt').off('click');
1788
+ $('#znm-submitBt').off('click');
1789
+ $(window).off('resize');
1790
+ $('#znm-reloadWordsBt').off('click');
1791
+ $('#znm-reloadZoneExtBt').off('click');
1792
+ $('#znm-kickBt').off('click');
1793
+ $('#znm-banBt').off('click');
1794
+
1795
+ // Clear request scheduling
1796
+ clearTimeout(this._requestTimer);
1797
+
1798
+ // Hide room creation panel
1799
+ $('#znm-createRoomModal').modal('hide');
1800
+
1801
+ // Remove room creation panel listener
1802
+ $('#znm-createRoomModal').off('hidden.bs.modal');
1803
+
1804
+ // Remove filter panels listeners
1805
+ $(this._roomFilter).off(this._roomFilter.EXPRESSION_UPDATED_EVENT);
1806
+ $(this._userFilter).off(this._userFilter.EXPRESSION_UPDATED_EVENT);
1807
+ }
1808
+
1809
+ onExtensionCommand(command, data)
1810
+ {
1811
+ // Data received
1812
+ if (command == this.RESP_DATA)
1813
+ {
1814
+ // We have to check if the response id corresponds to the current request id;
1815
+ // if not, the response is discarded as it refers to an outdatet request
1816
+ const responseId = data.getInt('id');
1817
+
1818
+ if (responseId == this._currentRequestId)
1819
+ {
1820
+ // --- ZONES LIST ---
1821
+ if (data.containsKey('zones'))
1822
+ {
1823
+ this._setZonesDataProvider(data.getSFSArray('zones'));
1824
+
1825
+ if (this._selectedZone)
1826
+ this._setScopeLabel();
1827
+ }
1828
+
1829
+ // --- ROOMS LIST ---
1830
+ if (data.containsKey('rooms'))
1831
+ {
1832
+ this._setGroupsDataProvider(data.getUtfStringArray('groups'));
1833
+
1834
+ // -------------------------------
1835
+
1836
+ // If a null rooms list is returned, the zone must have been deleted!
1837
+ if (!data.isNull('rooms'))
1838
+ {
1839
+ this._setRoomsDataProvider(data.getSFSArray('rooms'));
1840
+
1841
+ if (!this._selectedRoom)
1842
+ this._setScopeLabel();
1843
+
1844
+ // -------------------------------
1845
+
1846
+ // Show warning if the rooms list exceeds the server-side limit
1847
+ if (data.containsKey('rSize'))
1848
+ this._showLimitExceededWarning($('#znm-roomListWarning'), 'The received list is incomplete, because its size (' + data.getInt('rSize') + ' Rooms) exceeded this client\'s limit of ' + data.getInt('rLimit') + '; you should refine your search');
1849
+ else
1850
+ this._showLimitExceededWarning($('#znm-roomListWarning'), '');
1851
+ }
1852
+ else
1853
+ {
1854
+ if (this._activePanelType == 'room')
1855
+ {
1856
+ this._accordion.select('[data-item-type="zone"]');
1857
+ this._accordion.expand('[data-item-type="zone"]');
1858
+ this._onZoneSelected();
1859
+ this._onEntitiesPanelChange();
1860
+ }
1861
+ }
1862
+ }
1863
+
1864
+ // --- USERS LIST ---
1865
+ if (data.containsKey('users'))
1866
+ {
1867
+ // If a null users list is returned, the room must have been deleted!
1868
+ if (!data.isNull('users'))
1869
+ {
1870
+ this._setUsersDataProvider(data.getSFSArray('users'));
1871
+
1872
+ // Show warning if the users list exceeds the server-side limit
1873
+ if (data.containsKey('uSize'))
1874
+ this._showLimitExceededWarning($('#znm-userListWarning'), 'The received list is incomplete, because its size (' + data.getInt('uSize') + ' users) exceeds this client\'s limit of ' + data.getInt('uLimit') + '; you should refine your search');
1875
+ else
1876
+ this._showLimitExceededWarning($('#znm-userListWarning'), '');
1877
+ }
1878
+ else
1879
+ {
1880
+ if (this._activePanelType == 'user')
1881
+ {
1882
+ this._accordion.select('[data-item-type="room"]');
1883
+ this._accordion.expand('[data-item-type="room"]');
1884
+ this._onRoomSelected();
1885
+ this._onEntitiesPanelChange();
1886
+ }
1887
+ }
1888
+ }
1889
+
1890
+ // --- MONITORED DATA ---
1891
+ if (data.containsKey('monitored'))
1892
+ {
1893
+ const zone = data.getSFSObject('monitored').getUtfString('zone');
1894
+ const type = data.getSFSObject('monitored').getUtfString('type');
1895
+ const name = data.getSFSObject('monitored').getUtfString('name');
1896
+
1897
+ if (zone == this._monitoredZone && type == this._monitoredType && name == this._monitoredName)
1898
+ {
1899
+ if (!data.getSFSObject('monitored').isNull('params'))
1900
+ {
1901
+ const params = data.getSFSObject('monitored').getSFSArray('params');
1902
+
1903
+ this._setMonitoringInterface();
1904
+
1905
+ // Build interface
1906
+ if (!this._isEditing)
1907
+ {
1908
+ this._interfaceBuilder.buildInterface(params, `znm-${this._monitoredType}TabNavigator`, true);
1909
+
1910
+ if (!this._skipInitTabs)
1911
+ {
1912
+ $(`#znm-${this._monitoredType}TabNavigator #tabs`).scrollingTabs({
1913
+ bootstrapVersion: 4,
1914
+ scrollToTabEdge: true,
1915
+ enableSwiping: true,
1916
+ disableScrollArrowsOnFullyScrolled: true,
1917
+ cssClassLeftArrow: 'fa fa-chevron-left',
1918
+ cssClassRightArrow: 'fa fa-chevron-right'
1919
+ });
1920
+
1921
+ this._skipInitTabs = true;
1922
+
1923
+ // Set first tab panel as active
1924
+ this._interfaceBuilder.activateFirstTabPanel();
1925
+
1926
+ // Redraw time range slider to set its width
1927
+ this._timeSlider.resize();
1928
+
1929
+ // Add listener to redraw all charts on tab change
1930
+ // (to work around an issue with the chart resizing to default width when pane is hidden)
1931
+ $('a[data-toggle="tab"]').on('shown.bs.tab', $.proxy(this._onWindowResize, this));
1932
+ }
1933
+ }
1934
+
1935
+ // Disable categories
1936
+ let disabledCat = (data.getSFSObject('monitored').containsKey('exclude') ? data.getSFSObject('monitored').getUtfStringArray('exclude') : []);
1937
+
1938
+ for (let cat of disabledCat)
1939
+ {
1940
+ let navLink = $(`#znm-${this._monitoredType}TabNavigator #tabs #tab-${cat}`);
1941
+
1942
+ navLink.addClass('disabled');
1943
+ navLink.attr('tabindex', -1);
1944
+ navLink.attr('aria-disabled', true);
1945
+ }
1946
+
1947
+ if (this._monitoredType == this.MONITORED_TYPE_ZONE)
1948
+ this._showZoneTrafficData(data.getSFSObject('monitored').getSFSObject('traffic'));
1949
+
1950
+ if (this._monitoredType == this.MONITORED_TYPE_USER)
1951
+ {
1952
+ // Stats
1953
+ this._showUserStatsData(data.getSFSObject('monitored').getSFSObject('stats'));
1954
+
1955
+ // NPC
1956
+ const isNpc = data.getSFSObject('monitored').getBool('npc');
1957
+
1958
+ // Disable kick and ban buttons
1959
+ $('#znm-kickBt').attr('disabled', isNpc);
1960
+ $('#znm-banBt').attr('disabled', isNpc);
1961
+
1962
+ // Geo-location
1963
+ const geoLocData = data.getSFSObject('monitored').getSFSObject('geoLoc');
1964
+ this._setGeoLocationUI(geoLocData);
1965
+ }
1966
+ }
1967
+ else
1968
+ {
1969
+ // Show alert
1970
+ this.shellCtrl.showSimpleAlert(`The ${Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_4__["capitalizeFirst"])(this._monitoredType)} being monitored is no more available on the server, please select another one.`, false);
1971
+
1972
+ // Cancel monitoring
1973
+ this._onCloseMonitorBtClick();
1974
+ }
1975
+ }
1976
+ }
1977
+ }
1978
+ }
1979
+
1980
+ else if (command == this.RESP_UPDATE_ERROR)
1981
+ {
1982
+ if (data.getUtfString('zone') == this._monitoredZone
1983
+ && data.getUtfString('type') == this._monitoredType
1984
+ && data.getUtfString('name') == this._monitoredName)
1985
+ {
1986
+ // Show alert
1987
+ this.shellCtrl.showSimpleAlert(`Unable to update ${Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_4__["capitalizeFirst"])(this._monitoredType)} settings; the following error was reported: ${data.getUtfString('message')}.`);
1988
+ }
1989
+ }
1990
+
1991
+ else if (command == this.RESP_ROOM_CONFIG)
1992
+ {
1993
+ // Re-enable Create button
1994
+ $('#znm-createRoomBt').attr('disabled', false);
1995
+
1996
+ // Show Room creation panel
1997
+ this._showRoomCreationPanel(data.getSFSArray('settings'));
1998
+ }
1999
+
2000
+ else if (command == this.RESP_ROOM_CONFIG_ERROR)
2001
+ {
2002
+ // Re-enable Create button
2003
+ $('#znm-createRoomBt').attr('disabled', false);
2004
+
2005
+ // Show an alert
2006
+ this.shellCtrl.showSimpleAlert(data.getUtfString('error'));
2007
+ }
2008
+
2009
+ else if (command == this.RESP_ROOM_CREATED)
2010
+ {
2011
+ // Re-enable room creation panel
2012
+ this._enableCreateRoomPanel(true);
2013
+
2014
+ // Hide room creation panel
2015
+ $('#znm-createRoomModal').modal('hide');
2016
+
2017
+ // Update rooms list
2018
+ this._requestData(true);
2019
+ }
2020
+
2021
+ else if (command == this.RESP_ROOM_CREATION_ERROR)
2022
+ {
2023
+ // Display error message
2024
+ $('#znm-createRoomError').text(data.getUtfString('error'));
2025
+ $('#znm-createRoomError').show();
2026
+
2027
+ // Re-enable room creation panel
2028
+ this._enableCreateRoomPanel(true);
2029
+ }
2030
+
2031
+ // Unexpected error received
2032
+ // This error is returned in case something went wrong when retrieving the monitored entity parameters,
2033
+ // so we have to stop requesting the same entity
2034
+ else if (command == this.RESP_UNEXPECTED_ERROR)
2035
+ {
2036
+ // Cancel monitoring
2037
+ this._onCloseMonitorBtClick();
2038
+
2039
+ // Show an alert
2040
+ this.shellCtrl.showSimpleAlert(data.getUtfString('error'));
2041
+ }
2042
+
2043
+ // Extension (Zone or Room) log messages received
2044
+ else if (command == this.RESP_LOG_MESSAGES)
2045
+ {
2046
+ let logEntries = data.getSFSArray('entries');
2047
+
2048
+ for (let e = 0; e < logEntries.size(); e++)
2049
+ {
2050
+ let logEntry = logEntries.getSFSObject(e);
2051
+
2052
+ const logZone = logEntry.getUtfString('zone');
2053
+ const logRoom = logEntry.getUtfString('room');
2054
+
2055
+ // Check if the zone is currently monitored
2056
+ if (this._monitoredZone == logZone)
2057
+ {
2058
+ // console.log(logEntry.getLong('time'))
2059
+ // console.log(new Date(logEntry.getLong('time'))
2060
+
2061
+ let ele = {
2062
+ timestamp: kendo.toString(new Date(logEntry.getLong('time')), 'dd/MM/yyyy HH:mm:ss'),
2063
+ level: logEntry.getUtfString('level'),
2064
+ message: logEntry.getUtfString('msg'),
2065
+ };
2066
+
2067
+ if (this._monitoredType == this.MONITORED_TYPE_ZONE && logRoom == '')
2068
+ {
2069
+ // Add to zone extension log
2070
+ this._addLogEntryToGrid(this._zoneExtLogGrid, ele);
2071
+ }
2072
+ else
2073
+ {
2074
+ if (this._monitoredType == this.MONITORED_TYPE_ROOM && this._monitoredName == logRoom)
2075
+ {
2076
+ // Add to room extension log
2077
+ this._addLogEntryToGrid(this._roomExtLogGrid, ele);
2078
+ }
2079
+ }
2080
+ }
2081
+ }
2082
+ }
2083
+ }
2084
+
2085
+ //---------------------------------
2086
+ // UI EVENT LISTENERS
2087
+ //---------------------------------
2088
+
2089
+ _onUpdateIntervalChange()
2090
+ {
2091
+ // Request data to server
2092
+ this._requestData(false);
2093
+ }
2094
+
2095
+ _onEntitiesPanelChange()
2096
+ {
2097
+ // Set main controls state
2098
+ this._setMainControlsEnabled();
2099
+
2100
+ // Request data to server
2101
+ this._requestData(true);
2102
+ }
2103
+
2104
+ /**
2105
+ * Update the Scope label in the Rooms panel.
2106
+ */
2107
+ _onZoneSelected()
2108
+ {
2109
+ // Clear Room and User lists
2110
+ this._resetRoomList();
2111
+ this._resetUserList();
2112
+
2113
+ // Set scope label
2114
+ this._setScopeLabel();
2115
+
2116
+ // Enable/disable Room and User tools
2117
+ const disabled = this._selectedZone == undefined;
2118
+
2119
+ // (NOTE: this enables/disables whole fieldset; this doesn't affect Kendo DropDown, so we have to do it manually)
2120
+ $('#roomTools').attr('disabled', disabled);
2121
+ $('#userTools').attr('disabled', disabled);
2122
+
2123
+ this._groupsDropDown.enable(!disabled);
2124
+
2125
+ // Set main controls state
2126
+ this._setMainControlsEnabled();
2127
+ }
2128
+
2129
+ /**
2130
+ * Update the Scope label in the Users panel.
2131
+ */
2132
+ _onRoomSelected()
2133
+ {
2134
+ // Clear User list
2135
+ this._resetUserList();
2136
+
2137
+ // Set scope label
2138
+ this._setScopeLabel();
2139
+
2140
+ // Enable Remove button
2141
+ $('#znm-removeRoomBt').attr('disabled', this._selectedRoom == undefined);
2142
+
2143
+ // Set main controls state
2144
+ this._setMainControlsEnabled();
2145
+ }
2146
+
2147
+ /**
2148
+ * Update the scope label in the Users panel.
2149
+ */
2150
+ _onGroupChange()
2151
+ {
2152
+ // Clear Room and User lists
2153
+ this._resetRoomList();
2154
+ this._resetUserList();
2155
+
2156
+ // Set scope label
2157
+ this._setScopeLabel();
2158
+
2159
+ // Request data to server
2160
+ this._requestData(true);
2161
+
2162
+ // Set main controls state
2163
+ this._setMainControlsEnabled();
2164
+ }
2165
+
2166
+ _onUserSelected()
2167
+ {
2168
+ // Set main controls state
2169
+ this._setMainControlsEnabled();
2170
+ }
2171
+
2172
+ /**
2173
+ * Show room creation panel.
2174
+ */
2175
+ _onCreateRoomBtClick()
2176
+ {
2177
+ // Disable Create button
2178
+ $('#znm-createRoomBt').attr('disabled', true);
2179
+
2180
+ // Request default room settings to extension
2181
+ this.sendExtensionRequest(this.REQ_GET_ROOM_CONFIG);
2182
+ }
2183
+
2184
+ /**
2185
+ * Remove existing room.
2186
+ */
2187
+ _onRemoveRoomBtClick()
2188
+ {
2189
+ this.shellCtrl.showConfirmWarning('Are you sure you want to remove the selected Room?', $.proxy(this._onRemoveRemoveConfirm, this));
2190
+ }
2191
+
2192
+ _onRemoveRemoveConfirm()
2193
+ {
2194
+ const selectedZone = this._zoneListBox.dataItem(this._zoneListBox.select());
2195
+ let selectedRoom = this._roomListBox.dataItem(this._roomListBox.select());
2196
+
2197
+ if (selectedRoom)
2198
+ {
2199
+ // Send request to server
2200
+ let params = new SFS2X.SFSObject();
2201
+ params.putUtfString('zone', selectedZone.name);
2202
+ params.putUtfString('room', selectedRoom.name);
2203
+
2204
+ this.sendExtensionRequest(this.REQ_REMOVE_ROOM, params);
2205
+
2206
+ // Request data to server to update the rooms list
2207
+ this._requestData(true);
2208
+ }
2209
+ }
2210
+
2211
+ /**
2212
+ * Remove content of room creation panel.
2213
+ */
2214
+ _onCreateRoomModalHidden(e)
2215
+ {
2216
+ // If a nested modal is opened, its closing causes the parent modal to be closed too (Bootstrap doesn't support nested modals)
2217
+ // As a workaround, here we reset the css class 'modal-open' when the nested modal is closed and skip everything else
2218
+ // In addition we had to use a custom listener on the close/cancel buttons of the nested modal (see config-grid.js for example)
2219
+ if (e.target !== document.getElementById('znm-createRoomModal'))
2220
+ {
2221
+ $('body').addClass('modal-open')
2222
+ return;
2223
+ }
2224
+
2225
+ // Destroy scrolling tabs in room creation panel
2226
+ $('#znm-roomCreatorTabNav #tabs').scrollingTabs('destroy');
2227
+
2228
+ // Remove all tab navigator content
2229
+ this._roomCreationIBuilder.destroyInterface();
2230
+
2231
+ // Remove listener for custom actions triggered by configuration interface
2232
+ $('#znm-roomCreatorTabNav').off('value-set');
2233
+
2234
+ // Reset and hide error message
2235
+ this._resetRoomCreationError();
2236
+ }
2237
+
2238
+ _onConfigValueSet(e) // SAME METHOD DUPLICATED IN zone-configurator.js
2239
+ {
2240
+ const configParam = e.target.data;
2241
+
2242
+ // Handle extension name/type dropdowns update and update the main class dropdown datasource accordingly
2243
+ if (configParam.name == 'extension.name' || configParam.name == 'extension.type' || configParam.name == 'extension.filterClass')
2244
+ {
2245
+ // All involved ConfigFormItems must be available and initialized to proceed
2246
+ const nameFormItem = this._roomCreationIBuilder.getConfigFormItem('extension.name');
2247
+ const typeFormItem = this._roomCreationIBuilder.getConfigFormItem('extension.type');
2248
+ const classFormItem = this._roomCreationIBuilder.getConfigFormItem('extension.file');
2249
+ const filterFormItem = this._roomCreationIBuilder.getConfigFormItem('extension.filterClass');
2250
+
2251
+ if (nameFormItem != null && typeFormItem != null && classFormItem != null && filterFormItem != null)
2252
+ {
2253
+ const source = nameFormItem.data;
2254
+ let classesList = [];
2255
+
2256
+ let data = source.triggerData;
2257
+ for (let i = 0; i < data.size(); i++)
2258
+ {
2259
+ let ext = data.getSFSObject(i);
2260
+
2261
+ if (ext.getUtfString('name') == nameFormItem.data.value && ext.getUtfString('type') == typeFormItem.data.value)
2262
+ {
2263
+ let classes = ext.getUtfString('classesString').split(',');
2264
+
2265
+ if (filterFormItem.data.value == true)
2266
+ {
2267
+ let filteredClasses = classes.filter(_utils_utilities__WEBPACK_IMPORTED_MODULE_4__["filterClassName"]);
2268
+ classes = filteredClasses;
2269
+ }
2270
+
2271
+ classesList = classesList.concat(classes);
2272
+ }
2273
+ }
2274
+
2275
+ let currentClass = classFormItem.data.value;
2276
+
2277
+ // If the classes list doesn't contain the current value, create an empty entry and reset the value
2278
+ if (classesList.indexOf(currentClass) < 0)
2279
+ {
2280
+ if (classesList.length == 0)
2281
+ {
2282
+ classesList.push('');
2283
+ currentClass = '';
2284
+ }
2285
+ else
2286
+ currentClass = classesList[0];
2287
+ }
2288
+
2289
+ let mainClassDropDown = classFormItem._innerWidget;
2290
+ mainClassDropDown.setDataSource(classesList);
2291
+
2292
+ classFormItem.data.value = currentClass;
2293
+ classFormItem._setWidgetValue();
2294
+ }
2295
+ }
2296
+ }
2297
+
2298
+ _onRoomCreatorCreateBtClick()
2299
+ {
2300
+ // Reset and hide error message
2301
+ this._resetRoomCreationError();
2302
+
2303
+ // Check validity
2304
+ if (this._roomCreationIBuilder.checkIsValid())
2305
+ {
2306
+ let changes = this._roomCreationIBuilder.getChangedData();
2307
+
2308
+ if (changes.size() > 0)
2309
+ {
2310
+ // Check the room name against the rooms list (duplicate names not allowed!)
2311
+ if (true)//this._validateNewRoomName(changes))
2312
+ {
2313
+ // Disable room creation panel
2314
+ this._enableCreateRoomPanel(false);
2315
+
2316
+ // Send settings to server instance
2317
+ let params = new SFS2X.SFSObject();
2318
+ params.putSFSArray('settings', changes);
2319
+ params.putUtfString('zName', this._zoneListBox.dataItem(this._zoneListBox.select()).name);
2320
+ params.putBool('notify', $('#znm-notifyClientsCB').prop('checked'));
2321
+
2322
+ // Send settings to extension
2323
+ this.sendExtensionRequest(this.REQ_CREATE_ROOM, params);
2324
+ }
2325
+ else
2326
+ {}
2327
+ }
2328
+ }
2329
+ else
2330
+ {
2331
+ // Show alert
2332
+ this.shellCtrl.showSimpleAlert('Unable to submit Room configuration due to an invalid value; please verify the highlighted form fields in all tabs.', true);
2333
+ }
2334
+ }
2335
+
2336
+ _onShowRoomFilterBtClick()
2337
+ {
2338
+ this._roomFilter.show();
2339
+ }
2340
+
2341
+ _onShowUserFilterBtClick()
2342
+ {
2343
+ this._userFilter.show();
2344
+ }
2345
+
2346
+ _onApplyBtChange()
2347
+ {
2348
+ // Request data to server
2349
+ this._requestData(true);
2350
+ }
2351
+
2352
+ _onRoomFilterUpdated()
2353
+ {
2354
+ // Enable/disable "Apply" checkbox
2355
+ $('#znm-applyRoomFilterCB').attr('disabled', this._roomFilter.filterExpression == null);
2356
+
2357
+ // Request data to server
2358
+ this._requestData(true);
2359
+ }
2360
+
2361
+ _onUserFilterUpdated()
2362
+ {
2363
+ // Enable/disable "Apply" checkbox
2364
+ $('#znm-applyUserFilterCB').attr('disabled', this._userFilter.filterExpression == null);
2365
+
2366
+ // Request data to server
2367
+ this._requestData(true);
2368
+ }
2369
+
2370
+ _onMonitorSelectionBtClick()
2371
+ {
2372
+ if (this._selectedZone)
2373
+ {
2374
+ // Cancel previous monitoring
2375
+ this._onCloseMonitorBtClick();
2376
+
2377
+ let getZoneUserCountHistory = false;
2378
+
2379
+ this._monitoredZone = this._selectedZone.name;
2380
+
2381
+ // Zone must be monitored
2382
+ if (this._activePanelType == 'zone')
2383
+ {
2384
+ this._monitoredType = this.MONITORED_TYPE_ZONE;
2385
+ this._monitoredName = this._monitoredZone;
2386
+
2387
+ getZoneUserCountHistory = true;
2388
+ }
2389
+
2390
+ // Room must be monitored
2391
+ if (this._activePanelType == 'room' && this._selectedRoom != undefined)
2392
+ {
2393
+ this._monitoredType = this.MONITORED_TYPE_ROOM;
2394
+ this._monitoredName = this._selectedRoom.name;
2395
+ }
2396
+
2397
+ // User must be monitored
2398
+ if (this._activePanelType == 'user' && this._selectedUser != undefined)
2399
+ {
2400
+ this._monitoredType = this.MONITORED_TYPE_USER;
2401
+ this._monitoredName = this._selectedUser.name;
2402
+ }
2403
+
2404
+ // Show loading bar
2405
+ this._switchView('znm-loading');
2406
+
2407
+ // Request data to server
2408
+ this._requestData(true, getZoneUserCountHistory);
2409
+ }
2410
+ }
2411
+
2412
+ _onSendAdminMsgInKeyUp(event)
2413
+ {
2414
+ if (event.key !== 'Enter')
2415
+ return;
2416
+
2417
+ event.preventDefault();
2418
+ this._onSendAdminMsgBtClick();
2419
+ }
2420
+
2421
+ _onSendAdminMsgBtClick()
2422
+ {
2423
+ if (this._selectedZone && $('#znm-messageIn').val() != '')
2424
+ {
2425
+ // Build request parameters
2426
+ let params = new SFS2X.SFSObject();
2427
+
2428
+ // Always include zone
2429
+ params.putUtfString('zone', this._selectedZone.name);
2430
+
2431
+ // Send message to room?
2432
+ if (this._activePanelType == 'room' && this._selectedRoom != undefined)
2433
+ params.putUtfString('room', this._selectedRoom.name);
2434
+
2435
+ // Send message to user?
2436
+ if (this._activePanelType == 'user' && this._selectedUser != undefined)
2437
+ params.putUtfString('user', this._selectedUser.name);
2438
+
2439
+ // Add message
2440
+ params.putUtfString('msg', $('#znm-messageIn').val());
2441
+
2442
+ // Send request to extension
2443
+ this.sendExtensionRequest(this.REQ_ADMIN_MSG, params);
2444
+
2445
+ // Clear text input
2446
+ $('#znm-messageIn').val('');
2447
+ }
2448
+ }
2449
+
2450
+ _onCloseMonitorBtClick()
2451
+ {
2452
+ // Save ref. for later usage
2453
+ const monitoredType = this._monitoredType;
2454
+
2455
+ this._monitoredZone = null;
2456
+ this._monitoredType = null;
2457
+ this._monitoredName = null;
2458
+
2459
+ // Clear geolocation UI
2460
+ this._clearGeoLocationUI();
2461
+
2462
+ // Clear log datagrids dataproviders
2463
+ // NOTE: a try-catch is used here because, for an unknown reason, Kendo is throwing an error when resetting the data sources when the module is destroyed
2464
+ try
2465
+ {
2466
+ this._zoneExtLogGrid.setDataSource([]);
2467
+ this._roomExtLogGrid.setDataSource([]);
2468
+ }
2469
+ catch (e) { /* Ignore */ }
2470
+
2471
+ // Leave edit mode
2472
+ this._onCancelBtClick();
2473
+
2474
+ // Rearrange monitoring interface
2475
+ this._setMonitoringInterface();
2476
+
2477
+ // Clear tab navigator
2478
+ this._clearTabs(monitoredType);
2479
+ }
2480
+
2481
+ _onEditBtClick()
2482
+ {
2483
+ if (!this._isEditing)
2484
+ {
2485
+ // Show edit controls
2486
+ $('#znm-editControls').show();
2487
+
2488
+ // Hide edit button
2489
+ $('#znm-editBt').hide();
2490
+
2491
+ // Enable editable fields
2492
+ this._interfaceBuilder.disableInterface(false);
2493
+
2494
+ this._isEditMode = true;
2495
+ }
2496
+ }
2497
+
2498
+ _onCancelBtClick()
2499
+ {
2500
+ if (this._isEditing)
2501
+ {
2502
+ // Hide edit controls
2503
+ $('#znm-editControls').hide();
2504
+
2505
+ // Show edit button
2506
+ $('#znm-editBt').show();
2507
+
2508
+ // Disable editable fields
2509
+ this._interfaceBuilder.disableInterface(true);
2510
+
2511
+ this._isEditMode = false;
2512
+
2513
+ // Hide validation messages
2514
+ this._interfaceBuilder.resetValidation();
2515
+
2516
+ // Request data to update interface (updating suspended in edit mode)
2517
+ this._requestData(true);
2518
+ }
2519
+ }
2520
+
2521
+ _onSubmitBtClick()
2522
+ {
2523
+ if (this._isEditing)
2524
+ {
2525
+ // Check validity
2526
+ if (this._interfaceBuilder.checkIsValid())
2527
+ {
2528
+ let changes = this._interfaceBuilder.getChangedData();
2529
+
2530
+ if (changes.size() > 0)
2531
+ {
2532
+ //console.log(changes.getDump())
2533
+
2534
+ // Send settings to server instance
2535
+ let params = new SFS2X.SFSObject();
2536
+ params.putSFSArray('settings', changes);
2537
+ params.putUtfString('zone', this._monitoredZone);
2538
+
2539
+ if (this._monitoredType == this.MONITORED_TYPE_ROOM)
2540
+ {
2541
+ // Submit room settings
2542
+ params.putUtfString('room', this._monitoredName);
2543
+ this.sendExtensionRequest(this.REQ_SET_ROOM_SETTINGS, params);
2544
+ }
2545
+ else if (this._monitoredType == this.MONITORED_TYPE_USER)
2546
+ {
2547
+ // Submit user settings
2548
+ params.putUtfString('user', this._monitoredName);
2549
+ this.sendExtensionRequest(this.REQ_SET_USER_SETTINGS, params);
2550
+ }
2551
+ else
2552
+ {
2553
+ // Submit zone settings
2554
+ this.sendExtensionRequest(this.REQ_SET_ZONE_SETTINGS, params);
2555
+ }
2556
+
2557
+ // Leave edit mode
2558
+ this._onCancelBtClick();
2559
+ }
2560
+ }
2561
+ else
2562
+ {
2563
+ // Show alert
2564
+ this.shellCtrl.showSimpleAlert('Unable to submit changes due to an invalid value; please verify the highlighted form fields in all tabs.', true);
2565
+ }
2566
+ }
2567
+ }
2568
+
2569
+ _onTimeRangeChange()
2570
+ {
2571
+ let values = this._timeSlider.value();
2572
+
2573
+ if (values[0] == values[1])
2574
+ {
2575
+ if (values[1] == -24)
2576
+ values[1] = -23;
2577
+
2578
+ values[0] = values[1] - 1;
2579
+
2580
+ // Reset the time range slider value (we need to use setTimeout
2581
+ // bacause doing it in the change event listener doesn't redraw the slider)
2582
+ setTimeout($.proxy( function(values) { this._timeSlider.value(values); }, this), 10, values);
2583
+ }
2584
+
2585
+ this._userCountChart.range = values;
2586
+ }
2587
+
2588
+ _onWindowResize()
2589
+ {
2590
+ // Redraw charts
2591
+ this._userCountChart.redraw();
2592
+ this._packetQueueChart.redraw();
2593
+ this._droppedMsgChart.redraw();
2594
+ this._writtenDataChart.redraw();
2595
+ this._readDataChart.redraw();
2596
+
2597
+ // Redraw time range slider
2598
+ this._timeSlider.resize();
2599
+ }
2600
+
2601
+ _onWordsReloadBtClick()
2602
+ {
2603
+ if (this._monitoredType == this.MONITORED_TYPE_ZONE)
2604
+ {
2605
+ // Send request to extension
2606
+ let params = new SFS2X.SFSObject();
2607
+ params.putUtfString('zone', this._monitoredName);
2608
+
2609
+ this.sendExtensionRequest(this.REQ_RELOAD_WORDS, params);
2610
+ }
2611
+ }
2612
+
2613
+ _onZoneExtReloadBtClick()
2614
+ {
2615
+ if (this._monitoredType == this.MONITORED_TYPE_ZONE)
2616
+ {
2617
+ // Send request to extension
2618
+ let params = new SFS2X.SFSObject();
2619
+ params.putUtfString('zone', this._monitoredName);
2620
+
2621
+ this.sendExtensionRequest(this.REQ_RELOAD_ZONE_EXT, params);
2622
+ }
2623
+ }
2624
+
2625
+ _onKickBtClick()
2626
+ {
2627
+ if (this._monitoredType == this.MONITORED_TYPE_USER)
2628
+ {
2629
+ // Send request to extension
2630
+ let params = new SFS2X.SFSObject();
2631
+ params.putUtfString('zone', this._monitoredZone);
2632
+ params.putUtfString('user', this._monitoredName);
2633
+ params.putUtfString('msg', $('#znm-kickMsgIn').val());
2634
+ params.putInt('delay', (this._kickDelayIn.value() != null ? Number(this._kickDelayIn.value()) : this.KICK_BAN_DEFAULT_DELAY));
2635
+
2636
+ this.sendExtensionRequest(this.REQ_KICK_USER, params);
2637
+
2638
+ // Reset message
2639
+ $('#znm-kickMsgIn').val('');
2640
+ }
2641
+ }
2642
+
2643
+ _onBanBtClick()
2644
+ {
2645
+ if (this._monitoredType == this.MONITORED_TYPE_USER)
2646
+ {
2647
+ // Send request to extension
2648
+ let params = new SFS2X.SFSObject();
2649
+ params.putUtfString('zone', this._monitoredZone);
2650
+ params.putUtfString('user', this._monitoredName);
2651
+ params.putUtfString('msg', $('#znm-banMsgIn').val());
2652
+ params.putUtfString('mode', this._banModeDd.select() > 0 ? this._banModeDd.value() : 'NAME');
2653
+ params.putInt('delay', (this._banDelayIn.value() != null ? Number(this._banDelayIn.value()) : this.KICK_BAN_DEFAULT_DELAY));
2654
+
2655
+ let duration = this._banDurationIn.value() != null ? Number(this._banDurationIn.value()) : 1;
2656
+
2657
+ if (this._banDurUnitDd.value() == 'hours')
2658
+ duration = duration * 60;
2659
+ else if (this._banDurUnitDd.value() == 'days')
2660
+ duration = duration * 60 * 24;
2661
+
2662
+ params.putInt('duration', duration);
2663
+
2664
+ this.sendExtensionRequest(this.REQ_BAN_USER, params);
2665
+
2666
+ // Reset message
2667
+ $('#znm-banMsgIn').val('');
2668
+ }
2669
+ }
2670
+
2671
+ //------------------------------------
2672
+ // PRIVATE METHODS
2673
+ //------------------------------------
2674
+
2675
+ _setMonitoringInterface()
2676
+ {
2677
+ const enabled = (this._monitoredType != null && this._monitoredName != null);
2678
+
2679
+ // Show/hide header and footer
2680
+ if (enabled)
2681
+ {
2682
+ this._switchView(`znm-${this._monitoredType}Monitor`);
2683
+
2684
+ // Header title
2685
+ let title = 'Now monitoring ';
2686
+
2687
+ if (this._monitoredType == this.MONITORED_TYPE_USER)
2688
+ title += `User: <strong>${this._monitoredName}</strong> (Zone: ${this._monitoredZone})`;
2689
+ else if (this._monitoredType == this.MONITORED_TYPE_ROOM)
2690
+ title += `Room: <strong>${this._monitoredName}</strong> (Zone: ${this._monitoredZone})`;
2691
+ else
2692
+ title += `Zone: <strong>${this._monitoredZone}</strong>`;
2693
+
2694
+ $('#znm-monitoredHeader').html(title);
2695
+ $('#znm-monitoredFooter').show();
2696
+
2697
+ // Show panel
2698
+ this._switchPanel('znm-mainPanel');
2699
+ }
2700
+ else
2701
+ {
2702
+ this._switchView('znm-select');
2703
+
2704
+ $('#znm-monitoredHeader').html('');
2705
+ $('#znm-monitoredFooter').hide();
2706
+
2707
+ // Show panel
2708
+ this._switchPanel('znm-sidebarPanel');
2709
+ }
2710
+ }
2711
+
2712
+ _switchView(viewId)
2713
+ {
2714
+ document.getElementById('znm-viewstack').selectedElement = document.getElementById(viewId);
2715
+ }
2716
+
2717
+ _switchPanel(panelId)
2718
+ {
2719
+ document.getElementById('znm-view').selectedPanel = document.getElementById(panelId);
2720
+ }
2721
+
2722
+ /**
2723
+ * Build the polling request to be sent to the server, based on the selections and other settings in the accordion.
2724
+ */
2725
+ _requestData(newId = false, getZoneUserCountHistory = false)
2726
+ {
2727
+ // Clear previous request scheduling
2728
+ clearTimeout(this._requestTimer);
2729
+
2730
+ // Check if connection is still available
2731
+ if (this.smartFox.isConnected)
2732
+ {
2733
+ if (newId)
2734
+ this._currentRequestId++;
2735
+
2736
+ // Build request parameters
2737
+ let params = new SFS2X.SFSObject();
2738
+
2739
+ // The updated zones/rooms/users lists are requested if the corresponding panel is displayed only
2740
+ const getZones = (this._activePanelType == 'zone');
2741
+ const getRooms = (this._activePanelType == 'room' && this._selectedZone != undefined);
2742
+ const getUsers = (this._activePanelType == 'user' && this._selectedZone != undefined);
2743
+
2744
+ // --- ZONES ---
2745
+ params.putBool('zones', getZones);
2746
+
2747
+ // ROOMS & USERS
2748
+ if (getRooms || getUsers)
2749
+ {
2750
+ // Common filtering params:
2751
+
2752
+ // a) zone name
2753
+ params.putUtfString('zone', this._selectedZone.name);
2754
+
2755
+ // b) group name
2756
+ params.putUtfString('group', this._selectedGroup.name);
2757
+ }
2758
+
2759
+ // ROOMS
2760
+ params.putBool('rooms', getRooms);
2761
+ if (getRooms)
2762
+ {
2763
+ // Filtering params:
2764
+
2765
+ // c) advanced filtering params
2766
+ if ($('#znm-applyRoomFilterCB').prop('checked') && this._roomFilter.filterExpression != null)
2767
+ params.putSFSArray('rFilter', this._roomFilter.filterExpression.toSFSArray());
2768
+ }
2769
+
2770
+ // USERS
2771
+ params.putBool('users', getUsers);
2772
+ if (getUsers)
2773
+ {
2774
+ // Filtering params:
2775
+
2776
+ // c) room name
2777
+ if (this._selectedRoom)
2778
+ params.putUtfString('room', this._selectedRoom.name);
2779
+
2780
+ // d) advanced filtering params
2781
+ if ($('#znm-applyUserFilterCB').prop('checked') && this._userFilter.filterExpression != null)
2782
+ params.putSFSArray('uFilter', this._userFilter.filterExpression.toSFSArray());
2783
+ }
2784
+
2785
+ // --- CURRENTLY MONITORED DATA ---
2786
+ if (this._monitoredType != null && this._monitoredName != null)
2787
+ {
2788
+ let monitoredObj = this._getBasicMonitoredObject();
2789
+
2790
+ if (this._monitoredType == this.MONITORED_TYPE_ZONE)
2791
+ monitoredObj.putBool('uc', getZoneUserCountHistory);
2792
+
2793
+ params.putSFSObject('monitored', monitoredObj);
2794
+ }
2795
+
2796
+ // Set request id; when a response is received, we check its id matches the current request id: if not, the response is discarded
2797
+ params.putInt('id', this._currentRequestId);
2798
+
2799
+ // Send request to extension
2800
+ this.sendExtensionRequest(this.REQ_GET_DATA, params);
2801
+
2802
+ // Schedule next request
2803
+ this._requestTimer = setTimeout($.proxy(this._requestData, this), Number(this._intervalDropDown.value()) * 1000);
2804
+ }
2805
+ }
2806
+
2807
+ _getBasicMonitoredObject()
2808
+ {
2809
+ let monitoredObj = new SFS2X.SFSObject();
2810
+
2811
+ monitoredObj.putUtfString('zone', this._monitoredZone);
2812
+ monitoredObj.putUtfString('type', this._monitoredType);
2813
+ monitoredObj.putUtfString('name', this._monitoredName);
2814
+
2815
+ return monitoredObj;
2816
+ }
2817
+
2818
+ _setZonesDataProvider(zonesData)
2819
+ {
2820
+ this._setListDataProvider(this._zoneListBox, zonesData, true);
2821
+ }
2822
+
2823
+ _setRoomsDataProvider(roomsData)
2824
+ {
2825
+ this._setListDataProvider(this._roomListBox, roomsData, true);
2826
+
2827
+ // Set Remove button state
2828
+ $('#znm-removeRoomBt').attr('disabled', this._selectedRoom == undefined);
2829
+ }
2830
+
2831
+ _setUsersDataProvider(usersData)
2832
+ {
2833
+ this._setListDataProvider(this._userListBox, usersData);
2834
+ }
2835
+
2836
+ _setListDataProvider(listWidget, listData, countUsers = false)
2837
+ {
2838
+ // Save reference to selected item name
2839
+ // NOTE: as we are substituting the whole data source, we need it to re-select the same item after update
2840
+ let selectedDataItem = listWidget.dataItem(listWidget.select());
2841
+ let selectedDataItemName = selectedDataItem ? selectedDataItem.name : null;
2842
+
2843
+ let dataArray = [];
2844
+
2845
+ // Convert data coming from server
2846
+ for (let i = 0; i < listData.size(); i++)
2847
+ {
2848
+ let itemData = listData.getSFSObject(i);
2849
+
2850
+ let item = {};
2851
+ item.name = itemData.getUtfString('name');
2852
+
2853
+ if (countUsers)
2854
+ item.users = itemData.getInt('users');
2855
+
2856
+ dataArray.push(item);
2857
+ }
2858
+
2859
+ // Create new data source
2860
+ let listDS = new kendo.data.DataSource({
2861
+ data: dataArray,
2862
+ schema: {
2863
+ model: {
2864
+ id: 'name'
2865
+ }
2866
+ },
2867
+ sort: {
2868
+ field: 'name',
2869
+ dir: 'asc'
2870
+ }
2871
+ });
2872
+
2873
+ // Assign data source to list
2874
+ listWidget.setDataSource(listDS);
2875
+
2876
+ // Select again previously selected item
2877
+ if (selectedDataItemName != null)
2878
+ {
2879
+ selectedDataItem = listDS.get(selectedDataItemName);
2880
+
2881
+ if (selectedDataItem)
2882
+ {
2883
+ let selectedElement = listWidget.wrapper.find('[data-uid="' + selectedDataItem.uid + '"]');
2884
+ listWidget.select(selectedElement);
2885
+ }
2886
+ }
2887
+
2888
+ // Reset main control state
2889
+ this._setMainControlsEnabled();
2890
+ }
2891
+
2892
+ _setGroupsDataProvider(groupsData)
2893
+ {
2894
+ // Create Groups array, adding common entries
2895
+ let groupsArray = [
2896
+ this._getGroupObj('', this.ANY_LABEL),
2897
+ this._getGroupObj(this.DEFAULT_GROUP_NAME)
2898
+ ];
2899
+
2900
+ // Save reference to selected group name
2901
+ // NOTE: as we are substituting the whole data source, we need it to re-select the same item after update
2902
+ let selectedDataItem = this._selectedGroup;
2903
+ let selectedDataItemName = selectedDataItem ? selectedDataItem.name : null;
2904
+
2905
+ if (groupsData != null)
2906
+ {
2907
+ for (let i = 0; i < groupsData.length; i++)
2908
+ {
2909
+ if (groupsData[i] != this.DEFAULT_GROUP_NAME) // Default group was added before
2910
+ groupsArray.push(this._getGroupObj(groupsData[i]));
2911
+ }
2912
+ }
2913
+
2914
+ // Create new data source
2915
+ let groupDS = new kendo.data.DataSource({
2916
+ data: groupsArray,
2917
+ schema: {
2918
+ model: {
2919
+ id: 'name'
2920
+ }
2921
+ }
2922
+ });
2923
+
2924
+ // Assign data source to dropdown
2925
+ this._groupsDropDown.setDataSource(groupDS);
2926
+
2927
+ //--------------------------------
2928
+
2929
+ // Select previously selected item
2930
+ selectedDataItem = groupDS.get(selectedDataItemName);
2931
+
2932
+ // If group is not found, select the default one
2933
+ if (selectedDataItem == undefined)
2934
+ selectedDataItem = groupDS.get(this.DEFAULT_GROUP_NAME);
2935
+
2936
+ this._groupsDropDown.select(function(dataItem) {
2937
+ return dataItem.name === selectedDataItem.name;
2938
+ });
2939
+ }
2940
+
2941
+ _getGroupObj(name, label = null)
2942
+ {
2943
+ return {
2944
+ name: name,
2945
+ label: (label != null ? label : name)
2946
+ }
2947
+ }
2948
+
2949
+ /**
2950
+ * Update the Scope label in the Rooms panel and in the Users panel.
2951
+ */
2952
+ _setScopeLabel()
2953
+ {
2954
+ let roomScope = '';
2955
+ let userScope = '';
2956
+
2957
+ if (this._selectedZone)
2958
+ {
2959
+ let zoneName = this._selectedZone.name;
2960
+ roomScope = this._getScopeLabelPart('Zone:', zoneName);
2961
+
2962
+ let selectedGroup = this._selectedGroup;
2963
+ let groupName = (selectedGroup && selectedGroup.name != '') ? selectedGroup.name : this.ANY_LABEL;
2964
+ let roomName = (this._selectedRoom) ? this._selectedRoom.name : this.ANY_LABEL;
2965
+
2966
+ userScope = this._getScopeLabelPart('Zone:', zoneName) + '<br>' + this._getScopeLabelPart('Group:', groupName) + '<br>' + this._getScopeLabelPart('Room:', roomName);
2967
+ }
2968
+
2969
+ $('#znm-roomScopeLb').html(roomScope);
2970
+ $('#znm-userScopeLb').html(userScope);
2971
+ }
2972
+
2973
+ _getScopeLabelPart(label, text)
2974
+ {
2975
+ return `<span class="text-muted">${label}</span> <span>${text}</span>`;
2976
+ }
2977
+
2978
+ _resetRoomList()
2979
+ {
2980
+ this._roomListBox.setDataSource([]);
2981
+
2982
+ // Also disable Remove button
2983
+ $('#znm-removeRoomBt').attr('disabled', true);
2984
+ }
2985
+
2986
+ _resetUserList()
2987
+ {
2988
+ this._userListBox.setDataSource([]);
2989
+ }
2990
+
2991
+ _setMainControlsEnabled()
2992
+ {
2993
+ let enabled = (this._activePanelType == 'zone' && this._selectedZone != undefined)
2994
+ || (this._activePanelType == 'room' && this._selectedRoom != undefined)
2995
+ || (this._activePanelType == 'user' && this._selectedUser != undefined);
2996
+
2997
+ $('#znm-mainControls').attr('disabled', !enabled);
2998
+
2999
+ $('#znm-monitorTargetLb').text(enabled ? Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_4__["capitalizeFirst"])(this._activePanelType) : 'selection');
3000
+ $('#znm-messageIn').attr('placeholder', 'Message to ' + (enabled ? Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_4__["capitalizeFirst"])(this._activePanelType) : 'selection'));
3001
+ }
3002
+
3003
+ _showLimitExceededWarning(icon, title)
3004
+ {
3005
+ icon.attr('title', title);
3006
+
3007
+ if (title != '')
3008
+ icon.removeClass('hidden');
3009
+ else
3010
+ icon.addClass('hidden');
3011
+ }
3012
+
3013
+ _showRoomCreationPanel(roomSettings)
3014
+ {
3015
+ // Build user interface based on passed data
3016
+ this._roomCreationIBuilder.buildInterface(roomSettings, 'znm-roomCreatorTabNav', false, 'rc');
3017
+
3018
+ // Enable scrolling tabs
3019
+ $('#znm-roomCreatorTabNav > #tabs').scrollingTabs({
3020
+ bootstrapVersion: 4,
3021
+ scrollToTabEdge: true,
3022
+ enableSwiping: true,
3023
+ disableScrollArrowsOnFullyScrolled: true,
3024
+ cssClassLeftArrow: 'fa fa-chevron-left',
3025
+ cssClassRightArrow: 'fa fa-chevron-right'
3026
+ });
3027
+
3028
+ // Reset Notify clients checkbox
3029
+ $('#znm-notifyClientsCB').prop('checked', true);
3030
+
3031
+ // Set listener for custom actions triggered by configuration interface
3032
+ $('#znm-roomCreatorTabNav').on('value-set', $.proxy(this._onConfigValueSet, this));
3033
+
3034
+ // Display panel
3035
+ $('#znm-createRoomModal').modal('show');
3036
+
3037
+ // Reset and hide error message
3038
+ this._resetRoomCreationError();
3039
+ }
3040
+
3041
+ _resetRoomCreationError()
3042
+ {
3043
+ // Reset and hide error message
3044
+ $('#znm-createRoomError').text('');
3045
+ $('#znm-createRoomError').hide();
3046
+ }
3047
+
3048
+ _validateNewRoomName(changes)
3049
+ {
3050
+ for (let i = 0; i < changes.size(); i++)
3051
+ {
3052
+ const setting = changes.getSFSObject(i);
3053
+
3054
+ if (setting.containsKey('name') && setting.getUtfString('name') == 'name')
3055
+ {
3056
+ // Get name value
3057
+ const name = setting.getText('value');
3058
+
3059
+ // Get data source
3060
+ const ds = this._roomListBox.dataSource.data();
3061
+
3062
+ // Check if name exists in data source
3063
+ for (let j = 0; j < ds.length; j++)
3064
+ {
3065
+ if (ds[j].name == name)
3066
+ return false;
3067
+ }
3068
+
3069
+ break;
3070
+ }
3071
+ }
3072
+
3073
+ return true;
3074
+ }
3075
+
3076
+ _enableCreateRoomPanel(enable)
3077
+ {
3078
+ let modalElement = $('#znm-createRoomModal');
3079
+
3080
+ // Enable modal close buttons
3081
+ $('button[data-dismiss="modal"]', modalElement).attr('disabled', !enable);
3082
+
3083
+ // Enable create button
3084
+ $('#znm-roomCreatorCreateBt', modalElement).attr('disabled', !enable);
3085
+
3086
+ // Enable checkbox
3087
+ $('#znm-notifyClientsCB', modalElement).attr('disabled', !enable);
3088
+
3089
+ // Enable configuration interface
3090
+ this._roomCreationIBuilder.disableInterface(!enable);
3091
+ }
3092
+
3093
+ _clearTabs(monitoredType)
3094
+ {
3095
+ // Destroy scrolling tabs
3096
+ $(`#znm-${monitoredType}TabNavigator #tabs`).scrollingTabs('destroy');
3097
+
3098
+ // Remove all tab navigator content
3099
+ this._interfaceBuilder.destroyInterface();
3100
+
3101
+ // Set all tab panels as inactive
3102
+ $(`#znm-${monitoredType}TabNavigator #tabPanels .tab-pane`).removeClass('show active');
3103
+
3104
+ // Remove tab change event listener
3105
+ $('a[data-toggle="tab"]').off('shown.bs.tab');
3106
+
3107
+ this._skipInitTabs = false;
3108
+ }
3109
+
3110
+ _showZoneTrafficData(data)
3111
+ {
3112
+ // Build user count monitor history
3113
+ if (data.containsKey('history'))
3114
+ {
3115
+ let userCountData = data.getIntArray('history');
3116
+ let samplingRateMins = data.getInt('rate');
3117
+
3118
+ this._userCountChart.addHistoryEntries(userCountData, samplingRateMins * 60);
3119
+ }
3120
+
3121
+ // Add last user count value
3122
+ this._userCountChart.addEntry(data.getInt('current'));
3123
+ }
3124
+
3125
+ _addLogEntryToGrid(grid, item)
3126
+ {
3127
+ let ds = grid.dataSource;
3128
+
3129
+ // Check items limit
3130
+ if (ds.total() == this.MAX_EXTENSION_LOG_SIZE)
3131
+ ds.remove(ds.at(0));
3132
+
3133
+ ds.add(item);
3134
+ }
3135
+
3136
+ _showUserStatsData(data)
3137
+ {
3138
+ // Packet queue filling %
3139
+ let packetQueue = Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_4__["roundToDecimals"])(data.getFloat('packet'), 2);
3140
+ this._packetQueueChart.setDataSource([{category: 'Queue', value: packetQueue}]);
3141
+
3142
+ // Dropped messages
3143
+ let droppedMsg = data.getInt('dropped');
3144
+ this._droppedMsgChart.setDataSource([{category: 'Dropped', value: droppedMsg}]);
3145
+
3146
+ // Written data amount
3147
+ let writtenDataObj = Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_4__["scaleBytes"])(data.getLong('wBytes'), 2);
3148
+ this._writtenDataChart.setDataSource([{category: 'Written', value: writtenDataObj.value, unit: writtenDataObj.unit}]);
3149
+
3150
+ // Read data amount
3151
+ let readDataObj = Object(_utils_utilities__WEBPACK_IMPORTED_MODULE_4__["scaleBytes"])(data.getLong('rBytes'), 2);
3152
+ this._readDataChart.setDataSource([{category: 'Read', value: readDataObj.value, unit: readDataObj.unit}]);
3153
+ }
3154
+
3155
+ _setGeoLocationUI(geoLocData)
3156
+ {
3157
+ const location = geoLocData.getUtfString('location');
3158
+ const error = geoLocData.getUtfString('error');
3159
+ const latitude = geoLocData.getUtfString('latitude');
3160
+ const longitude = geoLocData.getUtfString('longitude');
3161
+
3162
+ // Show location
3163
+ $('#znm-geoLocationLb').text(location);
3164
+
3165
+ // Log error
3166
+ if (error != '')
3167
+ this.shellCtrl.logMessage(error, 'warn');
3168
+
3169
+ // Enable/disable Show map button
3170
+ if (latitude != '' && longitude != '')
3171
+ {
3172
+ $('#znm-showMapBt').attr('disabled', false);
3173
+
3174
+ const url = `https://www.google.com/maps/search/?api=1&query=${Number(latitude) + ',' + Number(longitude)}`;
3175
+ $('#znm-showMapBt').attr('href', url);
3176
+ }
3177
+ }
3178
+
3179
+ _clearGeoLocationUI()
3180
+ {
3181
+ $('#znm-geoLocationLb').text('');
3182
+ $('#znm-showMapBt').attr('disabled', true);
3183
+ $('#znm-showMapBt').attr('href', '#');
3184
+ }
3185
+
3186
+ //---------------------------------
3187
+ // PRIVATE GETTERS
3188
+ //---------------------------------
3189
+
3190
+ get _activePanelType()
3191
+ {
3192
+ return this._accordion.select().data('itemType');
3193
+ }
3194
+
3195
+ get _selectedZone()
3196
+ {
3197
+ return this._zoneListBox.dataItem(this._zoneListBox.select());
3198
+ }
3199
+
3200
+ get _selectedGroup()
3201
+ {
3202
+ return this._groupsDropDown.dataItem(this._groupsDropDown.select());
3203
+ }
3204
+
3205
+ get _selectedRoom()
3206
+ {
3207
+ return this._roomListBox.dataItem(this._roomListBox.select());
3208
+ }
3209
+
3210
+ get _selectedUser()
3211
+ {
3212
+ return this._userListBox.dataItem(this._userListBox.select());
3213
+ }
3214
+
3215
+ get _isEditing()
3216
+ {
3217
+ return (this._monitoredType != null && this._monitoredName != null && this._isEditMode);
3218
+ }
3219
+ }
3220
+
3221
+ /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! jquery */ "jquery")))
3222
+
3223
+ /***/ }),
3224
+
3225
+ /***/ "./src/utils/match-properties.js":
3226
+ /*!***************************************!*\
3227
+ !*** ./src/utils/match-properties.js ***!
3228
+ \***************************************/
3229
+ /*! exports provided: RoomPropertiesData, UserPropertiesData */
3230
+ /***/ (function(module, __webpack_exports__, __webpack_require__) {
3231
+
3232
+ "use strict";
3233
+ __webpack_require__.r(__webpack_exports__);
3234
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "RoomPropertiesData", function() { return RoomPropertiesData; });
3235
+ /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "UserPropertiesData", function() { return UserPropertiesData; });
3236
+ class RoomPropertiesData
3237
+ {
3238
+ static get LABELS() {
3239
+ let map = new Map();
3240
+
3241
+ map.set(SFS2X.RoomProperties.NAME, 'name');
3242
+ map.set(SFS2X.RoomProperties.GROUP_ID, 'groupId');
3243
+ map.set(SFS2X.RoomProperties.MAX_USERS, 'maxUsers');
3244
+ map.set(SFS2X.RoomProperties.MAX_SPECTATORS, 'maxSpectators');
3245
+ map.set(SFS2X.RoomProperties.USER_COUNT, 'userCount');
3246
+ map.set(SFS2X.RoomProperties.SPECTATOR_COUNT, 'spectatorCount');
3247
+ map.set(SFS2X.RoomProperties.IS_GAME, 'isGame');
3248
+ map.set(SFS2X.RoomProperties.IS_PRIVATE, 'isPrivate');
3249
+ map.set(SFS2X.RoomProperties.HAS_FREE_PLAYER_SLOTS, 'hasFreePlayerSlots');
3250
+ map.set(SFS2X.RoomProperties.IS_TYPE_SFSGAME, 'isSFSGameType');
3251
+
3252
+ return map;
3253
+ }
3254
+
3255
+ static getLabel(propName)
3256
+ {
3257
+ return 'Room.' + RoomPropertiesData.LABELS.get(propName);
3258
+ }
3259
+
3260
+ static get propertiesArray()
3261
+ {
3262
+ const arr = [];
3263
+
3264
+ for (const [key, value] of RoomPropertiesData.LABELS.entries())
3265
+ {
3266
+ arr.push({
3267
+ label: RoomPropertiesData.getLabel(key),
3268
+ value: key
3269
+ });
3270
+ }
3271
+
3272
+ return arr;
3273
+ }
3274
+ }
3275
+
3276
+ class UserPropertiesData
3277
+ {
3278
+ static get LABELS() {
3279
+ let map = new Map();
3280
+
3281
+ map.set(SFS2X.UserProperties.NAME, 'name');
3282
+ map.set(SFS2X.UserProperties.IS_PLAYER, 'isPlayer');
3283
+ map.set(SFS2X.UserProperties.IS_SPECTATOR, 'isSpectator');
3284
+ map.set(SFS2X.UserProperties.IS_NPC, 'isNPC');
3285
+ map.set(SFS2X.UserProperties.PRIVILEGE_ID, 'privilegeId');
3286
+
3287
+ return map;
3288
+ }
3289
+
3290
+ static getLabel(propName)
3291
+ {
3292
+ return 'User.' + UserPropertiesData.LABELS.get(propName);
3293
+ }
3294
+
3295
+ static get propertiesArray()
3296
+ {
3297
+ const arr = [];
3298
+
3299
+ for (const [key, value] of UserPropertiesData.LABELS.entries())
3300
+ {
3301
+ arr.push({
3302
+ label: UserPropertiesData.getLabel(key),
3303
+ value: key
3304
+ });
3305
+ }
3306
+
3307
+ return arr;
3308
+ }
3309
+ }
3310
+
3311
+
3312
+ /***/ })
3313
+
3314
+ }]);
3315
+ //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzZXRzL2pzL2NvcmUvbW9kdWxlcy9tb2R1bGUtMTMuYnVuZGxlLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vYXBwbGljYXRpb24vLi9zcmMvY29tcG9uZW50cy9jaGFydHMvY2hhcnQtdXRpbHMuanMiLCJ3ZWJwYWNrOi8vYXBwbGljYXRpb24vLi9zcmMvY29tcG9uZW50cy9jaGFydHMvdXNlci1jb3VudC1jaGFydC5qcyIsIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9jb21wb25lbnRzL21vZHVsZS1zcGVjaWZpYy9tYXRjaC1leHByZXNzaW9uLWJ1aWxkZXIuanMiLCJ3ZWJwYWNrOi8vYXBwbGljYXRpb24vLi9zcmMvY29tcG9uZW50cy9zaWRlYmFyLWxheW91dC5qcyIsIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy9tb2R1bGVzL3pvbmUtbW9uaXRvci5qcyIsIndlYnBhY2s6Ly9hcHBsaWNhdGlvbi8uL3NyYy91dGlscy9tYXRjaC1wcm9wZXJ0aWVzLmpzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7Ynl0ZXNUb1NpemUsIGtCeXRlc1RvU2l6ZX0gZnJvbSAnLi4vLi4vdXRpbHMvdXRpbGl0aWVzJztcblxuZXhwb3J0IGZ1bmN0aW9uIGdldEZvcm1hdHRlZERhdGVUaW1lKGRhdGUsIGZvcm1hdCA9ICdkZCBNTU0gSEg6bW06c3MnKVxue1xuXHRyZXR1cm4ga2VuZG8udG9TdHJpbmcoZGF0ZSwgZm9ybWF0KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEJhc2ljU2hhcmVkVGVtcGxhdGUodmFsdWVGb3JtYXQgPSAnezB9Jykge1xuXHRyZXR1cm4ga2VuZG8udGVtcGxhdGUoYFxuXHRcdDxkaXYgY2xhc3M9XCJjaGFydC10b29sdGlwLWNhdGVnb3J5XCI+PHN0cm9uZz4jOiBjYXRlZ29yeSAjPC9zdHJvbmc+PC9kaXY+XG5cdFx0IyBmb3IgKHZhciBpID0gMDsgaSA8IHBvaW50cy5sZW5ndGg7IGkrKykgeyAjXG5cdFx0PGRpdj5cblx0XHRcdDxpIGNsYXNzPVwiZmFzIGZhLXNxdWFyZVwiIHN0eWxlPVwiY29sb3I6ICM6IHBvaW50c1tpXS5jb2xvciAjIFwiPjwvaT5cblx0XHRcdCM6IHBvaW50c1tpXS5zZXJpZXMubmFtZSMgOiAjOiBrZW5kby5mb3JtYXQoJyR7dmFsdWVGb3JtYXR9JywgcG9pbnRzW2ldLnZhbHVlKSAjXG5cdFx0PC9kaXY+XG5cdFx0IyB9ICNcblx0YCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRNZW1vcnlTaGFyZWRUZW1wbGF0ZSgpIHtcblx0cmV0dXJuIGZ1bmN0aW9uKGRhdGFJdGVtKSB7XG5cdFx0ZGF0YUl0ZW0uYnl0ZXNUb1NpemUgPSBieXRlc1RvU2l6ZTsgLy8gUGFzcyBieXRlc1RvU2l6ZSB1dGlsaXR5IGZ1bmN0aW9uIHRvIHRlbXBsYXRlXG5cdFx0cmV0dXJuIGtlbmRvLnRlbXBsYXRlKGBcblx0XHRcdDxkaXYgY2xhc3M9XCJjaGFydC10b29sdGlwLWNhdGVnb3J5XCI+PHN0cm9uZz4jOiBjYXRlZ29yeSAjPC9zdHJvbmc+PC9kaXY+XG5cdFx0XHQjIGZvciAodmFyIGkgPSAwOyBpIDwgcG9pbnRzLmxlbmd0aDsgaSsrKSB7ICNcblx0XHRcdDxkaXY+XG5cdFx0XHRcdDxpIGNsYXNzPVwiZmFzIGZhLXNxdWFyZVwiIHN0eWxlPVwiY29sb3I6ICM6IHBvaW50c1tpXS5jb2xvciAjIFwiPjwvaT5cblx0XHRcdFx0IzogcG9pbnRzW2ldLnNlcmllcy5uYW1lIyA6ICM6IGJ5dGVzVG9TaXplKHBvaW50c1tpXS52YWx1ZSkgI1xuXHRcdFx0PC9kaXY+XG5cdFx0XHQjIH0gI1xuXHRcdGApKGRhdGFJdGVtKTtcblx0fTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE1lbW9yeVZhbHVlQXhpc0xhYmVsVGVtcGxhdGUoKSB7XG5cdHJldHVybiBmdW5jdGlvbihkYXRhSXRlbSkge1xuXHRcdGRhdGFJdGVtLmJ5dGVzVG9TaXplID0gYnl0ZXNUb1NpemU7IC8vIFBhc3MgYnl0ZXNUb1NpemUgdXRpbGl0eSBmdW5jdGlvbiB0byB0ZW1wbGF0ZVxuXHRcdHJldHVybiBrZW5kby50ZW1wbGF0ZShgXG5cdFx0XHQjOiBieXRlc1RvU2l6ZSh2YWx1ZSkgI1xuXHRcdGApKGRhdGFJdGVtKTtcblx0fTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE5ldHdvcmtTaGFyZWRUZW1wbGF0ZShjYXRlZ29yeUZvcm1hdCA9ICdkZCBNTU0gSEg6bW06c3MnKSB7XG5cdHJldHVybiBmdW5jdGlvbihkYXRhSXRlbSkge1xuXHRcdGRhdGFJdGVtLmtCeXRlc1RvU2l6ZSA9IGtCeXRlc1RvU2l6ZTsgLy8gUGFzcyBrQnl0ZXNUb1NpemUgdXRpbGl0eSBmdW5jdGlvbiB0byB0ZW1wbGF0ZVxuXHRcdHJldHVybiBrZW5kby50ZW1wbGF0ZShgXG5cdFx0XHQ8ZGl2IGNsYXNzPVwiY2hhcnQtdG9vbHRpcC1jYXRlZ29yeVwiPjxzdHJvbmc+Izoga2VuZG8udG9TdHJpbmcoY2F0ZWdvcnksICcke2NhdGVnb3J5Rm9ybWF0fScpICM8L3N0cm9uZz48L2Rpdj5cblx0XHRcdCMgZm9yICh2YXIgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHsgI1xuXHRcdFx0PGRpdj5cblx0XHRcdFx0PGkgY2xhc3M9XCJmYXMgZmEtc3F1YXJlXCIgc3R5bGU9XCJjb2xvcjogIzogcG9pbnRzW2ldLmNvbG9yICMgXCI+PC9pPlxuXHRcdFx0XHQjOiBwb2ludHNbaV0uc2VyaWVzLm5hbWUjIDogIzoga0J5dGVzVG9TaXplKHBvaW50c1tpXS52YWx1ZSwgMSwgJycsICcvcycpICNcblx0XHRcdDwvZGl2PlxuXHRcdFx0IyB9ICNcblx0XHRgKShkYXRhSXRlbSk7XG5cdH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXROZXR3b3JrVmFsdWVBeGlzTGFiZWxUZW1wbGF0ZSgpIHtcblx0cmV0dXJuIGZ1bmN0aW9uKGRhdGFJdGVtKSB7XG5cdFx0ZGF0YUl0ZW0ua0J5dGVzVG9TaXplID0ga0J5dGVzVG9TaXplOyAvLyBQYXNzIGtCeXRlc1RvU2l6ZSB1dGlsaXR5IGZ1bmN0aW9uIHRvIHRlbXBsYXRlXG5cdFx0cmV0dXJuIGtlbmRvLnRlbXBsYXRlKGBcblx0XHRcdCM6IGtCeXRlc1RvU2l6ZSh2YWx1ZSwgMSwgJycsICcvcycpICNcblx0XHRgKShkYXRhSXRlbSk7XG5cdH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRVc2VyQ291bnRTaGFyZWRUZW1wbGF0ZShjYXRlZ29yeUZvcm1hdCA9ICdkZCBNTU0gSEg6bW06c3MnKSB7XG5cdHJldHVybiBmdW5jdGlvbihkYXRhSXRlbSkge1xuXHRcdHJldHVybiBrZW5kby50ZW1wbGF0ZShgXG5cdFx0XHQ8ZGl2IGNsYXNzPVwiY2hhcnQtdG9vbHRpcC1jYXRlZ29yeVwiPjxzdHJvbmc+Izoga2VuZG8udG9TdHJpbmcoY2F0ZWdvcnksICcke2NhdGVnb3J5Rm9ybWF0fScpICM8L3N0cm9uZz48L2Rpdj5cblx0XHRcdCMgZm9yICh2YXIgaSA9IDA7IGkgPCBwb2ludHMubGVuZ3RoOyBpKyspIHsgI1xuXHRcdFx0PGRpdj5cblx0XHRcdFx0PGkgY2xhc3M9XCJmYXMgZmEtc3F1YXJlXCIgc3R5bGU9XCJjb2xvcjogIzogcG9pbnRzW2ldLmNvbG9yICMgXCI+PC9pPlxuXHRcdFx0XHQjOiBwb2ludHNbaV0uc2VyaWVzLm5hbWUjIDogIzogcG9pbnRzW2ldLnZhbHVlICNcblx0XHRcdDwvZGl2PlxuXHRcdFx0IyB9ICNcblx0XHRgKShkYXRhSXRlbSk7XG5cdH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUaW1lUmFuZ2VUb29sdGlwVGVtcGxhdGUoKSB7XG5cdHJldHVybiBmdW5jdGlvbihkYXRhSXRlbSkge1xuXHRcdGRhdGFJdGVtLmdldFRvb2x0aXBTdHJpbmcgPSBmdW5jdGlvbih2MSwgdjIpIHtcblx0XHRcdGlmICh2MSA9PSB2Milcblx0XHRcdHtcblx0XHRcdFx0aWYgKHYyID09IC0yNClcblx0XHRcdFx0XHR2MiA9IC0yMztcblxuXHRcdFx0XHR2MSA9IHYyIC0gMTtcblx0XHRcdH1cblxuXHRcdFx0bGV0IHN0YXJ0ID0gTWF0aC5hYnModjEpO1xuXHRcdFx0bGV0IGVuZCA9IE1hdGguYWJzKHYyKTtcblxuXHRcdFx0cmV0dXJuIGBGcm9tICR7c3RhcnR9IGhvdXIke3N0YXJ0ICE9IDEgPyAncycgOiAnJ30gYWdvIHRvICR7ZW5kID4gMCA/ICgndG8gJyArIGVuZCArICcgaG91cicgKyAoZW5kICE9IDEgPyAncycgOiAnJykgKyAnIGFnbycpIDogJ25vdyd9YDtcblx0XHR9OyAvLyBQYXNzIHV0aWxpdHkgZnVuY3Rpb24gdG8gdGVtcGxhdGVcblx0XHRyZXR1cm4ga2VuZG8udGVtcGxhdGUoYFxuXHRcdFx0IzogZ2V0VG9vbHRpcFN0cmluZyhzZWxlY3Rpb25TdGFydCwgc2VsZWN0aW9uRW5kKSAjXG5cdFx0YCkoZGF0YUl0ZW0pO1xuXHR9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0V1JCeXRlc0xhYmVsVGVtcGxhdGUoKSB7XG5cdHJldHVybiBmdW5jdGlvbihkYXRhSXRlbSkge1xuXHRcdHJldHVybiBrZW5kby50ZW1wbGF0ZShgXG5cdFx0XHQjOiB2YWx1ZSAjICM6IGRhdGFJdGVtLnVuaXQgI1xuXHRcdGApKGRhdGFJdGVtKTtcblx0fTtcbn1cbiIsImltcG9ydCB7Z2V0VXNlckNvdW50U2hhcmVkVGVtcGxhdGV9IGZyb20gJy4vY2hhcnQtdXRpbHMnO1xuaW1wb3J0ICogYXMgbW9tZW50IGZyb20gJ21vbWVudCc7XG5cbmV4cG9ydCBjbGFzcyBVc2VyQ291bnRDaGFydCBleHRlbmRzIEhUTUxFbGVtZW50XG57XG5cdGNvbnN0cnVjdG9yKClcblx0e1xuXHQgICAgc3VwZXIoKTtcblxuXHRcdC8vIENyZWF0ZSBjaGFydCBodG1sXG5cdFx0bGV0IGNoYXJ0SHRtbCA9ICQoJzxkaXY+Jyk7XG5cdFx0JCh0aGlzKS5hcHBlbmQoY2hhcnRIdG1sKTtcblxuXHRcdC8vIEluaXRpYWxpemUgY2hhcnRcblx0XHR0aGlzLl9jaGFydFdpZGdldCA9IHRoaXMuX2luaXRDaGFydFdpZGdldChjaGFydEh0bWwpO1xuXHR9XG5cblx0X2luaXRDaGFydFdpZGdldChjaGFydEh0bWwpXG5cdHtcblx0XHRyZXR1cm4gY2hhcnRIdG1sLmtlbmRvQ2hhcnQoe1xuXHRcdFx0dHJhbnNpdGlvbnM6IGZhbHNlLFxuXHRcdFx0Y2hhcnRBcmVhOiB7XG5cdFx0XHRcdGhlaWdodDogMjcwLFxuXHRcdFx0XHRiYWNrZ3JvdW5kOiAndHJhbnNwYXJlbnQnXG5cdFx0XHR9LFxuXHQgICAgICAgIGxlZ2VuZDoge1xuXHQgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgc2VyaWVzRGVmYXVsdHM6IHtcblx0ICAgICAgICAgICAgdHlwZTogJ2FyZWEnLFxuXHQgICAgICAgICAgICBsYWJlbHM6IHtcblx0ICAgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlLFxuXHQgICAgICAgICAgICAgICAgZm9ybWF0OiAnezB9Jyxcblx0ICAgICAgICAgICAgICAgIGJhY2tncm91bmQ6ICd0cmFuc3BhcmVudCdcblx0ICAgICAgICAgICAgfSxcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHNlcmllczogW3tcblx0XHRcdFx0bmFtZTogJ1VzZXJzJyxcblx0ICAgICAgICAgICAgZmllbGQ6ICd1c2VycycsXG5cdCAgICAgICAgICAgIGNhdGVnb3J5RmllbGQ6ICd0aW1lJyxcblx0XHRcdFx0Y29sb3I6ICcjZmQ3ZDI0Jyxcblx0XHRcdFx0bGluZToge1xuXHRcdFx0XHRcdHdpZHRoOiAyXG5cdFx0XHRcdH1cblx0ICAgICAgICB9XSxcblx0ICAgICAgICB2YWx1ZUF4aXM6IHtcblx0ICAgICAgICAgICAgbGFiZWxzOiB7XG5cdCAgICAgICAgICAgICAgICBmb3JtYXQ6ICd7MH0nLFxuXHQgICAgICAgICAgICB9LFxuXHQgICAgICAgICAgICBsaW5lOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHRcdFx0XHRtaW46IDAsXG5cdCAgICAgICAgfSxcblx0ICAgICAgICBjYXRlZ29yeUF4aXM6IHtcblx0XHRcdFx0bWFqb3JHcmlkTGluZXM6IHtcblx0ICAgICAgICAgICAgICAgIHZpc2libGU6IHRydWUsXG5cdFx0XHRcdFx0c3RlcDogNjBcblx0ICAgICAgICAgICAgfSxcblx0XHRcdFx0bWFqb3JUaWNrczoge1xuXHRcdFx0XHRcdHZpc2libGU6IHRydWUsXG5cdFx0XHRcdFx0c3RlcDogNjBcblx0XHRcdFx0fSxcblx0XHRcdFx0bGFiZWxzOiB7XG5cdFx0XHRcdFx0dmlzaWJsZTogdHJ1ZSxcblx0XHRcdFx0XHRzdGVwOiA2MFxuXHRcdFx0XHR9LFxuXHRcdFx0XHRiYXNlVW5pdDogJ21pbnV0ZXMnLFxuXHRcdFx0XHR0eXBlOiAnZGF0ZScsXG5cdCAgICAgICAgfSxcblx0ICAgICAgICB0b29sdGlwOiB7XG5cdFx0XHRcdHNoYXJlZDogdHJ1ZSxcblx0ICAgICAgICAgICAgdmlzaWJsZTogdHJ1ZSxcblx0XHRcdFx0c2hhcmVkVGVtcGxhdGU6IGdldFVzZXJDb3VudFNoYXJlZFRlbXBsYXRlKCdkZCBNTU0gSEg6bW0nKSxcblx0XHRcdFx0YmFja2dyb3VuZDogJyNlNGU0ZTQnXG5cdCAgICAgICAgfVxuXHQgICAgfSkuZGF0YSgna2VuZG9DaGFydCcpO1xuXHR9XG5cblx0cmVkcmF3KClcblx0e1xuXHRcdHRoaXMuX2NoYXJ0V2lkZ2V0LnJlZHJhdygpO1xuXHR9XG5cblx0c2V0IHJhbmdlKHZhbHVlcylcblx0e1xuXHRcdHRoaXMuX3JhbmdlID0gdmFsdWVzO1xuXG5cdFx0dGhpcy5fdXBkYXRlWEF4aXNMaW1pdHMoKTtcblx0fVxuXG5cdGdldCByYW5nZSgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fcmFuZ2U7XG5cdH1cblxuXHRhZGRIaXN0b3J5RW50cmllcyh1c2VyQ291bnREYXRhLCBzYW1wbGluZ1JhdGVTZWNvbmRzKVxuXHR7XG5cdFx0bGV0IGRhdGUgPSBuZXcgRGF0ZSgpO1xuXHRcdGxldCBzdGFydCA9IG1vbWVudChkYXRlKTtcblx0XHRzdGFydC5zdWJ0cmFjdCgoc2FtcGxpbmdSYXRlU2Vjb25kcyAqIHVzZXJDb3VudERhdGEubGVuZ3RoKSwgJ3MnKVxuXG5cdFx0bGV0IGRhdGFTb3VyY2UgPSBuZXcga2VuZG8uZGF0YS5EYXRhU291cmNlKCk7XG5cblx0XHRmb3IgKGxldCBpID0gMTsgaSA8IHVzZXJDb3VudERhdGEubGVuZ3RoOyBpKyspXG5cdFx0e1xuXHRcdFx0bGV0IGRhdGUgPSBzdGFydC5jbG9uZSgpO1xuXHRcdFx0ZGF0ZS5hZGQoaSAqIHNhbXBsaW5nUmF0ZVNlY29uZHMsICdzJyk7XG5cblx0XHRcdHRoaXMuYWRkRW50cnkodXNlckNvdW50RGF0YVtpXSwgZGF0YVNvdXJjZSwgZGF0ZS50b0RhdGUoKSwgZmFsc2UpO1xuXHRcdH1cblxuXHRcdC8vIEFzc2lnbiBkYXRhc291cmNlIHRvIGNoYXJ0XG5cdFx0dGhpcy5fY2hhcnRXaWRnZXQuc2V0RGF0YVNvdXJjZShkYXRhU291cmNlKTtcblxuXHRcdC8vIFVwZGF0ZSBheGlzXG5cdFx0dGhpcy5fdXBkYXRlWEF4aXNMaW1pdHMoKTtcblx0fVxuXG5cdGFkZEVudHJ5KHVzZXJDb3VudCwgZGF0YVNvdXJjZSA9IG51bGwsIGRhdGUgPSBudWxsLCB1cGRhdGVBeGlzID0gdHJ1ZSlcblx0e1xuXHRcdGlmIChkYXRlID09IG51bGwpXG5cdFx0XHRkYXRlID0gbmV3IERhdGUoKTtcblxuXHRcdGxldCBuZXdFbnRyeSA9IHtcblx0XHRcdHRpbWU6IGRhdGUsXG5cdFx0XHR1c2VyczogdXNlckNvdW50XG5cdFx0fTtcblxuXHRcdC8vIEFkZCBlbnRyeSB0byBkYXRhIHNvdXJjZVxuXHRcdGlmIChkYXRhU291cmNlID09IG51bGwpXG5cdFx0XHRkYXRhU291cmNlID0gdGhpcy5fZGF0YVNvdXJjZTtcblxuXHRcdGRhdGFTb3VyY2UuYWRkKG5ld0VudHJ5KTtcblxuXHRcdGlmICh1cGRhdGVBeGlzKVxuXHRcdFx0dGhpcy5fdXBkYXRlWEF4aXNMaW1pdHMoKTtcblx0fVxuXG5cdF91cGRhdGVYQXhpc0xpbWl0cygpXG5cdHtcblx0XHRsZXQgZHMgPSB0aGlzLl9kYXRhU291cmNlO1xuXG5cdFx0aWYgKGRzLnRvdGFsKCkgPiAwKVxuXHRcdHtcblx0XHRcdGNvbnN0IGNoYXJ0TWluaW11bSA9IG1vbWVudCh0aGlzLl9sYXN0RGF0ZSkuYWRkKHRoaXMuX3JhbmdlWzBdLCAnaCcpO1xuXHRcdFx0Y29uc3QgY2hhcnRNYXhpbXVtID0gbW9tZW50KHRoaXMuX2xhc3REYXRlKS5hZGQodGhpcy5fcmFuZ2VbMV0sICdoJyk7XG5cblx0XHRcdHRoaXMuX2NoYXJ0V2lkZ2V0Lm9wdGlvbnMuY2F0ZWdvcnlBeGlzLm1pbiA9IGNoYXJ0TWluaW11bS50b0RhdGUoKTtcblx0XHRcdHRoaXMuX2NoYXJ0V2lkZ2V0Lm9wdGlvbnMuY2F0ZWdvcnlBeGlzLm1heCA9IGNoYXJ0TWF4aW11bS50b0RhdGUoKTtcblxuXHRcdFx0dGhpcy5fY2hhcnRXaWRnZXQucmVkcmF3KCk7XG5cdFx0fVxuXHR9XG5cblx0Z2V0IF9kYXRhU291cmNlKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl9jaGFydFdpZGdldC5kYXRhU291cmNlO1xuXHR9XG59XG5cbi8vIERFRklORSBDT01QT05FTlRcbmlmICghd2luZG93LmN1c3RvbUVsZW1lbnRzLmdldCgndXNlci1jb3VudC1jaGFydCcpKVxuXHR3aW5kb3cuY3VzdG9tRWxlbWVudHMuZGVmaW5lKCd1c2VyLWNvdW50LWNoYXJ0JywgVXNlckNvdW50Q2hhcnQpO1xuIiwiZXhwb3J0IGNsYXNzIE1hdGNoRXhwcmVzc2lvbkJ1aWxkZXIgZXh0ZW5kcyBIVE1MRWxlbWVudFxue1xuXHRjb25zdHJ1Y3RvcigpXG5cdHtcblx0ICAgIHN1cGVyKCk7XG5cblx0XHR0aGlzLkVYUFJFU1NJT05fVVBEQVRFRF9FVkVOVCA9ICdleHByZXNzaW9uVXBkYXRlZCc7XG5cblx0XHR0aGlzLl9kaWFsb2cgPSAkKGBcblx0XHRcdDxkaXYgY2xhc3M9XCJtb2RhbFwiIGlkPVwibWF0Y2hFeHByQnVpbGRlck1vZGFsXCIgdGFiaW5kZXg9XCItMVwiIHJvbGU9XCJkaWFsb2dcIiBhcmlhLWxhYmVsbGVkYnk9XCJtYXRjaEV4cHJCdWlsZGVyTW9kYWxUaXRsZVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxuXHRcdFx0XHQ8ZGl2IGNsYXNzPVwibW9kYWwtZGlhbG9nIG1vZGFsLWRpYWxvZy1jZW50ZXJlZCBtb2RhbC1sZ1wiIHJvbGU9XCJkb2N1bWVudFwiPlxuXHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJtb2RhbC1jb250ZW50XCI+XG5cdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwibW9kYWwtaGVhZGVyXCI+XG5cdFx0XHRcdFx0XHRcdDxoNSBjbGFzcz1cIm1vZGFsLXRpdGxlIHRleHQtcHJpbWFyeVwiIGlkPVwibWF0Y2hFeHByQnVpbGRlck1vZGFsVGl0bGVcIj4uLi48L2g1PlxuXHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwibW9kYWwtYm9keSBwLTBcIj5cblx0XHRcdFx0XHRcdFx0PGZvcm0gY2xhc3M9XCJiZy1jb2xvci1kZWZhdWx0IHAtM1wiPlxuXHRcdFx0XHRcdFx0XHRcdDxkaXYgY2xhc3M9XCJkLWlubGluZS1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciByYWRpby1idXR0b24tZ3JvdXAgaW5saW5lLWZvcm0tZ3JvdXBzXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiY3VzdG9tLWNvbnRyb2wgY3VzdG9tLXJhZGlvIGN1c3RvbS1jb250cm9sLWlubGluZSBtci0yXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdDxpbnB1dCB0eXBlPVwicmFkaW9cIiBpZD1cImFuZE9wZXJhdG9yUkJcIiBuYW1lPVwib3BlcmF0b3JSQkdcIiBjbGFzcz1cImN1c3RvbS1jb250cm9sLWlucHV0XCIgdmFsdWU9XCJBTkRcIiBjaGVja2VkIGRpc2FibGVkPlxuXHRcdFx0XHRcdFx0XHRcdFx0XHQ8bGFiZWwgY2xhc3M9XCJjdXN0b20tY29udHJvbC1sYWJlbFwiIGZvcj1cImFuZE9wZXJhdG9yUkJcIj5BTkQ8L2xhYmVsPlxuXHRcdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiY3VzdG9tLWNvbnRyb2wgY3VzdG9tLXJhZGlvIGN1c3RvbS1jb250cm9sLWlubGluZSBtci0yXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdDxpbnB1dCB0eXBlPVwicmFkaW9cIiBpZD1cIm9yT3BlcmF0b3JSQlwiIG5hbWU9XCJvcGVyYXRvclJCR1wiIGNsYXNzPVwiY3VzdG9tLWNvbnRyb2wtaW5wdXRcIiB2YWx1ZT1cIk9SXCIgZGlzYWJsZWQ+XG5cdFx0XHRcdFx0XHRcdFx0XHRcdDxsYWJlbCBjbGFzcz1cImN1c3RvbS1jb250cm9sLWxhYmVsXCIgZm9yPVwib3JPcGVyYXRvclJCXCI+T1I8L2xhYmVsPlxuXHRcdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHRcdFx0PGRpdiBjbGFzcz1cImQtaW5saW5lLWJsb2NrXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiaW5saW5lLWZvcm0tZ3JvdXBzIG15LTFcIj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0PGlucHV0IGlkPVwidmFyTmFtZUNCXCIvPlxuXHRcdFx0XHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiaW5saW5lLWZvcm0tZ3JvdXBzIG15LTFcIj5cblx0XHRcdFx0XHRcdFx0XHRcdFx0PGlucHV0IGlkPVwidHlwZUREXCIgY2xhc3M9XCJtYXRjaFR5cGVEcm9wZG93blwiLz5cblx0XHRcdFx0XHRcdFx0XHRcdFx0PGlucHV0IGlkPVwiY29uZGl0aW9uRERcIiBjbGFzcz1cIm1hdGNoQ29uZGl0aW9uRHJvcGRvd25cIi8+XG5cdFx0XHRcdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiZC1pbmxpbmUgaW5saW5lLWZvcm0tZ3JvdXBzXCI+XG5cdFx0XHRcdFx0XHRcdFx0XHQ8aW5wdXQgaWQ9XCJ2YWx1ZUluXCIgY2xhc3M9XCJrLXRleHRib3ggbXQtMVwiIHBsYWNlaG9sZGVyPVwiVmFsdWVcIi8+XG5cdFx0XHRcdFx0XHRcdFx0XHQ8YnV0dG9uIGlkPVwibWF0Y2hFeHByQWRkQnRcIiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJrLWJ1dHRvbiBrLXNlY29uZGFyeSBtdC0xXCI+PGkgY2xhc3M9XCJmYXMgZmEtcGx1cyBtci0xXCI+PC9pPkFkZDwvYnV0dG9uPlxuXHRcdFx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdFx0XHQ8L2Zvcm0+XG5cblx0XHRcdFx0XHRcdFx0PGRpdiBpZD1cIm1hdGNoRXhwckdyaWRcIiBjbGFzcz1cIm0tM1wiPjwvZGl2PlxuXHRcdFx0XHRcdFx0PC9kaXY+XG5cdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwibW9kYWwtZm9vdGVyIGQtZmxleFwiPlxuXHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiZmxleC1ncm93LTEgdGV4dC1sZWZ0XCI+XG5cdFx0XHRcdFx0XHRcdFx0PGJ1dHRvbiBpZD1cIm1hdGNoRXhwckFwcGx5QnRcIiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJrLWJ1dHRvbiBrLXByaW1hcnkgbXItMlwiPjxpIGNsYXNzPVwiZmFzIGZhLWNoZWNrLWNpcmNsZSBtci0xXCI+PC9pPkFwcGx5PC9idXR0b24+XG5cdFx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdFx0XHQ8ZGl2IGNsYXNzPVwiZmxleC1ncm93LTEgdGV4dC1yaWdodFwiPlxuXHRcdFx0XHRcdFx0XHRcdDxidXR0b24gaWQ9XCJtYXRjaEV4cHJSZW1vdmVCdFwiIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImstYnV0dG9uIGstc2Vjb25kYXJ5XCIgZGlzYWJsZWQ+PGkgY2xhc3M9XCJmYXMgZmEtbWludXMtY2lyY2xlIG1yLTFcIj48L2k+UmVtb3ZlIHNlbGVjdGVkPC9idXR0b24+XG5cdFx0XHRcdFx0XHRcdFx0PGJ1dHRvbiBpZD1cIm1hdGNoRXhwckNsZWFyQnRcIiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJrLWJ1dHRvbiBrLXNlY29uZGFyeVwiPjxpIGNsYXNzPVwiZmFzIGZhLXRpbWVzLWNpcmNsZSBtci0xXCI+PC9pPkNsZWFyIGFsbDwvYnV0dG9uPlxuXHRcdFx0XHRcdFx0XHQ8L2Rpdj5cblx0XHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHQ8L2Rpdj5cblx0XHRcdDwvZGl2PlxuXHRcdGApO1xuXG5cdFx0JCgnI21hdGNoRXhwckFkZEJ0JywgdGhpcy5fZGlhbG9nKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uQWRkQnRDbGljaywgdGhpcykpO1xuXHRcdCQoJyNtYXRjaEV4cHJBcHBseUJ0JywgdGhpcy5fZGlhbG9nKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uQXBwbHlCdENsaWNrLCB0aGlzKSk7XG5cdFx0JCgnI21hdGNoRXhwclJlbW92ZUJ0JywgdGhpcy5fZGlhbG9nKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uUmVtb3ZlQnRDbGljaywgdGhpcykpO1xuXHRcdCQoJyNtYXRjaEV4cHJDbGVhckJ0JywgdGhpcy5fZGlhbG9nKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uQ2xlYXJCdENsaWNrLCB0aGlzKSk7XG5cblx0XHQvLyBJTklUSUFMSVpFIEZPUk0gSVRFTVNcblxuXHRcdHRoaXMuX3Zhck5hbWVDYiA9ICQoJyN2YXJOYW1lQ0InLCB0aGlzLl9kaWFsb2cpLmtlbmRvQ29tYm9Cb3goe1xuXHRcdFx0ZGF0YVRleHRGaWVsZDogJ2xhYmVsJyxcblx0XHRcdGRhdGFWYWx1ZUZpZWxkOiAndmFsdWUnLFxuXHRcdFx0cGxhY2Vob2xkZXI6ICdWYXJpYWJsZSBuYW1lJyxcblx0XHR9KS5kYXRhKCdrZW5kb0NvbWJvQm94Jyk7XG5cblx0XHQvLyBTZXQgdHlwZXMgZHJvcGRvd24gZGF0YSBzb3VyY2Vcblx0XHQvLyBOT1RFOiBpbiBvcmRlciB0byBhdm9pZCBYeHhNYXRjaCBvYmplY3RzIHRvIGJlIHdyYXBwZWQgYnkgS2VuZG8gZGF0YSBzb3VyY2UsIHdlIGhhdmUgdG8gcGFzcyB0aGVtIHVzaW5nIF8gcHJvcGVydHkgbmFtZXNcblx0XHRsZXQgdHlwZURTID0gW107XG5cblx0XHQvLyBCb29sZWFuIC0tLS0tLS0tLS0tLS0tLS1cblx0XHR0eXBlRFMucHVzaCh7XG5cdFx0XHRsYWJlbDogJ0Jvb2xlYW4nLFxuXHRcdFx0X3ZhbHVlOiBTRlMyWC5Cb29sTWF0Y2guRVFVQUxTLFxuXHRcdFx0Y29uZGl0aW9uczogW1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6IFNGUzJYLkJvb2xNYXRjaC5FUVVBTFMuc3ltYm9sLFxuXHRcdFx0XHRcdF92YWx1ZTogU0ZTMlguQm9vbE1hdGNoLkVRVUFMUyxcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGxhYmVsOiBTRlMyWC5Cb29sTWF0Y2guTk9UX0VRVUFMUy5zeW1ib2wsXG5cdFx0XHRcdFx0X3ZhbHVlOiBTRlMyWC5Cb29sTWF0Y2guTk9UX0VRVUFMUyxcblx0XHRcdFx0fVxuXHRcdFx0XVxuXHRcdH0pO1xuXG5cdFx0Ly8gTnVtYmVyIC0tLS0tLS0tLS0tLS0tLS1cblx0XHR0eXBlRFMucHVzaCh7XG5cdFx0XHRsYWJlbDogJ051bWJlcicsXG5cdFx0XHRfdmFsdWU6IFNGUzJYLk51bWJlck1hdGNoLkVRVUFMUyxcblx0XHRcdGNvbmRpdGlvbnM6IFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGxhYmVsOiBTRlMyWC5OdW1iZXJNYXRjaC5FUVVBTFMuc3ltYm9sLFxuXHRcdFx0XHRcdF92YWx1ZTogU0ZTMlguTnVtYmVyTWF0Y2guRVFVQUxTLFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6IFNGUzJYLk51bWJlck1hdGNoLk5PVF9FUVVBTFMuc3ltYm9sLFxuXHRcdFx0XHRcdF92YWx1ZTogU0ZTMlguTnVtYmVyTWF0Y2guTk9UX0VRVUFMUyxcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGxhYmVsOiBTRlMyWC5OdW1iZXJNYXRjaC5HUkVBVEVSX1RIQU4uc3ltYm9sLFxuXHRcdFx0XHRcdF92YWx1ZTogU0ZTMlguTnVtYmVyTWF0Y2guR1JFQVRFUl9USEFOLFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6IFNGUzJYLk51bWJlck1hdGNoLkxFU1NfVEhBTi5zeW1ib2wsXG5cdFx0XHRcdFx0X3ZhbHVlOiBTRlMyWC5OdW1iZXJNYXRjaC5MRVNTX1RIQU4sXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRsYWJlbDogU0ZTMlguTnVtYmVyTWF0Y2guR1JFQVRFUl9USEFOX09SX0VRVUFMX1RPLnN5bWJvbCxcblx0XHRcdFx0XHRfdmFsdWU6IFNGUzJYLk51bWJlck1hdGNoLkdSRUFURVJfVEhBTl9PUl9FUVVBTF9UTyxcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGxhYmVsOiBTRlMyWC5OdW1iZXJNYXRjaC5MRVNTX1RIQU5fT1JfRVFVQUxfVE8uc3ltYm9sLFxuXHRcdFx0XHRcdF92YWx1ZTogU0ZTMlguTnVtYmVyTWF0Y2guTEVTU19USEFOX09SX0VRVUFMX1RPLFxuXHRcdFx0XHR9XG5cdFx0XHRdXG5cdFx0fSk7XG5cblx0XHQvLyBTdHJpbmcgLS0tLS0tLS0tLS0tLS0tLVxuXHRcdHR5cGVEUy5wdXNoKHtcblx0XHRcdGxhYmVsOiAnU3RyaW5nJyxcblx0XHRcdF92YWx1ZTogU0ZTMlguU3RyaW5nTWF0Y2guRVFVQUxTLFxuXHRcdFx0Y29uZGl0aW9uczogW1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6IFNGUzJYLlN0cmluZ01hdGNoLkVRVUFMUy5zeW1ib2wsXG5cdFx0XHRcdFx0X3ZhbHVlOiBTRlMyWC5TdHJpbmdNYXRjaC5FUVVBTFMsXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRsYWJlbDogU0ZTMlguU3RyaW5nTWF0Y2guTk9UX0VRVUFMUy5zeW1ib2wsXG5cdFx0XHRcdFx0X3ZhbHVlOiBTRlMyWC5TdHJpbmdNYXRjaC5OT1RfRVFVQUxTLFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6IFNGUzJYLlN0cmluZ01hdGNoLkNPTlRBSU5TLnN5bWJvbCxcblx0XHRcdFx0XHRfdmFsdWU6IFNGUzJYLlN0cmluZ01hdGNoLkNPTlRBSU5TLFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6IFNGUzJYLlN0cmluZ01hdGNoLlNUQVJUU19XSVRILnN5bWJvbCxcblx0XHRcdFx0XHRfdmFsdWU6IFNGUzJYLlN0cmluZ01hdGNoLlNUQVJUU19XSVRILFxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGFiZWw6IFNGUzJYLlN0cmluZ01hdGNoLkVORFNfV0lUSC5zeW1ib2wsXG5cdFx0XHRcdFx0X3ZhbHVlOiBTRlMyWC5TdHJpbmdNYXRjaC5FTkRTX1dJVEgsXG5cdFx0XHRcdH1cblx0XHRcdF1cblx0XHR9KTtcblxuXHRcdHRoaXMuX3R5cGVEZCA9ICQoJyN0eXBlREQnLCB0aGlzLl9kaWFsb2cpLmtlbmRvRHJvcERvd25MaXN0KHtcblx0XHRcdGRhdGFTb3VyY2U6IHR5cGVEUyxcblx0XHRcdGRhdGFUZXh0RmllbGQ6ICdsYWJlbCcsXG5cdFx0XHRkYXRhVmFsdWVGaWVsZDogJ192YWx1ZScsXG5cdFx0XHRvcHRpb25MYWJlbDoge1xuXHRcdFx0XHRsYWJlbDogJ1R5cGUnLFxuXHRcdFx0XHRfdmFsdWU6ICcnXG5cdFx0XHR9LFxuXHRcdFx0b3B0aW9uTGFiZWxUZW1wbGF0ZTogJzxzcGFuIGNsYXNzPVwidGV4dC1tdXRlZFwiPiM6bGFiZWwjPC9zcGFuPicsXG5cdFx0XHRjaGFuZ2U6ICQucHJveHkoZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICh0aGlzLl90eXBlRGQgJiYgdGhpcy5fdHlwZURkLnNlbGVjdCgpKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGV0IHNlbGVjdGVkVHlwZSA9IHRoaXMuX3R5cGVEZC5kYXRhSXRlbSh0aGlzLl90eXBlRGQuc2VsZWN0KCkpO1xuXHRcdFx0XHRcdHRoaXMuX2NvbmRpdGlvbkRkLnNldERhdGFTb3VyY2Uoc2VsZWN0ZWRUeXBlLmNvbmRpdGlvbnMpO1xuXHRcdFx0XHRcdHRoaXMuX2NvbmRpdGlvbkRkLnNlbGVjdCgxKTtcblx0XHRcdFx0fVxuXHRcdFx0fSwgdGhpcylcblx0XHR9KS5kYXRhKCdrZW5kb0Ryb3BEb3duTGlzdCcpO1xuXG5cdFx0dGhpcy5fY29uZGl0aW9uRGQgPSAkKCcjY29uZGl0aW9uREQnLCB0aGlzLl9kaWFsb2cpLmtlbmRvRHJvcERvd25MaXN0KHtcblx0XHRcdGRhdGFUZXh0RmllbGQ6ICdsYWJlbCcsXG5cdFx0XHRkYXRhVmFsdWVGaWVsZDogJ192YWx1ZScsXG5cdFx0XHRvcHRpb25MYWJlbDoge1xuXHRcdFx0XHRsYWJlbDogJ0NvbmRpdGlvbicsXG5cdFx0XHRcdF92YWx1ZTogJydcblx0XHRcdH0sXG5cdFx0XHRvcHRpb25MYWJlbFRlbXBsYXRlOiAnPHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkXCI+IzpsYWJlbCM8L3NwYW4+Jyxcblx0XHR9KS5kYXRhKCdrZW5kb0Ryb3BEb3duTGlzdCcpO1xuXG5cdFx0dGhpcy5fdmFsdWVJbiA9ICQoJyN2YWx1ZUluJywgdGhpcy5fZGlhbG9nKTtcblxuXHRcdC8vIElOSVRJQUxJWkUgR1JJRFxuXG5cdFx0dGhpcy5fZ3JpZCA9ICQoJyNtYXRjaEV4cHJHcmlkJywgdGhpcy5fZGlhbG9nKS5rZW5kb0dyaWQoe1xuXHRcdFx0ZGF0YVNvdXJjZTogW10sXG5cdFx0XHRyZXNpemFibGU6IHRydWUsXG5cdFx0XHRzZWxlY3RhYmxlOiAncm93Jyxcblx0XHRcdGNoYW5nZTogJC5wcm94eSh0aGlzLl9vbkdyaWRTZWxlY3Rpb25DaGFuZ2UsIHRoaXMpLFxuXHRcdFx0bm9SZWNvcmRzOiB7XG5cdFx0XHRcdHRlbXBsYXRlOiAnTm8gZW50cmllcy4nXG5cdFx0XHR9LFxuXHRcdFx0Y29sdW1uczogW1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0ZmllbGQ6ICdvcGVyYXRvcicsXG5cdFx0XHRcdFx0dGl0bGU6ICdPcGVyYXRvcicsXG5cdFx0XHRcdFx0d2lkdGg6IDkwXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRmaWVsZDogJ2xhYmVsJyxcblx0XHRcdFx0XHR0aXRsZTogJ05hbWUnLFxuXHRcdFx0XHRcdHdpZHRoOiAxMjBcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGZpZWxkOiAndHlwZUxhYmVsJyxcblx0XHRcdFx0XHR0aXRsZTogJ1R5cGUnLFxuXHRcdFx0XHRcdHdpZHRoOiA4NVxuXHRcdFx0XHR9LFxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0ZmllbGQ6ICdzeW1ib2wnLFxuXHRcdFx0XHRcdHRpdGxlOiAnQ29uZGl0aW9uJyxcblx0XHRcdFx0XHR3aWR0aDogOTVcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGZpZWxkOiAndmFsdWUnLFxuXHRcdFx0XHRcdHRpdGxlOiAnVmFsdWUnLFxuXHRcdFx0XHRcdHdpZHRoOiAyMDBcblx0XHRcdFx0fSxcblx0XHRcdF1cblx0XHR9KS5kYXRhKCdrZW5kb0dyaWQnKTtcblx0fVxuXG5cdGdldCB0aXRsZSgpXG5cdHtcblx0XHRyZXR1cm4gJCgnI21hdGNoRXhwckJ1aWxkZXJNb2RhbFRpdGxlJywgdGhpcy5fZGlhbG9nKS50ZXh0KCk7XG5cdH1cblxuXHRzZXQgdGl0bGUodmFsdWUpXG5cdHtcblx0XHQkKCcjbWF0Y2hFeHByQnVpbGRlck1vZGFsVGl0bGUnLCB0aGlzLl9kaWFsb2cpLnRleHQodmFsdWUpO1xuXHR9XG5cblx0Z2V0IHByZWRlZmluZWRWYXJOYW1lcygpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fcHJlZGVmaW5lZFZhck5hbWVzO1xuXHR9XG5cblx0c2V0IHByZWRlZmluZWRWYXJOYW1lcyh2YWx1ZSlcblx0e1xuXHRcdHRoaXMuX3ByZWRlZmluZWRWYXJOYW1lcyA9IHZhbHVlO1xuXG5cdFx0dGhpcy5fdmFyTmFtZUNiLnNldERhdGFTb3VyY2UodmFsdWUpO1xuXHR9XG5cblx0Z2V0IGZpbHRlckV4cHJlc3Npb24oKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX2ZpbHRlckV4cHJlc3Npb247XG5cdH1cblxuXHRzaG93KClcblx0e1xuXHRcdHRoaXMuX2RpYWxvZy5tb2RhbCh7XG5cdFx0XHRiYWNrZHJvcDogJ3N0YXRpYycsXG5cdFx0XHRrZXlib2FyZDogZmFsc2UsXG5cdFx0XHRzaG93OiB0cnVlXG5cdFx0fSk7XG5cdH1cblxuXHRfb25HcmlkU2VsZWN0aW9uQ2hhbmdlKClcblx0e1xuXHRcdGxldCBzZWxlY3RlZFJvd3MgPSB0aGlzLl9ncmlkLnNlbGVjdCgpO1xuXHRcdGxldCBzZWxlY3RlZERhdGFJdGVtcyA9IFtdO1xuXG5cdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3RlZFJvd3MubGVuZ3RoOyBpKyspXG5cdFx0e1xuXHRcdFx0bGV0IGRhdGFJdGVtID0gdGhpcy5fZ3JpZC5kYXRhSXRlbShzZWxlY3RlZFJvd3NbaV0pO1xuXHRcdFx0c2VsZWN0ZWREYXRhSXRlbXMucHVzaChkYXRhSXRlbSk7XG5cdFx0fVxuXG5cdFx0Ly8gRW5hYmxlL2Rpc2FibGUgcmVtb3ZlIGJ1dHRvblxuXHRcdCQoJyNtYXRjaEV4cHJSZW1vdmVCdCcsIHRoaXMuX2RpYWxvZykuYXR0cignZGlzYWJsZWQnLCBzZWxlY3RlZERhdGFJdGVtcy5sZW5ndGggPT0gMCk7XG5cdH1cblxuXHRfb25BZGRCdENsaWNrKClcblx0e1xuXHRcdGlmICh0aGlzLl92YXJOYW1lQ2IudmFsdWUoKSAhPSAnJyAmJiB0aGlzLl90eXBlRGQuc2VsZWN0KCkpXG5cdFx0e1xuXHRcdFx0Ly8gVmFyaWFibGUgbmFtZSBhbmQgbGFiZWxcblx0XHRcdGxldCB2YXJOYW1lLCB2YXJMYWJlbDtcblxuXHRcdFx0aWYgKHRoaXMuX3Zhck5hbWVDYi5zZWxlY3QoKSA+IC0xKVxuXHRcdFx0e1xuXHRcdFx0XHRsZXQgZGF0YUl0ZW0gPSB0aGlzLl92YXJOYW1lQ2IuZGF0YUl0ZW0odGhpcy5fdmFyTmFtZUNiLnNlbGVjdCgpKTtcblx0XHRcdFx0dmFyTmFtZSA9IGRhdGFJdGVtLnZhbHVlO1xuXHRcdFx0XHR2YXJMYWJlbCA9IGRhdGFJdGVtLmxhYmVsO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZVxuXHRcdFx0XHR2YXJOYW1lID0gdmFyTGFiZWwgPSB0aGlzLl92YXJOYW1lQ2IudmFsdWUoKTtcblxuXHRcdFx0Ly8gVmFyaWFibGUgdHlwZSdzIGxhYmVsXG5cdFx0XHRsZXQgdHlwZUxhYmVsID0gdGhpcy5fdHlwZURkLmRhdGFJdGVtKHRoaXMuX3R5cGVEZC5zZWxlY3QoKSkubGFiZWw7XG5cblx0XHRcdC8vIE1hdGNoIGNvbmRpdGlvblxuXHRcdFx0bGV0IGNvbmRpdGlvbiA9IHRoaXMuX2NvbmRpdGlvbkRkLmRhdGFJdGVtKHRoaXMuX2NvbmRpdGlvbkRkLnNlbGVjdCgpKS5fdmFsdWU7XG5cblx0XHRcdC8vIEV4cHJlc3Npb24gb3BlcmF0b3Jcblx0XHRcdGxldCBvcGVyYXRvciA9IHRoaXMuX2dyaWQuZGF0YVNvdXJjZS50b3RhbCgpID4gMCA/ICQoJ2lucHV0W25hbWU9b3BlcmF0b3JSQkddOmNoZWNrZWQnLCB0aGlzLl9kaWFsb2cpLnZhbCgpIDogbnVsbDtcblxuXHRcdFx0Ly8gVmFyaWFibGUgdmFsdWVcblx0XHRcdGxldCB2YWwgPSB0aGlzLl92YWx1ZUluLnZhbCgpO1xuXHRcdFx0bGV0IHZhclZhbHVlO1xuXG5cdFx0XHRpZiAoY29uZGl0aW9uIGluc3RhbmNlb2YgU0ZTMlguQm9vbE1hdGNoKVxuXHRcdFx0XHR2YXJWYWx1ZSA9ICh2YWwgPT0gJ3RydWUnID8gdHJ1ZSA6IGZhbHNlKTtcblx0XHRcdGVsc2UgaWYgKGNvbmRpdGlvbiBpbnN0YW5jZW9mIFNGUzJYLk51bWJlck1hdGNoKVxuXHRcdFx0XHR2YXJWYWx1ZSA9IChpc05hTihOdW1iZXIodmFsKSkgPyAwIDogTnVtYmVyKHZhbCkpO1xuXHRcdFx0ZWxzZVxuXHRcdFx0XHR2YXJWYWx1ZSA9IHZhbDtcblxuXHRcdFx0Ly8gQWRkIGl0ZW0gdG8gZ3JpZFxuXHRcdFx0bGV0IGV4cHJQYXJ0ID0gdGhpcy5fZ2V0RXhwcmVzc2lvblBhcnQodmFyTGFiZWwsIHZhck5hbWUsIHZhclZhbHVlLCB0eXBlTGFiZWwsIGNvbmRpdGlvbiwgb3BlcmF0b3IpO1xuXHRcdFx0dGhpcy5fZ3JpZC5kYXRhU291cmNlLmFkZChleHByUGFydCk7XG5cblx0XHRcdC8vIFJlc2V0IGlucHV0c1xuXHRcdFx0dGhpcy5fdmFyTmFtZUNiLnZhbHVlKCcnKTtcblx0XHRcdHRoaXMuX3ZhbHVlSW4udmFsKCcnKTtcblxuXHRcdFx0Ly8gRW5hYmxlIG9wZXJhdG9yIHJhZGlvIGJ1dHRvbnNcblx0XHRcdHRoaXMuX2VuYWJsZU9wZXJhdG9yUmIodHJ1ZSk7XG5cdFx0fVxuXHR9XG5cblx0X29uQXBwbHlCdENsaWNrKClcblx0e1xuXHRcdC8vIEhpZGUgZGlhbG9nXG5cdFx0dGhpcy5fZGlhbG9nLm1vZGFsKCdoaWRlJyk7XG5cblx0XHQvLyBDbGVhciBncmlkIHNlbGVjdGlvblxuXHRcdHRoaXMuX2dyaWQuY2xlYXJTZWxlY3Rpb24oKTtcblxuXHRcdC8vIEJ1aWxkIGZpbmFsIG1hdGNoIGV4cHJlc3Npb25cblx0XHR0aGlzLl9maWx0ZXJFeHByZXNzaW9uID0gbnVsbDtcblxuXHRcdGlmICh0aGlzLl9ncmlkLmRhdGFTb3VyY2UudG90YWwoKSA+IDApXG5cdFx0e1xuXHRcdFx0bGV0IGV4cFBhcnQgPSB0aGlzLl9ncmlkLmRhdGFTb3VyY2UuYXQoMCk7XG5cdFx0XHR0aGlzLl9maWx0ZXJFeHByZXNzaW9uID0gbmV3IFNGUzJYLk1hdGNoRXhwcmVzc2lvbihleHBQYXJ0Lm5hbWUsIGV4cFBhcnQuX2NvbmRpdGlvbiwgZXhwUGFydC52YWx1ZSk7XG5cblx0XHRcdGZvciAobGV0IGkgPSAxOyBpIDwgdGhpcy5fZ3JpZC5kYXRhU291cmNlLnRvdGFsKCk7IGkrKylcblx0XHRcdHtcblx0XHRcdFx0ZXhwUGFydCA9IHRoaXMuX2dyaWQuZGF0YVNvdXJjZS5hdChpKTtcblxuXHRcdFx0XHRpZiAoZXhwUGFydC5vcGVyYXRvciA9PSBTRlMyWC5Mb2dpY09wZXJhdG9yLkFORC5pZClcblx0XHRcdFx0XHR0aGlzLl9maWx0ZXJFeHByZXNzaW9uID0gdGhpcy5fZmlsdGVyRXhwcmVzc2lvbi5hbmQoZXhwUGFydC5uYW1lLCBleHBQYXJ0Ll9jb25kaXRpb24sIGV4cFBhcnQudmFsdWUpO1xuXHRcdFx0XHRlbHNlIGlmIChleHBQYXJ0Lm9wZXJhdG9yID09IFNGUzJYLkxvZ2ljT3BlcmF0b3IuT1IuaWQpXG5cdFx0XHRcdFx0dGhpcy5fZmlsdGVyRXhwcmVzc2lvbiA9IHRoaXMuX2ZpbHRlckV4cHJlc3Npb24ub3IoZXhwUGFydC5uYW1lLCBleHBQYXJ0Ll9jb25kaXRpb24sIGV4cFBhcnQudmFsdWUpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIEZpcmUgZXZlbnRcblx0XHRsZXQgZXZ0ID0gbmV3IEN1c3RvbUV2ZW50KHRoaXMuRVhQUkVTU0lPTl9VUERBVEVEX0VWRU5ULCB7XG5cdFx0ICAgIFx0ZGV0YWlsOiBudWxsLFxuXHRcdFx0XHRidWJibGVzOiBmYWxzZSxcblx0XHRcdFx0Y2FuY2VsYWJsZTogZmFsc2Vcblx0XHRcdH0pO1xuXG5cdFx0dGhpcy5kaXNwYXRjaEV2ZW50KGV2dCk7XG5cdH1cblxuXHRfb25SZW1vdmVCdENsaWNrKClcblx0e1xuXHRcdGxldCBkYXRhSXRlbSA9IHRoaXMuX2dyaWQuZGF0YUl0ZW0odGhpcy5fZ3JpZC5zZWxlY3QoKSk7XG5cdFx0dGhpcy5fZ3JpZC5kYXRhU291cmNlLnJlbW92ZShkYXRhSXRlbSk7XG5cblx0XHQvLyBDbGVhciBncmlkIHNlbGVjdGlvblxuXHRcdHRoaXMuX2dyaWQuY2xlYXJTZWxlY3Rpb24oKTtcblxuXHRcdGlmICh0aGlzLl9ncmlkLmRhdGFTb3VyY2UudG90YWwoKSA9PSAwKVxuXHRcdHtcblx0XHRcdC8vIERpc2FibGUgb3BlcmF0b3IgcmFkaW8gYnV0dG9uc1xuXHRcdFx0dGhpcy5fZW5hYmxlT3BlcmF0b3JSYihmYWxzZSk7XG5cdFx0fVxuXHRcdGVsc2Vcblx0XHR7XG5cdFx0XHQvLyBSZXNldCBvcGVyYXRvciBvbiBmaXJzdCBlbnRyeVxuXHRcdFx0dGhpcy5fZ3JpZC5kYXRhU291cmNlLmF0KDApLm9wZXJhdG9yID0gbnVsbDtcblx0XHRcdHRoaXMuX2dyaWQucmVmcmVzaCgpO1xuXHRcdH1cblx0fVxuXG5cdF9vbkNsZWFyQnRDbGljaygpXG5cdHtcblx0XHQvLyBSZXNldCBmb3JtXG5cdFx0JCgnI2FuZE9wZXJhdG9yUkInLCB0aGlzLl9kaWFsb2cpLmF0dHIoJ2NoZWNrZWQnLCB0cnVlKTtcblx0XHQkKCcjb3JPcGVyYXRvclJCJywgdGhpcy5fZGlhbG9nKS5hdHRyKCdjaGVja2VkJywgZmFsc2UpO1xuXHRcdHRoaXMuX2VuYWJsZU9wZXJhdG9yUmIoZmFsc2UpO1xuXG5cdFx0dGhpcy5fdmFyTmFtZUNiLnZhbHVlKCcnKTtcblx0XHR0aGlzLl90eXBlRGQuc2VsZWN0KDApO1xuXHRcdHRoaXMuX2NvbmRpdGlvbkRkLnNlbGVjdCgwKTtcblxuXHRcdHRoaXMuX3ZhbHVlSW4udmFsKCcnKTtcblxuXHRcdC8vIENsZWFyIGdyaWQgc2VsZWN0aW9uXG5cdFx0dGhpcy5fZ3JpZC5jbGVhclNlbGVjdGlvbigpO1xuXG5cdFx0Ly8gQ2xlYXIgdGFibGVcblx0XHR0aGlzLl9ncmlkLnNldERhdGFTb3VyY2UoW10pO1xuXHR9XG5cblx0X2dldEV4cHJlc3Npb25QYXJ0KHZhckxhYmVsLCB2YXJOYW1lLCB2YXJWYWx1ZSwgdHlwZUxhYmVsLCBjb25kaXRpb24sIG9wZXJhdG9yKVxuXHR7XG5cdFx0cmV0dXJuIHtcblx0XHRcdCdsYWJlbCc6IHZhckxhYmVsLFxuXHRcdFx0J25hbWUnOiB2YXJOYW1lLFxuXHRcdFx0J3ZhbHVlJzogdmFyVmFsdWUsXG5cdFx0XHQndHlwZUxhYmVsJzogdHlwZUxhYmVsLFxuXHRcdFx0J3N5bWJvbCc6IGNvbmRpdGlvbi5zeW1ib2wsXG5cdFx0XHQnb3BlcmF0b3InOiBvcGVyYXRvcixcblx0XHRcdCdfY29uZGl0aW9uJzogY29uZGl0aW9uLFxuXHRcdH07XG5cdH1cblxuXHRfZW5hYmxlT3BlcmF0b3JSYihlbmFibGUpXG5cdHtcblx0XHQkKCcjYW5kT3BlcmF0b3JSQicsIHRoaXMuX2RpYWxvZykuYXR0cignZGlzYWJsZWQnLCAhZW5hYmxlKTtcblx0XHQkKCcjb3JPcGVyYXRvclJCJywgdGhpcy5fZGlhbG9nKS5hdHRyKCdkaXNhYmxlZCcsICFlbmFibGUpO1xuXHR9XG59XG5cbi8vIERFRklORSBDT01QT05FTlRcbmlmICghd2luZG93LmN1c3RvbUVsZW1lbnRzLmdldCgnbWF0Y2gtZXhwcmVzc2lvbi1idWlsZGVyJykpXG5cdHdpbmRvdy5jdXN0b21FbGVtZW50cy5kZWZpbmUoJ21hdGNoLWV4cHJlc3Npb24tYnVpbGRlcicsIE1hdGNoRXhwcmVzc2lvbkJ1aWxkZXIpO1xuIiwiZXhwb3J0IGNsYXNzIFNpZGViYXJMYXlvdXQgZXh0ZW5kcyBIVE1MRWxlbWVudFxue1xuXHRjb25zdHJ1Y3RvcigpXG5cdHtcblx0ICAgIHN1cGVyKCk7XG5cblx0XHQvLyBBdHRhY2ggYSBzaGFkb3cgcm9vdFxuXHRcdGNvbnN0IHNoYWRvd1Jvb3QgPSB0aGlzLmF0dGFjaFNoYWRvdyh7bW9kZTogJ29wZW4nfSk7XG5cdFx0c2hhZG93Um9vdC5pbm5lckhUTUwgPSBgXG5cdFx0XHQ8c3R5bGU+XG5cdFx0XHRcdDpob3N0IHtcblx0XHRcdFx0XHRkaXNwbGF5OiBmbGV4O1xuXHRcdFx0XHRcdGZsZXgtZGlyZWN0aW9uOiByb3c7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRAbWVkaWEgKG1heC13aWR0aDogNTc1Ljk4cHgpIHtcblx0XHRcdFx0XHQ6aG9zdCguc3BsaXQteHMpIDo6c2xvdHRlZCg6bm90KFthcmlhLXNlbGVjdGVkPVwidHJ1ZVwiXSkpIHtcblx0XHRcdFx0XHRcdGRpc3BsYXk6IG5vbmUgIWltcG9ydGFudDtcblx0XHRcdFx0ICAgIH1cblxuXHRcdFx0XHRcdDpob3N0KC5zcGxpdC14cykgOjpzbG90dGVkKFthcmlhLXNlbGVjdGVkPVwidHJ1ZVwiXSkge1xuXHRcdFx0XHRcdFx0ZmxleC1ncm93OiAxO1xuXHRcdFx0XHQgICAgfVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0QG1lZGlhIChtYXgtd2lkdGg6IDc2Ny45OHB4KSB7XG5cdFx0XHRcdFx0Omhvc3QoLnNwbGl0LXNtKSA6OnNsb3R0ZWQoOm5vdChbYXJpYS1zZWxlY3RlZD1cInRydWVcIl0pKSB7XG5cdFx0XHRcdFx0XHRkaXNwbGF5OiBub25lICFpbXBvcnRhbnQ7XG5cdFx0XHRcdCAgICB9XG5cblx0XHRcdFx0XHQ6aG9zdCguc3BsaXQtc20pIDo6c2xvdHRlZChbYXJpYS1zZWxlY3RlZD1cInRydWVcIl0pIHtcblx0XHRcdFx0XHRcdGZsZXgtZ3JvdzogMTtcblx0XHRcdFx0ICAgIH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdEBtZWRpYSAobWF4LXdpZHRoOiA5OTEuOThweCkge1xuXHRcdFx0XHRcdDpob3N0KC5zcGxpdC1tZCkgOjpzbG90dGVkKDpub3QoW2FyaWEtc2VsZWN0ZWQ9XCJ0cnVlXCJdKSkge1xuXHRcdFx0XHRcdFx0ZGlzcGxheTogbm9uZSAhaW1wb3J0YW50O1xuXHRcdFx0XHQgICAgfVxuXG5cdFx0XHRcdFx0Omhvc3QoLnNwbGl0LW1kKSA6OnNsb3R0ZWQoW2FyaWEtc2VsZWN0ZWQ9XCJ0cnVlXCJdKSB7XG5cdFx0XHRcdFx0XHRmbGV4LWdyb3c6IDE7XG5cdFx0XHRcdCAgICB9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRAbWVkaWEgKG1heC13aWR0aDogMTE5OS45OHB4KSB7XG5cdFx0XHRcdFx0Omhvc3QoLnNwbGl0LWxnKSA6OnNsb3R0ZWQoOm5vdChbYXJpYS1zZWxlY3RlZD1cInRydWVcIl0pKSB7XG5cdFx0XHRcdFx0XHRkaXNwbGF5OiBub25lICFpbXBvcnRhbnQ7XG5cdFx0XHRcdCAgICB9XG5cblx0XHRcdFx0XHQ6aG9zdCguc3BsaXQtbGcpIDo6c2xvdHRlZChbYXJpYS1zZWxlY3RlZD1cInRydWVcIl0pIHtcblx0XHRcdFx0XHRcdGZsZXgtZ3JvdzogMTtcblx0XHRcdFx0ICAgIH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC5zaWRlLWNvbDo6c2xvdHRlZCgqKSB7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQubWFpbi1jb2w6OnNsb3R0ZWQoKikge1xuXHRcdFx0XHRcdGZsZXgtZ3JvdzogMTtcblx0XHRcdFx0fVxuXHRcdFx0PC9zdHlsZT5cblxuXHRcdFx0PHNsb3QgY2xhc3M9XCJzaWRlLWNvbFwiIG5hbWU9XCJzaWRlLWNvbHVtblwiPjwvc2xvdD5cblx0XHRcdDxzbG90IGNsYXNzPVwibWFpbi1jb2xcIiBuYW1lPVwibWFpbi1jb2x1bW5cIj48L3Nsb3Q+XG5cdFx0YDtcblxuXHRcdC8vIFNldCBpbml0aWFsIHNlbGVjdGlvblxuXHRcdHRoaXMuc2VsZWN0ZWRJbmRleCA9IDA7XG5cdH1cblxuXHRnZXQgc2VsZWN0ZWRQYW5lbCgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fc2VsZWN0ZWRQYW5lbDtcblx0fVxuXG5cdHNldCBzZWxlY3RlZFBhbmVsKGVsZW1lbnQpIC8vICdzaWRlJyBvciAnbWFpbidcblx0e1xuXHRcdGlmIChlbGVtZW50ICE9IG51bGwgJiYgZWxlbWVudC5wYXJlbnROb2RlID09IHRoaXMpXG5cdFx0e1xuXHRcdFx0dGhpcy5fc2VsZWN0ZWRQYW5lbCA9IGVsZW1lbnQ7XG5cblx0XHRcdGZvciAobGV0IGVsZW1lbnQgb2YgdGhpcy5jaGlsZHJlbilcblx0XHRcdHtcblx0XHRcdFx0aWYgKGVsZW1lbnQgPT0gdGhpcy5fc2VsZWN0ZWRQYW5lbClcblx0XHRcdFx0XHRlbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1zZWxlY3RlZCcsICd0cnVlJyk7XG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRlbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1zZWxlY3RlZCcpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlXG5cdFx0e1xuXHRcdFx0Y29uc29sZS5lcnJvcignRWxlbWVudCBpcyBub3QgYSBjaGlsZCBvZiBTaWRlYmFyTGF5b3V0Jyk7XG5cdFx0fVxuXHR9XG5cblx0Z2V0IHNlbGVjdGVkSW5kZXgoKVxuXHR7XG5cdFx0cmV0dXJuIEFycmF5LmZyb20odGhpcy5jaGlsZHJlbikuaW5kZXhPZih0aGlzLl9zZWxlY3RlZFBhbmVsKTtcblx0fVxuXG5cdHNldCBzZWxlY3RlZEluZGV4KGluZGV4KVxuXHR7XG5cdFx0aWYgKHRoaXMuY2hpbGRyZW4ubGVuZ3RoID4gMClcblx0XHR7XG5cdFx0XHRpZiAodGhpcy5jaGlsZHJlbltpbmRleF0gPT0gbnVsbClcblx0XHRcdHtcblx0XHRcdFx0Y29uc29sZS5lcnJvcignSW52YWxpZCBTaWRlYmFyTGF5b3V0IGluZGV4Jyk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0bGV0IGVsZW1lbnQgPSB0aGlzLmNoaWxkcmVuW2luZGV4XTtcblx0XHRcdHRoaXMuc2VsZWN0ZWRQYW5lbCA9IGVsZW1lbnQ7XG5cdFx0fVxuXHR9XG59XG5cbi8vIERFRklORSBDT01QT05FTlRcbmlmICghd2luZG93LmN1c3RvbUVsZW1lbnRzLmdldCgnc2lkZWJhci1sYXlvdXQnKSlcblx0d2luZG93LmN1c3RvbUVsZW1lbnRzLmRlZmluZSgnc2lkZWJhci1sYXlvdXQnLCBTaWRlYmFyTGF5b3V0KTtcbiIsImltcG9ydCB7QmFzZU1vZHVsZX0gZnJvbSAnLi9iYXNlLW1vZHVsZSc7XG5pbXBvcnQge1NpZGViYXJMYXlvdXR9IGZyb20gJy4uL2NvbXBvbmVudHMvc2lkZWJhci1sYXlvdXQnO1xuaW1wb3J0IHtNYXRjaEV4cHJlc3Npb25CdWlsZGVyfSBmcm9tICcuLi9jb21wb25lbnRzL21vZHVsZS1zcGVjaWZpYy9tYXRjaC1leHByZXNzaW9uLWJ1aWxkZXInO1xuaW1wb3J0IHtDb25maWdJbnRlcmZhY2VCdWlsZGVyfSBmcm9tICcuLi91dGlscy91aWJ1aWxkZXIvY29uZmlnLWludGVyZmFjZS1idWlsZGVyJztcbmltcG9ydCB7Y2FwaXRhbGl6ZUZpcnN0LCBmaWx0ZXJDbGFzc05hbWUsIHJvdW5kVG9EZWNpbWFscywgc2NhbGVCeXRlc30gZnJvbSAnLi4vdXRpbHMvdXRpbGl0aWVzJztcbmltcG9ydCB7Um9vbVByb3BlcnRpZXNEYXRhLFVzZXJQcm9wZXJ0aWVzRGF0YX0gZnJvbSAnLi4vdXRpbHMvbWF0Y2gtcHJvcGVydGllcyc7XG5pbXBvcnQge1VzZXJDb3VudENoYXJ0fSBmcm9tICcuLi9jb21wb25lbnRzL2NoYXJ0cy91c2VyLWNvdW50LWNoYXJ0JztcbmltcG9ydCB7Z2V0VGltZVJhbmdlVG9vbHRpcFRlbXBsYXRlLCBnZXRXUkJ5dGVzTGFiZWxUZW1wbGF0ZX0gZnJvbSAnLi4vY29tcG9uZW50cy9jaGFydHMvY2hhcnQtdXRpbHMnO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBab25lTW9uaXRvciBleHRlbmRzIEJhc2VNb2R1bGVcbntcblx0Y29uc3RydWN0b3IoKVxuXHR7XG5cdCAgICBzdXBlcignem9uZU1vbml0b3InKTtcblxuXHRcdHRoaXMuTU9OSVRPUkVEX1RZUEVfWk9ORSA9ICd6b25lJztcblx0XHR0aGlzLk1PTklUT1JFRF9UWVBFX1JPT00gPSAncm9vbSc7XG5cdFx0dGhpcy5NT05JVE9SRURfVFlQRV9VU0VSID0gJ3VzZXInO1xuXG5cdFx0dGhpcy5BTllfTEFCRUwgPSAnW2FueV0nO1xuXHRcdHRoaXMuREVGQVVMVF9HUk9VUF9OQU1FID0gJ2RlZmF1bHQnO1xuXHRcdHRoaXMuTUFYX0VYVEVOU0lPTl9MT0dfU0laRSA9IDMwMDtcblx0XHR0aGlzLktJQ0tfQkFOX0RFRkFVTFRfREVMQVkgPSA1O1xuXG5cdFx0Ly8gT3V0Z29pbmcgcmVxdWVzdHNcblx0XHR0aGlzLlJFUV9HRVRfREFUQSA9ICdnZXREYXRhJztcblx0XHR0aGlzLlJFUV9TRVRfWk9ORV9TRVRUSU5HUyA9ICdzZXRab25lU2V0dGluZ3MnO1xuXHRcdHRoaXMuUkVRX1NFVF9ST09NX1NFVFRJTkdTID0gJ3NldFJvb21TZXR0aW5ncyc7XG5cdFx0dGhpcy5SRVFfU0VUX1VTRVJfU0VUVElOR1MgPSAnc2V0VXNlclNldHRpbmdzJztcblx0XHR0aGlzLlJFUV9SRUxPQURfWk9ORV9FWFQgPSAncmVsb2FkWm9uZUV4dCc7XG5cdFx0dGhpcy5SRVFfUkVMT0FEX1dPUkRTID0gJ3JlbG9hZFdvcmRzJztcblx0XHR0aGlzLlJFUV9LSUNLX1VTRVIgPSAna2lja1VzZXInO1xuXHRcdHRoaXMuUkVRX0JBTl9VU0VSID0gJ2JhblVzZXInO1xuXHRcdHRoaXMuUkVRX0dFVF9ST09NX0NPTkZJRyA9ICdnZXRSb29tQ29uZmlnJztcblx0XHR0aGlzLlJFUV9DUkVBVEVfUk9PTSA9ICdjcmVhdGVSb29tJztcblx0XHR0aGlzLlJFUV9SRU1PVkVfUk9PTSA9ICdyZW1vdmVSb29tJztcblx0XHR0aGlzLlJFUV9BRE1JTl9NU0cgPSAnYWRtaW5Nc2cnO1xuXG5cdFx0Ly8gSW5jb21pbmcgcmVzcG9uc2VzXG5cdFx0dGhpcy5SRVNQX0RBVEEgPSAnZGF0YSc7XG5cdFx0dGhpcy5SRVNQX1VORVhQRUNURURfRVJST1IgPSAndW5leHBFcnJvcic7XG5cdFx0dGhpcy5SRVNQX1VQREFURV9FUlJPUiA9ICd1cGRhdGVFcnJvcic7XG5cdFx0dGhpcy5SRVNQX1JPT01fQ09ORklHID0gJ3Jvb21Db25maWcnO1xuXHRcdHRoaXMuUkVTUF9ST09NX0NPTkZJR19FUlJPUiA9ICdyb29tQ29uZmlnRXJyJztcblx0XHR0aGlzLlJFU1BfUk9PTV9DUkVBVEVEID0gJ3Jvb21DcmVhdGVkJztcblx0XHR0aGlzLlJFU1BfUk9PTV9DUkVBVElPTl9FUlJPUiA9ICdyb29tRXJyb3InO1xuXHRcdHRoaXMuUkVTUF9MT0dfTUVTU0FHRVMgPSAnbG9nJzsgLy8gVGhpcyByZXNwb25zZSBkb2Vzbid0IGhhdmUgYSBjb3JyZXNwb25kaW5nIHJlcXVlc3QgYmVjYXVzZSBpdCBpcyBtYW5hZ2VkIGJ5IGEgc2VydmVyIGV2ZW50IGxpc3RlbmVyXG5cblx0XHR0aGlzLl9jdXJyZW50UmVxdWVzdElkID0gLTE7XG5cdH1cblxuXHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXHQvLyBDT01NT04gTU9EVUxFIElOVEVSRkFDRSBNRVRIT0RTXG5cdC8vIFRoaXMgbWVtYmVycyBhcmUgdXNlZCBieSB0aGUgbWFpbiBjb250cm9sbGVyXG5cdC8vIHRvIGNvbW11bmljYXRlIHdpdGggdGhlIG1vZHVsZSdzIGNvbnRyb2xsZXIuXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0aW5pdGlhbGl6ZShpZERhdGEsIHNoZWxsQ29udHJvbGxlcilcblx0e1xuXHRcdC8vIENhbGwgc3VwZXIgbWV0aG9kXG5cdFx0c3VwZXIuaW5pdGlhbGl6ZShpZERhdGEsIHNoZWxsQ29udHJvbGxlcik7XG5cblx0XHQvLyBTZXQgbW9uaXRvcmluZyBpbnRlcmZhY2Vcblx0XHR0aGlzLl9zZXRNb25pdG9yaW5nSW50ZXJmYWNlKCk7XG5cblx0XHQvLyBJbml0aWFsaXplIHByb2dyZXNzIGJhclxuXHRcdCQoJyN6bm0tcHJvZ3Jlc3NCYXInKS5rZW5kb1Byb2dyZXNzQmFyKHtcblx0XHRcdG1pbjogMCxcbiAgICAgICAgICAgIG1heDogMTAwLFxuXHRcdFx0dmFsdWU6IGZhbHNlLFxuICAgICAgICAgICAgdHlwZTogJ3ZhbHVlJyxcbiAgICAgICAgICAgIGFuaW1hdGlvbjoge1xuICAgICAgICAgICAgICAgIGR1cmF0aW9uOiA0MDBcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cblx0XHQvLyBMSVNUU1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBpbnRlcnZhbCBkcm9wZG93blxuXHRcdHRoaXMuX2ludGVydmFsRHJvcERvd24gPSAkKCcjem5tLWludGVydmFsREQnKS5rZW5kb0Ryb3BEb3duTGlzdCh7XG5cdFx0XHR2YWx1ZVRlbXBsYXRlOiAnPHNwYW4gY2xhc3M9XCJ0ZXh0LW11dGVkIHByLTFcIj5JbnRlcnZhbDo8L3NwYW4+PHNwYW4+IzpkYXRhLnRleHQjPC9zcGFuPicsXG5cdFx0XHRjaGFuZ2U6ICQucHJveHkodGhpcy5fb25VcGRhdGVJbnRlcnZhbENoYW5nZSwgdGhpcylcblx0XHR9KS5kYXRhKCdrZW5kb0Ryb3BEb3duTGlzdCcpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBwYW5lIGJhclxuXHRcdHRoaXMuX2FjY29yZGlvbiA9ICQoJyN6bm0tcGFuZWxiYXInKS5rZW5kb1BhbmVsQmFyKHtcbiAgICAgICAgICAgIGV4cGFuZE1vZGU6ICdzaW5nbGUnLFxuXHRcdFx0Y2hhbmdlOiAkLnByb3h5KHRoaXMuX29uRW50aXRpZXNQYW5lbENoYW5nZSwgdGhpcylcbiAgICAgICAgfSkuZGF0YSgna2VuZG9QYW5lbEJhcicpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBsaXN0c1xuXHRcdHRoaXMuX3pvbmVMaXN0Qm94ID0gJChcIiN6bm0tem9uZUxpc3RcIikua2VuZG9MaXN0Qm94KHtcblx0XHRcdHRlbXBsYXRlOiAnPGRpdj4jOmRhdGEubmFtZSMgKCM6ZGF0YS51c2VycyMpPC9kaXY+Jyxcblx0XHRcdGNoYW5nZTogJC5wcm94eSh0aGlzLl9vblpvbmVTZWxlY3RlZCwgdGhpcylcblx0XHR9KS5kYXRhKCdrZW5kb0xpc3RCb3gnKTtcblxuXHRcdHRoaXMuX3pvbmVMaXN0Qm94LndyYXBwZXIuZmluZCgnLmstbGlzdCcpLm9uKCdkYmxjbGljaycsICcuay1pdGVtJywgJC5wcm94eSh0aGlzLl9vbk1vbml0b3JTZWxlY3Rpb25CdENsaWNrLCB0aGlzKSk7XG5cblx0XHR0aGlzLl9yb29tTGlzdEJveCA9ICQoXCIjem5tLXJvb21MaXN0XCIpLmtlbmRvTGlzdEJveCh7XG5cdFx0XHR0ZW1wbGF0ZTogJzxkaXY+IzpkYXRhLm5hbWUjICgjOmRhdGEudXNlcnMjKTwvZGl2PicsXG5cdFx0XHRjaGFuZ2U6ICQucHJveHkodGhpcy5fb25Sb29tU2VsZWN0ZWQsIHRoaXMpXG5cdFx0fSkuZGF0YSgna2VuZG9MaXN0Qm94Jyk7XG5cblx0XHR0aGlzLl9yb29tTGlzdEJveC53cmFwcGVyLmZpbmQoJy5rLWxpc3QnKS5vbignZGJsY2xpY2snLCAnLmstaXRlbScsICQucHJveHkodGhpcy5fb25Nb25pdG9yU2VsZWN0aW9uQnRDbGljaywgdGhpcykpO1xuXG5cdFx0dGhpcy5fdXNlckxpc3RCb3ggPSAkKFwiI3pubS11c2VyTGlzdFwiKS5rZW5kb0xpc3RCb3goe1xuXHRcdFx0dGVtcGxhdGU6ICc8ZGl2PiM6ZGF0YS5uYW1lIzwvZGl2PicsXG5cdFx0XHRjaGFuZ2U6ICQucHJveHkodGhpcy5fb25Vc2VyU2VsZWN0ZWQsIHRoaXMpXG5cdFx0fSkuZGF0YSgna2VuZG9MaXN0Qm94Jyk7XG5cblx0XHR0aGlzLl91c2VyTGlzdEJveC53cmFwcGVyLmZpbmQoJy5rLWxpc3QnKS5vbignZGJsY2xpY2snLCAnLmstaXRlbScsICQucHJveHkodGhpcy5fb25Nb25pdG9yU2VsZWN0aW9uQnRDbGljaywgdGhpcykpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSBSb29tIEdyb3VwcyBkcm9wZG93blxuXHRcdHRoaXMuX2dyb3Vwc0Ryb3BEb3duID0gJCgnI3pubS1yb29tR3JvdXBzREQnKS5rZW5kb0Ryb3BEb3duTGlzdCh7XG5cdFx0XHRkYXRhVGV4dEZpZWxkOiAnbGFiZWwnLFxuICBcdFx0XHRkYXRhVmFsdWVGaWVsZDogJ25hbWUnLFxuXHRcdFx0Y2hhbmdlOiAkLnByb3h5KHRoaXMuX29uR3JvdXBDaGFuZ2UsIHRoaXMpXG5cdFx0fSkuZGF0YSgna2VuZG9Ecm9wRG93bkxpc3QnKTtcblxuXHRcdC8vIEJ1aWxkIGluaXRpYWwgZ3JvdXBzIGxpc3Rcblx0XHR0aGlzLl9zZXRHcm91cHNEYXRhUHJvdmlkZXIobnVsbCk7XG5cblx0XHQvLyAvLyBDcmVhdGUgaW50ZXJmYWNlIGJ1aWxkZXIgaW5zdGFuY2VzXG5cdFx0dGhpcy5faW50ZXJmYWNlQnVpbGRlciA9IG5ldyBDb25maWdJbnRlcmZhY2VCdWlsZGVyKCk7XG5cdFx0dGhpcy5fcm9vbUNyZWF0aW9uSUJ1aWxkZXIgPSBuZXcgQ29uZmlnSW50ZXJmYWNlQnVpbGRlcigpO1xuXG5cdFx0Ly8gQWRkIGxpc3RlbmVyIHRvIHNob3cgbGltaXQgd2FybmluZyB0b29sdGlwc1xuXHRcdCQoJyN6bm0tcGFuZWxiYXInKS5rZW5kb1Rvb2x0aXAoe1xuXHRcdFx0ZmlsdGVyOiAnaVt0aXRsZV0ubGltaXQtd2FybmluZycsXG5cdFx0XHRwb3NpdGlvbjogJ3JpZ2h0Jyxcblx0XHRcdHdpZHRoOiAnMjUwcHgnLFxuXHRcdFx0Y29udGVudDogZnVuY3Rpb24oZSkge1xuXHRcdFx0XHRyZXR1cm4gYDxkaXYgY2xhc3M9XCJoZWxwLXRvb2x0aXBcIj4ke2UudGFyZ2V0LmRhdGEoJ3RpdGxlJyl9PC9kaXY+YDtcblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdC8vIFJPT00gQ1JFQVRJT04gUEFORUxcblxuXHRcdC8vIEFkZCBjbGljayBsaXN0ZW5lciB0byBDcmVhdGUgJiBSZW1vdmUgUm9vbSBidXR0b25zXG5cdFx0JCgnI3pubS1jcmVhdGVSb29tQnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uQ3JlYXRlUm9vbUJ0Q2xpY2ssIHRoaXMpKTtcblx0XHQkKCcjem5tLXJlbW92ZVJvb21CdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25SZW1vdmVSb29tQnRDbGljaywgdGhpcykpO1xuXG5cdFx0Ly8gQ29uZmlndXJlIHJvb20gY3JlYXRpb24gcGFuZWxcblx0XHQkKCcjem5tLWNyZWF0ZVJvb21Nb2RhbCcpLm1vZGFsKHtcblx0XHRcdGJhY2tkcm9wOiAnc3RhdGljJyxcblx0XHRcdGtleWJvYXJkOiBmYWxzZSxcblx0XHRcdHNob3c6IGZhbHNlLFxuXHRcdH0pO1xuXG5cdFx0Ly8gQWRkIGxpc3RlbmVyIGZvciByb29tIGNyZWF0aW9uIHBhbmVsJ3MgY3JlYXRlIGJ1dHRvbiBjbGlja1xuXHRcdCQoJyN6bm0tcm9vbUNyZWF0b3JDcmVhdGVCdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25Sb29tQ3JlYXRvckNyZWF0ZUJ0Q2xpY2ssIHRoaXMpKTtcblxuXHRcdC8vIEFkZCBsaXN0ZW5lciBmb3Igcm9vbSBjcmVhdGlvbiBwYW5lbCBoaWRlXG5cdFx0JCgnI3pubS1jcmVhdGVSb29tTW9kYWwnKS5vbignaGlkZGVuLmJzLm1vZGFsJywgJC5wcm94eSh0aGlzLl9vbkNyZWF0ZVJvb21Nb2RhbEhpZGRlbiwgdGhpcykpO1xuXG5cdFx0Ly8gUk9PTSAmIFVTRVIgRklMVEVSSU5HIFBBTkVMU1xuXG5cdFx0Ly8gU2V0dXAgbWF0Y2ggZXhwcmVzc2lvbiBidWlsZGVyIHBhbmVsIGZvciByb29tc1xuXHRcdHRoaXMuX3Jvb21GaWx0ZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnem5tLXJvb21GaWx0ZXInKTtcblx0XHR0aGlzLl9yb29tRmlsdGVyLnRpdGxlID0gJ1Jvb20gRmlsdGVyIEV4cHJlc3Npb24gQnVpbGRlcic7XG5cdFx0dGhpcy5fcm9vbUZpbHRlci5wcmVkZWZpbmVkVmFyTmFtZXMgPSBSb29tUHJvcGVydGllc0RhdGEucHJvcGVydGllc0FycmF5O1xuXHRcdCQodGhpcy5fcm9vbUZpbHRlcikub24odGhpcy5fcm9vbUZpbHRlci5FWFBSRVNTSU9OX1VQREFURURfRVZFTlQsICQucHJveHkodGhpcy5fb25Sb29tRmlsdGVyVXBkYXRlZCwgdGhpcykpO1xuXG5cdFx0JCgnI3pubS1maWx0ZXJSb29tQnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uU2hvd1Jvb21GaWx0ZXJCdENsaWNrLCB0aGlzKSk7XG5cdFx0JCgnI3pubS1hcHBseVJvb21GaWx0ZXJDQicpLm9uKCdjaGFuZ2UnLCAkLnByb3h5KHRoaXMuX29uQXBwbHlCdENoYW5nZSwgdGhpcykpO1xuXG5cdFx0Ly8gU2V0dXAgbWF0Y2ggZXhwcmVzc2lvbiBidWlsZGVyIHBhbmVsIGZvciB1c2Vyc1xuXHRcdHRoaXMuX3VzZXJGaWx0ZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnem5tLXVzZXJGaWx0ZXInKTtcblx0XHR0aGlzLl91c2VyRmlsdGVyLnRpdGxlID0gJ1VzZXIgRmlsdGVyIEV4cHJlc3Npb24gQnVpbGRlcic7XG5cdFx0dGhpcy5fdXNlckZpbHRlci5wcmVkZWZpbmVkVmFyTmFtZXMgPSBVc2VyUHJvcGVydGllc0RhdGEucHJvcGVydGllc0FycmF5O1xuXHRcdCQodGhpcy5fdXNlckZpbHRlcikub24odGhpcy5fdXNlckZpbHRlci5FWFBSRVNTSU9OX1VQREFURURfRVZFTlQsICQucHJveHkodGhpcy5fb25Vc2VyRmlsdGVyVXBkYXRlZCwgdGhpcykpO1xuXG5cdFx0JCgnI3pubS1maWx0ZXJVc2VyQnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uU2hvd1VzZXJGaWx0ZXJCdENsaWNrLCB0aGlzKSk7XG5cdFx0JCgnI3pubS1hcHBseVVzZXJGaWx0ZXJDQicpLm9uKCdjaGFuZ2UnLCAkLnByb3h5KHRoaXMuX29uQXBwbHlCdENoYW5nZSwgdGhpcykpO1xuXG5cdFx0Ly8gTUFJTiBDT05UUk9MU1xuXG5cdFx0JCgnI3pubS1tb25pdG9yQnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uTW9uaXRvclNlbGVjdGlvbkJ0Q2xpY2ssIHRoaXMpKTtcblx0XHQkKCcjem5tLXNlbmRNZXNzYWdlQnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uU2VuZEFkbWluTXNnQnRDbGljaywgdGhpcykpO1xuXHRcdCQoJyN6bm0tbWVzc2FnZUluJykub24oJ2tleXVwJywgJC5wcm94eSh0aGlzLl9vblNlbmRBZG1pbk1zZ0luS2V5VXAsIHRoaXMpKTtcblxuXHRcdC8vIE1PTklUT1JJTkcgQ09OVFJPTFNcblxuXHRcdCQoJyN6bm0tY2xvc2VNb25pdG9yQnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uQ2xvc2VNb25pdG9yQnRDbGljaywgdGhpcykpO1xuXHRcdCQoJyN6bm0tZWRpdEJ0Jykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vbkVkaXRCdENsaWNrLCB0aGlzKSk7XG5cdFx0JCgnI3pubS1jYW5jZWxCdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25DYW5jZWxCdENsaWNrLCB0aGlzKSk7XG5cdFx0JCgnI3pubS1zdWJtaXRCdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25TdWJtaXRCdENsaWNrLCB0aGlzKSk7XG5cblx0XHQvLyBIaWRlIGVkaXQgY29udHJvbHNcblx0XHQkKCcjem5tLWVkaXRDb250cm9scycpLmhpZGUoKTtcblxuXHRcdC8vIFpPTkUgTU9OSVRPUiAtLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuXHRcdC8vIFNldCByZWZlcmVuY2UgdG8gdXNlciBjb3VudCBjaGFydFxuXHRcdHRoaXMuX3VzZXJDb3VudENoYXJ0ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3pubS11c2VyQ291bnRDaGFydCcpO1xuXG5cdFx0Ly8gSW5pdGlhbGl6ZSB0aW1lIHJhbmdlIHNsaWRlclxuXHRcdHRoaXMuX3RpbWVTbGlkZXIgPSAkKCcjem5tLXRpbWVTbGlkZXInKS5rZW5kb1JhbmdlU2xpZGVyKHtcblx0XHRcdG1pbjogLTI0LFxuICAgICAgICAgICAgbWF4OiAwLFxuICAgICAgICAgICAgc21hbGxTdGVwOiAxLFxuICAgICAgICAgICAgbGFyZ2VTdGVwOiAwLFxuXHRcdFx0Y2hhbmdlOiAkLnByb3h5KHRoaXMuX29uVGltZVJhbmdlQ2hhbmdlLCB0aGlzKSxcblx0XHRcdHRvb2x0aXA6IHtcblx0XHRcdFx0dGVtcGxhdGU6IGdldFRpbWVSYW5nZVRvb2x0aXBUZW1wbGF0ZSgpXG5cdFx0XHR9LFxuXHRcdFx0bGVmdERyYWdIYW5kbGVUaXRsZTogJ0RyYWcnLFxuXHRcdFx0cmlnaHREcmFnSGFuZGxlVGl0bGU6ICdEcmFnJyxcblx0XHR9KS5kYXRhKCdrZW5kb1JhbmdlU2xpZGVyJyk7XG5cblx0XHQvLyBSZXNldCB0aW1lIHJhbmdlIG9uIHVzZXIgY291bnQgY2hhcnRcblx0XHR0aGlzLl9vblRpbWVSYW5nZUNoYW5nZSgpO1xuXG5cdFx0Ly8gQWRkIGJ1dHRvbiBjbGljayBsaXN0ZW5lcnNcblx0XHQkKCcjem5tLXJlbG9hZFdvcmRzQnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uV29yZHNSZWxvYWRCdENsaWNrLCB0aGlzKSk7XG5cdFx0JCgnI3pubS1yZWxvYWRab25lRXh0QnQnKS5vbignY2xpY2snLCAkLnByb3h5KHRoaXMuX29uWm9uZUV4dFJlbG9hZEJ0Q2xpY2ssIHRoaXMpKTtcblxuXHRcdC8vIEluaXRpYWxpemUgZXh0ZW5zaW9uIGxvZyBncmlkXG5cdFx0dGhpcy5fem9uZUV4dExvZ0dyaWQgPSAkKCcjem5tLXpvbmVFeHRMb2dHcmlkJykua2VuZG9HcmlkKHtcblx0XHRcdGRhdGFTb3VyY2U6IFtdLFxuXHRcdFx0cmVzaXphYmxlOiB0cnVlLFxuXHRcdFx0c2VsZWN0YWJsZTogZmFsc2UsXG5cdFx0XHRub1JlY29yZHM6IHtcblx0XHRcdFx0dGVtcGxhdGU6ICdObyBlbnRyaWVzLidcblx0XHRcdH0sXG5cdFx0XHRjb2x1bW5zOiBbXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRmaWVsZDogJ3RpbWVzdGFtcCcsXG5cdFx0XHRcdFx0dGl0bGU6ICdUaW1lc3RhbXAnLFxuXHRcdFx0XHRcdHdpZHRoOiAxODBcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGZpZWxkOiAnbGV2ZWwnLFxuXHRcdFx0XHRcdHRpdGxlOiAnTGV2ZWwnLFxuXHRcdFx0XHRcdHdpZHRoOiAxMDBcblx0XHRcdFx0fSxcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGZpZWxkOiAnbWVzc2FnZScsXG5cdFx0XHRcdFx0dGl0bGU6ICdNZXNzYWdlJyxcblx0XHRcdFx0XHR3aWR0aDogNDAwXG5cdFx0XHRcdH0sXG5cdFx0XHRdLFxuXHRcdFx0ZGF0YUJvdW5kOiBmdW5jdGlvbigpIHtcblx0XHRcdCAgICB0aGlzLmNvbnRlbnQuc2Nyb2xsVG9wKHRoaXMudGJvZHkuaGVpZ2h0KCkpOyAvLyBTY3JvbGwgdG8gYm90dG9tXG5cdFx0XHR9XG5cdFx0fSkuZGF0YSgna2VuZG9HcmlkJyk7XG5cblx0XHQvLyBST09NIE1PTklUT1IgLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0XHQvLyBJbml0aWFsaXplIGV4dGVuc2lvbiBsb2cgZ3JpZFxuXHRcdHRoaXMuX3Jvb21FeHRMb2dHcmlkID0gJCgnI3pubS1yb29tRXh0TG9nR3JpZCcpLmtlbmRvR3JpZCh7XG5cdFx0XHRkYXRhU291cmNlOiBbXSxcblx0XHRcdHJlc2l6YWJsZTogdHJ1ZSxcblx0XHRcdHNlbGVjdGFibGU6IGZhbHNlLFxuXHRcdFx0bm9SZWNvcmRzOiB7XG5cdFx0XHRcdHRlbXBsYXRlOiAnTm8gZW50cmllcy4nXG5cdFx0XHR9LFxuXHRcdFx0Y29sdW1uczogW1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0ZmllbGQ6ICd0aW1lc3RhbXAnLFxuXHRcdFx0XHRcdHRpdGxlOiAnVGltZXN0YW1wJyxcblx0XHRcdFx0XHR3aWR0aDogMTgwXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRmaWVsZDogJ2xldmVsJyxcblx0XHRcdFx0XHR0aXRsZTogJ0xldmVsJyxcblx0XHRcdFx0XHR3aWR0aDogMTAwXG5cdFx0XHRcdH0sXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRmaWVsZDogJ21lc3NhZ2UnLFxuXHRcdFx0XHRcdHRpdGxlOiAnTWVzc2FnZScsXG5cdFx0XHRcdFx0d2lkdGg6IDQwMFxuXHRcdFx0XHR9LFxuXHRcdFx0XSxcblx0XHRcdGRhdGFCb3VuZDogZnVuY3Rpb24oKSB7XG5cdFx0XHQgICAgdGhpcy5jb250ZW50LnNjcm9sbFRvcCh0aGlzLnRib2R5LmhlaWdodCgpKTsgLy8gU2Nyb2xsIHRvIGJvdHRvbVxuXHRcdFx0fVxuXHRcdH0pLmRhdGEoJ2tlbmRvR3JpZCcpO1xuXG5cdFx0Ly8gVVNFUiBNT05JVE9SIC0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdFx0dGhpcy5fa2lja0RlbGF5SW4gPSAkKCcjem5tLWtpY2tEZWxheU5TJykua2VuZG9OdW1lcmljVGV4dEJveCh7XG5cdFx0ICAgIG1pbjogMCxcblx0XHQgICAgc3RlcDogMSxcblx0XHQgICAgZm9ybWF0OiAnIycsXG5cdFx0XHRwbGFjZWhvbGRlcjogJ0RlbGF5IChzKSdcblx0XHR9KS5kYXRhKCdrZW5kb051bWVyaWNUZXh0Qm94Jyk7XG5cblx0XHR0aGlzLl9iYW5Nb2RlRGQgPSAkKCcjem5tLWJhbk1vZGVERCcpLmtlbmRvRHJvcERvd25MaXN0KHtcblx0XHRcdGRhdGFTb3VyY2U6IFsnSVAnLCAnTkFNRSddLFxuXHRcdFx0YXV0b1dpZHRoOiB0cnVlLFxuXHRcdFx0b3B0aW9uTGFiZWw6IHtcblx0XHRcdFx0dGV4dDogJ01vZGUnXG5cdFx0XHR9LFxuXHRcdFx0b3B0aW9uTGFiZWxUZW1wbGF0ZTogJzxzcGFuIGNsYXNzPVwidGV4dC1tdXRlZFwiPiM6dGV4dCM8L3NwYW4+Jyxcblx0XHR9KS5kYXRhKCdrZW5kb0Ryb3BEb3duTGlzdCcpO1xuXG5cdFx0dGhpcy5fYmFuRHVyVW5pdERkID0gJCgnI3pubS1iYW5EdXJhdGlvblVuaXRERCcpLmtlbmRvRHJvcERvd25MaXN0KHtcblx0XHRcdGF1dG9XaWR0aDogdHJ1ZSxcblx0XHR9KS5kYXRhKCdrZW5kb0Ryb3BEb3duTGlzdCcpO1xuXG5cdFx0dGhpcy5fYmFuRHVyYXRpb25JbiA9ICQoJyN6bm0tYmFuRHVyYXRpb25OUycpLmtlbmRvTnVtZXJpY1RleHRCb3goe1xuXHRcdCAgICBtaW46IDEsXG5cdFx0ICAgIHN0ZXA6IDEsXG5cdFx0ICAgIGZvcm1hdDogJyMnLFxuXHRcdFx0cGxhY2Vob2xkZXI6ICdEdXJhdGlvbidcblx0XHR9KS5kYXRhKCdrZW5kb051bWVyaWNUZXh0Qm94Jyk7XG5cblx0XHR0aGlzLl9iYW5EZWxheUluID0gJCgnI3pubS1iYW5EZWxheU5TJykua2VuZG9OdW1lcmljVGV4dEJveCh7XG5cdFx0ICAgIG1pbjogMCxcblx0XHQgICAgc3RlcDogMSxcblx0XHQgICAgZm9ybWF0OiAnIycsXG5cdFx0XHRwbGFjZWhvbGRlcjogJ0RlbGF5IChzKSdcblx0XHR9KS5kYXRhKCdrZW5kb051bWVyaWNUZXh0Qm94Jyk7XG5cblx0XHQvLyBBZGQgYnV0dG9uIGNsaWNrIGxpc3RlbmVyc1xuXHRcdCQoJyN6bm0ta2lja0J0Jykub24oJ2NsaWNrJywgJC5wcm94eSh0aGlzLl9vbktpY2tCdENsaWNrLCB0aGlzKSk7XG5cdFx0JCgnI3pubS1iYW5CdCcpLm9uKCdjbGljaycsICQucHJveHkodGhpcy5fb25CYW5CdENsaWNrLCB0aGlzKSk7XG5cblx0XHQvLyBDaGFydHNcblxuXHRcdHRoaXMuX3BhY2tldFF1ZXVlQ2hhcnQgPSAkKCcjem5tLXBhY2tldFF1ZXVlQ2hhcnQnKS5rZW5kb0NoYXJ0KHtcblx0XHRcdHRyYW5zaXRpb25zOiBmYWxzZSxcblx0XHRcdGNoYXJ0QXJlYToge1xuXHRcdFx0XHRoZWlnaHQ6IDEwMFxuXHRcdFx0fSxcblx0ICAgICAgICBsZWdlbmQ6IHtcblx0ICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICB9LFxuXHQgICAgICAgIHNlcmllc0RlZmF1bHRzOiB7XG5cdCAgICAgICAgICAgIHR5cGU6ICdiYXInLFxuXHQgICAgICAgICAgICBsYWJlbHM6IHtcblx0ICAgICAgICAgICAgICAgIHZpc2libGU6IHRydWUsXG5cdCAgICAgICAgICAgICAgICBmb3JtYXQ6ICd7MH0lJyxcblx0ICAgICAgICAgICAgICAgIGJhY2tncm91bmQ6ICd0cmFuc3BhcmVudCcsXG5cdFx0XHRcdFx0cG9zaXRpb246ICdpbnNpZGVCYXNlJ1xuXHQgICAgICAgICAgICB9LFxuXHRcdFx0XHRnYXA6IC41LFxuXHRcdFx0XHRzcGFjaW5nOiAwLFxuXHRcdFx0XHRvdmVybGF5OiB7XG5cdFx0XHRcdFx0Z3JhZGllbnQ6ICdub25lJ1xuXHRcdFx0XHR9LFxuXHRcdFx0XHRib3JkZXI6IHtcblx0XHRcdFx0XHR3aWR0aDogMFxuXHRcdFx0XHR9XG5cdCAgICAgICAgfSxcblx0ICAgICAgICBzZXJpZXM6IFtcblx0XHRcdFx0e1xuXHRcdFx0XHRcdG5hbWU6ICdQYWNrZXQgcXVldWUnLFxuXHRcdCAgICAgICAgICAgIGZpZWxkOiAndmFsdWUnLFxuXHRcdCAgICAgICAgICAgIGNhdGVnb3J5RmllbGQ6ICdjYXRlZ29yeScsXG5cdFx0XHRcdFx0Y29sb3I6ICcjRkI3RDMzJ1xuXHRcdCAgICAgICAgfVxuXHRcdFx0XSxcblx0ICAgICAgICB2YWx1ZUF4aXM6IHtcblx0ICAgICAgICAgICAgbGFiZWxzOiB7XG5cdCAgICAgICAgICAgICAgICBmb3JtYXQ6ICd7MH0lJ1xuXHQgICAgICAgICAgICB9LFxuXHQgICAgICAgICAgICBsaW5lOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHRcdFx0XHRtaW46IDAsXG5cdCAgICBcdFx0bWF4OiAxMDBcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGNhdGVnb3J5QXhpczoge1xuXHQgICAgICAgICAgICBtYWpvckdyaWRMaW5lczoge1xuXHQgICAgICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICAgICAgfSxcblx0XHRcdFx0bWFqb3JUaWNrczoge1xuXHRcdFx0XHRcdHZpc2libGU6IGZhbHNlXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGxhYmVsczoge1xuXHRcdFx0XHRcdHZpc2libGU6IGZhbHNlXG5cdFx0XHRcdH1cblx0ICAgICAgICB9LFxuXHRcdFx0dG9vbHRpcDoge1xuXHRcdFx0XHR2aXNpYmxlOiBmYWxzZSxcblx0ICAgICAgICB9XG5cdCAgICB9KS5kYXRhKCdrZW5kb0NoYXJ0Jyk7XG5cblx0XHR0aGlzLl9kcm9wcGVkTXNnQ2hhcnQgPSAkKCcjem5tLWRyb3BwZWRNc2dDaGFydCcpLmtlbmRvQ2hhcnQoe1xuXHRcdFx0dHJhbnNpdGlvbnM6IGZhbHNlLFxuXHRcdFx0Y2hhcnRBcmVhOiB7XG5cdFx0XHRcdGhlaWdodDogMTAwXG5cdFx0XHR9LFxuXHQgICAgICAgIGxlZ2VuZDoge1xuXHQgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgc2VyaWVzRGVmYXVsdHM6IHtcblx0ICAgICAgICAgICAgdHlwZTogJ2JhcicsXG5cdCAgICAgICAgICAgIGxhYmVsczoge1xuXHQgICAgICAgICAgICAgICAgdmlzaWJsZTogdHJ1ZSxcblx0ICAgICAgICAgICAgICAgIGZvcm1hdDogJ3swfScsXG5cdCAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kOiAndHJhbnNwYXJlbnQnLFxuXHRcdFx0XHRcdHBvc2l0aW9uOiAnaW5zaWRlQmFzZScsXG5cdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdGdhcDogLjUsXG5cdFx0XHRcdHNwYWNpbmc6IDAsXG5cdFx0XHRcdG92ZXJsYXk6IHtcblx0XHRcdFx0XHRncmFkaWVudDogJ25vbmUnXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGJvcmRlcjoge1xuXHRcdFx0XHRcdHdpZHRoOiAwXG5cdFx0XHRcdH1cblx0ICAgICAgICB9LFxuXHQgICAgICAgIHNlcmllczogW1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bmFtZTogJ0Ryb3BwZWQgbWVzc2FnZXMnLFxuXHRcdCAgICAgICAgICAgIGZpZWxkOiAndmFsdWUnLFxuXHRcdCAgICAgICAgICAgIGNhdGVnb3J5RmllbGQ6ICdjYXRlZ29yeScsXG5cdFx0XHRcdFx0Y29sb3I6ICcjRkI3RDMzJ1xuXHRcdCAgICAgICAgfVxuXHRcdFx0XSxcblx0ICAgICAgICB2YWx1ZUF4aXM6IHtcblx0ICAgICAgICAgICAgbGFiZWxzOiB7XG5cdCAgICAgICAgICAgICAgICBmb3JtYXQ6ICd7MH0nXG5cdCAgICAgICAgICAgIH0sXG5cdCAgICAgICAgICAgIGxpbmU6IHtcblx0ICAgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlXG5cdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdG1pbjogMCxcblx0ICAgICAgICB9LFxuXHQgICAgICAgIGNhdGVnb3J5QXhpczoge1xuXHQgICAgICAgICAgICBtYWpvckdyaWRMaW5lczoge1xuXHQgICAgICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICAgICAgfSxcblx0XHRcdFx0bWFqb3JUaWNrczoge1xuXHRcdFx0XHRcdHZpc2libGU6IGZhbHNlXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGxhYmVsczoge1xuXHRcdFx0XHRcdHZpc2libGU6IGZhbHNlXG5cdFx0XHRcdH1cblx0ICAgICAgICB9LFxuXHRcdFx0dG9vbHRpcDoge1xuXHRcdFx0XHR2aXNpYmxlOiBmYWxzZSxcblx0ICAgICAgICB9XG5cdCAgICB9KS5kYXRhKCdrZW5kb0NoYXJ0Jyk7XG5cblx0XHR0aGlzLl93cml0dGVuRGF0YUNoYXJ0ID0gJCgnI3pubS13cml0dGVuRGF0YUNoYXJ0Jykua2VuZG9DaGFydCh7XG5cdFx0XHR0cmFuc2l0aW9uczogZmFsc2UsXG5cdFx0XHRjaGFydEFyZWE6IHtcblx0XHRcdFx0aGVpZ2h0OiAxMDBcblx0XHRcdH0sXG5cdCAgICAgICAgbGVnZW5kOiB7XG5cdCAgICAgICAgICAgIHZpc2libGU6IGZhbHNlXG5cdCAgICAgICAgfSxcblx0ICAgICAgICBzZXJpZXNEZWZhdWx0czoge1xuXHQgICAgICAgICAgICB0eXBlOiAnYmFyJyxcblx0ICAgICAgICAgICAgbGFiZWxzOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiB0cnVlLFxuXHQgICAgICAgICAgICAgICAgZm9ybWF0OiAnezB9Jyxcblx0ICAgICAgICAgICAgICAgIGJhY2tncm91bmQ6ICd0cmFuc3BhcmVudCcsXG5cdFx0XHRcdFx0cG9zaXRpb246ICdpbnNpZGVCYXNlJyxcblx0XHRcdFx0XHR0ZW1wbGF0ZTogZ2V0V1JCeXRlc0xhYmVsVGVtcGxhdGUoKSxcblx0ICAgICAgICAgICAgfSxcblx0XHRcdFx0Z2FwOiAuNSxcblx0XHRcdFx0c3BhY2luZzogMCxcblx0XHRcdFx0b3ZlcmxheToge1xuXHRcdFx0XHRcdGdyYWRpZW50OiAnbm9uZSdcblx0XHRcdFx0fSxcblx0XHRcdFx0Ym9yZGVyOiB7XG5cdFx0XHRcdFx0d2lkdGg6IDBcblx0XHRcdFx0fVxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgc2VyaWVzOiBbXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRuYW1lOiAnV3JpdHRlbiBkYXRhJyxcblx0XHQgICAgICAgICAgICBmaWVsZDogJ3ZhbHVlJyxcblx0XHQgICAgICAgICAgICBjYXRlZ29yeUZpZWxkOiAnY2F0ZWdvcnknLFxuXHRcdFx0XHRcdGNvbG9yOiAnI0ZCN0QzMydcblx0XHQgICAgICAgIH1cblx0XHRcdF0sXG5cdCAgICAgICAgdmFsdWVBeGlzOiB7XG5cdCAgICAgICAgICAgIGxhYmVsczoge1xuXHQgICAgICAgICAgICAgICAgZm9ybWF0OiAnezB9J1xuXHQgICAgICAgICAgICB9LFxuXHQgICAgICAgICAgICBsaW5lOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHRcdFx0XHRtaW46IDAsXG5cdCAgICAgICAgfSxcblx0ICAgICAgICBjYXRlZ29yeUF4aXM6IHtcblx0ICAgICAgICAgICAgbWFqb3JHcmlkTGluZXM6IHtcblx0ICAgICAgICAgICAgICAgIHZpc2libGU6IGZhbHNlXG5cdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdG1ham9yVGlja3M6IHtcblx0XHRcdFx0XHR2aXNpYmxlOiBmYWxzZVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRsYWJlbHM6IHtcblx0XHRcdFx0XHR2aXNpYmxlOiBmYWxzZVxuXHRcdFx0XHR9XG5cdCAgICAgICAgfSxcblx0XHRcdHRvb2x0aXA6IHtcblx0XHRcdFx0dmlzaWJsZTogZmFsc2UsXG5cdCAgICAgICAgfVxuXHQgICAgfSkuZGF0YSgna2VuZG9DaGFydCcpO1xuXG5cdFx0dGhpcy5fcmVhZERhdGFDaGFydCA9ICQoJyN6bm0tcmVhZERhdGFDaGFydCcpLmtlbmRvQ2hhcnQoe1xuXHRcdFx0dHJhbnNpdGlvbnM6IGZhbHNlLFxuXHRcdFx0Y2hhcnRBcmVhOiB7XG5cdFx0XHRcdGhlaWdodDogMTAwXG5cdFx0XHR9LFxuXHQgICAgICAgIGxlZ2VuZDoge1xuXHQgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgc2VyaWVzRGVmYXVsdHM6IHtcblx0ICAgICAgICAgICAgdHlwZTogJ2JhcicsXG5cdCAgICAgICAgICAgIGxhYmVsczoge1xuXHQgICAgICAgICAgICAgICAgdmlzaWJsZTogdHJ1ZSxcblx0ICAgICAgICAgICAgICAgIGZvcm1hdDogJ3swfScsXG5cdCAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kOiAndHJhbnNwYXJlbnQnLFxuXHRcdFx0XHRcdHBvc2l0aW9uOiAnaW5zaWRlQmFzZScsXG5cdFx0XHRcdFx0dGVtcGxhdGU6IGdldFdSQnl0ZXNMYWJlbFRlbXBsYXRlKCksXG5cdCAgICAgICAgICAgIH0sXG5cdFx0XHRcdGdhcDogLjUsXG5cdFx0XHRcdHNwYWNpbmc6IDAsXG5cdFx0XHRcdG92ZXJsYXk6IHtcblx0XHRcdFx0XHRncmFkaWVudDogJ25vbmUnXG5cdFx0XHRcdH0sXG5cdFx0XHRcdGJvcmRlcjoge1xuXHRcdFx0XHRcdHdpZHRoOiAwXG5cdFx0XHRcdH1cblx0ICAgICAgICB9LFxuXHQgICAgICAgIHNlcmllczogW1xuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bmFtZTogJ1JlYWQgZGF0YScsXG5cdFx0ICAgICAgICAgICAgZmllbGQ6ICd2YWx1ZScsXG5cdFx0ICAgICAgICAgICAgY2F0ZWdvcnlGaWVsZDogJ2NhdGVnb3J5Jyxcblx0XHRcdFx0XHRjb2xvcjogJyNGQjdEMzMnXG5cdFx0ICAgICAgICB9XG5cdFx0XHRdLFxuXHQgICAgICAgIHZhbHVlQXhpczoge1xuXHQgICAgICAgICAgICBsYWJlbHM6IHtcblx0ICAgICAgICAgICAgICAgIGZvcm1hdDogJ3swfSdcblx0ICAgICAgICAgICAgfSxcblx0ICAgICAgICAgICAgbGluZToge1xuXHQgICAgICAgICAgICAgICAgdmlzaWJsZTogZmFsc2Vcblx0ICAgICAgICAgICAgfSxcblx0XHRcdFx0bWluOiAwLFxuXHQgICAgICAgIH0sXG5cdCAgICAgICAgY2F0ZWdvcnlBeGlzOiB7XG5cdCAgICAgICAgICAgIG1ham9yR3JpZExpbmVzOiB7XG5cdCAgICAgICAgICAgICAgICB2aXNpYmxlOiBmYWxzZVxuXHQgICAgICAgICAgICB9LFxuXHRcdFx0XHRtYWpvclRpY2tzOiB7XG5cdFx0XHRcdFx0dmlzaWJsZTogZmFsc2Vcblx0XHRcdFx0fSxcblx0XHRcdFx0bGFiZWxzOiB7XG5cdFx0XHRcdFx0dmlzaWJsZTogZmFsc2Vcblx0XHRcdFx0fVxuXHQgICAgICAgIH0sXG5cdFx0XHR0b29sdGlwOiB7XG5cdFx0XHRcdHZpc2libGU6IGZhbHNlLFxuXHQgICAgICAgIH1cblx0ICAgIH0pLmRhdGEoJ2tlbmRvQ2hhcnQnKTtcblxuXHRcdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdFx0Ly8gQWRkIGxpc3RlbmVyIHRvIHJlZHJhdyBhbGwgY2hhcnRzIGluIGNhc2Ugb2Ygd2luZG93IHJlc2l6ZVxuXHRcdCQod2luZG93KS5vbigncmVzaXplJywgJC5wcm94eSh0aGlzLl9vbldpbmRvd1Jlc2l6ZSwgdGhpcykpO1xuXHRcdHRoaXMuX29uV2luZG93UmVzaXplKCk7IC8vIEFsc28gZG8gaXQgaW1tZWRpYXRlbHlcblxuXHRcdC8vIFJlcXVlc3QgZGF0YSB0byBzZXJ2ZXJcblx0XHR0aGlzLl9yZXF1ZXN0RGF0YSh0cnVlKTtcblx0fVxuXG5cdGRlc3Ryb3koKVxuXHR7XG5cdFx0Ly8gQ2FsbCBzdXBlciBtZXRob2Rcblx0XHRzdXBlci5kZXN0cm95KCk7XG5cblx0XHQvLyBDbG9zZSBtb25pdG9yaW5nXG5cdFx0dGhpcy5fb25DbG9zZU1vbml0b3JCdENsaWNrKCk7XG5cblx0XHQvLyBSZW1vdmUgZG91YmxlY2xpY2sgZXZlbnQgbGlzdGVuZXJzXG5cdFx0dGhpcy5fem9uZUxpc3RCb3gud3JhcHBlci5maW5kKCcuay1saXN0Jykub2ZmKCdkYmxjbGljaycpO1xuXHRcdHRoaXMuX3Jvb21MaXN0Qm94LndyYXBwZXIuZmluZCgnLmstbGlzdCcpLm9mZignZGJsY2xpY2snKTtcblx0XHR0aGlzLl91c2VyTGlzdEJveC53cmFwcGVyLmZpbmQoJy5rLWxpc3QnKS5vZmYoJ2RibGNsaWNrJyk7XG5cblx0XHQvLyBSZW1vdmUgb3RoZXIgZXZlbnQgbGlzdGVuZXJzXG5cdFx0JCgnI3pubS1jcmVhdGVSb29tQnQnKS5vZmYoJ2NsaWNrJyk7XG5cdFx0JCgnI3pubS1yZW1vdmVSb29tQnQnKS5vZmYoJ2NsaWNrJyk7XG5cdFx0JCgnI3pubS1yb29tQ3JlYXRvckNyZWF0ZUJ0Jykub2ZmKCdjbGljaycpO1xuXHRcdCQoJyN6bm0tZmlsdGVyUm9vbUJ0Jykub2ZmKCdjbGljaycpO1xuXHRcdCQoJyN6bm0tYXBwbHlSb29tRmlsdGVyQ0InKS5vZmYoJ2NoYW5nZScpO1xuXHRcdCQoJyN6bm0tZmlsdGVyVXNlckJ0Jykub2ZmKCdjbGljaycpO1xuXHRcdCQoJyN6bm0tYXBwbHlVc2VyRmlsdGVyQ0InKS5vZmYoJ2NoYW5nZScpO1xuXHRcdCQoJyN6bm0tbW9uaXRvckJ0Jykub2ZmKCdjbGljaycpO1xuXHRcdCQoJyN6bm0tc2VuZE1lc3NhZ2VCdCcpLm9mZignY2xpY2snKTtcblx0XHQkKCcjem5tLW1lc3NhZ2VJbicpLm9mZigna2V5dXAnKTtcblx0XHQkKCcjem5tLWNsb3NlTW9uaXRvckJ0Jykub2ZmKCdjbGljaycpO1xuXHRcdCQoJyN6bm0tZWRpdEJ0Jykub2ZmKCdjbGljaycpO1xuXHRcdCQoJyN6bm0tY2FuY2VsQnQnKS5vZmYoJ2NsaWNrJyk7XG5cdFx0JCgnI3pubS1zdWJtaXRCdCcpLm9mZignY2xpY2snKTtcblx0XHQkKHdpbmRvdykub2ZmKCdyZXNpemUnKTtcblx0XHQkKCcjem5tLXJlbG9hZFdvcmRzQnQnKS5vZmYoJ2NsaWNrJyk7XG5cdFx0JCgnI3pubS1yZWxvYWRab25lRXh0QnQnKS5vZmYoJ2NsaWNrJyk7XG5cdFx0JCgnI3pubS1raWNrQnQnKS5vZmYoJ2NsaWNrJyk7XG5cdFx0JCgnI3pubS1iYW5CdCcpLm9mZignY2xpY2snKTtcblxuXHRcdC8vIENsZWFyIHJlcXVlc3Qgc2NoZWR1bGluZ1xuXHRcdGNsZWFyVGltZW91dCh0aGlzLl9yZXF1ZXN0VGltZXIpO1xuXG5cdFx0Ly8gSGlkZSByb29tIGNyZWF0aW9uIHBhbmVsXG5cdFx0JCgnI3pubS1jcmVhdGVSb29tTW9kYWwnKS5tb2RhbCgnaGlkZScpO1xuXG5cdFx0Ly8gUmVtb3ZlIHJvb20gY3JlYXRpb24gcGFuZWwgbGlzdGVuZXJcblx0XHQkKCcjem5tLWNyZWF0ZVJvb21Nb2RhbCcpLm9mZignaGlkZGVuLmJzLm1vZGFsJyk7XG5cblx0XHQvLyBSZW1vdmUgZmlsdGVyIHBhbmVscyBsaXN0ZW5lcnNcblx0XHQkKHRoaXMuX3Jvb21GaWx0ZXIpLm9mZih0aGlzLl9yb29tRmlsdGVyLkVYUFJFU1NJT05fVVBEQVRFRF9FVkVOVCk7XG5cdFx0JCh0aGlzLl91c2VyRmlsdGVyKS5vZmYodGhpcy5fdXNlckZpbHRlci5FWFBSRVNTSU9OX1VQREFURURfRVZFTlQpO1xuXHR9XG5cblx0b25FeHRlbnNpb25Db21tYW5kKGNvbW1hbmQsIGRhdGEpXG5cdHtcblx0XHQvLyBEYXRhIHJlY2VpdmVkXG5cdFx0aWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0RBVEEpXG5cdFx0e1xuXHRcdFx0Ly8gV2UgaGF2ZSB0byBjaGVjayBpZiB0aGUgcmVzcG9uc2UgaWQgY29ycmVzcG9uZHMgdG8gdGhlIGN1cnJlbnQgcmVxdWVzdCBpZDtcblx0XHRcdC8vIGlmIG5vdCwgdGhlIHJlc3BvbnNlIGlzIGRpc2NhcmRlZCBhcyBpdCByZWZlcnMgdG8gYW4gb3V0ZGF0ZXQgcmVxdWVzdFxuXHRcdFx0Y29uc3QgcmVzcG9uc2VJZCA9IGRhdGEuZ2V0SW50KCdpZCcpO1xuXG5cdFx0XHRpZiAocmVzcG9uc2VJZCA9PSB0aGlzLl9jdXJyZW50UmVxdWVzdElkKVxuXHRcdFx0e1xuXHRcdFx0XHQvLyAtLS0gWk9ORVMgTElTVCAtLS1cblx0XHRcdFx0aWYgKGRhdGEuY29udGFpbnNLZXkoJ3pvbmVzJykpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHR0aGlzLl9zZXRab25lc0RhdGFQcm92aWRlcihkYXRhLmdldFNGU0FycmF5KCd6b25lcycpKTtcblxuXHRcdFx0XHRcdGlmICh0aGlzLl9zZWxlY3RlZFpvbmUpXG5cdFx0XHRcdFx0XHR0aGlzLl9zZXRTY29wZUxhYmVsKCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyAtLS0gUk9PTVMgTElTVCAtLS1cblx0XHRcdFx0aWYgKGRhdGEuY29udGFpbnNLZXkoJ3Jvb21zJykpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHR0aGlzLl9zZXRHcm91cHNEYXRhUHJvdmlkZXIoZGF0YS5nZXRVdGZTdHJpbmdBcnJheSgnZ3JvdXBzJykpO1xuXG5cdFx0XHRcdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdFx0XHRcdFx0Ly8gSWYgYSBudWxsIHJvb21zIGxpc3QgaXMgcmV0dXJuZWQsIHRoZSB6b25lIG11c3QgaGF2ZSBiZWVuIGRlbGV0ZWQhXG5cdFx0XHRcdFx0aWYgKCFkYXRhLmlzTnVsbCgncm9vbXMnKSlcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHR0aGlzLl9zZXRSb29tc0RhdGFQcm92aWRlcihkYXRhLmdldFNGU0FycmF5KCdyb29tcycpKTtcblxuXHRcdFx0XHRcdFx0aWYgKCF0aGlzLl9zZWxlY3RlZFJvb20pXG5cdFx0XHRcdFx0XHRcdHRoaXMuX3NldFNjb3BlTGFiZWwoKTtcblxuXHRcdFx0XHRcdFx0Ly8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5cdFx0XHRcdFx0XHQvLyBTaG93IHdhcm5pbmcgaWYgdGhlIHJvb21zIGxpc3QgZXhjZWVkcyB0aGUgc2VydmVyLXNpZGUgbGltaXRcblx0XHRcdFx0XHRcdGlmIChkYXRhLmNvbnRhaW5zS2V5KCdyU2l6ZScpKVxuXHRcdFx0XHRcdFx0XHR0aGlzLl9zaG93TGltaXRFeGNlZWRlZFdhcm5pbmcoJCgnI3pubS1yb29tTGlzdFdhcm5pbmcnKSwgJ1RoZSByZWNlaXZlZCBsaXN0IGlzIGluY29tcGxldGUsIGJlY2F1c2UgaXRzIHNpemUgKCcgKyBkYXRhLmdldEludCgnclNpemUnKSArICcgUm9vbXMpIGV4Y2VlZGVkIHRoaXMgY2xpZW50XFwncyBsaW1pdCBvZiAnICsgZGF0YS5nZXRJbnQoJ3JMaW1pdCcpICsgJzsgeW91IHNob3VsZCByZWZpbmUgeW91ciBzZWFyY2gnKTtcblx0XHRcdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRcdFx0dGhpcy5fc2hvd0xpbWl0RXhjZWVkZWRXYXJuaW5nKCQoJyN6bm0tcm9vbUxpc3RXYXJuaW5nJyksICcnKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGlmICh0aGlzLl9hY3RpdmVQYW5lbFR5cGUgPT0gJ3Jvb20nKVxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHR0aGlzLl9hY2NvcmRpb24uc2VsZWN0KCdbZGF0YS1pdGVtLXR5cGU9XCJ6b25lXCJdJyk7XG5cdFx0XHRcdFx0XHRcdHRoaXMuX2FjY29yZGlvbi5leHBhbmQoJ1tkYXRhLWl0ZW0tdHlwZT1cInpvbmVcIl0nKTtcblx0XHRcdFx0XHRcdFx0dGhpcy5fb25ab25lU2VsZWN0ZWQoKTtcblx0XHRcdFx0XHRcdFx0dGhpcy5fb25FbnRpdGllc1BhbmVsQ2hhbmdlKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gLS0tIFVTRVJTIExJU1QgLS0tXG5cdFx0XHRcdGlmIChkYXRhLmNvbnRhaW5zS2V5KCd1c2VycycpKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0Ly8gSWYgYSBudWxsIHVzZXJzIGxpc3QgaXMgcmV0dXJuZWQsIHRoZSByb29tIG11c3QgaGF2ZSBiZWVuIGRlbGV0ZWQhXG5cdFx0XHRcdFx0aWYgKCFkYXRhLmlzTnVsbCgndXNlcnMnKSlcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHR0aGlzLl9zZXRVc2Vyc0RhdGFQcm92aWRlcihkYXRhLmdldFNGU0FycmF5KCd1c2VycycpKTtcblxuXHRcdFx0XHRcdFx0Ly8gU2hvdyB3YXJuaW5nIGlmIHRoZSB1c2VycyBsaXN0IGV4Y2VlZHMgdGhlIHNlcnZlci1zaWRlIGxpbWl0XG5cdFx0XHRcdFx0XHRpZiAoZGF0YS5jb250YWluc0tleSgndVNpemUnKSlcblx0XHRcdFx0XHRcdFx0dGhpcy5fc2hvd0xpbWl0RXhjZWVkZWRXYXJuaW5nKCQoJyN6bm0tdXNlckxpc3RXYXJuaW5nJyksICdUaGUgcmVjZWl2ZWQgbGlzdCBpcyBpbmNvbXBsZXRlLCBiZWNhdXNlIGl0cyBzaXplICgnICsgZGF0YS5nZXRJbnQoJ3VTaXplJykgKyAnIHVzZXJzKSBleGNlZWRzIHRoaXMgY2xpZW50XFwncyBsaW1pdCBvZiAnICsgZGF0YS5nZXRJbnQoJ3VMaW1pdCcpICsgJzsgeW91IHNob3VsZCByZWZpbmUgeW91ciBzZWFyY2gnKTtcblx0XHRcdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRcdFx0dGhpcy5fc2hvd0xpbWl0RXhjZWVkZWRXYXJuaW5nKCQoJyN6bm0tdXNlckxpc3RXYXJuaW5nJyksICcnKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGlmICh0aGlzLl9hY3RpdmVQYW5lbFR5cGUgPT0gJ3VzZXInKVxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHR0aGlzLl9hY2NvcmRpb24uc2VsZWN0KCdbZGF0YS1pdGVtLXR5cGU9XCJyb29tXCJdJyk7XG5cdFx0XHRcdFx0XHRcdHRoaXMuX2FjY29yZGlvbi5leHBhbmQoJ1tkYXRhLWl0ZW0tdHlwZT1cInJvb21cIl0nKTtcblx0XHRcdFx0XHRcdFx0dGhpcy5fb25Sb29tU2VsZWN0ZWQoKTtcblx0XHRcdFx0XHRcdFx0dGhpcy5fb25FbnRpdGllc1BhbmVsQ2hhbmdlKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gLS0tIE1PTklUT1JFRCBEQVRBIC0tLVxuXHRcdFx0XHRpZiAoZGF0YS5jb250YWluc0tleSgnbW9uaXRvcmVkJykpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRjb25zdCB6b25lID0gZGF0YS5nZXRTRlNPYmplY3QoJ21vbml0b3JlZCcpLmdldFV0ZlN0cmluZygnem9uZScpO1xuXHRcdFx0XHRcdGNvbnN0IHR5cGUgPSBkYXRhLmdldFNGU09iamVjdCgnbW9uaXRvcmVkJykuZ2V0VXRmU3RyaW5nKCd0eXBlJyk7XG5cdFx0XHRcdFx0Y29uc3QgbmFtZSA9IGRhdGEuZ2V0U0ZTT2JqZWN0KCdtb25pdG9yZWQnKS5nZXRVdGZTdHJpbmcoJ25hbWUnKTtcblxuXHRcdFx0XHRcdGlmICh6b25lID09IHRoaXMuX21vbml0b3JlZFpvbmUgJiYgdHlwZSA9PSB0aGlzLl9tb25pdG9yZWRUeXBlICYmIG5hbWUgPT0gdGhpcy5fbW9uaXRvcmVkTmFtZSlcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRpZiAoIWRhdGEuZ2V0U0ZTT2JqZWN0KCdtb25pdG9yZWQnKS5pc051bGwoJ3BhcmFtcycpKVxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRjb25zdCBwYXJhbXMgPSBkYXRhLmdldFNGU09iamVjdCgnbW9uaXRvcmVkJykuZ2V0U0ZTQXJyYXkoJ3BhcmFtcycpO1xuXG5cdFx0XHRcdFx0XHRcdHRoaXMuX3NldE1vbml0b3JpbmdJbnRlcmZhY2UoKTtcblxuXHRcdFx0XHRcdFx0XHQvLyBCdWlsZCBpbnRlcmZhY2Vcblx0XHRcdFx0XHRcdFx0aWYgKCF0aGlzLl9pc0VkaXRpbmcpXG5cdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLl9pbnRlcmZhY2VCdWlsZGVyLmJ1aWxkSW50ZXJmYWNlKHBhcmFtcywgYHpubS0ke3RoaXMuX21vbml0b3JlZFR5cGV9VGFiTmF2aWdhdG9yYCwgdHJ1ZSk7XG5cblx0XHRcdFx0XHRcdFx0XHRpZiAoIXRoaXMuX3NraXBJbml0VGFicylcblx0XHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0XHQkKGAjem5tLSR7dGhpcy5fbW9uaXRvcmVkVHlwZX1UYWJOYXZpZ2F0b3IgI3RhYnNgKS5zY3JvbGxpbmdUYWJzKHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0Ym9vdHN0cmFwVmVyc2lvbjogNCxcblx0XHRcdFx0XHRcdFx0XHRcdFx0c2Nyb2xsVG9UYWJFZGdlOiB0cnVlLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRlbmFibGVTd2lwaW5nOiB0cnVlLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRkaXNhYmxlU2Nyb2xsQXJyb3dzT25GdWxseVNjcm9sbGVkOiB0cnVlLFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRjc3NDbGFzc0xlZnRBcnJvdzogJ2ZhIGZhLWNoZXZyb24tbGVmdCcsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGNzc0NsYXNzUmlnaHRBcnJvdzogJ2ZhIGZhLWNoZXZyb24tcmlnaHQnXG5cdFx0XHRcdFx0XHRcdFx0XHR9KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0dGhpcy5fc2tpcEluaXRUYWJzID0gdHJ1ZTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gU2V0IGZpcnN0IHRhYiBwYW5lbCBhcyBhY3RpdmVcblx0XHRcdFx0XHRcdFx0XHRcdHRoaXMuX2ludGVyZmFjZUJ1aWxkZXIuYWN0aXZhdGVGaXJzdFRhYlBhbmVsKCk7XG5cblx0XHRcdFx0XHRcdFx0XHRcdC8vIFJlZHJhdyB0aW1lIHJhbmdlIHNsaWRlciB0byBzZXQgaXRzIHdpZHRoXG5cdFx0XHRcdFx0XHRcdFx0XHR0aGlzLl90aW1lU2xpZGVyLnJlc2l6ZSgpO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBBZGQgbGlzdGVuZXIgdG8gcmVkcmF3IGFsbCBjaGFydHMgb24gdGFiIGNoYW5nZVxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gKHRvIHdvcmsgYXJvdW5kIGFuIGlzc3VlIHdpdGggdGhlIGNoYXJ0IHJlc2l6aW5nIHRvIGRlZmF1bHQgd2lkdGggd2hlbiBwYW5lIGlzIGhpZGRlbilcblx0XHRcdFx0XHRcdFx0XHRcdCQoJ2FbZGF0YS10b2dnbGU9XCJ0YWJcIl0nKS5vbignc2hvd24uYnMudGFiJywgJC5wcm94eSh0aGlzLl9vbldpbmRvd1Jlc2l6ZSwgdGhpcykpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdC8vIERpc2FibGUgY2F0ZWdvcmllc1xuXHRcdFx0XHRcdFx0XHRsZXQgZGlzYWJsZWRDYXQgPSAoZGF0YS5nZXRTRlNPYmplY3QoJ21vbml0b3JlZCcpLmNvbnRhaW5zS2V5KCdleGNsdWRlJykgPyBkYXRhLmdldFNGU09iamVjdCgnbW9uaXRvcmVkJykuZ2V0VXRmU3RyaW5nQXJyYXkoJ2V4Y2x1ZGUnKSA6IFtdKTtcblxuXHRcdFx0XHRcdFx0XHRmb3IgKGxldCBjYXQgb2YgZGlzYWJsZWRDYXQpXG5cdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHRsZXQgbmF2TGluayA9ICQoYCN6bm0tJHt0aGlzLl9tb25pdG9yZWRUeXBlfVRhYk5hdmlnYXRvciAjdGFicyAjdGFiLSR7Y2F0fWApO1xuXG5cdFx0XHRcdFx0XHRcdFx0bmF2TGluay5hZGRDbGFzcygnZGlzYWJsZWQnKTtcblx0XHRcdFx0XHRcdFx0XHRuYXZMaW5rLmF0dHIoJ3RhYmluZGV4JywgLTEpO1xuXHRcdFx0XHRcdFx0XHRcdG5hdkxpbmsuYXR0cignYXJpYS1kaXNhYmxlZCcsIHRydWUpO1xuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0aWYgKHRoaXMuX21vbml0b3JlZFR5cGUgPT0gdGhpcy5NT05JVE9SRURfVFlQRV9aT05FKVxuXHRcdFx0XHRcdFx0XHRcdHRoaXMuX3Nob3dab25lVHJhZmZpY0RhdGEoZGF0YS5nZXRTRlNPYmplY3QoJ21vbml0b3JlZCcpLmdldFNGU09iamVjdCgndHJhZmZpYycpKTtcblxuXHRcdFx0XHRcdFx0XHRpZiAodGhpcy5fbW9uaXRvcmVkVHlwZSA9PSB0aGlzLk1PTklUT1JFRF9UWVBFX1VTRVIpXG5cdFx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0XHQvLyBTdGF0c1xuXHRcdFx0XHRcdFx0XHRcdHRoaXMuX3Nob3dVc2VyU3RhdHNEYXRhKGRhdGEuZ2V0U0ZTT2JqZWN0KCdtb25pdG9yZWQnKS5nZXRTRlNPYmplY3QoJ3N0YXRzJykpO1xuXG5cdFx0XHRcdFx0XHRcdFx0Ly8gTlBDXG5cdFx0XHRcdFx0XHRcdFx0Y29uc3QgaXNOcGMgPSBkYXRhLmdldFNGU09iamVjdCgnbW9uaXRvcmVkJykuZ2V0Qm9vbCgnbnBjJyk7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBEaXNhYmxlIGtpY2sgYW5kIGJhbiBidXR0b25zXG5cdFx0XHRcdFx0XHRcdFx0JCgnI3pubS1raWNrQnQnKS5hdHRyKCdkaXNhYmxlZCcsIGlzTnBjKTtcblx0XHRcdFx0XHRcdFx0XHQkKCcjem5tLWJhbkJ0JykuYXR0cignZGlzYWJsZWQnLCBpc05wYyk7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBHZW8tbG9jYXRpb25cblx0XHRcdFx0XHRcdFx0XHRjb25zdCBnZW9Mb2NEYXRhID0gZGF0YS5nZXRTRlNPYmplY3QoJ21vbml0b3JlZCcpLmdldFNGU09iamVjdCgnZ2VvTG9jJyk7XG5cdFx0XHRcdFx0XHRcdFx0dGhpcy5fc2V0R2VvTG9jYXRpb25VSShnZW9Mb2NEYXRhKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHQvLyBTaG93IGFsZXJ0XG5cdFx0XHRcdFx0XHRcdHRoaXMuc2hlbGxDdHJsLnNob3dTaW1wbGVBbGVydChgVGhlICR7Y2FwaXRhbGl6ZUZpcnN0KHRoaXMuX21vbml0b3JlZFR5cGUpfSBiZWluZyBtb25pdG9yZWQgaXMgbm8gbW9yZSBhdmFpbGFibGUgb24gdGhlIHNlcnZlciwgcGxlYXNlIHNlbGVjdCBhbm90aGVyIG9uZS5gLCBmYWxzZSk7XG5cblx0XHRcdFx0XHRcdFx0Ly8gQ2FuY2VsIG1vbml0b3Jpbmdcblx0XHRcdFx0XHRcdFx0dGhpcy5fb25DbG9zZU1vbml0b3JCdENsaWNrKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0ZWxzZSBpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfVVBEQVRFX0VSUk9SKVxuXHRcdHtcblx0XHRcdGlmIChkYXRhLmdldFV0ZlN0cmluZygnem9uZScpID09IHRoaXMuX21vbml0b3JlZFpvbmVcblx0XHRcdFx0JiYgZGF0YS5nZXRVdGZTdHJpbmcoJ3R5cGUnKSA9PSAgdGhpcy5fbW9uaXRvcmVkVHlwZVxuXHRcdFx0XHQmJiBkYXRhLmdldFV0ZlN0cmluZygnbmFtZScpID09ICB0aGlzLl9tb25pdG9yZWROYW1lKVxuXHRcdFx0e1xuXHRcdFx0XHQvLyBTaG93IGFsZXJ0XG5cdFx0XHRcdHRoaXMuc2hlbGxDdHJsLnNob3dTaW1wbGVBbGVydChgVW5hYmxlIHRvIHVwZGF0ZSAke2NhcGl0YWxpemVGaXJzdCh0aGlzLl9tb25pdG9yZWRUeXBlKX0gc2V0dGluZ3M7IHRoZSBmb2xsb3dpbmcgZXJyb3Igd2FzIHJlcG9ydGVkOiAke2RhdGEuZ2V0VXRmU3RyaW5nKCdtZXNzYWdlJyl9LmApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX1JPT01fQ09ORklHKVxuXHRcdHtcblx0XHRcdC8vIFJlLWVuYWJsZSBDcmVhdGUgYnV0dG9uXG5cdFx0XHQkKCcjem5tLWNyZWF0ZVJvb21CdCcpLmF0dHIoJ2Rpc2FibGVkJywgZmFsc2UpO1xuXG5cdFx0XHQvLyBTaG93IFJvb20gY3JlYXRpb24gcGFuZWxcblx0XHRcdHRoaXMuX3Nob3dSb29tQ3JlYXRpb25QYW5lbChkYXRhLmdldFNGU0FycmF5KCdzZXR0aW5ncycpKTtcblx0XHR9XG5cblx0XHRlbHNlIGlmIChjb21tYW5kID09IHRoaXMuUkVTUF9ST09NX0NPTkZJR19FUlJPUilcblx0XHR7XG5cdFx0XHQvLyBSZS1lbmFibGUgQ3JlYXRlIGJ1dHRvblxuXHRcdFx0JCgnI3pubS1jcmVhdGVSb29tQnQnKS5hdHRyKCdkaXNhYmxlZCcsIGZhbHNlKTtcblxuXHRcdFx0Ly8gU2hvdyBhbiBhbGVydFxuXHRcdFx0dGhpcy5zaGVsbEN0cmwuc2hvd1NpbXBsZUFsZXJ0KGRhdGEuZ2V0VXRmU3RyaW5nKCdlcnJvcicpKTtcblx0XHR9XG5cblx0XHRlbHNlIGlmIChjb21tYW5kID09IHRoaXMuUkVTUF9ST09NX0NSRUFURUQpXG5cdFx0e1xuXHRcdFx0Ly8gUmUtZW5hYmxlIHJvb20gY3JlYXRpb24gcGFuZWxcblx0XHRcdHRoaXMuX2VuYWJsZUNyZWF0ZVJvb21QYW5lbCh0cnVlKTtcblxuXHRcdFx0Ly8gSGlkZSByb29tIGNyZWF0aW9uIHBhbmVsXG5cdFx0XHQkKCcjem5tLWNyZWF0ZVJvb21Nb2RhbCcpLm1vZGFsKCdoaWRlJyk7XG5cblx0XHRcdC8vIFVwZGF0ZSByb29tcyBsaXN0XG5cdFx0XHR0aGlzLl9yZXF1ZXN0RGF0YSh0cnVlKTtcblx0XHR9XG5cblx0XHRlbHNlIGlmIChjb21tYW5kID09IHRoaXMuUkVTUF9ST09NX0NSRUFUSU9OX0VSUk9SKVxuXHRcdHtcblx0XHRcdC8vIERpc3BsYXkgZXJyb3IgbWVzc2FnZVxuXHRcdFx0JCgnI3pubS1jcmVhdGVSb29tRXJyb3InKS50ZXh0KGRhdGEuZ2V0VXRmU3RyaW5nKCdlcnJvcicpKTtcblx0XHRcdCQoJyN6bm0tY3JlYXRlUm9vbUVycm9yJykuc2hvdygpO1xuXG5cdFx0XHQvLyBSZS1lbmFibGUgcm9vbSBjcmVhdGlvbiBwYW5lbFxuXHRcdFx0dGhpcy5fZW5hYmxlQ3JlYXRlUm9vbVBhbmVsKHRydWUpO1xuXHRcdH1cblxuXHRcdC8vIFVuZXhwZWN0ZWQgZXJyb3IgcmVjZWl2ZWRcblx0XHQvLyBUaGlzIGVycm9yIGlzIHJldHVybmVkIGluIGNhc2Ugc29tZXRoaW5nIHdlbnQgd3Jvbmcgd2hlbiByZXRyaWV2aW5nIHRoZSBtb25pdG9yZWQgZW50aXR5IHBhcmFtZXRlcnMsXG5cdFx0Ly8gc28gd2UgaGF2ZSB0byBzdG9wIHJlcXVlc3RpbmcgdGhlIHNhbWUgZW50aXR5XG5cdFx0ZWxzZSBpZiAoY29tbWFuZCA9PSB0aGlzLlJFU1BfVU5FWFBFQ1RFRF9FUlJPUilcblx0XHR7XG5cdFx0XHQvLyBDYW5jZWwgbW9uaXRvcmluZ1xuXHRcdFx0dGhpcy5fb25DbG9zZU1vbml0b3JCdENsaWNrKCk7XG5cblx0XHRcdC8vIFNob3cgYW4gYWxlcnRcblx0XHRcdHRoaXMuc2hlbGxDdHJsLnNob3dTaW1wbGVBbGVydChkYXRhLmdldFV0ZlN0cmluZygnZXJyb3InKSk7XG5cdFx0fVxuXG5cdFx0Ly8gRXh0ZW5zaW9uIChab25lIG9yIFJvb20pIGxvZyBtZXNzYWdlcyByZWNlaXZlZFxuXHRcdGVsc2UgaWYgKGNvbW1hbmQgPT0gdGhpcy5SRVNQX0xPR19NRVNTQUdFUylcblx0XHR7XG5cdFx0XHRsZXQgbG9nRW50cmllcyA9IGRhdGEuZ2V0U0ZTQXJyYXkoJ2VudHJpZXMnKTtcblxuXHRcdFx0Zm9yIChsZXQgZSA9IDA7IGUgPCBsb2dFbnRyaWVzLnNpemUoKTsgZSsrKVxuXHRcdFx0e1xuXHRcdFx0XHRsZXQgbG9nRW50cnkgPSBsb2dFbnRyaWVzLmdldFNGU09iamVjdChlKTtcblxuXHRcdFx0XHRjb25zdCBsb2dab25lID0gbG9nRW50cnkuZ2V0VXRmU3RyaW5nKCd6b25lJyk7XG5cdFx0XHRcdGNvbnN0IGxvZ1Jvb20gPSBsb2dFbnRyeS5nZXRVdGZTdHJpbmcoJ3Jvb20nKTtcblxuXHRcdFx0XHQvLyBDaGVjayBpZiB0aGUgem9uZSBpcyBjdXJyZW50bHkgbW9uaXRvcmVkXG5cdFx0XHRcdGlmICh0aGlzLl9tb25pdG9yZWRab25lID09IGxvZ1pvbmUpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHQvLyBjb25zb2xlLmxvZyhsb2dFbnRyeS5nZXRMb25nKCd0aW1lJykpXG5cdFx0XHRcdFx0Ly8gY29uc29sZS5sb2cobmV3IERhdGUobG9nRW50cnkuZ2V0TG9uZygndGltZScpKVxuXG5cdFx0XHRcdFx0bGV0IGVsZSA9IHtcblx0XHRcdFx0XHRcdHRpbWVzdGFtcDoga2VuZG8udG9TdHJpbmcobmV3IERhdGUobG9nRW50cnkuZ2V0TG9uZygndGltZScpKSwgJ2RkL01NL3l5eXkgSEg6bW06c3MnKSxcblx0XHRcdFx0XHRcdGxldmVsOiBsb2dFbnRyeS5nZXRVdGZTdHJpbmcoJ2xldmVsJyksXG5cdFx0XHRcdFx0XHRtZXNzYWdlOiBsb2dFbnRyeS5nZXRVdGZTdHJpbmcoJ21zZycpLFxuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHRpZiAodGhpcy5fbW9uaXRvcmVkVHlwZSA9PSB0aGlzLk1PTklUT1JFRF9UWVBFX1pPTkUgJiYgbG9nUm9vbSA9PSAnJylcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHQvLyBBZGQgdG8gem9uZSBleHRlbnNpb24gbG9nXG5cdFx0XHRcdFx0XHR0aGlzLl9hZGRMb2dFbnRyeVRvR3JpZCh0aGlzLl96b25lRXh0TG9nR3JpZCwgZWxlKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGlmICh0aGlzLl9tb25pdG9yZWRUeXBlID09IHRoaXMuTU9OSVRPUkVEX1RZUEVfUk9PTSAmJiB0aGlzLl9tb25pdG9yZWROYW1lID09IGxvZ1Jvb20pXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdC8vIEFkZCB0byByb29tIGV4dGVuc2lvbiBsb2dcblx0XHRcdFx0XHRcdFx0dGhpcy5fYWRkTG9nRW50cnlUb0dyaWQodGhpcy5fcm9vbUV4dExvZ0dyaWQsIGVsZSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8gVUkgRVZFTlQgTElTVEVORVJTXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0X29uVXBkYXRlSW50ZXJ2YWxDaGFuZ2UoKVxuXHR7XG5cdFx0Ly8gUmVxdWVzdCBkYXRhIHRvIHNlcnZlclxuXHRcdHRoaXMuX3JlcXVlc3REYXRhKGZhbHNlKTtcblx0fVxuXG5cdF9vbkVudGl0aWVzUGFuZWxDaGFuZ2UoKVxuXHR7XG5cdFx0Ly8gU2V0IG1haW4gY29udHJvbHMgc3RhdGVcblx0XHR0aGlzLl9zZXRNYWluQ29udHJvbHNFbmFibGVkKCk7XG5cblx0XHQvLyBSZXF1ZXN0IGRhdGEgdG8gc2VydmVyXG5cdFx0dGhpcy5fcmVxdWVzdERhdGEodHJ1ZSk7XG5cdH1cblxuXHQvKipcblx0ICogVXBkYXRlIHRoZSBTY29wZSBsYWJlbCBpbiB0aGUgUm9vbXMgcGFuZWwuXG5cdCAqL1xuXHRfb25ab25lU2VsZWN0ZWQoKVxuXHR7XG5cdFx0Ly8gQ2xlYXIgUm9vbSBhbmQgVXNlciBsaXN0c1xuXHRcdHRoaXMuX3Jlc2V0Um9vbUxpc3QoKTtcblx0XHR0aGlzLl9yZXNldFVzZXJMaXN0KCk7XG5cblx0XHQvLyBTZXQgc2NvcGUgbGFiZWxcblx0XHR0aGlzLl9zZXRTY29wZUxhYmVsKCk7XG5cblx0XHQvLyBFbmFibGUvZGlzYWJsZSBSb29tIGFuZCBVc2VyIHRvb2xzXG5cdFx0Y29uc3QgZGlzYWJsZWQgPSB0aGlzLl9zZWxlY3RlZFpvbmUgPT0gdW5kZWZpbmVkO1xuXG5cdFx0Ly8gKE5PVEU6IHRoaXMgZW5hYmxlcy9kaXNhYmxlcyB3aG9sZSBmaWVsZHNldDsgdGhpcyBkb2Vzbid0IGFmZmVjdCBLZW5kbyBEcm9wRG93biwgc28gd2UgaGF2ZSB0byBkbyBpdCBtYW51YWxseSlcblx0XHQkKCcjcm9vbVRvb2xzJykuYXR0cignZGlzYWJsZWQnLCBkaXNhYmxlZCk7XG5cdFx0JCgnI3VzZXJUb29scycpLmF0dHIoJ2Rpc2FibGVkJywgZGlzYWJsZWQpO1xuXG5cdFx0dGhpcy5fZ3JvdXBzRHJvcERvd24uZW5hYmxlKCFkaXNhYmxlZCk7XG5cblx0XHQvLyBTZXQgbWFpbiBjb250cm9scyBzdGF0ZVxuXHRcdHRoaXMuX3NldE1haW5Db250cm9sc0VuYWJsZWQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBVcGRhdGUgdGhlIFNjb3BlIGxhYmVsIGluIHRoZSBVc2VycyBwYW5lbC5cblx0ICovXG5cdF9vblJvb21TZWxlY3RlZCgpXG5cdHtcblx0XHQvLyBDbGVhciBVc2VyIGxpc3Rcblx0XHR0aGlzLl9yZXNldFVzZXJMaXN0KCk7XG5cblx0XHQvLyBTZXQgc2NvcGUgbGFiZWxcblx0XHR0aGlzLl9zZXRTY29wZUxhYmVsKCk7XG5cblx0XHQvLyBFbmFibGUgUmVtb3ZlIGJ1dHRvblxuXHRcdCQoJyN6bm0tcmVtb3ZlUm9vbUJ0JykuYXR0cignZGlzYWJsZWQnLCB0aGlzLl9zZWxlY3RlZFJvb20gPT0gdW5kZWZpbmVkKTtcblxuXHRcdC8vIFNldCBtYWluIGNvbnRyb2xzIHN0YXRlXG5cdFx0dGhpcy5fc2V0TWFpbkNvbnRyb2xzRW5hYmxlZCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFVwZGF0ZSB0aGUgc2NvcGUgbGFiZWwgaW4gdGhlIFVzZXJzIHBhbmVsLlxuXHQgKi9cblx0X29uR3JvdXBDaGFuZ2UoKVxuXHR7XG5cdFx0Ly8gQ2xlYXIgUm9vbSBhbmQgVXNlciBsaXN0c1xuXHRcdHRoaXMuX3Jlc2V0Um9vbUxpc3QoKTtcblx0XHR0aGlzLl9yZXNldFVzZXJMaXN0KCk7XG5cblx0XHQvLyBTZXQgc2NvcGUgbGFiZWxcblx0XHR0aGlzLl9zZXRTY29wZUxhYmVsKCk7XG5cblx0XHQvLyBSZXF1ZXN0IGRhdGEgdG8gc2VydmVyXG5cdFx0dGhpcy5fcmVxdWVzdERhdGEodHJ1ZSk7XG5cblx0XHQvLyBTZXQgbWFpbiBjb250cm9scyBzdGF0ZVxuXHRcdHRoaXMuX3NldE1haW5Db250cm9sc0VuYWJsZWQoKTtcblx0fVxuXG5cdF9vblVzZXJTZWxlY3RlZCgpXG5cdHtcblx0XHQvLyBTZXQgbWFpbiBjb250cm9scyBzdGF0ZVxuXHRcdHRoaXMuX3NldE1haW5Db250cm9sc0VuYWJsZWQoKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBTaG93IHJvb20gY3JlYXRpb24gcGFuZWwuXG5cdCAqL1xuXHRfb25DcmVhdGVSb29tQnRDbGljaygpXG5cdHtcblx0XHQvLyBEaXNhYmxlIENyZWF0ZSBidXR0b25cblx0XHQkKCcjem5tLWNyZWF0ZVJvb21CdCcpLmF0dHIoJ2Rpc2FibGVkJywgdHJ1ZSk7XG5cblx0XHQvLyBSZXF1ZXN0IGRlZmF1bHQgcm9vbSBzZXR0aW5ncyB0byBleHRlbnNpb25cblx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX0dFVF9ST09NX0NPTkZJRyk7XG5cdH1cblxuXHQvKipcblx0ICogUmVtb3ZlIGV4aXN0aW5nIHJvb20uXG5cdCAqL1xuXHRfb25SZW1vdmVSb29tQnRDbGljaygpXG5cdHtcblx0XHR0aGlzLnNoZWxsQ3RybC5zaG93Q29uZmlybVdhcm5pbmcoJ0FyZSB5b3Ugc3VyZSB5b3Ugd2FudCB0byByZW1vdmUgdGhlIHNlbGVjdGVkIFJvb20/JywgJC5wcm94eSh0aGlzLl9vblJlbW92ZVJlbW92ZUNvbmZpcm0sIHRoaXMpKTtcblx0fVxuXG5cdF9vblJlbW92ZVJlbW92ZUNvbmZpcm0oKVxuXHR7XG5cdFx0Y29uc3Qgc2VsZWN0ZWRab25lID0gdGhpcy5fem9uZUxpc3RCb3guZGF0YUl0ZW0odGhpcy5fem9uZUxpc3RCb3guc2VsZWN0KCkpO1xuXHRcdGxldCBzZWxlY3RlZFJvb20gPSB0aGlzLl9yb29tTGlzdEJveC5kYXRhSXRlbSh0aGlzLl9yb29tTGlzdEJveC5zZWxlY3QoKSk7XG5cblx0XHRpZiAoc2VsZWN0ZWRSb29tKVxuXHRcdHtcblx0XHRcdC8vIFNlbmQgcmVxdWVzdCB0byBzZXJ2ZXJcblx0XHRcdGxldCBwYXJhbXMgPSBuZXcgU0ZTMlguU0ZTT2JqZWN0KCk7XG5cdFx0XHRwYXJhbXMucHV0VXRmU3RyaW5nKCd6b25lJywgc2VsZWN0ZWRab25lLm5hbWUpO1xuXHRcdFx0cGFyYW1zLnB1dFV0ZlN0cmluZygncm9vbScsIHNlbGVjdGVkUm9vbS5uYW1lKTtcblxuXHRcdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9SRU1PVkVfUk9PTSwgcGFyYW1zKTtcblxuXHRcdFx0Ly8gUmVxdWVzdCBkYXRhIHRvIHNlcnZlciB0byB1cGRhdGUgdGhlIHJvb21zIGxpc3Rcblx0XHRcdHRoaXMuX3JlcXVlc3REYXRhKHRydWUpO1xuXHRcdH1cblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmUgY29udGVudCBvZiByb29tIGNyZWF0aW9uIHBhbmVsLlxuXHQgKi9cblx0X29uQ3JlYXRlUm9vbU1vZGFsSGlkZGVuKGUpXG5cdHtcblx0XHQvLyBJZiBhIG5lc3RlZCBtb2RhbCBpcyBvcGVuZWQsIGl0cyBjbG9zaW5nIGNhdXNlcyB0aGUgcGFyZW50IG1vZGFsIHRvIGJlIGNsb3NlZCB0b28gKEJvb3RzdHJhcCBkb2Vzbid0IHN1cHBvcnQgbmVzdGVkIG1vZGFscylcblx0XHQvLyBBcyBhIHdvcmthcm91bmQsIGhlcmUgd2UgcmVzZXQgdGhlIGNzcyBjbGFzcyAnbW9kYWwtb3Blbicgd2hlbiB0aGUgbmVzdGVkIG1vZGFsIGlzIGNsb3NlZCBhbmQgc2tpcCBldmVyeXRoaW5nIGVsc2Vcblx0XHQvLyBJbiBhZGRpdGlvbiB3ZSBoYWQgdG8gdXNlIGEgY3VzdG9tIGxpc3RlbmVyIG9uIHRoZSBjbG9zZS9jYW5jZWwgYnV0dG9ucyBvZiB0aGUgbmVzdGVkIG1vZGFsIChzZWUgY29uZmlnLWdyaWQuanMgZm9yIGV4YW1wbGUpXG5cdFx0aWYgKGUudGFyZ2V0ICE9PSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnem5tLWNyZWF0ZVJvb21Nb2RhbCcpKVxuXHRcdHtcblx0XHRcdCQoJ2JvZHknKS5hZGRDbGFzcygnbW9kYWwtb3BlbicpXG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gRGVzdHJveSBzY3JvbGxpbmcgdGFicyBpbiByb29tIGNyZWF0aW9uIHBhbmVsXG5cdFx0JCgnI3pubS1yb29tQ3JlYXRvclRhYk5hdiAjdGFicycpLnNjcm9sbGluZ1RhYnMoJ2Rlc3Ryb3knKTtcblxuXHRcdC8vIFJlbW92ZSBhbGwgdGFiIG5hdmlnYXRvciBjb250ZW50XG5cdFx0dGhpcy5fcm9vbUNyZWF0aW9uSUJ1aWxkZXIuZGVzdHJveUludGVyZmFjZSgpO1xuXG5cdFx0Ly8gUmVtb3ZlIGxpc3RlbmVyIGZvciBjdXN0b20gYWN0aW9ucyB0cmlnZ2VyZWQgYnkgY29uZmlndXJhdGlvbiBpbnRlcmZhY2Vcblx0XHQkKCcjem5tLXJvb21DcmVhdG9yVGFiTmF2Jykub2ZmKCd2YWx1ZS1zZXQnKTtcblxuXHRcdC8vIFJlc2V0IGFuZCBoaWRlIGVycm9yIG1lc3NhZ2Vcblx0XHR0aGlzLl9yZXNldFJvb21DcmVhdGlvbkVycm9yKCk7XG5cdH1cblxuXHRfb25Db25maWdWYWx1ZVNldChlKSAvLyBTQU1FIE1FVEhPRCBEVVBMSUNBVEVEIElOIHpvbmUtY29uZmlndXJhdG9yLmpzXG5cdHtcblx0XHRjb25zdCBjb25maWdQYXJhbSA9IGUudGFyZ2V0LmRhdGE7XG5cblx0XHQvLyBIYW5kbGUgZXh0ZW5zaW9uIG5hbWUvdHlwZSBkcm9wZG93bnMgdXBkYXRlIGFuZCB1cGRhdGUgdGhlIG1haW4gY2xhc3MgZHJvcGRvd24gZGF0YXNvdXJjZSBhY2NvcmRpbmdseVxuXHRcdGlmIChjb25maWdQYXJhbS5uYW1lID09ICdleHRlbnNpb24ubmFtZScgfHwgY29uZmlnUGFyYW0ubmFtZSA9PSAnZXh0ZW5zaW9uLnR5cGUnIHx8IGNvbmZpZ1BhcmFtLm5hbWUgPT0gJ2V4dGVuc2lvbi5maWx0ZXJDbGFzcycpXG5cdFx0e1xuXHRcdFx0Ly8gQWxsIGludm9sdmVkIENvbmZpZ0Zvcm1JdGVtcyBtdXN0IGJlIGF2YWlsYWJsZSBhbmQgaW5pdGlhbGl6ZWQgdG8gcHJvY2VlZFxuXHRcdFx0Y29uc3QgbmFtZUZvcm1JdGVtID0gdGhpcy5fcm9vbUNyZWF0aW9uSUJ1aWxkZXIuZ2V0Q29uZmlnRm9ybUl0ZW0oJ2V4dGVuc2lvbi5uYW1lJyk7XG5cdFx0XHRjb25zdCB0eXBlRm9ybUl0ZW0gPSB0aGlzLl9yb29tQ3JlYXRpb25JQnVpbGRlci5nZXRDb25maWdGb3JtSXRlbSgnZXh0ZW5zaW9uLnR5cGUnKTtcblx0XHRcdGNvbnN0IGNsYXNzRm9ybUl0ZW0gPSB0aGlzLl9yb29tQ3JlYXRpb25JQnVpbGRlci5nZXRDb25maWdGb3JtSXRlbSgnZXh0ZW5zaW9uLmZpbGUnKTtcblx0XHRcdGNvbnN0IGZpbHRlckZvcm1JdGVtID0gdGhpcy5fcm9vbUNyZWF0aW9uSUJ1aWxkZXIuZ2V0Q29uZmlnRm9ybUl0ZW0oJ2V4dGVuc2lvbi5maWx0ZXJDbGFzcycpO1xuXG5cdFx0XHRpZiAobmFtZUZvcm1JdGVtICE9IG51bGwgJiYgdHlwZUZvcm1JdGVtICE9IG51bGwgJiYgY2xhc3NGb3JtSXRlbSAhPSBudWxsICYmIGZpbHRlckZvcm1JdGVtICE9IG51bGwpXG5cdFx0XHR7XG5cdFx0XHRcdGNvbnN0IHNvdXJjZSA9IG5hbWVGb3JtSXRlbS5kYXRhO1xuXHRcdFx0XHRsZXQgY2xhc3Nlc0xpc3QgPSBbXTtcblxuXHRcdFx0XHRsZXQgZGF0YSA9IHNvdXJjZS50cmlnZ2VyRGF0YTtcblx0XHRcdFx0Zm9yIChsZXQgaSA9IDA7IGkgPCBkYXRhLnNpemUoKTsgaSsrKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0bGV0IGV4dCA9IGRhdGEuZ2V0U0ZTT2JqZWN0KGkpO1xuXG5cdFx0XHRcdFx0aWYgKGV4dC5nZXRVdGZTdHJpbmcoJ25hbWUnKSA9PSBuYW1lRm9ybUl0ZW0uZGF0YS52YWx1ZSAmJiBleHQuZ2V0VXRmU3RyaW5nKCd0eXBlJykgPT0gdHlwZUZvcm1JdGVtLmRhdGEudmFsdWUpXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0bGV0IGNsYXNzZXMgPSBleHQuZ2V0VXRmU3RyaW5nKCdjbGFzc2VzU3RyaW5nJykuc3BsaXQoJywnKTtcblxuXHRcdFx0XHRcdFx0aWYgKGZpbHRlckZvcm1JdGVtLmRhdGEudmFsdWUgPT0gdHJ1ZSlcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0bGV0IGZpbHRlcmVkQ2xhc3NlcyA9IGNsYXNzZXMuZmlsdGVyKGZpbHRlckNsYXNzTmFtZSk7XG5cdFx0XHRcdFx0XHRcdGNsYXNzZXMgPSBmaWx0ZXJlZENsYXNzZXM7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdGNsYXNzZXNMaXN0ID0gY2xhc3Nlc0xpc3QuY29uY2F0KGNsYXNzZXMpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdGxldCBjdXJyZW50Q2xhc3MgPSBjbGFzc0Zvcm1JdGVtLmRhdGEudmFsdWU7XG5cblx0XHRcdFx0Ly8gSWYgdGhlIGNsYXNzZXMgbGlzdCBkb2Vzbid0IGNvbnRhaW4gdGhlIGN1cnJlbnQgdmFsdWUsIGNyZWF0ZSBhbiBlbXB0eSBlbnRyeSBhbmQgcmVzZXQgdGhlIHZhbHVlXG5cdFx0XHRcdGlmIChjbGFzc2VzTGlzdC5pbmRleE9mKGN1cnJlbnRDbGFzcykgPCAwKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0aWYgKGNsYXNzZXNMaXN0Lmxlbmd0aCA9PSAwKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGNsYXNzZXNMaXN0LnB1c2goJycpO1xuXHRcdFx0XHRcdFx0Y3VycmVudENsYXNzID0gJyc7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHRcdGN1cnJlbnRDbGFzcyA9IGNsYXNzZXNMaXN0WzBdO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0bGV0IG1haW5DbGFzc0Ryb3BEb3duID0gY2xhc3NGb3JtSXRlbS5faW5uZXJXaWRnZXQ7XG5cdFx0XHRcdG1haW5DbGFzc0Ryb3BEb3duLnNldERhdGFTb3VyY2UoY2xhc3Nlc0xpc3QpO1xuXG5cdFx0XHRcdGNsYXNzRm9ybUl0ZW0uZGF0YS52YWx1ZSA9IGN1cnJlbnRDbGFzcztcblx0XHRcdFx0Y2xhc3NGb3JtSXRlbS5fc2V0V2lkZ2V0VmFsdWUoKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHRfb25Sb29tQ3JlYXRvckNyZWF0ZUJ0Q2xpY2soKVxuXHR7XG5cdFx0Ly8gUmVzZXQgYW5kIGhpZGUgZXJyb3IgbWVzc2FnZVxuXHRcdHRoaXMuX3Jlc2V0Um9vbUNyZWF0aW9uRXJyb3IoKTtcblxuXHRcdC8vIENoZWNrIHZhbGlkaXR5XG5cdFx0aWYgKHRoaXMuX3Jvb21DcmVhdGlvbklCdWlsZGVyLmNoZWNrSXNWYWxpZCgpKVxuXHRcdHtcblx0XHRcdGxldCBjaGFuZ2VzID0gdGhpcy5fcm9vbUNyZWF0aW9uSUJ1aWxkZXIuZ2V0Q2hhbmdlZERhdGEoKTtcblxuXHRcdFx0aWYgKGNoYW5nZXMuc2l6ZSgpID4gMClcblx0XHRcdHtcblx0XHRcdFx0Ly8gQ2hlY2sgdGhlIHJvb20gbmFtZSBhZ2FpbnN0IHRoZSByb29tcyBsaXN0IChkdXBsaWNhdGUgbmFtZXMgbm90IGFsbG93ZWQhKVxuXHRcdFx0XHRpZiAodHJ1ZSkvL3RoaXMuX3ZhbGlkYXRlTmV3Um9vbU5hbWUoY2hhbmdlcykpXG5cdFx0XHRcdHtcblx0XHRcdFx0XHQvLyBEaXNhYmxlIHJvb20gY3JlYXRpb24gcGFuZWxcblx0XHRcdFx0XHR0aGlzLl9lbmFibGVDcmVhdGVSb29tUGFuZWwoZmFsc2UpO1xuXG5cdFx0XHRcdFx0Ly8gU2VuZCBzZXR0aW5ncyB0byBzZXJ2ZXIgaW5zdGFuY2Vcblx0XHRcdFx0XHRsZXQgcGFyYW1zID0gbmV3IFNGUzJYLlNGU09iamVjdCgpO1xuXHRcdFx0XHRcdHBhcmFtcy5wdXRTRlNBcnJheSgnc2V0dGluZ3MnLCBjaGFuZ2VzKTtcblx0XHRcdFx0XHRwYXJhbXMucHV0VXRmU3RyaW5nKCd6TmFtZScsIHRoaXMuX3pvbmVMaXN0Qm94LmRhdGFJdGVtKHRoaXMuX3pvbmVMaXN0Qm94LnNlbGVjdCgpKS5uYW1lKTtcblx0XHRcdFx0XHRwYXJhbXMucHV0Qm9vbCgnbm90aWZ5JywgJCgnI3pubS1ub3RpZnlDbGllbnRzQ0InKS5wcm9wKCdjaGVja2VkJykpO1xuXG5cdFx0XHRcdFx0Ly8gU2VuZCBzZXR0aW5ncyB0byBleHRlbnNpb25cblx0XHRcdFx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX0NSRUFURV9ST09NLCBwYXJhbXMpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Vcblx0XHRcdFx0e1xuXHRcdFx0XHRcdC8vIFNob3cgYWxlcnRcblx0XHRcdFx0XHR0aGlzLnNoZWxsQ3RybC5zaG93U2ltcGxlQWxlcnQoJ1VuYWJsZSB0byBzdWJtaXQgY29uZmlndXJhdGlvbiBiZWNhdXNlIHRoZSBSb29tIG5hbWUgYWxyZWFkeSBleGlzdHM7IGR1cGxpY2F0ZSBuYW1lcyBhcmUgbm90IGFsbG93ZWQuJywgdHJ1ZSk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0ZWxzZVxuXHRcdHtcblx0XHRcdC8vIFNob3cgYWxlcnRcblx0XHRcdHRoaXMuc2hlbGxDdHJsLnNob3dTaW1wbGVBbGVydCgnVW5hYmxlIHRvIHN1Ym1pdCBSb29tIGNvbmZpZ3VyYXRpb24gZHVlIHRvIGFuIGludmFsaWQgdmFsdWU7IHBsZWFzZSB2ZXJpZnkgdGhlIGhpZ2hsaWdodGVkIGZvcm0gZmllbGRzIGluIGFsbCB0YWJzLicsIHRydWUpO1xuXHRcdH1cblx0fVxuXG5cdF9vblNob3dSb29tRmlsdGVyQnRDbGljaygpXG5cdHtcblx0XHR0aGlzLl9yb29tRmlsdGVyLnNob3coKTtcblx0fVxuXG5cdF9vblNob3dVc2VyRmlsdGVyQnRDbGljaygpXG5cdHtcblx0XHR0aGlzLl91c2VyRmlsdGVyLnNob3coKTtcblx0fVxuXG5cdF9vbkFwcGx5QnRDaGFuZ2UoKVxuXHR7XG5cdFx0Ly8gUmVxdWVzdCBkYXRhIHRvIHNlcnZlclxuXHRcdHRoaXMuX3JlcXVlc3REYXRhKHRydWUpO1xuXHR9XG5cblx0X29uUm9vbUZpbHRlclVwZGF0ZWQoKVxuXHR7XG5cdFx0Ly8gRW5hYmxlL2Rpc2FibGUgXCJBcHBseVwiIGNoZWNrYm94XG5cdFx0JCgnI3pubS1hcHBseVJvb21GaWx0ZXJDQicpLmF0dHIoJ2Rpc2FibGVkJywgdGhpcy5fcm9vbUZpbHRlci5maWx0ZXJFeHByZXNzaW9uID09IG51bGwpO1xuXG5cdFx0Ly8gUmVxdWVzdCBkYXRhIHRvIHNlcnZlclxuXHRcdHRoaXMuX3JlcXVlc3REYXRhKHRydWUpO1xuXHR9XG5cblx0X29uVXNlckZpbHRlclVwZGF0ZWQoKVxuXHR7XG5cdFx0Ly8gRW5hYmxlL2Rpc2FibGUgXCJBcHBseVwiIGNoZWNrYm94XG5cdFx0JCgnI3pubS1hcHBseVVzZXJGaWx0ZXJDQicpLmF0dHIoJ2Rpc2FibGVkJywgdGhpcy5fdXNlckZpbHRlci5maWx0ZXJFeHByZXNzaW9uID09IG51bGwpO1xuXG5cdFx0Ly8gUmVxdWVzdCBkYXRhIHRvIHNlcnZlclxuXHRcdHRoaXMuX3JlcXVlc3REYXRhKHRydWUpO1xuXHR9XG5cblx0X29uTW9uaXRvclNlbGVjdGlvbkJ0Q2xpY2soKVxuXHR7XG5cdFx0aWYgKHRoaXMuX3NlbGVjdGVkWm9uZSlcblx0XHR7XG5cdFx0XHQvLyBDYW5jZWwgcHJldmlvdXMgbW9uaXRvcmluZ1xuXHRcdFx0dGhpcy5fb25DbG9zZU1vbml0b3JCdENsaWNrKCk7XG5cblx0XHRcdGxldCBnZXRab25lVXNlckNvdW50SGlzdG9yeSA9IGZhbHNlO1xuXG5cdFx0XHR0aGlzLl9tb25pdG9yZWRab25lID0gdGhpcy5fc2VsZWN0ZWRab25lLm5hbWU7XG5cblx0XHRcdC8vIFpvbmUgbXVzdCBiZSBtb25pdG9yZWRcblx0XHRcdGlmICh0aGlzLl9hY3RpdmVQYW5lbFR5cGUgPT0gJ3pvbmUnKVxuXHRcdFx0e1xuXHRcdFx0XHR0aGlzLl9tb25pdG9yZWRUeXBlID0gdGhpcy5NT05JVE9SRURfVFlQRV9aT05FO1xuXHRcdFx0XHR0aGlzLl9tb25pdG9yZWROYW1lID0gdGhpcy5fbW9uaXRvcmVkWm9uZTtcblxuXHRcdFx0XHRnZXRab25lVXNlckNvdW50SGlzdG9yeSA9IHRydWU7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJvb20gbXVzdCBiZSBtb25pdG9yZWRcblx0XHRcdGlmICh0aGlzLl9hY3RpdmVQYW5lbFR5cGUgPT0gJ3Jvb20nICYmIHRoaXMuX3NlbGVjdGVkUm9vbSAhPSB1bmRlZmluZWQpXG5cdFx0XHR7XG5cdFx0XHRcdHRoaXMuX21vbml0b3JlZFR5cGUgPSB0aGlzLk1PTklUT1JFRF9UWVBFX1JPT007XG5cdFx0XHRcdHRoaXMuX21vbml0b3JlZE5hbWUgPSB0aGlzLl9zZWxlY3RlZFJvb20ubmFtZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gVXNlciBtdXN0IGJlIG1vbml0b3JlZFxuXHRcdFx0aWYgKHRoaXMuX2FjdGl2ZVBhbmVsVHlwZSA9PSAndXNlcicgJiYgdGhpcy5fc2VsZWN0ZWRVc2VyICE9IHVuZGVmaW5lZClcblx0XHRcdHtcblx0XHRcdFx0dGhpcy5fbW9uaXRvcmVkVHlwZSA9IHRoaXMuTU9OSVRPUkVEX1RZUEVfVVNFUjtcblx0XHRcdFx0dGhpcy5fbW9uaXRvcmVkTmFtZSA9IHRoaXMuX3NlbGVjdGVkVXNlci5uYW1lO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTaG93IGxvYWRpbmcgYmFyXG5cdFx0XHR0aGlzLl9zd2l0Y2hWaWV3KCd6bm0tbG9hZGluZycpO1xuXG5cdFx0XHQvLyBSZXF1ZXN0IGRhdGEgdG8gc2VydmVyXG5cdFx0XHR0aGlzLl9yZXF1ZXN0RGF0YSh0cnVlLCBnZXRab25lVXNlckNvdW50SGlzdG9yeSk7XG5cdFx0fVxuXHR9XG5cblx0X29uU2VuZEFkbWluTXNnSW5LZXlVcChldmVudClcblx0e1xuXHRcdGlmIChldmVudC5rZXkgIT09ICdFbnRlcicpXG5cdFx0XHRyZXR1cm47XG5cblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdHRoaXMuX29uU2VuZEFkbWluTXNnQnRDbGljaygpO1xuXHR9XG5cblx0X29uU2VuZEFkbWluTXNnQnRDbGljaygpXG5cdHtcblx0XHRpZiAodGhpcy5fc2VsZWN0ZWRab25lICYmICQoJyN6bm0tbWVzc2FnZUluJykudmFsKCkgIT0gJycpXG5cdFx0e1xuXHRcdFx0Ly8gQnVpbGQgcmVxdWVzdCBwYXJhbWV0ZXJzXG5cdFx0XHRsZXQgcGFyYW1zID0gbmV3IFNGUzJYLlNGU09iamVjdCgpO1xuXG5cdFx0XHQvLyBBbHdheXMgaW5jbHVkZSB6b25lXG5cdFx0XHRwYXJhbXMucHV0VXRmU3RyaW5nKCd6b25lJywgdGhpcy5fc2VsZWN0ZWRab25lLm5hbWUpO1xuXG5cdFx0XHQvLyBTZW5kIG1lc3NhZ2UgdG8gcm9vbT9cblx0XHRcdGlmICh0aGlzLl9hY3RpdmVQYW5lbFR5cGUgPT0gJ3Jvb20nICYmIHRoaXMuX3NlbGVjdGVkUm9vbSAhPSB1bmRlZmluZWQpXG5cdFx0XHRcdHBhcmFtcy5wdXRVdGZTdHJpbmcoJ3Jvb20nLCB0aGlzLl9zZWxlY3RlZFJvb20ubmFtZSk7XG5cblx0XHRcdC8vIFNlbmQgbWVzc2FnZSB0byB1c2VyP1xuXHRcdFx0aWYgKHRoaXMuX2FjdGl2ZVBhbmVsVHlwZSA9PSAndXNlcicgJiYgdGhpcy5fc2VsZWN0ZWRVc2VyICE9IHVuZGVmaW5lZClcblx0XHRcdFx0cGFyYW1zLnB1dFV0ZlN0cmluZygndXNlcicsIHRoaXMuX3NlbGVjdGVkVXNlci5uYW1lKTtcblxuXHRcdFx0Ly8gQWRkIG1lc3NhZ2Vcblx0XHRcdHBhcmFtcy5wdXRVdGZTdHJpbmcoJ21zZycsICQoJyN6bm0tbWVzc2FnZUluJykudmFsKCkpO1xuXG5cdFx0XHQvLyBTZW5kIHJlcXVlc3QgdG8gZXh0ZW5zaW9uXG5cdFx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX0FETUlOX01TRywgcGFyYW1zKTtcblxuXHRcdFx0Ly8gQ2xlYXIgdGV4dCBpbnB1dFxuXHRcdFx0JCgnI3pubS1tZXNzYWdlSW4nKS52YWwoJycpO1xuXHRcdH1cblx0fVxuXG5cdF9vbkNsb3NlTW9uaXRvckJ0Q2xpY2soKVxuXHR7XG5cdFx0Ly8gU2F2ZSByZWYuIGZvciBsYXRlciB1c2FnZVxuXHRcdGNvbnN0IG1vbml0b3JlZFR5cGUgPSB0aGlzLl9tb25pdG9yZWRUeXBlO1xuXG5cdFx0dGhpcy5fbW9uaXRvcmVkWm9uZSA9IG51bGw7XG5cdFx0dGhpcy5fbW9uaXRvcmVkVHlwZSA9IG51bGw7XG5cdFx0dGhpcy5fbW9uaXRvcmVkTmFtZSA9IG51bGw7XG5cblx0XHQvLyBDbGVhciBnZW9sb2NhdGlvbiBVSVxuXHRcdHRoaXMuX2NsZWFyR2VvTG9jYXRpb25VSSgpO1xuXG5cdFx0Ly8gQ2xlYXIgbG9nIGRhdGFncmlkcyBkYXRhcHJvdmlkZXJzXG5cdFx0Ly8gTk9URTogYSB0cnktY2F0Y2ggaXMgdXNlZCBoZXJlIGJlY2F1c2UsIGZvciBhbiB1bmtub3duIHJlYXNvbiwgS2VuZG8gaXMgdGhyb3dpbmcgYW4gZXJyb3Igd2hlbiByZXNldHRpbmcgdGhlIGRhdGEgc291cmNlcyB3aGVuIHRoZSBtb2R1bGUgaXMgZGVzdHJveWVkXG5cdFx0dHJ5XG5cdFx0e1xuXHRcdFx0dGhpcy5fem9uZUV4dExvZ0dyaWQuc2V0RGF0YVNvdXJjZShbXSk7XG5cdFx0XHR0aGlzLl9yb29tRXh0TG9nR3JpZC5zZXREYXRhU291cmNlKFtdKTtcblx0XHR9XG5cdFx0Y2F0Y2ggKGUpIHsgLyogSWdub3JlICovIH1cblxuXHRcdC8vIExlYXZlIGVkaXQgbW9kZVxuXHRcdHRoaXMuX29uQ2FuY2VsQnRDbGljaygpO1xuXG5cdFx0Ly8gUmVhcnJhbmdlIG1vbml0b3JpbmcgaW50ZXJmYWNlXG5cdFx0dGhpcy5fc2V0TW9uaXRvcmluZ0ludGVyZmFjZSgpO1xuXG5cdFx0Ly8gQ2xlYXIgdGFiIG5hdmlnYXRvclxuXHRcdHRoaXMuX2NsZWFyVGFicyhtb25pdG9yZWRUeXBlKTtcblx0fVxuXG5cdF9vbkVkaXRCdENsaWNrKClcblx0e1xuXHRcdGlmICghdGhpcy5faXNFZGl0aW5nKVxuXHRcdHtcblx0XHRcdC8vIFNob3cgZWRpdCBjb250cm9sc1xuXHRcdFx0JCgnI3pubS1lZGl0Q29udHJvbHMnKS5zaG93KCk7XG5cblx0XHRcdC8vIEhpZGUgZWRpdCBidXR0b25cblx0XHRcdCQoJyN6bm0tZWRpdEJ0JykuaGlkZSgpO1xuXG5cdFx0XHQvLyBFbmFibGUgZWRpdGFibGUgZmllbGRzXG5cdFx0XHR0aGlzLl9pbnRlcmZhY2VCdWlsZGVyLmRpc2FibGVJbnRlcmZhY2UoZmFsc2UpO1xuXG5cdFx0XHR0aGlzLl9pc0VkaXRNb2RlID0gdHJ1ZTtcblx0XHR9XG5cdH1cblxuXHRfb25DYW5jZWxCdENsaWNrKClcblx0e1xuXHRcdGlmICh0aGlzLl9pc0VkaXRpbmcpXG5cdFx0e1xuXHRcdFx0Ly8gSGlkZSBlZGl0IGNvbnRyb2xzXG5cdFx0XHQkKCcjem5tLWVkaXRDb250cm9scycpLmhpZGUoKTtcblxuXHRcdFx0Ly8gU2hvdyBlZGl0IGJ1dHRvblxuXHRcdFx0JCgnI3pubS1lZGl0QnQnKS5zaG93KCk7XG5cblx0XHRcdC8vIERpc2FibGUgZWRpdGFibGUgZmllbGRzXG5cdFx0XHR0aGlzLl9pbnRlcmZhY2VCdWlsZGVyLmRpc2FibGVJbnRlcmZhY2UodHJ1ZSk7XG5cblx0XHRcdHRoaXMuX2lzRWRpdE1vZGUgPSBmYWxzZTtcblxuXHRcdFx0Ly8gSGlkZSB2YWxpZGF0aW9uIG1lc3NhZ2VzXG5cdFx0XHR0aGlzLl9pbnRlcmZhY2VCdWlsZGVyLnJlc2V0VmFsaWRhdGlvbigpO1xuXG5cdFx0XHQvLyBSZXF1ZXN0IGRhdGEgdG8gdXBkYXRlIGludGVyZmFjZSAodXBkYXRpbmcgc3VzcGVuZGVkIGluIGVkaXQgbW9kZSlcblx0XHRcdHRoaXMuX3JlcXVlc3REYXRhKHRydWUpO1xuXHRcdH1cblx0fVxuXG5cdF9vblN1Ym1pdEJ0Q2xpY2soKVxuXHR7XG5cdFx0aWYgKHRoaXMuX2lzRWRpdGluZylcblx0XHR7XG5cdFx0XHQvLyBDaGVjayB2YWxpZGl0eVxuXHRcdFx0aWYgKHRoaXMuX2ludGVyZmFjZUJ1aWxkZXIuY2hlY2tJc1ZhbGlkKCkpXG5cdFx0XHR7XG5cdFx0XHRcdGxldCBjaGFuZ2VzID0gdGhpcy5faW50ZXJmYWNlQnVpbGRlci5nZXRDaGFuZ2VkRGF0YSgpO1xuXG5cdFx0XHRcdGlmIChjaGFuZ2VzLnNpemUoKSA+IDApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHQvL2NvbnNvbGUubG9nKGNoYW5nZXMuZ2V0RHVtcCgpKVxuXG5cdFx0XHRcdFx0Ly8gU2VuZCBzZXR0aW5ncyB0byBzZXJ2ZXIgaW5zdGFuY2Vcblx0XHRcdFx0XHRsZXQgcGFyYW1zID0gbmV3IFNGUzJYLlNGU09iamVjdCgpO1xuXHRcdFx0XHRcdHBhcmFtcy5wdXRTRlNBcnJheSgnc2V0dGluZ3MnLCBjaGFuZ2VzKTtcblx0XHRcdFx0XHRwYXJhbXMucHV0VXRmU3RyaW5nKCd6b25lJywgdGhpcy5fbW9uaXRvcmVkWm9uZSk7XG5cblx0XHRcdFx0XHRpZiAodGhpcy5fbW9uaXRvcmVkVHlwZSA9PSB0aGlzLk1PTklUT1JFRF9UWVBFX1JPT00pXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0Ly8gU3VibWl0IHJvb20gc2V0dGluZ3Ncblx0XHRcdFx0XHRcdHBhcmFtcy5wdXRVdGZTdHJpbmcoJ3Jvb20nLCB0aGlzLl9tb25pdG9yZWROYW1lKTtcblx0XHRcdFx0XHRcdHRoaXMuc2VuZEV4dGVuc2lvblJlcXVlc3QodGhpcy5SRVFfU0VUX1JPT01fU0VUVElOR1MsIHBhcmFtcyk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2UgaWYgKHRoaXMuX21vbml0b3JlZFR5cGUgPT0gdGhpcy5NT05JVE9SRURfVFlQRV9VU0VSKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdC8vIFN1Ym1pdCB1c2VyIHNldHRpbmdzXG5cdFx0XHRcdFx0XHRwYXJhbXMucHV0VXRmU3RyaW5nKCd1c2VyJywgdGhpcy5fbW9uaXRvcmVkTmFtZSk7XG5cdFx0XHRcdFx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX1NFVF9VU0VSX1NFVFRJTkdTLCBwYXJhbXMpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0Ly8gU3VibWl0IHpvbmUgc2V0dGluZ3Ncblx0XHRcdFx0XHRcdHRoaXMuc2VuZEV4dGVuc2lvblJlcXVlc3QodGhpcy5SRVFfU0VUX1pPTkVfU0VUVElOR1MsIHBhcmFtcyk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gTGVhdmUgZWRpdCBtb2RlXG5cdFx0XHRcdFx0dGhpcy5fb25DYW5jZWxCdENsaWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGVsc2Vcblx0XHRcdHtcblx0XHRcdFx0Ly8gU2hvdyBhbGVydFxuXHRcdFx0XHR0aGlzLnNoZWxsQ3RybC5zaG93U2ltcGxlQWxlcnQoJ1VuYWJsZSB0byBzdWJtaXQgY2hhbmdlcyBkdWUgdG8gYW4gaW52YWxpZCB2YWx1ZTsgcGxlYXNlIHZlcmlmeSB0aGUgaGlnaGxpZ2h0ZWQgZm9ybSBmaWVsZHMgaW4gYWxsIHRhYnMuJywgdHJ1ZSk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0X29uVGltZVJhbmdlQ2hhbmdlKClcblx0e1xuXHRcdGxldCB2YWx1ZXMgPSB0aGlzLl90aW1lU2xpZGVyLnZhbHVlKCk7XG5cblx0XHRpZiAodmFsdWVzWzBdID09IHZhbHVlc1sxXSlcblx0XHR7XG5cdFx0XHRpZiAodmFsdWVzWzFdID09IC0yNClcblx0XHRcdFx0dmFsdWVzWzFdID0gLTIzO1xuXG5cdFx0XHR2YWx1ZXNbMF0gPSB2YWx1ZXNbMV0gLSAxO1xuXG5cdFx0XHQvLyBSZXNldCB0aGUgdGltZSByYW5nZSBzbGlkZXIgdmFsdWUgKHdlIG5lZWQgdG8gdXNlIHNldFRpbWVvdXRcblx0XHRcdC8vIGJhY2F1c2UgZG9pbmcgaXQgaW4gdGhlIGNoYW5nZSBldmVudCBsaXN0ZW5lciBkb2Vzbid0IHJlZHJhdyB0aGUgc2xpZGVyKVxuXHRcdFx0c2V0VGltZW91dCgkLnByb3h5KCBmdW5jdGlvbih2YWx1ZXMpIHsgdGhpcy5fdGltZVNsaWRlci52YWx1ZSh2YWx1ZXMpOyB9LCB0aGlzKSwgMTAsIHZhbHVlcyk7XG5cdFx0fVxuXG5cdFx0dGhpcy5fdXNlckNvdW50Q2hhcnQucmFuZ2UgPSB2YWx1ZXM7XG5cdH1cblxuXHRfb25XaW5kb3dSZXNpemUoKVxuXHR7XG5cdFx0Ly8gUmVkcmF3IGNoYXJ0c1xuXHRcdHRoaXMuX3VzZXJDb3VudENoYXJ0LnJlZHJhdygpO1xuXHRcdHRoaXMuX3BhY2tldFF1ZXVlQ2hhcnQucmVkcmF3KCk7XG5cdFx0dGhpcy5fZHJvcHBlZE1zZ0NoYXJ0LnJlZHJhdygpO1xuXHRcdHRoaXMuX3dyaXR0ZW5EYXRhQ2hhcnQucmVkcmF3KCk7XG5cdFx0dGhpcy5fcmVhZERhdGFDaGFydC5yZWRyYXcoKTtcblxuXHRcdC8vIFJlZHJhdyB0aW1lIHJhbmdlIHNsaWRlclxuXHRcdHRoaXMuX3RpbWVTbGlkZXIucmVzaXplKCk7XG5cdH1cblxuXHRfb25Xb3Jkc1JlbG9hZEJ0Q2xpY2soKVxuXHR7XG5cdFx0aWYgKHRoaXMuX21vbml0b3JlZFR5cGUgPT0gdGhpcy5NT05JVE9SRURfVFlQRV9aT05FKVxuXHRcdHtcblx0XHRcdC8vIFNlbmQgcmVxdWVzdCB0byBleHRlbnNpb25cblx0XHRcdGxldCBwYXJhbXMgPSBuZXcgU0ZTMlguU0ZTT2JqZWN0KCk7XG5cdFx0XHRwYXJhbXMucHV0VXRmU3RyaW5nKCd6b25lJywgdGhpcy5fbW9uaXRvcmVkTmFtZSk7XG5cblx0XHRcdHRoaXMuc2VuZEV4dGVuc2lvblJlcXVlc3QodGhpcy5SRVFfUkVMT0FEX1dPUkRTLCBwYXJhbXMpO1xuXHRcdH1cblx0fVxuXG5cdF9vblpvbmVFeHRSZWxvYWRCdENsaWNrKClcblx0e1xuXHRcdGlmICh0aGlzLl9tb25pdG9yZWRUeXBlID09IHRoaXMuTU9OSVRPUkVEX1RZUEVfWk9ORSlcblx0XHR7XG5cdFx0XHQvLyBTZW5kIHJlcXVlc3QgdG8gZXh0ZW5zaW9uXG5cdFx0XHRsZXQgcGFyYW1zID0gbmV3IFNGUzJYLlNGU09iamVjdCgpO1xuXHRcdFx0cGFyYW1zLnB1dFV0ZlN0cmluZygnem9uZScsIHRoaXMuX21vbml0b3JlZE5hbWUpO1xuXG5cdFx0XHR0aGlzLnNlbmRFeHRlbnNpb25SZXF1ZXN0KHRoaXMuUkVRX1JFTE9BRF9aT05FX0VYVCwgcGFyYW1zKTtcblx0XHR9XG5cdH1cblxuXHRfb25LaWNrQnRDbGljaygpXG5cdHtcblx0XHRpZiAodGhpcy5fbW9uaXRvcmVkVHlwZSA9PSB0aGlzLk1PTklUT1JFRF9UWVBFX1VTRVIpXG5cdFx0e1xuXHRcdFx0Ly8gU2VuZCByZXF1ZXN0IHRvIGV4dGVuc2lvblxuXHRcdFx0bGV0IHBhcmFtcyA9IG5ldyBTRlMyWC5TRlNPYmplY3QoKTtcblx0XHRcdHBhcmFtcy5wdXRVdGZTdHJpbmcoJ3pvbmUnLCB0aGlzLl9tb25pdG9yZWRab25lKTtcblx0XHRcdHBhcmFtcy5wdXRVdGZTdHJpbmcoJ3VzZXInLCB0aGlzLl9tb25pdG9yZWROYW1lKTtcblx0XHRcdHBhcmFtcy5wdXRVdGZTdHJpbmcoJ21zZycsICQoJyN6bm0ta2lja01zZ0luJykudmFsKCkpO1xuXHRcdFx0cGFyYW1zLnB1dEludCgnZGVsYXknLCAodGhpcy5fa2lja0RlbGF5SW4udmFsdWUoKSAhPSBudWxsID8gTnVtYmVyKHRoaXMuX2tpY2tEZWxheUluLnZhbHVlKCkpIDogdGhpcy5LSUNLX0JBTl9ERUZBVUxUX0RFTEFZKSk7XG5cblx0XHRcdHRoaXMuc2VuZEV4dGVuc2lvblJlcXVlc3QodGhpcy5SRVFfS0lDS19VU0VSLCBwYXJhbXMpO1xuXG5cdFx0XHQvLyBSZXNldCBtZXNzYWdlXG5cdFx0XHQkKCcjem5tLWtpY2tNc2dJbicpLnZhbCgnJyk7XG5cdFx0fVxuXHR9XG5cblx0X29uQmFuQnRDbGljaygpXG5cdHtcblx0XHRpZiAodGhpcy5fbW9uaXRvcmVkVHlwZSA9PSB0aGlzLk1PTklUT1JFRF9UWVBFX1VTRVIpXG5cdFx0e1xuXHRcdFx0Ly8gU2VuZCByZXF1ZXN0IHRvIGV4dGVuc2lvblxuXHRcdFx0bGV0IHBhcmFtcyA9IG5ldyBTRlMyWC5TRlNPYmplY3QoKTtcblx0XHRcdHBhcmFtcy5wdXRVdGZTdHJpbmcoJ3pvbmUnLCB0aGlzLl9tb25pdG9yZWRab25lKTtcblx0XHRcdHBhcmFtcy5wdXRVdGZTdHJpbmcoJ3VzZXInLCB0aGlzLl9tb25pdG9yZWROYW1lKTtcblx0XHRcdHBhcmFtcy5wdXRVdGZTdHJpbmcoJ21zZycsICQoJyN6bm0tYmFuTXNnSW4nKS52YWwoKSk7XG5cdFx0XHRwYXJhbXMucHV0VXRmU3RyaW5nKCdtb2RlJywgdGhpcy5fYmFuTW9kZURkLnNlbGVjdCgpID4gMCA/IHRoaXMuX2Jhbk1vZGVEZC52YWx1ZSgpIDogJ05BTUUnKTtcblx0XHRcdHBhcmFtcy5wdXRJbnQoJ2RlbGF5JywgKHRoaXMuX2JhbkRlbGF5SW4udmFsdWUoKSAhPSBudWxsID8gTnVtYmVyKHRoaXMuX2JhbkRlbGF5SW4udmFsdWUoKSkgOiB0aGlzLktJQ0tfQkFOX0RFRkFVTFRfREVMQVkpKTtcblxuXHRcdFx0bGV0IGR1cmF0aW9uID0gdGhpcy5fYmFuRHVyYXRpb25Jbi52YWx1ZSgpICE9IG51bGwgPyBOdW1iZXIodGhpcy5fYmFuRHVyYXRpb25Jbi52YWx1ZSgpKSA6IDE7XG5cblx0XHRcdGlmICh0aGlzLl9iYW5EdXJVbml0RGQudmFsdWUoKSA9PSAnaG91cnMnKVxuXHRcdFx0XHRkdXJhdGlvbiA9IGR1cmF0aW9uICogNjA7XG5cdFx0XHRlbHNlIGlmICh0aGlzLl9iYW5EdXJVbml0RGQudmFsdWUoKSA9PSAnZGF5cycpXG5cdFx0XHRcdGR1cmF0aW9uID0gZHVyYXRpb24gKiA2MCAqIDI0O1xuXG5cdFx0XHRwYXJhbXMucHV0SW50KCdkdXJhdGlvbicsIGR1cmF0aW9uKTtcblxuXHRcdFx0dGhpcy5zZW5kRXh0ZW5zaW9uUmVxdWVzdCh0aGlzLlJFUV9CQU5fVVNFUiwgcGFyYW1zKTtcblxuXHRcdFx0Ly8gUmVzZXQgbWVzc2FnZVxuXHRcdFx0JCgnI3pubS1iYW5Nc2dJbicpLnZhbCgnJyk7XG5cdFx0fVxuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8gUFJJVkFURSBNRVRIT0RTXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0X3NldE1vbml0b3JpbmdJbnRlcmZhY2UoKVxuXHR7XG5cdFx0Y29uc3QgZW5hYmxlZCA9ICh0aGlzLl9tb25pdG9yZWRUeXBlICE9IG51bGwgJiYgdGhpcy5fbW9uaXRvcmVkTmFtZSAhPSBudWxsKTtcblxuXHRcdC8vIFNob3cvaGlkZSBoZWFkZXIgYW5kIGZvb3RlclxuXHRcdGlmIChlbmFibGVkKVxuXHRcdHtcblx0XHRcdHRoaXMuX3N3aXRjaFZpZXcoYHpubS0ke3RoaXMuX21vbml0b3JlZFR5cGV9TW9uaXRvcmApO1xuXG5cdFx0XHQvLyBIZWFkZXIgdGl0bGVcblx0XHRcdGxldCB0aXRsZSA9ICdOb3cgbW9uaXRvcmluZyAnO1xuXG5cdFx0XHRpZiAodGhpcy5fbW9uaXRvcmVkVHlwZSA9PSB0aGlzLk1PTklUT1JFRF9UWVBFX1VTRVIpXG5cdFx0XHRcdHRpdGxlICs9IGBVc2VyOiA8c3Ryb25nPiR7dGhpcy5fbW9uaXRvcmVkTmFtZX08L3N0cm9uZz4gKFpvbmU6ICR7dGhpcy5fbW9uaXRvcmVkWm9uZX0pYDtcblx0XHRcdGVsc2UgaWYgKHRoaXMuX21vbml0b3JlZFR5cGUgPT0gdGhpcy5NT05JVE9SRURfVFlQRV9ST09NKVxuXHRcdFx0XHR0aXRsZSArPSBgUm9vbTogPHN0cm9uZz4ke3RoaXMuX21vbml0b3JlZE5hbWV9PC9zdHJvbmc+IChab25lOiAke3RoaXMuX21vbml0b3JlZFpvbmV9KWA7XG5cdFx0XHRlbHNlXG5cdFx0XHRcdHRpdGxlICs9IGBab25lOiA8c3Ryb25nPiR7dGhpcy5fbW9uaXRvcmVkWm9uZX08L3N0cm9uZz5gO1xuXG5cdFx0XHQkKCcjem5tLW1vbml0b3JlZEhlYWRlcicpLmh0bWwodGl0bGUpO1xuXHRcdFx0JCgnI3pubS1tb25pdG9yZWRGb290ZXInKS5zaG93KCk7XG5cblx0XHRcdC8vIFNob3cgcGFuZWxcblx0XHRcdHRoaXMuX3N3aXRjaFBhbmVsKCd6bm0tbWFpblBhbmVsJyk7XG5cdFx0fVxuXHRcdGVsc2Vcblx0XHR7XG5cdFx0XHR0aGlzLl9zd2l0Y2hWaWV3KCd6bm0tc2VsZWN0Jyk7XG5cblx0XHRcdCQoJyN6bm0tbW9uaXRvcmVkSGVhZGVyJykuaHRtbCgnJyk7XG5cdFx0XHQkKCcjem5tLW1vbml0b3JlZEZvb3RlcicpLmhpZGUoKTtcblxuXHRcdFx0Ly8gU2hvdyBwYW5lbFxuXHRcdFx0dGhpcy5fc3dpdGNoUGFuZWwoJ3pubS1zaWRlYmFyUGFuZWwnKTtcblx0XHR9XG5cdH1cblxuXHRfc3dpdGNoVmlldyh2aWV3SWQpXG5cdHtcblx0XHRkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnem5tLXZpZXdzdGFjaycpLnNlbGVjdGVkRWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHZpZXdJZCk7XG5cdH1cblxuXHRfc3dpdGNoUGFuZWwocGFuZWxJZClcblx0e1xuXHRcdGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd6bm0tdmlldycpLnNlbGVjdGVkUGFuZWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChwYW5lbElkKTtcblx0fVxuXG5cdC8qKlxuXHQgKiBCdWlsZCB0aGUgcG9sbGluZyByZXF1ZXN0IHRvIGJlIHNlbnQgdG8gdGhlIHNlcnZlciwgYmFzZWQgb24gdGhlIHNlbGVjdGlvbnMgYW5kIG90aGVyIHNldHRpbmdzIGluIHRoZSBhY2NvcmRpb24uXG5cdCAqL1xuXHRfcmVxdWVzdERhdGEobmV3SWQgPSBmYWxzZSwgZ2V0Wm9uZVVzZXJDb3VudEhpc3RvcnkgPSBmYWxzZSlcblx0e1xuXHRcdC8vIENsZWFyIHByZXZpb3VzIHJlcXVlc3Qgc2NoZWR1bGluZ1xuXHRcdGNsZWFyVGltZW91dCh0aGlzLl9yZXF1ZXN0VGltZXIpO1xuXG5cdFx0Ly8gQ2hlY2sgaWYgY29ubmVjdGlvbiBpcyBzdGlsbCBhdmFpbGFibGVcblx0XHRpZiAodGhpcy5zbWFydEZveC5pc0Nvbm5lY3RlZClcblx0XHR7XG5cdFx0XHRpZiAobmV3SWQpXG5cdFx0XHRcdHRoaXMuX2N1cnJlbnRSZXF1ZXN0SWQrKztcblxuXHRcdFx0Ly8gQnVpbGQgcmVxdWVzdCBwYXJhbWV0ZXJzXG5cdFx0XHRsZXQgcGFyYW1zID0gbmV3IFNGUzJYLlNGU09iamVjdCgpO1xuXG5cdFx0XHQvLyBUaGUgdXBkYXRlZCB6b25lcy9yb29tcy91c2VycyBsaXN0cyBhcmUgcmVxdWVzdGVkIGlmIHRoZSBjb3JyZXNwb25kaW5nIHBhbmVsIGlzIGRpc3BsYXllZCBvbmx5XG5cdFx0XHRjb25zdCBnZXRab25lcyA9ICh0aGlzLl9hY3RpdmVQYW5lbFR5cGUgPT0gJ3pvbmUnKTtcblx0XHRcdGNvbnN0IGdldFJvb21zID0gKHRoaXMuX2FjdGl2ZVBhbmVsVHlwZSA9PSAncm9vbScgJiYgdGhpcy5fc2VsZWN0ZWRab25lICE9IHVuZGVmaW5lZCk7XG5cdFx0XHRjb25zdCBnZXRVc2VycyA9ICh0aGlzLl9hY3RpdmVQYW5lbFR5cGUgPT0gJ3VzZXInICYmIHRoaXMuX3NlbGVjdGVkWm9uZSAhPSB1bmRlZmluZWQpO1xuXG5cdFx0XHQvLyAtLS0gWk9ORVMgLS0tXG5cdFx0XHRwYXJhbXMucHV0Qm9vbCgnem9uZXMnLCBnZXRab25lcyk7XG5cblx0XHRcdC8vIFJPT01TICYgVVNFUlNcblx0XHRcdGlmIChnZXRSb29tcyB8fCBnZXRVc2Vycylcblx0XHRcdHtcblx0XHRcdFx0Ly8gQ29tbW9uIGZpbHRlcmluZyBwYXJhbXM6XG5cblx0XHRcdFx0Ly8gYSkgem9uZSBuYW1lXG5cdFx0XHRcdHBhcmFtcy5wdXRVdGZTdHJpbmcoJ3pvbmUnLCB0aGlzLl9zZWxlY3RlZFpvbmUubmFtZSk7XG5cblx0XHRcdFx0Ly8gYikgZ3JvdXAgbmFtZVxuXHRcdFx0XHRwYXJhbXMucHV0VXRmU3RyaW5nKCdncm91cCcsIHRoaXMuX3NlbGVjdGVkR3JvdXAubmFtZSk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJPT01TXG5cdFx0XHRwYXJhbXMucHV0Qm9vbCgncm9vbXMnLCBnZXRSb29tcyk7XG5cdFx0XHRpZiAoZ2V0Um9vbXMpXG5cdFx0XHR7XG5cdFx0XHRcdC8vIEZpbHRlcmluZyBwYXJhbXM6XG5cblx0XHRcdFx0Ly8gYykgYWR2YW5jZWQgZmlsdGVyaW5nIHBhcmFtc1xuXHRcdFx0XHRpZiAoJCgnI3pubS1hcHBseVJvb21GaWx0ZXJDQicpLnByb3AoJ2NoZWNrZWQnKSAmJiB0aGlzLl9yb29tRmlsdGVyLmZpbHRlckV4cHJlc3Npb24gIT0gbnVsbClcblx0XHRcdFx0XHRwYXJhbXMucHV0U0ZTQXJyYXkoJ3JGaWx0ZXInLCB0aGlzLl9yb29tRmlsdGVyLmZpbHRlckV4cHJlc3Npb24udG9TRlNBcnJheSgpKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gVVNFUlNcblx0XHRcdHBhcmFtcy5wdXRCb29sKCd1c2VycycsIGdldFVzZXJzKTtcblx0XHRcdGlmIChnZXRVc2Vycylcblx0XHRcdHtcblx0XHRcdFx0Ly8gRmlsdGVyaW5nIHBhcmFtczpcblxuXHRcdFx0XHQvLyBjKSByb29tIG5hbWVcblx0XHRcdFx0aWYgKHRoaXMuX3NlbGVjdGVkUm9vbSlcblx0XHRcdFx0XHRwYXJhbXMucHV0VXRmU3RyaW5nKCdyb29tJywgdGhpcy5fc2VsZWN0ZWRSb29tLm5hbWUpO1xuXG5cdFx0XHRcdC8vIGQpIGFkdmFuY2VkIGZpbHRlcmluZyBwYXJhbXNcblx0XHRcdFx0aWYgKCQoJyN6bm0tYXBwbHlVc2VyRmlsdGVyQ0InKS5wcm9wKCdjaGVja2VkJykgJiYgdGhpcy5fdXNlckZpbHRlci5maWx0ZXJFeHByZXNzaW9uICE9IG51bGwpXG5cdFx0XHRcdFx0cGFyYW1zLnB1dFNGU0FycmF5KCd1RmlsdGVyJywgdGhpcy5fdXNlckZpbHRlci5maWx0ZXJFeHByZXNzaW9uLnRvU0ZTQXJyYXkoKSk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIC0tLSBDVVJSRU5UTFkgTU9OSVRPUkVEIERBVEEgLS0tXG5cdFx0XHRpZiAodGhpcy5fbW9uaXRvcmVkVHlwZSAhPSBudWxsICYmIHRoaXMuX21vbml0b3JlZE5hbWUgIT0gbnVsbClcblx0XHRcdHtcblx0XHRcdFx0bGV0IG1vbml0b3JlZE9iaiA9IHRoaXMuX2dldEJhc2ljTW9uaXRvcmVkT2JqZWN0KCk7XG5cblx0XHRcdFx0aWYgKHRoaXMuX21vbml0b3JlZFR5cGUgPT0gdGhpcy5NT05JVE9SRURfVFlQRV9aT05FKVxuXHRcdFx0XHRcdG1vbml0b3JlZE9iai5wdXRCb29sKCd1YycsIGdldFpvbmVVc2VyQ291bnRIaXN0b3J5KTtcblxuXHRcdFx0XHRwYXJhbXMucHV0U0ZTT2JqZWN0KCdtb25pdG9yZWQnLCBtb25pdG9yZWRPYmopO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBTZXQgcmVxdWVzdCBpZDsgd2hlbiBhIHJlc3BvbnNlIGlzIHJlY2VpdmVkLCB3ZSBjaGVjayBpdHMgaWQgbWF0Y2hlcyB0aGUgY3VycmVudCByZXF1ZXN0IGlkOiBpZiBub3QsIHRoZSByZXNwb25zZSBpcyBkaXNjYXJkZWRcblx0XHRcdHBhcmFtcy5wdXRJbnQoJ2lkJywgdGhpcy5fY3VycmVudFJlcXVlc3RJZCk7XG5cblx0XHRcdC8vIFNlbmQgcmVxdWVzdCB0byBleHRlbnNpb25cblx0XHRcdHRoaXMuc2VuZEV4dGVuc2lvblJlcXVlc3QodGhpcy5SRVFfR0VUX0RBVEEsIHBhcmFtcyk7XG5cblx0XHRcdC8vIFNjaGVkdWxlIG5leHQgcmVxdWVzdFxuXHRcdFx0dGhpcy5fcmVxdWVzdFRpbWVyID0gc2V0VGltZW91dCgkLnByb3h5KHRoaXMuX3JlcXVlc3REYXRhLCB0aGlzKSwgTnVtYmVyKHRoaXMuX2ludGVydmFsRHJvcERvd24udmFsdWUoKSkgKiAxMDAwKTtcblx0XHR9XG5cdH1cblxuXHRfZ2V0QmFzaWNNb25pdG9yZWRPYmplY3QoKVxuXHR7XG5cdFx0bGV0IG1vbml0b3JlZE9iaiA9IG5ldyBTRlMyWC5TRlNPYmplY3QoKTtcblxuXHRcdG1vbml0b3JlZE9iai5wdXRVdGZTdHJpbmcoJ3pvbmUnLCB0aGlzLl9tb25pdG9yZWRab25lKTtcblx0XHRtb25pdG9yZWRPYmoucHV0VXRmU3RyaW5nKCd0eXBlJywgdGhpcy5fbW9uaXRvcmVkVHlwZSk7XG5cdFx0bW9uaXRvcmVkT2JqLnB1dFV0ZlN0cmluZygnbmFtZScsIHRoaXMuX21vbml0b3JlZE5hbWUpO1xuXG5cdFx0cmV0dXJuIG1vbml0b3JlZE9iajtcblx0fVxuXG5cdF9zZXRab25lc0RhdGFQcm92aWRlcih6b25lc0RhdGEpXG5cdHtcblx0XHR0aGlzLl9zZXRMaXN0RGF0YVByb3ZpZGVyKHRoaXMuX3pvbmVMaXN0Qm94LCB6b25lc0RhdGEsIHRydWUpO1xuXHR9XG5cblx0X3NldFJvb21zRGF0YVByb3ZpZGVyKHJvb21zRGF0YSlcblx0e1xuXHRcdHRoaXMuX3NldExpc3REYXRhUHJvdmlkZXIodGhpcy5fcm9vbUxpc3RCb3gsIHJvb21zRGF0YSwgdHJ1ZSk7XG5cblx0XHQvLyBTZXQgUmVtb3ZlIGJ1dHRvbiBzdGF0ZVxuXHRcdCQoJyN6bm0tcmVtb3ZlUm9vbUJ0JykuYXR0cignZGlzYWJsZWQnLCB0aGlzLl9zZWxlY3RlZFJvb20gPT0gdW5kZWZpbmVkKTtcblx0fVxuXG5cdF9zZXRVc2Vyc0RhdGFQcm92aWRlcih1c2Vyc0RhdGEpXG5cdHtcblx0XHR0aGlzLl9zZXRMaXN0RGF0YVByb3ZpZGVyKHRoaXMuX3VzZXJMaXN0Qm94LCB1c2Vyc0RhdGEpO1xuXHR9XG5cblx0X3NldExpc3REYXRhUHJvdmlkZXIobGlzdFdpZGdldCwgbGlzdERhdGEsIGNvdW50VXNlcnMgPSBmYWxzZSlcblx0e1xuXHRcdC8vIFNhdmUgcmVmZXJlbmNlIHRvIHNlbGVjdGVkIGl0ZW0gbmFtZVxuXHRcdC8vIE5PVEU6IGFzIHdlIGFyZSBzdWJzdGl0dXRpbmcgdGhlIHdob2xlIGRhdGEgc291cmNlLCB3ZSBuZWVkIGl0IHRvIHJlLXNlbGVjdCB0aGUgc2FtZSBpdGVtIGFmdGVyIHVwZGF0ZVxuXHRcdGxldCBzZWxlY3RlZERhdGFJdGVtID0gbGlzdFdpZGdldC5kYXRhSXRlbShsaXN0V2lkZ2V0LnNlbGVjdCgpKTtcblx0XHRsZXQgc2VsZWN0ZWREYXRhSXRlbU5hbWUgPSBzZWxlY3RlZERhdGFJdGVtID8gc2VsZWN0ZWREYXRhSXRlbS5uYW1lIDogbnVsbDtcblxuXHRcdGxldCBkYXRhQXJyYXkgPSBbXTtcblxuXHRcdC8vIENvbnZlcnQgZGF0YSBjb21pbmcgZnJvbSBzZXJ2ZXJcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGxpc3REYXRhLnNpemUoKTsgaSsrKVxuXHRcdHtcblx0XHRcdGxldCBpdGVtRGF0YSA9IGxpc3REYXRhLmdldFNGU09iamVjdChpKTtcblxuXHRcdFx0bGV0IGl0ZW0gPSB7fTtcblx0XHRcdGl0ZW0ubmFtZSA9IGl0ZW1EYXRhLmdldFV0ZlN0cmluZygnbmFtZScpO1xuXG5cdFx0XHRpZiAoY291bnRVc2Vycylcblx0XHRcdFx0aXRlbS51c2VycyA9IGl0ZW1EYXRhLmdldEludCgndXNlcnMnKTtcblxuXHRcdFx0ZGF0YUFycmF5LnB1c2goaXRlbSk7XG5cdFx0fVxuXG5cdFx0Ly8gQ3JlYXRlIG5ldyBkYXRhIHNvdXJjZVxuXHRcdGxldCBsaXN0RFMgPSBuZXcga2VuZG8uZGF0YS5EYXRhU291cmNlKHtcblx0XHRcdGRhdGE6IGRhdGFBcnJheSxcblx0XHRcdHNjaGVtYToge1xuXHRcdFx0XHRtb2RlbDoge1xuXHRcdFx0XHRcdGlkOiAnbmFtZSdcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdHNvcnQ6IHtcblx0XHRcdFx0ZmllbGQ6ICduYW1lJyxcblx0XHRcdFx0ZGlyOiAnYXNjJ1xuXHRcdFx0fVxuXHRcdH0pO1xuXG5cdFx0Ly8gQXNzaWduIGRhdGEgc291cmNlIHRvIGxpc3Rcblx0XHRsaXN0V2lkZ2V0LnNldERhdGFTb3VyY2UobGlzdERTKTtcblxuXHRcdC8vIFNlbGVjdCBhZ2FpbiBwcmV2aW91c2x5IHNlbGVjdGVkIGl0ZW1cblx0XHRpZiAoc2VsZWN0ZWREYXRhSXRlbU5hbWUgIT0gbnVsbClcblx0XHR7XG5cdFx0XHRzZWxlY3RlZERhdGFJdGVtID0gbGlzdERTLmdldChzZWxlY3RlZERhdGFJdGVtTmFtZSk7XG5cblx0XHRcdGlmIChzZWxlY3RlZERhdGFJdGVtKVxuXHRcdFx0e1xuXHRcdFx0XHRsZXQgc2VsZWN0ZWRFbGVtZW50ID0gbGlzdFdpZGdldC53cmFwcGVyLmZpbmQoJ1tkYXRhLXVpZD1cIicgKyBzZWxlY3RlZERhdGFJdGVtLnVpZCArICdcIl0nKTtcblx0XHRcdFx0bGlzdFdpZGdldC5zZWxlY3Qoc2VsZWN0ZWRFbGVtZW50KTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBSZXNldCBtYWluIGNvbnRyb2wgc3RhdGVcblx0XHR0aGlzLl9zZXRNYWluQ29udHJvbHNFbmFibGVkKCk7XG5cdH1cblxuXHRfc2V0R3JvdXBzRGF0YVByb3ZpZGVyKGdyb3Vwc0RhdGEpXG5cdHtcblx0XHQvLyBDcmVhdGUgR3JvdXBzIGFycmF5LCBhZGRpbmcgY29tbW9uIGVudHJpZXNcblx0XHRsZXQgZ3JvdXBzQXJyYXkgPSBbXG5cdFx0XHR0aGlzLl9nZXRHcm91cE9iaignJywgdGhpcy5BTllfTEFCRUwpLFxuXHRcdFx0dGhpcy5fZ2V0R3JvdXBPYmoodGhpcy5ERUZBVUxUX0dST1VQX05BTUUpXG5cdFx0XTtcblxuXHRcdC8vIFNhdmUgcmVmZXJlbmNlIHRvIHNlbGVjdGVkIGdyb3VwIG5hbWVcblx0XHQvLyBOT1RFOiBhcyB3ZSBhcmUgc3Vic3RpdHV0aW5nIHRoZSB3aG9sZSBkYXRhIHNvdXJjZSwgd2UgbmVlZCBpdCB0byByZS1zZWxlY3QgdGhlIHNhbWUgaXRlbSBhZnRlciB1cGRhdGVcblx0XHRsZXQgc2VsZWN0ZWREYXRhSXRlbSA9IHRoaXMuX3NlbGVjdGVkR3JvdXA7XG5cdFx0bGV0IHNlbGVjdGVkRGF0YUl0ZW1OYW1lID0gc2VsZWN0ZWREYXRhSXRlbSA/IHNlbGVjdGVkRGF0YUl0ZW0ubmFtZSA6IG51bGw7XG5cblx0XHRpZiAoZ3JvdXBzRGF0YSAhPSBudWxsKVxuXHRcdHtcblx0XHRcdGZvciAobGV0IGkgPSAwOyBpIDwgZ3JvdXBzRGF0YS5sZW5ndGg7IGkrKylcblx0XHRcdHtcblx0XHRcdFx0aWYgKGdyb3Vwc0RhdGFbaV0gIT0gdGhpcy5ERUZBVUxUX0dST1VQX05BTUUpIC8vIERlZmF1bHQgZ3JvdXAgd2FzIGFkZGVkIGJlZm9yZVxuXHRcdFx0XHRcdGdyb3Vwc0FycmF5LnB1c2godGhpcy5fZ2V0R3JvdXBPYmooZ3JvdXBzRGF0YVtpXSkpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIENyZWF0ZSBuZXcgZGF0YSBzb3VyY2Vcblx0XHRsZXQgZ3JvdXBEUyA9IG5ldyBrZW5kby5kYXRhLkRhdGFTb3VyY2Uoe1xuXHRcdFx0ZGF0YTogZ3JvdXBzQXJyYXksXG5cdFx0XHRzY2hlbWE6IHtcblx0XHRcdFx0bW9kZWw6IHtcblx0XHRcdFx0XHRpZDogJ25hbWUnXG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9KTtcblxuXHRcdC8vIEFzc2lnbiBkYXRhIHNvdXJjZSB0byBkcm9wZG93blxuXHRcdHRoaXMuX2dyb3Vwc0Ryb3BEb3duLnNldERhdGFTb3VyY2UoZ3JvdXBEUyk7XG5cblx0XHQvLy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0XHQvLyBTZWxlY3QgcHJldmlvdXNseSBzZWxlY3RlZCBpdGVtXG5cdFx0c2VsZWN0ZWREYXRhSXRlbSA9IGdyb3VwRFMuZ2V0KHNlbGVjdGVkRGF0YUl0ZW1OYW1lKTtcblxuXHRcdC8vIElmIGdyb3VwIGlzIG5vdCBmb3VuZCwgc2VsZWN0IHRoZSBkZWZhdWx0IG9uZVxuXHRcdGlmIChzZWxlY3RlZERhdGFJdGVtID09IHVuZGVmaW5lZClcblx0XHRcdHNlbGVjdGVkRGF0YUl0ZW0gPSBncm91cERTLmdldCh0aGlzLkRFRkFVTFRfR1JPVVBfTkFNRSk7XG5cblx0XHR0aGlzLl9ncm91cHNEcm9wRG93bi5zZWxlY3QoZnVuY3Rpb24oZGF0YUl0ZW0pIHtcblx0XHRcdHJldHVybiBkYXRhSXRlbS5uYW1lID09PSBzZWxlY3RlZERhdGFJdGVtLm5hbWU7XG5cdFx0fSk7XG5cdH1cblxuXHRfZ2V0R3JvdXBPYmoobmFtZSwgbGFiZWwgPSBudWxsKVxuXHR7XG5cdFx0cmV0dXJuIHtcblx0XHRcdG5hbWU6IG5hbWUsXG5cdFx0XHRsYWJlbDogKGxhYmVsICE9IG51bGwgPyBsYWJlbCA6IG5hbWUpXG5cdFx0fVxuXHR9XG5cblx0LyoqXG5cdCAqIFVwZGF0ZSB0aGUgU2NvcGUgbGFiZWwgaW4gdGhlIFJvb21zIHBhbmVsIGFuZCBpbiB0aGUgVXNlcnMgcGFuZWwuXG5cdCAqL1xuXHRfc2V0U2NvcGVMYWJlbCgpXG5cdHtcblx0XHRsZXQgcm9vbVNjb3BlID0gJyc7XG5cdFx0bGV0IHVzZXJTY29wZSA9ICcnO1xuXG5cdFx0aWYgKHRoaXMuX3NlbGVjdGVkWm9uZSlcblx0XHR7XG5cdFx0XHRsZXQgem9uZU5hbWUgPSB0aGlzLl9zZWxlY3RlZFpvbmUubmFtZTtcblx0XHRcdHJvb21TY29wZSA9IHRoaXMuX2dldFNjb3BlTGFiZWxQYXJ0KCdab25lOicsIHpvbmVOYW1lKTtcblxuXHRcdFx0bGV0IHNlbGVjdGVkR3JvdXAgPSB0aGlzLl9zZWxlY3RlZEdyb3VwO1xuXHRcdFx0bGV0IGdyb3VwTmFtZSA9IChzZWxlY3RlZEdyb3VwICYmIHNlbGVjdGVkR3JvdXAubmFtZSAhPSAnJykgPyBzZWxlY3RlZEdyb3VwLm5hbWUgOiB0aGlzLkFOWV9MQUJFTDtcblx0XHRcdGxldCByb29tTmFtZSA9ICh0aGlzLl9zZWxlY3RlZFJvb20pID8gdGhpcy5fc2VsZWN0ZWRSb29tLm5hbWUgOiB0aGlzLkFOWV9MQUJFTDtcblxuXHRcdFx0dXNlclNjb3BlID0gdGhpcy5fZ2V0U2NvcGVMYWJlbFBhcnQoJ1pvbmU6Jywgem9uZU5hbWUpICsgJzxicj4nICsgdGhpcy5fZ2V0U2NvcGVMYWJlbFBhcnQoJ0dyb3VwOicsIGdyb3VwTmFtZSkgKyAnPGJyPicgKyB0aGlzLl9nZXRTY29wZUxhYmVsUGFydCgnUm9vbTonLCByb29tTmFtZSk7XG5cdFx0fVxuXG5cdFx0JCgnI3pubS1yb29tU2NvcGVMYicpLmh0bWwocm9vbVNjb3BlKTtcblx0XHQkKCcjem5tLXVzZXJTY29wZUxiJykuaHRtbCh1c2VyU2NvcGUpO1xuXHR9XG5cblx0X2dldFNjb3BlTGFiZWxQYXJ0KGxhYmVsLCB0ZXh0KVxuXHR7XG5cdFx0cmV0dXJuIGA8c3BhbiBjbGFzcz1cInRleHQtbXV0ZWRcIj4ke2xhYmVsfTwvc3Bhbj4gPHNwYW4+JHt0ZXh0fTwvc3Bhbj5gO1xuXHR9XG5cblx0X3Jlc2V0Um9vbUxpc3QoKVxuXHR7XG5cdFx0dGhpcy5fcm9vbUxpc3RCb3guc2V0RGF0YVNvdXJjZShbXSk7XG5cblx0XHQvLyBBbHNvIGRpc2FibGUgUmVtb3ZlIGJ1dHRvblxuXHRcdCQoJyN6bm0tcmVtb3ZlUm9vbUJ0JykuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcblx0fVxuXG5cdF9yZXNldFVzZXJMaXN0KClcblx0e1xuXHRcdHRoaXMuX3VzZXJMaXN0Qm94LnNldERhdGFTb3VyY2UoW10pO1xuXHR9XG5cblx0X3NldE1haW5Db250cm9sc0VuYWJsZWQoKVxuXHR7XG5cdFx0bGV0IGVuYWJsZWQgPSAodGhpcy5fYWN0aXZlUGFuZWxUeXBlID09ICd6b25lJyAmJiB0aGlzLl9zZWxlY3RlZFpvbmUgIT0gdW5kZWZpbmVkKVxuXHRcdFx0XHRcdHx8ICh0aGlzLl9hY3RpdmVQYW5lbFR5cGUgPT0gJ3Jvb20nICYmIHRoaXMuX3NlbGVjdGVkUm9vbSAhPSB1bmRlZmluZWQpXG5cdFx0XHRcdFx0fHwgKHRoaXMuX2FjdGl2ZVBhbmVsVHlwZSA9PSAndXNlcicgJiYgdGhpcy5fc2VsZWN0ZWRVc2VyICE9IHVuZGVmaW5lZCk7XG5cblx0XHQkKCcjem5tLW1haW5Db250cm9scycpLmF0dHIoJ2Rpc2FibGVkJywgIWVuYWJsZWQpO1xuXG5cdFx0JCgnI3pubS1tb25pdG9yVGFyZ2V0TGInKS50ZXh0KGVuYWJsZWQgPyBjYXBpdGFsaXplRmlyc3QodGhpcy5fYWN0aXZlUGFuZWxUeXBlKSA6ICdzZWxlY3Rpb24nKTtcblx0XHQkKCcjem5tLW1lc3NhZ2VJbicpLmF0dHIoJ3BsYWNlaG9sZGVyJywgJ01lc3NhZ2UgdG8gJyArIChlbmFibGVkID8gY2FwaXRhbGl6ZUZpcnN0KHRoaXMuX2FjdGl2ZVBhbmVsVHlwZSkgOiAnc2VsZWN0aW9uJykpO1xuXHR9XG5cblx0X3Nob3dMaW1pdEV4Y2VlZGVkV2FybmluZyhpY29uLCB0aXRsZSlcblx0e1xuXHRcdGljb24uYXR0cigndGl0bGUnLCB0aXRsZSk7XG5cblx0XHRpZiAodGl0bGUgIT0gJycpXG5cdFx0XHRpY29uLnJlbW92ZUNsYXNzKCdoaWRkZW4nKTtcblx0XHRlbHNlXG5cdFx0XHRpY29uLmFkZENsYXNzKCdoaWRkZW4nKTtcblx0fVxuXG5cdF9zaG93Um9vbUNyZWF0aW9uUGFuZWwocm9vbVNldHRpbmdzKVxuXHR7XG5cdFx0Ly8gQnVpbGQgdXNlciBpbnRlcmZhY2UgYmFzZWQgb24gcGFzc2VkIGRhdGFcblx0XHR0aGlzLl9yb29tQ3JlYXRpb25JQnVpbGRlci5idWlsZEludGVyZmFjZShyb29tU2V0dGluZ3MsICd6bm0tcm9vbUNyZWF0b3JUYWJOYXYnLCBmYWxzZSwgJ3JjJyk7XG5cblx0XHQvLyBFbmFibGUgc2Nyb2xsaW5nIHRhYnNcblx0XHQkKCcjem5tLXJvb21DcmVhdG9yVGFiTmF2ID4gI3RhYnMnKS5zY3JvbGxpbmdUYWJzKHtcblx0XHRcdGJvb3RzdHJhcFZlcnNpb246IDQsXG5cdFx0XHRzY3JvbGxUb1RhYkVkZ2U6IHRydWUsXG5cdFx0XHRlbmFibGVTd2lwaW5nOiB0cnVlLFxuXHRcdFx0ZGlzYWJsZVNjcm9sbEFycm93c09uRnVsbHlTY3JvbGxlZDogdHJ1ZSxcblx0XHRcdGNzc0NsYXNzTGVmdEFycm93OiAnZmEgZmEtY2hldnJvbi1sZWZ0Jyxcblx0XHRcdGNzc0NsYXNzUmlnaHRBcnJvdzogJ2ZhIGZhLWNoZXZyb24tcmlnaHQnXG5cdFx0fSk7XG5cblx0XHQvLyBSZXNldCBOb3RpZnkgY2xpZW50cyBjaGVja2JveFxuXHRcdCQoJyN6bm0tbm90aWZ5Q2xpZW50c0NCJykucHJvcCgnY2hlY2tlZCcsIHRydWUpO1xuXG5cdFx0Ly8gU2V0IGxpc3RlbmVyIGZvciBjdXN0b20gYWN0aW9ucyB0cmlnZ2VyZWQgYnkgY29uZmlndXJhdGlvbiBpbnRlcmZhY2Vcblx0XHQkKCcjem5tLXJvb21DcmVhdG9yVGFiTmF2Jykub24oJ3ZhbHVlLXNldCcsICQucHJveHkodGhpcy5fb25Db25maWdWYWx1ZVNldCwgdGhpcykpO1xuXG5cdFx0Ly8gRGlzcGxheSBwYW5lbFxuXHRcdCQoJyN6bm0tY3JlYXRlUm9vbU1vZGFsJykubW9kYWwoJ3Nob3cnKTtcblxuXHRcdC8vIFJlc2V0IGFuZCBoaWRlIGVycm9yIG1lc3NhZ2Vcblx0XHR0aGlzLl9yZXNldFJvb21DcmVhdGlvbkVycm9yKCk7XG5cdH1cblxuXHRfcmVzZXRSb29tQ3JlYXRpb25FcnJvcigpXG5cdHtcblx0XHQvLyBSZXNldCBhbmQgaGlkZSBlcnJvciBtZXNzYWdlXG5cdFx0JCgnI3pubS1jcmVhdGVSb29tRXJyb3InKS50ZXh0KCcnKTtcblx0XHQkKCcjem5tLWNyZWF0ZVJvb21FcnJvcicpLmhpZGUoKTtcblx0fVxuXG5cdF92YWxpZGF0ZU5ld1Jvb21OYW1lKGNoYW5nZXMpXG5cdHtcblx0XHRmb3IgKGxldCBpID0gMDsgaSA8IGNoYW5nZXMuc2l6ZSgpOyBpKyspXG5cdFx0e1xuXHRcdFx0Y29uc3Qgc2V0dGluZyA9IGNoYW5nZXMuZ2V0U0ZTT2JqZWN0KGkpO1xuXG5cdFx0XHRpZiAoc2V0dGluZy5jb250YWluc0tleSgnbmFtZScpICYmIHNldHRpbmcuZ2V0VXRmU3RyaW5nKCduYW1lJykgPT0gJ25hbWUnKVxuXHRcdFx0e1xuXHRcdFx0XHQvLyBHZXQgbmFtZSB2YWx1ZVxuXHRcdFx0XHRjb25zdCBuYW1lID0gc2V0dGluZy5nZXRUZXh0KCd2YWx1ZScpO1xuXG5cdFx0XHRcdC8vIEdldCBkYXRhIHNvdXJjZVxuXHRcdFx0XHRjb25zdCBkcyA9IHRoaXMuX3Jvb21MaXN0Qm94LmRhdGFTb3VyY2UuZGF0YSgpO1xuXG5cdFx0XHRcdC8vIENoZWNrIGlmIG5hbWUgZXhpc3RzIGluIGRhdGEgc291cmNlXG5cdFx0XHRcdGZvciAobGV0IGogPSAwOyBqIDwgZHMubGVuZ3RoOyBqKyspXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRpZiAoZHNbal0ubmFtZSA9PSBuYW1lKVxuXHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHRfZW5hYmxlQ3JlYXRlUm9vbVBhbmVsKGVuYWJsZSlcblx0e1xuXHRcdGxldCBtb2RhbEVsZW1lbnQgPSAkKCcjem5tLWNyZWF0ZVJvb21Nb2RhbCcpO1xuXG5cdFx0Ly8gRW5hYmxlIG1vZGFsIGNsb3NlIGJ1dHRvbnNcblx0XHQkKCdidXR0b25bZGF0YS1kaXNtaXNzPVwibW9kYWxcIl0nLCBtb2RhbEVsZW1lbnQpLmF0dHIoJ2Rpc2FibGVkJywgIWVuYWJsZSk7XG5cblx0XHQvLyBFbmFibGUgY3JlYXRlIGJ1dHRvblxuXHRcdCQoJyN6bm0tcm9vbUNyZWF0b3JDcmVhdGVCdCcsIG1vZGFsRWxlbWVudCkuYXR0cignZGlzYWJsZWQnLCAhZW5hYmxlKTtcblxuXHRcdC8vIEVuYWJsZSBjaGVja2JveFxuXHRcdCQoJyN6bm0tbm90aWZ5Q2xpZW50c0NCJywgbW9kYWxFbGVtZW50KS5hdHRyKCdkaXNhYmxlZCcsICFlbmFibGUpO1xuXG5cdFx0Ly8gRW5hYmxlIGNvbmZpZ3VyYXRpb24gaW50ZXJmYWNlXG5cdFx0dGhpcy5fcm9vbUNyZWF0aW9uSUJ1aWxkZXIuZGlzYWJsZUludGVyZmFjZSghZW5hYmxlKTtcblx0fVxuXG5cdF9jbGVhclRhYnMobW9uaXRvcmVkVHlwZSlcblx0e1xuXHRcdC8vIERlc3Ryb3kgc2Nyb2xsaW5nIHRhYnNcblx0XHQkKGAjem5tLSR7bW9uaXRvcmVkVHlwZX1UYWJOYXZpZ2F0b3IgI3RhYnNgKS5zY3JvbGxpbmdUYWJzKCdkZXN0cm95Jyk7XG5cblx0XHQvLyBSZW1vdmUgYWxsIHRhYiBuYXZpZ2F0b3IgY29udGVudFxuXHRcdHRoaXMuX2ludGVyZmFjZUJ1aWxkZXIuZGVzdHJveUludGVyZmFjZSgpO1xuXG5cdFx0Ly8gU2V0IGFsbCB0YWIgcGFuZWxzIGFzIGluYWN0aXZlXG5cdFx0JChgI3pubS0ke21vbml0b3JlZFR5cGV9VGFiTmF2aWdhdG9yICN0YWJQYW5lbHMgLnRhYi1wYW5lYCkucmVtb3ZlQ2xhc3MoJ3Nob3cgYWN0aXZlJyk7XG5cblx0XHQvLyBSZW1vdmUgdGFiIGNoYW5nZSBldmVudCBsaXN0ZW5lclxuXHRcdCQoJ2FbZGF0YS10b2dnbGU9XCJ0YWJcIl0nKS5vZmYoJ3Nob3duLmJzLnRhYicpO1xuXG5cdFx0dGhpcy5fc2tpcEluaXRUYWJzID0gZmFsc2U7XG5cdH1cblxuXHRfc2hvd1pvbmVUcmFmZmljRGF0YShkYXRhKVxuXHR7XG5cdFx0Ly8gQnVpbGQgdXNlciBjb3VudCBtb25pdG9yIGhpc3Rvcnlcblx0XHRpZiAoZGF0YS5jb250YWluc0tleSgnaGlzdG9yeScpKVxuXHRcdHtcblx0XHRcdGxldCB1c2VyQ291bnREYXRhID0gZGF0YS5nZXRJbnRBcnJheSgnaGlzdG9yeScpO1xuXHRcdFx0bGV0IHNhbXBsaW5nUmF0ZU1pbnMgPSBkYXRhLmdldEludCgncmF0ZScpO1xuXG5cdFx0XHR0aGlzLl91c2VyQ291bnRDaGFydC5hZGRIaXN0b3J5RW50cmllcyh1c2VyQ291bnREYXRhLCBzYW1wbGluZ1JhdGVNaW5zICogNjApO1xuXHRcdH1cblxuXHRcdC8vIEFkZCBsYXN0IHVzZXIgY291bnQgdmFsdWVcblx0XHR0aGlzLl91c2VyQ291bnRDaGFydC5hZGRFbnRyeShkYXRhLmdldEludCgnY3VycmVudCcpKTtcblx0fVxuXG5cdF9hZGRMb2dFbnRyeVRvR3JpZChncmlkLCBpdGVtKVxuXHR7XG5cdFx0bGV0IGRzID0gZ3JpZC5kYXRhU291cmNlO1xuXG5cdFx0Ly8gQ2hlY2sgaXRlbXMgbGltaXRcblx0XHRpZiAoZHMudG90YWwoKSA9PSB0aGlzLk1BWF9FWFRFTlNJT05fTE9HX1NJWkUpXG5cdFx0XHRkcy5yZW1vdmUoZHMuYXQoMCkpO1xuXG5cdFx0ZHMuYWRkKGl0ZW0pO1xuXHR9XG5cblx0X3Nob3dVc2VyU3RhdHNEYXRhKGRhdGEpXG5cdHtcblx0XHQvLyBQYWNrZXQgcXVldWUgZmlsbGluZyAlXG5cdFx0bGV0IHBhY2tldFF1ZXVlID0gcm91bmRUb0RlY2ltYWxzKGRhdGEuZ2V0RmxvYXQoJ3BhY2tldCcpLCAyKTtcblx0XHR0aGlzLl9wYWNrZXRRdWV1ZUNoYXJ0LnNldERhdGFTb3VyY2UoW3tjYXRlZ29yeTogJ1F1ZXVlJywgdmFsdWU6IHBhY2tldFF1ZXVlfV0pO1xuXG5cdFx0Ly8gRHJvcHBlZCBtZXNzYWdlc1xuXHRcdGxldCBkcm9wcGVkTXNnID0gZGF0YS5nZXRJbnQoJ2Ryb3BwZWQnKTtcblx0XHR0aGlzLl9kcm9wcGVkTXNnQ2hhcnQuc2V0RGF0YVNvdXJjZShbe2NhdGVnb3J5OiAnRHJvcHBlZCcsIHZhbHVlOiBkcm9wcGVkTXNnfV0pO1xuXG5cdFx0Ly8gV3JpdHRlbiBkYXRhIGFtb3VudFxuXHRcdGxldCB3cml0dGVuRGF0YU9iaiA9IHNjYWxlQnl0ZXMoZGF0YS5nZXRMb25nKCd3Qnl0ZXMnKSwgMik7XG5cdFx0dGhpcy5fd3JpdHRlbkRhdGFDaGFydC5zZXREYXRhU291cmNlKFt7Y2F0ZWdvcnk6ICdXcml0dGVuJywgdmFsdWU6IHdyaXR0ZW5EYXRhT2JqLnZhbHVlLCB1bml0OiB3cml0dGVuRGF0YU9iai51bml0fV0pO1xuXG5cdFx0Ly8gUmVhZCBkYXRhIGFtb3VudFxuXHRcdGxldCByZWFkRGF0YU9iaiA9IHNjYWxlQnl0ZXMoZGF0YS5nZXRMb25nKCdyQnl0ZXMnKSwgMik7XG5cdFx0dGhpcy5fcmVhZERhdGFDaGFydC5zZXREYXRhU291cmNlKFt7Y2F0ZWdvcnk6ICdSZWFkJywgdmFsdWU6IHJlYWREYXRhT2JqLnZhbHVlLCB1bml0OiByZWFkRGF0YU9iai51bml0fV0pO1xuXHR9XG5cblx0X3NldEdlb0xvY2F0aW9uVUkoZ2VvTG9jRGF0YSlcblx0e1xuXHRcdGNvbnN0IGxvY2F0aW9uID0gZ2VvTG9jRGF0YS5nZXRVdGZTdHJpbmcoJ2xvY2F0aW9uJyk7XG5cdFx0Y29uc3QgZXJyb3IgPSBnZW9Mb2NEYXRhLmdldFV0ZlN0cmluZygnZXJyb3InKTtcblx0XHRjb25zdCBsYXRpdHVkZSA9IGdlb0xvY0RhdGEuZ2V0VXRmU3RyaW5nKCdsYXRpdHVkZScpO1xuXHRcdGNvbnN0IGxvbmdpdHVkZSA9IGdlb0xvY0RhdGEuZ2V0VXRmU3RyaW5nKCdsb25naXR1ZGUnKTtcblxuXHRcdC8vIFNob3cgbG9jYXRpb25cblx0XHQkKCcjem5tLWdlb0xvY2F0aW9uTGInKS50ZXh0KGxvY2F0aW9uKTtcblxuXHRcdC8vIExvZyBlcnJvclxuXHRcdGlmIChlcnJvciAhPSAnJylcblx0XHRcdHRoaXMuc2hlbGxDdHJsLmxvZ01lc3NhZ2UoZXJyb3IsICd3YXJuJyk7XG5cblx0XHQvLyBFbmFibGUvZGlzYWJsZSBTaG93IG1hcCBidXR0b25cblx0XHRpZiAobGF0aXR1ZGUgIT0gJycgJiYgbG9uZ2l0dWRlICE9ICcnKVxuXHRcdHtcblx0XHRcdCQoJyN6bm0tc2hvd01hcEJ0JykuYXR0cignZGlzYWJsZWQnLCBmYWxzZSk7XG5cblx0XHRcdGNvbnN0IHVybCA9IGBodHRwczovL3d3dy5nb29nbGUuY29tL21hcHMvc2VhcmNoLz9hcGk9MSZxdWVyeT0ke051bWJlcihsYXRpdHVkZSkgKyAnLCcgKyBOdW1iZXIobG9uZ2l0dWRlKX1gO1xuXHRcdFx0JCgnI3pubS1zaG93TWFwQnQnKS5hdHRyKCdocmVmJywgdXJsKTtcblx0XHR9XG5cdH1cblxuXHRfY2xlYXJHZW9Mb2NhdGlvblVJKClcblx0e1xuXHRcdCQoJyN6bm0tZ2VvTG9jYXRpb25MYicpLnRleHQoJycpO1xuXHRcdCQoJyN6bm0tc2hvd01hcEJ0JykuYXR0cignZGlzYWJsZWQnLCB0cnVlKTtcblx0XHQkKCcjem5tLXNob3dNYXBCdCcpLmF0dHIoJ2hyZWYnLCAnIycpO1xuXHR9XG5cblx0Ly8tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0Ly8gUFJJVkFURSBHRVRURVJTXG5cdC8vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblx0Z2V0IF9hY3RpdmVQYW5lbFR5cGUoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX2FjY29yZGlvbi5zZWxlY3QoKS5kYXRhKCdpdGVtVHlwZScpO1xuXHR9XG5cblx0Z2V0IF9zZWxlY3RlZFpvbmUoKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3pvbmVMaXN0Qm94LmRhdGFJdGVtKHRoaXMuX3pvbmVMaXN0Qm94LnNlbGVjdCgpKTtcblx0fVxuXG5cdGdldCBfc2VsZWN0ZWRHcm91cCgpXG5cdHtcblx0XHRyZXR1cm4gdGhpcy5fZ3JvdXBzRHJvcERvd24uZGF0YUl0ZW0odGhpcy5fZ3JvdXBzRHJvcERvd24uc2VsZWN0KCkpO1xuXHR9XG5cblx0Z2V0IF9zZWxlY3RlZFJvb20oKVxuXHR7XG5cdFx0cmV0dXJuIHRoaXMuX3Jvb21MaXN0Qm94LmRhdGFJdGVtKHRoaXMuX3Jvb21MaXN0Qm94LnNlbGVjdCgpKTtcblx0fVxuXG5cdGdldCBfc2VsZWN0ZWRVc2VyKClcblx0e1xuXHRcdHJldHVybiB0aGlzLl91c2VyTGlzdEJveC5kYXRhSXRlbSh0aGlzLl91c2VyTGlzdEJveC5zZWxlY3QoKSk7XG5cdH1cblxuXHRnZXQgX2lzRWRpdGluZygpXG5cdHtcblx0XHRyZXR1cm4gKHRoaXMuX21vbml0b3JlZFR5cGUgIT0gbnVsbCAmJiB0aGlzLl9tb25pdG9yZWROYW1lICE9IG51bGwgJiYgdGhpcy5faXNFZGl0TW9kZSk7XG5cdH1cbn1cbiIsImV4cG9ydCBjbGFzcyBSb29tUHJvcGVydGllc0RhdGFcbntcblx0c3RhdGljIGdldCBMQUJFTFMoKSB7XG5cdFx0bGV0IG1hcCA9IG5ldyBNYXAoKTtcblxuXHRcdG1hcC5zZXQoU0ZTMlguUm9vbVByb3BlcnRpZXMuTkFNRSwgJ25hbWUnKTtcblx0XHRtYXAuc2V0KFNGUzJYLlJvb21Qcm9wZXJ0aWVzLkdST1VQX0lELCAnZ3JvdXBJZCcpO1xuXHRcdG1hcC5zZXQoU0ZTMlguUm9vbVByb3BlcnRpZXMuTUFYX1VTRVJTLCAnbWF4VXNlcnMnKTtcblx0XHRtYXAuc2V0KFNGUzJYLlJvb21Qcm9wZXJ0aWVzLk1BWF9TUEVDVEFUT1JTLCAnbWF4U3BlY3RhdG9ycycpO1xuXHRcdG1hcC5zZXQoU0ZTMlguUm9vbVByb3BlcnRpZXMuVVNFUl9DT1VOVCwgJ3VzZXJDb3VudCcpO1xuXHRcdG1hcC5zZXQoU0ZTMlguUm9vbVByb3BlcnRpZXMuU1BFQ1RBVE9SX0NPVU5ULCAnc3BlY3RhdG9yQ291bnQnKTtcblx0XHRtYXAuc2V0KFNGUzJYLlJvb21Qcm9wZXJ0aWVzLklTX0dBTUUsICdpc0dhbWUnKTtcblx0XHRtYXAuc2V0KFNGUzJYLlJvb21Qcm9wZXJ0aWVzLklTX1BSSVZBVEUsICdpc1ByaXZhdGUnKTtcblx0XHRtYXAuc2V0KFNGUzJYLlJvb21Qcm9wZXJ0aWVzLkhBU19GUkVFX1BMQVlFUl9TTE9UUywgJ2hhc0ZyZWVQbGF5ZXJTbG90cycpO1xuXHRcdG1hcC5zZXQoU0ZTMlguUm9vbVByb3BlcnRpZXMuSVNfVFlQRV9TRlNHQU1FLCAnaXNTRlNHYW1lVHlwZScpO1xuXG5cdFx0cmV0dXJuIG1hcDtcblx0fVxuXG5cdHN0YXRpYyBnZXRMYWJlbChwcm9wTmFtZSlcblx0e1xuXHRcdHJldHVybiAnUm9vbS4nICsgUm9vbVByb3BlcnRpZXNEYXRhLkxBQkVMUy5nZXQocHJvcE5hbWUpO1xuXHR9XG5cblx0c3RhdGljIGdldCBwcm9wZXJ0aWVzQXJyYXkoKVxuXHR7XG5cdFx0Y29uc3QgYXJyID0gW107XG5cblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBSb29tUHJvcGVydGllc0RhdGEuTEFCRUxTLmVudHJpZXMoKSlcblx0XHR7XG5cdFx0XHRhcnIucHVzaCh7XG5cdFx0XHRcdGxhYmVsOiBSb29tUHJvcGVydGllc0RhdGEuZ2V0TGFiZWwoa2V5KSxcblx0XHRcdFx0dmFsdWU6IGtleVxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGFycjtcblx0fVxufVxuXG5leHBvcnQgY2xhc3MgVXNlclByb3BlcnRpZXNEYXRhXG57XG5cdHN0YXRpYyBnZXQgTEFCRUxTKCkge1xuXHRcdGxldCBtYXAgPSBuZXcgTWFwKCk7XG5cblx0XHRtYXAuc2V0KFNGUzJYLlVzZXJQcm9wZXJ0aWVzLk5BTUUsICduYW1lJyk7XG5cdFx0bWFwLnNldChTRlMyWC5Vc2VyUHJvcGVydGllcy5JU19QTEFZRVIsICdpc1BsYXllcicpO1xuXHRcdG1hcC5zZXQoU0ZTMlguVXNlclByb3BlcnRpZXMuSVNfU1BFQ1RBVE9SLCAnaXNTcGVjdGF0b3InKTtcblx0XHRtYXAuc2V0KFNGUzJYLlVzZXJQcm9wZXJ0aWVzLklTX05QQywgJ2lzTlBDJyk7XG5cdFx0bWFwLnNldChTRlMyWC5Vc2VyUHJvcGVydGllcy5QUklWSUxFR0VfSUQsICdwcml2aWxlZ2VJZCcpO1xuXG5cdFx0cmV0dXJuIG1hcDtcblx0fVxuXG5cdHN0YXRpYyBnZXRMYWJlbChwcm9wTmFtZSlcblx0e1xuXHRcdHJldHVybiAnVXNlci4nICsgVXNlclByb3BlcnRpZXNEYXRhLkxBQkVMUy5nZXQocHJvcE5hbWUpO1xuXHR9XG5cblx0c3RhdGljIGdldCBwcm9wZXJ0aWVzQXJyYXkoKVxuXHR7XG5cdFx0Y29uc3QgYXJyID0gW107XG5cblx0XHRmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBVc2VyUHJvcGVydGllc0RhdGEuTEFCRUxTLmVudHJpZXMoKSlcblx0XHR7XG5cdFx0XHRhcnIucHVzaCh7XG5cdFx0XHRcdGxhYmVsOiBVc2VyUHJvcGVydGllc0RhdGEuZ2V0TGFiZWwoa2V5KSxcblx0XHRcdFx0dmFsdWU6IGtleVxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGFycjtcblx0fVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQzdHQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7QUNuS0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7QUN0YUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQ3ZIQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7OztBQzMrREE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QSIsInNvdXJjZVJvb3QiOiIifQ==