rubyfox-server 2.13.4.1 → 2.16.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/rubyfox/server/data/config/UploadsLock.txt +3 -0
- data/lib/rubyfox/server/data/config/admin/admintool.xml +2 -0
- data/lib/rubyfox/server/data/config/admin/descriptors/config_room.txt +97 -43
- data/lib/rubyfox/server/data/config/admin/descriptors/config_server.txt +307 -93
- data/lib/rubyfox/server/data/config/admin/descriptors/config_zone.txt +311 -95
- data/lib/rubyfox/server/data/config/admin/descriptors/runtime_game.txt +5 -5
- data/lib/rubyfox/server/data/config/admin/descriptors/runtime_mmo.txt +6 -6
- data/lib/rubyfox/server/data/config/admin/descriptors/runtime_room.txt +69 -44
- data/lib/rubyfox/server/data/config/admin/descriptors/runtime_user.txt +55 -43
- data/lib/rubyfox/server/data/config/admin/descriptors/runtime_zone.txt +81 -36
- data/lib/rubyfox/server/data/config/admin/gmc/gmc.py +55 -18
- data/lib/rubyfox/server/data/config/admin/icons/Analytics.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/Analytics.svg +1 -0
- data/lib/rubyfox/server/data/config/admin/icons/BanManager.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/BanManager.svg +1 -0
- data/lib/rubyfox/server/data/config/admin/icons/BlueBoxMonitor.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/BlueBoxMonitor.svg +1 -0
- data/lib/rubyfox/server/data/config/admin/icons/Console.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/Console.svg +9 -0
- data/lib/rubyfox/server/data/config/admin/icons/Dashboard.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/Dashboard.svg +1 -0
- data/lib/rubyfox/server/data/config/admin/icons/ExtensionManager.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/ExtensionManager.svg +1 -0
- data/lib/rubyfox/server/data/config/admin/icons/LicenseManager.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/LicenseManager.svg +1 -0
- data/lib/rubyfox/server/data/config/admin/icons/LogViewer.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/LogViewer.svg +1 -0
- data/lib/rubyfox/server/data/config/admin/icons/ServerConfigurator.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/ServerConfigurator.svg +1 -0
- data/lib/rubyfox/server/data/config/admin/icons/ServletManager.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/ServletManager.svg +1 -0
- data/lib/rubyfox/server/data/config/admin/icons/ZoneConfigurator.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/ZoneConfigurator.svg +1 -0
- data/lib/rubyfox/server/data/config/admin/icons/ZoneMonitor.png +0 -0
- data/lib/rubyfox/server/data/config/admin/icons/ZoneMonitor.svg +1 -0
- data/lib/rubyfox/server/data/config/core.xml +2 -2
- data/lib/rubyfox/server/data/config/log4j.properties +7 -7
- data/lib/rubyfox/server/data/config/server.xml +9 -10
- data/lib/rubyfox/server/data/config/wordsFile.txt +0 -2
- data/lib/rubyfox/server/data/data/GeoLite2-Country.mmdb +0 -0
- data/lib/rubyfox/server/data/{config → data/buddylists/BasicExamples}/.keep +0 -0
- data/lib/rubyfox/server/data/data/{buddylists → uploads}/.keep +0 -0
- data/lib/rubyfox/server/data/lib/BlueBox.war +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/LICENSE +1061 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/NOTICE +68 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/README.md +79 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/RELEASE-NOTES +173 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/bootstrap.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/catalina-tasks.xml +39 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/catalina.bat +372 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/catalina.sh +648 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/ciphers.bat +58 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/ciphers.sh +60 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/commons-daemon-native.tar.gz +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/commons-daemon.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/configtest.bat +58 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/configtest.sh +60 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/daemon.sh +275 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/digest.bat +58 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/digest.sh +60 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/makebase.bat +114 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/makebase.sh +115 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/setclasspath.bat +94 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/setclasspath.sh +98 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/shutdown.bat +58 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/shutdown.sh +60 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/startup.bat +58 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/startup.sh +60 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tomcat-juli.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tomcat-native.tar.gz +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tool-wrapper.bat +110 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/tool-wrapper.sh +153 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/version.bat +58 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/bin/version.sh +60 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/Catalina/localhost/rewrite.config +1 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/catalina.policy +260 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/catalina.properties +205 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/context.xml +31 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/jaspic-providers.xml +23 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/jaspic-providers.xsd +53 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/keystore.jks +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/logging.properties +79 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/server.xml +161 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/tomcat-users.xml +41 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/tomcat-users.xsd +59 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/conf/web.xml +4737 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/annotations-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ant.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-ha.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-storeconfig.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina-tribes.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/catalina.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/ecj-4.12.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/el-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jasper-el.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jasper.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jaspic-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/jsp-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/servlet-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/sfs2x-ws-helper.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-api.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-coyote.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-dbcp.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-cs.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-de.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-es.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-fr.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ja.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ko.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-pt-BR.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-ru.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-i18n-zh-CN.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-jdbc.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-jni.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-util-scan.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-util.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/tomcat-websocket.jar +0 -0
- data/lib/rubyfox/server/data/lib/apache-tomcat/lib/websocket-api.jar +0 -0
- data/lib/rubyfox/server/data/{extensions → lib/apache-tomcat/logs}/.keep +0 -0
- data/lib/rubyfox/server/data/lib/{jetty/lib/ext/.donotdelete → apache-tomcat/temp/safeToDelete.tmp} +0 -0
- data/lib/rubyfox/server/data/lib/{jetty/resources → apache-tomcat/work}/.keep +0 -0
- data/lib/rubyfox/server/data/lib/commons-collections-3.2.2.jar +0 -0
- data/lib/rubyfox/server/data/lib/commons-compress-1.19.jar +0 -0
- data/lib/rubyfox/server/data/lib/js/LibApi.js +48 -181
- data/lib/rubyfox/server/data/lib/sfs2x-admin.jar +0 -0
- data/lib/rubyfox/server/data/lib/sfs2x-core.jar +0 -0
- data/lib/rubyfox/server/data/lib/sfs2x-lib.jar +0 -0
- data/lib/rubyfox/server/data/lib/sfs2x-util.jar +0 -0
- data/lib/rubyfox/server/data/lib/sfs2x.jar +0 -0
- data/lib/rubyfox/server/data/sfs2x-service +6 -6
- data/lib/rubyfox/server/data/sfs2x-service.vmoptions +1 -1
- data/lib/rubyfox/server/data/sfs2x.sh +1 -1
- data/lib/rubyfox/server/data/www/BlueBox.war +0 -0
- data/lib/rubyfox/server/data/www/HelloServlet/index.jsp +1 -1
- data/lib/rubyfox/server/data/www/{root → ROOT}/_css_/default.css +0 -0
- data/lib/rubyfox/server/data/www/{root → ROOT}/_css_/reset.css +0 -0
- data/lib/rubyfox/server/data/www/{root → ROOT}/_images_/background_gradient.png +0 -0
- data/lib/rubyfox/server/data/www/{root → ROOT}/_images_/background_logo.png +0 -0
- data/lib/rubyfox/server/data/www/{root → ROOT}/_images_/favicon.png +0 -0
- data/lib/rubyfox/server/data/www/{root → ROOT}/_images_/logo_smartfoxserver.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/_changes-to-default-themes_.txt +15 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/bootstrap.min.css +7 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/custom-bootstrap.min.css +1 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/css/all.min.css +5 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-brands-400.eot +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-brands-400.svg +3459 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-brands-400.ttf +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-brands-400.woff +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-brands-400.woff2 +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-regular-400.eot +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-regular-400.svg +803 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-regular-400.ttf +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-regular-400.woff +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-regular-400.woff2 +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-solid-900.eot +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-solid-900.svg +4527 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-solid-900.ttf +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-solid-900.woff +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fontawesome/webfonts/fa-solid-900.woff2 +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/fonts.css +175 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/jquery.scrolling-tabs.min.css +8 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/kendo.custom-bootstrap-v4.css +15280 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/reset.css +54 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/css/style.css +1428 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/data/countries.geo.json +178 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/FreeMono.otf +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/FreeMono.ttf +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/FreeMono.woff +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/FreeMono.woff2 +0 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/roboto-condensed-v16-latin-300.ttf +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/roboto-condensed-v16-latin-300.woff +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/roboto-condensed-v16-latin-300.woff2 +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/roboto-condensed-v16-latin-700.ttf +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/roboto-condensed-v16-latin-700.woff +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/fonts/roboto-condensed-v16-latin-700.woff2 +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/compare.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/demographicsChart.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/demographicsCompare.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/demographicsFilter.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/demographicsMap.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/demographicsTable.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/technologyChart.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/technologyCompare.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/technologyFilter.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/analytics-adv/technologyTable.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/apple-touch-icon-180x180.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/favicon-16x16.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/favicon-32x32.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/favicon-64x64.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/images/logo.png +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/application.bundle.js +2208 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-0.bundle.js +7662 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-1.bundle.js +929 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-10.bundle.js +766 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-11.bundle.js +71 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12.bundle.js +1184 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-12~module-13~module-9.bundle.js +2618 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-13.bundle.js +3315 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-3.bundle.js +280 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-4.bundle.js +1122 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-5.bundle.js +2624 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-6.bundle.js +801 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-7.bundle.js +607 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-8.bundle.js +1221 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/module-9.bundle.js +847 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-0.bundle.js +3240 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-0~module-1~module-13~module-4~module-5~module-7~module-8.bundle.js +17357 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/core/modules/vendors~module-9.bundle.js +807 -0
- data/lib/rubyfox/server/data/{lib/jetty/webapps → www/ROOT/admin/assets/js/custom-modules}/.keep +0 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/bootstrap.min.js +7 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/jquery-3.3.1.min.js +2 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/jquery.scrolling-tabs.min.js +8 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/js.cookie.min.js +8 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/kendo.all.min.js +136 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/popper.min.js +5 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/sfs2x-api-1.7.15.js +8 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/assets/js/libs/versions-readme.txt +16 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/index.html +244 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/manifest.json +25 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/analytics.html +328 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/ban-manager.html +160 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/blue-box-monitor.html +37 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/console.html +135 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/dashboard.html +368 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/extension-manager.html +98 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/license-manager.html +117 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/log-viewer.html +194 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/server-configurator.html +55 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/servlet-manager.html +98 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/zone-configurator.html +62 -0
- data/lib/rubyfox/server/data/www/ROOT/admin/modules/zone-monitor.html +346 -0
- data/lib/rubyfox/server/data/www/{root → ROOT}/crossdomain.xml +0 -0
- data/lib/rubyfox/server/data/www/{root → ROOT}/examples/index.html +0 -0
- data/lib/rubyfox/server/data/www/{root → ROOT}/favicon.ico +0 -0
- data/lib/rubyfox/server/data/www/{root → ROOT}/favicon.png +0 -0
- data/lib/rubyfox/server/data/www/{root → ROOT}/index.html +0 -0
- data/lib/rubyfox/server/data/www/host-manager/META-INF/context.xml +24 -0
- data/lib/rubyfox/server/data/www/host-manager/WEB-INF/jsp/401.jsp +71 -0
- data/lib/rubyfox/server/data/www/host-manager/WEB-INF/jsp/403.jsp +90 -0
- data/lib/rubyfox/server/data/www/host-manager/WEB-INF/jsp/404.jsp +62 -0
- data/lib/rubyfox/server/data/www/host-manager/WEB-INF/web.xml +131 -0
- data/lib/rubyfox/server/data/www/host-manager/images/asf-logo.svg +226 -0
- data/lib/rubyfox/server/data/www/host-manager/images/tomcat.gif +0 -0
- data/lib/rubyfox/server/data/www/host-manager/index.jsp +18 -0
- data/lib/rubyfox/server/data/www/host-manager/manager.xml +26 -0
- data/lib/rubyfox/server/data/{logs → www/logsBackup}/.keep +0 -0
- data/lib/rubyfox/server/data/www/manager/META-INF/context.xml +24 -0
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/401.jsp +80 -0
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/403.jsp +100 -0
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/404.jsp +63 -0
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorCerts.jsp +92 -0
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorCiphers.jsp +92 -0
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/connectorTrustedCerts.jsp +92 -0
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/sessionDetail.jsp +197 -0
- data/lib/rubyfox/server/data/www/manager/WEB-INF/jsp/sessionsList.jsp +170 -0
- data/lib/rubyfox/server/data/www/manager/WEB-INF/web.xml +195 -0
- data/lib/rubyfox/server/data/www/manager/images/asf-logo.svg +226 -0
- data/lib/rubyfox/server/data/www/manager/images/tomcat.gif +0 -0
- data/lib/rubyfox/server/data/www/manager/index.jsp +18 -0
- data/lib/rubyfox/server/data/www/manager/status.xsd +84 -0
- data/lib/rubyfox/server/data/www/manager/xform.xsl +125 -0
- data/lib/rubyfox/server/version.rb +1 -1
- metadata +257 -333
- data/lib/rubyfox/server/data/config/ExtensionManagerLock.txt +0 -2
- data/lib/rubyfox/server/data/data/bannedusers/users.bin +0 -0
- data/lib/rubyfox/server/data/lib/Lib/reindex$py.class +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/charsets.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/cldrdata.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/dnsns.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jaccess.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/javax.mail.glassfish-1.4.1.v201005082020.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/javax.transaction-api-1.2.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jce.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-annotations-9.3.11.v20160721.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-deploy-9.3.11.v20160721.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-http-9.3.11.v20160721.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-io-9.3.11.v20160721.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-jndi-9.3.11.v20160721.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-plus-9.3.11.v20160721.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-schemas-3.1.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-security-9.3.11.v20160721.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-server-9.3.11.v20160721.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-servlet-9.3.11.v20160721.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-util-9.3.11.v20160721.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-webapp-9.3.11.v20160721.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jetty-xml-9.3.11.v20160721.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jfr.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jfxrt.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/jsse.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/localedata.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/nashorn.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/packages.idx +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/resources.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/rt.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/servlet-api-3.1.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/sunec.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/sunjce_provider.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/sunpkcs11.pkc +0 -0
- data/lib/rubyfox/server/data/lib/cachedir/packages/zipfs.pkc +0 -0
- data/lib/rubyfox/server/data/lib/jetty/VERSION.txt +0 -9320
- data/lib/rubyfox/server/data/lib/jetty/etc/README.spnego +0 -62
- data/lib/rubyfox/server/data/lib/jetty/etc/jamon.xml +0 -32
- data/lib/rubyfox/server/data/lib/jetty/etc/jdbcRealm.properties +0 -72
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-alpn.xml +0 -32
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-annotations.xml +0 -20
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-cdi.xml +0 -19
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-debug.xml +0 -36
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-debuglog.xml +0 -25
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-deploy.xml +0 -76
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-gcloud-memcached-sessions.xml +0 -27
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-gcloud-session-idmgr.xml +0 -19
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-gcloud-sessions.xml +0 -27
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-gzip.xml +0 -67
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-http-forwarded.xml +0 -17
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-http.xml +0 -47
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-http2.xml +0 -26
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-http2c.xml +0 -18
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-https.xml +0 -29
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-infinispan.xml +0 -39
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-ipaccess.xml +0 -28
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-jaas.xml +0 -16
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-jdbc-sessions.xml +0 -34
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-jmx-remote.xml +0 -40
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-jmx.xml +0 -32
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-logging.xml +0 -36
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-lowresources.xml +0 -22
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-monitor.xml +0 -30
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-nosql.xml +0 -19
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-plus.xml +0 -26
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-proxy-protocol-ssl.xml +0 -10
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-proxy-protocol.xml +0 -10
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-proxy.xml +0 -35
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-requestlog.xml +0 -30
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-rewrite-customizer.xml +0 -17
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-rewrite.xml +0 -31
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-setuid.xml +0 -30
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-spring.xml +0 -61
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-ssl-context.xml +0 -29
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-ssl.xml +0 -58
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-started.xml +0 -15
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty-stats.xml +0 -18
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty.conf +0 -12
- data/lib/rubyfox/server/data/lib/jetty/etc/jetty.xml +0 -195
- data/lib/rubyfox/server/data/lib/jetty/etc/jminix.xml +0 -12
- data/lib/rubyfox/server/data/lib/jetty/etc/jolokia.xml +0 -16
- data/lib/rubyfox/server/data/lib/jetty/etc/keystore +0 -0
- data/lib/rubyfox/server/data/lib/jetty/etc/krb5.ini +0 -23
- data/lib/rubyfox/server/data/lib/jetty/etc/rewrite-compactpath.xml +0 -10
- data/lib/rubyfox/server/data/lib/jetty/etc/spnego.conf +0 -19
- data/lib/rubyfox/server/data/lib/jetty/etc/spnego.properties +0 -1
- data/lib/rubyfox/server/data/lib/jetty/etc/webdefault.xml +0 -539
- data/lib/rubyfox/server/data/lib/jetty/lib/asm-5.0.1.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/asm-commons-5.0.1.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/fcgi/fcgi-client-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/fcgi/fcgi-server-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/http2-common-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/http2-hpack-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/http2-server-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jaspi/javax.security.auth.message-1.0.0.v201108011116.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/javax-websocket-client-impl-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/javax-websocket-server-impl-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/javax.annotation-api-1.2.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/javax.websocket-api-1.0.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-alpn-server-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-annotations-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-client-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-continuation-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-deploy-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-gcloud-memcached-session-manager-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-gcloud-session-manager-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-http-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-infinispan-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-io-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-jaas-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-jaspi-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-jmx-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-jndi-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-nosql-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-plus-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-proxy-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-quickstart-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-rewrite-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-schemas-3.1.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-security-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-server-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-servlet-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-servlets-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-util-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-webapp-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jetty-xml-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jndi/javax.mail.glassfish-1.4.1.v201005082020.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/jndi/javax.transaction-api-1.2.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/monitor/jetty-monitor-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/org.apache.taglibs.taglibs-standard-impl-1.2.5.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/org.apache.taglibs.taglibs-standard-spec-1.2.5.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/org.eclipse.jdt.core.compiler.ecj-4.4.2.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/org.eclipse.jetty.apache-jsp-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/org.mortbay.jasper.apache-el-8.0.33.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/org.mortbay.jasper.apache-jsp-8.0.33.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/servlet-api-3.1.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/setuid/jetty-setuid-java-1.0.3.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/setuid/libsetuid-linux.so +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/setuid/libsetuid-osx.so +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/spring/jetty-spring-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/start.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/websocket-api-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/websocket-client-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/websocket-common-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/websocket-server-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/lib/websocket-servlet-9.3.11.v20160721.jar +0 -0
- data/lib/rubyfox/server/data/lib/jetty/license-eplv10-aslv20.html +0 -576
- data/lib/rubyfox/server/data/lib/jetty/modules/.donotdelete +0 -0
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_05.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_101.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_102.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_11.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_20.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_25.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_31.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_40.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_45.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_51.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_60.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_65.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_66.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_71.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_72.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_73.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_74.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_77.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_91.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn-impl/alpn-1.8.0_92.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/alpn.mod +0 -53
- data/lib/rubyfox/server/data/lib/jetty/modules/annotations.mod +0 -17
- data/lib/rubyfox/server/data/lib/jetty/modules/apache-jsp.mod +0 -10
- data/lib/rubyfox/server/data/lib/jetty/modules/apache-jstl.mod +0 -9
- data/lib/rubyfox/server/data/lib/jetty/modules/cdi.mod +0 -39
- data/lib/rubyfox/server/data/lib/jetty/modules/client.mod +0 -6
- data/lib/rubyfox/server/data/lib/jetty/modules/continuation.mod +0 -6
- data/lib/rubyfox/server/data/lib/jetty/modules/debug.mod +0 -29
- data/lib/rubyfox/server/data/lib/jetty/modules/debuglog.mod +0 -25
- data/lib/rubyfox/server/data/lib/jetty/modules/deploy.mod +0 -31
- data/lib/rubyfox/server/data/lib/jetty/modules/ext.mod +0 -11
- data/lib/rubyfox/server/data/lib/jetty/modules/fcgi.mod +0 -15
- data/lib/rubyfox/server/data/lib/jetty/modules/gcloud-memcached-sessions.mod +0 -26
- data/lib/rubyfox/server/data/lib/jetty/modules/gcloud-session-idmgr.mod +0 -63
- data/lib/rubyfox/server/data/lib/jetty/modules/gcloud-sessions.mod +0 -11
- data/lib/rubyfox/server/data/lib/jetty/modules/gzip.mod +0 -23
- data/lib/rubyfox/server/data/lib/jetty/modules/hawtio.mod +0 -28
- data/lib/rubyfox/server/data/lib/jetty/modules/home-base-warning.mod +0 -7
- data/lib/rubyfox/server/data/lib/jetty/modules/http-forwarded.mod +0 -20
- data/lib/rubyfox/server/data/lib/jetty/modules/http.mod +0 -39
- data/lib/rubyfox/server/data/lib/jetty/modules/http2.mod +0 -20
- data/lib/rubyfox/server/data/lib/jetty/modules/http2c.mod +0 -22
- data/lib/rubyfox/server/data/lib/jetty/modules/https.mod +0 -14
- data/lib/rubyfox/server/data/lib/jetty/modules/infinispan.mod +0 -33
- data/lib/rubyfox/server/data/lib/jetty/modules/ipaccess.mod +0 -9
- data/lib/rubyfox/server/data/lib/jetty/modules/jaas.mod +0 -17
- data/lib/rubyfox/server/data/lib/jetty/modules/jamon.mod +0 -31
- data/lib/rubyfox/server/data/lib/jetty/modules/jaspi.mod +0 -10
- data/lib/rubyfox/server/data/lib/jetty/modules/jdbc-sessions.mod +0 -27
- data/lib/rubyfox/server/data/lib/jetty/modules/jminix.mod +0 -41
- data/lib/rubyfox/server/data/lib/jetty/modules/jmx-remote.mod +0 -16
- data/lib/rubyfox/server/data/lib/jetty/modules/jmx.mod +0 -13
- data/lib/rubyfox/server/data/lib/jetty/modules/jndi.mod +0 -11
- data/lib/rubyfox/server/data/lib/jetty/modules/jolokia.mod +0 -19
- data/lib/rubyfox/server/data/lib/jetty/modules/jsp.mod +0 -9
- data/lib/rubyfox/server/data/lib/jetty/modules/jstl.mod +0 -8
- data/lib/rubyfox/server/data/lib/jetty/modules/jvm.mod +0 -22
- data/lib/rubyfox/server/data/lib/jetty/modules/logging.mod +0 -36
- data/lib/rubyfox/server/data/lib/jetty/modules/lowresources.mod +0 -28
- data/lib/rubyfox/server/data/lib/jetty/modules/monitor.mod +0 -13
- data/lib/rubyfox/server/data/lib/jetty/modules/nosql.mod +0 -31
- data/lib/rubyfox/server/data/lib/jetty/modules/plus.mod +0 -15
- data/lib/rubyfox/server/data/lib/jetty/modules/proxy-protocol-ssl.mod +0 -9
- data/lib/rubyfox/server/data/lib/jetty/modules/proxy-protocol.mod +0 -9
- data/lib/rubyfox/server/data/lib/jetty/modules/proxy.mod +0 -22
- data/lib/rubyfox/server/data/lib/jetty/modules/quickstart.mod +0 -11
- data/lib/rubyfox/server/data/lib/jetty/modules/requestlog.mod +0 -40
- data/lib/rubyfox/server/data/lib/jetty/modules/resources.mod +0 -10
- data/lib/rubyfox/server/data/lib/jetty/modules/rewrite-compactpath.mod +0 -10
- data/lib/rubyfox/server/data/lib/jetty/modules/rewrite-customizer.mod +0 -24
- data/lib/rubyfox/server/data/lib/jetty/modules/rewrite.mod +0 -23
- data/lib/rubyfox/server/data/lib/jetty/modules/security.mod +0 -9
- data/lib/rubyfox/server/data/lib/jetty/modules/server.mod +0 -79
- data/lib/rubyfox/server/data/lib/jetty/modules/servlet.mod +0 -9
- data/lib/rubyfox/server/data/lib/jetty/modules/servlets.mod +0 -11
- data/lib/rubyfox/server/data/lib/jetty/modules/setuid.mod +0 -19
- data/lib/rubyfox/server/data/lib/jetty/modules/spring.mod +0 -17
- data/lib/rubyfox/server/data/lib/jetty/modules/ssl.mod +0 -97
- data/lib/rubyfox/server/data/lib/jetty/modules/stats.mod +0 -9
- data/lib/rubyfox/server/data/lib/jetty/modules/webapp.mod +0 -10
- data/lib/rubyfox/server/data/lib/jetty/modules/websocket.mod +0 -12
- data/lib/rubyfox/server/data/lib/jetty/notice.html +0 -111
- data/lib/rubyfox/server/data/lib/jetty/start.d/README.TXT +0 -24
- data/lib/rubyfox/server/data/lib/jetty/start.d/http.ini +0 -7
- data/lib/rubyfox/server/data/lib/jetty/start.d/https.ini +0 -10
- data/lib/rubyfox/server/data/lib/jetty/start.d/ssl.ini +0 -19
- data/lib/rubyfox/server/data/lib/jetty/start.ini +0 -83
- data/lib/rubyfox/server/data/www/.keep +0 -0
- data/lib/rubyfox/server/data/www/HelloServlet/META-INF/context.xml +0 -2
- data/lib/rubyfox/server/data/www/PyServletExample/MyModule$py.class +0 -0
- data/lib/rubyfox/server/data/www/PyServletExample/MyModule.py +0 -5
- data/lib/rubyfox/server/data/www/PyServletExample/WEB-INF/web.xml +0 -37
- data/lib/rubyfox/server/data/www/PyServletExample/errors/404.htm +0 -20
- data/lib/rubyfox/server/data/www/PyServletExample/index.py +0 -42
- data/lib/rubyfox/server/data/www/root/admin/.keep +0 -0
- data/lib/rubyfox/server/data/www/root/admin/AdminTool.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/ReleaseNotes.txt +0 -192
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/adobeFlashPlayer.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/advanced.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/analytics.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/banManager.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/bannedIPs.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/bannedUsernames.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/bookmarks.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/bootLog.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/buddyList.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/buddyProperties.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/connection.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/databaseManager.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/floodFilter.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/gameSettings.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/general.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/globalServerStatus.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/hTML5WebSockets.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/iPDiscovery.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/iPFilter.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/jVMSettings.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/logsDownload.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/mMOSettings.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/mailer.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/permissionsAndEvents.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/privilegeManager.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/remoteAdmin.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/roomExtension.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/roomVariables.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/roomsAndGroups.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/runtimeLog.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/runtimeRoomSettings.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/runtimeUserSettings.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/runtimeZoneSettings.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/statsApplication.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/statsDemographics.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/statsExceptions.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/statsOverview.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/statsTechnology.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/systemQueueStatus.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/threadPools.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/userManagement.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/userVariables.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/webServer.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/wordsFilter.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/zoneExtension.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/assets/icons/tabs/zoneTraffic.png +0 -0
- data/lib/rubyfox/server/data/www/root/admin/expressInstall.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/index.html +0 -124
- data/lib/rubyfox/server/data/www/root/admin/modules/Analytics.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/BanManager.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/BlueBoxMonitor.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/Console.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/Dashboard.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/ExtensionManager.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/LicenseManager.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/LogViewer.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/ServerConfigurator.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/ZoneConfigurator.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/modules/ZoneMonitor.swf +0 -0
- data/lib/rubyfox/server/data/www/root/admin/swfobject.js +0 -4
- data/lib/rubyfox/server/data/www/root/examples/.keep +0 -0
- data/lib/rubyfox/server/data/www/sfs2x-ws.war +0 -0
- data/lib/rubyfox/server/data/www/sfs2x-ws.xml +0 -30
- 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==
|