From e363f819ff7ea5ec4af70cee03d31f114f7edddd Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Sat, 16 Jan 2021 04:03:58 +1100 Subject: [PATCH] Converts project to being bundled by webpack some of the current files in node_modules will be moved to static_node_modules so they can continue to be used --- .babelrc | 10 + .eslintrc.json | 19 + .gitignore | 70 +- README.md | 44 +- index.html | 69 +- js/CADWorker/CascadeStudioFileUtils.js | 17 +- js/CADWorker/CascadeStudioFontLoader.js | 22 + js/CADWorker/CascadeStudioMainWorker.js | 133 +- .../CascadeStudioSceneShapesService.js | 10 + js/CADWorker/CascadeStudioShapeToMesh.js | 7 +- js/CADWorker/CascadeStudioStandardLibrary.js | 228 +- js/CADWorker/CascadeStudioStandardUtils.js | 50 +- js/CADWorker/CascadeStudioWorkerState.js | 26 + js/MainPage/CascadeMain.js | 95 +- js/MainPage/CascadeState.js | 9 + js/MainPage/CascadeView.js | 57 +- js/MainPage/CascadeViewHandles.js | 5 +- js/MainPage/CascadeWorkerInit.js | 22 + js/MainPage/index.js | 17 + js/StandardLibraryIntellisense.ts | 2 +- my.test.js | 3 + node_modules/controlkit/bin/controlKit.js | 6889 -- node_modules/controlkit/bin/controlKit.min.js | 10 - .../controlkit/bin/controlKit.min.js.map | 1 - node_modules/controlkit/bin/controlkit.d.ts | 216 - .../golden-layout/dist/goldenlayout.js | 5339 -- .../golden-layout/dist/goldenlayout.min.js | 3 - node_modules/golden-layout/index.d.ts | 880 - node_modules/golden-layout/src/css/README.md | 4 - .../golden-layout/src/css/default-theme.css | 101 - .../src/css/goldenlayout-base.css | 1 - .../src/css/goldenlayout-base.css.map | 1 - .../src/css/goldenlayout-dark-theme.css | 1 - .../src/css/goldenlayout-dark-theme.css.map | 1 - .../src/css/goldenlayout-light-theme.css | 1 - .../src/css/goldenlayout-light-theme.css.map | 1 - .../src/css/goldenlayout-soda-theme.css | 1 - .../src/css/goldenlayout-soda-theme.css.map | 1 - .../css/goldenlayout-translucent-theme.css | 1 - .../goldenlayout-translucent-theme.css.map | 1 - node_modules/jquery/dist/core.js | 399 - node_modules/jquery/dist/jquery.js | 10872 ---- node_modules/jquery/dist/jquery.min.js | 2 - node_modules/jquery/dist/jquery.min.map | 1 - node_modules/jquery/dist/jquery.slim.js | 8777 --- node_modules/jquery/dist/jquery.slim.min.js | 2 - node_modules/jquery/dist/jquery.slim.min.map | 1 - node_modules/monaco-editor/CHANGELOG.md | 787 - node_modules/monaco-editor/LICENSE | 21 - node_modules/monaco-editor/README.md | 100 - .../monaco-editor/ThirdPartyNotices.txt | 339 - .../min-maps/vs/base/worker/workerMain.js.map | 1 - .../min-maps/vs/editor/editor.main.js.map | 1 - .../vs/editor/editor.main.nls.de.js.map | 1 - .../vs/editor/editor.main.nls.es.js.map | 1 - .../vs/editor/editor.main.nls.fr.js.map | 1 - .../vs/editor/editor.main.nls.it.js.map | 1 - .../vs/editor/editor.main.nls.ja.js.map | 1 - .../min-maps/vs/editor/editor.main.nls.js.map | 1 - .../vs/editor/editor.main.nls.ko.js.map | 1 - .../vs/editor/editor.main.nls.ru.js.map | 1 - .../vs/editor/editor.main.nls.zh-cn.js.map | 1 - .../vs/editor/editor.main.nls.zh-tw.js.map | 1 - .../monaco-editor/min-maps/vs/loader.js.map | 1 - .../ui/codiconLabel/codicon/codicon.ttf | Bin 56484 -> 0 bytes .../min/vs/base/worker/workerMain.js | 160 - .../min/vs/basic-languages/abap/abap.js | 7 - .../min/vs/basic-languages/apex/apex.js | 7 - .../min/vs/basic-languages/azcli/azcli.js | 7 - .../min/vs/basic-languages/bat/bat.js | 7 - .../vs/basic-languages/cameligo/cameligo.js | 7 - .../min/vs/basic-languages/clojure/clojure.js | 7 - .../min/vs/basic-languages/coffee/coffee.js | 7 - .../min/vs/basic-languages/cpp/cpp.js | 7 - .../min/vs/basic-languages/csharp/csharp.js | 7 - .../min/vs/basic-languages/csp/csp.js | 7 - .../min/vs/basic-languages/css/css.js | 7 - .../basic-languages/dockerfile/dockerfile.js | 7 - .../min/vs/basic-languages/fsharp/fsharp.js | 7 - .../min/vs/basic-languages/go/go.js | 7 - .../min/vs/basic-languages/graphql/graphql.js | 7 - .../basic-languages/handlebars/handlebars.js | 7 - .../min/vs/basic-languages/html/html.js | 7 - .../min/vs/basic-languages/ini/ini.js | 7 - .../min/vs/basic-languages/java/java.js | 7 - .../basic-languages/javascript/javascript.js | 7 - .../min/vs/basic-languages/kotlin/kotlin.js | 7 - .../min/vs/basic-languages/less/less.js | 7 - .../min/vs/basic-languages/lua/lua.js | 7 - .../vs/basic-languages/markdown/markdown.js | 7 - .../min/vs/basic-languages/mips/mips.js | 7 - .../min/vs/basic-languages/msdax/msdax.js | 7 - .../min/vs/basic-languages/mysql/mysql.js | 7 - .../objective-c/objective-c.js | 7 - .../min/vs/basic-languages/pascal/pascal.js | 7 - .../vs/basic-languages/pascaligo/pascaligo.js | 7 - .../min/vs/basic-languages/perl/perl.js | 7 - .../min/vs/basic-languages/pgsql/pgsql.js | 7 - .../min/vs/basic-languages/php/php.js | 7 - .../vs/basic-languages/postiats/postiats.js | 7 - .../basic-languages/powerquery/powerquery.js | 7 - .../basic-languages/powershell/powershell.js | 7 - .../min/vs/basic-languages/pug/pug.js | 7 - .../min/vs/basic-languages/python/python.js | 7 - .../min/vs/basic-languages/r/r.js | 7 - .../min/vs/basic-languages/razor/razor.js | 7 - .../min/vs/basic-languages/redis/redis.js | 7 - .../vs/basic-languages/redshift/redshift.js | 7 - .../restructuredtext/restructuredtext.js | 7 - .../min/vs/basic-languages/ruby/ruby.js | 7 - .../min/vs/basic-languages/rust/rust.js | 7 - .../min/vs/basic-languages/sb/sb.js | 7 - .../min/vs/basic-languages/scheme/scheme.js | 7 - .../min/vs/basic-languages/scss/scss.js | 7 - .../min/vs/basic-languages/shell/shell.js | 7 - .../vs/basic-languages/solidity/solidity.js | 7 - .../min/vs/basic-languages/sophia/sophia.js | 7 - .../min/vs/basic-languages/sql/sql.js | 7 - .../min/vs/basic-languages/st/st.js | 7 - .../min/vs/basic-languages/swift/swift.js | 10 - .../min/vs/basic-languages/tcl/tcl.js | 7 - .../min/vs/basic-languages/twig/twig.js | 7 - .../basic-languages/typescript/typescript.js | 7 - .../min/vs/basic-languages/vb/vb.js | 7 - .../min/vs/basic-languages/xml/xml.js | 7 - .../min/vs/basic-languages/yaml/yaml.js | 7 - .../min/vs/editor/editor.main.css | 6 - .../min/vs/editor/editor.main.js | 2339 - .../min/vs/editor/editor.main.nls.de.js | 37 - .../min/vs/editor/editor.main.nls.es.js | 37 - .../min/vs/editor/editor.main.nls.fr.js | 38 - .../min/vs/editor/editor.main.nls.it.js | 38 - .../min/vs/editor/editor.main.nls.ja.js | 29 - .../min/vs/editor/editor.main.nls.js | 34 - .../min/vs/editor/editor.main.nls.ko.js | 29 - .../min/vs/editor/editor.main.nls.ru.js | 37 - .../min/vs/editor/editor.main.nls.zh-cn.js | 25 - .../min/vs/editor/editor.main.nls.zh-tw.js | 25 - .../min/vs/language/css/cssMode.js | 7 - .../min/vs/language/css/cssWorker.js | 7 - .../min/vs/language/html/htmlMode.js | 7 - .../min/vs/language/html/htmlWorker.js | 7 - .../min/vs/language/json/jsonMode.js | 7 - .../min/vs/language/json/jsonWorker.js | 7 - .../min/vs/language/typescript/tsMode.js | 7 - .../min/vs/language/typescript/tsWorker.js | 21 - node_modules/monaco-editor/min/vs/loader.js | 37 - node_modules/monaco-editor/monaco.d.ts | 6886 -- node_modules/monaco-editor/package.json | 53 - node_modules/opentype.js/dist/opentype.js | 14268 ----- node_modules/opentype.js/dist/opentype.js.map | 1 - node_modules/opentype.js/dist/opentype.min.js | 2 - .../opentype.js/dist/opentype.min.js.map | 1 - .../opentype.js/dist/opentype.module.js | 14237 ----- .../opentype.js/dist/opentype.module.js.map | 1 - node_modules/three/build/three.d.ts | 8405 --- node_modules/three/build/three.js | 51878 ---------------- node_modules/three/build/three.min.js | 1064 - node_modules/three/build/three.module.js | 51536 --------------- .../js/controls/DeviceOrientationControls.js | 135 - .../examples/js/controls/DragControls.js | 265 - .../js/controls/FirstPersonControls.js | 353 - .../three/examples/js/controls/FlyControls.js | 291 - .../examples/js/controls/OrbitControls.js | 1177 - .../js/controls/PointerLockControls.js | 162 - .../examples/js/controls/TrackballControls.js | 697 - .../examples/js/controls/TransformControls.js | 1672 - .../examples/js/exporters/ColladaExporter.js | 664 - .../examples/js/exporters/DRACOExporter.js | 207 - .../examples/js/exporters/GLTFExporter.js | 2285 - .../examples/js/exporters/MMDExporter.js | 211 - .../examples/js/exporters/OBJExporter.js | 263 - .../examples/js/exporters/PLYExporter.js | 536 - .../examples/js/exporters/STLExporter.js | 167 - .../js/exporters/TypedGeometryExporter.js | 56 - package-lock.json | 40 - package.json | 34 +- postcss.config.js | 5 + service-worker.js | 33 +- .../opencascade.js/dist/LICENSE | 0 .../opencascade.js/dist/oc.d.ts | 0 .../opencascade.js/dist/opencascade.wasm.js | 2 +- .../opencascade.js/dist/opencascade.wasm.wasm | Bin static_node_modules/opencascade.js/index.js | 13 + .../rawflate/rawdeflate.js | 0 .../rawflate/rawinflate.js | 0 webpack.config.js | 97 + yarn.lock | 8200 +++ 188 files changed, 8919 insertions(+), 196024 deletions(-) create mode 100644 .babelrc create mode 100644 .eslintrc.json create mode 100644 js/CADWorker/CascadeStudioFontLoader.js create mode 100644 js/CADWorker/CascadeStudioSceneShapesService.js create mode 100644 js/CADWorker/CascadeStudioWorkerState.js create mode 100644 js/MainPage/CascadeState.js create mode 100644 js/MainPage/CascadeWorkerInit.js create mode 100644 js/MainPage/index.js create mode 100644 my.test.js delete mode 100644 node_modules/controlkit/bin/controlKit.js delete mode 100644 node_modules/controlkit/bin/controlKit.min.js delete mode 100644 node_modules/controlkit/bin/controlKit.min.js.map delete mode 100644 node_modules/controlkit/bin/controlkit.d.ts delete mode 100644 node_modules/golden-layout/dist/goldenlayout.js delete mode 100644 node_modules/golden-layout/dist/goldenlayout.min.js delete mode 100644 node_modules/golden-layout/index.d.ts delete mode 100644 node_modules/golden-layout/src/css/README.md delete mode 100644 node_modules/golden-layout/src/css/default-theme.css delete mode 100644 node_modules/golden-layout/src/css/goldenlayout-base.css delete mode 100644 node_modules/golden-layout/src/css/goldenlayout-base.css.map delete mode 100644 node_modules/golden-layout/src/css/goldenlayout-dark-theme.css delete mode 100644 node_modules/golden-layout/src/css/goldenlayout-dark-theme.css.map delete mode 100644 node_modules/golden-layout/src/css/goldenlayout-light-theme.css delete mode 100644 node_modules/golden-layout/src/css/goldenlayout-light-theme.css.map delete mode 100644 node_modules/golden-layout/src/css/goldenlayout-soda-theme.css delete mode 100644 node_modules/golden-layout/src/css/goldenlayout-soda-theme.css.map delete mode 100644 node_modules/golden-layout/src/css/goldenlayout-translucent-theme.css delete mode 100644 node_modules/golden-layout/src/css/goldenlayout-translucent-theme.css.map delete mode 100644 node_modules/jquery/dist/core.js delete mode 100644 node_modules/jquery/dist/jquery.js delete mode 100644 node_modules/jquery/dist/jquery.min.js delete mode 100644 node_modules/jquery/dist/jquery.min.map delete mode 100644 node_modules/jquery/dist/jquery.slim.js delete mode 100644 node_modules/jquery/dist/jquery.slim.min.js delete mode 100644 node_modules/jquery/dist/jquery.slim.min.map delete mode 100644 node_modules/monaco-editor/CHANGELOG.md delete mode 100644 node_modules/monaco-editor/LICENSE delete mode 100644 node_modules/monaco-editor/README.md delete mode 100644 node_modules/monaco-editor/ThirdPartyNotices.txt delete mode 100644 node_modules/monaco-editor/min-maps/vs/base/worker/workerMain.js.map delete mode 100644 node_modules/monaco-editor/min-maps/vs/editor/editor.main.js.map delete mode 100644 node_modules/monaco-editor/min-maps/vs/editor/editor.main.nls.de.js.map delete mode 100644 node_modules/monaco-editor/min-maps/vs/editor/editor.main.nls.es.js.map delete mode 100644 node_modules/monaco-editor/min-maps/vs/editor/editor.main.nls.fr.js.map delete mode 100644 node_modules/monaco-editor/min-maps/vs/editor/editor.main.nls.it.js.map delete mode 100644 node_modules/monaco-editor/min-maps/vs/editor/editor.main.nls.ja.js.map delete mode 100644 node_modules/monaco-editor/min-maps/vs/editor/editor.main.nls.js.map delete mode 100644 node_modules/monaco-editor/min-maps/vs/editor/editor.main.nls.ko.js.map delete mode 100644 node_modules/monaco-editor/min-maps/vs/editor/editor.main.nls.ru.js.map delete mode 100644 node_modules/monaco-editor/min-maps/vs/editor/editor.main.nls.zh-cn.js.map delete mode 100644 node_modules/monaco-editor/min-maps/vs/editor/editor.main.nls.zh-tw.js.map delete mode 100644 node_modules/monaco-editor/min-maps/vs/loader.js.map delete mode 100644 node_modules/monaco-editor/min/vs/base/browser/ui/codiconLabel/codicon/codicon.ttf delete mode 100644 node_modules/monaco-editor/min/vs/base/worker/workerMain.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/abap/abap.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/apex/apex.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/azcli/azcli.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/bat/bat.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/cameligo/cameligo.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/clojure/clojure.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/coffee/coffee.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/cpp/cpp.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/csharp/csharp.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/csp/csp.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/css/css.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/dockerfile/dockerfile.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/fsharp/fsharp.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/go/go.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/graphql/graphql.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/handlebars/handlebars.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/html/html.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/ini/ini.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/java/java.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/javascript/javascript.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/kotlin/kotlin.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/less/less.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/lua/lua.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/markdown/markdown.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/mips/mips.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/msdax/msdax.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/mysql/mysql.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/objective-c/objective-c.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/pascal/pascal.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/pascaligo/pascaligo.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/perl/perl.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/pgsql/pgsql.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/php/php.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/postiats/postiats.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/powerquery/powerquery.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/powershell/powershell.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/pug/pug.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/python/python.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/r/r.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/razor/razor.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/redis/redis.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/redshift/redshift.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/restructuredtext/restructuredtext.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/ruby/ruby.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/rust/rust.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/sb/sb.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/scheme/scheme.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/scss/scss.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/shell/shell.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/solidity/solidity.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/sophia/sophia.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/sql/sql.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/st/st.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/swift/swift.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/tcl/tcl.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/twig/twig.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/typescript/typescript.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/vb/vb.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/xml/xml.js delete mode 100644 node_modules/monaco-editor/min/vs/basic-languages/yaml/yaml.js delete mode 100644 node_modules/monaco-editor/min/vs/editor/editor.main.css delete mode 100644 node_modules/monaco-editor/min/vs/editor/editor.main.js delete mode 100644 node_modules/monaco-editor/min/vs/editor/editor.main.nls.de.js delete mode 100644 node_modules/monaco-editor/min/vs/editor/editor.main.nls.es.js delete mode 100644 node_modules/monaco-editor/min/vs/editor/editor.main.nls.fr.js delete mode 100644 node_modules/monaco-editor/min/vs/editor/editor.main.nls.it.js delete mode 100644 node_modules/monaco-editor/min/vs/editor/editor.main.nls.ja.js delete mode 100644 node_modules/monaco-editor/min/vs/editor/editor.main.nls.js delete mode 100644 node_modules/monaco-editor/min/vs/editor/editor.main.nls.ko.js delete mode 100644 node_modules/monaco-editor/min/vs/editor/editor.main.nls.ru.js delete mode 100644 node_modules/monaco-editor/min/vs/editor/editor.main.nls.zh-cn.js delete mode 100644 node_modules/monaco-editor/min/vs/editor/editor.main.nls.zh-tw.js delete mode 100644 node_modules/monaco-editor/min/vs/language/css/cssMode.js delete mode 100644 node_modules/monaco-editor/min/vs/language/css/cssWorker.js delete mode 100644 node_modules/monaco-editor/min/vs/language/html/htmlMode.js delete mode 100644 node_modules/monaco-editor/min/vs/language/html/htmlWorker.js delete mode 100644 node_modules/monaco-editor/min/vs/language/json/jsonMode.js delete mode 100644 node_modules/monaco-editor/min/vs/language/json/jsonWorker.js delete mode 100644 node_modules/monaco-editor/min/vs/language/typescript/tsMode.js delete mode 100644 node_modules/monaco-editor/min/vs/language/typescript/tsWorker.js delete mode 100644 node_modules/monaco-editor/min/vs/loader.js delete mode 100644 node_modules/monaco-editor/monaco.d.ts delete mode 100644 node_modules/monaco-editor/package.json delete mode 100644 node_modules/opentype.js/dist/opentype.js delete mode 100644 node_modules/opentype.js/dist/opentype.js.map delete mode 100644 node_modules/opentype.js/dist/opentype.min.js delete mode 100644 node_modules/opentype.js/dist/opentype.min.js.map delete mode 100644 node_modules/opentype.js/dist/opentype.module.js delete mode 100644 node_modules/opentype.js/dist/opentype.module.js.map delete mode 100644 node_modules/three/build/three.d.ts delete mode 100644 node_modules/three/build/three.js delete mode 100644 node_modules/three/build/three.min.js delete mode 100644 node_modules/three/build/three.module.js delete mode 100644 node_modules/three/examples/js/controls/DeviceOrientationControls.js delete mode 100644 node_modules/three/examples/js/controls/DragControls.js delete mode 100644 node_modules/three/examples/js/controls/FirstPersonControls.js delete mode 100644 node_modules/three/examples/js/controls/FlyControls.js delete mode 100644 node_modules/three/examples/js/controls/OrbitControls.js delete mode 100644 node_modules/three/examples/js/controls/PointerLockControls.js delete mode 100644 node_modules/three/examples/js/controls/TrackballControls.js delete mode 100644 node_modules/three/examples/js/controls/TransformControls.js delete mode 100644 node_modules/three/examples/js/exporters/ColladaExporter.js delete mode 100644 node_modules/three/examples/js/exporters/DRACOExporter.js delete mode 100644 node_modules/three/examples/js/exporters/GLTFExporter.js delete mode 100644 node_modules/three/examples/js/exporters/MMDExporter.js delete mode 100644 node_modules/three/examples/js/exporters/OBJExporter.js delete mode 100644 node_modules/three/examples/js/exporters/PLYExporter.js delete mode 100644 node_modules/three/examples/js/exporters/STLExporter.js delete mode 100644 node_modules/three/examples/js/exporters/TypedGeometryExporter.js delete mode 100644 package-lock.json create mode 100644 postcss.config.js rename {node_modules => static_node_modules}/opencascade.js/dist/LICENSE (100%) rename {node_modules => static_node_modules}/opencascade.js/dist/oc.d.ts (100%) rename {node_modules => static_node_modules}/opencascade.js/dist/opencascade.wasm.js (99%) rename {node_modules => static_node_modules}/opencascade.js/dist/opencascade.wasm.wasm (100%) create mode 100644 static_node_modules/opencascade.js/index.js rename {node_modules => static_node_modules}/rawflate/rawdeflate.js (100%) rename {node_modules => static_node_modules}/rawflate/rawinflate.js (100%) create mode 100644 webpack.config.js create mode 100644 yarn.lock diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..6d67db5 --- /dev/null +++ b/.babelrc @@ -0,0 +1,10 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "modules": false + } + ] + ] +} \ No newline at end of file diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..4cd29f7 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "rules": {}, + "env": { + "es6": true, + "browser": true + }, + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module" + }, + "extends": [ + "eslint:recommended", + "plugin:prettier/recommended" + ], + "globals": { + "Atomics": "readonly", + "SharedArrayBuffer": "readonly" + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9f8717c..d6d3277 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,9 @@ yarn-debug.log* yarn-error.log* lerna-debug.log* +# webpack bundle output file +dist/* + # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json @@ -38,70 +41,21 @@ bower_components build/Release # Dependency directories +static_node_modules/**/* node_modules/**/* CascadeStudio/ -# Three.js Build -!node_modules/three/ -!node_modules/three/*/ -!node_modules/three/build/* -# Three.js Controls -!node_modules/three/examples/*/ -!node_modules/three/examples/js/ -!node_modules/three/examples/js/*/ -!node_modules/three/examples/js/controls/ -!node_modules/three/examples/js/controls/* -!node_modules/three/examples/js/exporters/ -!node_modules/three/examples/js/exporters/* - -# Golden-Layout Scripts -!node_modules/golden-layout/ -!node_modules/golden-layout/*/ -!node_modules/golden-layout/index.d.ts -!node_modules/golden-layout/dist/ -!node_modules/golden-layout/dist/* -# Golden-Layout Scripts -!node_modules/golden-layout/src/ -!node_modules/golden-layout/src/*/ -!node_modules/golden-layout/src/css/ -!node_modules/golden-layout/src/css/* - -# Monaco Editor Scripts -!node_modules/monaco-editor -!node_modules/monaco-editor/* -!node_modules/monaco-editor/min/ -!node_modules/monaco-editor/min/** -!node_modules/monaco-editor/min-maps/ -!node_modules/monaco-editor/min-maps/** - -# JQuery Scripts -!node_modules/jquery/ -!node_modules/jquery/*/ -!node_modules/jquery/dist/ -!node_modules/jquery/dist/* - # Raw Inflate and Deflate -!node_modules/rawflate/ -!node_modules/rawflate/* - -# OpenType.js Scripts -!node_modules/opentype.js/ -!node_modules/opentype.js/*/ -!node_modules/opentype.js/dist/ -!node_modules/opentype.js/dist/* - -# ControlKit Bin -!node_modules/controlkit/ -!node_modules/controlkit/*/ -!node_modules/controlkit/bin/ -!node_modules/controlkit/bin/* +!static_node_modules/rawflate/ +!static_node_modules/rawflate/* # opencascade.js Bin -!node_modules/opencascade.js/ -!node_modules/opencascade.js/*/ -!node_modules/opencascade.js/dist/ -!node_modules/opencascade.js/dist/* -node_modules/opencascade.js/dist/opencascade.js +!static_node_modules/opencascade.js/index.js +!static_node_modules/opencascade.js/ +!static_node_modules/opencascade.js/*/ +!static_node_modules/opencascade.js/dist/ +!static_node_modules/opencascade.js/dist/* +static_node_modules/opencascade.js/dist/opencascade.js # Add the above line for now, can take it out if necessary jspm_packages/ diff --git a/README.md b/README.md index 96e576d..09556b2 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,6 @@ Model code is saved to the URL upon every successful evaluation, so you can copy ## Contributing -Cascade Studio is entirely static assets and vanilla javascript, so running it locally is as simple as running a server from the root directory (such as the [VS Code Live Server](https://github.com/ritwickdey/vscode-live-server), [Python live-server](https://pypi.org/project/live-server/), or [Node live-server](https://www.npmjs.com/package/live-server) ). - Pull Requests to this repo are automatically hosted to Vercel instances, so other users will be able to test and benefit from your modifications as soon as the PR is submitted. ## Credits @@ -78,3 +76,45 @@ Cascade Studio uses: - [rawinflate/rawdeflate](https://github.com/dankogai/js-deflate) (URL Code Serialization) Cascade Studio is maintained by [Johnathon Selstad @zalo](https://github.com/zalo) + + +## Building and running on localhost + +Quick start: +```sh +yarn install +yarn dev +``` + + +Install dependencies: + +```sh +yarn install +``` + +To create a production build: + +```sh +yarn build-prod +``` + +To create a development build: + +```sh +yarn build-dev +``` + +## Running + +```sh +yarn dev +``` + +## Testing + +To run unit tests: + +```sh +yarn test +``` diff --git a/index.html b/index.html index 7db501c..13d8d36 100644 --- a/index.html +++ b/index.html @@ -10,80 +10,27 @@ - - - - - - - - - - - - - - - - - - - - - - - +

Cascade Studio 0.0.6 - Save Project - Load Project - Save STEP - Save STL - Save OBJ + Save Project + Load Project + Save STEP + Save STL + Save OBJ - Clear Imported Files + Clear Imported Files
- - - - - -
diff --git a/js/CADWorker/CascadeStudioFileUtils.js b/js/CADWorker/CascadeStudioFileUtils.js index 2b4315b..56dfbfc 100644 --- a/js/CADWorker/CascadeStudioFileUtils.js +++ b/js/CADWorker/CascadeStudioFileUtils.js @@ -1,4 +1,17 @@ // File Import and Export Utilities +import { + oc, + messageHandlers, + externalShapes, + resetExternalShapes, + GUIState, + currentShape +} from "./CascadeStudioWorkerState"; +import { + sceneShapes, + resetSceneShapes +} from "./CascadeStudioSceneShapesService"; +import { stringToHash } from "./CascadeStudioStandardUtils.js"; /** This function synchronously loads the "files" in the * current project into the `externalFiles` dictionary upon startup.*/ @@ -25,7 +38,7 @@ const loadFileSync = async (file) => { * `externalShapes` dictionary and renders them to the viewport. */ function loadFiles(files) { let extFiles = {}; - sceneShapes = []; + resetSceneShapes(); for (let i = 0; i < files.length; i++) { var lastImportedShape = null; loadFileSync(files[i]).then(async (fileText) => { @@ -149,4 +162,4 @@ function saveShapeSTEP (filename = "CascadeStudioPart.step") { messageHandlers["saveShapeSTEP"] = saveShapeSTEP; /** Removes the externally imported shapes/files from the project. */ -messageHandlers["clearExternalFiles"] = () => { externalShapes = {}; }; +messageHandlers["clearExternalFiles"] = resetExternalShapes; diff --git a/js/CADWorker/CascadeStudioFontLoader.js b/js/CADWorker/CascadeStudioFontLoader.js new file mode 100644 index 0000000..f28ca95 --- /dev/null +++ b/js/CADWorker/CascadeStudioFontLoader.js @@ -0,0 +1,22 @@ +import openType from "opentype.js"; + +export const fonts = {}; + +// Preload the Various Fonts that are available via Text3D +var preloadedFonts = [ + "fonts/Roboto.ttf", + "fonts/Papyrus.ttf", + "fonts/Consolas.ttf" +]; + +Promise.all(preloadedFonts.map(async fontURL => fetch("/" + fontURL))).then( + async responses => { + const arrayBuffers = await Promise.all( + responses.map(response => response.arrayBuffer()) + ); + arrayBuffers.forEach((buffer, index) => { + let fontName = preloadedFonts[index].split("fonts/")[1].split(".ttf")[0]; + fonts[fontName] = openType.parse(buffer); + }); + } +); diff --git a/js/CADWorker/CascadeStudioMainWorker.js b/js/CADWorker/CascadeStudioMainWorker.js index f2382d9..209067d 100644 --- a/js/CADWorker/CascadeStudioMainWorker.js +++ b/js/CADWorker/CascadeStudioMainWorker.js @@ -1,9 +1,79 @@ -// Define the persistent global variables -var oc = null, externalShapes = {}, sceneShapes = [], - GUIState, fullShapeEdgeHashes = {}, fullShapeFaceHashes = {}, - currentShape; +import "babel-polyfill"; +import { initOpenCascade } from "../../static_node_modules/opencascade.js"; + +import { + oc, + setOc, + messageHandlers, + setGUIState, + currentShape, + setCurrentShape, + opNumber, + setOpNumber, + currentLineNumber, + argCache, + currentOp, + usedHashes, + setUsedHashes +} from "./CascadeStudioWorkerState"; +import * as remainingGlobals from "./CascadeStudioWorkerState"; +import { + sceneShapes, + resetSceneShapes +} from "./CascadeStudioSceneShapesService"; +import * as sceneShapesService from "./CascadeStudioSceneShapesService"; +import { ShapeToMesh } from "./CascadeStudioShapeToMesh.js"; +import * as standardLibraryModule from "./CascadeStudioStandardLibrary.js"; +const { ForEachEdge, ForEachFace } = standardLibraryModule; // Capture Logs and Errors and forward them to the main thread + +const runCode = code => { + // making the following available to eval + const { externalShapes } = remainingGlobals; + const { RemoveFromSceneShapes, sceneShapes } = sceneShapesService; + const { + BSpline, + Box, + Button, + ChamferEdges, + Checkbox, + Circle, + Cone, + Cylinder, + Difference, + Extrude, + FilletEdges, + ForEachEdge, + ForEachFace, + ForEachShell, + ForEachSolid, + ForEachVertex, + ForEachWire, + GetNumSolidsInCompound, + GetSolidFromCompound, + GetWire, + Intersection, + Loft, + Offset, + Pipe, + Polygon, + RemoveInternalEdges, + Revolve, + Rotate, + RotatedExtrude, + Scale, + Sketch, + Slider, + Sphere, + Text3D, + Transform, + Translate, + Union + } = standardLibraryModule; + eval(code); +}; + let realConsoleLog = console.log; let realConsoleError = console.error; console.log = function (message) { @@ -21,38 +91,9 @@ console.error = function (err, url, line, colno, errorObj) { realConsoleError.apply(console, arguments); }; // This is actually accessed via worker.onerror in the main thread -// Import the set of scripts we'll need to perform all the CAD operations -importScripts( - '../../node_modules/three/build/three.min.js', - './CascadeStudioStandardLibrary.js', - './CascadeStudioShapeToMesh.js', - '../../node_modules/opencascade.js/dist/opencascade.wasm.js', - '../../node_modules/opentype.js/dist/opentype.min.js'); - -// Preload the Various Fonts that are available via Text3D -var preloadedFonts = ['../../fonts/Roboto.ttf', - '../../fonts/Papyrus.ttf', '../../fonts/Consolas.ttf']; -var fonts = {}; -preloadedFonts.forEach((fontURL) => { - opentype.load(fontURL, function (err, font) { - if (err) { console.log(err); } - let fontName = fontURL.split("./fonts/")[1].split(".ttf")[0]; - fonts[fontName] = font; - }); -}); - -// Load the full Open Cascade Web Assembly Module -var messageHandlers = {}; -new opencascade({ - locateFile(path) { - if (path.endsWith('.wasm')) { - return "../../node_modules/opencascade.js/dist/opencascade.wasm.wasm"; - } - return path; - } -}).then((openCascade) => { +initOpenCascade().then(openCascade => { // Register the "OpenCascade" WebAssembly Module under the shorthand "oc" - oc = openCascade; + setOc(openCascade); // Ping Pong Messages Back and Forth based on their registration in messageHandlers onmessage = function (e) { @@ -63,14 +104,13 @@ new opencascade({ // Initial Evaluation after everything has been loaded... postMessage({ type: "startupCallback" }); }); - /** This function evaluates `payload.code` (the contents of the Editor Window) * and sets the GUI State. */ function Evaluate(payload) { - opNumber = 0; // This keeps track of the progress of the evaluation - GUIState = payload.GUIState; + setOpNumber(0); + setGUIState(payload.GUIState); try { - eval(payload.code); + runCode(payload.code); } catch (e) { setTimeout(() => { e.message = "Line " + currentLineNumber + ": " + currentOp + "() encountered " + e.message; @@ -81,7 +121,7 @@ function Evaluate(payload) { // Clean Cache; remove unused Objects for (let hash in argCache) { if (!usedHashes.hasOwnProperty(hash)) { delete argCache[hash]; } } - usedHashes = {}; + setUsedHashes({}); } } messageHandlers["Evaluate"] = Evaluate; @@ -90,11 +130,12 @@ messageHandlers["Evaluate"] = Evaluate; * and converts it to a mesh (and a set of edges) with `ShapeToMesh()`, and sends it off to be rendered. */ function combineAndRenderShapes(payload) { // Initialize currentShape as an empty Compound Solid - currentShape = new oc.TopoDS_Compound(); + setCurrentShape(new oc.TopoDS_Compound()); let sceneBuilder = new oc.BRep_Builder(); sceneBuilder.MakeCompound(currentShape); let fullShapeEdgeHashes = {}; let fullShapeFaceHashes = {}; - postMessage({ "type": "Progress", "payload": { "opNumber": opNumber++, "opType": "Combining Shapes" } }); + postMessage({ "type": "Progress", "payload": { "opNumber": opNumber, "opType": "Combining Shapes" } }); + setOpNumber(opNumber + 1); // If there are sceneShapes, iterate through them and add them to currentShape if (sceneShapes.length > 0) { @@ -120,10 +161,11 @@ function combineAndRenderShapes(payload) { } // Use ShapeToMesh to output a set of triangulated faces and discretized edges to the 3D Viewport - postMessage({ "type": "Progress", "payload": { "opNumber": opNumber++, "opType": "Triangulating Faces" } }); + postMessage({ "type": "Progress", "payload": { "opNumber": opNumber, "opType": "Triangulating Faces" } }); + setOpNumber(opNumber + 1); let facesAndEdges = ShapeToMesh(currentShape, payload.maxDeviation||0.1, fullShapeEdgeHashes, fullShapeFaceHashes); - sceneShapes = []; + resetSceneShapes(); postMessage({ "type": "Progress", "payload": { "opNumber": opNumber, "opType": "" } }); // Finish the progress return facesAndEdges; } else { @@ -132,6 +174,3 @@ function combineAndRenderShapes(payload) { postMessage({ "type": "Progress", "payload": { "opNumber": opNumber, "opType": "" } }); } messageHandlers["combineAndRenderShapes"] = combineAndRenderShapes; - -// Import the File IO Utilities -importScripts('./CascadeStudioFileUtils.js'); diff --git a/js/CADWorker/CascadeStudioSceneShapesService.js b/js/CADWorker/CascadeStudioSceneShapesService.js new file mode 100644 index 0000000..4936189 --- /dev/null +++ b/js/CADWorker/CascadeStudioSceneShapesService.js @@ -0,0 +1,10 @@ +export let sceneShapes = []; +export const resetSceneShapes = () => (sceneShapes = []); + +/** This function returns a version of the `inputArray` without the `objectToRemove`. */ +export function RemoveFromSceneShapes(objectToRemove) { + sceneShapes = sceneShapes.filter( + el => el.hash !== objectToRemove.hash || el.ptr !== objectToRemove.ptr + ); + return sceneShapes; +} diff --git a/js/CADWorker/CascadeStudioShapeToMesh.js b/js/CADWorker/CascadeStudioShapeToMesh.js index 72c9c38..5cc2ba7 100644 --- a/js/CADWorker/CascadeStudioShapeToMesh.js +++ b/js/CADWorker/CascadeStudioShapeToMesh.js @@ -1,4 +1,7 @@ -function ShapeToMesh (shape, maxDeviation, fullShapeEdgeHashes, fullShapeFaceHashes) { +import { oc, setArgCache } from "./CascadeStudioWorkerState"; +import { ForEachEdge, ForEachFace } from "./CascadeStudioStandardLibrary.js"; + +export function ShapeToMesh (shape, maxDeviation, fullShapeEdgeHashes, fullShapeFaceHashes) { let facelist = [], edgeList = []; try { shape = new oc.TopoDS_Shape(shape); @@ -14,7 +17,7 @@ function ShapeToMesh (shape, maxDeviation, fullShapeEdgeHashes, fullShapeFaceHas ForEachFace(shape, (faceIndex, myFace) => { let aLocation = new oc.TopLoc_Location(); let myT = oc.BRep_Tool.prototype.Triangulation(myFace, aLocation); - if (myT.IsNull()) { console.error("Encountered Null Face!"); argCache = {}; return; } + if (myT.IsNull()) { console.error("Encountered Null Face!"); setArgCache({}); return; } let this_face = { vertex_coord: [], diff --git a/js/CADWorker/CascadeStudioStandardLibrary.js b/js/CADWorker/CascadeStudioStandardLibrary.js index 60b828a..4f00cda 100644 --- a/js/CADWorker/CascadeStudioStandardLibrary.js +++ b/js/CADWorker/CascadeStudioStandardLibrary.js @@ -9,14 +9,27 @@ // (Optional) If base functions appear to be missing, fork opencascade.js and add them to this file: // - https://github.com/donalffons/opencascade.js/blob/master/opencascade.idl // - Upon push, Github Actions will build a new version of the library and commit it back to the repo -// - From there, you can graft those into CascadeStudio/node_modules/opencascade.js/dist (following its existing conventions) +// - From there, you can graft those into CascadeStudio/static_node_modules/opencascade.js/dist (following its existing conventions) /** Import Misc. Utilities that aren't part of the Exposed Library */ -importScripts('./CascadeStudioStandardUtils.js'); - -function Box(x, y, z, centered) { +import { + CacheOp, + ComputeHash, + stringToHash, + convertToPnt, + getCallingLocation, + isArrayLike +} from "./CascadeStudioStandardUtils.js"; +import { oc, GUIState, setArgCache } from "./CascadeStudioWorkerState"; +import { + sceneShapes, + RemoveFromSceneShapes +} from "./CascadeStudioSceneShapesService"; +import { fonts } from "./CascadeStudioFontLoader"; + +export function Box(x, y, z, centered) { if (!centered) { centered = false;} - let curBox = CacheOp(arguments, () => { + let curBox = CacheOp(Box, () => { // Construct a Box Primitive let box = new oc.BRepPrimAPI_MakeBox(x, y, z).Shape(); if (centered) { @@ -30,8 +43,8 @@ function Box(x, y, z, centered) { return curBox; } -function Sphere(radius) { - let curSphere = CacheOp(arguments, () => { +export function Sphere(radius) { + let curSphere = CacheOp(Sphere, () => { // Construct a Sphere Primitive let spherePlane = new oc.gp_Ax2(new oc.gp_Pnt(0, 0, 0), oc.gp.prototype.DZ()); return new oc.BRepPrimAPI_MakeSphere(spherePlane, radius).Shape(); @@ -41,8 +54,8 @@ function Sphere(radius) { return curSphere; } -function Cylinder(radius, height, centered) { - let curCylinder = CacheOp(arguments, () => { +export function Cylinder(radius, height, centered) { + let curCylinder = CacheOp(Cylinder, () => { let cylinderPlane = new oc.gp_Ax2(new oc.gp_Pnt(0, 0, centered ? -height / 2 : 0), new oc.gp_Dir(0, 0, 1)); return new oc.BRepPrimAPI_MakeCylinder(cylinderPlane, radius, height).Shape(); }); @@ -50,16 +63,16 @@ function Cylinder(radius, height, centered) { return curCylinder; } -function Cone(radius1, radius2, height) { - let curCone = CacheOp(arguments, () => { +export function Cone(radius1, radius2, height) { + let curCone = CacheOp(Cone, () => { return new oc.BRepPrimAPI_MakeCone(radius1, radius2, height).Shape(); }); sceneShapes.push(curCone); return curCone; } -function Polygon(points, wire) { - let curPolygon = CacheOp(arguments, () => { +export function Polygon(points, wire) { + let curPolygon = CacheOp(Polygon, () => { let gpPoints = []; for (let ind = 0; ind < points.length; ind++) { gpPoints.push(convertToPnt(points[ind])); @@ -88,8 +101,8 @@ function Polygon(points, wire) { return curPolygon; } -function Circle(radius, wire) { - let curCircle = CacheOp(arguments, () => { +export function Circle(radius, wire) { + let curCircle = CacheOp(Circle, () => { let circle = new oc.GC_MakeCircle(new oc.gp_Ax2(new oc.gp_Pnt(0, 0, 0), new oc.gp_Dir(0, 0, 1)), radius).Value(); let edge = new oc.BRepBuilderAPI_MakeEdge(circle).Edge(); @@ -101,8 +114,8 @@ function Circle(radius, wire) { return curCircle; } -function BSpline(inPoints, closed) { - let curSpline = CacheOp(arguments, () => { +export function BSpline(inPoints, closed) { + let curSpline = CacheOp(BSpline, () => { let ptList = new oc.TColgp_Array1OfPnt(1, inPoints.length + (closed ? 1 : 0)); for (let pIndex = 1; pIndex <= inPoints.length; pIndex++) { ptList.SetValue(pIndex, convertToPnt(inPoints[pIndex - 1])); @@ -117,14 +130,11 @@ function BSpline(inPoints, closed) { return curSpline; } -function Text3D(text, size, height, fontName) { - if (!size ) { size = 36; } - if (!height && height !== 0.0) { height = 0.15; } - if (!fontName) { fontName = "Consolas"; } +export function Text3D(text, size = 36, height = 0.15, fontName = "Consolas") { - let textArgs = JSON.stringify(arguments); - let curText = CacheOp(arguments, () => { - if (fonts[fontName] === undefined) { argCache = {}; console.log("Font not loaded or found yet! Try again..."); return; } + let textArgs = JSON.stringify({ text, size, height, fontName }); + let curText = CacheOp(Text3D, () => { + if (fonts[fontName] === undefined) { setArgCache({}); console.log("Font not loaded or found yet! Try again..."); return; } let textFaces = []; let commands = fonts[fontName].getPath(text, 0, 0, size).commands; for (let idx = 0; idx < commands.length; idx++) { @@ -188,7 +198,7 @@ function Text3D(text, size, height, fontName) { } else { textFaces[textFaces.length - 1].hash = stringToHash(textArgs); let textSolid = Rotate([1, 0, 0], -90, Extrude(textFaces[textFaces.length - 1], [0, 0, height * size])); - sceneShapes = Remove(sceneShapes, textSolid); + RemoveFromSceneShapes(textSolid); return textSolid; } }); @@ -198,24 +208,24 @@ function Text3D(text, size, height, fontName) { } // These foreach functions are not cache friendly right now! -function ForEachSolid(shape, callback) { +export function ForEachSolid(shape, callback) { let solid_index = 0; let anExplorer = new oc.TopExp_Explorer(shape, oc.TopAbs_SOLID); for (anExplorer.Init(shape, oc.TopAbs_SOLID); anExplorer.More(); anExplorer.Next()) { callback(solid_index++, oc.TopoDS.prototype.Solid(anExplorer.Current())); } } -function GetNumSolidsInCompound(shape) { +export function GetNumSolidsInCompound(shape) { if (!shape || shape.ShapeType() > 1 || shape.IsNull()) { console.error("Not a compound shape!"); return shape; } let solidsFound = 0; ForEachSolid(shape, (i, s) => { solidsFound++; }); return solidsFound; } -function GetSolidFromCompound(shape, index, keepOriginal) { +export function GetSolidFromCompound(shape, index, keepOriginal) { if (!shape || shape.ShapeType() > 1 || shape.IsNull()) { console.error("Not a compound shape!"); return shape; } if (!index) { index = 0;} - let sol = CacheOp(arguments, () => { + let sol = CacheOp(GetSolidFromCompound, () => { let innerSolid = {}; let solidsFound = 0; ForEachSolid(shape, (i, s) => { if (i === index) { innerSolid = new oc.TopoDS_Solid(s); } solidsFound++; @@ -225,13 +235,13 @@ function GetSolidFromCompound(shape, index, keepOriginal) { return innerSolid; }); - if (!keepOriginal) { sceneShapes = Remove(sceneShapes, shape); } + if (!keepOriginal) { RemoveFromSceneShapes(shape); } sceneShapes.push(sol); return sol; } -function ForEachShell(shape, callback) { +export function ForEachShell(shape, callback) { let shell_index = 0; let anExplorer = new oc.TopExp_Explorer(shape, oc.TopAbs_SHELL); for (anExplorer.Init(shape, oc.TopAbs_SHELL); anExplorer.More(); anExplorer.Next()) { @@ -239,7 +249,7 @@ function ForEachShell(shape, callback) { } } -function ForEachFace(shape, callback) { +export function ForEachFace(shape, callback) { let face_index = 0; let anExplorer = new oc.TopExp_Explorer(shape, oc.TopAbs_FACE); for (anExplorer.Init(shape, oc.TopAbs_FACE); anExplorer.More(); anExplorer.Next()) { @@ -247,18 +257,18 @@ function ForEachFace(shape, callback) { } } -function ForEachWire(shape, callback) { +export function ForEachWire(shape, callback) { let wire_index = 0; let anExplorer = new oc.TopExp_Explorer(shape, oc.TopAbs_WIRE); for (anExplorer.Init(shape, oc.TopAbs_WIRE); anExplorer.More(); anExplorer.Next()) { callback(wire_index++, oc.TopoDS.prototype.Wire(anExplorer.Current())); } } -function GetWire(shape, index, keepOriginal) { +export function GetWire(shape, index, keepOriginal) { if (!shape || shape.ShapeType() > 4 || shape.IsNull()) { console.error("Not a wire shape!"); return shape; } if (!index) { index = 0;} - let wire = CacheOp(arguments, () => { + let wire = CacheOp(GetWire, () => { let innerWire = {}; let wiresFound = 0; ForEachWire(shape, (i, s) => { if (i === index) { innerWire = new oc.TopoDS_Wire(s); } wiresFound++; @@ -268,13 +278,13 @@ function GetWire(shape, index, keepOriginal) { return innerWire; }); - if (!keepOriginal) { sceneShapes = Remove(sceneShapes, shape); } + if (!keepOriginal) { RemoveFromSceneShapes(shape); } sceneShapes.push(wire); return wire; } -function ForEachEdge(shape, callback) { +export function ForEachEdge(shape, callback) { let edgeHashes = {}; let edgeIndex = 0; let anExplorer = new oc.TopExp_Explorer(shape, oc.TopAbs_EDGE); @@ -289,15 +299,15 @@ function ForEachEdge(shape, callback) { return edgeHashes; } -function ForEachVertex(shape, callback) { +export function ForEachVertex(shape, callback) { let anExplorer = new oc.TopExp_Explorer(shape, oc.TopAbs_VERTEX); for (anExplorer.Init(shape, oc.TopAbs_VERTEX); anExplorer.More(); anExplorer.Next()) { callback(oc.TopoDS.prototype.Vertex(anExplorer.Current())); } } -function FilletEdges(shape, radius, edgeList, keepOriginal) { - let curFillet = CacheOp(arguments, () => { +export function FilletEdges(shape, radius, edgeList, keepOriginal) { + let curFillet = CacheOp(FilletEdges, () => { let mkFillet = new oc.BRepFilletAPI_MakeFillet(shape); let foundEdges = 0; ForEachEdge(shape, (index, edge) => { @@ -310,12 +320,12 @@ function FilletEdges(shape, radius, edgeList, keepOriginal) { return new oc.TopoDS_Solid(mkFillet.Shape()); }); sceneShapes.push(curFillet); - if (!keepOriginal) { sceneShapes = Remove(sceneShapes, shape); } + if (!keepOriginal) { RemoveFromSceneShapes(shape); } return curFillet; } -function ChamferEdges(shape, distance, edgeList, keepOriginal) { - let curChamfer = CacheOp(arguments, () => { +export function ChamferEdges(shape, distance, edgeList, keepOriginal) { + let curChamfer = CacheOp(ChamferEdges, () => { let mkChamfer = new oc.BRepFilletAPI_MakeChamfer(shape); let foundEdges = 0; ForEachEdge(shape, (index, edge) => { @@ -328,14 +338,13 @@ function ChamferEdges(shape, distance, edgeList, keepOriginal) { return new oc.TopoDS_Solid(mkChamfer.Shape()); }); sceneShapes.push(curChamfer); - if (!keepOriginal) { sceneShapes = Remove(sceneShapes, shape); } + if (!keepOriginal) { RemoveFromSceneShapes(shape); } return curChamfer; } -function Transform(translation, rotation, scale, shapes) { - let args = arguments; - return CacheOp(arguments, () => { - if (args.length == 4) { +export function Transform(translation, rotation, scale, shapes) { + return CacheOp(Transform, () => { + if (typeof shapes !== "undefined") { // Create the transform gizmo and add it to the scene postMessage({ "type": "createTransformHandle", payload: { translation: translation, rotation: rotation, scale: scale, lineAndColumn: getCallingLocation() } }); // Transform the Object(s) @@ -348,8 +357,8 @@ function Transform(translation, rotation, scale, shapes) { }); } -function Translate(offset, shapes, keepOriginal) { - let translated = CacheOp(arguments, () => { +export function Translate(offset, shapes, keepOriginal) { + let translated = CacheOp(Translate, () => { let transformation = new oc.gp_Trsf(); transformation.SetTranslation(new oc.gp_Vec(offset[0], offset[1], offset[2])); let translation = new oc.TopLoc_Location(transformation); @@ -364,18 +373,18 @@ function Translate(offset, shapes, keepOriginal) { } }); - if (!keepOriginal) { sceneShapes = Remove(sceneShapes, shapes); } + if (!keepOriginal) { RemoveFromSceneShapes(shapes); } sceneShapes.push(translated); return translated; } -function Rotate(axis, degrees, shapes, keepOriginal) { +export function Rotate(axis, degrees, shapes, keepOriginal) { let rotated = null; if (degrees === 0) { rotated = new oc.TopoDS_Shape(shapes); } else { - rotated = CacheOp(arguments, () => { + rotated = CacheOp(Rotate, () => { let newRot; let transformation = new oc.gp_Trsf(); transformation.SetRotation( @@ -392,13 +401,13 @@ function Rotate(axis, degrees, shapes, keepOriginal) { return newRot; }); } - if (!keepOriginal) { sceneShapes = Remove(sceneShapes, shapes); } + if (!keepOriginal) { RemoveFromSceneShapes(shapes); } sceneShapes.push(rotated); return rotated; } -function Scale(scale, shapes, keepOriginal) { - let scaled = CacheOp(arguments, () => { +export function Scale(scale, shapes, keepOriginal) { + let scaled = CacheOp(Scale, () => { let transformation = new oc.gp_Trsf(); transformation.SetScaleFactor(scale); let scaling = new oc.TopLoc_Location(transformation); @@ -413,16 +422,16 @@ function Scale(scale, shapes, keepOriginal) { } }); - if (!keepOriginal) { sceneShapes = Remove(sceneShapes, shapes); } + if (!keepOriginal) { RemoveFromSceneShapes(shapes); } sceneShapes.push(scaled); return scaled; } // TODO: These ops can be more cache optimized since they're multiple sequential ops -function Union(objectsToJoin, keepObjects, fuzzValue, keepEdges) { +export function Union(objectsToJoin, keepObjects, fuzzValue, keepEdges) { if (!fuzzValue) { fuzzValue = 0.1; } - let curUnion = CacheOp(arguments, () => { + let curUnion = CacheOp(Union, () => { let combined = new oc.TopoDS_Shape(objectsToJoin[0]); if (objectsToJoin.length > 1) { for (let i = 0; i < objectsToJoin.length; i++) { @@ -444,15 +453,14 @@ function Union(objectsToJoin, keepObjects, fuzzValue, keepEdges) { }); for (let i = 0; i < objectsToJoin.length; i++) { - if (!keepObjects) { sceneShapes = Remove(sceneShapes, objectsToJoin[i]); } + if (!keepObjects) { RemoveFromSceneShapes(objectsToJoin[i]); } } sceneShapes.push(curUnion); return curUnion; } -function Difference(mainBody, objectsToSubtract, keepObjects, fuzzValue, keepEdges) { - if (!fuzzValue) { fuzzValue = 0.1; } - let curDifference = CacheOp(arguments, () => { +export function Difference(mainBody, objectsToSubtract, keepObjects, fuzzValue = 0.1, keepEdges) { + let curDifference = CacheOp(Difference, () => { if (!mainBody || mainBody.IsNull()) { console.error("Main Shape in Difference is null!"); } let difference = new oc.TopoDS_Shape(mainBody); @@ -471,7 +479,7 @@ function Difference(mainBody, objectsToSubtract, keepObjects, fuzzValue, keepEdg difference = fusor.Shape(); } - difference.hash = ComputeHash(arguments); + difference.hash = ComputeHash(Difference); if (GetNumSolidsInCompound(difference) === 1) { difference = GetSolidFromCompound(difference, 0); } @@ -479,17 +487,17 @@ function Difference(mainBody, objectsToSubtract, keepObjects, fuzzValue, keepEdg return difference; }); - if (!keepObjects) { sceneShapes = Remove(sceneShapes, mainBody); } + if (!keepObjects) { RemoveFromSceneShapes(mainBody); } for (let i = 0; i < objectsToSubtract.length; i++) { - if (!keepObjects) { sceneShapes = Remove(sceneShapes, objectsToSubtract[i]); } + if (!keepObjects) { RemoveFromSceneShapes(objectsToSubtract[i]); } } sceneShapes.push(curDifference); return curDifference; } -function Intersection(objectsToIntersect, keepObjects, fuzzValue, keepEdges) { +export function Intersection(objectsToIntersect, keepObjects, fuzzValue, keepEdges) { if (!fuzzValue) { fuzzValue = 0.1; } - let curIntersection = CacheOp(arguments, () => { + let curIntersection = CacheOp(Intersection, () => { let intersected = new oc.TopoDS_Shape(objectsToIntersect[0]); if (objectsToIntersect.length > 1) { for (let i = 0; i < objectsToIntersect.length; i++) { @@ -511,40 +519,40 @@ function Intersection(objectsToIntersect, keepObjects, fuzzValue, keepEdges) { }); for (let i = 0; i < objectsToIntersect.length; i++) { - if (!keepObjects) { sceneShapes = Remove(sceneShapes, objectsToIntersect[i]); } + if (!keepObjects) { RemoveFromSceneShapes(objectsToIntersect[i]); } } sceneShapes.push(curIntersection); return curIntersection; } -function Extrude(face, direction, keepFace) { - let curExtrusion = CacheOp(arguments, () => { +export function Extrude(face, direction, keepFace) { + let curExtrusion = CacheOp(Extrude, () => { return new oc.BRepPrimAPI_MakePrism(face, new oc.gp_Vec(direction[0], direction[1], direction[2])).Shape(); }); - if (!keepFace) { sceneShapes = Remove(sceneShapes, face); } + if (!keepFace) { RemoveFromSceneShapes(face); } sceneShapes.push(curExtrusion); return curExtrusion; } -function RemoveInternalEdges(shape, keepShape) { - let cleanShape = CacheOp(arguments, () => { +export function RemoveInternalEdges(shape, keepShape) { + let cleanShape = CacheOp(RemoveInternalEdges, () => { let fusor = new oc.ShapeUpgrade_UnifySameDomain(shape); fusor.Build(); return fusor.Shape(); }); - if (!keepShape) { sceneShapes = Remove(sceneShapes, shape); } + if (!keepShape) { RemoveFromSceneShapes(shape); } sceneShapes.push(cleanShape); return cleanShape; } -function Offset(shape, offsetDistance, tolerance, keepShape) { +export function Offset(shape, offsetDistance, tolerance, keepShape) { if (!shape || shape.IsNull()) { console.error("Offset received Null Shape!"); } if (!tolerance) { tolerance = 0.1; } if (offsetDistance === 0.0) { return shape; } - let curOffset = CacheOp(arguments, () => { + let curOffset = CacheOp(Offset, () => { let offset = null; if (shape.ShapeType() === 5) { offset = new oc.BRepOffsetAPI_MakeOffset(); @@ -566,15 +574,15 @@ function Offset(shape, offsetDistance, tolerance, keepShape) { return offsetShape; }); - if (!keepShape) { sceneShapes = Remove(sceneShapes, shape); } + if (!keepShape) { RemoveFromSceneShapes(shape); } sceneShapes.push(curOffset); return curOffset; } -function Revolve(shape, degrees, direction, keepShape, copy) { +export function Revolve(shape, degrees, direction, keepShape, copy) { if (!degrees ) { degrees = 360.0; } if (!direction) { direction = [0, 0, 1]; } - let curRevolution = CacheOp(arguments, () => { + let curRevolution = CacheOp(Revolve, () => { if (degrees >= 360.0) { return new oc.BRepPrimAPI_MakeRevol(shape, new oc.gp_Ax1(new oc.gp_Pnt(0, 0, 0), @@ -588,22 +596,22 @@ function Revolve(shape, degrees, direction, keepShape, copy) { } }); - if (!keepShape) { sceneShapes = Remove(sceneShapes, shape); } + if (!keepShape) { RemoveFromSceneShapes(shape); } sceneShapes.push(curRevolution); return curRevolution; } -function RotatedExtrude(wire, height, rotation, keepWire) { +export function RotatedExtrude(wire, height, rotation, keepWire) { if (!wire || wire.IsNull()) { console.error("RotatedExtrude received Null Wire!"); } - let curExtrusion = CacheOp(arguments, () => { + let curExtrusion = CacheOp(RotatedExtrude, () => { let upperPolygon = Rotate([0, 0, 1], rotation, Translate([0, 0, height], wire, true)); - sceneShapes = Remove(sceneShapes, upperPolygon); + RemoveFromSceneShapes(upperPolygon); // Define the straight spine going up the middle of the sweep let spineWire = BSpline([ [0, 0, 0], [0, 0, height]], false); - sceneShapes = Remove(sceneShapes, spineWire); // Don't render these + RemoveFromSceneShapes(spineWire); // Don't render these // Define the guiding helical auxiliary spine (which controls the rotation) let steps = 30; @@ -617,7 +625,7 @@ function RotatedExtrude(wire, height, rotation, keepWire) { } let aspineWire = BSpline(aspinePoints, false); - sceneShapes = Remove(sceneShapes, aspineWire); // Don't render these + RemoveFromSceneShapes(aspineWire); // Don't render these // Sweep the face wires along the spine to create the extrusion let pipe = new oc.BRepOffsetAPI_MakePipeShell(spineWire); @@ -628,13 +636,13 @@ function RotatedExtrude(wire, height, rotation, keepWire) { pipe.MakeSolid(); return new oc.TopoDS_Shape(pipe.Shape()); }); - if (!keepWire) { sceneShapes = Remove(sceneShapes, wire); } + if (!keepWire) { RemoveFromSceneShapes(wire); } sceneShapes.push(curExtrusion); return curExtrusion; } -function Loft(wires, keepWires) { - let curLoft = CacheOp(arguments, () => { +export function Loft(wires, keepWires) { + let curLoft = CacheOp(Loft, () => { let pipe = new oc.BRepOffsetAPI_ThruSections(true); // Construct a Loft that passes through the wires @@ -645,22 +653,22 @@ function Loft(wires, keepWires) { }); wires.forEach((wire) => { - if (!keepWires) { sceneShapes = Remove(sceneShapes, wire); } + if (!keepWires) { RemoveFromSceneShapes(wire); } }); sceneShapes.push(curLoft); return curLoft; } -function Pipe(shape, wirePath, keepInputs) { - let curPipe = CacheOp(arguments, () => { +export function Pipe(shape, wirePath, keepInputs) { + let curPipe = CacheOp(Pipe, () => { let pipe = new oc.BRepOffsetAPI_MakePipe(wirePath, shape); pipe.Build(); return new oc.TopoDS_Shape(pipe.Shape()); }); if (!keepInputs) { - sceneShapes = Remove(sceneShapes, shape); - sceneShapes = Remove(sceneShapes, wirePath); + RemoveFromSceneShapes(shape); + RemoveFromSceneShapes(wirePath); } sceneShapes.push(curPipe); return curPipe; @@ -668,7 +676,7 @@ function Pipe(shape, wirePath, keepInputs) { // This is a utility class for drawing wires/shapes with lines, arcs, and splines // This is unique, it needs to be called with the "new" keyword prepended -function Sketch(startingPoint) { +export function Sketch(startingPoint) { this.currentIndex = 0; this.faces = []; this.wires = []; @@ -676,19 +684,19 @@ function Sketch(startingPoint) { this.lastPoint = this.firstPoint; this.wireBuilder = new oc.BRepBuilderAPI_MakeWire(); this.fillets = []; - this.argsString = ComputeHash(arguments, true); + this.argsString = ComputeHash(Sketch, true); // Functions are: BSplineTo, Fillet, Wire, and Face this.Start = function (startingPoint) { this.firstPoint = new oc.gp_Pnt(startingPoint[0], startingPoint[1], 0); this.lastPoint = this.firstPoint; this.wireBuilder = new oc.BRepBuilderAPI_MakeWire(); - this.argsString += ComputeHash(arguments, true); + this.argsString += ComputeHash(this.Start, true); return this; } this.End = function (closed, reversed) { - this.argsString += ComputeHash(arguments, true); + this.argsString += ComputeHash(this.End, true); if (closed && (this.firstPoint.X() !== this.lastPoint.X() || @@ -718,7 +726,7 @@ function Sketch(startingPoint) { } this.Wire = function (reversed) { - this.argsString += ComputeHash(arguments, true); + this.argsString += ComputeHash(this.Wire, true); //let wire = this.wires[this.wires.length - 1]; this.applyFillets(); this.faces[this.faces.length - 1].hash = stringToHash(this.argsString); @@ -728,7 +736,7 @@ function Sketch(startingPoint) { return wire; } this.Face = function (reversed) { - this.argsString += ComputeHash(arguments, true); + this.argsString += ComputeHash(this.Face, true); this.applyFillets(); let face = this.faces[this.faces.length - 1]; if (reversed) { face = face.Reversed(); } @@ -767,7 +775,7 @@ function Sketch(startingPoint) { } this.AddWire = function (wire) { - this.argsString += ComputeHash(arguments, true); + this.argsString += ComputeHash(this.AddWire, true); // This adds another wire (or edge??) to the currently constructing shape... this.wireBuilder.Add(wire); if (endPoint) { this.lastPoint = endPoint; } // Yike what to do here...? @@ -775,7 +783,7 @@ function Sketch(startingPoint) { } this.LineTo = function (nextPoint) { - this.argsString += ComputeHash(arguments, true); + this.argsString += ComputeHash(this.LineTo, true); let endPoint = null; if (nextPoint.X) { if (this.lastPoint.X() === nextPoint.X() && @@ -795,7 +803,7 @@ function Sketch(startingPoint) { } this.ArcTo = function (pointOnArc, arcEnd) { - this.argsString += ComputeHash(arguments, true); + this.argsString += ComputeHash(this.ArcTo, true); let onArc = new oc.gp_Pnt(pointOnArc[0], pointOnArc[1], 0); let nextPoint = new oc.gp_Pnt( arcEnd[0], arcEnd[1], 0); let arcCurve = new oc.GC_MakeArcOfCircle(this.lastPoint, onArc, nextPoint).Value(); @@ -809,7 +817,7 @@ function Sketch(startingPoint) { // Constructs an order-N Bezier Curve where the first N-1 points are control points // and the last point is the endpoint of the curve this.BezierTo = function (bezierControlPoints) { - this.argsString += ComputeHash(arguments, true); + this.argsString += ComputeHash(this.BezierTo, true); let ptList = new oc.TColgp_Array1OfPnt(1, bezierControlPoints.length+1); ptList.SetValue(1, this.lastPoint); for (let bInd = 0; bInd < bezierControlPoints.length; bInd++){ @@ -827,7 +835,7 @@ function Sketch(startingPoint) { /* Constructs a BSpline from the previous point through this set of points */ this.BSplineTo = function (bsplinePoints) { - this.argsString += ComputeHash(arguments, true); + this.argsString += ComputeHash(this.BSplineTo, true); let ptList = new oc.TColgp_Array1OfPnt(1, bsplinePoints.length+1); ptList.SetValue(1, this.lastPoint); for (let bInd = 0; bInd < bsplinePoints.length; bInd++){ @@ -843,13 +851,13 @@ function Sketch(startingPoint) { } this.Fillet = function (radius) { - this.argsString += ComputeHash(arguments, true); + this.argsString += ComputeHash(this.Fillet, true); this.fillets.push({ x: this.lastPoint.X(), y: this.lastPoint.Y(), radius: radius }); return this; } this.Circle = function (center, radius, reversed) { - this.argsString += ComputeHash(arguments, true); + this.argsString += ComputeHash(this.Circle, true); let circle = new oc.GC_MakeCircle(new oc.gp_Ax2(convertToPnt(center), new oc.gp_Dir(0, 0, 1)), radius).Value(); let edge = new oc.BRepBuilderAPI_MakeEdge(circle).Edge(); @@ -881,7 +889,7 @@ function SaveFile(filename, fileURL) { }); } -function Slider(name = "Val", defaultValue = 0.5, min = 0.0, max = 1.0, realTime=false, step, precision) { +export function Slider(name = "Val", defaultValue = 0.5, min = 0.0, max = 1.0, realTime=false, step, precision) { if (!(name in GUIState)) { GUIState[name] = defaultValue; } if (!step) { step = 0.01; } if (typeof precision === "undefined") { @@ -893,11 +901,11 @@ function Slider(name = "Val", defaultValue = 0.5, min = 0.0, max = 1.0, realTime return GUIState[name]; } -function Button(name = "Action") { +export function Button(name = "Action") { postMessage({ "type": "addButton", payload: { name: name } }); } -function Checkbox(name = "Toggle", defaultValue = false) { +export function Checkbox(name = "Toggle", defaultValue = false) { if (!(name in GUIState)) { GUIState[name] = defaultValue; } postMessage({ "type": "addCheckbox", payload: { name: name, default: defaultValue } }); return GUIState[name]; diff --git a/js/CADWorker/CascadeStudioStandardUtils.js b/js/CADWorker/CascadeStudioStandardUtils.js index 8bb2906..289ab1e 100644 --- a/js/CADWorker/CascadeStudioStandardUtils.js +++ b/js/CADWorker/CascadeStudioStandardUtils.js @@ -1,19 +1,34 @@ +import { + oc, + GUIState, + opNumber, + setOpNumber, + setCurrentLineNumber, + argCache, + setCurrentOp, + usedHashes +} from "./CascadeStudioWorkerState"; // Miscellaneous Helper Functions used in the Standard Library -// Caching functions to speed up evaluation of slow redundant operations -var argCache = {}; var usedHashes = {}; var opNumber = 0; var currentOp = ''; var currentLineNumber = 0; +function getCalleeName(fn) { + var ret = fn.toString(); + ret = ret.substr("function ".length); + ret = ret.substr(0, ret.indexOf("(")); + return ret; +} /** Hashes input arguments and checks the cache for that hash. * It returns a copy of the cached object if it exists, but will * call the `cacheMiss()` callback otherwise. The result will be * added to the cache if `GUIState["Cache?"]` is true. */ -function CacheOp(args, cacheMiss) { +export function CacheOp(callee, cacheMiss) { //toReturn = cacheMiss(); - currentOp = args.callee.name; - currentLineNumber = getCallingLocation()[0]; - postMessage({ "type": "Progress", "payload": { "opNumber": opNumber++, "opType": args.callee.name } }); // Poor Man's Progress Indicator + setCurrentOp(getCalleeName(callee)); + setCurrentLineNumber(getCallingLocation()[0]); + postMessage({ "type": "Progress", "payload": { "opNumber": opNumber, "opType": getCalleeName(callee) } }); // Poor Man's Progress Indicator + setOpNumber(opNumber + 1); let toReturn = null; - let curHash = ComputeHash(args); usedHashes[curHash] = curHash; + let curHash = ComputeHash(callee); usedHashes[curHash] = curHash; let check = CheckCache(curHash); if (check && GUIState["Cache?"]) { //console.log("HIT "+ ComputeHash(args) + ", " +ComputeHash(args, true)); @@ -40,12 +55,12 @@ function AddToCache(hash, shape) { /** This function computes a 32-bit integer hash given a set of `arguments`. * If `raw` is true, the raw set of sanitized arguments will be returned instead. */ -function ComputeHash(args, raw) { - let argsString = JSON.stringify(args); +export function ComputeHash(callee, raw) { + let argsString = JSON.stringify(getCalleeName(callee)); argsString = argsString.replace(/(\"ptr\"\:(-?[0-9]*?)\,)/g, ''); argsString = argsString.replace(/(\"ptr\"\:(-?[0-9]*))/g, ''); if (argsString.includes("ptr")) { console.error("YOU DONE MESSED UP YOUR REGEX."); } - let hashString = args.callee.name + argsString;// + GUIState["MeshRes"]; + let hashString = getCalleeName(callee) + argsString;// + GUIState["MeshRes"]; if (raw) { return hashString; } return stringToHash(hashString); } @@ -73,16 +88,9 @@ function recursiveTraverse(x, callback) { } } -/** This function returns a version of the `inputArray` without the `objectToRemove`. */ -function Remove(inputArray, objectToRemove) { - return inputArray.filter((el) => { - return el.hash !== objectToRemove.hash || - el.ptr !== objectToRemove.ptr; - }); -} /** This function returns true if item is indexable like an array. */ -function isArrayLike(item) { +export function isArrayLike(item) { return ( Array.isArray(item) || (!!item && @@ -97,7 +105,7 @@ function isArrayLike(item) { /** Mega Brittle Line Number Finding algorithm for Handle Backpropagation; only works in Chrome and FF. * Eventually this should be replaced with Microsoft's Typescript interpreter, but that's a big dependency...*/ -function getCallingLocation() { +export function getCallingLocation() { let errorStack = (new Error).stack; //console.log(errorStack); //console.log(navigator.userAgent); @@ -128,7 +136,7 @@ function getCallingLocation() { /** This function converts either single dimensional * array or a gp_Pnt to a gp_Pnt. Does not accept * `TopoDS_Vertex`'s yet! */ -function convertToPnt(pnt) { +export function convertToPnt(pnt) { let point = pnt; // Accept raw gp_Points if we got 'em if (point.length) { point = new oc.gp_Pnt(point[0], point[1], (point[2])?point[2]:0); @@ -137,7 +145,7 @@ function convertToPnt(pnt) { } /** This function converts a string to a 32bit integer. */ -function stringToHash(string) { +export function stringToHash(string) { let hash = 0; if (string.length == 0) return hash; for (let i = 0; i < string.length; i++) { diff --git a/js/CADWorker/CascadeStudioWorkerState.js b/js/CADWorker/CascadeStudioWorkerState.js new file mode 100644 index 0000000..7591ff4 --- /dev/null +++ b/js/CADWorker/CascadeStudioWorkerState.js @@ -0,0 +1,26 @@ +export const messageHandlers = {}; + +export let argCache = {}; +export let currentLineNumber = 0; +export let currentOp = ""; +export let currentShape; +export let externalShapes = {}; +export let GUIState = {}; +export let oc = null; +export let opNumber = 0; // This keeps track of the progress of the evaluation +export let usedHashes = {}; + +export const setArgCache = val => (argCache = val); +export const setCurrentOp = val => (currentOp = val); +export const setCurrentShape = val => (currentShape = val); +export const setCurrentLineNumber = val => (currentLineNumber = val); +export const resetExternalShapes = () => (externalShapes = {}); +export const setGUIState = val => (GUIState = val); +export const setOc = ocInit => (oc = ocInit); +export const setOpNumber = val => (opNumber = val); +export const setUsedHashes = val => (usedHashes = val); + + +// I can't see anywhere, where the following globals are used, variables with these names exist, but they are scoped. +let fullShapeEdgeHashes = {}; +let fullShapeFaceHashes = {}; diff --git a/js/MainPage/CascadeMain.js b/js/MainPage/CascadeMain.js index 3b73811..f0c73d9 100644 --- a/js/MainPage/CascadeMain.js +++ b/js/MainPage/CascadeMain.js @@ -1,11 +1,34 @@ +/* eslint-disable prettier/prettier */ +import { CascadeEnvironment } from "./CascadeView"; +import GoldenLayout from "golden-layout"; +import "golden-layout/src/css/goldenlayout-base.css"; +import "golden-layout/src/css/goldenlayout-dark-theme.css"; +import ControlKit from "controlkit"; +import * as monaco from "monaco-editor"; + +import '../../static_node_modules/rawflate/rawdeflate' +import '../../static_node_modules/rawflate/rawinflate' + +import { + messageHandlers, + workerWorking, + setWorkerWorking, + monacoEditor, + setMonacoEditor, + threejsViewport, + setThreejsViewport, +} from "./CascadeState"; +import cascadeStudioWorker from './CascadeWorkerInit'; + + + // This script governs the layout and intialization of all of the sub-windows // If you're looking for the internals of the CAD System, they're in /js/CADWorker // If you're looking for the 3D Three.js Viewport, they're in /js/MainPage/CascadeView* -var myLayout, monacoEditor, threejsViewport, +var myLayout, consoleContainer, consoleGolden, codeContainer, gui, guiPanel, GUIState, count = 0, //focused = true, - messageHandlers = {}, workerWorking = false, startup, file = {}, realConsoleLog; let starterCode = @@ -29,7 +52,7 @@ Translate([-25, 0, 40], Text3D("Hi!")); // Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!`; -function initialize(projectContent = null) { +export function initialize(projectContent = null) { this.searchParams = new URLSearchParams(window.location.search); // Load the initial Project from - "projectContent", the URL, or the Gallery @@ -106,7 +129,7 @@ function initialize(projectContent = null) { // Destroy the existing editor if it exists if (monacoEditor) { monaco.editor.getModels().forEach(model => model.dispose()); - monacoEditor = null; + setMonacoEditor(null); } // Set the Monaco Language Options @@ -118,29 +141,17 @@ function initialize(projectContent = null) { // Import Typescript Intellisense Definitions for the relevant libraries... var extraLibs = []; - let prefix = window.location.href.startsWith("https://zalo.github.io/") ? "/CascadeStudio" : ""; - // opencascade.js Typescript Definitions... - fetch(prefix + "/node_modules/opencascade.js/dist/oc.d.ts").then((response) => { - response.text().then(function (text) { - extraLibs.push({ content: text, filePath: 'file://' + prefix + '/node_modules/opencascade.js/dist/oc.d.ts' }); - }); - }).catch(error => console.log(error.message)); - - // Three.js Typescript definitions... - fetch(prefix + "/node_modules/three/build/three.d.ts").then((response) => { - response.text().then(function (text) { - extraLibs.push({ content: text, filePath: 'file://' + prefix + '/node_modules/three/build/three.d.ts' }); - }); - }).catch(error => console.log(error.message)); - - // CascadeStudio Typescript Definitions... - fetch(prefix + "/js/StandardLibraryIntellisense.ts").then((response) => { - response.text().then(function (text) { - extraLibs.push({ content: text, filePath: 'file://' + prefix + '/js/StandardLibraryIntellisense.d.ts' }); + const typescriptDefinitionFiles = ["opencascade.d.ts", "Three.d.ts", "js/StandardLibraryIntellisense.ts"] + + Promise.all(typescriptDefinitionFiles.map(fileLocation => fetch(fileLocation))) + .then(async responses => { + const files = await Promise.all(responses.map(response => response.text())) + extraLibs = files.map((file, index) => { + return ({ content: file, filePath: 'file://' + typescriptDefinitionFiles[index] }) + }) monaco.editor.createModel("", "typescript"); //text monaco.languages.typescript.typescriptDefaults.setExtraLibs(extraLibs); - }); - }).catch(error => console.log(error.message)); + }).catch(error => console.log(error.message)); // Check for code serialization as an array codeContainer = container; @@ -155,7 +166,7 @@ function initialize(projectContent = null) { } // Initialize the Monaco Code Editor inside this dockable container - monacoEditor = monaco.editor.create(container.getElement().get(0), { + const newMonacoEditor = monaco.editor.create(container.getElement().get(0), { value: state.code, language: "typescript", theme: "vs-dark", @@ -163,6 +174,7 @@ function initialize(projectContent = null) { minimap: { enabled: false }//, //model: null }); + setMonacoEditor(newMonacoEditor); // Collapse all Functions in the Editor to suppress library clutter ----------------- let codeLines = state.code.split(/\r\n|\r|\n/); @@ -197,7 +209,7 @@ function initialize(projectContent = null) { // Set the "workerWorking" flag, so we don't submit // multiple jobs to the worker thread simultaneously - workerWorking = true; + setWorkerWorking(true); // Refresh these every so often to ensure we're always getting intellisense monaco.languages.typescript.typescriptDefaults.setExtraLibs(extraLibs); @@ -301,7 +313,7 @@ function initialize(projectContent = null) { // Destroy the existing editor if it exists if (threejsViewport) { threejsViewport.active = false; - threejsViewport = null; + setThreejsViewport(null) } let floatingGUIContainer = document.createElement("div"); @@ -313,8 +325,8 @@ function initialize(projectContent = null) { gui = new ControlKit({ parentDomElementId: "controlKit" }); } else { // We are loading a new project, controlKit needs to have - // it's node ovirriden with the new element - gui._node._element = $('#controlKit')[0]; + // it's node overridden with the new element + gui._node._element = document.getElementById('controlKit'); } gui.clearPanels = function () { let curNode = this._node._element; @@ -325,7 +337,7 @@ function initialize(projectContent = null) { }.bind(gui); } - threejsViewport = new CascadeEnvironment(container); + setThreejsViewport(new CascadeEnvironment(container)); }); }); @@ -371,7 +383,10 @@ function initialize(projectContent = null) { }; // Call this console.log when triggered from the WASM messageHandlers["log" ] = (payload) => { console.log(payload); }; - messageHandlers["error"] = (payload) => { workerWorking = false; console.error(payload); }; + messageHandlers["error"] = (payload) => { + setWorkerWorking(false); + console.error(payload); + }; // Print Errors in Red window.onerror = function (err, url, line, colno, errorObj) { @@ -468,10 +483,10 @@ function initialize(projectContent = null) { if (!(payload.name in GUIState)) { GUIState[payload.name] = payload.default; } guiPanel.addCheckbox(GUIState, payload.name, { onChange: () => { monacoEditor.evaluateCode() } }); } - messageHandlers["resetWorking"] = () => { workerWorking = false; } + messageHandlers["resetWorking"] = () => setWorkerWorking(false) } -async function getNewFileHandle(desc, mime, ext, open = false) { +export async function getNewFileHandle(desc, mime, ext, open = false) { const options = { types: [ { @@ -489,7 +504,7 @@ async function getNewFileHandle(desc, mime, ext, open = false) { } } -async function writeFile(fileHandle, contents) { +export async function writeFile(fileHandle, contents) { // Create a FileSystemWritableFileStream to write to. const writable = await fileHandle.createWritable(); // Write the contents of the file to the stream. @@ -500,7 +515,7 @@ async function writeFile(fileHandle, contents) { /** This function serializes the Project's current state * into a `.json` file and saves it to the selected location. */ -async function saveProject() { +export async function saveProject() { let currentCode = monacoEditor.getValue(); if (!file.handle) { file.handle = await getNewFileHandle( @@ -520,7 +535,7 @@ async function saveProject() { } /** This loads a .json file as the currentProject.*/ -const loadProject = async () => { +export const loadProject = async () => { // Don't allow loading while the worker is working to prevent race conditions. if (workerWorking) { return; } @@ -534,14 +549,14 @@ const loadProject = async () => { let fileSystemFile = await file.handle.getFile(); let jsonContent = await fileSystemFile.text(); window.history.replaceState({}, 'Cascade Studio','?'); - initialize(projectContent=jsonContent); + new initialize(jsonContent); codeContainer.setTitle(file.handle.name); file.content = monacoEditor.getValue(); } /** This function triggers the CAD WebWorker to * load one or more .stl, .step, or .iges files. */ -function loadFiles(fileElementID = "files") { +export function loadFiles(fileElementID = "files") { // Ask the worker thread to load these files... // I can already feel this not working... let files = document.getElementById(fileElementID).files; @@ -560,7 +575,7 @@ function loadFiles(fileElementID = "files") { /** This function clears all Externally Loaded files * from the `externalFiles` dict. */ -function clearExternalFiles() { +export function clearExternalFiles() { cascadeStudioWorker.postMessage({ "type": "clearExternalFiles" }); diff --git a/js/MainPage/CascadeState.js b/js/MainPage/CascadeState.js new file mode 100644 index 0000000..f06c7cf --- /dev/null +++ b/js/MainPage/CascadeState.js @@ -0,0 +1,9 @@ +export const messageHandlers = {}; + +export let monacoEditor = null; +export let threejsViewport = {}; +export let workerWorking = false; + +export const setMonacoEditor = newEditor => (monacoEditor = newEditor); +export const setThreejsViewport = val => (threejsViewport = val); +export const setWorkerWorking = val => (workerWorking = val); diff --git a/js/MainPage/CascadeView.js b/js/MainPage/CascadeView.js index 342b5d4..96a2252 100644 --- a/js/MainPage/CascadeView.js +++ b/js/MainPage/CascadeView.js @@ -1,8 +1,55 @@ +import * as THREE from "three"; +import { STLExporter } from "three/examples/jsm/exporters/STLExporter"; +import { OBJExporter } from "three/examples/jsm/exporters/OBJExporter"; +import { initializeHandleGizmos } from "./CascadeViewHandles"; +import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; +import { + messageHandlers, + setWorkerWorking, + threejsViewport +} from "./CascadeState"; +import cascadeStudioWorker from "./CascadeWorkerInit"; +import { + getNewFileHandle, + writeFile, + loadProject, + saveProject, + loadFiles, + clearExternalFiles +} from "./CascadeMain"; // This file governs the 3D Viewport which displays the 3D Model // It is also in charge of saving to STL and OBJ /** Create the base class for a 3D Viewport. * This includes the floor, the grid, the fog, the camera, and lights */ + +function setupIdeButtonListeners() { + document.getElementById("save-step").addEventListener("click", () => { + threejsViewport.saveShapeSTEP(); + }); + document.getElementById("save-stl").addEventListener("click", () => { + threejsViewport.saveShapeSTL(); + }); + document.getElementById("save-obj").addEventListener("click", () => { + threejsViewport.saveShapeOBJ(); + }); + document.getElementById("load-project").addEventListener("click", () => { + loadProject(); + }); + document.getElementById("save-project").addEventListener("click", () => { + saveProject(); + }); + document.getElementById("files").addEventListener("click", () => { + loadFiles(); + }); + document + .getElementById("clear-external-files") + .addEventListener("click", () => { + clearExternalFiles(); + }); +} +setupIdeButtonListeners(); + var Environment = function (goldenContainer) { this.goldenContainer = goldenContainer; @@ -71,7 +118,7 @@ var Environment = function (goldenContainer) { this.scene.add(this.grid); // Set up the orbit controls used for Cascade Studio - this.controls = new THREE.OrbitControls(this.camera, this.renderer.domElement); + this.controls = new OrbitControls(this.camera, this.renderer.domElement); this.controls.target.set(0, 45, 0); this.controls.panSpeed = 2; this.controls.zoomSpeed = 1; @@ -105,7 +152,7 @@ var Environment = function (goldenContainer) { } /** This "inherits" from Environment (by including it as a sub object) */ -var CascadeEnvironment = function (goldenContainer) { +export function CascadeEnvironment (goldenContainer) { this.active = true; this.goldenContainer = goldenContainer; this.environment = new Environment(this.goldenContainer); @@ -133,7 +180,7 @@ var CascadeEnvironment = function (goldenContainer) { // A callback to load the Triangulated Shape from the Worker and add it to the Scene messageHandlers["combineAndRenderShapes"] = ([facelist, edgelist]) => { - workerWorking = false; // Untick this flag to allow Evaluations again + setWorkerWorking(false); // Untick this flag to allow Evaluations again if (!facelist) { return;} // Do nothing if the results are null // The old mainObject is dead! Long live the mainObject! @@ -264,7 +311,7 @@ var CascadeEnvironment = function (goldenContainer) { /** Save the current shape to an ASCII .stl */ this.saveShapeSTL = async () => { - this.stlExporter = new THREE.STLExporter(); + this.stlExporter = new STLExporter(); let result = this.stlExporter.parse(this.mainObject); const fileHandle = await getNewFileHandle("STL files", "text/plain", "stl"); @@ -275,7 +322,7 @@ var CascadeEnvironment = function (goldenContainer) { /** Save the current shape to .obj */ this.saveShapeOBJ = async () => { - this.objExporter = new THREE.OBJExporter(); + this.objExporter = new OBJExporter(); let result = this.objExporter.parse(this.mainObject); const fileHandle = await getNewFileHandle("OBJ files", "text/plain", "obj"); diff --git a/js/MainPage/CascadeViewHandles.js b/js/MainPage/CascadeViewHandles.js index 77d3546..a4a8721 100644 --- a/js/MainPage/CascadeViewHandles.js +++ b/js/MainPage/CascadeViewHandles.js @@ -1,7 +1,10 @@ +import * as THREE from "three"; +import { messageHandlers, monacoEditor } from "./CascadeState"; + // This file handles Transformation Gizmos /** Adds Handle Gizmo Functionality to the Cascade View */ -function initializeHandleGizmos(threejsViewport){ +export function initializeHandleGizmos(threejsViewport){ /** Create a Transformation Gizmo in the Scene View */ messageHandlers["createTransformHandle"] = function (payload) { if (payload.lineAndColumn[0] <= 0) { diff --git a/js/MainPage/CascadeWorkerInit.js b/js/MainPage/CascadeWorkerInit.js new file mode 100644 index 0000000..2548fb6 --- /dev/null +++ b/js/MainPage/CascadeWorkerInit.js @@ -0,0 +1,22 @@ +import { messageHandlers } from "./CascadeState"; +import Worker from "worker-loader!../CADWorker/CascadeStudioMainWorker.js"; + +// Begins loading the CAD Kernel Web Worker +let cascadeStudioWorker; +if (window.Worker) { + cascadeStudioWorker = new Worker(); + // Ping Pong Messages Back and Forth based on their registration in messageHandlers + cascadeStudioWorker.onmessage = function(e) { + if (e.data.type in messageHandlers) { + let response = messageHandlers[e.data.type](e.data.payload); + if (response) { + cascadeStudioWorker.postMessage({ + type: e.data.type, + payload: response + }); + } + } + } +} + +export default cascadeStudioWorker; diff --git a/js/MainPage/index.js b/js/MainPage/index.js new file mode 100644 index 0000000..2161242 --- /dev/null +++ b/js/MainPage/index.js @@ -0,0 +1,17 @@ +import "../../css/main.css"; +import { initialize } from "./CascadeMain"; + +if ("serviceWorker" in navigator) { + navigator.serviceWorker.register("service-worker.js").then( + function(registration) { + registration.update(); // Always update the registration for the latest assets + }, + function() { + console.log("Could not register Cascade Studio for offline use!"); + } + ); +} else { + console.log("Browser does not support offline access!"); +} + +new initialize(); diff --git a/js/StandardLibraryIntellisense.ts b/js/StandardLibraryIntellisense.ts index 9fc9e37..6bd0398 100644 --- a/js/StandardLibraryIntellisense.ts +++ b/js/StandardLibraryIntellisense.ts @@ -221,4 +221,4 @@ function CacheOp(arguments: IArguments, cacheMiss: () => oc.TopoDS_Shape): oc.To /** Remove this object from this array. Useful for preventing objects being added to `sceneShapes` (in cached functions). * [Source](https://github.com/zalo/CascadeStudio/blob/master/js/CADWorker/CascadeStudioStandardLibrary.js) * @example```let box = CacheOp(arguments, () => { let box = Box(x,y,z); sceneShapes = Remove(sceneShapes, box); return box; });``` */ -function Remove(array: any[], toRemove: any): any[]; +function RemoveFromSceneShapes(toRemove: any): any[]; diff --git a/my.test.js b/my.test.js new file mode 100644 index 0000000..902cde5 --- /dev/null +++ b/my.test.js @@ -0,0 +1,3 @@ +test('adds 1 + 2 to equal 3', () => { + expect(1+2).toBe(3); +}); \ No newline at end of file diff --git a/node_modules/controlkit/bin/controlKit.js b/node_modules/controlkit/bin/controlKit.js deleted file mode 100644 index 2b65c9e..0000000 --- a/node_modules/controlkit/bin/controlKit.js +++ /dev/null @@ -1,6889 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var o;"undefined"!=typeof window?o=window:"undefined"!=typeof global?o=global:"undefined"!=typeof self&&(o=self),o.ControlKit=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= countMax){ - count = 0; - self._canUpdate = true; - clearInterval(interval); - } - count++; - },25) - }); - - this._shortcutEnable = DEFAULT_TRIGGER_SHORTCUT_CHAR; - - document.addEventListener('keydown',function(e){ - if(!(e.ctrlKey && String.fromCharCode(e.which || e.keyCode).toLowerCase() == self._shortcutEnable)){ - return; - } - self._enabled = !self._enabled; - if(self._enabled){ - self._enable(); - } else { - self._disable(); - } - }); - - if(!this._enabled){ - this._disable(); - } - - initiated = true; -} -ControlKit.prototype = Object.create(EventDispatcher.prototype); -ControlKit.prototype.constructor = ControlKit; - -/** - * Adds a panel. - * @param {Object} [params] - Panel options - * @param {String} [params.label='Control Panel'] - The panel label - * @param {Number} [params.width=300] - The width - * @param {Number} [params.height] - Constrained panel height - * @param {Number} [params.ratio=40] - The ratio of label (default:40%) and component (default:60%) width - * @param {String} [params.align='right'] - Float 'left' or 'right', multiple panels get aligned next to each other - * @param {Boolean} [params.fixed=true] - If false the panel can be moved - * @param {Array} [params.position=[0,0]] - If unfixed, the panel panel position relative to alignment (eg. if 'left' 0 + position[0] or if 'right' window.innerHeight - position[0] - panelWidth) - * @param {Number} [params.opacity=1.0] - The panel´s opacity - * @param {String} [params.dock=false] - (Experimental) Indicates whether the panel should be docked to either the left or right window border (depending on params.align), docked panels height equal window height - * @returns {Panel} - */ -ControlKit.prototype.addPanel = function (params) { - var panel = new Panel(this, params); - this._panels.push(panel); - return panel; -}; - -/** - * Updates all ControlKit components if the wat - */ -ControlKit.prototype.update = function () { - if (!this._enabled || !this._canUpdate){ - return; - } - var i, j, k; - var l, m, n; - var panels = this._panels, - panel, - groups, - components, - component; - - i = -1; l = panels.length; - while (++i < l) { - panel = panels[i]; - - if (panel.isDisabled()){ - continue; - } - groups = panel.getGroups(); - j = -1; m = groups.length; - - while (++j < m) { - components = groups[j].getComponents(); - k = -1; n = components.length; - - while (++k < n) { - component = components[k]; - if (component.isDisabled()){ - continue; - } - if (component instanceof ValuePlotter || - component instanceof StringOutput || - component instanceof NumberOutput) { - component.update(); - } - } - } - } -}; - -ControlKit.prototype.historyIsEnabled = function () { - return this._historyEnabled; -}; - -ControlKit.prototype.statesAreEnabled = function(){ - return this._statesEnabled; -}; - -ControlKit.prototype.panelsAreClosable = function () { - return this._panelsClosable; -}; - -ControlKit.prototype._enable = function(){ - var i = -1, p = this._panels, l = p.length; - while (++i < l){ - p[i].enable(); - } - this._node.setStyleProperty('visibility', ''); -}; - -ControlKit.prototype._disable = function(){ - var i = -1, p = this._panels, l = p.length; - while (++i < l){ - p[i].disable(); - } - this._node.setStyleProperty('visibility', 'hidden'); -}; - -/** - * Enables and shows controlKit. - */ - -ControlKit.prototype.enable = function () { - this._enable(); - this._enabled = true; -}; - -/** - * Disable and hides controlKit. - */ - -ControlKit.prototype.disable = function () { - this._disable(); - this._enabled = false; -}; - - -/** - * Specifies the key to be used with ctrl & char, to trigger ControlKits visibility. - * @param char - */ - -ControlKit.prototype.setShortcutEnable = function(char){ - this._shortcutEnable = char; -}; - -ControlKit.prototype.onHistoryStatePush = function () { - this.dispatchEvent(new Event_(this, MenuEvent.UPDATE_MENU, null)); -}; - -ControlKit.prototype.onHistoryStatePop = function () { - this.dispatchEvent(new Event_(this, ComponentEvent.UPDATE_VALUE, {origin: null})); - this.dispatchEvent(new Event_(this, MenuEvent.UPDATE_MENU, null)); -}; - -ControlKit.prototype.loadSettings = function(data){ - var i = -1, l = data.length; - var panels = this._panels; - while(++i < l){ - panels[i].setData(data[i]); - } -}; - -ControlKit.prototype._loadState = function(){ - State.load(this.loadSettings.bind(this)); -}; - -ControlKit.prototype._saveState = function(){ - this.update(); //force sync - var p = this._panels, i = -1, l = p.length; - var data = new Array(l); - while(++i < l){ - data[i] = p[i].getData(); - } - State.save({data:data}); -}; - -/** - * Returns the root element. - * @returns {*} - */ - -ControlKit.prototype.getNode = function () { - return this._node; -}; - -ControlKit.destroy = function(){ - Mouse.get().destroy(); - Options.get().destroy(); - Picker.get().destroy(); - initiated = false; -}; - -module.exports = ControlKit; -},{"./component/NumberOutput":15,"./component/Options":16,"./component/Picker":19,"./component/StringOutput":28,"./component/ValuePlotter":29,"./core/ComponentEvent":31,"./core/History":33,"./core/HistoryEvent":34,"./core/State":38,"./core/document/CSS":42,"./core/document/DocumentEvent":43,"./core/document/Mouse":44,"./core/document/Node":45,"./core/document/NodeEvent":46,"./core/document/Style":47,"./core/event/Event":48,"./core/event/EventDispatcher":49,"./group/MenuEvent":55,"./group/Panel":56}],3:[function(require,module,exports){ -var Event_ = require('../core/event/Event'), - NodeEvent = require('../core/document/NodeEvent'), - ComponentEvent = require('../core/ComponentEvent'); - -var Node = require('../core/document/Node'), - Component = require('../core/Component'); - -var CSS = require('../core/document/CSS'); - -var DEFAULT_LABEL = ''; - -function Button(parent,label,onPress,params) { - onPress = onPress || function(){}; - params = params || {}; - params.label = params.label || DEFAULT_LABEL; - - Component.apply(this,[parent,params.label]); - - var node = this._inputNode = new Node(Node.INPUT_BUTTON); - - node.setStyleClass(CSS.Button); - node.setProperty('value',label); - - var self = this; - node.addEventListener(NodeEvent.ON_CLICK, - function() { - onPress.bind(self)(); - self.dispatchEvent(new Event_(self,ComponentEvent.VALUE_UPDATED)); - }); - - this._wrapNode.addChild(node); -} -Button.prototype = Object.create(Component.prototype); -Button.prototype.constructor = Button; - -Button.prototype.getButtonLabel = function(){ - return this._inputNode.getProperty('value'); -}; - -Button.prototype.setButtonLabel = function(label){ - this._inputNode.setProperty('value',label); -}; - -module.exports = Button; - -},{"../core/Component":30,"../core/ComponentEvent":31,"../core/document/CSS":42,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48}],4:[function(require,module,exports){ -var EventDispatcher = require('../core/event/EventDispatcher'); -var ObjectComponentNotifier = require('../core/ObjectComponentNotifier'); - -var Event_ = require('../core/event/Event'), - OptionEvent = require('../core/OptionEvent'), - NodeEvent = require('../core/document/NodeEvent'); - -var Node = require('../core/document/Node'); -var CSS = require('../core/document/CSS'); - -function ButtonPreset(parentNode) { - EventDispatcher.apply(this); - var node = this._btnNode = new Node(Node.INPUT_BUTTON), - imgNode = this._indiNode = new Node(); - - this._onActive = function () {}; - this._onDeactive = function () {}; - this._isActive = false; - - node.setStyleClass(CSS.ButtonPreset); - node.addEventListener(NodeEvent.MOUSE_DOWN, this._onMouseDown.bind(this)); - - node.addChild(imgNode); - parentNode.addChildAt(node, 0); - - ObjectComponentNotifier.get().addEventListener(OptionEvent.TRIGGER, this, 'onOptionTrigger'); - this.addEventListener(OptionEvent.TRIGGERED, ObjectComponentNotifier.get(), 'onOptionTriggered'); -} -ButtonPreset.prototype = Object.create(EventDispatcher.prototype); -ButtonPreset.prototype.constructor = ButtonPreset; - -ButtonPreset.prototype.onOptionTrigger = function(e){ - if(e.data.origin == this){ - if(!this._isActive){ - this._onActive(); - this._btnNode.setStyleClass(CSS.ButtonPresetActive); - this._isActive = true; - } else{ - this._onDeactive(); - } - return; - } - - if(this._isActive){ - this.deactivate(); - } -}; - -ButtonPreset.prototype._onMouseDown = function(){ - this.dispatchEvent(new Event_(this, OptionEvent.TRIGGERED, null)); -}; - -ButtonPreset.prototype.setOnActive = function(func){ - this._onActive = func; -}; - -ButtonPreset.prototype.setOnDeactive = function(func){ - this._onDeactive = func; -}; - -ButtonPreset.prototype.deactivate = function(){ - this._isActive = false; - this._btnNode.setStyleClass(CSS.ButtonPreset); -}; - -module.exports = ButtonPreset; - -},{"../core/ObjectComponentNotifier":36,"../core/OptionEvent":37,"../core/document/CSS":42,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48,"../core/event/EventDispatcher":49}],5:[function(require,module,exports){ -var Component = require('../core/Component'); -var CSS = require('../core/document/CSS'), - Metric = require('./Metric'); - -var Event_ = require('../core/event/Event'), - GroupEvent = require('../group/GroupEvent'); - -function Canvas(parent,params) { - Component.apply(this,arguments); - - var wrap = this._wrapNode; - wrap.setStyleClass(CSS.CanvasWrap); - var canvas = this._canvas = document.createElement('canvas'); - wrap.getElement().appendChild(canvas); - - var width = wrap.getWidth(); - this._canvasWidth = this._canvasHeight = 0; - this._setCanvasSize(width,width); - this._updateHeight(); - - this._node.setStyleClass(CSS.CanvasListItem); - this._parent.addEventListener(GroupEvent.GROUP_SIZE_CHANGE,this, 'onGroupSizeChange'); - this.addEventListener(GroupEvent.GROUP_SIZE_UPDATE,this._parent,'onGroupSizeUpdate'); -} -Canvas.prototype = Object.create(Component.prototype); -Canvas.prototype.constructor = Canvas; - -Canvas.prototype._updateHeight = function () { - var canvasHeight = this._canvas.height; - - this._wrapNode.setHeight(canvasHeight); - this._node.setHeight(canvasHeight + Metric.PADDING_WRAPPER); -}; - -Canvas.prototype.onGroupSizeChange = function () { - var width = this._wrapNode.getWidth(); - - this._setCanvasSize(width, width); - this._updateHeight(); - this._redraw(); - - this.dispatchEvent(new Event_(this, GroupEvent.GROUP_SIZE_UPDATE, null)); -}; - -Canvas.prototype._setCanvasSize = function (width, height) { - var canvasWidth = this._canvasWidth = width, - canvasHeight = this._canvasHeight = height; - - var canvas = this._canvas; - canvas.style.width = canvasWidth + 'px'; - canvas.style.height = canvasHeight + 'px'; - canvas.width = canvasWidth; - canvas.height = canvasHeight; -}; - -Canvas.prototype.getCanvas = function () { - return this._canvas; -}; - -Canvas.prototype.getContext = function () { - return this._canvas.getContext('2d'); -}; - -module.exports = Canvas; - -},{"../core/Component":30,"../core/document/CSS":42,"../core/event/Event":48,"../group/GroupEvent":54,"./Metric":12}],6:[function(require,module,exports){ -var ObjectComponent = require('../core/ObjectComponent'), - Node = require('../core/document/Node'); - -var Event_ = require('../core/event/Event'), - NodeEvent = require('../core/document/NodeEvent'), - ComponentEvent = require('../core/ComponentEvent'); - -function Checkbox(parent, object, value, params) { - ObjectComponent.apply(this,arguments); - - params = params || {}; - params.onChange = params.onChange || this._onChange; - this._onChange = params.onChange; - - var node = this._input = new Node(Node.INPUT_CHECKBOX); - node.setProperty('checked',this._obj[this._key]); - node.addEventListener(NodeEvent.CHANGE,this._onInputChange.bind(this)); - - this._wrapNode.addChild(this._input); -} -Checkbox.prototype = Object.create(ObjectComponent.prototype); -Checkbox.prototype.constructor = Checkbox; - -Checkbox.prototype.applyValue = function () { - this.pushHistoryState(); - - var obj = this._obj, key = this._key; - obj[key] = !obj[key]; - - this.dispatchEvent(new Event_(this, ComponentEvent.VALUE_UPDATED, null)); -}; - -Checkbox.prototype._onInputChange = function () { - this.applyValue(); - this._onChange(); -}; - -Checkbox.prototype.onValueUpdate = function (e) { - if (e.data.origin == this){ - return; - } - this._input.setProperty('checked', this._obj[this._key]); -}; - -module.exports = Checkbox; -},{"../core/ComponentEvent":31,"../core/ObjectComponent":35,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48}],7:[function(require,module,exports){ -var ObjectComponent = require('./../core/ObjectComponent'); - -var Node = require('../core/document/Node'); -var ColorMode = require('../core/color/ColorMode'); -var Picker = require('./Picker'); -var ColorUtil = require('../core/color/ColorUtil'); -var Options = require('./Options'); -var ButtonPreset = require('./ButtonPreset'); -var Metric = require('./Metric'), - CSS = require('../core/document/CSS'); - -var Event_ = require('../core/event/Event'), - NodeEvent = require('../core/document/NodeEvent'), - ComponentEvent = require('../core/ComponentEvent'); - -var ColorFormatError = require('../core/color/ColorFormatError'); - -var DEFAULT_COLOR_MODE = ColorMode.HEX, - DEFAULT_PRESETS = null; - -var MSG_COLOR_FORMAT_HEX = 'Color format should be hex. Set colorMode to rgb, rgbfv or hsv.', - MSG_COLOR_FORMAT_RGB_RGBFV_HSV = 'Color format should be rgb, rgbfv or hsv. Set colorMode to hex.', - MSG_COLOR_PRESET_FORMAT_HEX = 'Preset color format should be hex.', - MSG_COLOR_PRESET_FORMAT_RGB_RGBFV_HSV = 'Preset color format should be rgb, rgbfv or hsv.'; - -function Color(parent, object, value, params){ - ObjectComponent.apply(this, arguments); - - params = params || {}; - params.presets = params.presets || DEFAULT_PRESETS; - params.colorMode = params.colorMode || DEFAULT_COLOR_MODE; - params.onChange = params.onChange || this._onChange; - - - this._presetsKey = params.presets; - this._onChange = params.onChange; - - var color = this._color = new Node(); - value = this._value = this._obj[this._key]; - - var colorMode = this._colorMode = params.colorMode; - - this._validateColorFormat(value, MSG_COLOR_FORMAT_HEX, MSG_COLOR_FORMAT_RGB_RGBFV_HSV); - - var wrap = this._wrapNode; - - if(!this._presetsKey){ - color.setStyleClass(CSS.Color); - wrap.addChild(color); - } - else{ - color.setStyleClass(CSS.Color); - - var wrap_ = new Node(); - wrap_.setStyleClass(CSS.WrapColorWPreset); - - wrap.addChild(wrap_); - wrap_.addChild(color); - - var presets = this._obj[this._presetsKey]; - - var i = -1; - while(++i < presets.length){ - this._validateColorFormat(presets[i], MSG_COLOR_PRESET_FORMAT_HEX, - MSG_COLOR_PRESET_FORMAT_RGB_RGBFV_HSV); - } - - var options = Options.get(), - presetBtn = new ButtonPreset(wrap); - - var onPresetDeactivate = function(){ - options.clear(); - presetBtn.deactivate(); - }; - - var self = this; - var onPresetActivate = function(){ - options.build(presets, - self._value, - color, - function(){ - self.pushHistoryState(); - self._value = presets[options.getSelectedIndex()]; - self.applyValue(); - self._onChange(self._obj[self._key]); - }, - onPresetDeactivate, - Metric.PADDING_PRESET, - true, - colorMode); - }; - presetBtn.setOnActive(onPresetActivate); - presetBtn.setOnDeactive(onPresetDeactivate); - } - - color.addEventListener(NodeEvent.MOUSE_DOWN, this._onColorTrigger.bind(this)); - this._updateColor(); -} -Color.prototype = Object.create(ObjectComponent.prototype); -Color.prototype.constructor = Color; - -Color.prototype._onColorTrigger = function(){ - var colorMode = this._colorMode, - colorModeHEX = ColorMode.HEX, - colorModeRGB = ColorMode.RGB, - colorModeRGBfv = ColorMode.RGBfv, - colorModeHSV = ColorMode.HSV; - - var value = this._value, - temp; - - var onPickerPick = function(){ - this.pushHistoryState(); - - switch(colorMode){ - case colorModeHEX: - this._value = Picker.get().getHEX(); - break; - case colorModeRGB: - //if val = Float32array or so - temp = Picker.get().getRGB(); - value[0] = temp[0]; - value[1] = temp[1]; - value[2] = temp[2]; - break; - - case colorModeRGBfv: - temp = Picker.get().getRGBfv(); - value[0] = temp[0]; - value[1] = temp[1]; - value[2] = temp[2]; - break; - - case colorModeHSV: - this._value = Picker.get().getHSV(); - break; - } - - this.applyValue(); - - }.bind(this); - - var picker = Picker.get(); - - switch(colorMode){ - case colorModeHEX: - picker.setColorHEX(value); - break; - case colorModeRGB: - picker.setColorRGB(value[0], value[1], value[2]); - break; - case colorModeRGBfv: - picker.setColorRGBfv(value[0], value[1], value[2]); - break; - case colorModeHSV: - picker.setColorHSV(value[0], value[1], value[2]); - break; - } - - picker.setCallbackPick(onPickerPick); - picker.open(); -}; - -Color.prototype.applyValue = function(){ - this._obj[this._key] = this._value; - this._updateColor(); - this.dispatchEvent(new Event_(this, ComponentEvent.VALUE_UPDATED, null)); - this._onChange(this._obj[this._key]); -}; - -Color.prototype.onValueUpdate = function(e){ - if(e.data.origin == this)return; - this._value = this._obj[this._key]; - this._updateColor(); -}; - -Color.prototype._updateColor = function(){ - var color = this._value, - colorNode = this._color, - nodeColor; - - colorNode.setProperty('innerHTML', color); - - switch(this._colorMode){ - case ColorMode.HEX: - nodeColor = color; - break; - - case ColorMode.RGB: - nodeColor = ColorUtil.RGB2HEX(color[0], color[1], color[2]); - break; - - case ColorMode.RGBfv: - nodeColor = ColorUtil.RGBfv2HEX(color[0], color[1], color[2]); - break; - - case ColorMode.HSV: - nodeColor = ColorUtil.HSV2RGB(color[0], color[1], color[2]); - break; - } - - colorNode.getStyle().backgroundColor = nodeColor; -}; - -Color.prototype._validateColorFormat = function(value, msgHex, msgArr){ - var colorMode = this._colorMode; - - if(colorMode == ColorMode.HEX && Object.prototype.toString.call(value) === '[object Array]' || - colorMode == ColorMode.HEX && Object.prototype.toString.call(value) === '[object Float32Array]'){ - throw new ColorFormatError(msgHex); - } - if((colorMode == ColorMode.RGB || - colorMode == ColorMode.RGBfv || - colorMode == ColorMode.HSV) && - Object.prototype.toString.call(value) !== '[object Array]' || - colorMode == ColorMode.HSV && - Object.prototype.toString.call(value) !== '[object Float32Array]'){ - throw new ColorFormatError(msgArr); - } -}; - -module.exports = Color; - -},{"../core/ComponentEvent":31,"../core/color/ColorFormatError":39,"../core/color/ColorMode":40,"../core/color/ColorUtil":41,"../core/document/CSS":42,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48,"./../core/ObjectComponent":35,"./ButtonPreset":4,"./Metric":12,"./Options":16,"./Picker":19}],8:[function(require,module,exports){ -var FunctionPlotType = { - IMPLICIT: 'implicit', - NON_IMPLICIT: 'nonImplicit' -}; - -module.exports = FunctionPlotType; -},{}],9:[function(require,module,exports){ -var Plotter = require('./Plotter'); - -var Node = require('../core/document/Node'); -var CSS = require('../core/document/CSS'); -var FunctionPlotType = require('./FunctionPlotType'); - - -var Mouse = require('../core/document/Mouse'); -var Metric = require('./Metric'); - -var DocumentEvent = require('../core/document/DocumentEvent'), - ComponentEvent = require('../core/ComponentEvent'), - NodeEvent = require('../core/document/NodeEvent'); - -var FunctionPlotterObjectError = require('./FunctionPlotterObjectError'), - FunctionPlotterFunctionArgsError = require('./FunctionPlotterFunctionArgsError'); - -var ObjectComponentNotifier = require('../core/ObjectComponentNotifier'); - -var DEFAULT_SHOW_MIN_MAX_LABELS = true; - -var DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_UNIT_X = 1, - DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_UNIT_Y = 1, - DEFAULT_FUNCTION_PLOTTER_IMPLICIT_UNIT_X = 0.25, - DEFAULT_FUNCTION_PLOTTER_IMPLICIT_UNIT_Y = 0.25, - DEFAULT_FUNCTION_PLOTTER_UNIT_MIN = 0.15, - DEFAULT_FUNCTION_PLOTTER_UNIT_MAX = 4, - DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_SCALE = 10.0, - DEFAULT_FUNCTION_PLOTTER_IMPLICIT_SCALE = 1.0, - DEFAULT_FUNCTION_PLOTTER_SCALE_MIN = 0.02, - DEFAULT_FUNCTION_PLOTTER_SCALE_MAX = 25, - - DEFAULT_FUNCTION_PLOTTER_IMPLICIT_AXES_COLOR = 'rgba(255,255,255,0.75)', - DEFAULT_FUNCTION_PLOTTER_IMPLICIT_GRID_COLOR = 'rgba(25,25,25,0.75)', - - DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_AXES_COLOR = 'rgb(54,60,64)', - DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_GRID_COLOR = 'rgb(25,25,25)', - - DEFAULT_FUNCTION_PLOTTER_CIRCLE_LABEL_RADIUS = 3, - DEFAULT_FUNCTION_PLOTTER_CIRCLE_LABEL_FILL = 'rgb(255,255,255)', - DEFAULT_FUNCTION_PLOTTER_CIRCLE_STROKE = '#b12334'; - -function FunctionPlotter(parent, object, value, params) { - params = params || {}; - params.showMinMaxLabels = params.showMinMaxLabels === undefined ? DEFAULT_SHOW_MIN_MAX_LABELS : params.showMinMaxLabels; - - Plotter.apply(this, arguments); - - if (typeof object[value] !== 'function') { - throw new FunctionPlotterObjectError(object,value); - } - - var funcArgLength = object[value].length; - - if (funcArgLength > 2 || funcArgLength == 0) { - throw new FunctionPlotterFunctionArgsError(); - } - - var svgRoot = this._svgRoot, - path = this._path; - - var axes = this._axes = svgRoot.insertBefore(this._createSVGObject('path'), path); - axes.style.strokeWidth = 1; - - var axesLabels = this._axesLabels = svgRoot.insertBefore(this._createSVGObject('path'), path); - axesLabels.style.stroke = 'rgb(43,48,51)'; - axesLabels.style.strokeWidth = 1; - - var grid = this._grid; - - var svg = this._svg, - size = Number(svg.getAttribute('width')); - - var sliderXWrap = new Node(); - sliderXWrap.setStyleClass(CSS.GraphSliderXWrap); - - var sliderYWrap = new Node(); - sliderYWrap.setStyleClass(CSS.GraphSliderYWrap); - - var sliderXTrack = this._sliderXTrack = new Node(); - sliderXTrack.setStyleClass(CSS.GraphSliderX); - - var sliderYTrack = this._sliderYTrack = new Node(); - sliderYTrack.setStyleClass(CSS.GraphSliderY); - - var sliderXHandle = this._sliderXHandle = new Node(); - sliderXHandle.setStyleClass(CSS.GraphSliderXHandle); - - var sliderYHandle = this._sliderYHandle = new Node(); - sliderYHandle.setStyleClass(CSS.GraphSliderYHandle); - - sliderXTrack.addChild(sliderXHandle); - sliderYTrack.addChild(sliderYHandle); - sliderXWrap.addChild(sliderXTrack); - sliderYWrap.addChild(sliderYTrack); - - var wrapNode = this._wrapNode; - - var plotMode = this._plotMode = funcArgLength == 1 ? - FunctionPlotType.NON_IMPLICIT : - FunctionPlotType.IMPLICIT; - - if (plotMode == FunctionPlotType.IMPLICIT) { - var canvas = this._canvas = document.createElement('canvas'); - canvas.style.width = canvas.style.height = size + 'px'; - canvas.width = canvas.height = size; - - wrapNode.getElement().insertBefore(canvas, svg); - - this._canvasContext = canvas.getContext('2d'); - this._canvasImageData = this._canvasContext.getImageData(0, 0, size, size); - - axes.style.stroke = DEFAULT_FUNCTION_PLOTTER_IMPLICIT_AXES_COLOR; - grid.style.stroke = DEFAULT_FUNCTION_PLOTTER_IMPLICIT_GRID_COLOR; - } - else { - axes.style.stroke = DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_AXES_COLOR; - grid.style.stroke = DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_GRID_COLOR; - } - - wrapNode.addChild(sliderXWrap); - wrapNode.addChild(sliderYWrap); - - sliderXHandle.addEventListener(NodeEvent.MOUSE_DOWN, this._onSliderXHandleDown.bind(this)); - sliderYHandle.addEventListener(NodeEvent.MOUSE_DOWN, this._onSliderYHandleDown.bind(this)); - - var units = this._units = [null, null]; - this._scale = null; - - if (plotMode == FunctionPlotType.NON_IMPLICIT) { - units[0] = DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_UNIT_X; - units[1] = DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_UNIT_Y; - - this._scale = DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_SCALE; - } - else if (plotMode == FunctionPlotType.IMPLICIT) { - units[0] = DEFAULT_FUNCTION_PLOTTER_IMPLICIT_UNIT_X; - units[1] = DEFAULT_FUNCTION_PLOTTER_IMPLICIT_UNIT_Y; - - this._scale = DEFAULT_FUNCTION_PLOTTER_IMPLICIT_SCALE; - } - - this._unitsMinMax = [DEFAULT_FUNCTION_PLOTTER_UNIT_MIN, DEFAULT_FUNCTION_PLOTTER_UNIT_MAX]; //1/8->4 - - this._scaleMinMax = [DEFAULT_FUNCTION_PLOTTER_SCALE_MIN, DEFAULT_FUNCTION_PLOTTER_SCALE_MAX]; //1/50 -> 25 - - this._center = [Math.round(size * 0.5),Math.round(size * 0.5)]; - this._svgPos = [0, 0]; - - this._func = null; - this.setFunction(this._obj[this._key]); - - this._sliderXHandleUpdate(); - this._sliderYHandleUpdate(); - - svg.addEventListener(DocumentEvent.MOUSE_DOWN, this._onDragStart.bind(this), false); - this._wrapNode.getElement().addEventListener("mousewheel", this._onScale.bind(this, false)); - - ObjectComponentNotifier.get().addEventListener(ComponentEvent.UPDATE_VALUE, this, 'onValueUpdate'); -} -FunctionPlotter.prototype = Object.create(Plotter.prototype); -FunctionPlotter.prototype.constructor = FunctionPlotter; - -FunctionPlotter.prototype._updateCenter = function () { - var svg = this._svg, - width = Number(svg.getAttribute('width')), - height = Number(svg.getAttribute('height')); - - var mousePos = Mouse.get().getPosition(), - svgPos = this._svgPos, - center = this._center; - - center[0] = Math.max(0, Math.min(mousePos[0] - svgPos[0], width)); - center[1] = Math.max(0, Math.min(mousePos[1] - svgPos[1], height)); - - this._plotGraph(); -}; - -FunctionPlotter.prototype._onDragStart = function (e) { - var svgPos = this._svgPos; - svgPos[0] = 0; - svgPos[1] = 0; - - //skip to container - var element = this._svg.parentNode; - - while (element) { - svgPos[0] += element.offsetLeft; - svgPos[1] += element.offsetTop; - element = element.offsetParent; - } - - var eventMove = DocumentEvent.MOUSE_MOVE, - eventUp = DocumentEvent.MOUSE_UP; - - var onDrag = this._updateCenter.bind(this), - onDragEnd = function () { - this._updateCenter.bind(this); - document.removeEventListener(eventMove, onDrag, false); - document.removeEventListener(eventUp, onDragEnd, false); - - }.bind(this); - - document.addEventListener(eventMove, onDrag, false); - document.addEventListener(eventUp, onDragEnd, false); - - this._updateCenter(); -}; - -FunctionPlotter.prototype._onScale = function (e) { - e = window.event || e; - this._scale += Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail))) * -1; - - var scaleMinMax = this._scaleMinMax; - this._scale = Math.max(scaleMinMax[0], Math.min(this._scale, scaleMinMax[1])); - - this._plotGraph(); - - e.preventDefault(); - -}; - -FunctionPlotter.prototype.onValueUpdate = function () { - this.setFunction(this._obj[this._key]); -}; - -FunctionPlotter.prototype._redraw = function () { - if (this._plotMode == FunctionPlotType.IMPLICIT) { - var size = this._wrapNode.getWidth(), - canvas = this._canvas; - - canvas.style.width = canvas.style.height = size + 'px'; - canvas.width = canvas.height = size; - - this._canvasImageData = this._canvasContext.getImageData(0, 0, size, size); - } - - this._sliderXHandleUpdate(); - this._sliderYHandleUpdate(); - - this.setFunction(this._obj[this._key]); -}; - -FunctionPlotter.prototype.setFunction = function (func) { - this._func = func.bind(this._obj); - this._plotGraph(); -}; - -FunctionPlotter.prototype._plotGraph = function () { - this._drawGrid(); - this._drawAxes(); - this._drawPlot(); -}; - -FunctionPlotter.prototype._drawAxes = function () { - var svg = this._svg, - svgWidth = Number(svg.getAttribute('width')), - svgHeight = Number(svg.getAttribute('height')); - - var center = this._center, - centerX = center[0], - centerY = center[1]; - - var pathCmd = ''; - pathCmd += this._pathCmdLine(0, centerY, svgWidth, centerY); - pathCmd += this._pathCmdLine(centerX, 0, centerX, svgHeight); - - this._axes.setAttribute('d', pathCmd); -}; - -FunctionPlotter.prototype._drawPlot = function () { - var width, height; - - var center = this._center, - centerX = center[0], - centerY = center[1]; - - var units = this._units, - unitX, unitY; - - var scale = this._scale; - var normval, scaledVal, value, index; - var offsetX, offsetY; - - var i; - - if (this._plotMode == FunctionPlotType.NON_IMPLICIT) { - var svg = this._svg; - - width = Number(svg.getAttribute('width')); - height = Number(svg.getAttribute('height')); - unitX = units[0] * scale; - unitY = height / (units[1] * scale); - offsetX = centerX / width; - - var len = Math.floor(width), - points = new Array(len * 2); - - i = -1; - while (++i < len) { - normval = (-offsetX + i / len); - scaledVal = normval * unitX; - value = centerY - this._func(scaledVal) * unitY; - - index = i * 2; - - points[index] = i; - points[index + 1] = value; - } - - var pathCmd = ''; - pathCmd += this._pathCmdMoveTo(points[0], points[1]); - - i = 2; - while (i < points.length) { - pathCmd += this._pathCmdLineTo(points[i], points[i + 1]); - i += 2; - } - - this._path.setAttribute('d', pathCmd); - } - else { - var canvas = this._canvas, - context = this._canvasContext, - imgData = this._canvasImageData; - - width = canvas.width; - height = canvas.height; - - unitX = units[0] * scale; - unitY = units[1] * scale; - - offsetX = centerX / width; - offsetY = centerY / height; - - var invWidth = 1 / width, - invHeight = 1 / height; - var rgb = [0, 0, 0]; - - var col0 = [30, 34, 36], - col1 = [255, 255, 255]; - - i = -1; - var j; - while (++i < height) { - j = -1; - - while (++j < width) { - value = this._func((-offsetX + j * invWidth) * unitX, - (-offsetY + i * invHeight) * unitY); - - rgb[0] = Math.floor((col1[0] - col0[0]) * value + col0[0]); - rgb[1] = Math.floor((col1[1] - col0[1]) * value + col0[1]); - rgb[2] = Math.floor((col1[2] - col0[2]) * value + col0[2]); - - index = (i * width + j) * 4; - - imgData.data[index] = rgb[0]; - imgData.data[index + 1] = rgb[1]; - imgData.data[index + 2] = rgb[2]; - imgData.data[index + 3] = 255; - } - } - - context.clearRect(0, 0, width, height); - context.putImageData(imgData, 0, 0); - } -}; - -FunctionPlotter.prototype._drawGrid = function () { - var svg = this._svg, - width = Number(svg.getAttribute('width')), - height = Number(svg.getAttribute('height')); - - var scale = this._scale; - - var gridRes = this._units, - gridSpacingX = width / (gridRes[0] * scale), - gridSpacingY = height / (gridRes[1] * scale); - - var center = this._center, - centerX = center[0], - centerY = center[1]; - - var gridNumTop = Math.round(centerY / gridSpacingY) + 1, - gridNumBottom = Math.round((height - centerY) / gridSpacingY) + 1, - gridNumLeft = Math.round(centerX / gridSpacingX) + 1, - gridNumRight = Math.round((width - centerX) / gridSpacingX) + 1; - - var pathCmdGrid = '', - pathCmdAxesLabels = ''; - - var i, temp; - - var strokeSize = Metric.STROKE_SIZE; - - var labelTickSize = Metric.FUNCTION_PLOTTER_LABEL_TICK_SIZE, - labelTickPaddingRight = width - labelTickSize - strokeSize, - labelTickPaddingBottom = height - labelTickSize - strokeSize, - labelTickPaddingRightOffset = labelTickPaddingRight - labelTickSize, - labelTickPaddingBottomOffset = labelTickPaddingBottom - labelTickSize, - labelTickOffsetRight = labelTickPaddingRight - (labelTickSize + strokeSize) * 2, - labelTickOffsetBottom = labelTickPaddingBottom - (labelTickSize + strokeSize) * 2; - - i = -1; - while (++i < gridNumTop) { - temp = Math.round(centerY - gridSpacingY * i); - pathCmdGrid += this._pathCmdLine(0, temp, width, temp); - - if (temp > labelTickSize){ - pathCmdAxesLabels += this._pathCmdLine(labelTickPaddingRight, temp, - labelTickPaddingRightOffset, temp); - } - } - - i = -1; - while (++i < gridNumBottom) { - temp = Math.round(centerY + gridSpacingY * i); - pathCmdGrid += this._pathCmdLine(0, temp, width, temp); - - if (temp < labelTickOffsetBottom){ - pathCmdAxesLabels += this._pathCmdLine(labelTickPaddingRight, temp, - labelTickPaddingRightOffset, temp); - } - } - - i = -1; - while (++i < gridNumLeft) { - temp = Math.round(centerX - gridSpacingX * i); - pathCmdGrid += this._pathCmdLine(temp, 0, temp, height); - - if (temp > labelTickSize){ - pathCmdAxesLabels += this._pathCmdLine(temp, labelTickPaddingBottom, - temp, labelTickPaddingBottomOffset); - } - } - - i = -1; - while (++i < gridNumRight) { - temp = Math.round(centerX + gridSpacingX * i); - pathCmdGrid += this._pathCmdLine(temp, 0, temp, height); - - if (temp < labelTickOffsetRight){ - pathCmdAxesLabels += this._pathCmdLine(temp, labelTickPaddingBottom, - temp, labelTickPaddingBottomOffset); - } - } - - this._grid.setAttribute('d', pathCmdGrid); - this._axesLabels.setAttribute('d', pathCmdAxesLabels); -}; - - -FunctionPlotter.prototype._sliderXStep = function (mousePos) { - var mouseX = mousePos[0]; - - var handle = this._sliderXHandle, - handleWidth = handle.getWidth(), - handleWidthHalf = handleWidth * 0.5; - - var track = this._sliderXTrack, - trackWidth = track.getWidth(), - trackLeft = track.getPositionGlobalX(); - - var strokeSize = Metric.STROKE_SIZE; - - var max = trackWidth - handleWidthHalf - strokeSize * 2; - - var pos = Math.max(handleWidthHalf, Math.min(mouseX - trackLeft, max)), - handlePos = pos - handleWidthHalf; - - handle.setPositionX(handlePos); - - var unitsMin = this._unitsMinMax[0], - unitsMax = this._unitsMinMax[1]; - - var normVal = (pos - handleWidthHalf) / (max - handleWidthHalf), - mappedVal = unitsMin + (unitsMax - unitsMin) * normVal; - - this._units[0] = mappedVal; - - this._plotGraph(); -}; - -FunctionPlotter.prototype._sliderYStep = function (mousePos) { - var mouseY = mousePos[1]; - - var handle = this._sliderYHandle, - handleHeight = handle.getHeight(), - handleHeightHalf = handleHeight * 0.5; - - var track = this._sliderYTrack, - trackHeight = track.getHeight(), - trackTop = track.getPositionGlobalY(); - - var max = trackHeight - handleHeightHalf - 2; - - var pos = Math.max(handleHeightHalf, Math.min(mouseY - trackTop, max)), - handlePos = pos - handleHeightHalf; - - handle.setPositionY(handlePos); - - var unitsMax = this._unitsMinMax[0], - unitsMin = this._unitsMinMax[1]; - - var normVal = (pos - handleHeightHalf) / (max - handleHeightHalf), - mappedVal = unitsMin + (unitsMax - unitsMin) * normVal; - - this._units[1] = mappedVal; - - this._plotGraph(); -}; - -FunctionPlotter.prototype._onSliderXHandleDown = function () { - this._onSliderHandleDown(this._sliderXStep.bind(this)); -}; - -FunctionPlotter.prototype._onSliderYHandleDown = function () { - this._onSliderHandleDown(this._sliderYStep.bind(this)); -}; - -FunctionPlotter.prototype._onSliderHandleDown = function (sliderStepFunc) { - var eventMouseMove = DocumentEvent.MOUSE_MOVE, - eventMouseUp = DocumentEvent.MOUSE_UP; - - var mouse = Mouse.get(); - - var onDrag = function () { - sliderStepFunc(mouse.getPosition()) - }, - onDragEnd = function () { - document.removeEventListener(eventMouseMove, onDrag, false); - document.removeEventListener(eventMouseUp, onDragEnd, false); - }; - - sliderStepFunc(mouse.getPosition()); - document.addEventListener(eventMouseMove, onDrag, false); - document.addEventListener(eventMouseUp, onDragEnd, false); -}; - -FunctionPlotter.prototype._sliderXHandleUpdate = function () { - var unitMin = this._unitsMinMax[0], - unitMax = this._unitsMinMax[1], - unitX = this._units[0]; - - var handleX = this._sliderXHandle, - handleXWidth = handleX.getWidth(), - handleXWidthHalf = handleXWidth * 0.5, - trackXWidth = this._sliderXTrack.getWidth(); - - var strokeSize = Metric.STROKE_SIZE; - - var handleXMin = handleXWidthHalf, - handleXMax = trackXWidth - handleXWidthHalf - strokeSize * 2; - - handleX.setPositionX((handleXMin + (handleXMax - handleXMin) * ((unitX - unitMin) / (unitMax - unitMin))) - handleXWidthHalf); -}; - -FunctionPlotter.prototype._sliderYHandleUpdate = function () { - var unitMin = this._unitsMinMax[0], - unitMax = this._unitsMinMax[1], - unitY = this._units[1]; - - var handleY = this._sliderYHandle, - handleYHeight = handleY.getHeight(), - handleYHeightHalf = handleYHeight * 0.5, - trackYHeight = this._sliderYTrack.getHeight(); - - var strokeSize = Metric.STROKE_SIZE; - - var handleYMin = trackYHeight - handleYHeightHalf - strokeSize * 2, - handleYMax = handleYHeightHalf; - - handleY.setPositionY((handleYMin + (handleYMax - handleYMin) * ((unitY - unitMin) / (unitMax - unitMin))) - handleYHeightHalf); -}; - -module.exports = FunctionPlotter; -},{"../core/ComponentEvent":31,"../core/ObjectComponentNotifier":36,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Mouse":44,"../core/document/Node":45,"../core/document/NodeEvent":46,"./FunctionPlotType":8,"./FunctionPlotterFunctionArgsError":10,"./FunctionPlotterObjectError":11,"./Metric":12,"./Plotter":20}],10:[function(require,module,exports){ -function FunctionPlotterFunctionArgsError(){ - Error.apply(this); - Error.captureStackTrace(this,FunctionPlotterFunctionArgsError); - this.name = 'FunctionPlotterFunctionArgsError'; - this.message = 'Function should be of form f(x) or f(x,y).'; -} -FunctionPlotterFunctionArgsError.prototype = Object.create(Error.prototype); -FunctionPlotterFunctionArgsError.prototype.constructor = FunctionPlotterFunctionArgsError; - -module.exports = FunctionPlotterFunctionArgsError; -},{}],11:[function(require,module,exports){ -function FunctionPlotterObjectError(object,key){ - Error.apply(this); - Error.captureStackTrace(this,FunctionPlotterObjectError); - this.name = 'ComponentObjectError'; - this.message = 'Object ' + object.constructor.name + ' ' + key + 'should be of type Function.'; -} -FunctionPlotterObjectError.prototype = Object.create(Error.prototype); -FunctionPlotterObjectError.prototype.constructor = FunctionPlotterObjectError; - -module.exports = FunctionPlotterObjectError; -},{}],12:[function(require,module,exports){ -var Metric = { - COMPONENT_MIN_HEIGHT: 25, - STROKE_SIZE: 1, - PADDING_WRAPPER: 12, - PADDING_OPTIONS: 2, - PADDING_PRESET: 20, - - SCROLLBAR_TRACK_PADDING: 2, - FUNCTION_PLOTTER_LABEL_TICK_SIZE: 6 -}; - -module.exports = Metric; -},{}],13:[function(require,module,exports){ -var ObjectComponent = require('../core/ObjectComponent'); -var NumberInput_Internal = require('./NumberInput_Internal'); - -var Node = require('../core/document/Node'); - -var Options = require('./Options'); -var ButtonPreset = require('./ButtonPreset'); -var CSS = require('../core/document/CSS'), - Metric = require('./Metric'); - -var Event_ = require('../core/event/Event'), - DocumentEvent = require('../core/document/DocumentEvent'), - NodeEvent = require('../core/document/NodeEvent'), - ComponentEvent = require('../core/ComponentEvent'); - -var DEFAULT_INPUT_DP = 2, - DEFAULT_INPUT_STEP = 1, - DEFAULT_INPUT_PRESET = null; - - - -function NumberInput(parent,object,value,params) { - ObjectComponent.apply(this,arguments); - - params = params || {}; - params.onBegin = params.onBegin || null; - params.onChange = params.onChange || this._onChange; - params.onFinish = params.onFinish || null; - params.onError = params.onError || null; - params.dp = (params.dp === undefined || params.dp == null) ? DEFAULT_INPUT_DP : params.dp; - params.step = params.step || DEFAULT_INPUT_STEP; - params.presets = params.presets || DEFAULT_INPUT_PRESET; - - this._onBegin = params.onBegin; - this._onChange = params.onChange; - this._presetsKey = params.presets; - - var input = this._input = new NumberInput_Internal(params.step, - params.dp, - params.onBegin, - this._onInputChange.bind(this), - params.onFinish, - params.onError); - - var wrap = this._wrapNode; - - var presets = params.presets; - if (!presets) { - wrap.addChild(input.getNode()); - } - else { - var wrap_ = new Node(); - wrap_.setStyleClass(CSS.WrapInputWPreset); - - wrap.addChild(wrap_); - wrap_.addChild(input.getNode()); - - var options = Options.get(); - var presetBtn = this._btnPreset = new ButtonPreset(this._wrapNode); - - var onPresetDeactivate = function(){ - options.clear(); - presetBtn.deactivate(); - }; - - var self = this; - var onPresetActivate = function () { - options.build(presets, input.getValue(), input.getNode(), - function () { - input.setValue(presets[options.getSelectedIndex()]); - self.applyValue(); - self._onChange(self._obj[self._key]); - }, - onPresetDeactivate, Metric.PADDING_PRESET, - false); - }; - presetBtn.setOnActive(onPresetActivate); - presetBtn.setOnDeactive(onPresetDeactivate) - } - - input.getNode().addEventListener(NodeEvent.MOUSE_DOWN, this._onInputDragStart.bind(this)); - this.addEventListener(ComponentEvent.INPUT_SELECT_DRAG,this._parent,'onComponentSelectDrag'); - - input.setValue(this._obj[this._key]); -} -NumberInput.prototype = Object.create(ObjectComponent.prototype); -NumberInput.prototype.constructor = NumberInput; - -NumberInput.prototype._onInputChange = function () { - this.applyValue(); - this._onChange(this._obj[this._key]); -}; - -NumberInput.prototype.applyValue = function() { - this.pushHistoryState(); - this._obj[this._key] = this._input.getValue(); - this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED,null)); -}; - -NumberInput.prototype.onValueUpdate = function (e) { - if (e.data.origin == this){ - return; - } - this._input.setValue(this._obj[this._key]); -}; - -//Prevent chrome select drag -NumberInput.prototype._onInputDragStart = function () { - var eventMove = DocumentEvent.MOUSE_MOVE, - eventUp = DocumentEvent.MOUSE_UP; - - var event = ComponentEvent.INPUT_SELECT_DRAG; - - var self = this; - - var onDrag = function () { - self.dispatchEvent(new Event_(this, event, null)); - }, - onDragFinish = function () { - self.dispatchEvent(new Event_(this, event, null)); - document.removeEventListener(eventMove, onDrag, false); - document.removeEventListener(eventMove, onDragFinish, false); - }; - - this.dispatchEvent(new Event_(this, event, null)); - - document.addEventListener(eventMove, onDrag, false); - document.addEventListener(eventUp, onDragFinish, false); -}; - -module.exports = NumberInput; -},{"../core/ComponentEvent":31,"../core/ObjectComponent":35,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48,"./ButtonPreset":4,"./Metric":12,"./NumberInput_Internal":14,"./Options":16}],14:[function(require,module,exports){ -var EventDispatcher = require('../core/event/EventDispatcher'), - NodeEvent = require('../core/document/NodeEvent'); -var Node = require('../core/document/Node'); - -var PRESET_SHIFT_MULTIPLIER = 10; -var NUM_REGEX = /^-?\d*\.?\d*$/; - -var setCaretPos = null, - selectAll = null; - -function inputSetValue(input,value){ - input.setProperty('value',value); - input.dispatchEvent(new Event('input')); -} - -NumberInput_Internal = function (stepValue, dp, onBegin, onChange, onFinish, onError) { - EventDispatcher.apply(this, null); - - this._value = 0; - this._valueStep = stepValue; - this._valueDp = dp; - - this._onBegin = onBegin || function (){}; - this._onChange = onChange || function () {}; - this._onFinish = onFinish || function() {}; - this._onError = onError || function() {}; - - this._keyCode = null; - this._caretOffset = 0; - - var input = this._input = new Node('text'); - input.setProperty('value', this._value); - - input.addEventListener('input',this._onInput.bind(this)); - input.addEventListener('keydown',this._onKeydown.bind(this)); - - if(!setCaretPos){ - if(input.getElement().setSelectionRange){ - setCaretPos = function(input,pos){ - input.getElement().setSelectionRange(pos,pos); - }; - selectAll = function(input){ - input.getElement().setSelectionRange(0,input.getProperty('value').length); - }; - } else { - setCaretPos = function(input,pos){ - var range = input.getElement().createTextRange(); - range.collapse(true); - range.moveEnd('character',pos); - range.moveStart('character',pos); - range.select(); - }; - selectAll = function(input){ - var range = input.getElement().createTextRange(); - range.collapse(true); - range.moveStart('character',0); - range.moveEnd('character',input.getProperty('value').length); - range.select(); - } - } - } -}; -NumberInput_Internal.prototype = Object.create(EventDispatcher.prototype); -NumberInput_Internal.prototype.constructor = NumberInput_Internal; - -NumberInput_Internal.prototype._setValue = function(value){ - var prefix = ((value = +value) || 1 / value) < 0 && value == 0 ? '-' : ''; //-0 - value = Number(value).toFixed(this._valueDp); - this._input.setProperty('value',prefix + value); - this._value = Number(value); -}; - -NumberInput_Internal.prototype._onInput = function(){ - var input = this._input, - value = input.getProperty('value'), - start = input.getProperty('selectionStart'), - dp = this._valueDp; - - var first = value[0]; - - if(value == ''){ - value = 0; - } else if(first === '.'){ - value = '0' + value; - } - - if(!NUM_REGEX.test(value) || value == '-'){ - input.setProperty('value',this._value.toFixed(dp)); - setCaretPos(input,Math.max(--start,0)); - this._onError(this._keyCode); - return; - } - this._onBegin(this._value); - this._setValue(value); - setCaretPos(input,start - this._caretOffset); - this._onChange(); -}; - -NumberInput_Internal.prototype._onKeydown = function(e){ - var keyCode = this._keyCode = e.keyCode; - - if(keyCode == 13){ - this._onFinish(); - e.preventDefault(); - return; - } - - var input = this._input, - value = input.getProperty('value'); - var start = input.getProperty('selectionStart'), - end = input.getProperty('selectionEnd'); - var length = value.length; - - var isBackspaceDelete = keyCode == 8 || keyCode == 45, - isMetaKey = e.metaKey, - isCtrlKey = e.ctrlKey, - isLeft = keyCode == 37, - isRight = keyCode == 39, - isLeftRight = isLeft || isRight, - isShift = e.shiftKey, - isUpDown = keyCode == 38 || keyCode == 40, - isSelectAll = (isMetaKey || isCtrlKey) && keyCode == 65, - isRangeSelected = start != end, - isAllSelected = start == 0 && end == length, - isMinus = keyCode == 189; - - var indexDecimalMark = value.indexOf('.'); - - this._caretOffset = 0; - - //prevent cmd-z || ctrl-z - if((isMetaKey || isCtrlKey) && keyCode == 90){ - e.preventDefault(); - return; - } - //select all cmd+a || ctrl+a - if(isSelectAll){ - selectAll(input); - e.preventDefault(); - return; - } - //everything is selected - if(isAllSelected) { - if (isMinus) { - //set negative zero, as starting point for negative number - inputSetValue(input, '-0'); - //set caret after '-' - setCaretPos(input, 1); - } else { - //delete number / replace / ignore - inputSetValue(input, isBackspaceDelete ? 0 : String.fromCharCode(keyCode)); - //jump to start <--> end - setCaretPos(input, isLeft ? start : end); - } - e.preventDefault(); - return; - } - //jump over decimal mark - if(isBackspaceDelete && (start-1 == indexDecimalMark)){ - setCaretPos(input,start-1); - return; - } - // 0|. enter first dp without jumping over decimal mark - if(!isLeftRight && (value[0] == '0' && start == 1)){ - setCaretPos(input,1); - this._caretOffset = 1; - return; - } - //increase / decrease number by (step up / down) * multiplier on shift down - if(isUpDown){ - var step = (isShift ? PRESET_SHIFT_MULTIPLIER : 1) * this._valueStep, - mult = keyCode == 38 ? 1.0 : -1.0; - inputSetValue(input,Number(value) + (step * mult)); - setCaretPos(input,start); - e.preventDefault(); - return; - } - //range selected, not in selection process - if(isRangeSelected && !(isShift && isLeftRight)){ - //jump to start <--> end - if(isLeftRight){ - setCaretPos(input,isLeft ? start : end); - } else { //replace complete range, not just parts - value = value.substr(0,start) + String.fromCharCode(keyCode) + value.substr(end,length-end); - inputSetValue(input,value); - setCaretPos(input,end); - } - e.preventDefault(); - return; - } - //caret within fractional part, not moving caret, selecting, deleting - if(!isShift && !isLeftRight && !isBackspaceDelete && (start > indexDecimalMark && start < length)){ - value = value.substr(0,start) + String.fromCharCode(keyCode) + value.substr(start+1,length-1); - inputSetValue(input,value); - setCaretPos(input,Math.min(start+1,length-1)); - e.preventDefault(); - return; - } - //caret at end of number, do nothing - if(!isBackspaceDelete && !isLeftRight && !isUpDown && start >= length){ - e.preventDefault(); - } -}; - -NumberInput_Internal.prototype.getValue = function () { - return this._value; -}; - -NumberInput_Internal.prototype.setValue = function (n) { - this._setValue(n); -}; - -NumberInput_Internal.prototype.getNode = function () { - return this._input; -}; - -module.exports = NumberInput_Internal; - -},{"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/EventDispatcher":49}],15:[function(require,module,exports){ -var Output = require('./Output'); - -var DEFAULT_OUTPUT_DP = 2; - -function NumberOutput(parent, object, value, params) { - params = params || {}; - params.dp = params.dp || DEFAULT_OUTPUT_DP; - - Output.apply(this, arguments); - this._valueDp = params.dp + 1; -} -NumberOutput.prototype = Object.create(Output.prototype); -NumberOutput.prototype.constructor = NumberOutput; - -//FIXME -NumberOutput.prototype._setValue = function () { - if (this._parent.isDisabled()){ - return; - } - - var value = this._obj[this._key], - textArea = this._textArea, - dp = this._valueDp; - - var index, - out; - - if (typeof(value) === 'object' && - typeof(value.length) === 'number' && - typeof(value.splice) === 'function' && - !value.propertyIsEnumerable('length')) { - - out = value.slice(); - - var i = -1; - var temp; - var wrap = this._wrap; - - while (++i < out.length) { - temp = out[i] = out[i].toString(); - index = temp.indexOf('.'); - if (index > 0){ - out[i] = temp.slice(0, index + dp); - } - } - - if (wrap) { - textArea.setStyleProperty('white-space', 'nowrap'); - out = out.join('\n'); - } - - textArea.setProperty('value', out); - }else { - out = value.toString(); - index = out.indexOf('.'); - textArea.setProperty('value', index > 0 ? out.slice(0, index + dp) : out); - } - -}; - -module.exports = NumberOutput; -},{"./Output":17}],16:[function(require,module,exports){ -var Node = require('../core/document/Node'); -var DocumentEvent = require('../core/document/DocumentEvent'), - NodeEvent = require('../core/document/NodeEvent'); -var CSS = require('../core/document/CSS'); -var ColorMode = require('../core/color/ColorMode'); -var ColorUtil = require('../core/color/ColorUtil'); -var Metric = require('./Metric'); - -function Options(parentNode) { - this._parenNode = parentNode; - - var node = this._node = new Node(); - var listNode = this._listNode = new Node(Node.LIST); - - node.setStyleClass(CSS.Options); - node.addChild(listNode); - - this._selectedIndex = null; - this._callbackOut = function () { }; - - this._unfocusable = false; - - document.addEventListener(DocumentEvent.MOUSE_DOWN, this._onDocumentMouseDown.bind(this)); - document.addEventListener(DocumentEvent.MOUSE_UP, this._onDocumentMouseUp.bind(this)); - - this.clear(); -} - -Options.prototype = { - _onDocumentMouseDown: function () { - if (!this._unfocusable)return; - this._callbackOut(); - }, - - _onDocumentMouseUp: function () { - this._unfocusable = true; - }, - - build: function (entries, selected, element, callbackSelect, callbackOut, paddingRight, areColors, colorMode) { - this._clearList(); - - this._parenNode.addChild(this.getNode()); - - var rootNode = this._node, - listNode = this._listNode; - - paddingRight = paddingRight || 0; - - var self = this; - - // build list - var itemNode, entry; - var i = -1; - - if (areColors) { - colorMode = colorMode || ColorMode.HEX; - - listNode.setStyleClass(CSS.Color); - - var color, nodeColor; - - while (++i < entries.length) { - entry = entries[i]; - itemNode = listNode.addChild(new Node(Node.LIST_ITEM)); - color = itemNode.addChild(new Node()); - - switch (colorMode) { - case ColorMode.HEX: - nodeColor = entry; - break; - case ColorMode.RGB: - nodeColor = ColorUtil.RGB2HEX(entry[0], entry[1], entry[2]); - break; - case ColorMode.RGBfv: - nodeColor = ColorUtil.RGBfv2HEX(entry[0], entry[1], entry[2]); - break; - case ColorMode.HSV: - nodeColor = ColorUtil.HSV2RGB(entry[0], entry[1], entry[2]); - break; - } - - color.getStyle().backgroundColor = nodeColor; - color.getStyle().backgroundImage = 'linear-gradient( rgba(0,0,0,0) 0%, rgba(0,0,0,0.1) 100%)'; - color.setProperty('innerHTML', entry); - - if (entry == selected)itemNode.setStyleClass(CSS.OptionsSelected); - - itemNode.addEventListener(NodeEvent.MOUSE_DOWN, - function () { - self._selectedIndex = Array.prototype.indexOf.call(this.parentNode.children, this); - callbackSelect(); - }); - } - - } - else { - listNode.deleteStyleClass(); - - while (++i < entries.length) { - entry = entries[i]; - - itemNode = listNode.addChild(new Node(Node.LIST_ITEM)); - itemNode.setProperty('innerHTML', entry); - if (entry == selected)itemNode.setStyleClass(CSS.OptionsSelected); - - itemNode.addEventListener(NodeEvent.MOUSE_DOWN, - function () { - self._selectedIndex = Array.prototype.indexOf.call(this.parentNode.children, this); - callbackSelect(); - }); - } - } - - //position, set width and enable - - var elementPos = element.getPositionGlobal(), - elementWidth = element.getWidth() - paddingRight, - elementHeight = element.getHeight(); - - var listWidth = listNode.getWidth(), - listHeight = listNode.getHeight(), - strokeOffset = Metric.STROKE_SIZE * 2; - - var paddingOptions = Metric.PADDING_OPTIONS; - - var width = (listWidth < elementWidth ? elementWidth : listWidth) - strokeOffset, - posX = elementPos[0], - posY = elementPos[1] + elementHeight - paddingOptions; - - var windowWidth = window.innerWidth, - windowHeight = window.innerHeight; - - var rootPosX = (posX + width) > windowWidth ? (posX - width + elementWidth - strokeOffset) : posX, - rootPosY = (posY + listHeight) > windowHeight ? (posY - listHeight * 0.5 - elementHeight * 0.5) : posY; - - listNode.setWidth(width); - rootNode.setPositionGlobal(rootPosX, rootPosY); - - this._callbackOut = callbackOut; - this._unfocusable = false; - }, - - _clearList: function () { - this._listNode.removeAllChildren(); - this._listNode.deleteStyleProperty('width'); - this._selectedIndex = null; - this._build = false; - }, - - clear: function () { - this._clearList(); - this._callbackOut = function () { - }; - this._parenNode.removeChild(this.getNode()); - - }, - - isBuild: function () { - return this._build; - }, - getNode: function () { - return this._node; - }, - getSelectedIndex: function () { - return this._selectedIndex; - } -}; - -Options.setup = function(parentNode){return Options._instance = new Options(parentNode);}; -Options.get = function(){return Options._instance;}; -Options.destroy = function(){Options._instance = null;}; - -module.exports = Options; -},{"../core/color/ColorMode":40,"../core/color/ColorUtil":41,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Node":45,"../core/document/NodeEvent":46,"./Metric":12}],17:[function(require,module,exports){ -var ObjectComponent = require('../core/ObjectComponent'); -var Node = require('../core/document/Node'); - -var CSS = require('../core/document/CSS'); -var Metric = require('./Metric'); -var ScrollBar = require('../core/layout/ScrollBar'); - -var Event_ = require('../core/event/Event'), - DocumentEvent = require('../core/document/DocumentEvent'), - NodeEvent = require('../core/document/NodeEvent'), - ComponentEvent = require('../core/ComponentEvent'); - -var DEFAULT_HEIGHT = null, - DEFAULT_WRAP = false, - DEFAULT_UPDATE = true; - -function Output(parent,object,value,params) { - ObjectComponent.apply(this,arguments); - - params = params || {}; - params.height = params.height || DEFAULT_HEIGHT; - params.wrap = params.wrap === undefined ? DEFAULT_WRAP : params.wrap; - params.update = params.update === undefined ? DEFAULT_UPDATE : params.update; - - this._wrap = params.wrap; - this._update = params.update; - - var textArea = this._textArea = new Node(Node.TEXTAREA), - wrap = this._wrapNode, - root = this._node; - - textArea.setProperty('readOnly',true); - wrap.addChild(textArea); - - textArea.addEventListener(NodeEvent.MOUSE_DOWN,this._onInputDragStart.bind(this)); - this.addEventListener(ComponentEvent.INPUT_SELECT_DRAG,this._parent,'onComponentSelectDrag'); - - - if(params.height){ - var textAreaWrap = new Node(); - textAreaWrap.setStyleClass(CSS.TextAreaWrap); - textAreaWrap.addChild(textArea); - wrap.addChild(textAreaWrap); - - //FIXME - var height = this._height = params.height, - padding = 4; - - textArea.setHeight(Math.max(height + padding ,Metric.COMPONENT_MIN_HEIGHT)); - wrap.setHeight(textArea.getHeight()); - root.setHeight(wrap.getHeight() + padding); - - this._scrollBar = new ScrollBar(textAreaWrap,textArea,height - padding) - } - - if(params.wrap){ - textArea.setStyleProperty('white-space','pre-wrap'); - } - - this._prevString = ''; - this._prevScrollHeight = -1; - this._setValue(); -} -Output.prototype = Object.create(ObjectComponent.prototype); -Output.prototype.constructor = Output; - -//Override in subclass -Output.prototype._setValue = function () {}; - -Output.prototype.onValueUpdate = function () { - this._setValue(); -}; - -Output.prototype.update = function () { - if(!this._update){ - return; - } - this._setValue(); -}; - -//Prevent chrome select drag - -Output.prototype._onDrag = function(){ - this.dispatchEvent(new Event_(this, ComponentEvent.INPUT_SELECT_DRAG, null)); -}; - -Output.prototype._onDragFinish = function(){ - this.dispatchEvent(new Event_(this, ComponentEvent.INPUT_SELECT_DRAG, null)); - - document.removeEventListener(DocumentEvent.MOUSE_MOVE, this._onDrag, false); - document.removeEventListener(DocumentEvent.MOUSE_MOVE, this._onDragFinish, false); -}; - -Output.prototype._onInputDragStart = function() { - this.dispatchEvent(new Event_(this, ComponentEvent.INPUT_SELECT_DRAG, null)); - document.addEventListener(DocumentEvent.MOUSE_MOVE, this._onDrag.bind(this), false); - document.addEventListener(DocumentEvent.MOUSE_UP, this._onDragFinish.bind(this), false); -}; - - -module.exports = Output; - -},{"../core/ComponentEvent":31,"../core/ObjectComponent":35,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48,"../core/layout/ScrollBar":51,"./Metric":12}],18:[function(require,module,exports){ -var Plotter = require('./Plotter'); -var Mouse = require('../core/document/Mouse'); - -var Event_ = require('../core/event/Event'), - DocumentEvent = require('../core/document/DocumentEvent'), - ComponentEvent = require('../core/ComponentEvent'); - -var DEFAULT_BOUNDS_X = [-1,1], - DEFAULT_BOUNDS_Y = [-1,1], - DEFAULT_LABEL_X = '', - DEFAULT_LABEL_Y = ''; - -function Pad(parent, object, value, params) { - Plotter.apply(this,arguments); - - params = params || {}; - params.boundsX = params.boundsX || DEFAULT_BOUNDS_X; - params.boundsY = params.boundsY || DEFAULT_BOUNDS_Y; - params.labelX = params.labelX || DEFAULT_LABEL_X; - params.labelY = params.labelY || DEFAULT_LABEL_Y; - - params.showCross = params.showCross || true; - - - this._onChange = params.onChange || this._onChange; - this._onFinish = params.onFinish || function(){}; - - this._boundsX = params.boundsX; - this._boundsY = params.boundsY; - this._labelAxisX = params.labelX != '' && params.labelX != 'none' ? params.labelX : null; - this._labelAxisY = params.labelY != '' && params.labelY != 'none' ? params.labelY : null; - - var path = this._path; - path.style.strokeWidth = 1; - path.style.stroke = '#363c40'; - - this._grid.style.stroke = 'rgb(25,25,25)'; - - this._svgPos = [0,0]; - - - var handle = this._handle = this._svgRoot.appendChild(this._createSVGObject('g')); - var handleCircle0 = handle.appendChild(this._createSVGObject('circle')); - handleCircle0.setAttribute('r',String(11)); - handleCircle0.setAttribute('fill','rgba(0,0,0,0.05)'); - var handleCircle1 = handle.appendChild(this._createSVGObject('circle')); - handleCircle1.setAttribute('r',String(10)); - handleCircle1.setAttribute('fill','rgb(83,93,98)'); - - var handleCircle2 = handle.appendChild(this._createSVGObject('circle')); - handleCircle2.setAttribute('r',String(9)); - handleCircle2.setAttribute('fill','rgb(57,69,76)'); - handleCircle2.setAttribute('cy',String(0.75)); - - var handleCircle3 = handle.appendChild(this._createSVGObject('circle')); - handleCircle3.setAttribute('r',String(10)); - handleCircle3.setAttribute('stroke','rgb(17,19,20)'); - handleCircle3.setAttribute('stroke-width',String(1)); - handleCircle3.setAttribute('fill','none'); - - var handleCircle4 = handle.appendChild(this._createSVGObject('circle')); - handleCircle4.setAttribute('r',String(6)); - handleCircle4.setAttribute('fill','rgb(30,34,36)'); - var handleCircle5 = handle.appendChild(this._createSVGObject('circle')); - handleCircle5.setAttribute('r',String(3)); - handleCircle5.setAttribute('fill','rgb(255,255,255)'); - - handle.setAttribute('tranform','translate(0 0)'); - - this._svg.addEventListener(DocumentEvent.MOUSE_DOWN,this._onDragStart.bind(this),false); - this._drawValue(this._obj[this._key]); -} -Pad.prototype = Object.create(Plotter.prototype); -Pad.prototype.constructor = Pad; - -Pad.prototype._onDragStart = function () { - var svgPos = this._svgPos; - svgPos[0] = 0; - svgPos[1] = 0; - - //skip to container - var element = this._svg.parentNode; - - while (element) { - svgPos[0] += element.offsetLeft; - svgPos[1] += element.offsetTop; - element = element.offsetParent; - } - - var eventMove = DocumentEvent.MOUSE_MOVE, - eventUp = DocumentEvent.MOUSE_UP; - - var onDrag = function () { - this._drawValueInput(); - this.applyValue(); - this._onChange(); - }.bind(this); - - var onDragEnd = function () { - this.pushHistoryState(); - this._drawValueInput(); - this.applyValue(); - this._onFinish(); - - document.removeEventListener(eventMove, onDrag, false); - document.removeEventListener(eventUp, onDragEnd, false); - }.bind(this); - - document.addEventListener(eventMove, onDrag, false); - document.addEventListener(eventUp, onDragEnd, false); - - this._drawValueInput(); - this.applyValue(); - this._onChange(); -}; - -Pad.prototype._redraw = function () { - this._drawValue(this._obj[this._key]); -}; - -Pad.prototype._drawValueInput = function () { - this._drawValue(this._getMouseNormalized()); -}; - -Pad.prototype._drawValue = function (value) { - this._obj[this._key] = value; - this._drawGrid(); - this._drawPoint(); -}; - -Pad.prototype._drawGrid = function () { - var svgSize = Number(this._svg.getAttribute('width')), - svgMidX = Math.floor(svgSize * 0.5), - svgMidY = Math.floor(svgSize * 0.5); - - var pathCmd = ''; - pathCmd += this._pathCmdLine(0, svgMidY, svgSize, svgMidY); - pathCmd += this._pathCmdLine(svgMidX, 0, svgMidX, svgSize); - - this._grid.setAttribute('d', pathCmd); -}; - - -Pad.prototype._drawPoint = function () { - var svgSize = Number(this._svg.getAttribute('width')); - - var value = this._obj[this._key]; - - var localX = ( 0.5 + value[0] * 0.5 ) * svgSize, - localY = ( 0.5 + -value[1] * 0.5 ) * svgSize; - - var pathCmd = ''; - pathCmd += this._pathCmdLine(0, localY, svgSize, localY); - pathCmd += this._pathCmdLine(localX, 0, localX, svgSize); - - this._path.setAttribute('d', pathCmd); - this._handle.setAttribute('transform', 'translate(' + localX + ' ' + localY + ')'); -}; - -Pad.prototype._getMouseNormalized = function () { - var offset = this._svgPos, - mouse = Mouse.get().getPosition(), - svgSize = Number(this._svg.getAttribute('width')); - - return [-1 + Math.max(0, Math.min(mouse[0] - offset[0], svgSize)) / svgSize * 2, - ( 1 - Math.max(0, Math.min(mouse[1] - offset[1], svgSize)) / svgSize * 2)]; - -}; - -Pad.prototype.applyValue = function () { - this.dispatchEvent(new Event_(this, ComponentEvent.VALUE_UPDATED, null)); -}; - -Pad.prototype.onValueUpdate = function (e) { - if (e.data.origin == this)return; - this._drawValue(this._obj[this._key]); -}; - -module.exports = Pad; - -},{"../core/ComponentEvent":31,"../core/document/DocumentEvent":43,"../core/document/Mouse":44,"../core/event/Event":48,"./Plotter":20}],19:[function(require,module,exports){ -var Node = require('../core/document/Node'); - -var CSS = require('../core/document/CSS'); -var NumberInput_Internal = require('./NumberInput_Internal'); -var Mouse = require('../core/document/Mouse'); -var ColorUtil = require('../core/color/ColorUtil'); -var DocumentEvent = require('../core/document/DocumentEvent'), - NodeEvent = require('../core/document/NodeEvent'); - -var DEFAULT_VALUE_HUE = 200.0, - DEFAULT_VALUE_SAT = 50.0, - DEFAULT_VALUE_VAL = 50.0; - -function Picker(parentNode){ - var root = this._node = new Node().setStyleClass(CSS.Picker), - head = this._headNode = new Node().setStyleClass(CSS.Head), - labelWrap = new Node().setStyleClass(CSS.Wrap), - label = new Node().setStyleClass(CSS.Label), - menu = new Node().setStyleClass(CSS.Menu), - menuWrap = new Node().setStyleClass(CSS.Wrap); - - var menuClose = new Node(Node.INPUT_BUTTON); - menuClose.setStyleClass(CSS.ButtonMenuClose); - - var fieldWrap = new Node().setStyleClass( CSS.PickerFieldWrap), - sliderWrap = new Node().setStyleClass(CSS.SliderWrap), - inputWrap = new Node().setStyleClass( CSS.PickerInputWrap); - - var canvasField = this._canvasField = document.createElement('canvas'), - canvasSlider = this._canvasSlider = document.createElement('Canvas'); - - fieldWrap.getElement().appendChild(canvasField); - sliderWrap.getElement().appendChild(canvasSlider); - - this._setSizeCanvasField(154,154); - this._setSizeCanvasSlider(14,154); - - var contextCanvasField = this._contextCanvasField = canvasField.getContext('2d'), - contextCanvasSlider = this._contextCanvasSlider = canvasSlider.getContext('2d'); - - var handleField = this._handleField = new Node(); - handleField.setStyleClass(CSS.PickerHandleField); - - var handleSlider = this._handleSlider = new Node(); - handleSlider.setStyleClass(CSS.PickerHandleSlider); - - var step = 1.0, - dp = 0; - - var callbackHue = this._onInputHueChange.bind(this), - callbackSat = this._onInputSatChange.bind(this), - callbackVal = this._onInputValChange.bind(this), - callbackR = this._onInputRChange.bind(this), - callbackG = this._onInputGChange.bind(this), - callbackB = this._onInputBChange.bind(this); - - - var inputHue = this._inputHue = new NumberInput_Internal(step,dp,null,callbackHue), - inputSat = this._inputSat = new NumberInput_Internal(step,dp,null,callbackSat), - inputVal = this._inputVal = new NumberInput_Internal(step,dp,null,callbackVal), - inputR = this._inputR = new NumberInput_Internal(step,dp,null,callbackR), - inputG = this._inputG = new NumberInput_Internal(step,dp,null,callbackG), - inputB = this._inputB = new NumberInput_Internal(step,dp,null,callbackB); - - var controlsWrap = new Node().setStyleClass(CSS.PickerControlsWrap); - - var buttonPick = new Node(Node.INPUT_BUTTON).setStyleClass(CSS.Button).setProperty('value','pick'), - buttonCancel = new Node(Node.INPUT_BUTTON).setStyleClass(CSS.Button).setProperty('value','cancel'); - - - var colorContrast = new Node().setStyleClass(CSS.PickerColorContrast); - - var color0 = this._colorCurrNode = new Node(), - color1 = this._colorPrevNode = new Node(); - - colorContrast.addChild(color0); - colorContrast.addChild(color1); - - controlsWrap.addChild(buttonCancel); - controlsWrap.addChild(buttonPick); - controlsWrap.addChild(colorContrast); - - this._setContrasPrevColor(0,0,0); - - var inputFieldWrapHue = new Node().setStyleClass(CSS.PickerInputField), - inputFieldWrapSat = new Node().setStyleClass(CSS.PickerInputField), - inputFieldWrapVal = new Node().setStyleClass(CSS.PickerInputField); - - var inputFieldWrapHueLabel = new Node(Node.SPAN).setStyleClass(CSS.Label).setProperty('innerHTML','H'), - inputFieldWrapSatLabel = new Node(Node.SPAN).setStyleClass(CSS.Label).setProperty('innerHTML','S'), - inputFieldWrapValLabel = new Node(Node.SPAN).setStyleClass(CSS.Label).setProperty('innerHTML','V'); - - inputFieldWrapHue.addChildren(inputFieldWrapHueLabel,inputHue.getNode()); - inputFieldWrapSat.addChildren(inputFieldWrapSatLabel,inputSat.getNode()); - inputFieldWrapVal.addChildren(inputFieldWrapValLabel,inputVal.getNode()); - - var inputFieldWrapR = new Node().setStyleClass(CSS.PickerInputField), - inputFieldWrapG = new Node().setStyleClass(CSS.PickerInputField), - inputFieldWrapB = new Node().setStyleClass(CSS.PickerInputField); - - var inputFieldWrapRLabel = new Node(Node.SPAN).setStyleClass(CSS.Label).setProperty('innerHTML','R'), - inputFieldWrapGLabel = new Node(Node.SPAN).setStyleClass(CSS.Label).setProperty('innerHTML','G'), - inputFieldWrapBLabel = new Node(Node.SPAN).setStyleClass(CSS.Label).setProperty('innerHTML','B'); - - inputFieldWrapR.addChildren(inputFieldWrapRLabel,inputR.getNode()); - inputFieldWrapG.addChildren(inputFieldWrapGLabel,inputG.getNode()); - inputFieldWrapB.addChildren(inputFieldWrapBLabel,inputB.getNode()); - - - inputWrap.addChildren(inputFieldWrapR,inputFieldWrapHue, - inputFieldWrapG,inputFieldWrapSat, - inputFieldWrapB,inputFieldWrapVal,colorContrast); - - var hexInputWrap = new Node(); - hexInputWrap.setStyleClass(CSS.PickerInputWrap); - - var inputHEX = this._inputHEX = new Node(Node.INPUT_TEXT), - inputFieldWrapHEX = new Node().setStyleClass(CSS.PickerInputField), - inputFieldWrapHEXLabel = new Node(Node.SPAN).setStyleClass(CSS.Label); - - inputFieldWrapHEXLabel.setProperty('innerHTML','#'); - inputFieldWrapHEX.addChildren(inputFieldWrapHEXLabel,inputHEX); - - hexInputWrap.addChild(inputFieldWrapHEX); - - inputHEX.addEventListener(NodeEvent.CHANGE,this._onInputHEXFinish.bind(this)); - - label.setProperty('innerHTML','Color Picker'); - - menu.addChild(menuClose); - head.addChild(menu); - labelWrap.addChild(label); - head.addChild(labelWrap); - root.addChild(head); - root.addChild(menuWrap); - - //wrapNode.addChild(paletteWrap); - - menuWrap.addChild(fieldWrap); - menuWrap.addChild(sliderWrap); - menuWrap.addChild(inputWrap); - menuWrap.addChild(hexInputWrap); - menuWrap.addChild(controlsWrap); - - fieldWrap.addChild( handleField); - sliderWrap.addChild(handleSlider); - - var eventMouseDown = NodeEvent.MOUSE_DOWN, - callback = this._onCanvasFieldMouseDown.bind(this); - - fieldWrap.addEventListener( eventMouseDown, callback); - handleField.addEventListener(eventMouseDown, callback); - - callback = this._onCanvasSliderMouseDown.bind(this); - - sliderWrap.addEventListener( eventMouseDown, callback); - handleSlider.addEventListener(eventMouseDown, callback); - - menuClose.addEventListener( eventMouseDown, this._onClose.bind(this)); - buttonPick.addEventListener( eventMouseDown, this._onPick.bind(this)); - buttonCancel.addEventListener(eventMouseDown, this._onClose.bind(this)); - - head.addEventListener(NodeEvent.MOUSE_DOWN, this._onHeadDragStart.bind(this)); - - this._parentNode = parentNode; - - this._mouseOffset = [0,0]; - this._position = [null,null]; - - this._canvasSliderPos = [0,0]; - this._canvasFieldPos = [0,0]; - this._handleFieldSize = 12; - this._handleSliderHeight = 7; - - this._imageDataSlider = contextCanvasSlider.createImageData(canvasSlider.width,canvasSlider.height); - this._imageDataField = contextCanvasField.createImageData( canvasField.width, canvasField.height); - - this._valueHueMinMax = [0,360]; - this._valueSatMinMax = this._valueValMinMax = [0,100]; - this._valueRGBMinMax = [0,255]; - - this._valueHue = DEFAULT_VALUE_HUE; - this._valueSat = DEFAULT_VALUE_SAT; - this._valueVal = DEFAULT_VALUE_VAL; - this._valueR = 0; - this._valueG = 0; - this._valueB = 0; - - this._valueHEX = '#000000'; - this._valueHEXValid = this._valueHEX; - - this._callbackPick = function(){}; - - //this._canvasFieldImageDataFunc = function(i,j){return this._HSV2RGB(this._valueHue,j)} - - this._drawCanvasField(); - this._drawCanvasSlider(); - - this._setColorHSV(this._valueHue,this._valueSat,this._valueVal); - - this._updateColorRGBFromHSV(); - this._updateColorHEXFromRGB(); - - this._updateHandles(); -} - -Picker.prototype = -{ - _drawHandleField: function () { - var canvas = this._canvasField, - nodePos = this._canvasFieldPos, - mousePos = Mouse.get().getPosition(); - - var posX = Math.max(0, Math.min(mousePos[0] - nodePos[0], canvas.width)), - posY = Math.max(0, Math.min(mousePos[1] - nodePos[1], canvas.height)), - posXNorm = posX / canvas.width, - posYNorm = posY / canvas.height; - - var sat = Math.round(posXNorm * this._valueSatMinMax[1]), - val = Math.round((1.0 - posYNorm) * this._valueValMinMax[1]); - - this._setColorHSV(this._valueHue, sat, val); - - this._updateColorRGBFromHSV(); - this._updateColorHEXFromRGB(); - - this._updateHandleField(); - }, - - _updateHandleField: function () { - var width = this._canvasField.width, - height = this._canvasField.height, - offsetHandle = this._handleFieldSize * 0.25; - - var satNorm = this._valueSat / this._valueSatMinMax[1], - valNorm = this._valueVal / this._valueValMinMax[1]; - - this._handleField.setPositionGlobal(satNorm * width - offsetHandle, - (1.0 - valNorm) * height - offsetHandle); - - }, - - _drawHandleSlider: function () { - var canvas = this._canvasSlider, - canvasPosY = this._canvasSliderPos[1], - mousePosY = Mouse.get().getY(); - - var posY = Math.max(0, Math.min(mousePosY - canvasPosY, canvas.height)), - posYNorm = posY / canvas.height; - - var hue = Math.floor((1.0 - posYNorm) * this._valueHueMinMax[1]); - - this._setColorHSV(hue, this._valueSat, this._valueVal); - - this._updateColorRGBFromHSV(); - this._updateColorHEXFromRGB(); - - this._updateHandleSlider(); - }, - - _updateHandleSlider: function () { - var height = this._canvasSlider.height, - offsetHandle = this._handleSliderHeight * 0.25; - - var hueNorm = this._valueHue / this._valueHueMinMax[1]; - - this._handleSlider.setPositionGlobalY((height - offsetHandle) * (1.0 - hueNorm)); - }, - - _updateHandles: function () { - this._updateHandleField(); - this._updateHandleSlider(); - }, - - /*---------------------------------------------------------------------------------*/ - - _setHue: function (value) { - var minMax = this._valueHueMinMax; - - this._valueHue = value == minMax[1] ? minMax[0] : value; - this._updateColorHSV(); - this._drawCanvasField(); - }, - - _setSat: function (value) { - this._valueSat = Math.round(value); - this._updateColorHSV(); - }, - - _setVal: function (value) { - this._valueVal = Math.round(value); - this._updateColorHSV(); - }, - - _setR: function (value) { - this._valueR = Math.round(value); - this._updateColorRGB(); - }, - - _setG: function (value) { - this._valueG = Math.round(value); - this._updateColorRGB(); - }, - - _setB: function (value) { - this._valueB = Math.round(value); - this._updateColorRGB(); - }, - - /*---------------------------------------------------------------------------------*/ - - _onInputHueChange: function () { - var input = this._inputHue, - inputVal = this._getValueContrained(input, this._valueHueMinMax); - - var minMax = this._valueHueMinMax; - - if (inputVal == minMax[1]) { - inputVal = minMax[0]; - input.setValue(inputVal); - } - - this._setHue(inputVal); - this._updateColorRGBFromHSV(); - this._updateColorHEXFromRGB(); - this._updateHandleSlider(); - - this._drawCanvasField(); - }, - - _onInputSatChange: function () { - this._setSat(this._getValueContrained(this._inputSat, this._valueSatMinMax)); - this._onInputSVChange(); - }, - - _onInputValChange: function () { - this._setVal(this._getValueContrained(this._inputVal, this._valueValMinMax)); - this._onInputSVChange(); - }, - - _onInputRChange: function () { - this._setR(this._getValueContrained(this._inputR, this._valueRGBMinMax)); - this._onInputRGBChange(); - }, - - _onInputGChange: function () { - this._setG(this._getValueContrained(this._inputG, this._valueRGBMinMax)); - this._onInputRGBChange(); - }, - - _onInputBChange: function () { - this._setB(this._getValueContrained(this._inputB, this._valueRGBMinMax)); - this._onInputRGBChange(); - }, - - _onInputHEXFinish: function () { - var input = this._inputHEX, - value = input.getProperty('value'); - - if (!ColorUtil.isValidHEX(value)) { - input.setProperty('value', this._valueHEXValid); - return; - } - - this._valueHEX = this._valueHEXValid = value; - this._updateColorFromHEX(); - }, - - _onInputSVChange: function () { - this._updateColorRGBFromHSV(); - this._updateColorHEXFromRGB(); - this._updateHandleField(); - }, - - _onInputRGBChange: function () { - this._updateColorHSVFromRGB(); - this._updateColorHEXFromRGB(); - this._updateHandles(); - }, - - _getValueContrained: function (input, minMax) { - var inputVal = Math.round(input.getValue()), - min = minMax[0], - max = minMax[1]; - - if (inputVal <= min) { - inputVal = min; - input.setValue(inputVal); - } - if (inputVal >= max) { - inputVal = max; - input.setValue(inputVal); - } - - return inputVal; - }, - - - _updateInputHue: function () { - this._inputHue.setValue(this._valueHue); - }, - _updateInputSat: function () { - this._inputSat.setValue(this._valueSat); - }, - _updateInputVal: function () { - this._inputVal.setValue(this._valueVal); - }, - _updateInputR: function () { - this._inputR.setValue(this._valueR); - }, - _updateInputG: function () { - this._inputG.setValue(this._valueG); - }, - _updateInputB: function () { - this._inputB.setValue(this._valueB); - }, - _updateInputHEX: function () { - this._inputHEX.setProperty('value', this._valueHEX); - }, - - - _setColorHSV: function (hue, sat, val) { - this._valueHue = hue; - this._valueSat = sat; - this._valueVal = val; - - this._updateInputHue(); - this._updateInputSat(); - this._updateInputVal(); - - this._updateContrastCurrColor(); - }, - - _setColorRGB: function (r, g, b) { - this._valueR = r; - this._valueG = g; - this._valueB = b; - - this._updateInputR(); - this._updateInputG(); - this._updateInputB(); - - this._updateContrastCurrColor(); - }, - - _setColorHEX: function (hex) { - this._valueHEX = hex; - this._updateInputHEX(); - }, - - _updateColorHSV: function () { - this._setColorHSV(this._valueHue, this._valueSat, this._valueVal); - this._updateContrastCurrColor(); - }, - - _updateColorRGB: function () { - this._setColorRGB(this._valueR, this._valueG, this._valueB); - this._updateContrastCurrColor(); - }, - - _updateColorHSVFromRGB: function () { - var hsv = ColorUtil.RGB2HSV(this._valueR, this._valueG, this._valueB); - this._setColorHSV(hsv[0], hsv[1], hsv[2]); - }, - - _updateColorRGBFromHSV: function () { - var rgb = ColorUtil.HSV2RGB(this._valueHue, this._valueSat, this._valueVal); - this._setColorRGB(rgb[0], rgb[1], rgb[2]); - }, - - _updateColorHEXFromRGB: function () { - var hex = ColorUtil.RGB2HEX(this._valueR, this._valueG, this._valueB); - this._setColorHEX(hex); - }, - - _updateColorFromHEX: function () { - var rgb = ColorUtil.HEX2RGB(this._valueHEX); - - this._setColorRGB(rgb[0], rgb[1], rgb[2]); - this._updateColorHSVFromRGB(); - this._updateHandles(); - }, - - _updateContrastCurrColor: function () { - this._setContrastCurrColor(this._valueR, this._valueG, this._valueB); - }, - _updateContrastPrevColor: function () { - this._setContrasPrevColor(this._valueR, this._valueG, this._valueB) - }, - - _setContrastCurrColor: function (r, g, b) { - this._colorCurrNode.setStyleProperty('background', 'rgb(' + r + ',' + g + ',' + b + ')') - }, - _setContrasPrevColor: function (r, g, b) { - this._colorPrevNode.setStyleProperty('background', 'rgb(' + r + ',' + g + ',' + b + ')') - }, - - _onHeadDragStart: function () { - var node = this._node, - parentNode = this._parentNode; - - var nodePos = node.getPositionGlobal(), - mousePos = Mouse.get().getPosition(), - offsetPos = this._mouseOffset; - - offsetPos[0] = mousePos[0] - nodePos[0]; - offsetPos[1] = mousePos[1] - nodePos[1]; - - var eventMouseMove = DocumentEvent.MOUSE_MOVE, - eventMouseUp = DocumentEvent.MOUSE_UP; - - var self = this; - - var onDrag = function () { - self._updatePosition(); - self._updateCanvasNodePositions(); - }, - - onDragEnd = function () { - self._updateCanvasNodePositions(); - document.removeEventListener(eventMouseMove, onDrag, false); - document.removeEventListener(eventMouseUp, onDragEnd, false); - }; - - parentNode.removeChild(node); - parentNode.addChild(node); - - document.addEventListener(eventMouseMove, onDrag, false); - document.addEventListener(eventMouseUp, onDragEnd, false); - - this._updateCanvasNodePositions(); - }, - - _updatePosition: function () { - var mousePos = Mouse.get().getPosition(), - offsetPos = this._mouseOffset; - - var currPositionX = mousePos[0] - offsetPos[0], - currPositionY = mousePos[1] - offsetPos[1]; - - var node = this._node, - head = this._headNode, - position = this._position; - - var maxX = window.innerWidth - node.getWidth(), - maxY = window.innerHeight - head.getHeight(); - - position[0] = Math.max(0, Math.min(currPositionX, maxX)); - position[1] = Math.max(0, Math.min(currPositionY, maxY)); - - node.setPositionGlobal(position[0], position[1]); - }, - - _drawCanvasField: function () { - var canvas = this._canvasField, - context = this._contextCanvasField; - - var width = canvas.width, - height = canvas.height, - invWidth = 1 / width, - invHeight = 1 / height; - - var imageData = this._imageDataField, - rgb = [], - index = 0; - - var valueHue = this._valueHue; - - var i = -1, j; - while (++i < height) { - j = -1; - - while (++j < width) { - rgb = ColorUtil.HSV2RGB(valueHue, j * invWidth * 100.0, ( 1.0 - i * invHeight ) * 100.0); - index = (i * width + j) * 4; - - imageData.data[index] = rgb[0]; - imageData.data[index + 1] = rgb[1]; - imageData.data[index + 2] = rgb[2]; - imageData.data[index + 3] = 255; - } - } - - context.putImageData(imageData, 0, 0); - }, - - _drawCanvasSlider: function () { - var canvas = this._canvasSlider, - context = this._contextCanvasSlider; - - var width = canvas.width, - height = canvas.height, - invHeight = 1 / height; - - var imageData = this._imageDataSlider, - rgb = [], - index = 0; - - var i = -1, j; - while (++i < height) { - j = -1; - - while (++j < width) { - rgb = ColorUtil.HSV2RGB((1.0 - i * invHeight) * 360.0, 100.0, 100.0); - index = (i * width + j) * 4; - - imageData.data[index] = rgb[0]; - imageData.data[index + 1] = rgb[1]; - imageData.data[index + 2] = rgb[2]; - imageData.data[index + 3] = 255; - } - } - - context.putImageData(imageData, 0, 0); - - }, - - _onCanvasFieldMouseDown: function () { - var eventMouseMove = DocumentEvent.MOUSE_MOVE, - eventMouseUp = DocumentEvent.MOUSE_UP; - - var self = this; - - var onDrag = function () { - self._drawHandleField(); - }, - onDragEnd = function () { - document.removeEventListener(eventMouseMove, onDrag, false); - document.removeEventListener(eventMouseUp, onDragEnd, false); - }; - - document.addEventListener(eventMouseMove, onDrag, false); - document.addEventListener(eventMouseUp, onDragEnd, false); - - self._drawHandleField(); - }, - - _onCanvasSliderMouseDown: function () { - var eventMouseMove = DocumentEvent.MOUSE_MOVE, - eventMouseUp = DocumentEvent.MOUSE_UP; - - var self = this; - - var onDrag = function () { - self._drawHandleSlider(); - self._drawCanvasField(); - }, - - onDragEnd = function () { - document.removeEventListener(eventMouseMove, onDrag, false); - document.removeEventListener(eventMouseUp, onDragEnd, false); - self._drawCanvasField(); - }; - - document.addEventListener(eventMouseMove, onDrag, false); - document.addEventListener(eventMouseUp, onDragEnd, false); - - self._drawHandleSlider(); - self._drawCanvasField(); - }, - - _setSizeCanvasField: function (width, height) { - var canvas = this._canvasField; - canvas.style.width = width + 'px'; - canvas.style.height = height + 'px'; - canvas.width = width; - canvas.height = height; - - }, - - _setSizeCanvasSlider: function (width, height) { - var canvas = this._canvasSlider; - canvas.style.width = width + 'px'; - canvas.style.height = height + 'px'; - canvas.width = width; - canvas.height = height; - }, - - open: function () { - var node = this._node; - - this._parentNode.addChild(node); - - var position = this._position; - if(position[0] === null || position[1] === null){ - position[0] = window.innerWidth * 0.5 - node.getWidth() * 0.5; - position[1] = window.innerHeight * 0.5 - node.getHeight() * 0.5; - } else { - position[0] = Math.max(0,Math.min(position[0],window.innerWidth - node.getWidth())); - position[1] = Math.max(0,Math.min(position[1],window.innerHeight - node.getHeight())); - } - - node.setPositionGlobal(position[0],position[1]); - this._updateCanvasNodePositions(); - }, - - close: function () { - this._parentNode.removeChild(this._node); - }, - - _onClose: function (e) { - e.cancelBubble = true; - this.close(); - }, - _onPick: function () { - this._callbackPick(); - this.close(); - }, - - _updateCanvasNodePositions: function () { - var canvasSliderPos = this._canvasSliderPos, - canvasFieldPos = this._canvasFieldPos; - - canvasSliderPos[0] = canvasSliderPos[1] = 0; - canvasFieldPos[0] = canvasFieldPos[1] = 0; - - var element = this._canvasSlider; - - while (element) { - canvasSliderPos[0] += element.offsetLeft; - canvasSliderPos[1] += element.offsetTop; - element = element.offsetParent; - } - - element = this._canvasField; - - while (element) { - canvasFieldPos[0] += element.offsetLeft; - canvasFieldPos[1] += element.offsetTop; - element = element.offsetParent; - } - }, - - setCallbackPick: function (func) { - this._callbackPick = func; - }, - - setColorHEX: function (hex) { - this._setColorHEX(hex); - this._updateColorFromHEX(); - this._setColor(); - }, - - setColorRGB: function (r, g, b) { - this._setColorRGB(r, g, b); - this._updateColorHEXFromRGB(); - this._updateColorHSVFromRGB(); - this._setColor(); - }, - - setColorRGBfv: function (r, g, b) { - this.setColorRGB(Math.floor(r * 255.0), - Math.floor(g * 255.0), - Math.floor(b * 255.0)); - }, - - setColorHSV: function (h, s, v) { - this._setColorHSV(h, s, v); - this._updateColorRGBFromHSV(); - this._updateColorHEXFromRGB(); - this._setColor(); - }, - - _setColor: function () { - this._drawCanvasField(); - this._drawCanvasSlider(); - this._updateHandles(); - this._setContrasPrevColor(this._valueR, this._valueG, this._valueB); - }, - - getR: function () { - return this._valueR; - }, - getG: function () { - return this._valueG; - }, - getB: function () { - return this._valueB; - }, - getRGB: function () { - return [this._valueR, this._valueG, this._valueB]; - }, - getHue: function () { - return this._valueHue; - }, - getSat: function () { - return this._valueSat; - }, - getVal: function () { - return this._valueVal; - }, - getHSV: function () { - return [this._valueHue, this._valueSat, this._valueVal]; - }, - getHEX: function () { - return this._valueHEX; - }, - getRGBfv: function () { - return [this._valueR / 255.0, this._valueG / 255.0, this._valueB / 255.0]; - }, - - getNode: function () { - return this._node; - } -}; - -Picker.setup = function (parentNode) { - return Picker._instance = new Picker(parentNode); -}; -Picker.get = function () { - return Picker._instance; -}; -Picker.destroy = function(){ - Picker._instance = null; -}; - -module.exports = Picker; -},{"../core/color/ColorUtil":41,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Mouse":44,"../core/document/Node":45,"../core/document/NodeEvent":46,"./NumberInput_Internal":14}],20:[function(require,module,exports){ -var SVGComponent = require('./SVGComponent'); - -function Plotter(parent,object,value,params) { - params = params || {}; - params.lineWidth = params.lineWidth || 2; - params.lineColor = params.lineColor || [255,255,255]; - - SVGComponent.apply(this,arguments); - - var lineWidth = this._lineWidth = params.lineWidth; - var lineColor = params.lineColor; - - var grid = this._grid = this._svgRoot.appendChild(this._createSVGObject('path')); - grid.style.stroke = 'rgb(26,29,31)'; - - var path = this._path = this._svgRoot.appendChild(this._createSVGObject('path')); - path.style.stroke = 'rgb('+lineColor[0]+','+lineColor[1]+','+lineColor[2]+')'; - path.style.strokeWidth = lineWidth ; - path.style.fill = 'none'; -} -Plotter.prototype = Object.create(SVGComponent.prototype); -Plotter.prototype.constructor = Plotter; - -module.exports = Plotter; - -},{"./SVGComponent":23}],21:[function(require,module,exports){ -var ObjectComponent = require('../core/ObjectComponent'); -var Node = require('../core/document/Node'); -var NumberInput_Internal = require('./NumberInput_Internal'); -var CSS = require('../core/document/CSS'); - -var Event_ = require('../core/event/Event'), - ComponentEvent = require('../core/ComponentEvent'); - -var DEFAULT_STEP = 1.0, - DEFAULT_DP = 2; - -function Range(parent, object, value, params) { - ObjectComponent.apply(this,arguments); - - params = params || {}; - params.onChange = params.onChange || this._onChange; - params.step = params.step || DEFAULT_STEP; - params.dp = (params.dp != null) ? params.dp : DEFAULT_DP; - - this._onChange = params.onChange; - - var step = this._step = params.step, - dp = this._dp = params.dp; - - //FIXME: history push pop - - var labelMin = new Node(); - var inputMin = this._inputMin = new NumberInput_Internal(step,dp, this.pushHistoryState.bind(this), - this._onInputMinChange.bind(this)); - - var labelMax = new Node(); - var inputMax = this._inputMax = new NumberInput_Internal(step,dp, this.pushHistoryState.bind(this), - this._onInputMaxChange.bind(this)); - - var labelMinWrap = new Node().setStyleClass(CSS.Wrap), - inputMinWrap = new Node().setStyleClass(CSS.Wrap), - labelMaxWrap = new Node().setStyleClass(CSS.Wrap), - inputMaxWrap = new Node().setStyleClass(CSS.Wrap); - - labelMin.setStyleClass(CSS.Label).setProperty('innerHTML', 'MIN'); - labelMax.setStyleClass(CSS.Label).setProperty('innerHTML', 'MAX'); - - var values = this._obj[this._key]; - - inputMin.setValue(values[0]); - inputMax.setValue(values[1]); - - var wrap = this._wrapNode; - - labelMinWrap.addChild(labelMin); - inputMinWrap.addChild(inputMin.getNode()); - labelMaxWrap.addChild(labelMax); - inputMaxWrap.addChild(inputMax.getNode()); - - wrap.addChild(labelMinWrap); - wrap.addChild(inputMinWrap); - wrap.addChild(labelMaxWrap); - wrap.addChild(inputMaxWrap); -} -Range.prototype = Object.create(ObjectComponent.prototype); -Range.prototype.constructor = Range; - -Range.prototype._onInputChange = function () { - this.dispatchEvent(new Event_(this, ComponentEvent.VALUE_UPDATED, null)); - this._onChange(); -}; - -Range.prototype._updateValueMin = function () { - var values = this._obj[this._key]; - - var inputMin = this._inputMin, - inputValue = inputMin.getValue(); - - if (inputValue >= this._inputMax.getValue()) { - inputMin.setValue(values[0]); - return; - } - values[0] = inputValue; - -}; - -Range.prototype._updateValueMax = function () { - var values = this._obj[this._key]; - - var inputMax = this._inputMax, - inputValue = inputMax.getValue(); - - if (inputValue <= this._inputMin.getValue()) { - inputMax.setValue(values[1]); - return; - } - values[1] = inputValue; -}; - - -Range.prototype.onValueUpdate = function (e) { - if (e.data.origin == this){ - return; - } - if (e.data.origin == null) { - } - var o = this._obj,k = this._key; - this._inputMin.setValue(o[k][0]); - this._inputMax.setValue(o[k][1]); -}; - -Range.prototype.setValue = function(value){ - var o = this._obj,k = this._key; - o[k][0] = value[0]; - o[k][1] = value[1]; - this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED,null)); -}; - -Range.prototype._onInputMinChange = function () { - this._updateValueMin(); - this._onInputChange(); -}; - -Range.prototype._onInputMaxChange = function () { - this._updateValueMax(); - this._onInputChange(); -}; - -module.exports = Range; -},{"../core/ComponentEvent":31,"../core/ObjectComponent":35,"../core/document/CSS":42,"../core/document/Node":45,"../core/event/Event":48,"./NumberInput_Internal":14}],22:[function(require,module,exports){ -var Component = require('./../core/Component'); -var CSS = require('../core/document/CSS'); -var Metric = require('./Metric'); -var GroupEvent = require('../group/GroupEvent'); - -function SVG(parent, params) { - Component.apply(this, arguments); - - var wrap = this._wrapNode; - wrap.setStyleClass(CSS.CanvasWrap); - var wrapSize = wrap.getWidth(); - - var svg = this._svg = this._createSVGObject('svg'); - svg.setAttribute('version', '1.2'); - svg.setAttribute('baseProfile', 'tiny'); - svg.setAttribute('preserveAspectRatio', 'true'); - - wrap.getElement().appendChild(svg); - - this._svgSetSize(wrapSize, wrapSize); - this._updateHeight(); - - this._node.setStyleClass(CSS.CanvasListItem); - - this._parent.addEventListener(GroupEvent.GROUP_SIZE_CHANGE, this, 'onGroupSizeChange'); - this.addEventListener(GroupEvent.GROUP_SIZE_UPDATE, this._parent, 'onGroupSizeUpdate'); -} -SVG.prototype = Object.create(Component.prototype); -SVG.prototype.constructor = SVG; - -SVG.prototype._updateHeight = function () { - var svgHeight = Number(this._svg.getAttribute('height')); - this._wrapNode.setHeight(svgHeight); - this._node.setHeight(svgHeight + Metric.PADDING_WRAPPER); -}; - -SVG.prototype.onGroupSizeChange = function () { - var width = this._wrapNode.getWidth(); - this._svgSetSize(width, width); - this._updateHeight(); -}; - -SVG.prototype._svgSetSize = function (width, height) { - var svg = this._svg; - svg.setAttribute('width', width); - svg.setAttribute('height', height); - svg.setAttribute('viewbox', '0 0 ' + width + ' ' + height); -}; - -SVG.prototype.getSVG = function () { - return this._svg; -}; - -module.exports = SVG; -},{"../core/document/CSS":42,"../group/GroupEvent":54,"./../core/Component":30,"./Metric":12}],23:[function(require,module,exports){ -var ObjectComponent = require('../core/ObjectComponent'); -var CSS = require('../core/document/CSS'); -var GroupEvent = require('../group/GroupEvent'); -var Metric = require('./Metric'); - -function SVGComponent(parent,object,value,params){ - ObjectComponent.apply(this,arguments); - - var wrap = this._wrapNode; - wrap.setStyleClass(CSS.SVGWrap); - var wrapSize = wrap.getWidth(); - - var svg = this._svg = this._createSVGObject('svg'); - svg.setAttribute('version', '1.2'); - svg.setAttribute('baseProfile', 'tiny'); - - wrap.getElement().appendChild(svg); - - var svgRoot = this._svgRoot = svg.appendChild(this._createSVGObject('g')); - svgRoot.setAttribute('transform','translate(0.5 0.5)'); - - this._svgSetSize(wrapSize,wrapSize); - this._updateHeight(); - - this._node.setStyleClass(CSS.SVGListItem); - - this._parent.addEventListener(GroupEvent.GROUP_SIZE_CHANGE, this, 'onGroupSizeChange'); - this.addEventListener(GroupEvent.GROUP_SIZE_UPDATE, this._parent, 'onGroupSizeUpdate'); -} -SVGComponent.prototype = Object.create(ObjectComponent.prototype); -SVGComponent.prototype.constructor = SVGComponent; - -SVGComponent.prototype._updateHeight = function(){ - var svgHeight = Number(this._svg.getAttribute('height')); - - this._wrapNode.setHeight(svgHeight); - this._node.setHeight(svgHeight + Metric.PADDING_WRAPPER); -}; - -SVGComponent.prototype._redraw = function(){}; - -SVGComponent.prototype.onGroupSizeChange = function(){ - var width = this._wrapNode.getWidth(); - - this._svgSetSize(width,width); - this._updateHeight(); - this._redraw(); -}; - -SVGComponent.prototype._createSVGObject = function(type) { - return document.createElementNS("http://www.w3.org/2000/svg",type); -}; - -SVGComponent.prototype._svgSetSize = function(width,height) { - var svg = this._svg; - svg.setAttribute('width', width); - svg.setAttribute('height', height); - svg.setAttribute('viewbox', '0 0 ' + width + ' ' + height); -}; - - -SVGComponent.prototype._pathCmdMoveTo = function (x, y) { - return 'M ' + x + ' ' + y + ' '; -}; - -SVGComponent.prototype._pathCmdLineTo = function (x, y) { - return 'L ' + x + ' ' + y + ' '; -}; - -SVGComponent.prototype._pathCmdClose = function () { - return 'Z'; -}; - -SVGComponent.prototype._pathCmdLine = function (x0, y0, x1, y1) { - return 'M ' + x0 + ' ' + y0 + ' L ' + x1 + ' ' + y1; -}; - -SVGComponent.prototype._pathCmdBezierCubic = function (cmd, x0, y0, cx0, cy0, cx1, cy1, x1, y1) { - return 'M ' + x0 + ' ' + y0 + ' C ' + cx0 + ' ' + cy0 + ', ' + cx1 + ' ' + cy1 + ', ' + x1 + ' ' + y1; -}; - -SVGComponent.prototype._pathCmdBezierQuadratic = function (cmd, x0, y0, cx, cy, x1, y1) { - return 'M ' + x0 + ' ' + y0 + ' Q ' + cx + ' ' + cy + ', ' + x1 + ' ' + y1; -}; - -module.exports = SVGComponent; -},{"../core/ObjectComponent":35,"../core/document/CSS":42,"../group/GroupEvent":54,"./Metric":12}],24:[function(require,module,exports){ -var ObjectComponent = require('../core/ObjectComponent'); -var Node = require('../core/document/Node'); -var CSS = require('../core/document/CSS'); - -var Options = require('./Options'); - -var History = require('../core/History'); - -var Event_ = require('../core/event/Event'), - NodeEvent = require('../core/document/NodeEvent'), - ComponentEvent = require('../core/ComponentEvent'), - OptionEvent = require('../core/OptionEvent'); - -var ObjectComponentNotifier = require('../core/ObjectComponentNotifier'); - -var STR_CHOOSE = 'Choose ...'; - -function Select(parent, object, value, params) { - ObjectComponent.apply(this, arguments); - - params = params || {}; - params.onChange = params.onChange || this._onChange; - this._onChange = params.onChange; - - var obj = this._obj, - key = this._key; - - var targetKey = this._targetKey = params.target, - values = this._values = obj[key]; - - - this._selectedIndex = -1; - this._selected = null; - - var select = this._select = new Node(Node.INPUT_BUTTON); - select.setStyleClass(CSS.Select); - select.addEventListener(NodeEvent.MOUSE_DOWN, this._onOptionTrigger.bind(this)); - - if(this._hasTarget()) { - var targetObj = obj[targetKey] || ''; - var i = -1; - while (++i < values.length) { - if (targetObj == values[i]){ - this._selected = values[i]; - } - } - select.setProperty('value', targetObj.toString().length > 0 ? targetObj : values[0]); - } - else { - select.setProperty('value', params.selected ? values[params.selected] : STR_CHOOSE); - } - - this._wrapNode.addChild(select); - - ObjectComponentNotifier.get().addEventListener(OptionEvent.TRIGGER, this, 'onOptionTrigger'); - this.addEventListener(OptionEvent.TRIGGERED, ObjectComponentNotifier.get(), 'onOptionTriggered'); -} -Select.prototype = Object.create(ObjectComponent.prototype); -Select.prototype.constructor = Select; - -Select.prototype.onOptionTrigger = function (e) { - if (e.data.origin == this) { - this._active = !this._active; - this._updateAppearance(); - - if (this._active) { - this._buildOptions(); - } - else { - Options.get().clear(); - } - return; - } - this._active = false; - this._updateAppearance(); -}; - -Select.prototype._buildOptions = function () { - var options = Options.get(); - var self = this; - - options.build(this._values, this._selected, this._select, - function(){ - self.applyValue(); - self._active = false; - self._updateAppearance(); - self._selectedIndex = options.getSelectedIndex(); - self._onChange(self._selectedIndex); - options.clear(); - }, - function(){ - self._active = false; - self._updateAppearance(); - options.clear() - }, false); -}; - -Select.prototype._applySelected = function(selected){ - this._select.setProperty('value',selected); - this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED),null); -} - -Select.prototype.applyValue = function () { - var index = Options.get().getSelectedIndex(), - selected = this._selected = this._values[index]; - - if (this._hasTarget()) { - this.pushHistoryState(); - this._obj[this._targetKey] = selected; - } - - this._applySelected(selected); -}; - -Select.prototype.pushHistoryState = function () { - var obj = this._obj, - key = this._targetKey; - History.get().pushState(obj, key, obj[key]); -}; - -Select.prototype._onOptionTrigger = function () { - this.dispatchEvent(new Event_(this, OptionEvent.TRIGGERED, null)); -}; - -Select.prototype._updateAppearance = function () { - this._select.setStyleClass(this._active ? CSS.SelectActive : CSS.Select); -}; - -Select.prototype.onValueUpdate = function (e) { - if (!this._hasTarget()){ - return; - } - this._selected = this._obj[this._targetKey]; - this._select.setProperty('value', this._selected.toString()); -}; - -Select.prototype._hasTarget = function () { - return this._targetKey != null; -}; - -Select.prototype.setValue = function(value){ - this._selectedIndex = value; - if(value == -1){ - this._selected = null; - this._select.setProperty('value', STR_CHOOSE); - return; - } - this._selected = this._values[this._selectedIndex]; - this._applySelected(this._selected); -}; - -Select.prototype.getData = function(){ - var obj = {}; - obj['selectedIndex'] = this._selectedIndex; - return obj; -}; - -module.exports = Select; - -},{"../core/ComponentEvent":31,"../core/History":33,"../core/ObjectComponent":35,"../core/ObjectComponentNotifier":36,"../core/OptionEvent":37,"../core/document/CSS":42,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48,"./Options":16}],25:[function(require,module,exports){ -var ObjectComponent = require('../core/ObjectComponent'); -var CSS = require('../core/document/CSS'); -var Slider_Internal = require('./Slider_Internal'); - -var History = require('../core/History'); -var Range = require('./Range'); -var NumberInput_Internal = require('./NumberInput_Internal'); - -var Event_ = require('../core/event/Event'), - DocumentEvent = require('../core/document/DocumentEvent'), - PanelEvent = require('../group/PanelEvent'), - GroupEvent = require('../group/GroupEvent'), - ComponentEvent = require('../core/ComponentEvent'); - -var DEFAULT_STEP = 1.0, - DEFAULT_DP = 2; - - -function Slider(parent,object,value,range,params) { - params = params || {}; - params.label = params.label || value; - - ObjectComponent.apply(this,[parent,object,range,params]); - - this._values = this._obj[this._key]; - this._targetKey = value; - - params.step = params.step || DEFAULT_STEP; - params.dp = (params.dp === undefined || params.dp == null) ? DEFAULT_DP : params.dp; - params.onChange = params.onChange || this._onChange; - params.onFinish = params.onFinish || function(){}; - - this._dp = params.dp; - this._onChange = params.onChange; - this._onFinish = params.onFinish; - - var values = this._values, - obj = this._obj, - targetKey = this._targetKey; - - var wrap = this._wrapNode; - wrap.setStyleClass(CSS.WrapSlider); - - var slider = this._slider = new Slider_Internal(wrap, - this._onSliderBegin.bind(this), - this._onSliderMove.bind(this), - this._onSliderEnd.bind(this)); - - slider.setBoundMax(values[1]); - slider.setBoundMin(values[0]); - slider.setValue(obj[targetKey]); - - var input = this._input = new NumberInput_Internal(params.step, params.dp, null, - this._onInputChange.bind(this)); - - input.setValue(obj[targetKey]); - - wrap.addChild(input.getNode()); - - this._parent.addEventListener(PanelEvent.PANEL_MOVE_END, this, 'onPanelMoveEnd'); - this._parent.addEventListener(GroupEvent.GROUP_SIZE_CHANGE, this, 'onGroupWidthChange'); - this._parent.addEventListener(DocumentEvent.WINDOW_RESIZE, this, 'onWindowResize'); -} -Slider.prototype = Object.create(ObjectComponent.prototype); -Slider.prototype.constructor = Slider; - -Slider.prototype.pushHistoryState = function () { - var obj = this._obj, - key = this._targetKey; - History.get().pushState(obj, key, obj[key]); -}; - -Slider.prototype._onSliderBegin = function () { - this.pushHistoryState(); -}; - -Slider.prototype._onSliderMove = function () { - this.applyValue(); - this._updateValueField(); - this.dispatchEvent(new Event_(this, ComponentEvent.VALUE_UPDATED, null)); - this._onChange(); -}; - -Slider.prototype._onSliderEnd = function () { - this.applyValue(); - this._updateValueField(); - this.dispatchEvent(new Event_(this, ComponentEvent.VALUE_UPDATED, null)); - this._onFinish(); -}; - -Slider.prototype._onInputChange = function () { - var input = this._input, - valueMin = this._values[0], - valueMax = this._values[1]; - - if (input.getValue() >= valueMax){ - input.setValue(valueMax); - } - if (input.getValue() <= valueMin){ - input.setValue(valueMin); - } - - var value = input.getValue(); - - this._slider.setValue(value); - this._obj[this._targetKey] = value; - this.dispatchEvent(new Event_(this, ComponentEvent.VALUE_UPDATED, null)); - this._onFinish(); -}; - -Slider.prototype.applyValue = function () { - var value = this._slider.getValue(); - this._obj[this._targetKey] = parseFloat(value.toFixed(this._dp)); - this._input.setValue(value); -}; - - -Slider.prototype.onValueUpdate = function (e) { - var origin = e.data.origin; - if (origin == this){ - return; - } - var slider = this._slider; - if (!(origin instanceof Slider)) { - var values = this._values; - slider.setBoundMin(values[0]); - slider.setBoundMax(values[1]); - if (!(origin instanceof Range)) { - slider.setValue(this._obj[this._targetKey]); - } - } - else { - slider.setValue(this._obj[this._targetKey]); - } - this.applyValue(); -}; - - -Slider.prototype._updateValueField = function () { - this._input.setValue(this._slider.getValue()); -}; - -Slider.prototype.onPanelMoveEnd = - Slider.prototype.onGroupWidthChange = - Slider.prototype.onWindowResize = function () { - this._slider.resetOffset(); - }; - -Slider.prototype.setValue = function(value){ - if(value == -1){ - return; - } - this._obj[this._targetKey] = value; - this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED,null)); -}; - -Slider.prototype.getData = function(){ - var obj = {}; - obj[this._targetKey] = this._obj[this._targetKey]; - return obj; -}; - -module.exports = Slider; -},{"../core/ComponentEvent":31,"../core/History":33,"../core/ObjectComponent":35,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/event/Event":48,"../group/GroupEvent":54,"../group/PanelEvent":57,"./NumberInput_Internal":14,"./Range":21,"./Slider_Internal":26}],26:[function(require,module,exports){ -var Node = require('../core/document/Node'); - -var DocumentEvent = require('../core/document/DocumentEvent'), - NodeEvent = require('../core/document/NodeEvent'); - -var CSS = require('../core/document/CSS'); -var Mouse = require('../core/document/Mouse'); - -function Slider_Internal(parentNode,onBegin,onChange,onFinish) { - this._bounds = [0,1]; - this._value = 0; - this._intrpl = 0; - this._focus = false; - - - this._onBegin = onBegin || function(){}; - this._onChange = onChange || function(){}; - this._onFinish = onFinish || function(){}; - - - var wrap = new Node().setStyleClass(CSS.SliderWrap); - parentNode.addChild(wrap); - - var slot = this._slot = {node: new Node().setStyleClass(CSS.SliderSlot), - offsetX: 0, - width: 0, - padding: 3}; - - var handle = this._handle = {node : new Node().setStyleClass(CSS.SliderHandle), - width : 0, - dragging: false}; - - wrap.addChild(slot.node); - slot.node.addChild(handle.node); - - slot.offsetX = slot.node.getPositionGlobalX(); - slot.width = Math.floor(slot.node.getWidth() - slot.padding * 2) ; - - handle.node.setWidth(handle.width); - - slot.node.addEventListener(NodeEvent.MOUSE_DOWN,this._onSlotMouseDown.bind(this)); - slot.node.addEventListener(NodeEvent.MOUSE_UP, this._onSlotMouseUp.bind(this)); - - document.addEventListener(DocumentEvent.MOUSE_MOVE,this._onDocumentMouseMove.bind(this)); - document.addEventListener(DocumentEvent.MOUSE_UP, this._onDocumentMouseUp.bind(this)); -} - -Slider_Internal.prototype._onDocumentMouseMove = function(){ - if(!this._handle.dragging){ - return; - } - this._update(); - this._onChange(); -}; - -Slider_Internal.prototype._onDocumentMouseUp = function(){ - if(this._handle.dragging){ - this._onFinish(); - } - this._handle.dragging = false; -}; - -Slider_Internal.prototype._onSlotMouseDown = function(){ - this._onBegin(); - this._focus = true; - this._handle.dragging = true; - this._handle.node.getElement().focus(); - this._update(); -}; - -Slider_Internal.prototype._onSlotMouseUp = function(){ - if (this._focus) { - var handle = this._handle; - if (handle.dragging){ - this._onFinish(); - } - handle.dragging = false; - } - this._focus = false; -}; - -Slider_Internal.prototype._update = function(){ - var mx = Mouse.get().getX(), - sx = this._slot.offsetX, - sw = this._slot.width, - px = (mx < sx) ? 0 : (mx > (sx + sw)) ? sw : (mx - sx); - - this._handle.node.setWidth(Math.round(px)); - this._intrpl = px / sw; - this._interpolateValue(); -}; - -Slider_Internal.prototype._updateHandle = function(){ - var slotWidth = this._slot.width, - handleWidth = Math.round(this._intrpl * slotWidth); - this._handle.node.setWidth(Math.min(handleWidth,slotWidth)); -}; - -Slider_Internal.prototype._interpolateValue = function () { - var intrpl = this._intrpl, - bounds = this._bounds; - this._value = bounds[0] * (1.0 - intrpl) + bounds[1] * intrpl; -}; - -Slider_Internal.prototype.resetOffset = function () { - var slot = this._slot; - slot.offsetX = slot.node.getPositionGlobalX(); - slot.width = Math.floor(slot.node.getWidth() - slot.padding * 2) -}; - -Slider_Internal.prototype.setBoundMin = function (value) { - var bounds = this._bounds; - if (value >= bounds[1]){ - return; - } - bounds[0] = value; - this._updateFromBounds(); -}; - -Slider_Internal.prototype.setBoundMax = function (value) { - var bounds = this._bounds; - if (value <= bounds[0]){ - return; - } - bounds[1] = value; - this._updateFromBounds(); -}; - -Slider_Internal.prototype._updateFromBounds = function () { - var boundsMin = this._bounds[0], - boundsMax = this._bounds[1]; - this._value = Math.max(boundsMin,Math.min(this._value,boundsMax)); - this._intrpl = Math.abs((this._value - boundsMin) / (boundsMin - boundsMax)); - this._updateHandle(); -}; - -Slider_Internal.prototype.setValue = function (value) { - var boundsMin = this._bounds[0], - boundsMax = this._bounds[1]; - - if (value < boundsMin || value > boundsMax){ - return; - } - this._intrpl = Math.abs((value - boundsMin) / (boundsMin - boundsMax)); - this._updateHandle(); - this._value = value; -}; - -Slider_Internal.prototype.getValue = function () { - return this._value; -}; - - -module.exports = Slider_Internal; -},{"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Mouse":44,"../core/document/Node":45,"../core/document/NodeEvent":46}],27:[function(require,module,exports){ -var ObjectComponent = require('../core/ObjectComponent'); -var Node = require('../core/document/Node'); -var CSS = require('../core/document/CSS'); -var Options = require('./Options'); -var ButtonPreset = require('./ButtonPreset'); -var Metric = require('./Metric'); - -var Event_ = require('../core/event/Event'), - DocumentEvent = require('../core/document/DocumentEvent'), - NodeEvent = require('../core/document/NodeEvent'), - ComponentEvent = require('../core/ComponentEvent'); - -var DEFAULT_PRESET = null; - -function StringInput(parent,object,value,params) { - ObjectComponent.apply(this,arguments); - - params = params || {}; - params.onChange = params.onChange || this._onChange; - params.presets = params.presets || DEFAULT_PRESET; - - this._onChange = params.onChange; - - var input = this._input = new Node(Node.INPUT_TEXT); - - var wrap = this._wrapNode; - - var presets = params.presets; - if (!presets) { - wrap.addChild(input); - } - else { - var wrap_ = new Node(); - wrap_.setStyleClass(CSS.WrapInputWPreset); - - wrap.addChild(wrap_); - wrap_.addChild(input); - - var options = Options.get(), - btnPreset = new ButtonPreset(this._wrapNode); - - var onPresetDeactivate = function () { - options.clear(); - btnPreset.deactivate(); - }; - - var self = this; - var onPresetActivate = function () { - options.build(presets, - input.getProperty('value'), - input, - function () { - input.setProperty('value', presets[options.getSelectedIndex()]); - self.pushHistoryState(); - self.applyValue(); - }, - onPresetDeactivate, - Metric.PADDING_PRESET, - false); - }; - - btnPreset.setOnActive(onPresetActivate); - btnPreset.setOnDeactive(onPresetDeactivate) - } - - input.setProperty('value',this._obj[this._key]); - - input.addEventListener(NodeEvent.KEY_UP, this._onInputKeyUp.bind(this)); - input.addEventListener(NodeEvent.CHANGE, this._onInputChange.bind(this)); - - input.addEventListener(NodeEvent.MOUSE_DOWN, this._onInputDragStart.bind(this)); - this.addEventListener(ComponentEvent.INPUT_SELECT_DRAG,this._parent,'onComponentSelectDrag'); -} -StringInput.prototype = Object.create(ObjectComponent.prototype); -StringInput.prototype.constructor = StringInput; - -StringInput.prototype._onInputKeyUp = function (e) { - if (this._keyIsChar(e.keyCode)){ - this.pushHistoryState(); - } - this.applyValue(); - this._onChange(); -}; - -StringInput.prototype._onInputChange = function (e) { - if (this._keyIsChar(e.keyCode)){ - this.pushHistoryState(); - } - this.applyValue(); -}; - -//TODO: Finish check -StringInput.prototype._keyIsChar = function (keyCode) { - return keyCode != 17 && - keyCode != 18 && - keyCode != 20 && - keyCode != 37 && - keyCode != 38 && - keyCode != 39 && - keyCode != 40 && - keyCode != 16; -}; - - -StringInput.prototype.applyValue = function () { - this._obj[this._key] = this._input.getProperty('value'); - this.dispatchEvent(new Event_(this, ComponentEvent.VALUE_UPDATED, null)); -}; - -StringInput.prototype.onValueUpdate = function (e) { - if (e.data.origin == this)return; - this._input.setProperty('value', this._obj[this._key]); -}; - -//Prevent chrome select drag -StringInput.prototype._onInputDragStart = function () { - var eventMove = DocumentEvent.MOUSE_MOVE, - eventUp = DocumentEvent.MOUSE_UP; - - var event = ComponentEvent.INPUT_SELECT_DRAG; - var self = this; - var onDrag = function () { - self.dispatchEvent(new Event_(this, event, null)); - }, - - onDragFinish = function () { - self.dispatchEvent(new Event_(this, event, null)); - - document.removeEventListener(eventMove, onDrag, false); - document.removeEventListener(eventMove, onDragFinish, false); - }; - - this.dispatchEvent(new Event_(this, event, null)); - - document.addEventListener(eventMove, onDrag, false); - document.addEventListener(eventUp, onDragFinish, false); -}; - -module.exports = StringInput; -},{"../core/ComponentEvent":31,"../core/ObjectComponent":35,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48,"./ButtonPreset":4,"./Metric":12,"./Options":16}],28:[function(require,module,exports){ -var Output = require('./Output'); - -StringOutput = function (parent, object, value, params) { - Output.apply(this, arguments); -}; -StringOutput.prototype = Object.create(Output.prototype); -StringOutput.prototype.constructor = StringOutput; - -StringOutput.prototype._setValue = function () { - if (this._parent.isDisabled()) { - return; - } - var textAreaString = this._obj[this._key]; - - if (textAreaString == this._prevString){ - return; - } - var textArea = this._textArea, - textAreaElement = textArea.getElement(), - textAreaScrollHeight; - - textArea.setProperty('value', textAreaString); - textAreaScrollHeight = textAreaElement.scrollHeight; - textArea.setHeight(textAreaScrollHeight); - - var scrollBar = this._scrollBar; - - if (scrollBar) { - if (textAreaScrollHeight <= this._wrapNode.getHeight()) { - scrollBar.disable(); - } - else { - scrollBar.enable(); - scrollBar.update(); - scrollBar.reset(); - } - } - this._prevString = textAreaString; -}; - -module.exports = StringOutput; - -},{"./Output":17}],29:[function(require,module,exports){ -var Plotter = require('./Plotter'); -var Metric = require('./Metric'); - -var DEFAULT_RESOLUTION = 1; - -function ValuePlotter(parent,object,value,params) { - Plotter.apply(this,arguments); - - var svg = this._svg, - svgWidth = Number(svg.getAttribute('width')), - svgHeight = Number(svg.getAttribute('height')); - - params = params || {}; - params.height = params.height || svgHeight; - params.resolution = params.resolution || DEFAULT_RESOLUTION; - - var resolution = params.resolution, - length = Math.floor(svgWidth / resolution); - - var points = this._points = new Array(length * 2), - buffer0 = this._buffer0 = new Array(length), - buffer1 = this._buffer1 = new Array(length); - - var min = this._lineWidth * 0.5; - - var i = -1; - while (++i < length) { - buffer0[i] = buffer1[i] = points[i * 2] = points[i * 2 + 1] = min; - } - - this._height = params.height = params.height < Metric.COMPONENT_MIN_HEIGHT ? - Metric.COMPONENT_MIN_HEIGHT : params.height; - - this._svgSetSize(svgHeight,Math.floor(params.height)); - this._grid.style.stroke = 'rgb(39,44,46)'; - - this._updateHeight(); - this._drawValue(); -} -ValuePlotter.prototype = Object.create(Plotter.prototype); -ValuePlotter.prototype.constructor = ValuePlotter; - -ValuePlotter.prototype._redraw = function () { - var points = this._points, - bufferLen = this._buffer0.length; - - var width = Number(this._svg.getAttribute('width')), - ratio = width / (bufferLen - 1); - - var i = -1; - while (++i < bufferLen) { - points[i * 2] = width - i * ratio; - } - - this._drawValue(); -}; - -ValuePlotter.prototype.onGroupSizeChange = function () { - var width = this._wrapNode.getWidth(), - height = this._height; - - this._svgSetSize(width, height); - this._updateHeight(); - this._drawGrid(); - this._redraw(); -}; - -ValuePlotter.prototype._drawValue = function () { - this._drawCurve(); -}; - -ValuePlotter.prototype._drawGrid = function () { - var svg = this._svg; - - var svgWidth = Number(svg.getAttribute('width')), - svgHeightHalf = Math.floor(Number(svg.getAttribute('height')) * 0.5); - - var pathCmd = ''; - pathCmd += this._pathCmdMoveTo(0, svgHeightHalf); - pathCmd += this._pathCmdLineTo(svgWidth, svgHeightHalf); - - this._grid.setAttribute('d', pathCmd); -}; - -//TODO: merge update + pathcmd -ValuePlotter.prototype._drawCurve = function () { - var svg = this._svg; - - var value = this._obj[this._key]; - - var buffer0 = this._buffer0, - buffer1 = this._buffer1, - points = this._points; - - var bufferLength = buffer0.length; - - var pathCmd = ''; - - var heightHalf = Number(svg.getAttribute('height')) * 0.5, - unit = heightHalf - this._lineWidth * 0.5; - - points[1] = buffer0[0]; - buffer0[bufferLength - 1] = (value * unit) * -1 + Math.floor(heightHalf); - - pathCmd += this._pathCmdMoveTo(points[0], points[1]); - - var i = 0, index; - - while (++i < bufferLength) { - index = i * 2; - - buffer1[i - 1] = buffer0[i]; - points[index + 1] = buffer0[i - 1] = buffer1[i - 1]; - - pathCmd += this._pathCmdLineTo(points[index], points[index + 1]); - } - - this._path.setAttribute('d', pathCmd); -}; - -ValuePlotter.prototype.update = function () { - if (this._parent.isDisabled())return; - this._drawValue(); -} - - -module.exports = ValuePlotter; - - -},{"./Metric":12,"./Plotter":20}],30:[function(require,module,exports){ -var Node = require('./document/Node'), - CSS = require('./document/CSS'); -var EventDispatcher = require('./event/EventDispatcher'), - ComponentEvent = require('./ComponentEvent'); - -function Component(parent,label) { - EventDispatcher.apply(this,arguments); - - label = parent.usesLabels() ? label : 'none'; - - this._parent = parent; - this._enabled = true; - - var root = this._node = new Node(Node.LIST_ITEM), - wrap = this._wrapNode = new Node(); - wrap.setStyleClass(CSS.Wrap); - root.addChild(wrap); - - if (label !== undefined) { - if (label.length != 0 && label != 'none') { - var label_ = this._lablNode = new Node(Node.SPAN); - label_.setStyleClass(CSS.Label); - label_.setProperty('innerHTML', label); - root.addChild(label_); - } - - if (label == 'none') { - wrap.setStyleProperty('marginLeft', '0'); - wrap.setStyleProperty('width', '100%'); - } - } - - this._parent.addEventListener(ComponentEvent.ENABLE, this,'onEnable'); - this._parent.addEventListener(ComponentEvent.DISABLE,this,'onDisable'); - this._parent.addComponentNode(root); -} -Component.prototype = Object.create(EventDispatcher.prototype); -Component.prototype.constructor = Component; - -Component.prototype.enable = function () { - this._enabled = true; -}; - -Component.prototype.disable = function () { - this._enabled = false; -}; - -Component.prototype.isEnabled = function () { - return this._enabled; -}; -Component.prototype.isDisabled = function () { - return !this._enabled; -}; - -Component.prototype.onEnable = function () { - this.enable(); -}; - -Component.prototype.onDisable = function () { - this.disable(); -}; - -module.exports = Component; -},{"./ComponentEvent":31,"./document/CSS":42,"./document/Node":45,"./event/EventDispatcher":49}],31:[function(require,module,exports){ -var ComponentEvent = { - VALUE_UPDATED: 'valueUpdated', - UPDATE_VALUE: 'updateValue', - - INPUT_SELECT_DRAG: 'inputSelectDrag', - - ENABLE : 'enable', - DISABLE : 'disable' -}; - -module.exports = ComponentEvent; -},{}],32:[function(require,module,exports){ -function ComponentObjectError(object,key) { - Error.apply(this); - Error.captureStackTrace(this,ComponentObjectError); - this.name = 'ComponentObjectError'; - this.message = 'Object of type ' + object.constructor.name + ' has no member ' + key + '.'; -} -ComponentObjectError.prototype = Object.create(Error.prototype); -ComponentObjectError.prototype.constructor = ComponentObjectError; - -module.exports = ComponentObjectError; -},{}],33:[function(require,module,exports){ -var EventDispatcher = require('./event/EventDispatcher'), - Event_ = require('./event/Event'), - HistoryEvent = require('./HistoryEvent'); - -var MAX_STATES = 30; - -function History() { - EventDispatcher.apply(this, arguments); - this._states = []; - this._enabled = false; -} -History.prototype = Object.create(EventDispatcher.prototype); -History.prototype.constructor = History; - -History.prototype.pushState = function (object, key, value) { - if (this._enabled){ - return; - } - - var states = this._states; - if (states.length >= MAX_STATES){ - states.shift(); - } - states.push({object: object, key: key, value: value}); - this.dispatchEvent(new Event_(this, HistoryEvent.STATE_PUSH, null)); -}; - -History.prototype.getState = function (object, key) { - var states = this._states, - statesLen = states.length; - - if (statesLen == 0){ - return null; - } - - var state, value; - var i = -1; - while (++i < statesLen) { - state = states[i]; - if (state.object === object) { - if (state.key === key) { - value = state.value; - break; - } - } - } - return value; -}; - -History.prototype.popState = function () { - if (this._enabled){ - return; - } - - var states = this._states; - if (states.length < 1){ - return; - } - - var lastState = states.pop(); - lastState.object[lastState.key] = lastState.value; - - this.dispatchEvent(new Event_(this, HistoryEvent.STATE_POP, null)); -}; - -History.prototype.getNumStates = function () { - return this._states.length; -}; - -History._instance = null; - -History.setup = function () { - return History._instance = new History(); -}; - -History.get = function () { - return History._instance; -}; - -History.prototype.enable = function () { - this._enabled = false; -}; -History.prototype.disable = function () { - this._enabled = true; -}; - -module.exports = History; -},{"./HistoryEvent":34,"./event/Event":48,"./event/EventDispatcher":49}],34:[function(require,module,exports){ -var HistoryEvent = { - STATE_PUSH: 'historyStatePush', - STATE_POP: 'historyStatePop' -}; - -module.exports = HistoryEvent; -},{}],35:[function(require,module,exports){ -var History = require('./History'); -var Component = require('./Component'), - ComponentEvent = require('./ComponentEvent'), - ObjectComponentNotifier = require('./ObjectComponentNotifier'), - ComponentObjectError = require('./ComponentObjectError'); -var Event_ = require('./event/Event'); - -function ObjectComponent(parent, obj, key, params) { - if (obj[key] === undefined) { - throw new ComponentObjectError(obj, key); - } - params = params || {}; - params.label = params.label || key; - - Component.apply(this, [parent, params.label]); - - this._obj = obj; - this._key = key; - this._onChange = function(){}; - - ObjectComponentNotifier.get().addEventListener(ComponentEvent.UPDATE_VALUE, this, 'onValueUpdate'); - this.addEventListener(ComponentEvent.VALUE_UPDATED, ObjectComponentNotifier.get(), 'onValueUpdated'); -} -ObjectComponent.prototype = Object.create(Component.prototype); -ObjectComponent.prototype.constructor = ObjectComponent; - -//Override in Subclass -ObjectComponent.prototype.applyValue = function() {}; -ObjectComponent.prototype.onValueUpdate = function (e) {}; - -ObjectComponent.prototype.pushHistoryState = function () { - var obj = this._obj, key = this._key; - History.get().pushState(obj, key, obj[key]); -}; - -ObjectComponent.prototype.setValue = function (value) { - this._obj[this._key] = value; - this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED,null)); -}; - -ObjectComponent.prototype.getData = function(){ - var obj = {}; - obj[this._key] = this._obj[this._key]; - return obj; -}; - -module.exports = ObjectComponent; - -},{"./Component":30,"./ComponentEvent":31,"./ComponentObjectError":32,"./History":33,"./ObjectComponentNotifier":36,"./event/Event":48}],36:[function(require,module,exports){ -var EventDispatcher = require('./event/EventDispatcher'), - Event_ = require('./event/Event'); -var ComponentEvent = require('./ComponentEvent'), - OptionEvent = require('./OptionEvent'); - -function ObjectComponentNotifier(){ - EventDispatcher.apply(this); -} -ObjectComponentNotifier.prototype = Object.create(EventDispatcher.prototype); -ObjectComponentNotifier.prototype.constructor = ObjectComponentNotifier; - -ObjectComponentNotifier.prototype.onValueUpdated = function (e) { - this.dispatchEvent(new Event_(this, ComponentEvent.UPDATE_VALUE, {origin: e.sender})); -}; - -ObjectComponentNotifier.prototype.onOptionTriggered = function(e) { - this.dispatchEvent(new Event_(this, OptionEvent.TRIGGER, {origin: e.sender})); -}; - -var instance = null; - -ObjectComponentNotifier.get = function(){ - if(!instance){ - instance = new ObjectComponentNotifier(); - } - return instance; -}; - -ObjectComponentNotifier.destroy = function(){ - instance = null; -}; - -module.exports = ObjectComponentNotifier; -},{"./ComponentEvent":31,"./OptionEvent":37,"./event/Event":48,"./event/EventDispatcher":49}],37:[function(require,module,exports){ -var OptionEvent = { - TRIGGERED: 'selectTrigger', - TRIGGER: 'triggerSelect' -}; -module.exports = OptionEvent; -},{}],38:[function(require,module,exports){ -var DialogTemplate = - '\n' + - ' ControlKit State\n' + - ' \n' + - '\n' + - '\n' + - ' \n' + - ''; - -var SaveDialogTemplate = - '\n' + - ''; - -var LoadDialogTemplate = - '' + - ''; - -function createWindow(){ - var width = 320, height = 200; - var window_ = window.open('','','\ - width=' + width + ',\ - height=' + height + ',\ - left=' + (window.screenX + window.innerWidth * 0.5 - width * 0.5) + ',\ - top=' + (window.screenY + window.innerHeight * 0.5 - height * 0.5) + ',\ - location=0,\ - titlebar=0,\ - resizable=0'); - window_.document.documentElement.innerHTML = DialogTemplate; - return window_; -} - -function save(data){ - var window_ = createWindow(); - var document_ = window_.document; - document_.body.innerHTML += SaveDialogTemplate; - document_.getElementById('save').addEventListener('click',function(){ - //log & save in main window - var str = document_.getElementById('state').value, - blob = new Blob([str],{type:'application:json'}), - name = document_.getElementById('filename').value; - var a = document.createElement('a'); - a.download = name; - if(window.webkitURL){ - a.href = window.webkitURL.createObjectURL(blob); - } else { - a.href = window.createObjectURL(blob); - a.style.display = 'none'; - a.addEventListener('click',function(){ - document_.body.removeChild(a); - }); - document_.body.appendChild(a); - } - a.click(); - }); - document_.getElementById('state').innerText = JSON.stringify(data); -} - -function load(callback){ - var window_ = createWindow(); - var document_ = window_.document; - document_.body.innerHTML += LoadDialogTemplate; - var input = document_.getElementById('state'); - var btnLoad = document_.getElementById('load'); - btnLoad.disabled = true; - - function validateInput(){ - try{ - var obj = JSON.parse(input.value); - if(obj && typeof obj === 'object' && obj !== null){ - btnLoad.disabled = false; - } - } catch (e){ - btnLoad.disabled = true; - } - } - - input.addEventListener('input',function(){ - validateInput(); - }); - document_.getElementById('load').addEventListener('click',function(){ - var str = input.value; - callback(JSON.parse(str).data); - window_.close(); - }); - var loadFromDisk = document_.getElementById('load-disk'); - loadFromDisk.addEventListener('change',function(){ - var reader = new FileReader(); - reader.addEventListener('loadend',function(e){ - input.value = e.target.result; - validateInput(); - }); - reader.readAsText(loadFromDisk.files[0],'utf-8'); - }); -} - -module.exports = { - load : load, - save : save -}; -},{}],39:[function(require,module,exports){ -function ColorFormatError(msg) { - Error.apply(this); - Error.captureStackTrace(this,ColorFormatError); - this.name = 'ColorFormatError'; - this.message = msg; -} -ColorFormatError.prototype = Object.create(Error.prototype); -ColorFormatError.prototype.constructor = ColorFormatError; - -module.exports = ColorFormatError; -},{}],40:[function(require,module,exports){ -var ColorMode = { - RGB : 'rgb', - HSV : 'hsv', - HEX : 'hex', - RGBfv: 'rgbfv' -}; - -module.exports = ColorMode; -},{}],41:[function(require,module,exports){ -var ColorUtil = { - HSV2RGB: function (hue, sat, val) { - var max_hue = 360.0, - max_sat = 100.0, - max_val = 100.0; - - var min_hue = 0.0, - min_sat = 0, - min_val = 0; - - hue = hue % max_hue; - val = Math.max(min_val, Math.min(val, max_val)) / max_val * 255.0; - - if (sat <= min_sat) { - val = Math.round(val); - return [val, val, val]; - } - else if (sat > max_sat)sat = max_sat; - - sat = sat / max_sat; - - //http://d.hatena.ne.jp/ja9/20100903/128350434 - - var hi = Math.floor(hue / 60.0) % 6, - f = (hue / 60.0) - hi, - p = val * (1 - sat), - q = val * (1 - f * sat), - t = val * (1 - (1 - f) * sat); - - var r = 0, - g = 0, - b = 0; - - switch (hi) { - case 0: - r = val; - g = t; - b = p; - break; - case 1: - r = q; - g = val; - b = p; - break; - case 2: - r = p; - g = val; - b = t; - break; - case 3: - r = p; - g = q; - b = val; - break; - case 4: - r = t; - g = p; - b = val; - break; - case 5: - r = val; - g = p; - b = q; - break; - default: - break; - } - - r = Math.round(r); - g = Math.round(g); - b = Math.round(b); - - return [r, g, b]; - - }, - - RGB2HSV: function (r, g, b) { - var h = 0, - s = 0, - v = 0; - - r = r / 255.0; - g = g / 255.0; - b = b / 255.0; - - var minRGB = Math.min(r, Math.min(g, b)), - maxRGB = Math.max(r, Math.max(g, b)); - - if (minRGB == maxRGB) { - v = minRGB; - return [0, 0, Math.round(v)]; - } - - var dd = (r == minRGB) ? g - b : ((b == minRGB) ? r - g : b - r), - hh = (r == minRGB) ? 3 : ((b == minRGB) ? 1 : 5); - - h = Math.round(60 * (hh - dd / (maxRGB - minRGB))); - s = Math.round((maxRGB - minRGB) / maxRGB * 100.0); - v = Math.round(maxRGB * 100.0); - - return [h, s, v]; - }, - - RGB2HEX: function (r, g, b) { - return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); - }, - - RGBfv2HEX: function (r, g, b) { - return ColorUtil.RGB2HEX(Math.floor(r * 255.0), - Math.floor(g * 255.0), - Math.floor(b * 255.0)); - }, - - HSV2HEX: function (h, s, v) { - var rgb = ControlKit.ColorUtil.HSV2RGB(h, s, v); - return ControlKit.ColorUtil.RGB2HEX(rgb[0], rgb[1], rgb[2]); - }, - - HEX2RGB: function (hex) { - var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; - hex = hex.replace(shorthandRegex, function (m, r, g, b) { - return r + r + g + g + b + b; - }); - - var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); - return result ? [parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16)] : null; - - }, - - isValidHEX: function (hex) { - return /^#[0-9A-F]{6}$/i.test(hex); - }, - - isValidRGB: function (r, g, b) { - return r >= 0 && r <= 255 && - g >= 0 && g <= 255 && - b >= 0 && b <= 255; - }, - - isValidRGBfv: function (r, g, b) { - return r >= 0 && r <= 1.0 && - g >= 0 && g <= 1.0 && - b >= 0 && b <= 1.0; - } -}; - -module.exports = ColorUtil; -},{}],42:[function(require,module,exports){ -var CSS = { - ControlKit: 'controlKit', - - Panel: 'panel', - Head: 'head', - Label: 'label', - Menu: 'menu', - Wrap: 'wrap', - - ButtonMenuClose: 'button-menu-close', - ButtonMenuHide: 'button-menu-hide', - ButtonMenuShow: 'button-menu-show', - ButtonMenuUndo: 'button-menu-undo', - ButtonMenuLoad: 'button-menu-load', - ButtonMenuSave: 'button-menu-save', - MenuActive: 'menu-active', - - Button: 'button', - ButtonPreset: 'button-preset', - ButtonPresetActive: 'button-preset-active', - - WrapInputWPreset: 'input-with-preset-wrap', - WrapColorWPreset: 'color-with-preset-wrap', - - HeadInactive: 'head-inactive', - PanelHeadInactive: 'panel-head-inactive', - - GroupList: 'group-list', - Group: 'group', - SubGroupList: 'sub-group-list', - SubGroup: 'sub-group', - - - TextAreaWrap: 'textarea-wrap', - - WrapSlider: 'wrap-slider', - SliderWrap: 'slider-wrap', - SliderSlot: 'slider-slot', - SliderHandle: 'slider-handle', - - ArrowBMin: 'arrow-b-min', - ArrowBMax: 'arrow-b-max', - ArrowBSubMin: 'arrow-b-sub-min', - ArrowBSubMax: 'arrow-b-sub-max', - ArrowSMin: 'arrow-s-min', - ArrowSMax: 'arrow-s-max', - - Select: 'select', - SelectActive: 'select-active', - - Options: 'options', - OptionsSelected: 'li-selected', - - CanvasListItem: 'canvas-list-item', - CanvasWrap: 'canvas-wrap', - - SVGListItem: 'svg-list-item', - SVGWrap: 'svg-wrap', - - GraphSliderXWrap: 'graph-slider-x-wrap', - GraphSliderYWrap: 'graph-slider-y-wrap', - GraphSliderX: 'graph-slider-x', - GraphSliderY: 'graph-slider-y', - GraphSliderXHandle: 'graph-slider-x-handle', - GraphSliderYHandle: 'graph-slider-y-handle', - - Picker: 'picker', - PickerFieldWrap: 'field-wrap', - PickerInputWrap: 'input-wrap', - PickerInputField: 'input-field', - PickerControlsWrap: 'controls-wrap', - PickerColorContrast: 'color-contrast', - PickerHandleField: 'indicator', - PickerHandleSlider: 'indicator', - - Color: 'color', - - ScrollBar: 'scrollBar', - ScrollWrap: 'scroll-wrap', - ScrollBarBtnUp: 'btnUp', - ScrollBarBtnDown: 'btnDown', - ScrollBarTrack: 'track', - ScrollBarThumb: 'thumb', - ScrollBuffer: 'scroll-buffer', -}; - -module.exports = CSS; - -},{}],43:[function(require,module,exports){ -var DocumentEvent = { - MOUSE_MOVE: 'mousemove', - MOUSE_UP: 'mouseup', - MOUSE_DOWN: 'mousedown', - MOUSE_WHEEL: 'mousewheel', - WINDOW_RESIZE: 'resize' -}; - -module.exports = DocumentEvent; -},{}],44:[function(require,module,exports){ -var EventDispatcher = require('../event/EventDispatcher'), - Event_ = require('../event/Event'), - DocumentEvent = require('./DocumentEvent'); -var instance = null; - -function Mouse() { - EventDispatcher.apply(this); - this._pos = [0,0]; - this._wheelDirection = 0; - this._hoverElement = null; - - var self = this; - this._onDocumentMouseMove = function(e){ - var dx = 0, - dy = 0; - - if (!e)e = window.event; - if (e.pageX) { - dx = e.pageX; - dy = e.pageY; - } - else if (e.clientX) { - dx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; - dy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; - } - self._pos[0] = dx; - self._pos[1] = dy; - - self._hoverElement = document.elementFromPoint(dx,dy); - }; - - this._onDocumentMouseWheel = function(event){ - self._wheelDirection = (event.detail < 0) ? 1 : (event.wheelDelta > 0) ? 1 : -1; - self.dispatchEvent(new Event_(self,DocumentEvent.MOUSE_WHEEL,event)); - }; - - document.addEventListener(DocumentEvent.MOUSE_MOVE, this._onDocumentMouseMove); - document.addEventListener(DocumentEvent.MOUSE_WHEEL,this._onDocumentMouseWheel); -} -Mouse.prototype = Object.create(EventDispatcher.prototype); -Mouse.prototype.constructor = Mouse; - -Mouse.prototype._removeDocumentListener = function(){ - document.removeEventListener(DocumentEvent.MOUSE_MOVE, this._onDocumentMouseMove); - document.removeEventListener(DocumentEvent.MOUSE_WHEEL,this._onDocumentMouseWheel); -}; - -Mouse.prototype.getPosition = function () { - return this._pos; -}; - -Mouse.prototype.getX = function () { - return this._pos[0]; -}; - -Mouse.prototype.getY = function () { - return this._pos[1]; -}; - -Mouse.prototype.getWheelDirection = function(){ - return this._wheelDirection; -}; - -Mouse.prototype.getHoverElement = function(){ - return this._hoverElement; -}; - -Mouse.setup = function () { - instance = instance || new Mouse(); - return instance; -}; - -Mouse.get = function () { - return instance; -}; - -Mouse.destroy = function(){ - instance._removeDocumentListener(); - instance = null; -}; - -module.exports = Mouse; -},{"../event/Event":48,"../event/EventDispatcher":49,"./DocumentEvent":43}],45:[function(require,module,exports){ -function Node() { - this._element = null; - - switch (arguments.length){ - case 1 : - var arg = arguments[0]; - if (arg != Node.INPUT_TEXT && - arg != Node.INPUT_BUTTON && - arg != Node.INPUT_SELECT && - arg != Node.INPUT_CHECKBOX) { - this._element = document.createElement(arg); - } - else { - this._element = document.createElement('input'); - this._element.type = arg; - } - break; - case 0: - this._element = document.createElement('div'); - break; - } -} - -Node.DIV = 'div'; -Node.INPUT_TEXT = 'text'; -Node.INPUT_BUTTON = 'button'; -Node.INPUT_SELECT = 'select'; -Node.INPUT_CHECKBOX = 'checkbox'; -Node.OPTION = 'option'; -Node.LIST = 'ul'; -Node.LIST_ITEM = 'li'; -Node.SPAN = 'span'; -Node.TEXTAREA = 'textarea'; - -Node.prototype = { - addChild: function (node) { - this._element.appendChild(node.getElement()); - return node; - }, - addChildren: function () { - var i = -1, l = arguments.length, e = this._element; - while (++i < l) { - e.appendChild(arguments[i].getElement()); - } - return this; - }, - addChildAt: function (node, index) { - this._element.insertBefore(node.getElement(), this._element.children[index]); - return node; - }, - removeChild: function (node) { - if (!this.contains(node))return null; - this._element.removeChild(node.getElement()); - return node; - }, - removeChildren: function () { - var i = -1, l = arguments.length, e = this._element; - while (++i < l) { - e.removeChild(arguments[i].getElement()); - } - return this; - }, - removeChildAt: function (node, index) { - if (!this.contains(node))return null; - this._element.removeChild(node.getElement()); - return node; - }, - removeAllChildren: function () { - var element = this._element; - while (element.hasChildNodes())element.removeChild(element.lastChild); - return this; - }, - setWidth: function (value) { - this._element.style.width = value + 'px'; - return this; - }, - getWidth: function () { - return this._element.offsetWidth; - }, - setHeight: function (value) { - this._element.style.height = value + 'px'; - return this; - }, - getHeight: function () { - return this._element.offsetHeight; - }, - setPosition: function (x, y) { - return this.setPosition(x).setPosition(y); - }, - setPositionX: function (x) { - this._element.style.marginLeft = x + 'px'; - return this; - }, - setPositionY: function (y) { - this._element.style.marginTop = y + 'px'; - return this; - }, - setPositionGlobal: function (x, y) { - return this.setPositionGlobalX(x).setPositionGlobalY(y); - }, - setPositionGlobalX: function (x) { - this._element.style.left = x + 'px'; - return this; - }, - setPositionGlobalY: function (y) { - this._element.style.top = y + 'px'; - return this; - }, - getPosition: function () { - return [this.getPositionX(), this.getPositionY()]; - }, - getPositionX: function () { - return this._element.offsetLeft; - }, - getPositionY: function () { - return this._element.offsetTop; - }, - getPositionGlobal: function () { - var offset = [0, 0], - element = this._element; - - while (element) { - offset[0] += element.offsetLeft; - offset[1] += element.offsetTop; - element = element.offsetParent; - } - - return offset; - }, - getPositionGlobalX: function () { - var offset = 0, - element = this._element; - - while (element) { - offset += element.offsetLeft; - element = element.offsetParent; - } - - return offset; - }, - getPositionGlobalY: function () { - var offset = 0, - element = this._element; - - while (element) { - offset += element.offsetTop; - element = element.offsetParent; - } - - return offset; - }, - addEventListener: function (type, listener, useCapture) { - this._element.addEventListener(type, listener, useCapture); - return this; - }, - removeEventListener: function (type, listener, useCapture) { - this._element.removeEventListener(type, listener, useCapture); - return this; - }, - dispatchEvent : function(event) { - this._element.dispatchEvent(event); - return this; - }, - setStyleClass: function (style) { - this._element.className = style; - return this; - }, - setStyleProperty: function (property, value) { - this._element.style[property] = value; - return this; - }, - getStyleProperty: function (property) { - return this._element.style[property]; - }, - setStyleProperties: function (properties) { - for (var p in properties){ - this._element.style[p] = properties[p]; - } - return this; - }, - deleteStyleClass: function () { - this._element.className = ''; - return this - }, - deleteStyleProperty: function (property) { - this._element.style[property] = ''; - return this; - }, - deleteStyleProperties: function (properties) { - for (var p in properties){ - this._element.style[p] = ''; - } - return this; - }, - getChildAt: function (index) { - return new Node().setElement(this._element.children[index]); - }, - getChildIndex: function (node) { - return this._indexOf(this._element, node.getElement()); - }, - getNumChildren: function () { - return this._element.children.length; - }, - getFirstChild: function () { - return new Node().setElement(this._element.firstChild); - }, - getLastChild: function () { - return new Node().setElement(this._element.lastChild); - }, - hasChildren: function () { - return this._element.children.length != 0; - }, - contains: function (node) { - return this._indexOf(this._element, node.getElement()) != -1; - }, - _indexOf: function (parentElement, element) { - return Array.prototype.indexOf.call(parentElement.children, element); - }, - setProperty: function (property, value) { - this._element[property] = value; - return this; - }, - setProperties: function (properties) { - for (var p in properties){ - this._element[p] = properties[p]; - } - return this; - }, - getProperty: function (property) { - return this._element[property]; - }, - setElement: function (element) { - this._element = element; - return this; - }, - getElement: function () { - return this._element; - }, - getStyle: function () { - return this._element.style; - }, - getParent: function () { - return new Node().setElement(this._element.parentNode); - } -}; - -Node.getNodeByElement = function (element) { - return new Node().setElement(element); -}; -Node.getNodeById = function (id) { - return new Node().setElement(document.getElementById(id)); -}; - -module.exports = Node; -},{}],46:[function(require,module,exports){ -var NodeEvent = { - MOUSE_DOWN : 'mousedown', - MOUSE_UP : 'mouseup', - MOUSE_OVER : 'mouseover', - MOUSE_MOVE : 'mousemove', - MOUSE_OUT : 'mouseout', - KEY_DOWN : 'keydown', - KEY_UP : 'keyup', - CHANGE : 'change', - FINISH : 'finish', - DBL_CLICK : 'dblclick', - ON_CLICK : 'click', - SELECT_START : 'selectstart', - DRAG_START : 'dragstart', - DRAG : 'drag', - DRAG_END : 'dragend', - - DRAG_ENTER : 'dragenter', - DRAG_OVER : 'dragover', - DRAG_LEAVE : 'dragleave', - - RESIZE : 'resize' -}; - -module.exports = NodeEvent; -},{}],47:[function(require,module,exports){ -var Style = { - string : "#controlKit{position:absolute;top:0;left:0;width:100%;height:100%;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;pointer-events:none}#controlKit .panel{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;pointer-events:auto;position:relative;z-index:1;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:hidden;opacity:1;float:left;width:200px;border-radius:3px;-moz-border-radius:3px;box-shadow:0 2px 2px rgba(0,0,0,.25);margin:0;padding:0;background-color:#1a1a1a;font-family:Arial,sans-serif}#controlKit .panel .wrap{width:auto;height:auto;margin:0;padding:0;position:relative;overflow:hidden}#controlKit .panel ul{margin:0;padding:0;list-style:none}#controlKit .panel .color,#controlKit .panel input[type=text],#controlKit .panel textarea,#controlKit .picker input[type=text]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;height:25px;padding:0 0 0 8px;font-family:Arial,sans-serif;font-size:11px;color:#fff;text-shadow:1px 1px #000;outline:0;background:#222729;background-image:-o-linear-gradient(rgba(0,0,0,.075) 0,rgba(0,0,0,.125) 100%);background-image:linear-gradient(rgba(0,0,0,.075) 0,rgba(0,0,0,.125) 100%);border:none;box-shadow:0 0 0 1px #1f1f1f inset;border-radius:2px;-moz-border-radius:2px}#controlKit .panel .button,#controlKit .panel .select,#controlKit .panel .select-active,#controlKit .picker .button{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:pointer;width:100%;height:26px;margin:0;background-image:-o-linear-gradient(#404040 0,#3b3b3b 100%);background-image:linear-gradient(#404040 0,#3b3b3b 100%);border:none;outline:0;border-radius:2px;box-shadow:0 0 0 1px #1f1f1f inset,-1px 2px 0 0 #4a4a4a inset;font-family:Arial,sans-serif;color:#fff}#controlKit .panel textarea{padding:5px 8px 2px;overflow:hidden;resize:none;vertical-align:top;white-space:nowrap}#controlKit .panel .textarea-wrap{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;padding:0;float:left;height:100%;overflow:hidden;border:none;border-radius:2px;-moz-border-radius:2px;background-color:#222729;box-shadow:0 0 1px 2px rgba(0,0,0,.0125) inset,0 0 1px 1px #111314 inset;background-image:-o-linear-gradient(rgba(0,0,0,.075) 0,rgba(0,0,0,.125) 100%);background-image:linear-gradient(rgba(0,0,0,.075) 0,rgba(0,0,0,.125) 100%)}#controlKit .panel .textarea-wrap textarea{border:none;border-radius:2px;-moz-border-radius:2px;box-shadow:none;background:0 0}#controlKit .panel .textarea-wrap .scrollBar{border:1px solid #101213;border-bottom-right-radius:2px;border-top-right-radius:2px;border-left:none;box-shadow:0 0 1px 2px rgba(0,0,0,.0125) inset,0 0 1px 1px #111314 inset}#controlKit .panel canvas{cursor:pointer;vertical-align:bottom;border:none;box-shadow:0 0 0 1px #1f1f1f inset;border-radius:2px;-moz-border-radius:2px}#controlKit .panel .canvas-wrap,#controlKit .panel .svg-wrap{margin:6px 0 0;position:relative;width:70%;float:right;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border:none;border-radius:2px;-moz-border-radius:2px;background:#1e2224;background-image:-o-linear-gradient(transparent 0,rgba(0,0,0,.05) 100%);background-image:linear-gradient(transparent 0,rgba(0,0,0,.05) 100%)}#controlKit .panel .canvas-wrap svg,#controlKit .panel .svg-wrap svg{position:absolute;left:0;top:0;cursor:pointer;vertical-align:bottom;border:none;box-shadow:0 0 0 1px #1f1f1f inset;border-radius:2px;-moz-border-radius:2px}#controlKit .panel .button,#controlKit .picker .button{font-size:10px;font-weight:700;text-shadow:0 1px #000;text-transform:uppercase}#controlKit .panel .button:hover,#controlKit .picker .button:hover{background-image:-o-linear-gradient(#454545 0,#3b3b3b 100%);background-image:linear-gradient(#454545 0,#3b3b3b 100%)}#controlKit .panel .button:active,#controlKit .picker .button:active{background-image:-o-linear-gradient(#404040 0,#3b3b3b 100%);background-image:linear-gradient(#404040 0,#3b3b3b 100%)}#controlKit .panel .color-with-preset-wrap,#controlKit .panel .input-with-preset-wrap{width:100%;float:left}#controlKit .panel .color-with-preset-wrap .color,#controlKit .panel .input-with-preset-wrap input[type=text]{padding-right:25px;border-top-right-radius:2px;border-bottom-right-radius:2px;float:left}#controlKit .panel .button-preset,#controlKit .panel .button-preset-active{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;right:0;width:20px;height:25px;margin:0;cursor:pointer;float:right;border:none;border-top-right-radius:2px;border-bottom-right-radius:2px;box-shadow:0 0 0 1px #1f1f1f inset,-1px 2px 0 0 #4a4a4a inset;outline:0}#controlKit .panel .button-preset-active,#controlKit .panel .button-preset:hover{background:url(data:image/png;base64,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) 50% 50% no-repeat,linear-gradient(#454545 0,#3b3b3b 100%)}#controlKit .panel .button-preset{background:url(data:image/png;base64,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) 50% 50% no-repeat,linear-gradient(#404040 0,#3b3b3b 100%)}#controlKit .panel input[type=checkbox]{margin:6px 0 0}#controlKit .panel .select,#controlKit .panel .select-active{padding-left:10px;padding-right:20px;font-size:11px;text-align:left;text-shadow:1px 1px #000;cursor:pointer;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}#controlKit .panel .select{background:url(data:image/png;base64,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) 100% 50% no-repeat,linear-gradient(#404040 0,#3b3b3b 100%)}#controlKit .panel .select-active,#controlKit .panel .select:hover{background:url(data:image/png;base64,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) 100% 50% no-repeat,linear-gradient(#454545 0,#3b3b3b 100%)}#controlKit .panel .slider-handle,#controlKit .panel .slider-slot,#controlKit .panel .slider-wrap,#controlKit .panel .wrap-slider{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#controlKit .panel .wrap-slider{width:70%;padding:6px 0 0;float:right;height:100%}#controlKit .panel .wrap-slider input[type=text]{width:25%;text-align:center;padding:0;float:right}#controlKit .panel .slider-wrap{float:left;cursor:ew-resize;width:70%}#controlKit .panel .slider-slot{width:100%;height:25px;padding:3px;background-color:#1e2224;border:none;box-shadow:0 0 0 1px #1f1f1f inset;border-radius:2px;-moz-border-radius:2px}#controlKit .panel .slider-handle{position:relative;width:100%;height:100%;background:#b32435;background-image:-o-linear-gradient(transparent 0,rgba(0,0,0,.1) 100%);background-image:linear-gradient(transparent 0,rgba(0,0,0,.1) 100%);box-shadow:0 1px 0 0 #0f0f0f}#controlKit .panel .color{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;cursor:pointer;width:100%;height:25px;padding:0;border:none;background:#fff;box-shadow:0 0 0 1px #111314 inset;text-align:center;line-height:25px;border-radius:2px;-moz-border-radius:2px}#controlKit .panel .graph-slider-x-wrap,#controlKit .panel .graph-slider-y-wrap{position:absolute;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#controlKit .panel .graph-slider-x-wrap{bottom:0;left:0;width:100%;padding:6px 20px 6px 6px}#controlKit .panel .graph-slider-y-wrap{top:0;right:0;height:100%;padding:6px 6px 20px}#controlKit .panel .graph-slider-x,#controlKit .panel .graph-slider-y{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:2px;-moz-border-radius:2px;background:rgba(24,27,29,.5);border:1px solid #181b1d}#controlKit .panel .graph-slider-x{height:8px}#controlKit .panel .graph-slider-y{width:8px;height:100%}#controlKit .panel .graph-slider-x-handle,#controlKit .panel .graph-slider-y-handle{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:pointer;border:1px solid #181b1d;background:#303639}#controlKit .panel .graph-slider-x-handle{width:20px;height:100%;border-top:none;border-bottom:none}#controlKit .panel .graph-slider-y-handle{width:100%;height:20px;border-left:none;border-right:none}#controlKit .sub-group .wrap .wrap .wrap{width:25%!important;padding:0!important;float:left!important}#controlKit .sub-group .wrap .wrap .wrap .label{width:100%!important;padding:8px 0 0!important;color:#878787!important;text-align:center!important;text-transform:uppercase!important;font-weight:700!important;text-shadow:1px 1px #1a1a1a!important}#controlKit .sub-group .wrap .wrap .wrap input[type=text]{padding:0;text-align:center}#controlKit .options{pointer-events:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border:1px solid #1f1f1f;border-radius:2px;-moz-border-radius:2px;position:absolute;z-index:2147483638;left:0;top:0;width:auto;height:auto;box-shadow:0 1px 0 0 #4a4a4a inset;background-color:#454545;font-family:Arial,sans-serif;font-size:11px;color:#fff;text-shadow:1px 1px #000;overflow:hidden}#controlKit .options ul{width:100%;list-style:none;margin:0;padding:0}#controlKit .options ul li{margin:0;width:100%;height:25px;line-height:25px;padding:0 20px 0 10px;overflow:hidden;white-space:normal;text-overflow:ellipsis;cursor:pointer}#controlKit .options ul li:hover{background-color:#1f2325}#controlKit .options ul .li-selected{background-color:#292d30}#controlKit .options .color{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}#controlKit .options .color .li-selected,#controlKit .options .color li{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0;height:25px;line-height:25px;text-align:center}#controlKit .options .color .li-selected:hover,#controlKit .options .color li:hover{background:0 0;font-weight:700}#controlKit .options .color .li-selected{font-weight:700}#controlKit .panel .label,#controlKit .picker .label{width:100%;float:left;font-size:11px;font-weight:700;text-shadow:0 1px #000;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;cursor:default}#controlKit .panel .head,#controlKit .panel .panel-head-inactive,#controlKit .picker .head{height:30px;padding:0 10px;background:#1a1a1a;overflow:hidden}#controlKit .panel .head .wrap,#controlKit .panel .panel-head-inactive .wrap,#controlKit .picker .head .wrap{width:auto;height:auto;margin:0;padding:0;position:relative;overflow:hidden}#controlKit .panel .head .label,#controlKit .picker .head .label{cursor:pointer;line-height:30px;color:#65696b}#controlKit .panel .group-list .group .head{height:38px;padding:0 10px;border-top:1px solid #4f4f4f;border-bottom:1px solid #262626;background-image:-o-linear-gradient(#454545 0,#3b3b3b 100%);background-image:linear-gradient(#454545 0,#3b3b3b 100%);cursor:pointer}#controlKit .panel .group-list .group .head .label{font-size:12px;line-height:38px;color:#fff}#controlKit .panel .group-list .group .head:hover{border-top:1px solid #525252;background-image:-o-linear-gradient(#454545 0,#404040 100%);background-image:linear-gradient(#454545 0,#404040 100%)}#controlKit .panel .group-list .group li{height:35px;padding:0 10px}#controlKit .panel .group-list .group .sub-group-list .sub-group:last-of-type{border-bottom:none}#controlKit .panel .group-list .group .sub-group-list .sub-group{padding:0;height:auto;border-bottom:1px solid #242424}#controlKit .panel .group-list .group .sub-group-list .sub-group ul{overflow:hidden}#controlKit .panel .group-list .group .sub-group-list .sub-group ul li{background:#2e2e2e;border-bottom:1px solid #222729}#controlKit .panel .group-list .group .sub-group-list .sub-group ul li:last-of-type{border-bottom:none}#controlKit .panel .group-list .group .sub-group-list .sub-group:first-child{margin-top:0}#controlKit .panel .group-list .group .sub-group-list .sub-group .head,#controlKit .panel .group-list .group .sub-group-list .sub-group .head-inactive{cursor:pointer}#controlKit .panel .group-list .group .sub-group-list .sub-group .head{height:27px;padding:0 10px;border-top:none;border-bottom:1px solid #242424;background-image:none;background-color:#272727}#controlKit .panel .group-list .group .sub-group-list .sub-group .head:hover{background-image:none;background-color:#272727}#controlKit .panel .group-list .group .sub-group-list .sub-group .head-inactive{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;height:27px;padding:0 10px;box-shadow:0 1px 0 0 #404040 inset;background-image:-o-linear-gradient(#3b3b3b 0,#383838 100%);background-image:linear-gradient(#3b3b3b 0,#383838 100%)}#controlKit .panel .group-list .group .sub-group-list .sub-group .head-inactive:hover{box-shadow:0 1px 0 0 #474747 inset;background-image:none;background-image:-o-linear-gradient(#404040 0,#3b3b3b 100%);background-image:linear-gradient(#404040 0,#3b3b3b 100%)}#controlKit .panel .group-list .group .sub-group-list .sub-group .head .label,#controlKit .panel .group-list .group .sub-group-list .sub-group .head-inactive .label{margin:0;padding:0;line-height:27px;color:#fff;font-weight:700;font-size:11px;text-shadow:1px 1px #000;text-transform:capitalize}#controlKit .panel .group-list .group .sub-group-list .sub-group .head .wrap .label,#controlKit .panel .group-list .group .sub-group-list .sub-group .head-inactive .wrap .label{width:100%;font-weight:700;color:#fff;padding:0}#controlKit .panel .group-list .group .sub-group-list .sub-group .wrap .label{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;height:100%;width:30%;padding:12px 5px 0 0;float:left;font-size:11px;font-weight:400;color:#aeb5b8;text-shadow:1px 1px #000}#controlKit .panel .group-list .group .sub-group-list .sub-group .wrap .wrap{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:70%;padding:5px 0 0;float:right;height:100%}#controlKit .panel .group-list .group:last-child .scroll-buffer:nth-of-type(3),#controlKit .panel .group-list .group:last-child .sub-group-list{border-bottom:none}#controlKit .panel .scroll-wrap{position:relative;overflow:hidden}#controlKit .panel .scroll-buffer{width:100%;height:8px;border-top:1px solid #3b4447;border-bottom:1px solid #1e2224}#controlKit .panel .scrollBar{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;width:15px;height:100%;float:right;top:0;padding:0;margin:0;position:relative;background:#212628;background-image:linear-gradient(to right,#242424 0,#2e2e2e 100%)}#controlKit .panel .scrollBar .track{padding:0 3px 0 2px}#controlKit .panel .scrollBar .track .thumb{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:11px;position:absolute;cursor:pointer;background-color:#343434;border:1px solid #1b1f21;border-radius:10px;-moz-border-radius:10px;box-shadow:inset 0 1px 0 0 #434b50}#controlKit .panel .menu,#controlKit .panel .menu-active,#controlKit .picker .menu{float:right;padding:5px 0 0}#controlKit .panel .menu input[type=button],#controlKit .panel .menu-active input[type=button],#controlKit .picker .menu input[type=button]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:pointer;height:20px;border:none;vertical-align:top;border-radius:2px;-moz-border-radius:2px;font-family:Arial,sans-serif;font-size:10px;font-weight:700;color:#aaa;text-shadow:0 -1px #000;text-transform:uppercase;box-shadow:0 0 0 1px #131313 inset,-1px 2px 0 0 #212527 inset;outline:0}#controlKit .panel .menu .button-menu-close,#controlKit .panel .menu .button-menu-hide,#controlKit .panel .menu .button-menu-show,#controlKit .panel .menu-active .button-menu-close,#controlKit .panel .menu-active .button-menu-hide,#controlKit .panel .menu-active .button-menu-show,#controlKit .picker .menu .button-menu-close,#controlKit .picker .menu .button-menu-hide,#controlKit .picker .menu .button-menu-show{width:20px;margin-left:4px}#controlKit .panel .menu .button-menu-hide,#controlKit .panel .menu-active .button-menu-hide,#controlKit .picker .menu .button-menu-hide{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAGRJREFUeNpidPUNYoCBU0cO1DMwMDCY2Tg0wsRYkCVlFZUboGy4ImZldU24pJySCgO/oBADAwODw/VL5xmk5RQOMr99/RIuCQPIiljMbBwYGBgYGH7//MmADCSlZRkkpWUZAAMAvTsgXBvOsq0AAAAASUVORK5CYII=) 50% 50% no-repeat,#1a1d1f}#controlKit .panel .menu .button-menu-hide:hover,#controlKit .panel .menu-active .button-menu-hide:hover,#controlKit .picker .menu .button-menu-hide:hover{background:url(data:image/png;base64,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) 50% 50% no-repeat,#000;box-shadow:#fff 0,#000 100%}#controlKit .panel .menu .button-menu-show,#controlKit .panel .menu-active .button-menu-show,#controlKit .picker .menu .button-menu-show{background:url(data:image/png;base64,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) 50% 50% no-repeat,#1a1d1f}#controlKit .panel .menu .button-menu-show:hover,#controlKit .panel .menu-active .button-menu-show:hover,#controlKit .picker .menu .button-menu-show:hover{background:url(data:image/png;base64,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) 50% 50% no-repeat,#000;box-shadow:#fff 0,#000 100%}#controlKit .panel .menu .button-menu-close,#controlKit .panel .menu-active .button-menu-close,#controlKit .picker .menu .button-menu-close{background:url(data:image/png;base64,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) 50% 50% no-repeat,#1a1d1f}#controlKit .panel .menu .button-menu-close:hover,#controlKit .panel .menu-active .button-menu-close:hover,#controlKit .picker .menu .button-menu-close:hover{background:url(data:image/png;base64,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) 50% 50% no-repeat,#000;box-shadow:#fff 0,#000 100%}#controlKit .panel .menu .button-menu-undo,#controlKit .panel .menu-active .button-menu-undo{background:url(data:image/png;base64,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) 20% 50% no-repeat,#1a1d1f;padding:0 6px 1px 0;width:38px;vertical-align:top;text-align:end}#controlKit .panel .menu .button-menu-undo:hover,#controlKit .panel .menu-active .button-menu-undo:hover{background:url(data:image/png;base64,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) 20% 50% no-repeat,#000;box-shadow:#fff 0,#000 100%}#controlKit .panel .menu .button-menu-load,#controlKit .panel .menu-active .button-menu-load{margin-right:2px}#controlKit .panel .menu .button-menu-load,#controlKit .panel .menu .button-menu-save,#controlKit .panel .menu-active .button-menu-load,#controlKit .panel .menu-active .button-menu-save{background:#1a1d1f;font-size:9px!important}#controlKit .panel .menu .button-menu-load:hover,#controlKit .panel .menu .button-menu-save:hover,#controlKit .panel .menu-active .button-menu-load:hover,#controlKit .panel .menu-active .button-menu-save:hover{background:#000}#controlKit .panel .menu .wrap{display:none}#controlKit .panel .menu-active{width:100%;float:left}#controlKit .panel .menu-active .wrap{display:inline}#controlKit .panel .menu-active .button-menu-close,#controlKit .panel .menu-active .button-menu-hide,#controlKit .panel .menu-active .button-menu-show{float:right}#controlKit .panel .arrow-s-max{background:url(data:image/png;base64,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) center no-repeat}#controlKit .panel .arrow-s-min{background:url(data:image/png;base64,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) center no-repeat}#controlKit .panel .arrow-s-max,#controlKit .panel .arrow-s-min{width:100%;height:20px}#controlKit .panel .arrow-b-max{background:url(data:image/png;base64,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) center no-repeat}#controlKit .panel .arrow-b-min{background:url(data:image/png;base64,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) center no-repeat}#controlKit .panel .arrow-b-sub-max{background:url(data:image/png;base64,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) center no-repeat}#controlKit .panel .arrow-b-sub-min{background:url(data:image/png;base64,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) center no-repeat}#controlKit .panel .arrow-b-max,#controlKit .panel .arrow-b-min,#controlKit .panel .arrow-b-sub-max,#controlKit .panel .arrow-b-sub-min{width:10px;height:100%;float:right}#controlKit .picker{pointer-events:auto;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:3px;-moz-border-radius:3px;background-color:#3b3b3b;font-family:Arial,sans-serif;font-size:11px;color:#fff;text-shadow:1px 1px #000;overflow:hidden;position:absolute;z-index:2147483631;width:360px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;box-shadow:0 2px 2px rgba(0,0,0,.25)}#controlKit .picker canvas{vertical-align:bottom;cursor:pointer}#controlKit .picker .wrap{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:10px;float:left}#controlKit .picker .field-wrap{padding:3px}#controlKit .picker .slider-wrap{padding:3px 13px 3px 3px}#controlKit .picker .field-wrap,#controlKit .picker .input-wrap,#controlKit .picker .slider-wrap{height:auto;overflow:hidden;float:left}#controlKit .picker .input-wrap{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border:1px solid #242424;border-radius:2px;-moz-border-radius:2px;width:140px;float:right;padding:5px 10px 1px 0}#controlKit .picker .input-field{width:50%;float:right;margin-bottom:4px}#controlKit .picker .input-field .label{padding:8px 0 0;color:#878787;text-align:center;text-transform:uppercase;font-weight:700;text-shadow:1px 1px #1a1a1a;width:40%}#controlKit .picker .input-field .wrap{padding:0;width:60%;height:auto;float:right}#controlKit .picker .controls-wrap{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;width:100%;height:auto;float:right;padding:9px 0 0}#controlKit .picker .controls-wrap input[type=button]{float:right;width:65px;margin:0 0 0 10px}#controlKit .picker .color-contrast{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;border:none;box-shadow:0 0 0 1px #1f1f1f inset;border-radius:2px;-moz-border-radius:2px;height:25px;padding:3px;width:80%;margin-bottom:4px;float:right}#controlKit .picker .color-contrast div{width:50%;height:100%;float:left}#controlKit .picker input[type=text]{padding:0;text-align:center;width:60%;float:right}#controlKit .picker .wrap .input-wrap:nth-of-type(3){border-bottom-left-radius:0;border-bottom-right-radius:0}#controlKit .picker .wrap .input-wrap:nth-of-type(4){border-top:none;border-top-left-radius:0;border-top-right-radius:0}#controlKit .picker .wrap .input-wrap:nth-of-type(4) .input-field{width:100%}#controlKit .picker .wrap .input-wrap:nth-of-type(4) .input-field .label{width:20%}#controlKit .picker .wrap .input-wrap:nth-of-type(4) input[type=text]{width:80%}#controlKit .picker .field-wrap,#controlKit .picker .slider-wrap{background:#1e2224;border:none;box-shadow:0 0 0 1px #1f1f1f inset;border-radius:2px;-moz-border-radius:2px;position:relative;margin-right:5px}#controlKit .picker .field-wrap .indicator,#controlKit .picker .slider-wrap .indicator{position:absolute;border:2px solid #fff;box-shadow:0 1px black,0 1px #000 inset;cursor:pointer}#controlKit .picker .field-wrap .indicator{width:8px;height:8px;left:50%;top:50%;border-radius:50%;-moz-border-radius:50%}#controlKit .picker .slider-wrap .indicator{width:14px;height:3px;border-radius:8px;-moz-border-radius:8px;left:1px;top:1px}#controlKit .picker .slider-wrap .indicator:after{content:'';width:0;height:0;border-top:4.5px solid transparent;border-bottom:4.5px solid transparent;border-right:4px solid #fff;float:right;position:absolute;top:-2px;left:19px}#controlKit .picker .slider-wrap .indicator:before{content:'';width:0;height:0;border-top:4.5px solid transparent;border-bottom:4.5px solid transparent;border-right:4px solid #000;float:right;position:absolute;top:-3px;left:19px}" -}; -module.exports = Style; -},{}],48:[function(require,module,exports){ -function Event_(sender,type,data) { - this.sender = sender; - this.type = type; - this.data = data; -} -module.exports = Event_; -},{}],49:[function(require,module,exports){ -function EventDispatcher() { - this._listeners = []; -}; - -EventDispatcher.prototype = { - addEventListener: function (eventType, listener, callbackMethod) { - this._listeners[eventType] = this._listeners[eventType] || []; - this._listeners[eventType].push({obj: listener, method: callbackMethod}); - }, - - dispatchEvent: function (event) { - var type = event.type; - - if (!this.hasEventListener(type)){ - return; - } - - var listeners = this._listeners[type]; - var i = -1, l = listeners.length; - - var obj, method; - - while (++i < l) { - obj = listeners[i].obj; - method = listeners[i].method; - - if (!obj[method]){ - throw obj + ' has no method ' + method; - } - - obj[method](event); - } - }, - - removeEventListener: function (type, obj, method) { - if (!this.hasEventListener(type)){ - return; - } - - var listeners = this._listeners[type]; - - var i = listeners.length; - while (--i > -1) { - if (listeners[i].obj == obj && listeners[i].method == method) { - listeners.splice(i, 1); - if (listeners.length == 0){ - delete this._listeners[type]; - } - break; - } - } - }, - - removeAllEventListeners: function () { - this._listeners = []; - }, - - hasEventListener: function (type) { - return this._listeners[type] != undefined && this._listeners[type] != null; - } -}; - -module.exports = EventDispatcher; -},{}],50:[function(require,module,exports){ -var LayoutMode = { - LEFT : 'left', - RIGHT : 'right', - TOP : 'top', - BOTTOM : 'bottom', - NONE : 'none' -}; - -module.exports = LayoutMode; -},{}],51:[function(require,module,exports){ -var Node = require('../document/Node'); -var Metric = require('../../component/Metric'); -var CSS = require('../document/CSS'); -var DocumentEvent = require('../document/DocumentEvent'), - NodeEvent = require('../document/NodeEvent'); -var Mouse = require('../document/Mouse'); - -function ScrollBar(parentNode,targetNode,wrapHeight) { - this._parentNode = parentNode; - this._targetNode = targetNode; - this._wrapHeight = wrapHeight; - - var wrap = this._wrapNode = new Node().setStyleClass(CSS.ScrollWrap), - node = this._node = new Node().setStyleClass(CSS.ScrollBar), - track = this._trackNode = new Node().setStyleClass(CSS.ScrollBarTrack), - thumb = this._thumbNode = new Node().setStyleClass(CSS.ScrollBarThumb); - - parentNode.removeChild(targetNode); - parentNode.addChild(wrap); - parentNode.addChildAt(node,0); - - wrap.addChild(targetNode); - node.addChild(track); - track.addChild(thumb); - - this._mouseThumbOffset = 0; - this._scrollHeight = 0; - this._scrollUnit = 0; - this._scrollMin = 0; - this._scrollMax = 0; - - thumb.setPositionY(Metric.SCROLLBAR_TRACK_PADDING); - thumb.addEventListener(DocumentEvent.MOUSE_DOWN,this._onThumbDragStart.bind(this)); - - this._isValid = false; - this._enabled = false; - - var nodeElement = node.getElement(), - thumbElement = thumb.getElement(); - var self = this; - this._onMouseWheel = function(e){ - var sender = e.sender, - hoverElement = sender.getHoverElement(); - if(hoverElement != nodeElement && hoverElement != thumbElement){ - return; - } - var scrollStep = self._scrollHeight * 0.0125; - self._scroll(thumb.getPositionY() + sender.getWheelDirection() * scrollStep * -1); - e.data.preventDefault(); - }; - - this.addMouseListener(); -} - -ScrollBar.prototype.update = function(){ - var target = this._targetNode, - thumb = this._thumbNode; - - var padding = Metric.SCROLLBAR_TRACK_PADDING; - - var targetWrapHeight = this._wrapHeight, - targetHeight = target.getHeight(), - trackHeight = targetWrapHeight - padding * 2; - - thumb.setHeight(trackHeight); - - var ratio = targetWrapHeight / targetHeight; - - this._isValid = false; - - if (ratio > 1.0){ - return; - } - var thumbHeight = trackHeight * ratio; - - this._scrollHeight = trackHeight; - this._scrollUnit = targetHeight - this._scrollHeight - padding * 2; - this._scrollMin = padding; - this._scrollMax = padding + trackHeight - thumbHeight; - - thumb.setHeight(thumbHeight); - - this._isValid = true; -}; - -ScrollBar.prototype._scroll = function(y){ - var min = this._scrollMin, - max = this._scrollMax, - pos = Math.max(min, Math.min(y,max)), - pos_ = (pos-min)/(max-min); - - this._thumbNode.setPositionY(pos); - this._targetNode.setPositionY(pos_ * this._scrollUnit * -1); -}; - - -ScrollBar.prototype._onThumbDragStart = function () { - if (!this._isValid || this._enabled){ - return; - } - var eventMove = DocumentEvent.MOUSE_MOVE, - eventUp = DocumentEvent.MOUSE_UP; - - var mouse = Mouse.get(); - var trackOffset = this._trackNode.getPositionGlobalY(); - - this._mouseThumbOffset = mouse.getY() - this._thumbNode.getPositionGlobalY(); - - var self = this; - var onDrag = function () { - self._scroll(mouse.getY() - trackOffset - self._mouseThumbOffset); - }, - onDragEnd = function () { - document.removeEventListener(eventMove, onDrag, false); - document.removeEventListener(eventUp, onDragEnd, false); - }; - - document.addEventListener(eventMove, onDrag, false); - document.addEventListener(eventUp, onDragEnd, false); - this._scroll(mouse.getY() - trackOffset - self._mouseThumbOffset); -}; - - -ScrollBar.prototype.enable = function () { - this._enabled = false; - this._updateAppearance(); -}; - -ScrollBar.prototype.disable = function () { - this._enabled = true; - this._updateAppearance(); -}; -ScrollBar.prototype.reset = function () { - this._scroll(0); -}; - -ScrollBar.prototype._updateAppearance = function () { - if (this._enabled) { - this._node.setStyleProperty('display', 'none'); - this._targetNode.setPositionY(0); - this._thumbNode.setPositionY(Metric.SCROLLBAR_TRACK_PADDING); - } else { - this._node.setStyleProperty('display', 'block'); - } -}; - -ScrollBar.prototype.isValid = function () { - return this._isValid; -}; - -ScrollBar.prototype.setWrapHeight = function (height) { - this._wrapHeight = height; - this.update(); -}; - -ScrollBar.prototype.removeTargetNode = function () { - return this._wrapNode.removeChild(this._targetNode); -}; - -ScrollBar.prototype.removeMouseListener = function(){ - Mouse.get().removeEventListener(DocumentEvent.MOUSE_WHEEL,this,'_onMouseWheel'); -}; - -ScrollBar.prototype.addMouseListener = function(){ - Mouse.get().addEventListener(DocumentEvent.MOUSE_WHEEL,this,'_onMouseWheel'); -}; - -ScrollBar.prototype.removeFromParent = function () { - var parentNode = this._parentNode, - rootNode = this._node, - targetNode = this._targetNode; - - rootNode.removeChild(targetNode); - parentNode.removeChild(this._wrapNode); - parentNode.removeChild(rootNode); - - return targetNode; -}; - -ScrollBar.prototype.getWrapNode = function () { - return this._wrapNode; -}; - -ScrollBar.prototype.getNode = function () { - return this._node; -}; - -ScrollBar.prototype.getTargetNode = function () { - return this._targetNode; -}; - - -module.exports = ScrollBar; -},{"../../component/Metric":12,"../document/CSS":42,"../document/DocumentEvent":43,"../document/Mouse":44,"../document/Node":45,"../document/NodeEvent":46}],52:[function(require,module,exports){ -var EventDispatcher = require('../core/event/EventDispatcher'); -var Node = require('../core/document/Node'); -var ScrollBar = require('../core/layout/ScrollBar'); - -function AbstractGroup(parent, params) { - EventDispatcher.apply(this, arguments); - - params = params || {}; - params.height = params.height || null; - params.enable = params.enable === undefined ? true : params.enable; - - this._parent = parent; - this._height = params.height; - this._enabled = params.enable; - this._scrollBar = null; - - this._node = new Node(Node.LIST_ITEM); - this._wrapNode = new Node(); - this._listNode = new Node(Node.LIST); - - this._parent.getList().addChild(this._node); -} -AbstractGroup.prototype = Object.create(EventDispatcher.prototype); -AbstractGroup.prototype.constructor = AbstractGroup; - -AbstractGroup.prototype.addScrollWrap = function () { - var wrapNode = this._wrapNode, - maxHeight = this.getMaxHeight(); - - this._scrollBar = new ScrollBar(wrapNode, this._listNode, maxHeight); - if (this.isEnabled()) { - wrapNode.setHeight(maxHeight); - } -}; - -AbstractGroup.prototype.preventSelectDrag = function () { - this._parent.preventSelectDrag(); - - if (!this.hasScrollWrap()) { - return; - } - this._wrapNode.getElement().scrollTop = 0; -}; - -AbstractGroup.prototype.hasMaxHeight = function () { - return this._height != null; -}; - -AbstractGroup.prototype.getMaxHeight = function () { - return this._height; -}; - -AbstractGroup.prototype.hasScrollWrap = function () { - return this._scrollBar != null; -}; - -AbstractGroup.prototype.hasLabel = function () { - return this._lablNode != null; -}; - -AbstractGroup.prototype.disable = function () { - this._enabled = false; - this._updateAppearance(); -}; - -AbstractGroup.prototype.enable = function () { - this._enabled = true; - this._updateAppearance(); -}; - -AbstractGroup.prototype.isDisabled = function () { - return !this._enabled; -}; - -AbstractGroup.prototype.isEnabled = function () { - return this._enabled; -}; - -AbstractGroup.prototype.getList = function () { - return this._listNode; -}; - -module.exports = AbstractGroup; - - -},{"../core/document/Node":45,"../core/event/EventDispatcher":49,"../core/layout/ScrollBar":51}],53:[function(require,module,exports){ -var AbstractGroup = require('./AbstractGroup'); -var CSS = require('../core/document/CSS'); -var Node = require('../core/document/Node'); - -var SubGroup = require('./SubGroup'); - -var Event_ = require('../core/event/Event'), - DocumentEvent = require('../core/document/DocumentEvent'), - NodeEvent = require('../core/document/NodeEvent'), - PanelEvent = require('./PanelEvent'), - GroupEvent = require('./GroupEvent'); - -var ObjectComponent = require('../core/ObjectComponent'), - ValuePlotter = require('../component/ValuePlotter'), - FunctionPlotter = require('../component/FunctionPlotter'); - -function Group(parent,params) { - params = params || {}; - params.label = params.label || null; - params.useLabels = params.useLabels || true; - params.enable = params.enable === undefined ? true : params.enable; - - AbstractGroup.apply(this,arguments); - - this._components = []; - this._subGroups = []; - - var root = this._node, - wrap = this._wrapNode, - list = this._listNode; - - root.setStyleClass(CSS.Group); - wrap.setStyleClass(CSS.Wrap); - list.setStyleClass(CSS.SubGroupList); - - wrap.addChild(list); - - var label = params.label; - - if(label){ - var head = new Node(), - wrap_ = new Node(), - label_ = new Node(Node.SPAN), - indicator = this._indiNode = new Node(); - - head.setStyleClass(CSS.Head); - wrap_.setStyleClass(CSS.Wrap); - label_.setStyleClass(CSS.Label); - indicator.setStyleClass(CSS.ArrowBMax); - label_.setProperty('innerHTML',label); - - head.addChild(indicator); - wrap_.addChild(label_); - head.addChild(wrap_); - root.addChild(head); - - head.addEventListener(NodeEvent.MOUSE_DOWN,this._onHeadTrigger.bind(this)); - this.addEventListener(GroupEvent.GROUP_LIST_SIZE_CHANGE,parent,'onGroupListSizeChange'); - - this._updateAppearance(); - } - - if(this.hasMaxHeight()){ - this.addScrollWrap(); - } - - root.addChild(wrap); - - if(this.hasMaxHeight()){ - if(!label){ - var bufferTop = this._scrollBufferTop = new Node(); - bufferTop.setStyleClass(CSS.ScrollBuffer); - - root.addChildAt(bufferTop,0); - } - var bufferBottom = this._scrollBufferBottom = new Node(); - bufferBottom.setStyleClass(CSS.ScrollBuffer); - - root.addChild(bufferBottom); - } - - parent = this._parent; - - parent.addEventListener(PanelEvent.PANEL_MOVE_BEGIN, this, 'onPanelMoveBegin'); - parent.addEventListener(PanelEvent.PANEL_MOVE, this, 'onPanelMove'); - parent.addEventListener(PanelEvent.PANEL_MOVE_END, this, 'onPanelMoveEnd'); - parent.addEventListener(PanelEvent.PANEL_HIDE, this, 'onPanelHide'); - parent.addEventListener(PanelEvent.PANEL_SHOW, this, 'onPanelShow'); - parent.addEventListener(PanelEvent.PANEL_SCROLL_WRAP_ADDED, this, 'onPanelScrollWrapAdded'); - parent.addEventListener(PanelEvent.PANEL_SCROLL_WRAP_REMOVED, this, 'onPanelScrollWrapRemoved'); - parent.addEventListener(PanelEvent.PANEL_SIZE_CHANGE, this, 'onPanelSizeChange'); - parent.addEventListener(DocumentEvent.WINDOW_RESIZE, this, 'onWindowResize'); - - this.addEventListener(GroupEvent.GROUP_SIZE_CHANGE,parent,'onGroupListSizeChange'); -} -Group.prototype = Object.create(AbstractGroup.prototype); -Group.prototype.constructor = Group; - -Group.prototype.onPanelMoveBegin = function () { - this.dispatchEvent(new Event_(this, PanelEvent.PANEL_MOVE_BEGIN, null)); -}; - -Group.prototype.onPanelMove = function () { - this.dispatchEvent(new Event_(this, PanelEvent.PANEL_MOVE, null)); -}; - -Group.prototype.onPanelMoveEnd = function () { - this.dispatchEvent(new Event_(this, PanelEvent.PANEL_MOVE_END, null)); -}; - -Group.prototype.onPanelScrollWrapAdded = function () { - this.dispatchEvent(new Event_(this, GroupEvent.GROUP_SIZE_CHANGE, null)); -}; - -Group.prototype.onPanelScrollWrapRemoved = function () { - this.dispatchEvent(new Event_(this, GroupEvent.GROUP_SIZE_CHANGE, null)); -}; - -Group.prototype.onPanelHide = function () { - this.dispatchEvent(new Event_(this, GroupEvent.SUBGROUP_DISABLE, null)); -}; - -Group.prototype.onPanelShow = function () { - this.dispatchEvent(new Event_(this, GroupEvent.SUBGROUP_ENABLE, null)); -}; - -Group.prototype.onPanelSizeChange = function () { - this.dispatchEvent(new Event_(this, GroupEvent.GROUP_SIZE_CHANGE, null)); -}; - -Group.prototype.onWindowResize = function (e) { - this.dispatchEvent(e); -}; - -Group.prototype.onSubGroupTrigger = function () { - this._updateHeight(); - - if(!this.hasMaxHeight()){ - return; - } - var scrollBar = this._scrollBar, - wrap = this._wrapNode; - var bufferTop = this._scrollBufferTop, - bufferBottom = this._scrollBufferBottom; - - scrollBar.update(); - - if (!scrollBar.isValid()) { - scrollBar.disable(); - wrap.setHeight(wrap.getChildAt(1).getHeight()); - if (bufferTop){ - bufferTop.setStyleProperty('display', 'none'); - } - if (bufferBottom){ - bufferBottom.setStyleProperty('display', 'none'); - } - } - else { - scrollBar.enable(); - wrap.setHeight(this.getMaxHeight()); - - if (bufferTop){ - bufferTop.setStyleProperty('display', 'block'); - } - if (bufferBottom){ - bufferBottom.setStyleProperty('display', 'block'); - } - } - this.dispatchEvent(new Event_(this,GroupEvent.GROUP_SIZE_CHANGE,null)); -}; - -Group.prototype._onHeadTrigger = function () { - this._enabled = !this._enabled; - this._updateAppearance(); - this.dispatchEvent(new Event_(this, GroupEvent.GROUP_LIST_SIZE_CHANGE, null)); -}; - -Group.prototype.addComponent = function(){ - var Class_ = arguments[0]; - var args = Array.prototype.slice.call(arguments); - args.shift(); - args.unshift(this._getSubGroup()); - - var instance = Object.create(Class_.prototype); - Class_.apply(instance,args); - - this._components.push(instance); - this._updateHeight(); -}; - -Group.prototype._updateHeight = function () { - this._getSubGroup().update(); - this.dispatchEvent(new Event_(this,GroupEvent.GROUP_SIZE_CHANGE,null)); - if(this.hasMaxHeight()){ - this._scrollBar.update(); - } -}; - -Group.prototype._updateAppearance = function () { - var wrap = this._wrapNode, - indicator = this._indiNode; - - var scrollBar = this._scrollBar; - - var bufferTop = this._scrollBufferTop, - bufferBottom = this._scrollBufferBottom; - - if (this.isDisabled()) { - wrap.setHeight(0); - if (indicator){ - indicator.setStyleClass(CSS.ArrowBMin); - } - - if (scrollBar) { - if (bufferTop){ - bufferTop.setStyleProperty('display', 'none'); - } - if (bufferBottom){ - bufferBottom.setStyleProperty('display', 'none'); - } - } - return; - } - - if (this.hasMaxHeight()) { - var maxHeight = this.getMaxHeight(), - listHeight = wrap.getChildAt(1).getHeight(); - - wrap.setHeight(listHeight < maxHeight ? listHeight : maxHeight); - - if (scrollBar.isValid()) { - if (bufferTop){ - bufferTop.setStyleProperty('display', 'block'); - } - if (bufferBottom){ - bufferBottom.setStyleProperty('display', 'block'); - } - } - } - else { - wrap.deleteStyleProperty('height'); - } - if (indicator){ - indicator.setStyleClass(CSS.ArrowBMax); - } -}; - -Group.prototype.onGroupSizeUpdate = function () { - this._updateAppearance(); - if (this.hasMaxHeight()){ - this._scrollBar.update(); - } -}; - -Group.prototype.addSubGroup = function (params) { - this._subGroups.push(new SubGroup(this, params)); - this._updateHeight(); - return this; -}; - -Group.prototype._getSubGroup = function () { - var subGroups = this._subGroups; - if (subGroups.length == 0){ - subGroups.push(new SubGroup(this)); - } - return subGroups[subGroups.length - 1]; -}; - -Group.prototype.getComponents = function () { - return this._components; -}; - -function isDataComp(comp){ - return (comp instanceof ObjectComponent) && - !(comp instanceof ValuePlotter) && - !(comp instanceof FunctionPlotter); -} - - -Group.prototype.setData = function(data){ - var comps = this._components, comp, data_; - var i = -1, j = 0, l = comps.length; - while(++i < l){ - comp = comps[i]; - if(!isDataComp(comp)){ - continue; - } - data_ = data[j++]; - comp.setValue(data_[Object.keys(data_)[0]]); - } -}; - -Group.prototype.getData = function(){ - var comps = this._components, - i = -1, l = comps.length; - var values = []; - var comp; - while(++i < l){ - comp = comps[i]; - if(!isDataComp(comp)){ - continue; - } - values.push(comp.getData()); - } - return values; -}; - -module.exports = Group; - -},{"../component/FunctionPlotter":9,"../component/ValuePlotter":29,"../core/ObjectComponent":35,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48,"./AbstractGroup":52,"./GroupEvent":54,"./PanelEvent":57,"./SubGroup":58}],54:[function(require,module,exports){ -var GroupEvent = { - GROUP_SIZE_CHANGE : 'groupSizeChange', - GROUP_LIST_SIZE_CHANGE : 'groupListSizeChange', - GROUP_SIZE_UPDATE : 'groupSizeUpdate', - SUBGROUP_TRIGGER : 'subGroupTrigger', - - SUBGROUP_ENABLE : 'enableSubGroup', - SUBGROUP_DISABLE : 'disableSubGroup' -}; - -module.exports = GroupEvent; -},{}],55:[function(require,module,exports){ -var MenuEvent = { - UPDATE_MENU: 'updateMenu' -}; -module.exports = MenuEvent; -},{}],56:[function(require,module,exports){ -var Node = require('../core/document/Node'), - Group = require('./Group'), - ScrollBar = require('../core/layout/ScrollBar'); - -var CSS = require('../core/document/CSS'); -var LayoutMode = require('../core/layout/LayoutMode'); -var History = require('../core/History'); - -var EventDispatcher = require('../core/event/EventDispatcher'), - Event_ = require('../core/event/Event'), - DocumentEvent = require('../core/document/DocumentEvent'), - NodeEvent = require('../core/document/NodeEvent'), - PanelEvent = require('./PanelEvent'), - MenuEvent = require('./MenuEvent'); - -var Mouse = require('../core/document/Mouse'); - -var StringInput = require('../component/StringInput'), - NumberInput = require('../component/NumberInput'), - Range = require('../component/Range'), - Checkbox = require('../component/Checkbox'), - Color = require('../component/Color'), - Button = require('../component/Button'), - Select = require('../component/Select'), - Slider = require('../component/Slider'), - FunctionPlotter = require('../component/FunctionPlotter'), - Pad = require('../component/Pad'), - ValuePlotter = require('../component/ValuePlotter'), - NumberOutput = require('../component/NumberOutput'), - StringOutput = require('../component/StringOutput'), - Canvas_ = require('../component/Canvas'), - SVG_ = require('../component/SVG'); - -var DEFAULT_PANEL_POSITION = null, - DEFAULT_PANEL_WIDTH = 200, - DEFAULT_PANEL_HEIGHT = null, - DEFAULT_PANEL_WIDTH_MIN = 100, - DEFAULT_PANEL_WIDTH_MAX = 600, - DEFAULT_PANEL_RATIO = 40, - DEFAULT_PANEL_LABEL = 'Control Panel', - DEFAULT_PANEL_VALIGN = LayoutMode.TOP, - DEFAULT_PANEL_ALIGN = LayoutMode.RIGHT, - DEFAULT_PANEL_DOCK = {align:LayoutMode.RIGHT,resizable:true}, - DEFAULT_PANEL_ENABLE = true, - DEFAULT_PANEL_OPACITY = 1.0, - DEFAULT_PANEL_FIXED = true, - DEFAULT_PANEL_VCONSTRAIN = true; - -function Panel(controlKit,params){ - EventDispatcher.apply(this,arguments); - this._parent = controlKit; - - - params = params || {}; - params.valign = params.valign || DEFAULT_PANEL_VALIGN; - params.align = params.align || DEFAULT_PANEL_ALIGN; - params.position = params.position || DEFAULT_PANEL_POSITION; - params.width = params.width || DEFAULT_PANEL_WIDTH; - params.height = params.height || DEFAULT_PANEL_HEIGHT; - params.ratio = params.ratio || DEFAULT_PANEL_RATIO; - params.label = params.label || DEFAULT_PANEL_LABEL; - params.opacity = params.opacity || DEFAULT_PANEL_OPACITY; - params.fixed = params.fixed === undefined ? DEFAULT_PANEL_FIXED : params.fixed; - params.enable = params.enable === undefined ? DEFAULT_PANEL_ENABLE : params.enable; - params.vconstrain = params.vconstrain === undefined ? DEFAULT_PANEL_VCONSTRAIN : params.vconstrain; - - if (params.dock) { - params.dock.align = params.dock.align || DEFAULT_PANEL_DOCK.align; - params.dock.resizable = params.dock.resizable || DEFAULT_PANEL_DOCK.resizable; - } - - this._width = Math.max(DEFAULT_PANEL_WIDTH_MIN, - Math.min(params.width,DEFAULT_PANEL_WIDTH_MAX)); - this._height = params.height ? Math.max(0,Math.min(params.height,window.innerHeight)) : null; - this._fixed = params.fixed; - this._dock = params.dock; - this._position = params.position; - this._vConstrain = params.vconstrain; - this._label = params.label; - this._enabled = params.enable; - this._groups = []; - - - var width = this._width, - isFixed = this._fixed, - dock = this._dock, - position = this._position, - label = this._label, - align = params.align, - opacity = params.opacity; - - - var root = this._node = new Node().setStyleClass(CSS.Panel), - head = this._headNode = new Node().setStyleClass(CSS.Head), - menu = new Node().setStyleClass(CSS.Menu), - labelWrap = new Node().setStyleClass(CSS.Wrap), - label_ = new Node(Node.SPAN).setStyleClass(CSS.Label), - wrap = this._wrapNode = new Node(Node.DIV).setStyleClass(CSS.Wrap), - list = this._listNode = new Node(Node.LIST).setStyleClass(CSS.GroupList); - - root.setWidth(width); - label_.setProperty('innerHTML', label); - - labelWrap.addChild(label_); - head.addChild(menu); - head.addChild(labelWrap); - wrap.addChild(list); - root.addChild(head); - root.addChild(wrap); - - controlKit.getNode().addChild(root); - - - if (!dock) { - var menuHide = this._menuHide = new Node(Node.INPUT_BUTTON); - menuHide.setStyleClass(CSS.ButtonMenuHide); - menuHide.addEventListener(NodeEvent.MOUSE_DOWN, this._onMenuHideMouseDown.bind(this)); - - menu.addChild(menuHide); - - if (this._parent.panelsAreClosable()) { - var menuClose = new Node(Node.INPUT_BUTTON); - menuClose.setStyleClass(CSS.ButtonMenuClose); - menuClose.addEventListener(NodeEvent.MOUSE_DOWN, this.disable.bind(this)); - - menu.addChild(menuClose); - } - - - if (this.hasMaxHeight()) { - this._addScrollWrap(); - } - - if (!isFixed) { - if (position) { - if (align == LayoutMode.LEFT || - align == LayoutMode.TOP || - align == LayoutMode.BOTTOM) { - root.setPositionGlobal(position[0], position[1]); - } - else { - root.setPositionGlobal(window.innerWidth - width - position[0], position[1]); - this._position = root.getPosition(); - } - } - else this._position = root.getPosition(); - - this._mouseOffset = [0, 0]; - - root.setStyleProperty('position', 'absolute'); - head.addEventListener(NodeEvent.MOUSE_DOWN, this._onHeadDragStart.bind(this)); - } - else { - if (position) { - var positionX = position[0], - positionY = position[1]; - - if (positionY != 0)root.setPositionY(positionY); - if (positionX != 0)if (align == LayoutMode.RIGHT)root.getElement().marginRight = positionX; - else root.setPositionX(positionX); - } - - root.setStyleProperty('float', align); - } - } - else { - var dockAlignment = dock.align; - - if (dockAlignment == LayoutMode.LEFT || - dockAlignment == LayoutMode.RIGHT) { - align = dockAlignment; - this._height = window.innerHeight; - } - - if (dockAlignment == LayoutMode.TOP || - dockAlignment == LayoutMode.BOTTOM) { - - } - - /* - if(dock.resizable) - { - var sizeHandle = new ControlKit.Node(ControlKit.NodeType.DIV); - sizeHandle.setStyleClass(ControlKit.CSS.SizeHandle); - rootNode.addChild(sizeHandle); - } - */ - - root.setStyleProperty('float', align); - } - - var parent = this._parent; - var historyIsEnabled = parent.historyIsEnabled(), - statesAreEnabled = parent.statesAreEnabled(); - - if(historyIsEnabled || statesAreEnabled){ - menu.addChildAt(new Node(),0).setStyleClass(CSS.Wrap);//.setStyleProperty('display','none'); - } - - if (historyIsEnabled) { - this._menuUndo = menu.getChildAt(0) - .addChild(new Node(Node.INPUT_BUTTON)) - .setStyleClass(CSS.ButtonMenuUndo) - .setProperty('value',History.get().getNumStates()) - .addEventListener(NodeEvent.MOUSE_DOWN,function(){ - History.get().popState(); - }); - parent.addEventListener(MenuEvent.UPDATE_MENU,this, 'onUpdateMenu'); - } - if(statesAreEnabled){ - menu.getChildAt(0) - .addChild(new Node(Node.INPUT_BUTTON)) - .setStyleClass(CSS.ButtonMenuLoad) - .setProperty('value','Load') - .addEventListener(NodeEvent.MOUSE_DOWN,function(){ - controlKit._loadState(); - }); - menu.getChildAt(0) - .addChild(new Node(Node.INPUT_BUTTON)) - .setStyleClass(CSS.ButtonMenuSave) - .setProperty('value','Save') - .addEventListener(NodeEvent.MOUSE_DOWN,function(){ - controlKit._saveState(); - }); - } - if(historyIsEnabled || statesAreEnabled){ - head.addEventListener(NodeEvent.MOUSE_OVER,function(){ - menu.setStyleClass(CSS.MenuActive); - }); - head.addEventListener(NodeEvent.MOUSE_OUT,function(){ - menu.setStyleClass(CSS.Menu); - }); - } - if (opacity != 1.0 && opacity != 0.0) { - root.setStyleProperty('opacity', opacity); - } - window.addEventListener(DocumentEvent.WINDOW_RESIZE,this._onWindowResize.bind(this)); - this._updateAppearance(); -} -Panel.prototype = Object.create(EventDispatcher.prototype); -Panel.prototype.constructor = Panel; - -Panel.prototype._onMenuHideMouseDown = function () { - this._enabled = !this._enabled; - this._updateAppearance(); -}; - -Panel.prototype.onUpdateMenu = function () { - this._menuUndo.setProperty('value', History.get().getNumStates()); -}; - -Panel.prototype._onMenuUndoTrigger = function () { - History.get().popState(); -}; - - -Panel.prototype._updateAppearance = function () { - var rootNode = this._node, - headNode = this._headNode, - menuHide = this._menuHide; - - if (!this._enabled) { - headNode.getStyle().borderBottom = 'none'; - rootNode.setHeight(headNode.getHeight()); - menuHide.setStyleClass(CSS.ButtonMenuShow); - this.dispatchEvent(new Event_(this, PanelEvent.PANEL_HIDE, null)); - } - else { - rootNode.setHeight(headNode.getHeight() + this._wrapNode.getHeight()); - rootNode.deleteStyleProperty('height'); - menuHide.setStyleClass(CSS.ButtonMenuHide); - headNode.setStyleClass(CSS.Head); - this.dispatchEvent(new Event_(this, PanelEvent.PANEL_SHOW, null)); - } -}; - -Panel.prototype._onHeadDragStart = function(){ - var parentNode = this._parent.getNode(), - node = this._node; - - var nodePos = node.getPositionGlobal(), - mousePos = Mouse.get().getPosition(), - offsetPos = this._mouseOffset; - - offsetPos[0] = mousePos[0] - nodePos[0]; - offsetPos[1] = mousePos[1] - nodePos[1]; - - var eventMouseMove = DocumentEvent.MOUSE_MOVE, - eventMouseUp = DocumentEvent.MOUSE_UP; - - var self = this; - - var onDrag = function () { - self._updatePosition(); - }, - onDragEnd = function () { - document.removeEventListener(eventMouseMove, onDrag, false); - document.removeEventListener(eventMouseUp, onDragEnd, false); - self.dispatchEvent(new Event_(this, PanelEvent.PANEL_MOVE_END, null)); - }; - - parentNode.removeChild(node); - parentNode.addChild( node); - - document.addEventListener(eventMouseMove, onDrag, false); - document.addEventListener(eventMouseUp, onDragEnd, false); - - this.dispatchEvent(new Event_(this,PanelEvent.PANEL_MOVE_BEGIN,null)); -}; - -Panel.prototype._updatePosition = function () { - var mousePos = Mouse.get().getPosition(), - offsetPos = this._mouseOffset; - - var position = this._position; - position[0] = mousePos[0] - offsetPos[0]; - position[1] = mousePos[1] - offsetPos[1]; - - this._constrainHeight(); - this._constrainPosition(); - - this.dispatchEvent(new Event_(this, PanelEvent.PANEL_MOVE, null)); -}; - -Panel.prototype._onWindowResize = function () { - if (this.isDocked()) { - var dock = this._dock; - - if (dock.align == LayoutMode.RIGHT || - dock.align == LayoutMode.LEFT) { - var windowHeight = window.innerHeight, - listHeight = this._listNode.getHeight(), - headHeight = this._headNode.getHeight(); - - this._height = windowHeight; - - if ((windowHeight - headHeight) > listHeight){ - this._scrollBar.disable(); - } - else{ - this._scrollBar.enable(); - } - - this.dispatchEvent(new Event_(this, PanelEvent.PANEL_SIZE_CHANGE)); - } - } - else { - if (!this.isFixed()){ - this._constrainPosition(); - } - } - this._constrainHeight(); - this.dispatchEvent(new Event_(this, DocumentEvent.WINDOW_RESIZE)); -}; - -Panel.prototype._constrainPosition = function () { - var node = this._node; - - var maxX = window.innerWidth - node.getWidth(), - maxY = window.innerHeight - node.getHeight(); - - var position = this._position; - position[0] = Math.max(0, Math.min(position[0], maxX)); - position[1] = Math.max(0, Math.min(position[1], maxY)); - - node.setPositionGlobal(position[0], position[1]); -}; - -Panel.prototype._constrainHeight = function () { - if (!this._vConstrain)return; - - var hasMaxHeight = this.hasMaxHeight(), - hasScrollWrap = this.hasScrollWrap(); - - var head = this._headNode, - wrap = this._wrapNode; - - var scrollBar = this._scrollBar; - - var panelTop = this.isDocked() ? 0 : - this.isFixed() ? 0 : - this._position[1]; - - var panelHeight = hasMaxHeight ? this.getMaxHeight() : - hasScrollWrap ? scrollBar.getTargetNode().getHeight() : - wrap.getHeight(); - - var panelBottom = panelTop + panelHeight; - var headHeight = head.getHeight(); - - var windowHeight = window.innerHeight, - heightDiff = windowHeight - panelBottom - headHeight, - heightSum; - - if (heightDiff < 0.0) { - heightSum = panelHeight + heightDiff; - - if (!hasScrollWrap) { - this._addScrollWrap(heightSum); - this.dispatchEvent(new Event_(this, PanelEvent.PANEL_SCROLL_WRAP_ADDED, null)); - return; - } - - scrollBar.setWrapHeight(heightSum); - wrap.setHeight(heightSum); - } - else { - if (!hasMaxHeight && hasScrollWrap) { - scrollBar.removeFromParent(); - wrap.addChild(this._listNode); - wrap.deleteStyleProperty('height'); - this._scrollBar.removeMouseListener(); - this._scrollBar = null; - - this.dispatchEvent(new Event_(this, PanelEvent.PANEL_SCROLL_WRAP_REMOVED, null)); - } - } -}; - -Panel.prototype.onGroupListSizeChange = function () { - if (this.hasScrollWrap()){ - this._updateScrollWrap(); - } - this._constrainHeight(); -}; - -Panel.prototype._updateScrollWrap = function () { - var wrap = this._wrapNode, - scrollBar = this._scrollBar, - height = this.hasMaxHeight() ? this.getMaxHeight() : 100, - listHeight = this._listNode.getHeight(); - - wrap.setHeight(listHeight < height ? listHeight : height); - - scrollBar.update(); - - if (!scrollBar.isValid()) { - scrollBar.disable(); - wrap.setHeight(wrap.getChildAt(1).getHeight()); - } - else { - scrollBar.enable(); - wrap.setHeight(height); - } -}; - -Panel.prototype._addScrollWrap = function () { - var wrapNode = this._wrapNode, - listNode = this._listNode, - height = arguments.length == 0 ? - this.getMaxHeight() : - arguments[0]; - - this._scrollBar = new ScrollBar(wrapNode, listNode, height); - if (this.isEnabled()){ - wrapNode.setHeight(height); - } -}; - -Panel.prototype.hasScrollWrap = function () { - return this._scrollBar != null; -}; - - -Panel.prototype.preventSelectDrag = function () { - if (!this.hasScrollWrap()){ - return; - } - this._wrapNode.getElement().scrollTop = 0; -}; - -Panel.prototype.enable = function () { - this._node.setStyleProperty('display', 'block'); - this._enabled = true; - this._updateAppearance(); -}; - - -Panel.prototype.disable = function () { - this._node.setStyleProperty('display', 'none'); - this._enabled = false; - this._updateAppearance(); -}; - -Panel.prototype.isEnabled = function () { - return this._enabled; -}; - -Panel.prototype.isDisabled = function () { - return !this._enabled; -}; - -Panel.prototype.hasMaxHeight = function () { - return this._height != null; -}; - -Panel.prototype.getMaxHeight = function () { - return this._height; -}; - -Panel.prototype.isDocked = function () { - return this._dock; -}; - -Panel.prototype.isFixed = function () { - return this._fixed; -}; - -Panel.prototype.getGroups = function () { - return this._groups; -}; - -Panel.prototype.getNode = function () { - return this._node; -}; - -Panel.prototype.getList = function () { - return this._listNode; -}; - -Panel.prototype.getWidth = function () { - return this._width; -}; - -Panel.prototype.getPosition = function () { - return this._position; -}; - -Panel.prototype.getParent = function(){ - return this._parent; -}; - -/** - * Adds a new Group to the Panel. - * @param {Object} [params] - Group options - * @param {String} [params.label=''] - The Group label string - * @param {Boolean} [params.useLabel=true] - Trigger whether all contained SubGroups and Components should use labels - * @param {Boolean} [params.enable=true] - Defines initial state open / closed - * @param {Number} [params.height=null] - Defines if the height of the Group should be constrained to certain height - * @returns {Panel} - */ - -Panel.prototype.addGroup = function (params) { - var group = new Group(this, params); - this._groups.push(group); - if (this.isDocked()){ - this.dispatchEvent(new Event_(this, PanelEvent.PANEL_SIZE_CHANGE)); - } - return this; -}; - -/** - * Adds a new SubGroup to the last added Group. - * @param {Object} [params] - SubGroup options - * @param {String} [params.label=''] - The SubGroup label string - * @param {Boolean} [params.useLabel=true] - Trigger whether all Components should use labels - * @param {Boolean} [params.enable=true] - Defines initial state open / closed - * @param {Number} [params.height=null] - Defines if the height of the SubGroup should be constrained to certain height - * @returns {Panel} - */ - -Panel.prototype.addSubGroup = function(params){ - var groups = this._groups; - if(groups.length == 0){ - this.addGroup(); - } - groups[groups.length - 1].addSubGroup(params); - return this; -}; - -Panel.prototype._addComponent = function(){ - var groups = this._groups, - group; - if(groups.length == 0){ - groups.push(new Group(this)); - } - group = groups[groups.length-1]; - - group.addComponent.apply(group,arguments); - return this; -}; - -/** - * Adds a new StringInput to last added SubGroup. - * @param {Object} object - The object - * @param {String} value - The property key - * @param {Object} [params] - StringInput options - * @param {String} [params.label=value] - StringInput label - * @param {Function} [params.onChange] - Callback on change - * @param {Array} [params.presets] - A set of presets - * @returns {Panel} - */ - -Panel.prototype.addStringInput = function (object, value, params) { - return this._addComponent(StringInput,object,value,params); -}; - -/** - * Adds a new NumberInput to last added SubGroup. - * @param {Object} object - The object. - * @param {String} value - The property key. - * @param {Object} [params] - Component options. - * @param {String} [params.label=value] - NumberInput label - * @param {Function} [params.onChange] - Callback on change - * @param {Number} [params.step] - Amount subbed/added on arrowDown/arrowUp press - * @param {Number} [params.dp] - Decimal places displayed - * @param {Array} [params.presets] - A set of presets - * @returns {Panel} - */ - -Panel.prototype.addNumberInput = function (object, value, params) { - return this._addComponent(NumberInput,object,value,params); -}; - -/** - * Adds a new Range input to last added SubGroup. - * @param {Object} object - The object - * @param {String} value - The property key - * @param {Object} [params] - Component options - * @param {String} [params.label=value] - Range label - * @param {Function} [params.onChange] - Callback on change - * @param {Number} [params.step] - Amount subbed/added on arrowDown/arrowUp press - * @param {Number} [params.dp] - Decimal places displayed - * @returns {Panel} - */ - -Panel.prototype.addRange = function (object, value, params) { - return this._addComponent(Range,object,value,params); -}; - -/** - * Adds a new Checkbox to last added SubGroup. - * @param {Object} object - The object - * @param {String} value - The property key - * @param {Object} [params] - Component options - * @param {String} [params.label=value] - Checkbox label - * @param {Function} [params.onChange] - Callback on change - * @returns {Panel} - */ - -Panel.prototype.addCheckbox = function (object, value, params) { - return this._addComponent(Checkbox,object,value,params); -}; - -/** - * Adds a new Color modifier to last added SubGroup. - * @param {Object} object - The object - * @param {String} value - The property key - * @param {Object} [params] - Component options - * @param {String} [params.label=value] - Color label - * @param {Function} [params.onChange] - Callback on change - * @param {String} [params.colorMode='rgb'] - The colorMode to be used: 'hex' #ff00ff, 'rgb' [255,0,255], 'rgbfv' [1,0,1] - * @param {Array} [params.presets] - A set of preset colors matching params.colorMode - * @returns {Panel} - */ - -Panel.prototype.addColor = function (object, value, params) { - return this._addComponent(Color,object,value, params); -}; - -/** - * Adds a new Button to last added SubGroup. - * @param {String} label - The object - * @param {Function} onPress - Callback - * @param {Object} [params] - Component options - * @param {String} [params.label=value] - Button label - * @returns {Panel} - */ - -Panel.prototype.addButton = function (label, onPress, params) { - return this._addComponent(Button,label,onPress,params); -}; - -/** - * Adds a new Select to last added SubGroup. - * @param {Object} object - The object - * @param {String} value - The property key - * @param {Object} [params] - Component options - * @param {String} [params.label=value] - Button label - * @param {Function} [params.onChange] - Callback on change - function(index){} - * @param {String} [params.target] - The property to be set on select - * @returns {Panel} - */ - -Panel.prototype.addSelect = function (object, value, params) { - return this._addComponent(Select,object,value,params); -}; - -/** - * Adds a new Slider to last added SubGroup. - * @param {Object} object - The object - * @param {String} value - The property key - * @param {String} range - The min/max array key to be used - * @param {Object} [params] - Component options - * @param {String} [params.label=value] - Slider label - * @param {Function} [params.onChange] - Callback on change - * @param {Function} [params.onFinish] - Callback on finish - * @param {Number} [params.step] - Amount subbed/added on arrowDown/arrowUp press inside the input - * @param {Number} [params.dp] - Decimal places displayed - * @returns {Panel} - */ - -Panel.prototype.addSlider = function (object, value, range, params) { - return this._addComponent(Slider,object,value,range,params); -}; - -/** - * Adds a new FunctionPlotter to last added SubGroup. - * @param {Object} object - The object - * @param {String} value - The property key - f(x), f(x,y) - * @param {Object} [params] - Component options - * @param {String} [params.label=value] - FunctionPlotter label - * @returns {Panel} - */ - -Panel.prototype.addFunctionPlotter = function (object, value, params) { - return this._addComponent(FunctionPlotter,object,value,params); -}; - -/** - * Adds a new XY-Pad to last added SubGroup. - * @param {Object} object - The object - * @param {String} value - The property key - * @param {Object} [params] - Component options - * @param {String} [params.label=value] - Pad label - * @returns {Panel} - */ - -Panel.prototype.addPad = function (object, value, params) { - return this._addComponent(Pad,object,value,params); -}; - -/** - * Adds a new ValuePlotter to last added SubGroup. - * @param {Object} object - The object - * @param {String} value - The property key - * @param {Object} [params] - Component options - * @param {String} [params.label=value] - Plotter label - * @param {Number} [params.height] - Plotter height - * @param {Number} [params.resolution] - Graph resolution - * @returns {Panel} - */ - -Panel.prototype.addValuePlotter = function (object, value, params) { - return this._addComponent(ValuePlotter,object,value,params); -}; - -/** - * Adds a new NumberOutput to last added SubGroup. - * @param {Object} object - The object - * @param {String} value - The property key - * @param {Object} [params] - Component options - * @param {String} [params.label=value] - Output label - * @param {Number} [params.dp] - Decimal places displayed - * @returns {Panel} - */ - -Panel.prototype.addNumberOutput = function (object, value, params) { - return this._addComponent(NumberOutput,object,value,params); -}; - -/** - * Adds a new StringOutput to last added SubGroup. - * @param {Object} object - The object - * @param {String} value - The property key - * @param {Object} [params] - Component options - * @param {String} [params.label=value] - Output label - * @returns {Panel} - */ - -Panel.prototype.addStringOutput = function (object, value, params) { - return this._addComponent(StringOutput,object,value,params); -}; - -Panel.prototype.addCanvas = function (params) { - return this._addComponent(Canvas_,params); -}; - -Panel.prototype.addSVG = function (params) { - return this._addComponent(SVG_,params); -}; - -Panel.prototype.setData = function(data){ - var groups = this._groups, - i = -1, l = groups.length; - while(++i < l){ - groups[i].setData(data[i]); - } -}; - -Panel.prototype.getData = function(){ - var groups = this._groups, - i = -1, l = groups.length; - var data = []; - while(++i < l){ - data.push(groups[i].getData()); - } - return data; -}; - -module.exports = Panel; -},{"../component/Button":3,"../component/Canvas":5,"../component/Checkbox":6,"../component/Color":7,"../component/FunctionPlotter":9,"../component/NumberInput":13,"../component/NumberOutput":15,"../component/Pad":18,"../component/Range":21,"../component/SVG":22,"../component/Select":24,"../component/Slider":25,"../component/StringInput":27,"../component/StringOutput":28,"../component/ValuePlotter":29,"../core/History":33,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Mouse":44,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48,"../core/event/EventDispatcher":49,"../core/layout/LayoutMode":50,"../core/layout/ScrollBar":51,"./Group":53,"./MenuEvent":55,"./PanelEvent":57}],57:[function(require,module,exports){ -var PanelEvent = { - PANEL_MOVE_BEGIN : 'panelMoveBegin', - PANEL_MOVE : 'panelMove', - PANEL_MOVE_END : 'panelMoveEnd', - - PANEL_SHOW : 'panelShow', - PANEL_HIDE : 'panelHide', - - PANEL_SCROLL_WRAP_ADDED : 'panelScrollWrapAdded', - PANEL_SCROLL_WRAP_REMOVED : 'panelScrollWrapRemoved', - - PANEL_SIZE_CHANGE : 'panelSizeChange' -}; -module.exports = PanelEvent; -},{}],58:[function(require,module,exports){ -var AbstractGroup = require('./AbstractGroup'); -var Node = require('../core/document/Node'); -var CSS = require('../core/document/CSS'); - -var Event_ = require('../core/event/Event'), - DocumentEvent = require('../core/document/DocumentEvent'), - PanelEvent = require('./PanelEvent'), - GroupEvent = require('./GroupEvent'), - ComponentEvent = require('../core/ComponentEvent'); - -function SubGroup(parent,params){ - params = params || {}; - params.label = params.label || null; - params.useLabels = params.useLabels === undefined ? true : params.useLabels; - - AbstractGroup.apply(this,arguments); - - var rootNode = this._node, - wrapNode = this._wrapNode, - listNode = this._listNode; - - rootNode.setStyleClass(CSS.SubGroup); - wrapNode.setStyleClass(CSS.Wrap); - - wrapNode.addChild(listNode); - rootNode.addChild(wrapNode); - - this._useLabels = params.useLabels; - - var label = params.label; - - if (label && label.length != 0 && label != 'none') { - var headNode = this._headNode = new Node(), - lablWrap = new Node(), - lablNode = new Node(Node.SPAN); - - headNode.setStyleClass(CSS.Head); - lablWrap.setStyleClass(CSS.Wrap); - lablNode.setStyleClass(CSS.Label); - - lablNode.setProperty('innerHTML', label); - - lablWrap.addChild(lablNode); - headNode.addChild(lablWrap); - - - var indiNode = this._indiNode = new Node(); - indiNode.setStyleClass(CSS.ArrowBSubMax); - headNode.addChildAt(indiNode, 0); - - rootNode.addChildAt(headNode, 0); - - this.addEventListener(GroupEvent.SUBGROUP_TRIGGER, this._parent, 'onSubGroupTrigger'); - headNode.addEventListener(DocumentEvent.MOUSE_DOWN, this._onHeadMouseDown.bind(this)); - - this._updateAppearance(); - - } - - if(this.hasMaxHeight()){ - this.addScrollWrap(); - } - - this._parent.addEventListener(GroupEvent.SUBGROUP_ENABLE, this, 'onEnable'); - this._parent.addEventListener(GroupEvent.SUBGROUP_DISABLE, this, 'onDisable'); - this._parent.addEventListener(PanelEvent.PANEL_MOVE_END, this, 'onPanelMoveEnd'); - this._parent.addEventListener(GroupEvent.GROUP_SIZE_CHANGE,this, 'onGroupSizeChange'); - this._parent.addEventListener(PanelEvent.PANEL_SIZE_CHANGE,this, 'onPanelSizeChange'); - this._parent.addEventListener(DocumentEvent.WINDOW_RESIZE, this, 'onWindowResize'); - - this.addEventListener(GroupEvent.GROUP_SIZE_UPDATE,this._parent,'onGroupSizeUpdate'); -} -SubGroup.prototype = Object.create(AbstractGroup.prototype); -SubGroup.prototype.constructor = SubGroup; - -//FIXME -SubGroup.prototype._onHeadMouseDown = function () { - this._enabled = !this._enabled; - this._onTrigger(); - - var event = DocumentEvent.MOUSE_UP, - self = this; - var onDocumentMouseUp = function () { - self._onTrigger(); - document.removeEventListener(event, onDocumentMouseUp); - }; - - document.addEventListener(event,onDocumentMouseUp); -}; - -SubGroup.prototype._onTrigger = function() { - this._updateAppearance(); - this.dispatchEvent(new Event_(this,GroupEvent.SUBGROUP_TRIGGER,null)); -}; - - -SubGroup.prototype._updateAppearance = function () { - if (this.isDisabled()) { - this._wrapNode.setHeight(0); - if (this.hasLabel()) { - this._headNode.setStyleClass(CSS.HeadInactive); - this._indiNode.setStyleClass(CSS.ArrowBSubMin); - } - } - else { - if (this.hasMaxHeight()) { - this._wrapNode.setHeight(this.getMaxHeight()); - } else { - this._wrapNode.deleteStyleProperty('height'); - } - if (this.hasLabel()) { - this._headNode.setStyleClass(CSS.Head); - this._indiNode.setStyleClass(CSS.ArrowBSubMax); - } - } -}; - -SubGroup.prototype.update = function () { - if (this.hasMaxHeight()){ - this._scrollBar.update(); - } -}; - -SubGroup.prototype.onComponentSelectDrag = function () { - this.preventSelectDrag(); -}; - -SubGroup.prototype.onEnable = function () { - if (this.isDisabled()){ - return; - } - this.dispatchEvent(new Event_(this, ComponentEvent.ENABLE, null)); -}; -SubGroup.prototype.onDisable = function () { - if (this.isDisabled()){ - return; - } - this.dispatchEvent(new Event_(this, ComponentEvent.DISABLE, null)); -}; - -//bubble -SubGroup.prototype.onGroupSizeChange = function () { - this.dispatchEvent(new Event_(this, GroupEvent.GROUP_SIZE_CHANGE, null)); -}; -SubGroup.prototype.onGroupSizeUpdate = function () { - this.dispatchEvent(new Event_(this, GroupEvent.GROUP_SIZE_UPDATE, null)); -}; -SubGroup.prototype.onPanelMoveEnd = function () { - this.dispatchEvent(new Event_(this, PanelEvent.PANEL_MOVE_END, null)); -}; -SubGroup.prototype.onPanelSizeChange = function () { - this._updateAppearance(); -}; -SubGroup.prototype.onWindowResize = function (e) { - this.dispatchEvent(e); -}; - -SubGroup.prototype.hasLabel = function () { - return this._headNode != null; -}; -SubGroup.prototype.addComponentNode = function (node) { - this._listNode.addChild(node); -}; -SubGroup.prototype.usesLabels = function () { - return this._useLabels; -}; - -module.exports = SubGroup; -},{"../core/ComponentEvent":31,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Node":45,"../core/event/Event":48,"./AbstractGroup":52,"./GroupEvent":54,"./PanelEvent":57}]},{},[1])(1) -}); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIuLi9pbmRleC5qcyIsIi4uL2xpYi9Db250cm9sS2l0LmpzIiwiLi4vbGliL2NvbXBvbmVudC9CdXR0b24uanMiLCIuLi9saWIvY29tcG9uZW50L0J1dHRvblByZXNldC5qcyIsIi4uL2xpYi9jb21wb25lbnQvQ2FudmFzLmpzIiwiLi4vbGliL2NvbXBvbmVudC9DaGVja2JveC5qcyIsIi4uL2xpYi9jb21wb25lbnQvQ29sb3IuanMiLCIuLi9saWIvY29tcG9uZW50L0Z1bmN0aW9uUGxvdFR5cGUuanMiLCIuLi9saWIvY29tcG9uZW50L0Z1bmN0aW9uUGxvdHRlci5qcyIsIi4uL2xpYi9jb21wb25lbnQvRnVuY3Rpb25QbG90dGVyRnVuY3Rpb25BcmdzRXJyb3IuanMiLCIuLi9saWIvY29tcG9uZW50L0Z1bmN0aW9uUGxvdHRlck9iamVjdEVycm9yLmpzIiwiLi4vbGliL2NvbXBvbmVudC9NZXRyaWMuanMiLCIuLi9saWIvY29tcG9uZW50L051bWJlcklucHV0LmpzIiwiLi4vbGliL2NvbXBvbmVudC9OdW1iZXJJbnB1dF9JbnRlcm5hbC5qcyIsIi4uL2xpYi9jb21wb25lbnQvTnVtYmVyT3V0cHV0LmpzIiwiLi4vbGliL2NvbXBvbmVudC9PcHRpb25zLmpzIiwiLi4vbGliL2NvbXBvbmVudC9PdXRwdXQuanMiLCIuLi9saWIvY29tcG9uZW50L1BhZC5qcyIsIi4uL2xpYi9jb21wb25lbnQvUGlja2VyLmpzIiwiLi4vbGliL2NvbXBvbmVudC9QbG90dGVyLmpzIiwiLi4vbGliL2NvbXBvbmVudC9SYW5nZS5qcyIsIi4uL2xpYi9jb21wb25lbnQvU1ZHLmpzIiwiLi4vbGliL2NvbXBvbmVudC9TVkdDb21wb25lbnQuanMiLCIuLi9saWIvY29tcG9uZW50L1NlbGVjdC5qcyIsIi4uL2xpYi9jb21wb25lbnQvU2xpZGVyLmpzIiwiLi4vbGliL2NvbXBvbmVudC9TbGlkZXJfSW50ZXJuYWwuanMiLCIuLi9saWIvY29tcG9uZW50L1N0cmluZ0lucHV0LmpzIiwiLi4vbGliL2NvbXBvbmVudC9TdHJpbmdPdXRwdXQuanMiLCIuLi9saWIvY29tcG9uZW50L1ZhbHVlUGxvdHRlci5qcyIsIi4uL2xpYi9jb3JlL0NvbXBvbmVudC5qcyIsIi4uL2xpYi9jb3JlL0NvbXBvbmVudEV2ZW50LmpzIiwiLi4vbGliL2NvcmUvQ29tcG9uZW50T2JqZWN0RXJyb3IuanMiLCIuLi9saWIvY29yZS9IaXN0b3J5LmpzIiwiLi4vbGliL2NvcmUvSGlzdG9yeUV2ZW50LmpzIiwiLi4vbGliL2NvcmUvT2JqZWN0Q29tcG9uZW50LmpzIiwiLi4vbGliL2NvcmUvT2JqZWN0Q29tcG9uZW50Tm90aWZpZXIuanMiLCIuLi9saWIvY29yZS9PcHRpb25FdmVudC5qcyIsIi4uL2xpYi9jb3JlL1N0YXRlLmpzIiwiLi4vbGliL2NvcmUvY29sb3IvQ29sb3JGb3JtYXRFcnJvci5qcyIsIi4uL2xpYi9jb3JlL2NvbG9yL0NvbG9yTW9kZS5qcyIsIi4uL2xpYi9jb3JlL2NvbG9yL0NvbG9yVXRpbC5qcyIsIi4uL2xpYi9jb3JlL2RvY3VtZW50L0NTUy5qcyIsIi4uL2xpYi9jb3JlL2RvY3VtZW50L0RvY3VtZW50RXZlbnQuanMiLCIuLi9saWIvY29yZS9kb2N1bWVudC9Nb3VzZS5qcyIsIi4uL2xpYi9jb3JlL2RvY3VtZW50L05vZGUuanMiLCIuLi9saWIvY29yZS9kb2N1bWVudC9Ob2RlRXZlbnQuanMiLCIuLi9saWIvY29yZS9kb2N1bWVudC9TdHlsZS5qcyIsIi4uL2xpYi9jb3JlL2V2ZW50L0V2ZW50LmpzIiwiLi4vbGliL2NvcmUvZXZlbnQvRXZlbnREaXNwYXRjaGVyLmpzIiwiLi4vbGliL2NvcmUvbGF5b3V0L0xheW91dE1vZGUuanMiLCIuLi9saWIvY29yZS9sYXlvdXQvU2Nyb2xsQmFyLmpzIiwiLi4vbGliL2dyb3VwL0Fic3RyYWN0R3JvdXAuanMiLCIuLi9saWIvZ3JvdXAvR3JvdXAuanMiLCIuLi9saWIvZ3JvdXAvR3JvdXBFdmVudC5qcyIsIi4uL2xpYi9ncm91cC9NZW51RXZlbnQuanMiLCIuLi9saWIvZ3JvdXAvUGFuZWwuanMiLCIuLi9saWIvZ3JvdXAvUGFuZWxFdmVudC5qcyIsIi4uL2xpYi9ncm91cC9TdWJHcm91cC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOU5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoa0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkxBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2h6QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3UEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBOztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNWQTtBQUNBO0FBQ0E7QUFDQTs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaHlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJ2YXIgQ29udHJvbEtpdCAgICAgICAgPSByZXF1aXJlKCcuL2xpYi9Db250cm9sS2l0Jyk7XG5cdENvbnRyb2xLaXQuQ2FudmFzID0gcmVxdWlyZSgnLi9saWIvY29tcG9uZW50L0NhbnZhcycpO1xuXHRDb250cm9sS2l0LlNWRyAgICA9IHJlcXVpcmUoJy4vbGliL2NvbXBvbmVudC9TVkcnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBDb250cm9sS2l0OyIsInZhciBOb2RlICAgID0gcmVxdWlyZSgnLi9jb3JlL2RvY3VtZW50L05vZGUnKSxcbiAgICBQYW5lbCAgID0gcmVxdWlyZSgnLi9ncm91cC9QYW5lbCcpLFxuICAgIE9wdGlvbnMgPSByZXF1aXJlKCcuL2NvbXBvbmVudC9PcHRpb25zJyksXG4gICAgUGlja2VyICA9IHJlcXVpcmUoJy4vY29tcG9uZW50L1BpY2tlcicpO1xuXG52YXIgQ1NTID0gcmVxdWlyZSgnLi9jb3JlL2RvY3VtZW50L0NTUycpO1xuXG52YXIgRXZlbnREaXNwYXRjaGVyID0gcmVxdWlyZSgnLi9jb3JlL2V2ZW50L0V2ZW50RGlzcGF0Y2hlcicpLFxuICAgIEV2ZW50XyAgICAgICAgICA9IHJlcXVpcmUoJy4vY29yZS9ldmVudC9FdmVudCcpLFxuICAgIERvY3VtZW50RXZlbnQgICA9IHJlcXVpcmUoJy4vY29yZS9kb2N1bWVudC9Eb2N1bWVudEV2ZW50JyksXG4gICAgTm9kZUV2ZW50ICAgICAgID0gcmVxdWlyZSgnLi9jb3JlL2RvY3VtZW50L05vZGVFdmVudCcpLFxuICAgIENvbXBvbmVudEV2ZW50ICA9IHJlcXVpcmUoJy4vY29yZS9Db21wb25lbnRFdmVudCcpLFxuICAgIEhpc3RvcnlFdmVudCAgICA9IHJlcXVpcmUoJy4vY29yZS9IaXN0b3J5RXZlbnQnKSxcbiAgICBNZW51RXZlbnQgICAgICAgPSByZXF1aXJlKCcuL2dyb3VwL01lbnVFdmVudCcpO1xuXG52YXIgSGlzdG9yeSA9IHJlcXVpcmUoJy4vY29yZS9IaXN0b3J5JyksXG4gICAgU3RhdGUgICA9IHJlcXVpcmUoJy4vY29yZS9TdGF0ZScpO1xuXG52YXIgTW91c2UgICA9IHJlcXVpcmUoJy4vY29yZS9kb2N1bWVudC9Nb3VzZScpO1xuXG52YXIgVmFsdWVQbG90dGVyID0gcmVxdWlyZSgnLi9jb21wb25lbnQvVmFsdWVQbG90dGVyJyk7XG52YXIgU3RyaW5nT3V0cHV0ID0gcmVxdWlyZSgnLi9jb21wb25lbnQvU3RyaW5nT3V0cHV0JyksXG4gICAgTnVtYmVyT3V0cHV0ID0gcmVxdWlyZSgnLi9jb21wb25lbnQvTnVtYmVyT3V0cHV0Jyk7XG5cbnZhciBERUZBVUxUX0hJU1RPUlkgPSBmYWxzZSxcbiAgICBERUZBVUxUX09QQUNJVFkgPSAxLjAsXG4gICAgREVGQVVMVF9QQU5FTFNfQ0xPU0FCTEUgPSBmYWxzZSxcbiAgICBERUZBVUxUX0VOQUJMRSA9IHRydWUsXG4gICAgREVGQVVMVF9MT0FEX0FORF9TQVZFID0gZmFsc2U7XG5cbnZhciBERUZBVUxUX1RSSUdHRVJfU0hPUlRDVVRfQ0hBUiA9ICdoJztcblxudmFyIGluaXRpYXRlZCA9IGZhbHNlO1xuXG4vKipcbiAqIEluaXRpYWxpemVzIENvbnRyb2xLaXQuXG4gKiBAcGFyYW0ge09iamVjdH0gW29wdGlvbnNdIC0gQ29udHJvbEtpdCBvcHRpb25zXG4gKiBAcGFyYW0ge051bWJlcn0gW29wdGlvbnMub3BhY2l0eT0xLjBdIC0gT3ZlcmFsbCBvcGFjaXR5XG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLmVuYWJsZT10cnVlXSAtIEluaXRpYWwgQ29udHJvbEtpdCBzdGF0ZSwgZW5hYmxlZCAvIGRpc2FibGVkXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtvcHRpb25zLnVzZUV4dGVybmFsU3R5bGU9ZmFsc2VdIC0gSWYgdHJ1ZSwgYW4gZXh0ZXJuYWwgc3R5bGUgaXMgdXNlZCBpbnN0ZWFkIG9mIHRoZSBidWlsZC1pbiBvbmVcbiAqIEBwYXJhbSB7U3RyaW5nfSBbb3B0aW9ucy5zdHlsZVN0cmluZ10gLSBJZiB0cnVlLCBhbiBleHRlcm5hbCBzdHlsZSBpcyB1c2VkIGluc3RlYWQgb2YgdGhlIGJ1aWxkLWluIG9uZVxuICogQHBhcmFtIHtCb29sZWFufVtvcHRpb25zLmhpc3Rvcnk9ZmFsc2VdIC0gKEV4cGVyaW1lbnRhbCkgRW5hYmxlcyBhIHZhbHVlIGhpc3RvcnkgZm9yIGFsbCBjb21wb25lbnRzXG4gKi9cbmZ1bmN0aW9uIENvbnRyb2xLaXQob3B0aW9ucykge1xuICAgIGlmKGluaXRpYXRlZCl7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignQ29udHJvbEtpdCBpcyBhbHJlYWR5IGluaXRpYWxpemVkLicpO1xuICAgIH1cbiAgICBvcHRpb25zICAgICAgICAgICAgICAgICAgPSBvcHRpb25zIHx8IHt9O1xuICAgIG9wdGlvbnMuaGlzdG9yeSAgICAgICAgICA9IG9wdGlvbnMuaGlzdG9yeSA9PT0gdW5kZWZpbmVkID8gREVGQVVMVF9ISVNUT1JZIDogb3B0aW9ucy5oaXN0b3J5O1xuICAgIG9wdGlvbnMubG9hZEFuZFNhdmUgICAgICA9IG9wdGlvbnMubG9hZEFuZFNhdmUgPT09IHVuZGVmaW5lZCA/IERFRkFVTFRfTE9BRF9BTkRfU0FWRSA6IG9wdGlvbnMubG9hZEFuZFNhdmU7XG4gICAgb3B0aW9ucy5vcGFjaXR5ICAgICAgICAgID0gb3B0aW9ucy5vcGFjaXR5ID09PSB1bmRlZmluZWQgPyBERUZBVUxUX09QQUNJVFkgOiBvcHRpb25zLm9wYWNpdHk7XG4gICAgb3B0aW9ucy5wYW5lbHNDbG9zYWJsZSAgID0gb3B0aW9ucy5wYW5lbHNDbG9zYWJsZSA9PT0gdW5kZWZpbmVkID8gREVGQVVMVF9QQU5FTFNfQ0xPU0FCTEUgOiBvcHRpb25zLnBhbmVsc0Nsb3NhYmxlO1xuICAgIG9wdGlvbnMudXNlRXh0ZXJuYWxTdHlsZSA9IG9wdGlvbnMudXNlRXh0ZXJuYWxTdHlsZSA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiBvcHRpb25zLnVzZUV4dGVybmFsU3R5bGU7XG4gICAgb3B0aW9ucy5lbmFibGUgICAgICAgICAgID0gb3B0aW9ucy5lbmFibGUgPT09IHVuZGVmaW5lZCA/IERFRkFVTFRfRU5BQkxFIDogb3B0aW9ucy5lbmFibGU7XG5cbiAgICBFdmVudERpc3BhdGNoZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcblxuICAgIHZhciBub2RlID0gbnVsbDtcbiAgICBpZiAoIW9wdGlvbnMucGFyZW50RG9tRWxlbWVudElkKSB7XG4gICAgICAgIG5vZGUgPSBuZXcgTm9kZSgpO1xuICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKG5vZGUuZ2V0RWxlbWVudCgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBub2RlID0gTm9kZS5nZXROb2RlQnlJZChvcHRpb25zLnBhcmVudERvbUVsZW1lbnRJZCk7XG4gICAgfVxuXG4gICAgaWYoIW9wdGlvbnMudXNlRXh0ZXJuYWxTdHlsZSl7XG4gICAgICAgIHZhciBzdHlsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3N0eWxlJyk7XG4gICAgICAgICAgICBzdHlsZS50eXBlID0gJ3RleHQvY3NzJztcbiAgICAgICAgdmFyIGNzcyA9ICFvcHRpb25zLnN0eWxlID8gcmVxdWlyZSgnLi9jb3JlL2RvY3VtZW50L1N0eWxlJykuc3RyaW5nIDogb3B0aW9ucy5zdHlsZVN0cmluZztcbiAgICAgICAgaWYoc3R5bGUuc3R5bGVzaGVldCl7XG4gICAgICAgICAgICBzdHlsZS5zdHlsZXNoZWV0LmNzc1RleHQgPSBjc3M7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdHlsZS5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShjc3MpKTtcbiAgICAgICAgfVxuICAgICAgICAoZG9jdW1lbnQuaGVhZCB8fCBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgnaGVhZCcpWzBdKS5hcHBlbmRDaGlsZChzdHlsZSk7XG4gICAgfVxuXG4gICAgbm9kZS5zZXRQcm9wZXJ0eSgnaWQnLCBDU1MuQ29udHJvbEtpdCk7XG5cbiAgICB0aGlzLl9ub2RlID0gbm9kZTtcbiAgICB0aGlzLl9wYW5lbHMgPSBbXTtcbiAgICB0aGlzLl9lbmFibGVkID0gb3B0aW9ucy5lbmFibGU7XG4gICAgdGhpcy5faGlzdG9yeUVuYWJsZWQgPSBvcHRpb25zLmhpc3Rvcnk7XG4gICAgdGhpcy5fc3RhdGVzRW5hYmxlZCA9IG9wdGlvbnMubG9hZEFuZFNhdmU7XG4gICAgdGhpcy5fcGFuZWxzQ2xvc2FibGUgPSBvcHRpb25zLnBhbmVsc0Nsb3NhYmxlO1xuXG4gICAgdmFyIGhpc3RvcnkgPSBIaXN0b3J5LnNldHVwKCk7XG5cbiAgICBpZiAoIXRoaXMuX2hpc3RvcnlFbmFibGVkKXtcbiAgICAgICAgaGlzdG9yeS5kaXNhYmxlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaGlzdG9yeS5hZGRFdmVudExpc3RlbmVyKEhpc3RvcnlFdmVudC5TVEFURV9QVVNILCB0aGlzLCAnb25IaXN0b3J5U3RhdGVQdXNoJyk7XG4gICAgICAgIGhpc3RvcnkuYWRkRXZlbnRMaXN0ZW5lcihIaXN0b3J5RXZlbnQuU1RBVEVfUE9QLCB0aGlzLCAnb25IaXN0b3J5U3RhdGVQb3AnKTtcbiAgICB9XG5cbiAgICBNb3VzZS5zZXR1cCgpO1xuICAgIFBpY2tlci5zZXR1cChub2RlKTtcbiAgICBPcHRpb25zLnNldHVwKG5vZGUpO1xuXG4gICAgdmFyIG9wYWNpdHkgPSBvcHRpb25zLm9wYWNpdHk7XG4gICAgaWYgKG9wYWNpdHkgIT0gMS4wICYmIG9wYWNpdHkgIT0gMC4wKSB7XG4gICAgICAgIG5vZGUuc2V0U3R5bGVQcm9wZXJ0eSgnb3BhY2l0eScsIG9wYWNpdHkpO1xuICAgIH1cblxuICAgIHRoaXMuX2NhblVwZGF0ZSA9IHRydWU7XG5cbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB2YXIgaW50ZXJ2YWwsXG4gICAgICAgIGNvdW50ID0gMCxcbiAgICAgICAgY291bnRNYXggPSAxMDtcblxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKERvY3VtZW50RXZlbnQuV0lORE9XX1JFU0laRSxmdW5jdGlvbigpe1xuICAgICAgICBzZWxmLl9jYW5VcGRhdGUgPSBmYWxzZTtcbiAgICAgICAgY2xlYXJJbnRlcnZhbChpbnRlcnZhbCk7XG4gICAgICAgIGludGVydmFsID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIGlmKGNvdW50ID49IGNvdW50TWF4KXtcbiAgICAgICAgICAgICAgICBjb3VudCA9IDA7XG4gICAgICAgICAgICAgICAgc2VsZi5fY2FuVXBkYXRlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjbGVhckludGVydmFsKGludGVydmFsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvdW50Kys7XG4gICAgICAgIH0sMjUpXG4gICAgfSk7XG5cbiAgICB0aGlzLl9zaG9ydGN1dEVuYWJsZSA9IERFRkFVTFRfVFJJR0dFUl9TSE9SVENVVF9DSEFSO1xuXG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsZnVuY3Rpb24oZSl7XG4gICAgICAgIGlmKCEoZS5jdHJsS2V5ICYmIFN0cmluZy5mcm9tQ2hhckNvZGUoZS53aGljaCB8fCBlLmtleUNvZGUpLnRvTG93ZXJDYXNlKCkgPT0gc2VsZi5fc2hvcnRjdXRFbmFibGUpKXtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBzZWxmLl9lbmFibGVkID0gIXNlbGYuX2VuYWJsZWQ7XG4gICAgICAgIGlmKHNlbGYuX2VuYWJsZWQpe1xuICAgICAgICAgICAgc2VsZi5fZW5hYmxlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZWxmLl9kaXNhYmxlKCk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGlmKCF0aGlzLl9lbmFibGVkKXtcbiAgICAgICAgdGhpcy5fZGlzYWJsZSgpO1xuICAgIH1cblxuICAgIGluaXRpYXRlZCA9IHRydWU7XG59XG5Db250cm9sS2l0LnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXZlbnREaXNwYXRjaGVyLnByb3RvdHlwZSk7XG5Db250cm9sS2l0LnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IENvbnRyb2xLaXQ7XG5cbi8qKlxuICogQWRkcyBhIHBhbmVsLlxuICogQHBhcmFtIHtPYmplY3R9IFtwYXJhbXNdIC0gUGFuZWwgb3B0aW9uc1xuICogQHBhcmFtIHtTdHJpbmd9IFtwYXJhbXMubGFiZWw9J0NvbnRyb2wgUGFuZWwnXSAtIFRoZSBwYW5lbCBsYWJlbFxuICogQHBhcmFtIHtOdW1iZXJ9IFtwYXJhbXMud2lkdGg9MzAwXSAtIFRoZSB3aWR0aFxuICogQHBhcmFtIHtOdW1iZXJ9IFtwYXJhbXMuaGVpZ2h0XSAtIENvbnN0cmFpbmVkIHBhbmVsIGhlaWdodFxuICogQHBhcmFtIHtOdW1iZXJ9IFtwYXJhbXMucmF0aW89NDBdIC0gVGhlIHJhdGlvIG9mIGxhYmVsIChkZWZhdWx0OjQwJSkgYW5kIGNvbXBvbmVudCAoZGVmYXVsdDo2MCUpIHdpZHRoXG4gKiBAcGFyYW0ge1N0cmluZ30gW3BhcmFtcy5hbGlnbj0ncmlnaHQnXSAtIEZsb2F0ICdsZWZ0JyBvciAncmlnaHQnLCBtdWx0aXBsZSBwYW5lbHMgZ2V0IGFsaWduZWQgbmV4dCB0byBlYWNoIG90aGVyXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtwYXJhbXMuZml4ZWQ9dHJ1ZV0gLSBJZiBmYWxzZSB0aGUgcGFuZWwgY2FuIGJlIG1vdmVkXG4gKiBAcGFyYW0ge0FycmF5fSBbcGFyYW1zLnBvc2l0aW9uPVswLDBdXSAtIElmIHVuZml4ZWQsIHRoZSBwYW5lbCBwYW5lbCBwb3NpdGlvbiByZWxhdGl2ZSB0byBhbGlnbm1lbnQgKGVnLiBpZiAnbGVmdCcgMCArIHBvc2l0aW9uWzBdIG9yIGlmICdyaWdodCcgd2luZG93LmlubmVySGVpZ2h0IC0gcG9zaXRpb25bMF0gLSBwYW5lbFdpZHRoKVxuICogQHBhcmFtIHtOdW1iZXJ9IFtwYXJhbXMub3BhY2l0eT0xLjBdIC0gVGhlIHBhbmVswrRzIG9wYWNpdHlcbiAqIEBwYXJhbSB7U3RyaW5nfSBbcGFyYW1zLmRvY2s9ZmFsc2VdIC0gKEV4cGVyaW1lbnRhbCkgSW5kaWNhdGVzIHdoZXRoZXIgdGhlIHBhbmVsIHNob3VsZCBiZSBkb2NrZWQgdG8gZWl0aGVyIHRoZSBsZWZ0IG9yIHJpZ2h0IHdpbmRvdyBib3JkZXIgKGRlcGVuZGluZyBvbiBwYXJhbXMuYWxpZ24pLCBkb2NrZWQgcGFuZWxzIGhlaWdodCBlcXVhbCB3aW5kb3cgaGVpZ2h0XG4gICogQHJldHVybnMge1BhbmVsfVxuICovXG5Db250cm9sS2l0LnByb3RvdHlwZS5hZGRQYW5lbCA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICB2YXIgcGFuZWwgPSBuZXcgUGFuZWwodGhpcywgcGFyYW1zKTtcbiAgICB0aGlzLl9wYW5lbHMucHVzaChwYW5lbCk7XG4gICAgcmV0dXJuIHBhbmVsO1xufTtcblxuLyoqXG4gKiBVcGRhdGVzIGFsbCBDb250cm9sS2l0IGNvbXBvbmVudHMgaWYgdGhlIHdhdFxuICovXG5Db250cm9sS2l0LnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCF0aGlzLl9lbmFibGVkIHx8ICF0aGlzLl9jYW5VcGRhdGUpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBpLCBqLCBrO1xuICAgIHZhciBsLCBtLCBuO1xuICAgIHZhciBwYW5lbHMgPSB0aGlzLl9wYW5lbHMsXG4gICAgICAgIHBhbmVsLFxuICAgICAgICBncm91cHMsXG4gICAgICAgIGNvbXBvbmVudHMsXG4gICAgICAgIGNvbXBvbmVudDtcblxuICAgIGkgPSAtMTsgbCA9IHBhbmVscy5sZW5ndGg7XG4gICAgd2hpbGUgKCsraSA8IGwpIHtcbiAgICAgICAgcGFuZWwgPSBwYW5lbHNbaV07XG5cbiAgICAgICAgaWYgKHBhbmVsLmlzRGlzYWJsZWQoKSl7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBncm91cHMgPSBwYW5lbC5nZXRHcm91cHMoKTtcbiAgICAgICAgaiA9IC0xOyBtID0gZ3JvdXBzLmxlbmd0aDtcblxuICAgICAgICB3aGlsZSAoKytqIDwgbSkge1xuICAgICAgICAgICAgY29tcG9uZW50cyA9IGdyb3Vwc1tqXS5nZXRDb21wb25lbnRzKCk7XG4gICAgICAgICAgICBrID0gLTE7IG4gPSBjb21wb25lbnRzLmxlbmd0aDtcblxuICAgICAgICAgICAgd2hpbGUgKCsrayA8IG4pIHtcbiAgICAgICAgICAgICAgICBjb21wb25lbnQgPSBjb21wb25lbnRzW2tdO1xuICAgICAgICAgICAgICAgIGlmIChjb21wb25lbnQuaXNEaXNhYmxlZCgpKXtcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChjb21wb25lbnQgaW5zdGFuY2VvZiBWYWx1ZVBsb3R0ZXIgfHxcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50IGluc3RhbmNlb2YgU3RyaW5nT3V0cHV0IHx8XG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudCBpbnN0YW5jZW9mIE51bWJlck91dHB1dCkge1xuICAgICAgICAgICAgICAgICAgICBjb21wb25lbnQudXBkYXRlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufTtcblxuQ29udHJvbEtpdC5wcm90b3R5cGUuaGlzdG9yeUlzRW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5faGlzdG9yeUVuYWJsZWQ7XG59O1xuXG5Db250cm9sS2l0LnByb3RvdHlwZS5zdGF0ZXNBcmVFbmFibGVkID0gZnVuY3Rpb24oKXtcbiAgICByZXR1cm4gdGhpcy5fc3RhdGVzRW5hYmxlZDtcbn07XG5cbkNvbnRyb2xLaXQucHJvdG90eXBlLnBhbmVsc0FyZUNsb3NhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9wYW5lbHNDbG9zYWJsZTtcbn07XG5cbkNvbnRyb2xLaXQucHJvdG90eXBlLl9lbmFibGUgPSBmdW5jdGlvbigpe1xuICAgIHZhciBpID0gLTEsIHAgPSB0aGlzLl9wYW5lbHMsIGwgPSBwLmxlbmd0aDtcbiAgICB3aGlsZSAoKytpIDwgbCl7XG4gICAgICAgIHBbaV0uZW5hYmxlKCk7XG4gICAgfVxuICAgIHRoaXMuX25vZGUuc2V0U3R5bGVQcm9wZXJ0eSgndmlzaWJpbGl0eScsICcnKTtcbn07XG5cbkNvbnRyb2xLaXQucHJvdG90eXBlLl9kaXNhYmxlID0gZnVuY3Rpb24oKXtcbiAgICB2YXIgaSA9IC0xLCBwID0gdGhpcy5fcGFuZWxzLCBsID0gcC5sZW5ndGg7XG4gICAgd2hpbGUgKCsraSA8IGwpe1xuICAgICAgICBwW2ldLmRpc2FibGUoKTtcbiAgICB9XG4gICAgdGhpcy5fbm9kZS5zZXRTdHlsZVByb3BlcnR5KCd2aXNpYmlsaXR5JywgJ2hpZGRlbicpO1xufTtcblxuLyoqXG4gKiBFbmFibGVzIGFuZCBzaG93cyBjb250cm9sS2l0LlxuICovXG5cbkNvbnRyb2xLaXQucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLl9lbmFibGUoKTtcbiAgICB0aGlzLl9lbmFibGVkID0gdHJ1ZTtcbn07XG5cbi8qKlxuICogRGlzYWJsZSBhbmQgaGlkZXMgY29udHJvbEtpdC5cbiAqL1xuXG5Db250cm9sS2l0LnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX2Rpc2FibGUoKTtcbiAgICB0aGlzLl9lbmFibGVkID0gZmFsc2U7XG59O1xuXG5cbi8qKlxuICogU3BlY2lmaWVzIHRoZSBrZXkgdG8gYmUgdXNlZCB3aXRoIGN0cmwgJiBjaGFyLCB0byB0cmlnZ2VyIENvbnRyb2xLaXRzIHZpc2liaWxpdHkuXG4gKiBAcGFyYW0gY2hhclxuICovXG5cbkNvbnRyb2xLaXQucHJvdG90eXBlLnNldFNob3J0Y3V0RW5hYmxlID0gZnVuY3Rpb24oY2hhcil7XG4gICAgdGhpcy5fc2hvcnRjdXRFbmFibGUgPSBjaGFyO1xufTtcblxuQ29udHJvbEtpdC5wcm90b3R5cGUub25IaXN0b3J5U3RhdGVQdXNoID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIE1lbnVFdmVudC5VUERBVEVfTUVOVSwgbnVsbCkpO1xufTtcblxuQ29udHJvbEtpdC5wcm90b3R5cGUub25IaXN0b3J5U3RhdGVQb3AgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgQ29tcG9uZW50RXZlbnQuVVBEQVRFX1ZBTFVFLCB7b3JpZ2luOiBudWxsfSkpO1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIE1lbnVFdmVudC5VUERBVEVfTUVOVSwgbnVsbCkpO1xufTtcblxuQ29udHJvbEtpdC5wcm90b3R5cGUubG9hZFNldHRpbmdzID0gZnVuY3Rpb24oZGF0YSl7XG4gICAgdmFyIGkgPSAtMSwgbCA9IGRhdGEubGVuZ3RoO1xuICAgIHZhciBwYW5lbHMgPSB0aGlzLl9wYW5lbHM7XG4gICAgd2hpbGUoKytpIDwgbCl7XG4gICAgICAgIHBhbmVsc1tpXS5zZXREYXRhKGRhdGFbaV0pO1xuICAgIH1cbn07XG5cbkNvbnRyb2xLaXQucHJvdG90eXBlLl9sb2FkU3RhdGUgPSBmdW5jdGlvbigpe1xuICAgIFN0YXRlLmxvYWQodGhpcy5sb2FkU2V0dGluZ3MuYmluZCh0aGlzKSk7XG59O1xuXG5Db250cm9sS2l0LnByb3RvdHlwZS5fc2F2ZVN0YXRlID0gZnVuY3Rpb24oKXtcbiAgICB0aGlzLnVwZGF0ZSgpOyAvL2ZvcmNlIHN5bmNcbiAgICB2YXIgcCA9IHRoaXMuX3BhbmVscywgaSA9IC0xLCBsID0gcC5sZW5ndGg7XG4gICAgdmFyIGRhdGEgPSBuZXcgQXJyYXkobCk7XG4gICAgd2hpbGUoKytpIDwgbCl7XG4gICAgICAgIGRhdGFbaV0gPSBwW2ldLmdldERhdGEoKTtcbiAgICB9XG4gICAgU3RhdGUuc2F2ZSh7ZGF0YTpkYXRhfSk7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIHJvb3QgZWxlbWVudC5cbiAqIEByZXR1cm5zIHsqfVxuICovXG5cbkNvbnRyb2xLaXQucHJvdG90eXBlLmdldE5vZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX25vZGU7XG59O1xuXG5Db250cm9sS2l0LmRlc3Ryb3kgPSBmdW5jdGlvbigpe1xuICAgIE1vdXNlLmdldCgpLmRlc3Ryb3koKTtcbiAgICBPcHRpb25zLmdldCgpLmRlc3Ryb3koKTtcbiAgICBQaWNrZXIuZ2V0KCkuZGVzdHJveSgpO1xuICAgIGluaXRpYXRlZCA9IGZhbHNlO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBDb250cm9sS2l0OyIsInZhciBFdmVudF8gICAgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZXZlbnQvRXZlbnQnKSxcbiAgICBOb2RlRXZlbnQgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZUV2ZW50JyksXG4gICAgQ29tcG9uZW50RXZlbnQgPSByZXF1aXJlKCcuLi9jb3JlL0NvbXBvbmVudEV2ZW50Jyk7XG5cbnZhciBOb2RlICAgICAgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L05vZGUnKSxcbiAgICBDb21wb25lbnQgPSByZXF1aXJlKCcuLi9jb3JlL0NvbXBvbmVudCcpO1xuXG52YXIgQ1NTID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9DU1MnKTtcblxudmFyIERFRkFVTFRfTEFCRUwgPSAnJztcblxuZnVuY3Rpb24gQnV0dG9uKHBhcmVudCxsYWJlbCxvblByZXNzLHBhcmFtcykge1xuICAgIG9uUHJlc3MgICAgICA9IG9uUHJlc3MgfHwgZnVuY3Rpb24oKXt9O1xuICAgIHBhcmFtcyAgICAgICA9IHBhcmFtcyAgICAgICB8fCB7fTtcbiAgICBwYXJhbXMubGFiZWwgPSBwYXJhbXMubGFiZWwgfHwgREVGQVVMVF9MQUJFTDtcblxuICAgIENvbXBvbmVudC5hcHBseSh0aGlzLFtwYXJlbnQscGFyYW1zLmxhYmVsXSk7XG5cbiAgICB2YXIgbm9kZSA9IHRoaXMuX2lucHV0Tm9kZSA9IG5ldyBOb2RlKE5vZGUuSU5QVVRfQlVUVE9OKTtcblxuICAgIG5vZGUuc2V0U3R5bGVDbGFzcyhDU1MuQnV0dG9uKTtcbiAgICBub2RlLnNldFByb3BlcnR5KCd2YWx1ZScsbGFiZWwpO1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIG5vZGUuYWRkRXZlbnRMaXN0ZW5lcihOb2RlRXZlbnQuT05fQ0xJQ0ssXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvblByZXNzLmJpbmQoc2VsZikoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50XyhzZWxmLENvbXBvbmVudEV2ZW50LlZBTFVFX1VQREFURUQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgdGhpcy5fd3JhcE5vZGUuYWRkQ2hpbGQobm9kZSk7XG59XG5CdXR0b24ucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShDb21wb25lbnQucHJvdG90eXBlKTtcbkJ1dHRvbi5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBCdXR0b247XG5cbkJ1dHRvbi5wcm90b3R5cGUuZ2V0QnV0dG9uTGFiZWwgPSBmdW5jdGlvbigpe1xuICAgIHJldHVybiB0aGlzLl9pbnB1dE5vZGUuZ2V0UHJvcGVydHkoJ3ZhbHVlJyk7XG59O1xuXG5CdXR0b24ucHJvdG90eXBlLnNldEJ1dHRvbkxhYmVsID0gZnVuY3Rpb24obGFiZWwpe1xuICAgIHRoaXMuX2lucHV0Tm9kZS5zZXRQcm9wZXJ0eSgndmFsdWUnLGxhYmVsKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gQnV0dG9uO1xuIiwidmFyIEV2ZW50RGlzcGF0Y2hlciAgICAgICAgID0gcmVxdWlyZSgnLi4vY29yZS9ldmVudC9FdmVudERpc3BhdGNoZXInKTtcbnZhciBPYmplY3RDb21wb25lbnROb3RpZmllciA9IHJlcXVpcmUoJy4uL2NvcmUvT2JqZWN0Q29tcG9uZW50Tm90aWZpZXInKTtcblxudmFyIEV2ZW50XyAgICAgID0gcmVxdWlyZSgnLi4vY29yZS9ldmVudC9FdmVudCcpLFxuICAgIE9wdGlvbkV2ZW50ID0gcmVxdWlyZSgnLi4vY29yZS9PcHRpb25FdmVudCcpLFxuICAgIE5vZGVFdmVudCAgID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Ob2RlRXZlbnQnKTtcblxudmFyIE5vZGUgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L05vZGUnKTtcbnZhciBDU1MgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L0NTUycpO1xuXG5mdW5jdGlvbiBCdXR0b25QcmVzZXQocGFyZW50Tm9kZSkge1xuICAgIEV2ZW50RGlzcGF0Y2hlci5hcHBseSh0aGlzKTtcbiAgICB2YXIgbm9kZSAgICA9IHRoaXMuX2J0bk5vZGUgPSBuZXcgTm9kZShOb2RlLklOUFVUX0JVVFRPTiksXG4gICAgICAgIGltZ05vZGUgPSB0aGlzLl9pbmRpTm9kZSA9IG5ldyBOb2RlKCk7XG5cbiAgICB0aGlzLl9vbkFjdGl2ZSA9IGZ1bmN0aW9uICgpIHt9O1xuICAgIHRoaXMuX29uRGVhY3RpdmUgPSBmdW5jdGlvbiAoKSB7fTtcbiAgICB0aGlzLl9pc0FjdGl2ZSA9IGZhbHNlO1xuXG4gICAgbm9kZS5zZXRTdHlsZUNsYXNzKENTUy5CdXR0b25QcmVzZXQpO1xuICAgIG5vZGUuYWRkRXZlbnRMaXN0ZW5lcihOb2RlRXZlbnQuTU9VU0VfRE9XTiwgdGhpcy5fb25Nb3VzZURvd24uYmluZCh0aGlzKSk7XG5cbiAgICBub2RlLmFkZENoaWxkKGltZ05vZGUpO1xuICAgIHBhcmVudE5vZGUuYWRkQ2hpbGRBdChub2RlLCAwKTtcblxuICAgIE9iamVjdENvbXBvbmVudE5vdGlmaWVyLmdldCgpLmFkZEV2ZW50TGlzdGVuZXIoT3B0aW9uRXZlbnQuVFJJR0dFUiwgdGhpcywgJ29uT3B0aW9uVHJpZ2dlcicpO1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcihPcHRpb25FdmVudC5UUklHR0VSRUQsIE9iamVjdENvbXBvbmVudE5vdGlmaWVyLmdldCgpLCAnb25PcHRpb25UcmlnZ2VyZWQnKTtcbn1cbkJ1dHRvblByZXNldC5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEV2ZW50RGlzcGF0Y2hlci5wcm90b3R5cGUpO1xuQnV0dG9uUHJlc2V0LnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEJ1dHRvblByZXNldDtcblxuQnV0dG9uUHJlc2V0LnByb3RvdHlwZS5vbk9wdGlvblRyaWdnZXIgPSBmdW5jdGlvbihlKXtcbiAgICBpZihlLmRhdGEub3JpZ2luID09IHRoaXMpe1xuICAgICAgICBpZighdGhpcy5faXNBY3RpdmUpe1xuICAgICAgICAgICAgdGhpcy5fb25BY3RpdmUoKTtcbiAgICAgICAgICAgIHRoaXMuX2J0bk5vZGUuc2V0U3R5bGVDbGFzcyhDU1MuQnV0dG9uUHJlc2V0QWN0aXZlKTtcbiAgICAgICAgICAgIHRoaXMuX2lzQWN0aXZlID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNle1xuICAgICAgICAgICAgdGhpcy5fb25EZWFjdGl2ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZih0aGlzLl9pc0FjdGl2ZSl7XG4gICAgICAgIHRoaXMuZGVhY3RpdmF0ZSgpO1xuICAgIH1cbn07XG5cbkJ1dHRvblByZXNldC5wcm90b3R5cGUuX29uTW91c2VEb3duID0gZnVuY3Rpb24oKXtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50Xyh0aGlzLCBPcHRpb25FdmVudC5UUklHR0VSRUQsIG51bGwpKTtcbn07XG5cbkJ1dHRvblByZXNldC5wcm90b3R5cGUuc2V0T25BY3RpdmUgPSBmdW5jdGlvbihmdW5jKXtcbiAgICB0aGlzLl9vbkFjdGl2ZSA9IGZ1bmM7XG59O1xuXG5CdXR0b25QcmVzZXQucHJvdG90eXBlLnNldE9uRGVhY3RpdmUgPSBmdW5jdGlvbihmdW5jKXtcbiAgICB0aGlzLl9vbkRlYWN0aXZlID0gZnVuYztcbn07XG5cbkJ1dHRvblByZXNldC5wcm90b3R5cGUuZGVhY3RpdmF0ZSA9IGZ1bmN0aW9uKCl7XG4gICAgdGhpcy5faXNBY3RpdmUgPSBmYWxzZTtcbiAgICB0aGlzLl9idG5Ob2RlLnNldFN0eWxlQ2xhc3MoQ1NTLkJ1dHRvblByZXNldCk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEJ1dHRvblByZXNldDtcbiIsInZhciBDb21wb25lbnQgPSByZXF1aXJlKCcuLi9jb3JlL0NvbXBvbmVudCcpO1xudmFyIENTUyAgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvQ1NTJyksXG4gICAgTWV0cmljICAgID0gcmVxdWlyZSgnLi9NZXRyaWMnKTtcblxudmFyIEV2ZW50XyAgICAgPSByZXF1aXJlKCcuLi9jb3JlL2V2ZW50L0V2ZW50JyksXG4gICAgR3JvdXBFdmVudCA9IHJlcXVpcmUoJy4uL2dyb3VwL0dyb3VwRXZlbnQnKTtcblxuZnVuY3Rpb24gQ2FudmFzKHBhcmVudCxwYXJhbXMpIHtcbiAgICBDb21wb25lbnQuYXBwbHkodGhpcyxhcmd1bWVudHMpO1xuXG4gICAgdmFyIHdyYXAgPSB0aGlzLl93cmFwTm9kZTtcbiAgICAgICAgd3JhcC5zZXRTdHlsZUNsYXNzKENTUy5DYW52YXNXcmFwKTtcbiAgICB2YXIgY2FudmFzID0gdGhpcy5fY2FudmFzID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnY2FudmFzJyk7XG4gICAgICAgIHdyYXAuZ2V0RWxlbWVudCgpLmFwcGVuZENoaWxkKGNhbnZhcyk7XG5cbiAgICB2YXIgd2lkdGggPSB3cmFwLmdldFdpZHRoKCk7XG4gICAgdGhpcy5fY2FudmFzV2lkdGggPSB0aGlzLl9jYW52YXNIZWlnaHQgPSAwO1xuICAgIHRoaXMuX3NldENhbnZhc1NpemUod2lkdGgsd2lkdGgpO1xuICAgIHRoaXMuX3VwZGF0ZUhlaWdodCgpO1xuXG4gICAgdGhpcy5fbm9kZS5zZXRTdHlsZUNsYXNzKENTUy5DYW52YXNMaXN0SXRlbSk7XG4gICAgdGhpcy5fcGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoR3JvdXBFdmVudC5HUk9VUF9TSVpFX0NIQU5HRSx0aGlzLCAgJ29uR3JvdXBTaXplQ2hhbmdlJyk7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKEdyb3VwRXZlbnQuR1JPVVBfU0laRV9VUERBVEUsdGhpcy5fcGFyZW50LCdvbkdyb3VwU2l6ZVVwZGF0ZScpO1xufVxuQ2FudmFzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoQ29tcG9uZW50LnByb3RvdHlwZSk7XG5DYW52YXMucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gQ2FudmFzO1xuXG5DYW52YXMucHJvdG90eXBlLl91cGRhdGVIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNhbnZhc0hlaWdodCA9IHRoaXMuX2NhbnZhcy5oZWlnaHQ7XG5cbiAgICB0aGlzLl93cmFwTm9kZS5zZXRIZWlnaHQoY2FudmFzSGVpZ2h0KTtcbiAgICB0aGlzLl9ub2RlLnNldEhlaWdodChjYW52YXNIZWlnaHQgKyBNZXRyaWMuUEFERElOR19XUkFQUEVSKTtcbn07XG5cbkNhbnZhcy5wcm90b3R5cGUub25Hcm91cFNpemVDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHdpZHRoID0gdGhpcy5fd3JhcE5vZGUuZ2V0V2lkdGgoKTtcblxuICAgIHRoaXMuX3NldENhbnZhc1NpemUod2lkdGgsIHdpZHRoKTtcbiAgICB0aGlzLl91cGRhdGVIZWlnaHQoKTtcbiAgICB0aGlzLl9yZWRyYXcoKTtcblxuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIEdyb3VwRXZlbnQuR1JPVVBfU0laRV9VUERBVEUsIG51bGwpKTtcbn07XG5cbkNhbnZhcy5wcm90b3R5cGUuX3NldENhbnZhc1NpemUgPSBmdW5jdGlvbiAod2lkdGgsIGhlaWdodCkge1xuICAgIHZhciBjYW52YXNXaWR0aCA9IHRoaXMuX2NhbnZhc1dpZHRoID0gd2lkdGgsXG4gICAgICAgIGNhbnZhc0hlaWdodCA9IHRoaXMuX2NhbnZhc0hlaWdodCA9IGhlaWdodDtcblxuICAgIHZhciBjYW52YXMgPSB0aGlzLl9jYW52YXM7XG4gICAgICAgIGNhbnZhcy5zdHlsZS53aWR0aCA9IGNhbnZhc1dpZHRoICsgJ3B4JztcbiAgICAgICAgY2FudmFzLnN0eWxlLmhlaWdodCA9IGNhbnZhc0hlaWdodCArICdweCc7XG4gICAgICAgIGNhbnZhcy53aWR0aCA9IGNhbnZhc1dpZHRoO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gY2FudmFzSGVpZ2h0O1xufTtcblxuQ2FudmFzLnByb3RvdHlwZS5nZXRDYW52YXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NhbnZhcztcbn07XG5cbkNhbnZhcy5wcm90b3R5cGUuZ2V0Q29udGV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IENhbnZhcztcbiIsInZhciBPYmplY3RDb21wb25lbnQgPSByZXF1aXJlKCcuLi9jb3JlL09iamVjdENvbXBvbmVudCcpLFxuICAgIE5vZGUgICAgICAgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZScpO1xuXG52YXIgRXZlbnRfICAgICAgICAgPSByZXF1aXJlKCcuLi9jb3JlL2V2ZW50L0V2ZW50JyksXG4gICAgTm9kZUV2ZW50ICAgICAgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L05vZGVFdmVudCcpLFxuICAgIENvbXBvbmVudEV2ZW50ID0gcmVxdWlyZSgnLi4vY29yZS9Db21wb25lbnRFdmVudCcpO1xuXG5mdW5jdGlvbiBDaGVja2JveChwYXJlbnQsIG9iamVjdCwgdmFsdWUsIHBhcmFtcykge1xuICAgIE9iamVjdENvbXBvbmVudC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7XG5cbiAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gICAgcGFyYW1zLm9uQ2hhbmdlID0gcGFyYW1zLm9uQ2hhbmdlIHx8IHRoaXMuX29uQ2hhbmdlO1xuICAgIHRoaXMuX29uQ2hhbmdlID0gcGFyYW1zLm9uQ2hhbmdlO1xuXG4gICAgdmFyIG5vZGUgPSB0aGlzLl9pbnB1dCA9IG5ldyBOb2RlKE5vZGUuSU5QVVRfQ0hFQ0tCT1gpO1xuICAgIG5vZGUuc2V0UHJvcGVydHkoJ2NoZWNrZWQnLHRoaXMuX29ialt0aGlzLl9rZXldKTtcbiAgICBub2RlLmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50LkNIQU5HRSx0aGlzLl9vbklucHV0Q2hhbmdlLmJpbmQodGhpcykpO1xuXG4gICAgdGhpcy5fd3JhcE5vZGUuYWRkQ2hpbGQodGhpcy5faW5wdXQpO1xufVxuQ2hlY2tib3gucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShPYmplY3RDb21wb25lbnQucHJvdG90eXBlKTtcbkNoZWNrYm94LnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IENoZWNrYm94O1xuXG5DaGVja2JveC5wcm90b3R5cGUuYXBwbHlWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLnB1c2hIaXN0b3J5U3RhdGUoKTtcblxuICAgIHZhciBvYmogPSB0aGlzLl9vYmosIGtleSA9IHRoaXMuX2tleTtcbiAgICBvYmpba2V5XSA9ICFvYmpba2V5XTtcblxuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIENvbXBvbmVudEV2ZW50LlZBTFVFX1VQREFURUQsIG51bGwpKTtcbn07XG5cbkNoZWNrYm94LnByb3RvdHlwZS5fb25JbnB1dENoYW5nZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmFwcGx5VmFsdWUoKTtcbiAgICB0aGlzLl9vbkNoYW5nZSgpO1xufTtcblxuQ2hlY2tib3gucHJvdG90eXBlLm9uVmFsdWVVcGRhdGUgPSBmdW5jdGlvbiAoZSkge1xuICAgIGlmIChlLmRhdGEub3JpZ2luID09IHRoaXMpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX2lucHV0LnNldFByb3BlcnR5KCdjaGVja2VkJywgdGhpcy5fb2JqW3RoaXMuX2tleV0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBDaGVja2JveDsiLCJ2YXIgT2JqZWN0Q29tcG9uZW50ID0gcmVxdWlyZSgnLi8uLi9jb3JlL09iamVjdENvbXBvbmVudCcpO1xuXG52YXIgTm9kZSAgICAgID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Ob2RlJyk7XG52YXIgQ29sb3JNb2RlID0gcmVxdWlyZSgnLi4vY29yZS9jb2xvci9Db2xvck1vZGUnKTtcbnZhciBQaWNrZXIgICAgPSByZXF1aXJlKCcuL1BpY2tlcicpO1xudmFyIENvbG9yVXRpbCA9IHJlcXVpcmUoJy4uL2NvcmUvY29sb3IvQ29sb3JVdGlsJyk7XG52YXIgT3B0aW9ucyAgID0gcmVxdWlyZSgnLi9PcHRpb25zJyk7XG52YXIgQnV0dG9uUHJlc2V0ID0gcmVxdWlyZSgnLi9CdXR0b25QcmVzZXQnKTtcbnZhciBNZXRyaWMgPSByZXF1aXJlKCcuL01ldHJpYycpLFxuICAgIENTUyAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvQ1NTJyk7XG5cbnZhciBFdmVudF8gICAgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZXZlbnQvRXZlbnQnKSxcbiAgICBOb2RlRXZlbnQgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZUV2ZW50JyksXG4gICAgQ29tcG9uZW50RXZlbnQgPSByZXF1aXJlKCcuLi9jb3JlL0NvbXBvbmVudEV2ZW50Jyk7XG5cbnZhciBDb2xvckZvcm1hdEVycm9yID0gcmVxdWlyZSgnLi4vY29yZS9jb2xvci9Db2xvckZvcm1hdEVycm9yJyk7XG5cbnZhciBERUZBVUxUX0NPTE9SX01PREUgPSBDb2xvck1vZGUuSEVYLFxuICAgIERFRkFVTFRfUFJFU0VUUyA9IG51bGw7XG5cbnZhciBNU0dfQ09MT1JfRk9STUFUX0hFWCA9ICdDb2xvciBmb3JtYXQgc2hvdWxkIGJlIGhleC4gU2V0IGNvbG9yTW9kZSB0byByZ2IsIHJnYmZ2IG9yIGhzdi4nLFxuICAgIE1TR19DT0xPUl9GT1JNQVRfUkdCX1JHQkZWX0hTViA9ICdDb2xvciBmb3JtYXQgc2hvdWxkIGJlIHJnYiwgcmdiZnYgb3IgaHN2LiBTZXQgY29sb3JNb2RlIHRvIGhleC4nLFxuICAgIE1TR19DT0xPUl9QUkVTRVRfRk9STUFUX0hFWCA9ICdQcmVzZXQgY29sb3IgZm9ybWF0IHNob3VsZCBiZSBoZXguJyxcbiAgICBNU0dfQ09MT1JfUFJFU0VUX0ZPUk1BVF9SR0JfUkdCRlZfSFNWID0gJ1ByZXNldCBjb2xvciBmb3JtYXQgc2hvdWxkIGJlIHJnYiwgcmdiZnYgb3IgaHN2Lic7XG5cbmZ1bmN0aW9uIENvbG9yKHBhcmVudCwgb2JqZWN0LCB2YWx1ZSwgcGFyYW1zKXtcbiAgICBPYmplY3RDb21wb25lbnQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcblxuICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgICBwYXJhbXMucHJlc2V0cyA9IHBhcmFtcy5wcmVzZXRzIHx8IERFRkFVTFRfUFJFU0VUUztcbiAgICBwYXJhbXMuY29sb3JNb2RlID0gcGFyYW1zLmNvbG9yTW9kZSB8fCBERUZBVUxUX0NPTE9SX01PREU7XG4gICAgcGFyYW1zLm9uQ2hhbmdlID0gcGFyYW1zLm9uQ2hhbmdlIHx8IHRoaXMuX29uQ2hhbmdlO1xuXG5cbiAgICB0aGlzLl9wcmVzZXRzS2V5ID0gcGFyYW1zLnByZXNldHM7XG4gICAgdGhpcy5fb25DaGFuZ2UgPSBwYXJhbXMub25DaGFuZ2U7XG5cbiAgICB2YXIgY29sb3IgPSB0aGlzLl9jb2xvciA9IG5ldyBOb2RlKCk7XG4gICAgdmFsdWUgPSB0aGlzLl92YWx1ZSA9IHRoaXMuX29ialt0aGlzLl9rZXldO1xuXG4gICAgdmFyIGNvbG9yTW9kZSA9IHRoaXMuX2NvbG9yTW9kZSA9IHBhcmFtcy5jb2xvck1vZGU7XG5cbiAgICB0aGlzLl92YWxpZGF0ZUNvbG9yRm9ybWF0KHZhbHVlLCBNU0dfQ09MT1JfRk9STUFUX0hFWCwgTVNHX0NPTE9SX0ZPUk1BVF9SR0JfUkdCRlZfSFNWKTtcblxuICAgIHZhciB3cmFwID0gdGhpcy5fd3JhcE5vZGU7XG5cbiAgICBpZighdGhpcy5fcHJlc2V0c0tleSl7XG4gICAgICAgIGNvbG9yLnNldFN0eWxlQ2xhc3MoQ1NTLkNvbG9yKTtcbiAgICAgICAgd3JhcC5hZGRDaGlsZChjb2xvcik7XG4gICAgfVxuICAgIGVsc2V7XG4gICAgICAgIGNvbG9yLnNldFN0eWxlQ2xhc3MoQ1NTLkNvbG9yKTtcblxuICAgICAgICB2YXIgd3JhcF8gPSBuZXcgTm9kZSgpO1xuICAgICAgICB3cmFwXy5zZXRTdHlsZUNsYXNzKENTUy5XcmFwQ29sb3JXUHJlc2V0KTtcblxuICAgICAgICB3cmFwLmFkZENoaWxkKHdyYXBfKTtcbiAgICAgICAgd3JhcF8uYWRkQ2hpbGQoY29sb3IpO1xuXG4gICAgICAgIHZhciBwcmVzZXRzID0gdGhpcy5fb2JqW3RoaXMuX3ByZXNldHNLZXldO1xuXG4gICAgICAgIHZhciBpID0gLTE7XG4gICAgICAgIHdoaWxlKCsraSA8IHByZXNldHMubGVuZ3RoKXtcbiAgICAgICAgICAgIHRoaXMuX3ZhbGlkYXRlQ29sb3JGb3JtYXQocHJlc2V0c1tpXSwgTVNHX0NPTE9SX1BSRVNFVF9GT1JNQVRfSEVYLFxuICAgICAgICAgICAgICAgIE1TR19DT0xPUl9QUkVTRVRfRk9STUFUX1JHQl9SR0JGVl9IU1YpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG9wdGlvbnMgPSBPcHRpb25zLmdldCgpLFxuICAgICAgICAgICAgcHJlc2V0QnRuID0gbmV3IEJ1dHRvblByZXNldCh3cmFwKTtcblxuICAgICAgICB2YXIgb25QcmVzZXREZWFjdGl2YXRlID0gZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIG9wdGlvbnMuY2xlYXIoKTtcbiAgICAgICAgICAgIHByZXNldEJ0bi5kZWFjdGl2YXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICB2YXIgb25QcmVzZXRBY3RpdmF0ZSA9IGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICBvcHRpb25zLmJ1aWxkKHByZXNldHMsXG4gICAgICAgICAgICAgICAgc2VsZi5fdmFsdWUsXG4gICAgICAgICAgICAgICAgY29sb3IsXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24oKXtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5wdXNoSGlzdG9yeVN0YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuX3ZhbHVlID0gcHJlc2V0c1tvcHRpb25zLmdldFNlbGVjdGVkSW5kZXgoKV07XG4gICAgICAgICAgICAgICAgICAgIHNlbGYuYXBwbHlWYWx1ZSgpO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLl9vbkNoYW5nZShzZWxmLl9vYmpbc2VsZi5fa2V5XSk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvblByZXNldERlYWN0aXZhdGUsXG4gICAgICAgICAgICAgICAgTWV0cmljLlBBRERJTkdfUFJFU0VULFxuICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgICAgY29sb3JNb2RlKTtcbiAgICAgICAgfTtcbiAgICAgICAgcHJlc2V0QnRuLnNldE9uQWN0aXZlKG9uUHJlc2V0QWN0aXZhdGUpO1xuICAgICAgICBwcmVzZXRCdG4uc2V0T25EZWFjdGl2ZShvblByZXNldERlYWN0aXZhdGUpO1xuICAgIH1cblxuICAgIGNvbG9yLmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50Lk1PVVNFX0RPV04sIHRoaXMuX29uQ29sb3JUcmlnZ2VyLmJpbmQodGhpcykpO1xuICAgIHRoaXMuX3VwZGF0ZUNvbG9yKCk7XG59XG5Db2xvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKE9iamVjdENvbXBvbmVudC5wcm90b3R5cGUpO1xuQ29sb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gQ29sb3I7XG5cbkNvbG9yLnByb3RvdHlwZS5fb25Db2xvclRyaWdnZXIgPSBmdW5jdGlvbigpe1xuICAgIHZhciBjb2xvck1vZGUgPSB0aGlzLl9jb2xvck1vZGUsXG4gICAgICAgIGNvbG9yTW9kZUhFWCA9IENvbG9yTW9kZS5IRVgsXG4gICAgICAgIGNvbG9yTW9kZVJHQiA9IENvbG9yTW9kZS5SR0IsXG4gICAgICAgIGNvbG9yTW9kZVJHQmZ2ID0gQ29sb3JNb2RlLlJHQmZ2LFxuICAgICAgICBjb2xvck1vZGVIU1YgPSBDb2xvck1vZGUuSFNWO1xuXG4gICAgdmFyIHZhbHVlID0gdGhpcy5fdmFsdWUsXG4gICAgICAgIHRlbXA7XG5cbiAgICB2YXIgb25QaWNrZXJQaWNrID0gZnVuY3Rpb24oKXtcbiAgICAgICAgdGhpcy5wdXNoSGlzdG9yeVN0YXRlKCk7XG5cbiAgICAgICAgc3dpdGNoKGNvbG9yTW9kZSl7XG4gICAgICAgICAgICBjYXNlIGNvbG9yTW9kZUhFWDpcbiAgICAgICAgICAgICAgICB0aGlzLl92YWx1ZSA9IFBpY2tlci5nZXQoKS5nZXRIRVgoKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgY29sb3JNb2RlUkdCOlxuICAgICAgICAgICAgICAgIC8vaWYgdmFsID0gRmxvYXQzMmFycmF5IG9yIHNvXG4gICAgICAgICAgICAgICAgdGVtcCA9IFBpY2tlci5nZXQoKS5nZXRSR0IoKTtcbiAgICAgICAgICAgICAgICB2YWx1ZVswXSA9IHRlbXBbMF07XG4gICAgICAgICAgICAgICAgdmFsdWVbMV0gPSB0ZW1wWzFdO1xuICAgICAgICAgICAgICAgIHZhbHVlWzJdID0gdGVtcFsyXTtcbiAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgY2FzZSBjb2xvck1vZGVSR0JmdjpcbiAgICAgICAgICAgICAgICB0ZW1wID0gUGlja2VyLmdldCgpLmdldFJHQmZ2KCk7XG4gICAgICAgICAgICAgICAgdmFsdWVbMF0gPSB0ZW1wWzBdO1xuICAgICAgICAgICAgICAgIHZhbHVlWzFdID0gdGVtcFsxXTtcbiAgICAgICAgICAgICAgICB2YWx1ZVsyXSA9IHRlbXBbMl07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgY29sb3JNb2RlSFNWOlxuICAgICAgICAgICAgICAgIHRoaXMuX3ZhbHVlID0gUGlja2VyLmdldCgpLmdldEhTVigpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5hcHBseVZhbHVlKCk7XG5cbiAgICB9LmJpbmQodGhpcyk7XG5cbiAgICB2YXIgcGlja2VyID0gUGlja2VyLmdldCgpO1xuXG4gICAgc3dpdGNoKGNvbG9yTW9kZSl7XG4gICAgICAgIGNhc2UgY29sb3JNb2RlSEVYOlxuICAgICAgICAgICAgcGlja2VyLnNldENvbG9ySEVYKHZhbHVlKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIGNvbG9yTW9kZVJHQjpcbiAgICAgICAgICAgIHBpY2tlci5zZXRDb2xvclJHQih2YWx1ZVswXSwgdmFsdWVbMV0sIHZhbHVlWzJdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIGNvbG9yTW9kZVJHQmZ2OlxuICAgICAgICAgICAgcGlja2VyLnNldENvbG9yUkdCZnYodmFsdWVbMF0sIHZhbHVlWzFdLCB2YWx1ZVsyXSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSBjb2xvck1vZGVIU1Y6XG4gICAgICAgICAgICBwaWNrZXIuc2V0Q29sb3JIU1YodmFsdWVbMF0sIHZhbHVlWzFdLCB2YWx1ZVsyXSk7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBwaWNrZXIuc2V0Q2FsbGJhY2tQaWNrKG9uUGlja2VyUGljayk7XG4gICAgcGlja2VyLm9wZW4oKTtcbn07XG5cbkNvbG9yLnByb3RvdHlwZS5hcHBseVZhbHVlID0gZnVuY3Rpb24oKXtcbiAgICB0aGlzLl9vYmpbdGhpcy5fa2V5XSA9IHRoaXMuX3ZhbHVlO1xuICAgIHRoaXMuX3VwZGF0ZUNvbG9yKCk7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgQ29tcG9uZW50RXZlbnQuVkFMVUVfVVBEQVRFRCwgbnVsbCkpO1xuICAgIHRoaXMuX29uQ2hhbmdlKHRoaXMuX29ialt0aGlzLl9rZXldKTtcbn07XG5cbkNvbG9yLnByb3RvdHlwZS5vblZhbHVlVXBkYXRlID0gZnVuY3Rpb24oZSl7XG4gICAgaWYoZS5kYXRhLm9yaWdpbiA9PSB0aGlzKXJldHVybjtcbiAgICB0aGlzLl92YWx1ZSA9IHRoaXMuX29ialt0aGlzLl9rZXldO1xuICAgIHRoaXMuX3VwZGF0ZUNvbG9yKCk7XG59O1xuXG5Db2xvci5wcm90b3R5cGUuX3VwZGF0ZUNvbG9yID0gZnVuY3Rpb24oKXtcbiAgICB2YXIgY29sb3IgPSB0aGlzLl92YWx1ZSxcbiAgICAgICAgY29sb3JOb2RlID0gdGhpcy5fY29sb3IsXG4gICAgICAgIG5vZGVDb2xvcjtcblxuICAgIGNvbG9yTm9kZS5zZXRQcm9wZXJ0eSgnaW5uZXJIVE1MJywgY29sb3IpO1xuXG4gICAgc3dpdGNoKHRoaXMuX2NvbG9yTW9kZSl7XG4gICAgICAgIGNhc2UgQ29sb3JNb2RlLkhFWDpcbiAgICAgICAgICAgIG5vZGVDb2xvciA9IGNvbG9yO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgY2FzZSBDb2xvck1vZGUuUkdCOlxuICAgICAgICAgICAgbm9kZUNvbG9yID0gQ29sb3JVdGlsLlJHQjJIRVgoY29sb3JbMF0sIGNvbG9yWzFdLCBjb2xvclsyXSk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIENvbG9yTW9kZS5SR0JmdjpcbiAgICAgICAgICAgIG5vZGVDb2xvciA9IENvbG9yVXRpbC5SR0JmdjJIRVgoY29sb3JbMF0sIGNvbG9yWzFdLCBjb2xvclsyXSk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIENvbG9yTW9kZS5IU1Y6XG4gICAgICAgICAgICBub2RlQ29sb3IgPSBDb2xvclV0aWwuSFNWMlJHQihjb2xvclswXSwgY29sb3JbMV0sIGNvbG9yWzJdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIGNvbG9yTm9kZS5nZXRTdHlsZSgpLmJhY2tncm91bmRDb2xvciA9IG5vZGVDb2xvcjtcbn07XG5cbkNvbG9yLnByb3RvdHlwZS5fdmFsaWRhdGVDb2xvckZvcm1hdCA9IGZ1bmN0aW9uKHZhbHVlLCBtc2dIZXgsIG1zZ0Fycil7XG4gICAgdmFyIGNvbG9yTW9kZSA9IHRoaXMuX2NvbG9yTW9kZTtcblxuICAgIGlmKGNvbG9yTW9kZSA9PSBDb2xvck1vZGUuSEVYICYmIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT09ICdbb2JqZWN0IEFycmF5XScgfHxcbiAgICAgICAgY29sb3JNb2RlID09IENvbG9yTW9kZS5IRVggJiYgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PT0gJ1tvYmplY3QgRmxvYXQzMkFycmF5XScpe1xuICAgICAgICB0aHJvdyBuZXcgQ29sb3JGb3JtYXRFcnJvcihtc2dIZXgpO1xuICAgIH1cbiAgICBpZigoY29sb3JNb2RlID09IENvbG9yTW9kZS5SR0IgfHxcbiAgICAgICAgY29sb3JNb2RlID09IENvbG9yTW9kZS5SR0JmdiB8fFxuICAgICAgICBjb2xvck1vZGUgPT0gQ29sb3JNb2RlLkhTVikgJiZcbiAgICAgICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSAhPT0gJ1tvYmplY3QgQXJyYXldJyB8fFxuICAgICAgICBjb2xvck1vZGUgPT0gQ29sb3JNb2RlLkhTViAmJlxuICAgICAgICBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpICE9PSAnW29iamVjdCBGbG9hdDMyQXJyYXldJyl7XG4gICAgICAgIHRocm93IG5ldyBDb2xvckZvcm1hdEVycm9yKG1zZ0Fycik7XG4gICAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBDb2xvcjtcbiIsInZhciBGdW5jdGlvblBsb3RUeXBlID0ge1xuICAgIElNUExJQ0lUOiAnaW1wbGljaXQnLFxuICAgIE5PTl9JTVBMSUNJVDogJ25vbkltcGxpY2l0J1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBGdW5jdGlvblBsb3RUeXBlOyIsInZhciBQbG90dGVyID0gcmVxdWlyZSgnLi9QbG90dGVyJyk7XG5cbnZhciBOb2RlID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Ob2RlJyk7XG52YXIgQ1NTID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9DU1MnKTtcbnZhciBGdW5jdGlvblBsb3RUeXBlID0gcmVxdWlyZSgnLi9GdW5jdGlvblBsb3RUeXBlJyk7XG5cblxudmFyIE1vdXNlID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Nb3VzZScpO1xudmFyIE1ldHJpYyA9IHJlcXVpcmUoJy4vTWV0cmljJyk7XG5cbnZhciBEb2N1bWVudEV2ZW50ICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvRG9jdW1lbnRFdmVudCcpLFxuICAgIENvbXBvbmVudEV2ZW50ID0gcmVxdWlyZSgnLi4vY29yZS9Db21wb25lbnRFdmVudCcpLFxuICAgIE5vZGVFdmVudCAgICAgID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Ob2RlRXZlbnQnKTtcblxudmFyIEZ1bmN0aW9uUGxvdHRlck9iamVjdEVycm9yICAgICAgID0gcmVxdWlyZSgnLi9GdW5jdGlvblBsb3R0ZXJPYmplY3RFcnJvcicpLFxuICAgIEZ1bmN0aW9uUGxvdHRlckZ1bmN0aW9uQXJnc0Vycm9yID0gcmVxdWlyZSgnLi9GdW5jdGlvblBsb3R0ZXJGdW5jdGlvbkFyZ3NFcnJvcicpO1xuXG52YXIgT2JqZWN0Q29tcG9uZW50Tm90aWZpZXIgPSByZXF1aXJlKCcuLi9jb3JlL09iamVjdENvbXBvbmVudE5vdGlmaWVyJyk7XG5cbnZhciBERUZBVUxUX1NIT1dfTUlOX01BWF9MQUJFTFMgPSB0cnVlO1xuXG52YXIgREVGQVVMVF9GVU5DVElPTl9QTE9UVEVSX05PTl9JTVBMSUNJVF9VTklUX1ggID0gIDEsXG4gICAgREVGQVVMVF9GVU5DVElPTl9QTE9UVEVSX05PTl9JTVBMSUNJVF9VTklUX1kgID0gIDEsXG4gICAgREVGQVVMVF9GVU5DVElPTl9QTE9UVEVSX0lNUExJQ0lUX1VOSVRfWCAgPSAwLjI1LFxuICAgIERFRkFVTFRfRlVOQ1RJT05fUExPVFRFUl9JTVBMSUNJVF9VTklUX1kgID0gMC4yNSxcbiAgICBERUZBVUxUX0ZVTkNUSU9OX1BMT1RURVJfVU5JVF9NSU4gID0gMC4xNSxcbiAgICBERUZBVUxUX0ZVTkNUSU9OX1BMT1RURVJfVU5JVF9NQVggID0gNCxcbiAgICBERUZBVUxUX0ZVTkNUSU9OX1BMT1RURVJfTk9OX0lNUExJQ0lUX1NDQUxFICA9IDEwLjAsXG4gICAgREVGQVVMVF9GVU5DVElPTl9QTE9UVEVSX0lNUExJQ0lUX1NDQUxFID0gMS4wLFxuICAgIERFRkFVTFRfRlVOQ1RJT05fUExPVFRFUl9TQ0FMRV9NSU4gPSAwLjAyLFxuICAgIERFRkFVTFRfRlVOQ1RJT05fUExPVFRFUl9TQ0FMRV9NQVggPSAyNSxcblxuICAgIERFRkFVTFRfRlVOQ1RJT05fUExPVFRFUl9JTVBMSUNJVF9BWEVTX0NPTE9SID0gJ3JnYmEoMjU1LDI1NSwyNTUsMC43NSknLFxuICAgIERFRkFVTFRfRlVOQ1RJT05fUExPVFRFUl9JTVBMSUNJVF9HUklEX0NPTE9SID0gJ3JnYmEoMjUsMjUsMjUsMC43NSknLFxuXG4gICAgREVGQVVMVF9GVU5DVElPTl9QTE9UVEVSX05PTl9JTVBMSUNJVF9BWEVTX0NPTE9SID0gJ3JnYig1NCw2MCw2NCknLFxuICAgIERFRkFVTFRfRlVOQ1RJT05fUExPVFRFUl9OT05fSU1QTElDSVRfR1JJRF9DT0xPUiA9ICdyZ2IoMjUsMjUsMjUpJyxcblxuICAgIERFRkFVTFRfRlVOQ1RJT05fUExPVFRFUl9DSVJDTEVfTEFCRUxfUkFESVVTID0gMyxcbiAgICBERUZBVUxUX0ZVTkNUSU9OX1BMT1RURVJfQ0lSQ0xFX0xBQkVMX0ZJTEwgICA9ICdyZ2IoMjU1LDI1NSwyNTUpJyxcbiAgICBERUZBVUxUX0ZVTkNUSU9OX1BMT1RURVJfQ0lSQ0xFX1NUUk9LRSAgICAgICA9ICcjYjEyMzM0JztcblxuZnVuY3Rpb24gRnVuY3Rpb25QbG90dGVyKHBhcmVudCwgb2JqZWN0LCB2YWx1ZSwgcGFyYW1zKSB7XG4gICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICAgIHBhcmFtcy5zaG93TWluTWF4TGFiZWxzID0gcGFyYW1zLnNob3dNaW5NYXhMYWJlbHMgPT09IHVuZGVmaW5lZCA/IERFRkFVTFRfU0hPV19NSU5fTUFYX0xBQkVMUyA6IHBhcmFtcy5zaG93TWluTWF4TGFiZWxzO1xuXG4gICAgUGxvdHRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuXG4gICAgaWYgKHR5cGVvZiBvYmplY3RbdmFsdWVdICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBGdW5jdGlvblBsb3R0ZXJPYmplY3RFcnJvcihvYmplY3QsdmFsdWUpO1xuICAgIH1cblxuICAgIHZhciBmdW5jQXJnTGVuZ3RoID0gb2JqZWN0W3ZhbHVlXS5sZW5ndGg7XG5cbiAgICBpZiAoZnVuY0FyZ0xlbmd0aCA+IDIgfHwgZnVuY0FyZ0xlbmd0aCA9PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBGdW5jdGlvblBsb3R0ZXJGdW5jdGlvbkFyZ3NFcnJvcigpO1xuICAgIH1cblxuICAgIHZhciBzdmdSb290ID0gdGhpcy5fc3ZnUm9vdCxcbiAgICAgICAgcGF0aCA9IHRoaXMuX3BhdGg7XG5cbiAgICB2YXIgYXhlcyA9IHRoaXMuX2F4ZXMgPSBzdmdSb290Lmluc2VydEJlZm9yZSh0aGlzLl9jcmVhdGVTVkdPYmplY3QoJ3BhdGgnKSwgcGF0aCk7XG4gICAgICAgIGF4ZXMuc3R5bGUuc3Ryb2tlV2lkdGggPSAxO1xuXG4gICAgdmFyIGF4ZXNMYWJlbHMgPSB0aGlzLl9heGVzTGFiZWxzID0gc3ZnUm9vdC5pbnNlcnRCZWZvcmUodGhpcy5fY3JlYXRlU1ZHT2JqZWN0KCdwYXRoJyksIHBhdGgpO1xuICAgICAgICBheGVzTGFiZWxzLnN0eWxlLnN0cm9rZSA9ICdyZ2IoNDMsNDgsNTEpJztcbiAgICAgICAgYXhlc0xhYmVscy5zdHlsZS5zdHJva2VXaWR0aCA9IDE7XG5cbiAgICB2YXIgZ3JpZCA9IHRoaXMuX2dyaWQ7XG5cbiAgICB2YXIgc3ZnID0gdGhpcy5fc3ZnLFxuICAgICAgICBzaXplID0gTnVtYmVyKHN2Zy5nZXRBdHRyaWJ1dGUoJ3dpZHRoJykpO1xuXG4gICAgdmFyIHNsaWRlclhXcmFwID0gbmV3IE5vZGUoKTtcbiAgICAgICAgc2xpZGVyWFdyYXAuc2V0U3R5bGVDbGFzcyhDU1MuR3JhcGhTbGlkZXJYV3JhcCk7XG5cbiAgICB2YXIgc2xpZGVyWVdyYXAgPSBuZXcgTm9kZSgpO1xuICAgICAgICBzbGlkZXJZV3JhcC5zZXRTdHlsZUNsYXNzKENTUy5HcmFwaFNsaWRlcllXcmFwKTtcblxuICAgIHZhciBzbGlkZXJYVHJhY2sgPSB0aGlzLl9zbGlkZXJYVHJhY2sgPSBuZXcgTm9kZSgpO1xuICAgICAgICBzbGlkZXJYVHJhY2suc2V0U3R5bGVDbGFzcyhDU1MuR3JhcGhTbGlkZXJYKTtcblxuICAgIHZhciBzbGlkZXJZVHJhY2sgPSB0aGlzLl9zbGlkZXJZVHJhY2sgPSBuZXcgTm9kZSgpO1xuICAgICAgICBzbGlkZXJZVHJhY2suc2V0U3R5bGVDbGFzcyhDU1MuR3JhcGhTbGlkZXJZKTtcblxuICAgIHZhciBzbGlkZXJYSGFuZGxlID0gdGhpcy5fc2xpZGVyWEhhbmRsZSA9IG5ldyBOb2RlKCk7XG4gICAgICAgIHNsaWRlclhIYW5kbGUuc2V0U3R5bGVDbGFzcyhDU1MuR3JhcGhTbGlkZXJYSGFuZGxlKTtcblxuICAgIHZhciBzbGlkZXJZSGFuZGxlID0gdGhpcy5fc2xpZGVyWUhhbmRsZSA9IG5ldyBOb2RlKCk7XG4gICAgICAgIHNsaWRlcllIYW5kbGUuc2V0U3R5bGVDbGFzcyhDU1MuR3JhcGhTbGlkZXJZSGFuZGxlKTtcblxuICAgIHNsaWRlclhUcmFjay5hZGRDaGlsZChzbGlkZXJYSGFuZGxlKTtcbiAgICBzbGlkZXJZVHJhY2suYWRkQ2hpbGQoc2xpZGVyWUhhbmRsZSk7XG4gICAgc2xpZGVyWFdyYXAuYWRkQ2hpbGQoc2xpZGVyWFRyYWNrKTtcbiAgICBzbGlkZXJZV3JhcC5hZGRDaGlsZChzbGlkZXJZVHJhY2spO1xuXG4gICAgdmFyIHdyYXBOb2RlID0gdGhpcy5fd3JhcE5vZGU7XG5cbiAgICB2YXIgcGxvdE1vZGUgPSB0aGlzLl9wbG90TW9kZSA9IGZ1bmNBcmdMZW5ndGggPT0gMSA/XG4gICAgICAgIEZ1bmN0aW9uUGxvdFR5cGUuTk9OX0lNUExJQ0lUIDpcbiAgICAgICAgRnVuY3Rpb25QbG90VHlwZS5JTVBMSUNJVDtcblxuICAgIGlmIChwbG90TW9kZSA9PSBGdW5jdGlvblBsb3RUeXBlLklNUExJQ0lUKSB7XG4gICAgICAgIHZhciBjYW52YXMgPSB0aGlzLl9jYW52YXMgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdjYW52YXMnKTtcbiAgICAgICAgY2FudmFzLnN0eWxlLndpZHRoID0gY2FudmFzLnN0eWxlLmhlaWdodCA9IHNpemUgKyAncHgnO1xuICAgICAgICBjYW52YXMud2lkdGggPSBjYW52YXMuaGVpZ2h0ID0gc2l6ZTtcblxuICAgICAgICB3cmFwTm9kZS5nZXRFbGVtZW50KCkuaW5zZXJ0QmVmb3JlKGNhbnZhcywgc3ZnKTtcblxuICAgICAgICB0aGlzLl9jYW52YXNDb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XG4gICAgICAgIHRoaXMuX2NhbnZhc0ltYWdlRGF0YSA9IHRoaXMuX2NhbnZhc0NvbnRleHQuZ2V0SW1hZ2VEYXRhKDAsIDAsIHNpemUsIHNpemUpO1xuXG4gICAgICAgIGF4ZXMuc3R5bGUuc3Ryb2tlID0gREVGQVVMVF9GVU5DVElPTl9QTE9UVEVSX0lNUExJQ0lUX0FYRVNfQ09MT1I7XG4gICAgICAgIGdyaWQuc3R5bGUuc3Ryb2tlID0gREVGQVVMVF9GVU5DVElPTl9QTE9UVEVSX0lNUExJQ0lUX0dSSURfQ09MT1I7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBheGVzLnN0eWxlLnN0cm9rZSA9IERFRkFVTFRfRlVOQ1RJT05fUExPVFRFUl9OT05fSU1QTElDSVRfQVhFU19DT0xPUjtcbiAgICAgICAgZ3JpZC5zdHlsZS5zdHJva2UgPSBERUZBVUxUX0ZVTkNUSU9OX1BMT1RURVJfTk9OX0lNUExJQ0lUX0dSSURfQ09MT1I7XG4gICAgfVxuXG4gICAgd3JhcE5vZGUuYWRkQ2hpbGQoc2xpZGVyWFdyYXApO1xuICAgIHdyYXBOb2RlLmFkZENoaWxkKHNsaWRlcllXcmFwKTtcblxuICAgIHNsaWRlclhIYW5kbGUuYWRkRXZlbnRMaXN0ZW5lcihOb2RlRXZlbnQuTU9VU0VfRE9XTiwgdGhpcy5fb25TbGlkZXJYSGFuZGxlRG93bi5iaW5kKHRoaXMpKTtcbiAgICBzbGlkZXJZSGFuZGxlLmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50Lk1PVVNFX0RPV04sIHRoaXMuX29uU2xpZGVyWUhhbmRsZURvd24uYmluZCh0aGlzKSk7XG5cbiAgICB2YXIgdW5pdHMgPSB0aGlzLl91bml0cyA9IFtudWxsLCBudWxsXTtcbiAgICB0aGlzLl9zY2FsZSA9IG51bGw7XG5cbiAgICBpZiAocGxvdE1vZGUgPT0gRnVuY3Rpb25QbG90VHlwZS5OT05fSU1QTElDSVQpIHtcbiAgICAgICAgdW5pdHNbMF0gPSBERUZBVUxUX0ZVTkNUSU9OX1BMT1RURVJfTk9OX0lNUExJQ0lUX1VOSVRfWDtcbiAgICAgICAgdW5pdHNbMV0gPSBERUZBVUxUX0ZVTkNUSU9OX1BMT1RURVJfTk9OX0lNUExJQ0lUX1VOSVRfWTtcblxuICAgICAgICB0aGlzLl9zY2FsZSA9IERFRkFVTFRfRlVOQ1RJT05fUExPVFRFUl9OT05fSU1QTElDSVRfU0NBTEU7XG4gICAgfVxuICAgIGVsc2UgaWYgKHBsb3RNb2RlID09IEZ1bmN0aW9uUGxvdFR5cGUuSU1QTElDSVQpIHtcbiAgICAgICAgdW5pdHNbMF0gPSBERUZBVUxUX0ZVTkNUSU9OX1BMT1RURVJfSU1QTElDSVRfVU5JVF9YO1xuICAgICAgICB1bml0c1sxXSA9IERFRkFVTFRfRlVOQ1RJT05fUExPVFRFUl9JTVBMSUNJVF9VTklUX1k7XG5cbiAgICAgICAgdGhpcy5fc2NhbGUgPSBERUZBVUxUX0ZVTkNUSU9OX1BMT1RURVJfSU1QTElDSVRfU0NBTEU7XG4gICAgfVxuXG4gICAgdGhpcy5fdW5pdHNNaW5NYXggPSBbREVGQVVMVF9GVU5DVElPTl9QTE9UVEVSX1VOSVRfTUlOLCBERUZBVUxUX0ZVTkNUSU9OX1BMT1RURVJfVU5JVF9NQVhdOyAvLzEvOC0+NFxuXG4gICAgdGhpcy5fc2NhbGVNaW5NYXggPSBbREVGQVVMVF9GVU5DVElPTl9QTE9UVEVSX1NDQUxFX01JTiwgREVGQVVMVF9GVU5DVElPTl9QTE9UVEVSX1NDQUxFX01BWF07IC8vMS81MCAtPiAyNVxuXG4gICAgdGhpcy5fY2VudGVyID0gW01hdGgucm91bmQoc2l6ZSAqIDAuNSksTWF0aC5yb3VuZChzaXplICogMC41KV07XG4gICAgdGhpcy5fc3ZnUG9zID0gWzAsIDBdO1xuXG4gICAgdGhpcy5fZnVuYyA9IG51bGw7XG4gICAgdGhpcy5zZXRGdW5jdGlvbih0aGlzLl9vYmpbdGhpcy5fa2V5XSk7XG5cbiAgICB0aGlzLl9zbGlkZXJYSGFuZGxlVXBkYXRlKCk7XG4gICAgdGhpcy5fc2xpZGVyWUhhbmRsZVVwZGF0ZSgpO1xuXG4gICAgc3ZnLmFkZEV2ZW50TGlzdGVuZXIoRG9jdW1lbnRFdmVudC5NT1VTRV9ET1dOLCB0aGlzLl9vbkRyYWdTdGFydC5iaW5kKHRoaXMpLCBmYWxzZSk7XG4gICAgdGhpcy5fd3JhcE5vZGUuZ2V0RWxlbWVudCgpLmFkZEV2ZW50TGlzdGVuZXIoXCJtb3VzZXdoZWVsXCIsIHRoaXMuX29uU2NhbGUuYmluZCh0aGlzLCBmYWxzZSkpO1xuXG4gICAgT2JqZWN0Q29tcG9uZW50Tm90aWZpZXIuZ2V0KCkuYWRkRXZlbnRMaXN0ZW5lcihDb21wb25lbnRFdmVudC5VUERBVEVfVkFMVUUsIHRoaXMsICdvblZhbHVlVXBkYXRlJyk7XG59XG5GdW5jdGlvblBsb3R0ZXIucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShQbG90dGVyLnByb3RvdHlwZSk7XG5GdW5jdGlvblBsb3R0ZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gRnVuY3Rpb25QbG90dGVyO1xuXG5GdW5jdGlvblBsb3R0ZXIucHJvdG90eXBlLl91cGRhdGVDZW50ZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHN2ZyA9IHRoaXMuX3N2ZyxcbiAgICAgICAgd2lkdGggPSBOdW1iZXIoc3ZnLmdldEF0dHJpYnV0ZSgnd2lkdGgnKSksXG4gICAgICAgIGhlaWdodCA9IE51bWJlcihzdmcuZ2V0QXR0cmlidXRlKCdoZWlnaHQnKSk7XG5cbiAgICB2YXIgbW91c2VQb3MgPSBNb3VzZS5nZXQoKS5nZXRQb3NpdGlvbigpLFxuICAgICAgICBzdmdQb3MgPSB0aGlzLl9zdmdQb3MsXG4gICAgICAgIGNlbnRlciA9IHRoaXMuX2NlbnRlcjtcblxuICAgIGNlbnRlclswXSA9IE1hdGgubWF4KDAsIE1hdGgubWluKG1vdXNlUG9zWzBdIC0gc3ZnUG9zWzBdLCB3aWR0aCkpO1xuICAgIGNlbnRlclsxXSA9IE1hdGgubWF4KDAsIE1hdGgubWluKG1vdXNlUG9zWzFdIC0gc3ZnUG9zWzFdLCBoZWlnaHQpKTtcblxuICAgIHRoaXMuX3Bsb3RHcmFwaCgpO1xufTtcblxuRnVuY3Rpb25QbG90dGVyLnByb3RvdHlwZS5fb25EcmFnU3RhcnQgPSBmdW5jdGlvbiAoZSkge1xuICAgIHZhciBzdmdQb3MgPSB0aGlzLl9zdmdQb3M7XG4gICAgc3ZnUG9zWzBdID0gMDtcbiAgICBzdmdQb3NbMV0gPSAwO1xuXG4gICAgLy9za2lwIHRvIGNvbnRhaW5lclxuICAgIHZhciBlbGVtZW50ID0gdGhpcy5fc3ZnLnBhcmVudE5vZGU7XG5cbiAgICB3aGlsZSAoZWxlbWVudCkge1xuICAgICAgICBzdmdQb3NbMF0gKz0gZWxlbWVudC5vZmZzZXRMZWZ0O1xuICAgICAgICBzdmdQb3NbMV0gKz0gZWxlbWVudC5vZmZzZXRUb3A7XG4gICAgICAgIGVsZW1lbnQgPSBlbGVtZW50Lm9mZnNldFBhcmVudDtcbiAgICB9XG5cbiAgICB2YXIgZXZlbnRNb3ZlID0gRG9jdW1lbnRFdmVudC5NT1VTRV9NT1ZFLFxuICAgICAgICBldmVudFVwID0gRG9jdW1lbnRFdmVudC5NT1VTRV9VUDtcblxuICAgIHZhciBvbkRyYWcgPSB0aGlzLl91cGRhdGVDZW50ZXIuYmluZCh0aGlzKSxcbiAgICAgICAgb25EcmFnRW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5fdXBkYXRlQ2VudGVyLmJpbmQodGhpcyk7XG4gICAgICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50TW92ZSwgb25EcmFnLCBmYWxzZSk7XG4gICAgICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50VXAsIG9uRHJhZ0VuZCwgZmFsc2UpO1xuXG4gICAgICAgIH0uYmluZCh0aGlzKTtcblxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRNb3ZlLCBvbkRyYWcsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50VXAsIG9uRHJhZ0VuZCwgZmFsc2UpO1xuXG4gICAgdGhpcy5fdXBkYXRlQ2VudGVyKCk7XG59O1xuXG5GdW5jdGlvblBsb3R0ZXIucHJvdG90eXBlLl9vblNjYWxlID0gZnVuY3Rpb24gKGUpIHtcbiAgICBlID0gd2luZG93LmV2ZW50IHx8IGU7XG4gICAgdGhpcy5fc2NhbGUgKz0gTWF0aC5tYXgoLTEsIE1hdGgubWluKDEsIChlLndoZWVsRGVsdGEgfHwgLWUuZGV0YWlsKSkpICogLTE7XG5cbiAgICB2YXIgc2NhbGVNaW5NYXggPSB0aGlzLl9zY2FsZU1pbk1heDtcbiAgICB0aGlzLl9zY2FsZSA9IE1hdGgubWF4KHNjYWxlTWluTWF4WzBdLCBNYXRoLm1pbih0aGlzLl9zY2FsZSwgc2NhbGVNaW5NYXhbMV0pKTtcblxuICAgIHRoaXMuX3Bsb3RHcmFwaCgpO1xuXG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG59O1xuXG5GdW5jdGlvblBsb3R0ZXIucHJvdG90eXBlLm9uVmFsdWVVcGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5zZXRGdW5jdGlvbih0aGlzLl9vYmpbdGhpcy5fa2V5XSk7XG59O1xuXG5GdW5jdGlvblBsb3R0ZXIucHJvdG90eXBlLl9yZWRyYXcgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuX3Bsb3RNb2RlID09IEZ1bmN0aW9uUGxvdFR5cGUuSU1QTElDSVQpIHtcbiAgICAgICAgdmFyIHNpemUgPSB0aGlzLl93cmFwTm9kZS5nZXRXaWR0aCgpLFxuICAgICAgICAgICAgY2FudmFzID0gdGhpcy5fY2FudmFzO1xuXG4gICAgICAgIGNhbnZhcy5zdHlsZS53aWR0aCA9IGNhbnZhcy5zdHlsZS5oZWlnaHQgPSBzaXplICsgJ3B4JztcbiAgICAgICAgY2FudmFzLndpZHRoID0gY2FudmFzLmhlaWdodCA9IHNpemU7XG5cbiAgICAgICAgdGhpcy5fY2FudmFzSW1hZ2VEYXRhID0gdGhpcy5fY2FudmFzQ29udGV4dC5nZXRJbWFnZURhdGEoMCwgMCwgc2l6ZSwgc2l6ZSk7XG4gICAgfVxuXG4gICAgdGhpcy5fc2xpZGVyWEhhbmRsZVVwZGF0ZSgpO1xuICAgIHRoaXMuX3NsaWRlcllIYW5kbGVVcGRhdGUoKTtcblxuICAgIHRoaXMuc2V0RnVuY3Rpb24odGhpcy5fb2JqW3RoaXMuX2tleV0pO1xufTtcblxuRnVuY3Rpb25QbG90dGVyLnByb3RvdHlwZS5zZXRGdW5jdGlvbiA9IGZ1bmN0aW9uIChmdW5jKSB7XG4gICAgdGhpcy5fZnVuYyA9IGZ1bmMuYmluZCh0aGlzLl9vYmopO1xuICAgIHRoaXMuX3Bsb3RHcmFwaCgpO1xufTtcblxuRnVuY3Rpb25QbG90dGVyLnByb3RvdHlwZS5fcGxvdEdyYXBoID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX2RyYXdHcmlkKCk7XG4gICAgdGhpcy5fZHJhd0F4ZXMoKTtcbiAgICB0aGlzLl9kcmF3UGxvdCgpO1xufTtcblxuRnVuY3Rpb25QbG90dGVyLnByb3RvdHlwZS5fZHJhd0F4ZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHN2ZyA9IHRoaXMuX3N2ZyxcbiAgICAgICAgc3ZnV2lkdGggPSBOdW1iZXIoc3ZnLmdldEF0dHJpYnV0ZSgnd2lkdGgnKSksXG4gICAgICAgIHN2Z0hlaWdodCA9IE51bWJlcihzdmcuZ2V0QXR0cmlidXRlKCdoZWlnaHQnKSk7XG5cbiAgICB2YXIgY2VudGVyID0gdGhpcy5fY2VudGVyLFxuICAgICAgICBjZW50ZXJYID0gY2VudGVyWzBdLFxuICAgICAgICBjZW50ZXJZID0gY2VudGVyWzFdO1xuXG4gICAgdmFyIHBhdGhDbWQgPSAnJztcbiAgICBwYXRoQ21kICs9IHRoaXMuX3BhdGhDbWRMaW5lKDAsIGNlbnRlclksIHN2Z1dpZHRoLCBjZW50ZXJZKTtcbiAgICBwYXRoQ21kICs9IHRoaXMuX3BhdGhDbWRMaW5lKGNlbnRlclgsIDAsIGNlbnRlclgsIHN2Z0hlaWdodCk7XG5cbiAgICB0aGlzLl9heGVzLnNldEF0dHJpYnV0ZSgnZCcsIHBhdGhDbWQpO1xufTtcblxuRnVuY3Rpb25QbG90dGVyLnByb3RvdHlwZS5fZHJhd1Bsb3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHdpZHRoLCBoZWlnaHQ7XG5cbiAgICB2YXIgY2VudGVyID0gdGhpcy5fY2VudGVyLFxuICAgICAgICBjZW50ZXJYID0gY2VudGVyWzBdLFxuICAgICAgICBjZW50ZXJZID0gY2VudGVyWzFdO1xuXG4gICAgdmFyIHVuaXRzID0gdGhpcy5fdW5pdHMsXG4gICAgICAgIHVuaXRYLCB1bml0WTtcblxuICAgIHZhciBzY2FsZSA9IHRoaXMuX3NjYWxlO1xuICAgIHZhciBub3JtdmFsLCBzY2FsZWRWYWwsIHZhbHVlLCBpbmRleDtcbiAgICB2YXIgb2Zmc2V0WCwgb2Zmc2V0WTtcblxuICAgIHZhciBpO1xuXG4gICAgaWYgKHRoaXMuX3Bsb3RNb2RlID09IEZ1bmN0aW9uUGxvdFR5cGUuTk9OX0lNUExJQ0lUKSB7XG4gICAgICAgIHZhciBzdmcgPSB0aGlzLl9zdmc7XG5cbiAgICAgICAgd2lkdGggPSBOdW1iZXIoc3ZnLmdldEF0dHJpYnV0ZSgnd2lkdGgnKSk7XG4gICAgICAgIGhlaWdodCA9IE51bWJlcihzdmcuZ2V0QXR0cmlidXRlKCdoZWlnaHQnKSk7XG4gICAgICAgIHVuaXRYID0gdW5pdHNbMF0gKiBzY2FsZTtcbiAgICAgICAgdW5pdFkgPSBoZWlnaHQgLyAodW5pdHNbMV0gKiBzY2FsZSk7XG4gICAgICAgIG9mZnNldFggPSBjZW50ZXJYIC8gd2lkdGg7XG5cbiAgICAgICAgdmFyIGxlbiA9IE1hdGguZmxvb3Iod2lkdGgpLFxuICAgICAgICAgICAgcG9pbnRzID0gbmV3IEFycmF5KGxlbiAqIDIpO1xuXG4gICAgICAgIGkgPSAtMTtcbiAgICAgICAgd2hpbGUgKCsraSA8IGxlbikge1xuICAgICAgICAgICAgbm9ybXZhbCA9ICgtb2Zmc2V0WCArIGkgLyBsZW4pO1xuICAgICAgICAgICAgc2NhbGVkVmFsID0gbm9ybXZhbCAqIHVuaXRYO1xuICAgICAgICAgICAgdmFsdWUgPSBjZW50ZXJZIC0gdGhpcy5fZnVuYyhzY2FsZWRWYWwpICogdW5pdFk7XG5cbiAgICAgICAgICAgIGluZGV4ID0gaSAqIDI7XG5cbiAgICAgICAgICAgIHBvaW50c1tpbmRleF0gPSBpO1xuICAgICAgICAgICAgcG9pbnRzW2luZGV4ICsgMV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwYXRoQ21kID0gJyc7XG4gICAgICAgIHBhdGhDbWQgKz0gdGhpcy5fcGF0aENtZE1vdmVUbyhwb2ludHNbMF0sIHBvaW50c1sxXSk7XG5cbiAgICAgICAgaSA9IDI7XG4gICAgICAgIHdoaWxlIChpIDwgcG9pbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgcGF0aENtZCArPSB0aGlzLl9wYXRoQ21kTGluZVRvKHBvaW50c1tpXSwgcG9pbnRzW2kgKyAxXSk7XG4gICAgICAgICAgICBpICs9IDI7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9wYXRoLnNldEF0dHJpYnV0ZSgnZCcsIHBhdGhDbWQpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIGNhbnZhcyA9IHRoaXMuX2NhbnZhcyxcbiAgICAgICAgICAgIGNvbnRleHQgPSB0aGlzLl9jYW52YXNDb250ZXh0LFxuICAgICAgICAgICAgaW1nRGF0YSA9IHRoaXMuX2NhbnZhc0ltYWdlRGF0YTtcblxuICAgICAgICB3aWR0aCA9IGNhbnZhcy53aWR0aDtcbiAgICAgICAgaGVpZ2h0ID0gY2FudmFzLmhlaWdodDtcblxuICAgICAgICB1bml0WCA9IHVuaXRzWzBdICogc2NhbGU7XG4gICAgICAgIHVuaXRZID0gdW5pdHNbMV0gKiBzY2FsZTtcblxuICAgICAgICBvZmZzZXRYID0gY2VudGVyWCAvIHdpZHRoO1xuICAgICAgICBvZmZzZXRZID0gY2VudGVyWSAvIGhlaWdodDtcblxuICAgICAgICB2YXIgaW52V2lkdGggPSAxIC8gd2lkdGgsXG4gICAgICAgICAgICBpbnZIZWlnaHQgPSAxIC8gaGVpZ2h0O1xuICAgICAgICB2YXIgcmdiID0gWzAsIDAsIDBdO1xuXG4gICAgICAgIHZhciBjb2wwID0gWzMwLCAzNCwgMzZdLFxuICAgICAgICAgICAgY29sMSA9IFsyNTUsIDI1NSwgMjU1XTtcblxuICAgICAgICBpID0gLTE7XG4gICAgICAgIHZhciBqO1xuICAgICAgICB3aGlsZSAoKytpIDwgaGVpZ2h0KSB7XG4gICAgICAgICAgICBqID0gLTE7XG5cbiAgICAgICAgICAgIHdoaWxlICgrK2ogPCB3aWR0aCkge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5fZnVuYygoLW9mZnNldFggKyBqICogaW52V2lkdGgpICogdW5pdFgsXG4gICAgICAgICAgICAgICAgICAgICgtb2Zmc2V0WSArIGkgKiBpbnZIZWlnaHQpICogdW5pdFkpO1xuXG4gICAgICAgICAgICAgICAgcmdiWzBdID0gTWF0aC5mbG9vcigoY29sMVswXSAtIGNvbDBbMF0pICogdmFsdWUgKyBjb2wwWzBdKTtcbiAgICAgICAgICAgICAgICByZ2JbMV0gPSBNYXRoLmZsb29yKChjb2wxWzFdIC0gY29sMFsxXSkgKiB2YWx1ZSArIGNvbDBbMV0pO1xuICAgICAgICAgICAgICAgIHJnYlsyXSA9IE1hdGguZmxvb3IoKGNvbDFbMl0gLSBjb2wwWzJdKSAqIHZhbHVlICsgY29sMFsyXSk7XG5cbiAgICAgICAgICAgICAgICBpbmRleCA9IChpICogd2lkdGggKyBqKSAqIDQ7XG5cbiAgICAgICAgICAgICAgICBpbWdEYXRhLmRhdGFbaW5kZXhdID0gcmdiWzBdO1xuICAgICAgICAgICAgICAgIGltZ0RhdGEuZGF0YVtpbmRleCArIDFdID0gcmdiWzFdO1xuICAgICAgICAgICAgICAgIGltZ0RhdGEuZGF0YVtpbmRleCArIDJdID0gcmdiWzJdO1xuICAgICAgICAgICAgICAgIGltZ0RhdGEuZGF0YVtpbmRleCArIDNdID0gMjU1O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29udGV4dC5jbGVhclJlY3QoMCwgMCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgIGNvbnRleHQucHV0SW1hZ2VEYXRhKGltZ0RhdGEsIDAsIDApO1xuICAgIH1cbn07XG5cbkZ1bmN0aW9uUGxvdHRlci5wcm90b3R5cGUuX2RyYXdHcmlkID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzdmcgPSB0aGlzLl9zdmcsXG4gICAgICAgIHdpZHRoID0gTnVtYmVyKHN2Zy5nZXRBdHRyaWJ1dGUoJ3dpZHRoJykpLFxuICAgICAgICBoZWlnaHQgPSBOdW1iZXIoc3ZnLmdldEF0dHJpYnV0ZSgnaGVpZ2h0JykpO1xuXG4gICAgdmFyIHNjYWxlID0gdGhpcy5fc2NhbGU7XG5cbiAgICB2YXIgZ3JpZFJlcyA9IHRoaXMuX3VuaXRzLFxuICAgICAgICBncmlkU3BhY2luZ1ggPSB3aWR0aCAvIChncmlkUmVzWzBdICogc2NhbGUpLFxuICAgICAgICBncmlkU3BhY2luZ1kgPSBoZWlnaHQgLyAoZ3JpZFJlc1sxXSAqIHNjYWxlKTtcblxuICAgIHZhciBjZW50ZXIgPSB0aGlzLl9jZW50ZXIsXG4gICAgICAgIGNlbnRlclggPSBjZW50ZXJbMF0sXG4gICAgICAgIGNlbnRlclkgPSBjZW50ZXJbMV07XG5cbiAgICB2YXIgZ3JpZE51bVRvcCA9IE1hdGgucm91bmQoY2VudGVyWSAvIGdyaWRTcGFjaW5nWSkgKyAxLFxuICAgICAgICBncmlkTnVtQm90dG9tID0gTWF0aC5yb3VuZCgoaGVpZ2h0IC0gY2VudGVyWSkgLyBncmlkU3BhY2luZ1kpICsgMSxcbiAgICAgICAgZ3JpZE51bUxlZnQgPSBNYXRoLnJvdW5kKGNlbnRlclggLyBncmlkU3BhY2luZ1gpICsgMSxcbiAgICAgICAgZ3JpZE51bVJpZ2h0ID0gTWF0aC5yb3VuZCgod2lkdGggLSBjZW50ZXJYKSAvIGdyaWRTcGFjaW5nWCkgKyAxO1xuXG4gICAgdmFyIHBhdGhDbWRHcmlkID0gJycsXG4gICAgICAgIHBhdGhDbWRBeGVzTGFiZWxzID0gJyc7XG5cbiAgICB2YXIgaSwgdGVtcDtcblxuICAgIHZhciBzdHJva2VTaXplID0gTWV0cmljLlNUUk9LRV9TSVpFO1xuXG4gICAgdmFyIGxhYmVsVGlja1NpemUgPSBNZXRyaWMuRlVOQ1RJT05fUExPVFRFUl9MQUJFTF9USUNLX1NJWkUsXG4gICAgICAgIGxhYmVsVGlja1BhZGRpbmdSaWdodCA9IHdpZHRoIC0gbGFiZWxUaWNrU2l6ZSAtIHN0cm9rZVNpemUsXG4gICAgICAgIGxhYmVsVGlja1BhZGRpbmdCb3R0b20gPSBoZWlnaHQgLSBsYWJlbFRpY2tTaXplIC0gc3Ryb2tlU2l6ZSxcbiAgICAgICAgbGFiZWxUaWNrUGFkZGluZ1JpZ2h0T2Zmc2V0ID0gbGFiZWxUaWNrUGFkZGluZ1JpZ2h0IC0gbGFiZWxUaWNrU2l6ZSxcbiAgICAgICAgbGFiZWxUaWNrUGFkZGluZ0JvdHRvbU9mZnNldCA9IGxhYmVsVGlja1BhZGRpbmdCb3R0b20gLSBsYWJlbFRpY2tTaXplLFxuICAgICAgICBsYWJlbFRpY2tPZmZzZXRSaWdodCA9IGxhYmVsVGlja1BhZGRpbmdSaWdodCAtIChsYWJlbFRpY2tTaXplICsgc3Ryb2tlU2l6ZSkgKiAyLFxuICAgICAgICBsYWJlbFRpY2tPZmZzZXRCb3R0b20gPSBsYWJlbFRpY2tQYWRkaW5nQm90dG9tIC0gKGxhYmVsVGlja1NpemUgKyBzdHJva2VTaXplKSAqIDI7XG5cbiAgICBpID0gLTE7XG4gICAgd2hpbGUgKCsraSA8IGdyaWROdW1Ub3ApIHtcbiAgICAgICAgdGVtcCA9IE1hdGgucm91bmQoY2VudGVyWSAtIGdyaWRTcGFjaW5nWSAqIGkpO1xuICAgICAgICBwYXRoQ21kR3JpZCArPSB0aGlzLl9wYXRoQ21kTGluZSgwLCB0ZW1wLCB3aWR0aCwgdGVtcCk7XG5cbiAgICAgICAgaWYgKHRlbXAgPiBsYWJlbFRpY2tTaXplKXtcbiAgICAgICAgICAgIHBhdGhDbWRBeGVzTGFiZWxzICs9IHRoaXMuX3BhdGhDbWRMaW5lKGxhYmVsVGlja1BhZGRpbmdSaWdodCwgdGVtcCxcbiAgICAgICAgICAgICAgICBsYWJlbFRpY2tQYWRkaW5nUmlnaHRPZmZzZXQsIHRlbXApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaSA9IC0xO1xuICAgIHdoaWxlICgrK2kgPCBncmlkTnVtQm90dG9tKSB7XG4gICAgICAgIHRlbXAgPSBNYXRoLnJvdW5kKGNlbnRlclkgKyBncmlkU3BhY2luZ1kgKiBpKTtcbiAgICAgICAgcGF0aENtZEdyaWQgKz0gdGhpcy5fcGF0aENtZExpbmUoMCwgdGVtcCwgd2lkdGgsIHRlbXApO1xuXG4gICAgICAgIGlmICh0ZW1wIDwgbGFiZWxUaWNrT2Zmc2V0Qm90dG9tKXtcbiAgICAgICAgICAgIHBhdGhDbWRBeGVzTGFiZWxzICs9IHRoaXMuX3BhdGhDbWRMaW5lKGxhYmVsVGlja1BhZGRpbmdSaWdodCwgdGVtcCxcbiAgICAgICAgICAgICAgICBsYWJlbFRpY2tQYWRkaW5nUmlnaHRPZmZzZXQsIHRlbXApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaSA9IC0xO1xuICAgIHdoaWxlICgrK2kgPCBncmlkTnVtTGVmdCkge1xuICAgICAgICB0ZW1wID0gTWF0aC5yb3VuZChjZW50ZXJYIC0gZ3JpZFNwYWNpbmdYICogaSk7XG4gICAgICAgIHBhdGhDbWRHcmlkICs9IHRoaXMuX3BhdGhDbWRMaW5lKHRlbXAsIDAsIHRlbXAsIGhlaWdodCk7XG5cbiAgICAgICAgaWYgKHRlbXAgPiBsYWJlbFRpY2tTaXplKXtcbiAgICAgICAgICAgIHBhdGhDbWRBeGVzTGFiZWxzICs9IHRoaXMuX3BhdGhDbWRMaW5lKHRlbXAsIGxhYmVsVGlja1BhZGRpbmdCb3R0b20sXG4gICAgICAgICAgICAgICAgdGVtcCwgbGFiZWxUaWNrUGFkZGluZ0JvdHRvbU9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpID0gLTE7XG4gICAgd2hpbGUgKCsraSA8IGdyaWROdW1SaWdodCkge1xuICAgICAgICB0ZW1wID0gTWF0aC5yb3VuZChjZW50ZXJYICsgZ3JpZFNwYWNpbmdYICogaSk7XG4gICAgICAgIHBhdGhDbWRHcmlkICs9IHRoaXMuX3BhdGhDbWRMaW5lKHRlbXAsIDAsIHRlbXAsIGhlaWdodCk7XG5cbiAgICAgICAgaWYgKHRlbXAgPCBsYWJlbFRpY2tPZmZzZXRSaWdodCl7XG4gICAgICAgICAgICBwYXRoQ21kQXhlc0xhYmVscyArPSB0aGlzLl9wYXRoQ21kTGluZSh0ZW1wLCBsYWJlbFRpY2tQYWRkaW5nQm90dG9tLFxuICAgICAgICAgICAgICAgIHRlbXAsIGxhYmVsVGlja1BhZGRpbmdCb3R0b21PZmZzZXQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5fZ3JpZC5zZXRBdHRyaWJ1dGUoJ2QnLCBwYXRoQ21kR3JpZCk7XG4gICAgdGhpcy5fYXhlc0xhYmVscy5zZXRBdHRyaWJ1dGUoJ2QnLCBwYXRoQ21kQXhlc0xhYmVscyk7XG59O1xuXG5cbkZ1bmN0aW9uUGxvdHRlci5wcm90b3R5cGUuX3NsaWRlclhTdGVwID0gZnVuY3Rpb24gKG1vdXNlUG9zKSB7XG4gICAgdmFyIG1vdXNlWCA9IG1vdXNlUG9zWzBdO1xuXG4gICAgdmFyIGhhbmRsZSA9IHRoaXMuX3NsaWRlclhIYW5kbGUsXG4gICAgICAgIGhhbmRsZVdpZHRoID0gaGFuZGxlLmdldFdpZHRoKCksXG4gICAgICAgIGhhbmRsZVdpZHRoSGFsZiA9IGhhbmRsZVdpZHRoICogMC41O1xuXG4gICAgdmFyIHRyYWNrID0gdGhpcy5fc2xpZGVyWFRyYWNrLFxuICAgICAgICB0cmFja1dpZHRoID0gdHJhY2suZ2V0V2lkdGgoKSxcbiAgICAgICAgdHJhY2tMZWZ0ID0gdHJhY2suZ2V0UG9zaXRpb25HbG9iYWxYKCk7XG5cbiAgICB2YXIgc3Ryb2tlU2l6ZSA9IE1ldHJpYy5TVFJPS0VfU0laRTtcblxuICAgIHZhciBtYXggPSB0cmFja1dpZHRoIC0gaGFuZGxlV2lkdGhIYWxmIC0gc3Ryb2tlU2l6ZSAqIDI7XG5cbiAgICB2YXIgcG9zID0gTWF0aC5tYXgoaGFuZGxlV2lkdGhIYWxmLCBNYXRoLm1pbihtb3VzZVggLSB0cmFja0xlZnQsIG1heCkpLFxuICAgICAgICBoYW5kbGVQb3MgPSBwb3MgLSBoYW5kbGVXaWR0aEhhbGY7XG5cbiAgICBoYW5kbGUuc2V0UG9zaXRpb25YKGhhbmRsZVBvcyk7XG5cbiAgICB2YXIgdW5pdHNNaW4gPSB0aGlzLl91bml0c01pbk1heFswXSxcbiAgICAgICAgdW5pdHNNYXggPSB0aGlzLl91bml0c01pbk1heFsxXTtcblxuICAgIHZhciBub3JtVmFsID0gKHBvcyAtIGhhbmRsZVdpZHRoSGFsZikgLyAobWF4IC0gaGFuZGxlV2lkdGhIYWxmKSxcbiAgICAgICAgbWFwcGVkVmFsID0gdW5pdHNNaW4gKyAodW5pdHNNYXggLSB1bml0c01pbikgKiBub3JtVmFsO1xuXG4gICAgdGhpcy5fdW5pdHNbMF0gPSBtYXBwZWRWYWw7XG5cbiAgICB0aGlzLl9wbG90R3JhcGgoKTtcbn07XG5cbkZ1bmN0aW9uUGxvdHRlci5wcm90b3R5cGUuX3NsaWRlcllTdGVwID0gZnVuY3Rpb24gKG1vdXNlUG9zKSB7XG4gICAgdmFyIG1vdXNlWSA9IG1vdXNlUG9zWzFdO1xuXG4gICAgdmFyIGhhbmRsZSA9IHRoaXMuX3NsaWRlcllIYW5kbGUsXG4gICAgICAgIGhhbmRsZUhlaWdodCA9IGhhbmRsZS5nZXRIZWlnaHQoKSxcbiAgICAgICAgaGFuZGxlSGVpZ2h0SGFsZiA9IGhhbmRsZUhlaWdodCAqIDAuNTtcblxuICAgIHZhciB0cmFjayA9IHRoaXMuX3NsaWRlcllUcmFjayxcbiAgICAgICAgdHJhY2tIZWlnaHQgPSB0cmFjay5nZXRIZWlnaHQoKSxcbiAgICAgICAgdHJhY2tUb3AgPSB0cmFjay5nZXRQb3NpdGlvbkdsb2JhbFkoKTtcblxuICAgIHZhciBtYXggPSB0cmFja0hlaWdodCAtIGhhbmRsZUhlaWdodEhhbGYgLSAyO1xuXG4gICAgdmFyIHBvcyA9IE1hdGgubWF4KGhhbmRsZUhlaWdodEhhbGYsIE1hdGgubWluKG1vdXNlWSAtIHRyYWNrVG9wLCBtYXgpKSxcbiAgICAgICAgaGFuZGxlUG9zID0gcG9zIC0gaGFuZGxlSGVpZ2h0SGFsZjtcblxuICAgIGhhbmRsZS5zZXRQb3NpdGlvblkoaGFuZGxlUG9zKTtcblxuICAgIHZhciB1bml0c01heCA9IHRoaXMuX3VuaXRzTWluTWF4WzBdLFxuICAgICAgICB1bml0c01pbiA9IHRoaXMuX3VuaXRzTWluTWF4WzFdO1xuXG4gICAgdmFyIG5vcm1WYWwgPSAocG9zIC0gaGFuZGxlSGVpZ2h0SGFsZikgLyAobWF4IC0gaGFuZGxlSGVpZ2h0SGFsZiksXG4gICAgICAgIG1hcHBlZFZhbCA9IHVuaXRzTWluICsgKHVuaXRzTWF4IC0gdW5pdHNNaW4pICogbm9ybVZhbDtcblxuICAgIHRoaXMuX3VuaXRzWzFdID0gbWFwcGVkVmFsO1xuXG4gICAgdGhpcy5fcGxvdEdyYXBoKCk7XG59O1xuXG5GdW5jdGlvblBsb3R0ZXIucHJvdG90eXBlLl9vblNsaWRlclhIYW5kbGVEb3duID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX29uU2xpZGVySGFuZGxlRG93bih0aGlzLl9zbGlkZXJYU3RlcC5iaW5kKHRoaXMpKTtcbn07XG5cbkZ1bmN0aW9uUGxvdHRlci5wcm90b3R5cGUuX29uU2xpZGVyWUhhbmRsZURvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5fb25TbGlkZXJIYW5kbGVEb3duKHRoaXMuX3NsaWRlcllTdGVwLmJpbmQodGhpcykpO1xufTtcblxuRnVuY3Rpb25QbG90dGVyLnByb3RvdHlwZS5fb25TbGlkZXJIYW5kbGVEb3duID0gZnVuY3Rpb24gKHNsaWRlclN0ZXBGdW5jKSB7XG4gICAgdmFyIGV2ZW50TW91c2VNb3ZlID0gRG9jdW1lbnRFdmVudC5NT1VTRV9NT1ZFLFxuICAgICAgICBldmVudE1vdXNlVXAgPSBEb2N1bWVudEV2ZW50Lk1PVVNFX1VQO1xuXG4gICAgdmFyIG1vdXNlID0gTW91c2UuZ2V0KCk7XG5cbiAgICB2YXIgb25EcmFnID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc2xpZGVyU3RlcEZ1bmMobW91c2UuZ2V0UG9zaXRpb24oKSlcbiAgICAgICAgfSxcbiAgICAgICAgb25EcmFnRW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE1vdXNlTW92ZSwgb25EcmFnLCBmYWxzZSk7XG4gICAgICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50TW91c2VVcCwgb25EcmFnRW5kLCBmYWxzZSk7XG4gICAgICAgIH07XG5cbiAgICBzbGlkZXJTdGVwRnVuYyhtb3VzZS5nZXRQb3NpdGlvbigpKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TW91c2VNb3ZlLCBvbkRyYWcsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TW91c2VVcCwgb25EcmFnRW5kLCBmYWxzZSk7XG59O1xuXG5GdW5jdGlvblBsb3R0ZXIucHJvdG90eXBlLl9zbGlkZXJYSGFuZGxlVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciB1bml0TWluID0gdGhpcy5fdW5pdHNNaW5NYXhbMF0sXG4gICAgICAgIHVuaXRNYXggPSB0aGlzLl91bml0c01pbk1heFsxXSxcbiAgICAgICAgdW5pdFggPSB0aGlzLl91bml0c1swXTtcblxuICAgIHZhciBoYW5kbGVYID0gdGhpcy5fc2xpZGVyWEhhbmRsZSxcbiAgICAgICAgaGFuZGxlWFdpZHRoID0gaGFuZGxlWC5nZXRXaWR0aCgpLFxuICAgICAgICBoYW5kbGVYV2lkdGhIYWxmID0gaGFuZGxlWFdpZHRoICogMC41LFxuICAgICAgICB0cmFja1hXaWR0aCA9IHRoaXMuX3NsaWRlclhUcmFjay5nZXRXaWR0aCgpO1xuXG4gICAgdmFyIHN0cm9rZVNpemUgPSBNZXRyaWMuU1RST0tFX1NJWkU7XG5cbiAgICB2YXIgaGFuZGxlWE1pbiA9IGhhbmRsZVhXaWR0aEhhbGYsXG4gICAgICAgIGhhbmRsZVhNYXggPSB0cmFja1hXaWR0aCAtIGhhbmRsZVhXaWR0aEhhbGYgLSBzdHJva2VTaXplICogMjtcblxuICAgIGhhbmRsZVguc2V0UG9zaXRpb25YKChoYW5kbGVYTWluICsgKGhhbmRsZVhNYXggLSBoYW5kbGVYTWluKSAqICgodW5pdFggLSB1bml0TWluKSAvICh1bml0TWF4IC0gdW5pdE1pbikpKSAtIGhhbmRsZVhXaWR0aEhhbGYpO1xufTtcblxuRnVuY3Rpb25QbG90dGVyLnByb3RvdHlwZS5fc2xpZGVyWUhhbmRsZVVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgdW5pdE1pbiA9IHRoaXMuX3VuaXRzTWluTWF4WzBdLFxuICAgICAgICB1bml0TWF4ID0gdGhpcy5fdW5pdHNNaW5NYXhbMV0sXG4gICAgICAgIHVuaXRZID0gdGhpcy5fdW5pdHNbMV07XG5cbiAgICB2YXIgaGFuZGxlWSA9IHRoaXMuX3NsaWRlcllIYW5kbGUsXG4gICAgICAgIGhhbmRsZVlIZWlnaHQgPSBoYW5kbGVZLmdldEhlaWdodCgpLFxuICAgICAgICBoYW5kbGVZSGVpZ2h0SGFsZiA9IGhhbmRsZVlIZWlnaHQgKiAwLjUsXG4gICAgICAgIHRyYWNrWUhlaWdodCA9IHRoaXMuX3NsaWRlcllUcmFjay5nZXRIZWlnaHQoKTtcblxuICAgIHZhciBzdHJva2VTaXplID0gTWV0cmljLlNUUk9LRV9TSVpFO1xuXG4gICAgdmFyIGhhbmRsZVlNaW4gPSB0cmFja1lIZWlnaHQgLSBoYW5kbGVZSGVpZ2h0SGFsZiAtIHN0cm9rZVNpemUgKiAyLFxuICAgICAgICBoYW5kbGVZTWF4ID0gaGFuZGxlWUhlaWdodEhhbGY7XG5cbiAgICBoYW5kbGVZLnNldFBvc2l0aW9uWSgoaGFuZGxlWU1pbiArIChoYW5kbGVZTWF4IC0gaGFuZGxlWU1pbikgKiAoKHVuaXRZIC0gdW5pdE1pbikgLyAodW5pdE1heCAtIHVuaXRNaW4pKSkgLSBoYW5kbGVZSGVpZ2h0SGFsZik7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEZ1bmN0aW9uUGxvdHRlcjsiLCJmdW5jdGlvbiBGdW5jdGlvblBsb3R0ZXJGdW5jdGlvbkFyZ3NFcnJvcigpe1xuXHRFcnJvci5hcHBseSh0aGlzKTtcblx0RXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcyxGdW5jdGlvblBsb3R0ZXJGdW5jdGlvbkFyZ3NFcnJvcik7XG5cdHRoaXMubmFtZSA9ICdGdW5jdGlvblBsb3R0ZXJGdW5jdGlvbkFyZ3NFcnJvcic7XG5cdHRoaXMubWVzc2FnZSA9ICdGdW5jdGlvbiBzaG91bGQgYmUgb2YgZm9ybSBmKHgpIG9yIGYoeCx5KS4nO1xufVxuRnVuY3Rpb25QbG90dGVyRnVuY3Rpb25BcmdzRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFcnJvci5wcm90b3R5cGUpO1xuRnVuY3Rpb25QbG90dGVyRnVuY3Rpb25BcmdzRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gRnVuY3Rpb25QbG90dGVyRnVuY3Rpb25BcmdzRXJyb3I7XG5cbm1vZHVsZS5leHBvcnRzID0gRnVuY3Rpb25QbG90dGVyRnVuY3Rpb25BcmdzRXJyb3I7IiwiZnVuY3Rpb24gRnVuY3Rpb25QbG90dGVyT2JqZWN0RXJyb3Iob2JqZWN0LGtleSl7XG5cdEVycm9yLmFwcGx5KHRoaXMpO1xuXHRFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLEZ1bmN0aW9uUGxvdHRlck9iamVjdEVycm9yKTtcblx0dGhpcy5uYW1lID0gJ0NvbXBvbmVudE9iamVjdEVycm9yJztcblx0dGhpcy5tZXNzYWdlID0gJ09iamVjdCAnICsgb2JqZWN0LmNvbnN0cnVjdG9yLm5hbWUgKyAnICcgKyBrZXkgKyAnc2hvdWxkIGJlIG9mIHR5cGUgRnVuY3Rpb24uJztcbn1cbkZ1bmN0aW9uUGxvdHRlck9iamVjdEVycm9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXJyb3IucHJvdG90eXBlKTtcbkZ1bmN0aW9uUGxvdHRlck9iamVjdEVycm9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEZ1bmN0aW9uUGxvdHRlck9iamVjdEVycm9yO1xuXG5tb2R1bGUuZXhwb3J0cyA9IEZ1bmN0aW9uUGxvdHRlck9iamVjdEVycm9yOyIsInZhciBNZXRyaWMgPSB7XG5cdENPTVBPTkVOVF9NSU5fSEVJR0hUOiAyNSxcblx0U1RST0tFX1NJWkU6IDEsXG5cdFBBRERJTkdfV1JBUFBFUjogMTIsXG5cdFBBRERJTkdfT1BUSU9OUzogMixcblx0UEFERElOR19QUkVTRVQ6IDIwLFxuXG5cdFNDUk9MTEJBUl9UUkFDS19QQURESU5HOiAyLFxuXHRGVU5DVElPTl9QTE9UVEVSX0xBQkVMX1RJQ0tfU0laRTogNlxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBNZXRyaWM7IiwidmFyIE9iamVjdENvbXBvbmVudCA9IHJlcXVpcmUoJy4uL2NvcmUvT2JqZWN0Q29tcG9uZW50Jyk7XG52YXIgTnVtYmVySW5wdXRfSW50ZXJuYWwgPSByZXF1aXJlKCcuL051bWJlcklucHV0X0ludGVybmFsJyk7XG5cbnZhciBOb2RlID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Ob2RlJyk7XG5cbnZhciBPcHRpb25zID0gcmVxdWlyZSgnLi9PcHRpb25zJyk7XG52YXIgQnV0dG9uUHJlc2V0ID0gcmVxdWlyZSgnLi9CdXR0b25QcmVzZXQnKTtcbnZhciBDU1MgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L0NTUycpLFxuICAgIE1ldHJpYyA9IHJlcXVpcmUoJy4vTWV0cmljJyk7XG5cbnZhciBFdmVudF8gPSByZXF1aXJlKCcuLi9jb3JlL2V2ZW50L0V2ZW50JyksXG4gICAgRG9jdW1lbnRFdmVudCA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvRG9jdW1lbnRFdmVudCcpLFxuICAgIE5vZGVFdmVudCA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZUV2ZW50JyksXG4gICAgQ29tcG9uZW50RXZlbnQgPSByZXF1aXJlKCcuLi9jb3JlL0NvbXBvbmVudEV2ZW50Jyk7XG5cbnZhciBERUZBVUxUX0lOUFVUX0RQICAgICA9IDIsXG4gICAgREVGQVVMVF9JTlBVVF9TVEVQICAgPSAxLFxuICAgIERFRkFVTFRfSU5QVVRfUFJFU0VUID0gbnVsbDtcblxuXG5cbmZ1bmN0aW9uIE51bWJlcklucHV0KHBhcmVudCxvYmplY3QsdmFsdWUscGFyYW1zKSB7XG4gICAgT2JqZWN0Q29tcG9uZW50LmFwcGx5KHRoaXMsYXJndW1lbnRzKTtcblxuICAgIHBhcmFtcyAgICAgICAgICA9IHBhcmFtcyB8fCB7fTtcbiAgICBwYXJhbXMub25CZWdpbiAgPSBwYXJhbXMub25CZWdpbiB8fCBudWxsO1xuICAgIHBhcmFtcy5vbkNoYW5nZSA9IHBhcmFtcy5vbkNoYW5nZSB8fCB0aGlzLl9vbkNoYW5nZTtcbiAgICBwYXJhbXMub25GaW5pc2ggPSBwYXJhbXMub25GaW5pc2ggfHwgbnVsbDtcbiAgICBwYXJhbXMub25FcnJvciAgPSBwYXJhbXMub25FcnJvciB8fCBudWxsO1xuICAgIHBhcmFtcy5kcCAgICAgICA9IChwYXJhbXMuZHAgPT09IHVuZGVmaW5lZCB8fCBwYXJhbXMuZHAgPT0gbnVsbCkgPyBERUZBVUxUX0lOUFVUX0RQIDogcGFyYW1zLmRwO1xuICAgIHBhcmFtcy5zdGVwICAgICA9IHBhcmFtcy5zdGVwICAgICB8fCBERUZBVUxUX0lOUFVUX1NURVA7XG4gICAgcGFyYW1zLnByZXNldHMgID0gcGFyYW1zLnByZXNldHMgIHx8IERFRkFVTFRfSU5QVVRfUFJFU0VUO1xuXG4gICAgdGhpcy5fb25CZWdpbiAgICAgPSBwYXJhbXMub25CZWdpbjtcbiAgICB0aGlzLl9vbkNoYW5nZSAgICA9IHBhcmFtcy5vbkNoYW5nZTtcbiAgICB0aGlzLl9wcmVzZXRzS2V5ICA9IHBhcmFtcy5wcmVzZXRzO1xuXG4gICAgdmFyIGlucHV0ID0gdGhpcy5faW5wdXQgPSBuZXcgTnVtYmVySW5wdXRfSW50ZXJuYWwocGFyYW1zLnN0ZXAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zLmRwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhcmFtcy5vbkJlZ2luLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX29uSW5wdXRDaGFuZ2UuYmluZCh0aGlzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJhbXMub25GaW5pc2gsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyYW1zLm9uRXJyb3IpO1xuXG4gICAgdmFyIHdyYXAgPSB0aGlzLl93cmFwTm9kZTtcblxuICAgIHZhciBwcmVzZXRzID0gIHBhcmFtcy5wcmVzZXRzO1xuICAgIGlmICghcHJlc2V0cykge1xuICAgICAgICB3cmFwLmFkZENoaWxkKGlucHV0LmdldE5vZGUoKSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB2YXIgd3JhcF8gPSBuZXcgTm9kZSgpO1xuICAgICAgICAgICAgd3JhcF8uc2V0U3R5bGVDbGFzcyhDU1MuV3JhcElucHV0V1ByZXNldCk7XG5cbiAgICAgICAgd3JhcC5hZGRDaGlsZCh3cmFwXyk7XG4gICAgICAgIHdyYXBfLmFkZENoaWxkKGlucHV0LmdldE5vZGUoKSk7XG5cbiAgICAgICAgdmFyIG9wdGlvbnMgICA9IE9wdGlvbnMuZ2V0KCk7XG4gICAgICAgIHZhciBwcmVzZXRCdG4gPSB0aGlzLl9idG5QcmVzZXQgPSBuZXcgQnV0dG9uUHJlc2V0KHRoaXMuX3dyYXBOb2RlKTtcblxuICAgICAgICB2YXIgb25QcmVzZXREZWFjdGl2YXRlID0gZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIG9wdGlvbnMuY2xlYXIoKTtcbiAgICAgICAgICAgIHByZXNldEJ0bi5kZWFjdGl2YXRlKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgICAgICB2YXIgb25QcmVzZXRBY3RpdmF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIG9wdGlvbnMuYnVpbGQocHJlc2V0cywgaW5wdXQuZ2V0VmFsdWUoKSwgaW5wdXQuZ2V0Tm9kZSgpLFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQuc2V0VmFsdWUocHJlc2V0c1tvcHRpb25zLmdldFNlbGVjdGVkSW5kZXgoKV0pO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLmFwcGx5VmFsdWUoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5fb25DaGFuZ2Uoc2VsZi5fb2JqW3NlbGYuX2tleV0pO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgb25QcmVzZXREZWFjdGl2YXRlLCBNZXRyaWMuUEFERElOR19QUkVTRVQsXG4gICAgICAgICAgICAgICAgZmFsc2UpO1xuICAgICAgICB9O1xuICAgICAgICBwcmVzZXRCdG4uc2V0T25BY3RpdmUob25QcmVzZXRBY3RpdmF0ZSk7XG4gICAgICAgIHByZXNldEJ0bi5zZXRPbkRlYWN0aXZlKG9uUHJlc2V0RGVhY3RpdmF0ZSlcbiAgICB9XG5cbiAgICBpbnB1dC5nZXROb2RlKCkuYWRkRXZlbnRMaXN0ZW5lcihOb2RlRXZlbnQuTU9VU0VfRE9XTiwgICB0aGlzLl9vbklucHV0RHJhZ1N0YXJ0LmJpbmQodGhpcykpO1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcihDb21wb25lbnRFdmVudC5JTlBVVF9TRUxFQ1RfRFJBRyx0aGlzLl9wYXJlbnQsJ29uQ29tcG9uZW50U2VsZWN0RHJhZycpO1xuXG4gICAgaW5wdXQuc2V0VmFsdWUodGhpcy5fb2JqW3RoaXMuX2tleV0pO1xufVxuTnVtYmVySW5wdXQucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShPYmplY3RDb21wb25lbnQucHJvdG90eXBlKTtcbk51bWJlcklucHV0LnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IE51bWJlcklucHV0O1xuXG5OdW1iZXJJbnB1dC5wcm90b3R5cGUuX29uSW5wdXRDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5hcHBseVZhbHVlKCk7XG4gICAgdGhpcy5fb25DaGFuZ2UodGhpcy5fb2JqW3RoaXMuX2tleV0pO1xufTtcblxuTnVtYmVySW5wdXQucHJvdG90eXBlLmFwcGx5VmFsdWUgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLnB1c2hIaXN0b3J5U3RhdGUoKTtcbiAgICB0aGlzLl9vYmpbdGhpcy5fa2V5XSA9IHRoaXMuX2lucHV0LmdldFZhbHVlKCk7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcyxDb21wb25lbnRFdmVudC5WQUxVRV9VUERBVEVELG51bGwpKTtcbn07XG5cbk51bWJlcklucHV0LnByb3RvdHlwZS5vblZhbHVlVXBkYXRlID0gZnVuY3Rpb24gKGUpIHtcbiAgICBpZiAoZS5kYXRhLm9yaWdpbiA9PSB0aGlzKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLl9pbnB1dC5zZXRWYWx1ZSh0aGlzLl9vYmpbdGhpcy5fa2V5XSk7XG59O1xuXG4vL1ByZXZlbnQgY2hyb21lIHNlbGVjdCBkcmFnXG5OdW1iZXJJbnB1dC5wcm90b3R5cGUuX29uSW5wdXREcmFnU3RhcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV2ZW50TW92ZSA9IERvY3VtZW50RXZlbnQuTU9VU0VfTU9WRSxcbiAgICAgICAgZXZlbnRVcCA9IERvY3VtZW50RXZlbnQuTU9VU0VfVVA7XG5cbiAgICB2YXIgZXZlbnQgPSBDb21wb25lbnRFdmVudC5JTlBVVF9TRUxFQ1RfRFJBRztcblxuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIHZhciBvbkRyYWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzZWxmLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50Xyh0aGlzLCBldmVudCwgbnVsbCkpO1xuICAgICAgICB9LFxuICAgICAgICBvbkRyYWdGaW5pc2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzZWxmLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50Xyh0aGlzLCBldmVudCwgbnVsbCkpO1xuICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE1vdmUsIG9uRHJhZywgZmFsc2UpO1xuICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE1vdmUsIG9uRHJhZ0ZpbmlzaCwgZmFsc2UpO1xuICAgICAgICB9O1xuXG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgZXZlbnQsIG51bGwpKTtcblxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRNb3ZlLCBvbkRyYWcsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50VXAsIG9uRHJhZ0ZpbmlzaCwgZmFsc2UpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBOdW1iZXJJbnB1dDsiLCJ2YXIgRXZlbnREaXNwYXRjaGVyID0gcmVxdWlyZSgnLi4vY29yZS9ldmVudC9FdmVudERpc3BhdGNoZXInKSxcbiAgICBOb2RlRXZlbnQgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L05vZGVFdmVudCcpO1xudmFyIE5vZGUgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZScpO1xuXG52YXIgUFJFU0VUX1NISUZUX01VTFRJUExJRVIgID0gMTA7XG52YXIgTlVNX1JFR0VYID0gL14tP1xcZCpcXC4/XFxkKiQvO1xuXG52YXIgc2V0Q2FyZXRQb3MgPSBudWxsLFxuICAgIHNlbGVjdEFsbCA9IG51bGw7XG5cbmZ1bmN0aW9uIGlucHV0U2V0VmFsdWUoaW5wdXQsdmFsdWUpe1xuICAgIGlucHV0LnNldFByb3BlcnR5KCd2YWx1ZScsdmFsdWUpO1xuICAgIGlucHV0LmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdpbnB1dCcpKTtcbn1cblxuTnVtYmVySW5wdXRfSW50ZXJuYWwgPSBmdW5jdGlvbiAoc3RlcFZhbHVlLCBkcCwgb25CZWdpbiwgb25DaGFuZ2UsIG9uRmluaXNoLCBvbkVycm9yKSB7XG4gICAgRXZlbnREaXNwYXRjaGVyLmFwcGx5KHRoaXMsIG51bGwpO1xuXG4gICAgdGhpcy5fdmFsdWUgPSAwO1xuICAgIHRoaXMuX3ZhbHVlU3RlcCA9IHN0ZXBWYWx1ZTtcbiAgICB0aGlzLl92YWx1ZURwICAgPSBkcDtcblxuICAgIHRoaXMuX29uQmVnaW4gPSBvbkJlZ2luIHx8IGZ1bmN0aW9uICgpe307XG4gICAgdGhpcy5fb25DaGFuZ2UgPSBvbkNoYW5nZSB8fCBmdW5jdGlvbiAoKSB7fTtcbiAgICB0aGlzLl9vbkZpbmlzaCA9IG9uRmluaXNoIHx8IGZ1bmN0aW9uKCkge307XG4gICAgdGhpcy5fb25FcnJvciA9IG9uRXJyb3IgfHwgZnVuY3Rpb24oKSB7fTtcblxuICAgIHRoaXMuX2tleUNvZGUgPSBudWxsO1xuICAgIHRoaXMuX2NhcmV0T2Zmc2V0ID0gMDtcblxuICAgIHZhciBpbnB1dCA9IHRoaXMuX2lucHV0ID0gbmV3IE5vZGUoJ3RleHQnKTtcbiAgICAgICAgaW5wdXQuc2V0UHJvcGVydHkoJ3ZhbHVlJywgdGhpcy5fdmFsdWUpO1xuXG4gICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLHRoaXMuX29uSW5wdXQuYmluZCh0aGlzKSk7XG4gICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsdGhpcy5fb25LZXlkb3duLmJpbmQodGhpcykpO1xuXG4gICAgaWYoIXNldENhcmV0UG9zKXtcbiAgICAgICAgaWYoaW5wdXQuZ2V0RWxlbWVudCgpLnNldFNlbGVjdGlvblJhbmdlKXtcbiAgICAgICAgICAgIHNldENhcmV0UG9zID0gZnVuY3Rpb24oaW5wdXQscG9zKXtcbiAgICAgICAgICAgICAgICBpbnB1dC5nZXRFbGVtZW50KCkuc2V0U2VsZWN0aW9uUmFuZ2UocG9zLHBvcyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgc2VsZWN0QWxsID0gZnVuY3Rpb24oaW5wdXQpe1xuICAgICAgICAgICAgICAgIGlucHV0LmdldEVsZW1lbnQoKS5zZXRTZWxlY3Rpb25SYW5nZSgwLGlucHV0LmdldFByb3BlcnR5KCd2YWx1ZScpLmxlbmd0aCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2V0Q2FyZXRQb3MgPSBmdW5jdGlvbihpbnB1dCxwb3Mpe1xuICAgICAgICAgICAgICAgIHZhciByYW5nZSA9IGlucHV0LmdldEVsZW1lbnQoKS5jcmVhdGVUZXh0UmFuZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2UuY29sbGFwc2UodHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHJhbmdlLm1vdmVFbmQoJ2NoYXJhY3RlcicscG9zKTtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2UubW92ZVN0YXJ0KCdjaGFyYWN0ZXInLHBvcyk7XG4gICAgICAgICAgICAgICAgICAgIHJhbmdlLnNlbGVjdCgpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHNlbGVjdEFsbCA9IGZ1bmN0aW9uKGlucHV0KXtcbiAgICAgICAgICAgICAgICB2YXIgcmFuZ2UgPSBpbnB1dC5nZXRFbGVtZW50KCkuY3JlYXRlVGV4dFJhbmdlKCk7XG4gICAgICAgICAgICAgICAgICAgIHJhbmdlLmNvbGxhcHNlKHRydWUpO1xuICAgICAgICAgICAgICAgICAgICByYW5nZS5tb3ZlU3RhcnQoJ2NoYXJhY3RlcicsMCk7XG4gICAgICAgICAgICAgICAgICAgIHJhbmdlLm1vdmVFbmQoJ2NoYXJhY3RlcicsaW5wdXQuZ2V0UHJvcGVydHkoJ3ZhbHVlJykubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2Uuc2VsZWN0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG59O1xuTnVtYmVySW5wdXRfSW50ZXJuYWwucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFdmVudERpc3BhdGNoZXIucHJvdG90eXBlKTtcbk51bWJlcklucHV0X0ludGVybmFsLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IE51bWJlcklucHV0X0ludGVybmFsO1xuXG5OdW1iZXJJbnB1dF9JbnRlcm5hbC5wcm90b3R5cGUuX3NldFZhbHVlID0gZnVuY3Rpb24odmFsdWUpe1xuICAgIHZhciBwcmVmaXggPSAgKCh2YWx1ZSA9ICt2YWx1ZSkgfHwgMSAvIHZhbHVlKSA8IDAgJiYgdmFsdWUgPT0gMCA/ICctJyA6ICcnOyAvLy0wXG4gICAgICAgIHZhbHVlID0gTnVtYmVyKHZhbHVlKS50b0ZpeGVkKHRoaXMuX3ZhbHVlRHApO1xuICAgIHRoaXMuX2lucHV0LnNldFByb3BlcnR5KCd2YWx1ZScscHJlZml4ICsgdmFsdWUpO1xuICAgIHRoaXMuX3ZhbHVlID0gTnVtYmVyKHZhbHVlKTtcbn07XG5cbk51bWJlcklucHV0X0ludGVybmFsLnByb3RvdHlwZS5fb25JbnB1dCA9IGZ1bmN0aW9uKCl7XG4gICAgdmFyIGlucHV0ID0gdGhpcy5faW5wdXQsXG4gICAgICAgIHZhbHVlID0gaW5wdXQuZ2V0UHJvcGVydHkoJ3ZhbHVlJyksXG4gICAgICAgIHN0YXJ0ID0gaW5wdXQuZ2V0UHJvcGVydHkoJ3NlbGVjdGlvblN0YXJ0JyksXG4gICAgICAgIGRwICAgID0gdGhpcy5fdmFsdWVEcDtcblxuICAgIHZhciBmaXJzdCA9IHZhbHVlWzBdO1xuXG4gICAgaWYodmFsdWUgPT0gJycpe1xuICAgICAgICB2YWx1ZSA9IDA7XG4gICAgfSBlbHNlIGlmKGZpcnN0ID09PSAnLicpe1xuICAgICAgICB2YWx1ZSA9ICcwJyArIHZhbHVlO1xuICAgIH1cblxuICAgIGlmKCFOVU1fUkVHRVgudGVzdCh2YWx1ZSkgfHwgdmFsdWUgPT0gJy0nKXtcbiAgICAgICAgaW5wdXQuc2V0UHJvcGVydHkoJ3ZhbHVlJyx0aGlzLl92YWx1ZS50b0ZpeGVkKGRwKSk7XG4gICAgICAgIHNldENhcmV0UG9zKGlucHV0LE1hdGgubWF4KC0tc3RhcnQsMCkpO1xuICAgICAgICB0aGlzLl9vbkVycm9yKHRoaXMuX2tleUNvZGUpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX29uQmVnaW4odGhpcy5fdmFsdWUpO1xuICAgIHRoaXMuX3NldFZhbHVlKHZhbHVlKTtcbiAgICBzZXRDYXJldFBvcyhpbnB1dCxzdGFydCAtIHRoaXMuX2NhcmV0T2Zmc2V0KTtcbiAgICB0aGlzLl9vbkNoYW5nZSgpO1xufTtcblxuTnVtYmVySW5wdXRfSW50ZXJuYWwucHJvdG90eXBlLl9vbktleWRvd24gPSBmdW5jdGlvbihlKXtcbiAgICB2YXIga2V5Q29kZSA9IHRoaXMuX2tleUNvZGUgPSBlLmtleUNvZGU7XG5cbiAgICBpZihrZXlDb2RlID09IDEzKXtcbiAgICAgICAgdGhpcy5fb25GaW5pc2goKTtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGlucHV0ICA9IHRoaXMuX2lucHV0LFxuICAgICAgICB2YWx1ZSAgPSBpbnB1dC5nZXRQcm9wZXJ0eSgndmFsdWUnKTtcbiAgICB2YXIgc3RhcnQgID0gaW5wdXQuZ2V0UHJvcGVydHkoJ3NlbGVjdGlvblN0YXJ0JyksXG4gICAgICAgIGVuZCAgICA9IGlucHV0LmdldFByb3BlcnR5KCdzZWxlY3Rpb25FbmQnKTtcbiAgICB2YXIgbGVuZ3RoID0gdmFsdWUubGVuZ3RoO1xuXG4gICAgdmFyIGlzQmFja3NwYWNlRGVsZXRlID0ga2V5Q29kZSA9PSA4IHx8IGtleUNvZGUgPT0gNDUsXG4gICAgICAgIGlzTWV0YUtleSA9IGUubWV0YUtleSxcbiAgICAgICAgaXNDdHJsS2V5ID0gZS5jdHJsS2V5LFxuICAgICAgICBpc0xlZnQgPSBrZXlDb2RlID09IDM3LFxuICAgICAgICBpc1JpZ2h0ID0ga2V5Q29kZSA9PSAzOSxcbiAgICAgICAgaXNMZWZ0UmlnaHQgPSBpc0xlZnQgfHwgaXNSaWdodCxcbiAgICAgICAgaXNTaGlmdCA9IGUuc2hpZnRLZXksXG4gICAgICAgIGlzVXBEb3duID0ga2V5Q29kZSA9PSAzOCB8fCBrZXlDb2RlID09IDQwLFxuICAgICAgICBpc1NlbGVjdEFsbCA9IChpc01ldGFLZXkgfHwgaXNDdHJsS2V5KSAmJiBrZXlDb2RlID09IDY1LFxuICAgICAgICBpc1JhbmdlU2VsZWN0ZWQgPSBzdGFydCAhPSBlbmQsXG4gICAgICAgIGlzQWxsU2VsZWN0ZWQgPSBzdGFydCA9PSAwICYmIGVuZCA9PSBsZW5ndGgsXG4gICAgICAgIGlzTWludXMgPSBrZXlDb2RlID09IDE4OTtcblxuICAgIHZhciBpbmRleERlY2ltYWxNYXJrID0gdmFsdWUuaW5kZXhPZignLicpO1xuXG4gICAgdGhpcy5fY2FyZXRPZmZzZXQgPSAwO1xuXG4gICAgLy9wcmV2ZW50IGNtZC16IHx8IGN0cmwtelxuICAgIGlmKChpc01ldGFLZXkgfHwgaXNDdHJsS2V5KSAmJiBrZXlDb2RlID09IDkwKXtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vc2VsZWN0IGFsbCBjbWQrYSB8fCBjdHJsK2FcbiAgICBpZihpc1NlbGVjdEFsbCl7XG4gICAgICAgIHNlbGVjdEFsbChpbnB1dCk7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvL2V2ZXJ5dGhpbmcgaXMgc2VsZWN0ZWRcbiAgICBpZihpc0FsbFNlbGVjdGVkKSB7XG4gICAgICAgIGlmIChpc01pbnVzKSB7XG4gICAgICAgICAgICAvL3NldCBuZWdhdGl2ZSB6ZXJvLCBhcyBzdGFydGluZyBwb2ludCBmb3IgbmVnYXRpdmUgbnVtYmVyXG4gICAgICAgICAgICBpbnB1dFNldFZhbHVlKGlucHV0LCAnLTAnKTtcbiAgICAgICAgICAgIC8vc2V0IGNhcmV0IGFmdGVyICAnLSdcbiAgICAgICAgICAgIHNldENhcmV0UG9zKGlucHV0LCAxKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vZGVsZXRlIG51bWJlciAvIHJlcGxhY2UgLyBpZ25vcmVcbiAgICAgICAgICAgIGlucHV0U2V0VmFsdWUoaW5wdXQsIGlzQmFja3NwYWNlRGVsZXRlID8gMCA6IFN0cmluZy5mcm9tQ2hhckNvZGUoa2V5Q29kZSkpO1xuICAgICAgICAgICAgLy9qdW1wIHRvIHN0YXJ0IDwtLT4gZW5kXG4gICAgICAgICAgICBzZXRDYXJldFBvcyhpbnB1dCwgaXNMZWZ0ID8gc3RhcnQgOiBlbmQpO1xuICAgICAgICB9XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvL2p1bXAgb3ZlciBkZWNpbWFsIG1hcmtcbiAgICBpZihpc0JhY2tzcGFjZURlbGV0ZSAmJiAoc3RhcnQtMSA9PSBpbmRleERlY2ltYWxNYXJrKSl7XG4gICAgICAgIHNldENhcmV0UG9zKGlucHV0LHN0YXJ0LTEpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIDB8LiBlbnRlciBmaXJzdCBkcCB3aXRob3V0IGp1bXBpbmcgb3ZlciBkZWNpbWFsIG1hcmtcbiAgICBpZighaXNMZWZ0UmlnaHQgJiYgKHZhbHVlWzBdID09ICcwJyAmJiBzdGFydCA9PSAxKSl7XG4gICAgICAgIHNldENhcmV0UG9zKGlucHV0LDEpO1xuICAgICAgICB0aGlzLl9jYXJldE9mZnNldCA9IDE7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy9pbmNyZWFzZSAvIGRlY3JlYXNlIG51bWJlciBieSAoc3RlcCB1cCAvIGRvd24pICogbXVsdGlwbGllciBvbiBzaGlmdCBkb3duXG4gICAgaWYoaXNVcERvd24pe1xuICAgICAgICB2YXIgc3RlcCA9IChpc1NoaWZ0ID8gUFJFU0VUX1NISUZUX01VTFRJUExJRVIgOiAxKSAqIHRoaXMuX3ZhbHVlU3RlcCxcbiAgICAgICAgICAgIG11bHQgPSBrZXlDb2RlID09IDM4ID8gMS4wIDogLTEuMDtcbiAgICAgICAgaW5wdXRTZXRWYWx1ZShpbnB1dCxOdW1iZXIodmFsdWUpICsgKHN0ZXAgKiBtdWx0KSk7XG4gICAgICAgIHNldENhcmV0UG9zKGlucHV0LHN0YXJ0KTtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vcmFuZ2Ugc2VsZWN0ZWQsIG5vdCBpbiBzZWxlY3Rpb24gcHJvY2Vzc1xuICAgIGlmKGlzUmFuZ2VTZWxlY3RlZCAmJiAhKGlzU2hpZnQgJiYgaXNMZWZ0UmlnaHQpKXtcbiAgICAgICAgLy9qdW1wIHRvIHN0YXJ0IDwtLT4gZW5kXG4gICAgICAgIGlmKGlzTGVmdFJpZ2h0KXtcbiAgICAgICAgICAgIHNldENhcmV0UG9zKGlucHV0LGlzTGVmdCA/IHN0YXJ0IDogZW5kKTtcbiAgICAgICAgfSBlbHNlIHsgLy9yZXBsYWNlIGNvbXBsZXRlIHJhbmdlLCBub3QganVzdCBwYXJ0c1xuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5zdWJzdHIoMCxzdGFydCkgKyBTdHJpbmcuZnJvbUNoYXJDb2RlKGtleUNvZGUpICsgdmFsdWUuc3Vic3RyKGVuZCxsZW5ndGgtZW5kKTtcbiAgICAgICAgICAgIGlucHV0U2V0VmFsdWUoaW5wdXQsdmFsdWUpO1xuICAgICAgICAgICAgc2V0Q2FyZXRQb3MoaW5wdXQsZW5kKTtcbiAgICAgICAgfVxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy9jYXJldCB3aXRoaW4gZnJhY3Rpb25hbCBwYXJ0LCBub3QgbW92aW5nIGNhcmV0LCBzZWxlY3RpbmcsIGRlbGV0aW5nXG4gICAgaWYoIWlzU2hpZnQgJiYgIWlzTGVmdFJpZ2h0ICYmICFpc0JhY2tzcGFjZURlbGV0ZSAmJiAoc3RhcnQgPiBpbmRleERlY2ltYWxNYXJrICYmIHN0YXJ0IDwgbGVuZ3RoKSl7XG4gICAgICAgIHZhbHVlID0gdmFsdWUuc3Vic3RyKDAsc3RhcnQpICsgU3RyaW5nLmZyb21DaGFyQ29kZShrZXlDb2RlKSArIHZhbHVlLnN1YnN0cihzdGFydCsxLGxlbmd0aC0xKTtcbiAgICAgICAgaW5wdXRTZXRWYWx1ZShpbnB1dCx2YWx1ZSk7XG4gICAgICAgIHNldENhcmV0UG9zKGlucHV0LE1hdGgubWluKHN0YXJ0KzEsbGVuZ3RoLTEpKTtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vY2FyZXQgYXQgZW5kIG9mIG51bWJlciwgZG8gbm90aGluZ1xuICAgIGlmKCFpc0JhY2tzcGFjZURlbGV0ZSAmJiAhaXNMZWZ0UmlnaHQgJiYgIWlzVXBEb3duICYmIHN0YXJ0ID49IGxlbmd0aCl7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG59O1xuXG5OdW1iZXJJbnB1dF9JbnRlcm5hbC5wcm90b3R5cGUuZ2V0VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbHVlO1xufTtcblxuTnVtYmVySW5wdXRfSW50ZXJuYWwucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKG4pIHtcbiAgICB0aGlzLl9zZXRWYWx1ZShuKTtcbn07XG5cbk51bWJlcklucHV0X0ludGVybmFsLnByb3RvdHlwZS5nZXROb2RlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9pbnB1dDtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gTnVtYmVySW5wdXRfSW50ZXJuYWw7XG4iLCJ2YXIgT3V0cHV0ID0gcmVxdWlyZSgnLi9PdXRwdXQnKTtcblxudmFyIERFRkFVTFRfT1VUUFVUX0RQID0gMjtcblxuZnVuY3Rpb24gTnVtYmVyT3V0cHV0KHBhcmVudCwgb2JqZWN0LCB2YWx1ZSwgcGFyYW1zKSB7XG5cdHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblx0cGFyYW1zLmRwID0gcGFyYW1zLmRwIHx8IERFRkFVTFRfT1VUUFVUX0RQO1xuXG5cdE91dHB1dC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuXHR0aGlzLl92YWx1ZURwID0gcGFyYW1zLmRwICsgMTtcbn1cbk51bWJlck91dHB1dC5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKE91dHB1dC5wcm90b3R5cGUpO1xuTnVtYmVyT3V0cHV0LnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IE51bWJlck91dHB1dDtcblxuLy9GSVhNRVxuTnVtYmVyT3V0cHV0LnByb3RvdHlwZS5fc2V0VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG5cdGlmICh0aGlzLl9wYXJlbnQuaXNEaXNhYmxlZCgpKXtcblx0XHRyZXR1cm47XG5cdH1cblxuXHR2YXIgdmFsdWUgPSB0aGlzLl9vYmpbdGhpcy5fa2V5XSxcblx0XHR0ZXh0QXJlYSA9IHRoaXMuX3RleHRBcmVhLFxuXHRcdGRwID0gdGhpcy5fdmFsdWVEcDtcblxuXHR2YXIgaW5kZXgsXG5cdFx0b3V0O1xuXG5cdGlmICh0eXBlb2YodmFsdWUpID09PSAnb2JqZWN0JyAmJlxuXHRcdHR5cGVvZih2YWx1ZS5sZW5ndGgpID09PSAnbnVtYmVyJyAmJlxuXHRcdHR5cGVvZih2YWx1ZS5zcGxpY2UpID09PSAnZnVuY3Rpb24nICYmXG5cdFx0IXZhbHVlLnByb3BlcnR5SXNFbnVtZXJhYmxlKCdsZW5ndGgnKSkge1xuXG5cdFx0b3V0ID0gdmFsdWUuc2xpY2UoKTtcblxuXHRcdHZhciBpID0gLTE7XG5cdFx0dmFyIHRlbXA7XG5cdFx0dmFyIHdyYXAgPSB0aGlzLl93cmFwO1xuXG5cdFx0d2hpbGUgKCsraSA8IG91dC5sZW5ndGgpIHtcblx0XHRcdHRlbXAgPSBvdXRbaV0gPSBvdXRbaV0udG9TdHJpbmcoKTtcblx0XHRcdGluZGV4ID0gdGVtcC5pbmRleE9mKCcuJyk7XG5cdFx0XHRpZiAoaW5kZXggPiAwKXtcblx0XHRcdFx0b3V0W2ldID0gdGVtcC5zbGljZSgwLCBpbmRleCArIGRwKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAod3JhcCkge1xuXHRcdFx0dGV4dEFyZWEuc2V0U3R5bGVQcm9wZXJ0eSgnd2hpdGUtc3BhY2UnLCAnbm93cmFwJyk7XG5cdFx0XHRvdXQgPSBvdXQuam9pbignXFxuJyk7XG5cdFx0fVxuXG5cdFx0dGV4dEFyZWEuc2V0UHJvcGVydHkoJ3ZhbHVlJywgb3V0KTtcblx0fWVsc2Uge1xuXHRcdG91dCA9IHZhbHVlLnRvU3RyaW5nKCk7XG5cdFx0aW5kZXggPSBvdXQuaW5kZXhPZignLicpO1xuXHRcdHRleHRBcmVhLnNldFByb3BlcnR5KCd2YWx1ZScsIGluZGV4ID4gMCA/IG91dC5zbGljZSgwLCBpbmRleCArIGRwKSA6IG91dCk7XG5cdH1cblxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBOdW1iZXJPdXRwdXQ7IiwidmFyIE5vZGUgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L05vZGUnKTtcbnZhciBEb2N1bWVudEV2ZW50ID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Eb2N1bWVudEV2ZW50JyksXG4gICAgTm9kZUV2ZW50ICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZUV2ZW50Jyk7XG52YXIgQ1NTID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9DU1MnKTtcbnZhciBDb2xvck1vZGUgPSByZXF1aXJlKCcuLi9jb3JlL2NvbG9yL0NvbG9yTW9kZScpO1xudmFyIENvbG9yVXRpbCA9IHJlcXVpcmUoJy4uL2NvcmUvY29sb3IvQ29sb3JVdGlsJyk7XG52YXIgTWV0cmljID0gcmVxdWlyZSgnLi9NZXRyaWMnKTtcblxuZnVuY3Rpb24gT3B0aW9ucyhwYXJlbnROb2RlKSB7XG4gICAgdGhpcy5fcGFyZW5Ob2RlID0gcGFyZW50Tm9kZTtcblxuICAgIHZhciBub2RlID0gdGhpcy5fbm9kZSA9IG5ldyBOb2RlKCk7XG4gICAgdmFyIGxpc3ROb2RlID0gdGhpcy5fbGlzdE5vZGUgPSBuZXcgTm9kZShOb2RlLkxJU1QpO1xuXG4gICAgbm9kZS5zZXRTdHlsZUNsYXNzKENTUy5PcHRpb25zKTtcbiAgICBub2RlLmFkZENoaWxkKGxpc3ROb2RlKTtcblxuICAgIHRoaXMuX3NlbGVjdGVkSW5kZXggPSBudWxsO1xuICAgIHRoaXMuX2NhbGxiYWNrT3V0ID0gZnVuY3Rpb24gKCkgeyB9O1xuXG4gICAgdGhpcy5fdW5mb2N1c2FibGUgPSBmYWxzZTtcblxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoRG9jdW1lbnRFdmVudC5NT1VTRV9ET1dOLCB0aGlzLl9vbkRvY3VtZW50TW91c2VEb3duLmJpbmQodGhpcykpO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoRG9jdW1lbnRFdmVudC5NT1VTRV9VUCwgdGhpcy5fb25Eb2N1bWVudE1vdXNlVXAuYmluZCh0aGlzKSk7XG5cbiAgICB0aGlzLmNsZWFyKCk7XG59XG5cbk9wdGlvbnMucHJvdG90eXBlID0ge1xuICAgIF9vbkRvY3VtZW50TW91c2VEb3duOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5fdW5mb2N1c2FibGUpcmV0dXJuO1xuICAgICAgICB0aGlzLl9jYWxsYmFja091dCgpO1xuICAgIH0sXG5cbiAgICBfb25Eb2N1bWVudE1vdXNlVXA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5fdW5mb2N1c2FibGUgPSB0cnVlO1xuICAgIH0sXG5cbiAgICBidWlsZDogZnVuY3Rpb24gKGVudHJpZXMsIHNlbGVjdGVkLCBlbGVtZW50LCBjYWxsYmFja1NlbGVjdCwgY2FsbGJhY2tPdXQsIHBhZGRpbmdSaWdodCwgYXJlQ29sb3JzLCBjb2xvck1vZGUpIHtcbiAgICAgICAgdGhpcy5fY2xlYXJMaXN0KCk7XG5cbiAgICAgICAgdGhpcy5fcGFyZW5Ob2RlLmFkZENoaWxkKHRoaXMuZ2V0Tm9kZSgpKTtcblxuICAgICAgICB2YXIgcm9vdE5vZGUgPSB0aGlzLl9ub2RlLFxuICAgICAgICAgICAgbGlzdE5vZGUgPSB0aGlzLl9saXN0Tm9kZTtcblxuICAgICAgICBwYWRkaW5nUmlnaHQgPSBwYWRkaW5nUmlnaHQgfHwgMDtcblxuICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgLy8gYnVpbGQgbGlzdFxuICAgICAgICB2YXIgaXRlbU5vZGUsIGVudHJ5O1xuICAgICAgICB2YXIgaSA9IC0xO1xuXG4gICAgICAgIGlmIChhcmVDb2xvcnMpIHtcbiAgICAgICAgICAgIGNvbG9yTW9kZSA9IGNvbG9yTW9kZSB8fCBDb2xvck1vZGUuSEVYO1xuXG4gICAgICAgICAgICBsaXN0Tm9kZS5zZXRTdHlsZUNsYXNzKENTUy5Db2xvcik7XG5cbiAgICAgICAgICAgIHZhciBjb2xvciwgbm9kZUNvbG9yO1xuXG4gICAgICAgICAgICB3aGlsZSAoKytpIDwgZW50cmllcy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBlbnRyeSA9IGVudHJpZXNbaV07XG4gICAgICAgICAgICAgICAgaXRlbU5vZGUgPSBsaXN0Tm9kZS5hZGRDaGlsZChuZXcgTm9kZShOb2RlLkxJU1RfSVRFTSkpO1xuICAgICAgICAgICAgICAgIGNvbG9yID0gaXRlbU5vZGUuYWRkQ2hpbGQobmV3IE5vZGUoKSk7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGNvbG9yTW9kZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIENvbG9yTW9kZS5IRVg6XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlQ29sb3IgPSBlbnRyeTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIENvbG9yTW9kZS5SR0I6XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlQ29sb3IgPSBDb2xvclV0aWwuUkdCMkhFWChlbnRyeVswXSwgZW50cnlbMV0sIGVudHJ5WzJdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIENvbG9yTW9kZS5SR0JmdjpcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVDb2xvciA9IENvbG9yVXRpbC5SR0JmdjJIRVgoZW50cnlbMF0sIGVudHJ5WzFdLCBlbnRyeVsyXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBDb2xvck1vZGUuSFNWOlxuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZUNvbG9yID0gQ29sb3JVdGlsLkhTVjJSR0IoZW50cnlbMF0sIGVudHJ5WzFdLCBlbnRyeVsyXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBjb2xvci5nZXRTdHlsZSgpLmJhY2tncm91bmRDb2xvciA9IG5vZGVDb2xvcjtcbiAgICAgICAgICAgICAgICBjb2xvci5nZXRTdHlsZSgpLmJhY2tncm91bmRJbWFnZSA9ICdsaW5lYXItZ3JhZGllbnQoIHJnYmEoMCwwLDAsMCkgMCUsIHJnYmEoMCwwLDAsMC4xKSAxMDAlKSc7XG4gICAgICAgICAgICAgICAgY29sb3Iuc2V0UHJvcGVydHkoJ2lubmVySFRNTCcsIGVudHJ5KTtcblxuICAgICAgICAgICAgICAgIGlmIChlbnRyeSA9PSBzZWxlY3RlZClpdGVtTm9kZS5zZXRTdHlsZUNsYXNzKENTUy5PcHRpb25zU2VsZWN0ZWQpO1xuXG4gICAgICAgICAgICAgICAgaXRlbU5vZGUuYWRkRXZlbnRMaXN0ZW5lcihOb2RlRXZlbnQuTU9VU0VfRE9XTixcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2VsZWN0ZWRJbmRleCA9IEFycmF5LnByb3RvdHlwZS5pbmRleE9mLmNhbGwodGhpcy5wYXJlbnROb2RlLmNoaWxkcmVuLCB0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrU2VsZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBsaXN0Tm9kZS5kZWxldGVTdHlsZUNsYXNzKCk7XG5cbiAgICAgICAgICAgIHdoaWxlICgrK2kgPCBlbnRyaWVzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIGVudHJ5ID0gZW50cmllc1tpXTtcblxuICAgICAgICAgICAgICAgIGl0ZW1Ob2RlID0gbGlzdE5vZGUuYWRkQ2hpbGQobmV3IE5vZGUoTm9kZS5MSVNUX0lURU0pKTtcbiAgICAgICAgICAgICAgICBpdGVtTm9kZS5zZXRQcm9wZXJ0eSgnaW5uZXJIVE1MJywgZW50cnkpO1xuICAgICAgICAgICAgICAgIGlmIChlbnRyeSA9PSBzZWxlY3RlZClpdGVtTm9kZS5zZXRTdHlsZUNsYXNzKENTUy5PcHRpb25zU2VsZWN0ZWQpO1xuXG4gICAgICAgICAgICAgICAgaXRlbU5vZGUuYWRkRXZlbnRMaXN0ZW5lcihOb2RlRXZlbnQuTU9VU0VfRE9XTixcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fc2VsZWN0ZWRJbmRleCA9IEFycmF5LnByb3RvdHlwZS5pbmRleE9mLmNhbGwodGhpcy5wYXJlbnROb2RlLmNoaWxkcmVuLCB0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrU2VsZWN0KCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy9wb3NpdGlvbiwgc2V0IHdpZHRoIGFuZCBlbmFibGVcblxuICAgICAgICB2YXIgZWxlbWVudFBvcyA9IGVsZW1lbnQuZ2V0UG9zaXRpb25HbG9iYWwoKSxcbiAgICAgICAgICAgIGVsZW1lbnRXaWR0aCA9IGVsZW1lbnQuZ2V0V2lkdGgoKSAtIHBhZGRpbmdSaWdodCxcbiAgICAgICAgICAgIGVsZW1lbnRIZWlnaHQgPSBlbGVtZW50LmdldEhlaWdodCgpO1xuXG4gICAgICAgIHZhciBsaXN0V2lkdGggPSBsaXN0Tm9kZS5nZXRXaWR0aCgpLFxuICAgICAgICAgICAgbGlzdEhlaWdodCA9IGxpc3ROb2RlLmdldEhlaWdodCgpLFxuICAgICAgICAgICAgc3Ryb2tlT2Zmc2V0ID0gTWV0cmljLlNUUk9LRV9TSVpFICogMjtcblxuICAgICAgICB2YXIgcGFkZGluZ09wdGlvbnMgPSBNZXRyaWMuUEFERElOR19PUFRJT05TO1xuXG4gICAgICAgIHZhciB3aWR0aCA9IChsaXN0V2lkdGggPCBlbGVtZW50V2lkdGggPyBlbGVtZW50V2lkdGggOiBsaXN0V2lkdGgpIC0gc3Ryb2tlT2Zmc2V0LFxuICAgICAgICAgICAgcG9zWCA9IGVsZW1lbnRQb3NbMF0sXG4gICAgICAgICAgICBwb3NZID0gZWxlbWVudFBvc1sxXSArIGVsZW1lbnRIZWlnaHQgLSBwYWRkaW5nT3B0aW9ucztcblxuICAgICAgICB2YXIgd2luZG93V2lkdGggPSB3aW5kb3cuaW5uZXJXaWR0aCxcbiAgICAgICAgICAgIHdpbmRvd0hlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodDtcblxuICAgICAgICB2YXIgcm9vdFBvc1ggPSAocG9zWCArIHdpZHRoKSA+IHdpbmRvd1dpZHRoID8gKHBvc1ggLSB3aWR0aCArIGVsZW1lbnRXaWR0aCAtIHN0cm9rZU9mZnNldCkgOiBwb3NYLFxuICAgICAgICAgICAgcm9vdFBvc1kgPSAocG9zWSArIGxpc3RIZWlnaHQpID4gd2luZG93SGVpZ2h0ID8gKHBvc1kgLSBsaXN0SGVpZ2h0ICogMC41IC0gZWxlbWVudEhlaWdodCAqIDAuNSkgOiBwb3NZO1xuXG4gICAgICAgIGxpc3ROb2RlLnNldFdpZHRoKHdpZHRoKTtcbiAgICAgICAgcm9vdE5vZGUuc2V0UG9zaXRpb25HbG9iYWwocm9vdFBvc1gsIHJvb3RQb3NZKTtcblxuICAgICAgICB0aGlzLl9jYWxsYmFja091dCA9IGNhbGxiYWNrT3V0O1xuICAgICAgICB0aGlzLl91bmZvY3VzYWJsZSA9IGZhbHNlO1xuICAgIH0sXG5cbiAgICBfY2xlYXJMaXN0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuX2xpc3ROb2RlLnJlbW92ZUFsbENoaWxkcmVuKCk7XG4gICAgICAgIHRoaXMuX2xpc3ROb2RlLmRlbGV0ZVN0eWxlUHJvcGVydHkoJ3dpZHRoJyk7XG4gICAgICAgIHRoaXMuX3NlbGVjdGVkSW5kZXggPSBudWxsO1xuICAgICAgICB0aGlzLl9idWlsZCA9IGZhbHNlO1xuICAgIH0sXG5cbiAgICBjbGVhcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9jbGVhckxpc3QoKTtcbiAgICAgICAgdGhpcy5fY2FsbGJhY2tPdXQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuX3BhcmVuTm9kZS5yZW1vdmVDaGlsZCh0aGlzLmdldE5vZGUoKSk7XG5cbiAgICB9LFxuXG4gICAgaXNCdWlsZDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fYnVpbGQ7XG4gICAgfSxcbiAgICBnZXROb2RlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9ub2RlO1xuICAgIH0sXG4gICAgZ2V0U2VsZWN0ZWRJbmRleDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2VsZWN0ZWRJbmRleDtcbiAgICB9XG59O1xuXG5PcHRpb25zLnNldHVwID0gZnVuY3Rpb24ocGFyZW50Tm9kZSl7cmV0dXJuIE9wdGlvbnMuX2luc3RhbmNlID0gbmV3IE9wdGlvbnMocGFyZW50Tm9kZSk7fTtcbk9wdGlvbnMuZ2V0ICAgPSBmdW5jdGlvbigpe3JldHVybiBPcHRpb25zLl9pbnN0YW5jZTt9O1xuT3B0aW9ucy5kZXN0cm95ID0gZnVuY3Rpb24oKXtPcHRpb25zLl9pbnN0YW5jZSA9IG51bGw7fTtcblxubW9kdWxlLmV4cG9ydHMgPSBPcHRpb25zOyIsInZhciBPYmplY3RDb21wb25lbnQgPSByZXF1aXJlKCcuLi9jb3JlL09iamVjdENvbXBvbmVudCcpO1xudmFyIE5vZGUgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L05vZGUnKTtcblxudmFyIENTUyAgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvQ1NTJyk7XG52YXIgTWV0cmljICAgID0gcmVxdWlyZSgnLi9NZXRyaWMnKTtcbnZhciBTY3JvbGxCYXIgPSByZXF1aXJlKCcuLi9jb3JlL2xheW91dC9TY3JvbGxCYXInKTtcblxudmFyIEV2ZW50XyAgICAgICAgID0gcmVxdWlyZSgnLi4vY29yZS9ldmVudC9FdmVudCcpLFxuICAgIERvY3VtZW50RXZlbnQgID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Eb2N1bWVudEV2ZW50JyksXG4gICAgTm9kZUV2ZW50ICAgICAgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L05vZGVFdmVudCcpLFxuICAgIENvbXBvbmVudEV2ZW50ID0gcmVxdWlyZSgnLi4vY29yZS9Db21wb25lbnRFdmVudCcpO1xuXG52YXIgREVGQVVMVF9IRUlHSFQgPSBudWxsLFxuICAgIERFRkFVTFRfV1JBUCAgID0gZmFsc2UsXG4gICAgREVGQVVMVF9VUERBVEUgPSB0cnVlO1xuXG5mdW5jdGlvbiBPdXRwdXQocGFyZW50LG9iamVjdCx2YWx1ZSxwYXJhbXMpIHtcbiAgICBPYmplY3RDb21wb25lbnQuYXBwbHkodGhpcyxhcmd1bWVudHMpO1xuXG4gICAgcGFyYW1zICAgICAgICA9IHBhcmFtcyAgICAgICAgfHwge307XG4gICAgcGFyYW1zLmhlaWdodCA9IHBhcmFtcy5oZWlnaHQgfHwgREVGQVVMVF9IRUlHSFQ7XG4gICAgcGFyYW1zLndyYXAgICA9IHBhcmFtcy53cmFwICAgPT09IHVuZGVmaW5lZCA/IERFRkFVTFRfV1JBUCA6IHBhcmFtcy53cmFwO1xuICAgIHBhcmFtcy51cGRhdGUgPSBwYXJhbXMudXBkYXRlID09PSB1bmRlZmluZWQgPyBERUZBVUxUX1VQREFURSA6IHBhcmFtcy51cGRhdGU7XG5cbiAgICB0aGlzLl93cmFwICAgPSBwYXJhbXMud3JhcDtcbiAgICB0aGlzLl91cGRhdGUgPSBwYXJhbXMudXBkYXRlO1xuXG4gICAgdmFyIHRleHRBcmVhID0gdGhpcy5fdGV4dEFyZWEgPSBuZXcgTm9kZShOb2RlLlRFWFRBUkVBKSxcbiAgICAgICAgd3JhcCA9IHRoaXMuX3dyYXBOb2RlLFxuICAgICAgICByb290ID0gdGhpcy5fbm9kZTtcblxuICAgICAgICB0ZXh0QXJlYS5zZXRQcm9wZXJ0eSgncmVhZE9ubHknLHRydWUpO1xuICAgICAgICB3cmFwLmFkZENoaWxkKHRleHRBcmVhKTtcblxuICAgICAgICB0ZXh0QXJlYS5hZGRFdmVudExpc3RlbmVyKE5vZGVFdmVudC5NT1VTRV9ET1dOLHRoaXMuX29uSW5wdXREcmFnU3RhcnQuYmluZCh0aGlzKSk7XG4gICAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcihDb21wb25lbnRFdmVudC5JTlBVVF9TRUxFQ1RfRFJBRyx0aGlzLl9wYXJlbnQsJ29uQ29tcG9uZW50U2VsZWN0RHJhZycpO1xuXG5cbiAgICBpZihwYXJhbXMuaGVpZ2h0KXtcbiAgICAgICAgdmFyIHRleHRBcmVhV3JhcCA9IG5ldyBOb2RlKCk7XG4gICAgICAgICAgICB0ZXh0QXJlYVdyYXAuc2V0U3R5bGVDbGFzcyhDU1MuVGV4dEFyZWFXcmFwKTtcbiAgICAgICAgICAgIHRleHRBcmVhV3JhcC5hZGRDaGlsZCh0ZXh0QXJlYSk7XG4gICAgICAgICAgICB3cmFwLmFkZENoaWxkKHRleHRBcmVhV3JhcCk7XG5cbiAgICAgICAgLy9GSVhNRVxuICAgICAgICB2YXIgaGVpZ2h0ICA9IHRoaXMuX2hlaWdodCA9IHBhcmFtcy5oZWlnaHQsXG4gICAgICAgICAgICBwYWRkaW5nID0gNDtcblxuICAgICAgICAgICAgdGV4dEFyZWEuc2V0SGVpZ2h0KE1hdGgubWF4KGhlaWdodCArIHBhZGRpbmcgICxNZXRyaWMuQ09NUE9ORU5UX01JTl9IRUlHSFQpKTtcbiAgICAgICAgICAgIHdyYXAuc2V0SGVpZ2h0KHRleHRBcmVhLmdldEhlaWdodCgpKTtcbiAgICAgICAgICAgIHJvb3Quc2V0SGVpZ2h0KHdyYXAuZ2V0SGVpZ2h0KCkgKyBwYWRkaW5nKTtcblxuICAgICAgICB0aGlzLl9zY3JvbGxCYXIgPSBuZXcgU2Nyb2xsQmFyKHRleHRBcmVhV3JhcCx0ZXh0QXJlYSxoZWlnaHQgLSBwYWRkaW5nKVxuICAgIH1cblxuICAgIGlmKHBhcmFtcy53cmFwKXtcbiAgICAgICAgdGV4dEFyZWEuc2V0U3R5bGVQcm9wZXJ0eSgnd2hpdGUtc3BhY2UnLCdwcmUtd3JhcCcpO1xuICAgIH1cblxuICAgIHRoaXMuX3ByZXZTdHJpbmcgPSAnJztcbiAgICB0aGlzLl9wcmV2U2Nyb2xsSGVpZ2h0ID0gLTE7XG4gICAgdGhpcy5fc2V0VmFsdWUoKTtcbn1cbk91dHB1dC5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKE9iamVjdENvbXBvbmVudC5wcm90b3R5cGUpO1xuT3V0cHV0LnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IE91dHB1dDtcblxuLy9PdmVycmlkZSBpbiBzdWJjbGFzc1xuT3V0cHV0LnByb3RvdHlwZS5fc2V0VmFsdWUgPSBmdW5jdGlvbiAoKSB7fTtcblxuT3V0cHV0LnByb3RvdHlwZS5vblZhbHVlVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX3NldFZhbHVlKCk7XG59O1xuXG5PdXRwdXQucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZighdGhpcy5fdXBkYXRlKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLl9zZXRWYWx1ZSgpO1xufTtcblxuLy9QcmV2ZW50IGNocm9tZSBzZWxlY3QgZHJhZ1xuXG5PdXRwdXQucHJvdG90eXBlLl9vbkRyYWcgPSBmdW5jdGlvbigpe1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIENvbXBvbmVudEV2ZW50LklOUFVUX1NFTEVDVF9EUkFHLCBudWxsKSk7XG59O1xuXG5PdXRwdXQucHJvdG90eXBlLl9vbkRyYWdGaW5pc2ggPSBmdW5jdGlvbigpe1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIENvbXBvbmVudEV2ZW50LklOUFVUX1NFTEVDVF9EUkFHLCBudWxsKSk7XG5cbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKERvY3VtZW50RXZlbnQuTU9VU0VfTU9WRSwgdGhpcy5fb25EcmFnLCBmYWxzZSk7XG4gICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihEb2N1bWVudEV2ZW50Lk1PVVNFX01PVkUsIHRoaXMuX29uRHJhZ0ZpbmlzaCwgZmFsc2UpO1xufTtcblxuT3V0cHV0LnByb3RvdHlwZS5fb25JbnB1dERyYWdTdGFydCA9IGZ1bmN0aW9uKCkge1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIENvbXBvbmVudEV2ZW50LklOUFVUX1NFTEVDVF9EUkFHLCBudWxsKSk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihEb2N1bWVudEV2ZW50Lk1PVVNFX01PVkUsIHRoaXMuX29uRHJhZy5iaW5kKHRoaXMpLCBmYWxzZSk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihEb2N1bWVudEV2ZW50Lk1PVVNFX1VQLCAgIHRoaXMuX29uRHJhZ0ZpbmlzaC5iaW5kKHRoaXMpLCBmYWxzZSk7XG59O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gT3V0cHV0O1xuIiwidmFyIFBsb3R0ZXIgPSByZXF1aXJlKCcuL1Bsb3R0ZXInKTtcbnZhciBNb3VzZSA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTW91c2UnKTtcblxudmFyIEV2ZW50XyAgICAgICAgID0gcmVxdWlyZSgnLi4vY29yZS9ldmVudC9FdmVudCcpLFxuICAgIERvY3VtZW50RXZlbnQgID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Eb2N1bWVudEV2ZW50JyksXG4gICAgQ29tcG9uZW50RXZlbnQgPSByZXF1aXJlKCcuLi9jb3JlL0NvbXBvbmVudEV2ZW50Jyk7XG5cbnZhciBERUZBVUxUX0JPVU5EU19YID0gWy0xLDFdLFxuICAgIERFRkFVTFRfQk9VTkRTX1kgPSBbLTEsMV0sXG4gICAgREVGQVVMVF9MQUJFTF9YICA9ICcnLFxuICAgIERFRkFVTFRfTEFCRUxfWSAgPSAnJztcblxuZnVuY3Rpb24gUGFkKHBhcmVudCwgb2JqZWN0LCB2YWx1ZSwgcGFyYW1zKSB7XG4gICAgUGxvdHRlci5hcHBseSh0aGlzLGFyZ3VtZW50cyk7XG5cbiAgICBwYXJhbXMgICAgICAgICAgICA9IHBhcmFtcyAgICAgICAgICAgIHx8IHt9O1xuICAgIHBhcmFtcy5ib3VuZHNYICAgID0gcGFyYW1zLmJvdW5kc1ggICAgfHwgREVGQVVMVF9CT1VORFNfWDtcbiAgICBwYXJhbXMuYm91bmRzWSAgICA9IHBhcmFtcy5ib3VuZHNZICAgIHx8IERFRkFVTFRfQk9VTkRTX1k7XG4gICAgcGFyYW1zLmxhYmVsWCAgICAgPSBwYXJhbXMubGFiZWxYICAgICB8fCBERUZBVUxUX0xBQkVMX1g7XG4gICAgcGFyYW1zLmxhYmVsWSAgICAgPSBwYXJhbXMubGFiZWxZICAgICB8fCBERUZBVUxUX0xBQkVMX1k7XG5cbiAgICBwYXJhbXMuc2hvd0Nyb3NzICA9IHBhcmFtcy5zaG93Q3Jvc3MgIHx8IHRydWU7XG5cblxuICAgIHRoaXMuX29uQ2hhbmdlICAgICA9IHBhcmFtcy5vbkNoYW5nZSB8fCB0aGlzLl9vbkNoYW5nZTtcbiAgICB0aGlzLl9vbkZpbmlzaCAgICAgPSBwYXJhbXMub25GaW5pc2ggfHwgZnVuY3Rpb24oKXt9O1xuXG4gICAgdGhpcy5fYm91bmRzWCAgICAgID0gcGFyYW1zLmJvdW5kc1g7XG4gICAgdGhpcy5fYm91bmRzWSAgICAgID0gcGFyYW1zLmJvdW5kc1k7XG4gICAgdGhpcy5fbGFiZWxBeGlzWCAgID0gcGFyYW1zLmxhYmVsWCAhPSAnJyAmJiBwYXJhbXMubGFiZWxYICE9ICdub25lJyA/IHBhcmFtcy5sYWJlbFggOiBudWxsO1xuICAgIHRoaXMuX2xhYmVsQXhpc1kgICA9IHBhcmFtcy5sYWJlbFkgIT0gJycgJiYgcGFyYW1zLmxhYmVsWSAhPSAnbm9uZScgPyBwYXJhbXMubGFiZWxZIDogbnVsbDtcblxuICAgIHZhciBwYXRoID0gdGhpcy5fcGF0aDtcbiAgICAgICAgcGF0aC5zdHlsZS5zdHJva2VXaWR0aCA9IDE7XG4gICAgICAgIHBhdGguc3R5bGUuc3Ryb2tlICAgICAgPSAnIzM2M2M0MCc7XG5cbiAgICB0aGlzLl9ncmlkLnN0eWxlLnN0cm9rZSA9ICdyZ2IoMjUsMjUsMjUpJztcblxuICAgIHRoaXMuX3N2Z1BvcyA9IFswLDBdO1xuXG5cbiAgICB2YXIgaGFuZGxlID0gdGhpcy5faGFuZGxlID0gdGhpcy5fc3ZnUm9vdC5hcHBlbmRDaGlsZCh0aGlzLl9jcmVhdGVTVkdPYmplY3QoJ2cnKSk7XG4gICAgdmFyIGhhbmRsZUNpcmNsZTAgPSBoYW5kbGUuYXBwZW5kQ2hpbGQodGhpcy5fY3JlYXRlU1ZHT2JqZWN0KCdjaXJjbGUnKSk7XG4gICAgICAgIGhhbmRsZUNpcmNsZTAuc2V0QXR0cmlidXRlKCdyJyxTdHJpbmcoMTEpKTtcbiAgICAgICAgaGFuZGxlQ2lyY2xlMC5zZXRBdHRyaWJ1dGUoJ2ZpbGwnLCdyZ2JhKDAsMCwwLDAuMDUpJyk7XG4gICAgdmFyIGhhbmRsZUNpcmNsZTEgPSBoYW5kbGUuYXBwZW5kQ2hpbGQodGhpcy5fY3JlYXRlU1ZHT2JqZWN0KCdjaXJjbGUnKSk7XG4gICAgICAgIGhhbmRsZUNpcmNsZTEuc2V0QXR0cmlidXRlKCdyJyxTdHJpbmcoMTApKTtcbiAgICAgICAgaGFuZGxlQ2lyY2xlMS5zZXRBdHRyaWJ1dGUoJ2ZpbGwnLCdyZ2IoODMsOTMsOTgpJyk7XG5cbiAgICB2YXIgaGFuZGxlQ2lyY2xlMiA9IGhhbmRsZS5hcHBlbmRDaGlsZCh0aGlzLl9jcmVhdGVTVkdPYmplY3QoJ2NpcmNsZScpKTtcbiAgICAgICAgaGFuZGxlQ2lyY2xlMi5zZXRBdHRyaWJ1dGUoJ3InLFN0cmluZyg5KSk7XG4gICAgICAgIGhhbmRsZUNpcmNsZTIuc2V0QXR0cmlidXRlKCdmaWxsJywncmdiKDU3LDY5LDc2KScpO1xuICAgICAgICBoYW5kbGVDaXJjbGUyLnNldEF0dHJpYnV0ZSgnY3knLFN0cmluZygwLjc1KSk7XG5cbiAgICB2YXIgaGFuZGxlQ2lyY2xlMyA9IGhhbmRsZS5hcHBlbmRDaGlsZCh0aGlzLl9jcmVhdGVTVkdPYmplY3QoJ2NpcmNsZScpKTtcbiAgICAgICAgaGFuZGxlQ2lyY2xlMy5zZXRBdHRyaWJ1dGUoJ3InLFN0cmluZygxMCkpO1xuICAgICAgICBoYW5kbGVDaXJjbGUzLnNldEF0dHJpYnV0ZSgnc3Ryb2tlJywncmdiKDE3LDE5LDIwKScpO1xuICAgICAgICBoYW5kbGVDaXJjbGUzLnNldEF0dHJpYnV0ZSgnc3Ryb2tlLXdpZHRoJyxTdHJpbmcoMSkpO1xuICAgICAgICBoYW5kbGVDaXJjbGUzLnNldEF0dHJpYnV0ZSgnZmlsbCcsJ25vbmUnKTtcblxuICAgIHZhciBoYW5kbGVDaXJjbGU0ID0gaGFuZGxlLmFwcGVuZENoaWxkKHRoaXMuX2NyZWF0ZVNWR09iamVjdCgnY2lyY2xlJykpO1xuICAgICAgICBoYW5kbGVDaXJjbGU0LnNldEF0dHJpYnV0ZSgncicsU3RyaW5nKDYpKTtcbiAgICAgICAgaGFuZGxlQ2lyY2xlNC5zZXRBdHRyaWJ1dGUoJ2ZpbGwnLCdyZ2IoMzAsMzQsMzYpJyk7XG4gICAgdmFyIGhhbmRsZUNpcmNsZTUgPSBoYW5kbGUuYXBwZW5kQ2hpbGQodGhpcy5fY3JlYXRlU1ZHT2JqZWN0KCdjaXJjbGUnKSk7XG4gICAgICAgIGhhbmRsZUNpcmNsZTUuc2V0QXR0cmlidXRlKCdyJyxTdHJpbmcoMykpO1xuICAgICAgICBoYW5kbGVDaXJjbGU1LnNldEF0dHJpYnV0ZSgnZmlsbCcsJ3JnYigyNTUsMjU1LDI1NSknKTtcblxuICAgICAgICBoYW5kbGUuc2V0QXR0cmlidXRlKCd0cmFuZm9ybScsJ3RyYW5zbGF0ZSgwIDApJyk7XG5cbiAgICB0aGlzLl9zdmcuYWRkRXZlbnRMaXN0ZW5lcihEb2N1bWVudEV2ZW50Lk1PVVNFX0RPV04sdGhpcy5fb25EcmFnU3RhcnQuYmluZCh0aGlzKSxmYWxzZSk7XG4gICAgdGhpcy5fZHJhd1ZhbHVlKHRoaXMuX29ialt0aGlzLl9rZXldKTtcbn1cblBhZC5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKFBsb3R0ZXIucHJvdG90eXBlKTtcblBhZC5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBQYWQ7XG5cblBhZC5wcm90b3R5cGUuX29uRHJhZ1N0YXJ0ID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzdmdQb3MgPSB0aGlzLl9zdmdQb3M7XG4gICAgc3ZnUG9zWzBdID0gMDtcbiAgICBzdmdQb3NbMV0gPSAwO1xuXG4gICAgLy9za2lwIHRvIGNvbnRhaW5lclxuICAgIHZhciBlbGVtZW50ID0gdGhpcy5fc3ZnLnBhcmVudE5vZGU7XG5cbiAgICB3aGlsZSAoZWxlbWVudCkge1xuICAgICAgICBzdmdQb3NbMF0gKz0gZWxlbWVudC5vZmZzZXRMZWZ0O1xuICAgICAgICBzdmdQb3NbMV0gKz0gZWxlbWVudC5vZmZzZXRUb3A7XG4gICAgICAgIGVsZW1lbnQgPSBlbGVtZW50Lm9mZnNldFBhcmVudDtcbiAgICB9XG5cbiAgICB2YXIgZXZlbnRNb3ZlID0gRG9jdW1lbnRFdmVudC5NT1VTRV9NT1ZFLFxuICAgICAgICBldmVudFVwICAgPSBEb2N1bWVudEV2ZW50Lk1PVVNFX1VQO1xuXG4gICAgdmFyIG9uRHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5fZHJhd1ZhbHVlSW5wdXQoKTtcbiAgICAgICAgdGhpcy5hcHBseVZhbHVlKCk7XG4gICAgICAgIHRoaXMuX29uQ2hhbmdlKCk7XG4gICAgfS5iaW5kKHRoaXMpO1xuXG4gICAgdmFyIG9uRHJhZ0VuZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5wdXNoSGlzdG9yeVN0YXRlKCk7XG4gICAgICAgIHRoaXMuX2RyYXdWYWx1ZUlucHV0KCk7XG4gICAgICAgIHRoaXMuYXBwbHlWYWx1ZSgpO1xuICAgICAgICB0aGlzLl9vbkZpbmlzaCgpO1xuXG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRNb3ZlLCBvbkRyYWcsIGZhbHNlKTtcbiAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudFVwLCBvbkRyYWdFbmQsIGZhbHNlKTtcbiAgICB9LmJpbmQodGhpcyk7XG5cbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TW92ZSwgb25EcmFnLCAgICBmYWxzZSk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudFVwLCAgIG9uRHJhZ0VuZCwgZmFsc2UpO1xuXG4gICAgdGhpcy5fZHJhd1ZhbHVlSW5wdXQoKTtcbiAgICB0aGlzLmFwcGx5VmFsdWUoKTtcbiAgICB0aGlzLl9vbkNoYW5nZSgpO1xufTtcblxuUGFkLnByb3RvdHlwZS5fcmVkcmF3ID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX2RyYXdWYWx1ZSh0aGlzLl9vYmpbdGhpcy5fa2V5XSk7XG59O1xuXG5QYWQucHJvdG90eXBlLl9kcmF3VmFsdWVJbnB1dCA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLl9kcmF3VmFsdWUodGhpcy5fZ2V0TW91c2VOb3JtYWxpemVkKCkpO1xufTtcblxuUGFkLnByb3RvdHlwZS5fZHJhd1ZhbHVlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgdGhpcy5fb2JqW3RoaXMuX2tleV0gPSB2YWx1ZTtcbiAgICB0aGlzLl9kcmF3R3JpZCgpO1xuICAgIHRoaXMuX2RyYXdQb2ludCgpO1xufTtcblxuUGFkLnByb3RvdHlwZS5fZHJhd0dyaWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHN2Z1NpemUgPSBOdW1iZXIodGhpcy5fc3ZnLmdldEF0dHJpYnV0ZSgnd2lkdGgnKSksXG4gICAgICAgIHN2Z01pZFggPSBNYXRoLmZsb29yKHN2Z1NpemUgKiAwLjUpLFxuICAgICAgICBzdmdNaWRZID0gTWF0aC5mbG9vcihzdmdTaXplICogMC41KTtcblxuICAgIHZhciBwYXRoQ21kID0gJyc7XG4gICAgcGF0aENtZCArPSB0aGlzLl9wYXRoQ21kTGluZSgwLCBzdmdNaWRZLCBzdmdTaXplLCBzdmdNaWRZKTtcbiAgICBwYXRoQ21kICs9IHRoaXMuX3BhdGhDbWRMaW5lKHN2Z01pZFgsIDAsIHN2Z01pZFgsIHN2Z1NpemUpO1xuXG4gICAgdGhpcy5fZ3JpZC5zZXRBdHRyaWJ1dGUoJ2QnLCBwYXRoQ21kKTtcbn07XG5cblxuUGFkLnByb3RvdHlwZS5fZHJhd1BvaW50ID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzdmdTaXplID0gTnVtYmVyKHRoaXMuX3N2Zy5nZXRBdHRyaWJ1dGUoJ3dpZHRoJykpO1xuXG4gICAgdmFyIHZhbHVlID0gdGhpcy5fb2JqW3RoaXMuX2tleV07XG5cbiAgICB2YXIgbG9jYWxYID0gKCAwLjUgKyB2YWx1ZVswXSAqIDAuNSApICogc3ZnU2l6ZSxcbiAgICAgICAgbG9jYWxZID0gKCAwLjUgKyAtdmFsdWVbMV0gKiAwLjUgKSAqIHN2Z1NpemU7XG5cbiAgICB2YXIgcGF0aENtZCA9ICcnO1xuICAgICAgICBwYXRoQ21kICs9IHRoaXMuX3BhdGhDbWRMaW5lKDAsIGxvY2FsWSwgc3ZnU2l6ZSwgbG9jYWxZKTtcbiAgICAgICAgcGF0aENtZCArPSB0aGlzLl9wYXRoQ21kTGluZShsb2NhbFgsIDAsIGxvY2FsWCwgc3ZnU2l6ZSk7XG5cbiAgICB0aGlzLl9wYXRoLnNldEF0dHJpYnV0ZSgnZCcsIHBhdGhDbWQpO1xuICAgIHRoaXMuX2hhbmRsZS5zZXRBdHRyaWJ1dGUoJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUoJyArIGxvY2FsWCArICcgJyArIGxvY2FsWSArICcpJyk7XG59O1xuXG5QYWQucHJvdG90eXBlLl9nZXRNb3VzZU5vcm1hbGl6ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIG9mZnNldCA9IHRoaXMuX3N2Z1BvcyxcbiAgICAgICAgbW91c2UgPSBNb3VzZS5nZXQoKS5nZXRQb3NpdGlvbigpLFxuICAgICAgICBzdmdTaXplID0gTnVtYmVyKHRoaXMuX3N2Zy5nZXRBdHRyaWJ1dGUoJ3dpZHRoJykpO1xuXG4gICAgcmV0dXJuIFstMSArIE1hdGgubWF4KDAsIE1hdGgubWluKG1vdXNlWzBdIC0gb2Zmc2V0WzBdLCBzdmdTaXplKSkgLyBzdmdTaXplICogMixcbiAgICAgICAgICAgICggMSAtIE1hdGgubWF4KDAsIE1hdGgubWluKG1vdXNlWzFdIC0gb2Zmc2V0WzFdLCBzdmdTaXplKSkgLyBzdmdTaXplICogMildO1xuXG59O1xuXG5QYWQucHJvdG90eXBlLmFwcGx5VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgQ29tcG9uZW50RXZlbnQuVkFMVUVfVVBEQVRFRCwgbnVsbCkpO1xufTtcblxuUGFkLnByb3RvdHlwZS5vblZhbHVlVXBkYXRlID0gZnVuY3Rpb24gKGUpIHtcbiAgICBpZiAoZS5kYXRhLm9yaWdpbiA9PSB0aGlzKXJldHVybjtcbiAgICB0aGlzLl9kcmF3VmFsdWUodGhpcy5fb2JqW3RoaXMuX2tleV0pO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBQYWQ7XG4iLCJ2YXIgTm9kZSA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZScpO1xuXG52YXIgQ1NTID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9DU1MnKTtcbnZhciBOdW1iZXJJbnB1dF9JbnRlcm5hbCA9IHJlcXVpcmUoJy4vTnVtYmVySW5wdXRfSW50ZXJuYWwnKTtcbnZhciBNb3VzZSA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTW91c2UnKTtcbnZhciBDb2xvclV0aWwgPSByZXF1aXJlKCcuLi9jb3JlL2NvbG9yL0NvbG9yVXRpbCcpO1xudmFyIERvY3VtZW50RXZlbnQgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L0RvY3VtZW50RXZlbnQnKSxcbiAgICBOb2RlRXZlbnQgICAgID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Ob2RlRXZlbnQnKTtcblxudmFyIERFRkFVTFRfVkFMVUVfSFVFID0gMjAwLjAsXG4gICAgREVGQVVMVF9WQUxVRV9TQVQgPSA1MC4wLFxuICAgIERFRkFVTFRfVkFMVUVfVkFMID0gNTAuMDtcblxuZnVuY3Rpb24gUGlja2VyKHBhcmVudE5vZGUpe1xuICAgIHZhciByb290ID0gdGhpcy5fbm9kZSAgICAgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLlBpY2tlciksXG4gICAgICAgIGhlYWQgPSB0aGlzLl9oZWFkTm9kZSA9IG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuSGVhZCksXG4gICAgICAgIGxhYmVsV3JhcCA9IG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuV3JhcCksXG4gICAgICAgIGxhYmVsID0gbmV3IE5vZGUoKS5zZXRTdHlsZUNsYXNzKENTUy5MYWJlbCksXG4gICAgICAgIG1lbnUgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLk1lbnUpLFxuICAgICAgICBtZW51V3JhcCA9IG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuV3JhcCk7XG5cbiAgICB2YXIgbWVudUNsb3NlID0gbmV3IE5vZGUoTm9kZS5JTlBVVF9CVVRUT04pO1xuICAgICAgICBtZW51Q2xvc2Uuc2V0U3R5bGVDbGFzcyhDU1MuQnV0dG9uTWVudUNsb3NlKTtcblxuICAgIHZhciBmaWVsZFdyYXAgID0gbmV3IE5vZGUoKS5zZXRTdHlsZUNsYXNzKCBDU1MuUGlja2VyRmllbGRXcmFwKSxcbiAgICAgICAgc2xpZGVyV3JhcCA9IG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuU2xpZGVyV3JhcCksXG4gICAgICAgIGlucHV0V3JhcCAgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoIENTUy5QaWNrZXJJbnB1dFdyYXApO1xuXG4gICAgdmFyIGNhbnZhc0ZpZWxkICA9IHRoaXMuX2NhbnZhc0ZpZWxkICA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpLFxuICAgICAgICBjYW52YXNTbGlkZXIgPSB0aGlzLl9jYW52YXNTbGlkZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdDYW52YXMnKTtcblxuICAgICAgICBmaWVsZFdyYXAuZ2V0RWxlbWVudCgpLmFwcGVuZENoaWxkKGNhbnZhc0ZpZWxkKTtcbiAgICAgICAgc2xpZGVyV3JhcC5nZXRFbGVtZW50KCkuYXBwZW5kQ2hpbGQoY2FudmFzU2xpZGVyKTtcblxuICAgICAgICB0aGlzLl9zZXRTaXplQ2FudmFzRmllbGQoMTU0LDE1NCk7XG4gICAgICAgIHRoaXMuX3NldFNpemVDYW52YXNTbGlkZXIoMTQsMTU0KTtcblxuICAgIHZhciBjb250ZXh0Q2FudmFzRmllbGQgID0gdGhpcy5fY29udGV4dENhbnZhc0ZpZWxkICA9IGNhbnZhc0ZpZWxkLmdldENvbnRleHQoJzJkJyksXG4gICAgICAgIGNvbnRleHRDYW52YXNTbGlkZXIgPSB0aGlzLl9jb250ZXh0Q2FudmFzU2xpZGVyID0gY2FudmFzU2xpZGVyLmdldENvbnRleHQoJzJkJyk7XG5cbiAgICB2YXIgaGFuZGxlRmllbGQgID0gdGhpcy5faGFuZGxlRmllbGQgID0gbmV3IE5vZGUoKTtcbiAgICAgICAgaGFuZGxlRmllbGQuc2V0U3R5bGVDbGFzcyhDU1MuUGlja2VySGFuZGxlRmllbGQpO1xuXG4gICAgdmFyIGhhbmRsZVNsaWRlciA9IHRoaXMuX2hhbmRsZVNsaWRlciA9IG5ldyBOb2RlKCk7XG4gICAgICAgIGhhbmRsZVNsaWRlci5zZXRTdHlsZUNsYXNzKENTUy5QaWNrZXJIYW5kbGVTbGlkZXIpO1xuXG4gICAgdmFyIHN0ZXAgPSAxLjAsXG4gICAgICAgIGRwICAgPSAwO1xuXG4gICAgdmFyIGNhbGxiYWNrSHVlID0gdGhpcy5fb25JbnB1dEh1ZUNoYW5nZS5iaW5kKHRoaXMpLFxuICAgICAgICBjYWxsYmFja1NhdCA9IHRoaXMuX29uSW5wdXRTYXRDaGFuZ2UuYmluZCh0aGlzKSxcbiAgICAgICAgY2FsbGJhY2tWYWwgPSB0aGlzLl9vbklucHV0VmFsQ2hhbmdlLmJpbmQodGhpcyksXG4gICAgICAgIGNhbGxiYWNrUiAgID0gdGhpcy5fb25JbnB1dFJDaGFuZ2UuYmluZCh0aGlzKSxcbiAgICAgICAgY2FsbGJhY2tHICAgPSB0aGlzLl9vbklucHV0R0NoYW5nZS5iaW5kKHRoaXMpLFxuICAgICAgICBjYWxsYmFja0IgICA9IHRoaXMuX29uSW5wdXRCQ2hhbmdlLmJpbmQodGhpcyk7XG5cblxuICAgIHZhciBpbnB1dEh1ZSA9IHRoaXMuX2lucHV0SHVlID0gbmV3IE51bWJlcklucHV0X0ludGVybmFsKHN0ZXAsZHAsbnVsbCxjYWxsYmFja0h1ZSksXG4gICAgICAgIGlucHV0U2F0ID0gdGhpcy5faW5wdXRTYXQgPSBuZXcgTnVtYmVySW5wdXRfSW50ZXJuYWwoc3RlcCxkcCxudWxsLGNhbGxiYWNrU2F0KSxcbiAgICAgICAgaW5wdXRWYWwgPSB0aGlzLl9pbnB1dFZhbCA9IG5ldyBOdW1iZXJJbnB1dF9JbnRlcm5hbChzdGVwLGRwLG51bGwsY2FsbGJhY2tWYWwpLFxuICAgICAgICBpbnB1dFIgICA9IHRoaXMuX2lucHV0UiAgID0gbmV3IE51bWJlcklucHV0X0ludGVybmFsKHN0ZXAsZHAsbnVsbCxjYWxsYmFja1IpLFxuICAgICAgICBpbnB1dEcgICA9IHRoaXMuX2lucHV0RyAgID0gbmV3IE51bWJlcklucHV0X0ludGVybmFsKHN0ZXAsZHAsbnVsbCxjYWxsYmFja0cpLFxuICAgICAgICBpbnB1dEIgICA9IHRoaXMuX2lucHV0QiAgID0gbmV3IE51bWJlcklucHV0X0ludGVybmFsKHN0ZXAsZHAsbnVsbCxjYWxsYmFja0IpO1xuXG4gICAgdmFyIGNvbnRyb2xzV3JhcCA9IG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuUGlja2VyQ29udHJvbHNXcmFwKTtcblxuICAgIHZhciBidXR0b25QaWNrICAgPSBuZXcgTm9kZShOb2RlLklOUFVUX0JVVFRPTikuc2V0U3R5bGVDbGFzcyhDU1MuQnV0dG9uKS5zZXRQcm9wZXJ0eSgndmFsdWUnLCdwaWNrJyksXG4gICAgICAgIGJ1dHRvbkNhbmNlbCA9IG5ldyBOb2RlKE5vZGUuSU5QVVRfQlVUVE9OKS5zZXRTdHlsZUNsYXNzKENTUy5CdXR0b24pLnNldFByb3BlcnR5KCd2YWx1ZScsJ2NhbmNlbCcpO1xuXG5cbiAgICB2YXIgY29sb3JDb250cmFzdCA9IG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuUGlja2VyQ29sb3JDb250cmFzdCk7XG5cbiAgICB2YXIgY29sb3IwID0gdGhpcy5fY29sb3JDdXJyTm9kZSA9IG5ldyBOb2RlKCksXG4gICAgICAgIGNvbG9yMSA9IHRoaXMuX2NvbG9yUHJldk5vZGUgPSBuZXcgTm9kZSgpO1xuXG4gICAgY29sb3JDb250cmFzdC5hZGRDaGlsZChjb2xvcjApO1xuICAgIGNvbG9yQ29udHJhc3QuYWRkQ2hpbGQoY29sb3IxKTtcblxuICAgIGNvbnRyb2xzV3JhcC5hZGRDaGlsZChidXR0b25DYW5jZWwpO1xuICAgIGNvbnRyb2xzV3JhcC5hZGRDaGlsZChidXR0b25QaWNrKTtcbiAgICBjb250cm9sc1dyYXAuYWRkQ2hpbGQoY29sb3JDb250cmFzdCk7XG5cbiAgICB0aGlzLl9zZXRDb250cmFzUHJldkNvbG9yKDAsMCwwKTtcblxuICAgIHZhciBpbnB1dEZpZWxkV3JhcEh1ZSA9IG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuUGlja2VySW5wdXRGaWVsZCksXG4gICAgICAgIGlucHV0RmllbGRXcmFwU2F0ID0gbmV3IE5vZGUoKS5zZXRTdHlsZUNsYXNzKENTUy5QaWNrZXJJbnB1dEZpZWxkKSxcbiAgICAgICAgaW5wdXRGaWVsZFdyYXBWYWwgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLlBpY2tlcklucHV0RmllbGQpO1xuXG4gICAgdmFyIGlucHV0RmllbGRXcmFwSHVlTGFiZWwgPSBuZXcgTm9kZShOb2RlLlNQQU4pLnNldFN0eWxlQ2xhc3MoQ1NTLkxhYmVsKS5zZXRQcm9wZXJ0eSgnaW5uZXJIVE1MJywnSCcpLFxuICAgICAgICBpbnB1dEZpZWxkV3JhcFNhdExhYmVsID0gbmV3IE5vZGUoTm9kZS5TUEFOKS5zZXRTdHlsZUNsYXNzKENTUy5MYWJlbCkuc2V0UHJvcGVydHkoJ2lubmVySFRNTCcsJ1MnKSxcbiAgICAgICAgaW5wdXRGaWVsZFdyYXBWYWxMYWJlbCA9IG5ldyBOb2RlKE5vZGUuU1BBTikuc2V0U3R5bGVDbGFzcyhDU1MuTGFiZWwpLnNldFByb3BlcnR5KCdpbm5lckhUTUwnLCdWJyk7XG5cbiAgICAgICAgaW5wdXRGaWVsZFdyYXBIdWUuYWRkQ2hpbGRyZW4oaW5wdXRGaWVsZFdyYXBIdWVMYWJlbCxpbnB1dEh1ZS5nZXROb2RlKCkpO1xuICAgICAgICBpbnB1dEZpZWxkV3JhcFNhdC5hZGRDaGlsZHJlbihpbnB1dEZpZWxkV3JhcFNhdExhYmVsLGlucHV0U2F0LmdldE5vZGUoKSk7XG4gICAgICAgIGlucHV0RmllbGRXcmFwVmFsLmFkZENoaWxkcmVuKGlucHV0RmllbGRXcmFwVmFsTGFiZWwsaW5wdXRWYWwuZ2V0Tm9kZSgpKTtcblxuICAgIHZhciBpbnB1dEZpZWxkV3JhcFIgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLlBpY2tlcklucHV0RmllbGQpLFxuICAgICAgICBpbnB1dEZpZWxkV3JhcEcgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLlBpY2tlcklucHV0RmllbGQpLFxuICAgICAgICBpbnB1dEZpZWxkV3JhcEIgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLlBpY2tlcklucHV0RmllbGQpO1xuXG4gICAgdmFyIGlucHV0RmllbGRXcmFwUkxhYmVsID0gbmV3IE5vZGUoTm9kZS5TUEFOKS5zZXRTdHlsZUNsYXNzKENTUy5MYWJlbCkuc2V0UHJvcGVydHkoJ2lubmVySFRNTCcsJ1InKSxcbiAgICAgICAgaW5wdXRGaWVsZFdyYXBHTGFiZWwgPSBuZXcgTm9kZShOb2RlLlNQQU4pLnNldFN0eWxlQ2xhc3MoQ1NTLkxhYmVsKS5zZXRQcm9wZXJ0eSgnaW5uZXJIVE1MJywnRycpLFxuICAgICAgICBpbnB1dEZpZWxkV3JhcEJMYWJlbCA9IG5ldyBOb2RlKE5vZGUuU1BBTikuc2V0U3R5bGVDbGFzcyhDU1MuTGFiZWwpLnNldFByb3BlcnR5KCdpbm5lckhUTUwnLCdCJyk7XG5cbiAgICAgICAgaW5wdXRGaWVsZFdyYXBSLmFkZENoaWxkcmVuKGlucHV0RmllbGRXcmFwUkxhYmVsLGlucHV0Ui5nZXROb2RlKCkpO1xuICAgICAgICBpbnB1dEZpZWxkV3JhcEcuYWRkQ2hpbGRyZW4oaW5wdXRGaWVsZFdyYXBHTGFiZWwsaW5wdXRHLmdldE5vZGUoKSk7XG4gICAgICAgIGlucHV0RmllbGRXcmFwQi5hZGRDaGlsZHJlbihpbnB1dEZpZWxkV3JhcEJMYWJlbCxpbnB1dEIuZ2V0Tm9kZSgpKTtcblxuXG4gICAgICAgIGlucHV0V3JhcC5hZGRDaGlsZHJlbihpbnB1dEZpZWxkV3JhcFIsaW5wdXRGaWVsZFdyYXBIdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dEZpZWxkV3JhcEcsaW5wdXRGaWVsZFdyYXBTYXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnB1dEZpZWxkV3JhcEIsaW5wdXRGaWVsZFdyYXBWYWwsY29sb3JDb250cmFzdCk7XG5cbiAgICB2YXIgaGV4SW5wdXRXcmFwID0gbmV3IE5vZGUoKTtcbiAgICAgICAgaGV4SW5wdXRXcmFwLnNldFN0eWxlQ2xhc3MoQ1NTLlBpY2tlcklucHV0V3JhcCk7XG5cbiAgICB2YXIgaW5wdXRIRVggPSB0aGlzLl9pbnB1dEhFWCA9IG5ldyBOb2RlKE5vZGUuSU5QVVRfVEVYVCksXG4gICAgICAgIGlucHV0RmllbGRXcmFwSEVYICAgICAgICAgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLlBpY2tlcklucHV0RmllbGQpLFxuICAgICAgICBpbnB1dEZpZWxkV3JhcEhFWExhYmVsICAgID0gbmV3IE5vZGUoTm9kZS5TUEFOKS5zZXRTdHlsZUNsYXNzKENTUy5MYWJlbCk7XG5cbiAgICAgICAgaW5wdXRGaWVsZFdyYXBIRVhMYWJlbC5zZXRQcm9wZXJ0eSgnaW5uZXJIVE1MJywnIycpO1xuICAgICAgICBpbnB1dEZpZWxkV3JhcEhFWC5hZGRDaGlsZHJlbihpbnB1dEZpZWxkV3JhcEhFWExhYmVsLGlucHV0SEVYKTtcblxuICAgICAgICBoZXhJbnB1dFdyYXAuYWRkQ2hpbGQoaW5wdXRGaWVsZFdyYXBIRVgpO1xuXG4gICAgICAgIGlucHV0SEVYLmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50LkNIQU5HRSx0aGlzLl9vbklucHV0SEVYRmluaXNoLmJpbmQodGhpcykpO1xuXG4gICAgICAgIGxhYmVsLnNldFByb3BlcnR5KCdpbm5lckhUTUwnLCdDb2xvciBQaWNrZXInKTtcblxuICAgICAgICBtZW51LmFkZENoaWxkKG1lbnVDbG9zZSk7XG4gICAgICAgIGhlYWQuYWRkQ2hpbGQobWVudSk7XG4gICAgICAgIGxhYmVsV3JhcC5hZGRDaGlsZChsYWJlbCk7XG4gICAgICAgIGhlYWQuYWRkQ2hpbGQobGFiZWxXcmFwKTtcbiAgICAgICAgcm9vdC5hZGRDaGlsZChoZWFkKTtcbiAgICAgICAgcm9vdC5hZGRDaGlsZChtZW51V3JhcCk7XG5cbiAgICAgICAgLy93cmFwTm9kZS5hZGRDaGlsZChwYWxldHRlV3JhcCk7XG5cbiAgICAgICAgbWVudVdyYXAuYWRkQ2hpbGQoZmllbGRXcmFwKTtcbiAgICAgICAgbWVudVdyYXAuYWRkQ2hpbGQoc2xpZGVyV3JhcCk7XG4gICAgICAgIG1lbnVXcmFwLmFkZENoaWxkKGlucHV0V3JhcCk7XG4gICAgICAgIG1lbnVXcmFwLmFkZENoaWxkKGhleElucHV0V3JhcCk7XG4gICAgICAgIG1lbnVXcmFwLmFkZENoaWxkKGNvbnRyb2xzV3JhcCk7XG5cbiAgICAgICAgZmllbGRXcmFwLmFkZENoaWxkKCBoYW5kbGVGaWVsZCk7XG4gICAgICAgIHNsaWRlcldyYXAuYWRkQ2hpbGQoaGFuZGxlU2xpZGVyKTtcblxuICAgIHZhciBldmVudE1vdXNlRG93biA9IE5vZGVFdmVudC5NT1VTRV9ET1dOLFxuICAgICAgICBjYWxsYmFjayAgICAgICA9IHRoaXMuX29uQ2FudmFzRmllbGRNb3VzZURvd24uYmluZCh0aGlzKTtcblxuICAgICAgICBmaWVsZFdyYXAuYWRkRXZlbnRMaXN0ZW5lciggIGV2ZW50TW91c2VEb3duLCBjYWxsYmFjayk7XG4gICAgICAgIGhhbmRsZUZpZWxkLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRNb3VzZURvd24sIGNhbGxiYWNrKTtcblxuICAgICAgICBjYWxsYmFjayA9IHRoaXMuX29uQ2FudmFzU2xpZGVyTW91c2VEb3duLmJpbmQodGhpcyk7XG5cbiAgICAgICAgc2xpZGVyV3JhcC5hZGRFdmVudExpc3RlbmVyKCAgZXZlbnRNb3VzZURvd24sIGNhbGxiYWNrKTtcbiAgICAgICAgaGFuZGxlU2xpZGVyLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRNb3VzZURvd24sIGNhbGxiYWNrKTtcblxuICAgICAgICBtZW51Q2xvc2UuYWRkRXZlbnRMaXN0ZW5lciggICBldmVudE1vdXNlRG93biwgdGhpcy5fb25DbG9zZS5iaW5kKHRoaXMpKTtcbiAgICAgICAgYnV0dG9uUGljay5hZGRFdmVudExpc3RlbmVyKCAgZXZlbnRNb3VzZURvd24sIHRoaXMuX29uUGljay5iaW5kKHRoaXMpKTtcbiAgICAgICAgYnV0dG9uQ2FuY2VsLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRNb3VzZURvd24sIHRoaXMuX29uQ2xvc2UuYmluZCh0aGlzKSk7XG5cbiAgICAgICAgaGVhZC5hZGRFdmVudExpc3RlbmVyKE5vZGVFdmVudC5NT1VTRV9ET1dOLCB0aGlzLl9vbkhlYWREcmFnU3RhcnQuYmluZCh0aGlzKSk7XG5cbiAgICB0aGlzLl9wYXJlbnROb2RlID0gcGFyZW50Tm9kZTtcblxuICAgIHRoaXMuX21vdXNlT2Zmc2V0ID0gWzAsMF07XG4gICAgdGhpcy5fcG9zaXRpb24gICAgPSBbbnVsbCxudWxsXTtcblxuICAgIHRoaXMuX2NhbnZhc1NsaWRlclBvcyA9IFswLDBdO1xuICAgIHRoaXMuX2NhbnZhc0ZpZWxkUG9zICA9IFswLDBdO1xuICAgIHRoaXMuX2hhbmRsZUZpZWxkU2l6ZSAgICA9IDEyO1xuICAgIHRoaXMuX2hhbmRsZVNsaWRlckhlaWdodCA9IDc7XG5cbiAgICB0aGlzLl9pbWFnZURhdGFTbGlkZXIgPSBjb250ZXh0Q2FudmFzU2xpZGVyLmNyZWF0ZUltYWdlRGF0YShjYW52YXNTbGlkZXIud2lkdGgsY2FudmFzU2xpZGVyLmhlaWdodCk7XG4gICAgdGhpcy5faW1hZ2VEYXRhRmllbGQgID0gY29udGV4dENhbnZhc0ZpZWxkLmNyZWF0ZUltYWdlRGF0YSggY2FudmFzRmllbGQud2lkdGgsIGNhbnZhc0ZpZWxkLmhlaWdodCk7XG5cbiAgICB0aGlzLl92YWx1ZUh1ZU1pbk1heCA9IFswLDM2MF07XG4gICAgdGhpcy5fdmFsdWVTYXRNaW5NYXggPSB0aGlzLl92YWx1ZVZhbE1pbk1heCA9IFswLDEwMF07XG4gICAgdGhpcy5fdmFsdWVSR0JNaW5NYXggPSBbMCwyNTVdO1xuXG4gICAgdGhpcy5fdmFsdWVIdWUgPSBERUZBVUxUX1ZBTFVFX0hVRTtcbiAgICB0aGlzLl92YWx1ZVNhdCA9IERFRkFVTFRfVkFMVUVfU0FUO1xuICAgIHRoaXMuX3ZhbHVlVmFsID0gREVGQVVMVF9WQUxVRV9WQUw7XG4gICAgdGhpcy5fdmFsdWVSICAgPSAwO1xuICAgIHRoaXMuX3ZhbHVlRyAgID0gMDtcbiAgICB0aGlzLl92YWx1ZUIgICA9IDA7XG5cbiAgICB0aGlzLl92YWx1ZUhFWCA9ICcjMDAwMDAwJztcbiAgICB0aGlzLl92YWx1ZUhFWFZhbGlkID0gdGhpcy5fdmFsdWVIRVg7XG5cbiAgICB0aGlzLl9jYWxsYmFja1BpY2sgPSBmdW5jdGlvbigpe307XG5cbiAgICAvL3RoaXMuX2NhbnZhc0ZpZWxkSW1hZ2VEYXRhRnVuYyA9IGZ1bmN0aW9uKGksail7cmV0dXJuIHRoaXMuX0hTVjJSR0IodGhpcy5fdmFsdWVIdWUsail9XG5cbiAgICB0aGlzLl9kcmF3Q2FudmFzRmllbGQoKTtcbiAgICB0aGlzLl9kcmF3Q2FudmFzU2xpZGVyKCk7XG5cbiAgICB0aGlzLl9zZXRDb2xvckhTVih0aGlzLl92YWx1ZUh1ZSx0aGlzLl92YWx1ZVNhdCx0aGlzLl92YWx1ZVZhbCk7XG5cbiAgICB0aGlzLl91cGRhdGVDb2xvclJHQkZyb21IU1YoKTtcbiAgICB0aGlzLl91cGRhdGVDb2xvckhFWEZyb21SR0IoKTtcblxuICAgIHRoaXMuX3VwZGF0ZUhhbmRsZXMoKTtcbn1cblxuUGlja2VyLnByb3RvdHlwZSA9XG57XG4gICAgX2RyYXdIYW5kbGVGaWVsZDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY2FudmFzID0gdGhpcy5fY2FudmFzRmllbGQsXG4gICAgICAgICAgICBub2RlUG9zID0gdGhpcy5fY2FudmFzRmllbGRQb3MsXG4gICAgICAgICAgICBtb3VzZVBvcyA9IE1vdXNlLmdldCgpLmdldFBvc2l0aW9uKCk7XG5cbiAgICAgICAgdmFyIHBvc1ggPSBNYXRoLm1heCgwLCBNYXRoLm1pbihtb3VzZVBvc1swXSAtIG5vZGVQb3NbMF0sIGNhbnZhcy53aWR0aCkpLFxuICAgICAgICAgICAgcG9zWSA9IE1hdGgubWF4KDAsIE1hdGgubWluKG1vdXNlUG9zWzFdIC0gbm9kZVBvc1sxXSwgY2FudmFzLmhlaWdodCkpLFxuICAgICAgICAgICAgcG9zWE5vcm0gPSBwb3NYIC8gY2FudmFzLndpZHRoLFxuICAgICAgICAgICAgcG9zWU5vcm0gPSBwb3NZIC8gY2FudmFzLmhlaWdodDtcblxuICAgICAgICB2YXIgc2F0ID0gTWF0aC5yb3VuZChwb3NYTm9ybSAqIHRoaXMuX3ZhbHVlU2F0TWluTWF4WzFdKSxcbiAgICAgICAgICAgIHZhbCA9IE1hdGgucm91bmQoKDEuMCAtIHBvc1lOb3JtKSAqIHRoaXMuX3ZhbHVlVmFsTWluTWF4WzFdKTtcblxuICAgICAgICB0aGlzLl9zZXRDb2xvckhTVih0aGlzLl92YWx1ZUh1ZSwgc2F0LCB2YWwpO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZUNvbG9yUkdCRnJvbUhTVigpO1xuICAgICAgICB0aGlzLl91cGRhdGVDb2xvckhFWEZyb21SR0IoKTtcblxuICAgICAgICB0aGlzLl91cGRhdGVIYW5kbGVGaWVsZCgpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlSGFuZGxlRmllbGQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHdpZHRoID0gdGhpcy5fY2FudmFzRmllbGQud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQgPSB0aGlzLl9jYW52YXNGaWVsZC5oZWlnaHQsXG4gICAgICAgICAgICBvZmZzZXRIYW5kbGUgPSB0aGlzLl9oYW5kbGVGaWVsZFNpemUgKiAwLjI1O1xuXG4gICAgICAgIHZhciBzYXROb3JtID0gdGhpcy5fdmFsdWVTYXQgLyB0aGlzLl92YWx1ZVNhdE1pbk1heFsxXSxcbiAgICAgICAgICAgIHZhbE5vcm0gPSB0aGlzLl92YWx1ZVZhbCAvIHRoaXMuX3ZhbHVlVmFsTWluTWF4WzFdO1xuXG4gICAgICAgIHRoaXMuX2hhbmRsZUZpZWxkLnNldFBvc2l0aW9uR2xvYmFsKHNhdE5vcm0gKiB3aWR0aCAtIG9mZnNldEhhbmRsZSxcbiAgICAgICAgICAgICgxLjAgLSB2YWxOb3JtKSAqIGhlaWdodCAtIG9mZnNldEhhbmRsZSk7XG5cbiAgICB9LFxuXG4gICAgX2RyYXdIYW5kbGVTbGlkZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNhbnZhcyA9IHRoaXMuX2NhbnZhc1NsaWRlcixcbiAgICAgICAgICAgIGNhbnZhc1Bvc1kgPSB0aGlzLl9jYW52YXNTbGlkZXJQb3NbMV0sXG4gICAgICAgICAgICBtb3VzZVBvc1kgPSBNb3VzZS5nZXQoKS5nZXRZKCk7XG5cbiAgICAgICAgdmFyIHBvc1kgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihtb3VzZVBvc1kgLSBjYW52YXNQb3NZLCBjYW52YXMuaGVpZ2h0KSksXG4gICAgICAgICAgICBwb3NZTm9ybSA9IHBvc1kgLyBjYW52YXMuaGVpZ2h0O1xuXG4gICAgICAgIHZhciBodWUgPSBNYXRoLmZsb29yKCgxLjAgLSBwb3NZTm9ybSkgKiB0aGlzLl92YWx1ZUh1ZU1pbk1heFsxXSk7XG5cbiAgICAgICAgdGhpcy5fc2V0Q29sb3JIU1YoaHVlLCB0aGlzLl92YWx1ZVNhdCwgdGhpcy5fdmFsdWVWYWwpO1xuXG4gICAgICAgIHRoaXMuX3VwZGF0ZUNvbG9yUkdCRnJvbUhTVigpO1xuICAgICAgICB0aGlzLl91cGRhdGVDb2xvckhFWEZyb21SR0IoKTtcblxuICAgICAgICB0aGlzLl91cGRhdGVIYW5kbGVTbGlkZXIoKTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUhhbmRsZVNsaWRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaGVpZ2h0ID0gdGhpcy5fY2FudmFzU2xpZGVyLmhlaWdodCxcbiAgICAgICAgICAgIG9mZnNldEhhbmRsZSA9IHRoaXMuX2hhbmRsZVNsaWRlckhlaWdodCAqIDAuMjU7XG5cbiAgICAgICAgdmFyIGh1ZU5vcm0gPSB0aGlzLl92YWx1ZUh1ZSAvIHRoaXMuX3ZhbHVlSHVlTWluTWF4WzFdO1xuXG4gICAgICAgIHRoaXMuX2hhbmRsZVNsaWRlci5zZXRQb3NpdGlvbkdsb2JhbFkoKGhlaWdodCAtIG9mZnNldEhhbmRsZSkgKiAoMS4wIC0gaHVlTm9ybSkpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlSGFuZGxlczogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl91cGRhdGVIYW5kbGVGaWVsZCgpO1xuICAgICAgICB0aGlzLl91cGRhdGVIYW5kbGVTbGlkZXIoKTtcbiAgICB9LFxuXG4gICAgLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0qL1xuXG4gICAgX3NldEh1ZTogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHZhciBtaW5NYXggPSB0aGlzLl92YWx1ZUh1ZU1pbk1heDtcblxuICAgICAgICB0aGlzLl92YWx1ZUh1ZSA9IHZhbHVlID09IG1pbk1heFsxXSA/IG1pbk1heFswXSA6IHZhbHVlO1xuICAgICAgICB0aGlzLl91cGRhdGVDb2xvckhTVigpO1xuICAgICAgICB0aGlzLl9kcmF3Q2FudmFzRmllbGQoKTtcbiAgICB9LFxuXG4gICAgX3NldFNhdDogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX3ZhbHVlU2F0ID0gTWF0aC5yb3VuZCh2YWx1ZSk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUNvbG9ySFNWKCk7XG4gICAgfSxcblxuICAgIF9zZXRWYWw6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB0aGlzLl92YWx1ZVZhbCA9IE1hdGgucm91bmQodmFsdWUpO1xuICAgICAgICB0aGlzLl91cGRhdGVDb2xvckhTVigpO1xuICAgIH0sXG5cbiAgICBfc2V0UjogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX3ZhbHVlUiA9IE1hdGgucm91bmQodmFsdWUpO1xuICAgICAgICB0aGlzLl91cGRhdGVDb2xvclJHQigpO1xuICAgIH0sXG5cbiAgICBfc2V0RzogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX3ZhbHVlRyA9IE1hdGgucm91bmQodmFsdWUpO1xuICAgICAgICB0aGlzLl91cGRhdGVDb2xvclJHQigpO1xuICAgIH0sXG5cbiAgICBfc2V0QjogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX3ZhbHVlQiA9IE1hdGgucm91bmQodmFsdWUpO1xuICAgICAgICB0aGlzLl91cGRhdGVDb2xvclJHQigpO1xuICAgIH0sXG5cbiAgICAvKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSovXG5cbiAgICBfb25JbnB1dEh1ZUNoYW5nZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLl9pbnB1dEh1ZSxcbiAgICAgICAgICAgIGlucHV0VmFsID0gdGhpcy5fZ2V0VmFsdWVDb250cmFpbmVkKGlucHV0LCB0aGlzLl92YWx1ZUh1ZU1pbk1heCk7XG5cbiAgICAgICAgdmFyIG1pbk1heCA9IHRoaXMuX3ZhbHVlSHVlTWluTWF4O1xuXG4gICAgICAgIGlmIChpbnB1dFZhbCA9PSBtaW5NYXhbMV0pIHtcbiAgICAgICAgICAgIGlucHV0VmFsID0gbWluTWF4WzBdO1xuICAgICAgICAgICAgaW5wdXQuc2V0VmFsdWUoaW5wdXRWYWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fc2V0SHVlKGlucHV0VmFsKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlQ29sb3JSR0JGcm9tSFNWKCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUNvbG9ySEVYRnJvbVJHQigpO1xuICAgICAgICB0aGlzLl91cGRhdGVIYW5kbGVTbGlkZXIoKTtcblxuICAgICAgICB0aGlzLl9kcmF3Q2FudmFzRmllbGQoKTtcbiAgICB9LFxuXG4gICAgX29uSW5wdXRTYXRDaGFuZ2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5fc2V0U2F0KHRoaXMuX2dldFZhbHVlQ29udHJhaW5lZCh0aGlzLl9pbnB1dFNhdCwgdGhpcy5fdmFsdWVTYXRNaW5NYXgpKTtcbiAgICAgICAgdGhpcy5fb25JbnB1dFNWQ2hhbmdlKCk7XG4gICAgfSxcblxuICAgIF9vbklucHV0VmFsQ2hhbmdlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuX3NldFZhbCh0aGlzLl9nZXRWYWx1ZUNvbnRyYWluZWQodGhpcy5faW5wdXRWYWwsIHRoaXMuX3ZhbHVlVmFsTWluTWF4KSk7XG4gICAgICAgIHRoaXMuX29uSW5wdXRTVkNoYW5nZSgpO1xuICAgIH0sXG5cbiAgICBfb25JbnB1dFJDaGFuZ2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5fc2V0Uih0aGlzLl9nZXRWYWx1ZUNvbnRyYWluZWQodGhpcy5faW5wdXRSLCB0aGlzLl92YWx1ZVJHQk1pbk1heCkpO1xuICAgICAgICB0aGlzLl9vbklucHV0UkdCQ2hhbmdlKCk7XG4gICAgfSxcblxuICAgIF9vbklucHV0R0NoYW5nZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9zZXRHKHRoaXMuX2dldFZhbHVlQ29udHJhaW5lZCh0aGlzLl9pbnB1dEcsIHRoaXMuX3ZhbHVlUkdCTWluTWF4KSk7XG4gICAgICAgIHRoaXMuX29uSW5wdXRSR0JDaGFuZ2UoKTtcbiAgICB9LFxuXG4gICAgX29uSW5wdXRCQ2hhbmdlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuX3NldEIodGhpcy5fZ2V0VmFsdWVDb250cmFpbmVkKHRoaXMuX2lucHV0QiwgdGhpcy5fdmFsdWVSR0JNaW5NYXgpKTtcbiAgICAgICAgdGhpcy5fb25JbnB1dFJHQkNoYW5nZSgpO1xuICAgIH0sXG5cbiAgICBfb25JbnB1dEhFWEZpbmlzaDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaW5wdXQgPSB0aGlzLl9pbnB1dEhFWCxcbiAgICAgICAgICAgIHZhbHVlID0gaW5wdXQuZ2V0UHJvcGVydHkoJ3ZhbHVlJyk7XG5cbiAgICAgICAgaWYgKCFDb2xvclV0aWwuaXNWYWxpZEhFWCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIGlucHV0LnNldFByb3BlcnR5KCd2YWx1ZScsIHRoaXMuX3ZhbHVlSEVYVmFsaWQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fdmFsdWVIRVggPSB0aGlzLl92YWx1ZUhFWFZhbGlkID0gdmFsdWU7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUNvbG9yRnJvbUhFWCgpO1xuICAgIH0sXG5cbiAgICBfb25JbnB1dFNWQ2hhbmdlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUNvbG9yUkdCRnJvbUhTVigpO1xuICAgICAgICB0aGlzLl91cGRhdGVDb2xvckhFWEZyb21SR0IoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlSGFuZGxlRmllbGQoKTtcbiAgICB9LFxuXG4gICAgX29uSW5wdXRSR0JDaGFuZ2U6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlQ29sb3JIU1ZGcm9tUkdCKCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUNvbG9ySEVYRnJvbVJHQigpO1xuICAgICAgICB0aGlzLl91cGRhdGVIYW5kbGVzKCk7XG4gICAgfSxcblxuICAgIF9nZXRWYWx1ZUNvbnRyYWluZWQ6IGZ1bmN0aW9uIChpbnB1dCwgbWluTWF4KSB7XG4gICAgICAgIHZhciBpbnB1dFZhbCA9IE1hdGgucm91bmQoaW5wdXQuZ2V0VmFsdWUoKSksXG4gICAgICAgICAgICBtaW4gPSBtaW5NYXhbMF0sXG4gICAgICAgICAgICBtYXggPSBtaW5NYXhbMV07XG5cbiAgICAgICAgaWYgKGlucHV0VmFsIDw9IG1pbikge1xuICAgICAgICAgICAgaW5wdXRWYWwgPSBtaW47XG4gICAgICAgICAgICBpbnB1dC5zZXRWYWx1ZShpbnB1dFZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlucHV0VmFsID49IG1heCkge1xuICAgICAgICAgICAgaW5wdXRWYWwgPSBtYXg7XG4gICAgICAgICAgICBpbnB1dC5zZXRWYWx1ZShpbnB1dFZhbCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gaW5wdXRWYWw7XG4gICAgfSxcblxuXG4gICAgX3VwZGF0ZUlucHV0SHVlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuX2lucHV0SHVlLnNldFZhbHVlKHRoaXMuX3ZhbHVlSHVlKTtcbiAgICB9LFxuICAgIF91cGRhdGVJbnB1dFNhdDogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9pbnB1dFNhdC5zZXRWYWx1ZSh0aGlzLl92YWx1ZVNhdCk7XG4gICAgfSxcbiAgICBfdXBkYXRlSW5wdXRWYWw6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5faW5wdXRWYWwuc2V0VmFsdWUodGhpcy5fdmFsdWVWYWwpO1xuICAgIH0sXG4gICAgX3VwZGF0ZUlucHV0UjogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9pbnB1dFIuc2V0VmFsdWUodGhpcy5fdmFsdWVSKTtcbiAgICB9LFxuICAgIF91cGRhdGVJbnB1dEc6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5faW5wdXRHLnNldFZhbHVlKHRoaXMuX3ZhbHVlRyk7XG4gICAgfSxcbiAgICBfdXBkYXRlSW5wdXRCOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuX2lucHV0Qi5zZXRWYWx1ZSh0aGlzLl92YWx1ZUIpO1xuICAgIH0sXG4gICAgX3VwZGF0ZUlucHV0SEVYOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuX2lucHV0SEVYLnNldFByb3BlcnR5KCd2YWx1ZScsIHRoaXMuX3ZhbHVlSEVYKTtcbiAgICB9LFxuXG5cbiAgICBfc2V0Q29sb3JIU1Y6IGZ1bmN0aW9uIChodWUsIHNhdCwgdmFsKSB7XG4gICAgICAgIHRoaXMuX3ZhbHVlSHVlID0gaHVlO1xuICAgICAgICB0aGlzLl92YWx1ZVNhdCA9IHNhdDtcbiAgICAgICAgdGhpcy5fdmFsdWVWYWwgPSB2YWw7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlSW5wdXRIdWUoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlSW5wdXRTYXQoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlSW5wdXRWYWwoKTtcblxuICAgICAgICB0aGlzLl91cGRhdGVDb250cmFzdEN1cnJDb2xvcigpO1xuICAgIH0sXG5cbiAgICBfc2V0Q29sb3JSR0I6IGZ1bmN0aW9uIChyLCBnLCBiKSB7XG4gICAgICAgIHRoaXMuX3ZhbHVlUiA9IHI7XG4gICAgICAgIHRoaXMuX3ZhbHVlRyA9IGc7XG4gICAgICAgIHRoaXMuX3ZhbHVlQiA9IGI7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlSW5wdXRSKCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUlucHV0RygpO1xuICAgICAgICB0aGlzLl91cGRhdGVJbnB1dEIoKTtcblxuICAgICAgICB0aGlzLl91cGRhdGVDb250cmFzdEN1cnJDb2xvcigpO1xuICAgIH0sXG5cbiAgICBfc2V0Q29sb3JIRVg6IGZ1bmN0aW9uIChoZXgpIHtcbiAgICAgICAgdGhpcy5fdmFsdWVIRVggPSBoZXg7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUlucHV0SEVYKCk7XG4gICAgfSxcblxuICAgIF91cGRhdGVDb2xvckhTVjogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9zZXRDb2xvckhTVih0aGlzLl92YWx1ZUh1ZSwgdGhpcy5fdmFsdWVTYXQsIHRoaXMuX3ZhbHVlVmFsKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlQ29udHJhc3RDdXJyQ29sb3IoKTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUNvbG9yUkdCOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuX3NldENvbG9yUkdCKHRoaXMuX3ZhbHVlUiwgdGhpcy5fdmFsdWVHLCB0aGlzLl92YWx1ZUIpO1xuICAgICAgICB0aGlzLl91cGRhdGVDb250cmFzdEN1cnJDb2xvcigpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlQ29sb3JIU1ZGcm9tUkdCOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBoc3YgPSBDb2xvclV0aWwuUkdCMkhTVih0aGlzLl92YWx1ZVIsIHRoaXMuX3ZhbHVlRywgdGhpcy5fdmFsdWVCKTtcbiAgICAgICAgdGhpcy5fc2V0Q29sb3JIU1YoaHN2WzBdLCBoc3ZbMV0sIGhzdlsyXSk7XG4gICAgfSxcblxuICAgIF91cGRhdGVDb2xvclJHQkZyb21IU1Y6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJnYiA9IENvbG9yVXRpbC5IU1YyUkdCKHRoaXMuX3ZhbHVlSHVlLCB0aGlzLl92YWx1ZVNhdCwgdGhpcy5fdmFsdWVWYWwpO1xuICAgICAgICB0aGlzLl9zZXRDb2xvclJHQihyZ2JbMF0sIHJnYlsxXSwgcmdiWzJdKTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUNvbG9ySEVYRnJvbVJHQjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaGV4ID0gQ29sb3JVdGlsLlJHQjJIRVgodGhpcy5fdmFsdWVSLCB0aGlzLl92YWx1ZUcsIHRoaXMuX3ZhbHVlQik7XG4gICAgICAgIHRoaXMuX3NldENvbG9ySEVYKGhleCk7XG4gICAgfSxcblxuICAgIF91cGRhdGVDb2xvckZyb21IRVg6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJnYiA9IENvbG9yVXRpbC5IRVgyUkdCKHRoaXMuX3ZhbHVlSEVYKTtcblxuICAgICAgICB0aGlzLl9zZXRDb2xvclJHQihyZ2JbMF0sIHJnYlsxXSwgcmdiWzJdKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlQ29sb3JIU1ZGcm9tUkdCKCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUhhbmRsZXMoKTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUNvbnRyYXN0Q3VyckNvbG9yOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuX3NldENvbnRyYXN0Q3VyckNvbG9yKHRoaXMuX3ZhbHVlUiwgdGhpcy5fdmFsdWVHLCB0aGlzLl92YWx1ZUIpO1xuICAgIH0sXG4gICAgX3VwZGF0ZUNvbnRyYXN0UHJldkNvbG9yOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuX3NldENvbnRyYXNQcmV2Q29sb3IodGhpcy5fdmFsdWVSLCB0aGlzLl92YWx1ZUcsIHRoaXMuX3ZhbHVlQilcbiAgICB9LFxuXG4gICAgX3NldENvbnRyYXN0Q3VyckNvbG9yOiBmdW5jdGlvbiAociwgZywgYikge1xuICAgICAgICB0aGlzLl9jb2xvckN1cnJOb2RlLnNldFN0eWxlUHJvcGVydHkoJ2JhY2tncm91bmQnLCAncmdiKCcgKyByICsgJywnICsgZyArICcsJyArIGIgKyAnKScpXG4gICAgfSxcbiAgICBfc2V0Q29udHJhc1ByZXZDb2xvcjogZnVuY3Rpb24gKHIsIGcsIGIpIHtcbiAgICAgICAgdGhpcy5fY29sb3JQcmV2Tm9kZS5zZXRTdHlsZVByb3BlcnR5KCdiYWNrZ3JvdW5kJywgJ3JnYignICsgciArICcsJyArIGcgKyAnLCcgKyBiICsgJyknKVxuICAgIH0sXG5cbiAgICBfb25IZWFkRHJhZ1N0YXJ0OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBub2RlID0gdGhpcy5fbm9kZSxcbiAgICAgICAgICAgIHBhcmVudE5vZGUgPSB0aGlzLl9wYXJlbnROb2RlO1xuXG4gICAgICAgIHZhciBub2RlUG9zID0gbm9kZS5nZXRQb3NpdGlvbkdsb2JhbCgpLFxuICAgICAgICAgICAgbW91c2VQb3MgPSBNb3VzZS5nZXQoKS5nZXRQb3NpdGlvbigpLFxuICAgICAgICAgICAgb2Zmc2V0UG9zID0gdGhpcy5fbW91c2VPZmZzZXQ7XG5cbiAgICAgICAgb2Zmc2V0UG9zWzBdID0gbW91c2VQb3NbMF0gLSBub2RlUG9zWzBdO1xuICAgICAgICBvZmZzZXRQb3NbMV0gPSBtb3VzZVBvc1sxXSAtIG5vZGVQb3NbMV07XG5cbiAgICAgICAgdmFyIGV2ZW50TW91c2VNb3ZlID0gRG9jdW1lbnRFdmVudC5NT1VTRV9NT1ZFLFxuICAgICAgICAgICAgZXZlbnRNb3VzZVVwID0gRG9jdW1lbnRFdmVudC5NT1VTRV9VUDtcblxuICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICAgICAgdmFyIG9uRHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl91cGRhdGVQb3NpdGlvbigpO1xuICAgICAgICAgICAgICAgIHNlbGYuX3VwZGF0ZUNhbnZhc05vZGVQb3NpdGlvbnMoKTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIG9uRHJhZ0VuZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBzZWxmLl91cGRhdGVDYW52YXNOb2RlUG9zaXRpb25zKCk7XG4gICAgICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE1vdXNlTW92ZSwgb25EcmFnLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE1vdXNlVXAsIG9uRHJhZ0VuZCwgZmFsc2UpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICBwYXJlbnROb2RlLmFkZENoaWxkKG5vZGUpO1xuXG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRNb3VzZU1vdmUsIG9uRHJhZywgZmFsc2UpO1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TW91c2VVcCwgb25EcmFnRW5kLCBmYWxzZSk7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlQ2FudmFzTm9kZVBvc2l0aW9ucygpO1xuICAgIH0sXG5cbiAgICBfdXBkYXRlUG9zaXRpb246IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG1vdXNlUG9zID0gTW91c2UuZ2V0KCkuZ2V0UG9zaXRpb24oKSxcbiAgICAgICAgICAgIG9mZnNldFBvcyA9IHRoaXMuX21vdXNlT2Zmc2V0O1xuXG4gICAgICAgIHZhciBjdXJyUG9zaXRpb25YID0gbW91c2VQb3NbMF0gLSBvZmZzZXRQb3NbMF0sXG4gICAgICAgICAgICBjdXJyUG9zaXRpb25ZID0gbW91c2VQb3NbMV0gLSBvZmZzZXRQb3NbMV07XG5cbiAgICAgICAgdmFyIG5vZGUgPSB0aGlzLl9ub2RlLFxuICAgICAgICAgICAgaGVhZCA9IHRoaXMuX2hlYWROb2RlLFxuICAgICAgICAgICAgcG9zaXRpb24gPSB0aGlzLl9wb3NpdGlvbjtcblxuICAgICAgICB2YXIgbWF4WCA9IHdpbmRvdy5pbm5lcldpZHRoIC0gbm9kZS5nZXRXaWR0aCgpLFxuICAgICAgICAgICAgbWF4WSA9IHdpbmRvdy5pbm5lckhlaWdodCAtIGhlYWQuZ2V0SGVpZ2h0KCk7XG5cbiAgICAgICAgcG9zaXRpb25bMF0gPSBNYXRoLm1heCgwLCBNYXRoLm1pbihjdXJyUG9zaXRpb25YLCBtYXhYKSk7XG4gICAgICAgIHBvc2l0aW9uWzFdID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oY3VyclBvc2l0aW9uWSwgbWF4WSkpO1xuXG4gICAgICAgIG5vZGUuc2V0UG9zaXRpb25HbG9iYWwocG9zaXRpb25bMF0sIHBvc2l0aW9uWzFdKTtcbiAgICB9LFxuXG4gICAgX2RyYXdDYW52YXNGaWVsZDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgY2FudmFzID0gdGhpcy5fY2FudmFzRmllbGQsXG4gICAgICAgICAgICBjb250ZXh0ID0gdGhpcy5fY29udGV4dENhbnZhc0ZpZWxkO1xuXG4gICAgICAgIHZhciB3aWR0aCA9IGNhbnZhcy53aWR0aCxcbiAgICAgICAgICAgIGhlaWdodCA9IGNhbnZhcy5oZWlnaHQsXG4gICAgICAgICAgICBpbnZXaWR0aCA9IDEgLyB3aWR0aCxcbiAgICAgICAgICAgIGludkhlaWdodCA9IDEgLyBoZWlnaHQ7XG5cbiAgICAgICAgdmFyIGltYWdlRGF0YSA9IHRoaXMuX2ltYWdlRGF0YUZpZWxkLFxuICAgICAgICAgICAgcmdiID0gW10sXG4gICAgICAgICAgICBpbmRleCA9IDA7XG5cbiAgICAgICAgdmFyIHZhbHVlSHVlID0gdGhpcy5fdmFsdWVIdWU7XG5cbiAgICAgICAgdmFyIGkgPSAtMSwgajtcbiAgICAgICAgd2hpbGUgKCsraSA8IGhlaWdodCkge1xuICAgICAgICAgICAgaiA9IC0xO1xuXG4gICAgICAgICAgICB3aGlsZSAoKytqIDwgd2lkdGgpIHtcbiAgICAgICAgICAgICAgICByZ2IgPSBDb2xvclV0aWwuSFNWMlJHQih2YWx1ZUh1ZSwgaiAqIGludldpZHRoICogMTAwLjAsICggMS4wIC0gaSAqIGludkhlaWdodCApICogMTAwLjApO1xuICAgICAgICAgICAgICAgIGluZGV4ID0gKGkgKiB3aWR0aCArIGopICogNDtcblxuICAgICAgICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4XSA9IHJnYlswXTtcbiAgICAgICAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleCArIDFdID0gcmdiWzFdO1xuICAgICAgICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgMl0gPSByZ2JbMl07XG4gICAgICAgICAgICAgICAgaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAzXSA9IDI1NTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnRleHQucHV0SW1hZ2VEYXRhKGltYWdlRGF0YSwgMCwgMCk7XG4gICAgfSxcblxuICAgIF9kcmF3Q2FudmFzU2xpZGVyOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBjYW52YXMgPSB0aGlzLl9jYW52YXNTbGlkZXIsXG4gICAgICAgICAgICBjb250ZXh0ID0gdGhpcy5fY29udGV4dENhbnZhc1NsaWRlcjtcblxuICAgICAgICB2YXIgd2lkdGggPSBjYW52YXMud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQgPSBjYW52YXMuaGVpZ2h0LFxuICAgICAgICAgICAgaW52SGVpZ2h0ID0gMSAvIGhlaWdodDtcblxuICAgICAgICB2YXIgaW1hZ2VEYXRhID0gdGhpcy5faW1hZ2VEYXRhU2xpZGVyLFxuICAgICAgICAgICAgcmdiID0gW10sXG4gICAgICAgICAgICBpbmRleCA9IDA7XG5cbiAgICAgICAgdmFyIGkgPSAtMSwgajtcbiAgICAgICAgd2hpbGUgKCsraSA8IGhlaWdodCkge1xuICAgICAgICAgICAgaiA9IC0xO1xuXG4gICAgICAgICAgICB3aGlsZSAoKytqIDwgd2lkdGgpIHtcbiAgICAgICAgICAgICAgICByZ2IgPSBDb2xvclV0aWwuSFNWMlJHQigoMS4wIC0gaSAqIGludkhlaWdodCkgKiAzNjAuMCwgMTAwLjAsIDEwMC4wKTtcbiAgICAgICAgICAgICAgICBpbmRleCA9IChpICogd2lkdGggKyBqKSAqIDQ7XG5cbiAgICAgICAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleF0gPSByZ2JbMF07XG4gICAgICAgICAgICAgICAgaW1hZ2VEYXRhLmRhdGFbaW5kZXggKyAxXSA9IHJnYlsxXTtcbiAgICAgICAgICAgICAgICBpbWFnZURhdGEuZGF0YVtpbmRleCArIDJdID0gcmdiWzJdO1xuICAgICAgICAgICAgICAgIGltYWdlRGF0YS5kYXRhW2luZGV4ICsgM10gPSAyNTU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb250ZXh0LnB1dEltYWdlRGF0YShpbWFnZURhdGEsIDAsIDApO1xuXG4gICAgfSxcblxuICAgIF9vbkNhbnZhc0ZpZWxkTW91c2VEb3duOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBldmVudE1vdXNlTW92ZSA9IERvY3VtZW50RXZlbnQuTU9VU0VfTU9WRSxcbiAgICAgICAgICAgIGV2ZW50TW91c2VVcCA9IERvY3VtZW50RXZlbnQuTU9VU0VfVVA7XG5cbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIHZhciBvbkRyYWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fZHJhd0hhbmRsZUZpZWxkKCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb25EcmFnRW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRNb3VzZU1vdmUsIG9uRHJhZywgZmFsc2UpO1xuICAgICAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRNb3VzZVVwLCBvbkRyYWdFbmQsIGZhbHNlKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudE1vdXNlTW92ZSwgb25EcmFnLCBmYWxzZSk7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRNb3VzZVVwLCBvbkRyYWdFbmQsIGZhbHNlKTtcblxuICAgICAgICBzZWxmLl9kcmF3SGFuZGxlRmllbGQoKTtcbiAgICB9LFxuXG4gICAgX29uQ2FudmFzU2xpZGVyTW91c2VEb3duOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBldmVudE1vdXNlTW92ZSA9IERvY3VtZW50RXZlbnQuTU9VU0VfTU9WRSxcbiAgICAgICAgICAgIGV2ZW50TW91c2VVcCA9IERvY3VtZW50RXZlbnQuTU9VU0VfVVA7XG5cbiAgICAgICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgICAgIHZhciBvbkRyYWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5fZHJhd0hhbmRsZVNsaWRlcigpO1xuICAgICAgICAgICAgICAgIHNlbGYuX2RyYXdDYW52YXNGaWVsZCgpO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgb25EcmFnRW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRNb3VzZU1vdmUsIG9uRHJhZywgZmFsc2UpO1xuICAgICAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRNb3VzZVVwLCBvbkRyYWdFbmQsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICBzZWxmLl9kcmF3Q2FudmFzRmllbGQoKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudE1vdXNlTW92ZSwgb25EcmFnLCBmYWxzZSk7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRNb3VzZVVwLCBvbkRyYWdFbmQsIGZhbHNlKTtcblxuICAgICAgICBzZWxmLl9kcmF3SGFuZGxlU2xpZGVyKCk7XG4gICAgICAgIHNlbGYuX2RyYXdDYW52YXNGaWVsZCgpO1xuICAgIH0sXG5cbiAgICBfc2V0U2l6ZUNhbnZhc0ZpZWxkOiBmdW5jdGlvbiAod2lkdGgsIGhlaWdodCkge1xuICAgICAgICB2YXIgY2FudmFzID0gdGhpcy5fY2FudmFzRmllbGQ7XG4gICAgICAgIGNhbnZhcy5zdHlsZS53aWR0aCA9IHdpZHRoICsgJ3B4JztcbiAgICAgICAgY2FudmFzLnN0eWxlLmhlaWdodCA9IGhlaWdodCArICdweCc7XG4gICAgICAgIGNhbnZhcy53aWR0aCA9IHdpZHRoO1xuICAgICAgICBjYW52YXMuaGVpZ2h0ID0gaGVpZ2h0O1xuXG4gICAgfSxcblxuICAgIF9zZXRTaXplQ2FudmFzU2xpZGVyOiBmdW5jdGlvbiAod2lkdGgsIGhlaWdodCkge1xuICAgICAgICB2YXIgY2FudmFzID0gdGhpcy5fY2FudmFzU2xpZGVyO1xuICAgICAgICBjYW52YXMuc3R5bGUud2lkdGggPSB3aWR0aCArICdweCc7XG4gICAgICAgIGNhbnZhcy5zdHlsZS5oZWlnaHQgPSBoZWlnaHQgKyAncHgnO1xuICAgICAgICBjYW52YXMud2lkdGggPSB3aWR0aDtcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IGhlaWdodDtcbiAgICB9LFxuXG4gICAgb3BlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbm9kZSA9IHRoaXMuX25vZGU7XG5cbiAgICAgICAgdGhpcy5fcGFyZW50Tm9kZS5hZGRDaGlsZChub2RlKTtcblxuICAgICAgICB2YXIgcG9zaXRpb24gPSB0aGlzLl9wb3NpdGlvbjtcbiAgICAgICAgaWYocG9zaXRpb25bMF0gPT09IG51bGwgfHwgcG9zaXRpb25bMV0gPT09IG51bGwpe1xuICAgICAgICAgICAgcG9zaXRpb25bMF0gPSB3aW5kb3cuaW5uZXJXaWR0aCAqIDAuNSAtIG5vZGUuZ2V0V2lkdGgoKSAqIDAuNTtcbiAgICAgICAgICAgIHBvc2l0aW9uWzFdID0gd2luZG93LmlubmVySGVpZ2h0ICogMC41IC0gbm9kZS5nZXRIZWlnaHQoKSAqIDAuNTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHBvc2l0aW9uWzBdID0gTWF0aC5tYXgoMCxNYXRoLm1pbihwb3NpdGlvblswXSx3aW5kb3cuaW5uZXJXaWR0aCAtIG5vZGUuZ2V0V2lkdGgoKSkpO1xuICAgICAgICAgICAgcG9zaXRpb25bMV0gPSBNYXRoLm1heCgwLE1hdGgubWluKHBvc2l0aW9uWzFdLHdpbmRvdy5pbm5lckhlaWdodCAtIG5vZGUuZ2V0SGVpZ2h0KCkpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG5vZGUuc2V0UG9zaXRpb25HbG9iYWwocG9zaXRpb25bMF0scG9zaXRpb25bMV0pO1xuICAgICAgICB0aGlzLl91cGRhdGVDYW52YXNOb2RlUG9zaXRpb25zKCk7XG4gICAgfSxcblxuICAgIGNsb3NlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuX3BhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5fbm9kZSk7XG4gICAgfSxcblxuICAgIF9vbkNsb3NlOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLmNhbmNlbEJ1YmJsZSA9IHRydWU7XG4gICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICB9LFxuICAgIF9vblBpY2s6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5fY2FsbGJhY2tQaWNrKCk7XG4gICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICB9LFxuXG4gICAgX3VwZGF0ZUNhbnZhc05vZGVQb3NpdGlvbnM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNhbnZhc1NsaWRlclBvcyA9IHRoaXMuX2NhbnZhc1NsaWRlclBvcyxcbiAgICAgICAgICAgIGNhbnZhc0ZpZWxkUG9zID0gdGhpcy5fY2FudmFzRmllbGRQb3M7XG5cbiAgICAgICAgY2FudmFzU2xpZGVyUG9zWzBdID0gY2FudmFzU2xpZGVyUG9zWzFdID0gMDtcbiAgICAgICAgY2FudmFzRmllbGRQb3NbMF0gPSBjYW52YXNGaWVsZFBvc1sxXSA9IDA7XG5cbiAgICAgICAgdmFyIGVsZW1lbnQgPSB0aGlzLl9jYW52YXNTbGlkZXI7XG5cbiAgICAgICAgd2hpbGUgKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIGNhbnZhc1NsaWRlclBvc1swXSArPSBlbGVtZW50Lm9mZnNldExlZnQ7XG4gICAgICAgICAgICBjYW52YXNTbGlkZXJQb3NbMV0gKz0gZWxlbWVudC5vZmZzZXRUb3A7XG4gICAgICAgICAgICBlbGVtZW50ID0gZWxlbWVudC5vZmZzZXRQYXJlbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBlbGVtZW50ID0gdGhpcy5fY2FudmFzRmllbGQ7XG5cbiAgICAgICAgd2hpbGUgKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIGNhbnZhc0ZpZWxkUG9zWzBdICs9IGVsZW1lbnQub2Zmc2V0TGVmdDtcbiAgICAgICAgICAgIGNhbnZhc0ZpZWxkUG9zWzFdICs9IGVsZW1lbnQub2Zmc2V0VG9wO1xuICAgICAgICAgICAgZWxlbWVudCA9IGVsZW1lbnQub2Zmc2V0UGFyZW50O1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNldENhbGxiYWNrUGljazogZnVuY3Rpb24gKGZ1bmMpIHtcbiAgICAgICAgdGhpcy5fY2FsbGJhY2tQaWNrID0gZnVuYztcbiAgICB9LFxuXG4gICAgc2V0Q29sb3JIRVg6IGZ1bmN0aW9uIChoZXgpIHtcbiAgICAgICAgdGhpcy5fc2V0Q29sb3JIRVgoaGV4KTtcbiAgICAgICAgdGhpcy5fdXBkYXRlQ29sb3JGcm9tSEVYKCk7XG4gICAgICAgIHRoaXMuX3NldENvbG9yKCk7XG4gICAgfSxcblxuICAgIHNldENvbG9yUkdCOiBmdW5jdGlvbiAociwgZywgYikge1xuICAgICAgICB0aGlzLl9zZXRDb2xvclJHQihyLCBnLCBiKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlQ29sb3JIRVhGcm9tUkdCKCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUNvbG9ySFNWRnJvbVJHQigpO1xuICAgICAgICB0aGlzLl9zZXRDb2xvcigpO1xuICAgIH0sXG5cbiAgICBzZXRDb2xvclJHQmZ2OiBmdW5jdGlvbiAociwgZywgYikge1xuICAgICAgICB0aGlzLnNldENvbG9yUkdCKE1hdGguZmxvb3IociAqIDI1NS4wKSxcbiAgICAgICAgICAgIE1hdGguZmxvb3IoZyAqIDI1NS4wKSxcbiAgICAgICAgICAgIE1hdGguZmxvb3IoYiAqIDI1NS4wKSk7XG4gICAgfSxcblxuICAgIHNldENvbG9ySFNWOiBmdW5jdGlvbiAoaCwgcywgdikge1xuICAgICAgICB0aGlzLl9zZXRDb2xvckhTVihoLCBzLCB2KTtcbiAgICAgICAgdGhpcy5fdXBkYXRlQ29sb3JSR0JGcm9tSFNWKCk7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUNvbG9ySEVYRnJvbVJHQigpO1xuICAgICAgICB0aGlzLl9zZXRDb2xvcigpO1xuICAgIH0sXG5cbiAgICBfc2V0Q29sb3I6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5fZHJhd0NhbnZhc0ZpZWxkKCk7XG4gICAgICAgIHRoaXMuX2RyYXdDYW52YXNTbGlkZXIoKTtcbiAgICAgICAgdGhpcy5fdXBkYXRlSGFuZGxlcygpO1xuICAgICAgICB0aGlzLl9zZXRDb250cmFzUHJldkNvbG9yKHRoaXMuX3ZhbHVlUiwgdGhpcy5fdmFsdWVHLCB0aGlzLl92YWx1ZUIpO1xuICAgIH0sXG5cbiAgICBnZXRSOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZVI7XG4gICAgfSxcbiAgICBnZXRHOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZUc7XG4gICAgfSxcbiAgICBnZXRCOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZUI7XG4gICAgfSxcbiAgICBnZXRSR0I6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFt0aGlzLl92YWx1ZVIsIHRoaXMuX3ZhbHVlRywgdGhpcy5fdmFsdWVCXTtcbiAgICB9LFxuICAgIGdldEh1ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fdmFsdWVIdWU7XG4gICAgfSxcbiAgICBnZXRTYXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZhbHVlU2F0O1xuICAgIH0sXG4gICAgZ2V0VmFsOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZVZhbDtcbiAgICB9LFxuICAgIGdldEhTVjogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gW3RoaXMuX3ZhbHVlSHVlLCB0aGlzLl92YWx1ZVNhdCwgdGhpcy5fdmFsdWVWYWxdO1xuICAgIH0sXG4gICAgZ2V0SEVYOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZUhFWDtcbiAgICB9LFxuICAgIGdldFJHQmZ2OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBbdGhpcy5fdmFsdWVSIC8gMjU1LjAsIHRoaXMuX3ZhbHVlRyAvIDI1NS4wLCB0aGlzLl92YWx1ZUIgLyAyNTUuMF07XG4gICAgfSxcblxuICAgIGdldE5vZGU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX25vZGU7XG4gICAgfVxufTtcblxuUGlja2VyLnNldHVwID0gZnVuY3Rpb24gKHBhcmVudE5vZGUpIHtcbiAgICByZXR1cm4gUGlja2VyLl9pbnN0YW5jZSA9IG5ldyBQaWNrZXIocGFyZW50Tm9kZSk7XG59O1xuUGlja2VyLmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gUGlja2VyLl9pbnN0YW5jZTtcbn07XG5QaWNrZXIuZGVzdHJveSA9IGZ1bmN0aW9uKCl7XG4gICAgUGlja2VyLl9pbnN0YW5jZSA9IG51bGw7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFBpY2tlcjsiLCJ2YXIgU1ZHQ29tcG9uZW50ID0gcmVxdWlyZSgnLi9TVkdDb21wb25lbnQnKTtcblxuZnVuY3Rpb24gUGxvdHRlcihwYXJlbnQsb2JqZWN0LHZhbHVlLHBhcmFtcykge1xuICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcbiAgICBwYXJhbXMubGluZVdpZHRoICA9IHBhcmFtcy5saW5lV2lkdGggIHx8IDI7XG4gICAgcGFyYW1zLmxpbmVDb2xvciAgPSBwYXJhbXMubGluZUNvbG9yICB8fCBbMjU1LDI1NSwyNTVdO1xuXG4gICAgU1ZHQ29tcG9uZW50LmFwcGx5KHRoaXMsYXJndW1lbnRzKTtcblxuICAgIHZhciBsaW5lV2lkdGggPSB0aGlzLl9saW5lV2lkdGggPSBwYXJhbXMubGluZVdpZHRoO1xuICAgIHZhciBsaW5lQ29sb3IgPSBwYXJhbXMubGluZUNvbG9yO1xuXG4gICAgdmFyIGdyaWQgPSB0aGlzLl9ncmlkID0gdGhpcy5fc3ZnUm9vdC5hcHBlbmRDaGlsZCh0aGlzLl9jcmVhdGVTVkdPYmplY3QoJ3BhdGgnKSk7XG4gICAgICAgIGdyaWQuc3R5bGUuc3Ryb2tlID0gJ3JnYigyNiwyOSwzMSknO1xuXG4gICAgdmFyIHBhdGggPSB0aGlzLl9wYXRoID0gdGhpcy5fc3ZnUm9vdC5hcHBlbmRDaGlsZCh0aGlzLl9jcmVhdGVTVkdPYmplY3QoJ3BhdGgnKSk7XG4gICAgICAgIHBhdGguc3R5bGUuc3Ryb2tlICAgICAgPSAncmdiKCcrbGluZUNvbG9yWzBdKycsJytsaW5lQ29sb3JbMV0rJywnK2xpbmVDb2xvclsyXSsnKSc7XG4gICAgICAgIHBhdGguc3R5bGUuc3Ryb2tlV2lkdGggPSBsaW5lV2lkdGggO1xuICAgICAgICBwYXRoLnN0eWxlLmZpbGwgICAgICAgID0gJ25vbmUnO1xufVxuUGxvdHRlci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKFNWR0NvbXBvbmVudC5wcm90b3R5cGUpO1xuUGxvdHRlci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBQbG90dGVyO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFBsb3R0ZXI7XG4iLCJ2YXIgT2JqZWN0Q29tcG9uZW50ID0gcmVxdWlyZSgnLi4vY29yZS9PYmplY3RDb21wb25lbnQnKTtcbnZhciBOb2RlID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Ob2RlJyk7XG52YXIgTnVtYmVySW5wdXRfSW50ZXJuYWwgPSByZXF1aXJlKCcuL051bWJlcklucHV0X0ludGVybmFsJyk7XG52YXIgQ1NTID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9DU1MnKTtcblxudmFyIEV2ZW50XyAgICAgICAgID0gcmVxdWlyZSgnLi4vY29yZS9ldmVudC9FdmVudCcpLFxuICAgIENvbXBvbmVudEV2ZW50ID0gcmVxdWlyZSgnLi4vY29yZS9Db21wb25lbnRFdmVudCcpO1xuXG52YXIgREVGQVVMVF9TVEVQID0gMS4wLFxuICAgIERFRkFVTFRfRFAgICA9IDI7XG5cbmZ1bmN0aW9uIFJhbmdlKHBhcmVudCwgb2JqZWN0LCB2YWx1ZSwgcGFyYW1zKSB7XG4gICAgT2JqZWN0Q29tcG9uZW50LmFwcGx5KHRoaXMsYXJndW1lbnRzKTtcblxuICAgIHBhcmFtcyAgICAgICAgICA9IHBhcmFtcyAgICAgICAgICB8fCB7fTtcbiAgICBwYXJhbXMub25DaGFuZ2UgPSBwYXJhbXMub25DaGFuZ2UgfHwgdGhpcy5fb25DaGFuZ2U7XG4gICAgcGFyYW1zLnN0ZXAgICAgID0gcGFyYW1zLnN0ZXAgfHwgREVGQVVMVF9TVEVQO1xuICAgIHBhcmFtcy5kcCAgICAgICA9IChwYXJhbXMuZHAgIT0gbnVsbCkgPyBwYXJhbXMuZHAgOiBERUZBVUxUX0RQO1xuXG4gICAgdGhpcy5fb25DaGFuZ2UgID0gcGFyYW1zLm9uQ2hhbmdlO1xuXG4gICAgdmFyIHN0ZXAgPSB0aGlzLl9zdGVwID0gcGFyYW1zLnN0ZXAsXG4gICAgICAgIGRwICAgPSB0aGlzLl9kcCAgID0gcGFyYW1zLmRwO1xuXG4gICAgLy9GSVhNRTogaGlzdG9yeSBwdXNoIHBvcFxuXG4gICAgdmFyIGxhYmVsTWluID0gbmV3IE5vZGUoKTtcbiAgICB2YXIgaW5wdXRNaW4gPSB0aGlzLl9pbnB1dE1pbiA9IG5ldyBOdW1iZXJJbnB1dF9JbnRlcm5hbChzdGVwLGRwLCB0aGlzLnB1c2hIaXN0b3J5U3RhdGUuYmluZCh0aGlzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9vbklucHV0TWluQ2hhbmdlLmJpbmQodGhpcykpO1xuXG4gICAgdmFyIGxhYmVsTWF4ID0gbmV3IE5vZGUoKTtcbiAgICB2YXIgaW5wdXRNYXggPSB0aGlzLl9pbnB1dE1heCA9IG5ldyBOdW1iZXJJbnB1dF9JbnRlcm5hbChzdGVwLGRwLCB0aGlzLnB1c2hIaXN0b3J5U3RhdGUuYmluZCh0aGlzKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9vbklucHV0TWF4Q2hhbmdlLmJpbmQodGhpcykpO1xuXG4gICAgdmFyIGxhYmVsTWluV3JhcCA9IG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuV3JhcCksXG4gICAgICAgIGlucHV0TWluV3JhcCA9IG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuV3JhcCksXG4gICAgICAgIGxhYmVsTWF4V3JhcCA9IG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuV3JhcCksXG4gICAgICAgIGlucHV0TWF4V3JhcCA9IG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuV3JhcCk7XG5cbiAgICBsYWJlbE1pbi5zZXRTdHlsZUNsYXNzKENTUy5MYWJlbCkuc2V0UHJvcGVydHkoJ2lubmVySFRNTCcsICdNSU4nKTtcbiAgICBsYWJlbE1heC5zZXRTdHlsZUNsYXNzKENTUy5MYWJlbCkuc2V0UHJvcGVydHkoJ2lubmVySFRNTCcsICdNQVgnKTtcblxuICAgIHZhciB2YWx1ZXMgPSB0aGlzLl9vYmpbdGhpcy5fa2V5XTtcblxuICAgIGlucHV0TWluLnNldFZhbHVlKHZhbHVlc1swXSk7XG4gICAgaW5wdXRNYXguc2V0VmFsdWUodmFsdWVzWzFdKTtcblxuICAgIHZhciB3cmFwID0gdGhpcy5fd3JhcE5vZGU7XG5cbiAgICBsYWJlbE1pbldyYXAuYWRkQ2hpbGQobGFiZWxNaW4pO1xuICAgIGlucHV0TWluV3JhcC5hZGRDaGlsZChpbnB1dE1pbi5nZXROb2RlKCkpO1xuICAgIGxhYmVsTWF4V3JhcC5hZGRDaGlsZChsYWJlbE1heCk7XG4gICAgaW5wdXRNYXhXcmFwLmFkZENoaWxkKGlucHV0TWF4LmdldE5vZGUoKSk7XG5cbiAgICB3cmFwLmFkZENoaWxkKGxhYmVsTWluV3JhcCk7XG4gICAgd3JhcC5hZGRDaGlsZChpbnB1dE1pbldyYXApO1xuICAgIHdyYXAuYWRkQ2hpbGQobGFiZWxNYXhXcmFwKTtcbiAgICB3cmFwLmFkZENoaWxkKGlucHV0TWF4V3JhcCk7XG59XG5SYW5nZS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKE9iamVjdENvbXBvbmVudC5wcm90b3R5cGUpO1xuUmFuZ2UucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gUmFuZ2U7XG5cblJhbmdlLnByb3RvdHlwZS5fb25JbnB1dENoYW5nZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50Xyh0aGlzLCBDb21wb25lbnRFdmVudC5WQUxVRV9VUERBVEVELCBudWxsKSk7XG4gICAgdGhpcy5fb25DaGFuZ2UoKTtcbn07XG5cblJhbmdlLnByb3RvdHlwZS5fdXBkYXRlVmFsdWVNaW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHZhbHVlcyA9IHRoaXMuX29ialt0aGlzLl9rZXldO1xuXG4gICAgdmFyIGlucHV0TWluID0gdGhpcy5faW5wdXRNaW4sXG4gICAgICAgIGlucHV0VmFsdWUgPSBpbnB1dE1pbi5nZXRWYWx1ZSgpO1xuXG4gICAgaWYgKGlucHV0VmFsdWUgPj0gdGhpcy5faW5wdXRNYXguZ2V0VmFsdWUoKSkge1xuICAgICAgICBpbnB1dE1pbi5zZXRWYWx1ZSh2YWx1ZXNbMF0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhbHVlc1swXSA9IGlucHV0VmFsdWU7XG5cbn07XG5cblJhbmdlLnByb3RvdHlwZS5fdXBkYXRlVmFsdWVNYXggPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHZhbHVlcyA9IHRoaXMuX29ialt0aGlzLl9rZXldO1xuXG4gICAgdmFyIGlucHV0TWF4ID0gdGhpcy5faW5wdXRNYXgsXG4gICAgICAgIGlucHV0VmFsdWUgPSBpbnB1dE1heC5nZXRWYWx1ZSgpO1xuXG4gICAgaWYgKGlucHV0VmFsdWUgPD0gdGhpcy5faW5wdXRNaW4uZ2V0VmFsdWUoKSkge1xuICAgICAgICBpbnB1dE1heC5zZXRWYWx1ZSh2YWx1ZXNbMV0pO1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhbHVlc1sxXSA9IGlucHV0VmFsdWU7XG59O1xuXG5cblJhbmdlLnByb3RvdHlwZS5vblZhbHVlVXBkYXRlID0gZnVuY3Rpb24gKGUpIHtcbiAgICBpZiAoZS5kYXRhLm9yaWdpbiA9PSB0aGlzKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoZS5kYXRhLm9yaWdpbiA9PSBudWxsKSB7XG4gICAgfVxuICAgIHZhciBvID0gdGhpcy5fb2JqLGsgPSB0aGlzLl9rZXk7XG4gICAgdGhpcy5faW5wdXRNaW4uc2V0VmFsdWUob1trXVswXSk7XG4gICAgdGhpcy5faW5wdXRNYXguc2V0VmFsdWUob1trXVsxXSk7XG59O1xuXG5SYW5nZS5wcm90b3R5cGUuc2V0VmFsdWUgPSBmdW5jdGlvbih2YWx1ZSl7XG4gICAgdmFyIG8gPSB0aGlzLl9vYmosayA9IHRoaXMuX2tleTtcbiAgICBvW2tdWzBdID0gdmFsdWVbMF07XG4gICAgb1trXVsxXSA9IHZhbHVlWzFdO1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsQ29tcG9uZW50RXZlbnQuVkFMVUVfVVBEQVRFRCxudWxsKSk7XG59O1xuXG5SYW5nZS5wcm90b3R5cGUuX29uSW5wdXRNaW5DaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5fdXBkYXRlVmFsdWVNaW4oKTtcbiAgICB0aGlzLl9vbklucHV0Q2hhbmdlKCk7XG59O1xuXG5SYW5nZS5wcm90b3R5cGUuX29uSW5wdXRNYXhDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5fdXBkYXRlVmFsdWVNYXgoKTtcbiAgICB0aGlzLl9vbklucHV0Q2hhbmdlKCk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFJhbmdlOyIsInZhciBDb21wb25lbnQgPSByZXF1aXJlKCcuLy4uL2NvcmUvQ29tcG9uZW50Jyk7XG52YXIgQ1NTID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9DU1MnKTtcbnZhciBNZXRyaWMgPSByZXF1aXJlKCcuL01ldHJpYycpO1xudmFyIEdyb3VwRXZlbnQgPSByZXF1aXJlKCcuLi9ncm91cC9Hcm91cEV2ZW50Jyk7XG5cbmZ1bmN0aW9uIFNWRyhwYXJlbnQsIHBhcmFtcykge1xuICAgIENvbXBvbmVudC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuXG4gICAgdmFyIHdyYXAgPSB0aGlzLl93cmFwTm9kZTtcbiAgICAgICAgd3JhcC5zZXRTdHlsZUNsYXNzKENTUy5DYW52YXNXcmFwKTtcbiAgICB2YXIgd3JhcFNpemUgPSB3cmFwLmdldFdpZHRoKCk7XG5cbiAgICB2YXIgc3ZnID0gdGhpcy5fc3ZnID0gdGhpcy5fY3JlYXRlU1ZHT2JqZWN0KCdzdmcnKTtcbiAgICAgICAgc3ZnLnNldEF0dHJpYnV0ZSgndmVyc2lvbicsICcxLjInKTtcbiAgICAgICAgc3ZnLnNldEF0dHJpYnV0ZSgnYmFzZVByb2ZpbGUnLCAndGlueScpO1xuICAgICAgICBzdmcuc2V0QXR0cmlidXRlKCdwcmVzZXJ2ZUFzcGVjdFJhdGlvJywgJ3RydWUnKTtcblxuICAgIHdyYXAuZ2V0RWxlbWVudCgpLmFwcGVuZENoaWxkKHN2Zyk7XG5cbiAgICB0aGlzLl9zdmdTZXRTaXplKHdyYXBTaXplLCB3cmFwU2l6ZSk7XG4gICAgdGhpcy5fdXBkYXRlSGVpZ2h0KCk7XG5cbiAgICB0aGlzLl9ub2RlLnNldFN0eWxlQ2xhc3MoQ1NTLkNhbnZhc0xpc3RJdGVtKTtcblxuICAgIHRoaXMuX3BhcmVudC5hZGRFdmVudExpc3RlbmVyKEdyb3VwRXZlbnQuR1JPVVBfU0laRV9DSEFOR0UsIHRoaXMsICdvbkdyb3VwU2l6ZUNoYW5nZScpO1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcihHcm91cEV2ZW50LkdST1VQX1NJWkVfVVBEQVRFLCB0aGlzLl9wYXJlbnQsICdvbkdyb3VwU2l6ZVVwZGF0ZScpO1xufVxuU1ZHLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoQ29tcG9uZW50LnByb3RvdHlwZSk7XG5TVkcucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gU1ZHO1xuXG5TVkcucHJvdG90eXBlLl91cGRhdGVIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHN2Z0hlaWdodCA9IE51bWJlcih0aGlzLl9zdmcuZ2V0QXR0cmlidXRlKCdoZWlnaHQnKSk7XG4gICAgdGhpcy5fd3JhcE5vZGUuc2V0SGVpZ2h0KHN2Z0hlaWdodCk7XG4gICAgdGhpcy5fbm9kZS5zZXRIZWlnaHQoc3ZnSGVpZ2h0ICsgTWV0cmljLlBBRERJTkdfV1JBUFBFUik7XG59O1xuXG5TVkcucHJvdG90eXBlLm9uR3JvdXBTaXplQ2hhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciB3aWR0aCA9IHRoaXMuX3dyYXBOb2RlLmdldFdpZHRoKCk7XG4gICAgdGhpcy5fc3ZnU2V0U2l6ZSh3aWR0aCwgd2lkdGgpO1xuICAgIHRoaXMuX3VwZGF0ZUhlaWdodCgpO1xufTtcblxuU1ZHLnByb3RvdHlwZS5fc3ZnU2V0U2l6ZSA9IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgdmFyIHN2ZyA9IHRoaXMuX3N2ZztcbiAgICBzdmcuc2V0QXR0cmlidXRlKCd3aWR0aCcsIHdpZHRoKTtcbiAgICBzdmcuc2V0QXR0cmlidXRlKCdoZWlnaHQnLCBoZWlnaHQpO1xuICAgIHN2Zy5zZXRBdHRyaWJ1dGUoJ3ZpZXdib3gnLCAnMCAwICcgKyB3aWR0aCArICcgJyArIGhlaWdodCk7XG59O1xuXG5TVkcucHJvdG90eXBlLmdldFNWRyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fc3ZnO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBTVkc7IiwidmFyIE9iamVjdENvbXBvbmVudCA9IHJlcXVpcmUoJy4uL2NvcmUvT2JqZWN0Q29tcG9uZW50Jyk7XG52YXIgQ1NTID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9DU1MnKTtcbnZhciBHcm91cEV2ZW50ID0gcmVxdWlyZSgnLi4vZ3JvdXAvR3JvdXBFdmVudCcpO1xudmFyIE1ldHJpYyA9IHJlcXVpcmUoJy4vTWV0cmljJyk7XG5cbmZ1bmN0aW9uIFNWR0NvbXBvbmVudChwYXJlbnQsb2JqZWN0LHZhbHVlLHBhcmFtcyl7XG4gICAgT2JqZWN0Q29tcG9uZW50LmFwcGx5KHRoaXMsYXJndW1lbnRzKTtcblxuICAgIHZhciB3cmFwID0gdGhpcy5fd3JhcE5vZGU7XG4gICAgICAgIHdyYXAuc2V0U3R5bGVDbGFzcyhDU1MuU1ZHV3JhcCk7XG4gICAgdmFyIHdyYXBTaXplID0gd3JhcC5nZXRXaWR0aCgpO1xuXG4gICAgdmFyIHN2ZyA9IHRoaXMuX3N2ZyA9IHRoaXMuX2NyZWF0ZVNWR09iamVjdCgnc3ZnJyk7XG4gICAgICAgIHN2Zy5zZXRBdHRyaWJ1dGUoJ3ZlcnNpb24nLCAnMS4yJyk7XG4gICAgICAgIHN2Zy5zZXRBdHRyaWJ1dGUoJ2Jhc2VQcm9maWxlJywgJ3RpbnknKTtcblxuICAgICAgICB3cmFwLmdldEVsZW1lbnQoKS5hcHBlbmRDaGlsZChzdmcpO1xuXG4gICAgdmFyIHN2Z1Jvb3QgPSB0aGlzLl9zdmdSb290ID0gc3ZnLmFwcGVuZENoaWxkKHRoaXMuX2NyZWF0ZVNWR09iamVjdCgnZycpKTtcbiAgICAgICAgc3ZnUm9vdC5zZXRBdHRyaWJ1dGUoJ3RyYW5zZm9ybScsJ3RyYW5zbGF0ZSgwLjUgMC41KScpO1xuXG4gICAgdGhpcy5fc3ZnU2V0U2l6ZSh3cmFwU2l6ZSx3cmFwU2l6ZSk7XG4gICAgdGhpcy5fdXBkYXRlSGVpZ2h0KCk7XG5cbiAgICB0aGlzLl9ub2RlLnNldFN0eWxlQ2xhc3MoQ1NTLlNWR0xpc3RJdGVtKTtcblxuICAgIHRoaXMuX3BhcmVudC5hZGRFdmVudExpc3RlbmVyKEdyb3VwRXZlbnQuR1JPVVBfU0laRV9DSEFOR0UsIHRoaXMsICdvbkdyb3VwU2l6ZUNoYW5nZScpO1xuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcihHcm91cEV2ZW50LkdST1VQX1NJWkVfVVBEQVRFLCB0aGlzLl9wYXJlbnQsICdvbkdyb3VwU2l6ZVVwZGF0ZScpO1xufVxuU1ZHQ29tcG9uZW50LnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoT2JqZWN0Q29tcG9uZW50LnByb3RvdHlwZSk7XG5TVkdDb21wb25lbnQucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gU1ZHQ29tcG9uZW50O1xuXG5TVkdDb21wb25lbnQucHJvdG90eXBlLl91cGRhdGVIZWlnaHQgPSBmdW5jdGlvbigpe1xuICAgIHZhciBzdmdIZWlnaHQgPSBOdW1iZXIodGhpcy5fc3ZnLmdldEF0dHJpYnV0ZSgnaGVpZ2h0JykpO1xuXG4gICAgdGhpcy5fd3JhcE5vZGUuc2V0SGVpZ2h0KHN2Z0hlaWdodCk7XG4gICAgdGhpcy5fbm9kZS5zZXRIZWlnaHQoc3ZnSGVpZ2h0ICsgTWV0cmljLlBBRERJTkdfV1JBUFBFUik7XG59O1xuXG5TVkdDb21wb25lbnQucHJvdG90eXBlLl9yZWRyYXcgPSBmdW5jdGlvbigpe307XG5cblNWR0NvbXBvbmVudC5wcm90b3R5cGUub25Hcm91cFNpemVDaGFuZ2UgPSBmdW5jdGlvbigpe1xuICAgIHZhciB3aWR0aCA9IHRoaXMuX3dyYXBOb2RlLmdldFdpZHRoKCk7XG5cbiAgICB0aGlzLl9zdmdTZXRTaXplKHdpZHRoLHdpZHRoKTtcbiAgICB0aGlzLl91cGRhdGVIZWlnaHQoKTtcbiAgICB0aGlzLl9yZWRyYXcoKTtcbn07XG5cblNWR0NvbXBvbmVudC5wcm90b3R5cGUuX2NyZWF0ZVNWR09iamVjdCA9IGZ1bmN0aW9uKHR5cGUpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudE5TKFwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIix0eXBlKTtcbn07XG5cblNWR0NvbXBvbmVudC5wcm90b3R5cGUuX3N2Z1NldFNpemUgPSBmdW5jdGlvbih3aWR0aCxoZWlnaHQpIHtcbiAgICB2YXIgc3ZnID0gdGhpcy5fc3ZnO1xuICAgICAgICBzdmcuc2V0QXR0cmlidXRlKCd3aWR0aCcsICB3aWR0aCk7XG4gICAgICAgIHN2Zy5zZXRBdHRyaWJ1dGUoJ2hlaWdodCcsIGhlaWdodCk7XG4gICAgICAgIHN2Zy5zZXRBdHRyaWJ1dGUoJ3ZpZXdib3gnLCAnMCAwICcgKyB3aWR0aCArICcgJyArIGhlaWdodCk7XG59O1xuXG5cblNWR0NvbXBvbmVudC5wcm90b3R5cGUuX3BhdGhDbWRNb3ZlVG8gPSBmdW5jdGlvbiAoeCwgeSkge1xuICAgIHJldHVybiAnTSAnICsgeCArICcgJyArIHkgKyAnICc7XG59O1xuXG5TVkdDb21wb25lbnQucHJvdG90eXBlLl9wYXRoQ21kTGluZVRvID0gZnVuY3Rpb24gKHgsIHkpIHtcbiAgICByZXR1cm4gJ0wgJyArIHggKyAnICcgKyB5ICsgJyAnO1xufTtcblxuU1ZHQ29tcG9uZW50LnByb3RvdHlwZS5fcGF0aENtZENsb3NlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAnWic7XG59O1xuXG5TVkdDb21wb25lbnQucHJvdG90eXBlLl9wYXRoQ21kTGluZSA9IGZ1bmN0aW9uICh4MCwgeTAsIHgxLCB5MSkge1xuICAgIHJldHVybiAnTSAnICsgeDAgKyAnICcgKyB5MCArICcgTCAnICsgeDEgKyAnICcgKyB5MTtcbn07XG5cblNWR0NvbXBvbmVudC5wcm90b3R5cGUuX3BhdGhDbWRCZXppZXJDdWJpYyA9IGZ1bmN0aW9uIChjbWQsIHgwLCB5MCwgY3gwLCBjeTAsIGN4MSwgY3kxLCB4MSwgeTEpIHtcbiAgICByZXR1cm4gJ00gJyArIHgwICsgJyAnICsgeTAgKyAnIEMgJyArIGN4MCArICcgJyArIGN5MCArICcsICcgKyBjeDEgKyAnICcgKyBjeTEgKyAnLCAnICsgeDEgKyAnICcgKyB5MTtcbn07XG5cblNWR0NvbXBvbmVudC5wcm90b3R5cGUuX3BhdGhDbWRCZXppZXJRdWFkcmF0aWMgPSBmdW5jdGlvbiAoY21kLCB4MCwgeTAsIGN4LCBjeSwgeDEsIHkxKSB7XG4gICAgcmV0dXJuICdNICcgKyB4MCArICcgJyArIHkwICsgJyBRICcgKyBjeCArICcgJyArIGN5ICsgJywgJyArIHgxICsgJyAnICsgeTE7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFNWR0NvbXBvbmVudDsiLCJ2YXIgT2JqZWN0Q29tcG9uZW50ID0gcmVxdWlyZSgnLi4vY29yZS9PYmplY3RDb21wb25lbnQnKTtcbnZhciBOb2RlID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Ob2RlJyk7XG52YXIgQ1NTICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvQ1NTJyk7XG5cbnZhciBPcHRpb25zID0gcmVxdWlyZSgnLi9PcHRpb25zJyk7XG5cbnZhciBIaXN0b3J5ID0gcmVxdWlyZSgnLi4vY29yZS9IaXN0b3J5Jyk7XG5cbnZhciBFdmVudF8gICAgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZXZlbnQvRXZlbnQnKSxcbiAgICBOb2RlRXZlbnQgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZUV2ZW50JyksXG4gICAgQ29tcG9uZW50RXZlbnQgPSByZXF1aXJlKCcuLi9jb3JlL0NvbXBvbmVudEV2ZW50JyksXG4gICAgT3B0aW9uRXZlbnQgICAgPSByZXF1aXJlKCcuLi9jb3JlL09wdGlvbkV2ZW50Jyk7XG5cbnZhciBPYmplY3RDb21wb25lbnROb3RpZmllciA9IHJlcXVpcmUoJy4uL2NvcmUvT2JqZWN0Q29tcG9uZW50Tm90aWZpZXInKTtcblxudmFyIFNUUl9DSE9PU0UgPSAnQ2hvb3NlIC4uLic7XG5cbmZ1bmN0aW9uIFNlbGVjdChwYXJlbnQsIG9iamVjdCwgdmFsdWUsIHBhcmFtcykge1xuICAgIE9iamVjdENvbXBvbmVudC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuXG4gICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICAgIHBhcmFtcy5vbkNoYW5nZSA9IHBhcmFtcy5vbkNoYW5nZSB8fCB0aGlzLl9vbkNoYW5nZTtcbiAgICB0aGlzLl9vbkNoYW5nZSA9IHBhcmFtcy5vbkNoYW5nZTtcblxuICAgIHZhciBvYmogPSB0aGlzLl9vYmosXG4gICAgICAgIGtleSA9IHRoaXMuX2tleTtcblxuICAgIHZhciB0YXJnZXRLZXkgPSB0aGlzLl90YXJnZXRLZXkgPSBwYXJhbXMudGFyZ2V0LFxuICAgICAgICB2YWx1ZXMgPSB0aGlzLl92YWx1ZXMgPSBvYmpba2V5XTtcblxuXG4gICAgdGhpcy5fc2VsZWN0ZWRJbmRleCA9IC0xO1xuICAgIHRoaXMuX3NlbGVjdGVkID0gbnVsbDtcblxuICAgIHZhciBzZWxlY3QgPSB0aGlzLl9zZWxlY3QgPSBuZXcgTm9kZShOb2RlLklOUFVUX0JVVFRPTik7XG4gICAgICAgIHNlbGVjdC5zZXRTdHlsZUNsYXNzKENTUy5TZWxlY3QpO1xuICAgICAgICBzZWxlY3QuYWRkRXZlbnRMaXN0ZW5lcihOb2RlRXZlbnQuTU9VU0VfRE9XTiwgdGhpcy5fb25PcHRpb25UcmlnZ2VyLmJpbmQodGhpcykpO1xuXG4gICAgaWYodGhpcy5faGFzVGFyZ2V0KCkpIHtcbiAgICAgICAgdmFyIHRhcmdldE9iaiA9IG9ialt0YXJnZXRLZXldIHx8ICcnO1xuICAgICAgICB2YXIgaSA9IC0xO1xuICAgICAgICB3aGlsZSAoKytpIDwgdmFsdWVzLmxlbmd0aCkge1xuICAgICAgICAgICAgaWYgKHRhcmdldE9iaiA9PSB2YWx1ZXNbaV0pe1xuICAgICAgICAgICAgICAgIHRoaXMuX3NlbGVjdGVkID0gdmFsdWVzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHNlbGVjdC5zZXRQcm9wZXJ0eSgndmFsdWUnLCB0YXJnZXRPYmoudG9TdHJpbmcoKS5sZW5ndGggPiAwID8gdGFyZ2V0T2JqIDogdmFsdWVzWzBdKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNlbGVjdC5zZXRQcm9wZXJ0eSgndmFsdWUnLCBwYXJhbXMuc2VsZWN0ZWQgPyB2YWx1ZXNbcGFyYW1zLnNlbGVjdGVkXSA6IFNUUl9DSE9PU0UpO1xuICAgIH1cblxuICAgIHRoaXMuX3dyYXBOb2RlLmFkZENoaWxkKHNlbGVjdCk7XG5cbiAgICBPYmplY3RDb21wb25lbnROb3RpZmllci5nZXQoKS5hZGRFdmVudExpc3RlbmVyKE9wdGlvbkV2ZW50LlRSSUdHRVIsIHRoaXMsICdvbk9wdGlvblRyaWdnZXInKTtcbiAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoT3B0aW9uRXZlbnQuVFJJR0dFUkVELCBPYmplY3RDb21wb25lbnROb3RpZmllci5nZXQoKSwgJ29uT3B0aW9uVHJpZ2dlcmVkJyk7XG59XG5TZWxlY3QucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShPYmplY3RDb21wb25lbnQucHJvdG90eXBlKTtcblNlbGVjdC5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBTZWxlY3Q7XG5cblNlbGVjdC5wcm90b3R5cGUub25PcHRpb25UcmlnZ2VyID0gZnVuY3Rpb24gKGUpIHtcbiAgICBpZiAoZS5kYXRhLm9yaWdpbiA9PSB0aGlzKSB7XG4gICAgICAgIHRoaXMuX2FjdGl2ZSA9ICF0aGlzLl9hY3RpdmU7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUFwcGVhcmFuY2UoKTtcblxuICAgICAgICBpZiAodGhpcy5fYWN0aXZlKSB7XG4gICAgICAgICAgICB0aGlzLl9idWlsZE9wdGlvbnMoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIE9wdGlvbnMuZ2V0KCkuY2xlYXIoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX2FjdGl2ZSA9IGZhbHNlO1xuICAgIHRoaXMuX3VwZGF0ZUFwcGVhcmFuY2UoKTtcbn07XG5cblNlbGVjdC5wcm90b3R5cGUuX2J1aWxkT3B0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgb3B0aW9ucyA9IE9wdGlvbnMuZ2V0KCk7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgb3B0aW9ucy5idWlsZCh0aGlzLl92YWx1ZXMsIHRoaXMuX3NlbGVjdGVkLCB0aGlzLl9zZWxlY3QsXG4gICAgICAgIGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICBzZWxmLmFwcGx5VmFsdWUoKTtcbiAgICAgICAgICAgIHNlbGYuX2FjdGl2ZSA9IGZhbHNlO1xuICAgICAgICAgICAgc2VsZi5fdXBkYXRlQXBwZWFyYW5jZSgpO1xuICAgICAgICAgICAgc2VsZi5fc2VsZWN0ZWRJbmRleCA9IG9wdGlvbnMuZ2V0U2VsZWN0ZWRJbmRleCgpO1xuICAgICAgICAgICAgc2VsZi5fb25DaGFuZ2Uoc2VsZi5fc2VsZWN0ZWRJbmRleCk7XG4gICAgICAgICAgICBvcHRpb25zLmNsZWFyKCk7XG4gICAgICAgIH0sXG4gICAgICAgIGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICBzZWxmLl9hY3RpdmUgPSBmYWxzZTtcbiAgICAgICAgICAgIHNlbGYuX3VwZGF0ZUFwcGVhcmFuY2UoKTtcbiAgICAgICAgICAgIG9wdGlvbnMuY2xlYXIoKVxuICAgICAgICB9LCBmYWxzZSk7XG59O1xuXG5TZWxlY3QucHJvdG90eXBlLl9hcHBseVNlbGVjdGVkID0gZnVuY3Rpb24oc2VsZWN0ZWQpe1xuICAgIHRoaXMuX3NlbGVjdC5zZXRQcm9wZXJ0eSgndmFsdWUnLHNlbGVjdGVkKTtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50Xyh0aGlzLENvbXBvbmVudEV2ZW50LlZBTFVFX1VQREFURUQpLG51bGwpO1xufVxuXG5TZWxlY3QucHJvdG90eXBlLmFwcGx5VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGluZGV4ID0gT3B0aW9ucy5nZXQoKS5nZXRTZWxlY3RlZEluZGV4KCksXG4gICAgICAgIHNlbGVjdGVkID0gdGhpcy5fc2VsZWN0ZWQgPSB0aGlzLl92YWx1ZXNbaW5kZXhdO1xuXG4gICAgaWYgKHRoaXMuX2hhc1RhcmdldCgpKSB7XG4gICAgICAgIHRoaXMucHVzaEhpc3RvcnlTdGF0ZSgpO1xuICAgICAgICB0aGlzLl9vYmpbdGhpcy5fdGFyZ2V0S2V5XSA9IHNlbGVjdGVkO1xuICAgIH1cblxuICAgIHRoaXMuX2FwcGx5U2VsZWN0ZWQoc2VsZWN0ZWQpO1xufTtcblxuU2VsZWN0LnByb3RvdHlwZS5wdXNoSGlzdG9yeVN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBvYmogPSB0aGlzLl9vYmosXG4gICAgICAgIGtleSA9IHRoaXMuX3RhcmdldEtleTtcbiAgICBIaXN0b3J5LmdldCgpLnB1c2hTdGF0ZShvYmosIGtleSwgb2JqW2tleV0pO1xufTtcblxuU2VsZWN0LnByb3RvdHlwZS5fb25PcHRpb25UcmlnZ2VyID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIE9wdGlvbkV2ZW50LlRSSUdHRVJFRCwgbnVsbCkpO1xufTtcblxuU2VsZWN0LnByb3RvdHlwZS5fdXBkYXRlQXBwZWFyYW5jZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLl9zZWxlY3Quc2V0U3R5bGVDbGFzcyh0aGlzLl9hY3RpdmUgPyBDU1MuU2VsZWN0QWN0aXZlIDogQ1NTLlNlbGVjdCk7XG59O1xuXG5TZWxlY3QucHJvdG90eXBlLm9uVmFsdWVVcGRhdGUgPSBmdW5jdGlvbiAoZSkge1xuICAgIGlmICghdGhpcy5faGFzVGFyZ2V0KCkpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX3NlbGVjdGVkID0gdGhpcy5fb2JqW3RoaXMuX3RhcmdldEtleV07XG4gICAgdGhpcy5fc2VsZWN0LnNldFByb3BlcnR5KCd2YWx1ZScsIHRoaXMuX3NlbGVjdGVkLnRvU3RyaW5nKCkpO1xufTtcblxuU2VsZWN0LnByb3RvdHlwZS5faGFzVGFyZ2V0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl90YXJnZXRLZXkgIT0gbnVsbDtcbn07XG5cblNlbGVjdC5wcm90b3R5cGUuc2V0VmFsdWUgPSBmdW5jdGlvbih2YWx1ZSl7XG4gICAgdGhpcy5fc2VsZWN0ZWRJbmRleCA9IHZhbHVlO1xuICAgIGlmKHZhbHVlID09IC0xKXtcbiAgICAgICAgdGhpcy5fc2VsZWN0ZWQgPSBudWxsO1xuICAgICAgICB0aGlzLl9zZWxlY3Quc2V0UHJvcGVydHkoJ3ZhbHVlJywgU1RSX0NIT09TRSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5fc2VsZWN0ZWQgPSB0aGlzLl92YWx1ZXNbdGhpcy5fc2VsZWN0ZWRJbmRleF07XG4gICAgdGhpcy5fYXBwbHlTZWxlY3RlZCh0aGlzLl9zZWxlY3RlZCk7XG59O1xuXG5TZWxlY3QucHJvdG90eXBlLmdldERhdGEgPSBmdW5jdGlvbigpe1xuICAgIHZhciBvYmogPSB7fTtcbiAgICAgICAgb2JqWydzZWxlY3RlZEluZGV4J10gPSB0aGlzLl9zZWxlY3RlZEluZGV4O1xuICAgIHJldHVybiBvYmo7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFNlbGVjdDtcbiIsInZhciBPYmplY3RDb21wb25lbnQgPSByZXF1aXJlKCcuLi9jb3JlL09iamVjdENvbXBvbmVudCcpO1xudmFyIENTUyA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvQ1NTJyk7XG52YXIgU2xpZGVyX0ludGVybmFsID0gcmVxdWlyZSgnLi9TbGlkZXJfSW50ZXJuYWwnKTtcblxudmFyIEhpc3RvcnkgPSByZXF1aXJlKCcuLi9jb3JlL0hpc3RvcnknKTtcbnZhciBSYW5nZSA9IHJlcXVpcmUoJy4vUmFuZ2UnKTtcbnZhciBOdW1iZXJJbnB1dF9JbnRlcm5hbCA9IHJlcXVpcmUoJy4vTnVtYmVySW5wdXRfSW50ZXJuYWwnKTtcblxudmFyIEV2ZW50XyAgICAgICAgID0gcmVxdWlyZSgnLi4vY29yZS9ldmVudC9FdmVudCcpLFxuICAgIERvY3VtZW50RXZlbnQgID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Eb2N1bWVudEV2ZW50JyksXG4gICAgUGFuZWxFdmVudCAgICAgPSByZXF1aXJlKCcuLi9ncm91cC9QYW5lbEV2ZW50JyksXG4gICAgR3JvdXBFdmVudCAgICAgPSByZXF1aXJlKCcuLi9ncm91cC9Hcm91cEV2ZW50JyksXG4gICAgQ29tcG9uZW50RXZlbnQgPSByZXF1aXJlKCcuLi9jb3JlL0NvbXBvbmVudEV2ZW50Jyk7XG5cbnZhciBERUZBVUxUX1NURVAgPSAxLjAsXG4gICAgREVGQVVMVF9EUCAgID0gMjtcblxuXG5mdW5jdGlvbiBTbGlkZXIocGFyZW50LG9iamVjdCx2YWx1ZSxyYW5nZSxwYXJhbXMpIHtcbiAgICBwYXJhbXMgICAgICAgICAgPSBwYXJhbXMgICAgICAgICAgfHwge307XG4gICAgcGFyYW1zLmxhYmVsICAgID0gcGFyYW1zLmxhYmVsICAgIHx8IHZhbHVlO1xuXG4gICAgT2JqZWN0Q29tcG9uZW50LmFwcGx5KHRoaXMsW3BhcmVudCxvYmplY3QscmFuZ2UscGFyYW1zXSk7XG5cbiAgICB0aGlzLl92YWx1ZXMgID0gdGhpcy5fb2JqW3RoaXMuX2tleV07XG4gICAgdGhpcy5fdGFyZ2V0S2V5ID0gdmFsdWU7XG5cbiAgICBwYXJhbXMuc3RlcCAgICAgPSBwYXJhbXMuc3RlcCAgICAgfHwgREVGQVVMVF9TVEVQO1xuICAgIHBhcmFtcy5kcCAgICAgICA9IChwYXJhbXMuZHAgPT09IHVuZGVmaW5lZCB8fCBwYXJhbXMuZHAgPT0gbnVsbCkgPyAgREVGQVVMVF9EUCA6IHBhcmFtcy5kcDtcbiAgICBwYXJhbXMub25DaGFuZ2UgPSBwYXJhbXMub25DaGFuZ2UgfHwgdGhpcy5fb25DaGFuZ2U7XG4gICAgcGFyYW1zLm9uRmluaXNoID0gcGFyYW1zLm9uRmluaXNoIHx8IGZ1bmN0aW9uKCl7fTtcblxuICAgIHRoaXMuX2RwICAgICAgID0gcGFyYW1zLmRwO1xuICAgIHRoaXMuX29uQ2hhbmdlID0gcGFyYW1zLm9uQ2hhbmdlO1xuICAgIHRoaXMuX29uRmluaXNoID0gcGFyYW1zLm9uRmluaXNoO1xuXG4gICAgdmFyIHZhbHVlcyAgICA9IHRoaXMuX3ZhbHVlcyxcbiAgICAgICAgb2JqICAgICAgID0gdGhpcy5fb2JqLFxuICAgICAgICB0YXJnZXRLZXkgPSB0aGlzLl90YXJnZXRLZXk7XG5cbiAgICB2YXIgd3JhcCAgPSB0aGlzLl93cmFwTm9kZTtcbiAgICAgICAgd3JhcC5zZXRTdHlsZUNsYXNzKENTUy5XcmFwU2xpZGVyKTtcblxuICAgIHZhciBzbGlkZXIgPSB0aGlzLl9zbGlkZXIgPSBuZXcgU2xpZGVyX0ludGVybmFsKHdyYXAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fb25TbGlkZXJCZWdpbi5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX29uU2xpZGVyTW92ZS5iaW5kKHRoaXMpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX29uU2xpZGVyRW5kLmJpbmQodGhpcykpO1xuXG4gICAgc2xpZGVyLnNldEJvdW5kTWF4KHZhbHVlc1sxXSk7XG4gICAgc2xpZGVyLnNldEJvdW5kTWluKHZhbHVlc1swXSk7XG4gICAgc2xpZGVyLnNldFZhbHVlKG9ialt0YXJnZXRLZXldKTtcblxuICAgIHZhciBpbnB1dCAgPSB0aGlzLl9pbnB1dCA9IG5ldyBOdW1iZXJJbnB1dF9JbnRlcm5hbChwYXJhbXMuc3RlcCwgcGFyYW1zLmRwLCBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9vbklucHV0Q2hhbmdlLmJpbmQodGhpcykpO1xuXG4gICAgaW5wdXQuc2V0VmFsdWUob2JqW3RhcmdldEtleV0pO1xuXG4gICAgd3JhcC5hZGRDaGlsZChpbnB1dC5nZXROb2RlKCkpO1xuXG4gICAgdGhpcy5fcGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoUGFuZWxFdmVudC5QQU5FTF9NT1ZFX0VORCwgICAgdGhpcywgJ29uUGFuZWxNb3ZlRW5kJyk7XG4gICAgdGhpcy5fcGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoR3JvdXBFdmVudC5HUk9VUF9TSVpFX0NIQU5HRSwgdGhpcywgJ29uR3JvdXBXaWR0aENoYW5nZScpO1xuICAgIHRoaXMuX3BhcmVudC5hZGRFdmVudExpc3RlbmVyKERvY3VtZW50RXZlbnQuV0lORE9XX1JFU0laRSwgIHRoaXMsICdvbldpbmRvd1Jlc2l6ZScpO1xufVxuU2xpZGVyLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoT2JqZWN0Q29tcG9uZW50LnByb3RvdHlwZSk7XG5TbGlkZXIucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gU2xpZGVyO1xuXG5TbGlkZXIucHJvdG90eXBlLnB1c2hIaXN0b3J5U3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIG9iaiA9IHRoaXMuX29iaixcbiAgICAgICAga2V5ID0gdGhpcy5fdGFyZ2V0S2V5O1xuICAgIEhpc3RvcnkuZ2V0KCkucHVzaFN0YXRlKG9iaiwga2V5LCBvYmpba2V5XSk7XG59O1xuXG5TbGlkZXIucHJvdG90eXBlLl9vblNsaWRlckJlZ2luID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMucHVzaEhpc3RvcnlTdGF0ZSgpO1xufTtcblxuU2xpZGVyLnByb3RvdHlwZS5fb25TbGlkZXJNb3ZlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuYXBwbHlWYWx1ZSgpO1xuICAgIHRoaXMuX3VwZGF0ZVZhbHVlRmllbGQoKTtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50Xyh0aGlzLCBDb21wb25lbnRFdmVudC5WQUxVRV9VUERBVEVELCBudWxsKSk7XG4gICAgdGhpcy5fb25DaGFuZ2UoKTtcbn07XG5cblNsaWRlci5wcm90b3R5cGUuX29uU2xpZGVyRW5kID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuYXBwbHlWYWx1ZSgpO1xuICAgIHRoaXMuX3VwZGF0ZVZhbHVlRmllbGQoKTtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50Xyh0aGlzLCBDb21wb25lbnRFdmVudC5WQUxVRV9VUERBVEVELCBudWxsKSk7XG4gICAgdGhpcy5fb25GaW5pc2goKTtcbn07XG5cblNsaWRlci5wcm90b3R5cGUuX29uSW5wdXRDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGlucHV0ID0gdGhpcy5faW5wdXQsXG4gICAgICAgIHZhbHVlTWluID0gdGhpcy5fdmFsdWVzWzBdLFxuICAgICAgICB2YWx1ZU1heCA9IHRoaXMuX3ZhbHVlc1sxXTtcblxuICAgIGlmIChpbnB1dC5nZXRWYWx1ZSgpID49IHZhbHVlTWF4KXtcbiAgICAgICAgaW5wdXQuc2V0VmFsdWUodmFsdWVNYXgpO1xuICAgIH1cbiAgICBpZiAoaW5wdXQuZ2V0VmFsdWUoKSA8PSB2YWx1ZU1pbil7XG4gICAgICAgIGlucHV0LnNldFZhbHVlKHZhbHVlTWluKTtcbiAgICB9XG5cbiAgICB2YXIgdmFsdWUgPSBpbnB1dC5nZXRWYWx1ZSgpO1xuXG4gICAgdGhpcy5fc2xpZGVyLnNldFZhbHVlKHZhbHVlKTtcbiAgICB0aGlzLl9vYmpbdGhpcy5fdGFyZ2V0S2V5XSA9IHZhbHVlO1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIENvbXBvbmVudEV2ZW50LlZBTFVFX1VQREFURUQsIG51bGwpKTtcbiAgICB0aGlzLl9vbkZpbmlzaCgpO1xufTtcblxuU2xpZGVyLnByb3RvdHlwZS5hcHBseVZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciB2YWx1ZSAgPSB0aGlzLl9zbGlkZXIuZ2V0VmFsdWUoKTtcbiAgICB0aGlzLl9vYmpbdGhpcy5fdGFyZ2V0S2V5XSA9IHBhcnNlRmxvYXQodmFsdWUudG9GaXhlZCh0aGlzLl9kcCkpO1xuICAgIHRoaXMuX2lucHV0LnNldFZhbHVlKHZhbHVlKTtcbn07XG5cblxuU2xpZGVyLnByb3RvdHlwZS5vblZhbHVlVXBkYXRlID0gZnVuY3Rpb24gKGUpIHtcbiAgICB2YXIgb3JpZ2luID0gZS5kYXRhLm9yaWdpbjtcbiAgICBpZiAob3JpZ2luID09IHRoaXMpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciBzbGlkZXIgPSB0aGlzLl9zbGlkZXI7XG4gICAgaWYgKCEob3JpZ2luIGluc3RhbmNlb2YgU2xpZGVyKSkge1xuICAgICAgICB2YXIgdmFsdWVzID0gdGhpcy5fdmFsdWVzO1xuICAgICAgICBzbGlkZXIuc2V0Qm91bmRNaW4odmFsdWVzWzBdKTtcbiAgICAgICAgc2xpZGVyLnNldEJvdW5kTWF4KHZhbHVlc1sxXSk7XG4gICAgICAgIGlmICghKG9yaWdpbiBpbnN0YW5jZW9mIFJhbmdlKSkge1xuICAgICAgICAgICAgc2xpZGVyLnNldFZhbHVlKHRoaXMuX29ialt0aGlzLl90YXJnZXRLZXldKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgc2xpZGVyLnNldFZhbHVlKHRoaXMuX29ialt0aGlzLl90YXJnZXRLZXldKTtcbiAgICB9XG4gICAgdGhpcy5hcHBseVZhbHVlKCk7XG59O1xuXG5cblNsaWRlci5wcm90b3R5cGUuX3VwZGF0ZVZhbHVlRmllbGQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5faW5wdXQuc2V0VmFsdWUodGhpcy5fc2xpZGVyLmdldFZhbHVlKCkpO1xufTtcblxuU2xpZGVyLnByb3RvdHlwZS5vblBhbmVsTW92ZUVuZCA9XG4gICAgU2xpZGVyLnByb3RvdHlwZS5vbkdyb3VwV2lkdGhDaGFuZ2UgPVxuICAgICAgICBTbGlkZXIucHJvdG90eXBlLm9uV2luZG93UmVzaXplID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy5fc2xpZGVyLnJlc2V0T2Zmc2V0KCk7XG4gICAgICAgIH07XG5cblNsaWRlci5wcm90b3R5cGUuc2V0VmFsdWUgPSBmdW5jdGlvbih2YWx1ZSl7XG4gICAgaWYodmFsdWUgPT0gLTEpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX29ialt0aGlzLl90YXJnZXRLZXldID0gdmFsdWU7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcyxDb21wb25lbnRFdmVudC5WQUxVRV9VUERBVEVELG51bGwpKTtcbn07XG5cblNsaWRlci5wcm90b3R5cGUuZ2V0RGF0YSA9IGZ1bmN0aW9uKCl7XG4gICAgdmFyIG9iaiA9IHt9O1xuICAgICAgICBvYmpbdGhpcy5fdGFyZ2V0S2V5XSA9IHRoaXMuX29ialt0aGlzLl90YXJnZXRLZXldO1xuICAgIHJldHVybiBvYmo7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IFNsaWRlcjsiLCJ2YXIgTm9kZSA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZScpO1xuXG52YXIgRG9jdW1lbnRFdmVudCA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvRG9jdW1lbnRFdmVudCcpLFxuICAgIE5vZGVFdmVudCA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZUV2ZW50Jyk7XG5cbnZhciBDU1MgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L0NTUycpO1xudmFyIE1vdXNlID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Nb3VzZScpO1xuXG5mdW5jdGlvbiBTbGlkZXJfSW50ZXJuYWwocGFyZW50Tm9kZSxvbkJlZ2luLG9uQ2hhbmdlLG9uRmluaXNoKSB7XG4gICAgdGhpcy5fYm91bmRzID0gWzAsMV07XG4gICAgdGhpcy5fdmFsdWUgID0gMDtcbiAgICB0aGlzLl9pbnRycGwgPSAwO1xuICAgIHRoaXMuX2ZvY3VzICA9IGZhbHNlO1xuXG5cbiAgICB0aGlzLl9vbkJlZ2luICA9IG9uQmVnaW4gIHx8IGZ1bmN0aW9uKCl7fTtcbiAgICB0aGlzLl9vbkNoYW5nZSA9IG9uQ2hhbmdlIHx8IGZ1bmN0aW9uKCl7fTtcbiAgICB0aGlzLl9vbkZpbmlzaCA9IG9uRmluaXNoIHx8IGZ1bmN0aW9uKCl7fTtcblxuXG4gICAgdmFyIHdyYXAgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLlNsaWRlcldyYXApO1xuICAgIHBhcmVudE5vZGUuYWRkQ2hpbGQod3JhcCk7XG5cbiAgICB2YXIgc2xvdCAgID0gdGhpcy5fc2xvdCAgID0ge25vZGU6ICAgIG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuU2xpZGVyU2xvdCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvZmZzZXRYOiAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg6ICAgMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhZGRpbmc6IDN9O1xuXG4gICAgdmFyIGhhbmRsZSA9IHRoaXMuX2hhbmRsZSA9IHtub2RlICAgIDogbmV3IE5vZGUoKS5zZXRTdHlsZUNsYXNzKENTUy5TbGlkZXJIYW5kbGUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd2lkdGggICA6IDAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcmFnZ2luZzogZmFsc2V9O1xuXG4gICAgd3JhcC5hZGRDaGlsZChzbG90Lm5vZGUpO1xuICAgIHNsb3Qubm9kZS5hZGRDaGlsZChoYW5kbGUubm9kZSk7XG5cbiAgICBzbG90Lm9mZnNldFggPSBzbG90Lm5vZGUuZ2V0UG9zaXRpb25HbG9iYWxYKCk7XG4gICAgc2xvdC53aWR0aCAgID0gTWF0aC5mbG9vcihzbG90Lm5vZGUuZ2V0V2lkdGgoKSAtIHNsb3QucGFkZGluZyAqIDIpIDtcblxuICAgIGhhbmRsZS5ub2RlLnNldFdpZHRoKGhhbmRsZS53aWR0aCk7XG5cbiAgICBzbG90Lm5vZGUuYWRkRXZlbnRMaXN0ZW5lcihOb2RlRXZlbnQuTU9VU0VfRE9XTix0aGlzLl9vblNsb3RNb3VzZURvd24uYmluZCh0aGlzKSk7XG4gICAgc2xvdC5ub2RlLmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50Lk1PVVNFX1VQLCAgdGhpcy5fb25TbG90TW91c2VVcC5iaW5kKHRoaXMpKTtcblxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoRG9jdW1lbnRFdmVudC5NT1VTRV9NT1ZFLHRoaXMuX29uRG9jdW1lbnRNb3VzZU1vdmUuYmluZCh0aGlzKSk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihEb2N1bWVudEV2ZW50Lk1PVVNFX1VQLCAgdGhpcy5fb25Eb2N1bWVudE1vdXNlVXAuYmluZCh0aGlzKSk7XG59XG5cblNsaWRlcl9JbnRlcm5hbC5wcm90b3R5cGUuX29uRG9jdW1lbnRNb3VzZU1vdmUgPSBmdW5jdGlvbigpe1xuICAgIGlmKCF0aGlzLl9oYW5kbGUuZHJhZ2dpbmcpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX3VwZGF0ZSgpO1xuICAgIHRoaXMuX29uQ2hhbmdlKCk7XG59O1xuXG5TbGlkZXJfSW50ZXJuYWwucHJvdG90eXBlLl9vbkRvY3VtZW50TW91c2VVcCA9IGZ1bmN0aW9uKCl7XG4gICAgaWYodGhpcy5faGFuZGxlLmRyYWdnaW5nKXtcbiAgICAgICAgdGhpcy5fb25GaW5pc2goKTtcbiAgICB9XG4gICAgdGhpcy5faGFuZGxlLmRyYWdnaW5nID0gZmFsc2U7XG59O1xuXG5TbGlkZXJfSW50ZXJuYWwucHJvdG90eXBlLl9vblNsb3RNb3VzZURvd24gPSBmdW5jdGlvbigpe1xuICAgIHRoaXMuX29uQmVnaW4oKTtcbiAgICB0aGlzLl9mb2N1cyA9IHRydWU7XG4gICAgdGhpcy5faGFuZGxlLmRyYWdnaW5nID0gdHJ1ZTtcbiAgICB0aGlzLl9oYW5kbGUubm9kZS5nZXRFbGVtZW50KCkuZm9jdXMoKTtcbiAgICB0aGlzLl91cGRhdGUoKTtcbn07XG5cblNsaWRlcl9JbnRlcm5hbC5wcm90b3R5cGUuX29uU2xvdE1vdXNlVXAgPSBmdW5jdGlvbigpe1xuICAgIGlmICh0aGlzLl9mb2N1cykge1xuICAgICAgICB2YXIgaGFuZGxlID0gdGhpcy5faGFuZGxlO1xuICAgICAgICBpZiAoaGFuZGxlLmRyYWdnaW5nKXtcbiAgICAgICAgICAgIHRoaXMuX29uRmluaXNoKCk7XG4gICAgICAgIH1cbiAgICAgICAgaGFuZGxlLmRyYWdnaW5nID0gZmFsc2U7XG4gICAgfVxuICAgIHRoaXMuX2ZvY3VzID0gZmFsc2U7XG59O1xuXG5TbGlkZXJfSW50ZXJuYWwucHJvdG90eXBlLl91cGRhdGUgPSBmdW5jdGlvbigpe1xuICAgIHZhciBteCA9IE1vdXNlLmdldCgpLmdldFgoKSxcbiAgICAgICAgc3ggPSB0aGlzLl9zbG90Lm9mZnNldFgsXG4gICAgICAgIHN3ID0gdGhpcy5fc2xvdC53aWR0aCxcbiAgICAgICAgcHggPSAobXggPCBzeCkgPyAwIDogKG14ID4gKHN4ICsgc3cpKSA/IHN3IDogKG14IC0gc3gpO1xuXG4gICAgdGhpcy5faGFuZGxlLm5vZGUuc2V0V2lkdGgoTWF0aC5yb3VuZChweCkpO1xuICAgIHRoaXMuX2ludHJwbCA9IHB4IC8gc3c7XG4gICAgdGhpcy5faW50ZXJwb2xhdGVWYWx1ZSgpO1xufTtcblxuU2xpZGVyX0ludGVybmFsLnByb3RvdHlwZS5fdXBkYXRlSGFuZGxlID0gZnVuY3Rpb24oKXtcbiAgICB2YXIgc2xvdFdpZHRoICAgPSB0aGlzLl9zbG90LndpZHRoLFxuICAgICAgICBoYW5kbGVXaWR0aCA9IE1hdGgucm91bmQodGhpcy5faW50cnBsICogc2xvdFdpZHRoKTtcbiAgICB0aGlzLl9oYW5kbGUubm9kZS5zZXRXaWR0aChNYXRoLm1pbihoYW5kbGVXaWR0aCxzbG90V2lkdGgpKTtcbn07XG5cblNsaWRlcl9JbnRlcm5hbC5wcm90b3R5cGUuX2ludGVycG9sYXRlVmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGludHJwbCA9IHRoaXMuX2ludHJwbCxcbiAgICAgICAgYm91bmRzID0gdGhpcy5fYm91bmRzO1xuICAgIHRoaXMuX3ZhbHVlID0gYm91bmRzWzBdICogKDEuMCAtIGludHJwbCkgKyBib3VuZHNbMV0gKiBpbnRycGw7XG59O1xuXG5TbGlkZXJfSW50ZXJuYWwucHJvdG90eXBlLnJlc2V0T2Zmc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzbG90ID0gdGhpcy5fc2xvdDtcbiAgICBzbG90Lm9mZnNldFggPSBzbG90Lm5vZGUuZ2V0UG9zaXRpb25HbG9iYWxYKCk7XG4gICAgc2xvdC53aWR0aCA9IE1hdGguZmxvb3Ioc2xvdC5ub2RlLmdldFdpZHRoKCkgLSBzbG90LnBhZGRpbmcgKiAyKVxufTtcblxuU2xpZGVyX0ludGVybmFsLnByb3RvdHlwZS5zZXRCb3VuZE1pbiA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHZhciBib3VuZHMgPSB0aGlzLl9ib3VuZHM7XG4gICAgaWYgKHZhbHVlID49IGJvdW5kc1sxXSl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYm91bmRzWzBdID0gdmFsdWU7XG4gICAgdGhpcy5fdXBkYXRlRnJvbUJvdW5kcygpO1xufTtcblxuU2xpZGVyX0ludGVybmFsLnByb3RvdHlwZS5zZXRCb3VuZE1heCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHZhciBib3VuZHMgPSB0aGlzLl9ib3VuZHM7XG4gICAgaWYgKHZhbHVlIDw9IGJvdW5kc1swXSl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYm91bmRzWzFdID0gdmFsdWU7XG4gICAgdGhpcy5fdXBkYXRlRnJvbUJvdW5kcygpO1xufTtcblxuU2xpZGVyX0ludGVybmFsLnByb3RvdHlwZS5fdXBkYXRlRnJvbUJvdW5kcyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgYm91bmRzTWluID0gdGhpcy5fYm91bmRzWzBdLFxuICAgICAgICBib3VuZHNNYXggPSB0aGlzLl9ib3VuZHNbMV07XG4gICAgdGhpcy5fdmFsdWUgPSBNYXRoLm1heChib3VuZHNNaW4sTWF0aC5taW4odGhpcy5fdmFsdWUsYm91bmRzTWF4KSk7XG4gICAgdGhpcy5faW50cnBsID0gTWF0aC5hYnMoKHRoaXMuX3ZhbHVlIC0gYm91bmRzTWluKSAvIChib3VuZHNNaW4gLSBib3VuZHNNYXgpKTtcbiAgICB0aGlzLl91cGRhdGVIYW5kbGUoKTtcbn07XG5cblNsaWRlcl9JbnRlcm5hbC5wcm90b3R5cGUuc2V0VmFsdWUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICB2YXIgYm91bmRzTWluID0gdGhpcy5fYm91bmRzWzBdLFxuICAgICAgICBib3VuZHNNYXggPSB0aGlzLl9ib3VuZHNbMV07XG5cbiAgICBpZiAodmFsdWUgPCBib3VuZHNNaW4gfHwgdmFsdWUgPiBib3VuZHNNYXgpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX2ludHJwbCA9IE1hdGguYWJzKCh2YWx1ZSAtIGJvdW5kc01pbikgLyAoYm91bmRzTWluIC0gYm91bmRzTWF4KSk7XG4gICAgdGhpcy5fdXBkYXRlSGFuZGxlKCk7XG4gICAgdGhpcy5fdmFsdWUgPSB2YWx1ZTtcbn07XG5cblNsaWRlcl9JbnRlcm5hbC5wcm90b3R5cGUuZ2V0VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZhbHVlO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFNsaWRlcl9JbnRlcm5hbDsiLCJ2YXIgT2JqZWN0Q29tcG9uZW50ID0gcmVxdWlyZSgnLi4vY29yZS9PYmplY3RDb21wb25lbnQnKTtcbnZhciBOb2RlID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Ob2RlJyk7XG52YXIgQ1NTID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9DU1MnKTtcbnZhciBPcHRpb25zID0gcmVxdWlyZSgnLi9PcHRpb25zJyk7XG52YXIgQnV0dG9uUHJlc2V0ID0gcmVxdWlyZSgnLi9CdXR0b25QcmVzZXQnKTtcbnZhciBNZXRyaWMgPSByZXF1aXJlKCcuL01ldHJpYycpO1xuXG52YXIgRXZlbnRfID0gcmVxdWlyZSgnLi4vY29yZS9ldmVudC9FdmVudCcpLFxuICAgIERvY3VtZW50RXZlbnQgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L0RvY3VtZW50RXZlbnQnKSxcbiAgICBOb2RlRXZlbnQgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L05vZGVFdmVudCcpLFxuICAgIENvbXBvbmVudEV2ZW50ID0gIHJlcXVpcmUoJy4uL2NvcmUvQ29tcG9uZW50RXZlbnQnKTtcblxudmFyIERFRkFVTFRfUFJFU0VUID0gbnVsbDtcblxuZnVuY3Rpb24gU3RyaW5nSW5wdXQocGFyZW50LG9iamVjdCx2YWx1ZSxwYXJhbXMpIHtcbiAgICBPYmplY3RDb21wb25lbnQuYXBwbHkodGhpcyxhcmd1bWVudHMpO1xuXG4gICAgcGFyYW1zICAgICAgICAgID0gcGFyYW1zIHx8IHt9O1xuICAgIHBhcmFtcy5vbkNoYW5nZSA9IHBhcmFtcy5vbkNoYW5nZSB8fCB0aGlzLl9vbkNoYW5nZTtcbiAgICBwYXJhbXMucHJlc2V0cyAgPSBwYXJhbXMucHJlc2V0cyAgfHwgREVGQVVMVF9QUkVTRVQ7XG5cbiAgICB0aGlzLl9vbkNoYW5nZSAgID0gcGFyYW1zLm9uQ2hhbmdlO1xuXG4gICAgdmFyIGlucHV0ID0gdGhpcy5faW5wdXQgPSBuZXcgTm9kZShOb2RlLklOUFVUX1RFWFQpO1xuXG4gICAgdmFyIHdyYXAgPSB0aGlzLl93cmFwTm9kZTtcblxuICAgIHZhciBwcmVzZXRzID0gcGFyYW1zLnByZXNldHM7XG4gICAgaWYgKCFwcmVzZXRzKSB7XG4gICAgICAgIHdyYXAuYWRkQ2hpbGQoaW5wdXQpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgdmFyIHdyYXBfID0gbmV3IE5vZGUoKTtcbiAgICAgICAgd3JhcF8uc2V0U3R5bGVDbGFzcyhDU1MuV3JhcElucHV0V1ByZXNldCk7XG5cbiAgICAgICAgd3JhcC5hZGRDaGlsZCh3cmFwXyk7XG4gICAgICAgIHdyYXBfLmFkZENoaWxkKGlucHV0KTtcblxuICAgICAgICB2YXIgb3B0aW9ucyA9IE9wdGlvbnMuZ2V0KCksXG4gICAgICAgICAgICBidG5QcmVzZXQgPSBuZXcgQnV0dG9uUHJlc2V0KHRoaXMuX3dyYXBOb2RlKTtcblxuICAgICAgICB2YXIgb25QcmVzZXREZWFjdGl2YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgb3B0aW9ucy5jbGVhcigpO1xuICAgICAgICAgICAgYnRuUHJlc2V0LmRlYWN0aXZhdGUoKTtcbiAgICAgICAgfTtcblxuICAgICAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgICAgIHZhciBvblByZXNldEFjdGl2YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgb3B0aW9ucy5idWlsZChwcmVzZXRzLFxuICAgICAgICAgICAgICAgIGlucHV0LmdldFByb3BlcnR5KCd2YWx1ZScpLFxuICAgICAgICAgICAgICAgIGlucHV0LFxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQuc2V0UHJvcGVydHkoJ3ZhbHVlJywgcHJlc2V0c1tvcHRpb25zLmdldFNlbGVjdGVkSW5kZXgoKV0pO1xuICAgICAgICAgICAgICAgICAgICBzZWxmLnB1c2hIaXN0b3J5U3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgc2VsZi5hcHBseVZhbHVlKCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBvblByZXNldERlYWN0aXZhdGUsXG4gICAgICAgICAgICAgICAgTWV0cmljLlBBRERJTkdfUFJFU0VULFxuICAgICAgICAgICAgICAgIGZhbHNlKTtcbiAgICAgICAgfTtcblxuICAgICAgICBidG5QcmVzZXQuc2V0T25BY3RpdmUob25QcmVzZXRBY3RpdmF0ZSk7XG4gICAgICAgIGJ0blByZXNldC5zZXRPbkRlYWN0aXZlKG9uUHJlc2V0RGVhY3RpdmF0ZSlcbiAgICB9XG5cbiAgICBpbnB1dC5zZXRQcm9wZXJ0eSgndmFsdWUnLHRoaXMuX29ialt0aGlzLl9rZXldKTtcblxuICAgIGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50LktFWV9VUCwgdGhpcy5fb25JbnB1dEtleVVwLmJpbmQodGhpcykpO1xuICAgIGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50LkNIQU5HRSwgdGhpcy5fb25JbnB1dENoYW5nZS5iaW5kKHRoaXMpKTtcblxuICAgIGlucHV0LmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50Lk1PVVNFX0RPV04sIHRoaXMuX29uSW5wdXREcmFnU3RhcnQuYmluZCh0aGlzKSk7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKENvbXBvbmVudEV2ZW50LklOUFVUX1NFTEVDVF9EUkFHLHRoaXMuX3BhcmVudCwnb25Db21wb25lbnRTZWxlY3REcmFnJyk7XG59XG5TdHJpbmdJbnB1dC5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKE9iamVjdENvbXBvbmVudC5wcm90b3R5cGUpO1xuU3RyaW5nSW5wdXQucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gU3RyaW5nSW5wdXQ7XG5cblN0cmluZ0lucHV0LnByb3RvdHlwZS5fb25JbnB1dEtleVVwID0gZnVuY3Rpb24gKGUpIHtcbiAgICBpZiAodGhpcy5fa2V5SXNDaGFyKGUua2V5Q29kZSkpe1xuICAgICAgICB0aGlzLnB1c2hIaXN0b3J5U3RhdGUoKTtcbiAgICB9XG4gICAgdGhpcy5hcHBseVZhbHVlKCk7XG4gICAgdGhpcy5fb25DaGFuZ2UoKTtcbn07XG5cblN0cmluZ0lucHV0LnByb3RvdHlwZS5fb25JbnB1dENoYW5nZSA9IGZ1bmN0aW9uIChlKSB7XG4gICAgaWYgKHRoaXMuX2tleUlzQ2hhcihlLmtleUNvZGUpKXtcbiAgICAgICAgdGhpcy5wdXNoSGlzdG9yeVN0YXRlKCk7XG4gICAgfVxuICAgIHRoaXMuYXBwbHlWYWx1ZSgpO1xufTtcblxuLy9UT0RPOiBGaW5pc2ggY2hlY2tcblN0cmluZ0lucHV0LnByb3RvdHlwZS5fa2V5SXNDaGFyID0gZnVuY3Rpb24gKGtleUNvZGUpIHtcbiAgICByZXR1cm4ga2V5Q29kZSAhPSAxNyAmJlxuICAgICAgICBrZXlDb2RlICE9IDE4ICYmXG4gICAgICAgIGtleUNvZGUgIT0gMjAgJiZcbiAgICAgICAga2V5Q29kZSAhPSAzNyAmJlxuICAgICAgICBrZXlDb2RlICE9IDM4ICYmXG4gICAgICAgIGtleUNvZGUgIT0gMzkgJiZcbiAgICAgICAga2V5Q29kZSAhPSA0MCAmJlxuICAgICAgICBrZXlDb2RlICE9IDE2O1xufTtcblxuXG5TdHJpbmdJbnB1dC5wcm90b3R5cGUuYXBwbHlWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLl9vYmpbdGhpcy5fa2V5XSA9IHRoaXMuX2lucHV0LmdldFByb3BlcnR5KCd2YWx1ZScpO1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIENvbXBvbmVudEV2ZW50LlZBTFVFX1VQREFURUQsIG51bGwpKTtcbn07XG5cblN0cmluZ0lucHV0LnByb3RvdHlwZS5vblZhbHVlVXBkYXRlID0gZnVuY3Rpb24gKGUpIHtcbiAgICBpZiAoZS5kYXRhLm9yaWdpbiA9PSB0aGlzKXJldHVybjtcbiAgICB0aGlzLl9pbnB1dC5zZXRQcm9wZXJ0eSgndmFsdWUnLCB0aGlzLl9vYmpbdGhpcy5fa2V5XSk7XG59O1xuXG4vL1ByZXZlbnQgY2hyb21lIHNlbGVjdCBkcmFnXG5TdHJpbmdJbnB1dC5wcm90b3R5cGUuX29uSW5wdXREcmFnU3RhcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV2ZW50TW92ZSA9IERvY3VtZW50RXZlbnQuTU9VU0VfTU9WRSxcbiAgICAgICAgZXZlbnRVcCA9IERvY3VtZW50RXZlbnQuTU9VU0VfVVA7XG5cbiAgICB2YXIgZXZlbnQgPSBDb21wb25lbnRFdmVudC5JTlBVVF9TRUxFQ1RfRFJBRztcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIG9uRHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHNlbGYuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIGV2ZW50LCBudWxsKSk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgb25EcmFnRmluaXNoID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc2VsZi5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgZXZlbnQsIG51bGwpKTtcblxuICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE1vdmUsIG9uRHJhZywgZmFsc2UpO1xuICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE1vdmUsIG9uRHJhZ0ZpbmlzaCwgZmFsc2UpO1xuICAgICAgICB9O1xuXG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgZXZlbnQsIG51bGwpKTtcblxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRNb3ZlLCBvbkRyYWcsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50VXAsIG9uRHJhZ0ZpbmlzaCwgZmFsc2UpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBTdHJpbmdJbnB1dDsiLCJ2YXIgT3V0cHV0ID0gcmVxdWlyZSgnLi9PdXRwdXQnKTtcblxuU3RyaW5nT3V0cHV0ID0gZnVuY3Rpb24gKHBhcmVudCwgb2JqZWN0LCB2YWx1ZSwgcGFyYW1zKSB7XG4gICAgT3V0cHV0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59O1xuU3RyaW5nT3V0cHV0LnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoT3V0cHV0LnByb3RvdHlwZSk7XG5TdHJpbmdPdXRwdXQucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gU3RyaW5nT3V0cHV0O1xuXG5TdHJpbmdPdXRwdXQucHJvdG90eXBlLl9zZXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5fcGFyZW50LmlzRGlzYWJsZWQoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0ZXh0QXJlYVN0cmluZyA9IHRoaXMuX29ialt0aGlzLl9rZXldO1xuXG4gICAgaWYgKHRleHRBcmVhU3RyaW5nID09IHRoaXMuX3ByZXZTdHJpbmcpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0ZXh0QXJlYSA9IHRoaXMuX3RleHRBcmVhLFxuICAgICAgICB0ZXh0QXJlYUVsZW1lbnQgPSB0ZXh0QXJlYS5nZXRFbGVtZW50KCksXG4gICAgICAgIHRleHRBcmVhU2Nyb2xsSGVpZ2h0O1xuXG4gICAgdGV4dEFyZWEuc2V0UHJvcGVydHkoJ3ZhbHVlJywgdGV4dEFyZWFTdHJpbmcpO1xuICAgIHRleHRBcmVhU2Nyb2xsSGVpZ2h0ID0gdGV4dEFyZWFFbGVtZW50LnNjcm9sbEhlaWdodDtcbiAgICB0ZXh0QXJlYS5zZXRIZWlnaHQodGV4dEFyZWFTY3JvbGxIZWlnaHQpO1xuXG4gICAgdmFyIHNjcm9sbEJhciA9IHRoaXMuX3Njcm9sbEJhcjtcblxuICAgIGlmIChzY3JvbGxCYXIpIHtcbiAgICAgICAgaWYgKHRleHRBcmVhU2Nyb2xsSGVpZ2h0IDw9IHRoaXMuX3dyYXBOb2RlLmdldEhlaWdodCgpKSB7XG4gICAgICAgICAgICBzY3JvbGxCYXIuZGlzYWJsZSgpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgc2Nyb2xsQmFyLmVuYWJsZSgpO1xuICAgICAgICAgICAgc2Nyb2xsQmFyLnVwZGF0ZSgpO1xuICAgICAgICAgICAgc2Nyb2xsQmFyLnJlc2V0KCk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5fcHJldlN0cmluZyA9IHRleHRBcmVhU3RyaW5nO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBTdHJpbmdPdXRwdXQ7XG4iLCJ2YXIgUGxvdHRlciA9IHJlcXVpcmUoJy4vUGxvdHRlcicpO1xudmFyIE1ldHJpYyAgPSByZXF1aXJlKCcuL01ldHJpYycpO1xuXG52YXIgREVGQVVMVF9SRVNPTFVUSU9OID0gMTtcblxuZnVuY3Rpb24gVmFsdWVQbG90dGVyKHBhcmVudCxvYmplY3QsdmFsdWUscGFyYW1zKSB7XG4gICAgUGxvdHRlci5hcHBseSh0aGlzLGFyZ3VtZW50cyk7XG5cbiAgICB2YXIgc3ZnICAgICAgID0gdGhpcy5fc3ZnLFxuICAgICAgICBzdmdXaWR0aCAgPSBOdW1iZXIoc3ZnLmdldEF0dHJpYnV0ZSgnd2lkdGgnKSksXG4gICAgICAgIHN2Z0hlaWdodCA9IE51bWJlcihzdmcuZ2V0QXR0cmlidXRlKCdoZWlnaHQnKSk7XG5cbiAgICBwYXJhbXMgICAgICAgICAgICA9IHBhcmFtcyAgICAgICAgICAgIHx8IHt9O1xuICAgIHBhcmFtcy5oZWlnaHQgICAgID0gcGFyYW1zLmhlaWdodCAgICAgfHwgc3ZnSGVpZ2h0O1xuICAgIHBhcmFtcy5yZXNvbHV0aW9uID0gcGFyYW1zLnJlc29sdXRpb24gfHwgREVGQVVMVF9SRVNPTFVUSU9OO1xuXG4gICAgdmFyIHJlc29sdXRpb24gPSBwYXJhbXMucmVzb2x1dGlvbixcbiAgICAgICAgbGVuZ3RoICAgICA9IE1hdGguZmxvb3Ioc3ZnV2lkdGggLyByZXNvbHV0aW9uKTtcblxuICAgIHZhciBwb2ludHMgICAgID0gdGhpcy5fcG9pbnRzICA9IG5ldyBBcnJheShsZW5ndGggKiAyKSxcbiAgICAgICAgYnVmZmVyMCAgICA9IHRoaXMuX2J1ZmZlcjAgPSBuZXcgQXJyYXkobGVuZ3RoKSxcbiAgICAgICAgYnVmZmVyMSAgICA9IHRoaXMuX2J1ZmZlcjEgPSBuZXcgQXJyYXkobGVuZ3RoKTtcblxuICAgIHZhciBtaW4gPSB0aGlzLl9saW5lV2lkdGggKiAwLjU7XG5cbiAgICB2YXIgaSA9IC0xO1xuICAgIHdoaWxlICgrK2kgPCBsZW5ndGgpIHtcbiAgICAgICAgYnVmZmVyMFtpXSA9IGJ1ZmZlcjFbaV0gPSBwb2ludHNbaSAqIDJdID0gcG9pbnRzW2kgKiAyICsgMV0gPSBtaW47XG4gICAgfVxuXG4gICAgdGhpcy5faGVpZ2h0ID0gcGFyYW1zLmhlaWdodCA9IHBhcmFtcy5oZWlnaHQgIDwgTWV0cmljLkNPTVBPTkVOVF9NSU5fSEVJR0hUID9cbiAgICAgICAgICAgICAgICAgICBNZXRyaWMuQ09NUE9ORU5UX01JTl9IRUlHSFQgOiBwYXJhbXMuaGVpZ2h0O1xuXG4gICAgdGhpcy5fc3ZnU2V0U2l6ZShzdmdIZWlnaHQsTWF0aC5mbG9vcihwYXJhbXMuaGVpZ2h0KSk7XG4gICAgdGhpcy5fZ3JpZC5zdHlsZS5zdHJva2UgPSAncmdiKDM5LDQ0LDQ2KSc7XG5cbiAgICB0aGlzLl91cGRhdGVIZWlnaHQoKTtcbiAgICB0aGlzLl9kcmF3VmFsdWUoKTtcbn1cblZhbHVlUGxvdHRlci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKFBsb3R0ZXIucHJvdG90eXBlKTtcblZhbHVlUGxvdHRlci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBWYWx1ZVBsb3R0ZXI7XG5cblZhbHVlUGxvdHRlci5wcm90b3R5cGUuX3JlZHJhdyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcG9pbnRzID0gdGhpcy5fcG9pbnRzLFxuICAgICAgICBidWZmZXJMZW4gPSB0aGlzLl9idWZmZXIwLmxlbmd0aDtcblxuICAgIHZhciB3aWR0aCA9IE51bWJlcih0aGlzLl9zdmcuZ2V0QXR0cmlidXRlKCd3aWR0aCcpKSxcbiAgICAgICAgcmF0aW8gPSB3aWR0aCAvIChidWZmZXJMZW4gLSAxKTtcblxuICAgIHZhciBpID0gLTE7XG4gICAgd2hpbGUgKCsraSA8IGJ1ZmZlckxlbikge1xuICAgICAgICBwb2ludHNbaSAqIDJdID0gd2lkdGggLSBpICogcmF0aW87XG4gICAgfVxuXG4gICAgdGhpcy5fZHJhd1ZhbHVlKCk7XG59O1xuXG5WYWx1ZVBsb3R0ZXIucHJvdG90eXBlLm9uR3JvdXBTaXplQ2hhbmdlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciB3aWR0aCA9IHRoaXMuX3dyYXBOb2RlLmdldFdpZHRoKCksXG4gICAgICAgIGhlaWdodCA9IHRoaXMuX2hlaWdodDtcblxuICAgIHRoaXMuX3N2Z1NldFNpemUod2lkdGgsIGhlaWdodCk7XG4gICAgdGhpcy5fdXBkYXRlSGVpZ2h0KCk7XG4gICAgdGhpcy5fZHJhd0dyaWQoKTtcbiAgICB0aGlzLl9yZWRyYXcoKTtcbn07XG5cblZhbHVlUGxvdHRlci5wcm90b3R5cGUuX2RyYXdWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLl9kcmF3Q3VydmUoKTtcbn07XG5cblZhbHVlUGxvdHRlci5wcm90b3R5cGUuX2RyYXdHcmlkID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzdmcgPSB0aGlzLl9zdmc7XG5cbiAgICB2YXIgc3ZnV2lkdGggPSBOdW1iZXIoc3ZnLmdldEF0dHJpYnV0ZSgnd2lkdGgnKSksXG4gICAgICAgIHN2Z0hlaWdodEhhbGYgPSBNYXRoLmZsb29yKE51bWJlcihzdmcuZ2V0QXR0cmlidXRlKCdoZWlnaHQnKSkgKiAwLjUpO1xuXG4gICAgdmFyIHBhdGhDbWQgPSAnJztcbiAgICAgICAgcGF0aENtZCArPSB0aGlzLl9wYXRoQ21kTW92ZVRvKDAsIHN2Z0hlaWdodEhhbGYpO1xuICAgICAgICBwYXRoQ21kICs9IHRoaXMuX3BhdGhDbWRMaW5lVG8oc3ZnV2lkdGgsIHN2Z0hlaWdodEhhbGYpO1xuXG4gICAgdGhpcy5fZ3JpZC5zZXRBdHRyaWJ1dGUoJ2QnLCBwYXRoQ21kKTtcbn07XG5cbi8vVE9ETzogbWVyZ2UgdXBkYXRlICsgcGF0aGNtZFxuVmFsdWVQbG90dGVyLnByb3RvdHlwZS5fZHJhd0N1cnZlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzdmcgPSB0aGlzLl9zdmc7XG5cbiAgICB2YXIgdmFsdWUgPSB0aGlzLl9vYmpbdGhpcy5fa2V5XTtcblxuICAgIHZhciBidWZmZXIwID0gdGhpcy5fYnVmZmVyMCxcbiAgICAgICAgYnVmZmVyMSA9IHRoaXMuX2J1ZmZlcjEsXG4gICAgICAgIHBvaW50cyA9IHRoaXMuX3BvaW50cztcblxuICAgIHZhciBidWZmZXJMZW5ndGggPSBidWZmZXIwLmxlbmd0aDtcblxuICAgIHZhciBwYXRoQ21kID0gJyc7XG5cbiAgICB2YXIgaGVpZ2h0SGFsZiA9IE51bWJlcihzdmcuZ2V0QXR0cmlidXRlKCdoZWlnaHQnKSkgKiAwLjUsXG4gICAgICAgIHVuaXQgPSBoZWlnaHRIYWxmIC0gdGhpcy5fbGluZVdpZHRoICogMC41O1xuXG4gICAgcG9pbnRzWzFdID0gYnVmZmVyMFswXTtcbiAgICBidWZmZXIwW2J1ZmZlckxlbmd0aCAtIDFdID0gKHZhbHVlICogdW5pdCkgKiAtMSArIE1hdGguZmxvb3IoaGVpZ2h0SGFsZik7XG5cbiAgICBwYXRoQ21kICs9IHRoaXMuX3BhdGhDbWRNb3ZlVG8ocG9pbnRzWzBdLCBwb2ludHNbMV0pO1xuXG4gICAgdmFyIGkgPSAwLCBpbmRleDtcblxuICAgIHdoaWxlICgrK2kgPCBidWZmZXJMZW5ndGgpIHtcbiAgICAgICAgaW5kZXggPSBpICogMjtcblxuICAgICAgICBidWZmZXIxW2kgLSAxXSA9IGJ1ZmZlcjBbaV07XG4gICAgICAgIHBvaW50c1tpbmRleCArIDFdID0gYnVmZmVyMFtpIC0gMV0gPSBidWZmZXIxW2kgLSAxXTtcblxuICAgICAgICBwYXRoQ21kICs9IHRoaXMuX3BhdGhDbWRMaW5lVG8ocG9pbnRzW2luZGV4XSwgcG9pbnRzW2luZGV4ICsgMV0pO1xuICAgIH1cblxuICAgIHRoaXMuX3BhdGguc2V0QXR0cmlidXRlKCdkJywgcGF0aENtZCk7XG59O1xuXG5WYWx1ZVBsb3R0ZXIucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5fcGFyZW50LmlzRGlzYWJsZWQoKSlyZXR1cm47XG4gICAgdGhpcy5fZHJhd1ZhbHVlKCk7XG59XG5cblxubW9kdWxlLmV4cG9ydHMgPSBWYWx1ZVBsb3R0ZXI7XG5cbiIsInZhciBOb2RlID0gcmVxdWlyZSgnLi9kb2N1bWVudC9Ob2RlJyksXG4gICAgQ1NTID0gcmVxdWlyZSgnLi9kb2N1bWVudC9DU1MnKTtcbnZhciBFdmVudERpc3BhdGNoZXIgPSByZXF1aXJlKCcuL2V2ZW50L0V2ZW50RGlzcGF0Y2hlcicpLFxuICAgIENvbXBvbmVudEV2ZW50ICA9IHJlcXVpcmUoJy4vQ29tcG9uZW50RXZlbnQnKTtcblxuZnVuY3Rpb24gQ29tcG9uZW50KHBhcmVudCxsYWJlbCkge1xuICAgIEV2ZW50RGlzcGF0Y2hlci5hcHBseSh0aGlzLGFyZ3VtZW50cyk7XG5cbiAgICBsYWJlbCA9IHBhcmVudC51c2VzTGFiZWxzKCkgPyBsYWJlbCA6ICdub25lJztcblxuICAgIHRoaXMuX3BhcmVudCAgPSBwYXJlbnQ7XG4gICAgdGhpcy5fZW5hYmxlZCA9IHRydWU7XG5cbiAgICB2YXIgcm9vdCA9IHRoaXMuX25vZGUgPSBuZXcgTm9kZShOb2RlLkxJU1RfSVRFTSksXG4gICAgICAgIHdyYXAgPSB0aGlzLl93cmFwTm9kZSA9IG5ldyBOb2RlKCk7XG4gICAgICAgIHdyYXAuc2V0U3R5bGVDbGFzcyhDU1MuV3JhcCk7XG4gICAgICAgIHJvb3QuYWRkQ2hpbGQod3JhcCk7XG5cbiAgICBpZiAobGFiZWwgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAobGFiZWwubGVuZ3RoICE9IDAgJiYgbGFiZWwgIT0gJ25vbmUnKSB7XG4gICAgICAgICAgICB2YXIgbGFiZWxfID0gdGhpcy5fbGFibE5vZGUgPSBuZXcgTm9kZShOb2RlLlNQQU4pO1xuICAgICAgICAgICAgICAgIGxhYmVsXy5zZXRTdHlsZUNsYXNzKENTUy5MYWJlbCk7XG4gICAgICAgICAgICAgICAgbGFiZWxfLnNldFByb3BlcnR5KCdpbm5lckhUTUwnLCBsYWJlbCk7XG4gICAgICAgICAgICAgICAgcm9vdC5hZGRDaGlsZChsYWJlbF8pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxhYmVsID09ICdub25lJykge1xuICAgICAgICAgICAgd3JhcC5zZXRTdHlsZVByb3BlcnR5KCdtYXJnaW5MZWZ0JywgJzAnKTtcbiAgICAgICAgICAgIHdyYXAuc2V0U3R5bGVQcm9wZXJ0eSgnd2lkdGgnLCAnMTAwJScpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5fcGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoQ29tcG9uZW50RXZlbnQuRU5BQkxFLCB0aGlzLCdvbkVuYWJsZScpO1xuICAgIHRoaXMuX3BhcmVudC5hZGRFdmVudExpc3RlbmVyKENvbXBvbmVudEV2ZW50LkRJU0FCTEUsdGhpcywnb25EaXNhYmxlJyk7XG4gICAgdGhpcy5fcGFyZW50LmFkZENvbXBvbmVudE5vZGUocm9vdCk7XG59XG5Db21wb25lbnQucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFdmVudERpc3BhdGNoZXIucHJvdG90eXBlKTtcbkNvbXBvbmVudC5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBDb21wb25lbnQ7XG5cbkNvbXBvbmVudC5wcm90b3R5cGUuZW5hYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX2VuYWJsZWQgPSB0cnVlO1xufTtcblxuQ29tcG9uZW50LnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX2VuYWJsZWQgPSBmYWxzZTtcbn07XG5cbkNvbXBvbmVudC5wcm90b3R5cGUuaXNFbmFibGVkID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9lbmFibGVkO1xufTtcbkNvbXBvbmVudC5wcm90b3R5cGUuaXNEaXNhYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gIXRoaXMuX2VuYWJsZWQ7XG59O1xuXG5Db21wb25lbnQucHJvdG90eXBlLm9uRW5hYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZW5hYmxlKCk7XG59O1xuXG5Db21wb25lbnQucHJvdG90eXBlLm9uRGlzYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmRpc2FibGUoKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gQ29tcG9uZW50OyIsInZhciBDb21wb25lbnRFdmVudCA9IHtcblx0VkFMVUVfVVBEQVRFRDogJ3ZhbHVlVXBkYXRlZCcsXG5cdFVQREFURV9WQUxVRTogJ3VwZGF0ZVZhbHVlJyxcblxuXHRJTlBVVF9TRUxFQ1RfRFJBRzogJ2lucHV0U2VsZWN0RHJhZycsXG5cblx0RU5BQkxFICA6ICdlbmFibGUnLFxuXHRESVNBQkxFIDogJ2Rpc2FibGUnXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvbXBvbmVudEV2ZW50OyIsImZ1bmN0aW9uIENvbXBvbmVudE9iamVjdEVycm9yKG9iamVjdCxrZXkpIHtcblx0RXJyb3IuYXBwbHkodGhpcyk7XG5cdEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsQ29tcG9uZW50T2JqZWN0RXJyb3IpO1xuXHR0aGlzLm5hbWUgPSAnQ29tcG9uZW50T2JqZWN0RXJyb3InO1xuXHR0aGlzLm1lc3NhZ2UgPSAnT2JqZWN0IG9mIHR5cGUgJyArIG9iamVjdC5jb25zdHJ1Y3Rvci5uYW1lICsgJyBoYXMgbm8gbWVtYmVyICcgKyBrZXkgKyAnLic7XG59XG5Db21wb25lbnRPYmplY3RFcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEVycm9yLnByb3RvdHlwZSk7XG5Db21wb25lbnRPYmplY3RFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBDb21wb25lbnRPYmplY3RFcnJvcjtcblxubW9kdWxlLmV4cG9ydHMgPSBDb21wb25lbnRPYmplY3RFcnJvcjsiLCJ2YXIgRXZlbnREaXNwYXRjaGVyID0gcmVxdWlyZSgnLi9ldmVudC9FdmVudERpc3BhdGNoZXInKSxcbiAgICBFdmVudF8gPSByZXF1aXJlKCcuL2V2ZW50L0V2ZW50JyksXG4gICAgSGlzdG9yeUV2ZW50ID0gcmVxdWlyZSgnLi9IaXN0b3J5RXZlbnQnKTtcblxudmFyIE1BWF9TVEFURVMgPSAzMDtcblxuZnVuY3Rpb24gSGlzdG9yeSgpIHtcbiAgICBFdmVudERpc3BhdGNoZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB0aGlzLl9zdGF0ZXMgPSBbXTtcbiAgICB0aGlzLl9lbmFibGVkID0gZmFsc2U7XG59XG5IaXN0b3J5LnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXZlbnREaXNwYXRjaGVyLnByb3RvdHlwZSk7XG5IaXN0b3J5LnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEhpc3Rvcnk7XG5cbkhpc3RvcnkucHJvdG90eXBlLnB1c2hTdGF0ZSA9IGZ1bmN0aW9uIChvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgICBpZiAodGhpcy5fZW5hYmxlZCl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgc3RhdGVzID0gdGhpcy5fc3RhdGVzO1xuICAgIGlmIChzdGF0ZXMubGVuZ3RoID49IE1BWF9TVEFURVMpe1xuICAgICAgICBzdGF0ZXMuc2hpZnQoKTtcbiAgICB9XG4gICAgc3RhdGVzLnB1c2goe29iamVjdDogb2JqZWN0LCBrZXk6IGtleSwgdmFsdWU6IHZhbHVlfSk7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgSGlzdG9yeUV2ZW50LlNUQVRFX1BVU0gsIG51bGwpKTtcbn07XG5cbkhpc3RvcnkucHJvdG90eXBlLmdldFN0YXRlID0gZnVuY3Rpb24gKG9iamVjdCwga2V5KSB7XG4gICAgdmFyIHN0YXRlcyA9IHRoaXMuX3N0YXRlcyxcbiAgICAgICAgc3RhdGVzTGVuID0gc3RhdGVzLmxlbmd0aDtcblxuICAgIGlmIChzdGF0ZXNMZW4gPT0gMCl7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciBzdGF0ZSwgdmFsdWU7XG4gICAgdmFyIGkgPSAtMTtcbiAgICB3aGlsZSAoKytpIDwgc3RhdGVzTGVuKSB7XG4gICAgICAgIHN0YXRlID0gc3RhdGVzW2ldO1xuICAgICAgICBpZiAoc3RhdGUub2JqZWN0ID09PSBvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChzdGF0ZS5rZXkgPT09IGtleSkge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gc3RhdGUudmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xufTtcblxuSGlzdG9yeS5wcm90b3R5cGUucG9wU3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuX2VuYWJsZWQpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIHN0YXRlcyA9IHRoaXMuX3N0YXRlcztcbiAgICBpZiAoc3RhdGVzLmxlbmd0aCA8IDEpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIGxhc3RTdGF0ZSA9IHN0YXRlcy5wb3AoKTtcbiAgICBsYXN0U3RhdGUub2JqZWN0W2xhc3RTdGF0ZS5rZXldID0gbGFzdFN0YXRlLnZhbHVlO1xuXG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgSGlzdG9yeUV2ZW50LlNUQVRFX1BPUCwgbnVsbCkpO1xufTtcblxuSGlzdG9yeS5wcm90b3R5cGUuZ2V0TnVtU3RhdGVzID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9zdGF0ZXMubGVuZ3RoO1xufTtcblxuSGlzdG9yeS5faW5zdGFuY2UgPSBudWxsO1xuXG5IaXN0b3J5LnNldHVwID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBIaXN0b3J5Ll9pbnN0YW5jZSA9IG5ldyBIaXN0b3J5KCk7XG59O1xuXG5IaXN0b3J5LmdldCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gSGlzdG9yeS5faW5zdGFuY2U7XG59O1xuXG5IaXN0b3J5LnByb3RvdHlwZS5lbmFibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5fZW5hYmxlZCA9IGZhbHNlO1xufTtcbkhpc3RvcnkucHJvdG90eXBlLmRpc2FibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5fZW5hYmxlZCA9IHRydWU7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEhpc3Rvcnk7IiwidmFyIEhpc3RvcnlFdmVudCA9IHtcblx0U1RBVEVfUFVTSDogJ2hpc3RvcnlTdGF0ZVB1c2gnLFxuXHRTVEFURV9QT1A6ICdoaXN0b3J5U3RhdGVQb3AnXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEhpc3RvcnlFdmVudDsiLCJ2YXIgSGlzdG9yeSA9IHJlcXVpcmUoJy4vSGlzdG9yeScpO1xudmFyIENvbXBvbmVudCA9IHJlcXVpcmUoJy4vQ29tcG9uZW50JyksXG4gICAgQ29tcG9uZW50RXZlbnQgPSByZXF1aXJlKCcuL0NvbXBvbmVudEV2ZW50JyksXG4gICAgT2JqZWN0Q29tcG9uZW50Tm90aWZpZXIgPSByZXF1aXJlKCcuL09iamVjdENvbXBvbmVudE5vdGlmaWVyJyksXG4gICAgQ29tcG9uZW50T2JqZWN0RXJyb3IgPSByZXF1aXJlKCcuL0NvbXBvbmVudE9iamVjdEVycm9yJyk7XG52YXIgRXZlbnRfID0gcmVxdWlyZSgnLi9ldmVudC9FdmVudCcpO1xuXG5mdW5jdGlvbiBPYmplY3RDb21wb25lbnQocGFyZW50LCBvYmosIGtleSwgcGFyYW1zKSB7XG4gICAgaWYgKG9ialtrZXldID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IENvbXBvbmVudE9iamVjdEVycm9yKG9iaiwga2V5KTtcbiAgICB9XG4gICAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICAgIHBhcmFtcy5sYWJlbCA9IHBhcmFtcy5sYWJlbCB8fCBrZXk7XG5cbiAgICBDb21wb25lbnQuYXBwbHkodGhpcywgW3BhcmVudCwgcGFyYW1zLmxhYmVsXSk7XG5cbiAgICB0aGlzLl9vYmogPSBvYmo7XG4gICAgdGhpcy5fa2V5ID0ga2V5O1xuICAgIHRoaXMuX29uQ2hhbmdlID0gZnVuY3Rpb24oKXt9O1xuXG4gICAgT2JqZWN0Q29tcG9uZW50Tm90aWZpZXIuZ2V0KCkuYWRkRXZlbnRMaXN0ZW5lcihDb21wb25lbnRFdmVudC5VUERBVEVfVkFMVUUsIHRoaXMsICdvblZhbHVlVXBkYXRlJyk7XG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKENvbXBvbmVudEV2ZW50LlZBTFVFX1VQREFURUQsIE9iamVjdENvbXBvbmVudE5vdGlmaWVyLmdldCgpLCAnb25WYWx1ZVVwZGF0ZWQnKTtcbn1cbk9iamVjdENvbXBvbmVudC5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKENvbXBvbmVudC5wcm90b3R5cGUpO1xuT2JqZWN0Q29tcG9uZW50LnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IE9iamVjdENvbXBvbmVudDtcblxuLy9PdmVycmlkZSBpbiBTdWJjbGFzc1xuT2JqZWN0Q29tcG9uZW50LnByb3RvdHlwZS5hcHBseVZhbHVlID0gZnVuY3Rpb24oKSB7fTtcbk9iamVjdENvbXBvbmVudC5wcm90b3R5cGUub25WYWx1ZVVwZGF0ZSA9IGZ1bmN0aW9uIChlKSB7fTtcblxuT2JqZWN0Q29tcG9uZW50LnByb3RvdHlwZS5wdXNoSGlzdG9yeVN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBvYmogPSB0aGlzLl9vYmosIGtleSA9IHRoaXMuX2tleTtcbiAgICBIaXN0b3J5LmdldCgpLnB1c2hTdGF0ZShvYmosIGtleSwgb2JqW2tleV0pO1xufTtcblxuT2JqZWN0Q29tcG9uZW50LnByb3RvdHlwZS5zZXRWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHRoaXMuX29ialt0aGlzLl9rZXldID0gdmFsdWU7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcyxDb21wb25lbnRFdmVudC5WQUxVRV9VUERBVEVELG51bGwpKTtcbn07XG5cbk9iamVjdENvbXBvbmVudC5wcm90b3R5cGUuZ2V0RGF0YSA9IGZ1bmN0aW9uKCl7XG4gICAgdmFyIG9iaiA9IHt9O1xuICAgICAgICBvYmpbdGhpcy5fa2V5XSA9IHRoaXMuX29ialt0aGlzLl9rZXldO1xuICAgIHJldHVybiBvYmo7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdENvbXBvbmVudDtcbiIsInZhciBFdmVudERpc3BhdGNoZXIgPSByZXF1aXJlKCcuL2V2ZW50L0V2ZW50RGlzcGF0Y2hlcicpLFxuXHRFdmVudF8gXHRcdFx0PSByZXF1aXJlKCcuL2V2ZW50L0V2ZW50Jyk7XG52YXIgQ29tcG9uZW50RXZlbnQgID0gcmVxdWlyZSgnLi9Db21wb25lbnRFdmVudCcpLFxuXHRPcHRpb25FdmVudFx0XHQ9IHJlcXVpcmUoJy4vT3B0aW9uRXZlbnQnKTtcblxuZnVuY3Rpb24gT2JqZWN0Q29tcG9uZW50Tm90aWZpZXIoKXtcblx0RXZlbnREaXNwYXRjaGVyLmFwcGx5KHRoaXMpO1xufVxuT2JqZWN0Q29tcG9uZW50Tm90aWZpZXIucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFdmVudERpc3BhdGNoZXIucHJvdG90eXBlKTtcbk9iamVjdENvbXBvbmVudE5vdGlmaWVyLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IE9iamVjdENvbXBvbmVudE5vdGlmaWVyO1xuXG5PYmplY3RDb21wb25lbnROb3RpZmllci5wcm90b3R5cGUub25WYWx1ZVVwZGF0ZWQgPSBmdW5jdGlvbiAoZSkge1xuXHR0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50Xyh0aGlzLCBDb21wb25lbnRFdmVudC5VUERBVEVfVkFMVUUsIHtvcmlnaW46IGUuc2VuZGVyfSkpO1xufTtcblxuT2JqZWN0Q29tcG9uZW50Tm90aWZpZXIucHJvdG90eXBlLm9uT3B0aW9uVHJpZ2dlcmVkID0gZnVuY3Rpb24oZSkge1xuXHR0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50Xyh0aGlzLCBPcHRpb25FdmVudC5UUklHR0VSLCB7b3JpZ2luOiBlLnNlbmRlcn0pKTtcbn07XG5cbnZhciBpbnN0YW5jZSA9IG51bGw7XG5cbk9iamVjdENvbXBvbmVudE5vdGlmaWVyLmdldCA9IGZ1bmN0aW9uKCl7XG5cdGlmKCFpbnN0YW5jZSl7XG5cdFx0aW5zdGFuY2UgPSBuZXcgT2JqZWN0Q29tcG9uZW50Tm90aWZpZXIoKTtcblx0fVxuXHRyZXR1cm4gaW5zdGFuY2U7XG59O1xuXG5PYmplY3RDb21wb25lbnROb3RpZmllci5kZXN0cm95ID0gZnVuY3Rpb24oKXtcblx0aW5zdGFuY2UgPSBudWxsO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBPYmplY3RDb21wb25lbnROb3RpZmllcjsiLCJ2YXIgT3B0aW9uRXZlbnQgPSB7XG5cdFRSSUdHRVJFRDogJ3NlbGVjdFRyaWdnZXInLFxuXHRUUklHR0VSOiAndHJpZ2dlclNlbGVjdCdcbn07XG5tb2R1bGUuZXhwb3J0cyA9IE9wdGlvbkV2ZW50OyIsInZhciBEaWFsb2dUZW1wbGF0ZSA9XG4gICAgJzxoZWFkPlxcbicgK1xuICAgICcgICA8dGl0bGU+Q29udHJvbEtpdCBTdGF0ZTwvdGl0bGU+XFxuJyArXG4gICAgJyAgIDxzdHlsZSB0eXBlPVwidGV4dC9jc3NcIj5cXG4nICtcbiAgICAnICAgICAgYm9keXtcXG4nICtcbiAgICAnICAgICAgICAgIGJveC1zaXppbmc6IGJvcmRlci1ib3g7XFxuJyArXG4gICAgJyAgICAgICAgICBwYWRkaW5nOiAyMHB4O1xcbicgK1xuICAgICcgICAgICAgICAgbWFyZ2luOiAwO1xcbicgK1xuICAgICcgICAgICAgICAgZm9udC1mYW1pbHk6IEFyaWFsLCBzYW5zLXNlcmlmO1xcbicgK1xuICAgICcgICAgICAgICAgd2lkdGg6IDEwMCU7XFxuJyArXG4gICAgJyAgICAgIH1cXG4nICtcbiAgICAnICAgICAgdGV4dGFyZWF7XFxuJyArXG4gICAgJyAgICAgICAgICBtYXJnaW4tYm90dG9tOjEwcHg7XFxuJyArXG4gICAgJyAgICAgICAgICBib3gtc2l6aW5nOiBib3JkZXItYm94O1xcbicgK1xuICAgICcgICAgICAgICAgcGFkZGluZzogMDtcXG4nICtcbiAgICAnICAgICAgICAgIGJvcmRlcjogMDtcXG4nICtcbiAgICAnICAgICAgICAgIGJvcmRlcjogMXB4IHNvbGlkICNkZWRlZGU7XFxuJyArXG4gICAgJyAgICAgICAgICBvdXRsaW5lOiBub25lO1xcbicgK1xuICAgICcgICAgICAgICAgZm9udC1mYW1pbHk6IE1vbmFjbywgbW9ub3NwYWNlO1xcbicgK1xuICAgICcgICAgICAgICAgZm9udC1zaXplOiAxMXB4O1xcbicgK1xuICAgICcgICAgICAgICAgcmVzaXplOiBub25lO1xcbicgK1xuICAgICcgICAgICAgICAgd29yZC13cmFwOiBicmVhay13b3JkO1xcbicgK1xuICAgICcgICAgICAgICAgZGlzcGxheTogYmxvY2s7XFxuJyArXG4gICAgJyAgICAgICAgICB3aWR0aDogMTAwJTtcXG4nICtcbiAgICAnICAgICAgICAgIG92ZXJmbG93LXk6IHNjcm9sbDtcXG4nICtcbiAgICAnICAgICAgICAgIGhlaWdodDogMTI1cHg7XFxuJyArXG4gICAgJyAgICAgIH1cXG4nICtcbiAgICAnICAgICAgYnV0dG9ue1xcbicgK1xuICAgICcgICAgICAgICAgbWFyZ2luOiAwO1xcbicgK1xuICAgICcgICAgICAgICAgcGFkZGluZzogMCA1cHggM3B4IDVweDtcXG4nICtcbiAgICAnICAgICAgICAgIGhlaWdodDogMjBweDtcXG4nICtcbiAgICAnICAgICAgfVxcbicrXG4gICAgJyAgICAgICNzYXZlLCNmaWxlbmFtZSwjbG9hZHtcXG4nICtcbiAgICAnICAgICAgICAgIGZsb2F0OiByaWdodDtcXG4nICtcbiAgICAnICAgICAgfVxcbicgK1xuICAgICcgICAgICBpbnB1dFt0eXBlPVwidGV4dFwiXXtcXG4nICtcbiAgICAnICAgICAgICAgIG1hcmdpbjogMDtcXG4nICtcbiAgICAnICAgICAgICAgIHBhZGRpbmc6IDA7XFxuJyArXG4gICAgJyAgICAgICAgICB3aWR0aDogNDUlO1xcbicgK1xuICAgICcgICAgICAgICAgaGVpZ2h0OjIwcHg7XFxuJyArXG4gICAgJyAgICAgIH1cXG4nK1xuICAgICcgICA8L3N0eWxlPlxcbicgK1xuICAgICc8L2hlYWQ+XFxuJyArXG4gICAgJzxib2R5PlxcbicgK1xuICAgICcgICA8dGV4dGFyZWEgbmFtZT1cInN0YXRlXCIgaWQ9XCJzdGF0ZVwiPjwvdGV4dGFyZWE+XFxuJyArXG4gICAgJzwvYm9keT4nO1xuXG52YXIgU2F2ZURpYWxvZ1RlbXBsYXRlID1cbiAgICAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgaWQ9XCJzYXZlXCI+U2F2ZTwvYnV0dG9uPlxcbicgK1xuICAgICc8aW5wdXQgdHlwZT1cInRleHRcIiBpZD1cImZpbGVuYW1lXCIgdmFsdWU9XCJjay1zdGF0ZS5qc29uXCI+PC9pbnB1dD4nO1xuXG52YXIgTG9hZERpYWxvZ1RlbXBsYXRlID1cbiAgICAnPGlucHV0IHR5cGU9XCJmaWxlXCIgaWQ9XCJsb2FkLWRpc2tcIj48L2J1dHRvbj4nICtcbiAgICAnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgaWQ9XCJsb2FkXCI+TG9hZDwvYnV0dG9uPic7XG5cbmZ1bmN0aW9uIGNyZWF0ZVdpbmRvdygpe1xuICAgIHZhciB3aWR0aCA9IDMyMCwgaGVpZ2h0ID0gMjAwO1xuICAgIHZhciB3aW5kb3dfID0gd2luZG93Lm9wZW4oJycsJycsJ1xcXG4gICAgICAgIHdpZHRoPScgKyB3aWR0aCArICcsXFxcbiAgICAgICAgaGVpZ2h0PScgKyBoZWlnaHQgKyAnLFxcXG4gICAgICAgIGxlZnQ9JyArICh3aW5kb3cuc2NyZWVuWCArIHdpbmRvdy5pbm5lcldpZHRoICogMC41IC0gd2lkdGggKiAwLjUpICsgJyxcXFxuICAgICAgICB0b3A9JyArICh3aW5kb3cuc2NyZWVuWSArIHdpbmRvdy5pbm5lckhlaWdodCAqIDAuNSAtIGhlaWdodCAqIDAuNSkgKyAnLFxcXG4gICAgICAgIGxvY2F0aW9uPTAsXFxcbiAgICAgICAgdGl0bGViYXI9MCxcXFxuICAgICAgICByZXNpemFibGU9MCcpO1xuICAgIHdpbmRvd18uZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmlubmVySFRNTCA9IERpYWxvZ1RlbXBsYXRlO1xuICAgIHJldHVybiB3aW5kb3dfO1xufVxuXG5mdW5jdGlvbiBzYXZlKGRhdGEpe1xuICAgIHZhciB3aW5kb3dfID0gY3JlYXRlV2luZG93KCk7XG4gICAgdmFyIGRvY3VtZW50XyA9IHdpbmRvd18uZG9jdW1lbnQ7XG4gICAgICAgIGRvY3VtZW50Xy5ib2R5LmlubmVySFRNTCArPSBTYXZlRGlhbG9nVGVtcGxhdGU7XG4gICAgICAgIGRvY3VtZW50Xy5nZXRFbGVtZW50QnlJZCgnc2F2ZScpLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJyxmdW5jdGlvbigpe1xuICAgICAgICAgICAgLy9sb2cgJiBzYXZlIGluIG1haW4gd2luZG93XG4gICAgICAgICAgICB2YXIgc3RyICA9IGRvY3VtZW50Xy5nZXRFbGVtZW50QnlJZCgnc3RhdGUnKS52YWx1ZSxcbiAgICAgICAgICAgICAgICBibG9iID0gbmV3IEJsb2IoW3N0cl0se3R5cGU6J2FwcGxpY2F0aW9uOmpzb24nfSksXG4gICAgICAgICAgICAgICAgbmFtZSA9IGRvY3VtZW50Xy5nZXRFbGVtZW50QnlJZCgnZmlsZW5hbWUnKS52YWx1ZTtcbiAgICAgICAgICAgIHZhciBhID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuICAgICAgICAgICAgYS5kb3dubG9hZCA9IG5hbWU7XG4gICAgICAgICAgICBpZih3aW5kb3cud2Via2l0VVJMKXtcbiAgICAgICAgICAgICAgICBhLmhyZWYgPSB3aW5kb3cud2Via2l0VVJMLmNyZWF0ZU9iamVjdFVSTChibG9iKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYS5ocmVmID0gd2luZG93LmNyZWF0ZU9iamVjdFVSTChibG9iKTtcbiAgICAgICAgICAgICAgICBhLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgICAgICAgICAgYS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsZnVuY3Rpb24oKXtcbiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnRfLmJvZHkucmVtb3ZlQ2hpbGQoYSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgZG9jdW1lbnRfLmJvZHkuYXBwZW5kQ2hpbGQoYSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhLmNsaWNrKCk7XG4gICAgICAgIH0pO1xuICAgIGRvY3VtZW50Xy5nZXRFbGVtZW50QnlJZCgnc3RhdGUnKS5pbm5lclRleHQgPSBKU09OLnN0cmluZ2lmeShkYXRhKTtcbn1cblxuZnVuY3Rpb24gbG9hZChjYWxsYmFjayl7XG4gICAgdmFyIHdpbmRvd18gPSBjcmVhdGVXaW5kb3coKTtcbiAgICB2YXIgZG9jdW1lbnRfID0gd2luZG93Xy5kb2N1bWVudDtcbiAgICAgICAgZG9jdW1lbnRfLmJvZHkuaW5uZXJIVE1MICs9IExvYWREaWFsb2dUZW1wbGF0ZTtcbiAgICB2YXIgaW5wdXQgICA9IGRvY3VtZW50Xy5nZXRFbGVtZW50QnlJZCgnc3RhdGUnKTtcbiAgICB2YXIgYnRuTG9hZCA9IGRvY3VtZW50Xy5nZXRFbGVtZW50QnlJZCgnbG9hZCcpO1xuICAgICAgICBidG5Mb2FkLmRpc2FibGVkID0gdHJ1ZTtcblxuICAgIGZ1bmN0aW9uIHZhbGlkYXRlSW5wdXQoKXtcbiAgICAgICAgdHJ5e1xuICAgICAgICAgICAgdmFyIG9iaiA9IEpTT04ucGFyc2UoaW5wdXQudmFsdWUpO1xuICAgICAgICAgICAgaWYob2JqICYmIHR5cGVvZiBvYmogPT09ICdvYmplY3QnICYmIG9iaiAhPT0gbnVsbCl7XG4gICAgICAgICAgICAgICAgYnRuTG9hZC5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgICAgIGJ0bkxvYWQuZGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaW5wdXQuYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLGZ1bmN0aW9uKCl7XG4gICAgICAgIHZhbGlkYXRlSW5wdXQoKTtcbiAgICB9KTtcbiAgICBkb2N1bWVudF8uZ2V0RWxlbWVudEJ5SWQoJ2xvYWQnKS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsZnVuY3Rpb24oKXtcbiAgICAgICAgdmFyIHN0ciA9IGlucHV0LnZhbHVlO1xuICAgICAgICBjYWxsYmFjayhKU09OLnBhcnNlKHN0cikuZGF0YSk7XG4gICAgICAgIHdpbmRvd18uY2xvc2UoKTtcbiAgICB9KTtcbiAgICB2YXIgbG9hZEZyb21EaXNrID0gZG9jdW1lbnRfLmdldEVsZW1lbnRCeUlkKCdsb2FkLWRpc2snKTtcbiAgICAgICAgbG9hZEZyb21EaXNrLmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIHZhciByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgICAgICAgICAgcmVhZGVyLmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWRlbmQnLGZ1bmN0aW9uKGUpe1xuICAgICAgICAgICAgICAgIGlucHV0LnZhbHVlID0gZS50YXJnZXQucmVzdWx0O1xuICAgICAgICAgICAgICAgIHZhbGlkYXRlSW5wdXQoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmVhZGVyLnJlYWRBc1RleHQobG9hZEZyb21EaXNrLmZpbGVzWzBdLCd1dGYtOCcpO1xuICAgICAgICB9KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgbG9hZCA6IGxvYWQsXG4gICAgc2F2ZSA6IHNhdmVcbn07IiwiZnVuY3Rpb24gQ29sb3JGb3JtYXRFcnJvcihtc2cpIHtcblx0RXJyb3IuYXBwbHkodGhpcyk7XG5cdEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsQ29sb3JGb3JtYXRFcnJvcik7XG5cdHRoaXMubmFtZSA9ICdDb2xvckZvcm1hdEVycm9yJztcblx0dGhpcy5tZXNzYWdlID0gbXNnO1xufVxuQ29sb3JGb3JtYXRFcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEVycm9yLnByb3RvdHlwZSk7XG5Db2xvckZvcm1hdEVycm9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IENvbG9yRm9ybWF0RXJyb3I7XG5cbm1vZHVsZS5leHBvcnRzID0gQ29sb3JGb3JtYXRFcnJvcjsiLCJ2YXIgQ29sb3JNb2RlID0ge1xuXHRSR0IgIDogJ3JnYicsXG5cdEhTViAgOiAnaHN2Jyxcblx0SEVYICA6ICdoZXgnLFxuXHRSR0JmdjogJ3JnYmZ2J1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBDb2xvck1vZGU7IiwidmFyIENvbG9yVXRpbCA9IHtcblx0SFNWMlJHQjogZnVuY3Rpb24gKGh1ZSwgc2F0LCB2YWwpIHtcblx0XHR2YXIgbWF4X2h1ZSA9IDM2MC4wLFxuXHRcdFx0bWF4X3NhdCA9IDEwMC4wLFxuXHRcdFx0bWF4X3ZhbCA9IDEwMC4wO1xuXG5cdFx0dmFyIG1pbl9odWUgPSAwLjAsXG5cdFx0XHRtaW5fc2F0ID0gMCxcblx0XHRcdG1pbl92YWwgPSAwO1xuXG5cdFx0aHVlID0gaHVlICUgbWF4X2h1ZTtcblx0XHR2YWwgPSBNYXRoLm1heChtaW5fdmFsLCBNYXRoLm1pbih2YWwsIG1heF92YWwpKSAvIG1heF92YWwgKiAyNTUuMDtcblxuXHRcdGlmIChzYXQgPD0gbWluX3NhdCkge1xuXHRcdFx0dmFsID0gTWF0aC5yb3VuZCh2YWwpO1xuXHRcdFx0cmV0dXJuIFt2YWwsIHZhbCwgdmFsXTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoc2F0ID4gbWF4X3NhdClzYXQgPSBtYXhfc2F0O1xuXG5cdFx0c2F0ID0gc2F0IC8gbWF4X3NhdDtcblxuXHRcdC8vaHR0cDovL2QuaGF0ZW5hLm5lLmpwL2phOS8yMDEwMDkwMy8xMjgzNTA0MzRcblxuXHRcdHZhciBoaSA9IE1hdGguZmxvb3IoaHVlIC8gNjAuMCkgJSA2LFxuXHRcdFx0ZiA9IChodWUgLyA2MC4wKSAtIGhpLFxuXHRcdFx0cCA9IHZhbCAqICgxIC0gc2F0KSxcblx0XHRcdHEgPSB2YWwgKiAoMSAtIGYgKiBzYXQpLFxuXHRcdFx0dCA9IHZhbCAqICgxIC0gKDEgLSBmKSAqIHNhdCk7XG5cblx0XHR2YXIgciA9IDAsXG5cdFx0XHRnID0gMCxcblx0XHRcdGIgPSAwO1xuXG5cdFx0c3dpdGNoIChoaSkge1xuXHRcdFx0Y2FzZSAwOlxuXHRcdFx0XHRyID0gdmFsO1xuXHRcdFx0XHRnID0gdDtcblx0XHRcdFx0YiA9IHA7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAxOlxuXHRcdFx0XHRyID0gcTtcblx0XHRcdFx0ZyA9IHZhbDtcblx0XHRcdFx0YiA9IHA7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAyOlxuXHRcdFx0XHRyID0gcDtcblx0XHRcdFx0ZyA9IHZhbDtcblx0XHRcdFx0YiA9IHQ7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAzOlxuXHRcdFx0XHRyID0gcDtcblx0XHRcdFx0ZyA9IHE7XG5cdFx0XHRcdGIgPSB2YWw7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSA0OlxuXHRcdFx0XHRyID0gdDtcblx0XHRcdFx0ZyA9IHA7XG5cdFx0XHRcdGIgPSB2YWw7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSA1OlxuXHRcdFx0XHRyID0gdmFsO1xuXHRcdFx0XHRnID0gcDtcblx0XHRcdFx0YiA9IHE7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0YnJlYWs7XG5cdFx0fVxuXG5cdFx0ciA9IE1hdGgucm91bmQocik7XG5cdFx0ZyA9IE1hdGgucm91bmQoZyk7XG5cdFx0YiA9IE1hdGgucm91bmQoYik7XG5cblx0XHRyZXR1cm4gW3IsIGcsIGJdO1xuXG5cdH0sXG5cblx0UkdCMkhTVjogZnVuY3Rpb24gKHIsIGcsIGIpIHtcblx0XHR2YXIgaCA9IDAsXG5cdFx0XHRzID0gMCxcblx0XHRcdHYgPSAwO1xuXG5cdFx0ciA9IHIgLyAyNTUuMDtcblx0XHRnID0gZyAvIDI1NS4wO1xuXHRcdGIgPSBiIC8gMjU1LjA7XG5cblx0XHR2YXIgbWluUkdCID0gTWF0aC5taW4ociwgTWF0aC5taW4oZywgYikpLFxuXHRcdFx0bWF4UkdCID0gTWF0aC5tYXgociwgTWF0aC5tYXgoZywgYikpO1xuXG5cdFx0aWYgKG1pblJHQiA9PSBtYXhSR0IpIHtcblx0XHRcdHYgPSBtaW5SR0I7XG5cdFx0XHRyZXR1cm4gWzAsIDAsIE1hdGgucm91bmQodildO1xuXHRcdH1cblxuXHRcdHZhciBkZCA9IChyID09IG1pblJHQikgPyBnIC0gYiA6ICgoYiA9PSBtaW5SR0IpID8gciAtIGcgOiBiIC0gciksXG5cdFx0XHRoaCA9IChyID09IG1pblJHQikgPyAzIDogKChiID09IG1pblJHQikgPyAxIDogNSk7XG5cblx0XHRoID0gTWF0aC5yb3VuZCg2MCAqIChoaCAtIGRkIC8gKG1heFJHQiAtIG1pblJHQikpKTtcblx0XHRzID0gTWF0aC5yb3VuZCgobWF4UkdCIC0gbWluUkdCKSAvIG1heFJHQiAqIDEwMC4wKTtcblx0XHR2ID0gTWF0aC5yb3VuZChtYXhSR0IgKiAxMDAuMCk7XG5cblx0XHRyZXR1cm4gW2gsIHMsIHZdO1xuXHR9LFxuXG5cdFJHQjJIRVg6IGZ1bmN0aW9uIChyLCBnLCBiKSB7XG5cdFx0cmV0dXJuIFwiI1wiICsgKCgxIDw8IDI0KSArIChyIDw8IDE2KSArIChnIDw8IDgpICsgYikudG9TdHJpbmcoMTYpLnNsaWNlKDEpO1xuXHR9LFxuXG5cdFJHQmZ2MkhFWDogZnVuY3Rpb24gKHIsIGcsIGIpIHtcblx0XHRyZXR1cm4gQ29sb3JVdGlsLlJHQjJIRVgoTWF0aC5mbG9vcihyICogMjU1LjApLFxuXHRcdFx0TWF0aC5mbG9vcihnICogMjU1LjApLFxuXHRcdFx0TWF0aC5mbG9vcihiICogMjU1LjApKTtcblx0fSxcblxuXHRIU1YySEVYOiBmdW5jdGlvbiAoaCwgcywgdikge1xuXHRcdHZhciByZ2IgPSBDb250cm9sS2l0LkNvbG9yVXRpbC5IU1YyUkdCKGgsIHMsIHYpO1xuXHRcdHJldHVybiBDb250cm9sS2l0LkNvbG9yVXRpbC5SR0IySEVYKHJnYlswXSwgcmdiWzFdLCByZ2JbMl0pO1xuXHR9LFxuXG5cdEhFWDJSR0I6IGZ1bmN0aW9uIChoZXgpIHtcblx0XHR2YXIgc2hvcnRoYW5kUmVnZXggPSAvXiM/KFthLWZcXGRdKShbYS1mXFxkXSkoW2EtZlxcZF0pJC9pO1xuXHRcdGhleCA9IGhleC5yZXBsYWNlKHNob3J0aGFuZFJlZ2V4LCBmdW5jdGlvbiAobSwgciwgZywgYikge1xuXHRcdFx0cmV0dXJuIHIgKyByICsgZyArIGcgKyBiICsgYjtcblx0XHR9KTtcblxuXHRcdHZhciByZXN1bHQgPSAvXiM/KFthLWZcXGRdezJ9KShbYS1mXFxkXXsyfSkoW2EtZlxcZF17Mn0pJC9pLmV4ZWMoaGV4KTtcblx0XHRyZXR1cm4gcmVzdWx0ID8gW3BhcnNlSW50KHJlc3VsdFsxXSwgMTYpLCBwYXJzZUludChyZXN1bHRbMl0sIDE2KSwgcGFyc2VJbnQocmVzdWx0WzNdLCAxNildIDogbnVsbDtcblxuXHR9LFxuXG5cdGlzVmFsaWRIRVg6IGZ1bmN0aW9uIChoZXgpIHtcblx0XHRyZXR1cm4gL14jWzAtOUEtRl17Nn0kL2kudGVzdChoZXgpO1xuXHR9LFxuXG5cdGlzVmFsaWRSR0I6IGZ1bmN0aW9uIChyLCBnLCBiKSB7XG5cdFx0cmV0dXJuIHIgPj0gMCAmJiByIDw9IDI1NSAmJlxuXHRcdFx0ZyA+PSAwICYmIGcgPD0gMjU1ICYmXG5cdFx0XHRiID49IDAgJiYgYiA8PSAyNTU7XG5cdH0sXG5cblx0aXNWYWxpZFJHQmZ2OiBmdW5jdGlvbiAociwgZywgYikge1xuXHRcdHJldHVybiByID49IDAgJiYgciA8PSAxLjAgJiZcblx0XHRcdGcgPj0gMCAmJiBnIDw9IDEuMCAmJlxuXHRcdFx0YiA+PSAwICYmIGIgPD0gMS4wO1xuXHR9XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IENvbG9yVXRpbDsiLCJ2YXIgQ1NTID0ge1xuICAgIENvbnRyb2xLaXQ6ICdjb250cm9sS2l0JyxcblxuICAgIFBhbmVsOiAncGFuZWwnLFxuICAgIEhlYWQ6ICdoZWFkJyxcbiAgICBMYWJlbDogJ2xhYmVsJyxcbiAgICBNZW51OiAnbWVudScsXG4gICAgV3JhcDogJ3dyYXAnLFxuXG4gICAgQnV0dG9uTWVudUNsb3NlOiAnYnV0dG9uLW1lbnUtY2xvc2UnLFxuICAgIEJ1dHRvbk1lbnVIaWRlOiAnYnV0dG9uLW1lbnUtaGlkZScsXG4gICAgQnV0dG9uTWVudVNob3c6ICdidXR0b24tbWVudS1zaG93JyxcbiAgICBCdXR0b25NZW51VW5kbzogJ2J1dHRvbi1tZW51LXVuZG8nLFxuICAgIEJ1dHRvbk1lbnVMb2FkOiAnYnV0dG9uLW1lbnUtbG9hZCcsXG4gICAgQnV0dG9uTWVudVNhdmU6ICdidXR0b24tbWVudS1zYXZlJyxcbiAgICBNZW51QWN0aXZlOiAnbWVudS1hY3RpdmUnLFxuXG4gICAgQnV0dG9uOiAnYnV0dG9uJyxcbiAgICBCdXR0b25QcmVzZXQ6ICdidXR0b24tcHJlc2V0JyxcbiAgICBCdXR0b25QcmVzZXRBY3RpdmU6ICdidXR0b24tcHJlc2V0LWFjdGl2ZScsXG5cbiAgICBXcmFwSW5wdXRXUHJlc2V0OiAnaW5wdXQtd2l0aC1wcmVzZXQtd3JhcCcsXG4gICAgV3JhcENvbG9yV1ByZXNldDogJ2NvbG9yLXdpdGgtcHJlc2V0LXdyYXAnLFxuXG4gICAgSGVhZEluYWN0aXZlOiAnaGVhZC1pbmFjdGl2ZScsXG4gICAgUGFuZWxIZWFkSW5hY3RpdmU6ICdwYW5lbC1oZWFkLWluYWN0aXZlJyxcblxuICAgIEdyb3VwTGlzdDogJ2dyb3VwLWxpc3QnLFxuICAgIEdyb3VwOiAnZ3JvdXAnLFxuICAgIFN1Ykdyb3VwTGlzdDogJ3N1Yi1ncm91cC1saXN0JyxcbiAgICBTdWJHcm91cDogJ3N1Yi1ncm91cCcsXG5cblxuICAgIFRleHRBcmVhV3JhcDogJ3RleHRhcmVhLXdyYXAnLFxuXG4gICAgV3JhcFNsaWRlcjogJ3dyYXAtc2xpZGVyJyxcbiAgICBTbGlkZXJXcmFwOiAnc2xpZGVyLXdyYXAnLFxuICAgIFNsaWRlclNsb3Q6ICdzbGlkZXItc2xvdCcsXG4gICAgU2xpZGVySGFuZGxlOiAnc2xpZGVyLWhhbmRsZScsXG5cbiAgICBBcnJvd0JNaW46ICdhcnJvdy1iLW1pbicsXG4gICAgQXJyb3dCTWF4OiAnYXJyb3ctYi1tYXgnLFxuICAgIEFycm93QlN1Yk1pbjogJ2Fycm93LWItc3ViLW1pbicsXG4gICAgQXJyb3dCU3ViTWF4OiAnYXJyb3ctYi1zdWItbWF4JyxcbiAgICBBcnJvd1NNaW46ICdhcnJvdy1zLW1pbicsXG4gICAgQXJyb3dTTWF4OiAnYXJyb3ctcy1tYXgnLFxuXG4gICAgU2VsZWN0OiAnc2VsZWN0JyxcbiAgICBTZWxlY3RBY3RpdmU6ICdzZWxlY3QtYWN0aXZlJyxcblxuICAgIE9wdGlvbnM6ICdvcHRpb25zJyxcbiAgICBPcHRpb25zU2VsZWN0ZWQ6ICdsaS1zZWxlY3RlZCcsXG5cbiAgICBDYW52YXNMaXN0SXRlbTogJ2NhbnZhcy1saXN0LWl0ZW0nLFxuICAgIENhbnZhc1dyYXA6ICdjYW52YXMtd3JhcCcsXG5cbiAgICBTVkdMaXN0SXRlbTogJ3N2Zy1saXN0LWl0ZW0nLFxuICAgIFNWR1dyYXA6ICdzdmctd3JhcCcsXG5cbiAgICBHcmFwaFNsaWRlclhXcmFwOiAnZ3JhcGgtc2xpZGVyLXgtd3JhcCcsXG4gICAgR3JhcGhTbGlkZXJZV3JhcDogJ2dyYXBoLXNsaWRlci15LXdyYXAnLFxuICAgIEdyYXBoU2xpZGVyWDogJ2dyYXBoLXNsaWRlci14JyxcbiAgICBHcmFwaFNsaWRlclk6ICdncmFwaC1zbGlkZXIteScsXG4gICAgR3JhcGhTbGlkZXJYSGFuZGxlOiAnZ3JhcGgtc2xpZGVyLXgtaGFuZGxlJyxcbiAgICBHcmFwaFNsaWRlcllIYW5kbGU6ICdncmFwaC1zbGlkZXIteS1oYW5kbGUnLFxuXG4gICAgUGlja2VyOiAncGlja2VyJyxcbiAgICBQaWNrZXJGaWVsZFdyYXA6ICdmaWVsZC13cmFwJyxcbiAgICBQaWNrZXJJbnB1dFdyYXA6ICdpbnB1dC13cmFwJyxcbiAgICBQaWNrZXJJbnB1dEZpZWxkOiAnaW5wdXQtZmllbGQnLFxuICAgIFBpY2tlckNvbnRyb2xzV3JhcDogJ2NvbnRyb2xzLXdyYXAnLFxuICAgIFBpY2tlckNvbG9yQ29udHJhc3Q6ICdjb2xvci1jb250cmFzdCcsXG4gICAgUGlja2VySGFuZGxlRmllbGQ6ICdpbmRpY2F0b3InLFxuICAgIFBpY2tlckhhbmRsZVNsaWRlcjogJ2luZGljYXRvcicsXG5cbiAgICBDb2xvcjogJ2NvbG9yJyxcblxuICAgIFNjcm9sbEJhcjogJ3Njcm9sbEJhcicsXG4gICAgU2Nyb2xsV3JhcDogJ3Njcm9sbC13cmFwJyxcbiAgICBTY3JvbGxCYXJCdG5VcDogJ2J0blVwJyxcbiAgICBTY3JvbGxCYXJCdG5Eb3duOiAnYnRuRG93bicsXG4gICAgU2Nyb2xsQmFyVHJhY2s6ICd0cmFjaycsXG4gICAgU2Nyb2xsQmFyVGh1bWI6ICd0aHVtYicsXG4gICAgU2Nyb2xsQnVmZmVyOiAnc2Nyb2xsLWJ1ZmZlcicsXG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IENTUztcbiIsInZhciBEb2N1bWVudEV2ZW50ID0ge1xuICAgIE1PVVNFX01PVkU6ICdtb3VzZW1vdmUnLFxuICAgIE1PVVNFX1VQOiAnbW91c2V1cCcsXG4gICAgTU9VU0VfRE9XTjogJ21vdXNlZG93bicsXG4gICAgTU9VU0VfV0hFRUw6ICdtb3VzZXdoZWVsJyxcbiAgICBXSU5ET1dfUkVTSVpFOiAncmVzaXplJ1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBEb2N1bWVudEV2ZW50OyIsInZhciBFdmVudERpc3BhdGNoZXIgPSByZXF1aXJlKCcuLi9ldmVudC9FdmVudERpc3BhdGNoZXInKSxcbiAgICBFdmVudF8gPSByZXF1aXJlKCcuLi9ldmVudC9FdmVudCcpLFxuICAgIERvY3VtZW50RXZlbnQgPSByZXF1aXJlKCcuL0RvY3VtZW50RXZlbnQnKTtcbnZhciBpbnN0YW5jZSA9IG51bGw7XG5cbmZ1bmN0aW9uIE1vdXNlKCkge1xuICAgIEV2ZW50RGlzcGF0Y2hlci5hcHBseSh0aGlzKTtcbiAgICB0aGlzLl9wb3MgPSBbMCwwXTtcbiAgICB0aGlzLl93aGVlbERpcmVjdGlvbiA9IDA7XG4gICAgdGhpcy5faG92ZXJFbGVtZW50ID0gbnVsbDtcblxuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICB0aGlzLl9vbkRvY3VtZW50TW91c2VNb3ZlID0gZnVuY3Rpb24oZSl7XG4gICAgICAgIHZhciBkeCA9IDAsXG4gICAgICAgICAgICBkeSA9IDA7XG5cbiAgICAgICAgaWYgKCFlKWUgPSB3aW5kb3cuZXZlbnQ7XG4gICAgICAgIGlmIChlLnBhZ2VYKSB7XG4gICAgICAgICAgICBkeCA9IGUucGFnZVg7XG4gICAgICAgICAgICBkeSA9IGUucGFnZVk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoZS5jbGllbnRYKSB7XG4gICAgICAgICAgICBkeCA9IGUuY2xpZW50WCArIGRvY3VtZW50LmJvZHkuc2Nyb2xsTGVmdCArIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxMZWZ0O1xuICAgICAgICAgICAgZHkgPSBlLmNsaWVudFkgKyBkb2N1bWVudC5ib2R5LnNjcm9sbFRvcCArIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxUb3A7XG4gICAgICAgIH1cbiAgICAgICAgc2VsZi5fcG9zWzBdID0gZHg7XG4gICAgICAgIHNlbGYuX3Bvc1sxXSA9IGR5O1xuXG4gICAgICAgIHNlbGYuX2hvdmVyRWxlbWVudCA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQoZHgsZHkpO1xuICAgIH07XG5cbiAgICB0aGlzLl9vbkRvY3VtZW50TW91c2VXaGVlbCA9IGZ1bmN0aW9uKGV2ZW50KXtcbiAgICAgICAgc2VsZi5fd2hlZWxEaXJlY3Rpb24gPSAoZXZlbnQuZGV0YWlsIDwgMCkgPyAxIDogKGV2ZW50LndoZWVsRGVsdGEgPiAwKSA/IDEgOiAtMTtcbiAgICAgICAgc2VsZi5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8oc2VsZixEb2N1bWVudEV2ZW50Lk1PVVNFX1dIRUVMLGV2ZW50KSk7XG4gICAgfTtcblxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoRG9jdW1lbnRFdmVudC5NT1VTRV9NT1ZFLCB0aGlzLl9vbkRvY3VtZW50TW91c2VNb3ZlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKERvY3VtZW50RXZlbnQuTU9VU0VfV0hFRUwsdGhpcy5fb25Eb2N1bWVudE1vdXNlV2hlZWwpO1xufVxuTW91c2UucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFdmVudERpc3BhdGNoZXIucHJvdG90eXBlKTtcbk1vdXNlLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IE1vdXNlO1xuXG5Nb3VzZS5wcm90b3R5cGUuX3JlbW92ZURvY3VtZW50TGlzdGVuZXIgPSBmdW5jdGlvbigpe1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoRG9jdW1lbnRFdmVudC5NT1VTRV9NT1ZFLCB0aGlzLl9vbkRvY3VtZW50TW91c2VNb3ZlKTtcbiAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKERvY3VtZW50RXZlbnQuTU9VU0VfV0hFRUwsdGhpcy5fb25Eb2N1bWVudE1vdXNlV2hlZWwpO1xufTtcblxuTW91c2UucHJvdG90eXBlLmdldFBvc2l0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9wb3M7XG59O1xuXG5Nb3VzZS5wcm90b3R5cGUuZ2V0WCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fcG9zWzBdO1xufTtcblxuTW91c2UucHJvdG90eXBlLmdldFkgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3Bvc1sxXTtcbn07XG5cbk1vdXNlLnByb3RvdHlwZS5nZXRXaGVlbERpcmVjdGlvbiA9IGZ1bmN0aW9uKCl7XG4gICAgcmV0dXJuIHRoaXMuX3doZWVsRGlyZWN0aW9uO1xufTtcblxuTW91c2UucHJvdG90eXBlLmdldEhvdmVyRWxlbWVudCA9IGZ1bmN0aW9uKCl7XG4gICAgcmV0dXJuIHRoaXMuX2hvdmVyRWxlbWVudDtcbn07XG5cbk1vdXNlLnNldHVwID0gZnVuY3Rpb24gKCkge1xuICAgIGluc3RhbmNlID0gaW5zdGFuY2UgfHwgbmV3IE1vdXNlKCk7XG4gICAgcmV0dXJuIGluc3RhbmNlO1xufTtcblxuTW91c2UuZ2V0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBpbnN0YW5jZTtcbn07XG5cbk1vdXNlLmRlc3Ryb3kgPSBmdW5jdGlvbigpe1xuICAgIGluc3RhbmNlLl9yZW1vdmVEb2N1bWVudExpc3RlbmVyKCk7XG4gICAgaW5zdGFuY2UgPSBudWxsO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBNb3VzZTsiLCJmdW5jdGlvbiBOb2RlKCkge1xuICAgIHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuXG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKXtcbiAgICAgICAgY2FzZSAxIDpcbiAgICAgICAgICAgIHZhciBhcmcgPSBhcmd1bWVudHNbMF07XG4gICAgICAgICAgICBpZiAoYXJnICE9IE5vZGUuSU5QVVRfVEVYVCAmJlxuICAgICAgICAgICAgICAgIGFyZyAhPSBOb2RlLklOUFVUX0JVVFRPTiAmJlxuICAgICAgICAgICAgICAgIGFyZyAhPSBOb2RlLklOUFVUX1NFTEVDVCAmJlxuICAgICAgICAgICAgICAgIGFyZyAhPSBOb2RlLklOUFVUX0NIRUNLQk9YKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoYXJnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX2VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbnB1dCcpO1xuICAgICAgICAgICAgICAgIHRoaXMuX2VsZW1lbnQudHlwZSA9IGFyZztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG59XG5cbk5vZGUuRElWICAgICAgICAgICAgPSAnZGl2Jztcbk5vZGUuSU5QVVRfVEVYVCAgICAgPSAndGV4dCc7XG5Ob2RlLklOUFVUX0JVVFRPTiAgID0gJ2J1dHRvbic7XG5Ob2RlLklOUFVUX1NFTEVDVCAgID0gJ3NlbGVjdCc7XG5Ob2RlLklOUFVUX0NIRUNLQk9YID0gJ2NoZWNrYm94Jztcbk5vZGUuT1BUSU9OICAgICAgICAgPSAnb3B0aW9uJztcbk5vZGUuTElTVCAgICAgICAgICAgPSAndWwnO1xuTm9kZS5MSVNUX0lURU0gICAgICA9ICdsaSc7XG5Ob2RlLlNQQU4gICAgICAgICAgID0gJ3NwYW4nO1xuTm9kZS5URVhUQVJFQSAgICAgICA9ICd0ZXh0YXJlYSc7XG5cbk5vZGUucHJvdG90eXBlID0ge1xuICAgIGFkZENoaWxkOiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICB0aGlzLl9lbGVtZW50LmFwcGVuZENoaWxkKG5vZGUuZ2V0RWxlbWVudCgpKTtcbiAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgfSxcbiAgICBhZGRDaGlsZHJlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaSA9IC0xLCBsID0gYXJndW1lbnRzLmxlbmd0aCwgZSA9IHRoaXMuX2VsZW1lbnQ7XG4gICAgICAgIHdoaWxlICgrK2kgPCBsKSB7XG4gICAgICAgICAgICBlLmFwcGVuZENoaWxkKGFyZ3VtZW50c1tpXS5nZXRFbGVtZW50KCkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG4gICAgYWRkQ2hpbGRBdDogZnVuY3Rpb24gKG5vZGUsIGluZGV4KSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuaW5zZXJ0QmVmb3JlKG5vZGUuZ2V0RWxlbWVudCgpLCB0aGlzLl9lbGVtZW50LmNoaWxkcmVuW2luZGV4XSk7XG4gICAgICAgIHJldHVybiBub2RlO1xuICAgIH0sXG4gICAgcmVtb3ZlQ2hpbGQ6IGZ1bmN0aW9uIChub2RlKSB7XG4gICAgICAgIGlmICghdGhpcy5jb250YWlucyhub2RlKSlyZXR1cm4gbnVsbDtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5yZW1vdmVDaGlsZChub2RlLmdldEVsZW1lbnQoKSk7XG4gICAgICAgIHJldHVybiBub2RlO1xuICAgIH0sXG4gICAgcmVtb3ZlQ2hpbGRyZW46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGkgPSAtMSwgbCA9IGFyZ3VtZW50cy5sZW5ndGgsIGUgPSB0aGlzLl9lbGVtZW50O1xuICAgICAgICB3aGlsZSAoKytpIDwgbCkge1xuICAgICAgICAgICAgZS5yZW1vdmVDaGlsZChhcmd1bWVudHNbaV0uZ2V0RWxlbWVudCgpKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuICAgIHJlbW92ZUNoaWxkQXQ6IGZ1bmN0aW9uIChub2RlLCBpbmRleCkge1xuICAgICAgICBpZiAoIXRoaXMuY29udGFpbnMobm9kZSkpcmV0dXJuIG51bGw7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQucmVtb3ZlQ2hpbGQobm9kZS5nZXRFbGVtZW50KCkpO1xuICAgICAgICByZXR1cm4gbm9kZTtcbiAgICB9LFxuICAgIHJlbW92ZUFsbENoaWxkcmVuOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5fZWxlbWVudDtcbiAgICAgICAgd2hpbGUgKGVsZW1lbnQuaGFzQ2hpbGROb2RlcygpKWVsZW1lbnQucmVtb3ZlQ2hpbGQoZWxlbWVudC5sYXN0Q2hpbGQpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuICAgIHNldFdpZHRoOiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZS53aWR0aCA9IHZhbHVlICsgJ3B4JztcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICBnZXRXaWR0aDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICB9LFxuICAgIHNldEhlaWdodDogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gdmFsdWUgKyAncHgnO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuICAgIGdldEhlaWdodDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZWxlbWVudC5vZmZzZXRIZWlnaHQ7XG4gICAgfSxcbiAgICBzZXRQb3NpdGlvbjogZnVuY3Rpb24gKHgsIHkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0UG9zaXRpb24oeCkuc2V0UG9zaXRpb24oeSk7XG4gICAgfSxcbiAgICBzZXRQb3NpdGlvblg6IGZ1bmN0aW9uICh4KSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGUubWFyZ2luTGVmdCA9IHggKyAncHgnO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuICAgIHNldFBvc2l0aW9uWTogZnVuY3Rpb24gKHkpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZS5tYXJnaW5Ub3AgPSB5ICsgJ3B4JztcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICBzZXRQb3NpdGlvbkdsb2JhbDogZnVuY3Rpb24gKHgsIHkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0UG9zaXRpb25HbG9iYWxYKHgpLnNldFBvc2l0aW9uR2xvYmFsWSh5KTtcbiAgICB9LFxuICAgIHNldFBvc2l0aW9uR2xvYmFsWDogZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZS5sZWZ0ID0geCArICdweCc7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG4gICAgc2V0UG9zaXRpb25HbG9iYWxZOiBmdW5jdGlvbiAoeSkge1xuICAgICAgICB0aGlzLl9lbGVtZW50LnN0eWxlLnRvcCA9IHkgKyAncHgnO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuICAgIGdldFBvc2l0aW9uOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBbdGhpcy5nZXRQb3NpdGlvblgoKSwgdGhpcy5nZXRQb3NpdGlvblkoKV07XG4gICAgfSxcbiAgICBnZXRQb3NpdGlvblg6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VsZW1lbnQub2Zmc2V0TGVmdDtcbiAgICB9LFxuICAgIGdldFBvc2l0aW9uWTogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZWxlbWVudC5vZmZzZXRUb3A7XG4gICAgfSxcbiAgICBnZXRQb3NpdGlvbkdsb2JhbDogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgb2Zmc2V0ID0gWzAsIDBdLFxuICAgICAgICAgICAgZWxlbWVudCA9IHRoaXMuX2VsZW1lbnQ7XG5cbiAgICAgICAgd2hpbGUgKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIG9mZnNldFswXSArPSBlbGVtZW50Lm9mZnNldExlZnQ7XG4gICAgICAgICAgICBvZmZzZXRbMV0gKz0gZWxlbWVudC5vZmZzZXRUb3A7XG4gICAgICAgICAgICBlbGVtZW50ID0gZWxlbWVudC5vZmZzZXRQYXJlbnQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH0sXG4gICAgZ2V0UG9zaXRpb25HbG9iYWxYOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvZmZzZXQgPSAwLFxuICAgICAgICAgICAgZWxlbWVudCA9IHRoaXMuX2VsZW1lbnQ7XG5cbiAgICAgICAgd2hpbGUgKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIG9mZnNldCArPSBlbGVtZW50Lm9mZnNldExlZnQ7XG4gICAgICAgICAgICBlbGVtZW50ID0gZWxlbWVudC5vZmZzZXRQYXJlbnQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gb2Zmc2V0O1xuICAgIH0sXG4gICAgZ2V0UG9zaXRpb25HbG9iYWxZOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvZmZzZXQgPSAwLFxuICAgICAgICAgICAgZWxlbWVudCA9IHRoaXMuX2VsZW1lbnQ7XG5cbiAgICAgICAgd2hpbGUgKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIG9mZnNldCArPSBlbGVtZW50Lm9mZnNldFRvcDtcbiAgICAgICAgICAgIGVsZW1lbnQgPSBlbGVtZW50Lm9mZnNldFBhcmVudDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvZmZzZXQ7XG4gICAgfSxcbiAgICBhZGRFdmVudExpc3RlbmVyOiBmdW5jdGlvbiAodHlwZSwgbGlzdGVuZXIsIHVzZUNhcHR1cmUpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyLCB1c2VDYXB0dXJlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICByZW1vdmVFdmVudExpc3RlbmVyOiBmdW5jdGlvbiAodHlwZSwgbGlzdGVuZXIsIHVzZUNhcHR1cmUpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyLCB1c2VDYXB0dXJlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICBkaXNwYXRjaEV2ZW50IDogZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICBzZXRTdHlsZUNsYXNzOiBmdW5jdGlvbiAoc3R5bGUpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5jbGFzc05hbWUgPSBzdHlsZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICBzZXRTdHlsZVByb3BlcnR5OiBmdW5jdGlvbiAocHJvcGVydHksIHZhbHVlKSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGVbcHJvcGVydHldID0gdmFsdWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG4gICAgZ2V0U3R5bGVQcm9wZXJ0eTogZnVuY3Rpb24gKHByb3BlcnR5KSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbGVtZW50LnN0eWxlW3Byb3BlcnR5XTtcbiAgICB9LFxuICAgIHNldFN0eWxlUHJvcGVydGllczogZnVuY3Rpb24gKHByb3BlcnRpZXMpIHtcbiAgICAgICAgZm9yICh2YXIgcCBpbiBwcm9wZXJ0aWVzKXtcbiAgICAgICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGVbcF0gPSBwcm9wZXJ0aWVzW3BdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG4gICAgZGVsZXRlU3R5bGVDbGFzczogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9lbGVtZW50LmNsYXNzTmFtZSA9ICcnO1xuICAgICAgICByZXR1cm4gdGhpc1xuICAgIH0sXG4gICAgZGVsZXRlU3R5bGVQcm9wZXJ0eTogZnVuY3Rpb24gKHByb3BlcnR5KSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGVbcHJvcGVydHldID0gJyc7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG4gICAgZGVsZXRlU3R5bGVQcm9wZXJ0aWVzOiBmdW5jdGlvbiAocHJvcGVydGllcykge1xuICAgICAgICBmb3IgKHZhciBwIGluIHByb3BlcnRpZXMpe1xuICAgICAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZVtwXSA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG4gICAgZ2V0Q2hpbGRBdDogZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICAgIHJldHVybiBuZXcgTm9kZSgpLnNldEVsZW1lbnQodGhpcy5fZWxlbWVudC5jaGlsZHJlbltpbmRleF0pO1xuICAgIH0sXG4gICAgZ2V0Q2hpbGRJbmRleDogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2luZGV4T2YodGhpcy5fZWxlbWVudCwgbm9kZS5nZXRFbGVtZW50KCkpO1xuICAgIH0sXG4gICAgZ2V0TnVtQ2hpbGRyZW46IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VsZW1lbnQuY2hpbGRyZW4ubGVuZ3RoO1xuICAgIH0sXG4gICAgZ2V0Rmlyc3RDaGlsZDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gbmV3IE5vZGUoKS5zZXRFbGVtZW50KHRoaXMuX2VsZW1lbnQuZmlyc3RDaGlsZCk7XG4gICAgfSxcbiAgICBnZXRMYXN0Q2hpbGQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBOb2RlKCkuc2V0RWxlbWVudCh0aGlzLl9lbGVtZW50Lmxhc3RDaGlsZCk7XG4gICAgfSxcbiAgICBoYXNDaGlsZHJlbjogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZWxlbWVudC5jaGlsZHJlbi5sZW5ndGggIT0gMDtcbiAgICB9LFxuICAgIGNvbnRhaW5zOiBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5faW5kZXhPZih0aGlzLl9lbGVtZW50LCBub2RlLmdldEVsZW1lbnQoKSkgIT0gLTE7XG4gICAgfSxcbiAgICBfaW5kZXhPZjogZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQsIGVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5pbmRleE9mLmNhbGwocGFyZW50RWxlbWVudC5jaGlsZHJlbiwgZWxlbWVudCk7XG4gICAgfSxcbiAgICBzZXRQcm9wZXJ0eTogZnVuY3Rpb24gKHByb3BlcnR5LCB2YWx1ZSkge1xuICAgICAgICB0aGlzLl9lbGVtZW50W3Byb3BlcnR5XSA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuICAgIHNldFByb3BlcnRpZXM6IGZ1bmN0aW9uIChwcm9wZXJ0aWVzKSB7XG4gICAgICAgIGZvciAodmFyIHAgaW4gcHJvcGVydGllcyl7XG4gICAgICAgICAgICB0aGlzLl9lbGVtZW50W3BdID0gcHJvcGVydGllc1twXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuICAgIGdldFByb3BlcnR5OiBmdW5jdGlvbiAocHJvcGVydHkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2VsZW1lbnRbcHJvcGVydHldO1xuICAgIH0sXG4gICAgc2V0RWxlbWVudDogZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG4gICAgZ2V0RWxlbWVudDogZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fZWxlbWVudDtcbiAgICB9LFxuICAgIGdldFN0eWxlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9lbGVtZW50LnN0eWxlO1xuICAgIH0sXG4gICAgZ2V0UGFyZW50OiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBuZXcgTm9kZSgpLnNldEVsZW1lbnQodGhpcy5fZWxlbWVudC5wYXJlbnROb2RlKTtcbiAgICB9XG59O1xuXG5Ob2RlLmdldE5vZGVCeUVsZW1lbnQgPSBmdW5jdGlvbiAoZWxlbWVudCkge1xuICAgIHJldHVybiBuZXcgTm9kZSgpLnNldEVsZW1lbnQoZWxlbWVudCk7XG59O1xuTm9kZS5nZXROb2RlQnlJZCA9IGZ1bmN0aW9uIChpZCkge1xuICAgIHJldHVybiBuZXcgTm9kZSgpLnNldEVsZW1lbnQoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaWQpKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gTm9kZTsiLCJ2YXIgTm9kZUV2ZW50ID0ge1xuICAgIE1PVVNFX0RPV04gICA6ICdtb3VzZWRvd24nLFxuICAgIE1PVVNFX1VQICAgICA6ICdtb3VzZXVwJyxcbiAgICBNT1VTRV9PVkVSICAgOiAnbW91c2VvdmVyJyxcbiAgICBNT1VTRV9NT1ZFICAgOiAnbW91c2Vtb3ZlJyxcbiAgICBNT1VTRV9PVVQgICAgOiAnbW91c2VvdXQnLFxuICAgIEtFWV9ET1dOICAgICA6ICdrZXlkb3duJyxcbiAgICBLRVlfVVAgICAgICAgOiAna2V5dXAnLFxuICAgIENIQU5HRSAgICAgICA6ICdjaGFuZ2UnLFxuICAgIEZJTklTSCAgICAgICA6ICdmaW5pc2gnLFxuICAgIERCTF9DTElDSyAgICA6ICdkYmxjbGljaycsXG4gICAgT05fQ0xJQ0sgICAgIDogJ2NsaWNrJyxcbiAgICBTRUxFQ1RfU1RBUlQgOiAnc2VsZWN0c3RhcnQnLFxuICAgIERSQUdfU1RBUlQgICA6ICdkcmFnc3RhcnQnLFxuICAgIERSQUcgICAgICAgICA6ICdkcmFnJyxcbiAgICBEUkFHX0VORCAgICAgOiAnZHJhZ2VuZCcsXG5cbiAgICBEUkFHX0VOVEVSICAgOiAnZHJhZ2VudGVyJyxcbiAgICBEUkFHX09WRVIgICAgOiAnZHJhZ292ZXInLFxuICAgIERSQUdfTEVBVkUgICA6ICdkcmFnbGVhdmUnLFxuXG4gICAgUkVTSVpFICAgICAgIDogJ3Jlc2l6ZSdcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gTm9kZUV2ZW50OyIsInZhciBTdHlsZSA9IHsgXG5cdHN0cmluZyA6IFwiI2NvbnRyb2xLaXR7cG9zaXRpb246YWJzb2x1dGU7dG9wOjA7bGVmdDowO3dpZHRoOjEwMCU7aGVpZ2h0OjEwMCU7LXdlYmtpdC10b3VjaC1jYWxsb3V0Om5vbmU7LXdlYmtpdC11c2VyLXNlbGVjdDpub25lOy1raHRtbC11c2VyLXNlbGVjdDpub25lOy1tb3otdXNlci1zZWxlY3Q6bm9uZTstbXMtdXNlci1zZWxlY3Q6bm9uZTt1c2VyLXNlbGVjdDpub25lO3BvaW50ZXItZXZlbnRzOm5vbmV9I2NvbnRyb2xLaXQgLnBhbmVsey13ZWJraXQtYm94LXNpemluZzpib3JkZXItYm94Oy1tb3otYm94LXNpemluZzpib3JkZXItYm94O2JveC1zaXppbmc6Ym9yZGVyLWJveDtwb2ludGVyLWV2ZW50czphdXRvO3Bvc2l0aW9uOnJlbGF0aXZlO3otaW5kZXg6MTstd2Via2l0LXRvdWNoLWNhbGxvdXQ6bm9uZTstd2Via2l0LXVzZXItc2VsZWN0Om5vbmU7LWtodG1sLXVzZXItc2VsZWN0Om5vbmU7LW1vei11c2VyLXNlbGVjdDpub25lOy1tcy11c2VyLXNlbGVjdDpub25lO3VzZXItc2VsZWN0Om5vbmU7b3ZlcmZsb3c6aGlkZGVuO29wYWNpdHk6MTtmbG9hdDpsZWZ0O3dpZHRoOjIwMHB4O2JvcmRlci1yYWRpdXM6M3B4Oy1tb3otYm9yZGVyLXJhZGl1czozcHg7Ym94LXNoYWRvdzowIDJweCAycHggcmdiYSgwLDAsMCwuMjUpO21hcmdpbjowO3BhZGRpbmc6MDtiYWNrZ3JvdW5kLWNvbG9yOiMxYTFhMWE7Zm9udC1mYW1pbHk6QXJpYWwsc2Fucy1zZXJpZn0jY29udHJvbEtpdCAucGFuZWwgLndyYXB7d2lkdGg6YXV0bztoZWlnaHQ6YXV0bzttYXJnaW46MDtwYWRkaW5nOjA7cG9zaXRpb246cmVsYXRpdmU7b3ZlcmZsb3c6aGlkZGVufSNjb250cm9sS2l0IC5wYW5lbCB1bHttYXJnaW46MDtwYWRkaW5nOjA7bGlzdC1zdHlsZTpub25lfSNjb250cm9sS2l0IC5wYW5lbCAuY29sb3IsI2NvbnRyb2xLaXQgLnBhbmVsIGlucHV0W3R5cGU9dGV4dF0sI2NvbnRyb2xLaXQgLnBhbmVsIHRleHRhcmVhLCNjb250cm9sS2l0IC5waWNrZXIgaW5wdXRbdHlwZT10ZXh0XXstd2Via2l0LWJveC1zaXppbmc6Ym9yZGVyLWJveDstbW96LWJveC1zaXppbmc6Ym9yZGVyLWJveDtib3gtc2l6aW5nOmJvcmRlci1ib3g7d2lkdGg6MTAwJTtoZWlnaHQ6MjVweDtwYWRkaW5nOjAgMCAwIDhweDtmb250LWZhbWlseTpBcmlhbCxzYW5zLXNlcmlmO2ZvbnQtc2l6ZToxMXB4O2NvbG9yOiNmZmY7dGV4dC1zaGFkb3c6MXB4IDFweCAjMDAwO291dGxpbmU6MDtiYWNrZ3JvdW5kOiMyMjI3Mjk7YmFja2dyb3VuZC1pbWFnZTotby1saW5lYXItZ3JhZGllbnQocmdiYSgwLDAsMCwuMDc1KSAwLHJnYmEoMCwwLDAsLjEyNSkgMTAwJSk7YmFja2dyb3VuZC1pbWFnZTpsaW5lYXItZ3JhZGllbnQocmdiYSgwLDAsMCwuMDc1KSAwLHJnYmEoMCwwLDAsLjEyNSkgMTAwJSk7Ym9yZGVyOm5vbmU7Ym94LXNoYWRvdzowIDAgMCAxcHggIzFmMWYxZiBpbnNldDtib3JkZXItcmFkaXVzOjJweDstbW96LWJvcmRlci1yYWRpdXM6MnB4fSNjb250cm9sS2l0IC5wYW5lbCAuYnV0dG9uLCNjb250cm9sS2l0IC5wYW5lbCAuc2VsZWN0LCNjb250cm9sS2l0IC5wYW5lbCAuc2VsZWN0LWFjdGl2ZSwjY29udHJvbEtpdCAucGlja2VyIC5idXR0b257LXdlYmtpdC1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW1vei1ib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym94LXNpemluZzpib3JkZXItYm94O2N1cnNvcjpwb2ludGVyO3dpZHRoOjEwMCU7aGVpZ2h0OjI2cHg7bWFyZ2luOjA7YmFja2dyb3VuZC1pbWFnZTotby1saW5lYXItZ3JhZGllbnQoIzQwNDA0MCAwLCMzYjNiM2IgMTAwJSk7YmFja2dyb3VuZC1pbWFnZTpsaW5lYXItZ3JhZGllbnQoIzQwNDA0MCAwLCMzYjNiM2IgMTAwJSk7Ym9yZGVyOm5vbmU7b3V0bGluZTowO2JvcmRlci1yYWRpdXM6MnB4O2JveC1zaGFkb3c6MCAwIDAgMXB4ICMxZjFmMWYgaW5zZXQsLTFweCAycHggMCAwICM0YTRhNGEgaW5zZXQ7Zm9udC1mYW1pbHk6QXJpYWwsc2Fucy1zZXJpZjtjb2xvcjojZmZmfSNjb250cm9sS2l0IC5wYW5lbCB0ZXh0YXJlYXtwYWRkaW5nOjVweCA4cHggMnB4O292ZXJmbG93OmhpZGRlbjtyZXNpemU6bm9uZTt2ZXJ0aWNhbC1hbGlnbjp0b3A7d2hpdGUtc3BhY2U6bm93cmFwfSNjb250cm9sS2l0IC5wYW5lbCAudGV4dGFyZWEtd3JhcHstd2Via2l0LWJveC1zaXppbmc6Ym9yZGVyLWJveDstbW96LWJveC1zaXppbmc6Ym9yZGVyLWJveDtib3gtc2l6aW5nOmJvcmRlci1ib3g7d2lkdGg6MTAwJTtwYWRkaW5nOjA7ZmxvYXQ6bGVmdDtoZWlnaHQ6MTAwJTtvdmVyZmxvdzpoaWRkZW47Ym9yZGVyOm5vbmU7Ym9yZGVyLXJhZGl1czoycHg7LW1vei1ib3JkZXItcmFkaXVzOjJweDtiYWNrZ3JvdW5kLWNvbG9yOiMyMjI3Mjk7Ym94LXNoYWRvdzowIDAgMXB4IDJweCByZ2JhKDAsMCwwLC4wMTI1KSBpbnNldCwwIDAgMXB4IDFweCAjMTExMzE0IGluc2V0O2JhY2tncm91bmQtaW1hZ2U6LW8tbGluZWFyLWdyYWRpZW50KHJnYmEoMCwwLDAsLjA3NSkgMCxyZ2JhKDAsMCwwLC4xMjUpIDEwMCUpO2JhY2tncm91bmQtaW1hZ2U6bGluZWFyLWdyYWRpZW50KHJnYmEoMCwwLDAsLjA3NSkgMCxyZ2JhKDAsMCwwLC4xMjUpIDEwMCUpfSNjb250cm9sS2l0IC5wYW5lbCAudGV4dGFyZWEtd3JhcCB0ZXh0YXJlYXtib3JkZXI6bm9uZTtib3JkZXItcmFkaXVzOjJweDstbW96LWJvcmRlci1yYWRpdXM6MnB4O2JveC1zaGFkb3c6bm9uZTtiYWNrZ3JvdW5kOjAgMH0jY29udHJvbEtpdCAucGFuZWwgLnRleHRhcmVhLXdyYXAgLnNjcm9sbEJhcntib3JkZXI6MXB4IHNvbGlkICMxMDEyMTM7Ym9yZGVyLWJvdHRvbS1yaWdodC1yYWRpdXM6MnB4O2JvcmRlci10b3AtcmlnaHQtcmFkaXVzOjJweDtib3JkZXItbGVmdDpub25lO2JveC1zaGFkb3c6MCAwIDFweCAycHggcmdiYSgwLDAsMCwuMDEyNSkgaW5zZXQsMCAwIDFweCAxcHggIzExMTMxNCBpbnNldH0jY29udHJvbEtpdCAucGFuZWwgY2FudmFze2N1cnNvcjpwb2ludGVyO3ZlcnRpY2FsLWFsaWduOmJvdHRvbTtib3JkZXI6bm9uZTtib3gtc2hhZG93OjAgMCAwIDFweCAjMWYxZjFmIGluc2V0O2JvcmRlci1yYWRpdXM6MnB4Oy1tb3otYm9yZGVyLXJhZGl1czoycHh9I2NvbnRyb2xLaXQgLnBhbmVsIC5jYW52YXMtd3JhcCwjY29udHJvbEtpdCAucGFuZWwgLnN2Zy13cmFwe21hcmdpbjo2cHggMCAwO3Bvc2l0aW9uOnJlbGF0aXZlO3dpZHRoOjcwJTtmbG9hdDpyaWdodDstd2Via2l0LWJveC1zaXppbmc6Ym9yZGVyLWJveDstbW96LWJveC1zaXppbmc6Ym9yZGVyLWJveDtib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym9yZGVyOm5vbmU7Ym9yZGVyLXJhZGl1czoycHg7LW1vei1ib3JkZXItcmFkaXVzOjJweDtiYWNrZ3JvdW5kOiMxZTIyMjQ7YmFja2dyb3VuZC1pbWFnZTotby1saW5lYXItZ3JhZGllbnQodHJhbnNwYXJlbnQgMCxyZ2JhKDAsMCwwLC4wNSkgMTAwJSk7YmFja2dyb3VuZC1pbWFnZTpsaW5lYXItZ3JhZGllbnQodHJhbnNwYXJlbnQgMCxyZ2JhKDAsMCwwLC4wNSkgMTAwJSl9I2NvbnRyb2xLaXQgLnBhbmVsIC5jYW52YXMtd3JhcCBzdmcsI2NvbnRyb2xLaXQgLnBhbmVsIC5zdmctd3JhcCBzdmd7cG9zaXRpb246YWJzb2x1dGU7bGVmdDowO3RvcDowO2N1cnNvcjpwb2ludGVyO3ZlcnRpY2FsLWFsaWduOmJvdHRvbTtib3JkZXI6bm9uZTtib3gtc2hhZG93OjAgMCAwIDFweCAjMWYxZjFmIGluc2V0O2JvcmRlci1yYWRpdXM6MnB4Oy1tb3otYm9yZGVyLXJhZGl1czoycHh9I2NvbnRyb2xLaXQgLnBhbmVsIC5idXR0b24sI2NvbnRyb2xLaXQgLnBpY2tlciAuYnV0dG9ue2ZvbnQtc2l6ZToxMHB4O2ZvbnQtd2VpZ2h0OjcwMDt0ZXh0LXNoYWRvdzowIDFweCAjMDAwO3RleHQtdHJhbnNmb3JtOnVwcGVyY2FzZX0jY29udHJvbEtpdCAucGFuZWwgLmJ1dHRvbjpob3ZlciwjY29udHJvbEtpdCAucGlja2VyIC5idXR0b246aG92ZXJ7YmFja2dyb3VuZC1pbWFnZTotby1saW5lYXItZ3JhZGllbnQoIzQ1NDU0NSAwLCMzYjNiM2IgMTAwJSk7YmFja2dyb3VuZC1pbWFnZTpsaW5lYXItZ3JhZGllbnQoIzQ1NDU0NSAwLCMzYjNiM2IgMTAwJSl9I2NvbnRyb2xLaXQgLnBhbmVsIC5idXR0b246YWN0aXZlLCNjb250cm9sS2l0IC5waWNrZXIgLmJ1dHRvbjphY3RpdmV7YmFja2dyb3VuZC1pbWFnZTotby1saW5lYXItZ3JhZGllbnQoIzQwNDA0MCAwLCMzYjNiM2IgMTAwJSk7YmFja2dyb3VuZC1pbWFnZTpsaW5lYXItZ3JhZGllbnQoIzQwNDA0MCAwLCMzYjNiM2IgMTAwJSl9I2NvbnRyb2xLaXQgLnBhbmVsIC5jb2xvci13aXRoLXByZXNldC13cmFwLCNjb250cm9sS2l0IC5wYW5lbCAuaW5wdXQtd2l0aC1wcmVzZXQtd3JhcHt3aWR0aDoxMDAlO2Zsb2F0OmxlZnR9I2NvbnRyb2xLaXQgLnBhbmVsIC5jb2xvci13aXRoLXByZXNldC13cmFwIC5jb2xvciwjY29udHJvbEtpdCAucGFuZWwgLmlucHV0LXdpdGgtcHJlc2V0LXdyYXAgaW5wdXRbdHlwZT10ZXh0XXtwYWRkaW5nLXJpZ2h0OjI1cHg7Ym9yZGVyLXRvcC1yaWdodC1yYWRpdXM6MnB4O2JvcmRlci1ib3R0b20tcmlnaHQtcmFkaXVzOjJweDtmbG9hdDpsZWZ0fSNjb250cm9sS2l0IC5wYW5lbCAuYnV0dG9uLXByZXNldCwjY29udHJvbEtpdCAucGFuZWwgLmJ1dHRvbi1wcmVzZXQtYWN0aXZley13ZWJraXQtYm94LXNpemluZzpib3JkZXItYm94Oy1tb3otYm94LXNpemluZzpib3JkZXItYm94O2JveC1zaXppbmc6Ym9yZGVyLWJveDtwb3NpdGlvbjphYnNvbHV0ZTtyaWdodDowO3dpZHRoOjIwcHg7aGVpZ2h0OjI1cHg7bWFyZ2luOjA7Y3Vyc29yOnBvaW50ZXI7ZmxvYXQ6cmlnaHQ7Ym9yZGVyOm5vbmU7Ym9yZGVyLXRvcC1yaWdodC1yYWRpdXM6MnB4O2JvcmRlci1ib3R0b20tcmlnaHQtcmFkaXVzOjJweDtib3gtc2hhZG93OjAgMCAwIDFweCAjMWYxZjFmIGluc2V0LC0xcHggMnB4IDAgMCAjNGE0YTRhIGluc2V0O291dGxpbmU6MH0jY29udHJvbEtpdCAucGFuZWwgLmJ1dHRvbi1wcmVzZXQtYWN0aXZlLCNjb250cm9sS2l0IC5wYW5lbCAuYnV0dG9uLXByZXNldDpob3ZlcntiYWNrZ3JvdW5kOnVybChkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFnQUFBQUZDQVlBQUFCNGthMVZBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBRzVKUkVGVWVOcGk1T0RpYW1SZ1lLaGp3QTRhbVZ4OGd4am1MMXJDOFAzclZ4UThiK0VTQmhmZklBWm1OUjI5QTVldlhXZGlaR0MwMTlYU1pHQmdZR0JZdm1ZOXc3STE2eG9aR0JnYVdLQkcxUzlicys0L0F3TkRQUU1EQTF5U2dZR0JnZEVuUEFiWnpnWTBtZ0V3QUU5bEpUMWxyc2ZmQUFBQUFFbEZUa1N1UW1DQykgNTAlIDUwJSBuby1yZXBlYXQsbGluZWFyLWdyYWRpZW50KCM0NTQ1NDUgMCwjM2IzYjNiIDEwMCUpfSNjb250cm9sS2l0IC5wYW5lbCAuYnV0dG9uLXByZXNldHtiYWNrZ3JvdW5kOnVybChkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFnQUFBQUZDQVlBQUFCNGthMVZBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBRzVKUkVGVWVOcGk1T0RpYW1SZ1lLaGp3QTRhbVZ4OGd4am1MMXJDOFAzclZ4UThiK0VTQmhmZklBWm1OUjI5QTVldlhXZGlaR0MwMTlYU1pHQmdZR0JZdm1ZOXc3STE2eG9aR0JnYVdLQkcxUzlicys0L0F3TkRQUU1EQTF5U2dZR0JnZEVuUEFiWnpnWTBtZ0V3QUU5bEpUMWxyc2ZmQUFBQUFFbEZUa1N1UW1DQykgNTAlIDUwJSBuby1yZXBlYXQsbGluZWFyLWdyYWRpZW50KCM0MDQwNDAgMCwjM2IzYjNiIDEwMCUpfSNjb250cm9sS2l0IC5wYW5lbCBpbnB1dFt0eXBlPWNoZWNrYm94XXttYXJnaW46NnB4IDAgMH0jY29udHJvbEtpdCAucGFuZWwgLnNlbGVjdCwjY29udHJvbEtpdCAucGFuZWwgLnNlbGVjdC1hY3RpdmV7cGFkZGluZy1sZWZ0OjEwcHg7cGFkZGluZy1yaWdodDoyMHB4O2ZvbnQtc2l6ZToxMXB4O3RleHQtYWxpZ246bGVmdDt0ZXh0LXNoYWRvdzoxcHggMXB4ICMwMDA7Y3Vyc29yOnBvaW50ZXI7b3ZlcmZsb3c6aGlkZGVuO3doaXRlLXNwYWNlOm5vd3JhcDt0ZXh0LW92ZXJmbG93OmVsbGlwc2lzfSNjb250cm9sS2l0IC5wYW5lbCAuc2VsZWN0e2JhY2tncm91bmQ6dXJsKGRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQkFBQUFBTENBWUFBQUIyNGcwNUFBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFLVDJsRFExQlFhRzkwYjNOb2IzQWdTVU5ESUhCeWIyWnBiR1VBQUhqYW5WTm5WRlBwRmozMzN2UkNTNGlBbEV0dlVoVUlJRkpDaTRBVWtTWXFJUWtRU29naG9ka1ZVY0VSUlVVRUc4aWdpQU9Pam9DTUZWRXNESW9LMkFma0lhS09nNk9JaXNyNzRYdWphOWE4OStiTi9yWFhQdWVzODUyenp3ZkFDQXlXU0ROUk5ZQU1xVUllRWVDRHg4VEc0ZVF1UUlFS0pIQUFFQWl6WkNGei9TTUJBUGgrUER3cklzQUh2Z0FCZU5NTENBREFUWnZBTUJ5SC93L3FRcGxjQVlDRUFjQjBrVGhMQ0lBVUFFQjZqa0ttQUVCR0FZQ2RtQ1pUQUtBRUFHRExZMkxqQUZBdEFHQW5mK2JUQUlDZCtKbDdBUUJibENFVkFhQ1JBQ0FUWlloRUFHZzdBS3pQVm9wRkFGZ3dBQlJtUzhRNUFOZ3RBREJKVjJaSUFMQzNBTURPRUF1eUFBZ01BREJSaUlVcEFBUjdBR0RJSXlONEFJU1pBQlJHOGxjODhTdXVFT2NxQUFCNG1iSTh1U1E1UllGYkNDMXhCMWRYTGg0b3pra1hLeFEyWVFKaG1rQXV3bm1aR1RLQk5BL2c4OHdBQUtDUkZSSGdnL1A5ZU00T3JzN09ObzYyRGw4dDZyOEcveUppWXVQKzVjK3JjRUFBQU9GMGZ0SCtMQyt6R29BN0JvQnQvcUlsN2dSb1hndWdkZmVMWnJJUFFMVUFvT25hVi9OdytINDhQRVdoa0xuWjJlWGs1TmhLeEVKYlljcFhmZjVud2wvQVYvMXMrWDQ4L1BmMTRMN2lKSUV5WFlGSEJQamd3c3owVEtVY3o1SUpoR0xjNW85SC9MY0wvL3dkMHlMRVNXSzVXQ29VNDFFU2NZNUVtb3p6TXFVaWlVS1NLY1VsMHY5azR0OHMrd00rM3pVQXNHbytBWHVSTGFoZFl3UDJTeWNRV0hUQTR2Y0FBUEs3YjhIVUtBZ0RnR2lENGM5My8rOC8vVWVnSlFDQVprbVNjUUFBWGtRa0xsVEtzei9IQ0FBQVJLQ0JLckJCRy9UQkdDekFCaHpCQmR6QkMveGdOb1JDSk1UQ1FoQkNDbVNBSEhKZ0theUNRaWlHemJBZEttQXYxRUFkTk1CUmFJYVRjQTR1d2xXNERqMXdEL3BoQ0o3QktMeUJDUVJCeUFnVFlTSGFpQUZpaWxnampnZ1htWVg0SWNGSUJCS0xKQ0RKaUJSUklrdVJOVWd4VW9wVUlGVklIZkk5Y2dJNWgxeEd1cEU3eUFBeWd2eUd2RWN4bElHeVVUM1VETFZEdWFnM0dvUkdvZ3ZRWkhReG1vOFdvSnZRY3JRYVBZdzJvZWZRcTJnUDJvOCtROGN3d09nWUJ6UEViREF1eHNOQ3NUZ3NDWk5qeTdFaXJBeXJ4aHF3VnF3RHU0bjFZOCt4ZHdRU2dVWEFDVFlFZDBJZ1lSNUJTRmhNV0U3WVNLZ2dIQ1EwRWRvSk53a0RoRkhDSnlLVHFFdTBKcm9SK2NRWVlqSXhoMWhJTENQV0VvOFRMeEI3aUVQRU55UVNpVU15SjdtUUFrbXhwRlRTRXRKRzBtNVNJK2tzcVpzMFNCb2prOG5hWkd1eUJ6bVVMQ0FyeUlYa25lVEQ1RFBrRytRaDhsc0tuV0pBY2FUNFUrSW9Vc3BxU2hubEVPVTA1UVpsbURKQlZhT2FVdDJvb1ZRUk5ZOWFRcTJodGxLdlVZZW9FelIxbWpuTmd4WkpTNld0b3BYVEdtZ1hhUGRwcitoMHVoSGRsUjVPbDlCWDBzdnBSK2lYNkFQMGR3d05oaFdEeDRobktCbWJHQWNZWnhsM0dLK1lUS1laMDRzWngxUXdOekhybU9lWkQ1bHZWVmdxdGlwOEZaSEtDcFZLbFNhVkd5b3ZWS21xcHFyZXFndFY4MVhMVkkrcFhsTjlya1pWTTFQanFRblVscXRWcXAxUTYxTWJVMmVwTzZpSHFtZW9iMVEvcEg1Wi9Za0dXY05NdzA5RHBGR2dzVi9qdk1ZZ0MyTVpzM2dzSVdzTnE0WjFnVFhFSnJITjJYeDJLcnVZL1IyN2l6MnFxYUU1UXpOS00xZXpVdk9VWmo4SDQ1aHgrSngwVGdubktLZVg4MzZLM2hUdktlSXBHNlkwVExreFpWeHJxcGFYbGxpclNLdFJxMGZydlRhdTdhZWRwcjFGdTFuN2dRNUJ4MG9uWENkSFo0L09CWjNuVTlsVDNhY0tweFpOUFRyMXJpNnFhNlVib2J0RWQ3OXVwKzZZbnI1ZWdKNU1iNmZlZWIzbitoeDlMLzFVL1czNnAvVkhERmdHc3d3a0J0c016aGc4eFRWeGJ6d2RMOGZiOFZGRFhjTkFRNlZobFdHWDRZU1J1ZEU4bzlWR2pVWVBqR25HWE9NazQyM0diY2FqSmdZbUlTWkxUZXBON3BwU1RibW1LYVk3VER0TXg4M016YUxOMXBrMW16MHgxekxubStlYjE1dmZ0MkJhZUZvc3RxaTJ1R1ZKc3VSYXBsbnV0cnh1aFZvNVdhVllWVnBkczBhdG5hMGwxcnV0dTZjUnA3bE9rMDZybnRabnc3RHh0c20ycWJjWnNPWFlCdHV1dG0yMmZXRm5ZaGRudDhXdXcrNlR2Wk45dW4yTi9UMEhEWWZaRHFzZFdoMStjN1J5RkRwV090NmF6cHp1UDMzRjlKYnBMMmRZenhEUDJEUGp0aFBMS2NScG5WT2IwMGRuRjJlNWM0UHppSXVKUzRMTExwYytMcHNieHQzSXZlUktkUFZ4WGVGNjB2V2RtN09id3UybzI2L3VOdTVwN29mY244dzBueW1lV1ROejBNUElRK0JSNWRFL0M1K1ZNR3Zmckg1UFEwK0JaN1huSXk5akw1RlhyZGV3dDZWM3F2ZGg3eGMrOWo1eW4rTSs0enczM2pMZVdWL01OOEMzeUxmTFQ4TnZubCtGMzBOL0kvOWsvM3IvMFFDbmdDVUJad09KZ1VHQld3TDcrSHA4SWIrT1B6cmJaZmF5MmUxQmpLQzVRUlZCajRLdGd1WEJyU0ZveU95UXJTSDM1NWpPa2M1cERvVlFmdWpXMEFkaDVtR0x3MzRNSjRXSGhWZUdQNDV3aUZnYTBUR1hOWGZSM0VOejMwVDZSSlpFM3B0bk1VODVyeTFLTlNvK3FpNXFQTm8zdWpTNlA4WXVabG5NMVZpZFdFbHNTeHc1TGlxdU5tNXN2dC84N2ZPSDRwM2lDK043RjVndnlGMXdlYUhPd3ZTRnB4YXBMaElzT3BaQVRJaE9PSlR3UVJBcXFCYU1KZklUZHlXT0NubkNIY0puSWkvUk50R0kyRU5jS2g1TzhrZ3FUWHFTN0pHOE5Ya2t4VE9sTE9XNWhDZXBrTHhNRFV6ZG16cWVGcHAySUcweVBUcTlNWU9Ta1pCeFFxb2hUWk8yWitwbjVtWjJ5NnhsaGJMK3hXNkx0eThlbFFmSmE3T1FyQVZaTFFxMlFxYm9WRm9vMXlvSHNtZGxWMmEvelluS09aYXJuaXZON2N5enl0dVFONXp2bi8vdEVzSVM0WksycFlaTFZ5MGRXT2E5ckdvNXNqeHhlZHNLNHhVRks0WldCcXc4dUlxMkttM1ZUNnZ0VjVldWZyMG1lazFyZ1Y3QnlvTEJ0UUZyNnd0VkN1V0ZmZXZjMSsxZFQxZ3ZXZCsxWWZxR25ScytGWW1LcmhUYkY1Y1ZmOWdvM0hqbEc0ZHZ5citaM0pTMHFhdkV1V1RQWnRKbTZlYmVMWjViRHBhcWwrYVhEbTROMmRxMERkOVd0TzMxOWtYYkw1Zk5LTnU3ZzdaRHVhTy9QTGk4WmFmSnpzMDdQMVNrVlBSVStsUTI3dExkdFdIWCtHN1I3aHQ3dlBZMDdOWGJXN3ozL1Q3SnZ0dFZBVlZOMVdiVlpmdEorN1AzUDY2SnF1bjRsdnR0WGExT2JYSHR4d1BTQS8wSEl3NjIxN25VMVIzU1BWUlNqOVlyNjBjT3h4KysvcDN2ZHkwTk5nMVZqWnpHNGlOd1JIbms2ZmNKMy9jZURUcmFkb3g3ck9FSDB4OTJIV2NkTDJwQ212S2FScHRUbXZ0YllsdTZUOHcrMGRicTNucjhSOXNmRDV3MFBGbDVTdk5VeVduYTZZTFRrMmZ5ejR5ZGxaMTlmaTc1M0dEYm9yWjc1MlBPMzJvUGIrKzZFSFRoMGtYL2krYzd2RHZPWFBLNGRQS3kyK1VUVjdoWG1xODZYMjNxZE9vOC9wUFRUOGU3bkx1YXJybGNhN251ZXIyMWUyYjM2UnVlTjg3ZDlMMTU4UmIvMXRXZU9UM2R2Zk42Yi9mRjkvWGZGdDErY2lmOXpzdTcyWGNuN3EyOFQ3eGY5RUR0UWRsRDNZZlZQMXYrM05qdjNIOXF3SGVnODlIY1IvY0doWVBQL3BIMWp3OURCWStaajh1R0RZYnJuamcrT1RuaVAzTDk2ZnluUTg5a3p5YWVGLzZpL3N1dUZ4WXZmdmpWNjlmTzBaalJvWmZ5bDVPL2JYeWwvZXJBNnhtdjI4YkN4aDYreVhnek1WNzBWdnZ0d1hmY2R4M3ZvOThQVCtSOElIOG8vMmo1c2ZWVDBLZjdreG1Uay84RUE1anovR016TGRzQUFBQWdZMGhTVFFBQWVpVUFBSUNEQUFENS93QUFnT2tBQUhVd0FBRHFZQUFBT3BnQUFCZHZrbC9GUmdBQUFNTkpSRUZVZU5xY2tqRUt3akFVaGo4bDUzQVE1MjZCSEtLTEloU2xIa0h4QmtrdUlGV1BJTFFPUVFkM1Y0VnVYaWd1RmxyRlJQemhMWGw4MzN1QjEwdXpuQ2FQK3E0QkVxbHM4M1k1SGdoRnRPSDFhbWtBaXQyK0l3a216WElHdzVIZUZGdmZaRk5zL1dBNDBtbVc0NzBQMWdmOExva0pSQ0lWMTF2TjliYjQyQzZSS3ZvREFkaFgvUlh4cU84RzBGLzZGakJCUVNJVjgrbUUyWFRjYVZUdVRPbE8wUTM2Z0NuZHlWYnUvQTVIcDdmdndMeW1hZUJudUhOSUxRbS93Z0RQQVFBUE5Jc0huTzc5NFFBQUFBQkpSVTVFcmtKZ2dnPT0pIDEwMCUgNTAlIG5vLXJlcGVhdCxsaW5lYXItZ3JhZGllbnQoIzQwNDA0MCAwLCMzYjNiM2IgMTAwJSl9I2NvbnRyb2xLaXQgLnBhbmVsIC5zZWxlY3QtYWN0aXZlLCNjb250cm9sS2l0IC5wYW5lbCAuc2VsZWN0OmhvdmVye2JhY2tncm91bmQ6dXJsKGRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQkFBQUFBTENBWUFBQUIyNGcwNUFBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFLVDJsRFExQlFhRzkwYjNOb2IzQWdTVU5ESUhCeWIyWnBiR1VBQUhqYW5WTm5WRlBwRmozMzN2UkNTNGlBbEV0dlVoVUlJRkpDaTRBVWtTWXFJUWtRU29naG9ka1ZVY0VSUlVVRUc4aWdpQU9Pam9DTUZWRXNESW9LMkFma0lhS09nNk9JaXNyNzRYdWphOWE4OStiTi9yWFhQdWVzODUyenp3ZkFDQXlXU0ROUk5ZQU1xVUllRWVDRHg4VEc0ZVF1UUlFS0pIQUFFQWl6WkNGei9TTUJBUGgrUER3cklzQUh2Z0FCZU5NTENBREFUWnZBTUJ5SC93L3FRcGxjQVlDRUFjQjBrVGhMQ0lBVUFFQjZqa0ttQUVCR0FZQ2RtQ1pUQUtBRUFHRExZMkxqQUZBdEFHQW5mK2JUQUlDZCtKbDdBUUJibENFVkFhQ1JBQ0FUWlloRUFHZzdBS3pQVm9wRkFGZ3dBQlJtUzhRNUFOZ3RBREJKVjJaSUFMQzNBTURPRUF1eUFBZ01BREJSaUlVcEFBUjdBR0RJSXlONEFJU1pBQlJHOGxjODhTdXVFT2NxQUFCNG1iSTh1U1E1UllGYkNDMXhCMWRYTGg0b3pra1hLeFEyWVFKaG1rQXV3bm1aR1RLQk5BL2c4OHdBQUtDUkZSSGdnL1A5ZU00T3JzN09ObzYyRGw4dDZyOEcveUppWXVQKzVjK3JjRUFBQU9GMGZ0SCtMQyt6R29BN0JvQnQvcUlsN2dSb1hndWdkZmVMWnJJUFFMVUFvT25hVi9OdytINDhQRVdoa0xuWjJlWGs1TmhLeEVKYlljcFhmZjVud2wvQVYvMXMrWDQ4L1BmMTRMN2lKSUV5WFlGSEJQamd3c3owVEtVY3o1SUpoR0xjNW85SC9MY0wvL3dkMHlMRVNXSzVXQ29VNDFFU2NZNUVtb3p6TXFVaWlVS1NLY1VsMHY5azR0OHMrd00rM3pVQXNHbytBWHVSTGFoZFl3UDJTeWNRV0hUQTR2Y0FBUEs3YjhIVUtBZ0RnR2lENGM5My8rOC8vVWVnSlFDQVprbVNjUUFBWGtRa0xsVEtzei9IQ0FBQVJLQ0JLckJCRy9UQkdDekFCaHpCQmR6QkMveGdOb1JDSk1UQ1FoQkNDbVNBSEhKZ0theUNRaWlHemJBZEttQXYxRUFkTk1CUmFJYVRjQTR1d2xXNERqMXdEL3BoQ0o3QktMeUJDUVJCeUFnVFlTSGFpQUZpaWxnampnZ1htWVg0SWNGSUJCS0xKQ0RKaUJSUklrdVJOVWd4VW9wVUlGVklIZkk5Y2dJNWgxeEd1cEU3eUFBeWd2eUd2RWN4bElHeVVUM1VETFZEdWFnM0dvUkdvZ3ZRWkhReG1vOFdvSnZRY3JRYVBZdzJvZWZRcTJnUDJvOCtROGN3d09nWUJ6UEViREF1eHNOQ3NUZ3NDWk5qeTdFaXJBeXJ4aHF3VnF3RHU0bjFZOCt4ZHdRU2dVWEFDVFlFZDBJZ1lSNUJTRmhNV0U3WVNLZ2dIQ1EwRWRvSk53a0RoRkhDSnlLVHFFdTBKcm9SK2NRWVlqSXhoMWhJTENQV0VvOFRMeEI3aUVQRU55UVNpVU15SjdtUUFrbXhwRlRTRXRKRzBtNVNJK2tzcVpzMFNCb2prOG5hWkd1eUJ6bVVMQ0FyeUlYa25lVEQ1RFBrRytRaDhsc0tuV0pBY2FUNFUrSW9Vc3BxU2hubEVPVTA1UVpsbURKQlZhT2FVdDJvb1ZRUk5ZOWFRcTJodGxLdlVZZW9FelIxbWpuTmd4WkpTNld0b3BYVEdtZ1hhUGRwcitoMHVoSGRsUjVPbDlCWDBzdnBSK2lYNkFQMGR3d05oaFdEeDRobktCbWJHQWNZWnhsM0dLK1lUS1laMDRzWngxUXdOekhybU9lWkQ1bHZWVmdxdGlwOEZaSEtDcFZLbFNhVkd5b3ZWS21xcHFyZXFndFY4MVhMVkkrcFhsTjlya1pWTTFQanFRblVscXRWcXAxUTYxTWJVMmVwTzZpSHFtZW9iMVEvcEg1Wi9Za0dXY05NdzA5RHBGR2dzVi9qdk1ZZ0MyTVpzM2dzSVdzTnE0WjFnVFhFSnJITjJYeDJLcnVZL1IyN2l6MnFxYUU1UXpOS00xZXpVdk9VWmo4SDQ1aHgrSngwVGdubktLZVg4MzZLM2hUdktlSXBHNlkwVExreFpWeHJxcGFYbGxpclNLdFJxMGZydlRhdTdhZWRwcjFGdTFuN2dRNUJ4MG9uWENkSFo0L09CWjNuVTlsVDNhY0tweFpOUFRyMXJpNnFhNlVib2J0RWQ3OXVwKzZZbnI1ZWdKNU1iNmZlZWIzbitoeDlMLzFVL1czNnAvVkhERmdHc3d3a0J0c016aGc4eFRWeGJ6d2RMOGZiOFZGRFhjTkFRNlZobFdHWDRZU1J1ZEU4bzlWR2pVWVBqR25HWE9NazQyM0diY2FqSmdZbUlTWkxUZXBON3BwU1RibW1LYVk3VER0TXg4M016YUxOMXBrMW16MHgxekxubStlYjE1dmZ0MkJhZUZvc3RxaTJ1R1ZKc3VSYXBsbnV0cnh1aFZvNVdhVllWVnBkczBhdG5hMGwxcnV0dTZjUnA3bE9rMDZybnRabnc3RHh0c20ycWJjWnNPWFlCdHV1dG0yMmZXRm5ZaGRudDhXdXcrNlR2Wk45dW4yTi9UMEhEWWZaRHFzZFdoMStjN1J5RkRwV090NmF6cHp1UDMzRjlKYnBMMmRZenhEUDJEUGp0aFBMS2NScG5WT2IwMGRuRjJlNWM0UHppSXVKUzRMTExwYytMcHNieHQzSXZlUktkUFZ4WGVGNjB2V2RtN09id3UybzI2L3VOdTVwN29mY244dzBueW1lV1ROejBNUElRK0JSNWRFL0M1K1ZNR3Zmckg1UFEwK0JaN1huSXk5akw1RlhyZGV3dDZWM3F2ZGg3eGMrOWo1eW4rTSs0enczM2pMZVdWL01OOEMzeUxmTFQ4TnZubCtGMzBOL0kvOWsvM3IvMFFDbmdDVUJad09KZ1VHQld3TDcrSHA4SWIrT1B6cmJaZmF5MmUxQmpLQzVRUlZCajRLdGd1WEJyU0ZveU95UXJTSDM1NWpPa2M1cERvVlFmdWpXMEFkaDVtR0x3MzRNSjRXSGhWZUdQNDV3aUZnYTBUR1hOWGZSM0VOejMwVDZSSlpFM3B0bk1VODVyeTFLTlNvK3FpNXFQTm8zdWpTNlA4WXVabG5NMVZpZFdFbHNTeHc1TGlxdU5tNXN2dC84N2ZPSDRwM2lDK043RjVndnlGMXdlYUhPd3ZTRnB4YXBMaElzT3BaQVRJaE9PSlR3UVJBcXFCYU1KZklUZHlXT0NubkNIY0puSWkvUk50R0kyRU5jS2g1TzhrZ3FUWHFTN0pHOE5Ya2t4VE9sTE9XNWhDZXBrTHhNRFV6ZG16cWVGcHAySUcweVBUcTlNWU9Ta1pCeFFxb2hUWk8yWitwbjVtWjJ5NnhsaGJMK3hXNkx0eThlbFFmSmE3T1FyQVZaTFFxMlFxYm9WRm9vMXlvSHNtZGxWMmEvelluS09aYXJuaXZON2N5enl0dVFONXp2bi8vdEVzSVM0WksycFlaTFZ5MGRXT2E5ckdvNXNqeHhlZHNLNHhVRks0WldCcXc4dUlxMkttM1ZUNnZ0VjVldWZyMG1lazFyZ1Y3QnlvTEJ0UUZyNnd0VkN1V0ZmZXZjMSsxZFQxZ3ZXZCsxWWZxR25ScytGWW1LcmhUYkY1Y1ZmOWdvM0hqbEc0ZHZ5citaM0pTMHFhdkV1V1RQWnRKbTZlYmVMWjViRHBhcWwrYVhEbTROMmRxMERkOVd0TzMxOWtYYkw1Zk5LTnU3ZzdaRHVhTy9QTGk4WmFmSnpzMDdQMVNrVlBSVStsUTI3dExkdFdIWCtHN1I3aHQ3dlBZMDdOWGJXN3ozL1Q3SnZ0dFZBVlZOMVdiVlpmdEorN1AzUDY2SnF1bjRsdnR0WGExT2JYSHR4d1BTQS8wSEl3NjIxN25VMVIzU1BWUlNqOVlyNjBjT3h4KysvcDN2ZHkwTk5nMVZqWnpHNGlOd1JIbms2ZmNKMy9jZURUcmFkb3g3ck9FSDB4OTJIV2NkTDJwQ212S2FScHRUbXZ0YllsdTZUOHcrMGRicTNucjhSOXNmRDV3MFBGbDVTdk5VeVduYTZZTFRrMmZ5ejR5ZGxaMTlmaTc1M0dEYm9yWjc1MlBPMzJvUGIrKzZFSFRoMGtYL2krYzd2RHZPWFBLNGRQS3kyK1VUVjdoWG1xODZYMjNxZE9vOC9wUFRUOGU3bkx1YXJybGNhN251ZXIyMWUyYjM2UnVlTjg3ZDlMMTU4UmIvMXRXZU9UM2R2Zk42Yi9mRjkvWGZGdDErY2lmOXpzdTcyWGNuN3EyOFQ3eGY5RUR0UWRsRDNZZlZQMXYrM05qdjNIOXF3SGVnODlIY1IvY0doWVBQL3BIMWp3OURCWStaajh1R0RZYnJuamcrT1RuaVAzTDk2ZnluUTg5a3p5YWVGLzZpL3N1dUZ4WXZmdmpWNjlmTzBaalJvWmZ5bDVPL2JYeWwvZXJBNnhtdjI4YkN4aDYreVhnek1WNzBWdnZ0d1hmY2R4M3ZvOThQVCtSOElIOG8vMmo1c2ZWVDBLZjdreG1Uay84RUE1anovR016TGRzQUFBQWdZMGhTVFFBQWVpVUFBSUNEQUFENS93QUFnT2tBQUhVd0FBRHFZQUFBT3BnQUFCZHZrbC9GUmdBQUFNTkpSRUZVZU5xY2tqRUt3akFVaGo4bDUzQVE1MjZCSEtLTEloU2xIa0h4QmtrdUlGV1BJTFFPUVFkM1Y0VnVYaWd1RmxyRlJQemhMWGw4MzN1QjEwdXpuQ2FQK3E0QkVxbHM4M1k1SGdoRnRPSDFhbWtBaXQyK0l3a216WElHdzVIZUZGdmZaRk5zL1dBNDBtbVc0NzBQMWdmOExva0pSQ0lWMTF2TjliYjQyQzZSS3ZvREFkaFgvUlh4cU84RzBGLzZGakJCUVNJVjgrbUUyWFRjYVZUdVRPbE8wUTM2Z0NuZHlWYnUvQTVIcDdmdndMeW1hZUJudUhOSUxRbS93Z0RQQVFBUE5Jc0huTzc5NFFBQUFBQkpSVTVFcmtKZ2dnPT0pIDEwMCUgNTAlIG5vLXJlcGVhdCxsaW5lYXItZ3JhZGllbnQoIzQ1NDU0NSAwLCMzYjNiM2IgMTAwJSl9I2NvbnRyb2xLaXQgLnBhbmVsIC5zbGlkZXItaGFuZGxlLCNjb250cm9sS2l0IC5wYW5lbCAuc2xpZGVyLXNsb3QsI2NvbnRyb2xLaXQgLnBhbmVsIC5zbGlkZXItd3JhcCwjY29udHJvbEtpdCAucGFuZWwgLndyYXAtc2xpZGVyey13ZWJraXQtYm94LXNpemluZzpib3JkZXItYm94Oy1tb3otYm94LXNpemluZzpib3JkZXItYm94O2JveC1zaXppbmc6Ym9yZGVyLWJveH0jY29udHJvbEtpdCAucGFuZWwgLndyYXAtc2xpZGVye3dpZHRoOjcwJTtwYWRkaW5nOjZweCAwIDA7ZmxvYXQ6cmlnaHQ7aGVpZ2h0OjEwMCV9I2NvbnRyb2xLaXQgLnBhbmVsIC53cmFwLXNsaWRlciBpbnB1dFt0eXBlPXRleHRde3dpZHRoOjI1JTt0ZXh0LWFsaWduOmNlbnRlcjtwYWRkaW5nOjA7ZmxvYXQ6cmlnaHR9I2NvbnRyb2xLaXQgLnBhbmVsIC5zbGlkZXItd3JhcHtmbG9hdDpsZWZ0O2N1cnNvcjpldy1yZXNpemU7d2lkdGg6NzAlfSNjb250cm9sS2l0IC5wYW5lbCAuc2xpZGVyLXNsb3R7d2lkdGg6MTAwJTtoZWlnaHQ6MjVweDtwYWRkaW5nOjNweDtiYWNrZ3JvdW5kLWNvbG9yOiMxZTIyMjQ7Ym9yZGVyOm5vbmU7Ym94LXNoYWRvdzowIDAgMCAxcHggIzFmMWYxZiBpbnNldDtib3JkZXItcmFkaXVzOjJweDstbW96LWJvcmRlci1yYWRpdXM6MnB4fSNjb250cm9sS2l0IC5wYW5lbCAuc2xpZGVyLWhhbmRsZXtwb3NpdGlvbjpyZWxhdGl2ZTt3aWR0aDoxMDAlO2hlaWdodDoxMDAlO2JhY2tncm91bmQ6I2IzMjQzNTtiYWNrZ3JvdW5kLWltYWdlOi1vLWxpbmVhci1ncmFkaWVudCh0cmFuc3BhcmVudCAwLHJnYmEoMCwwLDAsLjEpIDEwMCUpO2JhY2tncm91bmQtaW1hZ2U6bGluZWFyLWdyYWRpZW50KHRyYW5zcGFyZW50IDAscmdiYSgwLDAsMCwuMSkgMTAwJSk7Ym94LXNoYWRvdzowIDFweCAwIDAgIzBmMGYwZn0jY29udHJvbEtpdCAucGFuZWwgLmNvbG9yey13ZWJraXQtYm94LXNpemluZzpib3JkZXItYm94Oy1tb3otYm94LXNpemluZzpib3JkZXItYm94O2JveC1zaXppbmc6Ym9yZGVyLWJveDstd2Via2l0LXRvdWNoLWNhbGxvdXQ6bm9uZTstd2Via2l0LXVzZXItc2VsZWN0Om5vbmU7LWtodG1sLXVzZXItc2VsZWN0Om5vbmU7LW1vei11c2VyLXNlbGVjdDpub25lOy1tcy11c2VyLXNlbGVjdDpub25lO3VzZXItc2VsZWN0Om5vbmU7Y3Vyc29yOnBvaW50ZXI7d2lkdGg6MTAwJTtoZWlnaHQ6MjVweDtwYWRkaW5nOjA7Ym9yZGVyOm5vbmU7YmFja2dyb3VuZDojZmZmO2JveC1zaGFkb3c6MCAwIDAgMXB4ICMxMTEzMTQgaW5zZXQ7dGV4dC1hbGlnbjpjZW50ZXI7bGluZS1oZWlnaHQ6MjVweDtib3JkZXItcmFkaXVzOjJweDstbW96LWJvcmRlci1yYWRpdXM6MnB4fSNjb250cm9sS2l0IC5wYW5lbCAuZ3JhcGgtc2xpZGVyLXgtd3JhcCwjY29udHJvbEtpdCAucGFuZWwgLmdyYXBoLXNsaWRlci15LXdyYXB7cG9zaXRpb246YWJzb2x1dGU7LXdlYmtpdC1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW1vei1ib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym94LXNpemluZzpib3JkZXItYm94fSNjb250cm9sS2l0IC5wYW5lbCAuZ3JhcGgtc2xpZGVyLXgtd3JhcHtib3R0b206MDtsZWZ0OjA7d2lkdGg6MTAwJTtwYWRkaW5nOjZweCAyMHB4IDZweCA2cHh9I2NvbnRyb2xLaXQgLnBhbmVsIC5ncmFwaC1zbGlkZXIteS13cmFwe3RvcDowO3JpZ2h0OjA7aGVpZ2h0OjEwMCU7cGFkZGluZzo2cHggNnB4IDIwcHh9I2NvbnRyb2xLaXQgLnBhbmVsIC5ncmFwaC1zbGlkZXIteCwjY29udHJvbEtpdCAucGFuZWwgLmdyYXBoLXNsaWRlci15ey13ZWJraXQtYm94LXNpemluZzpib3JkZXItYm94Oy1tb3otYm94LXNpemluZzpib3JkZXItYm94O2JveC1zaXppbmc6Ym9yZGVyLWJveDtib3JkZXItcmFkaXVzOjJweDstbW96LWJvcmRlci1yYWRpdXM6MnB4O2JhY2tncm91bmQ6cmdiYSgyNCwyNywyOSwuNSk7Ym9yZGVyOjFweCBzb2xpZCAjMTgxYjFkfSNjb250cm9sS2l0IC5wYW5lbCAuZ3JhcGgtc2xpZGVyLXh7aGVpZ2h0OjhweH0jY29udHJvbEtpdCAucGFuZWwgLmdyYXBoLXNsaWRlci15e3dpZHRoOjhweDtoZWlnaHQ6MTAwJX0jY29udHJvbEtpdCAucGFuZWwgLmdyYXBoLXNsaWRlci14LWhhbmRsZSwjY29udHJvbEtpdCAucGFuZWwgLmdyYXBoLXNsaWRlci15LWhhbmRsZXstd2Via2l0LWJveC1zaXppbmc6Ym9yZGVyLWJveDstbW96LWJveC1zaXppbmc6Ym9yZGVyLWJveDtib3gtc2l6aW5nOmJvcmRlci1ib3g7Y3Vyc29yOnBvaW50ZXI7Ym9yZGVyOjFweCBzb2xpZCAjMTgxYjFkO2JhY2tncm91bmQ6IzMwMzYzOX0jY29udHJvbEtpdCAucGFuZWwgLmdyYXBoLXNsaWRlci14LWhhbmRsZXt3aWR0aDoyMHB4O2hlaWdodDoxMDAlO2JvcmRlci10b3A6bm9uZTtib3JkZXItYm90dG9tOm5vbmV9I2NvbnRyb2xLaXQgLnBhbmVsIC5ncmFwaC1zbGlkZXIteS1oYW5kbGV7d2lkdGg6MTAwJTtoZWlnaHQ6MjBweDtib3JkZXItbGVmdDpub25lO2JvcmRlci1yaWdodDpub25lfSNjb250cm9sS2l0IC5zdWItZ3JvdXAgLndyYXAgLndyYXAgLndyYXB7d2lkdGg6MjUlIWltcG9ydGFudDtwYWRkaW5nOjAhaW1wb3J0YW50O2Zsb2F0OmxlZnQhaW1wb3J0YW50fSNjb250cm9sS2l0IC5zdWItZ3JvdXAgLndyYXAgLndyYXAgLndyYXAgLmxhYmVse3dpZHRoOjEwMCUhaW1wb3J0YW50O3BhZGRpbmc6OHB4IDAgMCFpbXBvcnRhbnQ7Y29sb3I6Izg3ODc4NyFpbXBvcnRhbnQ7dGV4dC1hbGlnbjpjZW50ZXIhaW1wb3J0YW50O3RleHQtdHJhbnNmb3JtOnVwcGVyY2FzZSFpbXBvcnRhbnQ7Zm9udC13ZWlnaHQ6NzAwIWltcG9ydGFudDt0ZXh0LXNoYWRvdzoxcHggMXB4ICMxYTFhMWEhaW1wb3J0YW50fSNjb250cm9sS2l0IC5zdWItZ3JvdXAgLndyYXAgLndyYXAgLndyYXAgaW5wdXRbdHlwZT10ZXh0XXtwYWRkaW5nOjA7dGV4dC1hbGlnbjpjZW50ZXJ9I2NvbnRyb2xLaXQgLm9wdGlvbnN7cG9pbnRlci1ldmVudHM6YXV0bzstd2Via2l0LWJveC1zaXppbmc6Ym9yZGVyLWJveDstbW96LWJveC1zaXppbmc6Ym9yZGVyLWJveDtib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym9yZGVyOjFweCBzb2xpZCAjMWYxZjFmO2JvcmRlci1yYWRpdXM6MnB4Oy1tb3otYm9yZGVyLXJhZGl1czoycHg7cG9zaXRpb246YWJzb2x1dGU7ei1pbmRleDoyMTQ3NDgzNjM4O2xlZnQ6MDt0b3A6MDt3aWR0aDphdXRvO2hlaWdodDphdXRvO2JveC1zaGFkb3c6MCAxcHggMCAwICM0YTRhNGEgaW5zZXQ7YmFja2dyb3VuZC1jb2xvcjojNDU0NTQ1O2ZvbnQtZmFtaWx5OkFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjExcHg7Y29sb3I6I2ZmZjt0ZXh0LXNoYWRvdzoxcHggMXB4ICMwMDA7b3ZlcmZsb3c6aGlkZGVufSNjb250cm9sS2l0IC5vcHRpb25zIHVse3dpZHRoOjEwMCU7bGlzdC1zdHlsZTpub25lO21hcmdpbjowO3BhZGRpbmc6MH0jY29udHJvbEtpdCAub3B0aW9ucyB1bCBsaXttYXJnaW46MDt3aWR0aDoxMDAlO2hlaWdodDoyNXB4O2xpbmUtaGVpZ2h0OjI1cHg7cGFkZGluZzowIDIwcHggMCAxMHB4O292ZXJmbG93OmhpZGRlbjt3aGl0ZS1zcGFjZTpub3JtYWw7dGV4dC1vdmVyZmxvdzplbGxpcHNpcztjdXJzb3I6cG9pbnRlcn0jY29udHJvbEtpdCAub3B0aW9ucyB1bCBsaTpob3ZlcntiYWNrZ3JvdW5kLWNvbG9yOiMxZjIzMjV9I2NvbnRyb2xLaXQgLm9wdGlvbnMgdWwgLmxpLXNlbGVjdGVke2JhY2tncm91bmQtY29sb3I6IzI5MmQzMH0jY29udHJvbEtpdCAub3B0aW9ucyAuY29sb3J7LXdlYmtpdC1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW1vei1ib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym94LXNpemluZzpib3JkZXItYm94fSNjb250cm9sS2l0IC5vcHRpb25zIC5jb2xvciAubGktc2VsZWN0ZWQsI2NvbnRyb2xLaXQgLm9wdGlvbnMgLmNvbG9yIGxpey13ZWJraXQtYm94LXNpemluZzpib3JkZXItYm94Oy1tb3otYm94LXNpemluZzpib3JkZXItYm94O2JveC1zaXppbmc6Ym9yZGVyLWJveDtwYWRkaW5nOjA7aGVpZ2h0OjI1cHg7bGluZS1oZWlnaHQ6MjVweDt0ZXh0LWFsaWduOmNlbnRlcn0jY29udHJvbEtpdCAub3B0aW9ucyAuY29sb3IgLmxpLXNlbGVjdGVkOmhvdmVyLCNjb250cm9sS2l0IC5vcHRpb25zIC5jb2xvciBsaTpob3ZlcntiYWNrZ3JvdW5kOjAgMDtmb250LXdlaWdodDo3MDB9I2NvbnRyb2xLaXQgLm9wdGlvbnMgLmNvbG9yIC5saS1zZWxlY3RlZHtmb250LXdlaWdodDo3MDB9I2NvbnRyb2xLaXQgLnBhbmVsIC5sYWJlbCwjY29udHJvbEtpdCAucGlja2VyIC5sYWJlbHt3aWR0aDoxMDAlO2Zsb2F0OmxlZnQ7Zm9udC1zaXplOjExcHg7Zm9udC13ZWlnaHQ6NzAwO3RleHQtc2hhZG93OjAgMXB4ICMwMDA7b3ZlcmZsb3c6aGlkZGVuO3doaXRlLXNwYWNlOm5vd3JhcDt0ZXh0LW92ZXJmbG93OmVsbGlwc2lzO2N1cnNvcjpkZWZhdWx0fSNjb250cm9sS2l0IC5wYW5lbCAuaGVhZCwjY29udHJvbEtpdCAucGFuZWwgLnBhbmVsLWhlYWQtaW5hY3RpdmUsI2NvbnRyb2xLaXQgLnBpY2tlciAuaGVhZHtoZWlnaHQ6MzBweDtwYWRkaW5nOjAgMTBweDtiYWNrZ3JvdW5kOiMxYTFhMWE7b3ZlcmZsb3c6aGlkZGVufSNjb250cm9sS2l0IC5wYW5lbCAuaGVhZCAud3JhcCwjY29udHJvbEtpdCAucGFuZWwgLnBhbmVsLWhlYWQtaW5hY3RpdmUgLndyYXAsI2NvbnRyb2xLaXQgLnBpY2tlciAuaGVhZCAud3JhcHt3aWR0aDphdXRvO2hlaWdodDphdXRvO21hcmdpbjowO3BhZGRpbmc6MDtwb3NpdGlvbjpyZWxhdGl2ZTtvdmVyZmxvdzpoaWRkZW59I2NvbnRyb2xLaXQgLnBhbmVsIC5oZWFkIC5sYWJlbCwjY29udHJvbEtpdCAucGlja2VyIC5oZWFkIC5sYWJlbHtjdXJzb3I6cG9pbnRlcjtsaW5lLWhlaWdodDozMHB4O2NvbG9yOiM2NTY5NmJ9I2NvbnRyb2xLaXQgLnBhbmVsIC5ncm91cC1saXN0IC5ncm91cCAuaGVhZHtoZWlnaHQ6MzhweDtwYWRkaW5nOjAgMTBweDtib3JkZXItdG9wOjFweCBzb2xpZCAjNGY0ZjRmO2JvcmRlci1ib3R0b206MXB4IHNvbGlkICMyNjI2MjY7YmFja2dyb3VuZC1pbWFnZTotby1saW5lYXItZ3JhZGllbnQoIzQ1NDU0NSAwLCMzYjNiM2IgMTAwJSk7YmFja2dyb3VuZC1pbWFnZTpsaW5lYXItZ3JhZGllbnQoIzQ1NDU0NSAwLCMzYjNiM2IgMTAwJSk7Y3Vyc29yOnBvaW50ZXJ9I2NvbnRyb2xLaXQgLnBhbmVsIC5ncm91cC1saXN0IC5ncm91cCAuaGVhZCAubGFiZWx7Zm9udC1zaXplOjEycHg7bGluZS1oZWlnaHQ6MzhweDtjb2xvcjojZmZmfSNjb250cm9sS2l0IC5wYW5lbCAuZ3JvdXAtbGlzdCAuZ3JvdXAgLmhlYWQ6aG92ZXJ7Ym9yZGVyLXRvcDoxcHggc29saWQgIzUyNTI1MjtiYWNrZ3JvdW5kLWltYWdlOi1vLWxpbmVhci1ncmFkaWVudCgjNDU0NTQ1IDAsIzQwNDA0MCAxMDAlKTtiYWNrZ3JvdW5kLWltYWdlOmxpbmVhci1ncmFkaWVudCgjNDU0NTQ1IDAsIzQwNDA0MCAxMDAlKX0jY29udHJvbEtpdCAucGFuZWwgLmdyb3VwLWxpc3QgLmdyb3VwIGxpe2hlaWdodDozNXB4O3BhZGRpbmc6MCAxMHB4fSNjb250cm9sS2l0IC5wYW5lbCAuZ3JvdXAtbGlzdCAuZ3JvdXAgLnN1Yi1ncm91cC1saXN0IC5zdWItZ3JvdXA6bGFzdC1vZi10eXBle2JvcmRlci1ib3R0b206bm9uZX0jY29udHJvbEtpdCAucGFuZWwgLmdyb3VwLWxpc3QgLmdyb3VwIC5zdWItZ3JvdXAtbGlzdCAuc3ViLWdyb3Vwe3BhZGRpbmc6MDtoZWlnaHQ6YXV0bztib3JkZXItYm90dG9tOjFweCBzb2xpZCAjMjQyNDI0fSNjb250cm9sS2l0IC5wYW5lbCAuZ3JvdXAtbGlzdCAuZ3JvdXAgLnN1Yi1ncm91cC1saXN0IC5zdWItZ3JvdXAgdWx7b3ZlcmZsb3c6aGlkZGVufSNjb250cm9sS2l0IC5wYW5lbCAuZ3JvdXAtbGlzdCAuZ3JvdXAgLnN1Yi1ncm91cC1saXN0IC5zdWItZ3JvdXAgdWwgbGl7YmFja2dyb3VuZDojMmUyZTJlO2JvcmRlci1ib3R0b206MXB4IHNvbGlkICMyMjI3Mjl9I2NvbnRyb2xLaXQgLnBhbmVsIC5ncm91cC1saXN0IC5ncm91cCAuc3ViLWdyb3VwLWxpc3QgLnN1Yi1ncm91cCB1bCBsaTpsYXN0LW9mLXR5cGV7Ym9yZGVyLWJvdHRvbTpub25lfSNjb250cm9sS2l0IC5wYW5lbCAuZ3JvdXAtbGlzdCAuZ3JvdXAgLnN1Yi1ncm91cC1saXN0IC5zdWItZ3JvdXA6Zmlyc3QtY2hpbGR7bWFyZ2luLXRvcDowfSNjb250cm9sS2l0IC5wYW5lbCAuZ3JvdXAtbGlzdCAuZ3JvdXAgLnN1Yi1ncm91cC1saXN0IC5zdWItZ3JvdXAgLmhlYWQsI2NvbnRyb2xLaXQgLnBhbmVsIC5ncm91cC1saXN0IC5ncm91cCAuc3ViLWdyb3VwLWxpc3QgLnN1Yi1ncm91cCAuaGVhZC1pbmFjdGl2ZXtjdXJzb3I6cG9pbnRlcn0jY29udHJvbEtpdCAucGFuZWwgLmdyb3VwLWxpc3QgLmdyb3VwIC5zdWItZ3JvdXAtbGlzdCAuc3ViLWdyb3VwIC5oZWFke2hlaWdodDoyN3B4O3BhZGRpbmc6MCAxMHB4O2JvcmRlci10b3A6bm9uZTtib3JkZXItYm90dG9tOjFweCBzb2xpZCAjMjQyNDI0O2JhY2tncm91bmQtaW1hZ2U6bm9uZTtiYWNrZ3JvdW5kLWNvbG9yOiMyNzI3Mjd9I2NvbnRyb2xLaXQgLnBhbmVsIC5ncm91cC1saXN0IC5ncm91cCAuc3ViLWdyb3VwLWxpc3QgLnN1Yi1ncm91cCAuaGVhZDpob3ZlcntiYWNrZ3JvdW5kLWltYWdlOm5vbmU7YmFja2dyb3VuZC1jb2xvcjojMjcyNzI3fSNjb250cm9sS2l0IC5wYW5lbCAuZ3JvdXAtbGlzdCAuZ3JvdXAgLnN1Yi1ncm91cC1saXN0IC5zdWItZ3JvdXAgLmhlYWQtaW5hY3RpdmV7LXdlYmtpdC1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW1vei1ib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym94LXNpemluZzpib3JkZXItYm94O2hlaWdodDoyN3B4O3BhZGRpbmc6MCAxMHB4O2JveC1zaGFkb3c6MCAxcHggMCAwICM0MDQwNDAgaW5zZXQ7YmFja2dyb3VuZC1pbWFnZTotby1saW5lYXItZ3JhZGllbnQoIzNiM2IzYiAwLCMzODM4MzggMTAwJSk7YmFja2dyb3VuZC1pbWFnZTpsaW5lYXItZ3JhZGllbnQoIzNiM2IzYiAwLCMzODM4MzggMTAwJSl9I2NvbnRyb2xLaXQgLnBhbmVsIC5ncm91cC1saXN0IC5ncm91cCAuc3ViLWdyb3VwLWxpc3QgLnN1Yi1ncm91cCAuaGVhZC1pbmFjdGl2ZTpob3Zlcntib3gtc2hhZG93OjAgMXB4IDAgMCAjNDc0NzQ3IGluc2V0O2JhY2tncm91bmQtaW1hZ2U6bm9uZTtiYWNrZ3JvdW5kLWltYWdlOi1vLWxpbmVhci1ncmFkaWVudCgjNDA0MDQwIDAsIzNiM2IzYiAxMDAlKTtiYWNrZ3JvdW5kLWltYWdlOmxpbmVhci1ncmFkaWVudCgjNDA0MDQwIDAsIzNiM2IzYiAxMDAlKX0jY29udHJvbEtpdCAucGFuZWwgLmdyb3VwLWxpc3QgLmdyb3VwIC5zdWItZ3JvdXAtbGlzdCAuc3ViLWdyb3VwIC5oZWFkIC5sYWJlbCwjY29udHJvbEtpdCAucGFuZWwgLmdyb3VwLWxpc3QgLmdyb3VwIC5zdWItZ3JvdXAtbGlzdCAuc3ViLWdyb3VwIC5oZWFkLWluYWN0aXZlIC5sYWJlbHttYXJnaW46MDtwYWRkaW5nOjA7bGluZS1oZWlnaHQ6MjdweDtjb2xvcjojZmZmO2ZvbnQtd2VpZ2h0OjcwMDtmb250LXNpemU6MTFweDt0ZXh0LXNoYWRvdzoxcHggMXB4ICMwMDA7dGV4dC10cmFuc2Zvcm06Y2FwaXRhbGl6ZX0jY29udHJvbEtpdCAucGFuZWwgLmdyb3VwLWxpc3QgLmdyb3VwIC5zdWItZ3JvdXAtbGlzdCAuc3ViLWdyb3VwIC5oZWFkIC53cmFwIC5sYWJlbCwjY29udHJvbEtpdCAucGFuZWwgLmdyb3VwLWxpc3QgLmdyb3VwIC5zdWItZ3JvdXAtbGlzdCAuc3ViLWdyb3VwIC5oZWFkLWluYWN0aXZlIC53cmFwIC5sYWJlbHt3aWR0aDoxMDAlO2ZvbnQtd2VpZ2h0OjcwMDtjb2xvcjojZmZmO3BhZGRpbmc6MH0jY29udHJvbEtpdCAucGFuZWwgLmdyb3VwLWxpc3QgLmdyb3VwIC5zdWItZ3JvdXAtbGlzdCAuc3ViLWdyb3VwIC53cmFwIC5sYWJlbHstd2Via2l0LWJveC1zaXppbmc6Ym9yZGVyLWJveDstbW96LWJveC1zaXppbmc6Ym9yZGVyLWJveDtib3gtc2l6aW5nOmJvcmRlci1ib3g7aGVpZ2h0OjEwMCU7d2lkdGg6MzAlO3BhZGRpbmc6MTJweCA1cHggMCAwO2Zsb2F0OmxlZnQ7Zm9udC1zaXplOjExcHg7Zm9udC13ZWlnaHQ6NDAwO2NvbG9yOiNhZWI1Yjg7dGV4dC1zaGFkb3c6MXB4IDFweCAjMDAwfSNjb250cm9sS2l0IC5wYW5lbCAuZ3JvdXAtbGlzdCAuZ3JvdXAgLnN1Yi1ncm91cC1saXN0IC5zdWItZ3JvdXAgLndyYXAgLndyYXB7LXdlYmtpdC1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW1vei1ib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym94LXNpemluZzpib3JkZXItYm94O3dpZHRoOjcwJTtwYWRkaW5nOjVweCAwIDA7ZmxvYXQ6cmlnaHQ7aGVpZ2h0OjEwMCV9I2NvbnRyb2xLaXQgLnBhbmVsIC5ncm91cC1saXN0IC5ncm91cDpsYXN0LWNoaWxkIC5zY3JvbGwtYnVmZmVyOm50aC1vZi10eXBlKDMpLCNjb250cm9sS2l0IC5wYW5lbCAuZ3JvdXAtbGlzdCAuZ3JvdXA6bGFzdC1jaGlsZCAuc3ViLWdyb3VwLWxpc3R7Ym9yZGVyLWJvdHRvbTpub25lfSNjb250cm9sS2l0IC5wYW5lbCAuc2Nyb2xsLXdyYXB7cG9zaXRpb246cmVsYXRpdmU7b3ZlcmZsb3c6aGlkZGVufSNjb250cm9sS2l0IC5wYW5lbCAuc2Nyb2xsLWJ1ZmZlcnt3aWR0aDoxMDAlO2hlaWdodDo4cHg7Ym9yZGVyLXRvcDoxcHggc29saWQgIzNiNDQ0Nztib3JkZXItYm90dG9tOjFweCBzb2xpZCAjMWUyMjI0fSNjb250cm9sS2l0IC5wYW5lbCAuc2Nyb2xsQmFyey13ZWJraXQtYm94LXNpemluZzpjb250ZW50LWJveDstbW96LWJveC1zaXppbmc6Y29udGVudC1ib3g7Ym94LXNpemluZzpjb250ZW50LWJveDt3aWR0aDoxNXB4O2hlaWdodDoxMDAlO2Zsb2F0OnJpZ2h0O3RvcDowO3BhZGRpbmc6MDttYXJnaW46MDtwb3NpdGlvbjpyZWxhdGl2ZTtiYWNrZ3JvdW5kOiMyMTI2Mjg7YmFja2dyb3VuZC1pbWFnZTpsaW5lYXItZ3JhZGllbnQodG8gcmlnaHQsIzI0MjQyNCAwLCMyZTJlMmUgMTAwJSl9I2NvbnRyb2xLaXQgLnBhbmVsIC5zY3JvbGxCYXIgLnRyYWNre3BhZGRpbmc6MCAzcHggMCAycHh9I2NvbnRyb2xLaXQgLnBhbmVsIC5zY3JvbGxCYXIgLnRyYWNrIC50aHVtYnstd2Via2l0LWJveC1zaXppbmc6Ym9yZGVyLWJveDstbW96LWJveC1zaXppbmc6Ym9yZGVyLWJveDtib3gtc2l6aW5nOmJvcmRlci1ib3g7d2lkdGg6MTFweDtwb3NpdGlvbjphYnNvbHV0ZTtjdXJzb3I6cG9pbnRlcjtiYWNrZ3JvdW5kLWNvbG9yOiMzNDM0MzQ7Ym9yZGVyOjFweCBzb2xpZCAjMWIxZjIxO2JvcmRlci1yYWRpdXM6MTBweDstbW96LWJvcmRlci1yYWRpdXM6MTBweDtib3gtc2hhZG93Omluc2V0IDAgMXB4IDAgMCAjNDM0YjUwfSNjb250cm9sS2l0IC5wYW5lbCAubWVudSwjY29udHJvbEtpdCAucGFuZWwgLm1lbnUtYWN0aXZlLCNjb250cm9sS2l0IC5waWNrZXIgLm1lbnV7ZmxvYXQ6cmlnaHQ7cGFkZGluZzo1cHggMCAwfSNjb250cm9sS2l0IC5wYW5lbCAubWVudSBpbnB1dFt0eXBlPWJ1dHRvbl0sI2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51LWFjdGl2ZSBpbnB1dFt0eXBlPWJ1dHRvbl0sI2NvbnRyb2xLaXQgLnBpY2tlciAubWVudSBpbnB1dFt0eXBlPWJ1dHRvbl17LXdlYmtpdC1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW1vei1ib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym94LXNpemluZzpib3JkZXItYm94O2N1cnNvcjpwb2ludGVyO2hlaWdodDoyMHB4O2JvcmRlcjpub25lO3ZlcnRpY2FsLWFsaWduOnRvcDtib3JkZXItcmFkaXVzOjJweDstbW96LWJvcmRlci1yYWRpdXM6MnB4O2ZvbnQtZmFtaWx5OkFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjEwcHg7Zm9udC13ZWlnaHQ6NzAwO2NvbG9yOiNhYWE7dGV4dC1zaGFkb3c6MCAtMXB4ICMwMDA7dGV4dC10cmFuc2Zvcm06dXBwZXJjYXNlO2JveC1zaGFkb3c6MCAwIDAgMXB4ICMxMzEzMTMgaW5zZXQsLTFweCAycHggMCAwICMyMTI1MjcgaW5zZXQ7b3V0bGluZTowfSNjb250cm9sS2l0IC5wYW5lbCAubWVudSAuYnV0dG9uLW1lbnUtY2xvc2UsI2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51IC5idXR0b24tbWVudS1oaWRlLCNjb250cm9sS2l0IC5wYW5lbCAubWVudSAuYnV0dG9uLW1lbnUtc2hvdywjY29udHJvbEtpdCAucGFuZWwgLm1lbnUtYWN0aXZlIC5idXR0b24tbWVudS1jbG9zZSwjY29udHJvbEtpdCAucGFuZWwgLm1lbnUtYWN0aXZlIC5idXR0b24tbWVudS1oaWRlLCNjb250cm9sS2l0IC5wYW5lbCAubWVudS1hY3RpdmUgLmJ1dHRvbi1tZW51LXNob3csI2NvbnRyb2xLaXQgLnBpY2tlciAubWVudSAuYnV0dG9uLW1lbnUtY2xvc2UsI2NvbnRyb2xLaXQgLnBpY2tlciAubWVudSAuYnV0dG9uLW1lbnUtaGlkZSwjY29udHJvbEtpdCAucGlja2VyIC5tZW51IC5idXR0b24tbWVudS1zaG93e3dpZHRoOjIwcHg7bWFyZ2luLWxlZnQ6NHB4fSNjb250cm9sS2l0IC5wYW5lbCAubWVudSAuYnV0dG9uLW1lbnUtaGlkZSwjY29udHJvbEtpdCAucGFuZWwgLm1lbnUtYWN0aXZlIC5idXR0b24tbWVudS1oaWRlLCNjb250cm9sS2l0IC5waWNrZXIgLm1lbnUgLmJ1dHRvbi1tZW51LWhpZGV7YmFja2dyb3VuZDp1cmwoZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFBZ0FBQUFGQ0FZQUFBQjRrYTFWQUFBQUNYQklXWE1BQUFzVEFBQUxFd0VBbXB3WUFBQUtUMmxEUTFCUWFHOTBiM05vYjNBZ1NVTkRJSEJ5YjJacGJHVUFBSGphblZOblZGUHBGajMzM3ZSQ1M0aUFsRXR2VWhVSUlGSkNpNEFVa1NZcUlRa1FTb2dob2RrVlVjRVJSVVVFRzhpZ2lBT09qb0NNRlZFc0RJb0syQWZrSWFLT2c2T0lpc3I3NFh1amE5YTg5K2JOL3JYWFB1ZXM4NTJ6endmQUNBeVdTRE5STllBTXFVSWVFZUNEeDhURzRlUXVRSUVLSkhBQUVBaXpaQ0Z6L1NNQkFQaCtQRHdySXNBSHZnQUJlTk1MQ0FEQVRadkFNQnlIL3cvcVFwbGNBWUNFQWNCMGtUaExDSUFVQUVCNmprS21BRUJHQVlDZG1DWlRBS0FFQUdETFkyTGpBRkF0QUdBbmYrYlRBSUNkK0psN0FRQmJsQ0VWQWFDUkFDQVRaWWhFQUdnN0FLelBWb3BGQUZnd0FCUm1TOFE1QU5ndEFEQkpWMlpJQUxDM0FNRE9FQXV5QUFnTUFEQlJpSVVwQUFSN0FHRElJeU40QUlTWkFCUkc4bGM4OFN1dUVPY3FBQUI0bWJJOHVTUTVSWUZiQ0MxeEIxZFhMaDRvemtrWEt4UTJZUUpobWtBdXdubVpHVEtCTkEvZzg4d0FBS0NSRlJIZ2cvUDllTTRPcnM3T05vNjJEbDh0NnI4Ry95SmlZdVArNWMrcmNFQUFBT0YwZnRIK0xDK3pHb0E3Qm9CdC9xSWw3Z1JvWGd1Z2RmZUxacklQUUxVQW9PbmFWL053K0g0OFBFV2hrTG5aMmVYazVOaEt4RUpiWWNwWGZmNW53bC9BVi8xcytYNDgvUGYxNEw3aUpJRXlYWUZIQlBqZ3dzejBUS1VjejVJSmhHTGM1bzlIL0xjTC8vd2QweUxFU1dLNVdDb1U0MUVTY1k1RW1venpNcVVpaVVLU0tjVWwwdjlrNHQ4cyt3TSszelVBc0dvK0FYdVJMYWhkWXdQMlN5Y1FXSFRBNHZjQUFQSzdiOEhVS0FnRGdHaUQ0YzkzLys4Ly9VZWdKUUNBWmttU2NRQUFYa1FrTGxUS3N6L0hDQUFBUktDQktyQkJHL1RCR0N6QUJoekJCZHpCQy94Z05vUkNKTVRDUWhCQ0NtU0FISEpnS2F5Q1FpaUd6YkFkS21BdjFFQWROTUJSYUlhVGNBNHV3bFc0RGoxd0QvcGhDSjdCS0x5QkNRUkJ5QWdUWVNIYWlBRmlpbGdqamdnWG1ZWDRJY0ZJQkJLTEpDREppQlJSSWt1Uk5VZ3hVb3BVSUZWSUhmSTljZ0k1aDF4R3VwRTd5QUF5Z3Z5R3ZFY3hsSUd5VVQzVURMVkR1YWczR29SR29ndlFaSFF4bW84V29KdlFjclFhUFl3Mm9lZlFxMmdQMm84K1E4Y3d3T2dZQnpQRWJEQXV4c05Dc1Rnc0NaTmp5N0VpckF5cnhocXdWcXdEdTRuMVk4K3hkd1FTZ1VYQUNUWUVkMElnWVI1QlNGaE1XRTdZU0tnZ0hDUTBFZG9KTndrRGhGSENKeUtUcUV1MEpyb1IrY1FZWWpJeGgxaElMQ1BXRW84VEx4QjdpRVBFTnlRU2lVTXlKN21RQWtteHBGVFNFdEpHMG01U0kra3NxWnMwU0Jvams4bmFaR3V5QnptVUxDQXJ5SVhrbmVURDVEUGtHK1FoOGxzS25XSkFjYVQ0VStJb1VzcHFTaG5sRU9VMDVRWmxtREpCVmFPYVV0Mm9vVlFSTlk5YVFxMmh0bEt2VVllb0V6UjFtam5OZ3haSlM2V3RvcFhUR21nWGFQZHByK2gwdWhIZGxSNU9sOUJYMHN2cFIraVg2QVAwZHd3TmhoV0R4NGhuS0JtYkdBY1laeGwzR0srWVRLWVowNHNaeDFRd056SHJtT2VaRDVsdlZWZ3F0aXA4RlpIS0NwVktsU2FWR3lvdlZLbXFwcXJlcWd0VjgxWExWSStwWGxOOXJrWlZNMVBqcVFuVWxxdFZxcDFRNjFNYlUyZXBPNmlIcW1lb2IxUS9wSDVaL1lrR1djTk13MDlEcEZHZ3NWL2p2TVlnQzJNWnMzZ3NJV3NOcTRaMWdUWEVKckhOMlh4MktydVkvUjI3aXoycXFhRTVRek5LTTFlelV2T1VaajhINDVoeCtKeDBUZ25uS0tlWDgzNkszaFR2S2VJcEc2WTBUTGt4WlZ4cnFwYVhsbGlyU0t0UnEwZnJ2VGF1N2FlZHByMUZ1MW43Z1E1Qngwb25YQ2RIWjQvT0JaM25VOWxUM2FjS3B4Wk5QVHIxcmk2cWE2VWJvYnRFZDc5dXArNllucjVlZ0o1TWI2ZmVlYjNuK2h4OUwvMVUvVzM2cC9WSERGZ0dzd3drQnRzTXpoZzh4VFZ4Ynp3ZEw4ZmI4VkZEWGNOQVE2VmhsV0dYNFlTUnVkRThvOVZHalVZUGpHbkdYT01rNDIzR2JjYWpKZ1ltSVNaTFRlcE43cHBTVGJtbUthWTdURHRNeDgzTXphTE4xcGsxbXoweDF6TG5tK2ViMTV2ZnQyQmFlRm9zdHFpMnVHVkpzdVJhcGxudXRyeHVoVm81V2FWWVZWcGRzMGF0bmEwbDFydXR1NmNScDdsT2swNnJudFpudzdEeHRzbTJxYmNac09YWUJ0dXV0bTIyZldGblloZG50OFd1dys2VHZaTjl1bjJOL1QwSERZZlpEcXNkV2gxK2M3UnlGRHBXT3Q2YXpwenVQMzNGOUpicEwyZFl6eERQMkRQanRoUExLY1JwblZPYjAwZG5GMmU1YzRQemlJdUpTNExMTHBjK0xwc2J4dDNJdmVSS2RQVnhYZUY2MHZXZG03T2J3dTJvMjYvdU51NXA3b2Zjbjh3MG55bWVXVE56ME1QSVErQlI1ZEUvQzUrVk1HdmZySDVQUTArQlo3WG5JeTlqTDVGWHJkZXd0NlYzcXZkaDd4Yys5ajV5bitNKzR6dzMzakxlV1YvTU44QzN5TGZMVDhOdm5sK0YzME4vSS85ay8zci8wUUNuZ0NVQlp3T0pnVUdCV3dMNytIcDhJYitPUHpyYlpmYXkyZTFCaktDNVFSVkJqNEt0Z3VYQnJTRm95T3lRclNIMzU1ak9rYzVwRG9WUWZ1alcwQWRoNW1HTHczNE1KNFdIaFZlR1A0NXdpRmdhMFRHWE5YZlIzRU56MzBUNlJKWkUzcHRuTVU4NXJ5MUtOU28rcWk1cVBObzN1alM2UDhZdVpsbk0xVmlkV0Vsc1N4dzVMaXF1Tm01c3Z0Lzg3Zk9INHAzaUMrTjdGNWd2eUYxd2VhSE93dlNGcHhhcExoSXNPcFpBVEloT09KVHdRUkFxcUJhTUpmSVRkeVdPQ25uQ0hjSm5JaS9STnRHSTJFTmNLaDVPOGtncVRYcVM3Skc4Tlhra3hUT2xMT1c1aENlcGtMeE1EVXpkbXpxZUZwcDJJRzB5UFRxOU1ZT1NrWkJ4UXFvaFRaTzJaK3BuNW1aMnk2eGxoYkwreFc2THR5OGVsUWZKYTdPUXJBVlpMUXEyUXFib1ZGb28xeW9Ic21kbFYyYS96WW5LT1phcm5pdk43Y3l6eXR1UU41enZuLy90RXNJUzRaSzJwWVpMVnkwZFdPYTlyR281c2p4eGVkc0s0eFVGSzRaV0Jxdzh1SXEyS20zVlQ2dnRWNWV1ZnIwbWVrMXJnVjdCeW9MQnRRRnI2d3RWQ3VXRmZldmMxKzFkVDFndldkKzFZZnFHblJzK0ZZbUtyaFRiRjVjVmY5Z28zSGpsRzRkdnlyK1ozSlMwcWF2RXVXVFBadEptNmViZUxaNWJEcGFxbCthWERtNE4yZHEwRGQ5V3RPMzE5a1hiTDVmTktOdTdnN1pEdWFPL1BMaThaYWZKenMwN1AxU2tWUFJVK2xRMjd0TGR0V0hYK0c3UjdodDd2UFkwN05YYlc3ejMvVDdKdnR0VkFWVk4xV2JWWmZ0Sis3UDNQNjZKcXVuNGx2dHRYYTFPYlhIdHh3UFNBLzBISXc2MjE3blUxUjNTUFZSU2o5WXI2MGNPeHgrKy9wM3ZkeTBOTmcxVmpaekc0aU53UkhuazZmY0ozL2NlRFRyYWRveDdyT0VIMHg5MkhXY2RMMnBDbXZLYVJwdFRtdnRiWWx1NlQ4dyswZGJxM25yOFI5c2ZENXcwUEZsNVN2TlV5V25hNllMVGsyZnl6NHlkbFoxOWZpNzUzR0Rib3JaNzUyUE8zMm9QYisrNkVIVGgwa1gvaStjN3ZEdk9YUEs0ZFBLeTIrVVRWN2hYbXE4NlgyM3FkT284L3BQVFQ4ZTduTHVhcnJsY2E3bnVlcjIxZTJiMzZSdWVOODdkOUwxNThSYi8xdFdlT1QzZHZmTjZiL2ZGOS9YZkZ0MStjaWY5enN1NzJYY243cTI4VDd4ZjlFRHRRZGxEM1lmVlAxdiszTmp2M0g5cXdIZWc4OUhjUi9jR2hZUFAvcEgxanc5REJZK1pqOHVHRFlicm5qZytPVG5pUDNMOTZmeW5RODlrenlhZUYvNmkvc3V1RnhZdmZ2alY2OWZPMFpqUm9aZnlsNU8vYlh5bC9lckE2eG12MjhiQ3hoNit5WGd6TVY3MFZ2dnR3WGZjZHgzdm85OFBUK1I4SUg4by8yajVzZlZUMEtmN2t4bVRrLzhFQTVqei9HTXpMZHNBQUFBZ1kwaFNUUUFBZWlVQUFJQ0RBQUQ1L3dBQWdPa0FBSFV3QUFEcVlBQUFPcGdBQUJkdmtsL0ZSZ0FBQUdSSlJFRlVlTnBpZFBVTllvQ0JVMGNPMURNd01EQ1kyVGcwd3NSWWtDVmxGWlVib0d5NEltWmxkVTI0cEp5U0NnTy9vQkFEQXdPRHcvVkw1eG1rNVJRT01yOTkvUkl1Q1FQSWlsak1iQndZR0JnWUdINy8vTW1BRENTbFpSa2twV1VaQUFNQXZUc2dYQnZPc3EwQUFBQUFTVVZPUks1Q1lJST0pIDUwJSA1MCUgbm8tcmVwZWF0LCMxYTFkMWZ9I2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51IC5idXR0b24tbWVudS1oaWRlOmhvdmVyLCNjb250cm9sS2l0IC5wYW5lbCAubWVudS1hY3RpdmUgLmJ1dHRvbi1tZW51LWhpZGU6aG92ZXIsI2NvbnRyb2xLaXQgLnBpY2tlciAubWVudSAuYnV0dG9uLW1lbnUtaGlkZTpob3ZlcntiYWNrZ3JvdW5kOnVybChkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFnQUFBQUZDQVlBQUFCNGthMVZBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBR1JKUkVGVWVOcGlkUFVOWW9DQlUwY08xRE13TURDWTJUZzB3c1JZa0NWbEZaVWJvR3k0SW1abGRVMjRwSnlTQ2dPL29CQURBd09Edy9WTDV4bWs1UlFPTXI5OS9SSXVDUVBJaWxqTWJCd1lHQmdZR0g3Ly9NbUFEQ1NsWlJra3BXVVpBQU1BdlRzZ1hCdk9zcTBBQUFBQVNVVk9SSzVDWUlJPSkgNTAlIDUwJSBuby1yZXBlYXQsIzAwMDtib3gtc2hhZG93OiNmZmYgMCwjMDAwIDEwMCV9I2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51IC5idXR0b24tbWVudS1zaG93LCNjb250cm9sS2l0IC5wYW5lbCAubWVudS1hY3RpdmUgLmJ1dHRvbi1tZW51LXNob3csI2NvbnRyb2xLaXQgLnBpY2tlciAubWVudSAuYnV0dG9uLW1lbnUtc2hvd3tiYWNrZ3JvdW5kOnVybChkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFnQUFBQUZDQVlBQUFCNGthMVZBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBRnBKUkVGVWVOcHNqREVPZ0NBUUJPYzRlcU5mb0NCOHdNckNud2svODJFSFdFa3djYXRKWnJLeXJGc0dMdjVYL0g2Y3FQYzQxWTlwdFZMTjBCRFQzVnNURVRuRnVWa1dJR3VJQ1dCRXZmY2hBZnowbXF2WjRCZWVBUUR6VmlNekp5MFJYZ0FBQUFCSlJVNUVya0pnZ2c9PSkgNTAlIDUwJSBuby1yZXBlYXQsIzFhMWQxZn0jY29udHJvbEtpdCAucGFuZWwgLm1lbnUgLmJ1dHRvbi1tZW51LXNob3c6aG92ZXIsI2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51LWFjdGl2ZSAuYnV0dG9uLW1lbnUtc2hvdzpob3ZlciwjY29udHJvbEtpdCAucGlja2VyIC5tZW51IC5idXR0b24tbWVudS1zaG93OmhvdmVye2JhY2tncm91bmQ6dXJsKGRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQWdBQUFBRkNBWUFBQUI0a2ExVkFBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFLVDJsRFExQlFhRzkwYjNOb2IzQWdTVU5ESUhCeWIyWnBiR1VBQUhqYW5WTm5WRlBwRmozMzN2UkNTNGlBbEV0dlVoVUlJRkpDaTRBVWtTWXFJUWtRU29naG9ka1ZVY0VSUlVVRUc4aWdpQU9Pam9DTUZWRXNESW9LMkFma0lhS09nNk9JaXNyNzRYdWphOWE4OStiTi9yWFhQdWVzODUyenp3ZkFDQXlXU0ROUk5ZQU1xVUllRWVDRHg4VEc0ZVF1UUlFS0pIQUFFQWl6WkNGei9TTUJBUGgrUER3cklzQUh2Z0FCZU5NTENBREFUWnZBTUJ5SC93L3FRcGxjQVlDRUFjQjBrVGhMQ0lBVUFFQjZqa0ttQUVCR0FZQ2RtQ1pUQUtBRUFHRExZMkxqQUZBdEFHQW5mK2JUQUlDZCtKbDdBUUJibENFVkFhQ1JBQ0FUWlloRUFHZzdBS3pQVm9wRkFGZ3dBQlJtUzhRNUFOZ3RBREJKVjJaSUFMQzNBTURPRUF1eUFBZ01BREJSaUlVcEFBUjdBR0RJSXlONEFJU1pBQlJHOGxjODhTdXVFT2NxQUFCNG1iSTh1U1E1UllGYkNDMXhCMWRYTGg0b3pra1hLeFEyWVFKaG1rQXV3bm1aR1RLQk5BL2c4OHdBQUtDUkZSSGdnL1A5ZU00T3JzN09ObzYyRGw4dDZyOEcveUppWXVQKzVjK3JjRUFBQU9GMGZ0SCtMQyt6R29BN0JvQnQvcUlsN2dSb1hndWdkZmVMWnJJUFFMVUFvT25hVi9OdytINDhQRVdoa0xuWjJlWGs1TmhLeEVKYlljcFhmZjVud2wvQVYvMXMrWDQ4L1BmMTRMN2lKSUV5WFlGSEJQamd3c3owVEtVY3o1SUpoR0xjNW85SC9MY0wvL3dkMHlMRVNXSzVXQ29VNDFFU2NZNUVtb3p6TXFVaWlVS1NLY1VsMHY5azR0OHMrd00rM3pVQXNHbytBWHVSTGFoZFl3UDJTeWNRV0hUQTR2Y0FBUEs3YjhIVUtBZ0RnR2lENGM5My8rOC8vVWVnSlFDQVprbVNjUUFBWGtRa0xsVEtzei9IQ0FBQVJLQ0JLckJCRy9UQkdDekFCaHpCQmR6QkMveGdOb1JDSk1UQ1FoQkNDbVNBSEhKZ0theUNRaWlHemJBZEttQXYxRUFkTk1CUmFJYVRjQTR1d2xXNERqMXdEL3BoQ0o3QktMeUJDUVJCeUFnVFlTSGFpQUZpaWxnampnZ1htWVg0SWNGSUJCS0xKQ0RKaUJSUklrdVJOVWd4VW9wVUlGVklIZkk5Y2dJNWgxeEd1cEU3eUFBeWd2eUd2RWN4bElHeVVUM1VETFZEdWFnM0dvUkdvZ3ZRWkhReG1vOFdvSnZRY3JRYVBZdzJvZWZRcTJnUDJvOCtROGN3d09nWUJ6UEViREF1eHNOQ3NUZ3NDWk5qeTdFaXJBeXJ4aHF3VnF3RHU0bjFZOCt4ZHdRU2dVWEFDVFlFZDBJZ1lSNUJTRmhNV0U3WVNLZ2dIQ1EwRWRvSk53a0RoRkhDSnlLVHFFdTBKcm9SK2NRWVlqSXhoMWhJTENQV0VvOFRMeEI3aUVQRU55UVNpVU15SjdtUUFrbXhwRlRTRXRKRzBtNVNJK2tzcVpzMFNCb2prOG5hWkd1eUJ6bVVMQ0FyeUlYa25lVEQ1RFBrRytRaDhsc0tuV0pBY2FUNFUrSW9Vc3BxU2hubEVPVTA1UVpsbURKQlZhT2FVdDJvb1ZRUk5ZOWFRcTJodGxLdlVZZW9FelIxbWpuTmd4WkpTNld0b3BYVEdtZ1hhUGRwcitoMHVoSGRsUjVPbDlCWDBzdnBSK2lYNkFQMGR3d05oaFdEeDRobktCbWJHQWNZWnhsM0dLK1lUS1laMDRzWngxUXdOekhybU9lWkQ1bHZWVmdxdGlwOEZaSEtDcFZLbFNhVkd5b3ZWS21xcHFyZXFndFY4MVhMVkkrcFhsTjlya1pWTTFQanFRblVscXRWcXAxUTYxTWJVMmVwTzZpSHFtZW9iMVEvcEg1Wi9Za0dXY05NdzA5RHBGR2dzVi9qdk1ZZ0MyTVpzM2dzSVdzTnE0WjFnVFhFSnJITjJYeDJLcnVZL1IyN2l6MnFxYUU1UXpOS00xZXpVdk9VWmo4SDQ1aHgrSngwVGdubktLZVg4MzZLM2hUdktlSXBHNlkwVExreFpWeHJxcGFYbGxpclNLdFJxMGZydlRhdTdhZWRwcjFGdTFuN2dRNUJ4MG9uWENkSFo0L09CWjNuVTlsVDNhY0tweFpOUFRyMXJpNnFhNlVib2J0RWQ3OXVwKzZZbnI1ZWdKNU1iNmZlZWIzbitoeDlMLzFVL1czNnAvVkhERmdHc3d3a0J0c016aGc4eFRWeGJ6d2RMOGZiOFZGRFhjTkFRNlZobFdHWDRZU1J1ZEU4bzlWR2pVWVBqR25HWE9NazQyM0diY2FqSmdZbUlTWkxUZXBON3BwU1RibW1LYVk3VER0TXg4M016YUxOMXBrMW16MHgxekxubStlYjE1dmZ0MkJhZUZvc3RxaTJ1R1ZKc3VSYXBsbnV0cnh1aFZvNVdhVllWVnBkczBhdG5hMGwxcnV0dTZjUnA3bE9rMDZybnRabnc3RHh0c20ycWJjWnNPWFlCdHV1dG0yMmZXRm5ZaGRudDhXdXcrNlR2Wk45dW4yTi9UMEhEWWZaRHFzZFdoMStjN1J5RkRwV090NmF6cHp1UDMzRjlKYnBMMmRZenhEUDJEUGp0aFBMS2NScG5WT2IwMGRuRjJlNWM0UHppSXVKUzRMTExwYytMcHNieHQzSXZlUktkUFZ4WGVGNjB2V2RtN09id3UybzI2L3VOdTVwN29mY244dzBueW1lV1ROejBNUElRK0JSNWRFL0M1K1ZNR3Zmckg1UFEwK0JaN1huSXk5akw1RlhyZGV3dDZWM3F2ZGg3eGMrOWo1eW4rTSs0enczM2pMZVdWL01OOEMzeUxmTFQ4TnZubCtGMzBOL0kvOWsvM3IvMFFDbmdDVUJad09KZ1VHQld3TDcrSHA4SWIrT1B6cmJaZmF5MmUxQmpLQzVRUlZCajRLdGd1WEJyU0ZveU95UXJTSDM1NWpPa2M1cERvVlFmdWpXMEFkaDVtR0x3MzRNSjRXSGhWZUdQNDV3aUZnYTBUR1hOWGZSM0VOejMwVDZSSlpFM3B0bk1VODVyeTFLTlNvK3FpNXFQTm8zdWpTNlA4WXVabG5NMVZpZFdFbHNTeHc1TGlxdU5tNXN2dC84N2ZPSDRwM2lDK043RjVndnlGMXdlYUhPd3ZTRnB4YXBMaElzT3BaQVRJaE9PSlR3UVJBcXFCYU1KZklUZHlXT0NubkNIY0puSWkvUk50R0kyRU5jS2g1TzhrZ3FUWHFTN0pHOE5Ya2t4VE9sTE9XNWhDZXBrTHhNRFV6ZG16cWVGcHAySUcweVBUcTlNWU9Ta1pCeFFxb2hUWk8yWitwbjVtWjJ5NnhsaGJMK3hXNkx0eThlbFFmSmE3T1FyQVZaTFFxMlFxYm9WRm9vMXlvSHNtZGxWMmEvelluS09aYXJuaXZON2N5enl0dVFONXp2bi8vdEVzSVM0WksycFlaTFZ5MGRXT2E5ckdvNXNqeHhlZHNLNHhVRks0WldCcXc4dUlxMkttM1ZUNnZ0VjVldWZyMG1lazFyZ1Y3QnlvTEJ0UUZyNnd0VkN1V0ZmZXZjMSsxZFQxZ3ZXZCsxWWZxR25ScytGWW1LcmhUYkY1Y1ZmOWdvM0hqbEc0ZHZ5citaM0pTMHFhdkV1V1RQWnRKbTZlYmVMWjViRHBhcWwrYVhEbTROMmRxMERkOVd0TzMxOWtYYkw1Zk5LTnU3ZzdaRHVhTy9QTGk4WmFmSnpzMDdQMVNrVlBSVStsUTI3dExkdFdIWCtHN1I3aHQ3dlBZMDdOWGJXN3ozL1Q3SnZ0dFZBVlZOMVdiVlpmdEorN1AzUDY2SnF1bjRsdnR0WGExT2JYSHR4d1BTQS8wSEl3NjIxN25VMVIzU1BWUlNqOVlyNjBjT3h4KysvcDN2ZHkwTk5nMVZqWnpHNGlOd1JIbms2ZmNKMy9jZURUcmFkb3g3ck9FSDB4OTJIV2NkTDJwQ212S2FScHRUbXZ0YllsdTZUOHcrMGRicTNucjhSOXNmRDV3MFBGbDVTdk5VeVduYTZZTFRrMmZ5ejR5ZGxaMTlmaTc1M0dEYm9yWjc1MlBPMzJvUGIrKzZFSFRoMGtYL2krYzd2RHZPWFBLNGRQS3kyK1VUVjdoWG1xODZYMjNxZE9vOC9wUFRUOGU3bkx1YXJybGNhN251ZXIyMWUyYjM2UnVlTjg3ZDlMMTU4UmIvMXRXZU9UM2R2Zk42Yi9mRjkvWGZGdDErY2lmOXpzdTcyWGNuN3EyOFQ3eGY5RUR0UWRsRDNZZlZQMXYrM05qdjNIOXF3SGVnODlIY1IvY0doWVBQL3BIMWp3OURCWStaajh1R0RZYnJuamcrT1RuaVAzTDk2ZnluUTg5a3p5YWVGLzZpL3N1dUZ4WXZmdmpWNjlmTzBaalJvWmZ5bDVPL2JYeWwvZXJBNnhtdjI4YkN4aDYreVhnek1WNzBWdnZ0d1hmY2R4M3ZvOThQVCtSOElIOG8vMmo1c2ZWVDBLZjdreG1Uay84RUE1anovR016TGRzQUFBQWdZMGhTVFFBQWVpVUFBSUNEQUFENS93QUFnT2tBQUhVd0FBRHFZQUFBT3BnQUFCZHZrbC9GUmdBQUFGcEpSRUZVZU5wc2pERU9nQ0FRQk9jNGVxTmZvQ0I4d01yQ253ay84MkVIV0Vrd2NhdEpackt5ckZzR0x2NVgvSDZjcVBjNDFZOXB0VkxOMEJEVDNWc1RFVG5GdVZrV0lHdUlDV0JFdmZjaEFmejBtcXZaNEJlZUFRRHpWaU16SnkwUlhnQUFBQUJKUlU1RXJrSmdnZz09KSA1MCUgNTAlIG5vLXJlcGVhdCwjMDAwO2JveC1zaGFkb3c6I2ZmZiAwLCMwMDAgMTAwJX0jY29udHJvbEtpdCAucGFuZWwgLm1lbnUgLmJ1dHRvbi1tZW51LWNsb3NlLCNjb250cm9sS2l0IC5wYW5lbCAubWVudS1hY3RpdmUgLmJ1dHRvbi1tZW51LWNsb3NlLCNjb250cm9sS2l0IC5waWNrZXIgLm1lbnUgLmJ1dHRvbi1tZW51LWNsb3Nle2JhY2tncm91bmQ6dXJsKGRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQWdBQUFBSkNBWUFBQUFQVTIwdUFBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFLVDJsRFExQlFhRzkwYjNOb2IzQWdTVU5ESUhCeWIyWnBiR1VBQUhqYW5WTm5WRlBwRmozMzN2UkNTNGlBbEV0dlVoVUlJRkpDaTRBVWtTWXFJUWtRU29naG9ka1ZVY0VSUlVVRUc4aWdpQU9Pam9DTUZWRXNESW9LMkFma0lhS09nNk9JaXNyNzRYdWphOWE4OStiTi9yWFhQdWVzODUyenp3ZkFDQXlXU0ROUk5ZQU1xVUllRWVDRHg4VEc0ZVF1UUlFS0pIQUFFQWl6WkNGei9TTUJBUGgrUER3cklzQUh2Z0FCZU5NTENBREFUWnZBTUJ5SC93L3FRcGxjQVlDRUFjQjBrVGhMQ0lBVUFFQjZqa0ttQUVCR0FZQ2RtQ1pUQUtBRUFHRExZMkxqQUZBdEFHQW5mK2JUQUlDZCtKbDdBUUJibENFVkFhQ1JBQ0FUWlloRUFHZzdBS3pQVm9wRkFGZ3dBQlJtUzhRNUFOZ3RBREJKVjJaSUFMQzNBTURPRUF1eUFBZ01BREJSaUlVcEFBUjdBR0RJSXlONEFJU1pBQlJHOGxjODhTdXVFT2NxQUFCNG1iSTh1U1E1UllGYkNDMXhCMWRYTGg0b3pra1hLeFEyWVFKaG1rQXV3bm1aR1RLQk5BL2c4OHdBQUtDUkZSSGdnL1A5ZU00T3JzN09ObzYyRGw4dDZyOEcveUppWXVQKzVjK3JjRUFBQU9GMGZ0SCtMQyt6R29BN0JvQnQvcUlsN2dSb1hndWdkZmVMWnJJUFFMVUFvT25hVi9OdytINDhQRVdoa0xuWjJlWGs1TmhLeEVKYlljcFhmZjVud2wvQVYvMXMrWDQ4L1BmMTRMN2lKSUV5WFlGSEJQamd3c3owVEtVY3o1SUpoR0xjNW85SC9MY0wvL3dkMHlMRVNXSzVXQ29VNDFFU2NZNUVtb3p6TXFVaWlVS1NLY1VsMHY5azR0OHMrd00rM3pVQXNHbytBWHVSTGFoZFl3UDJTeWNRV0hUQTR2Y0FBUEs3YjhIVUtBZ0RnR2lENGM5My8rOC8vVWVnSlFDQVprbVNjUUFBWGtRa0xsVEtzei9IQ0FBQVJLQ0JLckJCRy9UQkdDekFCaHpCQmR6QkMveGdOb1JDSk1UQ1FoQkNDbVNBSEhKZ0theUNRaWlHemJBZEttQXYxRUFkTk1CUmFJYVRjQTR1d2xXNERqMXdEL3BoQ0o3QktMeUJDUVJCeUFnVFlTSGFpQUZpaWxnampnZ1htWVg0SWNGSUJCS0xKQ0RKaUJSUklrdVJOVWd4VW9wVUlGVklIZkk5Y2dJNWgxeEd1cEU3eUFBeWd2eUd2RWN4bElHeVVUM1VETFZEdWFnM0dvUkdvZ3ZRWkhReG1vOFdvSnZRY3JRYVBZdzJvZWZRcTJnUDJvOCtROGN3d09nWUJ6UEViREF1eHNOQ3NUZ3NDWk5qeTdFaXJBeXJ4aHF3VnF3RHU0bjFZOCt4ZHdRU2dVWEFDVFlFZDBJZ1lSNUJTRmhNV0U3WVNLZ2dIQ1EwRWRvSk53a0RoRkhDSnlLVHFFdTBKcm9SK2NRWVlqSXhoMWhJTENQV0VvOFRMeEI3aUVQRU55UVNpVU15SjdtUUFrbXhwRlRTRXRKRzBtNVNJK2tzcVpzMFNCb2prOG5hWkd1eUJ6bVVMQ0FyeUlYa25lVEQ1RFBrRytRaDhsc0tuV0pBY2FUNFUrSW9Vc3BxU2hubEVPVTA1UVpsbURKQlZhT2FVdDJvb1ZRUk5ZOWFRcTJodGxLdlVZZW9FelIxbWpuTmd4WkpTNld0b3BYVEdtZ1hhUGRwcitoMHVoSGRsUjVPbDlCWDBzdnBSK2lYNkFQMGR3d05oaFdEeDRobktCbWJHQWNZWnhsM0dLK1lUS1laMDRzWngxUXdOekhybU9lWkQ1bHZWVmdxdGlwOEZaSEtDcFZLbFNhVkd5b3ZWS21xcHFyZXFndFY4MVhMVkkrcFhsTjlya1pWTTFQanFRblVscXRWcXAxUTYxTWJVMmVwTzZpSHFtZW9iMVEvcEg1Wi9Za0dXY05NdzA5RHBGR2dzVi9qdk1ZZ0MyTVpzM2dzSVdzTnE0WjFnVFhFSnJITjJYeDJLcnVZL1IyN2l6MnFxYUU1UXpOS00xZXpVdk9VWmo4SDQ1aHgrSngwVGdubktLZVg4MzZLM2hUdktlSXBHNlkwVExreFpWeHJxcGFYbGxpclNLdFJxMGZydlRhdTdhZWRwcjFGdTFuN2dRNUJ4MG9uWENkSFo0L09CWjNuVTlsVDNhY0tweFpOUFRyMXJpNnFhNlVib2J0RWQ3OXVwKzZZbnI1ZWdKNU1iNmZlZWIzbitoeDlMLzFVL1czNnAvVkhERmdHc3d3a0J0c016aGc4eFRWeGJ6d2RMOGZiOFZGRFhjTkFRNlZobFdHWDRZU1J1ZEU4bzlWR2pVWVBqR25HWE9NazQyM0diY2FqSmdZbUlTWkxUZXBON3BwU1RibW1LYVk3VER0TXg4M016YUxOMXBrMW16MHgxekxubStlYjE1dmZ0MkJhZUZvc3RxaTJ1R1ZKc3VSYXBsbnV0cnh1aFZvNVdhVllWVnBkczBhdG5hMGwxcnV0dTZjUnA3bE9rMDZybnRabnc3RHh0c20ycWJjWnNPWFlCdHV1dG0yMmZXRm5ZaGRudDhXdXcrNlR2Wk45dW4yTi9UMEhEWWZaRHFzZFdoMStjN1J5RkRwV090NmF6cHp1UDMzRjlKYnBMMmRZenhEUDJEUGp0aFBMS2NScG5WT2IwMGRuRjJlNWM0UHppSXVKUzRMTExwYytMcHNieHQzSXZlUktkUFZ4WGVGNjB2V2RtN09id3UybzI2L3VOdTVwN29mY244dzBueW1lV1ROejBNUElRK0JSNWRFL0M1K1ZNR3Zmckg1UFEwK0JaN1huSXk5akw1RlhyZGV3dDZWM3F2ZGg3eGMrOWo1eW4rTSs0enczM2pMZVdWL01OOEMzeUxmTFQ4TnZubCtGMzBOL0kvOWsvM3IvMFFDbmdDVUJad09KZ1VHQld3TDcrSHA4SWIrT1B6cmJaZmF5MmUxQmpLQzVRUlZCajRLdGd1WEJyU0ZveU95UXJTSDM1NWpPa2M1cERvVlFmdWpXMEFkaDVtR0x3MzRNSjRXSGhWZUdQNDV3aUZnYTBUR1hOWGZSM0VOejMwVDZSSlpFM3B0bk1VODVyeTFLTlNvK3FpNXFQTm8zdWpTNlA4WXVabG5NMVZpZFdFbHNTeHc1TGlxdU5tNXN2dC84N2ZPSDRwM2lDK043RjVndnlGMXdlYUhPd3ZTRnB4YXBMaElzT3BaQVRJaE9PSlR3UVJBcXFCYU1KZklUZHlXT0NubkNIY0puSWkvUk50R0kyRU5jS2g1TzhrZ3FUWHFTN0pHOE5Ya2t4VE9sTE9XNWhDZXBrTHhNRFV6ZG16cWVGcHAySUcweVBUcTlNWU9Ta1pCeFFxb2hUWk8yWitwbjVtWjJ5NnhsaGJMK3hXNkx0eThlbFFmSmE3T1FyQVZaTFFxMlFxYm9WRm9vMXlvSHNtZGxWMmEvelluS09aYXJuaXZON2N5enl0dVFONXp2bi8vdEVzSVM0WksycFlaTFZ5MGRXT2E5ckdvNXNqeHhlZHNLNHhVRks0WldCcXc4dUlxMkttM1ZUNnZ0VjVldWZyMG1lazFyZ1Y3QnlvTEJ0UUZyNnd0VkN1V0ZmZXZjMSsxZFQxZ3ZXZCsxWWZxR25ScytGWW1LcmhUYkY1Y1ZmOWdvM0hqbEc0ZHZ5citaM0pTMHFhdkV1V1RQWnRKbTZlYmVMWjViRHBhcWwrYVhEbTROMmRxMERkOVd0TzMxOWtYYkw1Zk5LTnU3ZzdaRHVhTy9QTGk4WmFmSnpzMDdQMVNrVlBSVStsUTI3dExkdFdIWCtHN1I3aHQ3dlBZMDdOWGJXN3ozL1Q3SnZ0dFZBVlZOMVdiVlpmdEorN1AzUDY2SnF1bjRsdnR0WGExT2JYSHR4d1BTQS8wSEl3NjIxN25VMVIzU1BWUlNqOVlyNjBjT3h4KysvcDN2ZHkwTk5nMVZqWnpHNGlOd1JIbms2ZmNKMy9jZURUcmFkb3g3ck9FSDB4OTJIV2NkTDJwQ212S2FScHRUbXZ0YllsdTZUOHcrMGRicTNucjhSOXNmRDV3MFBGbDVTdk5VeVduYTZZTFRrMmZ5ejR5ZGxaMTlmaTc1M0dEYm9yWjc1MlBPMzJvUGIrKzZFSFRoMGtYL2krYzd2RHZPWFBLNGRQS3kyK1VUVjdoWG1xODZYMjNxZE9vOC9wUFRUOGU3bkx1YXJybGNhN251ZXIyMWUyYjM2UnVlTjg3ZDlMMTU4UmIvMXRXZU9UM2R2Zk42Yi9mRjkvWGZGdDErY2lmOXpzdTcyWGNuN3EyOFQ3eGY5RUR0UWRsRDNZZlZQMXYrM05qdjNIOXF3SGVnODlIY1IvY0doWVBQL3BIMWp3OURCWStaajh1R0RZYnJuamcrT1RuaVAzTDk2ZnluUTg5a3p5YWVGLzZpL3N1dUZ4WXZmdmpWNjlmTzBaalJvWmZ5bDVPL2JYeWwvZXJBNnhtdjI4YkN4aDYreVhnek1WNzBWdnZ0d1hmY2R4M3ZvOThQVCtSOElIOG8vMmo1c2ZWVDBLZjdreG1Uay84RUE1anovR016TGRzQUFBQWdZMGhTVFFBQWVpVUFBSUNEQUFENS93QUFnT2tBQUhVd0FBRHFZQUFBT3BnQUFCZHZrbC9GUmdBQUFRMUpSRUZVZU5wTTBEOUxBbUVBeC9IdlBYZURUcWVYcFZlWVlqcFlHUTFoQlE3U254ZlEwcEExRkVWYnI2RmVSZ1p1Q2IyRW9PQ2dtMjZzcG9JZ2lLQlFRYUlVbnVjZVcyN3d0MzZIRC93TU8rbmNBbmExVmw5amJJSHZ0WUFOYTJsbHRZSmh1SUh2WFZWcjlaTW9IcFhtRncvdHBDT3RXQ3grTDB4enYxaGVPQTU4THc2OHBxZG56bE5wbDFES053czQwR0g0a0pyS1hBcGhOZ1ovdjJUekJaU1ViYUFoSXJMWi9mNjZtOHk0ekJhSy9QVDdYYUFCSUNMemJEZ2NiT2t3SkZRS1BkSVRnZSsxQVF3NzZkeTQyZHh1ZnE1RXFGUUxlQmRDWFBSNkhWNmVIeitNOWZyMlo4SnhYQ1ZsRXppTnlEM1RzcTZWa3Nvc1Y1WTN0ZFlkWUdmc2hxZVIxamtESS9FL0FPOHJZUmx3WEJxdUFBQUFBRWxGVGtTdVFtQ0MpIDUwJSA1MCUgbm8tcmVwZWF0LCMxYTFkMWZ9I2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51IC5idXR0b24tbWVudS1jbG9zZTpob3ZlciwjY29udHJvbEtpdCAucGFuZWwgLm1lbnUtYWN0aXZlIC5idXR0b24tbWVudS1jbG9zZTpob3ZlciwjY29udHJvbEtpdCAucGlja2VyIC5tZW51IC5idXR0b24tbWVudS1jbG9zZTpob3ZlcntiYWNrZ3JvdW5kOnVybChkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFnQUFBQUpDQVlBQUFBUFUyMHVBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBUTFKUkVGVWVOcE0wRDlMQW1FQXgvSHZQWGVEVHFlWHBWZVlZanBZR1ExaEJRN1NueGZRMHBBMUZFVmJyNkZlUmdadUNiMkVvT0NnbTI2c3BvSWdpS0JRUWFJVW51Y2VXMjd3dDM2SEQvd01PK25jQW5hMVZsOWpiSUh2dFlBTmEybGx0WUpodUlIdlhWVnI5Wk1vSHBYbUZ3L3RwQ090V0N4K0wweHp2MWhlT0E1OEx3NjhwcWRuemxOcGwxREtOd3M0MEdINGtKcktYQXBoTmdaL3YyVHpCWlNVYmFBaElyTFovZjY2bTh5NHpCYUsvUFQ3WGFBQklDTHpiRGdjYk9rd0pGUUtQZElUZ2UrMUFRdzc2ZHk0MmR4dWZxNUVxRlFMZUJkQ1hQUjZIVjZlSHorTTlmcjJaOEp4WENWbEV6aU55RDNUc3E2Vmtzb3NWNVkzdGRZZFlHZnNocWVSMWprREkvRS9BTzhyWVJsd1hCcXVBQUFBQUVsRlRrU3VRbUNDKSA1MCUgNTAlIG5vLXJlcGVhdCwjMDAwO2JveC1zaGFkb3c6I2ZmZiAwLCMwMDAgMTAwJX0jY29udHJvbEtpdCAucGFuZWwgLm1lbnUgLmJ1dHRvbi1tZW51LXVuZG8sI2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51LWFjdGl2ZSAuYnV0dG9uLW1lbnUtdW5kb3tiYWNrZ3JvdW5kOnVybChkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUF3QUFBQUxDQVlBQUFCTGNHeGZBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBWVZKUkVGVWVOcGNrRDFJVzFFWWhwOXo3cm0zb3FraHpaL3hENnRSMUVwRktlbGdobEJvblZ3S0RwYVdEbmJxMmxWRjBNSEJVYmRDcDVhQ1VpZ2RuSVNnb1VQQXFXTWxZc0dsTnRZSzFaaHp6cjFkVkc3emJ0L0w5N3g4N3ljZVR6MGxySEtwK0JKWUJIcXVyRy9BZkM1ZitBd2d3a0M1Vkh5YnlyVFBkdmRtQTlmMUJFSlFPLy9MWVdXZmsrT2ZTN2w4WWVFR0tKZUtyN05EOTlhVDZReldtSFBnRStBQU00N3JjblI0d0kvSy9xUzhUczkwZHErbE1oMVlZMWFCRnVBRjhBeVFWdXZOcnJ0OXhPS0pqeUlhdS9NT0dKcDQ5T1JoclhaaDlyN3ViZ1BQYy9uQ3IzQTM2VGpHOTMxSERZK09UeWpQNnc4QUtSMDFNdmFnY0ZxdHhvSC9nTFBUM3dleFJES3JJcmRiZDZUajlBc2hjRDBQUWFUYTNCSTVvVUZhMTNzSUFpVHd5cmQyd1dxTnFWL3VBUjNBY2NPclB5UlNiVXJYNjMvVWxiZmsrMzRGeEpkeXFkZ0VMQU8zZ0Rnd1BUQnkvM3B2Um9XQzNnTWtVbTNwU0RUNlJrcUpjbDNpeVhRUVdJczFaZ1hZVW8yMzlnNE0xc0t6MWZvN01BZHNBUHdiQUw5aGZ0dlRsTmtkQUFBQUFFbEZUa1N1UW1DQykgMjAlIDUwJSBuby1yZXBlYXQsIzFhMWQxZjtwYWRkaW5nOjAgNnB4IDFweCAwO3dpZHRoOjM4cHg7dmVydGljYWwtYWxpZ246dG9wO3RleHQtYWxpZ246ZW5kfSNjb250cm9sS2l0IC5wYW5lbCAubWVudSAuYnV0dG9uLW1lbnUtdW5kbzpob3ZlciwjY29udHJvbEtpdCAucGFuZWwgLm1lbnUtYWN0aXZlIC5idXR0b24tbWVudS11bmRvOmhvdmVye2JhY2tncm91bmQ6dXJsKGRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQXdBQUFBTENBWUFBQUJMY0d4ZkFBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFLVDJsRFExQlFhRzkwYjNOb2IzQWdTVU5ESUhCeWIyWnBiR1VBQUhqYW5WTm5WRlBwRmozMzN2UkNTNGlBbEV0dlVoVUlJRkpDaTRBVWtTWXFJUWtRU29naG9ka1ZVY0VSUlVVRUc4aWdpQU9Pam9DTUZWRXNESW9LMkFma0lhS09nNk9JaXNyNzRYdWphOWE4OStiTi9yWFhQdWVzODUyenp3ZkFDQXlXU0ROUk5ZQU1xVUllRWVDRHg4VEc0ZVF1UUlFS0pIQUFFQWl6WkNGei9TTUJBUGgrUER3cklzQUh2Z0FCZU5NTENBREFUWnZBTUJ5SC93L3FRcGxjQVlDRUFjQjBrVGhMQ0lBVUFFQjZqa0ttQUVCR0FZQ2RtQ1pUQUtBRUFHRExZMkxqQUZBdEFHQW5mK2JUQUlDZCtKbDdBUUJibENFVkFhQ1JBQ0FUWlloRUFHZzdBS3pQVm9wRkFGZ3dBQlJtUzhRNUFOZ3RBREJKVjJaSUFMQzNBTURPRUF1eUFBZ01BREJSaUlVcEFBUjdBR0RJSXlONEFJU1pBQlJHOGxjODhTdXVFT2NxQUFCNG1iSTh1U1E1UllGYkNDMXhCMWRYTGg0b3pra1hLeFEyWVFKaG1rQXV3bm1aR1RLQk5BL2c4OHdBQUtDUkZSSGdnL1A5ZU00T3JzN09ObzYyRGw4dDZyOEcveUppWXVQKzVjK3JjRUFBQU9GMGZ0SCtMQyt6R29BN0JvQnQvcUlsN2dSb1hndWdkZmVMWnJJUFFMVUFvT25hVi9OdytINDhQRVdoa0xuWjJlWGs1TmhLeEVKYlljcFhmZjVud2wvQVYvMXMrWDQ4L1BmMTRMN2lKSUV5WFlGSEJQamd3c3owVEtVY3o1SUpoR0xjNW85SC9MY0wvL3dkMHlMRVNXSzVXQ29VNDFFU2NZNUVtb3p6TXFVaWlVS1NLY1VsMHY5azR0OHMrd00rM3pVQXNHbytBWHVSTGFoZFl3UDJTeWNRV0hUQTR2Y0FBUEs3YjhIVUtBZ0RnR2lENGM5My8rOC8vVWVnSlFDQVprbVNjUUFBWGtRa0xsVEtzei9IQ0FBQVJLQ0JLckJCRy9UQkdDekFCaHpCQmR6QkMveGdOb1JDSk1UQ1FoQkNDbVNBSEhKZ0theUNRaWlHemJBZEttQXYxRUFkTk1CUmFJYVRjQTR1d2xXNERqMXdEL3BoQ0o3QktMeUJDUVJCeUFnVFlTSGFpQUZpaWxnampnZ1htWVg0SWNGSUJCS0xKQ0RKaUJSUklrdVJOVWd4VW9wVUlGVklIZkk5Y2dJNWgxeEd1cEU3eUFBeWd2eUd2RWN4bElHeVVUM1VETFZEdWFnM0dvUkdvZ3ZRWkhReG1vOFdvSnZRY3JRYVBZdzJvZWZRcTJnUDJvOCtROGN3d09nWUJ6UEViREF1eHNOQ3NUZ3NDWk5qeTdFaXJBeXJ4aHF3VnF3RHU0bjFZOCt4ZHdRU2dVWEFDVFlFZDBJZ1lSNUJTRmhNV0U3WVNLZ2dIQ1EwRWRvSk53a0RoRkhDSnlLVHFFdTBKcm9SK2NRWVlqSXhoMWhJTENQV0VvOFRMeEI3aUVQRU55UVNpVU15SjdtUUFrbXhwRlRTRXRKRzBtNVNJK2tzcVpzMFNCb2prOG5hWkd1eUJ6bVVMQ0FyeUlYa25lVEQ1RFBrRytRaDhsc0tuV0pBY2FUNFUrSW9Vc3BxU2hubEVPVTA1UVpsbURKQlZhT2FVdDJvb1ZRUk5ZOWFRcTJodGxLdlVZZW9FelIxbWpuTmd4WkpTNld0b3BYVEdtZ1hhUGRwcitoMHVoSGRsUjVPbDlCWDBzdnBSK2lYNkFQMGR3d05oaFdEeDRobktCbWJHQWNZWnhsM0dLK1lUS1laMDRzWngxUXdOekhybU9lWkQ1bHZWVmdxdGlwOEZaSEtDcFZLbFNhVkd5b3ZWS21xcHFyZXFndFY4MVhMVkkrcFhsTjlya1pWTTFQanFRblVscXRWcXAxUTYxTWJVMmVwTzZpSHFtZW9iMVEvcEg1Wi9Za0dXY05NdzA5RHBGR2dzVi9qdk1ZZ0MyTVpzM2dzSVdzTnE0WjFnVFhFSnJITjJYeDJLcnVZL1IyN2l6MnFxYUU1UXpOS00xZXpVdk9VWmo4SDQ1aHgrSngwVGdubktLZVg4MzZLM2hUdktlSXBHNlkwVExreFpWeHJxcGFYbGxpclNLdFJxMGZydlRhdTdhZWRwcjFGdTFuN2dRNUJ4MG9uWENkSFo0L09CWjNuVTlsVDNhY0tweFpOUFRyMXJpNnFhNlVib2J0RWQ3OXVwKzZZbnI1ZWdKNU1iNmZlZWIzbitoeDlMLzFVL1czNnAvVkhERmdHc3d3a0J0c016aGc4eFRWeGJ6d2RMOGZiOFZGRFhjTkFRNlZobFdHWDRZU1J1ZEU4bzlWR2pVWVBqR25HWE9NazQyM0diY2FqSmdZbUlTWkxUZXBON3BwU1RibW1LYVk3VER0TXg4M016YUxOMXBrMW16MHgxekxubStlYjE1dmZ0MkJhZUZvc3RxaTJ1R1ZKc3VSYXBsbnV0cnh1aFZvNVdhVllWVnBkczBhdG5hMGwxcnV0dTZjUnA3bE9rMDZybnRabnc3RHh0c20ycWJjWnNPWFlCdHV1dG0yMmZXRm5ZaGRudDhXdXcrNlR2Wk45dW4yTi9UMEhEWWZaRHFzZFdoMStjN1J5RkRwV090NmF6cHp1UDMzRjlKYnBMMmRZenhEUDJEUGp0aFBMS2NScG5WT2IwMGRuRjJlNWM0UHppSXVKUzRMTExwYytMcHNieHQzSXZlUktkUFZ4WGVGNjB2V2RtN09id3UybzI2L3VOdTVwN29mY244dzBueW1lV1ROejBNUElRK0JSNWRFL0M1K1ZNR3Zmckg1UFEwK0JaN1huSXk5akw1RlhyZGV3dDZWM3F2ZGg3eGMrOWo1eW4rTSs0enczM2pMZVdWL01OOEMzeUxmTFQ4TnZubCtGMzBOL0kvOWsvM3IvMFFDbmdDVUJad09KZ1VHQld3TDcrSHA4SWIrT1B6cmJaZmF5MmUxQmpLQzVRUlZCajRLdGd1WEJyU0ZveU95UXJTSDM1NWpPa2M1cERvVlFmdWpXMEFkaDVtR0x3MzRNSjRXSGhWZUdQNDV3aUZnYTBUR1hOWGZSM0VOejMwVDZSSlpFM3B0bk1VODVyeTFLTlNvK3FpNXFQTm8zdWpTNlA4WXVabG5NMVZpZFdFbHNTeHc1TGlxdU5tNXN2dC84N2ZPSDRwM2lDK043RjVndnlGMXdlYUhPd3ZTRnB4YXBMaElzT3BaQVRJaE9PSlR3UVJBcXFCYU1KZklUZHlXT0NubkNIY0puSWkvUk50R0kyRU5jS2g1TzhrZ3FUWHFTN0pHOE5Ya2t4VE9sTE9XNWhDZXBrTHhNRFV6ZG16cWVGcHAySUcweVBUcTlNWU9Ta1pCeFFxb2hUWk8yWitwbjVtWjJ5NnhsaGJMK3hXNkx0eThlbFFmSmE3T1FyQVZaTFFxMlFxYm9WRm9vMXlvSHNtZGxWMmEvelluS09aYXJuaXZON2N5enl0dVFONXp2bi8vdEVzSVM0WksycFlaTFZ5MGRXT2E5ckdvNXNqeHhlZHNLNHhVRks0WldCcXc4dUlxMkttM1ZUNnZ0VjVldWZyMG1lazFyZ1Y3QnlvTEJ0UUZyNnd0VkN1V0ZmZXZjMSsxZFQxZ3ZXZCsxWWZxR25ScytGWW1LcmhUYkY1Y1ZmOWdvM0hqbEc0ZHZ5citaM0pTMHFhdkV1V1RQWnRKbTZlYmVMWjViRHBhcWwrYVhEbTROMmRxMERkOVd0TzMxOWtYYkw1Zk5LTnU3ZzdaRHVhTy9QTGk4WmFmSnpzMDdQMVNrVlBSVStsUTI3dExkdFdIWCtHN1I3aHQ3dlBZMDdOWGJXN3ozL1Q3SnZ0dFZBVlZOMVdiVlpmdEorN1AzUDY2SnF1bjRsdnR0WGExT2JYSHR4d1BTQS8wSEl3NjIxN25VMVIzU1BWUlNqOVlyNjBjT3h4KysvcDN2ZHkwTk5nMVZqWnpHNGlOd1JIbms2ZmNKMy9jZURUcmFkb3g3ck9FSDB4OTJIV2NkTDJwQ212S2FScHRUbXZ0YllsdTZUOHcrMGRicTNucjhSOXNmRDV3MFBGbDVTdk5VeVduYTZZTFRrMmZ5ejR5ZGxaMTlmaTc1M0dEYm9yWjc1MlBPMzJvUGIrKzZFSFRoMGtYL2krYzd2RHZPWFBLNGRQS3kyK1VUVjdoWG1xODZYMjNxZE9vOC9wUFRUOGU3bkx1YXJybGNhN251ZXIyMWUyYjM2UnVlTjg3ZDlMMTU4UmIvMXRXZU9UM2R2Zk42Yi9mRjkvWGZGdDErY2lmOXpzdTcyWGNuN3EyOFQ3eGY5RUR0UWRsRDNZZlZQMXYrM05qdjNIOXF3SGVnODlIY1IvY0doWVBQL3BIMWp3OURCWStaajh1R0RZYnJuamcrT1RuaVAzTDk2ZnluUTg5a3p5YWVGLzZpL3N1dUZ4WXZmdmpWNjlmTzBaalJvWmZ5bDVPL2JYeWwvZXJBNnhtdjI4YkN4aDYreVhnek1WNzBWdnZ0d1hmY2R4M3ZvOThQVCtSOElIOG8vMmo1c2ZWVDBLZjdreG1Uay84RUE1anovR016TGRzQUFBQWdZMGhTVFFBQWVpVUFBSUNEQUFENS93QUFnT2tBQUhVd0FBRHFZQUFBT3BnQUFCZHZrbC9GUmdBQUFZVkpSRUZVZU5wY2tEMUlXMUVZaHA5ejdybTNvcWtoeloveEQ2dFIxRXBGS2VsZ2hsQm9uVndLRHBhV0RuYnEybFZGME1IQlViZENwNWFDVWlnZG5JU2dvVVBBcVdNbFlzR2xOdFlLMVpoenpyMWRWRzd6YnQvTDk3eDg3eWNlVHowbHJIS3ArQkpZQkhxdXJHL0FmQzVmK0F3Z3drQzVWSHlieXJUUGR2ZG1BOWYxQkVKUU8vL0xZV1dmaytPZlM3bDhZZUVHS0plS3I3TkQ5OWFUNlF6V21IUGdFK0FBTTQ3cmNuUjR3SS9LL3FTOFRzOTBkcStsTWgxWVkxYUJGdUFGOEF5UVZ1dk5ycnQ5eE9LSmp5SWF1L01PR0pwNDlPUmhyWFpoOXI3dWJnUFBjL25DcjNBMzZUakc5MzFIRFkrT1R5alA2dzhBS1IwMU12YWdjRnF0eG9IL2dMUFQzd2V4UkRLcklyZGJkNlRqOUFzaGNEMFBRYVRhM0JJNW9VRmExM3NJQWlUd3lyZDJ3V3FOcVYvdUFSM0FjY09yUHlSU2JVclg2My9VbGJmayszNEZ4SmR5cWRnRUxBTzNnRGd3UFRCeS8zcHZSb1dDM2dNa1VtM3BTRFQ2UmtxSmNsM2l5WFFRV0lzMVpnWFlVbzIzOWc0TTFzS3oxZm83TUFkc0FQd2JBTDloZnR2VGxOa2RBQUFBQUVsRlRrU3VRbUNDKSAyMCUgNTAlIG5vLXJlcGVhdCwjMDAwO2JveC1zaGFkb3c6I2ZmZiAwLCMwMDAgMTAwJX0jY29udHJvbEtpdCAucGFuZWwgLm1lbnUgLmJ1dHRvbi1tZW51LWxvYWQsI2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51LWFjdGl2ZSAuYnV0dG9uLW1lbnUtbG9hZHttYXJnaW4tcmlnaHQ6MnB4fSNjb250cm9sS2l0IC5wYW5lbCAubWVudSAuYnV0dG9uLW1lbnUtbG9hZCwjY29udHJvbEtpdCAucGFuZWwgLm1lbnUgLmJ1dHRvbi1tZW51LXNhdmUsI2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51LWFjdGl2ZSAuYnV0dG9uLW1lbnUtbG9hZCwjY29udHJvbEtpdCAucGFuZWwgLm1lbnUtYWN0aXZlIC5idXR0b24tbWVudS1zYXZle2JhY2tncm91bmQ6IzFhMWQxZjtmb250LXNpemU6OXB4IWltcG9ydGFudH0jY29udHJvbEtpdCAucGFuZWwgLm1lbnUgLmJ1dHRvbi1tZW51LWxvYWQ6aG92ZXIsI2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51IC5idXR0b24tbWVudS1zYXZlOmhvdmVyLCNjb250cm9sS2l0IC5wYW5lbCAubWVudS1hY3RpdmUgLmJ1dHRvbi1tZW51LWxvYWQ6aG92ZXIsI2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51LWFjdGl2ZSAuYnV0dG9uLW1lbnUtc2F2ZTpob3ZlcntiYWNrZ3JvdW5kOiMwMDB9I2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51IC53cmFwe2Rpc3BsYXk6bm9uZX0jY29udHJvbEtpdCAucGFuZWwgLm1lbnUtYWN0aXZle3dpZHRoOjEwMCU7ZmxvYXQ6bGVmdH0jY29udHJvbEtpdCAucGFuZWwgLm1lbnUtYWN0aXZlIC53cmFwe2Rpc3BsYXk6aW5saW5lfSNjb250cm9sS2l0IC5wYW5lbCAubWVudS1hY3RpdmUgLmJ1dHRvbi1tZW51LWNsb3NlLCNjb250cm9sS2l0IC5wYW5lbCAubWVudS1hY3RpdmUgLmJ1dHRvbi1tZW51LWhpZGUsI2NvbnRyb2xLaXQgLnBhbmVsIC5tZW51LWFjdGl2ZSAuYnV0dG9uLW1lbnUtc2hvd3tmbG9hdDpyaWdodH0jY29udHJvbEtpdCAucGFuZWwgLmFycm93LXMtbWF4e2JhY2tncm91bmQ6dXJsKGRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQWdBQUFBRkNBWUFBQUI0a2ExVkFBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFLVDJsRFExQlFhRzkwYjNOb2IzQWdTVU5ESUhCeWIyWnBiR1VBQUhqYW5WTm5WRlBwRmozMzN2UkNTNGlBbEV0dlVoVUlJRkpDaTRBVWtTWXFJUWtRU29naG9ka1ZVY0VSUlVVRUc4aWdpQU9Pam9DTUZWRXNESW9LMkFma0lhS09nNk9JaXNyNzRYdWphOWE4OStiTi9yWFhQdWVzODUyenp3ZkFDQXlXU0ROUk5ZQU1xVUllRWVDRHg4VEc0ZVF1UUlFS0pIQUFFQWl6WkNGei9TTUJBUGgrUER3cklzQUh2Z0FCZU5NTENBREFUWnZBTUJ5SC93L3FRcGxjQVlDRUFjQjBrVGhMQ0lBVUFFQjZqa0ttQUVCR0FZQ2RtQ1pUQUtBRUFHRExZMkxqQUZBdEFHQW5mK2JUQUlDZCtKbDdBUUJibENFVkFhQ1JBQ0FUWlloRUFHZzdBS3pQVm9wRkFGZ3dBQlJtUzhRNUFOZ3RBREJKVjJaSUFMQzNBTURPRUF1eUFBZ01BREJSaUlVcEFBUjdBR0RJSXlONEFJU1pBQlJHOGxjODhTdXVFT2NxQUFCNG1iSTh1U1E1UllGYkNDMXhCMWRYTGg0b3pra1hLeFEyWVFKaG1rQXV3bm1aR1RLQk5BL2c4OHdBQUtDUkZSSGdnL1A5ZU00T3JzN09ObzYyRGw4dDZyOEcveUppWXVQKzVjK3JjRUFBQU9GMGZ0SCtMQyt6R29BN0JvQnQvcUlsN2dSb1hndWdkZmVMWnJJUFFMVUFvT25hVi9OdytINDhQRVdoa0xuWjJlWGs1TmhLeEVKYlljcFhmZjVud2wvQVYvMXMrWDQ4L1BmMTRMN2lKSUV5WFlGSEJQamd3c3owVEtVY3o1SUpoR0xjNW85SC9MY0wvL3dkMHlMRVNXSzVXQ29VNDFFU2NZNUVtb3p6TXFVaWlVS1NLY1VsMHY5azR0OHMrd00rM3pVQXNHbytBWHVSTGFoZFl3UDJTeWNRV0hUQTR2Y0FBUEs3YjhIVUtBZ0RnR2lENGM5My8rOC8vVWVnSlFDQVprbVNjUUFBWGtRa0xsVEtzei9IQ0FBQVJLQ0JLckJCRy9UQkdDekFCaHpCQmR6QkMveGdOb1JDSk1UQ1FoQkNDbVNBSEhKZ0theUNRaWlHemJBZEttQXYxRUFkTk1CUmFJYVRjQTR1d2xXNERqMXdEL3BoQ0o3QktMeUJDUVJCeUFnVFlTSGFpQUZpaWxnampnZ1htWVg0SWNGSUJCS0xKQ0RKaUJSUklrdVJOVWd4VW9wVUlGVklIZkk5Y2dJNWgxeEd1cEU3eUFBeWd2eUd2RWN4bElHeVVUM1VETFZEdWFnM0dvUkdvZ3ZRWkhReG1vOFdvSnZRY3JRYVBZdzJvZWZRcTJnUDJvOCtROGN3d09nWUJ6UEViREF1eHNOQ3NUZ3NDWk5qeTdFaXJBeXJ4aHF3VnF3RHU0bjFZOCt4ZHdRU2dVWEFDVFlFZDBJZ1lSNUJTRmhNV0U3WVNLZ2dIQ1EwRWRvSk53a0RoRkhDSnlLVHFFdTBKcm9SK2NRWVlqSXhoMWhJTENQV0VvOFRMeEI3aUVQRU55UVNpVU15SjdtUUFrbXhwRlRTRXRKRzBtNVNJK2tzcVpzMFNCb2prOG5hWkd1eUJ6bVVMQ0FyeUlYa25lVEQ1RFBrRytRaDhsc0tuV0pBY2FUNFUrSW9Vc3BxU2hubEVPVTA1UVpsbURKQlZhT2FVdDJvb1ZRUk5ZOWFRcTJodGxLdlVZZW9FelIxbWpuTmd4WkpTNld0b3BYVEdtZ1hhUGRwcitoMHVoSGRsUjVPbDlCWDBzdnBSK2lYNkFQMGR3d05oaFdEeDRobktCbWJHQWNZWnhsM0dLK1lUS1laMDRzWngxUXdOekhybU9lWkQ1bHZWVmdxdGlwOEZaSEtDcFZLbFNhVkd5b3ZWS21xcHFyZXFndFY4MVhMVkkrcFhsTjlya1pWTTFQanFRblVscXRWcXAxUTYxTWJVMmVwTzZpSHFtZW9iMVEvcEg1Wi9Za0dXY05NdzA5RHBGR2dzVi9qdk1ZZ0MyTVpzM2dzSVdzTnE0WjFnVFhFSnJITjJYeDJLcnVZL1IyN2l6MnFxYUU1UXpOS00xZXpVdk9VWmo4SDQ1aHgrSngwVGdubktLZVg4MzZLM2hUdktlSXBHNlkwVExreFpWeHJxcGFYbGxpclNLdFJxMGZydlRhdTdhZWRwcjFGdTFuN2dRNUJ4MG9uWENkSFo0L09CWjNuVTlsVDNhY0tweFpOUFRyMXJpNnFhNlVib2J0RWQ3OXVwKzZZbnI1ZWdKNU1iNmZlZWIzbitoeDlMLzFVL1czNnAvVkhERmdHc3d3a0J0c016aGc4eFRWeGJ6d2RMOGZiOFZGRFhjTkFRNlZobFdHWDRZU1J1ZEU4bzlWR2pVWVBqR25HWE9NazQyM0diY2FqSmdZbUlTWkxUZXBON3BwU1RibW1LYVk3VER0TXg4M016YUxOMXBrMW16MHgxekxubStlYjE1dmZ0MkJhZUZvc3RxaTJ1R1ZKc3VSYXBsbnV0cnh1aFZvNVdhVllWVnBkczBhdG5hMGwxcnV0dTZjUnA3bE9rMDZybnRabnc3RHh0c20ycWJjWnNPWFlCdHV1dG0yMmZXRm5ZaGRudDhXdXcrNlR2Wk45dW4yTi9UMEhEWWZaRHFzZFdoMStjN1J5RkRwV090NmF6cHp1UDMzRjlKYnBMMmRZenhEUDJEUGp0aFBMS2NScG5WT2IwMGRuRjJlNWM0UHppSXVKUzRMTExwYytMcHNieHQzSXZlUktkUFZ4WGVGNjB2V2RtN09id3UybzI2L3VOdTVwN29mY244dzBueW1lV1ROejBNUElRK0JSNWRFL0M1K1ZNR3Zmckg1UFEwK0JaN1huSXk5akw1RlhyZGV3dDZWM3F2ZGg3eGMrOWo1eW4rTSs0enczM2pMZVdWL01OOEMzeUxmTFQ4TnZubCtGMzBOL0kvOWsvM3IvMFFDbmdDVUJad09KZ1VHQld3TDcrSHA4SWIrT1B6cmJaZmF5MmUxQmpLQzVRUlZCajRLdGd1WEJyU0ZveU95UXJTSDM1NWpPa2M1cERvVlFmdWpXMEFkaDVtR0x3MzRNSjRXSGhWZUdQNDV3aUZnYTBUR1hOWGZSM0VOejMwVDZSSlpFM3B0bk1VODVyeTFLTlNvK3FpNXFQTm8zdWpTNlA4WXVabG5NMVZpZFdFbHNTeHc1TGlxdU5tNXN2dC84N2ZPSDRwM2lDK043RjVndnlGMXdlYUhPd3ZTRnB4YXBMaElzT3BaQVRJaE9PSlR3UVJBcXFCYU1KZklUZHlXT0NubkNIY0puSWkvUk50R0kyRU5jS2g1TzhrZ3FUWHFTN0pHOE5Ya2t4VE9sTE9XNWhDZXBrTHhNRFV6ZG16cWVGcHAySUcweVBUcTlNWU9Ta1pCeFFxb2hUWk8yWitwbjVtWjJ5NnhsaGJMK3hXNkx0eThlbFFmSmE3T1FyQVZaTFFxMlFxYm9WRm9vMXlvSHNtZGxWMmEvelluS09aYXJuaXZON2N5enl0dVFONXp2bi8vdEVzSVM0WksycFlaTFZ5MGRXT2E5ckdvNXNqeHhlZHNLNHhVRks0WldCcXc4dUlxMkttM1ZUNnZ0VjVldWZyMG1lazFyZ1Y3QnlvTEJ0UUZyNnd0VkN1V0ZmZXZjMSsxZFQxZ3ZXZCsxWWZxR25ScytGWW1LcmhUYkY1Y1ZmOWdvM0hqbEc0ZHZ5citaM0pTMHFhdkV1V1RQWnRKbTZlYmVMWjViRHBhcWwrYVhEbTROMmRxMERkOVd0TzMxOWtYYkw1Zk5LTnU3ZzdaRHVhTy9QTGk4WmFmSnpzMDdQMVNrVlBSVStsUTI3dExkdFdIWCtHN1I3aHQ3dlBZMDdOWGJXN3ozL1Q3SnZ0dFZBVlZOMVdiVlpmdEorN1AzUDY2SnF1bjRsdnR0WGExT2JYSHR4d1BTQS8wSEl3NjIxN25VMVIzU1BWUlNqOVlyNjBjT3h4KysvcDN2ZHkwTk5nMVZqWnpHNGlOd1JIbms2ZmNKMy9jZURUcmFkb3g3ck9FSDB4OTJIV2NkTDJwQ212S2FScHRUbXZ0YllsdTZUOHcrMGRicTNucjhSOXNmRDV3MFBGbDVTdk5VeVduYTZZTFRrMmZ5ejR5ZGxaMTlmaTc1M0dEYm9yWjc1MlBPMzJvUGIrKzZFSFRoMGtYL2krYzd2RHZPWFBLNGRQS3kyK1VUVjdoWG1xODZYMjNxZE9vOC9wUFRUOGU3bkx1YXJybGNhN251ZXIyMWUyYjM2UnVlTjg3ZDlMMTU4UmIvMXRXZU9UM2R2Zk42Yi9mRjkvWGZGdDErY2lmOXpzdTcyWGNuN3EyOFQ3eGY5RUR0UWRsRDNZZlZQMXYrM05qdjNIOXF3SGVnODlIY1IvY0doWVBQL3BIMWp3OURCWStaajh1R0RZYnJuamcrT1RuaVAzTDk2ZnluUTg5a3p5YWVGLzZpL3N1dUZ4WXZmdmpWNjlmTzBaalJvWmZ5bDVPL2JYeWwvZXJBNnhtdjI4YkN4aDYreVhnek1WNzBWdnZ0d1hmY2R4M3ZvOThQVCtSOElIOG8vMmo1c2ZWVDBLZjdreG1Uay84RUE1anovR016TGRzQUFBQWdZMGhTVFFBQWVpVUFBSUNEQUFENS93QUFnT2tBQUhVd0FBRHFZQUFBT3BnQUFCZHZrbC9GUmdBQUFHNUpSRUZVZU5waTVPRGlhbVJnWUtoandBNGFtVng4Z3hqbUwxckM4UDNyVnhROGIrRVNCaGZmSUFabU5SMjlBNWV2WFdkaVpHQzAxOVhTWkdCZ1lHQll2bVk5dzdJMTZ4b1pHQmdhV0tCRzFTOWJzKzQvQXdORFBRTURBMXlTZ1lHQmdkRW5QQWJaemdZMG1nRXdBRTlsSlQxbHJzZmZBQUFBQUVsRlRrU3VRbUNDKSBjZW50ZXIgbm8tcmVwZWF0fSNjb250cm9sS2l0IC5wYW5lbCAuYXJyb3ctcy1taW57YmFja2dyb3VuZDp1cmwoZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFBZ0FBQUFGQ0FZQUFBQjRrYTFWQUFBQUNYQklXWE1BQUFzVEFBQUxFd0VBbXB3WUFBQUtUMmxEUTFCUWFHOTBiM05vYjNBZ1NVTkRJSEJ5YjJacGJHVUFBSGphblZOblZGUHBGajMzM3ZSQ1M0aUFsRXR2VWhVSUlGSkNpNEFVa1NZcUlRa1FTb2dob2RrVlVjRVJSVVVFRzhpZ2lBT09qb0NNRlZFc0RJb0syQWZrSWFLT2c2T0lpc3I3NFh1amE5YTg5K2JOL3JYWFB1ZXM4NTJ6endmQUNBeVdTRE5STllBTXFVSWVFZUNEeDhURzRlUXVRSUVLSkhBQUVBaXpaQ0Z6L1NNQkFQaCtQRHdySXNBSHZnQUJlTk1MQ0FEQVRadkFNQnlIL3cvcVFwbGNBWUNFQWNCMGtUaExDSUFVQUVCNmprS21BRUJHQVlDZG1DWlRBS0FFQUdETFkyTGpBRkF0QUdBbmYrYlRBSUNkK0psN0FRQmJsQ0VWQWFDUkFDQVRaWWhFQUdnN0FLelBWb3BGQUZnd0FCUm1TOFE1QU5ndEFEQkpWMlpJQUxDM0FNRE9FQXV5QUFnTUFEQlJpSVVwQUFSN0FHRElJeU40QUlTWkFCUkc4bGM4OFN1dUVPY3FBQUI0bWJJOHVTUTVSWUZiQ0MxeEIxZFhMaDRvemtrWEt4UTJZUUpobWtBdXdubVpHVEtCTkEvZzg4d0FBS0NSRlJIZ2cvUDllTTRPcnM3T05vNjJEbDh0NnI4Ry95SmlZdVArNWMrcmNFQUFBT0YwZnRIK0xDK3pHb0E3Qm9CdC9xSWw3Z1JvWGd1Z2RmZUxacklQUUxVQW9PbmFWL053K0g0OFBFV2hrTG5aMmVYazVOaEt4RUpiWWNwWGZmNW53bC9BVi8xcytYNDgvUGYxNEw3aUpJRXlYWUZIQlBqZ3dzejBUS1VjejVJSmhHTGM1bzlIL0xjTC8vd2QweUxFU1dLNVdDb1U0MUVTY1k1RW1venpNcVVpaVVLU0tjVWwwdjlrNHQ4cyt3TSszelVBc0dvK0FYdVJMYWhkWXdQMlN5Y1FXSFRBNHZjQUFQSzdiOEhVS0FnRGdHaUQ0YzkzLys4Ly9VZWdKUUNBWmttU2NRQUFYa1FrTGxUS3N6L0hDQUFBUktDQktyQkJHL1RCR0N6QUJoekJCZHpCQy94Z05vUkNKTVRDUWhCQ0NtU0FISEpnS2F5Q1FpaUd6YkFkS21BdjFFQWROTUJSYUlhVGNBNHV3bFc0RGoxd0QvcGhDSjdCS0x5QkNRUkJ5QWdUWVNIYWlBRmlpbGdqamdnWG1ZWDRJY0ZJQkJLTEpDREppQlJSSWt1Uk5VZ3hVb3BVSUZWSUhmSTljZ0k1aDF4R3VwRTd5QUF5Z3Z5R3ZFY3hsSUd5VVQzVURMVkR1YWczR29SR29ndlFaSFF4bW84V29KdlFjclFhUFl3Mm9lZlFxMmdQMm84K1E4Y3d3T2dZQnpQRWJEQXV4c05Dc1Rnc0NaTmp5N0VpckF5cnhocXdWcXdEdTRuMVk4K3hkd1FTZ1VYQUNUWUVkMElnWVI1QlNGaE1XRTdZU0tnZ0hDUTBFZG9KTndrRGhGSENKeUtUcUV1MEpyb1IrY1FZWWpJeGgxaElMQ1BXRW84VEx4QjdpRVBFTnlRU2lVTXlKN21RQWtteHBGVFNFdEpHMG01U0kra3NxWnMwU0Jvams4bmFaR3V5QnptVUxDQXJ5SVhrbmVURDVEUGtHK1FoOGxzS25XSkFjYVQ0VStJb1VzcHFTaG5sRU9VMDVRWmxtREpCVmFPYVV0Mm9vVlFSTlk5YVFxMmh0bEt2VVllb0V6UjFtam5OZ3haSlM2V3RvcFhUR21nWGFQZHByK2gwdWhIZGxSNU9sOUJYMHN2cFIraVg2QVAwZHd3TmhoV0R4NGhuS0JtYkdBY1laeGwzR0srWVRLWVowNHNaeDFRd056SHJtT2VaRDVsdlZWZ3F0aXA4RlpIS0NwVktsU2FWR3lvdlZLbXFwcXJlcWd0VjgxWExWSStwWGxOOXJrWlZNMVBqcVFuVWxxdFZxcDFRNjFNYlUyZXBPNmlIcW1lb2IxUS9wSDVaL1lrR1djTk13MDlEcEZHZ3NWL2p2TVlnQzJNWnMzZ3NJV3NOcTRaMWdUWEVKckhOMlh4MktydVkvUjI3aXoycXFhRTVRek5LTTFlelV2T1VaajhINDVoeCtKeDBUZ25uS0tlWDgzNkszaFR2S2VJcEc2WTBUTGt4WlZ4cnFwYVhsbGlyU0t0UnEwZnJ2VGF1N2FlZHByMUZ1MW43Z1E1Qngwb25YQ2RIWjQvT0JaM25VOWxUM2FjS3B4Wk5QVHIxcmk2cWE2VWJvYnRFZDc5dXArNllucjVlZ0o1TWI2ZmVlYjNuK2h4OUwvMVUvVzM2cC9WSERGZ0dzd3drQnRzTXpoZzh4VFZ4Ynp3ZEw4ZmI4VkZEWGNOQVE2VmhsV0dYNFlTUnVkRThvOVZHalVZUGpHbkdYT01rNDIzR2JjYWpKZ1ltSVNaTFRlcE43cHBTVGJtbUthWTdURHRNeDgzTXphTE4xcGsxbXoweDF6TG5tK2ViMTV2ZnQyQmFlRm9zdHFpMnVHVkpzdVJhcGxudXRyeHVoVm81V2FWWVZWcGRzMGF0bmEwbDFydXR1NmNScDdsT2swNnJudFpudzdEeHRzbTJxYmNac09YWUJ0dXV0bTIyZldGblloZG50OFd1dys2VHZaTjl1bjJOL1QwSERZZlpEcXNkV2gxK2M3UnlGRHBXT3Q2YXpwenVQMzNGOUpicEwyZFl6eERQMkRQanRoUExLY1JwblZPYjAwZG5GMmU1YzRQemlJdUpTNExMTHBjK0xwc2J4dDNJdmVSS2RQVnhYZUY2MHZXZG03T2J3dTJvMjYvdU51NXA3b2Zjbjh3MG55bWVXVE56ME1QSVErQlI1ZEUvQzUrVk1HdmZySDVQUTArQlo3WG5JeTlqTDVGWHJkZXd0NlYzcXZkaDd4Yys5ajV5bitNKzR6dzMzakxlV1YvTU44QzN5TGZMVDhOdm5sK0YzME4vSS85ay8zci8wUUNuZ0NVQlp3T0pnVUdCV3dMNytIcDhJYitPUHpyYlpmYXkyZTFCaktDNVFSVkJqNEt0Z3VYQnJTRm95T3lRclNIMzU1ak9rYzVwRG9WUWZ1alcwQWRoNW1HTHczNE1KNFdIaFZlR1A0NXdpRmdhMFRHWE5YZlIzRU56MzBUNlJKWkUzcHRuTVU4NXJ5MUtOU28rcWk1cVBObzN1alM2UDhZdVpsbk0xVmlkV0Vsc1N4dzVMaXF1Tm01c3Z0Lzg3Zk9INHAzaUMrTjdGNWd2eUYxd2VhSE93dlNGcHhhcExoSXNPcFpBVEloT09KVHdRUkFxcUJhTUpmSVRkeVdPQ25uQ0hjSm5JaS9STnRHSTJFTmNLaDVPOGtncVRYcVM3Skc4Tlhra3hUT2xMT1c1aENlcGtMeE1EVXpkbXpxZUZwcDJJRzB5UFRxOU1ZT1NrWkJ4UXFvaFRaTzJaK3BuNW1aMnk2eGxoYkwreFc2THR5OGVsUWZKYTdPUXJBVlpMUXEyUXFib1ZGb28xeW9Ic21kbFYyYS96WW5LT1phcm5pdk43Y3l6eXR1UU41enZuLy90RXNJUzRaSzJwWVpMVnkwZFdPYTlyR281c2p4eGVkc0s0eFVGSzRaV0Jxdzh1SXEyS20zVlQ2dnRWNWV1ZnIwbWVrMXJnVjdCeW9MQnRRRnI2d3RWQ3VXRmZldmMxKzFkVDFndldkKzFZZnFHblJzK0ZZbUtyaFRiRjVjVmY5Z28zSGpsRzRkdnlyK1ozSlMwcWF2RXVXVFBadEptNmViZUxaNWJEcGFxbCthWERtNE4yZHEwRGQ5V3RPMzE5a1hiTDVmTktOdTdnN1pEdWFPL1BMaThaYWZKenMwN1AxU2tWUFJVK2xRMjd0TGR0V0hYK0c3UjdodDd2UFkwN05YYlc3ejMvVDdKdnR0VkFWVk4xV2JWWmZ0Sis3UDNQNjZKcXVuNGx2dHRYYTFPYlhIdHh3UFNBLzBISXc2MjE3blUxUjNTUFZSU2o5WXI2MGNPeHgrKy9wM3ZkeTBOTmcxVmpaekc0aU53UkhuazZmY0ozL2NlRFRyYWRveDdyT0VIMHg5MkhXY2RMMnBDbXZLYVJwdFRtdnRiWWx1NlQ4dyswZGJxM25yOFI5c2ZENXcwUEZsNVN2TlV5V25hNllMVGsyZnl6NHlkbFoxOWZpNzUzR0Rib3JaNzUyUE8zMm9QYisrNkVIVGgwa1gvaStjN3ZEdk9YUEs0ZFBLeTIrVVRWN2hYbXE4NlgyM3FkT284L3BQVFQ4ZTduTHVhcnJsY2E3bnVlcjIxZTJiMzZSdWVOODdkOUwxNThSYi8xdFdlT1QzZHZmTjZiL2ZGOS9YZkZ0MStjaWY5enN1NzJYY243cTI4VDd4ZjlFRHRRZGxEM1lmVlAxdiszTmp2M0g5cXdIZWc4OUhjUi9jR2hZUFAvcEgxanc5REJZK1pqOHVHRFlicm5qZytPVG5pUDNMOTZmeW5RODlrenlhZUYvNmkvc3V1RnhZdmZ2alY2OWZPMFpqUm9aZnlsNU8vYlh5bC9lckE2eG12MjhiQ3hoNit5WGd6TVY3MFZ2dnR3WGZjZHgzdm85OFBUK1I4SUg4by8yajVzZlZUMEtmN2t4bVRrLzhFQTVqei9HTXpMZHNBQUFBZ1kwaFNUUUFBZWlVQUFJQ0RBQUQ1L3dBQWdPa0FBSFV3QUFEcVlBQUFPcGdBQUJkdmtsL0ZSZ0FBQUZwSlJFRlVlTnBzaWlFT2dEQU1SZjhTeE5KeklZZkIxUFFrUTdSa1pjZkJZTG5iVUFzTDRjbjNYa2dzNk56WHFRQXdMK3ZlM1RUR0xXY0RnS1BXZDBvc2lFUmEzRnVudUxkSXBJa0ZpRVEyeHU4VUVvc0JVUHhqendBVFNqVi84cWxNR0FBQUFBQkpSVTVFcmtKZ2dnPT0pIGNlbnRlciBuby1yZXBlYXR9I2NvbnRyb2xLaXQgLnBhbmVsIC5hcnJvdy1zLW1heCwjY29udHJvbEtpdCAucGFuZWwgLmFycm93LXMtbWlue3dpZHRoOjEwMCU7aGVpZ2h0OjIwcHh9I2NvbnRyb2xLaXQgLnBhbmVsIC5hcnJvdy1iLW1heHtiYWNrZ3JvdW5kOnVybChkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFnQUFBQUZDQVlBQUFCNGthMVZBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBREpKUkVGVWVOcHN5c0VOQUNBTUF6RTI5K2poQXhLbFBTbXZlSzJhc3pFSU1pSEk3VWZsYkNoSmZ4KzNBUUFBLy84REFQTGtTYW1IYXN0eEFBQUFBRWxGVGtTdVFtQ0MpIGNlbnRlciBuby1yZXBlYXR9I2NvbnRyb2xLaXQgLnBhbmVsIC5hcnJvdy1iLW1pbntiYWNrZ3JvdW5kOnVybChkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFnQUFBQUZDQVlBQUFCNGthMVZBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBQzlKUkVGVWVOcUVqREVPQUNBUWd4aDhPRC9IMlJoUGtrNDBBQWowbUt2aVMyVTNUaWVuMGlFM0FBQUEvLzhEQUVkMU50SUNWNEV1QUFBQUFFbEZUa1N1UW1DQykgY2VudGVyIG5vLXJlcGVhdH0jY29udHJvbEtpdCAucGFuZWwgLmFycm93LWItc3ViLW1heHtiYWNrZ3JvdW5kOnVybChkYXRhOmltYWdlL3BuZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUFvQUFBQUdDQVlBQUFENjhBL0dBQUFBQ1hCSVdYTUFBQXNUQUFBTEV3RUFtcHdZQUFBS1QybERRMUJRYUc5MGIzTm9iM0FnU1VORElIQnliMlpwYkdVQUFIamFuVk5uVkZQcEZqMzMzdlJDUzRpQWxFdHZVaFVJSUZKQ2k0QVVrU1lxSVFrUVNvZ2hvZGtWVWNFUlJVVUVHOGlnaUFPT2pvQ01GVkVzRElvSzJBZmtJYUtPZzZPSWlzcjc0WHVqYTlhODkrYk4vclhYUHVlczg1Mnp6d2ZBQ0F5V1NETlJOWUFNcVVJZUVlQ0R4OFRHNGVRdVFJRUtKSEFBRUFpelpDRnovU01CQVBoK1BEd3JJc0FIdmdBQmVOTUxDQURBVFp2QU1CeUgvdy9xUXBsY0FZQ0VBY0Iwa1RoTENJQVVBRUI2amtLbUFFQkdBWUNkbUNaVEFLQUVBR0RMWTJMakFGQXRBR0FuZitiVEFJQ2QrSmw3QVFCYmxDRVZBYUNSQUNBVFpZaEVBR2c3QUt6UFZvcEZBRmd3QUJSbVM4UTVBTmd0QURCSlYyWklBTEMzQU1ET0VBdXlBQWdNQURCUmlJVXBBQVI3QUdESUl5TjRBSVNaQUJSRzhsYzg4U3V1RU9jcUFBQjRtYkk4dVNRNVJZRmJDQzF4QjFkWExoNG96a2tYS3hRMllRSmhta0F1d25tWkdUS0JOQS9nODh3QUFLQ1JGUkhnZy9QOWVNNE9yczdPTm82MkRsOHQ2cjhHL3lKaVl1UCs1YytyY0VBQUFPRjBmdEgrTEMrekdvQTdCb0J0L3FJbDdnUm9YZ3VnZGZlTFpySVBRTFVBb09uYVYvTncrSDQ4UEVXaGtMbloyZVhrNU5oS3hFSmJZY3BYZmY1bndsL0FWLzFzK1g0OC9QZjE0TDdpSklFeVhZRkhCUGpnd3N6MFRLVWN6NUlKaEdMYzVvOUgvTGNMLy93ZDB5TEVTV0s1V0NvVTQxRVNjWTVFbW96ek1xVWlpVUtTS2NVbDB2OWs0dDhzK3dNKzN6VUFzR28rQVh1UkxhaGRZd1AyU3ljUVdIVEE0dmNBQVBLN2I4SFVLQWdEZ0dpRDRjOTMvKzgvL1VlZ0pRQ0Faa21TY1FBQVhrUWtMbFRLc3ovSENBQUFSS0NCS3JCQkcvVEJHQ3pBQmh6QkJkekJDL3hnTm9SQ0pNVENRaEJDQ21TQUhISmdLYXlDUWlpR3piQWRLbUF2MUVBZE5NQlJhSWFUY0E0dXdsVzREajF3RC9waENKN0JLTHlCQ1FSQnlBZ1RZU0hhaUFGaWlsZ2pqZ2dYbVlYNEljRklCQktMSkNESmlCUlJJa3VSTlVneFVvcFVJRlZJSGZJOWNnSTVoMXhHdXBFN3lBQXlndnlHdkVjeGxJR3lVVDNVRExWRHVhZzNHb1JHb2d2UVpIUXhtbzhXb0p2UWNyUWFQWXcyb2VmUXEyZ1AybzgrUThjd3dPZ1lCelBFYkRBdXhzTkNzVGdzQ1pOank3RWlyQXlyeGhxd1Zxd0R1NG4xWTgreGR3UVNnVVhBQ1RZRWQwSWdZUjVCU0ZoTVdFN1lTS2dnSENRMEVkb0pOd2tEaEZIQ0p5S1RxRXUwSnJvUitjUVlZakl4aDFoSUxDUFdFbzhUTHhCN2lFUEVOeVFTaVVNeUo3bVFBa214cEZUU0V0SkcwbTVTSStrc3FaczBTQm9qazhuYVpHdXlCem1VTENBcnlJWGtuZVRENURQa0crUWg4bHNLbldKQWNhVDRVK0lvVXNwcVNobmxFT1UwNVFabG1ESkJWYU9hVXQyb29WUVJOWTlhUXEyaHRsS3ZVWWVvRXpSMW1qbk5neFpKUzZXdG9wWFRHbWdYYVBkcHIraDB1aEhkbFI1T2w5Qlgwc3ZwUitpWDZBUDBkd3dOaGhXRHg0aG5LQm1iR0FjWVp4bDNHSytZVEtZWjA0c1p4MVF3TnpIcm1PZVpENWx2VlZncXRpcDhGWkhLQ3BWS2xTYVZHeW92VkttcXBxcmVxZ3RWODFYTFZJK3BYbE45cmtaVk0xUGpxUW5VbHF0VnFwMVE2MU1iVTJlcE82aUhxbWVvYjFRL3BINVovWWtHV2NOTXcwOURwRkdnc1YvanZNWWdDMk1aczNnc0lXc05xNFoxZ1RYRUpySE4yWHgyS3J1WS9SMjdpejJxcWFFNVF6TktNMWV6VXZPVVpqOEg0NWh4K0p4MFRnbm5LS2VYODM2SzNoVHZLZUlwRzZZMFRMa3haVnhycXBhWGxsaXJTS3RScTBmcnZUYXU3YWVkcHIxRnUxbjdnUTVCeDBvblhDZEhaNC9PQlozblU5bFQzYWNLcHhaTlBUcjFyaTZxYTZVYm9idEVkNzl1cCs2WW5yNWVnSjVNYjZmZWViM24raHg5TC8xVS9XMzZwL1ZIREZnR3N3d2tCdHNNemhnOHhUVnhiendkTDhmYjhWRkRYY05BUTZWaGxXR1g0WVNSdWRFOG85VkdqVVlQakduR1hPTWs0MjNHYmNhakpnWW1JU1pMVGVwTjdwcFNUYm1tS2FZN1REdE14ODNNemFMTjFwazFtejB4MXpMbm0rZWIxNXZmdDJCYWVGb3N0cWkydUdWSnN1UmFwbG51dHJ4dWhWbzVXYVZZVlZwZHMwYXRuYTBsMXJ1dHU2Y1JwN2xPazA2cm50Wm53N0R4dHNtMnFiY1pzT1hZQnR1dXRtMjJmV0ZuWWhkbnQ4V3V3KzZUdlpOOXVuMk4vVDBIRFlmWkRxc2RXaDErYzdSeUZEcFdPdDZhenB6dVAzM0Y5SmJwTDJkWXp4RFAyRFBqdGhQTEtjUnBuVk9iMDBkbkYyZTVjNFB6aUl1SlM0TExMcGMrTHBzYnh0M0l2ZVJLZFBWeFhlRjYwdldkbTdPYnd1Mm8yNi91TnU1cDdvZmNuOHcwbnltZVdUTnowTVBJUStCUjVkRS9DNStWTUd2ZnJINVBRMCtCWjdYbkl5OWpMNUZYcmRld3Q2VjNxdmRoN3hjKzlqNXluK00rNHp3MzNqTGVXVi9NTjhDM3lMZkxUOE52bmwrRjMwTi9JLzlrLzNyLzBRQ25nQ1VCWndPSmdVR0JXd0w3K0hwOEliK09QenJiWmZheTJlMUJqS0M1UVJWQmo0S3RndVhCclNGb3lPeVFyU0gzNTVqT2tjNXBEb1ZRZnVqVzBBZGg1bUdMdzM0TUo0V0hoVmVHUDQ1d2lGZ2EwVEdYTlhmUjNFTnozMFQ2UkpaRTNwdG5NVTg1cnkxS05TbytxaTVxUE5vM3VqUzZQOFl1WmxuTTFWaWRXRWxzU3h3NUxpcXVObTVzdnQvODdmT0g0cDNpQytON0Y1Z3Z5RjF3ZWFIT3d2U0ZweGFwTGhJc09wWkFUSWhPT0pUd1FSQXFxQmFNSmZJVGR5V09Dbm5DSGNKbklpL1JOdEdJMkVOY0toNU84a2dxVFhxUzdKRzhOWGtreFRPbExPVzVoQ2Vwa0x4TURVemRtenFlRnBwMklHMHlQVHE5TVlPU2taQnhRcW9oVFpPMlorcG41bVoyeTZ4bGhiTCt4VzZMdHk4ZWxRZkphN09RckFWWkxRcTJRcWJvVkZvbzF5b0hzbWRsVjJhL3pZbktPWmFybml2TjdjeXp5dHVRTjV6dm4vL3RFc0lTNFpLMnBZWkxWeTBkV09hOXJHbzVzanh4ZWRzSzR4VUZLNFpXQnF3OHVJcTJLbTNWVDZ2dFY1ZXVmcjBtZWsxcmdWN0J5b0xCdFFGcjZ3dFZDdVdGZmV2YzErMWRUMWd2V2QrMVlmcUduUnMrRlltS3JoVGJGNWNWZjlnbzNIamxHNGR2eXIrWjNKUzBxYXZFdVdUUFp0Sm02ZWJlTFo1YkRwYXFsK2FYRG00TjJkcTBEZDlXdE8zMTlrWGJMNWZOS051N2c3WkR1YU8vUExpOFphZkp6czA3UDFTa1ZQUlUrbFEyN3RMZHRXSFgrRzdSN2h0N3ZQWTA3TlhiVzd6My9UN0p2dHRWQVZWTjFXYlZaZnRKKzdQM1A2NkpxdW40bHZ0dFhhMU9iWEh0eHdQU0EvMEhJdzYyMTduVTFSM1NQVlJTajlZcjYwY094eCsrL3AzdmR5ME5OZzFWalp6RzRpTndSSG5rNmZjSjMvY2VEVHJhZG94N3JPRUgweDkySFdjZEwycENtdkthUnB0VG12dGJZbHU2VDh3KzBkYnEzbnI4UjlzZkQ1dzBQRmw1U3ZOVXlXbmE2WUxUazJmeXo0eWRsWjE5Zmk3NTNHRGJvclo3NTJQTzMyb1BiKys2RUhUaDBrWC9pK2M3dkR2T1hQSzRkUEt5MitVVFY3aFhtcTg2WDIzcWRPbzgvcFBUVDhlN25MdWFycmxjYTdudWVyMjFlMmIzNlJ1ZU44N2Q5TDE1OFJiLzF0V2VPVDNkdmZONmIvZkY5L1hmRnQxK2NpZjl6c3U3MlhjbjdxMjhUN3hmOUVEdFFkbEQzWWZWUDF2KzNOanYzSDlxd0hlZzg5SGNSL2NHaFlQUC9wSDFqdzlEQlkrWmo4dUdEWWJybmpnK09UbmlQM0w5NmZ5blE4OWt6eWFlRi82aS9zdXVGeFl2ZnZqVjY5Zk8wWmpSb1pmeWw1Ty9iWHlsL2VyQTZ4bXYyOGJDeGg2K3lYZ3pNVjcwVnZ2dHdYZmNkeDN2bzk4UFQrUjhJSDhvLzJqNXNmVlQwS2Y3a3htVGsvOEVBNWp6L0dNekxkc0FBQUFnWTBoU1RRQUFlaVVBQUlDREFBRDUvd0FBZ09rQUFIVXdBQURxWUFBQU9wZ0FBQmR2a2wvRlJnQUFBR0pKUkVGVWVOcGk5QW1QWVVBR2V6YXZxMmRnWUdCdzhRMXFSQlpuUVZka2FlL2NBR1dqS0daVzA5RkRVV1RwNE1JZ3E2REV3TURBNEhCbzF6WUdKWFhOZzNDRnlJcGdBRjB4ODZQN2R4clFGV0ZUek9nVEh0UEF3TUJRejRBZk5BQUdBTjFDS1BzNE5ETHZBQUFBQUVsRlRrU3VRbUNDKSBjZW50ZXIgbm8tcmVwZWF0fSNjb250cm9sS2l0IC5wYW5lbCAuYXJyb3ctYi1zdWItbWlue2JhY2tncm91bmQ6dXJsKGRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCxpVkJPUncwS0dnb0FBQUFOU1VoRVVnQUFBQW9BQUFBR0NBWUFBQUQ2OEEvR0FBQUFDWEJJV1hNQUFBc1RBQUFMRXdFQW1wd1lBQUFLVDJsRFExQlFhRzkwYjNOb2IzQWdTVU5ESUhCeWIyWnBiR1VBQUhqYW5WTm5WRlBwRmozMzN2UkNTNGlBbEV0dlVoVUlJRkpDaTRBVWtTWXFJUWtRU29naG9ka1ZVY0VSUlVVRUc4aWdpQU9Pam9DTUZWRXNESW9LMkFma0lhS09nNk9JaXNyNzRYdWphOWE4OStiTi9yWFhQdWVzODUyenp3ZkFDQXlXU0ROUk5ZQU1xVUllRWVDRHg4VEc0ZVF1UUlFS0pIQUFFQWl6WkNGei9TTUJBUGgrUER3cklzQUh2Z0FCZU5NTENBREFUWnZBTUJ5SC93L3FRcGxjQVlDRUFjQjBrVGhMQ0lBVUFFQjZqa0ttQUVCR0FZQ2RtQ1pUQUtBRUFHRExZMkxqQUZBdEFHQW5mK2JUQUlDZCtKbDdBUUJibENFVkFhQ1JBQ0FUWlloRUFHZzdBS3pQVm9wRkFGZ3dBQlJtUzhRNUFOZ3RBREJKVjJaSUFMQzNBTURPRUF1eUFBZ01BREJSaUlVcEFBUjdBR0RJSXlONEFJU1pBQlJHOGxjODhTdXVFT2NxQUFCNG1iSTh1U1E1UllGYkNDMXhCMWRYTGg0b3pra1hLeFEyWVFKaG1rQXV3bm1aR1RLQk5BL2c4OHdBQUtDUkZSSGdnL1A5ZU00T3JzN09ObzYyRGw4dDZyOEcveUppWXVQKzVjK3JjRUFBQU9GMGZ0SCtMQyt6R29BN0JvQnQvcUlsN2dSb1hndWdkZmVMWnJJUFFMVUFvT25hVi9OdytINDhQRVdoa0xuWjJlWGs1TmhLeEVKYlljcFhmZjVud2wvQVYvMXMrWDQ4L1BmMTRMN2lKSUV5WFlGSEJQamd3c3owVEtVY3o1SUpoR0xjNW85SC9MY0wvL3dkMHlMRVNXSzVXQ29VNDFFU2NZNUVtb3p6TXFVaWlVS1NLY1VsMHY5azR0OHMrd00rM3pVQXNHbytBWHVSTGFoZFl3UDJTeWNRV0hUQTR2Y0FBUEs3YjhIVUtBZ0RnR2lENGM5My8rOC8vVWVnSlFDQVprbVNjUUFBWGtRa0xsVEtzei9IQ0FBQVJLQ0JLckJCRy9UQkdDekFCaHpCQmR6QkMveGdOb1JDSk1UQ1FoQkNDbVNBSEhKZ0theUNRaWlHemJBZEttQXYxRUFkTk1CUmFJYVRjQTR1d2xXNERqMXdEL3BoQ0o3QktMeUJDUVJCeUFnVFlTSGFpQUZpaWxnampnZ1htWVg0SWNGSUJCS0xKQ0RKaUJSUklrdVJOVWd4VW9wVUlGVklIZkk5Y2dJNWgxeEd1cEU3eUFBeWd2eUd2RWN4bElHeVVUM1VETFZEdWFnM0dvUkdvZ3ZRWkhReG1vOFdvSnZRY3JRYVBZdzJvZWZRcTJnUDJvOCtROGN3d09nWUJ6UEViREF1eHNOQ3NUZ3NDWk5qeTdFaXJBeXJ4aHF3VnF3RHU0bjFZOCt4ZHdRU2dVWEFDVFlFZDBJZ1lSNUJTRmhNV0U3WVNLZ2dIQ1EwRWRvSk53a0RoRkhDSnlLVHFFdTBKcm9SK2NRWVlqSXhoMWhJTENQV0VvOFRMeEI3aUVQRU55UVNpVU15SjdtUUFrbXhwRlRTRXRKRzBtNVNJK2tzcVpzMFNCb2prOG5hWkd1eUJ6bVVMQ0FyeUlYa25lVEQ1RFBrRytRaDhsc0tuV0pBY2FUNFUrSW9Vc3BxU2hubEVPVTA1UVpsbURKQlZhT2FVdDJvb1ZRUk5ZOWFRcTJodGxLdlVZZW9FelIxbWpuTmd4WkpTNld0b3BYVEdtZ1hhUGRwcitoMHVoSGRsUjVPbDlCWDBzdnBSK2lYNkFQMGR3d05oaFdEeDRobktCbWJHQWNZWnhsM0dLK1lUS1laMDRzWngxUXdOekhybU9lWkQ1bHZWVmdxdGlwOEZaSEtDcFZLbFNhVkd5b3ZWS21xcHFyZXFndFY4MVhMVkkrcFhsTjlya1pWTTFQanFRblVscXRWcXAxUTYxTWJVMmVwTzZpSHFtZW9iMVEvcEg1Wi9Za0dXY05NdzA5RHBGR2dzVi9qdk1ZZ0MyTVpzM2dzSVdzTnE0WjFnVFhFSnJITjJYeDJLcnVZL1IyN2l6MnFxYUU1UXpOS00xZXpVdk9VWmo4SDQ1aHgrSngwVGdubktLZVg4MzZLM2hUdktlSXBHNlkwVExreFpWeHJxcGFYbGxpclNLdFJxMGZydlRhdTdhZWRwcjFGdTFuN2dRNUJ4MG9uWENkSFo0L09CWjNuVTlsVDNhY0tweFpOUFRyMXJpNnFhNlVib2J0RWQ3OXVwKzZZbnI1ZWdKNU1iNmZlZWIzbitoeDlMLzFVL1czNnAvVkhERmdHc3d3a0J0c016aGc4eFRWeGJ6d2RMOGZiOFZGRFhjTkFRNlZobFdHWDRZU1J1ZEU4bzlWR2pVWVBqR25HWE9NazQyM0diY2FqSmdZbUlTWkxUZXBON3BwU1RibW1LYVk3VER0TXg4M016YUxOMXBrMW16MHgxekxubStlYjE1dmZ0MkJhZUZvc3RxaTJ1R1ZKc3VSYXBsbnV0cnh1aFZvNVdhVllWVnBkczBhdG5hMGwxcnV0dTZjUnA3bE9rMDZybnRabnc3RHh0c20ycWJjWnNPWFlCdHV1dG0yMmZXRm5ZaGRudDhXdXcrNlR2Wk45dW4yTi9UMEhEWWZaRHFzZFdoMStjN1J5RkRwV090NmF6cHp1UDMzRjlKYnBMMmRZenhEUDJEUGp0aFBMS2NScG5WT2IwMGRuRjJlNWM0UHppSXVKUzRMTExwYytMcHNieHQzSXZlUktkUFZ4WGVGNjB2V2RtN09id3UybzI2L3VOdTVwN29mY244dzBueW1lV1ROejBNUElRK0JSNWRFL0M1K1ZNR3Zmckg1UFEwK0JaN1huSXk5akw1RlhyZGV3dDZWM3F2ZGg3eGMrOWo1eW4rTSs0enczM2pMZVdWL01OOEMzeUxmTFQ4TnZubCtGMzBOL0kvOWsvM3IvMFFDbmdDVUJad09KZ1VHQld3TDcrSHA4SWIrT1B6cmJaZmF5MmUxQmpLQzVRUlZCajRLdGd1WEJyU0ZveU95UXJTSDM1NWpPa2M1cERvVlFmdWpXMEFkaDVtR0x3MzRNSjRXSGhWZUdQNDV3aUZnYTBUR1hOWGZSM0VOejMwVDZSSlpFM3B0bk1VODVyeTFLTlNvK3FpNXFQTm8zdWpTNlA4WXVabG5NMVZpZFdFbHNTeHc1TGlxdU5tNXN2dC84N2ZPSDRwM2lDK043RjVndnlGMXdlYUhPd3ZTRnB4YXBMaElzT3BaQVRJaE9PSlR3UVJBcXFCYU1KZklUZHlXT0NubkNIY0puSWkvUk50R0kyRU5jS2g1TzhrZ3FUWHFTN0pHOE5Ya2t4VE9sTE9XNWhDZXBrTHhNRFV6ZG16cWVGcHAySUcweVBUcTlNWU9Ta1pCeFFxb2hUWk8yWitwbjVtWjJ5NnhsaGJMK3hXNkx0eThlbFFmSmE3T1FyQVZaTFFxMlFxYm9WRm9vMXlvSHNtZGxWMmEvelluS09aYXJuaXZON2N5enl0dVFONXp2bi8vdEVzSVM0WksycFlaTFZ5MGRXT2E5ckdvNXNqeHhlZHNLNHhVRks0WldCcXc4dUlxMkttM1ZUNnZ0VjVldWZyMG1lazFyZ1Y3QnlvTEJ0UUZyNnd0VkN1V0ZmZXZjMSsxZFQxZ3ZXZCsxWWZxR25ScytGWW1LcmhUYkY1Y1ZmOWdvM0hqbEc0ZHZ5citaM0pTMHFhdkV1V1RQWnRKbTZlYmVMWjViRHBhcWwrYVhEbTROMmRxMERkOVd0TzMxOWtYYkw1Zk5LTnU3ZzdaRHVhTy9QTGk4WmFmSnpzMDdQMVNrVlBSVStsUTI3dExkdFdIWCtHN1I3aHQ3dlBZMDdOWGJXN3ozL1Q3SnZ0dFZBVlZOMVdiVlpmdEorN1AzUDY2SnF1bjRsdnR0WGExT2JYSHR4d1BTQS8wSEl3NjIxN25VMVIzU1BWUlNqOVlyNjBjT3h4KysvcDN2ZHkwTk5nMVZqWnpHNGlOd1JIbms2ZmNKMy9jZURUcmFkb3g3ck9FSDB4OTJIV2NkTDJwQ212S2FScHRUbXZ0YllsdTZUOHcrMGRicTNucjhSOXNmRDV3MFBGbDVTdk5VeVduYTZZTFRrMmZ5ejR5ZGxaMTlmaTc1M0dEYm9yWjc1MlBPMzJvUGIrKzZFSFRoMGtYL2krYzd2RHZPWFBLNGRQS3kyK1VUVjdoWG1xODZYMjNxZE9vOC9wUFRUOGU3bkx1YXJybGNhN251ZXIyMWUyYjM2UnVlTjg3ZDlMMTU4UmIvMXRXZU9UM2R2Zk42Yi9mRjkvWGZGdDErY2lmOXpzdTcyWGNuN3EyOFQ3eGY5RUR0UWRsRDNZZlZQMXYrM05qdjNIOXF3SGVnODlIY1IvY0doWVBQL3BIMWp3OURCWStaajh1R0RZYnJuamcrT1RuaVAzTDk2ZnluUTg5a3p5YWVGLzZpL3N1dUZ4WXZmdmpWNjlmTzBaalJvWmZ5bDVPL2JYeWwvZXJBNnhtdjI4YkN4aDYreVhnek1WNzBWdnZ0d1hmY2R4M3ZvOThQVCtSOElIOG8vMmo1c2ZWVDBLZjdreG1Uay84RUE1anovR016TGRzQUFBQWdZMGhTVFFBQWVpVUFBSUNEQUFENS93QUFnT2tBQUhVd0FBRHFZQUFBT3BnQUFCZHZrbC9GUmdBQUFHOUpSRUZVZU5wOHpyRU9RREFBaE9HL0dFU1lCYnRKdkFLRDFlS0JSTitzTDFOTjU3YTdpU0RpcGt2dUcwNmtXU2FCbGYvSVpKb1h5cXFock9wUFljMk9OWnE0N1hvVnZJdEFESGxSZkNFSmJISGI5UUFxZUNkQWpDZStJNEFUUG5EdzdvRUFrdGVselJwOTlmdHdEQUNmc1MwWEFiejRQd0FBQUFCSlJVNUVya0pnZ2c9PSkgY2VudGVyIG5vLXJlcGVhdH0jY29udHJvbEtpdCAucGFuZWwgLmFycm93LWItbWF4LCNjb250cm9sS2l0IC5wYW5lbCAuYXJyb3ctYi1taW4sI2NvbnRyb2xLaXQgLnBhbmVsIC5hcnJvdy1iLXN1Yi1tYXgsI2NvbnRyb2xLaXQgLnBhbmVsIC5hcnJvdy1iLXN1Yi1taW57d2lkdGg6MTBweDtoZWlnaHQ6MTAwJTtmbG9hdDpyaWdodH0jY29udHJvbEtpdCAucGlja2Vye3BvaW50ZXItZXZlbnRzOmF1dG87LXdlYmtpdC1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW1vei1ib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym94LXNpemluZzpib3JkZXItYm94O2JvcmRlci1yYWRpdXM6M3B4Oy1tb3otYm9yZGVyLXJhZGl1czozcHg7YmFja2dyb3VuZC1jb2xvcjojM2IzYjNiO2ZvbnQtZmFtaWx5OkFyaWFsLHNhbnMtc2VyaWY7Zm9udC1zaXplOjExcHg7Y29sb3I6I2ZmZjt0ZXh0LXNoYWRvdzoxcHggMXB4ICMwMDA7b3ZlcmZsb3c6aGlkZGVuO3Bvc2l0aW9uOmFic29sdXRlO3otaW5kZXg6MjE0NzQ4MzYzMTt3aWR0aDozNjBweDstd2Via2l0LXRvdWNoLWNhbGxvdXQ6bm9uZTstd2Via2l0LXVzZXItc2VsZWN0Om5vbmU7LWtodG1sLXVzZXItc2VsZWN0Om5vbmU7LW1vei11c2VyLXNlbGVjdDpub25lOy1tcy11c2VyLXNlbGVjdDpub25lO3VzZXItc2VsZWN0Om5vbmU7Ym94LXNoYWRvdzowIDJweCAycHggcmdiYSgwLDAsMCwuMjUpfSNjb250cm9sS2l0IC5waWNrZXIgY2FudmFze3ZlcnRpY2FsLWFsaWduOmJvdHRvbTtjdXJzb3I6cG9pbnRlcn0jY29udHJvbEtpdCAucGlja2VyIC53cmFwey13ZWJraXQtYm94LXNpemluZzpib3JkZXItYm94Oy1tb3otYm94LXNpemluZzpib3JkZXItYm94O2JveC1zaXppbmc6Ym9yZGVyLWJveDtwYWRkaW5nOjEwcHg7ZmxvYXQ6bGVmdH0jY29udHJvbEtpdCAucGlja2VyIC5maWVsZC13cmFwe3BhZGRpbmc6M3B4fSNjb250cm9sS2l0IC5waWNrZXIgLnNsaWRlci13cmFwe3BhZGRpbmc6M3B4IDEzcHggM3B4IDNweH0jY29udHJvbEtpdCAucGlja2VyIC5maWVsZC13cmFwLCNjb250cm9sS2l0IC5waWNrZXIgLmlucHV0LXdyYXAsI2NvbnRyb2xLaXQgLnBpY2tlciAuc2xpZGVyLXdyYXB7aGVpZ2h0OmF1dG87b3ZlcmZsb3c6aGlkZGVuO2Zsb2F0OmxlZnR9I2NvbnRyb2xLaXQgLnBpY2tlciAuaW5wdXQtd3JhcHstd2Via2l0LWJveC1zaXppbmc6Ym9yZGVyLWJveDstbW96LWJveC1zaXppbmc6Ym9yZGVyLWJveDtib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym9yZGVyOjFweCBzb2xpZCAjMjQyNDI0O2JvcmRlci1yYWRpdXM6MnB4Oy1tb3otYm9yZGVyLXJhZGl1czoycHg7d2lkdGg6MTQwcHg7ZmxvYXQ6cmlnaHQ7cGFkZGluZzo1cHggMTBweCAxcHggMH0jY29udHJvbEtpdCAucGlja2VyIC5pbnB1dC1maWVsZHt3aWR0aDo1MCU7ZmxvYXQ6cmlnaHQ7bWFyZ2luLWJvdHRvbTo0cHh9I2NvbnRyb2xLaXQgLnBpY2tlciAuaW5wdXQtZmllbGQgLmxhYmVse3BhZGRpbmc6OHB4IDAgMDtjb2xvcjojODc4Nzg3O3RleHQtYWxpZ246Y2VudGVyO3RleHQtdHJhbnNmb3JtOnVwcGVyY2FzZTtmb250LXdlaWdodDo3MDA7dGV4dC1zaGFkb3c6MXB4IDFweCAjMWExYTFhO3dpZHRoOjQwJX0jY29udHJvbEtpdCAucGlja2VyIC5pbnB1dC1maWVsZCAud3JhcHtwYWRkaW5nOjA7d2lkdGg6NjAlO2hlaWdodDphdXRvO2Zsb2F0OnJpZ2h0fSNjb250cm9sS2l0IC5waWNrZXIgLmNvbnRyb2xzLXdyYXB7LXdlYmtpdC1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW1vei1ib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym94LXNpemluZzpib3JkZXItYm94O3dpZHRoOjEwMCU7aGVpZ2h0OmF1dG87ZmxvYXQ6cmlnaHQ7cGFkZGluZzo5cHggMCAwfSNjb250cm9sS2l0IC5waWNrZXIgLmNvbnRyb2xzLXdyYXAgaW5wdXRbdHlwZT1idXR0b25de2Zsb2F0OnJpZ2h0O3dpZHRoOjY1cHg7bWFyZ2luOjAgMCAwIDEwcHh9I2NvbnRyb2xLaXQgLnBpY2tlciAuY29sb3ItY29udHJhc3R7LXdlYmtpdC1ib3gtc2l6aW5nOmJvcmRlci1ib3g7LW1vei1ib3gtc2l6aW5nOmJvcmRlci1ib3g7Ym94LXNpemluZzpib3JkZXItYm94O2JvcmRlcjpub25lO2JveC1zaGFkb3c6MCAwIDAgMXB4ICMxZjFmMWYgaW5zZXQ7Ym9yZGVyLXJhZGl1czoycHg7LW1vei1ib3JkZXItcmFkaXVzOjJweDtoZWlnaHQ6MjVweDtwYWRkaW5nOjNweDt3aWR0aDo4MCU7bWFyZ2luLWJvdHRvbTo0cHg7ZmxvYXQ6cmlnaHR9I2NvbnRyb2xLaXQgLnBpY2tlciAuY29sb3ItY29udHJhc3QgZGl2e3dpZHRoOjUwJTtoZWlnaHQ6MTAwJTtmbG9hdDpsZWZ0fSNjb250cm9sS2l0IC5waWNrZXIgaW5wdXRbdHlwZT10ZXh0XXtwYWRkaW5nOjA7dGV4dC1hbGlnbjpjZW50ZXI7d2lkdGg6NjAlO2Zsb2F0OnJpZ2h0fSNjb250cm9sS2l0IC5waWNrZXIgLndyYXAgLmlucHV0LXdyYXA6bnRoLW9mLXR5cGUoMyl7Ym9yZGVyLWJvdHRvbS1sZWZ0LXJhZGl1czowO2JvcmRlci1ib3R0b20tcmlnaHQtcmFkaXVzOjB9I2NvbnRyb2xLaXQgLnBpY2tlciAud3JhcCAuaW5wdXQtd3JhcDpudGgtb2YtdHlwZSg0KXtib3JkZXItdG9wOm5vbmU7Ym9yZGVyLXRvcC1sZWZ0LXJhZGl1czowO2JvcmRlci10b3AtcmlnaHQtcmFkaXVzOjB9I2NvbnRyb2xLaXQgLnBpY2tlciAud3JhcCAuaW5wdXQtd3JhcDpudGgtb2YtdHlwZSg0KSAuaW5wdXQtZmllbGR7d2lkdGg6MTAwJX0jY29udHJvbEtpdCAucGlja2VyIC53cmFwIC5pbnB1dC13cmFwOm50aC1vZi10eXBlKDQpIC5pbnB1dC1maWVsZCAubGFiZWx7d2lkdGg6MjAlfSNjb250cm9sS2l0IC5waWNrZXIgLndyYXAgLmlucHV0LXdyYXA6bnRoLW9mLXR5cGUoNCkgaW5wdXRbdHlwZT10ZXh0XXt3aWR0aDo4MCV9I2NvbnRyb2xLaXQgLnBpY2tlciAuZmllbGQtd3JhcCwjY29udHJvbEtpdCAucGlja2VyIC5zbGlkZXItd3JhcHtiYWNrZ3JvdW5kOiMxZTIyMjQ7Ym9yZGVyOm5vbmU7Ym94LXNoYWRvdzowIDAgMCAxcHggIzFmMWYxZiBpbnNldDtib3JkZXItcmFkaXVzOjJweDstbW96LWJvcmRlci1yYWRpdXM6MnB4O3Bvc2l0aW9uOnJlbGF0aXZlO21hcmdpbi1yaWdodDo1cHh9I2NvbnRyb2xLaXQgLnBpY2tlciAuZmllbGQtd3JhcCAuaW5kaWNhdG9yLCNjb250cm9sS2l0IC5waWNrZXIgLnNsaWRlci13cmFwIC5pbmRpY2F0b3J7cG9zaXRpb246YWJzb2x1dGU7Ym9yZGVyOjJweCBzb2xpZCAjZmZmO2JveC1zaGFkb3c6MCAxcHggYmxhY2ssMCAxcHggIzAwMCBpbnNldDtjdXJzb3I6cG9pbnRlcn0jY29udHJvbEtpdCAucGlja2VyIC5maWVsZC13cmFwIC5pbmRpY2F0b3J7d2lkdGg6OHB4O2hlaWdodDo4cHg7bGVmdDo1MCU7dG9wOjUwJTtib3JkZXItcmFkaXVzOjUwJTstbW96LWJvcmRlci1yYWRpdXM6NTAlfSNjb250cm9sS2l0IC5waWNrZXIgLnNsaWRlci13cmFwIC5pbmRpY2F0b3J7d2lkdGg6MTRweDtoZWlnaHQ6M3B4O2JvcmRlci1yYWRpdXM6OHB4Oy1tb3otYm9yZGVyLXJhZGl1czo4cHg7bGVmdDoxcHg7dG9wOjFweH0jY29udHJvbEtpdCAucGlja2VyIC5zbGlkZXItd3JhcCAuaW5kaWNhdG9yOmFmdGVye2NvbnRlbnQ6Jyc7d2lkdGg6MDtoZWlnaHQ6MDtib3JkZXItdG9wOjQuNXB4IHNvbGlkIHRyYW5zcGFyZW50O2JvcmRlci1ib3R0b206NC41cHggc29saWQgdHJhbnNwYXJlbnQ7Ym9yZGVyLXJpZ2h0OjRweCBzb2xpZCAjZmZmO2Zsb2F0OnJpZ2h0O3Bvc2l0aW9uOmFic29sdXRlO3RvcDotMnB4O2xlZnQ6MTlweH0jY29udHJvbEtpdCAucGlja2VyIC5zbGlkZXItd3JhcCAuaW5kaWNhdG9yOmJlZm9yZXtjb250ZW50OicnO3dpZHRoOjA7aGVpZ2h0OjA7Ym9yZGVyLXRvcDo0LjVweCBzb2xpZCB0cmFuc3BhcmVudDtib3JkZXItYm90dG9tOjQuNXB4IHNvbGlkIHRyYW5zcGFyZW50O2JvcmRlci1yaWdodDo0cHggc29saWQgIzAwMDtmbG9hdDpyaWdodDtwb3NpdGlvbjphYnNvbHV0ZTt0b3A6LTNweDtsZWZ0OjE5cHh9XCJcbn07IFxubW9kdWxlLmV4cG9ydHMgPSBTdHlsZTsiLCJmdW5jdGlvbiBFdmVudF8oc2VuZGVyLHR5cGUsZGF0YSkge1xuICAgIHRoaXMuc2VuZGVyID0gc2VuZGVyO1xuICAgIHRoaXMudHlwZSAgID0gdHlwZTtcbiAgICB0aGlzLmRhdGEgICA9IGRhdGE7XG59XG5tb2R1bGUuZXhwb3J0cyA9IEV2ZW50XzsiLCJmdW5jdGlvbiBFdmVudERpc3BhdGNoZXIoKSB7XG4gICAgdGhpcy5fbGlzdGVuZXJzID0gW107XG59O1xuXG5FdmVudERpc3BhdGNoZXIucHJvdG90eXBlID0ge1xuICAgIGFkZEV2ZW50TGlzdGVuZXI6IGZ1bmN0aW9uIChldmVudFR5cGUsIGxpc3RlbmVyLCBjYWxsYmFja01ldGhvZCkge1xuICAgICAgICB0aGlzLl9saXN0ZW5lcnNbZXZlbnRUeXBlXSA9IHRoaXMuX2xpc3RlbmVyc1tldmVudFR5cGVdIHx8IFtdO1xuICAgICAgICB0aGlzLl9saXN0ZW5lcnNbZXZlbnRUeXBlXS5wdXNoKHtvYmo6IGxpc3RlbmVyLCBtZXRob2Q6IGNhbGxiYWNrTWV0aG9kfSk7XG4gICAgfSxcblxuICAgIGRpc3BhdGNoRXZlbnQ6IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICB2YXIgdHlwZSA9IGV2ZW50LnR5cGU7XG5cbiAgICAgICAgaWYgKCF0aGlzLmhhc0V2ZW50TGlzdGVuZXIodHlwZSkpe1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuX2xpc3RlbmVyc1t0eXBlXTtcbiAgICAgICAgdmFyIGkgPSAtMSwgbCA9IGxpc3RlbmVycy5sZW5ndGg7XG5cbiAgICAgICAgdmFyIG9iaiwgbWV0aG9kO1xuXG4gICAgICAgIHdoaWxlICgrK2kgPCBsKSB7XG4gICAgICAgICAgICBvYmogPSBsaXN0ZW5lcnNbaV0ub2JqO1xuICAgICAgICAgICAgbWV0aG9kID0gbGlzdGVuZXJzW2ldLm1ldGhvZDtcblxuICAgICAgICAgICAgaWYgKCFvYmpbbWV0aG9kXSl7XG4gICAgICAgICAgICAgICAgdGhyb3cgb2JqICsgJyBoYXMgbm8gbWV0aG9kICcgKyBtZXRob2Q7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIG9ialttZXRob2RdKGV2ZW50KTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICByZW1vdmVFdmVudExpc3RlbmVyOiBmdW5jdGlvbiAodHlwZSwgb2JqLCBtZXRob2QpIHtcbiAgICAgICAgaWYgKCF0aGlzLmhhc0V2ZW50TGlzdGVuZXIodHlwZSkpe1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxpc3RlbmVycyA9IHRoaXMuX2xpc3RlbmVyc1t0eXBlXTtcblxuICAgICAgICB2YXIgaSA9IGxpc3RlbmVycy5sZW5ndGg7XG4gICAgICAgIHdoaWxlICgtLWkgPiAtMSkge1xuICAgICAgICAgICAgaWYgKGxpc3RlbmVyc1tpXS5vYmogPT0gb2JqICYmIGxpc3RlbmVyc1tpXS5tZXRob2QgPT0gbWV0aG9kKSB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXJzLnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PSAwKXtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMuX2xpc3RlbmVyc1t0eXBlXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgcmVtb3ZlQWxsRXZlbnRMaXN0ZW5lcnM6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5fbGlzdGVuZXJzID0gW107XG4gICAgfSxcblxuICAgIGhhc0V2ZW50TGlzdGVuZXI6IGZ1bmN0aW9uICh0eXBlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9saXN0ZW5lcnNbdHlwZV0gIT0gdW5kZWZpbmVkICYmIHRoaXMuX2xpc3RlbmVyc1t0eXBlXSAhPSBudWxsO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gRXZlbnREaXNwYXRjaGVyOyIsInZhciBMYXlvdXRNb2RlID0ge1xuICAgIExFRlQgICA6ICdsZWZ0JyxcbiAgICBSSUdIVCAgOiAncmlnaHQnLFxuICAgIFRPUCAgICA6ICd0b3AnLFxuICAgIEJPVFRPTSA6ICdib3R0b20nLFxuICAgIE5PTkUgICA6ICdub25lJ1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBMYXlvdXRNb2RlOyIsInZhciBOb2RlICAgPSByZXF1aXJlKCcuLi9kb2N1bWVudC9Ob2RlJyk7XG52YXIgTWV0cmljID0gcmVxdWlyZSgnLi4vLi4vY29tcG9uZW50L01ldHJpYycpO1xudmFyIENTUyAgICA9IHJlcXVpcmUoJy4uL2RvY3VtZW50L0NTUycpO1xudmFyIERvY3VtZW50RXZlbnQgPSByZXF1aXJlKCcuLi9kb2N1bWVudC9Eb2N1bWVudEV2ZW50JyksXG4gICAgTm9kZUV2ZW50ICAgICA9IHJlcXVpcmUoJy4uL2RvY3VtZW50L05vZGVFdmVudCcpO1xudmFyIE1vdXNlICA9IHJlcXVpcmUoJy4uL2RvY3VtZW50L01vdXNlJyk7XG5cbmZ1bmN0aW9uIFNjcm9sbEJhcihwYXJlbnROb2RlLHRhcmdldE5vZGUsd3JhcEhlaWdodCkge1xuICAgIHRoaXMuX3BhcmVudE5vZGUgPSBwYXJlbnROb2RlO1xuICAgIHRoaXMuX3RhcmdldE5vZGUgPSB0YXJnZXROb2RlO1xuICAgIHRoaXMuX3dyYXBIZWlnaHQgPSB3cmFwSGVpZ2h0O1xuXG4gICAgdmFyIHdyYXAgICA9IHRoaXMuX3dyYXBOb2RlICAgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLlNjcm9sbFdyYXApLFxuICAgICAgICBub2RlICAgPSB0aGlzLl9ub2RlICAgICAgID0gbmV3IE5vZGUoKS5zZXRTdHlsZUNsYXNzKENTUy5TY3JvbGxCYXIpLFxuICAgICAgICB0cmFjayAgPSB0aGlzLl90cmFja05vZGUgID0gbmV3IE5vZGUoKS5zZXRTdHlsZUNsYXNzKENTUy5TY3JvbGxCYXJUcmFjayksXG4gICAgICAgIHRodW1iICA9IHRoaXMuX3RodW1iTm9kZSAgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLlNjcm9sbEJhclRodW1iKTtcblxuICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGFyZ2V0Tm9kZSk7XG4gICAgcGFyZW50Tm9kZS5hZGRDaGlsZCh3cmFwKTtcbiAgICBwYXJlbnROb2RlLmFkZENoaWxkQXQobm9kZSwwKTtcblxuICAgIHdyYXAuYWRkQ2hpbGQodGFyZ2V0Tm9kZSk7XG4gICAgbm9kZS5hZGRDaGlsZCh0cmFjayk7XG4gICAgdHJhY2suYWRkQ2hpbGQodGh1bWIpO1xuXG4gICAgdGhpcy5fbW91c2VUaHVtYk9mZnNldCA9IDA7XG4gICAgdGhpcy5fc2Nyb2xsSGVpZ2h0ID0gMDtcbiAgICB0aGlzLl9zY3JvbGxVbml0ICAgPSAwO1xuICAgIHRoaXMuX3Njcm9sbE1pbiAgICA9IDA7XG4gICAgdGhpcy5fc2Nyb2xsTWF4ICAgID0gMDtcblxuICAgIHRodW1iLnNldFBvc2l0aW9uWShNZXRyaWMuU0NST0xMQkFSX1RSQUNLX1BBRERJTkcpO1xuICAgIHRodW1iLmFkZEV2ZW50TGlzdGVuZXIoRG9jdW1lbnRFdmVudC5NT1VTRV9ET1dOLHRoaXMuX29uVGh1bWJEcmFnU3RhcnQuYmluZCh0aGlzKSk7XG5cbiAgICB0aGlzLl9pc1ZhbGlkICA9IGZhbHNlO1xuICAgIHRoaXMuX2VuYWJsZWQgPSBmYWxzZTtcblxuICAgIHZhciBub2RlRWxlbWVudCA9IG5vZGUuZ2V0RWxlbWVudCgpLFxuICAgICAgICB0aHVtYkVsZW1lbnQgPSB0aHVtYi5nZXRFbGVtZW50KCk7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHRoaXMuX29uTW91c2VXaGVlbCA9IGZ1bmN0aW9uKGUpe1xuICAgICAgICB2YXIgc2VuZGVyID0gZS5zZW5kZXIsXG4gICAgICAgICAgICBob3ZlckVsZW1lbnQgPSBzZW5kZXIuZ2V0SG92ZXJFbGVtZW50KCk7XG4gICAgICAgIGlmKGhvdmVyRWxlbWVudCAhPSBub2RlRWxlbWVudCAmJiBob3ZlckVsZW1lbnQgIT0gdGh1bWJFbGVtZW50KXtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc2Nyb2xsU3RlcCA9IHNlbGYuX3Njcm9sbEhlaWdodCAqIDAuMDEyNTtcbiAgICAgICAgc2VsZi5fc2Nyb2xsKHRodW1iLmdldFBvc2l0aW9uWSgpICsgc2VuZGVyLmdldFdoZWVsRGlyZWN0aW9uKCkgKiBzY3JvbGxTdGVwICogLTEpO1xuICAgICAgICBlLmRhdGEucHJldmVudERlZmF1bHQoKTtcbiAgICB9O1xuXG4gICAgdGhpcy5hZGRNb3VzZUxpc3RlbmVyKCk7XG59XG5cblNjcm9sbEJhci5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24oKXtcbiAgICB2YXIgdGFyZ2V0ID0gdGhpcy5fdGFyZ2V0Tm9kZSxcbiAgICAgICAgdGh1bWIgPSB0aGlzLl90aHVtYk5vZGU7XG5cbiAgICB2YXIgcGFkZGluZyA9IE1ldHJpYy5TQ1JPTExCQVJfVFJBQ0tfUEFERElORztcblxuICAgIHZhciB0YXJnZXRXcmFwSGVpZ2h0ID0gdGhpcy5fd3JhcEhlaWdodCxcbiAgICAgICAgdGFyZ2V0SGVpZ2h0ID0gdGFyZ2V0LmdldEhlaWdodCgpLFxuICAgICAgICB0cmFja0hlaWdodCA9IHRhcmdldFdyYXBIZWlnaHQgLSBwYWRkaW5nICogMjtcblxuICAgIHRodW1iLnNldEhlaWdodCh0cmFja0hlaWdodCk7XG5cbiAgICB2YXIgcmF0aW8gPSB0YXJnZXRXcmFwSGVpZ2h0IC8gdGFyZ2V0SGVpZ2h0O1xuXG4gICAgdGhpcy5faXNWYWxpZCA9IGZhbHNlO1xuXG4gICAgaWYgKHJhdGlvID4gMS4wKXtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB2YXIgdGh1bWJIZWlnaHQgPSB0cmFja0hlaWdodCAqIHJhdGlvO1xuXG4gICAgdGhpcy5fc2Nyb2xsSGVpZ2h0ID0gdHJhY2tIZWlnaHQ7XG4gICAgdGhpcy5fc2Nyb2xsVW5pdCAgID0gdGFyZ2V0SGVpZ2h0IC0gdGhpcy5fc2Nyb2xsSGVpZ2h0IC0gcGFkZGluZyAqIDI7XG4gICAgdGhpcy5fc2Nyb2xsTWluICAgID0gcGFkZGluZztcbiAgICB0aGlzLl9zY3JvbGxNYXggICAgPSBwYWRkaW5nICsgdHJhY2tIZWlnaHQgLSB0aHVtYkhlaWdodDtcblxuICAgIHRodW1iLnNldEhlaWdodCh0aHVtYkhlaWdodCk7XG5cbiAgICB0aGlzLl9pc1ZhbGlkID0gdHJ1ZTtcbn07XG5cblNjcm9sbEJhci5wcm90b3R5cGUuX3Njcm9sbCA9IGZ1bmN0aW9uKHkpe1xuICAgIHZhciBtaW4gID0gdGhpcy5fc2Nyb2xsTWluLFxuICAgICAgICBtYXggID0gdGhpcy5fc2Nyb2xsTWF4LFxuICAgICAgICBwb3MgID0gTWF0aC5tYXgobWluLCBNYXRoLm1pbih5LG1heCkpLFxuICAgICAgICBwb3NfID0gKHBvcy1taW4pLyhtYXgtbWluKTtcblxuICAgIHRoaXMuX3RodW1iTm9kZS5zZXRQb3NpdGlvblkocG9zKTtcbiAgICB0aGlzLl90YXJnZXROb2RlLnNldFBvc2l0aW9uWShwb3NfICogdGhpcy5fc2Nyb2xsVW5pdCAqIC0xKTtcbn07XG5cblxuU2Nyb2xsQmFyLnByb3RvdHlwZS5fb25UaHVtYkRyYWdTdGFydCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXRoaXMuX2lzVmFsaWQgfHwgdGhpcy5fZW5hYmxlZCl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIGV2ZW50TW92ZSA9IERvY3VtZW50RXZlbnQuTU9VU0VfTU9WRSxcbiAgICAgICAgZXZlbnRVcCA9IERvY3VtZW50RXZlbnQuTU9VU0VfVVA7XG5cbiAgICB2YXIgbW91c2UgPSBNb3VzZS5nZXQoKTtcbiAgICB2YXIgdHJhY2tPZmZzZXQgPSB0aGlzLl90cmFja05vZGUuZ2V0UG9zaXRpb25HbG9iYWxZKCk7XG5cbiAgICB0aGlzLl9tb3VzZVRodW1iT2Zmc2V0ID0gbW91c2UuZ2V0WSgpIC0gdGhpcy5fdGh1bWJOb2RlLmdldFBvc2l0aW9uR2xvYmFsWSgpO1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHZhciBvbkRyYWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzZWxmLl9zY3JvbGwobW91c2UuZ2V0WSgpIC0gdHJhY2tPZmZzZXQgLSBzZWxmLl9tb3VzZVRodW1iT2Zmc2V0KTtcbiAgICAgICAgfSxcbiAgICAgICAgb25EcmFnRW5kID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE1vdmUsIG9uRHJhZywgZmFsc2UpO1xuICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudFVwLCBvbkRyYWdFbmQsIGZhbHNlKTtcbiAgICAgICAgfTtcblxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnRNb3ZlLCBvbkRyYWcsIGZhbHNlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50VXAsIG9uRHJhZ0VuZCwgZmFsc2UpO1xuICAgIHRoaXMuX3Njcm9sbChtb3VzZS5nZXRZKCkgLSB0cmFja09mZnNldCAtIHNlbGYuX21vdXNlVGh1bWJPZmZzZXQpO1xufTtcblxuXG5TY3JvbGxCYXIucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLl9lbmFibGVkID0gZmFsc2U7XG4gICAgdGhpcy5fdXBkYXRlQXBwZWFyYW5jZSgpO1xufTtcblxuU2Nyb2xsQmFyLnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX2VuYWJsZWQgPSB0cnVlO1xuICAgIHRoaXMuX3VwZGF0ZUFwcGVhcmFuY2UoKTtcbn07XG5TY3JvbGxCYXIucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX3Njcm9sbCgwKTtcbn07XG5cblNjcm9sbEJhci5wcm90b3R5cGUuX3VwZGF0ZUFwcGVhcmFuY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuX2VuYWJsZWQpIHtcbiAgICAgICAgdGhpcy5fbm9kZS5zZXRTdHlsZVByb3BlcnR5KCdkaXNwbGF5JywgJ25vbmUnKTtcbiAgICAgICAgdGhpcy5fdGFyZ2V0Tm9kZS5zZXRQb3NpdGlvblkoMCk7XG4gICAgICAgIHRoaXMuX3RodW1iTm9kZS5zZXRQb3NpdGlvblkoTWV0cmljLlNDUk9MTEJBUl9UUkFDS19QQURESU5HKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9ub2RlLnNldFN0eWxlUHJvcGVydHkoJ2Rpc3BsYXknLCAnYmxvY2snKTtcbiAgICB9XG59O1xuXG5TY3JvbGxCYXIucHJvdG90eXBlLmlzVmFsaWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2lzVmFsaWQ7XG59O1xuXG5TY3JvbGxCYXIucHJvdG90eXBlLnNldFdyYXBIZWlnaHQgPSBmdW5jdGlvbiAoaGVpZ2h0KSB7XG4gICAgdGhpcy5fd3JhcEhlaWdodCA9IGhlaWdodDtcbiAgICB0aGlzLnVwZGF0ZSgpO1xufTtcblxuU2Nyb2xsQmFyLnByb3RvdHlwZS5yZW1vdmVUYXJnZXROb2RlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl93cmFwTm9kZS5yZW1vdmVDaGlsZCh0aGlzLl90YXJnZXROb2RlKTtcbn07XG5cblNjcm9sbEJhci5wcm90b3R5cGUucmVtb3ZlTW91c2VMaXN0ZW5lciA9IGZ1bmN0aW9uKCl7XG4gICAgTW91c2UuZ2V0KCkucmVtb3ZlRXZlbnRMaXN0ZW5lcihEb2N1bWVudEV2ZW50Lk1PVVNFX1dIRUVMLHRoaXMsJ19vbk1vdXNlV2hlZWwnKTtcbn07XG5cblNjcm9sbEJhci5wcm90b3R5cGUuYWRkTW91c2VMaXN0ZW5lciA9IGZ1bmN0aW9uKCl7XG4gICAgTW91c2UuZ2V0KCkuYWRkRXZlbnRMaXN0ZW5lcihEb2N1bWVudEV2ZW50Lk1PVVNFX1dIRUVMLHRoaXMsJ19vbk1vdXNlV2hlZWwnKTtcbn07XG5cblNjcm9sbEJhci5wcm90b3R5cGUucmVtb3ZlRnJvbVBhcmVudCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcGFyZW50Tm9kZSA9IHRoaXMuX3BhcmVudE5vZGUsXG4gICAgICAgIHJvb3ROb2RlID0gdGhpcy5fbm9kZSxcbiAgICAgICAgdGFyZ2V0Tm9kZSA9IHRoaXMuX3RhcmdldE5vZGU7XG5cbiAgICByb290Tm9kZS5yZW1vdmVDaGlsZCh0YXJnZXROb2RlKTtcbiAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMuX3dyYXBOb2RlKTtcbiAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKHJvb3ROb2RlKTtcblxuICAgIHJldHVybiB0YXJnZXROb2RlO1xufTtcblxuU2Nyb2xsQmFyLnByb3RvdHlwZS5nZXRXcmFwTm9kZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fd3JhcE5vZGU7XG59O1xuXG5TY3JvbGxCYXIucHJvdG90eXBlLmdldE5vZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX25vZGU7XG59O1xuXG5TY3JvbGxCYXIucHJvdG90eXBlLmdldFRhcmdldE5vZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3RhcmdldE5vZGU7XG59O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gU2Nyb2xsQmFyOyIsInZhciBFdmVudERpc3BhdGNoZXIgPSByZXF1aXJlKCcuLi9jb3JlL2V2ZW50L0V2ZW50RGlzcGF0Y2hlcicpO1xudmFyIE5vZGUgICAgICAgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZScpO1xudmFyIFNjcm9sbEJhciAgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvbGF5b3V0L1Njcm9sbEJhcicpO1xuXG5mdW5jdGlvbiBBYnN0cmFjdEdyb3VwKHBhcmVudCwgcGFyYW1zKSB7XG4gICAgRXZlbnREaXNwYXRjaGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG5cbiAgICBwYXJhbXMgPSBwYXJhbXMgfHwge307XG4gICAgcGFyYW1zLmhlaWdodCA9IHBhcmFtcy5oZWlnaHQgfHwgbnVsbDtcbiAgICBwYXJhbXMuZW5hYmxlID0gcGFyYW1zLmVuYWJsZSA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IHBhcmFtcy5lbmFibGU7XG5cbiAgICB0aGlzLl9wYXJlbnQgPSBwYXJlbnQ7XG4gICAgdGhpcy5faGVpZ2h0ID0gcGFyYW1zLmhlaWdodDtcbiAgICB0aGlzLl9lbmFibGVkID0gcGFyYW1zLmVuYWJsZTtcbiAgICB0aGlzLl9zY3JvbGxCYXIgPSBudWxsO1xuXG4gICAgdGhpcy5fbm9kZSA9IG5ldyBOb2RlKE5vZGUuTElTVF9JVEVNKTtcbiAgICB0aGlzLl93cmFwTm9kZSA9IG5ldyBOb2RlKCk7XG4gICAgdGhpcy5fbGlzdE5vZGUgPSBuZXcgTm9kZShOb2RlLkxJU1QpO1xuXG4gICAgdGhpcy5fcGFyZW50LmdldExpc3QoKS5hZGRDaGlsZCh0aGlzLl9ub2RlKTtcbn1cbkFic3RyYWN0R3JvdXAucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFdmVudERpc3BhdGNoZXIucHJvdG90eXBlKTtcbkFic3RyYWN0R3JvdXAucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gQWJzdHJhY3RHcm91cDtcblxuQWJzdHJhY3RHcm91cC5wcm90b3R5cGUuYWRkU2Nyb2xsV3JhcCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgd3JhcE5vZGUgPSB0aGlzLl93cmFwTm9kZSxcbiAgICAgICAgbWF4SGVpZ2h0ID0gdGhpcy5nZXRNYXhIZWlnaHQoKTtcblxuICAgIHRoaXMuX3Njcm9sbEJhciA9IG5ldyBTY3JvbGxCYXIod3JhcE5vZGUsIHRoaXMuX2xpc3ROb2RlLCBtYXhIZWlnaHQpO1xuICAgIGlmICh0aGlzLmlzRW5hYmxlZCgpKSB7XG4gICAgICAgIHdyYXBOb2RlLnNldEhlaWdodChtYXhIZWlnaHQpO1xuICAgIH1cbn07XG5cbkFic3RyYWN0R3JvdXAucHJvdG90eXBlLnByZXZlbnRTZWxlY3REcmFnID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX3BhcmVudC5wcmV2ZW50U2VsZWN0RHJhZygpO1xuXG4gICAgaWYgKCF0aGlzLmhhc1Njcm9sbFdyYXAoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuX3dyYXBOb2RlLmdldEVsZW1lbnQoKS5zY3JvbGxUb3AgPSAwO1xufTtcblxuQWJzdHJhY3RHcm91cC5wcm90b3R5cGUuaGFzTWF4SGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9oZWlnaHQgIT0gbnVsbDtcbn07XG5cbkFic3RyYWN0R3JvdXAucHJvdG90eXBlLmdldE1heEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5faGVpZ2h0O1xufTtcblxuQWJzdHJhY3RHcm91cC5wcm90b3R5cGUuaGFzU2Nyb2xsV3JhcCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fc2Nyb2xsQmFyICE9IG51bGw7XG59O1xuXG5BYnN0cmFjdEdyb3VwLnByb3RvdHlwZS5oYXNMYWJlbCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fbGFibE5vZGUgIT0gbnVsbDtcbn07XG5cbkFic3RyYWN0R3JvdXAucHJvdG90eXBlLmRpc2FibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5fZW5hYmxlZCA9IGZhbHNlO1xuICAgIHRoaXMuX3VwZGF0ZUFwcGVhcmFuY2UoKTtcbn07XG5cbkFic3RyYWN0R3JvdXAucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLl9lbmFibGVkID0gdHJ1ZTtcbiAgICB0aGlzLl91cGRhdGVBcHBlYXJhbmNlKCk7XG59O1xuXG5BYnN0cmFjdEdyb3VwLnByb3RvdHlwZS5pc0Rpc2FibGVkID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAhdGhpcy5fZW5hYmxlZDtcbn07XG5cbkFic3RyYWN0R3JvdXAucHJvdG90eXBlLmlzRW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fZW5hYmxlZDtcbn07XG5cbkFic3RyYWN0R3JvdXAucHJvdG90eXBlLmdldExpc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2xpc3ROb2RlO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBBYnN0cmFjdEdyb3VwO1xuXG4iLCJ2YXIgQWJzdHJhY3RHcm91cCA9IHJlcXVpcmUoJy4vQWJzdHJhY3RHcm91cCcpO1xudmFyIENTUyA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvQ1NTJyk7XG52YXIgTm9kZSA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZScpO1xuXG52YXIgU3ViR3JvdXAgPSByZXF1aXJlKCcuL1N1Ykdyb3VwJyk7XG5cbnZhciBFdmVudF8gPSByZXF1aXJlKCcuLi9jb3JlL2V2ZW50L0V2ZW50JyksXG4gICAgRG9jdW1lbnRFdmVudCA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvRG9jdW1lbnRFdmVudCcpLFxuICAgIE5vZGVFdmVudCA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTm9kZUV2ZW50JyksXG4gICAgUGFuZWxFdmVudCA9IHJlcXVpcmUoJy4vUGFuZWxFdmVudCcpLFxuICAgIEdyb3VwRXZlbnQgPSByZXF1aXJlKCcuL0dyb3VwRXZlbnQnKTtcblxudmFyIE9iamVjdENvbXBvbmVudCA9IHJlcXVpcmUoJy4uL2NvcmUvT2JqZWN0Q29tcG9uZW50JyksXG4gICAgVmFsdWVQbG90dGVyICAgID0gcmVxdWlyZSgnLi4vY29tcG9uZW50L1ZhbHVlUGxvdHRlcicpLFxuICAgIEZ1bmN0aW9uUGxvdHRlciA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudC9GdW5jdGlvblBsb3R0ZXInKTtcblxuZnVuY3Rpb24gR3JvdXAocGFyZW50LHBhcmFtcykge1xuICAgIHBhcmFtcyAgICAgICAgICAgPSBwYXJhbXMgfHwge307XG4gICAgcGFyYW1zLmxhYmVsICAgICA9IHBhcmFtcy5sYWJlbCAgICAgfHwgbnVsbDtcbiAgICBwYXJhbXMudXNlTGFiZWxzID0gcGFyYW1zLnVzZUxhYmVscyB8fCB0cnVlO1xuICAgIHBhcmFtcy5lbmFibGUgICAgPSBwYXJhbXMuZW5hYmxlICAgICA9PT0gdW5kZWZpbmVkID8gdHJ1ZSA6IHBhcmFtcy5lbmFibGU7XG5cbiAgICBBYnN0cmFjdEdyb3VwLmFwcGx5KHRoaXMsYXJndW1lbnRzKTtcblxuICAgIHRoaXMuX2NvbXBvbmVudHMgPSBbXTtcbiAgICB0aGlzLl9zdWJHcm91cHMgID0gW107XG5cbiAgICB2YXIgcm9vdCA9IHRoaXMuX25vZGUsXG4gICAgICAgIHdyYXAgPSB0aGlzLl93cmFwTm9kZSxcbiAgICAgICAgbGlzdCA9IHRoaXMuX2xpc3ROb2RlO1xuXG4gICAgICAgIHJvb3Quc2V0U3R5bGVDbGFzcyhDU1MuR3JvdXApO1xuICAgICAgICB3cmFwLnNldFN0eWxlQ2xhc3MoQ1NTLldyYXApO1xuICAgICAgICBsaXN0LnNldFN0eWxlQ2xhc3MoQ1NTLlN1Ykdyb3VwTGlzdCk7XG5cbiAgICAgICAgd3JhcC5hZGRDaGlsZChsaXN0KTtcblxuICAgIHZhciBsYWJlbCA9IHBhcmFtcy5sYWJlbDtcblxuICAgIGlmKGxhYmVsKXtcbiAgICAgICAgdmFyIGhlYWQgID0gbmV3IE5vZGUoKSxcbiAgICAgICAgICAgIHdyYXBfID0gbmV3IE5vZGUoKSxcbiAgICAgICAgICAgIGxhYmVsXyAgPSBuZXcgTm9kZShOb2RlLlNQQU4pLFxuICAgICAgICAgICAgaW5kaWNhdG9yID0gdGhpcy5faW5kaU5vZGUgPSBuZXcgTm9kZSgpO1xuXG4gICAgICAgICAgICBoZWFkLnNldFN0eWxlQ2xhc3MoQ1NTLkhlYWQpO1xuICAgICAgICAgICAgd3JhcF8uc2V0U3R5bGVDbGFzcyhDU1MuV3JhcCk7XG4gICAgICAgICAgICBsYWJlbF8uc2V0U3R5bGVDbGFzcyhDU1MuTGFiZWwpO1xuICAgICAgICAgICAgaW5kaWNhdG9yLnNldFN0eWxlQ2xhc3MoQ1NTLkFycm93Qk1heCk7XG4gICAgICAgICAgICBsYWJlbF8uc2V0UHJvcGVydHkoJ2lubmVySFRNTCcsbGFiZWwpO1xuXG4gICAgICAgICAgICBoZWFkLmFkZENoaWxkKGluZGljYXRvcik7XG4gICAgICAgICAgICB3cmFwXy5hZGRDaGlsZChsYWJlbF8pO1xuICAgICAgICAgICAgaGVhZC5hZGRDaGlsZCh3cmFwXyk7XG4gICAgICAgICAgICByb290LmFkZENoaWxkKGhlYWQpO1xuXG4gICAgICAgIGhlYWQuYWRkRXZlbnRMaXN0ZW5lcihOb2RlRXZlbnQuTU9VU0VfRE9XTix0aGlzLl9vbkhlYWRUcmlnZ2VyLmJpbmQodGhpcykpO1xuICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoR3JvdXBFdmVudC5HUk9VUF9MSVNUX1NJWkVfQ0hBTkdFLHBhcmVudCwnb25Hcm91cExpc3RTaXplQ2hhbmdlJyk7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlQXBwZWFyYW5jZSgpO1xuICAgIH1cblxuICAgIGlmKHRoaXMuaGFzTWF4SGVpZ2h0KCkpe1xuICAgICAgICB0aGlzLmFkZFNjcm9sbFdyYXAoKTtcbiAgICB9XG5cbiAgICByb290LmFkZENoaWxkKHdyYXApO1xuXG4gICAgaWYodGhpcy5oYXNNYXhIZWlnaHQoKSl7XG4gICAgICAgIGlmKCFsYWJlbCl7XG4gICAgICAgICAgICB2YXIgYnVmZmVyVG9wID0gdGhpcy5fc2Nyb2xsQnVmZmVyVG9wID0gbmV3IE5vZGUoKTtcbiAgICAgICAgICAgICAgICBidWZmZXJUb3Auc2V0U3R5bGVDbGFzcyhDU1MuU2Nyb2xsQnVmZmVyKTtcblxuICAgICAgICAgICAgcm9vdC5hZGRDaGlsZEF0KGJ1ZmZlclRvcCwwKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYnVmZmVyQm90dG9tID0gdGhpcy5fc2Nyb2xsQnVmZmVyQm90dG9tID0gbmV3IE5vZGUoKTtcbiAgICAgICAgICAgIGJ1ZmZlckJvdHRvbS5zZXRTdHlsZUNsYXNzKENTUy5TY3JvbGxCdWZmZXIpO1xuXG4gICAgICAgIHJvb3QuYWRkQ2hpbGQoYnVmZmVyQm90dG9tKTtcbiAgICB9XG5cbiAgICBwYXJlbnQgPSB0aGlzLl9wYXJlbnQ7XG5cbiAgICBwYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcihQYW5lbEV2ZW50LlBBTkVMX01PVkVfQkVHSU4sIHRoaXMsICdvblBhbmVsTW92ZUJlZ2luJyk7XG4gICAgcGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoUGFuZWxFdmVudC5QQU5FTF9NT1ZFLCB0aGlzLCAnb25QYW5lbE1vdmUnKTtcbiAgICBwYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcihQYW5lbEV2ZW50LlBBTkVMX01PVkVfRU5ELCB0aGlzLCAnb25QYW5lbE1vdmVFbmQnKTtcbiAgICBwYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcihQYW5lbEV2ZW50LlBBTkVMX0hJREUsIHRoaXMsICdvblBhbmVsSGlkZScpO1xuICAgIHBhcmVudC5hZGRFdmVudExpc3RlbmVyKFBhbmVsRXZlbnQuUEFORUxfU0hPVywgdGhpcywgJ29uUGFuZWxTaG93Jyk7XG4gICAgcGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoUGFuZWxFdmVudC5QQU5FTF9TQ1JPTExfV1JBUF9BRERFRCwgdGhpcywgJ29uUGFuZWxTY3JvbGxXcmFwQWRkZWQnKTtcbiAgICBwYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcihQYW5lbEV2ZW50LlBBTkVMX1NDUk9MTF9XUkFQX1JFTU9WRUQsIHRoaXMsICdvblBhbmVsU2Nyb2xsV3JhcFJlbW92ZWQnKTtcbiAgICBwYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcihQYW5lbEV2ZW50LlBBTkVMX1NJWkVfQ0hBTkdFLCB0aGlzLCAnb25QYW5lbFNpemVDaGFuZ2UnKTtcbiAgICBwYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcihEb2N1bWVudEV2ZW50LldJTkRPV19SRVNJWkUsIHRoaXMsICdvbldpbmRvd1Jlc2l6ZScpO1xuXG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVyKEdyb3VwRXZlbnQuR1JPVVBfU0laRV9DSEFOR0UscGFyZW50LCdvbkdyb3VwTGlzdFNpemVDaGFuZ2UnKTtcbn1cbkdyb3VwLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoQWJzdHJhY3RHcm91cC5wcm90b3R5cGUpO1xuR3JvdXAucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gR3JvdXA7XG5cbkdyb3VwLnByb3RvdHlwZS5vblBhbmVsTW92ZUJlZ2luID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIFBhbmVsRXZlbnQuUEFORUxfTU9WRV9CRUdJTiwgbnVsbCkpO1xufTtcblxuR3JvdXAucHJvdG90eXBlLm9uUGFuZWxNb3ZlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIFBhbmVsRXZlbnQuUEFORUxfTU9WRSwgbnVsbCkpO1xufTtcblxuR3JvdXAucHJvdG90eXBlLm9uUGFuZWxNb3ZlRW5kID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIFBhbmVsRXZlbnQuUEFORUxfTU9WRV9FTkQsIG51bGwpKTtcbn07XG5cbkdyb3VwLnByb3RvdHlwZS5vblBhbmVsU2Nyb2xsV3JhcEFkZGVkID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIEdyb3VwRXZlbnQuR1JPVVBfU0laRV9DSEFOR0UsIG51bGwpKTtcbn07XG5cbkdyb3VwLnByb3RvdHlwZS5vblBhbmVsU2Nyb2xsV3JhcFJlbW92ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgR3JvdXBFdmVudC5HUk9VUF9TSVpFX0NIQU5HRSwgbnVsbCkpO1xufTtcblxuR3JvdXAucHJvdG90eXBlLm9uUGFuZWxIaWRlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIEdyb3VwRXZlbnQuU1VCR1JPVVBfRElTQUJMRSwgbnVsbCkpO1xufTtcblxuR3JvdXAucHJvdG90eXBlLm9uUGFuZWxTaG93ID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIEdyb3VwRXZlbnQuU1VCR1JPVVBfRU5BQkxFLCBudWxsKSk7XG59O1xuXG5Hcm91cC5wcm90b3R5cGUub25QYW5lbFNpemVDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgR3JvdXBFdmVudC5HUk9VUF9TSVpFX0NIQU5HRSwgbnVsbCkpO1xufTtcblxuR3JvdXAucHJvdG90eXBlLm9uV2luZG93UmVzaXplID0gZnVuY3Rpb24gKGUpIHtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQoZSk7XG59O1xuXG5Hcm91cC5wcm90b3R5cGUub25TdWJHcm91cFRyaWdnZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5fdXBkYXRlSGVpZ2h0KCk7XG5cbiAgICBpZighdGhpcy5oYXNNYXhIZWlnaHQoKSl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHNjcm9sbEJhciA9IHRoaXMuX3Njcm9sbEJhcixcbiAgICAgICAgd3JhcCAgPSB0aGlzLl93cmFwTm9kZTtcbiAgICB2YXIgYnVmZmVyVG9wICAgID0gdGhpcy5fc2Nyb2xsQnVmZmVyVG9wLFxuICAgICAgICBidWZmZXJCb3R0b20gPSB0aGlzLl9zY3JvbGxCdWZmZXJCb3R0b207XG5cbiAgICBzY3JvbGxCYXIudXBkYXRlKCk7XG5cbiAgICBpZiAoIXNjcm9sbEJhci5pc1ZhbGlkKCkpIHtcbiAgICAgICAgc2Nyb2xsQmFyLmRpc2FibGUoKTtcbiAgICAgICAgd3JhcC5zZXRIZWlnaHQod3JhcC5nZXRDaGlsZEF0KDEpLmdldEhlaWdodCgpKTtcbiAgICAgICAgaWYgKGJ1ZmZlclRvcCl7XG4gICAgICAgICAgICBidWZmZXJUb3Auc2V0U3R5bGVQcm9wZXJ0eSgnZGlzcGxheScsICdub25lJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJ1ZmZlckJvdHRvbSl7XG4gICAgICAgICAgICBidWZmZXJCb3R0b20uc2V0U3R5bGVQcm9wZXJ0eSgnZGlzcGxheScsICdub25lJyk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNjcm9sbEJhci5lbmFibGUoKTtcbiAgICAgICAgd3JhcC5zZXRIZWlnaHQodGhpcy5nZXRNYXhIZWlnaHQoKSk7XG5cbiAgICAgICAgaWYgKGJ1ZmZlclRvcCl7XG4gICAgICAgICAgICBidWZmZXJUb3Auc2V0U3R5bGVQcm9wZXJ0eSgnZGlzcGxheScsICdibG9jaycpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChidWZmZXJCb3R0b20pe1xuICAgICAgICAgICAgYnVmZmVyQm90dG9tLnNldFN0eWxlUHJvcGVydHkoJ2Rpc3BsYXknLCAnYmxvY2snKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50Xyh0aGlzLEdyb3VwRXZlbnQuR1JPVVBfU0laRV9DSEFOR0UsbnVsbCkpO1xufTtcblxuR3JvdXAucHJvdG90eXBlLl9vbkhlYWRUcmlnZ2VyID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX2VuYWJsZWQgPSAhdGhpcy5fZW5hYmxlZDtcbiAgICB0aGlzLl91cGRhdGVBcHBlYXJhbmNlKCk7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgR3JvdXBFdmVudC5HUk9VUF9MSVNUX1NJWkVfQ0hBTkdFLCBudWxsKSk7XG59O1xuXG5Hcm91cC5wcm90b3R5cGUuYWRkQ29tcG9uZW50ID0gZnVuY3Rpb24oKXtcbiAgICB2YXIgQ2xhc3NfID0gYXJndW1lbnRzWzBdO1xuICAgIHZhciBhcmdzICAgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgICAgICBhcmdzLnNoaWZ0KCk7XG4gICAgICAgIGFyZ3MudW5zaGlmdCh0aGlzLl9nZXRTdWJHcm91cCgpKTtcblxuICAgIHZhciBpbnN0YW5jZSA9IE9iamVjdC5jcmVhdGUoQ2xhc3NfLnByb3RvdHlwZSk7XG4gICAgQ2xhc3NfLmFwcGx5KGluc3RhbmNlLGFyZ3MpO1xuXG4gICAgdGhpcy5fY29tcG9uZW50cy5wdXNoKGluc3RhbmNlKTtcbiAgICB0aGlzLl91cGRhdGVIZWlnaHQoKTtcbn07XG5cbkdyb3VwLnByb3RvdHlwZS5fdXBkYXRlSGVpZ2h0ID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX2dldFN1Ykdyb3VwKCkudXBkYXRlKCk7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcyxHcm91cEV2ZW50LkdST1VQX1NJWkVfQ0hBTkdFLG51bGwpKTtcbiAgICBpZih0aGlzLmhhc01heEhlaWdodCgpKXtcbiAgICAgICAgdGhpcy5fc2Nyb2xsQmFyLnVwZGF0ZSgpO1xuICAgIH1cbn07XG5cbkdyb3VwLnByb3RvdHlwZS5fdXBkYXRlQXBwZWFyYW5jZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgd3JhcCA9IHRoaXMuX3dyYXBOb2RlLFxuICAgICAgICBpbmRpY2F0b3IgPSB0aGlzLl9pbmRpTm9kZTtcblxuICAgIHZhciBzY3JvbGxCYXIgPSB0aGlzLl9zY3JvbGxCYXI7XG5cbiAgICB2YXIgYnVmZmVyVG9wICAgID0gdGhpcy5fc2Nyb2xsQnVmZmVyVG9wLFxuICAgICAgICBidWZmZXJCb3R0b20gPSB0aGlzLl9zY3JvbGxCdWZmZXJCb3R0b207XG5cbiAgICBpZiAodGhpcy5pc0Rpc2FibGVkKCkpIHtcbiAgICAgICAgd3JhcC5zZXRIZWlnaHQoMCk7XG4gICAgICAgIGlmIChpbmRpY2F0b3Ipe1xuICAgICAgICAgICAgaW5kaWNhdG9yLnNldFN0eWxlQ2xhc3MoQ1NTLkFycm93Qk1pbik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2Nyb2xsQmFyKSB7XG4gICAgICAgICAgICBpZiAoYnVmZmVyVG9wKXtcbiAgICAgICAgICAgICAgICBidWZmZXJUb3Auc2V0U3R5bGVQcm9wZXJ0eSgnZGlzcGxheScsICdub25lJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYnVmZmVyQm90dG9tKXtcbiAgICAgICAgICAgICAgICBidWZmZXJCb3R0b20uc2V0U3R5bGVQcm9wZXJ0eSgnZGlzcGxheScsICdub25lJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmhhc01heEhlaWdodCgpKSB7XG4gICAgICAgIHZhciBtYXhIZWlnaHQgPSB0aGlzLmdldE1heEhlaWdodCgpLFxuICAgICAgICAgICAgbGlzdEhlaWdodCA9IHdyYXAuZ2V0Q2hpbGRBdCgxKS5nZXRIZWlnaHQoKTtcblxuICAgICAgICB3cmFwLnNldEhlaWdodChsaXN0SGVpZ2h0IDwgbWF4SGVpZ2h0ID8gbGlzdEhlaWdodCA6IG1heEhlaWdodCk7XG5cbiAgICAgICAgaWYgKHNjcm9sbEJhci5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIGlmIChidWZmZXJUb3Ape1xuICAgICAgICAgICAgICAgIGJ1ZmZlclRvcC5zZXRTdHlsZVByb3BlcnR5KCdkaXNwbGF5JywgJ2Jsb2NrJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYnVmZmVyQm90dG9tKXtcbiAgICAgICAgICAgICAgICBidWZmZXJCb3R0b20uc2V0U3R5bGVQcm9wZXJ0eSgnZGlzcGxheScsICdibG9jaycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB3cmFwLmRlbGV0ZVN0eWxlUHJvcGVydHkoJ2hlaWdodCcpO1xuICAgIH1cbiAgICBpZiAoaW5kaWNhdG9yKXtcbiAgICAgICAgaW5kaWNhdG9yLnNldFN0eWxlQ2xhc3MoQ1NTLkFycm93Qk1heCk7XG4gICAgfVxufTtcblxuR3JvdXAucHJvdG90eXBlLm9uR3JvdXBTaXplVXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX3VwZGF0ZUFwcGVhcmFuY2UoKTtcbiAgICBpZiAodGhpcy5oYXNNYXhIZWlnaHQoKSl7XG4gICAgICAgIHRoaXMuX3Njcm9sbEJhci51cGRhdGUoKTtcbiAgICB9XG59O1xuXG5Hcm91cC5wcm90b3R5cGUuYWRkU3ViR3JvdXAgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgdGhpcy5fc3ViR3JvdXBzLnB1c2gobmV3IFN1Ykdyb3VwKHRoaXMsIHBhcmFtcykpO1xuICAgIHRoaXMuX3VwZGF0ZUhlaWdodCgpO1xuICAgIHJldHVybiB0aGlzO1xufTtcblxuR3JvdXAucHJvdG90eXBlLl9nZXRTdWJHcm91cCA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc3ViR3JvdXBzID0gdGhpcy5fc3ViR3JvdXBzO1xuICAgIGlmIChzdWJHcm91cHMubGVuZ3RoID09IDApe1xuICAgICAgICBzdWJHcm91cHMucHVzaChuZXcgU3ViR3JvdXAodGhpcykpO1xuICAgIH1cbiAgICByZXR1cm4gc3ViR3JvdXBzW3N1Ykdyb3Vwcy5sZW5ndGggLSAxXTtcbn07XG5cbkdyb3VwLnByb3RvdHlwZS5nZXRDb21wb25lbnRzID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9jb21wb25lbnRzO1xufTtcblxuZnVuY3Rpb24gaXNEYXRhQ29tcChjb21wKXtcbiAgICByZXR1cm4gIChjb21wIGluc3RhbmNlb2YgT2JqZWN0Q29tcG9uZW50KSAmJlxuICAgICAgICAgICAhKGNvbXAgaW5zdGFuY2VvZiBWYWx1ZVBsb3R0ZXIpICYmXG4gICAgICAgICAgICEoY29tcCBpbnN0YW5jZW9mIEZ1bmN0aW9uUGxvdHRlcik7XG59XG5cblxuR3JvdXAucHJvdG90eXBlLnNldERhdGEgPSBmdW5jdGlvbihkYXRhKXtcbiAgICB2YXIgY29tcHMgPSB0aGlzLl9jb21wb25lbnRzLCBjb21wLCBkYXRhXztcbiAgICB2YXIgaSA9IC0xLCBqID0gMCwgbCA9IGNvbXBzLmxlbmd0aDtcbiAgICB3aGlsZSgrK2kgPCBsKXtcbiAgICAgICAgY29tcCA9IGNvbXBzW2ldO1xuICAgICAgICBpZighaXNEYXRhQ29tcChjb21wKSl7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICBkYXRhXyA9IGRhdGFbaisrXTtcbiAgICAgICAgY29tcC5zZXRWYWx1ZShkYXRhX1tPYmplY3Qua2V5cyhkYXRhXylbMF1dKTtcbiAgICB9XG59O1xuXG5Hcm91cC5wcm90b3R5cGUuZ2V0RGF0YSA9IGZ1bmN0aW9uKCl7XG4gICAgdmFyIGNvbXBzID0gdGhpcy5fY29tcG9uZW50cyxcbiAgICAgICAgaSA9IC0xLCBsID0gY29tcHMubGVuZ3RoO1xuICAgIHZhciB2YWx1ZXMgPSBbXTtcbiAgICB2YXIgY29tcDtcbiAgICB3aGlsZSgrK2kgPCBsKXtcbiAgICAgICAgY29tcCA9IGNvbXBzW2ldO1xuICAgICAgICBpZighaXNEYXRhQ29tcChjb21wKSl7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZXMucHVzaChjb21wLmdldERhdGEoKSk7XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZXM7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEdyb3VwO1xuIiwidmFyIEdyb3VwRXZlbnQgPSB7XG5cdEdST1VQX1NJWkVfQ0hBTkdFICAgICAgICA6ICdncm91cFNpemVDaGFuZ2UnLFxuXHRHUk9VUF9MSVNUX1NJWkVfQ0hBTkdFICAgOiAnZ3JvdXBMaXN0U2l6ZUNoYW5nZScsXG5cdEdST1VQX1NJWkVfVVBEQVRFICAgICAgICA6ICdncm91cFNpemVVcGRhdGUnLFxuXHRTVUJHUk9VUF9UUklHR0VSICAgICAgICAgOiAnc3ViR3JvdXBUcmlnZ2VyJyxcblxuXHRTVUJHUk9VUF9FTkFCTEUgICAgICAgICAgOiAnZW5hYmxlU3ViR3JvdXAnLFxuXHRTVUJHUk9VUF9ESVNBQkxFICAgICAgICAgOiAnZGlzYWJsZVN1Ykdyb3VwJ1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBHcm91cEV2ZW50OyIsInZhciBNZW51RXZlbnQgPSB7XG5cdFVQREFURV9NRU5VOiAndXBkYXRlTWVudSdcbn07XG5tb2R1bGUuZXhwb3J0cyA9IE1lbnVFdmVudDsiLCJ2YXIgTm9kZSAgICAgID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Ob2RlJyksXG4gICAgR3JvdXAgICAgID0gcmVxdWlyZSgnLi9Hcm91cCcpLFxuICAgIFNjcm9sbEJhciA9IHJlcXVpcmUoJy4uL2NvcmUvbGF5b3V0L1Njcm9sbEJhcicpO1xuXG52YXIgQ1NTICAgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvQ1NTJyk7XG52YXIgTGF5b3V0TW9kZSA9IHJlcXVpcmUoJy4uL2NvcmUvbGF5b3V0L0xheW91dE1vZGUnKTtcbnZhciBIaXN0b3J5ICAgID0gcmVxdWlyZSgnLi4vY29yZS9IaXN0b3J5Jyk7XG5cbnZhciBFdmVudERpc3BhdGNoZXIgPSByZXF1aXJlKCcuLi9jb3JlL2V2ZW50L0V2ZW50RGlzcGF0Y2hlcicpLFxuICAgIEV2ZW50XyAgICAgICAgICA9IHJlcXVpcmUoJy4uL2NvcmUvZXZlbnQvRXZlbnQnKSxcbiAgICBEb2N1bWVudEV2ZW50ICAgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L0RvY3VtZW50RXZlbnQnKSxcbiAgICBOb2RlRXZlbnQgICAgICAgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L05vZGVFdmVudCcpLFxuICAgIFBhbmVsRXZlbnQgICAgICA9IHJlcXVpcmUoJy4vUGFuZWxFdmVudCcpLFxuICAgIE1lbnVFdmVudCAgICAgICA9IHJlcXVpcmUoJy4vTWVudUV2ZW50Jyk7XG5cbnZhciBNb3VzZSA9IHJlcXVpcmUoJy4uL2NvcmUvZG9jdW1lbnQvTW91c2UnKTtcblxudmFyIFN0cmluZ0lucHV0ICAgICA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudC9TdHJpbmdJbnB1dCcpLFxuICAgIE51bWJlcklucHV0ICAgICA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudC9OdW1iZXJJbnB1dCcpLFxuICAgIFJhbmdlICAgICAgICAgICA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudC9SYW5nZScpLFxuICAgIENoZWNrYm94ICAgICAgICA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudC9DaGVja2JveCcpLFxuICAgIENvbG9yICAgICAgICAgICA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudC9Db2xvcicpLFxuICAgIEJ1dHRvbiAgICAgICAgICA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudC9CdXR0b24nKSxcbiAgICBTZWxlY3QgICAgICAgICAgPSByZXF1aXJlKCcuLi9jb21wb25lbnQvU2VsZWN0JyksXG4gICAgU2xpZGVyICAgICAgICAgID0gcmVxdWlyZSgnLi4vY29tcG9uZW50L1NsaWRlcicpLFxuICAgIEZ1bmN0aW9uUGxvdHRlciA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudC9GdW5jdGlvblBsb3R0ZXInKSxcbiAgICBQYWQgICAgICAgICAgICAgPSByZXF1aXJlKCcuLi9jb21wb25lbnQvUGFkJyksXG4gICAgVmFsdWVQbG90dGVyICAgID0gcmVxdWlyZSgnLi4vY29tcG9uZW50L1ZhbHVlUGxvdHRlcicpLFxuICAgIE51bWJlck91dHB1dCAgICA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudC9OdW1iZXJPdXRwdXQnKSxcbiAgICBTdHJpbmdPdXRwdXQgICAgPSByZXF1aXJlKCcuLi9jb21wb25lbnQvU3RyaW5nT3V0cHV0JyksXG4gICAgQ2FudmFzXyAgICAgICAgID0gcmVxdWlyZSgnLi4vY29tcG9uZW50L0NhbnZhcycpLFxuICAgIFNWR18gICAgICAgICAgICA9IHJlcXVpcmUoJy4uL2NvbXBvbmVudC9TVkcnKTtcblxudmFyIERFRkFVTFRfUEFORUxfUE9TSVRJT04gPSBudWxsLFxuICAgIERFRkFVTFRfUEFORUxfV0lEVEggICAgICA9IDIwMCxcbiAgICBERUZBVUxUX1BBTkVMX0hFSUdIVCAgICAgPSBudWxsLFxuICAgIERFRkFVTFRfUEFORUxfV0lEVEhfTUlOICA9IDEwMCxcbiAgICBERUZBVUxUX1BBTkVMX1dJRFRIX01BWCAgPSA2MDAsXG4gICAgREVGQVVMVF9QQU5FTF9SQVRJTyAgICAgID0gNDAsXG4gICAgREVGQVVMVF9QQU5FTF9MQUJFTCAgICAgID0gJ0NvbnRyb2wgUGFuZWwnLFxuICAgIERFRkFVTFRfUEFORUxfVkFMSUdOICAgICA9IExheW91dE1vZGUuVE9QLFxuICAgIERFRkFVTFRfUEFORUxfQUxJR04gICAgICA9IExheW91dE1vZGUuUklHSFQsXG4gICAgREVGQVVMVF9QQU5FTF9ET0NLICAgICAgID0ge2FsaWduOkxheW91dE1vZGUuUklHSFQscmVzaXphYmxlOnRydWV9LFxuICAgIERFRkFVTFRfUEFORUxfRU5BQkxFICAgICA9IHRydWUsXG4gICAgREVGQVVMVF9QQU5FTF9PUEFDSVRZICAgID0gMS4wLFxuICAgIERFRkFVTFRfUEFORUxfRklYRUQgICAgICA9IHRydWUsXG4gICAgREVGQVVMVF9QQU5FTF9WQ09OU1RSQUlOID0gdHJ1ZTtcblxuZnVuY3Rpb24gUGFuZWwoY29udHJvbEtpdCxwYXJhbXMpe1xuICAgIEV2ZW50RGlzcGF0Y2hlci5hcHBseSh0aGlzLGFyZ3VtZW50cyk7XG4gICAgdGhpcy5fcGFyZW50ID0gY29udHJvbEtpdDtcblxuXG4gICAgcGFyYW1zICAgICAgICAgICAgPSBwYXJhbXMgICAgICAgICAgIHx8IHt9O1xuICAgIHBhcmFtcy52YWxpZ24gICAgID0gcGFyYW1zLnZhbGlnbiAgICB8fCBERUZBVUxUX1BBTkVMX1ZBTElHTjtcbiAgICBwYXJhbXMuYWxpZ24gICAgICA9IHBhcmFtcy5hbGlnbiAgICAgfHwgREVGQVVMVF9QQU5FTF9BTElHTjtcbiAgICBwYXJhbXMucG9zaXRpb24gICA9IHBhcmFtcy5wb3NpdGlvbiAgfHwgREVGQVVMVF9QQU5FTF9QT1NJVElPTjtcbiAgICBwYXJhbXMud2lkdGggICAgICA9IHBhcmFtcy53aWR0aCAgICAgfHwgREVGQVVMVF9QQU5FTF9XSURUSDtcbiAgICBwYXJhbXMuaGVpZ2h0ICAgICA9IHBhcmFtcy5oZWlnaHQgICAgfHwgREVGQVVMVF9QQU5FTF9IRUlHSFQ7XG4gICAgcGFyYW1zLnJhdGlvICAgICAgPSBwYXJhbXMucmF0aW8gICAgIHx8IERFRkFVTFRfUEFORUxfUkFUSU87XG4gICAgcGFyYW1zLmxhYmVsICAgICAgPSBwYXJhbXMubGFiZWwgICAgIHx8IERFRkFVTFRfUEFORUxfTEFCRUw7XG4gICAgcGFyYW1zLm9wYWNpdHkgICAgPSBwYXJhbXMub3BhY2l0eSAgIHx8IERFRkFVTFRfUEFORUxfT1BBQ0lUWTtcbiAgICBwYXJhbXMuZml4ZWQgICAgICA9IHBhcmFtcy5maXhlZCAgICAgID09PSB1bmRlZmluZWQgPyBERUZBVUxUX1BBTkVMX0ZJWEVEICAgICAgOiBwYXJhbXMuZml4ZWQ7XG4gICAgcGFyYW1zLmVuYWJsZSAgICAgPSBwYXJhbXMuZW5hYmxlICAgICA9PT0gdW5kZWZpbmVkID8gREVGQVVMVF9QQU5FTF9FTkFCTEUgICAgIDogcGFyYW1zLmVuYWJsZTtcbiAgICBwYXJhbXMudmNvbnN0cmFpbiA9IHBhcmFtcy52Y29uc3RyYWluID09PSB1bmRlZmluZWQgPyBERUZBVUxUX1BBTkVMX1ZDT05TVFJBSU4gOiBwYXJhbXMudmNvbnN0cmFpbjtcblxuICAgIGlmIChwYXJhbXMuZG9jaykge1xuICAgICAgICBwYXJhbXMuZG9jay5hbGlnbiA9IHBhcmFtcy5kb2NrLmFsaWduIHx8IERFRkFVTFRfUEFORUxfRE9DSy5hbGlnbjtcbiAgICAgICAgcGFyYW1zLmRvY2sucmVzaXphYmxlID0gcGFyYW1zLmRvY2sucmVzaXphYmxlIHx8IERFRkFVTFRfUEFORUxfRE9DSy5yZXNpemFibGU7XG4gICAgfVxuXG4gICAgdGhpcy5fd2lkdGggICAgICA9IE1hdGgubWF4KERFRkFVTFRfUEFORUxfV0lEVEhfTUlOLFxuICAgICAgICAgICAgICAgICAgICAgICBNYXRoLm1pbihwYXJhbXMud2lkdGgsREVGQVVMVF9QQU5FTF9XSURUSF9NQVgpKTtcbiAgICB0aGlzLl9oZWlnaHQgICAgID0gcGFyYW1zLmhlaWdodCA/ICBNYXRoLm1heCgwLE1hdGgubWluKHBhcmFtcy5oZWlnaHQsd2luZG93LmlubmVySGVpZ2h0KSkgOiBudWxsO1xuICAgIHRoaXMuX2ZpeGVkICAgICAgPSBwYXJhbXMuZml4ZWQ7XG4gICAgdGhpcy5fZG9jayAgICAgICA9IHBhcmFtcy5kb2NrO1xuICAgIHRoaXMuX3Bvc2l0aW9uICAgPSBwYXJhbXMucG9zaXRpb247XG4gICAgdGhpcy5fdkNvbnN0cmFpbiA9IHBhcmFtcy52Y29uc3RyYWluO1xuICAgIHRoaXMuX2xhYmVsICAgICAgPSBwYXJhbXMubGFiZWw7XG4gICAgdGhpcy5fZW5hYmxlZCAgICA9IHBhcmFtcy5lbmFibGU7XG4gICAgdGhpcy5fZ3JvdXBzICAgICA9IFtdO1xuXG5cbiAgICB2YXIgd2lkdGggICAgPSB0aGlzLl93aWR0aCxcbiAgICAgICAgaXNGaXhlZCAgPSB0aGlzLl9maXhlZCxcbiAgICAgICAgZG9jayAgICAgPSB0aGlzLl9kb2NrLFxuICAgICAgICBwb3NpdGlvbiA9IHRoaXMuX3Bvc2l0aW9uLFxuICAgICAgICBsYWJlbCAgICA9IHRoaXMuX2xhYmVsLFxuICAgICAgICBhbGlnbiAgICA9IHBhcmFtcy5hbGlnbixcbiAgICAgICAgb3BhY2l0eSAgPSBwYXJhbXMub3BhY2l0eTtcblxuXG4gICAgdmFyIHJvb3QgPSB0aGlzLl9ub2RlICAgICA9IG5ldyBOb2RlKCkuc2V0U3R5bGVDbGFzcyhDU1MuUGFuZWwpLFxuICAgICAgICBoZWFkID0gdGhpcy5faGVhZE5vZGUgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLkhlYWQpLFxuICAgICAgICBtZW51ICAgICAgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLk1lbnUpLFxuICAgICAgICBsYWJlbFdyYXAgPSBuZXcgTm9kZSgpLnNldFN0eWxlQ2xhc3MoQ1NTLldyYXApLFxuICAgICAgICBsYWJlbF8gICAgPSBuZXcgTm9kZShOb2RlLlNQQU4pLnNldFN0eWxlQ2xhc3MoQ1NTLkxhYmVsKSxcbiAgICAgICAgd3JhcCA9IHRoaXMuX3dyYXBOb2RlID0gbmV3IE5vZGUoTm9kZS5ESVYpLnNldFN0eWxlQ2xhc3MoQ1NTLldyYXApLFxuICAgICAgICBsaXN0ID0gdGhpcy5fbGlzdE5vZGUgPSBuZXcgTm9kZShOb2RlLkxJU1QpLnNldFN0eWxlQ2xhc3MoQ1NTLkdyb3VwTGlzdCk7XG5cbiAgICByb290LnNldFdpZHRoKHdpZHRoKTtcbiAgICBsYWJlbF8uc2V0UHJvcGVydHkoJ2lubmVySFRNTCcsIGxhYmVsKTtcblxuICAgIGxhYmVsV3JhcC5hZGRDaGlsZChsYWJlbF8pO1xuICAgIGhlYWQuYWRkQ2hpbGQobWVudSk7XG4gICAgaGVhZC5hZGRDaGlsZChsYWJlbFdyYXApO1xuICAgIHdyYXAuYWRkQ2hpbGQobGlzdCk7XG4gICAgcm9vdC5hZGRDaGlsZChoZWFkKTtcbiAgICByb290LmFkZENoaWxkKHdyYXApO1xuXG4gICAgY29udHJvbEtpdC5nZXROb2RlKCkuYWRkQ2hpbGQocm9vdCk7XG5cblxuICAgIGlmICghZG9jaykge1xuICAgICAgICB2YXIgbWVudUhpZGUgPSB0aGlzLl9tZW51SGlkZSA9IG5ldyBOb2RlKE5vZGUuSU5QVVRfQlVUVE9OKTtcbiAgICAgICAgICAgIG1lbnVIaWRlLnNldFN0eWxlQ2xhc3MoQ1NTLkJ1dHRvbk1lbnVIaWRlKTtcbiAgICAgICAgICAgIG1lbnVIaWRlLmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50Lk1PVVNFX0RPV04sIHRoaXMuX29uTWVudUhpZGVNb3VzZURvd24uYmluZCh0aGlzKSk7XG5cbiAgICAgICAgbWVudS5hZGRDaGlsZChtZW51SGlkZSk7XG5cbiAgICAgICAgaWYgKHRoaXMuX3BhcmVudC5wYW5lbHNBcmVDbG9zYWJsZSgpKSB7XG4gICAgICAgICAgICB2YXIgbWVudUNsb3NlID0gbmV3IE5vZGUoTm9kZS5JTlBVVF9CVVRUT04pO1xuICAgICAgICAgICAgbWVudUNsb3NlLnNldFN0eWxlQ2xhc3MoQ1NTLkJ1dHRvbk1lbnVDbG9zZSk7XG4gICAgICAgICAgICBtZW51Q2xvc2UuYWRkRXZlbnRMaXN0ZW5lcihOb2RlRXZlbnQuTU9VU0VfRE9XTiwgdGhpcy5kaXNhYmxlLmJpbmQodGhpcykpO1xuXG4gICAgICAgICAgICBtZW51LmFkZENoaWxkKG1lbnVDbG9zZSk7XG4gICAgICAgIH1cblxuXG4gICAgICAgIGlmICh0aGlzLmhhc01heEhlaWdodCgpKSB7XG4gICAgICAgICAgICB0aGlzLl9hZGRTY3JvbGxXcmFwKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWlzRml4ZWQpIHtcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbikge1xuICAgICAgICAgICAgICAgIGlmIChhbGlnbiA9PSBMYXlvdXRNb2RlLkxFRlQgfHxcbiAgICAgICAgICAgICAgICAgICAgYWxpZ24gPT0gTGF5b3V0TW9kZS5UT1AgfHxcbiAgICAgICAgICAgICAgICAgICAgYWxpZ24gPT0gTGF5b3V0TW9kZS5CT1RUT00pIHtcbiAgICAgICAgICAgICAgICAgICAgcm9vdC5zZXRQb3NpdGlvbkdsb2JhbChwb3NpdGlvblswXSwgcG9zaXRpb25bMV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcm9vdC5zZXRQb3NpdGlvbkdsb2JhbCh3aW5kb3cuaW5uZXJXaWR0aCAtIHdpZHRoIC0gcG9zaXRpb25bMF0sIHBvc2l0aW9uWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcG9zaXRpb24gPSByb290LmdldFBvc2l0aW9uKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB0aGlzLl9wb3NpdGlvbiA9IHJvb3QuZ2V0UG9zaXRpb24oKTtcblxuICAgICAgICAgICAgdGhpcy5fbW91c2VPZmZzZXQgPSBbMCwgMF07XG5cbiAgICAgICAgICAgIHJvb3Quc2V0U3R5bGVQcm9wZXJ0eSgncG9zaXRpb24nLCAnYWJzb2x1dGUnKTtcbiAgICAgICAgICAgIGhlYWQuYWRkRXZlbnRMaXN0ZW5lcihOb2RlRXZlbnQuTU9VU0VfRE9XTiwgdGhpcy5fb25IZWFkRHJhZ1N0YXJ0LmJpbmQodGhpcykpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKHBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBvc2l0aW9uWCA9IHBvc2l0aW9uWzBdLFxuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvblkgPSBwb3NpdGlvblsxXTtcblxuICAgICAgICAgICAgICAgIGlmIChwb3NpdGlvblkgIT0gMClyb290LnNldFBvc2l0aW9uWShwb3NpdGlvblkpO1xuICAgICAgICAgICAgICAgIGlmIChwb3NpdGlvblggIT0gMClpZiAoYWxpZ24gPT0gTGF5b3V0TW9kZS5SSUdIVClyb290LmdldEVsZW1lbnQoKS5tYXJnaW5SaWdodCA9IHBvc2l0aW9uWDtcbiAgICAgICAgICAgICAgICBlbHNlIHJvb3Quc2V0UG9zaXRpb25YKHBvc2l0aW9uWCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJvb3Quc2V0U3R5bGVQcm9wZXJ0eSgnZmxvYXQnLCBhbGlnbik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHZhciBkb2NrQWxpZ25tZW50ID0gZG9jay5hbGlnbjtcblxuICAgICAgICBpZiAoZG9ja0FsaWdubWVudCA9PSBMYXlvdXRNb2RlLkxFRlQgfHxcbiAgICAgICAgICAgIGRvY2tBbGlnbm1lbnQgPT0gTGF5b3V0TW9kZS5SSUdIVCkge1xuICAgICAgICAgICAgYWxpZ24gPSBkb2NrQWxpZ25tZW50O1xuICAgICAgICAgICAgdGhpcy5faGVpZ2h0ID0gd2luZG93LmlubmVySGVpZ2h0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRvY2tBbGlnbm1lbnQgPT0gTGF5b3V0TW9kZS5UT1AgfHxcbiAgICAgICAgICAgIGRvY2tBbGlnbm1lbnQgPT0gTGF5b3V0TW9kZS5CT1RUT00pIHtcblxuICAgICAgICB9XG5cbiAgICAgICAgLypcbiAgICAgICAgIGlmKGRvY2sucmVzaXphYmxlKVxuICAgICAgICAge1xuICAgICAgICAgdmFyIHNpemVIYW5kbGUgPSBuZXcgQ29udHJvbEtpdC5Ob2RlKENvbnRyb2xLaXQuTm9kZVR5cGUuRElWKTtcbiAgICAgICAgIHNpemVIYW5kbGUuc2V0U3R5bGVDbGFzcyhDb250cm9sS2l0LkNTUy5TaXplSGFuZGxlKTtcbiAgICAgICAgIHJvb3ROb2RlLmFkZENoaWxkKHNpemVIYW5kbGUpO1xuICAgICAgICAgfVxuICAgICAgICAgKi9cblxuICAgICAgICByb290LnNldFN0eWxlUHJvcGVydHkoJ2Zsb2F0JywgYWxpZ24pO1xuICAgIH1cblxuICAgIHZhciBwYXJlbnQgPSB0aGlzLl9wYXJlbnQ7XG4gICAgdmFyIGhpc3RvcnlJc0VuYWJsZWQgPSBwYXJlbnQuaGlzdG9yeUlzRW5hYmxlZCgpLFxuICAgICAgICBzdGF0ZXNBcmVFbmFibGVkID0gcGFyZW50LnN0YXRlc0FyZUVuYWJsZWQoKTtcblxuICAgIGlmKGhpc3RvcnlJc0VuYWJsZWQgfHwgc3RhdGVzQXJlRW5hYmxlZCl7XG4gICAgICAgIG1lbnUuYWRkQ2hpbGRBdChuZXcgTm9kZSgpLDApLnNldFN0eWxlQ2xhc3MoQ1NTLldyYXApOy8vLnNldFN0eWxlUHJvcGVydHkoJ2Rpc3BsYXknLCdub25lJyk7XG4gICAgfVxuXG4gICAgaWYgKGhpc3RvcnlJc0VuYWJsZWQpIHtcbiAgICAgICAgdGhpcy5fbWVudVVuZG8gPSBtZW51LmdldENoaWxkQXQoMClcbiAgICAgICAgICAgIC5hZGRDaGlsZChuZXcgTm9kZShOb2RlLklOUFVUX0JVVFRPTikpXG4gICAgICAgICAgICAgICAgLnNldFN0eWxlQ2xhc3MoQ1NTLkJ1dHRvbk1lbnVVbmRvKVxuICAgICAgICAgICAgICAgIC5zZXRQcm9wZXJ0eSgndmFsdWUnLEhpc3RvcnkuZ2V0KCkuZ2V0TnVtU3RhdGVzKCkpXG4gICAgICAgICAgICAgICAgLmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50Lk1PVVNFX0RPV04sZnVuY3Rpb24oKXtcbiAgICAgICAgICAgICAgICAgICAgSGlzdG9yeS5nZXQoKS5wb3BTdGF0ZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICBwYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcihNZW51RXZlbnQuVVBEQVRFX01FTlUsdGhpcywgJ29uVXBkYXRlTWVudScpO1xuICAgIH1cbiAgICBpZihzdGF0ZXNBcmVFbmFibGVkKXtcbiAgICAgICAgbWVudS5nZXRDaGlsZEF0KDApXG4gICAgICAgICAgICAuYWRkQ2hpbGQobmV3IE5vZGUoTm9kZS5JTlBVVF9CVVRUT04pKVxuICAgICAgICAgICAgICAgIC5zZXRTdHlsZUNsYXNzKENTUy5CdXR0b25NZW51TG9hZClcbiAgICAgICAgICAgICAgICAuc2V0UHJvcGVydHkoJ3ZhbHVlJywnTG9hZCcpXG4gICAgICAgICAgICAgICAgLmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50Lk1PVVNFX0RPV04sZnVuY3Rpb24oKXtcbiAgICAgICAgICAgICAgICAgICAgY29udHJvbEtpdC5fbG9hZFN0YXRlKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIG1lbnUuZ2V0Q2hpbGRBdCgwKVxuICAgICAgICAgICAgLmFkZENoaWxkKG5ldyBOb2RlKE5vZGUuSU5QVVRfQlVUVE9OKSlcbiAgICAgICAgICAgICAgICAuc2V0U3R5bGVDbGFzcyhDU1MuQnV0dG9uTWVudVNhdmUpXG4gICAgICAgICAgICAgICAgLnNldFByb3BlcnR5KCd2YWx1ZScsJ1NhdmUnKVxuICAgICAgICAgICAgICAgIC5hZGRFdmVudExpc3RlbmVyKE5vZGVFdmVudC5NT1VTRV9ET1dOLGZ1bmN0aW9uKCl7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRyb2xLaXQuX3NhdmVTdGF0ZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgIH1cbiAgICBpZihoaXN0b3J5SXNFbmFibGVkIHx8IHN0YXRlc0FyZUVuYWJsZWQpe1xuICAgICAgICBoZWFkLmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50Lk1PVVNFX09WRVIsZnVuY3Rpb24oKXtcbiAgICAgICAgICAgIG1lbnUuc2V0U3R5bGVDbGFzcyhDU1MuTWVudUFjdGl2ZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBoZWFkLmFkZEV2ZW50TGlzdGVuZXIoTm9kZUV2ZW50Lk1PVVNFX09VVCxmdW5jdGlvbigpe1xuICAgICAgICAgICAgbWVudS5zZXRTdHlsZUNsYXNzKENTUy5NZW51KTtcbiAgICAgICAgfSk7XG4gICAgfVxuICAgIGlmIChvcGFjaXR5ICE9IDEuMCAmJiBvcGFjaXR5ICE9IDAuMCkge1xuICAgICAgICByb290LnNldFN0eWxlUHJvcGVydHkoJ29wYWNpdHknLCBvcGFjaXR5KTtcbiAgICB9XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoRG9jdW1lbnRFdmVudC5XSU5ET1dfUkVTSVpFLHRoaXMuX29uV2luZG93UmVzaXplLmJpbmQodGhpcykpO1xuICAgIHRoaXMuX3VwZGF0ZUFwcGVhcmFuY2UoKTtcbn1cblBhbmVsLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXZlbnREaXNwYXRjaGVyLnByb3RvdHlwZSk7XG5QYW5lbC5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBQYW5lbDtcblxuUGFuZWwucHJvdG90eXBlLl9vbk1lbnVIaWRlTW91c2VEb3duID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX2VuYWJsZWQgPSAhdGhpcy5fZW5hYmxlZDtcbiAgICB0aGlzLl91cGRhdGVBcHBlYXJhbmNlKCk7XG59O1xuXG5QYW5lbC5wcm90b3R5cGUub25VcGRhdGVNZW51ID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX21lbnVVbmRvLnNldFByb3BlcnR5KCd2YWx1ZScsIEhpc3RvcnkuZ2V0KCkuZ2V0TnVtU3RhdGVzKCkpO1xufTtcblxuUGFuZWwucHJvdG90eXBlLl9vbk1lbnVVbmRvVHJpZ2dlciA9IGZ1bmN0aW9uICgpIHtcbiAgICBIaXN0b3J5LmdldCgpLnBvcFN0YXRlKCk7XG59O1xuXG5cblBhbmVsLnByb3RvdHlwZS5fdXBkYXRlQXBwZWFyYW5jZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgcm9vdE5vZGUgPSB0aGlzLl9ub2RlLFxuICAgICAgICBoZWFkTm9kZSA9IHRoaXMuX2hlYWROb2RlLFxuICAgICAgICBtZW51SGlkZSA9IHRoaXMuX21lbnVIaWRlO1xuXG4gICAgaWYgKCF0aGlzLl9lbmFibGVkKSB7XG4gICAgICAgIGhlYWROb2RlLmdldFN0eWxlKCkuYm9yZGVyQm90dG9tID0gJ25vbmUnO1xuICAgICAgICByb290Tm9kZS5zZXRIZWlnaHQoaGVhZE5vZGUuZ2V0SGVpZ2h0KCkpO1xuICAgICAgICBtZW51SGlkZS5zZXRTdHlsZUNsYXNzKENTUy5CdXR0b25NZW51U2hvdyk7XG4gICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIFBhbmVsRXZlbnQuUEFORUxfSElERSwgbnVsbCkpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgcm9vdE5vZGUuc2V0SGVpZ2h0KGhlYWROb2RlLmdldEhlaWdodCgpICsgdGhpcy5fd3JhcE5vZGUuZ2V0SGVpZ2h0KCkpO1xuICAgICAgICByb290Tm9kZS5kZWxldGVTdHlsZVByb3BlcnR5KCdoZWlnaHQnKTtcbiAgICAgICAgbWVudUhpZGUuc2V0U3R5bGVDbGFzcyhDU1MuQnV0dG9uTWVudUhpZGUpO1xuICAgICAgICBoZWFkTm9kZS5zZXRTdHlsZUNsYXNzKENTUy5IZWFkKTtcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgUGFuZWxFdmVudC5QQU5FTF9TSE9XLCBudWxsKSk7XG4gICAgfVxufTtcblxuUGFuZWwucHJvdG90eXBlLl9vbkhlYWREcmFnU3RhcnQgPSBmdW5jdGlvbigpe1xuICAgIHZhciBwYXJlbnROb2RlID0gdGhpcy5fcGFyZW50LmdldE5vZGUoKSxcbiAgICAgICAgbm9kZSAgICAgICA9IHRoaXMuX25vZGU7XG5cbiAgICB2YXIgbm9kZVBvcyAgID0gbm9kZS5nZXRQb3NpdGlvbkdsb2JhbCgpLFxuICAgICAgICBtb3VzZVBvcyAgPSBNb3VzZS5nZXQoKS5nZXRQb3NpdGlvbigpLFxuICAgICAgICBvZmZzZXRQb3MgPSB0aGlzLl9tb3VzZU9mZnNldDtcblxuICAgICAgICBvZmZzZXRQb3NbMF0gPSBtb3VzZVBvc1swXSAtIG5vZGVQb3NbMF07XG4gICAgICAgIG9mZnNldFBvc1sxXSA9IG1vdXNlUG9zWzFdIC0gbm9kZVBvc1sxXTtcblxuICAgIHZhciBldmVudE1vdXNlTW92ZSA9IERvY3VtZW50RXZlbnQuTU9VU0VfTU9WRSxcbiAgICAgICAgZXZlbnRNb3VzZVVwICAgPSBEb2N1bWVudEV2ZW50Lk1PVVNFX1VQO1xuXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIG9uRHJhZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHNlbGYuX3VwZGF0ZVBvc2l0aW9uKCk7XG4gICAgICAgIH0sXG4gICAgICAgIG9uRHJhZ0VuZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnRNb3VzZU1vdmUsIG9uRHJhZywgZmFsc2UpO1xuICAgICAgICAgICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudE1vdXNlVXAsIG9uRHJhZ0VuZCwgZmFsc2UpO1xuICAgICAgICAgICAgc2VsZi5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgUGFuZWxFdmVudC5QQU5FTF9NT1ZFX0VORCwgbnVsbCkpO1xuICAgICAgICB9O1xuXG4gICAgcGFyZW50Tm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICBwYXJlbnROb2RlLmFkZENoaWxkKCAgIG5vZGUpO1xuXG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudE1vdXNlTW92ZSwgb25EcmFnLCAgICBmYWxzZSk7XG4gICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihldmVudE1vdXNlVXAsICAgb25EcmFnRW5kLCBmYWxzZSk7XG5cbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50Xyh0aGlzLFBhbmVsRXZlbnQuUEFORUxfTU9WRV9CRUdJTixudWxsKSk7XG59O1xuXG5QYW5lbC5wcm90b3R5cGUuX3VwZGF0ZVBvc2l0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBtb3VzZVBvcyA9IE1vdXNlLmdldCgpLmdldFBvc2l0aW9uKCksXG4gICAgICAgIG9mZnNldFBvcyA9IHRoaXMuX21vdXNlT2Zmc2V0O1xuXG4gICAgdmFyIHBvc2l0aW9uID0gdGhpcy5fcG9zaXRpb247XG4gICAgcG9zaXRpb25bMF0gPSBtb3VzZVBvc1swXSAtIG9mZnNldFBvc1swXTtcbiAgICBwb3NpdGlvblsxXSA9IG1vdXNlUG9zWzFdIC0gb2Zmc2V0UG9zWzFdO1xuXG4gICAgdGhpcy5fY29uc3RyYWluSGVpZ2h0KCk7XG4gICAgdGhpcy5fY29uc3RyYWluUG9zaXRpb24oKTtcblxuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIFBhbmVsRXZlbnQuUEFORUxfTU9WRSwgbnVsbCkpO1xufTtcblxuUGFuZWwucHJvdG90eXBlLl9vbldpbmRvd1Jlc2l6ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5pc0RvY2tlZCgpKSB7XG4gICAgICAgIHZhciBkb2NrID0gdGhpcy5fZG9jaztcblxuICAgICAgICBpZiAoZG9jay5hbGlnbiA9PSBMYXlvdXRNb2RlLlJJR0hUIHx8XG4gICAgICAgICAgICBkb2NrLmFsaWduID09IExheW91dE1vZGUuTEVGVCkge1xuICAgICAgICAgICAgdmFyIHdpbmRvd0hlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodCxcbiAgICAgICAgICAgICAgICBsaXN0SGVpZ2h0ID0gdGhpcy5fbGlzdE5vZGUuZ2V0SGVpZ2h0KCksXG4gICAgICAgICAgICAgICAgaGVhZEhlaWdodCA9IHRoaXMuX2hlYWROb2RlLmdldEhlaWdodCgpO1xuXG4gICAgICAgICAgICB0aGlzLl9oZWlnaHQgPSB3aW5kb3dIZWlnaHQ7XG5cbiAgICAgICAgICAgIGlmICgod2luZG93SGVpZ2h0IC0gaGVhZEhlaWdodCkgPiBsaXN0SGVpZ2h0KXtcbiAgICAgICAgICAgICAgICB0aGlzLl9zY3JvbGxCYXIuZGlzYWJsZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZXtcbiAgICAgICAgICAgICAgICB0aGlzLl9zY3JvbGxCYXIuZW5hYmxlKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIFBhbmVsRXZlbnQuUEFORUxfU0laRV9DSEFOR0UpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzRml4ZWQoKSl7XG4gICAgICAgICAgICB0aGlzLl9jb25zdHJhaW5Qb3NpdGlvbigpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHRoaXMuX2NvbnN0cmFpbkhlaWdodCgpO1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIERvY3VtZW50RXZlbnQuV0lORE9XX1JFU0laRSkpO1xufTtcblxuUGFuZWwucHJvdG90eXBlLl9jb25zdHJhaW5Qb3NpdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgbm9kZSA9IHRoaXMuX25vZGU7XG5cbiAgICB2YXIgbWF4WCA9IHdpbmRvdy5pbm5lcldpZHRoIC0gbm9kZS5nZXRXaWR0aCgpLFxuICAgICAgICBtYXhZID0gd2luZG93LmlubmVySGVpZ2h0IC0gbm9kZS5nZXRIZWlnaHQoKTtcblxuICAgIHZhciBwb3NpdGlvbiA9IHRoaXMuX3Bvc2l0aW9uO1xuICAgIHBvc2l0aW9uWzBdID0gTWF0aC5tYXgoMCwgTWF0aC5taW4ocG9zaXRpb25bMF0sIG1heFgpKTtcbiAgICBwb3NpdGlvblsxXSA9IE1hdGgubWF4KDAsIE1hdGgubWluKHBvc2l0aW9uWzFdLCBtYXhZKSk7XG5cbiAgICBub2RlLnNldFBvc2l0aW9uR2xvYmFsKHBvc2l0aW9uWzBdLCBwb3NpdGlvblsxXSk7XG59O1xuXG5QYW5lbC5wcm90b3R5cGUuX2NvbnN0cmFpbkhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXRoaXMuX3ZDb25zdHJhaW4pcmV0dXJuO1xuXG4gICAgdmFyIGhhc01heEhlaWdodCA9IHRoaXMuaGFzTWF4SGVpZ2h0KCksXG4gICAgICAgIGhhc1Njcm9sbFdyYXAgPSB0aGlzLmhhc1Njcm9sbFdyYXAoKTtcblxuICAgIHZhciBoZWFkID0gdGhpcy5faGVhZE5vZGUsXG4gICAgICAgIHdyYXAgPSB0aGlzLl93cmFwTm9kZTtcblxuICAgIHZhciBzY3JvbGxCYXIgPSB0aGlzLl9zY3JvbGxCYXI7XG5cbiAgICB2YXIgcGFuZWxUb3AgPSB0aGlzLmlzRG9ja2VkKCkgPyAwIDpcbiAgICAgICAgdGhpcy5pc0ZpeGVkKCkgPyAwIDpcbiAgICAgICAgICAgIHRoaXMuX3Bvc2l0aW9uWzFdO1xuXG4gICAgdmFyIHBhbmVsSGVpZ2h0ID0gaGFzTWF4SGVpZ2h0ID8gdGhpcy5nZXRNYXhIZWlnaHQoKSA6XG4gICAgICAgIGhhc1Njcm9sbFdyYXAgPyBzY3JvbGxCYXIuZ2V0VGFyZ2V0Tm9kZSgpLmdldEhlaWdodCgpIDpcbiAgICAgICAgICAgIHdyYXAuZ2V0SGVpZ2h0KCk7XG5cbiAgICB2YXIgcGFuZWxCb3R0b20gPSBwYW5lbFRvcCArIHBhbmVsSGVpZ2h0O1xuICAgIHZhciBoZWFkSGVpZ2h0ID0gaGVhZC5nZXRIZWlnaHQoKTtcblxuICAgIHZhciB3aW5kb3dIZWlnaHQgPSB3aW5kb3cuaW5uZXJIZWlnaHQsXG4gICAgICAgIGhlaWdodERpZmYgPSB3aW5kb3dIZWlnaHQgLSBwYW5lbEJvdHRvbSAtIGhlYWRIZWlnaHQsXG4gICAgICAgIGhlaWdodFN1bTtcblxuICAgIGlmIChoZWlnaHREaWZmIDwgMC4wKSB7XG4gICAgICAgIGhlaWdodFN1bSA9IHBhbmVsSGVpZ2h0ICsgaGVpZ2h0RGlmZjtcblxuICAgICAgICBpZiAoIWhhc1Njcm9sbFdyYXApIHtcbiAgICAgICAgICAgIHRoaXMuX2FkZFNjcm9sbFdyYXAoaGVpZ2h0U3VtKTtcbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIFBhbmVsRXZlbnQuUEFORUxfU0NST0xMX1dSQVBfQURERUQsIG51bGwpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHNjcm9sbEJhci5zZXRXcmFwSGVpZ2h0KGhlaWdodFN1bSk7XG4gICAgICAgIHdyYXAuc2V0SGVpZ2h0KGhlaWdodFN1bSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBpZiAoIWhhc01heEhlaWdodCAmJiBoYXNTY3JvbGxXcmFwKSB7XG4gICAgICAgICAgICBzY3JvbGxCYXIucmVtb3ZlRnJvbVBhcmVudCgpO1xuICAgICAgICAgICAgd3JhcC5hZGRDaGlsZCh0aGlzLl9saXN0Tm9kZSk7XG4gICAgICAgICAgICB3cmFwLmRlbGV0ZVN0eWxlUHJvcGVydHkoJ2hlaWdodCcpO1xuICAgICAgICAgICAgdGhpcy5fc2Nyb2xsQmFyLnJlbW92ZU1vdXNlTGlzdGVuZXIoKTtcbiAgICAgICAgICAgIHRoaXMuX3Njcm9sbEJhciA9IG51bGw7XG5cbiAgICAgICAgICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIFBhbmVsRXZlbnQuUEFORUxfU0NST0xMX1dSQVBfUkVNT1ZFRCwgbnVsbCkpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxuUGFuZWwucHJvdG90eXBlLm9uR3JvdXBMaXN0U2l6ZUNoYW5nZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5oYXNTY3JvbGxXcmFwKCkpe1xuICAgICAgICB0aGlzLl91cGRhdGVTY3JvbGxXcmFwKCk7XG4gICAgfVxuICAgIHRoaXMuX2NvbnN0cmFpbkhlaWdodCgpO1xufTtcblxuUGFuZWwucHJvdG90eXBlLl91cGRhdGVTY3JvbGxXcmFwID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciB3cmFwICAgPSB0aGlzLl93cmFwTm9kZSxcbiAgICAgICAgc2Nyb2xsQmFyICA9IHRoaXMuX3Njcm9sbEJhcixcbiAgICAgICAgaGVpZ2h0ICAgICA9IHRoaXMuaGFzTWF4SGVpZ2h0KCkgPyB0aGlzLmdldE1heEhlaWdodCgpIDogMTAwLFxuICAgICAgICBsaXN0SGVpZ2h0ID0gdGhpcy5fbGlzdE5vZGUuZ2V0SGVpZ2h0KCk7XG5cbiAgICB3cmFwLnNldEhlaWdodChsaXN0SGVpZ2h0IDwgaGVpZ2h0ID8gbGlzdEhlaWdodCA6IGhlaWdodCk7XG5cbiAgICBzY3JvbGxCYXIudXBkYXRlKCk7XG5cbiAgICBpZiAoIXNjcm9sbEJhci5pc1ZhbGlkKCkpIHtcbiAgICAgICAgc2Nyb2xsQmFyLmRpc2FibGUoKTtcbiAgICAgICAgd3JhcC5zZXRIZWlnaHQod3JhcC5nZXRDaGlsZEF0KDEpLmdldEhlaWdodCgpKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHNjcm9sbEJhci5lbmFibGUoKTtcbiAgICAgICAgd3JhcC5zZXRIZWlnaHQoaGVpZ2h0KTtcbiAgICB9XG59O1xuXG5QYW5lbC5wcm90b3R5cGUuX2FkZFNjcm9sbFdyYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHdyYXBOb2RlID0gdGhpcy5fd3JhcE5vZGUsXG4gICAgICAgIGxpc3ROb2RlID0gdGhpcy5fbGlzdE5vZGUsXG4gICAgICAgIGhlaWdodCA9IGFyZ3VtZW50cy5sZW5ndGggPT0gMCA/XG4gICAgICAgICAgICB0aGlzLmdldE1heEhlaWdodCgpIDpcbiAgICAgICAgICAgIGFyZ3VtZW50c1swXTtcblxuICAgIHRoaXMuX3Njcm9sbEJhciA9IG5ldyBTY3JvbGxCYXIod3JhcE5vZGUsIGxpc3ROb2RlLCBoZWlnaHQpO1xuICAgIGlmICh0aGlzLmlzRW5hYmxlZCgpKXtcbiAgICAgICAgd3JhcE5vZGUuc2V0SGVpZ2h0KGhlaWdodCk7XG4gICAgfVxufTtcblxuUGFuZWwucHJvdG90eXBlLmhhc1Njcm9sbFdyYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3Njcm9sbEJhciAhPSBudWxsO1xufTtcblxuXG5QYW5lbC5wcm90b3R5cGUucHJldmVudFNlbGVjdERyYWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKCF0aGlzLmhhc1Njcm9sbFdyYXAoKSl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5fd3JhcE5vZGUuZ2V0RWxlbWVudCgpLnNjcm9sbFRvcCA9IDA7XG59O1xuXG5QYW5lbC5wcm90b3R5cGUuZW5hYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX25vZGUuc2V0U3R5bGVQcm9wZXJ0eSgnZGlzcGxheScsICdibG9jaycpO1xuICAgIHRoaXMuX2VuYWJsZWQgPSB0cnVlO1xuICAgIHRoaXMuX3VwZGF0ZUFwcGVhcmFuY2UoKTtcbn07XG5cblxuUGFuZWwucHJvdG90eXBlLmRpc2FibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5fbm9kZS5zZXRTdHlsZVByb3BlcnR5KCdkaXNwbGF5JywgJ25vbmUnKTtcbiAgICB0aGlzLl9lbmFibGVkID0gZmFsc2U7XG4gICAgdGhpcy5fdXBkYXRlQXBwZWFyYW5jZSgpO1xufTtcblxuUGFuZWwucHJvdG90eXBlLmlzRW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fZW5hYmxlZDtcbn07XG5cblBhbmVsLnByb3RvdHlwZS5pc0Rpc2FibGVkID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAhdGhpcy5fZW5hYmxlZDtcbn07XG5cblBhbmVsLnByb3RvdHlwZS5oYXNNYXhIZWlnaHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2hlaWdodCAhPSBudWxsO1xufTtcblxuUGFuZWwucHJvdG90eXBlLmdldE1heEhlaWdodCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5faGVpZ2h0O1xufTtcblxuUGFuZWwucHJvdG90eXBlLmlzRG9ja2VkID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9kb2NrO1xufTtcblxuUGFuZWwucHJvdG90eXBlLmlzRml4ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2ZpeGVkO1xufTtcblxuUGFuZWwucHJvdG90eXBlLmdldEdyb3VwcyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fZ3JvdXBzO1xufTtcblxuUGFuZWwucHJvdG90eXBlLmdldE5vZGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX25vZGU7XG59O1xuXG5QYW5lbC5wcm90b3R5cGUuZ2V0TGlzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fbGlzdE5vZGU7XG59O1xuXG5QYW5lbC5wcm90b3R5cGUuZ2V0V2lkdGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3dpZHRoO1xufTtcblxuUGFuZWwucHJvdG90eXBlLmdldFBvc2l0aW9uID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9wb3NpdGlvbjtcbn07XG5cblBhbmVsLnByb3RvdHlwZS5nZXRQYXJlbnQgPSBmdW5jdGlvbigpe1xuICAgIHJldHVybiB0aGlzLl9wYXJlbnQ7XG59O1xuXG4vKipcbiAqIEFkZHMgYSBuZXcgR3JvdXAgdG8gdGhlIFBhbmVsLlxuICogQHBhcmFtIHtPYmplY3R9IFtwYXJhbXNdIC0gR3JvdXAgb3B0aW9uc1xuICogQHBhcmFtIHtTdHJpbmd9IFtwYXJhbXMubGFiZWw9JyddIC0gVGhlIEdyb3VwIGxhYmVsIHN0cmluZ1xuICogQHBhcmFtIHtCb29sZWFufSBbcGFyYW1zLnVzZUxhYmVsPXRydWVdIC0gVHJpZ2dlciB3aGV0aGVyIGFsbCBjb250YWluZWQgU3ViR3JvdXBzIGFuZCBDb21wb25lbnRzIHNob3VsZCB1c2UgbGFiZWxzXG4gKiBAcGFyYW0ge0Jvb2xlYW59IFtwYXJhbXMuZW5hYmxlPXRydWVdIC0gRGVmaW5lcyBpbml0aWFsIHN0YXRlIG9wZW4gLyBjbG9zZWRcbiAqIEBwYXJhbSB7TnVtYmVyfSBbcGFyYW1zLmhlaWdodD1udWxsXSAtIERlZmluZXMgaWYgdGhlIGhlaWdodCBvZiB0aGUgR3JvdXAgc2hvdWxkIGJlIGNvbnN0cmFpbmVkIHRvIGNlcnRhaW4gaGVpZ2h0XG4gKiBAcmV0dXJucyB7UGFuZWx9XG4gKi9cblxuUGFuZWwucHJvdG90eXBlLmFkZEdyb3VwID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgIHZhciBncm91cCA9IG5ldyBHcm91cCh0aGlzLCBwYXJhbXMpO1xuICAgIHRoaXMuX2dyb3Vwcy5wdXNoKGdyb3VwKTtcbiAgICBpZiAodGhpcy5pc0RvY2tlZCgpKXtcbiAgICAgICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgUGFuZWxFdmVudC5QQU5FTF9TSVpFX0NIQU5HRSkpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogQWRkcyBhIG5ldyBTdWJHcm91cCB0byB0aGUgbGFzdCBhZGRlZCBHcm91cC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbcGFyYW1zXSAtIFN1Ykdyb3VwIG9wdGlvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfSBbcGFyYW1zLmxhYmVsPScnXSAtIFRoZSBTdWJHcm91cCBsYWJlbCBzdHJpbmdcbiAqIEBwYXJhbSB7Qm9vbGVhbn0gW3BhcmFtcy51c2VMYWJlbD10cnVlXSAtIFRyaWdnZXIgd2hldGhlciBhbGwgQ29tcG9uZW50cyBzaG91bGQgdXNlIGxhYmVsc1xuICogQHBhcmFtIHtCb29sZWFufSBbcGFyYW1zLmVuYWJsZT10cnVlXSAtIERlZmluZXMgaW5pdGlhbCBzdGF0ZSBvcGVuIC8gY2xvc2VkXG4gKiBAcGFyYW0ge051bWJlcn0gW3BhcmFtcy5oZWlnaHQ9bnVsbF0gLSBEZWZpbmVzIGlmIHRoZSBoZWlnaHQgb2YgdGhlIFN1Ykdyb3VwIHNob3VsZCBiZSBjb25zdHJhaW5lZCB0byBjZXJ0YWluIGhlaWdodFxuICogQHJldHVybnMge1BhbmVsfVxuICovXG5cblBhbmVsLnByb3RvdHlwZS5hZGRTdWJHcm91cCA9IGZ1bmN0aW9uKHBhcmFtcyl7XG4gICAgdmFyIGdyb3VwcyA9IHRoaXMuX2dyb3VwcztcbiAgICBpZihncm91cHMubGVuZ3RoID09IDApe1xuICAgICAgICB0aGlzLmFkZEdyb3VwKCk7XG4gICAgfVxuICAgIGdyb3Vwc1tncm91cHMubGVuZ3RoIC0gMV0uYWRkU3ViR3JvdXAocGFyYW1zKTtcbiAgICByZXR1cm4gdGhpcztcbn07XG5cblBhbmVsLnByb3RvdHlwZS5fYWRkQ29tcG9uZW50ID0gZnVuY3Rpb24oKXtcbiAgICB2YXIgZ3JvdXBzID0gdGhpcy5fZ3JvdXBzLFxuICAgICAgICBncm91cDtcbiAgICBpZihncm91cHMubGVuZ3RoID09IDApe1xuICAgICAgICBncm91cHMucHVzaChuZXcgR3JvdXAodGhpcykpO1xuICAgIH1cbiAgICBncm91cCA9IGdyb3Vwc1tncm91cHMubGVuZ3RoLTFdO1xuXG4gICAgZ3JvdXAuYWRkQ29tcG9uZW50LmFwcGx5KGdyb3VwLGFyZ3VtZW50cyk7XG4gICAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIEFkZHMgYSBuZXcgU3RyaW5nSW5wdXQgdG8gbGFzdCBhZGRlZCBTdWJHcm91cC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgLSBUaGUgb2JqZWN0XG4gKiBAcGFyYW0ge1N0cmluZ30gdmFsdWUgLSBUaGUgcHJvcGVydHkga2V5XG4gKiBAcGFyYW0ge09iamVjdH0gW3BhcmFtc10gLSBTdHJpbmdJbnB1dCBvcHRpb25zXG4gKiBAcGFyYW0ge1N0cmluZ30gW3BhcmFtcy5sYWJlbD12YWx1ZV0gLSBTdHJpbmdJbnB1dCBsYWJlbFxuICogQHBhcmFtIHtGdW5jdGlvbn0gW3BhcmFtcy5vbkNoYW5nZV0gLSBDYWxsYmFjayBvbiBjaGFuZ2VcbiAqIEBwYXJhbSB7QXJyYXl9IFtwYXJhbXMucHJlc2V0c10gLSBBIHNldCBvZiBwcmVzZXRzXG4gKiBAcmV0dXJucyB7UGFuZWx9XG4gKi9cblxuUGFuZWwucHJvdG90eXBlLmFkZFN0cmluZ0lucHV0ID0gZnVuY3Rpb24gKG9iamVjdCwgdmFsdWUsIHBhcmFtcykge1xuICAgIHJldHVybiB0aGlzLl9hZGRDb21wb25lbnQoU3RyaW5nSW5wdXQsb2JqZWN0LHZhbHVlLHBhcmFtcyk7XG59O1xuXG4vKipcbiAqIEFkZHMgYSBuZXcgTnVtYmVySW5wdXQgdG8gbGFzdCBhZGRlZCBTdWJHcm91cC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgLSBUaGUgb2JqZWN0LlxuICogQHBhcmFtIHtTdHJpbmd9IHZhbHVlIC0gVGhlIHByb3BlcnR5IGtleS5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbcGFyYW1zXSAtIENvbXBvbmVudCBvcHRpb25zLlxuICogQHBhcmFtIHtTdHJpbmd9IFtwYXJhbXMubGFiZWw9dmFsdWVdIC0gTnVtYmVySW5wdXQgbGFiZWxcbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtwYXJhbXMub25DaGFuZ2VdIC0gQ2FsbGJhY2sgb24gY2hhbmdlXG4gKiBAcGFyYW0ge051bWJlcn0gW3BhcmFtcy5zdGVwXSAtIEFtb3VudCBzdWJiZWQvYWRkZWQgb24gYXJyb3dEb3duL2Fycm93VXAgcHJlc3NcbiAqIEBwYXJhbSB7TnVtYmVyfSBbcGFyYW1zLmRwXSAtIERlY2ltYWwgcGxhY2VzIGRpc3BsYXllZFxuICogQHBhcmFtIHtBcnJheX0gW3BhcmFtcy5wcmVzZXRzXSAtIEEgc2V0IG9mIHByZXNldHNcbiAqIEByZXR1cm5zIHtQYW5lbH1cbiAqL1xuXG5QYW5lbC5wcm90b3R5cGUuYWRkTnVtYmVySW5wdXQgPSBmdW5jdGlvbiAob2JqZWN0LCB2YWx1ZSwgcGFyYW1zKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkZENvbXBvbmVudChOdW1iZXJJbnB1dCxvYmplY3QsdmFsdWUscGFyYW1zKTtcbn07XG5cbi8qKlxuICogQWRkcyBhIG5ldyBSYW5nZSBpbnB1dCB0byBsYXN0IGFkZGVkIFN1Ykdyb3VwLlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3RcbiAqIEBwYXJhbSB7U3RyaW5nfSB2YWx1ZSAtIFRoZSBwcm9wZXJ0eSBrZXlcbiAqIEBwYXJhbSB7T2JqZWN0fSBbcGFyYW1zXSAtIENvbXBvbmVudCBvcHRpb25zXG4gKiBAcGFyYW0ge1N0cmluZ30gW3BhcmFtcy5sYWJlbD12YWx1ZV0gLSBSYW5nZSBsYWJlbFxuICogQHBhcmFtIHtGdW5jdGlvbn0gW3BhcmFtcy5vbkNoYW5nZV0gLSBDYWxsYmFjayBvbiBjaGFuZ2VcbiAqIEBwYXJhbSB7TnVtYmVyfSBbcGFyYW1zLnN0ZXBdIC0gQW1vdW50IHN1YmJlZC9hZGRlZCBvbiBhcnJvd0Rvd24vYXJyb3dVcCBwcmVzc1xuICogQHBhcmFtIHtOdW1iZXJ9IFtwYXJhbXMuZHBdIC0gRGVjaW1hbCBwbGFjZXMgZGlzcGxheWVkXG4gKiBAcmV0dXJucyB7UGFuZWx9XG4gKi9cblxuUGFuZWwucHJvdG90eXBlLmFkZFJhbmdlID0gZnVuY3Rpb24gKG9iamVjdCwgdmFsdWUsIHBhcmFtcykge1xuICAgIHJldHVybiB0aGlzLl9hZGRDb21wb25lbnQoUmFuZ2Usb2JqZWN0LHZhbHVlLHBhcmFtcyk7XG59O1xuXG4vKipcbiAqIEFkZHMgYSBuZXcgQ2hlY2tib3ggdG8gbGFzdCBhZGRlZCBTdWJHcm91cC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgLSBUaGUgb2JqZWN0XG4gKiBAcGFyYW0ge1N0cmluZ30gdmFsdWUgLSBUaGUgcHJvcGVydHkga2V5XG4gKiBAcGFyYW0ge09iamVjdH0gW3BhcmFtc10gLSBDb21wb25lbnQgb3B0aW9uc1xuICogQHBhcmFtIHtTdHJpbmd9IFtwYXJhbXMubGFiZWw9dmFsdWVdIC0gQ2hlY2tib3ggbGFiZWxcbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtwYXJhbXMub25DaGFuZ2VdIC0gQ2FsbGJhY2sgb24gY2hhbmdlXG4gKiBAcmV0dXJucyB7UGFuZWx9XG4gKi9cblxuUGFuZWwucHJvdG90eXBlLmFkZENoZWNrYm94ID0gZnVuY3Rpb24gKG9iamVjdCwgdmFsdWUsIHBhcmFtcykge1xuICAgIHJldHVybiB0aGlzLl9hZGRDb21wb25lbnQoQ2hlY2tib3gsb2JqZWN0LHZhbHVlLHBhcmFtcyk7XG59O1xuXG4vKipcbiAqIEFkZHMgYSBuZXcgQ29sb3IgbW9kaWZpZXIgdG8gbGFzdCBhZGRlZCBTdWJHcm91cC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgLSBUaGUgb2JqZWN0XG4gKiBAcGFyYW0ge1N0cmluZ30gdmFsdWUgLSBUaGUgcHJvcGVydHkga2V5XG4gKiBAcGFyYW0ge09iamVjdH0gW3BhcmFtc10gLSBDb21wb25lbnQgb3B0aW9uc1xuICogQHBhcmFtIHtTdHJpbmd9IFtwYXJhbXMubGFiZWw9dmFsdWVdIC0gQ29sb3IgbGFiZWxcbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtwYXJhbXMub25DaGFuZ2VdIC0gQ2FsbGJhY2sgb24gY2hhbmdlXG4gKiBAcGFyYW0ge1N0cmluZ30gW3BhcmFtcy5jb2xvck1vZGU9J3JnYiddIC0gVGhlIGNvbG9yTW9kZSB0byBiZSB1c2VkOiAnaGV4JyAjZmYwMGZmLCAncmdiJyBbMjU1LDAsMjU1XSwgJ3JnYmZ2JyBbMSwwLDFdXG4gKiBAcGFyYW0ge0FycmF5fSBbcGFyYW1zLnByZXNldHNdIC0gQSBzZXQgb2YgcHJlc2V0IGNvbG9ycyBtYXRjaGluZyBwYXJhbXMuY29sb3JNb2RlXG4gKiBAcmV0dXJucyB7UGFuZWx9XG4gKi9cblxuUGFuZWwucHJvdG90eXBlLmFkZENvbG9yID0gZnVuY3Rpb24gKG9iamVjdCwgdmFsdWUsIHBhcmFtcykge1xuICAgIHJldHVybiB0aGlzLl9hZGRDb21wb25lbnQoQ29sb3Isb2JqZWN0LHZhbHVlLCBwYXJhbXMpO1xufTtcblxuLyoqXG4gKiBBZGRzIGEgbmV3IEJ1dHRvbiB0byBsYXN0IGFkZGVkIFN1Ykdyb3VwLlxuICogQHBhcmFtIHtTdHJpbmd9IGxhYmVsIC0gVGhlIG9iamVjdFxuICogQHBhcmFtIHtGdW5jdGlvbn0gb25QcmVzcyAtIENhbGxiYWNrXG4gKiBAcGFyYW0ge09iamVjdH0gW3BhcmFtc10gLSBDb21wb25lbnQgb3B0aW9uc1xuICogQHBhcmFtIHtTdHJpbmd9IFtwYXJhbXMubGFiZWw9dmFsdWVdIC0gQnV0dG9uIGxhYmVsXG4gKiBAcmV0dXJucyB7UGFuZWx9XG4gKi9cblxuUGFuZWwucHJvdG90eXBlLmFkZEJ1dHRvbiA9IGZ1bmN0aW9uIChsYWJlbCwgb25QcmVzcywgcGFyYW1zKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkZENvbXBvbmVudChCdXR0b24sbGFiZWwsb25QcmVzcyxwYXJhbXMpO1xufTtcblxuLyoqXG4gKiBBZGRzIGEgbmV3IFNlbGVjdCB0byBsYXN0IGFkZGVkIFN1Ykdyb3VwLlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3RcbiAqIEBwYXJhbSB7U3RyaW5nfSB2YWx1ZSAtIFRoZSBwcm9wZXJ0eSBrZXlcbiAqIEBwYXJhbSB7T2JqZWN0fSBbcGFyYW1zXSAtIENvbXBvbmVudCBvcHRpb25zXG4gKiBAcGFyYW0ge1N0cmluZ30gW3BhcmFtcy5sYWJlbD12YWx1ZV0gLSBCdXR0b24gbGFiZWxcbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtwYXJhbXMub25DaGFuZ2VdIC0gQ2FsbGJhY2sgb24gY2hhbmdlIC0gZnVuY3Rpb24oaW5kZXgpe31cbiAqIEBwYXJhbSB7U3RyaW5nfSBbcGFyYW1zLnRhcmdldF0gLSBUaGUgcHJvcGVydHkgdG8gYmUgc2V0IG9uIHNlbGVjdFxuICogQHJldHVybnMge1BhbmVsfVxuICovXG5cblBhbmVsLnByb3RvdHlwZS5hZGRTZWxlY3QgPSBmdW5jdGlvbiAob2JqZWN0LCB2YWx1ZSwgcGFyYW1zKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkZENvbXBvbmVudChTZWxlY3Qsb2JqZWN0LHZhbHVlLHBhcmFtcyk7XG59O1xuXG4vKipcbiAqIEFkZHMgYSBuZXcgU2xpZGVyIHRvIGxhc3QgYWRkZWQgU3ViR3JvdXAuXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IC0gVGhlIG9iamVjdFxuICogQHBhcmFtIHtTdHJpbmd9IHZhbHVlIC0gVGhlIHByb3BlcnR5IGtleVxuICogQHBhcmFtIHtTdHJpbmd9IHJhbmdlIC0gVGhlIG1pbi9tYXggYXJyYXkga2V5IHRvIGJlIHVzZWRcbiAqIEBwYXJhbSB7T2JqZWN0fSBbcGFyYW1zXSAtIENvbXBvbmVudCBvcHRpb25zXG4gKiBAcGFyYW0ge1N0cmluZ30gW3BhcmFtcy5sYWJlbD12YWx1ZV0gLSBTbGlkZXIgbGFiZWxcbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtwYXJhbXMub25DaGFuZ2VdIC0gQ2FsbGJhY2sgb24gY2hhbmdlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbcGFyYW1zLm9uRmluaXNoXSAtIENhbGxiYWNrIG9uIGZpbmlzaFxuICogQHBhcmFtIHtOdW1iZXJ9IFtwYXJhbXMuc3RlcF0gLSBBbW91bnQgc3ViYmVkL2FkZGVkIG9uIGFycm93RG93bi9hcnJvd1VwIHByZXNzIGluc2lkZSB0aGUgaW5wdXRcbiAqIEBwYXJhbSB7TnVtYmVyfSBbcGFyYW1zLmRwXSAtIERlY2ltYWwgcGxhY2VzIGRpc3BsYXllZFxuICogQHJldHVybnMge1BhbmVsfVxuICovXG5cblBhbmVsLnByb3RvdHlwZS5hZGRTbGlkZXIgPSBmdW5jdGlvbiAob2JqZWN0LCB2YWx1ZSwgcmFuZ2UsIHBhcmFtcykge1xuICAgIHJldHVybiB0aGlzLl9hZGRDb21wb25lbnQoU2xpZGVyLG9iamVjdCx2YWx1ZSxyYW5nZSxwYXJhbXMpO1xufTtcblxuLyoqXG4gKiBBZGRzIGEgbmV3IEZ1bmN0aW9uUGxvdHRlciB0byBsYXN0IGFkZGVkIFN1Ykdyb3VwLlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3RcbiAqIEBwYXJhbSB7U3RyaW5nfSB2YWx1ZSAtIFRoZSBwcm9wZXJ0eSBrZXkgLSBmKHgpLCBmKHgseSlcbiAqIEBwYXJhbSB7T2JqZWN0fSBbcGFyYW1zXSAtIENvbXBvbmVudCBvcHRpb25zXG4gKiBAcGFyYW0ge1N0cmluZ30gW3BhcmFtcy5sYWJlbD12YWx1ZV0gLSBGdW5jdGlvblBsb3R0ZXIgbGFiZWxcbiAqIEByZXR1cm5zIHtQYW5lbH1cbiAqL1xuXG5QYW5lbC5wcm90b3R5cGUuYWRkRnVuY3Rpb25QbG90dGVyID0gZnVuY3Rpb24gKG9iamVjdCwgdmFsdWUsIHBhcmFtcykge1xuICAgIHJldHVybiB0aGlzLl9hZGRDb21wb25lbnQoRnVuY3Rpb25QbG90dGVyLG9iamVjdCx2YWx1ZSxwYXJhbXMpO1xufTtcblxuLyoqXG4gKiBBZGRzIGEgbmV3IFhZLVBhZCB0byBsYXN0IGFkZGVkIFN1Ykdyb3VwLlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3RcbiAqIEBwYXJhbSB7U3RyaW5nfSB2YWx1ZSAtIFRoZSBwcm9wZXJ0eSBrZXlcbiAqIEBwYXJhbSB7T2JqZWN0fSBbcGFyYW1zXSAtIENvbXBvbmVudCBvcHRpb25zXG4gKiBAcGFyYW0ge1N0cmluZ30gW3BhcmFtcy5sYWJlbD12YWx1ZV0gLSBQYWQgbGFiZWxcbiAqIEByZXR1cm5zIHtQYW5lbH1cbiAqL1xuXG5QYW5lbC5wcm90b3R5cGUuYWRkUGFkID0gZnVuY3Rpb24gKG9iamVjdCwgdmFsdWUsIHBhcmFtcykge1xuICAgIHJldHVybiB0aGlzLl9hZGRDb21wb25lbnQoUGFkLG9iamVjdCx2YWx1ZSxwYXJhbXMpO1xufTtcblxuLyoqXG4gKiBBZGRzIGEgbmV3IFZhbHVlUGxvdHRlciB0byBsYXN0IGFkZGVkIFN1Ykdyb3VwLlxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCAtIFRoZSBvYmplY3RcbiAqIEBwYXJhbSB7U3RyaW5nfSB2YWx1ZSAtIFRoZSBwcm9wZXJ0eSBrZXlcbiAqIEBwYXJhbSB7T2JqZWN0fSBbcGFyYW1zXSAtIENvbXBvbmVudCBvcHRpb25zXG4gKiBAcGFyYW0ge1N0cmluZ30gW3BhcmFtcy5sYWJlbD12YWx1ZV0gLSBQbG90dGVyIGxhYmVsXG4gKiBAcGFyYW0ge051bWJlcn0gW3BhcmFtcy5oZWlnaHRdIC0gUGxvdHRlciBoZWlnaHRcbiAqIEBwYXJhbSB7TnVtYmVyfSBbcGFyYW1zLnJlc29sdXRpb25dIC0gR3JhcGggcmVzb2x1dGlvblxuICogQHJldHVybnMge1BhbmVsfVxuICovXG5cblBhbmVsLnByb3RvdHlwZS5hZGRWYWx1ZVBsb3R0ZXIgPSBmdW5jdGlvbiAob2JqZWN0LCB2YWx1ZSwgcGFyYW1zKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkZENvbXBvbmVudChWYWx1ZVBsb3R0ZXIsb2JqZWN0LHZhbHVlLHBhcmFtcyk7XG59O1xuXG4vKipcbiAqIEFkZHMgYSBuZXcgTnVtYmVyT3V0cHV0IHRvIGxhc3QgYWRkZWQgU3ViR3JvdXAuXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IC0gVGhlIG9iamVjdFxuICogQHBhcmFtIHtTdHJpbmd9IHZhbHVlIC0gVGhlIHByb3BlcnR5IGtleVxuICogQHBhcmFtIHtPYmplY3R9IFtwYXJhbXNdIC0gQ29tcG9uZW50IG9wdGlvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfSBbcGFyYW1zLmxhYmVsPXZhbHVlXSAtIE91dHB1dCBsYWJlbFxuICogQHBhcmFtIHtOdW1iZXJ9IFtwYXJhbXMuZHBdIC0gRGVjaW1hbCBwbGFjZXMgZGlzcGxheWVkXG4gKiBAcmV0dXJucyB7UGFuZWx9XG4gKi9cblxuUGFuZWwucHJvdG90eXBlLmFkZE51bWJlck91dHB1dCA9IGZ1bmN0aW9uIChvYmplY3QsIHZhbHVlLCBwYXJhbXMpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRkQ29tcG9uZW50KE51bWJlck91dHB1dCxvYmplY3QsdmFsdWUscGFyYW1zKTtcbn07XG5cbi8qKlxuICogQWRkcyBhIG5ldyBTdHJpbmdPdXRwdXQgdG8gbGFzdCBhZGRlZCBTdWJHcm91cC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgLSBUaGUgb2JqZWN0XG4gKiBAcGFyYW0ge1N0cmluZ30gdmFsdWUgLSBUaGUgcHJvcGVydHkga2V5XG4gKiBAcGFyYW0ge09iamVjdH0gW3BhcmFtc10gLSBDb21wb25lbnQgb3B0aW9uc1xuICogQHBhcmFtIHtTdHJpbmd9IFtwYXJhbXMubGFiZWw9dmFsdWVdIC0gT3V0cHV0IGxhYmVsXG4gKiBAcmV0dXJucyB7UGFuZWx9XG4gKi9cblxuUGFuZWwucHJvdG90eXBlLmFkZFN0cmluZ091dHB1dCA9IGZ1bmN0aW9uIChvYmplY3QsIHZhbHVlLCBwYXJhbXMpIHtcbiAgICByZXR1cm4gdGhpcy5fYWRkQ29tcG9uZW50KFN0cmluZ091dHB1dCxvYmplY3QsdmFsdWUscGFyYW1zKTtcbn07XG5cblBhbmVsLnByb3RvdHlwZS5hZGRDYW52YXMgPSBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgcmV0dXJuIHRoaXMuX2FkZENvbXBvbmVudChDYW52YXNfLHBhcmFtcyk7XG59O1xuXG5QYW5lbC5wcm90b3R5cGUuYWRkU1ZHID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgIHJldHVybiB0aGlzLl9hZGRDb21wb25lbnQoU1ZHXyxwYXJhbXMpO1xufTtcblxuUGFuZWwucHJvdG90eXBlLnNldERhdGEgPSBmdW5jdGlvbihkYXRhKXtcbiAgICB2YXIgZ3JvdXBzID0gdGhpcy5fZ3JvdXBzLFxuICAgICAgICBpID0gLTEsIGwgPSBncm91cHMubGVuZ3RoO1xuICAgIHdoaWxlKCsraSA8IGwpe1xuICAgICAgICBncm91cHNbaV0uc2V0RGF0YShkYXRhW2ldKTtcbiAgICB9XG59O1xuXG5QYW5lbC5wcm90b3R5cGUuZ2V0RGF0YSA9IGZ1bmN0aW9uKCl7XG4gICAgdmFyIGdyb3VwcyA9IHRoaXMuX2dyb3VwcyxcbiAgICAgICAgaSA9IC0xLCBsID0gZ3JvdXBzLmxlbmd0aDtcbiAgICB2YXIgZGF0YSA9IFtdO1xuICAgIHdoaWxlKCsraSAgPCBsKXtcbiAgICAgICAgZGF0YS5wdXNoKGdyb3Vwc1tpXS5nZXREYXRhKCkpO1xuICAgIH1cbiAgICByZXR1cm4gZGF0YTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gUGFuZWw7IiwidmFyIFBhbmVsRXZlbnQgPSB7XG5cdFBBTkVMX01PVkVfQkVHSU4gICAgICAgICAgOiAncGFuZWxNb3ZlQmVnaW4nLFxuXHRQQU5FTF9NT1ZFICAgICAgICAgICAgICAgIDogJ3BhbmVsTW92ZScsXG5cdFBBTkVMX01PVkVfRU5EICAgICAgICAgICAgOiAncGFuZWxNb3ZlRW5kJyxcblxuXHRQQU5FTF9TSE9XICAgICAgICAgICAgICAgIDogJ3BhbmVsU2hvdycsXG5cdFBBTkVMX0hJREUgICAgICAgICAgICAgICAgOiAncGFuZWxIaWRlJyxcblxuXHRQQU5FTF9TQ1JPTExfV1JBUF9BRERFRCAgIDogJ3BhbmVsU2Nyb2xsV3JhcEFkZGVkJyxcblx0UEFORUxfU0NST0xMX1dSQVBfUkVNT1ZFRCA6ICdwYW5lbFNjcm9sbFdyYXBSZW1vdmVkJyxcblxuXHRQQU5FTF9TSVpFX0NIQU5HRSAgICAgICAgOiAncGFuZWxTaXplQ2hhbmdlJ1xufTtcbm1vZHVsZS5leHBvcnRzID0gUGFuZWxFdmVudDsiLCJ2YXIgQWJzdHJhY3RHcm91cCA9IHJlcXVpcmUoJy4vQWJzdHJhY3RHcm91cCcpO1xudmFyIE5vZGUgPSByZXF1aXJlKCcuLi9jb3JlL2RvY3VtZW50L05vZGUnKTtcbnZhciBDU1MgID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9DU1MnKTtcblxudmFyIEV2ZW50XyAgICAgICAgID0gcmVxdWlyZSgnLi4vY29yZS9ldmVudC9FdmVudCcpLFxuICAgIERvY3VtZW50RXZlbnQgID0gcmVxdWlyZSgnLi4vY29yZS9kb2N1bWVudC9Eb2N1bWVudEV2ZW50JyksXG4gICAgUGFuZWxFdmVudCAgICAgPSByZXF1aXJlKCcuL1BhbmVsRXZlbnQnKSxcbiAgICBHcm91cEV2ZW50ICAgICA9IHJlcXVpcmUoJy4vR3JvdXBFdmVudCcpLFxuICAgIENvbXBvbmVudEV2ZW50ID0gcmVxdWlyZSgnLi4vY29yZS9Db21wb25lbnRFdmVudCcpO1xuXG5mdW5jdGlvbiBTdWJHcm91cChwYXJlbnQscGFyYW1zKXtcbiAgICBwYXJhbXMgICAgICAgICAgICA9IHBhcmFtcyAgICAgICAgICB8fCB7fTtcbiAgICBwYXJhbXMubGFiZWwgICAgICA9IHBhcmFtcy5sYWJlbCAgICB8fCBudWxsO1xuICAgIHBhcmFtcy51c2VMYWJlbHMgID0gcGFyYW1zLnVzZUxhYmVscyAgPT09IHVuZGVmaW5lZCA/IHRydWUgOiBwYXJhbXMudXNlTGFiZWxzO1xuXG4gICAgQWJzdHJhY3RHcm91cC5hcHBseSh0aGlzLGFyZ3VtZW50cyk7XG5cbiAgICB2YXIgcm9vdE5vZGUgPSB0aGlzLl9ub2RlLFxuICAgICAgICB3cmFwTm9kZSA9IHRoaXMuX3dyYXBOb2RlLFxuICAgICAgICBsaXN0Tm9kZSA9IHRoaXMuX2xpc3ROb2RlO1xuXG4gICAgICAgIHJvb3ROb2RlLnNldFN0eWxlQ2xhc3MoQ1NTLlN1Ykdyb3VwKTtcbiAgICAgICAgd3JhcE5vZGUuc2V0U3R5bGVDbGFzcyhDU1MuV3JhcCk7XG5cbiAgICAgICAgd3JhcE5vZGUuYWRkQ2hpbGQobGlzdE5vZGUpO1xuICAgICAgICByb290Tm9kZS5hZGRDaGlsZCh3cmFwTm9kZSk7XG5cbiAgICB0aGlzLl91c2VMYWJlbHMgID0gcGFyYW1zLnVzZUxhYmVscztcblxuICAgIHZhciBsYWJlbCA9IHBhcmFtcy5sYWJlbDtcblxuICAgIGlmIChsYWJlbCAmJiBsYWJlbC5sZW5ndGggIT0gMCAmJiBsYWJlbCAhPSAnbm9uZScpIHtcbiAgICAgICAgdmFyIGhlYWROb2RlID0gdGhpcy5faGVhZE5vZGUgPSBuZXcgTm9kZSgpLFxuICAgICAgICAgICAgbGFibFdyYXAgPSBuZXcgTm9kZSgpLFxuICAgICAgICAgICAgbGFibE5vZGUgPSBuZXcgTm9kZShOb2RlLlNQQU4pO1xuXG4gICAgICAgIGhlYWROb2RlLnNldFN0eWxlQ2xhc3MoQ1NTLkhlYWQpO1xuICAgICAgICBsYWJsV3JhcC5zZXRTdHlsZUNsYXNzKENTUy5XcmFwKTtcbiAgICAgICAgbGFibE5vZGUuc2V0U3R5bGVDbGFzcyhDU1MuTGFiZWwpO1xuXG4gICAgICAgIGxhYmxOb2RlLnNldFByb3BlcnR5KCdpbm5lckhUTUwnLCBsYWJlbCk7XG5cbiAgICAgICAgbGFibFdyYXAuYWRkQ2hpbGQobGFibE5vZGUpO1xuICAgICAgICBoZWFkTm9kZS5hZGRDaGlsZChsYWJsV3JhcCk7XG5cblxuICAgICAgICB2YXIgaW5kaU5vZGUgPSB0aGlzLl9pbmRpTm9kZSA9IG5ldyBOb2RlKCk7XG4gICAgICAgIGluZGlOb2RlLnNldFN0eWxlQ2xhc3MoQ1NTLkFycm93QlN1Yk1heCk7XG4gICAgICAgIGhlYWROb2RlLmFkZENoaWxkQXQoaW5kaU5vZGUsIDApO1xuXG4gICAgICAgIHJvb3ROb2RlLmFkZENoaWxkQXQoaGVhZE5vZGUsIDApO1xuXG4gICAgICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcihHcm91cEV2ZW50LlNVQkdST1VQX1RSSUdHRVIsIHRoaXMuX3BhcmVudCwgJ29uU3ViR3JvdXBUcmlnZ2VyJyk7XG4gICAgICAgIGhlYWROb2RlLmFkZEV2ZW50TGlzdGVuZXIoRG9jdW1lbnRFdmVudC5NT1VTRV9ET1dOLCB0aGlzLl9vbkhlYWRNb3VzZURvd24uYmluZCh0aGlzKSk7XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlQXBwZWFyYW5jZSgpO1xuXG4gICAgfVxuXG4gICAgaWYodGhpcy5oYXNNYXhIZWlnaHQoKSl7XG4gICAgICAgIHRoaXMuYWRkU2Nyb2xsV3JhcCgpO1xuICAgIH1cblxuICAgIHRoaXMuX3BhcmVudC5hZGRFdmVudExpc3RlbmVyKEdyb3VwRXZlbnQuU1VCR1JPVVBfRU5BQkxFLCAgdGhpcywgJ29uRW5hYmxlJyk7XG4gICAgdGhpcy5fcGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoR3JvdXBFdmVudC5TVUJHUk9VUF9ESVNBQkxFLCB0aGlzLCAnb25EaXNhYmxlJyk7XG4gICAgdGhpcy5fcGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoUGFuZWxFdmVudC5QQU5FTF9NT1ZFX0VORCwgICB0aGlzLCAnb25QYW5lbE1vdmVFbmQnKTtcbiAgICB0aGlzLl9wYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcihHcm91cEV2ZW50LkdST1VQX1NJWkVfQ0hBTkdFLHRoaXMsICdvbkdyb3VwU2l6ZUNoYW5nZScpO1xuICAgIHRoaXMuX3BhcmVudC5hZGRFdmVudExpc3RlbmVyKFBhbmVsRXZlbnQuUEFORUxfU0laRV9DSEFOR0UsdGhpcywgJ29uUGFuZWxTaXplQ2hhbmdlJyk7XG4gICAgdGhpcy5fcGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoRG9jdW1lbnRFdmVudC5XSU5ET1dfUkVTSVpFLCAgICB0aGlzLCAnb25XaW5kb3dSZXNpemUnKTtcblxuICAgIHRoaXMuYWRkRXZlbnRMaXN0ZW5lcihHcm91cEV2ZW50LkdST1VQX1NJWkVfVVBEQVRFLHRoaXMuX3BhcmVudCwnb25Hcm91cFNpemVVcGRhdGUnKTtcbn1cblN1Ykdyb3VwLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoQWJzdHJhY3RHcm91cC5wcm90b3R5cGUpO1xuU3ViR3JvdXAucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gU3ViR3JvdXA7XG5cbi8vRklYTUVcblN1Ykdyb3VwLnByb3RvdHlwZS5fb25IZWFkTW91c2VEb3duID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuX2VuYWJsZWQgPSAhdGhpcy5fZW5hYmxlZDtcbiAgICB0aGlzLl9vblRyaWdnZXIoKTtcblxuICAgIHZhciBldmVudCA9IERvY3VtZW50RXZlbnQuTU9VU0VfVVAsXG4gICAgICAgIHNlbGYgID0gdGhpcztcbiAgICB2YXIgb25Eb2N1bWVudE1vdXNlVXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNlbGYuX29uVHJpZ2dlcigpO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBvbkRvY3VtZW50TW91c2VVcCk7XG4gICAgfTtcblxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsb25Eb2N1bWVudE1vdXNlVXApO1xufTtcblxuU3ViR3JvdXAucHJvdG90eXBlLl9vblRyaWdnZXIgPSBmdW5jdGlvbigpIHtcbiAgICB0aGlzLl91cGRhdGVBcHBlYXJhbmNlKCk7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcyxHcm91cEV2ZW50LlNVQkdST1VQX1RSSUdHRVIsbnVsbCkpO1xufTtcblxuXG5TdWJHcm91cC5wcm90b3R5cGUuX3VwZGF0ZUFwcGVhcmFuY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuaXNEaXNhYmxlZCgpKSB7XG4gICAgICAgIHRoaXMuX3dyYXBOb2RlLnNldEhlaWdodCgwKTtcbiAgICAgICAgaWYgKHRoaXMuaGFzTGFiZWwoKSkge1xuICAgICAgICAgICAgdGhpcy5faGVhZE5vZGUuc2V0U3R5bGVDbGFzcyhDU1MuSGVhZEluYWN0aXZlKTtcbiAgICAgICAgICAgIHRoaXMuX2luZGlOb2RlLnNldFN0eWxlQ2xhc3MoQ1NTLkFycm93QlN1Yk1pbik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIGlmICh0aGlzLmhhc01heEhlaWdodCgpKSB7XG4gICAgICAgICAgICB0aGlzLl93cmFwTm9kZS5zZXRIZWlnaHQodGhpcy5nZXRNYXhIZWlnaHQoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl93cmFwTm9kZS5kZWxldGVTdHlsZVByb3BlcnR5KCdoZWlnaHQnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5oYXNMYWJlbCgpKSB7XG4gICAgICAgICAgICB0aGlzLl9oZWFkTm9kZS5zZXRTdHlsZUNsYXNzKENTUy5IZWFkKTtcbiAgICAgICAgICAgIHRoaXMuX2luZGlOb2RlLnNldFN0eWxlQ2xhc3MoQ1NTLkFycm93QlN1Yk1heCk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG5TdWJHcm91cC5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmhhc01heEhlaWdodCgpKXtcbiAgICAgICAgdGhpcy5fc2Nyb2xsQmFyLnVwZGF0ZSgpO1xuICAgIH1cbn07XG5cblN1Ykdyb3VwLnByb3RvdHlwZS5vbkNvbXBvbmVudFNlbGVjdERyYWcgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5wcmV2ZW50U2VsZWN0RHJhZygpO1xufTtcblxuU3ViR3JvdXAucHJvdG90eXBlLm9uRW5hYmxlID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmlzRGlzYWJsZWQoKSl7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgQ29tcG9uZW50RXZlbnQuRU5BQkxFLCBudWxsKSk7XG59O1xuU3ViR3JvdXAucHJvdG90eXBlLm9uRGlzYWJsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5pc0Rpc2FibGVkKCkpe1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIENvbXBvbmVudEV2ZW50LkRJU0FCTEUsIG51bGwpKTtcbn07XG5cbi8vYnViYmxlXG5TdWJHcm91cC5wcm90b3R5cGUub25Hcm91cFNpemVDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KG5ldyBFdmVudF8odGhpcywgR3JvdXBFdmVudC5HUk9VUF9TSVpFX0NIQU5HRSwgbnVsbCkpO1xufTtcblN1Ykdyb3VwLnByb3RvdHlwZS5vbkdyb3VwU2l6ZVVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50Xyh0aGlzLCBHcm91cEV2ZW50LkdST1VQX1NJWkVfVVBEQVRFLCBudWxsKSk7XG59O1xuU3ViR3JvdXAucHJvdG90eXBlLm9uUGFuZWxNb3ZlRW5kID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuZGlzcGF0Y2hFdmVudChuZXcgRXZlbnRfKHRoaXMsIFBhbmVsRXZlbnQuUEFORUxfTU9WRV9FTkQsIG51bGwpKTtcbn07XG5TdWJHcm91cC5wcm90b3R5cGUub25QYW5lbFNpemVDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5fdXBkYXRlQXBwZWFyYW5jZSgpO1xufTtcblN1Ykdyb3VwLnByb3RvdHlwZS5vbldpbmRvd1Jlc2l6ZSA9IGZ1bmN0aW9uIChlKSB7XG4gICAgdGhpcy5kaXNwYXRjaEV2ZW50KGUpO1xufTtcblxuU3ViR3JvdXAucHJvdG90eXBlLmhhc0xhYmVsID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9oZWFkTm9kZSAhPSBudWxsO1xufTtcblN1Ykdyb3VwLnByb3RvdHlwZS5hZGRDb21wb25lbnROb2RlID0gZnVuY3Rpb24gKG5vZGUpIHtcbiAgICB0aGlzLl9saXN0Tm9kZS5hZGRDaGlsZChub2RlKTtcbn07XG5TdWJHcm91cC5wcm90b3R5cGUudXNlc0xhYmVscyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5fdXNlTGFiZWxzO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBTdWJHcm91cDsiXX0= diff --git a/node_modules/controlkit/bin/controlKit.min.js b/node_modules/controlkit/bin/controlKit.min.js deleted file mode 100644 index 976f6da..0000000 --- a/node_modules/controlkit/bin/controlKit.min.js +++ /dev/null @@ -1,10 +0,0 @@ -!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var o;"undefined"!=typeof window?o=window:"undefined"!=typeof global?o=global:"undefined"!=typeof self&&(o=self),o.ControlKit=e()}}(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o=countMax){count=0;self._canUpdate=true;clearInterval(interval)}count++},25)});this._shortcutEnable=DEFAULT_TRIGGER_SHORTCUT_CHAR;document.addEventListener("keydown",function(e){if(!(e.ctrlKey&&String.fromCharCode(e.which||e.keyCode).toLowerCase()==self._shortcutEnable)){return}self._enabled=!self._enabled;if(self._enabled){self._enable()}else{self._disable()}});if(!this._enabled){this._disable()}initiated=true}ControlKit.prototype=Object.create(EventDispatcher.prototype);ControlKit.prototype.constructor=ControlKit;ControlKit.prototype.addPanel=function(params){var panel=new Panel(this,params);this._panels.push(panel);return panel};ControlKit.prototype.update=function(){if(!this._enabled||!this._canUpdate){return}var i,j,k;var l,m,n;var panels=this._panels,panel,groups,components,component;i=-1;l=panels.length;while(++i2||funcArgLength==0){throw new FunctionPlotterFunctionArgsError}var svgRoot=this._svgRoot,path=this._path;var axes=this._axes=svgRoot.insertBefore(this._createSVGObject("path"),path);axes.style.strokeWidth=1;var axesLabels=this._axesLabels=svgRoot.insertBefore(this._createSVGObject("path"),path);axesLabels.style.stroke="rgb(43,48,51)";axesLabels.style.strokeWidth=1;var grid=this._grid;var svg=this._svg,size=Number(svg.getAttribute("width"));var sliderXWrap=new Node;sliderXWrap.setStyleClass(CSS.GraphSliderXWrap);var sliderYWrap=new Node;sliderYWrap.setStyleClass(CSS.GraphSliderYWrap);var sliderXTrack=this._sliderXTrack=new Node;sliderXTrack.setStyleClass(CSS.GraphSliderX);var sliderYTrack=this._sliderYTrack=new Node;sliderYTrack.setStyleClass(CSS.GraphSliderY);var sliderXHandle=this._sliderXHandle=new Node;sliderXHandle.setStyleClass(CSS.GraphSliderXHandle);var sliderYHandle=this._sliderYHandle=new Node;sliderYHandle.setStyleClass(CSS.GraphSliderYHandle);sliderXTrack.addChild(sliderXHandle);sliderYTrack.addChild(sliderYHandle);sliderXWrap.addChild(sliderXTrack);sliderYWrap.addChild(sliderYTrack);var wrapNode=this._wrapNode;var plotMode=this._plotMode=funcArgLength==1?FunctionPlotType.NON_IMPLICIT:FunctionPlotType.IMPLICIT;if(plotMode==FunctionPlotType.IMPLICIT){var canvas=this._canvas=document.createElement("canvas");canvas.style.width=canvas.style.height=size+"px";canvas.width=canvas.height=size;wrapNode.getElement().insertBefore(canvas,svg);this._canvasContext=canvas.getContext("2d");this._canvasImageData=this._canvasContext.getImageData(0,0,size,size);axes.style.stroke=DEFAULT_FUNCTION_PLOTTER_IMPLICIT_AXES_COLOR;grid.style.stroke=DEFAULT_FUNCTION_PLOTTER_IMPLICIT_GRID_COLOR}else{axes.style.stroke=DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_AXES_COLOR;grid.style.stroke=DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_GRID_COLOR}wrapNode.addChild(sliderXWrap);wrapNode.addChild(sliderYWrap);sliderXHandle.addEventListener(NodeEvent.MOUSE_DOWN,this._onSliderXHandleDown.bind(this));sliderYHandle.addEventListener(NodeEvent.MOUSE_DOWN,this._onSliderYHandleDown.bind(this));var units=this._units=[null,null];this._scale=null;if(plotMode==FunctionPlotType.NON_IMPLICIT){units[0]=DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_UNIT_X;units[1]=DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_UNIT_Y;this._scale=DEFAULT_FUNCTION_PLOTTER_NON_IMPLICIT_SCALE}else if(plotMode==FunctionPlotType.IMPLICIT){units[0]=DEFAULT_FUNCTION_PLOTTER_IMPLICIT_UNIT_X;units[1]=DEFAULT_FUNCTION_PLOTTER_IMPLICIT_UNIT_Y;this._scale=DEFAULT_FUNCTION_PLOTTER_IMPLICIT_SCALE}this._unitsMinMax=[DEFAULT_FUNCTION_PLOTTER_UNIT_MIN,DEFAULT_FUNCTION_PLOTTER_UNIT_MAX];this._scaleMinMax=[DEFAULT_FUNCTION_PLOTTER_SCALE_MIN,DEFAULT_FUNCTION_PLOTTER_SCALE_MAX];this._center=[Math.round(size*.5),Math.round(size*.5)];this._svgPos=[0,0];this._func=null;this.setFunction(this._obj[this._key]);this._sliderXHandleUpdate();this._sliderYHandleUpdate();svg.addEventListener(DocumentEvent.MOUSE_DOWN,this._onDragStart.bind(this),false);this._wrapNode.getElement().addEventListener("mousewheel",this._onScale.bind(this,false));ObjectComponentNotifier.get().addEventListener(ComponentEvent.UPDATE_VALUE,this,"onValueUpdate")}FunctionPlotter.prototype=Object.create(Plotter.prototype);FunctionPlotter.prototype.constructor=FunctionPlotter;FunctionPlotter.prototype._updateCenter=function(){var svg=this._svg,width=Number(svg.getAttribute("width")),height=Number(svg.getAttribute("height"));var mousePos=Mouse.get().getPosition(),svgPos=this._svgPos,center=this._center;center[0]=Math.max(0,Math.min(mousePos[0]-svgPos[0],width));center[1]=Math.max(0,Math.min(mousePos[1]-svgPos[1],height));this._plotGraph()};FunctionPlotter.prototype._onDragStart=function(e){var svgPos=this._svgPos;svgPos[0]=0;svgPos[1]=0;var element=this._svg.parentNode;while(element){svgPos[0]+=element.offsetLeft;svgPos[1]+=element.offsetTop;element=element.offsetParent}var eventMove=DocumentEvent.MOUSE_MOVE,eventUp=DocumentEvent.MOUSE_UP;var onDrag=this._updateCenter.bind(this),onDragEnd=function(){this._updateCenter.bind(this);document.removeEventListener(eventMove,onDrag,false);document.removeEventListener(eventUp,onDragEnd,false)}.bind(this);document.addEventListener(eventMove,onDrag,false);document.addEventListener(eventUp,onDragEnd,false);this._updateCenter()};FunctionPlotter.prototype._onScale=function(e){e=window.event||e;this._scale+=Math.max(-1,Math.min(1,e.wheelDelta||-e.detail))*-1;var scaleMinMax=this._scaleMinMax;this._scale=Math.max(scaleMinMax[0],Math.min(this._scale,scaleMinMax[1]));this._plotGraph();e.preventDefault()};FunctionPlotter.prototype.onValueUpdate=function(){this.setFunction(this._obj[this._key])};FunctionPlotter.prototype._redraw=function(){if(this._plotMode==FunctionPlotType.IMPLICIT){var size=this._wrapNode.getWidth(),canvas=this._canvas;canvas.style.width=canvas.style.height=size+"px";canvas.width=canvas.height=size;this._canvasImageData=this._canvasContext.getImageData(0,0,size,size)}this._sliderXHandleUpdate();this._sliderYHandleUpdate();this.setFunction(this._obj[this._key])};FunctionPlotter.prototype.setFunction=function(func){this._func=func.bind(this._obj);this._plotGraph()};FunctionPlotter.prototype._plotGraph=function(){this._drawGrid();this._drawAxes();this._drawPlot()};FunctionPlotter.prototype._drawAxes=function(){var svg=this._svg,svgWidth=Number(svg.getAttribute("width")),svgHeight=Number(svg.getAttribute("height"));var center=this._center,centerX=center[0],centerY=center[1];var pathCmd="";pathCmd+=this._pathCmdLine(0,centerY,svgWidth,centerY);pathCmd+=this._pathCmdLine(centerX,0,centerX,svgHeight);this._axes.setAttribute("d",pathCmd)};FunctionPlotter.prototype._drawPlot=function(){var width,height;var center=this._center,centerX=center[0],centerY=center[1];var units=this._units,unitX,unitY;var scale=this._scale;var normval,scaledVal,value,index;var offsetX,offsetY;var i;if(this._plotMode==FunctionPlotType.NON_IMPLICIT){var svg=this._svg;width=Number(svg.getAttribute("width"));height=Number(svg.getAttribute("height"));unitX=units[0]*scale;unitY=height/(units[1]*scale);offsetX=centerX/width;var len=Math.floor(width),points=new Array(len*2);i=-1;while(++ilabelTickSize){pathCmdAxesLabels+=this._pathCmdLine(labelTickPaddingRight,temp,labelTickPaddingRightOffset,temp)}}i=-1;while(++ilabelTickSize){pathCmdAxesLabels+=this._pathCmdLine(temp,labelTickPaddingBottom,temp,labelTickPaddingBottomOffset)}}i=-1;while(++iindexDecimalMark&&start=length){e.preventDefault()}};NumberInput_Internal.prototype.getValue=function(){return this._value};NumberInput_Internal.prototype.setValue=function(n){this._setValue(n)};NumberInput_Internal.prototype.getNode=function(){return this._input};module.exports=NumberInput_Internal},{"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/EventDispatcher":49}],15:[function(require,module,exports){var Output=require("./Output");var DEFAULT_OUTPUT_DP=2;function NumberOutput(parent,object,value,params){params=params||{};params.dp=params.dp||DEFAULT_OUTPUT_DP;Output.apply(this,arguments);this._valueDp=params.dp+1}NumberOutput.prototype=Object.create(Output.prototype);NumberOutput.prototype.constructor=NumberOutput;NumberOutput.prototype._setValue=function(){if(this._parent.isDisabled()){return}var value=this._obj[this._key],textArea=this._textArea,dp=this._valueDp;var index,out;if(typeof value==="object"&&typeof value.length==="number"&&typeof value.splice==="function"&&!value.propertyIsEnumerable("length")){out=value.slice();var i=-1;var temp;var wrap=this._wrap;while(++i0){out[i]=temp.slice(0,index+dp)}}if(wrap){textArea.setStyleProperty("white-space","nowrap");out=out.join("\n")}textArea.setProperty("value",out)}else{out=value.toString();index=out.indexOf(".");textArea.setProperty("value",index>0?out.slice(0,index+dp):out)}};module.exports=NumberOutput},{"./Output":17}],16:[function(require,module,exports){var Node=require("../core/document/Node");var DocumentEvent=require("../core/document/DocumentEvent"),NodeEvent=require("../core/document/NodeEvent");var CSS=require("../core/document/CSS");var ColorMode=require("../core/color/ColorMode");var ColorUtil=require("../core/color/ColorUtil");var Metric=require("./Metric");function Options(parentNode){this._parenNode=parentNode;var node=this._node=new Node;var listNode=this._listNode=new Node(Node.LIST);node.setStyleClass(CSS.Options);node.addChild(listNode);this._selectedIndex=null;this._callbackOut=function(){};this._unfocusable=false;document.addEventListener(DocumentEvent.MOUSE_DOWN,this._onDocumentMouseDown.bind(this));document.addEventListener(DocumentEvent.MOUSE_UP,this._onDocumentMouseUp.bind(this));this.clear()}Options.prototype={_onDocumentMouseDown:function(){if(!this._unfocusable)return;this._callbackOut()},_onDocumentMouseUp:function(){this._unfocusable=true},build:function(entries,selected,element,callbackSelect,callbackOut,paddingRight,areColors,colorMode){this._clearList();this._parenNode.addChild(this.getNode());var rootNode=this._node,listNode=this._listNode;paddingRight=paddingRight||0;var self=this;var itemNode,entry;var i=-1;if(areColors){colorMode=colorMode||ColorMode.HEX;listNode.setStyleClass(CSS.Color);var color,nodeColor;while(++iwindowWidth?posX-width+elementWidth-strokeOffset:posX,rootPosY=posY+listHeight>windowHeight?posY-listHeight*.5-elementHeight*.5:posY;listNode.setWidth(width);rootNode.setPositionGlobal(rootPosX,rootPosY);this._callbackOut=callbackOut;this._unfocusable=false},_clearList:function(){this._listNode.removeAllChildren();this._listNode.deleteStyleProperty("width");this._selectedIndex=null;this._build=false},clear:function(){this._clearList();this._callbackOut=function(){};this._parenNode.removeChild(this.getNode())},isBuild:function(){return this._build},getNode:function(){return this._node},getSelectedIndex:function(){return this._selectedIndex}};Options.setup=function(parentNode){return Options._instance=new Options(parentNode)};Options.get=function(){return Options._instance};Options.destroy=function(){Options._instance=null};module.exports=Options},{"../core/color/ColorMode":40,"../core/color/ColorUtil":41,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Node":45,"../core/document/NodeEvent":46,"./Metric":12}],17:[function(require,module,exports){var ObjectComponent=require("../core/ObjectComponent");var Node=require("../core/document/Node");var CSS=require("../core/document/CSS");var Metric=require("./Metric");var ScrollBar=require("../core/layout/ScrollBar");var Event_=require("../core/event/Event"),DocumentEvent=require("../core/document/DocumentEvent"),NodeEvent=require("../core/document/NodeEvent"),ComponentEvent=require("../core/ComponentEvent");var DEFAULT_HEIGHT=null,DEFAULT_WRAP=false,DEFAULT_UPDATE=true;function Output(parent,object,value,params){ObjectComponent.apply(this,arguments);params=params||{};params.height=params.height||DEFAULT_HEIGHT;params.wrap=params.wrap===undefined?DEFAULT_WRAP:params.wrap;params.update=params.update===undefined?DEFAULT_UPDATE:params.update;this._wrap=params.wrap;this._update=params.update;var textArea=this._textArea=new Node(Node.TEXTAREA),wrap=this._wrapNode,root=this._node;textArea.setProperty("readOnly",true);wrap.addChild(textArea);textArea.addEventListener(NodeEvent.MOUSE_DOWN,this._onInputDragStart.bind(this));this.addEventListener(ComponentEvent.INPUT_SELECT_DRAG,this._parent,"onComponentSelectDrag");if(params.height){var textAreaWrap=new Node;textAreaWrap.setStyleClass(CSS.TextAreaWrap);textAreaWrap.addChild(textArea);wrap.addChild(textAreaWrap);var height=this._height=params.height,padding=4;textArea.setHeight(Math.max(height+padding,Metric.COMPONENT_MIN_HEIGHT));wrap.setHeight(textArea.getHeight());root.setHeight(wrap.getHeight()+padding);this._scrollBar=new ScrollBar(textAreaWrap,textArea,height-padding)}if(params.wrap){textArea.setStyleProperty("white-space","pre-wrap")}this._prevString="";this._prevScrollHeight=-1;this._setValue()}Output.prototype=Object.create(ObjectComponent.prototype);Output.prototype.constructor=Output;Output.prototype._setValue=function(){};Output.prototype.onValueUpdate=function(){this._setValue()};Output.prototype.update=function(){if(!this._update){return}this._setValue()};Output.prototype._onDrag=function(){this.dispatchEvent(new Event_(this,ComponentEvent.INPUT_SELECT_DRAG,null))};Output.prototype._onDragFinish=function(){this.dispatchEvent(new Event_(this,ComponentEvent.INPUT_SELECT_DRAG,null));document.removeEventListener(DocumentEvent.MOUSE_MOVE,this._onDrag,false);document.removeEventListener(DocumentEvent.MOUSE_MOVE,this._onDragFinish,false)};Output.prototype._onInputDragStart=function(){this.dispatchEvent(new Event_(this,ComponentEvent.INPUT_SELECT_DRAG,null));document.addEventListener(DocumentEvent.MOUSE_MOVE,this._onDrag.bind(this),false);document.addEventListener(DocumentEvent.MOUSE_UP,this._onDragFinish.bind(this),false)};module.exports=Output},{"../core/ComponentEvent":31,"../core/ObjectComponent":35,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48,"../core/layout/ScrollBar":51,"./Metric":12}],18:[function(require,module,exports){var Plotter=require("./Plotter");var Mouse=require("../core/document/Mouse");var Event_=require("../core/event/Event"),DocumentEvent=require("../core/document/DocumentEvent"),ComponentEvent=require("../core/ComponentEvent");var DEFAULT_BOUNDS_X=[-1,1],DEFAULT_BOUNDS_Y=[-1,1],DEFAULT_LABEL_X="",DEFAULT_LABEL_Y="";function Pad(parent,object,value,params){Plotter.apply(this,arguments);params=params||{};params.boundsX=params.boundsX||DEFAULT_BOUNDS_X;params.boundsY=params.boundsY||DEFAULT_BOUNDS_Y;params.labelX=params.labelX||DEFAULT_LABEL_X;params.labelY=params.labelY||DEFAULT_LABEL_Y;params.showCross=params.showCross||true;this._onChange=params.onChange||this._onChange;this._onFinish=params.onFinish||function(){};this._boundsX=params.boundsX;this._boundsY=params.boundsY;this._labelAxisX=params.labelX!=""&¶ms.labelX!="none"?params.labelX:null;this._labelAxisY=params.labelY!=""&¶ms.labelY!="none"?params.labelY:null;var path=this._path;path.style.strokeWidth=1;path.style.stroke="#363c40";this._grid.style.stroke="rgb(25,25,25)";this._svgPos=[0,0];var handle=this._handle=this._svgRoot.appendChild(this._createSVGObject("g"));var handleCircle0=handle.appendChild(this._createSVGObject("circle"));handleCircle0.setAttribute("r",String(11));handleCircle0.setAttribute("fill","rgba(0,0,0,0.05)");var handleCircle1=handle.appendChild(this._createSVGObject("circle"));handleCircle1.setAttribute("r",String(10));handleCircle1.setAttribute("fill","rgb(83,93,98)");var handleCircle2=handle.appendChild(this._createSVGObject("circle"));handleCircle2.setAttribute("r",String(9));handleCircle2.setAttribute("fill","rgb(57,69,76)");handleCircle2.setAttribute("cy",String(.75));var handleCircle3=handle.appendChild(this._createSVGObject("circle"));handleCircle3.setAttribute("r",String(10));handleCircle3.setAttribute("stroke","rgb(17,19,20)");handleCircle3.setAttribute("stroke-width",String(1));handleCircle3.setAttribute("fill","none");var handleCircle4=handle.appendChild(this._createSVGObject("circle"));handleCircle4.setAttribute("r",String(6));handleCircle4.setAttribute("fill","rgb(30,34,36)");var handleCircle5=handle.appendChild(this._createSVGObject("circle"));handleCircle5.setAttribute("r",String(3));handleCircle5.setAttribute("fill","rgb(255,255,255)");handle.setAttribute("tranform","translate(0 0)");this._svg.addEventListener(DocumentEvent.MOUSE_DOWN,this._onDragStart.bind(this),false);this._drawValue(this._obj[this._key])}Pad.prototype=Object.create(Plotter.prototype);Pad.prototype.constructor=Pad;Pad.prototype._onDragStart=function(){var svgPos=this._svgPos;svgPos[0]=0;svgPos[1]=0;var element=this._svg.parentNode;while(element){svgPos[0]+=element.offsetLeft;svgPos[1]+=element.offsetTop;element=element.offsetParent}var eventMove=DocumentEvent.MOUSE_MOVE,eventUp=DocumentEvent.MOUSE_UP;var onDrag=function(){this._drawValueInput();this.applyValue();this._onChange()}.bind(this);var onDragEnd=function(){this.pushHistoryState();this._drawValueInput();this.applyValue();this._onFinish();document.removeEventListener(eventMove,onDrag,false);document.removeEventListener(eventUp,onDragEnd,false)}.bind(this);document.addEventListener(eventMove,onDrag,false);document.addEventListener(eventUp,onDragEnd,false);this._drawValueInput();this.applyValue();this._onChange()};Pad.prototype._redraw=function(){this._drawValue(this._obj[this._key])};Pad.prototype._drawValueInput=function(){this._drawValue(this._getMouseNormalized())};Pad.prototype._drawValue=function(value){this._obj[this._key]=value;this._drawGrid();this._drawPoint()};Pad.prototype._drawGrid=function(){var svgSize=Number(this._svg.getAttribute("width")),svgMidX=Math.floor(svgSize*.5),svgMidY=Math.floor(svgSize*.5);var pathCmd="";pathCmd+=this._pathCmdLine(0,svgMidY,svgSize,svgMidY);pathCmd+=this._pathCmdLine(svgMidX,0,svgMidX,svgSize);this._grid.setAttribute("d",pathCmd)};Pad.prototype._drawPoint=function(){var svgSize=Number(this._svg.getAttribute("width"));var value=this._obj[this._key];var localX=(.5+value[0]*.5)*svgSize,localY=(.5+-value[1]*.5)*svgSize;var pathCmd="";pathCmd+=this._pathCmdLine(0,localY,svgSize,localY);pathCmd+=this._pathCmdLine(localX,0,localX,svgSize);this._path.setAttribute("d",pathCmd);this._handle.setAttribute("transform","translate("+localX+" "+localY+")")};Pad.prototype._getMouseNormalized=function(){var offset=this._svgPos,mouse=Mouse.get().getPosition(),svgSize=Number(this._svg.getAttribute("width"));return[-1+Math.max(0,Math.min(mouse[0]-offset[0],svgSize))/svgSize*2,1-Math.max(0,Math.min(mouse[1]-offset[1],svgSize))/svgSize*2]};Pad.prototype.applyValue=function(){this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED,null))};Pad.prototype.onValueUpdate=function(e){if(e.data.origin==this)return;this._drawValue(this._obj[this._key])};module.exports=Pad},{"../core/ComponentEvent":31,"../core/document/DocumentEvent":43,"../core/document/Mouse":44,"../core/event/Event":48,"./Plotter":20}],19:[function(require,module,exports){var Node=require("../core/document/Node");var CSS=require("../core/document/CSS");var NumberInput_Internal=require("./NumberInput_Internal");var Mouse=require("../core/document/Mouse");var ColorUtil=require("../core/color/ColorUtil");var DocumentEvent=require("../core/document/DocumentEvent"),NodeEvent=require("../core/document/NodeEvent");var DEFAULT_VALUE_HUE=200,DEFAULT_VALUE_SAT=50,DEFAULT_VALUE_VAL=50;function Picker(parentNode){var root=this._node=(new Node).setStyleClass(CSS.Picker),head=this._headNode=(new Node).setStyleClass(CSS.Head),labelWrap=(new Node).setStyleClass(CSS.Wrap),label=(new Node).setStyleClass(CSS.Label),menu=(new Node).setStyleClass(CSS.Menu),menuWrap=(new Node).setStyleClass(CSS.Wrap);var menuClose=new Node(Node.INPUT_BUTTON);menuClose.setStyleClass(CSS.ButtonMenuClose);var fieldWrap=(new Node).setStyleClass(CSS.PickerFieldWrap),sliderWrap=(new Node).setStyleClass(CSS.SliderWrap),inputWrap=(new Node).setStyleClass(CSS.PickerInputWrap);var canvasField=this._canvasField=document.createElement("canvas"),canvasSlider=this._canvasSlider=document.createElement("Canvas");fieldWrap.getElement().appendChild(canvasField);sliderWrap.getElement().appendChild(canvasSlider);this._setSizeCanvasField(154,154);this._setSizeCanvasSlider(14,154);var contextCanvasField=this._contextCanvasField=canvasField.getContext("2d"),contextCanvasSlider=this._contextCanvasSlider=canvasSlider.getContext("2d");var handleField=this._handleField=new Node;handleField.setStyleClass(CSS.PickerHandleField);var handleSlider=this._handleSlider=new Node;handleSlider.setStyleClass(CSS.PickerHandleSlider);var step=1,dp=0;var callbackHue=this._onInputHueChange.bind(this),callbackSat=this._onInputSatChange.bind(this),callbackVal=this._onInputValChange.bind(this),callbackR=this._onInputRChange.bind(this),callbackG=this._onInputGChange.bind(this),callbackB=this._onInputBChange.bind(this);var inputHue=this._inputHue=new NumberInput_Internal(step,dp,null,callbackHue),inputSat=this._inputSat=new NumberInput_Internal(step,dp,null,callbackSat),inputVal=this._inputVal=new NumberInput_Internal(step,dp,null,callbackVal),inputR=this._inputR=new NumberInput_Internal(step,dp,null,callbackR),inputG=this._inputG=new NumberInput_Internal(step,dp,null,callbackG),inputB=this._inputB=new NumberInput_Internal(step,dp,null,callbackB);var controlsWrap=(new Node).setStyleClass(CSS.PickerControlsWrap);var buttonPick=new Node(Node.INPUT_BUTTON).setStyleClass(CSS.Button).setProperty("value","pick"),buttonCancel=new Node(Node.INPUT_BUTTON).setStyleClass(CSS.Button).setProperty("value","cancel");var colorContrast=(new Node).setStyleClass(CSS.PickerColorContrast);var color0=this._colorCurrNode=new Node,color1=this._colorPrevNode=new Node;colorContrast.addChild(color0);colorContrast.addChild(color1);controlsWrap.addChild(buttonCancel);controlsWrap.addChild(buttonPick);controlsWrap.addChild(colorContrast);this._setContrasPrevColor(0,0,0);var inputFieldWrapHue=(new Node).setStyleClass(CSS.PickerInputField),inputFieldWrapSat=(new Node).setStyleClass(CSS.PickerInputField),inputFieldWrapVal=(new Node).setStyleClass(CSS.PickerInputField);var inputFieldWrapHueLabel=new Node(Node.SPAN).setStyleClass(CSS.Label).setProperty("innerHTML","H"),inputFieldWrapSatLabel=new Node(Node.SPAN).setStyleClass(CSS.Label).setProperty("innerHTML","S"),inputFieldWrapValLabel=new Node(Node.SPAN).setStyleClass(CSS.Label).setProperty("innerHTML","V");inputFieldWrapHue.addChildren(inputFieldWrapHueLabel,inputHue.getNode());inputFieldWrapSat.addChildren(inputFieldWrapSatLabel,inputSat.getNode());inputFieldWrapVal.addChildren(inputFieldWrapValLabel,inputVal.getNode());var inputFieldWrapR=(new Node).setStyleClass(CSS.PickerInputField),inputFieldWrapG=(new Node).setStyleClass(CSS.PickerInputField),inputFieldWrapB=(new Node).setStyleClass(CSS.PickerInputField);var inputFieldWrapRLabel=new Node(Node.SPAN).setStyleClass(CSS.Label).setProperty("innerHTML","R"),inputFieldWrapGLabel=new Node(Node.SPAN).setStyleClass(CSS.Label).setProperty("innerHTML","G"),inputFieldWrapBLabel=new Node(Node.SPAN).setStyleClass(CSS.Label).setProperty("innerHTML","B");inputFieldWrapR.addChildren(inputFieldWrapRLabel,inputR.getNode());inputFieldWrapG.addChildren(inputFieldWrapGLabel,inputG.getNode());inputFieldWrapB.addChildren(inputFieldWrapBLabel,inputB.getNode());inputWrap.addChildren(inputFieldWrapR,inputFieldWrapHue,inputFieldWrapG,inputFieldWrapSat,inputFieldWrapB,inputFieldWrapVal,colorContrast);var hexInputWrap=new Node;hexInputWrap.setStyleClass(CSS.PickerInputWrap);var inputHEX=this._inputHEX=new Node(Node.INPUT_TEXT),inputFieldWrapHEX=(new Node).setStyleClass(CSS.PickerInputField),inputFieldWrapHEXLabel=new Node(Node.SPAN).setStyleClass(CSS.Label);inputFieldWrapHEXLabel.setProperty("innerHTML","#");inputFieldWrapHEX.addChildren(inputFieldWrapHEXLabel,inputHEX);hexInputWrap.addChild(inputFieldWrapHEX);inputHEX.addEventListener(NodeEvent.CHANGE,this._onInputHEXFinish.bind(this));label.setProperty("innerHTML","Color Picker");menu.addChild(menuClose);head.addChild(menu);labelWrap.addChild(label);head.addChild(labelWrap);root.addChild(head);root.addChild(menuWrap);menuWrap.addChild(fieldWrap);menuWrap.addChild(sliderWrap);menuWrap.addChild(inputWrap);menuWrap.addChild(hexInputWrap);menuWrap.addChild(controlsWrap);fieldWrap.addChild(handleField);sliderWrap.addChild(handleSlider);var eventMouseDown=NodeEvent.MOUSE_DOWN,callback=this._onCanvasFieldMouseDown.bind(this);fieldWrap.addEventListener(eventMouseDown,callback);handleField.addEventListener(eventMouseDown,callback);callback=this._onCanvasSliderMouseDown.bind(this);sliderWrap.addEventListener(eventMouseDown,callback);handleSlider.addEventListener(eventMouseDown,callback);menuClose.addEventListener(eventMouseDown,this._onClose.bind(this));buttonPick.addEventListener(eventMouseDown,this._onPick.bind(this));buttonCancel.addEventListener(eventMouseDown,this._onClose.bind(this));head.addEventListener(NodeEvent.MOUSE_DOWN,this._onHeadDragStart.bind(this));this._parentNode=parentNode;this._mouseOffset=[0,0];this._position=[null,null];this._canvasSliderPos=[0,0];this._canvasFieldPos=[0,0];this._handleFieldSize=12;this._handleSliderHeight=7;this._imageDataSlider=contextCanvasSlider.createImageData(canvasSlider.width,canvasSlider.height);this._imageDataField=contextCanvasField.createImageData(canvasField.width,canvasField.height);this._valueHueMinMax=[0,360];this._valueSatMinMax=this._valueValMinMax=[0,100];this._valueRGBMinMax=[0,255];this._valueHue=DEFAULT_VALUE_HUE;this._valueSat=DEFAULT_VALUE_SAT;this._valueVal=DEFAULT_VALUE_VAL;this._valueR=0;this._valueG=0;this._valueB=0;this._valueHEX="#000000";this._valueHEXValid=this._valueHEX;this._callbackPick=function(){};this._drawCanvasField();this._drawCanvasSlider();this._setColorHSV(this._valueHue,this._valueSat,this._valueVal);this._updateColorRGBFromHSV();this._updateColorHEXFromRGB();this._updateHandles()}Picker.prototype={_drawHandleField:function(){var canvas=this._canvasField,nodePos=this._canvasFieldPos,mousePos=Mouse.get().getPosition();var posX=Math.max(0,Math.min(mousePos[0]-nodePos[0],canvas.width)),posY=Math.max(0,Math.min(mousePos[1]-nodePos[1],canvas.height)),posXNorm=posX/canvas.width,posYNorm=posY/canvas.height; - -var sat=Math.round(posXNorm*this._valueSatMinMax[1]),val=Math.round((1-posYNorm)*this._valueValMinMax[1]);this._setColorHSV(this._valueHue,sat,val);this._updateColorRGBFromHSV();this._updateColorHEXFromRGB();this._updateHandleField()},_updateHandleField:function(){var width=this._canvasField.width,height=this._canvasField.height,offsetHandle=this._handleFieldSize*.25;var satNorm=this._valueSat/this._valueSatMinMax[1],valNorm=this._valueVal/this._valueValMinMax[1];this._handleField.setPositionGlobal(satNorm*width-offsetHandle,(1-valNorm)*height-offsetHandle)},_drawHandleSlider:function(){var canvas=this._canvasSlider,canvasPosY=this._canvasSliderPos[1],mousePosY=Mouse.get().getY();var posY=Math.max(0,Math.min(mousePosY-canvasPosY,canvas.height)),posYNorm=posY/canvas.height;var hue=Math.floor((1-posYNorm)*this._valueHueMinMax[1]);this._setColorHSV(hue,this._valueSat,this._valueVal);this._updateColorRGBFromHSV();this._updateColorHEXFromRGB();this._updateHandleSlider()},_updateHandleSlider:function(){var height=this._canvasSlider.height,offsetHandle=this._handleSliderHeight*.25;var hueNorm=this._valueHue/this._valueHueMinMax[1];this._handleSlider.setPositionGlobalY((height-offsetHandle)*(1-hueNorm))},_updateHandles:function(){this._updateHandleField();this._updateHandleSlider()},_setHue:function(value){var minMax=this._valueHueMinMax;this._valueHue=value==minMax[1]?minMax[0]:value;this._updateColorHSV();this._drawCanvasField()},_setSat:function(value){this._valueSat=Math.round(value);this._updateColorHSV()},_setVal:function(value){this._valueVal=Math.round(value);this._updateColorHSV()},_setR:function(value){this._valueR=Math.round(value);this._updateColorRGB()},_setG:function(value){this._valueG=Math.round(value);this._updateColorRGB()},_setB:function(value){this._valueB=Math.round(value);this._updateColorRGB()},_onInputHueChange:function(){var input=this._inputHue,inputVal=this._getValueContrained(input,this._valueHueMinMax);var minMax=this._valueHueMinMax;if(inputVal==minMax[1]){inputVal=minMax[0];input.setValue(inputVal)}this._setHue(inputVal);this._updateColorRGBFromHSV();this._updateColorHEXFromRGB();this._updateHandleSlider();this._drawCanvasField()},_onInputSatChange:function(){this._setSat(this._getValueContrained(this._inputSat,this._valueSatMinMax));this._onInputSVChange()},_onInputValChange:function(){this._setVal(this._getValueContrained(this._inputVal,this._valueValMinMax));this._onInputSVChange()},_onInputRChange:function(){this._setR(this._getValueContrained(this._inputR,this._valueRGBMinMax));this._onInputRGBChange()},_onInputGChange:function(){this._setG(this._getValueContrained(this._inputG,this._valueRGBMinMax));this._onInputRGBChange()},_onInputBChange:function(){this._setB(this._getValueContrained(this._inputB,this._valueRGBMinMax));this._onInputRGBChange()},_onInputHEXFinish:function(){var input=this._inputHEX,value=input.getProperty("value");if(!ColorUtil.isValidHEX(value)){input.setProperty("value",this._valueHEXValid);return}this._valueHEX=this._valueHEXValid=value;this._updateColorFromHEX()},_onInputSVChange:function(){this._updateColorRGBFromHSV();this._updateColorHEXFromRGB();this._updateHandleField()},_onInputRGBChange:function(){this._updateColorHSVFromRGB();this._updateColorHEXFromRGB();this._updateHandles()},_getValueContrained:function(input,minMax){var inputVal=Math.round(input.getValue()),min=minMax[0],max=minMax[1];if(inputVal<=min){inputVal=min;input.setValue(inputVal)}if(inputVal>=max){inputVal=max;input.setValue(inputVal)}return inputVal},_updateInputHue:function(){this._inputHue.setValue(this._valueHue)},_updateInputSat:function(){this._inputSat.setValue(this._valueSat)},_updateInputVal:function(){this._inputVal.setValue(this._valueVal)},_updateInputR:function(){this._inputR.setValue(this._valueR)},_updateInputG:function(){this._inputG.setValue(this._valueG)},_updateInputB:function(){this._inputB.setValue(this._valueB)},_updateInputHEX:function(){this._inputHEX.setProperty("value",this._valueHEX)},_setColorHSV:function(hue,sat,val){this._valueHue=hue;this._valueSat=sat;this._valueVal=val;this._updateInputHue();this._updateInputSat();this._updateInputVal();this._updateContrastCurrColor()},_setColorRGB:function(r,g,b){this._valueR=r;this._valueG=g;this._valueB=b;this._updateInputR();this._updateInputG();this._updateInputB();this._updateContrastCurrColor()},_setColorHEX:function(hex){this._valueHEX=hex;this._updateInputHEX()},_updateColorHSV:function(){this._setColorHSV(this._valueHue,this._valueSat,this._valueVal);this._updateContrastCurrColor()},_updateColorRGB:function(){this._setColorRGB(this._valueR,this._valueG,this._valueB);this._updateContrastCurrColor()},_updateColorHSVFromRGB:function(){var hsv=ColorUtil.RGB2HSV(this._valueR,this._valueG,this._valueB);this._setColorHSV(hsv[0],hsv[1],hsv[2])},_updateColorRGBFromHSV:function(){var rgb=ColorUtil.HSV2RGB(this._valueHue,this._valueSat,this._valueVal);this._setColorRGB(rgb[0],rgb[1],rgb[2])},_updateColorHEXFromRGB:function(){var hex=ColorUtil.RGB2HEX(this._valueR,this._valueG,this._valueB);this._setColorHEX(hex)},_updateColorFromHEX:function(){var rgb=ColorUtil.HEX2RGB(this._valueHEX);this._setColorRGB(rgb[0],rgb[1],rgb[2]);this._updateColorHSVFromRGB();this._updateHandles()},_updateContrastCurrColor:function(){this._setContrastCurrColor(this._valueR,this._valueG,this._valueB)},_updateContrastPrevColor:function(){this._setContrasPrevColor(this._valueR,this._valueG,this._valueB)},_setContrastCurrColor:function(r,g,b){this._colorCurrNode.setStyleProperty("background","rgb("+r+","+g+","+b+")")},_setContrasPrevColor:function(r,g,b){this._colorPrevNode.setStyleProperty("background","rgb("+r+","+g+","+b+")")},_onHeadDragStart:function(){var node=this._node,parentNode=this._parentNode;var nodePos=node.getPositionGlobal(),mousePos=Mouse.get().getPosition(),offsetPos=this._mouseOffset;offsetPos[0]=mousePos[0]-nodePos[0];offsetPos[1]=mousePos[1]-nodePos[1];var eventMouseMove=DocumentEvent.MOUSE_MOVE,eventMouseUp=DocumentEvent.MOUSE_UP;var self=this;var onDrag=function(){self._updatePosition();self._updateCanvasNodePositions()},onDragEnd=function(){self._updateCanvasNodePositions();document.removeEventListener(eventMouseMove,onDrag,false);document.removeEventListener(eventMouseUp,onDragEnd,false)};parentNode.removeChild(node);parentNode.addChild(node);document.addEventListener(eventMouseMove,onDrag,false);document.addEventListener(eventMouseUp,onDragEnd,false);this._updateCanvasNodePositions()},_updatePosition:function(){var mousePos=Mouse.get().getPosition(),offsetPos=this._mouseOffset;var currPositionX=mousePos[0]-offsetPos[0],currPositionY=mousePos[1]-offsetPos[1];var node=this._node,head=this._headNode,position=this._position;var maxX=window.innerWidth-node.getWidth(),maxY=window.innerHeight-head.getHeight();position[0]=Math.max(0,Math.min(currPositionX,maxX));position[1]=Math.max(0,Math.min(currPositionY,maxY));node.setPositionGlobal(position[0],position[1])},_drawCanvasField:function(){var canvas=this._canvasField,context=this._contextCanvasField;var width=canvas.width,height=canvas.height,invWidth=1/width,invHeight=1/height;var imageData=this._imageDataField,rgb=[],index=0;var valueHue=this._valueHue;var i=-1,j;while(++i=this._inputMax.getValue()){inputMin.setValue(values[0]);return}values[0]=inputValue};Range.prototype._updateValueMax=function(){var values=this._obj[this._key];var inputMax=this._inputMax,inputValue=inputMax.getValue();if(inputValue<=this._inputMin.getValue()){inputMax.setValue(values[1]);return}values[1]=inputValue};Range.prototype.onValueUpdate=function(e){if(e.data.origin==this){return}if(e.data.origin==null){}var o=this._obj,k=this._key;this._inputMin.setValue(o[k][0]);this._inputMax.setValue(o[k][1])};Range.prototype.setValue=function(value){var o=this._obj,k=this._key;o[k][0]=value[0];o[k][1]=value[1];this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED,null))};Range.prototype._onInputMinChange=function(){this._updateValueMin();this._onInputChange()};Range.prototype._onInputMaxChange=function(){this._updateValueMax();this._onInputChange()};module.exports=Range},{"../core/ComponentEvent":31,"../core/ObjectComponent":35,"../core/document/CSS":42,"../core/document/Node":45,"../core/event/Event":48,"./NumberInput_Internal":14}],22:[function(require,module,exports){var Component=require("./../core/Component");var CSS=require("../core/document/CSS");var Metric=require("./Metric");var GroupEvent=require("../group/GroupEvent");function SVG(parent,params){Component.apply(this,arguments);var wrap=this._wrapNode;wrap.setStyleClass(CSS.CanvasWrap);var wrapSize=wrap.getWidth();var svg=this._svg=this._createSVGObject("svg");svg.setAttribute("version","1.2");svg.setAttribute("baseProfile","tiny");svg.setAttribute("preserveAspectRatio","true");wrap.getElement().appendChild(svg);this._svgSetSize(wrapSize,wrapSize);this._updateHeight();this._node.setStyleClass(CSS.CanvasListItem);this._parent.addEventListener(GroupEvent.GROUP_SIZE_CHANGE,this,"onGroupSizeChange");this.addEventListener(GroupEvent.GROUP_SIZE_UPDATE,this._parent,"onGroupSizeUpdate")}SVG.prototype=Object.create(Component.prototype);SVG.prototype.constructor=SVG;SVG.prototype._updateHeight=function(){var svgHeight=Number(this._svg.getAttribute("height"));this._wrapNode.setHeight(svgHeight);this._node.setHeight(svgHeight+Metric.PADDING_WRAPPER)};SVG.prototype.onGroupSizeChange=function(){var width=this._wrapNode.getWidth();this._svgSetSize(width,width);this._updateHeight()};SVG.prototype._svgSetSize=function(width,height){var svg=this._svg;svg.setAttribute("width",width);svg.setAttribute("height",height);svg.setAttribute("viewbox","0 0 "+width+" "+height)};SVG.prototype.getSVG=function(){return this._svg};module.exports=SVG},{"../core/document/CSS":42,"../group/GroupEvent":54,"./../core/Component":30,"./Metric":12}],23:[function(require,module,exports){var ObjectComponent=require("../core/ObjectComponent");var CSS=require("../core/document/CSS");var GroupEvent=require("../group/GroupEvent");var Metric=require("./Metric");function SVGComponent(parent,object,value,params){ObjectComponent.apply(this,arguments);var wrap=this._wrapNode;wrap.setStyleClass(CSS.SVGWrap);var wrapSize=wrap.getWidth();var svg=this._svg=this._createSVGObject("svg");svg.setAttribute("version","1.2");svg.setAttribute("baseProfile","tiny");wrap.getElement().appendChild(svg);var svgRoot=this._svgRoot=svg.appendChild(this._createSVGObject("g"));svgRoot.setAttribute("transform","translate(0.5 0.5)");this._svgSetSize(wrapSize,wrapSize);this._updateHeight();this._node.setStyleClass(CSS.SVGListItem);this._parent.addEventListener(GroupEvent.GROUP_SIZE_CHANGE,this,"onGroupSizeChange");this.addEventListener(GroupEvent.GROUP_SIZE_UPDATE,this._parent,"onGroupSizeUpdate")}SVGComponent.prototype=Object.create(ObjectComponent.prototype);SVGComponent.prototype.constructor=SVGComponent;SVGComponent.prototype._updateHeight=function(){var svgHeight=Number(this._svg.getAttribute("height"));this._wrapNode.setHeight(svgHeight);this._node.setHeight(svgHeight+Metric.PADDING_WRAPPER)};SVGComponent.prototype._redraw=function(){};SVGComponent.prototype.onGroupSizeChange=function(){var width=this._wrapNode.getWidth();this._svgSetSize(width,width);this._updateHeight();this._redraw()};SVGComponent.prototype._createSVGObject=function(type){return document.createElementNS("http://www.w3.org/2000/svg",type)};SVGComponent.prototype._svgSetSize=function(width,height){var svg=this._svg;svg.setAttribute("width",width);svg.setAttribute("height",height);svg.setAttribute("viewbox","0 0 "+width+" "+height)};SVGComponent.prototype._pathCmdMoveTo=function(x,y){return"M "+x+" "+y+" "};SVGComponent.prototype._pathCmdLineTo=function(x,y){return"L "+x+" "+y+" "};SVGComponent.prototype._pathCmdClose=function(){return"Z"};SVGComponent.prototype._pathCmdLine=function(x0,y0,x1,y1){return"M "+x0+" "+y0+" L "+x1+" "+y1};SVGComponent.prototype._pathCmdBezierCubic=function(cmd,x0,y0,cx0,cy0,cx1,cy1,x1,y1){return"M "+x0+" "+y0+" C "+cx0+" "+cy0+", "+cx1+" "+cy1+", "+x1+" "+y1};SVGComponent.prototype._pathCmdBezierQuadratic=function(cmd,x0,y0,cx,cy,x1,y1){return"M "+x0+" "+y0+" Q "+cx+" "+cy+", "+x1+" "+y1};module.exports=SVGComponent},{"../core/ObjectComponent":35,"../core/document/CSS":42,"../group/GroupEvent":54,"./Metric":12}],24:[function(require,module,exports){var ObjectComponent=require("../core/ObjectComponent");var Node=require("../core/document/Node");var CSS=require("../core/document/CSS");var Options=require("./Options");var History=require("../core/History");var Event_=require("../core/event/Event"),NodeEvent=require("../core/document/NodeEvent"),ComponentEvent=require("../core/ComponentEvent"),OptionEvent=require("../core/OptionEvent");var ObjectComponentNotifier=require("../core/ObjectComponentNotifier");var STR_CHOOSE="Choose ...";function Select(parent,object,value,params){ObjectComponent.apply(this,arguments);params=params||{};params.onChange=params.onChange||this._onChange;this._onChange=params.onChange;var obj=this._obj,key=this._key;var targetKey=this._targetKey=params.target,values=this._values=obj[key];this._selectedIndex=-1;this._selected=null;var select=this._select=new Node(Node.INPUT_BUTTON);select.setStyleClass(CSS.Select);select.addEventListener(NodeEvent.MOUSE_DOWN,this._onOptionTrigger.bind(this));if(this._hasTarget()){var targetObj=obj[targetKey]||"";var i=-1;while(++i0?targetObj:values[0])}else{select.setProperty("value",params.selected?values[params.selected]:STR_CHOOSE)}this._wrapNode.addChild(select);ObjectComponentNotifier.get().addEventListener(OptionEvent.TRIGGER,this,"onOptionTrigger");this.addEventListener(OptionEvent.TRIGGERED,ObjectComponentNotifier.get(),"onOptionTriggered")}Select.prototype=Object.create(ObjectComponent.prototype);Select.prototype.constructor=Select;Select.prototype.onOptionTrigger=function(e){if(e.data.origin==this){this._active=!this._active;this._updateAppearance();if(this._active){this._buildOptions()}else{Options.get().clear()}return}this._active=false;this._updateAppearance()};Select.prototype._buildOptions=function(){var options=Options.get();var self=this;options.build(this._values,this._selected,this._select,function(){self.applyValue();self._active=false;self._updateAppearance();self._selectedIndex=options.getSelectedIndex();self._onChange(self._selectedIndex);options.clear()},function(){self._active=false;self._updateAppearance();options.clear()},false)};Select.prototype._applySelected=function(selected){this._select.setProperty("value",selected);this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED),null)};Select.prototype.applyValue=function(){var index=Options.get().getSelectedIndex(),selected=this._selected=this._values[index];if(this._hasTarget()){this.pushHistoryState();this._obj[this._targetKey]=selected}this._applySelected(selected)};Select.prototype.pushHistoryState=function(){var obj=this._obj,key=this._targetKey;History.get().pushState(obj,key,obj[key])};Select.prototype._onOptionTrigger=function(){this.dispatchEvent(new Event_(this,OptionEvent.TRIGGERED,null))};Select.prototype._updateAppearance=function(){this._select.setStyleClass(this._active?CSS.SelectActive:CSS.Select)};Select.prototype.onValueUpdate=function(e){if(!this._hasTarget()){return}this._selected=this._obj[this._targetKey];this._select.setProperty("value",this._selected.toString())};Select.prototype._hasTarget=function(){return this._targetKey!=null};Select.prototype.setValue=function(value){this._selectedIndex=value;if(value==-1){this._selected=null;this._select.setProperty("value",STR_CHOOSE);return}this._selected=this._values[this._selectedIndex];this._applySelected(this._selected)};Select.prototype.getData=function(){var obj={};obj["selectedIndex"]=this._selectedIndex;return obj};module.exports=Select},{"../core/ComponentEvent":31,"../core/History":33,"../core/ObjectComponent":35,"../core/ObjectComponentNotifier":36,"../core/OptionEvent":37,"../core/document/CSS":42,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48,"./Options":16}],25:[function(require,module,exports){var ObjectComponent=require("../core/ObjectComponent");var CSS=require("../core/document/CSS");var Slider_Internal=require("./Slider_Internal");var History=require("../core/History");var Range=require("./Range");var NumberInput_Internal=require("./NumberInput_Internal");var Event_=require("../core/event/Event"),DocumentEvent=require("../core/document/DocumentEvent"),PanelEvent=require("../group/PanelEvent"),GroupEvent=require("../group/GroupEvent"),ComponentEvent=require("../core/ComponentEvent");var DEFAULT_STEP=1,DEFAULT_DP=2;function Slider(parent,object,value,range,params){params=params||{};params.label=params.label||value;ObjectComponent.apply(this,[parent,object,range,params]);this._values=this._obj[this._key];this._targetKey=value;params.step=params.step||DEFAULT_STEP;params.dp=params.dp===undefined||params.dp==null?DEFAULT_DP:params.dp;params.onChange=params.onChange||this._onChange;params.onFinish=params.onFinish||function(){};this._dp=params.dp;this._onChange=params.onChange;this._onFinish=params.onFinish;var values=this._values,obj=this._obj,targetKey=this._targetKey;var wrap=this._wrapNode;wrap.setStyleClass(CSS.WrapSlider);var slider=this._slider=new Slider_Internal(wrap,this._onSliderBegin.bind(this),this._onSliderMove.bind(this),this._onSliderEnd.bind(this));slider.setBoundMax(values[1]);slider.setBoundMin(values[0]);slider.setValue(obj[targetKey]);var input=this._input=new NumberInput_Internal(params.step,params.dp,null,this._onInputChange.bind(this));input.setValue(obj[targetKey]);wrap.addChild(input.getNode());this._parent.addEventListener(PanelEvent.PANEL_MOVE_END,this,"onPanelMoveEnd");this._parent.addEventListener(GroupEvent.GROUP_SIZE_CHANGE,this,"onGroupWidthChange");this._parent.addEventListener(DocumentEvent.WINDOW_RESIZE,this,"onWindowResize")}Slider.prototype=Object.create(ObjectComponent.prototype);Slider.prototype.constructor=Slider;Slider.prototype.pushHistoryState=function(){var obj=this._obj,key=this._targetKey;History.get().pushState(obj,key,obj[key])};Slider.prototype._onSliderBegin=function(){this.pushHistoryState()};Slider.prototype._onSliderMove=function(){this.applyValue();this._updateValueField();this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED,null));this._onChange()};Slider.prototype._onSliderEnd=function(){this.applyValue();this._updateValueField();this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED,null));this._onFinish()};Slider.prototype._onInputChange=function(){var input=this._input,valueMin=this._values[0],valueMax=this._values[1];if(input.getValue()>=valueMax){input.setValue(valueMax)}if(input.getValue()<=valueMin){input.setValue(valueMin)}var value=input.getValue();this._slider.setValue(value);this._obj[this._targetKey]=value;this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED,null));this._onFinish()};Slider.prototype.applyValue=function(){var value=this._slider.getValue();this._obj[this._targetKey]=parseFloat(value.toFixed(this._dp));this._input.setValue(value)};Slider.prototype.onValueUpdate=function(e){var origin=e.data.origin;if(origin==this){return}var slider=this._slider;if(!(origin instanceof Slider)){var values=this._values;slider.setBoundMin(values[0]);slider.setBoundMax(values[1]);if(!(origin instanceof Range)){slider.setValue(this._obj[this._targetKey])}}else{slider.setValue(this._obj[this._targetKey])}this.applyValue()};Slider.prototype._updateValueField=function(){this._input.setValue(this._slider.getValue())};Slider.prototype.onPanelMoveEnd=Slider.prototype.onGroupWidthChange=Slider.prototype.onWindowResize=function(){this._slider.resetOffset()};Slider.prototype.setValue=function(value){if(value==-1){return}this._obj[this._targetKey]=value;this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED,null))};Slider.prototype.getData=function(){var obj={};obj[this._targetKey]=this._obj[this._targetKey];return obj};module.exports=Slider},{"../core/ComponentEvent":31,"../core/History":33,"../core/ObjectComponent":35,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/event/Event":48,"../group/GroupEvent":54,"../group/PanelEvent":57,"./NumberInput_Internal":14,"./Range":21,"./Slider_Internal":26}],26:[function(require,module,exports){var Node=require("../core/document/Node");var DocumentEvent=require("../core/document/DocumentEvent"),NodeEvent=require("../core/document/NodeEvent");var CSS=require("../core/document/CSS");var Mouse=require("../core/document/Mouse");function Slider_Internal(parentNode,onBegin,onChange,onFinish){this._bounds=[0,1];this._value=0;this._intrpl=0;this._focus=false;this._onBegin=onBegin||function(){};this._onChange=onChange||function(){};this._onFinish=onFinish||function(){};var wrap=(new Node).setStyleClass(CSS.SliderWrap);parentNode.addChild(wrap);var slot=this._slot={node:(new Node).setStyleClass(CSS.SliderSlot),offsetX:0,width:0,padding:3};var handle=this._handle={node:(new Node).setStyleClass(CSS.SliderHandle),width:0,dragging:false};wrap.addChild(slot.node);slot.node.addChild(handle.node);slot.offsetX=slot.node.getPositionGlobalX();slot.width=Math.floor(slot.node.getWidth()-slot.padding*2);handle.node.setWidth(handle.width);slot.node.addEventListener(NodeEvent.MOUSE_DOWN,this._onSlotMouseDown.bind(this));slot.node.addEventListener(NodeEvent.MOUSE_UP,this._onSlotMouseUp.bind(this));document.addEventListener(DocumentEvent.MOUSE_MOVE,this._onDocumentMouseMove.bind(this));document.addEventListener(DocumentEvent.MOUSE_UP,this._onDocumentMouseUp.bind(this))}Slider_Internal.prototype._onDocumentMouseMove=function(){if(!this._handle.dragging){return}this._update();this._onChange()};Slider_Internal.prototype._onDocumentMouseUp=function(){if(this._handle.dragging){this._onFinish()}this._handle.dragging=false};Slider_Internal.prototype._onSlotMouseDown=function(){this._onBegin();this._focus=true;this._handle.dragging=true;this._handle.node.getElement().focus();this._update()};Slider_Internal.prototype._onSlotMouseUp=function(){if(this._focus){var handle=this._handle;if(handle.dragging){this._onFinish()}handle.dragging=false}this._focus=false};Slider_Internal.prototype._update=function(){var mx=Mouse.get().getX(),sx=this._slot.offsetX,sw=this._slot.width,px=mxsx+sw?sw:mx-sx;this._handle.node.setWidth(Math.round(px));this._intrpl=px/sw;this._interpolateValue()};Slider_Internal.prototype._updateHandle=function(){var slotWidth=this._slot.width,handleWidth=Math.round(this._intrpl*slotWidth);this._handle.node.setWidth(Math.min(handleWidth,slotWidth))};Slider_Internal.prototype._interpolateValue=function(){var intrpl=this._intrpl,bounds=this._bounds;this._value=bounds[0]*(1-intrpl)+bounds[1]*intrpl};Slider_Internal.prototype.resetOffset=function(){var slot=this._slot;slot.offsetX=slot.node.getPositionGlobalX();slot.width=Math.floor(slot.node.getWidth()-slot.padding*2)};Slider_Internal.prototype.setBoundMin=function(value){var bounds=this._bounds;if(value>=bounds[1]){return}bounds[0]=value;this._updateFromBounds()};Slider_Internal.prototype.setBoundMax=function(value){var bounds=this._bounds;if(value<=bounds[0]){return}bounds[1]=value;this._updateFromBounds()};Slider_Internal.prototype._updateFromBounds=function(){var boundsMin=this._bounds[0],boundsMax=this._bounds[1];this._value=Math.max(boundsMin,Math.min(this._value,boundsMax));this._intrpl=Math.abs((this._value-boundsMin)/(boundsMin-boundsMax));this._updateHandle()};Slider_Internal.prototype.setValue=function(value){var boundsMin=this._bounds[0],boundsMax=this._bounds[1];if(valueboundsMax){return}this._intrpl=Math.abs((value-boundsMin)/(boundsMin-boundsMax));this._updateHandle();this._value=value};Slider_Internal.prototype.getValue=function(){return this._value};module.exports=Slider_Internal},{"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Mouse":44,"../core/document/Node":45,"../core/document/NodeEvent":46}],27:[function(require,module,exports){var ObjectComponent=require("../core/ObjectComponent");var Node=require("../core/document/Node"); - -var CSS=require("../core/document/CSS");var Options=require("./Options");var ButtonPreset=require("./ButtonPreset");var Metric=require("./Metric");var Event_=require("../core/event/Event"),DocumentEvent=require("../core/document/DocumentEvent"),NodeEvent=require("../core/document/NodeEvent"),ComponentEvent=require("../core/ComponentEvent");var DEFAULT_PRESET=null;function StringInput(parent,object,value,params){ObjectComponent.apply(this,arguments);params=params||{};params.onChange=params.onChange||this._onChange;params.presets=params.presets||DEFAULT_PRESET;this._onChange=params.onChange;var input=this._input=new Node(Node.INPUT_TEXT);var wrap=this._wrapNode;var presets=params.presets;if(!presets){wrap.addChild(input)}else{var wrap_=new Node;wrap_.setStyleClass(CSS.WrapInputWPreset);wrap.addChild(wrap_);wrap_.addChild(input);var options=Options.get(),btnPreset=new ButtonPreset(this._wrapNode);var onPresetDeactivate=function(){options.clear();btnPreset.deactivate()};var self=this;var onPresetActivate=function(){options.build(presets,input.getProperty("value"),input,function(){input.setProperty("value",presets[options.getSelectedIndex()]);self.pushHistoryState();self.applyValue()},onPresetDeactivate,Metric.PADDING_PRESET,false)};btnPreset.setOnActive(onPresetActivate);btnPreset.setOnDeactive(onPresetDeactivate)}input.setProperty("value",this._obj[this._key]);input.addEventListener(NodeEvent.KEY_UP,this._onInputKeyUp.bind(this));input.addEventListener(NodeEvent.CHANGE,this._onInputChange.bind(this));input.addEventListener(NodeEvent.MOUSE_DOWN,this._onInputDragStart.bind(this));this.addEventListener(ComponentEvent.INPUT_SELECT_DRAG,this._parent,"onComponentSelectDrag")}StringInput.prototype=Object.create(ObjectComponent.prototype);StringInput.prototype.constructor=StringInput;StringInput.prototype._onInputKeyUp=function(e){if(this._keyIsChar(e.keyCode)){this.pushHistoryState()}this.applyValue();this._onChange()};StringInput.prototype._onInputChange=function(e){if(this._keyIsChar(e.keyCode)){this.pushHistoryState()}this.applyValue()};StringInput.prototype._keyIsChar=function(keyCode){return keyCode!=17&&keyCode!=18&&keyCode!=20&&keyCode!=37&&keyCode!=38&&keyCode!=39&&keyCode!=40&&keyCode!=16};StringInput.prototype.applyValue=function(){this._obj[this._key]=this._input.getProperty("value");this.dispatchEvent(new Event_(this,ComponentEvent.VALUE_UPDATED,null))};StringInput.prototype.onValueUpdate=function(e){if(e.data.origin==this)return;this._input.setProperty("value",this._obj[this._key])};StringInput.prototype._onInputDragStart=function(){var eventMove=DocumentEvent.MOUSE_MOVE,eventUp=DocumentEvent.MOUSE_UP;var event=ComponentEvent.INPUT_SELECT_DRAG;var self=this;var onDrag=function(){self.dispatchEvent(new Event_(this,event,null))},onDragFinish=function(){self.dispatchEvent(new Event_(this,event,null));document.removeEventListener(eventMove,onDrag,false);document.removeEventListener(eventMove,onDragFinish,false)};this.dispatchEvent(new Event_(this,event,null));document.addEventListener(eventMove,onDrag,false);document.addEventListener(eventUp,onDragFinish,false)};module.exports=StringInput},{"../core/ComponentEvent":31,"../core/ObjectComponent":35,"../core/document/CSS":42,"../core/document/DocumentEvent":43,"../core/document/Node":45,"../core/document/NodeEvent":46,"../core/event/Event":48,"./ButtonPreset":4,"./Metric":12,"./Options":16}],28:[function(require,module,exports){var Output=require("./Output");StringOutput=function(parent,object,value,params){Output.apply(this,arguments)};StringOutput.prototype=Object.create(Output.prototype);StringOutput.prototype.constructor=StringOutput;StringOutput.prototype._setValue=function(){if(this._parent.isDisabled()){return}var textAreaString=this._obj[this._key];if(textAreaString==this._prevString){return}var textArea=this._textArea,textAreaElement=textArea.getElement(),textAreaScrollHeight;textArea.setProperty("value",textAreaString);textAreaScrollHeight=textAreaElement.scrollHeight;textArea.setHeight(textAreaScrollHeight);var scrollBar=this._scrollBar;if(scrollBar){if(textAreaScrollHeight<=this._wrapNode.getHeight()){scrollBar.disable()}else{scrollBar.enable();scrollBar.update();scrollBar.reset()}}this._prevString=textAreaString};module.exports=StringOutput},{"./Output":17}],29:[function(require,module,exports){var Plotter=require("./Plotter");var Metric=require("./Metric");var DEFAULT_RESOLUTION=1;function ValuePlotter(parent,object,value,params){Plotter.apply(this,arguments);var svg=this._svg,svgWidth=Number(svg.getAttribute("width")),svgHeight=Number(svg.getAttribute("height"));params=params||{};params.height=params.height||svgHeight;params.resolution=params.resolution||DEFAULT_RESOLUTION;var resolution=params.resolution,length=Math.floor(svgWidth/resolution);var points=this._points=new Array(length*2),buffer0=this._buffer0=new Array(length),buffer1=this._buffer1=new Array(length);var min=this._lineWidth*.5;var i=-1;while(++i=MAX_STATES){states.shift()}states.push({object:object,key:key,value:value});this.dispatchEvent(new Event_(this,HistoryEvent.STATE_PUSH,null))};History.prototype.getState=function(object,key){var states=this._states,statesLen=states.length;if(statesLen==0){return null}var state,value;var i=-1;while(++iControlKit State\n"+' \n"+"\n"+"\n"+' \n'+"";var SaveDialogTemplate='\n'+'';var LoadDialogTemplate=''+'';function createWindow(){var width=320,height=200;var window_=window.open("",""," width="+width+", height="+height+", left="+(window.screenX+window.innerWidth*.5-width*.5)+", top="+(window.screenY+window.innerHeight*.5-height*.5)+", location=0, titlebar=0, resizable=0");window_.document.documentElement.innerHTML=DialogTemplate;return window_}function save(data){var window_=createWindow();var document_=window_.document;document_.body.innerHTML+=SaveDialogTemplate;document_.getElementById("save").addEventListener("click",function(){var str=document_.getElementById("state").value,blob=new Blob([str],{type:"application:json"}),name=document_.getElementById("filename").value;var a=document.createElement("a");a.download=name;if(window.webkitURL){a.href=window.webkitURL.createObjectURL(blob)}else{a.href=window.createObjectURL(blob);a.style.display="none";a.addEventListener("click",function(){document_.body.removeChild(a)});document_.body.appendChild(a)}a.click()});document_.getElementById("state").innerText=JSON.stringify(data)}function load(callback){var window_=createWindow();var document_=window_.document;document_.body.innerHTML+=LoadDialogTemplate;var input=document_.getElementById("state");var btnLoad=document_.getElementById("load");btnLoad.disabled=true;function validateInput(){try{var obj=JSON.parse(input.value);if(obj&&typeof obj==="object"&&obj!==null){btnLoad.disabled=false}}catch(e){btnLoad.disabled=true}}input.addEventListener("input",function(){validateInput()});document_.getElementById("load").addEventListener("click",function(){var str=input.value;callback(JSON.parse(str).data);window_.close()});var loadFromDisk=document_.getElementById("load-disk");loadFromDisk.addEventListener("change",function(){var reader=new FileReader;reader.addEventListener("loadend",function(e){input.value=e.target.result;validateInput()});reader.readAsText(loadFromDisk.files[0],"utf-8")})}module.exports={load:load,save:save}},{}],39:[function(require,module,exports){function ColorFormatError(msg){Error.apply(this);Error.captureStackTrace(this,ColorFormatError);this.name="ColorFormatError";this.message=msg}ColorFormatError.prototype=Object.create(Error.prototype);ColorFormatError.prototype.constructor=ColorFormatError;module.exports=ColorFormatError},{}],40:[function(require,module,exports){var ColorMode={RGB:"rgb",HSV:"hsv",HEX:"hex",RGBfv:"rgbfv"};module.exports=ColorMode},{}],41:[function(require,module,exports){var ColorUtil={HSV2RGB:function(hue,sat,val){var max_hue=360,max_sat=100,max_val=100;var min_hue=0,min_sat=0,min_val=0;hue=hue%max_hue;val=Math.max(min_val,Math.min(val,max_val))/max_val*255;if(sat<=min_sat){val=Math.round(val);return[val,val,val]}else if(sat>max_sat)sat=max_sat;sat=sat/max_sat;var hi=Math.floor(hue/60)%6,f=hue/60-hi,p=val*(1-sat),q=val*(1-f*sat),t=val*(1-(1-f)*sat);var r=0,g=0,b=0;switch(hi){case 0:r=val;g=t;b=p;break;case 1:r=q;g=val;b=p;break;case 2:r=p;g=val;b=t;break;case 3:r=p;g=q;b=val;break;case 4:r=t;g=p;b=val;break;case 5:r=val;g=p;b=q;break;default:break}r=Math.round(r);g=Math.round(g);b=Math.round(b);return[r,g,b]},RGB2HSV:function(r,g,b){var h=0,s=0,v=0;r=r/255;g=g/255;b=b/255;var minRGB=Math.min(r,Math.min(g,b)),maxRGB=Math.max(r,Math.max(g,b));if(minRGB==maxRGB){v=minRGB;return[0,0,Math.round(v)]}var dd=r==minRGB?g-b:b==minRGB?r-g:b-r,hh=r==minRGB?3:b==minRGB?1:5;h=Math.round(60*(hh-dd/(maxRGB-minRGB)));s=Math.round((maxRGB-minRGB)/maxRGB*100);v=Math.round(maxRGB*100);return[h,s,v]},RGB2HEX:function(r,g,b){return"#"+((1<<24)+(r<<16)+(g<<8)+b).toString(16).slice(1)},RGBfv2HEX:function(r,g,b){return ColorUtil.RGB2HEX(Math.floor(r*255),Math.floor(g*255),Math.floor(b*255))},HSV2HEX:function(h,s,v){var rgb=ControlKit.ColorUtil.HSV2RGB(h,s,v);return ControlKit.ColorUtil.RGB2HEX(rgb[0],rgb[1],rgb[2])},HEX2RGB:function(hex){var shorthandRegex=/^#?([a-f\d])([a-f\d])([a-f\d])$/i;hex=hex.replace(shorthandRegex,function(m,r,g,b){return r+r+g+g+b+b});var result=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);return result?[parseInt(result[1],16),parseInt(result[2],16),parseInt(result[3],16)]:null},isValidHEX:function(hex){return/^#[0-9A-F]{6}$/i.test(hex)},isValidRGB:function(r,g,b){return r>=0&&r<=255&&g>=0&&g<=255&&b>=0&&b<=255},isValidRGBfv:function(r,g,b){return r>=0&&r<=1&&g>=0&&g<=1&&b>=0&&b<=1}};module.exports=ColorUtil},{}],42:[function(require,module,exports){var CSS={ControlKit:"controlKit",Panel:"panel",Head:"head",Label:"label",Menu:"menu",Wrap:"wrap",ButtonMenuClose:"button-menu-close",ButtonMenuHide:"button-menu-hide",ButtonMenuShow:"button-menu-show",ButtonMenuUndo:"button-menu-undo",ButtonMenuLoad:"button-menu-load",ButtonMenuSave:"button-menu-save",MenuActive:"menu-active",Button:"button",ButtonPreset:"button-preset",ButtonPresetActive:"button-preset-active",WrapInputWPreset:"input-with-preset-wrap",WrapColorWPreset:"color-with-preset-wrap",HeadInactive:"head-inactive",PanelHeadInactive:"panel-head-inactive",GroupList:"group-list",Group:"group",SubGroupList:"sub-group-list",SubGroup:"sub-group",TextAreaWrap:"textarea-wrap",WrapSlider:"wrap-slider",SliderWrap:"slider-wrap",SliderSlot:"slider-slot",SliderHandle:"slider-handle",ArrowBMin:"arrow-b-min",ArrowBMax:"arrow-b-max",ArrowBSubMin:"arrow-b-sub-min",ArrowBSubMax:"arrow-b-sub-max",ArrowSMin:"arrow-s-min",ArrowSMax:"arrow-s-max",Select:"select",SelectActive:"select-active",Options:"options",OptionsSelected:"li-selected",CanvasListItem:"canvas-list-item",CanvasWrap:"canvas-wrap",SVGListItem:"svg-list-item",SVGWrap:"svg-wrap",GraphSliderXWrap:"graph-slider-x-wrap",GraphSliderYWrap:"graph-slider-y-wrap",GraphSliderX:"graph-slider-x",GraphSliderY:"graph-slider-y",GraphSliderXHandle:"graph-slider-x-handle",GraphSliderYHandle:"graph-slider-y-handle",Picker:"picker",PickerFieldWrap:"field-wrap",PickerInputWrap:"input-wrap",PickerInputField:"input-field",PickerControlsWrap:"controls-wrap",PickerColorContrast:"color-contrast",PickerHandleField:"indicator",PickerHandleSlider:"indicator",Color:"color",ScrollBar:"scrollBar",ScrollWrap:"scroll-wrap",ScrollBarBtnUp:"btnUp",ScrollBarBtnDown:"btnDown",ScrollBarTrack:"track",ScrollBarThumb:"thumb",ScrollBuffer:"scroll-buffer"};module.exports=CSS},{}],43:[function(require,module,exports){var DocumentEvent={MOUSE_MOVE:"mousemove",MOUSE_UP:"mouseup",MOUSE_DOWN:"mousedown",MOUSE_WHEEL:"mousewheel",WINDOW_RESIZE:"resize"};module.exports=DocumentEvent},{}],44:[function(require,module,exports){var EventDispatcher=require("../event/EventDispatcher"),Event_=require("../event/Event"),DocumentEvent=require("./DocumentEvent");var instance=null;function Mouse(){EventDispatcher.apply(this);this._pos=[0,0];this._wheelDirection=0;this._hoverElement=null;var self=this;this._onDocumentMouseMove=function(e){var dx=0,dy=0;if(!e)e=window.event;if(e.pageX){dx=e.pageX;dy=e.pageY}else if(e.clientX){dx=e.clientX+document.body.scrollLeft+document.documentElement.scrollLeft;dy=e.clientY+document.body.scrollTop+document.documentElement.scrollTop}self._pos[0]=dx;self._pos[1]=dy;self._hoverElement=document.elementFromPoint(dx,dy)};this._onDocumentMouseWheel=function(event){self._wheelDirection=event.detail<0?1:event.wheelDelta>0?1:-1;self.dispatchEvent(new Event_(self,DocumentEvent.MOUSE_WHEEL,event))};document.addEventListener(DocumentEvent.MOUSE_MOVE,this._onDocumentMouseMove);document.addEventListener(DocumentEvent.MOUSE_WHEEL,this._onDocumentMouseWheel)}Mouse.prototype=Object.create(EventDispatcher.prototype);Mouse.prototype.constructor=Mouse;Mouse.prototype._removeDocumentListener=function(){document.removeEventListener(DocumentEvent.MOUSE_MOVE,this._onDocumentMouseMove);document.removeEventListener(DocumentEvent.MOUSE_WHEEL,this._onDocumentMouseWheel)};Mouse.prototype.getPosition=function(){return this._pos};Mouse.prototype.getX=function(){return this._pos[0]};Mouse.prototype.getY=function(){return this._pos[1]};Mouse.prototype.getWheelDirection=function(){return this._wheelDirection};Mouse.prototype.getHoverElement=function(){return this._hoverElement};Mouse.setup=function(){instance=instance||new Mouse;return instance};Mouse.get=function(){return instance};Mouse.destroy=function(){instance._removeDocumentListener();instance=null};module.exports=Mouse},{"../event/Event":48,"../event/EventDispatcher":49,"./DocumentEvent":43}],45:[function(require,module,exports){function Node(){this._element=null;switch(arguments.length){case 1:var arg=arguments[0];if(arg!=Node.INPUT_TEXT&&arg!=Node.INPUT_BUTTON&&arg!=Node.INPUT_SELECT&&arg!=Node.INPUT_CHECKBOX){this._element=document.createElement(arg)}else{this._element=document.createElement("input");this._element.type=arg}break;case 0:this._element=document.createElement("div");break}}Node.DIV="div";Node.INPUT_TEXT="text";Node.INPUT_BUTTON="button";Node.INPUT_SELECT="select";Node.INPUT_CHECKBOX="checkbox";Node.OPTION="option";Node.LIST="ul";Node.LIST_ITEM="li";Node.SPAN="span";Node.TEXTAREA="textarea";Node.prototype={addChild:function(node){this._element.appendChild(node.getElement());return node},addChildren:function(){var i=-1,l=arguments.length,e=this._element;while(++i-1){if(listeners[i].obj==obj&&listeners[i].method==method){listeners.splice(i,1);if(listeners.length==0){delete this._listeners[type]}break}}},removeAllEventListeners:function(){this._listeners=[]},hasEventListener:function(type){return this._listeners[type]!=undefined&&this._listeners[type]!=null}};module.exports=EventDispatcher},{}],50:[function(require,module,exports){var LayoutMode={LEFT:"left",RIGHT:"right",TOP:"top",BOTTOM:"bottom",NONE:"none"};module.exports=LayoutMode},{}],51:[function(require,module,exports){var Node=require("../document/Node");var Metric=require("../../component/Metric");var CSS=require("../document/CSS");var DocumentEvent=require("../document/DocumentEvent"),NodeEvent=require("../document/NodeEvent");var Mouse=require("../document/Mouse");function ScrollBar(parentNode,targetNode,wrapHeight){this._parentNode=parentNode;this._targetNode=targetNode;this._wrapHeight=wrapHeight;var wrap=this._wrapNode=(new Node).setStyleClass(CSS.ScrollWrap),node=this._node=(new Node).setStyleClass(CSS.ScrollBar),track=this._trackNode=(new Node).setStyleClass(CSS.ScrollBarTrack),thumb=this._thumbNode=(new Node).setStyleClass(CSS.ScrollBarThumb);parentNode.removeChild(targetNode);parentNode.addChild(wrap);parentNode.addChildAt(node,0);wrap.addChild(targetNode);node.addChild(track);track.addChild(thumb);this._mouseThumbOffset=0;this._scrollHeight=0;this._scrollUnit=0;this._scrollMin=0;this._scrollMax=0;thumb.setPositionY(Metric.SCROLLBAR_TRACK_PADDING);thumb.addEventListener(DocumentEvent.MOUSE_DOWN,this._onThumbDragStart.bind(this));this._isValid=false;this._enabled=false;var nodeElement=node.getElement(),thumbElement=thumb.getElement();var self=this;this._onMouseWheel=function(e){var sender=e.sender,hoverElement=sender.getHoverElement();if(hoverElement!=nodeElement&&hoverElement!=thumbElement){return}var scrollStep=self._scrollHeight*.0125;self._scroll(thumb.getPositionY()+sender.getWheelDirection()*scrollStep*-1);e.data.preventDefault()};this.addMouseListener()}ScrollBar.prototype.update=function(){var target=this._targetNode,thumb=this._thumbNode;var padding=Metric.SCROLLBAR_TRACK_PADDING;var targetWrapHeight=this._wrapHeight,targetHeight=target.getHeight(),trackHeight=targetWrapHeight-padding*2;thumb.setHeight(trackHeight);var ratio=targetWrapHeight/targetHeight;this._isValid=false;if(ratio>1){return}var thumbHeight=trackHeight*ratio;this._scrollHeight=trackHeight;this._scrollUnit=targetHeight-this._scrollHeight-padding*2;this._scrollMin=padding;this._scrollMax=padding+trackHeight-thumbHeight;thumb.setHeight(thumbHeight);this._isValid=true};ScrollBar.prototype._scroll=function(y){var min=this._scrollMin,max=this._scrollMax,pos=Math.max(min,Math.min(y,max)),pos_=(pos-min)/(max-min);this._thumbNode.setPositionY(pos);this._targetNode.setPositionY(pos_*this._scrollUnit*-1)};ScrollBar.prototype._onThumbDragStart=function(){if(!this._isValid||this._enabled){return}var eventMove=DocumentEvent.MOUSE_MOVE,eventUp=DocumentEvent.MOUSE_UP;var mouse=Mouse.get();var trackOffset=this._trackNode.getPositionGlobalY();this._mouseThumbOffset=mouse.getY()-this._thumbNode.getPositionGlobalY();var self=this;var onDrag=function(){self._scroll(mouse.getY()-trackOffset-self._mouseThumbOffset)},onDragEnd=function(){document.removeEventListener(eventMove,onDrag,false);document.removeEventListener(eventUp,onDragEnd,false)};document.addEventListener(eventMove,onDrag,false);document.addEventListener(eventUp,onDragEnd,false);this._scroll(mouse.getY()-trackOffset-self._mouseThumbOffset)};ScrollBar.prototype.enable=function(){this._enabled=false;this._updateAppearance()};ScrollBar.prototype.disable=function(){this._enabled=true;this._updateAppearance()};ScrollBar.prototype.reset=function(){this._scroll(0)};ScrollBar.prototype._updateAppearance=function(){if(this._enabled){this._node.setStyleProperty("display","none");this._targetNode.setPositionY(0);this._thumbNode.setPositionY(Metric.SCROLLBAR_TRACK_PADDING)}else{this._node.setStyleProperty("display","block")}};ScrollBar.prototype.isValid=function(){return this._isValid};ScrollBar.prototype.setWrapHeight=function(height){this._wrapHeight=height;this.update()};ScrollBar.prototype.removeTargetNode=function(){return this._wrapNode.removeChild(this._targetNode)};ScrollBar.prototype.removeMouseListener=function(){Mouse.get().removeEventListener(DocumentEvent.MOUSE_WHEEL,this,"_onMouseWheel")};ScrollBar.prototype.addMouseListener=function(){Mouse.get().addEventListener(DocumentEvent.MOUSE_WHEEL,this,"_onMouseWheel")};ScrollBar.prototype.removeFromParent=function(){var parentNode=this._parentNode,rootNode=this._node,targetNode=this._targetNode;rootNode.removeChild(targetNode);parentNode.removeChild(this._wrapNode);parentNode.removeChild(rootNode);return targetNode};ScrollBar.prototype.getWrapNode=function(){return this._wrapNode};ScrollBar.prototype.getNode=function(){return this._node};ScrollBar.prototype.getTargetNode=function(){return this._targetNode};module.exports=ScrollBar},{"../../component/Metric":12,"../document/CSS":42,"../document/DocumentEvent":43,"../document/Mouse":44,"../document/Node":45,"../document/NodeEvent":46}],52:[function(require,module,exports){var EventDispatcher=require("../core/event/EventDispatcher");var Node=require("../core/document/Node");var ScrollBar=require("../core/layout/ScrollBar");function AbstractGroup(parent,params){EventDispatcher.apply(this,arguments);params=params||{};params.height=params.height||null;params.enable=params.enable===undefined?true:params.enable;this._parent=parent;this._height=params.height;this._enabled=params.enable;this._scrollBar=null;this._node=new Node(Node.LIST_ITEM);this._wrapNode=new Node;this._listNode=new Node(Node.LIST);this._parent.getList().addChild(this._node)}AbstractGroup.prototype=Object.create(EventDispatcher.prototype);AbstractGroup.prototype.constructor=AbstractGroup;AbstractGroup.prototype.addScrollWrap=function(){var wrapNode=this._wrapNode,maxHeight=this.getMaxHeight();this._scrollBar=new ScrollBar(wrapNode,this._listNode,maxHeight);if(this.isEnabled()){wrapNode.setHeight(maxHeight)}};AbstractGroup.prototype.preventSelectDrag=function(){this._parent.preventSelectDrag();if(!this.hasScrollWrap()){return}this._wrapNode.getElement().scrollTop=0};AbstractGroup.prototype.hasMaxHeight=function(){return this._height!=null};AbstractGroup.prototype.getMaxHeight=function(){return this._height};AbstractGroup.prototype.hasScrollWrap=function(){return this._scrollBar!=null};AbstractGroup.prototype.hasLabel=function(){return this._lablNode!=null};AbstractGroup.prototype.disable=function(){this._enabled=false;this._updateAppearance()};AbstractGroup.prototype.enable=function(){this._enabled=true;this._updateAppearance()};AbstractGroup.prototype.isDisabled=function(){return!this._enabled};AbstractGroup.prototype.isEnabled=function(){return this._enabled};AbstractGroup.prototype.getList=function(){return this._listNode};module.exports=AbstractGroup},{"../core/document/Node":45,"../core/event/EventDispatcher":49,"../core/layout/ScrollBar":51}],53:[function(require,module,exports){var AbstractGroup=require("./AbstractGroup");var CSS=require("../core/document/CSS");var Node=require("../core/document/Node");var SubGroup=require("./SubGroup");var Event_=require("../core/event/Event"),DocumentEvent=require("../core/document/DocumentEvent"),NodeEvent=require("../core/document/NodeEvent"),PanelEvent=require("./PanelEvent"),GroupEvent=require("./GroupEvent");var ObjectComponent=require("../core/ObjectComponent"),ValuePlotter=require("../component/ValuePlotter"),FunctionPlotter=require("../component/FunctionPlotter");function Group(parent,params){params=params||{};params.label=params.label||null;params.useLabels=params.useLabels||true;params.enable=params.enable===undefined?true:params.enable;AbstractGroup.apply(this,arguments);this._components=[];this._subGroups=[];var root=this._node,wrap=this._wrapNode,list=this._listNode;root.setStyleClass(CSS.Group);wrap.setStyleClass(CSS.Wrap);list.setStyleClass(CSS.SubGroupList);wrap.addChild(list);var label=params.label;if(label){var head=new Node,wrap_=new Node,label_=new Node(Node.SPAN),indicator=this._indiNode=new Node;head.setStyleClass(CSS.Head);wrap_.setStyleClass(CSS.Wrap);label_.setStyleClass(CSS.Label);indicator.setStyleClass(CSS.ArrowBMax);label_.setProperty("innerHTML",label);head.addChild(indicator);wrap_.addChild(label_);head.addChild(wrap_);root.addChild(head);head.addEventListener(NodeEvent.MOUSE_DOWN,this._onHeadTrigger.bind(this));this.addEventListener(GroupEvent.GROUP_LIST_SIZE_CHANGE,parent,"onGroupListSizeChange");this._updateAppearance()}if(this.hasMaxHeight()){this.addScrollWrap()}root.addChild(wrap);if(this.hasMaxHeight()){if(!label){var bufferTop=this._scrollBufferTop=new Node;bufferTop.setStyleClass(CSS.ScrollBuffer);root.addChildAt(bufferTop,0)}var bufferBottom=this._scrollBufferBottom=new Node;bufferBottom.setStyleClass(CSS.ScrollBuffer);root.addChild(bufferBottom)}parent=this._parent;parent.addEventListener(PanelEvent.PANEL_MOVE_BEGIN,this,"onPanelMoveBegin");parent.addEventListener(PanelEvent.PANEL_MOVE,this,"onPanelMove");parent.addEventListener(PanelEvent.PANEL_MOVE_END,this,"onPanelMoveEnd");parent.addEventListener(PanelEvent.PANEL_HIDE,this,"onPanelHide");parent.addEventListener(PanelEvent.PANEL_SHOW,this,"onPanelShow");parent.addEventListener(PanelEvent.PANEL_SCROLL_WRAP_ADDED,this,"onPanelScrollWrapAdded");parent.addEventListener(PanelEvent.PANEL_SCROLL_WRAP_REMOVED,this,"onPanelScrollWrapRemoved");parent.addEventListener(PanelEvent.PANEL_SIZE_CHANGE,this,"onPanelSizeChange");parent.addEventListener(DocumentEvent.WINDOW_RESIZE,this,"onWindowResize");this.addEventListener(GroupEvent.GROUP_SIZE_CHANGE,parent,"onGroupListSizeChange")}Group.prototype=Object.create(AbstractGroup.prototype);Group.prototype.constructor=Group;Group.prototype.onPanelMoveBegin=function(){this.dispatchEvent(new Event_(this,PanelEvent.PANEL_MOVE_BEGIN,null))};Group.prototype.onPanelMove=function(){this.dispatchEvent(new Event_(this,PanelEvent.PANEL_MOVE,null))};Group.prototype.onPanelMoveEnd=function(){this.dispatchEvent(new Event_(this,PanelEvent.PANEL_MOVE_END,null))};Group.prototype.onPanelScrollWrapAdded=function(){this.dispatchEvent(new Event_(this,GroupEvent.GROUP_SIZE_CHANGE,null))};Group.prototype.onPanelScrollWrapRemoved=function(){this.dispatchEvent(new Event_(this,GroupEvent.GROUP_SIZE_CHANGE,null))};Group.prototype.onPanelHide=function(){this.dispatchEvent(new Event_(this,GroupEvent.SUBGROUP_DISABLE,null))};Group.prototype.onPanelShow=function(){this.dispatchEvent(new Event_(this,GroupEvent.SUBGROUP_ENABLE,null))};Group.prototype.onPanelSizeChange=function(){this.dispatchEvent(new Event_(this,GroupEvent.GROUP_SIZE_CHANGE,null))};Group.prototype.onWindowResize=function(e){this.dispatchEvent(e)};Group.prototype.onSubGroupTrigger=function(){this._updateHeight();if(!this.hasMaxHeight()){return}var scrollBar=this._scrollBar,wrap=this._wrapNode;var bufferTop=this._scrollBufferTop,bufferBottom=this._scrollBufferBottom;scrollBar.update();if(!scrollBar.isValid()){scrollBar.disable();wrap.setHeight(wrap.getChildAt(1).getHeight());if(bufferTop){bufferTop.setStyleProperty("display","none")}if(bufferBottom){bufferBottom.setStyleProperty("display","none")}}else{scrollBar.enable();wrap.setHeight(this.getMaxHeight());if(bufferTop){bufferTop.setStyleProperty("display","block")}if(bufferBottom){bufferBottom.setStyleProperty("display","block")}}this.dispatchEvent(new Event_(this,GroupEvent.GROUP_SIZE_CHANGE,null))};Group.prototype._onHeadTrigger=function(){this._enabled=!this._enabled;this._updateAppearance();this.dispatchEvent(new Event_(this,GroupEvent.GROUP_LIST_SIZE_CHANGE,null))};Group.prototype.addComponent=function(){var Class_=arguments[0];var args=Array.prototype.slice.call(arguments);args.shift();args.unshift(this._getSubGroup());var instance=Object.create(Class_.prototype);Class_.apply(instance,args);this._components.push(instance);this._updateHeight()};Group.prototype._updateHeight=function(){this._getSubGroup().update();this.dispatchEvent(new Event_(this,GroupEvent.GROUP_SIZE_CHANGE,null));if(this.hasMaxHeight()){this._scrollBar.update()}};Group.prototype._updateAppearance=function(){var wrap=this._wrapNode,indicator=this._indiNode;var scrollBar=this._scrollBar;var bufferTop=this._scrollBufferTop,bufferBottom=this._scrollBufferBottom;if(this.isDisabled()){wrap.setHeight(0);if(indicator){indicator.setStyleClass(CSS.ArrowBMin)}if(scrollBar){if(bufferTop){bufferTop.setStyleProperty("display","none")}if(bufferBottom){bufferBottom.setStyleProperty("display","none")}}return}if(this.hasMaxHeight()){var maxHeight=this.getMaxHeight(),listHeight=wrap.getChildAt(1).getHeight();wrap.setHeight(listHeightlistHeight){this._scrollBar.disable()}else{this._scrollBar.enable()}this.dispatchEvent(new Event_(this,PanelEvent.PANEL_SIZE_CHANGE))}}else{if(!this.isFixed()){this._constrainPosition()}}this._constrainHeight();this.dispatchEvent(new Event_(this,DocumentEvent.WINDOW_RESIZE))};Panel.prototype._constrainPosition=function(){var node=this._node;var maxX=window.innerWidth-node.getWidth(),maxY=window.innerHeight-node.getHeight();var position=this._position;position[0]=Math.max(0,Math.min(position[0],maxX));position[1]=Math.max(0,Math.min(position[1],maxY));node.setPositionGlobal(position[0],position[1])};Panel.prototype._constrainHeight=function(){if(!this._vConstrain)return;var hasMaxHeight=this.hasMaxHeight(),hasScrollWrap=this.hasScrollWrap();var head=this._headNode,wrap=this._wrapNode;var scrollBar=this._scrollBar;var panelTop=this.isDocked()?0:this.isFixed()?0:this._position[1];var panelHeight=hasMaxHeight?this.getMaxHeight():hasScrollWrap?scrollBar.getTargetNode().getHeight():wrap.getHeight();var panelBottom=panelTop+panelHeight;var headHeight=head.getHeight();var windowHeight=window.innerHeight,heightDiff=windowHeight-panelBottom-headHeight,heightSum;if(heightDiff<0){heightSum=panelHeight+heightDiff;if(!hasScrollWrap){this._addScrollWrap(heightSum);this.dispatchEvent(new Event_(this,PanelEvent.PANEL_SCROLL_WRAP_ADDED,null));return}scrollBar.setWrapHeight(heightSum);wrap.setHeight(heightSum)}else{if(!hasMaxHeight&&hasScrollWrap){scrollBar.removeFromParent();wrap.addChild(this._listNode);wrap.deleteStyleProperty("height");this._scrollBar.removeMouseListener();this._scrollBar=null;this.dispatchEvent(new Event_(this,PanelEvent.PANEL_SCROLL_WRAP_REMOVED,null))}}};Panel.prototype.onGroupListSizeChange=function(){if(this.hasScrollWrap()){this._updateScrollWrap()}this._constrainHeight()};Panel.prototype._updateScrollWrap=function(){var wrap=this._wrapNode,scrollBar=this._scrollBar,height=this.hasMaxHeight()?this.getMaxHeight():100,listHeight=this._listNode.getHeight();wrap.setHeight(listHeight/g, '>' ) - .replace( /]+)>)/ig, '' ) ); -}; -/** - * A generic and very fast EventEmitter - * implementation. On top of emitting the - * actual event it emits an - * - * lm.utils.EventEmitter.ALL_EVENT - * - * event for every event triggered. This allows - * to hook into it and proxy events forwards - * - * @constructor - */ -lm.utils.EventEmitter = function() { - this._mSubscriptions = {}; - this._mSubscriptions[ lm.utils.EventEmitter.ALL_EVENT ] = []; - - /** - * Listen for events - * - * @param {String} sEvent The name of the event to listen to - * @param {Function} fCallback The callback to execute when the event occurs - * @param {[Object]} oContext The value of the this pointer within the callback function - * - * @returns {void} - */ - this.on = function( sEvent, fCallback, oContext ) { - if( !lm.utils.isFunction( fCallback ) ) { - throw new Error( 'Tried to listen to event ' + sEvent + ' with non-function callback ' + fCallback ); - } - - if( !this._mSubscriptions[ sEvent ] ) { - this._mSubscriptions[ sEvent ] = []; - } - - this._mSubscriptions[ sEvent ].push( { fn: fCallback, ctx: oContext } ); - }; - - /** - * Emit an event and notify listeners - * - * @param {String} sEvent The name of the event - * @param {Mixed} various additional arguments that will be passed to the listener - * - * @returns {void} - */ - this.emit = function( sEvent ) { - var i, ctx, args; - - args = Array.prototype.slice.call( arguments, 1 ); - - var subs = this._mSubscriptions[ sEvent ]; - - if( subs ) { - subs = subs.slice(); - for( i = 0; i < subs.length; i++ ) { - ctx = subs[ i ].ctx || {}; - subs[ i ].fn.apply( ctx, args ); - } - } - - args.unshift( sEvent ); - - var allEventSubs = this._mSubscriptions[ lm.utils.EventEmitter.ALL_EVENT ].slice() - - for( i = 0; i this._nDistance || - Math.abs( this._nY ) > this._nDistance - ) { - clearTimeout( this._timeout ); - this._startDrag(); - } - } - - if( this._bDragging ) { - this.emit( 'drag', this._nX, this._nY, oEvent ); - } - } - }, - - onMouseUp: function( oEvent ) { - if( this._timeout != null ) { - clearTimeout( this._timeout ); - this._eBody.removeClass( 'lm_dragging' ); - this._eElement.removeClass( 'lm_dragging' ); - this._oDocument.find( 'iframe' ).css( 'pointer-events', '' ); - this._oDocument.unbind( 'mousemove touchmove', this._fMove ); - this._oDocument.unbind( 'mouseup touchend', this._fUp ); - - if( this._bDragging === true ) { - this._bDragging = false; - this.emit( 'dragStop', oEvent, this._nOriginalX + this._nX ); - } - } - }, - - _startDrag: function() { - this._bDragging = true; - this._eBody.addClass( 'lm_dragging' ); - this._eElement.addClass( 'lm_dragging' ); - this._oDocument.find( 'iframe' ).css( 'pointer-events', 'none' ); - this.emit( 'dragStart', this._nOriginalX, this._nOriginalY ); - }, - - _getCoordinates: function( event ) { - event = event.originalEvent && event.originalEvent.touches ? event.originalEvent.touches[ 0 ] : event; - return { - x: event.pageX, - y: event.pageY - }; - } -} ); -/** - * The main class that will be exposed as GoldenLayout. - * - * @public - * @constructor - * @param {GoldenLayout config} config - * @param {[DOM element container]} container Can be a jQuery selector string or a Dom element. Defaults to body - * - * @returns {VOID} - */ -lm.LayoutManager = function( config, container ) { - - if( !$ || typeof $.noConflict !== 'function' ) { - var errorMsg = 'jQuery is missing as dependency for GoldenLayout. '; - errorMsg += 'Please either expose $ on GoldenLayout\'s scope (e.g. window) or add "jquery" to '; - errorMsg += 'your paths when using RequireJS/AMD'; - throw new Error( errorMsg ); - } - lm.utils.EventEmitter.call( this ); - - this.isInitialised = false; - this._isFullPage = false; - this._resizeTimeoutId = null; - this._components = { 'lm-react-component': lm.utils.ReactComponentHandler }; - this._itemAreas = []; - this._resizeFunction = lm.utils.fnBind( this._onResize, this ); - this._unloadFunction = lm.utils.fnBind( this._onUnload, this ); - this._maximisedItem = null; - this._maximisePlaceholder = $( '
' ); - this._creationTimeoutPassed = false; - this._subWindowsCreated = false; - this._dragSources = []; - this._updatingColumnsResponsive = false; - this._firstLoad = true; - - this.width = null; - this.height = null; - this.root = null; - this.openPopouts = []; - this.selectedItem = null; - this.isSubWindow = false; - this.eventHub = new lm.utils.EventHub( this ); - this.config = this._createConfig( config ); - this.container = container; - this.dropTargetIndicator = null; - this.transitionIndicator = null; - this.tabDropPlaceholder = $( '
' ); - - if( this.isSubWindow === true ) { - $( 'body' ).css( 'visibility', 'hidden' ); - } - - this._typeToItem = { - 'column': lm.utils.fnBind( lm.items.RowOrColumn, this, [ true ] ), - 'row': lm.utils.fnBind( lm.items.RowOrColumn, this, [ false ] ), - 'stack': lm.items.Stack, - 'component': lm.items.Component - }; -}; - -/** - * Hook that allows to access private classes - */ -lm.LayoutManager.__lm = lm; - -/** - * Takes a GoldenLayout configuration object and - * replaces its keys and values recursively with - * one letter codes - * - * @static - * @public - * @param {Object} config A GoldenLayout config object - * - * @returns {Object} minified config - */ -lm.LayoutManager.minifyConfig = function( config ) { - return ( new lm.utils.ConfigMinifier() ).minifyConfig( config ); -}; - -/** - * Takes a configuration Object that was previously minified - * using minifyConfig and returns its original version - * - * @static - * @public - * @param {Object} minifiedConfig - * - * @returns {Object} the original configuration - */ -lm.LayoutManager.unminifyConfig = function( config ) { - return ( new lm.utils.ConfigMinifier() ).unminifyConfig( config ); -}; - -lm.utils.copy( lm.LayoutManager.prototype, { - - /** - * Register a component with the layout manager. If a configuration node - * of type component is reached it will look up componentName and create the - * associated component - * - * { - * type: "component", - * componentName: "EquityNewsFeed", - * componentState: { "feedTopic": "us-bluechips" } - * } - * - * @public - * @param {String} name - * @param {Function} constructor - * - * @returns {void} - */ - registerComponent: function( name, constructor ) { - if( typeof constructor !== 'function' ) { - throw new Error( 'Please register a constructor function' ); - } - - if( this._components[ name ] !== undefined ) { - throw new Error( 'Component ' + name + ' is already registered' ); - } - - this._components[ name ] = constructor; - }, - - /** - * Creates a layout configuration object based on the the current state - * - * @public - * @returns {Object} GoldenLayout configuration - */ - toConfig: function( root ) { - var config, next, i; - - if( this.isInitialised === false ) { - throw new Error( 'Can\'t create config, layout not yet initialised' ); - } - - if( root && !( root instanceof lm.items.AbstractContentItem ) ) { - throw new Error( 'Root must be a ContentItem' ); - } - - /* - * settings & labels - */ - config = { - settings: lm.utils.copy( {}, this.config.settings ), - dimensions: lm.utils.copy( {}, this.config.dimensions ), - labels: lm.utils.copy( {}, this.config.labels ) - }; - - /* - * Content - */ - config.content = []; - next = function( configNode, item ) { - var key, i; - - for( key in item.config ) { - if( key !== 'content' ) { - configNode[ key ] = item.config[ key ]; - } - } - - if( item.contentItems.length ) { - configNode.content = []; - - for( i = 0; i < item.contentItems.length; i++ ) { - configNode.content[ i ] = {}; - next( configNode.content[ i ], item.contentItems[ i ] ); - } - } - }; - - if( root ) { - next( config, { contentItems: [ root ] } ); - } else { - next( config, this.root ); - } - - /* - * Retrieve config for subwindows - */ - this._$reconcilePopoutWindows(); - config.openPopouts = []; - for( i = 0; i < this.openPopouts.length; i++ ) { - config.openPopouts.push( this.openPopouts[ i ].toConfig() ); - } - - /* - * Add maximised item - */ - config.maximisedItemId = this._maximisedItem ? '__glMaximised' : null; - return config; - }, - - /** - * Returns a previously registered component - * - * @public - * @param {String} name The name used - * - * @returns {Function} - */ - getComponent: function( name ) { - if( this._components[ name ] === undefined ) { - throw new lm.errors.ConfigurationError( 'Unknown component "' + name + '"' ); - } - - return this._components[ name ]; - }, - - /** - * Creates the actual layout. Must be called after all initial components - * are registered. Recurses through the configuration and sets up - * the item tree. - * - * If called before the document is ready it adds itself as a listener - * to the document.ready event - * - * @public - * - * @returns {void} - */ - init: function() { - - /** - * Create the popout windows straight away. If popouts are blocked - * an error is thrown on the same 'thread' rather than a timeout and can - * be caught. This also prevents any further initilisation from taking place. - */ - if( this._subWindowsCreated === false ) { - this._createSubWindows(); - this._subWindowsCreated = true; - } - - - /** - * If the document isn't ready yet, wait for it. - */ - if( document.readyState === 'loading' || document.body === null ) { - $( document ).ready( lm.utils.fnBind( this.init, this ) ); - return; - } - - /** - * If this is a subwindow, wait a few milliseconds for the original - * page's js calls to be executed, then replace the bodies content - * with GoldenLayout - */ - if( this.isSubWindow === true && this._creationTimeoutPassed === false ) { - setTimeout( lm.utils.fnBind( this.init, this ), 7 ); - this._creationTimeoutPassed = true; - return; - } - - if( this.isSubWindow === true ) { - this._adjustToWindowMode(); - } - - this._setContainer(); - this.dropTargetIndicator = new lm.controls.DropTargetIndicator( this.container ); - this.transitionIndicator = new lm.controls.TransitionIndicator(); - this.updateSize(); - this._create( this.config ); - this._bindEvents(); - this.isInitialised = true; - this._adjustColumnsResponsive(); - this.emit( 'initialised' ); - }, - - /** - * Updates the layout managers size - * - * @public - * @param {[int]} width height in pixels - * @param {[int]} height width in pixels - * - * @returns {void} - */ - updateSize: function( width, height ) { - if( arguments.length === 2 ) { - this.width = width; - this.height = height; - } else { - this.width = this.container.width(); - this.height = this.container.height(); - } - - if( this.isInitialised === true ) { - this.root.callDownwards( 'setSize', [ this.width, this.height ] ); - - if( this._maximisedItem ) { - this._maximisedItem.element.width( this.container.width() ); - this._maximisedItem.element.height( this.container.height() ); - this._maximisedItem.callDownwards( 'setSize' ); - } - - this._adjustColumnsResponsive(); - } - }, - - /** - * Destroys the LayoutManager instance itself as well as every ContentItem - * within it. After this is called nothing should be left of the LayoutManager. - * - * @public - * @returns {void} - */ - destroy: function() { - if( this.isInitialised === false ) { - return; - } - this._onUnload(); - $( window ).off( 'resize', this._resizeFunction ); - $( window ).off( 'unload beforeunload', this._unloadFunction ); - this.root.callDownwards( '_$destroy', [], true ); - this.root.contentItems = []; - this.tabDropPlaceholder.remove(); - this.dropTargetIndicator.destroy(); - this.transitionIndicator.destroy(); - this.eventHub.destroy(); - - this._dragSources.forEach( function( dragSource ) { - dragSource._dragListener.destroy(); - dragSource._element = null; - dragSource._itemConfig = null; - dragSource._dragListener = null; - } ); - this._dragSources = []; - }, - - /** - * Recursively creates new item tree structures based on a provided - * ItemConfiguration object - * - * @public - * @param {Object} config ItemConfig - * @param {[ContentItem]} parent The item the newly created item should be a child of - * - * @returns {lm.items.ContentItem} - */ - createContentItem: function( config, parent ) { - var typeErrorMsg, contentItem; - - if( typeof config.type !== 'string' ) { - throw new lm.errors.ConfigurationError( 'Missing parameter \'type\'', config ); - } - - if( config.type === 'react-component' ) { - config.type = 'component'; - config.componentName = 'lm-react-component'; - } - - if( !this._typeToItem[ config.type ] ) { - typeErrorMsg = 'Unknown type \'' + config.type + '\'. ' + - 'Valid types are ' + lm.utils.objectKeys( this._typeToItem ).join( ',' ); - - throw new lm.errors.ConfigurationError( typeErrorMsg ); - } - - - /** - * We add an additional stack around every component that's not within a stack anyways. - */ - if( - // If this is a component - config.type === 'component' && - - // and it's not already within a stack - !( parent instanceof lm.items.Stack ) && - - // and we have a parent - !!parent && - - // and it's not the topmost item in a new window - !( this.isSubWindow === true && parent instanceof lm.items.Root ) - ) { - config = { - type: 'stack', - width: config.width, - height: config.height, - content: [ config ] - }; - } - - contentItem = new this._typeToItem[ config.type ]( this, config, parent ); - return contentItem; - }, - - /** - * Creates a popout window with the specified content and dimensions - * - * @param {Object|lm.itemsAbstractContentItem} configOrContentItem - * @param {[Object]} dimensions A map with width, height, left and top - * @param {[String]} parentId the id of the element this item will be appended to - * when popIn is called - * @param {[Number]} indexInParent The position of this item within its parent element - - * @returns {lm.controls.BrowserPopout} - */ - createPopout: function( configOrContentItem, dimensions, parentId, indexInParent ) { - var config = configOrContentItem, - isItem = configOrContentItem instanceof lm.items.AbstractContentItem, - self = this, - windowLeft, - windowTop, - offset, - parent, - child, - browserPopout; - - parentId = parentId || null; - - if( isItem ) { - config = this.toConfig( configOrContentItem ).content; - parentId = lm.utils.getUniqueId(); - - /** - * If the item is the only component within a stack or for some - * other reason the only child of its parent the parent will be destroyed - * when the child is removed. - * - * In order to support this we move up the tree until we find something - * that will remain after the item is being popped out - */ - parent = configOrContentItem.parent; - child = configOrContentItem; - while( parent.contentItems.length === 1 && !parent.isRoot ) { - parent = parent.parent; - child = child.parent; - } - - parent.addId( parentId ); - if( isNaN( indexInParent ) ) { - indexInParent = lm.utils.indexOf( child, parent.contentItems ); - } - } else { - if( !( config instanceof Array ) ) { - config = [ config ]; - } - } - - - if( !dimensions && isItem ) { - windowLeft = window.screenX || window.screenLeft; - windowTop = window.screenY || window.screenTop; - offset = configOrContentItem.element.offset(); - - dimensions = { - left: windowLeft + offset.left, - top: windowTop + offset.top, - width: configOrContentItem.element.width(), - height: configOrContentItem.element.height() - }; - } - - if( !dimensions && !isItem ) { - dimensions = { - left: window.screenX || window.screenLeft + 20, - top: window.screenY || window.screenTop + 20, - width: 500, - height: 309 - }; - } - - if( isItem ) { - configOrContentItem.remove(); - } - - browserPopout = new lm.controls.BrowserPopout( config, dimensions, parentId, indexInParent, this ); - - browserPopout.on( 'initialised', function() { - self.emit( 'windowOpened', browserPopout ); - } ); - - browserPopout.on( 'closed', function() { - self._$reconcilePopoutWindows(); - } ); - - this.openPopouts.push( browserPopout ); - - return browserPopout; - }, - - /** - * Attaches DragListener to any given DOM element - * and turns it into a way of creating new ContentItems - * by 'dragging' the DOM element into the layout - * - * @param {jQuery DOM element} element - * @param {Object|Function} itemConfig for the new item to be created, or a function which will provide it - * - * @returns {void} - */ - createDragSource: function( element, itemConfig ) { - this.config.settings.constrainDragToContainer = false; - var dragSource = new lm.controls.DragSource( $( element ), itemConfig, this ); - this._dragSources.push( dragSource ); - - return dragSource; - }, - - /** - * Programmatically selects an item. This deselects - * the currently selected item, selects the specified item - * and emits a selectionChanged event - * - * @param {lm.item.AbstractContentItem} item# - * @param {[Boolean]} _$silent Wheather to notify the item of its selection - * @event selectionChanged - * - * @returns {VOID} - */ - selectItem: function( item, _$silent ) { - - if( this.config.settings.selectionEnabled !== true ) { - throw new Error( 'Please set selectionEnabled to true to use this feature' ); - } - - if( item === this.selectedItem ) { - return; - } - - if( this.selectedItem !== null ) { - this.selectedItem.deselect(); - } - - if( item && _$silent !== true ) { - item.select(); - } - - this.selectedItem = item; - - this.emit( 'selectionChanged', item ); - }, - - /************************* - * PACKAGE PRIVATE - *************************/ - _$maximiseItem: function( contentItem ) { - if( this._maximisedItem !== null ) { - this._$minimiseItem( this._maximisedItem ); - } - this._maximisedItem = contentItem; - this._maximisedItem.addId( '__glMaximised' ); - contentItem.element.addClass( 'lm_maximised' ); - contentItem.element.after( this._maximisePlaceholder ); - this.root.element.prepend( contentItem.element ); - contentItem.element.width( this.container.width() ); - contentItem.element.height( this.container.height() ); - contentItem.callDownwards( 'setSize' ); - this._maximisedItem.emit( 'maximised' ); - this.emit( 'stateChanged' ); - }, - - _$minimiseItem: function( contentItem ) { - contentItem.element.removeClass( 'lm_maximised' ); - contentItem.removeId( '__glMaximised' ); - this._maximisePlaceholder.after( contentItem.element ); - this._maximisePlaceholder.remove(); - contentItem.parent.callDownwards( 'setSize' ); - this._maximisedItem = null; - contentItem.emit( 'minimised' ); - this.emit( 'stateChanged' ); - }, - - /** - * This method is used to get around sandboxed iframe restrictions. - * If 'allow-top-navigation' is not specified in the iframe's 'sandbox' attribute - * (as is the case with codepens) the parent window is forbidden from calling certain - * methods on the child, such as window.close() or setting document.location.href. - * - * This prevented GoldenLayout popouts from popping in in codepens. The fix is to call - * _$closeWindow on the child window's gl instance which (after a timeout to disconnect - * the invoking method from the close call) closes itself. - * - * @packagePrivate - * - * @returns {void} - */ - _$closeWindow: function() { - window.setTimeout( function() { - window.close(); - }, 1 ); - }, - - _$getArea: function( x, y ) { - var i, area, smallestSurface = Infinity, mathingArea = null; - - for( i = 0; i < this._itemAreas.length; i++ ) { - area = this._itemAreas[ i ]; - - if( - x > area.x1 && - x < area.x2 && - y > area.y1 && - y < area.y2 && - smallestSurface > area.surface - ) { - smallestSurface = area.surface; - mathingArea = area; - } - } - - return mathingArea; - }, - - _$createRootItemAreas: function() { - var areaSize = 50; - var sides = { y2: 0, x2: 0, y1: 'y2', x1: 'x2' }; - for( var side in sides ) { - var area = this.root._$getArea(); - area.side = side; - if( sides [ side ] ) - area[ side ] = area[ sides [ side ] ] - areaSize; - else - area[ side ] = areaSize; - area.surface = ( area.x2 - area.x1 ) * ( area.y2 - area.y1 ); - this._itemAreas.push( area ); - } - }, - - _$calculateItemAreas: function() { - var i, area, allContentItems = this._getAllContentItems(); - this._itemAreas = []; - - /** - * If the last item is dragged out, highlight the entire container size to - * allow to re-drop it. allContentItems[ 0 ] === this.root at this point - * - * Don't include root into the possible drop areas though otherwise since it - * will used for every gap in the layout, e.g. splitters - */ - if( allContentItems.length === 1 ) { - this._itemAreas.push( this.root._$getArea() ); - return; - } - this._$createRootItemAreas(); - - for( i = 0; i < allContentItems.length; i++ ) { - - if( !( allContentItems[ i ].isStack ) ) { - continue; - } - - area = allContentItems[ i ]._$getArea(); - - if( area === null ) { - continue; - } else if( area instanceof Array ) { - this._itemAreas = this._itemAreas.concat( area ); - } else { - this._itemAreas.push( area ); - var header = {}; - lm.utils.copy( header, area ); - lm.utils.copy( header, area.contentItem._contentAreaDimensions.header.highlightArea ); - header.surface = ( header.x2 - header.x1 ) * ( header.y2 - header.y1 ); - this._itemAreas.push( header ); - } - } - }, - - /** - * Takes a contentItem or a configuration and optionally a parent - * item and returns an initialised instance of the contentItem. - * If the contentItem is a function, it is first called - * - * @packagePrivate - * - * @param {lm.items.AbtractContentItem|Object|Function} contentItemOrConfig - * @param {lm.items.AbtractContentItem} parent Only necessary when passing in config - * - * @returns {lm.items.AbtractContentItem} - */ - _$normalizeContentItem: function( contentItemOrConfig, parent ) { - if( !contentItemOrConfig ) { - throw new Error( 'No content item defined' ); - } - - if( lm.utils.isFunction( contentItemOrConfig ) ) { - contentItemOrConfig = contentItemOrConfig(); - } - - if( contentItemOrConfig instanceof lm.items.AbstractContentItem ) { - return contentItemOrConfig; - } - - if( $.isPlainObject( contentItemOrConfig ) && contentItemOrConfig.type ) { - var newContentItem = this.createContentItem( contentItemOrConfig, parent ); - newContentItem.callDownwards( '_$init' ); - return newContentItem; - } else { - throw new Error( 'Invalid contentItem' ); - } - }, - - /** - * Iterates through the array of open popout windows and removes the ones - * that are effectively closed. This is necessary due to the lack of reliably - * listening for window.close / unload events in a cross browser compatible fashion. - * - * @packagePrivate - * - * @returns {void} - */ - _$reconcilePopoutWindows: function() { - var openPopouts = [], i; - - for( i = 0; i < this.openPopouts.length; i++ ) { - if( this.openPopouts[ i ].getWindow().closed === false ) { - openPopouts.push( this.openPopouts[ i ] ); - } else { - this.emit( 'windowClosed', this.openPopouts[ i ] ); - } - } - - if( this.openPopouts.length !== openPopouts.length ) { - this.emit( 'stateChanged' ); - this.openPopouts = openPopouts; - } - - }, - - /*************************** - * PRIVATE - ***************************/ - /** - * Returns a flattened array of all content items, - * regardles of level or type - * - * @private - * - * @returns {void} - */ - _getAllContentItems: function() { - var allContentItems = []; - - var addChildren = function( contentItem ) { - allContentItems.push( contentItem ); - - if( contentItem.contentItems instanceof Array ) { - for( var i = 0; i < contentItem.contentItems.length; i++ ) { - addChildren( contentItem.contentItems[ i ] ); - } - } - }; - - addChildren( this.root ); - - return allContentItems; - }, - - /** - * Binds to DOM/BOM events on init - * - * @private - * - * @returns {void} - */ - _bindEvents: function() { - if( this._isFullPage ) { - $( window ).resize( this._resizeFunction ); - } - $( window ).on( 'unload beforeunload', this._unloadFunction ); - }, - - /** - * Debounces resize events - * - * @private - * - * @returns {void} - */ - _onResize: function() { - clearTimeout( this._resizeTimeoutId ); - this._resizeTimeoutId = setTimeout( lm.utils.fnBind( this.updateSize, this ), 100 ); - }, - - /** - * Extends the default config with the user specific settings and applies - * derivations. Please note that there's a seperate method (AbstractContentItem._extendItemNode) - * that deals with the extension of item configs - * - * @param {Object} config - * @static - * @returns {Object} config - */ - _createConfig: function( config ) { - var windowConfigKey = lm.utils.getQueryStringParam( 'gl-window' ); - - if( windowConfigKey ) { - this.isSubWindow = true; - config = localStorage.getItem( windowConfigKey ); - config = JSON.parse( config ); - config = ( new lm.utils.ConfigMinifier() ).unminifyConfig( config ); - localStorage.removeItem( windowConfigKey ); - } - - config = $.extend( true, {}, lm.config.defaultConfig, config ); - - var nextNode = function( node ) { - for( var key in node ) { - if( key !== 'props' && typeof node[ key ] === 'object' ) { - nextNode( node[ key ] ); - } - else if( key === 'type' && node[ key ] === 'react-component' ) { - node.type = 'component'; - node.componentName = 'lm-react-component'; - } - } - } - - nextNode( config ); - - if( config.settings.hasHeaders === false ) { - config.dimensions.headerHeight = 0; - } - - return config; - }, - - /** - * This is executed when GoldenLayout detects that it is run - * within a previously opened popout window. - * - * @private - * - * @returns {void} - */ - _adjustToWindowMode: function() { - var popInButton = $( '
' + - '
' + - '
' + - '
' ); - - popInButton.click( lm.utils.fnBind( function() { - this.emit( 'popIn' ); - }, this ) ); - - document.title = lm.utils.stripTags( this.config.content[ 0 ].title ); - - $( 'head' ).append( $( 'body link, body style, template, .gl_keep' ) ); - - this.container = $( 'body' ) - .html( '' ) - .css( 'visibility', 'visible' ) - .append( popInButton ); - - /* - * This seems a bit pointless, but actually causes a reflow/re-evaluation getting around - * slickgrid's "Cannot find stylesheet." bug in chrome - */ - var x = document.body.offsetHeight; // jshint ignore:line - - /* - * Expose this instance on the window object - * to allow the opening window to interact with - * it - */ - window.__glInstance = this; - }, - - /** - * Creates Subwindows (if there are any). Throws an error - * if popouts are blocked. - * - * @returns {void} - */ - _createSubWindows: function() { - var i, popout; - - for( i = 0; i < this.config.openPopouts.length; i++ ) { - popout = this.config.openPopouts[ i ]; - - this.createPopout( - popout.content, - popout.dimensions, - popout.parentId, - popout.indexInParent - ); - } - }, - - /** - * Determines what element the layout will be created in - * - * @private - * - * @returns {void} - */ - _setContainer: function() { - var container = $( this.container || 'body' ); - - if( container.length === 0 ) { - throw new Error( 'GoldenLayout container not found' ); - } - - if( container.length > 1 ) { - throw new Error( 'GoldenLayout more than one container element specified' ); - } - - if( container[ 0 ] === document.body ) { - this._isFullPage = true; - - $( 'html, body' ).css( { - height: '100%', - margin: 0, - padding: 0, - overflow: 'hidden' - } ); - } - - this.container = container; - }, - - /** - * Kicks of the initial, recursive creation chain - * - * @param {Object} config GoldenLayout Config - * - * @returns {void} - */ - _create: function( config ) { - var errorMsg; - - if( !( config.content instanceof Array ) ) { - if( config.content === undefined ) { - errorMsg = 'Missing setting \'content\' on top level of configuration'; - } else { - errorMsg = 'Configuration parameter \'content\' must be an array'; - } - - throw new lm.errors.ConfigurationError( errorMsg, config ); - } - - if( config.content.length > 1 ) { - errorMsg = 'Top level content can\'t contain more then one element.'; - throw new lm.errors.ConfigurationError( errorMsg, config ); - } - - this.root = new lm.items.Root( this, { content: config.content }, this.container ); - this.root.callDownwards( '_$init' ); - - if( config.maximisedItemId === '__glMaximised' ) { - this.root.getItemsById( config.maximisedItemId )[ 0 ].toggleMaximise(); - } - }, - - /** - * Called when the window is closed or the user navigates away - * from the page - * - * @returns {void} - */ - _onUnload: function() { - if( this.config.settings.closePopoutsOnUnload === true ) { - for( var i = 0; i < this.openPopouts.length; i++ ) { - this.openPopouts[ i ].close(); - } - } - }, - - /** - * Adjusts the number of columns to be lower to fit the screen and still maintain minItemWidth. - * - * @returns {void} - */ - _adjustColumnsResponsive: function() { - - // If there is no min width set, or not content items, do nothing. - if( !this._useResponsiveLayout() || this._updatingColumnsResponsive || !this.config.dimensions || !this.config.dimensions.minItemWidth || this.root.contentItems.length === 0 || !this.root.contentItems[ 0 ].isRow ) { - this._firstLoad = false; - return; - } - - this._firstLoad = false; - - // If there is only one column, do nothing. - var columnCount = this.root.contentItems[ 0 ].contentItems.length; - if( columnCount <= 1 ) { - return; - } - - // If they all still fit, do nothing. - var minItemWidth = this.config.dimensions.minItemWidth; - var totalMinWidth = columnCount * minItemWidth; - if( totalMinWidth <= this.width ) { - return; - } - - // Prevent updates while it is already happening. - this._updatingColumnsResponsive = true; - - // Figure out how many columns to stack, and put them all in the first stack container. - var finalColumnCount = Math.max( Math.floor( this.width / minItemWidth ), 1 ); - var stackColumnCount = columnCount - finalColumnCount; - - var rootContentItem = this.root.contentItems[ 0 ]; - var firstStackContainer = this._findAllStackContainers()[ 0 ]; - for( var i = 0; i < stackColumnCount; i++ ) { - // Stack from right. - var column = rootContentItem.contentItems[ rootContentItem.contentItems.length - 1 ]; - this._addChildContentItemsToContainer( firstStackContainer, column ); - } - - this._updatingColumnsResponsive = false; - }, - - /** - * Determines if responsive layout should be used. - * - * @returns {bool} - True if responsive layout should be used; otherwise false. - */ - _useResponsiveLayout: function() { - return this.config.settings && ( this.config.settings.responsiveMode == 'always' || ( this.config.settings.responsiveMode == 'onload' && this._firstLoad ) ); - }, - - /** - * Adds all children of a node to another container recursively. - * @param {object} container - Container to add child content items to. - * @param {object} node - Node to search for content items. - * @returns {void} - */ - _addChildContentItemsToContainer: function( container, node ) { - if( node.type === 'stack' ) { - node.contentItems.forEach( function( item ) { - container.addChild( item ); - node.removeChild( item, true ); - } ); - } - else { - node.contentItems.forEach( lm.utils.fnBind( function( item ) { - this._addChildContentItemsToContainer( container, item ); - }, this ) ); - } - }, - - /** - * Finds all the stack containers. - * @returns {array} - The found stack containers. - */ - _findAllStackContainers: function() { - var stackContainers = []; - this._findAllStackContainersRecursive( stackContainers, this.root ); - - return stackContainers; - }, - - /** - * Finds all the stack containers. - * - * @param {array} - Set of containers to populate. - * @param {object} - Current node to process. - * - * @returns {void} - */ - _findAllStackContainersRecursive: function( stackContainers, node ) { - node.contentItems.forEach( lm.utils.fnBind( function( item ) { - if( item.type == 'stack' ) { - stackContainers.push( item ); - } - else if( !item.isComponent ) { - this._findAllStackContainersRecursive( stackContainers, item ); - } - }, this ) ); - } -} ); - -/** - * Expose the Layoutmanager as the single entrypoint using UMD - */ -(function() { - /* global define */ - if( typeof define === 'function' && define.amd ) { - define( [ 'jquery' ], function( jquery ) { - $ = jquery; - return lm.LayoutManager; - } ); // jshint ignore:line - } else if( typeof exports === 'object' ) { - module.exports = lm.LayoutManager; - } else { - window.GoldenLayout = lm.LayoutManager; - } -})(); - -lm.config.itemDefaultConfig = { - isClosable: true, - reorderEnabled: true, - title: '' -}; -lm.config.defaultConfig = { - openPopouts: [], - settings: { - hasHeaders: true, - constrainDragToContainer: true, - reorderEnabled: true, - selectionEnabled: false, - popoutWholeStack: false, - blockedPopoutsThrowError: true, - closePopoutsOnUnload: true, - showPopoutIcon: true, - showMaximiseIcon: true, - showCloseIcon: true, - responsiveMode: 'onload', // Can be onload, always, or none. - tabOverlapAllowance: 0, // maximum pixel overlap per tab - reorderOnTabMenuClick: true, - tabControlOffset: 10 - }, - dimensions: { - borderWidth: 5, - borderGrabWidth: 15, - minItemHeight: 10, - minItemWidth: 10, - headerHeight: 20, - dragProxyWidth: 300, - dragProxyHeight: 200 - }, - labels: { - close: 'close', - maximise: 'maximise', - minimise: 'minimise', - popout: 'open in new window', - popin: 'pop in', - tabDropdown: 'additional tabs' - } -}; - -lm.container.ItemContainer = function( config, parent, layoutManager ) { - lm.utils.EventEmitter.call( this ); - - this.width = null; - this.height = null; - this.title = config.componentName; - this.parent = parent; - this.layoutManager = layoutManager; - this.isHidden = false; - - this._config = config; - this._element = $( [ - '
', - '
', - '
' - ].join( '' ) ); - - this._contentElement = this._element.find( '.lm_content' ); -}; - -lm.utils.copy( lm.container.ItemContainer.prototype, { - - /** - * Get the inner DOM element the container's content - * is intended to live in - * - * @returns {DOM element} - */ - getElement: function() { - return this._contentElement; - }, - - /** - * Hide the container. Notifies the containers content first - * and then hides the DOM node. If the container is already hidden - * this should have no effect - * - * @returns {void} - */ - hide: function() { - this.emit( 'hide' ); - this.isHidden = true; - this._element.hide(); - }, - - /** - * Shows a previously hidden container. Notifies the - * containers content first and then shows the DOM element. - * If the container is already visible this has no effect. - * - * @returns {void} - */ - show: function() { - this.emit( 'show' ); - this.isHidden = false; - this._element.show(); - // call shown only if the container has a valid size - if( this.height != 0 || this.width != 0 ) { - this.emit( 'shown' ); - } - }, - - /** - * Set the size from within the container. Traverses up - * the item tree until it finds a row or column element - * and resizes its items accordingly. - * - * If this container isn't a descendant of a row or column - * it returns false - * @todo Rework!!! - * @param {Number} width The new width in pixel - * @param {Number} height The new height in pixel - * - * @returns {Boolean} resizeSuccesful - */ - setSize: function( width, height ) { - var rowOrColumn = this.parent, - rowOrColumnChild = this, - totalPixel, - percentage, - direction, - newSize, - delta, - i; - - while( !rowOrColumn.isColumn && !rowOrColumn.isRow ) { - rowOrColumnChild = rowOrColumn; - rowOrColumn = rowOrColumn.parent; - - - /** - * No row or column has been found - */ - if( rowOrColumn.isRoot ) { - return false; - } - } - - direction = rowOrColumn.isColumn ? "height" : "width"; - newSize = direction === "height" ? height : width; - - totalPixel = this[ direction ] * ( 1 / ( rowOrColumnChild.config[ direction ] / 100 ) ); - percentage = ( newSize / totalPixel ) * 100; - delta = ( rowOrColumnChild.config[ direction ] - percentage ) / (rowOrColumn.contentItems.length - 1); - - for( i = 0; i < rowOrColumn.contentItems.length; i++ ) { - if( rowOrColumn.contentItems[ i ] === rowOrColumnChild ) { - rowOrColumn.contentItems[ i ].config[ direction ] = percentage; - } else { - rowOrColumn.contentItems[ i ].config[ direction ] += delta; - } - } - - rowOrColumn.callDownwards( 'setSize' ); - - return true; - }, - - /** - * Closes the container if it is closable. Can be called by - * both the component within at as well as the contentItem containing - * it. Emits a close event before the container itself is closed. - * - * @returns {void} - */ - close: function() { - if( this._config.isClosable ) { - this.emit( 'close' ); - this.parent.close(); - } - }, - - /** - * Returns the current state object - * - * @returns {Object} state - */ - getState: function() { - return this._config.componentState; - }, - - /** - * Merges the provided state into the current one - * - * @param {Object} state - * - * @returns {void} - */ - extendState: function( state ) { - this.setState( $.extend( true, this.getState(), state ) ); - }, - - /** - * Notifies the layout manager of a stateupdate - * - * @param {serialisable} state - */ - setState: function( state ) { - this._config.componentState = state; - this.parent.emitBubblingEvent( 'stateChanged' ); - }, - - /** - * Set's the components title - * - * @param {String} title - */ - setTitle: function( title ) { - this.parent.setTitle( title ); - }, - - /** - * Set's the containers size. Called by the container's component. - * To set the size programmatically from within the container please - * use the public setSize method - * - * @param {[Int]} width in px - * @param {[Int]} height in px - * - * @returns {void} - */ - _$setSize: function( width, height ) { - if( width !== this.width || height !== this.height ) { - this.width = width; - this.height = height; - var cl = this._contentElement[0]; - var hdelta = cl.offsetWidth - cl.clientWidth; - var vdelta = cl.offsetHeight - cl.clientHeight; - this._contentElement.width( this.width-hdelta ) - .height( this.height-vdelta ); - this.emit( 'resize' ); - } - } -} ); - -/** - * Pops a content item out into a new browser window. - * This is achieved by - * - * - Creating a new configuration with the content item as root element - * - Serializing and minifying the configuration - * - Opening the current window's URL with the configuration as a GET parameter - * - GoldenLayout when opened in the new window will look for the GET parameter - * and use it instead of the provided configuration - * - * @param {Object} config GoldenLayout item config - * @param {Object} dimensions A map with width, height, top and left - * @param {String} parentId The id of the element the item will be appended to on popIn - * @param {Number} indexInParent The position of this element within its parent - * @param {lm.LayoutManager} layoutManager - */ -lm.controls.BrowserPopout = function( config, dimensions, parentId, indexInParent, layoutManager ) { - lm.utils.EventEmitter.call( this ); - this.isInitialised = false; - - this._config = config; - this._dimensions = dimensions; - this._parentId = parentId; - this._indexInParent = indexInParent; - this._layoutManager = layoutManager; - this._popoutWindow = null; - this._id = null; - this._createWindow(); -}; - -lm.utils.copy( lm.controls.BrowserPopout.prototype, { - - toConfig: function() { - if( this.isInitialised === false ) { - throw new Error( 'Can\'t create config, layout not yet initialised' ); - return; - } - return { - dimensions: { - width: this.getGlInstance().width, - height: this.getGlInstance().height, - left: this._popoutWindow.screenX || this._popoutWindow.screenLeft, - top: this._popoutWindow.screenY || this._popoutWindow.screenTop - }, - content: this.getGlInstance().toConfig().content, - parentId: this._parentId, - indexInParent: this._indexInParent - }; - }, - - getGlInstance: function() { - return this._popoutWindow.__glInstance; - }, - - getWindow: function() { - return this._popoutWindow; - }, - - close: function() { - if( this.getGlInstance() ) { - this.getGlInstance()._$closeWindow(); - } else { - try { - this.getWindow().close(); - } catch( e ) { - } - } - }, - - /** - * Returns the popped out item to its original position. If the original - * parent isn't available anymore it falls back to the layout's topmost element - */ - popIn: function() { - var childConfig, - parentItem, - index = this._indexInParent; - - if( this._parentId ) { - - /* - * The $.extend call seems a bit pointless, but it's crucial to - * copy the config returned by this.getGlInstance().toConfig() - * onto a new object. Internet Explorer keeps the references - * to objects on the child window, resulting in the following error - * once the child window is closed: - * - * The callee (server [not server application]) is not available and disappeared - */ - childConfig = $.extend( true, {}, this.getGlInstance().toConfig() ).content[ 0 ]; - parentItem = this._layoutManager.root.getItemsById( this._parentId )[ 0 ]; - - /* - * Fallback if parentItem is not available. Either add it to the topmost - * item or make it the topmost item if the layout is empty - */ - if( !parentItem ) { - if( this._layoutManager.root.contentItems.length > 0 ) { - parentItem = this._layoutManager.root.contentItems[ 0 ]; - } else { - parentItem = this._layoutManager.root; - } - index = 0; - } - } - - parentItem.addChild( childConfig, this._indexInParent ); - this.close(); - }, - - /** - * Creates the URL and window parameter - * and opens a new window - * - * @private - * - * @returns {void} - */ - _createWindow: function() { - var checkReadyInterval, - url = this._createUrl(), - - /** - * Bogus title to prevent re-usage of existing window with the - * same title. The actual title will be set by the new window's - * GoldenLayout instance if it detects that it is in subWindowMode - */ - title = Math.floor( Math.random() * 1000000 ).toString( 36 ), - - /** - * The options as used in the window.open string - */ - options = this._serializeWindowOptions( { - width: this._dimensions.width, - height: this._dimensions.height, - innerWidth: this._dimensions.width, - innerHeight: this._dimensions.height, - menubar: 'no', - toolbar: 'no', - location: 'no', - personalbar: 'no', - resizable: 'yes', - scrollbars: 'no', - status: 'no' - } ); - - this._popoutWindow = window.open( url, title, options ); - - if( !this._popoutWindow ) { - if( this._layoutManager.config.settings.blockedPopoutsThrowError === true ) { - var error = new Error( 'Popout blocked' ); - error.type = 'popoutBlocked'; - throw error; - } else { - return; - } - } - - $( this._popoutWindow ) - .on( 'load', lm.utils.fnBind( this._positionWindow, this ) ) - .on( 'unload beforeunload', lm.utils.fnBind( this._onClose, this ) ); - - /** - * Polling the childwindow to find out if GoldenLayout has been initialised - * doesn't seem optimal, but the alternatives - adding a callback to the parent - * window or raising an event on the window object - both would introduce knowledge - * about the parent to the child window which we'd rather avoid - */ - checkReadyInterval = setInterval( lm.utils.fnBind( function() { - if( this._popoutWindow.__glInstance && this._popoutWindow.__glInstance.isInitialised ) { - this._onInitialised(); - clearInterval( checkReadyInterval ); - } - }, this ), 10 ); - }, - - /** - * Serialises a map of key:values to a window options string - * - * @param {Object} windowOptions - * - * @returns {String} serialised window options - */ - _serializeWindowOptions: function( windowOptions ) { - var windowOptionsString = [], key; - - for( key in windowOptions ) { - windowOptionsString.push( key + '=' + windowOptions[ key ] ); - } - - return windowOptionsString.join( ',' ); - }, - - /** - * Creates the URL for the new window, including the - * config GET parameter - * - * @returns {String} URL - */ - _createUrl: function() { - var config = { content: this._config }, - storageKey = 'gl-window-config-' + lm.utils.getUniqueId(), - urlParts; - - config = ( new lm.utils.ConfigMinifier() ).minifyConfig( config ); - - try { - localStorage.setItem( storageKey, JSON.stringify( config ) ); - } catch( e ) { - throw new Error( 'Error while writing to localStorage ' + e.toString() ); - } - - urlParts = document.location.href.split( '?' ); - - // URL doesn't contain GET-parameters - if( urlParts.length === 1 ) { - return urlParts[ 0 ] + '?gl-window=' + storageKey; - - // URL contains GET-parameters - } else { - return document.location.href + '&gl-window=' + storageKey; - } - }, - - /** - * Move the newly created window roughly to - * where the component used to be. - * - * @private - * - * @returns {void} - */ - _positionWindow: function() { - this._popoutWindow.moveTo( this._dimensions.left, this._dimensions.top ); - this._popoutWindow.focus(); - }, - - /** - * Callback when the new window is opened and the GoldenLayout instance - * within it is initialised - * - * @returns {void} - */ - _onInitialised: function() { - this.isInitialised = true; - this.getGlInstance().on( 'popIn', this.popIn, this ); - this.emit( 'initialised' ); - }, - - /** - * Invoked 50ms after the window unload event - * - * @private - * - * @returns {void} - */ - _onClose: function() { - setTimeout( lm.utils.fnBind( this.emit, this, [ 'closed' ] ), 50 ); - } -} ); -/** - * This class creates a temporary container - * for the component whilst it is being dragged - * and handles drag events - * - * @constructor - * @private - * - * @param {Number} x The initial x position - * @param {Number} y The initial y position - * @param {lm.utils.DragListener} dragListener - * @param {lm.LayoutManager} layoutManager - * @param {lm.item.AbstractContentItem} contentItem - * @param {lm.item.AbstractContentItem} originalParent - */ -lm.controls.DragProxy = function( x, y, dragListener, layoutManager, contentItem, originalParent ) { - - lm.utils.EventEmitter.call( this ); - - this._dragListener = dragListener; - this._layoutManager = layoutManager; - this._contentItem = contentItem; - this._originalParent = originalParent; - - this._area = null; - this._lastValidArea = null; - - this._dragListener.on( 'drag', this._onDrag, this ); - this._dragListener.on( 'dragStop', this._onDrop, this ); - - this.element = $( lm.controls.DragProxy._template ); - if( originalParent && originalParent._side ) { - this._sided = originalParent._sided; - this.element.addClass( 'lm_' + originalParent._side ); - if( [ 'right', 'bottom' ].indexOf( originalParent._side ) >= 0 ) - this.element.find( '.lm_content' ).after( this.element.find( '.lm_header' ) ); - } - this.element.css( { left: x, top: y } ); - this.element.find( '.lm_tab' ).attr( 'title', lm.utils.stripTags( this._contentItem.config.title ) ); - this.element.find( '.lm_title' ).html( this._contentItem.config.title ); - this.childElementContainer = this.element.find( '.lm_content' ); - this.childElementContainer.append( contentItem.element ); - - this._updateTree(); - this._layoutManager._$calculateItemAreas(); - this._setDimensions(); - - $( document.body ).append( this.element ); - - var offset = this._layoutManager.container.offset(); - - this._minX = offset.left; - this._minY = offset.top; - this._maxX = this._layoutManager.container.width() + this._minX; - this._maxY = this._layoutManager.container.height() + this._minY; - this._width = this.element.width(); - this._height = this.element.height(); - - this._setDropPosition( x, y ); -}; - -lm.controls.DragProxy._template = '
' + - '
' + - '
    ' + - '
  • ' + - '' + - '
  • ' + - '
' + - '
' + - '
' + - '
'; - -lm.utils.copy( lm.controls.DragProxy.prototype, { - - /** - * Callback on every mouseMove event during a drag. Determines if the drag is - * still within the valid drag area and calls the layoutManager to highlight the - * current drop area - * - * @param {Number} offsetX The difference from the original x position in px - * @param {Number} offsetY The difference from the original y position in px - * @param {jQuery DOM event} event - * - * @private - * - * @returns {void} - */ - _onDrag: function( offsetX, offsetY, event ) { - - event = event.originalEvent && event.originalEvent.touches ? event.originalEvent.touches[ 0 ] : event; - - var x = event.pageX, - y = event.pageY, - isWithinContainer = x > this._minX && x < this._maxX && y > this._minY && y < this._maxY; - - if( !isWithinContainer && this._layoutManager.config.settings.constrainDragToContainer === true ) { - return; - } - - this._setDropPosition( x, y ); - }, - - /** - * Sets the target position, highlighting the appropriate area - * - * @param {Number} x The x position in px - * @param {Number} y The y position in px - * - * @private - * - * @returns {void} - */ - _setDropPosition: function( x, y ) { - this.element.css( { left: x, top: y } ); - this._area = this._layoutManager._$getArea( x, y ); - - if( this._area !== null ) { - this._lastValidArea = this._area; - this._area.contentItem._$highlightDropZone( x, y, this._area ); - } - }, - - /** - * Callback when the drag has finished. Determines the drop area - * and adds the child to it - * - * @private - * - * @returns {void} - */ - _onDrop: function() { - this._layoutManager.dropTargetIndicator.hide(); - - /* - * Valid drop area found - */ - if( this._area !== null ) { - this._area.contentItem._$onDrop( this._contentItem, this._area ); - - /** - * No valid drop area available at present, but one has been found before. - * Use it - */ - } else if( this._lastValidArea !== null ) { - this._lastValidArea.contentItem._$onDrop( this._contentItem, this._lastValidArea ); - - /** - * No valid drop area found during the duration of the drag. Return - * content item to its original position if a original parent is provided. - * (Which is not the case if the drag had been initiated by createDragSource) - */ - } else if( this._originalParent ) { - this._originalParent.addChild( this._contentItem ); - - /** - * The drag didn't ultimately end up with adding the content item to - * any container. In order to ensure clean up happens, destroy the - * content item. - */ - } else { - this._contentItem._$destroy(); - } - - this.element.remove(); - - this._layoutManager.emit( 'itemDropped', this._contentItem ); - }, - - /** - * Removes the item from its original position within the tree - * - * @private - * - * @returns {void} - */ - _updateTree: function() { - - /** - * parent is null if the drag had been initiated by a external drag source - */ - if( this._contentItem.parent ) { - this._contentItem.parent.removeChild( this._contentItem, true ); - } - - this._contentItem._$setParent( this ); - }, - - /** - * Updates the Drag Proxie's dimensions - * - * @private - * - * @returns {void} - */ - _setDimensions: function() { - var dimensions = this._layoutManager.config.dimensions, - width = dimensions.dragProxyWidth, - height = dimensions.dragProxyHeight; - - this.element.width( width ); - this.element.height( height ); - width -= ( this._sided ? dimensions.headerHeight : 0 ); - height -= ( !this._sided ? dimensions.headerHeight : 0 ); - this.childElementContainer.width( width ); - this.childElementContainer.height( height ); - this._contentItem.element.width( width ); - this._contentItem.element.height( height ); - this._contentItem.callDownwards( '_$show' ); - this._contentItem.callDownwards( 'setSize' ); - } -} ); - -/** - * Allows for any DOM item to create a component on drag - * start tobe dragged into the Layout - * - * @param {jQuery element} element - * @param {Object} itemConfig the configuration for the contentItem that will be created - * @param {LayoutManager} layoutManager - * - * @constructor - */ -lm.controls.DragSource = function( element, itemConfig, layoutManager ) { - this._element = element; - this._itemConfig = itemConfig; - this._layoutManager = layoutManager; - this._dragListener = null; - - this._createDragListener(); -}; - -lm.utils.copy( lm.controls.DragSource.prototype, { - - /** - * Called initially and after every drag - * - * @returns {void} - */ - _createDragListener: function() { - if( this._dragListener !== null ) { - this._dragListener.destroy(); - } - - this._dragListener = new lm.utils.DragListener( this._element ); - this._dragListener.on( 'dragStart', this._onDragStart, this ); - this._dragListener.on( 'dragStop', this._createDragListener, this ); - }, - - /** - * Callback for the DragListener's dragStart event - * - * @param {int} x the x position of the mouse on dragStart - * @param {int} y the x position of the mouse on dragStart - * - * @returns {void} - */ - _onDragStart: function( x, y ) { - var itemConfig = this._itemConfig; - if( lm.utils.isFunction( itemConfig ) ) { - itemConfig = itemConfig(); - } - var contentItem = this._layoutManager._$normalizeContentItem( $.extend( true, {}, itemConfig ) ), - dragProxy = new lm.controls.DragProxy( x, y, this._dragListener, this._layoutManager, contentItem, null ); - - this._layoutManager.transitionIndicator.transitionElements( this._element, dragProxy.element ); - } -} ); - -lm.controls.DropTargetIndicator = function() { - this.element = $( lm.controls.DropTargetIndicator._template ); - $( document.body ).append( this.element ); -}; - -lm.controls.DropTargetIndicator._template = '
'; - -lm.utils.copy( lm.controls.DropTargetIndicator.prototype, { - destroy: function() { - this.element.remove(); - }, - - highlight: function( x1, y1, x2, y2 ) { - this.highlightArea( { x1: x1, y1: y1, x2: x2, y2: y2 } ); - }, - - highlightArea: function( area ) { - this.element.css( { - left: area.x1, - top: area.y1, - width: area.x2 - area.x1, - height: area.y2 - area.y1 - } ).show(); - }, - - hide: function() { - this.element.hide(); - } -} ); -/** - * This class represents a header above a Stack ContentItem. - * - * @param {lm.LayoutManager} layoutManager - * @param {lm.item.AbstractContentItem} parent - */ -lm.controls.Header = function( layoutManager, parent ) { - lm.utils.EventEmitter.call( this ); - - this.layoutManager = layoutManager; - this.element = $( lm.controls.Header._template ); - - if( this.layoutManager.config.settings.selectionEnabled === true ) { - this.element.addClass( 'lm_selectable' ); - this.element.on( 'click touchstart', lm.utils.fnBind( this._onHeaderClick, this ) ); - } - - this.tabsContainer = this.element.find( '.lm_tabs' ); - this.tabDropdownContainer = this.element.find( '.lm_tabdropdown_list' ); - this.tabDropdownContainer.hide(); - this.controlsContainer = this.element.find( '.lm_controls' ); - this.parent = parent; - this.parent.on( 'resize', this._updateTabSizes, this ); - this.tabs = []; - this.activeContentItem = null; - this.closeButton = null; - this.tabDropdownButton = null; - this.hideAdditionalTabsDropdown = lm.utils.fnBind(this._hideAdditionalTabsDropdown, this); - $( document ).mouseup(this.hideAdditionalTabsDropdown); - - this._lastVisibleTabIndex = -1; - this._tabControlOffset = this.layoutManager.config.settings.tabControlOffset; - this._createControls(); -}; - -lm.controls.Header._template = [ - '
', - '
    ', - '
      ', - '
        ', - '
        ' -].join( '' ); - -lm.utils.copy( lm.controls.Header.prototype, { - - /** - * Creates a new tab and associates it with a contentItem - * - * @param {lm.item.AbstractContentItem} contentItem - * @param {Integer} index The position of the tab - * - * @returns {void} - */ - createTab: function( contentItem, index ) { - var tab, i; - - //If there's already a tab relating to the - //content item, don't do anything - for( i = 0; i < this.tabs.length; i++ ) { - if( this.tabs[ i ].contentItem === contentItem ) { - return; - } - } - - tab = new lm.controls.Tab( this, contentItem ); - - if( this.tabs.length === 0 ) { - this.tabs.push( tab ); - this.tabsContainer.append( tab.element ); - return; - } - - if( index === undefined ) { - index = this.tabs.length; - } - - if( index > 0 ) { - this.tabs[ index - 1 ].element.after( tab.element ); - } else { - this.tabs[ 0 ].element.before( tab.element ); - } - - this.tabs.splice( index, 0, tab ); - this._updateTabSizes(); - }, - - /** - * Finds a tab based on the contentItem its associated with and removes it. - * - * @param {lm.item.AbstractContentItem} contentItem - * - * @returns {void} - */ - removeTab: function( contentItem ) { - for( var i = 0; i < this.tabs.length; i++ ) { - if( this.tabs[ i ].contentItem === contentItem ) { - this.tabs[ i ]._$destroy(); - this.tabs.splice( i, 1 ); - return; - } - } - - throw new Error( 'contentItem is not controlled by this header' ); - }, - - /** - * The programmatical equivalent of clicking a Tab. - * - * @param {lm.item.AbstractContentItem} contentItem - */ - setActiveContentItem: function( contentItem ) { - var i, j, isActive, activeTab; - - for( i = 0; i < this.tabs.length; i++ ) { - isActive = this.tabs[ i ].contentItem === contentItem; - this.tabs[ i ].setActive( isActive ); - if( isActive === true ) { - this.activeContentItem = contentItem; - this.parent.config.activeItemIndex = i; - } - } - - if (this.layoutManager.config.settings.reorderOnTabMenuClick) { - /** - * If the tab selected was in the dropdown, move everything down one to make way for this one to be the first. - * This will make sure the most used tabs stay visible. - */ - if (this._lastVisibleTabIndex !== -1 && this.parent.config.activeItemIndex > this._lastVisibleTabIndex) { - activeTab = this.tabs[this.parent.config.activeItemIndex]; - for ( j = this.parent.config.activeItemIndex; j > 0; j-- ) { - this.tabs[j] = this.tabs[j - 1]; - } - this.tabs[0] = activeTab; - this.parent.config.activeItemIndex = 0; - } - } - - this._updateTabSizes(); - this.parent.emitBubblingEvent( 'stateChanged' ); - }, - - /** - * Programmatically operate with header position. - * - * @param {string} position one of ('top','left','right','bottom') to set or empty to get it. - * - * @returns {string} previous header position - */ - position: function( position ) { - var previous = this.parent._header.show; - if( previous && !this.parent._side ) - previous = 'top'; - if( position !== undefined && this.parent._header.show != position ) { - this.parent._header.show = position; - this.parent._setupHeaderPosition(); - } - return previous; - }, - - /** - * Programmatically set closability. - * - * @package private - * @param {Boolean} isClosable Whether to enable/disable closability. - * - * @returns {Boolean} Whether the action was successful - */ - _$setClosable: function( isClosable ) { - if( this.closeButton && this._isClosable() ) { - this.closeButton.element[ isClosable ? "show" : "hide" ](); - return true; - } - - return false; - }, - - /** - * Destroys the entire header - * - * @package private - * - * @returns {void} - */ - _$destroy: function() { - this.emit( 'destroy', this ); - - for( var i = 0; i < this.tabs.length; i++ ) { - this.tabs[ i ]._$destroy(); - } - $( document ).off('mouseup', this.hideAdditionalTabsDropdown); - this.element.remove(); - }, - - /** - * get settings from header - * - * @returns {string} when exists - */ - _getHeaderSetting: function( name ) { - if( name in this.parent._header ) - return this.parent._header[ name ]; - }, - /** - * Creates the popout, maximise and close buttons in the header's top right corner - * - * @returns {void} - */ - _createControls: function() { - var closeStack, - popout, - label, - maximiseLabel, - minimiseLabel, - maximise, - maximiseButton, - tabDropdownLabel, - showTabDropdown; - - /** - * Dropdown to show additional tabs. - */ - showTabDropdown = lm.utils.fnBind( this._showAdditionalTabsDropdown, this ); - tabDropdownLabel = this.layoutManager.config.labels.tabDropdown; - this.tabDropdownButton = new lm.controls.HeaderButton( this, tabDropdownLabel, 'lm_tabdropdown', showTabDropdown ); - this.tabDropdownButton.element.hide(); - - /** - * Popout control to launch component in new window. - */ - if( this._getHeaderSetting( 'popout' ) ) { - popout = lm.utils.fnBind( this._onPopoutClick, this ); - label = this._getHeaderSetting( 'popout' ); - new lm.controls.HeaderButton( this, label, 'lm_popout', popout ); - } - - /** - * Maximise control - set the component to the full size of the layout - */ - if( this._getHeaderSetting( 'maximise' ) ) { - maximise = lm.utils.fnBind( this.parent.toggleMaximise, this.parent ); - maximiseLabel = this._getHeaderSetting( 'maximise' ); - minimiseLabel = this._getHeaderSetting( 'minimise' ); - maximiseButton = new lm.controls.HeaderButton( this, maximiseLabel, 'lm_maximise', maximise ); - - this.parent.on( 'maximised', function() { - maximiseButton.element.attr( 'title', minimiseLabel ); - } ); - - this.parent.on( 'minimised', function() { - maximiseButton.element.attr( 'title', maximiseLabel ); - } ); - } - - /** - * Close button - */ - if( this._isClosable() ) { - closeStack = lm.utils.fnBind( this.parent.remove, this.parent ); - label = this._getHeaderSetting( 'close' ); - this.closeButton = new lm.controls.HeaderButton( this, label, 'lm_close', closeStack ); - } - }, - - /** - * Shows drop down for additional tabs when there are too many to display. - * - * @returns {void} - */ - _showAdditionalTabsDropdown: function() { - this.tabDropdownContainer.show(); - }, - - /** - * Hides drop down for additional tabs when there are too many to display. - * - * @returns {void} - */ - _hideAdditionalTabsDropdown: function( e ) { - this.tabDropdownContainer.hide(); - }, - - /** - * Checks whether the header is closable based on the parent config and - * the global config. - * - * @returns {Boolean} Whether the header is closable. - */ - _isClosable: function() { - return this.parent.config.isClosable && this.layoutManager.config.settings.showCloseIcon; - }, - - _onPopoutClick: function() { - if( this.layoutManager.config.settings.popoutWholeStack === true ) { - this.parent.popout(); - } else { - this.activeContentItem.popout(); - } - }, - - - /** - * Invoked when the header's background is clicked (not it's tabs or controls) - * - * @param {jQuery DOM event} event - * - * @returns {void} - */ - _onHeaderClick: function( event ) { - if( event.target === this.element[ 0 ] ) { - this.parent.select(); - } - }, - - /** - * Pushes the tabs to the tab dropdown if the available space is not sufficient - * - * @returns {void} - */ - _updateTabSizes: function(showTabMenu) { - if( this.tabs.length === 0 ) { - return; - } - - //Show the menu based on function argument - this.tabDropdownButton.element.toggle(showTabMenu === true); - - var size = function( val ) { - return val ? 'width' : 'height'; - }; - this.element.css( size( !this.parent._sided ), '' ); - this.element[ size( this.parent._sided ) ]( this.layoutManager.config.dimensions.headerHeight ); - var availableWidth = this.element.outerWidth() - this.controlsContainer.outerWidth() - this._tabControlOffset, - cumulativeTabWidth = 0, - visibleTabWidth = 0, - tabElement, - i, - j, - marginLeft, - overlap = 0, - tabWidth, - tabOverlapAllowance = this.layoutManager.config.settings.tabOverlapAllowance, - tabOverlapAllowanceExceeded = false, - activeIndex = (this.activeContentItem ? this.tabs.indexOf(this.activeContentItem.tab) : 0), - activeTab = this.tabs[activeIndex]; - if( this.parent._sided ) - availableWidth = this.element.outerHeight() - this.controlsContainer.outerHeight() - this._tabControlOffset; - this._lastVisibleTabIndex = -1; - - for( i = 0; i < this.tabs.length; i++ ) { - tabElement = this.tabs[ i ].element; - - //Put the tab in the tabContainer so its true width can be checked - this.tabsContainer.append( tabElement ); - tabWidth = tabElement.outerWidth() + parseInt( tabElement.css( 'margin-right' ), 10 ); - - cumulativeTabWidth += tabWidth; - - //Include the active tab's width if it isn't already - //This is to ensure there is room to show the active tab - if (activeIndex <= i) { - visibleTabWidth = cumulativeTabWidth; - } else { - visibleTabWidth = cumulativeTabWidth + activeTab.element.outerWidth() + parseInt(activeTab.element.css('margin-right'), 10); - } - - // If the tabs won't fit, check the overlap allowance. - if( visibleTabWidth > availableWidth ) { - - //Once allowance is exceeded, all remaining tabs go to menu. - if (!tabOverlapAllowanceExceeded) { - - //No overlap for first tab or active tab - //Overlap spreads among non-active, non-first tabs - if (activeIndex > 0 && activeIndex <= i) { - overlap = ( visibleTabWidth - availableWidth ) / (i - 1); - } else { - overlap = ( visibleTabWidth - availableWidth ) / i; - } - - //Check overlap against allowance. - if (overlap < tabOverlapAllowance) { - for ( j = 0; j <= i; j++ ) { - marginLeft = (j !== activeIndex && j !== 0) ? '-' + overlap + 'px' : ''; - this.tabs[j].element.css({'z-index': i - j, 'margin-left': marginLeft}); - } - this._lastVisibleTabIndex = i; - this.tabsContainer.append(tabElement); - } else { - tabOverlapAllowanceExceeded = true; - } - - } else if (i === activeIndex) { - //Active tab should show even if allowance exceeded. (We left room.) - tabElement.css({'z-index': 'auto', 'margin-left': ''}); - this.tabsContainer.append(tabElement); - } - - if (tabOverlapAllowanceExceeded && i !== activeIndex) { - if (showTabMenu) { - //Tab menu already shown, so we just add to it. - tabElement.css({'z-index': 'auto', 'margin-left': ''}); - this.tabDropdownContainer.append(tabElement); - } else { - //We now know the tab menu must be shown, so we have to recalculate everything. - this._updateTabSizes(true); - return; - } - } - - } - else { - this._lastVisibleTabIndex = i; - tabElement.css({'z-index': 'auto', 'margin-left': ''}); - this.tabsContainer.append( tabElement ); - } - } - - } -} ); - - -lm.controls.HeaderButton = function( header, label, cssClass, action ) { - this._header = header; - this.element = $( '
      • ' ); - this._header.on( 'destroy', this._$destroy, this ); - this._action = action; - this.element.on( 'click touchstart', this._action ); - this._header.controlsContainer.append( this.element ); -}; - -lm.utils.copy( lm.controls.HeaderButton.prototype, { - _$destroy: function() { - this.element.off(); - this.element.remove(); - } -} ); -lm.controls.Splitter = function( isVertical, size, grabSize ) { - this._isVertical = isVertical; - this._size = size; - this._grabSize = grabSize < size ? size : grabSize; - - this.element = this._createElement(); - this._dragListener = new lm.utils.DragListener( this.element ); -}; - -lm.utils.copy( lm.controls.Splitter.prototype, { - on: function( event, callback, context ) { - this._dragListener.on( event, callback, context ); - }, - - _$destroy: function() { - this.element.remove(); - }, - - _createElement: function() { - var dragHandle = $( '
        ' ); - var element = $( '
        ' ); - element.append(dragHandle); - - var handleExcessSize = this._grabSize - this._size; - var handleExcessPos = handleExcessSize / 2; - - if( this._isVertical ) { - dragHandle.css( 'top', -handleExcessPos ); - dragHandle.css( 'height', this._size + handleExcessSize ); - element.addClass( 'lm_vertical' ); - element[ 'height' ]( this._size ); - } else { - dragHandle.css( 'left', -handleExcessPos ); - dragHandle.css( 'width', this._size + handleExcessSize ); - element.addClass( 'lm_horizontal' ); - element[ 'width' ]( this._size ); - } - - return element; - } -} ); - -/** - * Represents an individual tab within a Stack's header - * - * @param {lm.controls.Header} header - * @param {lm.items.AbstractContentItem} contentItem - * - * @constructor - */ -lm.controls.Tab = function( header, contentItem ) { - this.header = header; - this.contentItem = contentItem; - this.element = $( lm.controls.Tab._template ); - this.titleElement = this.element.find( '.lm_title' ); - this.closeElement = this.element.find( '.lm_close_tab' ); - this.closeElement[ contentItem.config.isClosable ? 'show' : 'hide' ](); - this.isActive = false; - - this.setTitle( contentItem.config.title ); - this.contentItem.on( 'titleChanged', this.setTitle, this ); - - this._layoutManager = this.contentItem.layoutManager; - - if( - this._layoutManager.config.settings.reorderEnabled === true && - contentItem.config.reorderEnabled === true - ) { - this._dragListener = new lm.utils.DragListener( this.element ); - this._dragListener.on( 'dragStart', this._onDragStart, this ); - this.contentItem.on( 'destroy', this._dragListener.destroy, this._dragListener ); - } - - this._onTabClickFn = lm.utils.fnBind( this._onTabClick, this ); - this._onCloseClickFn = lm.utils.fnBind( this._onCloseClick, this ); - - this.element.on( 'mousedown touchstart', this._onTabClickFn ); - - if( this.contentItem.config.isClosable ) { - this.closeElement.on( 'click touchstart', this._onCloseClickFn ); - this.closeElement.on('mousedown', this._onCloseMousedown); - } else { - this.closeElement.remove(); - } - - this.contentItem.tab = this; - this.contentItem.emit( 'tab', this ); - this.contentItem.layoutManager.emit( 'tabCreated', this ); - - if( this.contentItem.isComponent ) { - this.contentItem.container.tab = this; - this.contentItem.container.emit( 'tab', this ); - } -}; - -/** - * The tab's html template - * - * @type {String} - */ -lm.controls.Tab._template = '
      • ' + - '
        ' + - '
      • '; - -lm.utils.copy( lm.controls.Tab.prototype, { - - /** - * Sets the tab's title to the provided string and sets - * its title attribute to a pure text representation (without - * html tags) of the same string. - * - * @public - * @param {String} title can contain html - */ - setTitle: function( title ) { - this.element.attr( 'title', lm.utils.stripTags( title ) ); - this.titleElement.html( title ); - }, - - /** - * Sets this tab's active state. To programmatically - * switch tabs, use header.setActiveContentItem( item ) instead. - * - * @public - * @param {Boolean} isActive - */ - setActive: function( isActive ) { - if( isActive === this.isActive ) { - return; - } - this.isActive = isActive; - - if( isActive ) { - this.element.addClass( 'lm_active' ); - } else { - this.element.removeClass( 'lm_active' ); - } - }, - - /** - * Destroys the tab - * - * @private - * @returns {void} - */ - _$destroy: function() { - this.element.off( 'mousedown touchstart', this._onTabClickFn ); - this.closeElement.off( 'click touchstart', this._onCloseClickFn ); - if( this._dragListener ) { - this.contentItem.off( 'destroy', this._dragListener.destroy, this._dragListener ); - this._dragListener.off( 'dragStart', this._onDragStart ); - this._dragListener = null; - } - this.element.remove(); - }, - - /** - * Callback for the DragListener - * - * @param {Number} x The tabs absolute x position - * @param {Number} y The tabs absolute y position - * - * @private - * @returns {void} - */ - _onDragStart: function( x, y ) { - if( this.contentItem.parent.isMaximised === true ) { - this.contentItem.parent.toggleMaximise(); - } - new lm.controls.DragProxy( - x, - y, - this._dragListener, - this._layoutManager, - this.contentItem, - this.header.parent - ); - }, - - /** - * Callback when the tab is clicked - * - * @param {jQuery DOM event} event - * - * @private - * @returns {void} - */ - _onTabClick: function( event ) { - // left mouse button or tap - if( event.button === 0 || event.type === 'touchstart' ) { - var activeContentItem = this.header.parent.getActiveContentItem(); - if( this.contentItem !== activeContentItem ) { - this.header.parent.setActiveContentItem( this.contentItem ); - } - - // middle mouse button - } else if( event.button === 1 && this.contentItem.config.isClosable ) { - this._onCloseClick( event ); - } - }, - - /** - * Callback when the tab's close button is - * clicked - * - * @param {jQuery DOM event} event - * - * @private - * @returns {void} - */ - _onCloseClick: function( event ) { - event.stopPropagation(); - this.header.parent.removeChild( this.contentItem ); - }, - - - /** - * Callback to capture tab close button mousedown - * to prevent tab from activating. - * - * @param (jQuery DOM event) event - * - * @private - * @returns {void} - */ - _onCloseMousedown: function(event) { - event.stopPropagation(); - } -} ); - -lm.controls.TransitionIndicator = function() { - this._element = $( '
        ' ); - $( document.body ).append( this._element ); - - this._toElement = null; - this._fromDimensions = null; - this._totalAnimationDuration = 200; - this._animationStartTime = null; -}; - -lm.utils.copy( lm.controls.TransitionIndicator.prototype, { - destroy: function() { - this._element.remove(); - }, - - transitionElements: function( fromElement, toElement ) { - /** - * TODO - This is not quite as cool as expected. Review. - */ - return; - this._toElement = toElement; - this._animationStartTime = lm.utils.now(); - this._fromDimensions = this._measure( fromElement ); - this._fromDimensions.opacity = 0.8; - this._element.show().css( this._fromDimensions ); - lm.utils.animFrame( lm.utils.fnBind( this._nextAnimationFrame, this ) ); - }, - - _nextAnimationFrame: function() { - var toDimensions = this._measure( this._toElement ), - animationProgress = ( lm.utils.now() - this._animationStartTime ) / this._totalAnimationDuration, - currentFrameStyles = {}, - cssProperty; - - if( animationProgress >= 1 ) { - this._element.hide(); - return; - } - - toDimensions.opacity = 0; - - for( cssProperty in this._fromDimensions ) { - currentFrameStyles[ cssProperty ] = this._fromDimensions[ cssProperty ] + - ( toDimensions[ cssProperty ] - this._fromDimensions[ cssProperty ] ) * - animationProgress; - } - - this._element.css( currentFrameStyles ); - lm.utils.animFrame( lm.utils.fnBind( this._nextAnimationFrame, this ) ); - }, - - _measure: function( element ) { - var offset = element.offset(); - - return { - left: offset.left, - top: offset.top, - width: element.outerWidth(), - height: element.outerHeight() - }; - } -} ); -lm.errors.ConfigurationError = function( message, node ) { - Error.call( this ); - - this.name = 'Configuration Error'; - this.message = message; - this.node = node; -}; - -lm.errors.ConfigurationError.prototype = new Error(); - -/** - * This is the baseclass that all content items inherit from. - * Most methods provide a subset of what the sub-classes do. - * - * It also provides a number of functions for tree traversal - * - * @param {lm.LayoutManager} layoutManager - * @param {item node configuration} config - * @param {lm.item} parent - * - * @event stateChanged - * @event beforeItemDestroyed - * @event itemDestroyed - * @event itemCreated - * @event componentCreated - * @event rowCreated - * @event columnCreated - * @event stackCreated - * - * @constructor - */ -lm.items.AbstractContentItem = function( layoutManager, config, parent ) { - lm.utils.EventEmitter.call( this ); - - this.config = this._extendItemNode( config ); - this.type = config.type; - this.contentItems = []; - this.parent = parent; - - this.isInitialised = false; - this.isMaximised = false; - this.isRoot = false; - this.isRow = false; - this.isColumn = false; - this.isStack = false; - this.isComponent = false; - - this.layoutManager = layoutManager; - this._pendingEventPropagations = {}; - this._throttledEvents = [ 'stateChanged' ]; - - this.on( lm.utils.EventEmitter.ALL_EVENT, this._propagateEvent, this ); - - if( config.content ) { - this._createContentItems( config ); - } -}; - -lm.utils.copy( lm.items.AbstractContentItem.prototype, { - - /** - * Set the size of the component and its children, called recursively - * - * @abstract - * @returns void - */ - setSize: function() { - throw new Error( 'Abstract Method' ); - }, - - /** - * Calls a method recursively downwards on the tree - * - * @param {String} functionName the name of the function to be called - * @param {[Array]}functionArguments optional arguments that are passed to every function - * @param {[bool]} bottomUp Call methods from bottom to top, defaults to false - * @param {[bool]} skipSelf Don't invoke the method on the class that calls it, defaults to false - * - * @returns {void} - */ - callDownwards: function( functionName, functionArguments, bottomUp, skipSelf ) { - var i; - - if( bottomUp !== true && skipSelf !== true ) { - this[ functionName ].apply( this, functionArguments || [] ); - } - for( i = 0; i < this.contentItems.length; i++ ) { - this.contentItems[ i ].callDownwards( functionName, functionArguments, bottomUp ); - } - if( bottomUp === true && skipSelf !== true ) { - this[ functionName ].apply( this, functionArguments || [] ); - } - }, - - /** - * Removes a child node (and its children) from the tree - * - * @param {lm.items.ContentItem} contentItem - * - * @returns {void} - */ - removeChild: function( contentItem, keepChild ) { - - /* - * Get the position of the item that's to be removed within all content items this node contains - */ - var index = lm.utils.indexOf( contentItem, this.contentItems ); - - /* - * Make sure the content item to be removed is actually a child of this item - */ - if( index === -1 ) { - throw new Error( 'Can\'t remove child item. Unknown content item' ); - } - - /** - * Call ._$destroy on the content item. This also calls ._$destroy on all its children - */ - if( keepChild !== true ) { - this.contentItems[ index ]._$destroy(); - } - - /** - * Remove the content item from this nodes array of children - */ - this.contentItems.splice( index, 1 ); - - /** - * Remove the item from the configuration - */ - this.config.content.splice( index, 1 ); - - /** - * If this node still contains other content items, adjust their size - */ - if( this.contentItems.length > 0 ) { - this.callDownwards( 'setSize' ); - - /** - * If this was the last content item, remove this node as well - */ - } else if( !(this instanceof lm.items.Root) && this.config.isClosable === true ) { - this.parent.removeChild( this ); - } - }, - - /** - * Sets up the tree structure for the newly added child - * The responsibility for the actual DOM manipulations lies - * with the concrete item - * - * @param {lm.items.AbstractContentItem} contentItem - * @param {[Int]} index If omitted item will be appended - */ - addChild: function( contentItem, index ) { - if( index === undefined ) { - index = this.contentItems.length; - } - - this.contentItems.splice( index, 0, contentItem ); - - if( this.config.content === undefined ) { - this.config.content = []; - } - - this.config.content.splice( index, 0, contentItem.config ); - contentItem.parent = this; - - if( contentItem.parent.isInitialised === true && contentItem.isInitialised === false ) { - contentItem._$init(); - } - }, - - /** - * Replaces oldChild with newChild. This used to use jQuery.replaceWith... which for - * some reason removes all event listeners, so isn't really an option. - * - * @param {lm.item.AbstractContentItem} oldChild - * @param {lm.item.AbstractContentItem} newChild - * - * @returns {void} - */ - replaceChild: function( oldChild, newChild, _$destroyOldChild ) { - - newChild = this.layoutManager._$normalizeContentItem( newChild ); - - var index = lm.utils.indexOf( oldChild, this.contentItems ), - parentNode = oldChild.element[ 0 ].parentNode; - - if( index === -1 ) { - throw new Error( 'Can\'t replace child. oldChild is not child of this' ); - } - - parentNode.replaceChild( newChild.element[ 0 ], oldChild.element[ 0 ] ); - - /* - * Optionally destroy the old content item - */ - if( _$destroyOldChild === true ) { - oldChild.parent = null; - oldChild._$destroy(); - } - - /* - * Wire the new contentItem into the tree - */ - this.contentItems[ index ] = newChild; - newChild.parent = this; - - /* - * Update tab reference - */ - if( this.isStack ) { - this.header.tabs[ index ].contentItem = newChild; - } - - //TODO This doesn't update the config... refactor to leave item nodes untouched after creation - if( newChild.parent.isInitialised === true && newChild.isInitialised === false ) { - newChild._$init(); - } - - this.callDownwards( 'setSize' ); - }, - - /** - * Convenience method. - * Shorthand for this.parent.removeChild( this ) - * - * @returns {void} - */ - remove: function() { - this.parent.removeChild( this ); - }, - - /** - * Removes the component from the layout and creates a new - * browser window with the component and its children inside - * - * @returns {lm.controls.BrowserPopout} - */ - popout: function() { - var browserPopout = this.layoutManager.createPopout( this ); - this.emitBubblingEvent( 'stateChanged' ); - return browserPopout; - }, - - /** - * Maximises the Item or minimises it if it is already maximised - * - * @returns {void} - */ - toggleMaximise: function( e ) { - e && e.preventDefault(); - if( this.isMaximised === true ) { - this.layoutManager._$minimiseItem( this ); - } else { - this.layoutManager._$maximiseItem( this ); - } - - this.isMaximised = !this.isMaximised; - this.emitBubblingEvent( 'stateChanged' ); - }, - - /** - * Selects the item if it is not already selected - * - * @returns {void} - */ - select: function() { - if( this.layoutManager.selectedItem !== this ) { - this.layoutManager.selectItem( this, true ); - this.element.addClass( 'lm_selected' ); - } - }, - - /** - * De-selects the item if it is selected - * - * @returns {void} - */ - deselect: function() { - if( this.layoutManager.selectedItem === this ) { - this.layoutManager.selectedItem = null; - this.element.removeClass( 'lm_selected' ); - } - }, - - /** - * Set this component's title - * - * @public - * @param {String} title - * - * @returns {void} - */ - setTitle: function( title ) { - this.config.title = title; - this.emit( 'titleChanged', title ); - this.emit( 'stateChanged' ); - }, - - /** - * Checks whether a provided id is present - * - * @public - * @param {String} id - * - * @returns {Boolean} isPresent - */ - hasId: function( id ) { - if( !this.config.id ) { - return false; - } else if( typeof this.config.id === 'string' ) { - return this.config.id === id; - } else if( this.config.id instanceof Array ) { - return lm.utils.indexOf( id, this.config.id ) !== -1; - } - }, - - /** - * Adds an id. Adds it as a string if the component doesn't - * have an id yet or creates/uses an array - * - * @public - * @param {String} id - * - * @returns {void} - */ - addId: function( id ) { - if( this.hasId( id ) ) { - return; - } - - if( !this.config.id ) { - this.config.id = id; - } else if( typeof this.config.id === 'string' ) { - this.config.id = [ this.config.id, id ]; - } else if( this.config.id instanceof Array ) { - this.config.id.push( id ); - } - }, - - /** - * Removes an existing id. Throws an error - * if the id is not present - * - * @public - * @param {String} id - * - * @returns {void} - */ - removeId: function( id ) { - if( !this.hasId( id ) ) { - throw new Error( 'Id not found' ); - } - - if( typeof this.config.id === 'string' ) { - delete this.config.id; - } else if( this.config.id instanceof Array ) { - var index = lm.utils.indexOf( id, this.config.id ); - this.config.id.splice( index, 1 ); - } - }, - - /**************************************** - * SELECTOR - ****************************************/ - getItemsByFilter: function( filter ) { - var result = [], - next = function( contentItem ) { - for( var i = 0; i < contentItem.contentItems.length; i++ ) { - - if( filter( contentItem.contentItems[ i ] ) === true ) { - result.push( contentItem.contentItems[ i ] ); - } - - next( contentItem.contentItems[ i ] ); - } - }; - - next( this ); - return result; - }, - - getItemsById: function( id ) { - return this.getItemsByFilter( function( item ) { - if( item.config.id instanceof Array ) { - return lm.utils.indexOf( id, item.config.id ) !== -1; - } else { - return item.config.id === id; - } - } ); - }, - - getItemsByType: function( type ) { - return this._$getItemsByProperty( 'type', type ); - }, - - getComponentsByName: function( componentName ) { - var components = this._$getItemsByProperty( 'componentName', componentName ), - instances = [], - i; - - for( i = 0; i < components.length; i++ ) { - instances.push( components[ i ].instance ); - } - - return instances; - }, - - /**************************************** - * PACKAGE PRIVATE - ****************************************/ - _$getItemsByProperty: function( key, value ) { - return this.getItemsByFilter( function( item ) { - return item[ key ] === value; - } ); - }, - - _$setParent: function( parent ) { - this.parent = parent; - }, - - _$highlightDropZone: function( x, y, area ) { - this.layoutManager.dropTargetIndicator.highlightArea( area ); - }, - - _$onDrop: function( contentItem ) { - this.addChild( contentItem ); - }, - - _$hide: function() { - this._callOnActiveComponents( 'hide' ); - this.element.hide(); - this.layoutManager.updateSize(); - }, - - _$show: function() { - this._callOnActiveComponents( 'show' ); - this.element.show(); - this.layoutManager.updateSize(); - }, - - _callOnActiveComponents: function( methodName ) { - var stacks = this.getItemsByType( 'stack' ), - activeContentItem, - i; - - for( i = 0; i < stacks.length; i++ ) { - activeContentItem = stacks[ i ].getActiveContentItem(); - - if( activeContentItem && activeContentItem.isComponent ) { - activeContentItem.container[ methodName ](); - } - } - }, - - /** - * Destroys this item ands its children - * - * @returns {void} - */ - _$destroy: function() { - this.emitBubblingEvent( 'beforeItemDestroyed' ); - this.callDownwards( '_$destroy', [], true, true ); - this.element.remove(); - this.emitBubblingEvent( 'itemDestroyed' ); - }, - - /** - * Returns the area the component currently occupies in the format - * - * { - * x1: int - * xy: int - * y1: int - * y2: int - * contentItem: contentItem - * } - */ - _$getArea: function( element ) { - element = element || this.element; - - var offset = element.offset(), - width = element.width(), - height = element.height(); - - return { - x1: offset.left, - y1: offset.top, - x2: offset.left + width, - y2: offset.top + height, - surface: width * height, - contentItem: this - }; - }, - - /** - * The tree of content items is created in two steps: First all content items are instantiated, - * then init is called recursively from top to bottem. This is the basic init function, - * it can be used, extended or overwritten by the content items - * - * Its behaviour depends on the content item - * - * @package private - * - * @returns {void} - */ - _$init: function() { - var i; - this.setSize(); - - for( i = 0; i < this.contentItems.length; i++ ) { - this.childElementContainer.append( this.contentItems[ i ].element ); - } - - this.isInitialised = true; - this.emitBubblingEvent( 'itemCreated' ); - this.emitBubblingEvent( this.type + 'Created' ); - }, - - /** - * Emit an event that bubbles up the item tree. - * - * @param {String} name The name of the event - * - * @returns {void} - */ - emitBubblingEvent: function( name ) { - var event = new lm.utils.BubblingEvent( name, this ); - this.emit( name, event ); - }, - - /** - * Private method, creates all content items for this node at initialisation time - * PLEASE NOTE, please see addChild for adding contentItems add runtime - * @private - * @param {configuration item node} config - * - * @returns {void} - */ - _createContentItems: function( config ) { - var oContentItem, i; - - if( !( config.content instanceof Array ) ) { - throw new lm.errors.ConfigurationError( 'content must be an Array', config ); - } - - for( i = 0; i < config.content.length; i++ ) { - oContentItem = this.layoutManager.createContentItem( config.content[ i ], this ); - this.contentItems.push( oContentItem ); - } - }, - - /** - * Extends an item configuration node with default settings - * @private - * @param {configuration item node} config - * - * @returns {configuration item node} extended config - */ - _extendItemNode: function( config ) { - - for( var key in lm.config.itemDefaultConfig ) { - if( config[ key ] === undefined ) { - config[ key ] = lm.config.itemDefaultConfig[ key ]; - } - } - - return config; - }, - - /** - * Called for every event on the item tree. Decides whether the event is a bubbling - * event and propagates it to its parent - * - * @param {String} name the name of the event - * @param {lm.utils.BubblingEvent} event - * - * @returns {void} - */ - _propagateEvent: function( name, event ) { - if( event instanceof lm.utils.BubblingEvent && - event.isPropagationStopped === false && - this.isInitialised === true ) { - - /** - * In some cases (e.g. if an element is created from a DragSource) it - * doesn't have a parent and is not below root. If that's the case - * propagate the bubbling event from the top level of the substree directly - * to the layoutManager - */ - if( this.isRoot === false && this.parent ) { - this.parent.emit.apply( this.parent, Array.prototype.slice.call( arguments, 0 ) ); - } else { - this._scheduleEventPropagationToLayoutManager( name, event ); - } - } - }, - - /** - * All raw events bubble up to the root element. Some events that - * are propagated to - and emitted by - the layoutManager however are - * only string-based, batched and sanitized to make them more usable - * - * @param {String} name the name of the event - * - * @private - * @returns {void} - */ - _scheduleEventPropagationToLayoutManager: function( name, event ) { - if( lm.utils.indexOf( name, this._throttledEvents ) === -1 ) { - this.layoutManager.emit( name, event.origin ); - } else { - if( this._pendingEventPropagations[ name ] !== true ) { - this._pendingEventPropagations[ name ] = true; - lm.utils.animFrame( lm.utils.fnBind( this._propagateEventToLayoutManager, this, [ name, event ] ) ); - } - } - - }, - - /** - * Callback for events scheduled by _scheduleEventPropagationToLayoutManager - * - * @param {String} name the name of the event - * - * @private - * @returns {void} - */ - _propagateEventToLayoutManager: function( name, event ) { - this._pendingEventPropagations[ name ] = false; - this.layoutManager.emit( name, event ); - } -} ); - -/** - * @param {[type]} layoutManager [description] - * @param {[type]} config [description] - * @param {[type]} parent [description] - */ -lm.items.Component = function( layoutManager, config, parent ) { - lm.items.AbstractContentItem.call( this, layoutManager, config, parent ); - - var ComponentConstructor = layoutManager.getComponent( this.config.componentName ), - componentConfig = $.extend( true, {}, this.config.componentState || {} ); - - componentConfig.componentName = this.config.componentName; - this.componentName = this.config.componentName; - - if( this.config.title === '' ) { - this.config.title = this.config.componentName; - } - - this.isComponent = true; - this.container = new lm.container.ItemContainer( this.config, this, layoutManager ); - this.instance = new ComponentConstructor( this.container, componentConfig ); - this.element = this.container._element; -}; - -lm.utils.extend( lm.items.Component, lm.items.AbstractContentItem ); - -lm.utils.copy( lm.items.Component.prototype, { - - close: function() { - this.parent.removeChild( this ); - }, - - setSize: function() { - if( this.element.is( ':visible' ) ) { - // Do not update size of hidden components to prevent unwanted reflows - this.container._$setSize( this.element.width(), this.element.height() ); - } - }, - - _$init: function() { - lm.items.AbstractContentItem.prototype._$init.call( this ); - this.container.emit( 'open' ); - }, - - _$hide: function() { - this.container.hide(); - lm.items.AbstractContentItem.prototype._$hide.call( this ); - }, - - _$show: function() { - this.container.show(); - lm.items.AbstractContentItem.prototype._$show.call( this ); - }, - - _$shown: function() { - this.container.shown(); - lm.items.AbstractContentItem.prototype._$shown.call( this ); - }, - - _$destroy: function() { - this.container.emit( 'destroy', this ); - lm.items.AbstractContentItem.prototype._$destroy.call( this ); - }, - - /** - * Dragging onto a component directly is not an option - * - * @returns null - */ - _$getArea: function() { - return null; - } -} ); - -lm.items.Root = function( layoutManager, config, containerElement ) { - lm.items.AbstractContentItem.call( this, layoutManager, config, null ); - this.isRoot = true; - this.type = 'root'; - this.element = $( '
        ' ); - this.childElementContainer = this.element; - this._containerElement = containerElement; - this._containerElement.append( this.element ); -}; - -lm.utils.extend( lm.items.Root, lm.items.AbstractContentItem ); - -lm.utils.copy( lm.items.Root.prototype, { - addChild: function( contentItem ) { - if( this.contentItems.length > 0 ) { - throw new Error( 'Root node can only have a single child' ); - } - - contentItem = this.layoutManager._$normalizeContentItem( contentItem, this ); - this.childElementContainer.append( contentItem.element ); - lm.items.AbstractContentItem.prototype.addChild.call( this, contentItem ); - - this.callDownwards( 'setSize' ); - this.emitBubblingEvent( 'stateChanged' ); - }, - - setSize: function( width, height ) { - width = (typeof width === 'undefined') ? this._containerElement.width() : width; - height = (typeof height === 'undefined') ? this._containerElement.height() : height; - - this.element.width( width ); - this.element.height( height ); - - /* - * Root can be empty - */ - if( this.contentItems[ 0 ] ) { - this.contentItems[ 0 ].element.width( width ); - this.contentItems[ 0 ].element.height( height ); - } - }, - _$highlightDropZone: function( x, y, area ) { - this.layoutManager.tabDropPlaceholder.remove(); - lm.items.AbstractContentItem.prototype._$highlightDropZone.apply( this, arguments ); - }, - - _$onDrop: function( contentItem, area ) { - var stack; - - if( contentItem.isComponent ) { - stack = this.layoutManager.createContentItem( { - type: 'stack', - header: contentItem.config.header || {} - }, this ); - stack._$init(); - stack.addChild( contentItem ); - contentItem = stack; - } - - if( !this.contentItems.length ) { - this.addChild( contentItem ); - } else { - var type = area.side[ 0 ] == 'x' ? 'row' : 'column'; - var dimension = area.side[ 0 ] == 'x' ? 'width' : 'height'; - var insertBefore = area.side[ 1 ] == '2'; - var column = this.contentItems[ 0 ]; - if( !column instanceof lm.items.RowOrColumn || column.type != type ) { - var rowOrColumn = this.layoutManager.createContentItem( { type: type }, this ); - this.replaceChild( column, rowOrColumn ); - rowOrColumn.addChild( contentItem, insertBefore ? 0 : undefined, true ); - rowOrColumn.addChild( column, insertBefore ? undefined : 0, true ); - column.config[ dimension ] = 50; - contentItem.config[ dimension ] = 50; - rowOrColumn.callDownwards( 'setSize' ); - } else { - var sibbling = column.contentItems[ insertBefore ? 0 : column.contentItems.length - 1 ] - column.addChild( contentItem, insertBefore ? 0 : undefined, true ); - sibbling.config[ dimension ] *= 0.5; - contentItem.config[ dimension ] = sibbling.config[ dimension ]; - column.callDownwards( 'setSize' ); - } - } - } -} ); - - - -lm.items.RowOrColumn = function( isColumn, layoutManager, config, parent ) { - lm.items.AbstractContentItem.call( this, layoutManager, config, parent ); - - this.isRow = !isColumn; - this.isColumn = isColumn; - - this.element = $( '
        ' ); - this.childElementContainer = this.element; - this._splitterSize = layoutManager.config.dimensions.borderWidth; - this._splitterGrabSize = layoutManager.config.dimensions.borderGrabWidth; - this._isColumn = isColumn; - this._dimension = isColumn ? 'height' : 'width'; - this._splitter = []; - this._splitterPosition = null; - this._splitterMinPosition = null; - this._splitterMaxPosition = null; -}; - -lm.utils.extend( lm.items.RowOrColumn, lm.items.AbstractContentItem ); - -lm.utils.copy( lm.items.RowOrColumn.prototype, { - - /** - * Add a new contentItem to the Row or Column - * - * @param {lm.item.AbstractContentItem} contentItem - * @param {[int]} index The position of the new item within the Row or Column. - * If no index is provided the item will be added to the end - * @param {[bool]} _$suspendResize If true the items won't be resized. This will leave the item in - * an inconsistent state and is only intended to be used if multiple - * children need to be added in one go and resize is called afterwards - * - * @returns {void} - */ - addChild: function( contentItem, index, _$suspendResize ) { - - var newItemSize, itemSize, i, splitterElement; - - contentItem = this.layoutManager._$normalizeContentItem( contentItem, this ); - - if( index === undefined ) { - index = this.contentItems.length; - } - - if( this.contentItems.length > 0 ) { - splitterElement = this._createSplitter( Math.max( 0, index - 1 ) ).element; - - if( index > 0 ) { - this.contentItems[ index - 1 ].element.after( splitterElement ); - splitterElement.after( contentItem.element ); - } else { - this.contentItems[ 0 ].element.before( splitterElement ); - splitterElement.before( contentItem.element ); - } - } else { - this.childElementContainer.append( contentItem.element ); - } - - lm.items.AbstractContentItem.prototype.addChild.call( this, contentItem, index ); - - newItemSize = ( 1 / this.contentItems.length ) * 100; - - if( _$suspendResize === true ) { - this.emitBubblingEvent( 'stateChanged' ); - return; - } - - for( i = 0; i < this.contentItems.length; i++ ) { - if( this.contentItems[ i ] === contentItem ) { - contentItem.config[ this._dimension ] = newItemSize; - } else { - itemSize = this.contentItems[ i ].config[ this._dimension ] *= ( 100 - newItemSize ) / 100; - this.contentItems[ i ].config[ this._dimension ] = itemSize; - } - } - - this.callDownwards( 'setSize' ); - this.emitBubblingEvent( 'stateChanged' ); - }, - - /** - * Removes a child of this element - * - * @param {lm.items.AbstractContentItem} contentItem - * @param {boolean} keepChild If true the child will be removed, but not destroyed - * - * @returns {void} - */ - removeChild: function( contentItem, keepChild ) { - var removedItemSize = contentItem.config[ this._dimension ], - index = lm.utils.indexOf( contentItem, this.contentItems ), - splitterIndex = Math.max( index - 1, 0 ), - i, - childItem; - - if( index === -1 ) { - throw new Error( 'Can\'t remove child. ContentItem is not child of this Row or Column' ); - } - - /** - * Remove the splitter before the item or after if the item happens - * to be the first in the row/column - */ - if( this._splitter[ splitterIndex ] ) { - this._splitter[ splitterIndex ]._$destroy(); - this._splitter.splice( splitterIndex, 1 ); - } - - /** - * Allocate the space that the removed item occupied to the remaining items - */ - for( i = 0; i < this.contentItems.length; i++ ) { - if( this.contentItems[ i ] !== contentItem ) { - this.contentItems[ i ].config[ this._dimension ] += removedItemSize / ( this.contentItems.length - 1 ); - } - } - - lm.items.AbstractContentItem.prototype.removeChild.call( this, contentItem, keepChild ); - - if( this.contentItems.length === 1 && this.config.isClosable === true ) { - childItem = this.contentItems[ 0 ]; - this.contentItems = []; - this.parent.replaceChild( this, childItem, true ); - } else { - this.callDownwards( 'setSize' ); - this.emitBubblingEvent( 'stateChanged' ); - } - }, - - /** - * Replaces a child of this Row or Column with another contentItem - * - * @param {lm.items.AbstractContentItem} oldChild - * @param {lm.items.AbstractContentItem} newChild - * - * @returns {void} - */ - replaceChild: function( oldChild, newChild ) { - var size = oldChild.config[ this._dimension ]; - lm.items.AbstractContentItem.prototype.replaceChild.call( this, oldChild, newChild ); - newChild.config[ this._dimension ] = size; - this.callDownwards( 'setSize' ); - this.emitBubblingEvent( 'stateChanged' ); - }, - - /** - * Called whenever the dimensions of this item or one of its parents change - * - * @returns {void} - */ - setSize: function() { - if( this.contentItems.length > 0 ) { - this._calculateRelativeSizes(); - this._setAbsoluteSizes(); - } - this.emitBubblingEvent( 'stateChanged' ); - this.emit( 'resize' ); - }, - - /** - * Invoked recursively by the layout manager. AbstractContentItem.init appends - * the contentItem's DOM elements to the container, RowOrColumn init adds splitters - * in between them - * - * @package private - * @override AbstractContentItem._$init - * @returns {void} - */ - _$init: function() { - if( this.isInitialised === true ) return; - - var i; - - lm.items.AbstractContentItem.prototype._$init.call( this ); - - for( i = 0; i < this.contentItems.length - 1; i++ ) { - this.contentItems[ i ].element.after( this._createSplitter( i ).element ); - } - }, - - /** - * Turns the relative sizes calculated by _calculateRelativeSizes into - * absolute pixel values and applies them to the children's DOM elements - * - * Assigns additional pixels to counteract Math.floor - * - * @private - * @returns {void} - */ - _setAbsoluteSizes: function() { - var i, - sizeData = this._calculateAbsoluteSizes(); - - for( i = 0; i < this.contentItems.length; i++ ) { - if( sizeData.additionalPixel - i > 0 ) { - sizeData.itemSizes[ i ]++; - } - - if( this._isColumn ) { - this.contentItems[ i ].element.width( sizeData.totalWidth ); - this.contentItems[ i ].element.height( sizeData.itemSizes[ i ] ); - } else { - this.contentItems[ i ].element.width( sizeData.itemSizes[ i ] ); - this.contentItems[ i ].element.height( sizeData.totalHeight ); - } - } - }, - - /** - * Calculates the absolute sizes of all of the children of this Item. - * @returns {object} - Set with absolute sizes and additional pixels. - */ - _calculateAbsoluteSizes: function() { - var i, - totalSplitterSize = (this.contentItems.length - 1) * this._splitterSize, - totalWidth = this.element.width(), - totalHeight = this.element.height(), - totalAssigned = 0, - additionalPixel, - itemSize, - itemSizes = []; - - if( this._isColumn ) { - totalHeight -= totalSplitterSize; - } else { - totalWidth -= totalSplitterSize; - } - - for( i = 0; i < this.contentItems.length; i++ ) { - if( this._isColumn ) { - itemSize = Math.floor( totalHeight * ( this.contentItems[ i ].config.height / 100 ) ); - } else { - itemSize = Math.floor( totalWidth * (this.contentItems[ i ].config.width / 100) ); - } - - totalAssigned += itemSize; - itemSizes.push( itemSize ); - } - - additionalPixel = Math.floor( (this._isColumn ? totalHeight : totalWidth) - totalAssigned ); - - return { - itemSizes: itemSizes, - additionalPixel: additionalPixel, - totalWidth: totalWidth, - totalHeight: totalHeight - }; - }, - - /** - * Calculates the relative sizes of all children of this Item. The logic - * is as follows: - * - * - Add up the total size of all items that have a configured size - * - * - If the total == 100 (check for floating point errors) - * Excellent, job done - * - * - If the total is > 100, - * set the size of items without set dimensions to 1/3 and add this to the total - * set the size off all items so that the total is hundred relative to their original size - * - * - If the total is < 100 - * If there are items without set dimensions, distribute the remainder to 100 evenly between them - * If there are no items without set dimensions, increase all items sizes relative to - * their original size so that they add up to 100 - * - * @private - * @returns {void} - */ - _calculateRelativeSizes: function() { - - var i, - total = 0, - itemsWithoutSetDimension = [], - dimension = this._isColumn ? 'height' : 'width'; - - for( i = 0; i < this.contentItems.length; i++ ) { - if( this.contentItems[ i ].config[ dimension ] !== undefined ) { - total += this.contentItems[ i ].config[ dimension ]; - } else { - itemsWithoutSetDimension.push( this.contentItems[ i ] ); - } - } - - /** - * Everything adds up to hundred, all good :-) - */ - if( Math.round( total ) === 100 ) { - this._respectMinItemWidth(); - return; - } - - /** - * Allocate the remaining size to the items without a set dimension - */ - if( Math.round( total ) < 100 && itemsWithoutSetDimension.length > 0 ) { - for( i = 0; i < itemsWithoutSetDimension.length; i++ ) { - itemsWithoutSetDimension[ i ].config[ dimension ] = ( 100 - total ) / itemsWithoutSetDimension.length; - } - this._respectMinItemWidth(); - return; - } - - /** - * If the total is > 100, but there are also items without a set dimension left, assing 50 - * as their dimension and add it to the total - * - * This will be reset in the next step - */ - if( Math.round( total ) > 100 ) { - for( i = 0; i < itemsWithoutSetDimension.length; i++ ) { - itemsWithoutSetDimension[ i ].config[ dimension ] = 50; - total += 50; - } - } - - /** - * Set every items size relative to 100 relative to its size to total - */ - for( i = 0; i < this.contentItems.length; i++ ) { - this.contentItems[ i ].config[ dimension ] = ( this.contentItems[ i ].config[ dimension ] / total ) * 100; - } - - this._respectMinItemWidth(); - }, - - /** - * Adjusts the column widths to respect the dimensions minItemWidth if set. - * @returns {} - */ - _respectMinItemWidth: function() { - var minItemWidth = this.layoutManager.config.dimensions ? (this.layoutManager.config.dimensions.minItemWidth || 0) : 0, - sizeData = null, - entriesOverMin = [], - totalOverMin = 0, - totalUnderMin = 0, - remainingWidth = 0, - itemSize = 0, - contentItem = null, - reducePercent, - reducedWidth, - allEntries = [], - entry; - - if( this._isColumn || !minItemWidth || this.contentItems.length <= 1 ) { - return; - } - - sizeData = this._calculateAbsoluteSizes(); - - /** - * Figure out how much we are under the min item size total and how much room we have to use. - */ - for( var i = 0; i < this.contentItems.length; i++ ) { - - contentItem = this.contentItems[ i ]; - itemSize = sizeData.itemSizes[ i ]; - - if( itemSize < minItemWidth ) { - totalUnderMin += minItemWidth - itemSize; - entry = { width: minItemWidth }; - - } - else { - totalOverMin += itemSize - minItemWidth; - entry = { width: itemSize }; - entriesOverMin.push( entry ); - } - - allEntries.push( entry ); - } - - /** - * If there is nothing under min, or there is not enough over to make up the difference, do nothing. - */ - if( totalUnderMin === 0 || totalUnderMin > totalOverMin ) { - return; - } - - /** - * Evenly reduce all columns that are over the min item width to make up the difference. - */ - reducePercent = totalUnderMin / totalOverMin; - remainingWidth = totalUnderMin; - for( i = 0; i < entriesOverMin.length; i++ ) { - entry = entriesOverMin[ i ]; - reducedWidth = Math.round( ( entry.width - minItemWidth ) * reducePercent ); - remainingWidth -= reducedWidth; - entry.width -= reducedWidth; - } - - /** - * Take anything remaining from the last item. - */ - if( remainingWidth !== 0 ) { - allEntries[ allEntries.length - 1 ].width -= remainingWidth; - } - - /** - * Set every items size relative to 100 relative to its size to total - */ - for( i = 0; i < this.contentItems.length; i++ ) { - this.contentItems[ i ].config.width = (allEntries[ i ].width / sizeData.totalWidth) * 100; - } - }, - - /** - * Instantiates a new lm.controls.Splitter, binds events to it and adds - * it to the array of splitters at the position specified as the index argument - * - * What it doesn't do though is append the splitter to the DOM - * - * @param {Int} index The position of the splitter - * - * @returns {lm.controls.Splitter} - */ - _createSplitter: function( index ) { - var splitter; - splitter = new lm.controls.Splitter( this._isColumn, this._splitterSize, this._splitterGrabSize ); - splitter.on( 'drag', lm.utils.fnBind( this._onSplitterDrag, this, [ splitter ] ), this ); - splitter.on( 'dragStop', lm.utils.fnBind( this._onSplitterDragStop, this, [ splitter ] ), this ); - splitter.on( 'dragStart', lm.utils.fnBind( this._onSplitterDragStart, this, [ splitter ] ), this ); - this._splitter.splice( index, 0, splitter ); - return splitter; - }, - - /** - * Locates the instance of lm.controls.Splitter in the array of - * registered splitters and returns a map containing the contentItem - * before and after the splitters, both of which are affected if the - * splitter is moved - * - * @param {lm.controls.Splitter} splitter - * - * @returns {Object} A map of contentItems that the splitter affects - */ - _getItemsForSplitter: function( splitter ) { - var index = lm.utils.indexOf( splitter, this._splitter ); - - return { - before: this.contentItems[ index ], - after: this.contentItems[ index + 1 ] - }; - }, - - /** - * Gets the minimum dimensions for the given item configuration array - * @param item - * @private - */ - _getMinimumDimensions: function( arr ) { - var minWidth = 0, minHeight = 0; - - for( var i = 0; i < arr.length; ++i ) { - minWidth = Math.max( arr[ i ].minWidth || 0, minWidth ); - minHeight = Math.max( arr[ i ].minHeight || 0, minHeight ); - } - - return { horizontal: minWidth, vertical: minHeight }; - }, - - /** - * Invoked when a splitter's dragListener fires dragStart. Calculates the splitters - * movement area once (so that it doesn't need calculating on every mousemove event) - * - * @param {lm.controls.Splitter} splitter - * - * @returns {void} - */ - _onSplitterDragStart: function( splitter ) { - var items = this._getItemsForSplitter( splitter ), - minSize = this.layoutManager.config.dimensions[ this._isColumn ? 'minItemHeight' : 'minItemWidth' ]; - - var beforeMinDim = this._getMinimumDimensions( items.before.config.content ); - var beforeMinSize = this._isColumn ? beforeMinDim.vertical : beforeMinDim.horizontal; - - var afterMinDim = this._getMinimumDimensions( items.after.config.content ); - var afterMinSize = this._isColumn ? afterMinDim.vertical : afterMinDim.horizontal; - - this._splitterPosition = 0; - this._splitterMinPosition = -1 * ( items.before.element[ this._dimension ]() - (beforeMinSize || minSize) ); - this._splitterMaxPosition = items.after.element[ this._dimension ]() - (afterMinSize || minSize); - }, - - /** - * Invoked when a splitter's DragListener fires drag. Updates the splitters DOM position, - * but not the sizes of the elements the splitter controls in order to minimize resize events - * - * @param {lm.controls.Splitter} splitter - * @param {Int} offsetX Relative pixel values to the splitters original position. Can be negative - * @param {Int} offsetY Relative pixel values to the splitters original position. Can be negative - * - * @returns {void} - */ - _onSplitterDrag: function( splitter, offsetX, offsetY ) { - var offset = this._isColumn ? offsetY : offsetX; - - if( offset > this._splitterMinPosition && offset < this._splitterMaxPosition ) { - this._splitterPosition = offset; - splitter.element.css( this._isColumn ? 'top' : 'left', offset ); - } - }, - - /** - * Invoked when a splitter's DragListener fires dragStop. Resets the splitters DOM position, - * and applies the new sizes to the elements before and after the splitter and their children - * on the next animation frame - * - * @param {lm.controls.Splitter} splitter - * - * @returns {void} - */ - _onSplitterDragStop: function( splitter ) { - - var items = this._getItemsForSplitter( splitter ), - sizeBefore = items.before.element[ this._dimension ](), - sizeAfter = items.after.element[ this._dimension ](), - splitterPositionInRange = ( this._splitterPosition + sizeBefore ) / ( sizeBefore + sizeAfter ), - totalRelativeSize = items.before.config[ this._dimension ] + items.after.config[ this._dimension ]; - - items.before.config[ this._dimension ] = splitterPositionInRange * totalRelativeSize; - items.after.config[ this._dimension ] = ( 1 - splitterPositionInRange ) * totalRelativeSize; - - splitter.element.css( { - 'top': 0, - 'left': 0 - } ); - - lm.utils.animFrame( lm.utils.fnBind( this.callDownwards, this, [ 'setSize' ] ) ); - } -} ); - -lm.items.Stack = function( layoutManager, config, parent ) { - lm.items.AbstractContentItem.call( this, layoutManager, config, parent ); - - this.element = $( '
        ' ); - this._activeContentItem = null; - var cfg = layoutManager.config; - this._header = { // defaults' reconstruction from old configuration style - show: cfg.settings.hasHeaders === true && config.hasHeaders !== false, - popout: cfg.settings.showPopoutIcon && cfg.labels.popout, - maximise: cfg.settings.showMaximiseIcon && cfg.labels.maximise, - close: cfg.settings.showCloseIcon && cfg.labels.close, - minimise: cfg.labels.minimise, - }; - if( cfg.header ) // load simplified version of header configuration (https://github.com/deepstreamIO/golden-layout/pull/245) - lm.utils.copy( this._header, cfg.header ); - if( config.header ) // load from stack - lm.utils.copy( this._header, config.header ); - if( config.content && config.content[ 0 ] && config.content[ 0 ].header ) // load from component if stack omitted - lm.utils.copy( this._header, config.content[ 0 ].header ); - - this._dropZones = {}; - this._dropSegment = null; - this._contentAreaDimensions = null; - this._dropIndex = null; - - this.isStack = true; - - this.childElementContainer = $( '
        ' ); - this.header = new lm.controls.Header( layoutManager, this ); - - this.element.append( this.header.element ); - this.element.append( this.childElementContainer ); - this._setupHeaderPosition(); - this._$validateClosability(); -}; - -lm.utils.extend( lm.items.Stack, lm.items.AbstractContentItem ); - -lm.utils.copy( lm.items.Stack.prototype, { - - setSize: function() { - var i, - headerSize = this._header.show ? this.layoutManager.config.dimensions.headerHeight : 0, - contentWidth = this.element.width() - (this._sided ? headerSize : 0), - contentHeight = this.element.height() - (!this._sided ? headerSize : 0); - - this.childElementContainer.width( contentWidth ); - this.childElementContainer.height( contentHeight ); - - for( i = 0; i < this.contentItems.length; i++ ) { - this.contentItems[ i ].element.width( contentWidth ).height( contentHeight ); - } - this.emit( 'resize' ); - this.emitBubblingEvent( 'stateChanged' ); - }, - - _$init: function() { - var i, initialItem; - - if( this.isInitialised === true ) return; - - lm.items.AbstractContentItem.prototype._$init.call( this ); - - for( i = 0; i < this.contentItems.length; i++ ) { - this.header.createTab( this.contentItems[ i ] ); - this.contentItems[ i ]._$hide(); - } - - if( this.contentItems.length > 0 ) { - initialItem = this.contentItems[ this.config.activeItemIndex || 0 ]; - - if( !initialItem ) { - throw new Error( 'Configured activeItemIndex out of bounds' ); - } - - this.setActiveContentItem( initialItem ); - } - }, - - setActiveContentItem: function( contentItem ) { - if( lm.utils.indexOf( contentItem, this.contentItems ) === -1 ) { - throw new Error( 'contentItem is not a child of this stack' ); - } - - if( this._activeContentItem !== null ) { - this._activeContentItem._$hide(); - } - - this._activeContentItem = contentItem; - this.header.setActiveContentItem( contentItem ); - contentItem._$show(); - this.emit( 'activeContentItemChanged', contentItem ); - this.layoutManager.emit( 'activeContentItemChanged', contentItem ); - this.emitBubblingEvent( 'stateChanged' ); - }, - - getActiveContentItem: function() { - return this.header.activeContentItem; - }, - - addChild: function( contentItem, index ) { - contentItem = this.layoutManager._$normalizeContentItem( contentItem, this ); - lm.items.AbstractContentItem.prototype.addChild.call( this, contentItem, index ); - this.childElementContainer.append( contentItem.element ); - this.header.createTab( contentItem, index ); - this.setActiveContentItem( contentItem ); - this.callDownwards( 'setSize' ); - this._$validateClosability(); - this.emitBubblingEvent( 'stateChanged' ); - }, - - removeChild: function( contentItem, keepChild ) { - var index = lm.utils.indexOf( contentItem, this.contentItems ); - lm.items.AbstractContentItem.prototype.removeChild.call( this, contentItem, keepChild ); - this.header.removeTab( contentItem ); - if (this.header.activeContentItem === contentItem) { - if (this.contentItems.length > 0) { - this.setActiveContentItem(this.contentItems[Math.max(index - 1, 0)]); - } else { - this._activeContentItem = null; - } - } - - this._$validateClosability(); - this.emitBubblingEvent( 'stateChanged' ); - }, - - /** - * Validates that the stack is still closable or not. If a stack is able - * to close, but has a non closable component added to it, the stack is no - * longer closable until all components are closable. - * - * @returns {void} - */ - _$validateClosability: function() { - var contentItem, - isClosable, - len, - i; - - isClosable = this.header._isClosable(); - - for( i = 0, len = this.contentItems.length; i < len; i++ ) { - if( !isClosable ) { - break; - } - - isClosable = this.contentItems[ i ].config.isClosable; - } - - this.header._$setClosable( isClosable ); - }, - - _$destroy: function() { - lm.items.AbstractContentItem.prototype._$destroy.call( this ); - this.header._$destroy(); - }, - - - /** - * Ok, this one is going to be the tricky one: The user has dropped {contentItem} onto this stack. - * - * It was dropped on either the stacks header or the top, right, bottom or left bit of the content area - * (which one of those is stored in this._dropSegment). Now, if the user has dropped on the header the case - * is relatively clear: We add the item to the existing stack... job done (might be good to have - * tab reordering at some point, but lets not sweat it right now) - * - * If the item was dropped on the content part things are a bit more complicated. If it was dropped on either the - * top or bottom region we need to create a new column and place the items accordingly. - * Unless, of course if the stack is already within a column... in which case we want - * to add the newly created item to the existing column... - * either prepend or append it, depending on wether its top or bottom. - * - * Same thing for rows and left / right drop segments... so in total there are 9 things that can potentially happen - * (left, top, right, bottom) * is child of the right parent (row, column) + header drop - * - * @param {lm.item} contentItem - * - * @returns {void} - */ - _$onDrop: function( contentItem ) { - - /* - * The item was dropped on the header area. Just add it as a child of this stack and - * get the hell out of this logic - */ - if( this._dropSegment === 'header' ) { - this._resetHeaderDropZone(); - this.addChild( contentItem, this._dropIndex ); - return; - } - - /* - * The stack is empty. Let's just add the element. - */ - if( this._dropSegment === 'body' ) { - this.addChild( contentItem ); - return; - } - - /* - * The item was dropped on the top-, left-, bottom- or right- part of the content. Let's - * aggregate some conditions to make the if statements later on more readable - */ - var isVertical = this._dropSegment === 'top' || this._dropSegment === 'bottom', - isHorizontal = this._dropSegment === 'left' || this._dropSegment === 'right', - insertBefore = this._dropSegment === 'top' || this._dropSegment === 'left', - hasCorrectParent = ( isVertical && this.parent.isColumn ) || ( isHorizontal && this.parent.isRow ), - type = isVertical ? 'column' : 'row', - dimension = isVertical ? 'height' : 'width', - index, - stack, - rowOrColumn; - - /* - * The content item can be either a component or a stack. If it is a component, wrap it into a stack - */ - if( contentItem.isComponent ) { - stack = this.layoutManager.createContentItem( { - type: 'stack', - header: contentItem.config.header || {} - }, this ); - stack._$init(); - stack.addChild( contentItem ); - contentItem = stack; - } - - /* - * If the item is dropped on top or bottom of a column or left and right of a row, it's already - * layd out in the correct way. Just add it as a child - */ - if( hasCorrectParent ) { - index = lm.utils.indexOf( this, this.parent.contentItems ); - this.parent.addChild( contentItem, insertBefore ? index : index + 1, true ); - this.config[ dimension ] *= 0.5; - contentItem.config[ dimension ] = this.config[ dimension ]; - this.parent.callDownwards( 'setSize' ); - /* - * This handles items that are dropped on top or bottom of a row or left / right of a column. We need - * to create the appropriate contentItem for them to live in - */ - } else { - type = isVertical ? 'column' : 'row'; - rowOrColumn = this.layoutManager.createContentItem( { type: type }, this ); - this.parent.replaceChild( this, rowOrColumn ); - - rowOrColumn.addChild( contentItem, insertBefore ? 0 : undefined, true ); - rowOrColumn.addChild( this, insertBefore ? undefined : 0, true ); - - this.config[ dimension ] = 50; - contentItem.config[ dimension ] = 50; - rowOrColumn.callDownwards( 'setSize' ); - } - }, - - /** - * If the user hovers above the header part of the stack, indicate drop positions for tabs. - * otherwise indicate which segment of the body the dragged item would be dropped on - * - * @param {Int} x Absolute Screen X - * @param {Int} y Absolute Screen Y - * - * @returns {void} - */ - _$highlightDropZone: function( x, y ) { - var segment, area; - - for( segment in this._contentAreaDimensions ) { - area = this._contentAreaDimensions[ segment ].hoverArea; - - if( area.x1 < x && area.x2 > x && area.y1 < y && area.y2 > y ) { - - if( segment === 'header' ) { - this._dropSegment = 'header'; - this._highlightHeaderDropZone( this._sided ? y : x ); - } else { - this._resetHeaderDropZone(); - this._highlightBodyDropZone( segment ); - } - - return; - } - } - }, - - _$getArea: function() { - if( this.element.is( ':visible' ) === false ) { - return null; - } - - var getArea = lm.items.AbstractContentItem.prototype._$getArea, - headerArea = getArea.call( this, this.header.element ), - contentArea = getArea.call( this, this.childElementContainer ), - contentWidth = contentArea.x2 - contentArea.x1, - contentHeight = contentArea.y2 - contentArea.y1; - - this._contentAreaDimensions = { - header: { - hoverArea: { - x1: headerArea.x1, - y1: headerArea.y1, - x2: headerArea.x2, - y2: headerArea.y2 - }, - highlightArea: { - x1: headerArea.x1, - y1: headerArea.y1, - x2: headerArea.x2, - y2: headerArea.y2 - } - } - }; - - /** - * If this Stack is a parent to rows, columns or other stacks only its - * header is a valid dropzone. - */ - if( this._activeContentItem && this._activeContentItem.isComponent === false ) { - return headerArea; - } - - /** - * Highlight the entire body if the stack is empty - */ - if( this.contentItems.length === 0 ) { - - this._contentAreaDimensions.body = { - hoverArea: { - x1: contentArea.x1, - y1: contentArea.y1, - x2: contentArea.x2, - y2: contentArea.y2 - }, - highlightArea: { - x1: contentArea.x1, - y1: contentArea.y1, - x2: contentArea.x2, - y2: contentArea.y2 - } - }; - - return getArea.call( this, this.element ); - } - - this._contentAreaDimensions.left = { - hoverArea: { - x1: contentArea.x1, - y1: contentArea.y1, - x2: contentArea.x1 + contentWidth * 0.25, - y2: contentArea.y2 - }, - highlightArea: { - x1: contentArea.x1, - y1: contentArea.y1, - x2: contentArea.x1 + contentWidth * 0.5, - y2: contentArea.y2 - } - }; - - this._contentAreaDimensions.top = { - hoverArea: { - x1: contentArea.x1 + contentWidth * 0.25, - y1: contentArea.y1, - x2: contentArea.x1 + contentWidth * 0.75, - y2: contentArea.y1 + contentHeight * 0.5 - }, - highlightArea: { - x1: contentArea.x1, - y1: contentArea.y1, - x2: contentArea.x2, - y2: contentArea.y1 + contentHeight * 0.5 - } - }; - - this._contentAreaDimensions.right = { - hoverArea: { - x1: contentArea.x1 + contentWidth * 0.75, - y1: contentArea.y1, - x2: contentArea.x2, - y2: contentArea.y2 - }, - highlightArea: { - x1: contentArea.x1 + contentWidth * 0.5, - y1: contentArea.y1, - x2: contentArea.x2, - y2: contentArea.y2 - } - }; - - this._contentAreaDimensions.bottom = { - hoverArea: { - x1: contentArea.x1 + contentWidth * 0.25, - y1: contentArea.y1 + contentHeight * 0.5, - x2: contentArea.x1 + contentWidth * 0.75, - y2: contentArea.y2 - }, - highlightArea: { - x1: contentArea.x1, - y1: contentArea.y1 + contentHeight * 0.5, - x2: contentArea.x2, - y2: contentArea.y2 - } - }; - - return getArea.call( this, this.element ); - }, - - _highlightHeaderDropZone: function( x ) { - var i, - tabElement, - tabsLength = this.header.tabs.length, - isAboveTab = false, - tabTop, - tabLeft, - offset, - placeHolderLeft, - headerOffset, - tabWidth, - halfX; - - // Empty stack - if( tabsLength === 0 ) { - headerOffset = this.header.element.offset(); - - this.layoutManager.dropTargetIndicator.highlightArea( { - x1: headerOffset.left, - x2: headerOffset.left + 100, - y1: headerOffset.top + this.header.element.height() - 20, - y2: headerOffset.top + this.header.element.height() - } ); - - return; - } - - for( i = 0; i < tabsLength; i++ ) { - tabElement = this.header.tabs[ i ].element; - offset = tabElement.offset(); - if( this._sided ) { - tabLeft = offset.top; - tabTop = offset.left; - tabWidth = tabElement.height(); - } else { - tabLeft = offset.left; - tabTop = offset.top; - tabWidth = tabElement.width(); - } - - if( x > tabLeft && x < tabLeft + tabWidth ) { - isAboveTab = true; - break; - } - } - - if( isAboveTab === false && x < tabLeft ) { - return; - } - - halfX = tabLeft + tabWidth / 2; - - if( x < halfX ) { - this._dropIndex = i; - tabElement.before( this.layoutManager.tabDropPlaceholder ); - } else { - this._dropIndex = Math.min( i + 1, tabsLength ); - tabElement.after( this.layoutManager.tabDropPlaceholder ); - } - - - if( this._sided ) { - placeHolderTop = this.layoutManager.tabDropPlaceholder.offset().top; - this.layoutManager.dropTargetIndicator.highlightArea( { - x1: tabTop, - x2: tabTop + tabElement.innerHeight(), - y1: placeHolderTop, - y2: placeHolderTop + this.layoutManager.tabDropPlaceholder.width() - } ); - return; - } - placeHolderLeft = this.layoutManager.tabDropPlaceholder.offset().left; - - this.layoutManager.dropTargetIndicator.highlightArea( { - x1: placeHolderLeft, - x2: placeHolderLeft + this.layoutManager.tabDropPlaceholder.width(), - y1: tabTop, - y2: tabTop + tabElement.innerHeight() - } ); - }, - - _resetHeaderDropZone: function() { - this.layoutManager.tabDropPlaceholder.remove(); - }, - - _setupHeaderPosition: function() { - var side = [ 'right', 'left', 'bottom' ].indexOf( this._header.show ) >= 0 && this._header.show; - this.header.element.toggle( !!this._header.show ); - this._side = side; - this._sided = [ 'right', 'left' ].indexOf( this._side ) >= 0; - this.element.removeClass( 'lm_left lm_right lm_bottom' ); - if( this._side ) - this.element.addClass( 'lm_' + this._side ); - if( this.element.find( '.lm_header' ).length && this.childElementContainer ) { - var headerPosition = [ 'right', 'bottom' ].indexOf( this._side ) >= 0 ? 'before' : 'after'; - this.header.element[ headerPosition ]( this.childElementContainer ); - this.callDownwards( 'setSize' ); - } - }, - - _highlightBodyDropZone: function( segment ) { - var highlightArea = this._contentAreaDimensions[ segment ].highlightArea; - this.layoutManager.dropTargetIndicator.highlightArea( highlightArea ); - this._dropSegment = segment; - } -} ); - -lm.utils.BubblingEvent = function( name, origin ) { - this.name = name; - this.origin = origin; - this.isPropagationStopped = false; -}; - -lm.utils.BubblingEvent.prototype.stopPropagation = function() { - this.isPropagationStopped = true; -}; -/** - * Minifies and unminifies configs by replacing frequent keys - * and values with one letter substitutes. Config options must - * retain array position/index, add new options at the end. - * - * @constructor - */ -lm.utils.ConfigMinifier = function() { - this._keys = [ - 'settings', - 'hasHeaders', - 'constrainDragToContainer', - 'selectionEnabled', - 'dimensions', - 'borderWidth', - 'minItemHeight', - 'minItemWidth', - 'headerHeight', - 'dragProxyWidth', - 'dragProxyHeight', - 'labels', - 'close', - 'maximise', - 'minimise', - 'popout', - 'content', - 'componentName', - 'componentState', - 'id', - 'width', - 'type', - 'height', - 'isClosable', - 'title', - 'popoutWholeStack', - 'openPopouts', - 'parentId', - 'activeItemIndex', - 'reorderEnabled', - 'borderGrabWidth', - - - - - //Maximum 36 entries, do not cross this line! - ]; - if( this._keys.length > 36 ) { - throw new Error( 'Too many keys in config minifier map' ); - } - - this._values = [ - true, - false, - 'row', - 'column', - 'stack', - 'component', - 'close', - 'maximise', - 'minimise', - 'open in new window' - ]; -}; - -lm.utils.copy( lm.utils.ConfigMinifier.prototype, { - - /** - * Takes a GoldenLayout configuration object and - * replaces its keys and values recursively with - * one letter counterparts - * - * @param {Object} config A GoldenLayout config object - * - * @returns {Object} minified config - */ - minifyConfig: function( config ) { - var min = {}; - this._nextLevel( config, min, '_min' ); - return min; - }, - - /** - * Takes a configuration Object that was previously minified - * using minifyConfig and returns its original version - * - * @param {Object} minifiedConfig - * - * @returns {Object} the original configuration - */ - unminifyConfig: function( minifiedConfig ) { - var orig = {}; - this._nextLevel( minifiedConfig, orig, '_max' ); - return orig; - }, - - /** - * Recursive function, called for every level of the config structure - * - * @param {Array|Object} orig - * @param {Array|Object} min - * @param {String} translationFn - * - * @returns {void} - */ - _nextLevel: function( from, to, translationFn ) { - var key, minKey; - - for( key in from ) { - - /** - * For in returns array indices as keys, so let's cast them to numbers - */ - if( from instanceof Array ) key = parseInt( key, 10 ); - - /** - * In case something has extended Object prototypes - */ - if( !from.hasOwnProperty( key ) ) continue; - - /** - * Translate the key to a one letter substitute - */ - minKey = this[ translationFn ]( key, this._keys ); - - /** - * For Arrays and Objects, create a new Array/Object - * on the minified object and recurse into it - */ - if( typeof from[ key ] === 'object' ) { - to[ minKey ] = from[ key ] instanceof Array ? [] : {}; - this._nextLevel( from[ key ], to[ minKey ], translationFn ); - - /** - * For primitive values (Strings, Numbers, Boolean etc.) - * minify the value - */ - } else { - to[ minKey ] = this[ translationFn ]( from[ key ], this._values ); - } - } - }, - - /** - * Minifies value based on a dictionary - * - * @param {String|Boolean} value - * @param {Array} dictionary - * - * @returns {String} The minified version - */ - _min: function( value, dictionary ) { - /** - * If a value actually is a single character, prefix it - * with ___ to avoid mistaking it for a minification code - */ - if( typeof value === 'string' && value.length === 1 ) { - return '___' + value; - } - - var index = lm.utils.indexOf( value, dictionary ); - - /** - * value not found in the dictionary, return it unmodified - */ - if( index === -1 ) { - return value; - - /** - * value found in dictionary, return its base36 counterpart - */ - } else { - return index.toString( 36 ); - } - }, - - _max: function( value, dictionary ) { - /** - * value is a single character. Assume that it's a translation - * and return the original value from the dictionary - */ - if( typeof value === 'string' && value.length === 1 ) { - return dictionary[ parseInt( value, 36 ) ]; - } - - /** - * value originally was a single character and was prefixed with ___ - * to avoid mistaking it for a translation. Remove the prefix - * and return the original character - */ - if( typeof value === 'string' && value.substr( 0, 3 ) === '___' ) { - return value[ 3 ]; - } - /** - * value was not minified - */ - return value; - } -} ); - -/** - * An EventEmitter singleton that propagates events - * across multiple windows. This is a little bit trickier since - * windows are allowed to open childWindows in their own right - * - * This means that we deal with a tree of windows. Hence the rules for event propagation are: - * - * - Propagate events from this layout to both parents and children - * - Propagate events from parent to this and children - * - Propagate events from children to the other children (but not the emitting one) and the parent - * - * @constructor - * - * @param {lm.LayoutManager} layoutManager - */ -lm.utils.EventHub = function( layoutManager ) { - lm.utils.EventEmitter.call( this ); - this._layoutManager = layoutManager; - this._dontPropagateToParent = null; - this._childEventSource = null; - this.on( lm.utils.EventEmitter.ALL_EVENT, lm.utils.fnBind( this._onEventFromThis, this ) ); - this._boundOnEventFromChild = lm.utils.fnBind( this._onEventFromChild, this ); - $( window ).on( 'gl_child_event', this._boundOnEventFromChild ); -}; - -/** - * Called on every event emitted on this eventHub, regardles of origin. - * - * @private - * - * @param {Mixed} - * - * @returns {void} - */ -lm.utils.EventHub.prototype._onEventFromThis = function() { - var args = Array.prototype.slice.call( arguments ); - - if( this._layoutManager.isSubWindow && args[ 0 ] !== this._dontPropagateToParent ) { - this._propagateToParent( args ); - } - this._propagateToChildren( args ); - - //Reset - this._dontPropagateToParent = null; - this._childEventSource = null; -}; - -/** - * Called by the parent layout. - * - * @param {Array} args Event name + arguments - * - * @returns {void} - */ -lm.utils.EventHub.prototype._$onEventFromParent = function( args ) { - this._dontPropagateToParent = args[ 0 ]; - this.emit.apply( this, args ); -}; - -/** - * Callback for child events raised on the window - * - * @param {DOMEvent} event - * @private - * - * @returns {void} - */ -lm.utils.EventHub.prototype._onEventFromChild = function( event ) { - this._childEventSource = event.originalEvent.__gl; - this.emit.apply( this, event.originalEvent.__glArgs ); -}; - -/** - * Propagates the event to the parent by emitting - * it on the parent's DOM window - * - * @param {Array} args Event name + arguments - * @private - * - * @returns {void} - */ -lm.utils.EventHub.prototype._propagateToParent = function( args ) { - var event, - eventName = 'gl_child_event'; - - if( document.createEvent ) { - event = window.opener.document.createEvent( 'HTMLEvents' ); - event.initEvent( eventName, true, true ); - } else { - event = window.opener.document.createEventObject(); - event.eventType = eventName; - } - - event.eventName = eventName; - event.__glArgs = args; - event.__gl = this._layoutManager; - - if( document.createEvent ) { - window.opener.dispatchEvent( event ); - } else { - window.opener.fireEvent( 'on' + event.eventType, event ); - } -}; - -/** - * Propagate events to children - * - * @param {Array} args Event name + arguments - * @private - * - * @returns {void} - */ -lm.utils.EventHub.prototype._propagateToChildren = function( args ) { - var childGl, i; - - for( i = 0; i < this._layoutManager.openPopouts.length; i++ ) { - childGl = this._layoutManager.openPopouts[ i ].getGlInstance(); - - if( childGl && childGl !== this._childEventSource ) { - childGl.eventHub._$onEventFromParent( args ); - } - } -}; - - -/** - * Destroys the EventHub - * - * @public - * @returns {void} - */ - -lm.utils.EventHub.prototype.destroy = function() { - $( window ).off( 'gl_child_event', this._boundOnEventFromChild ); -}; -/** - * A specialised GoldenLayout component that binds GoldenLayout container - * lifecycle events to react components - * - * @constructor - * - * @param {lm.container.ItemContainer} container - * @param {Object} state state is not required for react components - */ -lm.utils.ReactComponentHandler = function( container, state ) { - this._reactComponent = null; - this._originalComponentWillUpdate = null; - this._container = container; - this._initialState = state; - this._reactClass = this._getReactClass(); - this._container.on( 'open', this._render, this ); - this._container.on( 'destroy', this._destroy, this ); -}; - -lm.utils.copy( lm.utils.ReactComponentHandler.prototype, { - - /** - * Creates the react class and component and hydrates it with - * the initial state - if one is present - * - * By default, react's getInitialState will be used - * - * @private - * @returns {void} - */ - _render: function() { - this._reactComponent = ReactDOM.render( this._getReactComponent(), this._container.getElement()[ 0 ] ); - this._originalComponentWillUpdate = this._reactComponent.componentWillUpdate || function() { - }; - this._reactComponent.componentWillUpdate = this._onUpdate.bind( this ); - if( this._container.getState() ) { - this._reactComponent.setState( this._container.getState() ); - } - }, - - /** - * Removes the component from the DOM and thus invokes React's unmount lifecycle - * - * @private - * @returns {void} - */ - _destroy: function() { - ReactDOM.unmountComponentAtNode( this._container.getElement()[ 0 ] ); - this._container.off( 'open', this._render, this ); - this._container.off( 'destroy', this._destroy, this ); - }, - - /** - * Hooks into React's state management and applies the componentstate - * to GoldenLayout - * - * @private - * @returns {void} - */ - _onUpdate: function( nextProps, nextState ) { - this._container.setState( nextState ); - this._originalComponentWillUpdate.call( this._reactComponent, nextProps, nextState ); - }, - - /** - * Retrieves the react class from GoldenLayout's registry - * - * @private - * @returns {React.Class} - */ - _getReactClass: function() { - var componentName = this._container._config.component; - var reactClass; - - if( !componentName ) { - throw new Error( 'No react component name. type: react-component needs a field `component`' ); - } - - reactClass = this._container.layoutManager.getComponent( componentName ); - - if( !reactClass ) { - throw new Error( 'React component "' + componentName + '" not found. ' + - 'Please register all components with GoldenLayout using `registerComponent(name, component)`' ); - } - - return reactClass; - }, - - /** - * Copies and extends the properties array and returns the React element - * - * @private - * @returns {React.Element} - */ - _getReactComponent: function() { - var defaultProps = { - glEventHub: this._container.layoutManager.eventHub, - glContainer: this._container, - }; - var props = $.extend( defaultProps, this._container._config.props ); - return React.createElement( this._reactClass, props ); - } -} );})(window.$); \ No newline at end of file diff --git a/node_modules/golden-layout/dist/goldenlayout.min.js b/node_modules/golden-layout/dist/goldenlayout.min.js deleted file mode 100644 index 5c9f173..0000000 --- a/node_modules/golden-layout/dist/goldenlayout.min.js +++ /dev/null @@ -1,3 +0,0 @@ -!function(t){var e={config:{},container:{},controls:{},errors:{},items:{},utils:{}};e.utils.F=function(){},e.utils.extend=function(t,i){t.prototype=e.utils.createObject(i.prototype),t.prototype.contructor=t},e.utils.createObject=function(t){return"function"==typeof Object.create?Object.create(t):(e.utils.F.prototype=t,new e.utils.F)},e.utils.objectKeys=function(t){var e,i;if("function"==typeof Object.keys)return Object.keys(t);e=[];for(i in t)e.push(i);return e},e.utils.getHashValue=function(t){var e=location.hash.match(new RegExp(t+"=([^&]*)"));return e?e[1]:null},e.utils.getQueryStringParam=function(t){if(window.location.hash)return e.utils.getHashValue(t);if(!window.location.search)return null;var i,n,s=window.location.search.substr(1).split("&"),o={};for(n=0;n/g,">").replace(/]+)>)/gi,""))},e.utils.EventEmitter=function(){this._mSubscriptions={},this._mSubscriptions[e.utils.EventEmitter.ALL_EVENT]=[],this.on=function(t,i,n){if(!e.utils.isFunction(i))throw new Error("Tried to listen to event "+t+" with non-function callback "+i);this._mSubscriptions[t]||(this._mSubscriptions[t]=[]),this._mSubscriptions[t].push({fn:i,ctx:n})},this.emit=function(t){var i,n,s;s=Array.prototype.slice.call(arguments,1);var o=this._mSubscriptions[t];if(o)for(o=o.slice(),i=0;ithis._nDistance||Math.abs(this._nY)>this._nDistance)&&(clearTimeout(this._timeout),this._startDrag()),this._bDragging&&this.emit("drag",this._nX,this._nY,t)}},onMouseUp:function(t){null!=this._timeout&&(clearTimeout(this._timeout),this._eBody.removeClass("lm_dragging"),this._eElement.removeClass("lm_dragging"),this._oDocument.find("iframe").css("pointer-events",""),this._oDocument.unbind("mousemove touchmove",this._fMove),this._oDocument.unbind("mouseup touchend",this._fUp),this._bDragging===!0&&(this._bDragging=!1,this.emit("dragStop",t,this._nOriginalX+this._nX)))},_startDrag:function(){this._bDragging=!0,this._eBody.addClass("lm_dragging"),this._eElement.addClass("lm_dragging"),this._oDocument.find("iframe").css("pointer-events","none"),this.emit("dragStart",this._nOriginalX,this._nOriginalY)},_getCoordinates:function(t){return t=t.originalEvent&&t.originalEvent.touches?t.originalEvent.touches[0]:t,{x:t.pageX,y:t.pageY}}}),e.LayoutManager=function(i,n){if(!t||"function"!=typeof t.noConflict){var s="jQuery is missing as dependency for GoldenLayout. ";throw s+='Please either expose $ on GoldenLayout\'s scope (e.g. window) or add "jquery" to ',s+="your paths when using RequireJS/AMD",new Error(s)}e.utils.EventEmitter.call(this),this.isInitialised=!1,this._isFullPage=!1,this._resizeTimeoutId=null,this._components={"lm-react-component":e.utils.ReactComponentHandler},this._itemAreas=[],this._resizeFunction=e.utils.fnBind(this._onResize,this),this._unloadFunction=e.utils.fnBind(this._onUnload,this),this._maximisedItem=null,this._maximisePlaceholder=t('
        '),this._creationTimeoutPassed=!1,this._subWindowsCreated=!1,this._dragSources=[],this._updatingColumnsResponsive=!1,this._firstLoad=!0,this.width=null,this.height=null,this.root=null,this.openPopouts=[],this.selectedItem=null,this.isSubWindow=!1,this.eventHub=new e.utils.EventHub(this),this.config=this._createConfig(i),this.container=n,this.dropTargetIndicator=null,this.transitionIndicator=null,this.tabDropPlaceholder=t('
        '),this.isSubWindow===!0&&t("body").css("visibility","hidden"),this._typeToItem={column:e.utils.fnBind(e.items.RowOrColumn,this,[!0]),row:e.utils.fnBind(e.items.RowOrColumn,this,[!1]),stack:e.items.Stack,component:e.items.Component}},e.LayoutManager.__lm=e,e.LayoutManager.minifyConfig=function(t){return(new e.utils.ConfigMinifier).minifyConfig(t)},e.LayoutManager.unminifyConfig=function(t){return(new e.utils.ConfigMinifier).unminifyConfig(t)},e.utils.copy(e.LayoutManager.prototype,{registerComponent:function(t,e){if("function"!=typeof e)throw new Error("Please register a constructor function");if(void 0!==this._components[t])throw new Error("Component "+t+" is already registered");this._components[t]=e},toConfig:function(t){var i,n,s;if(this.isInitialised===!1)throw new Error("Can't create config, layout not yet initialised");if(t&&!(t instanceof e.items.AbstractContentItem))throw new Error("Root must be a ContentItem");for(i={settings:e.utils.copy({},this.config.settings),dimensions:e.utils.copy({},this.config.dimensions),labels:e.utils.copy({},this.config.labels)},i.content=[],n=function(t,e){var i,s;for(i in e.config)"content"!==i&&(t[i]=e.config[i]);if(e.contentItems.length)for(t.content=[],s=0;sn.x1&&tn.y1&&en.surface&&(s=n.surface,o=n);return o},_$createRootItemAreas:function(){var t=50,e={y2:0,x2:0,y1:"y2",x1:"x2"};for(var i in e){var n=this.root._$getArea();n.side=i,e[i]?n[i]=n[e[i]]-t:n[i]=t,n.surface=(n.x2-n.x1)*(n.y2-n.y1),this._itemAreas.push(n)}},_$calculateItemAreas:function(){var t,i,n=this._getAllContentItems();if(this._itemAreas=[],1===n.length)return void this._itemAreas.push(this.root._$getArea());for(this._$createRootItemAreas(),t=0;t
        ');i.click(e.utils.fnBind(function(){this.emit("popIn")},this)),document.title=e.utils.stripTags(this.config.content[0].title),t("head").append(t("body link, body style, template, .gl_keep")),this.container=t("body").html("").css("visibility","visible").append(i);document.body.offsetHeight;window.__glInstance=this},_createSubWindows:function(){var t,e;for(t=0;t1)throw new Error("GoldenLayout more than one container element specified");e[0]===document.body&&(this._isFullPage=!0,t("html, body").css({height:"100%",margin:0,padding:0,overflow:"hidden"})),this.container=e},_create:function(t){var i;if(!(t.content instanceof Array))throw i=void 0===t.content?"Missing setting 'content' on top level of configuration":"Configuration parameter 'content' must be an array",new e.errors.ConfigurationError(i,t);if(t.content.length>1)throw i="Top level content can't contain more then one element.",new e.errors.ConfigurationError(i,t);this.root=new e.items.Root(this,{content:t.content},this.container),this.root.callDownwards("_$init"),"__glMaximised"===t.maximisedItemId&&this.root.getItemsById(t.maximisedItemId)[0].toggleMaximise()},_onUnload:function(){if(this.config.settings.closePopoutsOnUnload===!0)for(var t=0;t','
        ',""].join("")),this._contentElement=this._element.find(".lm_content")},e.utils.copy(e.container.ItemContainer.prototype,{getElement:function(){return this._contentElement},hide:function(){this.emit("hide"),this.isHidden=!0,this._element.hide()},show:function(){this.emit("show"),this.isHidden=!1,this._element.show(),0==this.height&&0==this.width||this.emit("shown")},setSize:function(t,e){for(var i,n,s,o,r,a,h=this.parent,l=this;!h.isColumn&&!h.isRow;)if(l=h,h=h.parent,h.isRoot)return!1;for(s=h.isColumn?"height":"width",o="height"===s?e:t,i=this[s]*(1/(l.config[s]/100)),n=o/i*100,r=(l.config[s]-n)/(h.contentItems.length-1),a=0;a0?this._layoutManager.root.contentItems[0]:this._layoutManager.root,n=0)),i.addChild(e,this._indexInParent),this.close()},_createWindow:function(){var i,n=this._createUrl(),s=Math.floor(1e6*Math.random()).toString(36),o=this._serializeWindowOptions({width:this._dimensions.width,height:this._dimensions.height,innerWidth:this._dimensions.width,innerHeight:this._dimensions.height,menubar:"no",toolbar:"no",location:"no",personalbar:"no",resizable:"yes",scrollbars:"no",status:"no"});if(this._popoutWindow=window.open(n,s,o),this._popoutWindow)t(this._popoutWindow).on("load",e.utils.fnBind(this._positionWindow,this)).on("unload beforeunload",e.utils.fnBind(this._onClose,this)),i=setInterval(e.utils.fnBind(function(){this._popoutWindow.__glInstance&&this._popoutWindow.__glInstance.isInitialised&&(this._onInitialised(),clearInterval(i))},this),10);else if(this._layoutManager.config.settings.blockedPopoutsThrowError===!0){var r=new Error("Popout blocked");throw r.type="popoutBlocked",r}},_serializeWindowOptions:function(t){var e,i=[];for(e in t)i.push(e+"="+t[e]);return i.join(",")},_createUrl:function(){var t,i={content:this._config},n="gl-window-config-"+e.utils.getUniqueId();i=(new e.utils.ConfigMinifier).minifyConfig(i);try{localStorage.setItem(n,JSON.stringify(i))}catch(s){throw new Error("Error while writing to localStorage "+s.toString())}return t=document.location.href.split("?"),1===t.length?t[0]+"?gl-window="+n:document.location.href+"&gl-window="+n},_positionWindow:function(){this._popoutWindow.moveTo(this._dimensions.left,this._dimensions.top),this._popoutWindow.focus()},_onInitialised:function(){this.isInitialised=!0,this.getGlInstance().on("popIn",this.popIn,this),this.emit("initialised")},_onClose:function(){setTimeout(e.utils.fnBind(this.emit,this,["closed"]),50)}}),e.controls.DragProxy=function(i,n,s,o,r,a){e.utils.EventEmitter.call(this),this._dragListener=s,this._layoutManager=o,this._contentItem=r,this._originalParent=a,this._area=null,this._lastValidArea=null,this._dragListener.on("drag",this._onDrag,this),this._dragListener.on("dragStop",this._onDrop,this),this.element=t(e.controls.DragProxy._template),a&&a._side&&(this._sided=a._sided,this.element.addClass("lm_"+a._side),["right","bottom"].indexOf(a._side)>=0&&this.element.find(".lm_content").after(this.element.find(".lm_header"))),this.element.css({left:i,top:n}),this.element.find(".lm_tab").attr("title",e.utils.stripTags(this._contentItem.config.title)),this.element.find(".lm_title").html(this._contentItem.config.title),this.childElementContainer=this.element.find(".lm_content"),this.childElementContainer.append(r.element),this._updateTree(),this._layoutManager._$calculateItemAreas(),this._setDimensions(),t(document.body).append(this.element);var h=this._layoutManager.container.offset();this._minX=h.left,this._minY=h.top,this._maxX=this._layoutManager.container.width()+this._minX,this._maxY=this._layoutManager.container.height()+this._minY,this._width=this.element.width(),this._height=this.element.height(),this._setDropPosition(i,n)},e.controls.DragProxy._template='
        ',e.utils.copy(e.controls.DragProxy.prototype,{_onDrag:function(t,e,i){i=i.originalEvent&&i.originalEvent.touches?i.originalEvent.touches[0]:i;var n=i.pageX,s=i.pageY,o=n>this._minX&&nthis._minY&&s
        ',e.utils.copy(e.controls.DropTargetIndicator.prototype,{destroy:function(){this.element.remove()},highlight:function(t,e,i,n){this.highlightArea({x1:t,y1:e,x2:i,y2:n})},highlightArea:function(t){this.element.css({left:t.x1,top:t.y1,width:t.x2-t.x1,height:t.y2-t.y1}).show()},hide:function(){this.element.hide()}}),e.controls.Header=function(i,n){e.utils.EventEmitter.call(this),this.layoutManager=i,this.element=t(e.controls.Header._template),this.layoutManager.config.settings.selectionEnabled===!0&&(this.element.addClass("lm_selectable"),this.element.on("click touchstart",e.utils.fnBind(this._onHeaderClick,this))),this.tabsContainer=this.element.find(".lm_tabs"),this.tabDropdownContainer=this.element.find(".lm_tabdropdown_list"),this.tabDropdownContainer.hide(),this.controlsContainer=this.element.find(".lm_controls"),this.parent=n,this.parent.on("resize",this._updateTabSizes,this),this.tabs=[],this.activeContentItem=null,this.closeButton=null,this.tabDropdownButton=null,this.hideAdditionalTabsDropdown=e.utils.fnBind(this._hideAdditionalTabsDropdown,this),t(document).mouseup(this.hideAdditionalTabsDropdown),this._lastVisibleTabIndex=-1,this._tabControlOffset=this.layoutManager.config.settings.tabControlOffset,this._createControls()},e.controls.Header._template=['
        ','
          ','
            ','
              ',"
              "].join(""),e.utils.copy(e.controls.Header.prototype,{createTab:function(t,i){var n,s;for(s=0;s0?this.tabs[i-1].element.after(n.element):this.tabs[0].element.before(n.element),this.tabs.splice(i,0,n),void this._updateTabSizes())},removeTab:function(t){for(var e=0;ethis._lastVisibleTabIndex){for(s=this.tabs[this.parent.config.activeItemIndex],i=this.parent.config.activeItemIndex;i>0;i--)this.tabs[i]=this.tabs[i-1];this.tabs[0]=s,this.parent.config.activeItemIndex=0}this._updateTabSizes(),this.parent.emitBubblingEvent("stateChanged")},position:function(t){var e=this.parent._header.show;return e&&!this.parent._side&&(e="top"),void 0!==t&&this.parent._header.show!=t&&(this.parent._header.show=t,this.parent._setupHeaderPosition()),e},_$setClosable:function(t){return!(!this.closeButton||!this._isClosable())&&(this.closeButton.element[t?"show":"hide"](),!0)},_$destroy:function(){this.emit("destroy",this);for(var e=0;ea){if(m)n===u&&(i.css({"z-index":"auto","margin-left":""}),this.tabsContainer.append(i));else if(c=u>0&&u<=n?(l-a)/(n-1):(l-a)/n,c'),this._header.on("destroy",this._$destroy,this),this._action=s,this.element.on("click touchstart",this._action),this._header.controlsContainer.append(this.element)},e.utils.copy(e.controls.HeaderButton.prototype,{_$destroy:function(){this.element.off(),this.element.remove()}}),e.controls.Splitter=function(t,i,n){this._isVertical=t,this._size=i,this._grabSize=n'),i=t('
              ');i.append(e);var n=this._grabSize-this._size,s=n/2;return this._isVertical?(e.css("top",-s),e.css("height",this._size+n),i.addClass("lm_vertical"),i.height(this._size)):(e.css("left",-s),e.css("width",this._size+n),i.addClass("lm_horizontal"),i.width(this._size)),i}}),e.controls.Tab=function(i,n){this.header=i,this.contentItem=n,this.element=t(e.controls.Tab._template),this.titleElement=this.element.find(".lm_title"),this.closeElement=this.element.find(".lm_close_tab"),this.closeElement[n.config.isClosable?"show":"hide"](),this.isActive=!1,this.setTitle(n.config.title),this.contentItem.on("titleChanged",this.setTitle,this),this._layoutManager=this.contentItem.layoutManager,this._layoutManager.config.settings.reorderEnabled===!0&&n.config.reorderEnabled===!0&&(this._dragListener=new e.utils.DragListener(this.element),this._dragListener.on("dragStart",this._onDragStart,this),this.contentItem.on("destroy",this._dragListener.destroy,this._dragListener)),this._onTabClickFn=e.utils.fnBind(this._onTabClick,this),this._onCloseClickFn=e.utils.fnBind(this._onCloseClick,this),this.element.on("mousedown touchstart",this._onTabClickFn),this.contentItem.config.isClosable?(this.closeElement.on("click touchstart",this._onCloseClickFn),this.closeElement.on("mousedown",this._onCloseMousedown)):this.closeElement.remove(),this.contentItem.tab=this,this.contentItem.emit("tab",this),this.contentItem.layoutManager.emit("tabCreated",this),this.contentItem.isComponent&&(this.contentItem.container.tab=this,this.contentItem.container.emit("tab",this))},e.controls.Tab._template='
            • ',e.utils.copy(e.controls.Tab.prototype,{setTitle:function(t){this.element.attr("title",e.utils.stripTags(t)),this.titleElement.html(t)},setActive:function(t){t!==this.isActive&&(this.isActive=t,t?this.element.addClass("lm_active"):this.element.removeClass("lm_active"))},_$destroy:function(){this.element.off("mousedown touchstart",this._onTabClickFn),this.closeElement.off("click touchstart",this._onCloseClickFn),this._dragListener&&(this.contentItem.off("destroy",this._dragListener.destroy,this._dragListener),this._dragListener.off("dragStart",this._onDragStart),this._dragListener=null),this.element.remove()},_onDragStart:function(t,i){this.contentItem.parent.isMaximised===!0&&this.contentItem.parent.toggleMaximise(),new e.controls.DragProxy(t,i,this._dragListener,this._layoutManager,this.contentItem,this.header.parent)},_onTabClick:function(t){if(0===t.button||"touchstart"===t.type){var e=this.header.parent.getActiveContentItem();this.contentItem!==e&&this.header.parent.setActiveContentItem(this.contentItem)}else 1===t.button&&this.contentItem.config.isClosable&&this._onCloseClick(t)},_onCloseClick:function(t){t.stopPropagation(),this.header.parent.removeChild(this.contentItem)},_onCloseMousedown:function(t){t.stopPropagation()}}),e.controls.TransitionIndicator=function(){this._element=t('
              '),t(document.body).append(this._element),this._toElement=null,this._fromDimensions=null,this._totalAnimationDuration=200,this._animationStartTime=null},e.utils.copy(e.controls.TransitionIndicator.prototype,{destroy:function(){this._element.remove()},transitionElements:function(t,e){},_nextAnimationFrame:function(){var t,i=this._measure(this._toElement),n=(e.utils.now()-this._animationStartTime)/this._totalAnimationDuration,s={};if(n>=1)return void this._element.hide();i.opacity=0;for(t in this._fromDimensions)s[t]=this._fromDimensions[t]+(i[t]-this._fromDimensions[t])*n;this._element.css(s),e.utils.animFrame(e.utils.fnBind(this._nextAnimationFrame,this))},_measure:function(t){var e=t.offset();return{left:e.left,top:e.top,width:t.outerWidth(),height:t.outerHeight()}}}),e.errors.ConfigurationError=function(t,e){Error.call(this),this.name="Configuration Error",this.message=t,this.node=e},e.errors.ConfigurationError.prototype=new Error,e.items.AbstractContentItem=function(t,i,n){e.utils.EventEmitter.call(this),this.config=this._extendItemNode(i),this.type=i.type,this.contentItems=[],this.parent=n,this.isInitialised=!1,this.isMaximised=!1,this.isRoot=!1,this.isRow=!1,this.isColumn=!1,this.isStack=!1,this.isComponent=!1,this.layoutManager=t,this._pendingEventPropagations={},this._throttledEvents=["stateChanged"],this.on(e.utils.EventEmitter.ALL_EVENT,this._propagateEvent,this),i.content&&this._createContentItems(i)},e.utils.copy(e.items.AbstractContentItem.prototype,{setSize:function(){throw new Error("Abstract Method")},callDownwards:function(t,e,i,n){var s;for(i!==!0&&n!==!0&&this[t].apply(this,e||[]),s=0;s0?this.callDownwards("setSize"):this instanceof e.items.Root||this.config.isClosable!==!0||this.parent.removeChild(this)},addChild:function(t,e){void 0===e&&(e=this.contentItems.length),this.contentItems.splice(e,0,t),void 0===this.config.content&&(this.config.content=[]),this.config.content.splice(e,0,t.config),t.parent=this,t.parent.isInitialised===!0&&t.isInitialised===!1&&t._$init()},replaceChild:function(t,i,n){i=this.layoutManager._$normalizeContentItem(i);var s=e.utils.indexOf(t,this.contentItems),o=t.element[0].parentNode;if(s===-1)throw new Error("Can't replace child. oldChild is not child of this");o.replaceChild(i.element[0],t.element[0]),n===!0&&(t.parent=null,t._$destroy()),this.contentItems[s]=i,i.parent=this,this.isStack&&(this.header.tabs[s].contentItem=i),i.parent.isInitialised===!0&&i.isInitialised===!1&&i._$init(),this.callDownwards("setSize")},remove:function(){this.parent.removeChild(this)},popout:function(){var t=this.layoutManager.createPopout(this);return this.emitBubblingEvent("stateChanged"),t},toggleMaximise:function(t){t&&t.preventDefault(),this.isMaximised===!0?this.layoutManager._$minimiseItem(this):this.layoutManager._$maximiseItem(this),this.isMaximised=!this.isMaximised,this.emitBubblingEvent("stateChanged")},select:function(){this.layoutManager.selectedItem!==this&&(this.layoutManager.selectItem(this,!0),this.element.addClass("lm_selected"))},deselect:function(){this.layoutManager.selectedItem===this&&(this.layoutManager.selectedItem=null,this.element.removeClass("lm_selected"))},setTitle:function(t){this.config.title=t,this.emit("titleChanged",t),this.emit("stateChanged")},hasId:function(t){return!!this.config.id&&("string"==typeof this.config.id?this.config.id===t:this.config.id instanceof Array?e.utils.indexOf(t,this.config.id)!==-1:void 0)},addId:function(t){this.hasId(t)||(this.config.id?"string"==typeof this.config.id?this.config.id=[this.config.id,t]:this.config.id instanceof Array&&this.config.id.push(t):this.config.id=t)},removeId:function(t){if(!this.hasId(t))throw new Error("Id not found");if("string"==typeof this.config.id)delete this.config.id;else if(this.config.id instanceof Array){var i=e.utils.indexOf(t,this.config.id);this.config.id.splice(i,1)}},getItemsByFilter:function(t){var e=[],i=function(n){for(var s=0;s'),this.childElementContainer=this.element,this._containerElement=s,this._containerElement.append(this.element)},e.utils.extend(e.items.Root,e.items.AbstractContentItem),e.utils.copy(e.items.Root.prototype,{addChild:function(t){if(this.contentItems.length>0)throw new Error("Root node can only have a single child");t=this.layoutManager._$normalizeContentItem(t,this),this.childElementContainer.append(t.element),e.items.AbstractContentItem.prototype.addChild.call(this,t),this.callDownwards("setSize"),this.emitBubblingEvent("stateChanged")},setSize:function(t,e){t="undefined"==typeof t?this._containerElement.width():t,e="undefined"==typeof e?this._containerElement.height():e,this.element.width(t),this.element.height(e),this.contentItems[0]&&(this.contentItems[0].element.width(t),this.contentItems[0].element.height(e))},_$highlightDropZone:function(t,i,n){this.layoutManager.tabDropPlaceholder.remove(),e.items.AbstractContentItem.prototype._$highlightDropZone.apply(this,arguments)},_$onDrop:function(t,i){var n;if(t.isComponent&&(n=this.layoutManager.createContentItem({type:"stack",header:t.config.header||{}},this),n._$init(),n.addChild(t),t=n),this.contentItems.length){var s="x"==i.side[0]?"row":"column",o="x"==i.side[0]?"width":"height",r="2"==i.side[1],a=this.contentItems[0];if(!a instanceof e.items.RowOrColumn||a.type!=s){var h=this.layoutManager.createContentItem({type:s},this);this.replaceChild(a,h),h.addChild(t,r?0:void 0,!0),h.addChild(a,r?void 0:0,!0),a.config[o]=50,t.config[o]=50,h.callDownwards("setSize")}else{var l=a.contentItems[r?0:a.contentItems.length-1];a.addChild(t,r?0:void 0,!0),l.config[o]*=.5,t.config[o]=l.config[o],a.callDownwards("setSize")}}else this.addChild(t)}}),e.items.RowOrColumn=function(i,n,s,o){e.items.AbstractContentItem.call(this,n,s,o),this.isRow=!i,this.isColumn=i,this.element=t('
              '),this.childElementContainer=this.element,this._splitterSize=n.config.dimensions.borderWidth,this._splitterGrabSize=n.config.dimensions.borderGrabWidth,this._isColumn=i,this._dimension=i?"height":"width",this._splitter=[],this._splitterPosition=null,this._splitterMinPosition=null,this._splitterMaxPosition=null},e.utils.extend(e.items.RowOrColumn,e.items.AbstractContentItem),e.utils.copy(e.items.RowOrColumn.prototype,{addChild:function(t,i,n){var s,o,r,a;if(t=this.layoutManager._$normalizeContentItem(t,this),void 0===i&&(i=this.contentItems.length),this.contentItems.length>0?(a=this._createSplitter(Math.max(0,i-1)).element,i>0?(this.contentItems[i-1].element.after(a),a.after(t.element)):(this.contentItems[0].element.before(a),a.before(t.element))):this.childElementContainer.append(t.element),e.items.AbstractContentItem.prototype.addChild.call(this,t,i),s=1/this.contentItems.length*100,n===!0)return void this.emitBubblingEvent("stateChanged");for(r=0;r0&&(this._calculateRelativeSizes(),this._setAbsoluteSizes()),this.emitBubblingEvent("stateChanged"),this.emit("resize")},_$init:function(){if(this.isInitialised!==!0){var t;for(e.items.AbstractContentItem.prototype._$init.call(this),t=0;t0&&e.itemSizes[t]++,this._isColumn?(this.contentItems[t].element.width(e.totalWidth),this.contentItems[t].element.height(e.itemSizes[t])):(this.contentItems[t].element.width(e.itemSizes[t]),this.contentItems[t].element.height(e.totalHeight))},_calculateAbsoluteSizes:function(){var t,e,i,n=(this.contentItems.length-1)*this._splitterSize,s=this.element.width(),o=this.element.height(),r=0,a=[];for(this._isColumn?o-=n:s-=n,t=0;t0){for(t=0;t100)for(t=0;tr)){for(t=a/r,h=a,m=0;mthis._splitterMinPosition&&n'),this._activeContentItem=null;var o=i.config;this._header={show:o.settings.hasHeaders===!0&&n.hasHeaders!==!1,popout:o.settings.showPopoutIcon&&o.labels.popout,maximise:o.settings.showMaximiseIcon&&o.labels.maximise,close:o.settings.showCloseIcon&&o.labels.close,minimise:o.labels.minimise},o.header&&e.utils.copy(this._header,o.header),n.header&&e.utils.copy(this._header,n.header),n.content&&n.content[0]&&n.content[0].header&&e.utils.copy(this._header,n.content[0].header),this._dropZones={},this._dropSegment=null,this._contentAreaDimensions=null,this._dropIndex=null,this.isStack=!0,this.childElementContainer=t('
              '),this.header=new e.controls.Header(i,this),this.element.append(this.header.element),this.element.append(this.childElementContainer),this._setupHeaderPosition(),this._$validateClosability()},e.utils.extend(e.items.Stack,e.items.AbstractContentItem),e.utils.copy(e.items.Stack.prototype,{setSize:function(){var t,e=this._header.show?this.layoutManager.config.dimensions.headerHeight:0,i=this.element.width()-(this._sided?e:0),n=this.element.height()-(this._sided?0:e);for(this.childElementContainer.width(i),this.childElementContainer.height(n),t=0;t0){if(i=this.contentItems[this.config.activeItemIndex||0],!i)throw new Error("Configured activeItemIndex out of bounds");this.setActiveContentItem(i)}}},setActiveContentItem:function(t){if(e.utils.indexOf(t,this.contentItems)===-1)throw new Error("contentItem is not a child of this stack");null!==this._activeContentItem&&this._activeContentItem._$hide(),this._activeContentItem=t,this.header.setActiveContentItem(t),t._$show(),this.emit("activeContentItemChanged",t),this.layoutManager.emit("activeContentItemChanged",t),this.emitBubblingEvent("stateChanged")},getActiveContentItem:function(){return this.header.activeContentItem},addChild:function(t,i){t=this.layoutManager._$normalizeContentItem(t,this),e.items.AbstractContentItem.prototype.addChild.call(this,t,i),this.childElementContainer.append(t.element),this.header.createTab(t,i),this.setActiveContentItem(t),this.callDownwards("setSize"),this._$validateClosability(),this.emitBubblingEvent("stateChanged")},removeChild:function(t,i){var n=e.utils.indexOf(t,this.contentItems);e.items.AbstractContentItem.prototype.removeChild.call(this,t,i),this.header.removeTab(t),this.header.activeContentItem===t&&(this.contentItems.length>0?this.setActiveContentItem(this.contentItems[Math.max(n-1,0)]):this._activeContentItem=null),this._$validateClosability(),this.emitBubblingEvent("stateChanged")},_$validateClosability:function(){var t,e,i;for(t=this.header._isClosable(),i=0,e=this.contentItems.length;it&&n.y1e)return void("header"===i?(this._dropSegment="header",this._highlightHeaderDropZone(this._sided?e:t)):(this._resetHeaderDropZone(),this._highlightBodyDropZone(i)))},_$getArea:function(){if(this.element.is(":visible")===!1)return null;var t=e.items.AbstractContentItem.prototype._$getArea,i=t.call(this,this.header.element),n=t.call(this,this.childElementContainer),s=n.x2-n.x1,o=n.y2-n.y1;return this._contentAreaDimensions={header:{hoverArea:{x1:i.x1,y1:i.y1,x2:i.x2,y2:i.y2},highlightArea:{x1:i.x1,y1:i.y1,x2:i.x2,y2:i.y2}}},this._activeContentItem&&this._activeContentItem.isComponent===!1?i:0===this.contentItems.length?(this._contentAreaDimensions.body={hoverArea:{x1:n.x1,y1:n.y1,x2:n.x2,y2:n.y2},highlightArea:{x1:n.x1,y1:n.y1,x2:n.x2,y2:n.y2}},t.call(this,this.element)):(this._contentAreaDimensions.left={hoverArea:{x1:n.x1,y1:n.y1,x2:n.x1+.25*s,y2:n.y2},highlightArea:{x1:n.x1,y1:n.y1,x2:n.x1+.5*s,y2:n.y2}},this._contentAreaDimensions.top={hoverArea:{x1:n.x1+.25*s,y1:n.y1,x2:n.x1+.75*s,y2:n.y1+.5*o},highlightArea:{x1:n.x1,y1:n.y1,x2:n.x2,y2:n.y1+.5*o}},this._contentAreaDimensions.right={hoverArea:{x1:n.x1+.75*s,y1:n.y1,x2:n.x2,y2:n.y2},highlightArea:{x1:n.x1+.5*s,y1:n.y1,x2:n.x2,y2:n.y2}},this._contentAreaDimensions.bottom={hoverArea:{x1:n.x1+.25*s,y1:n.y1+.5*o,x2:n.x1+.75*s,y2:n.y2},highlightArea:{x1:n.x1,y1:n.y1+.5*o,x2:n.x2,y2:n.y2}},t.call(this,this.element))},_highlightHeaderDropZone:function(t){var e,i,n,s,o,r,a,h,l,c=this.header.tabs.length,d=!1;if(0===c)return a=this.header.element.offset(),void this.layoutManager.dropTargetIndicator.highlightArea({x1:a.left,x2:a.left+100,y1:a.top+this.header.element.height()-20,y2:a.top+this.header.element.height()});for(e=0;es&&t=0&&this._header.show;if(this.header.element.toggle(!!this._header.show),this._side=t,this._sided=["right","left"].indexOf(this._side)>=0,this.element.removeClass("lm_left lm_right lm_bottom"),this._side&&this.element.addClass("lm_"+this._side),this.element.find(".lm_header").length&&this.childElementContainer){var e=["right","bottom"].indexOf(this._side)>=0?"before":"after";this.header.element[e](this.childElementContainer),this.callDownwards("setSize")}},_highlightBodyDropZone:function(t){var e=this._contentAreaDimensions[t].highlightArea;this.layoutManager.dropTargetIndicator.highlightArea(e),this._dropSegment=t}}),e.utils.BubblingEvent=function(t,e){this.name=t,this.origin=e,this.isPropagationStopped=!1},e.utils.BubblingEvent.prototype.stopPropagation=function(){this.isPropagationStopped=!0},e.utils.ConfigMinifier=function(){if(this._keys=["settings","hasHeaders","constrainDragToContainer","selectionEnabled","dimensions","borderWidth","minItemHeight","minItemWidth","headerHeight","dragProxyWidth","dragProxyHeight","labels","close","maximise","minimise","popout","content","componentName","componentState","id","width","type","height","isClosable","title","popoutWholeStack","openPopouts","parentId","activeItemIndex","reorderEnabled","borderGrabWidth"],this._keys.length>36)throw new Error("Too many keys in config minifier map");this._values=[!0,!1,"row","column","stack","component","close","maximise","minimise","open in new window"]},e.utils.copy(e.utils.ConfigMinifier.prototype,{ -minifyConfig:function(t){var e={};return this._nextLevel(t,e,"_min"),e},unminifyConfig:function(t){var e={};return this._nextLevel(t,e,"_max"),e},_nextLevel:function(t,e,i){var n,s;for(n in t)t instanceof Array&&(n=parseInt(n,10)),t.hasOwnProperty(n)&&(s=this[i](n,this._keys),"object"==typeof t[n]?(e[s]=t[n]instanceof Array?[]:{},this._nextLevel(t[n],e[s],i)):e[s]=this[i](t[n],this._values))},_min:function(t,i){if("string"==typeof t&&1===t.length)return"___"+t;var n=e.utils.indexOf(t,i);return n===-1?t:n.toString(36)},_max:function(t,e){return"string"==typeof t&&1===t.length?e[parseInt(t,36)]:"string"==typeof t&&"___"===t.substr(0,3)?t[3]:t}}),e.utils.EventHub=function(i){e.utils.EventEmitter.call(this),this._layoutManager=i,this._dontPropagateToParent=null,this._childEventSource=null,this.on(e.utils.EventEmitter.ALL_EVENT,e.utils.fnBind(this._onEventFromThis,this)),this._boundOnEventFromChild=e.utils.fnBind(this._onEventFromChild,this),t(window).on("gl_child_event",this._boundOnEventFromChild)},e.utils.EventHub.prototype._onEventFromThis=function(){var t=Array.prototype.slice.call(arguments);this._layoutManager.isSubWindow&&t[0]!==this._dontPropagateToParent&&this._propagateToParent(t),this._propagateToChildren(t),this._dontPropagateToParent=null,this._childEventSource=null},e.utils.EventHub.prototype._$onEventFromParent=function(t){this._dontPropagateToParent=t[0],this.emit.apply(this,t)},e.utils.EventHub.prototype._onEventFromChild=function(t){this._childEventSource=t.originalEvent.__gl,this.emit.apply(this,t.originalEvent.__glArgs)},e.utils.EventHub.prototype._propagateToParent=function(t){var e,i="gl_child_event";document.createEvent?(e=window.opener.document.createEvent("HTMLEvents"),e.initEvent(i,!0,!0)):(e=window.opener.document.createEventObject(),e.eventType=i),e.eventName=i,e.__glArgs=t,e.__gl=this._layoutManager,document.createEvent?window.opener.dispatchEvent(e):window.opener.fireEvent("on"+e.eventType,e)},e.utils.EventHub.prototype._propagateToChildren=function(t){var e,i;for(i=0;i