From 28b48de4540f695fbcfe875300af432a9cc45d15 Mon Sep 17 00:00:00 2001 From: Kevin Jahns Date: Tue, 12 Aug 2014 19:13:42 +0200 Subject: [PATCH] switched to Gulp --- Gruntfile.coffee | 135 - LICENSE.txt | 2 +- bower.json | 2 +- build/browser/Connectors/IwcConnector.js | 118 + build/browser/Connectors/IwcConnector.min.js | 1 + build/browser/Connectors/TestConnector.js | 1434 ++ build/browser/Connectors/TestConnector.min.js | 1 + build/browser/Engine.js | 110 + build/browser/Engine.min.js | 1 + build/browser/Frameworks/JsonYatta.js | 1298 ++ build/browser/Frameworks/JsonYatta.min.js | 1 + build/browser/Frameworks/TextYatta.js | 1114 ++ build/browser/Frameworks/TextYatta.min.js | 1 + build/browser/HistoryBuffer.js | 128 + build/browser/HistoryBuffer.min.js | 1 + build/browser/Types/BasicTypes.js | 361 + build/browser/Types/BasicTypes.min.js | 1 + build/browser/Types/JsonTypes.js | 985 ++ build/browser/Types/JsonTypes.min.js | 1 + build/browser/Types/StructuredTypes.js | 636 + build/browser/Types/StructuredTypes.min.js | 1 + build/browser/Types/TextTypes.js | 816 + build/browser/Types/TextTypes.min.js | 1 + build/browser/Types/XmlTypes.js | 6 + build/browser/Types/XmlTypes.min.js | 1 + build/browser/index.js | 2920 ++++ build/browser/index.min.js | 2 + build/node/Connectors/IwcConnector.coffee | 112 + build/node/Connectors/IwcConnector.coffee.map | 1 + build/node/Connectors/IwcConnector.js | 2 + build/node/Connectors/IwcConnector.js.map | 1 + build/node/Connectors/TestConnector.coffee | 76 + .../node/Connectors/TestConnector.coffee.map | 1 + build/node/Connectors/TestConnector.js | 2 + build/node/Connectors/TestConnector.js.map | 1 + build/node/Engine.coffee | 101 + build/node/Engine.js | 2 + build/node/Frameworks/JsonYatta.coffee | 85 + build/node/Frameworks/JsonYatta.coffee.map | 1 + build/node/Frameworks/JsonYatta.js | 2 + build/node/Frameworks/JsonYatta.js.map | 1 + build/node/Frameworks/TextYatta.coffee | 82 + build/node/Frameworks/TextYatta.coffee.map | 1 + build/node/Frameworks/TextYatta.js | 2 + build/node/Frameworks/TextYatta.js.map | 1 + build/node/HistoryBuffer.coffee | 123 + build/node/HistoryBuffer.js | 2 + build/node/HistoryBuffer.js.map | 1 + build/node/Types/BasicTypes.coffee | 439 + build/node/Types/BasicTypes.coffee.map | 1 + build/node/Types/BasicTypes.js | 2 + build/node/Types/BasicTypes.js.map | 1 + build/node/Types/JsonTypes.coffee | 210 + build/node/Types/JsonTypes.coffee.map | 1 + build/node/Types/JsonTypes.js | 2 + build/node/Types/JsonTypes.js.map | 1 + build/node/Types/StructuredTypes.coffee | 310 + build/node/Types/StructuredTypes.coffee.map | 1 + build/node/Types/StructuredTypes.js | 2 + build/node/Types/StructuredTypes.js.map | 1 + build/node/Types/TextTypes.coffee | 177 + build/node/Types/TextTypes.coffee.map | 1 + build/node/Types/TextTypes.js | 2 + build/node/Types/TextTypes.js.map | 1 + build/node/Types/XmlTypes.coffee | 0 build/node/Types/XmlTypes.coffee.map | 1 + build/node/Types/XmlTypes.js | 2 + build/node/Types/XmlTypes.js.map | 1 + build/node/index.coffee | 10 + build/node/index.js | 2 + build/node/index.js.map | 1 + build/test/Yatta_test.js | 13748 +++++++++++++++ {dest/browser => build}/test/index.html | 4 +- dest/browser/Frameworks/JsonIwcYatta.js | 1385 -- dest/browser/Frameworks/JsonIwcYatta.min.js | 10 - dest/browser/Widgets/CollaborationWidget.xml | 31 - dest/browser/Widgets/CollaborationWidget2.xml | 32 - dest/browser/Widgets/iwc-teststub.xml | 241 - dest/browser/Widgets/libs/DUIClient.js | 371 - dest/browser/Widgets/libs/DUIClient.min.js | 2 - dest/browser/test/Yatta_test.js | 13780 ---------------- dest/lib/Connectors/IwcConnector.js | 115 - dest/lib/Connectors/IwcConnector.js.map | 10 - dest/lib/Connectors/TestConnector.js | 86 - dest/lib/Connectors/TestConnector.js.map | 10 - dest/lib/Engine.js | 107 - dest/lib/Engine.js.map | 10 - dest/lib/Frameworks/JsonYatta.js | 78 - dest/lib/Frameworks/JsonYatta.js.map | 10 - dest/lib/Frameworks/TextYatta.js | 63 - dest/lib/Frameworks/TextYatta.js.map | 10 - dest/lib/HistoryBuffer.js | 125 - dest/lib/HistoryBuffer.js.map | 10 - dest/lib/Types/BasicTypes.js | 330 - dest/lib/Types/BasicTypes.js.map | 10 - dest/lib/Types/JsonTypes.js | 168 - dest/lib/Types/JsonTypes.js.map | 10 - dest/lib/Types/StructuredTypes.js | 274 - dest/lib/Types/StructuredTypes.js.map | 10 - dest/lib/Types/TextTypes.js | 179 - dest/lib/Types/TextTypes.js.map | 10 - dest/lib/Types/XmlTypes.js | 3 - dest/lib/Types/XmlTypes.js.map | 10 - dest/test/Yatta_test.js | 442 - doc/alphabetical_index.html | 2857 +++- doc/class/A.html | 109 + doc/class/ASTApi.html | 147 + doc/class/ASTLinter.html | 221 + doc/class/AddName.html | 8 +- doc/class/Another/Namespace.MyClass.html | 119 + doc/class/App/TestMethodDocumentation.html | 505 + doc/class/ArrowSpacing.html | 184 + doc/class/BaseLinter.html | 239 + doc/class/CSVReporter.html | 167 + doc/class/Cache.html | 254 + doc/class/CamelCaseClasses.html | 159 + doc/class/CheckstyleReporter.html | 178 + doc/class/Class.html | 120 + doc/class/Code.html | 197 + doc/class/CodoCommand.html | 197 + doc/class/CoffeeMaker.html | 293 + doc/class/ColonAssignmentSpacing.html | 163 + doc/class/Command.html | 328 + doc/class/Comment.html | 198 + doc/class/Delete.html | 11 +- doc/class/Delimiter.html | 11 +- doc/class/Directive.html | 262 + doc/class/Documentation.html | 187 + doc/class/DuplicateKey.html | 218 + doc/class/EmptyConstructorNeedsParens.html | 184 + doc/class/Engine.html | 8 +- doc/class/Entities/Class.html | 482 + doc/class/Entities/Extra.html | 169 + doc/class/Entities/File.html | 189 + doc/class/Entities/Method.html | 175 + doc/class/Entities/Mixin.html | 355 + doc/class/Entities/Property.html | 246 + doc/class/Entities/Variable.html | 214 + doc/class/Entity.html | 211 + doc/class/Environment.html | 453 + doc/class/ErrorReport.html | 273 + doc/class/Example/Animal.Lion.html | 279 + doc/class/Example/Animal.html | 256 + doc/class/Example/Cell.html | 169 + doc/class/Example/Concern.html | 133 + doc/class/Example/Events.html | 186 + doc/class/Example/Methods.Virtual.html | 310 + doc/class/Example/Overload.html | 247 + doc/class/Example/Plant.html | 238 + doc/class/Filter.html | 262 + doc/class/Fluffy.html | 129 + doc/class/GlobalTestClass.html | 115 + doc/class/Haml.html | 738 + doc/class/HamlCoffee.html | 1293 ++ doc/class/HistoryBuffer.html | 8 +- doc/class/ImmutableObject.html | 11 +- doc/class/Indentation.html | 274 + doc/class/Insert.html | 11 +- doc/class/IwcConnector.html | 8 +- doc/class/JSLintReporter.html | 187 + doc/class/JsonType.html | 8 +- doc/class/JsonWrapper.html | 8 +- doc/class/JsonYatta.html | 8 +- doc/class/LexicalLinter.html | 243 + doc/class/LineApi.html | 254 + doc/class/LineEndings.html | 152 + doc/class/LineLinter.html | 269 + doc/class/ListManager.html | 8 +- doc/class/MapManager.html | 8 +- doc/class/MaxLineLength.html | 153 + doc/class/Meta/Method.html | 315 + doc/class/Meta/Parameter.html | 255 + doc/class/MissingFatArrows.html | 343 + doc/class/MyTestClass.html | 109 + doc/class/NS/Clazz.html | 117 + doc/class/NewlinesAfterClasses.html | 152 + doc/class/NoBackticks.html | 159 + doc/class/NoDebugger.html | 159 + doc/class/NoEmptyFunctions.html | 171 + doc/class/NoEmptyParamList.html | 159 + doc/class/NoImplicitBraces.html | 180 + doc/class/NoImplicitParens.html | 160 + doc/class/NoInterpolationInSingleQuotes.html | 159 + doc/class/NoPlusPlus.html | 159 + doc/class/NoStandAloneAt.html | 159 + doc/class/NoTabs.html | 151 + doc/class/NoThrowingStrings.html | 159 + doc/class/NoTrailingSemicolons.html | 151 + doc/class/NoTrailingWhitespace.html | 153 + doc/class/NoUnnecessaryDoubleQuotes.html | 199 + doc/class/NoUnnecessaryFatArrows.html | 275 + doc/class/Node.html | 730 + doc/class/NonEmptyConstructorNeedsParens.html | 157 + doc/class/Operation.html | 107 +- doc/class/OverDocumentedClass.html | 677 + doc/class/Person.html | 277 + doc/class/RawReporter.html | 167 + doc/class/ReplaceManager.html | 8 +- doc/class/Replaceable.html | 8 +- doc/class/Reporter.html | 253 + doc/class/Some/Namespace.MyClass.html | 119 + doc/class/SomeNamespace/MyClass.html | 148 + doc/class/SpaceOperators.html | 291 + doc/class/Subclass.html | 140 + doc/class/Subsubclass.html | 140 + doc/class/Test.html | 397 + doc/class/TestAssignedParameters.html | 135 + doc/class/TestClassDocumentation.html | 183 + doc/class/TestClassMethods.html | 219 + doc/class/TestClassVariables.html | 147 + doc/class/TestConnector.html | 8 +- doc/class/TestContstantVariables.html | 132 + doc/class/TestExample.html | 157 + doc/class/TestExportClass.html | 115 + doc/class/TestInstanceMethods.html | 221 + doc/class/TestInstanceVariables.html | 147 + doc/class/TestMarkdownDocumentation.html | 164 + doc/class/TestNamedParameters.html | 147 + doc/class/Text.html | 183 + doc/class/TextDelete.html | 8 +- doc/class/TextInsert.html | 8 +- doc/class/TextYatta.html | 8 +- doc/class/Theme/Templater.html | 230 + doc/class/Theme/Theme.html | 514 + doc/class/Theme/TreeBuilder.html | 175 + doc/class/TokenApi.html | 163 + doc/class/Tools/Markdown.html | 246 + doc/class/Tools/Referencer.html | 149 + .../Tower/Model.Relation.HasMany.Scope.html | 121 + .../Tower/Model.Relation.HasMany.Scope2.html | 123 + doc/class/Tower/Model.Relation.HasMany.html | 121 + doc/class/Traverser.html | 399 + doc/class/Word.html | 8 +- doc/class_list.html | 1083 +- doc/extra/LICENSE.txt.html | 2 +- doc/extra/README.md.html | 8 +- doc/extra/examples/IwcJson.md.html | 2 +- doc/extra/examples/README.md.html | 2 +- doc/extra/extras/imgs/Yatta_logo.png | Bin 0 -> 9259 bytes doc/extra_list.html | 28 +- doc/file/gulpfile.coffee.html | 133 + .../lib/Connectors/IwcConnector.coffee.html | 8 +- .../lib/Connectors/TestConnector.coffee.html | 8 +- doc/file/lib/Engine.coffee.html | 8 +- doc/file/lib/Frameworks/JsonYatta.coffee.html | 8 +- doc/file/lib/Frameworks/TextYatta.coffee.html | 8 +- doc/file/lib/HistoryBuffer.coffee.html | 8 +- doc/file/lib/Types/BasicTypes.coffee.html | 8 +- doc/file/lib/Types/JsonTypes.coffee.html | 8 +- .../lib/Types/StructuredTypes.coffee.html | 8 +- doc/file/lib/Types/TextTypes.coffee.html | 8 +- doc/file/lib/Types/XmlTypes.coffee.html | 8 +- doc/file/lib/index.coffee.html | 111 + .../coffeeify/example/baz.coffee.html | 115 + .../coffeeify/example/foo.coffee.html | 115 + .../Base64/test/base64.coffee.html | 127 + .../esutils/test/code.coffee.html | 146 + .../esutils/test/keyword.coffee.html | 162 + .../resolve/test/resolver/cup.coffee.html | 129 + .../resolve/test/resolver/mug.coffee.html | 129 + .../resolve/test/resolver/cup.coffee.html | 125 + .../resolve/test/resolver/mug.coffee.html | 125 + .../resolve/test/resolver/cup.coffee.html | 133 + .../resolve/test/resolver/mug.coffee.html | 133 + .../test/coffee_bin/main.coffee.html | 121 + .../browserify/test/coffee_bin/x.coffee.html | 121 + .../test/coffeeify/main.coffee.html | 121 + .../resolve/test/resolver/cup.coffee.html | 121 + .../resolve/test/resolver/mug.coffee.html | 121 + .../grunt-codo/Gruntfile.coffee.html | 113 + .../node_modules/codo/Gruntfile.coffee.html | 117 + .../codo/lib/_entities.coffee.html | 130 + .../node_modules/codo/lib/_meta.coffee.html | 130 + .../node_modules/codo/lib/_tools.coffee.html | 130 + .../node_modules/codo/lib/codo.coffee.html | 262 + .../node_modules/codo/lib/command.coffee.html | 129 + .../codo/lib/documentation.coffee.html | 129 + .../codo/lib/entities/class.coffee.html | 131 + .../codo/lib/entities/extra.coffee.html | 131 + .../codo/lib/entities/file.coffee.html | 131 + .../codo/lib/entities/method.coffee.html | 131 + .../codo/lib/entities/mixin.coffee.html | 131 + .../codo/lib/entities/property.coffee.html | 131 + .../codo/lib/entities/variable.coffee.html | 131 + .../node_modules/codo/lib/entity.coffee.html | 129 + .../codo/lib/environment.coffee.html | 129 + .../codo/lib/meta/method.coffee.html | 131 + .../codo/lib/meta/parameter.coffee.html | 131 + .../codo/lib/tools/markdown.coffee.html | 131 + .../codo/lib/tools/referencer.coffee.html | 131 + .../codo/lib/traverser.coffee.html | 129 + .../haml-coffee/Gruntfile.coffee.html | 121 + .../spec/compiler_spec.coffee.html | 134 + .../src/cli/coffee-maker.coffee.html | 154 + .../haml-coffee/src/cli/command.coffee.html | 185 + .../haml-coffee/src/haml-coffee.coffee.html | 133 + .../haml-coffee/src/hamlc.coffee.html | 284 + .../haml-coffee/src/nodes/code.coffee.html | 135 + .../haml-coffee/src/nodes/comment.coffee.html | 135 + .../src/nodes/directive.coffee.html | 135 + .../haml-coffee/src/nodes/filter.coffee.html | 135 + .../haml-coffee/src/nodes/haml.coffee.html | 135 + .../haml-coffee/src/nodes/node.coffee.html | 135 + .../haml-coffee/src/nodes/text.coffee.html | 135 + .../haml-coffee/src/util/text.coffee.html | 222 + .../assets/javascripts/app.js.coffee.html | 127 + .../fixtures/app/views/people.coffee.html | 133 + .../spec/shellwords_spec.coffee.html | 127 + .../shellwords/src/shellwords.coffee.html | 193 + .../class_description_markdown.coffee.html | 133 + .../classes/class_documentation.coffee.html | 133 + .../classes/class_extends.coffee.html | 133 + .../classes/empty_class.coffee.html | 133 + .../classes/export_class.coffee.html | 133 + .../classes/global_class.coffee.html | 133 + .../classes/inner_class.coffee.html | 133 + .../classes/namespaced_class.coffee.html | 136 + .../classes/simple_class.coffee.html | 133 + .../complicateds/methods.coffee.html | 152 + .../complicateds/variables.coffee.html | 139 + .../_templates/environment/class.coffee.html | 133 + .../_templates/environment/mixin.coffee.html | 133 + .../example/src/angry_animal.coffee.html | 210 + .../_templates/example/src/animal.coffee.html | 135 + .../_templates/example/src/lion.coffee.html | 135 + .../src/over_documented_class.coffee.html | 135 + .../src/over_documented_mixin.coffee.html | 135 + .../files/non_class_file.coffee.html | 299 + .../methods/assigned_parameters.coffee.html | 133 + .../methods/class_methods.coffee.html | 133 + .../curly_method_documentation.coffee.html | 133 + .../methods/dynamic_methods.coffee.html | 133 + .../methods/instance_methods.coffee.html | 133 + .../methods/method_documentation.coffee.html | 133 + .../methods/method_events.coffee.html | 133 + .../methods/method_example.coffee.html | 133 + .../methods/named_parameters.coffee.html | 133 + .../methods/overload_method.coffee.html | 133 + .../_templates/mixins/concern.coffee.html | 143 + .../mixins/extend_mixin.coffee.html | 143 + .../mixins/include_mixin.coffee.html | 143 + .../mixins/missing_mixins.coffee.html | 133 + .../mixins/mixin_documentation.coffee.html | 133 + .../mixins/mixin_methods.coffee.html | 133 + .../properties/properties.coffee.html | 133 + .../variables/class_variables.coffee.html | 133 + .../variables/constant_variables.coffee.html | 133 + .../variables/instance_variables.coffee.html | 133 + .../codo/spec/lib/codo_spec.coffee.html | 121 + .../spec/lib/entities/class_spec.coffee.html | 123 + .../spec/lib/entities/mixin_spec.coffee.html | 123 + .../spec/lib/environment_spec.coffee.html | 121 + .../spec/lib/meta/method_spec.coffee.html | 123 + .../spec/lib/meta/parameter_spec.coffee.html | 123 + .../default/lib/templater_spec.coffee.html | 125 + .../themes/default/lib/theme_spec.coffee.html | 125 + .../default/lib/tree_builder_spec.coffee.html | 125 + .../assets/javascript/codo.coffee.html | 125 + .../assets/javascript/fuzzy.coffee.html | 125 + .../assets/javascript/keys.coffee.html | 125 + .../assets/javascript/sidebar.coffee.html | 125 + .../default/assets/javascript/toc.coffee.html | 125 + .../javascript/vendor/fuzzy.coffee.html | 245 + .../themes/default/lib/_theme.coffee.html | 134 + .../themes/default/lib/templater.coffee.html | 133 + .../codo/themes/default/lib/theme.coffee.html | 133 + .../default/lib/tree_builder.coffee.html | 133 + .../grunt-codo/src/codo.coffee.html | 115 + .../grunt-codo/src/utils/command.coffee.html | 127 + .../test/fixtures/custom/animal.coffee.html | 129 + .../test/fixtures/custom/cell.coffee.html | 129 + .../test/fixtures/custom/plant.coffee.html | 129 + .../test/fixtures/default/animal.coffee.html | 129 + .../grunt-coffeelint/Gruntfile.coffee.html | 113 + .../coffeelint/src/ast_linter.coffee.html | 132 + .../coffeelint/src/base_linter.coffee.html | 185 + .../coffeelint/src/coffeelint.coffee.html | 384 + .../coffeelint/src/commandline.coffee.html | 324 + .../coffeelint/src/configfinder.coffee.html | 247 + .../coffeelint/src/htmldoc.coffee.html | 156 + .../coffeelint/src/lexical_linter.coffee.html | 132 + .../coffeelint/src/line_linter.coffee.html | 147 + .../coffeelint/src/rules.coffee.html | 167 + .../src/rules/arrow_spacing.coffee.html | 131 + .../src/rules/camel_case_classes.coffee.html | 144 + .../colon_assignment_spacing.coffee.html | 131 + .../rules/cyclomatic_complexity.coffee.html | 131 + .../src/rules/duplicate_key.coffee.html | 131 + ...empty_constructor_needs_parens.coffee.html | 131 + .../src/rules/indentation.coffee.html | 131 + .../src/rules/line_endings.coffee.html | 131 + .../src/rules/max_line_length.coffee.html | 145 + .../src/rules/missing_fat_arrows.coffee.html | 317 + .../rules/newlines_after_classes.coffee.html | 131 + .../src/rules/no_backticks.coffee.html | 131 + .../src/rules/no_empty_param_list.coffee.html | 131 + .../src/rules/no_implicit_braces.coffee.html | 131 + .../src/rules/no_implicit_parens.coffee.html | 131 + .../src/rules/no_plusplus.coffee.html | 131 + .../src/rules/no_stand_alone_at.coffee.html | 131 + .../coffeelint/src/rules/no_tabs.coffee.html | 142 + .../src/rules/no_throwing_strings.coffee.html | 131 + .../rules/no_trailing_semicolons.coffee.html | 144 + .../rules/no_trailing_whitespace.coffee.html | 146 + .../no_unnecessary_fat_arrows.coffee.html | 237 + ...empty_constructor_needs_parens.coffee.html | 131 + .../src/rules/space_operators.coffee.html | 131 + .../coffeelint/vowsrunner.coffee.html | 117 + .../Base64/test/base64.coffee.html | 127 + .../esutils/test/code.coffee.html | 146 + .../esutils/test/keyword.coffee.html | 162 + .../resolve/test/resolver/cup.coffee.html | 125 + .../resolve/test/resolver/mug.coffee.html | 125 + .../resolve/test/resolver/cup.coffee.html | 133 + .../resolve/test/resolver/mug.coffee.html | 133 + .../test/coffee_bin/main.coffee.html | 121 + .../browserify/test/coffee_bin/x.coffee.html | 121 + .../test/coffeeify/main.coffee.html | 121 + .../test/fixtures/trans_bar.coffee.html | 130 + .../test/fixtures/trans_foo.coffee.html | 131 + .../test/fixtures/transform.coffee.html | 117 + .../test/fixtures/grammar.coffee.html | 1028 ++ .../resolve/test/resolver/cup.coffee.html | 125 + .../resolve/test/resolver/mug.coffee.html | 125 + .../coffeelint/src/ast_linter.coffee.html | 180 + .../coffeelint/src/base_linter.coffee.html | 185 + .../coffeelint/src/cache.coffee.html | 148 + .../coffeelint/src/coffeelint.coffee.html | 448 + .../coffeelint/src/commandline.coffee.html | 355 + .../coffeelint/src/configfinder.coffee.html | 247 + .../coffeelint/src/htmldoc.coffee.html | 156 + .../coffeelint/src/lexical_linter.coffee.html | 132 + .../coffeelint/src/line_linter.coffee.html | 147 + .../src/reporters/checkstyle.coffee.html | 131 + .../coffeelint/src/reporters/csv.coffee.html | 131 + .../src/reporters/default.coffee.html | 131 + .../src/reporters/jslint.coffee.html | 131 + .../coffeelint/src/reporters/raw.coffee.html | 131 + .../coffeelint/src/ruleLoader.coffee.html | 198 + .../coffeelint/src/rules.coffee.html | 167 + .../src/rules/arrow_spacing.coffee.html | 131 + .../src/rules/camel_case_classes.coffee.html | 144 + .../colon_assignment_spacing.coffee.html | 131 + .../rules/cyclomatic_complexity.coffee.html | 131 + .../src/rules/duplicate_key.coffee.html | 131 + ...empty_constructor_needs_parens.coffee.html | 131 + .../src/rules/indentation.coffee.html | 131 + .../src/rules/line_endings.coffee.html | 131 + .../src/rules/max_line_length.coffee.html | 145 + .../src/rules/missing_fat_arrows.coffee.html | 177 + .../rules/newlines_after_classes.coffee.html | 131 + .../src/rules/no_backticks.coffee.html | 131 + .../src/rules/no_debugger.coffee.html | 131 + .../src/rules/no_empty_functions.coffee.html | 157 + .../src/rules/no_empty_param_list.coffee.html | 131 + .../src/rules/no_implicit_braces.coffee.html | 131 + .../src/rules/no_implicit_parens.coffee.html | 131 + ...interpolation_in_single_quotes.coffee.html | 131 + .../src/rules/no_plusplus.coffee.html | 131 + .../src/rules/no_stand_alone_at.coffee.html | 131 + .../coffeelint/src/rules/no_tabs.coffee.html | 142 + .../src/rules/no_throwing_strings.coffee.html | 131 + .../rules/no_trailing_semicolons.coffee.html | 144 + .../rules/no_trailing_whitespace.coffee.html | 146 + .../no_unnecessary_double_quotes.coffee.html | 131 + .../no_unnecessary_fat_arrows.coffee.html | 157 + ...empty_constructor_needs_parens.coffee.html | 131 + .../src/rules/space_operators.coffee.html | 131 + .../coffeelint/vowsrunner.coffee.html | 117 + .../require-dir/test/simple/c.coffee.html | 132 + .../resolve/test/resolver/cup.coffee.html | 125 + .../resolve/test/resolver/mug.coffee.html | 125 + .../test/fixtures/test.coffee.html | 125 + .../test/fixtures/test.coffee.html | 125 + doc/file/test/Yatta_test.coffee.html | 132 + doc/file_list.html | 3125 +++- doc/index.html | 2 +- doc/javascript/search.js | 2 +- doc/method_list.html | 5165 +++++- doc/mixin/Concern.html | 171 + doc/mixin/Example/AngryAnimal.html | 146 + doc/mixin/Example/Mixins.Concern.html | 322 + doc/mixin/Foo.html | 280 + doc/mixin/Foo/Bar.html | 177 + doc/mixin/LookAndFeel.html | 164 + doc/mixin/Mixin.html | 150 + doc/mixin/Name/Space.MyMixin.html | 162 + doc/mixin/OverDocumentedMixin.html | 240 + doc/mixin_list.html | 112 +- examples/{ => IwcJson}/IwcJson.xml | 0 examples/{IwcJson.md => IwcJson/README.md} | 4 +- examples/{IwcJson.js => IwcJson/index.js} | 0 examples/README.md | 2 +- gulpfile.coffee | 97 + lib/Connectors/IwcConnector.coffee | 9 +- lib/Frameworks/JsonYatta.coffee | 8 +- lib/Frameworks/TextYatta.coffee | 6 +- lib/HistoryBuffer.coffee | 7 +- lib/Types/BasicTypes.coffee | 37 +- lib/Types/JsonTypes.coffee | 2 +- lib/Types/StructuredTypes.coffee | 2 +- lib/Types/TextTypes.coffee | 2 +- lib/index.coffee | 10 + package.json | 45 +- test/Yatta_test.coffee | 6 +- 505 files changed, 97711 insertions(+), 18525 deletions(-) delete mode 100644 Gruntfile.coffee create mode 100644 build/browser/Connectors/IwcConnector.js create mode 100644 build/browser/Connectors/IwcConnector.min.js create mode 100644 build/browser/Connectors/TestConnector.js create mode 100644 build/browser/Connectors/TestConnector.min.js create mode 100644 build/browser/Engine.js create mode 100644 build/browser/Engine.min.js create mode 100644 build/browser/Frameworks/JsonYatta.js create mode 100644 build/browser/Frameworks/JsonYatta.min.js create mode 100644 build/browser/Frameworks/TextYatta.js create mode 100644 build/browser/Frameworks/TextYatta.min.js create mode 100644 build/browser/HistoryBuffer.js create mode 100644 build/browser/HistoryBuffer.min.js create mode 100644 build/browser/Types/BasicTypes.js create mode 100644 build/browser/Types/BasicTypes.min.js create mode 100644 build/browser/Types/JsonTypes.js create mode 100644 build/browser/Types/JsonTypes.min.js create mode 100644 build/browser/Types/StructuredTypes.js create mode 100644 build/browser/Types/StructuredTypes.min.js create mode 100644 build/browser/Types/TextTypes.js create mode 100644 build/browser/Types/TextTypes.min.js create mode 100644 build/browser/Types/XmlTypes.js create mode 100644 build/browser/Types/XmlTypes.min.js create mode 100644 build/browser/index.js create mode 100644 build/browser/index.min.js create mode 100644 build/node/Connectors/IwcConnector.coffee create mode 100755 build/node/Connectors/IwcConnector.coffee.map create mode 100644 build/node/Connectors/IwcConnector.js create mode 100755 build/node/Connectors/IwcConnector.js.map create mode 100644 build/node/Connectors/TestConnector.coffee create mode 100755 build/node/Connectors/TestConnector.coffee.map create mode 100644 build/node/Connectors/TestConnector.js create mode 100755 build/node/Connectors/TestConnector.js.map create mode 100644 build/node/Engine.coffee create mode 100644 build/node/Engine.js create mode 100644 build/node/Frameworks/JsonYatta.coffee create mode 100755 build/node/Frameworks/JsonYatta.coffee.map create mode 100644 build/node/Frameworks/JsonYatta.js create mode 100755 build/node/Frameworks/JsonYatta.js.map create mode 100644 build/node/Frameworks/TextYatta.coffee create mode 100755 build/node/Frameworks/TextYatta.coffee.map create mode 100644 build/node/Frameworks/TextYatta.js create mode 100755 build/node/Frameworks/TextYatta.js.map create mode 100644 build/node/HistoryBuffer.coffee create mode 100644 build/node/HistoryBuffer.js create mode 100755 build/node/HistoryBuffer.js.map create mode 100644 build/node/Types/BasicTypes.coffee create mode 100755 build/node/Types/BasicTypes.coffee.map create mode 100644 build/node/Types/BasicTypes.js create mode 100755 build/node/Types/BasicTypes.js.map create mode 100644 build/node/Types/JsonTypes.coffee create mode 100755 build/node/Types/JsonTypes.coffee.map create mode 100644 build/node/Types/JsonTypes.js create mode 100755 build/node/Types/JsonTypes.js.map create mode 100644 build/node/Types/StructuredTypes.coffee create mode 100755 build/node/Types/StructuredTypes.coffee.map create mode 100644 build/node/Types/StructuredTypes.js create mode 100755 build/node/Types/StructuredTypes.js.map create mode 100644 build/node/Types/TextTypes.coffee create mode 100755 build/node/Types/TextTypes.coffee.map create mode 100644 build/node/Types/TextTypes.js create mode 100755 build/node/Types/TextTypes.js.map create mode 100644 build/node/Types/XmlTypes.coffee create mode 100755 build/node/Types/XmlTypes.coffee.map create mode 100644 build/node/Types/XmlTypes.js create mode 100755 build/node/Types/XmlTypes.js.map create mode 100644 build/node/index.coffee create mode 100644 build/node/index.js create mode 100755 build/node/index.js.map create mode 100644 build/test/Yatta_test.js rename {dest/browser => build}/test/index.html (65%) delete mode 100644 dest/browser/Frameworks/JsonIwcYatta.js delete mode 100644 dest/browser/Frameworks/JsonIwcYatta.min.js delete mode 100644 dest/browser/Widgets/CollaborationWidget.xml delete mode 100644 dest/browser/Widgets/CollaborationWidget2.xml delete mode 100644 dest/browser/Widgets/iwc-teststub.xml delete mode 100644 dest/browser/Widgets/libs/DUIClient.js delete mode 100644 dest/browser/Widgets/libs/DUIClient.min.js delete mode 100644 dest/browser/test/Yatta_test.js delete mode 100644 dest/lib/Connectors/IwcConnector.js delete mode 100644 dest/lib/Connectors/IwcConnector.js.map delete mode 100644 dest/lib/Connectors/TestConnector.js delete mode 100644 dest/lib/Connectors/TestConnector.js.map delete mode 100644 dest/lib/Engine.js delete mode 100644 dest/lib/Engine.js.map delete mode 100644 dest/lib/Frameworks/JsonYatta.js delete mode 100644 dest/lib/Frameworks/JsonYatta.js.map delete mode 100644 dest/lib/Frameworks/TextYatta.js delete mode 100644 dest/lib/Frameworks/TextYatta.js.map delete mode 100644 dest/lib/HistoryBuffer.js delete mode 100644 dest/lib/HistoryBuffer.js.map delete mode 100644 dest/lib/Types/BasicTypes.js delete mode 100644 dest/lib/Types/BasicTypes.js.map delete mode 100644 dest/lib/Types/JsonTypes.js delete mode 100644 dest/lib/Types/JsonTypes.js.map delete mode 100644 dest/lib/Types/StructuredTypes.js delete mode 100644 dest/lib/Types/StructuredTypes.js.map delete mode 100644 dest/lib/Types/TextTypes.js delete mode 100644 dest/lib/Types/TextTypes.js.map delete mode 100644 dest/lib/Types/XmlTypes.js delete mode 100644 dest/lib/Types/XmlTypes.js.map delete mode 100644 dest/test/Yatta_test.js create mode 100644 doc/class/A.html create mode 100644 doc/class/ASTApi.html create mode 100644 doc/class/ASTLinter.html create mode 100644 doc/class/Another/Namespace.MyClass.html create mode 100644 doc/class/App/TestMethodDocumentation.html create mode 100644 doc/class/ArrowSpacing.html create mode 100644 doc/class/BaseLinter.html create mode 100644 doc/class/CSVReporter.html create mode 100644 doc/class/Cache.html create mode 100644 doc/class/CamelCaseClasses.html create mode 100644 doc/class/CheckstyleReporter.html create mode 100644 doc/class/Class.html create mode 100644 doc/class/Code.html create mode 100644 doc/class/CodoCommand.html create mode 100644 doc/class/CoffeeMaker.html create mode 100644 doc/class/ColonAssignmentSpacing.html create mode 100644 doc/class/Command.html create mode 100644 doc/class/Comment.html create mode 100644 doc/class/Directive.html create mode 100644 doc/class/Documentation.html create mode 100644 doc/class/DuplicateKey.html create mode 100644 doc/class/EmptyConstructorNeedsParens.html create mode 100644 doc/class/Entities/Class.html create mode 100644 doc/class/Entities/Extra.html create mode 100644 doc/class/Entities/File.html create mode 100644 doc/class/Entities/Method.html create mode 100644 doc/class/Entities/Mixin.html create mode 100644 doc/class/Entities/Property.html create mode 100644 doc/class/Entities/Variable.html create mode 100644 doc/class/Entity.html create mode 100644 doc/class/Environment.html create mode 100644 doc/class/ErrorReport.html create mode 100644 doc/class/Example/Animal.Lion.html create mode 100644 doc/class/Example/Animal.html create mode 100644 doc/class/Example/Cell.html create mode 100644 doc/class/Example/Concern.html create mode 100644 doc/class/Example/Events.html create mode 100644 doc/class/Example/Methods.Virtual.html create mode 100644 doc/class/Example/Overload.html create mode 100644 doc/class/Example/Plant.html create mode 100644 doc/class/Filter.html create mode 100644 doc/class/Fluffy.html create mode 100644 doc/class/GlobalTestClass.html create mode 100644 doc/class/Haml.html create mode 100644 doc/class/HamlCoffee.html create mode 100644 doc/class/Indentation.html create mode 100644 doc/class/JSLintReporter.html create mode 100644 doc/class/LexicalLinter.html create mode 100644 doc/class/LineApi.html create mode 100644 doc/class/LineEndings.html create mode 100644 doc/class/LineLinter.html create mode 100644 doc/class/MaxLineLength.html create mode 100644 doc/class/Meta/Method.html create mode 100644 doc/class/Meta/Parameter.html create mode 100644 doc/class/MissingFatArrows.html create mode 100644 doc/class/MyTestClass.html create mode 100644 doc/class/NS/Clazz.html create mode 100644 doc/class/NewlinesAfterClasses.html create mode 100644 doc/class/NoBackticks.html create mode 100644 doc/class/NoDebugger.html create mode 100644 doc/class/NoEmptyFunctions.html create mode 100644 doc/class/NoEmptyParamList.html create mode 100644 doc/class/NoImplicitBraces.html create mode 100644 doc/class/NoImplicitParens.html create mode 100644 doc/class/NoInterpolationInSingleQuotes.html create mode 100644 doc/class/NoPlusPlus.html create mode 100644 doc/class/NoStandAloneAt.html create mode 100644 doc/class/NoTabs.html create mode 100644 doc/class/NoThrowingStrings.html create mode 100644 doc/class/NoTrailingSemicolons.html create mode 100644 doc/class/NoTrailingWhitespace.html create mode 100644 doc/class/NoUnnecessaryDoubleQuotes.html create mode 100644 doc/class/NoUnnecessaryFatArrows.html create mode 100644 doc/class/Node.html create mode 100644 doc/class/NonEmptyConstructorNeedsParens.html create mode 100644 doc/class/OverDocumentedClass.html create mode 100644 doc/class/Person.html create mode 100644 doc/class/RawReporter.html create mode 100644 doc/class/Reporter.html create mode 100644 doc/class/Some/Namespace.MyClass.html create mode 100644 doc/class/SomeNamespace/MyClass.html create mode 100644 doc/class/SpaceOperators.html create mode 100644 doc/class/Subclass.html create mode 100644 doc/class/Subsubclass.html create mode 100644 doc/class/Test.html create mode 100644 doc/class/TestAssignedParameters.html create mode 100644 doc/class/TestClassDocumentation.html create mode 100644 doc/class/TestClassMethods.html create mode 100644 doc/class/TestClassVariables.html create mode 100644 doc/class/TestContstantVariables.html create mode 100644 doc/class/TestExample.html create mode 100644 doc/class/TestExportClass.html create mode 100644 doc/class/TestInstanceMethods.html create mode 100644 doc/class/TestInstanceVariables.html create mode 100644 doc/class/TestMarkdownDocumentation.html create mode 100644 doc/class/TestNamedParameters.html create mode 100644 doc/class/Text.html create mode 100644 doc/class/Theme/Templater.html create mode 100644 doc/class/Theme/Theme.html create mode 100644 doc/class/Theme/TreeBuilder.html create mode 100644 doc/class/TokenApi.html create mode 100644 doc/class/Tools/Markdown.html create mode 100644 doc/class/Tools/Referencer.html create mode 100644 doc/class/Tower/Model.Relation.HasMany.Scope.html create mode 100644 doc/class/Tower/Model.Relation.HasMany.Scope2.html create mode 100644 doc/class/Tower/Model.Relation.HasMany.html create mode 100644 doc/class/Traverser.html create mode 100644 doc/extra/extras/imgs/Yatta_logo.png create mode 100644 doc/file/gulpfile.coffee.html create mode 100644 doc/file/lib/index.coffee.html create mode 100644 doc/file/node_modules/coffeeify/example/baz.coffee.html create mode 100644 doc/file/node_modules/coffeeify/example/foo.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/browserify/node_modules/http-browserify/node_modules/Base64/test/base64.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/browserify/node_modules/module-deps/node_modules/detective/node_modules/escodegen/node_modules/esutils/test/code.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/browserify/node_modules/module-deps/node_modules/detective/node_modules/escodegen/node_modules/esutils/test/keyword.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/browserify/node_modules/module-deps/node_modules/resolve/test/resolver/cup.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/browserify/node_modules/module-deps/node_modules/resolve/test/resolver/mug.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/browserify/node_modules/resolve/test/resolver/cup.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/browserify/node_modules/resolve/test/resolver/mug.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/browserify/node_modules/umd/node_modules/rfile/node_modules/resolve/test/resolver/cup.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/browserify/node_modules/umd/node_modules/rfile/node_modules/resolve/test/resolver/mug.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/browserify/test/coffee_bin/main.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/browserify/test/coffee_bin/x.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/browserify/test/coffeeify/main.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/resolve/test/resolver/cup.coffee.html create mode 100644 doc/file/node_modules/grunt-browserify/node_modules/resolve/test/resolver/mug.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/Gruntfile.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/Gruntfile.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/_entities.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/_meta.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/_tools.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/codo.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/command.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/documentation.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/entities/class.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/entities/extra.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/entities/file.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/entities/method.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/entities/mixin.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/entities/property.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/entities/variable.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/entity.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/environment.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/meta/method.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/meta/parameter.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/tools/markdown.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/tools/referencer.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/lib/traverser.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/Gruntfile.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/spec/compiler_spec.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/src/cli/coffee-maker.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/src/cli/command.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/src/haml-coffee.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/src/hamlc.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/src/nodes/code.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/src/nodes/comment.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/src/nodes/directive.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/src/nodes/filter.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/src/nodes/haml.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/src/nodes/node.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/src/nodes/text.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/haml-coffee/src/util/text.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/mincer/examples/assets/javascripts/app.js.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/mincer/node_modules/hike/test/fixtures/app/views/people.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/mincer/node_modules/shellwords/spec/shellwords_spec.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/node_modules/mincer/node_modules/shellwords/src/shellwords.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/classes/class_description_markdown.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/classes/class_documentation.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/classes/class_extends.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/classes/empty_class.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/classes/export_class.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/classes/global_class.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/classes/inner_class.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/classes/namespaced_class.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/classes/simple_class.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/complicateds/methods.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/complicateds/variables.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/environment/class.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/environment/mixin.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/example/src/angry_animal.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/example/src/animal.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/example/src/lion.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/example/src/over_documented_class.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/example/src/over_documented_mixin.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/files/non_class_file.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/methods/assigned_parameters.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/methods/class_methods.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/methods/curly_method_documentation.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/methods/dynamic_methods.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/methods/instance_methods.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/methods/method_documentation.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/methods/method_events.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/methods/method_example.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/methods/named_parameters.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/methods/overload_method.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/mixins/concern.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/mixins/extend_mixin.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/mixins/include_mixin.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/mixins/missing_mixins.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/mixins/mixin_documentation.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/mixins/mixin_methods.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/properties/properties.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/variables/class_variables.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/variables/constant_variables.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/_templates/variables/instance_variables.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/lib/codo_spec.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/lib/entities/class_spec.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/lib/entities/mixin_spec.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/lib/environment_spec.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/lib/meta/method_spec.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/lib/meta/parameter_spec.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/themes/default/lib/templater_spec.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/themes/default/lib/theme_spec.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/spec/themes/default/lib/tree_builder_spec.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/themes/default/assets/javascript/codo.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/themes/default/assets/javascript/fuzzy.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/themes/default/assets/javascript/keys.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/themes/default/assets/javascript/sidebar.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/themes/default/assets/javascript/toc.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/themes/default/assets/javascript/vendor/fuzzy.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/themes/default/lib/_theme.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/themes/default/lib/templater.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/themes/default/lib/theme.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/node_modules/codo/themes/default/lib/tree_builder.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/src/codo.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/src/utils/command.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/test/fixtures/custom/animal.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/test/fixtures/custom/cell.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/test/fixtures/custom/plant.coffee.html create mode 100644 doc/file/node_modules/grunt-codo/test/fixtures/default/animal.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/Gruntfile.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/ast_linter.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/base_linter.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/coffeelint.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/commandline.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/configfinder.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/htmldoc.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/lexical_linter.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/line_linter.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/arrow_spacing.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/camel_case_classes.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/colon_assignment_spacing.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/cyclomatic_complexity.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/duplicate_key.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/empty_constructor_needs_parens.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/indentation.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/line_endings.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/max_line_length.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/missing_fat_arrows.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/newlines_after_classes.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/no_backticks.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/no_empty_param_list.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/no_implicit_braces.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/no_implicit_parens.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/no_plusplus.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/no_stand_alone_at.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/no_tabs.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/no_throwing_strings.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/no_trailing_semicolons.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/no_trailing_whitespace.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/no_unnecessary_fat_arrows.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/non_empty_constructor_needs_parens.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/src/rules/space_operators.coffee.html create mode 100644 doc/file/node_modules/grunt-coffeelint/node_modules/coffeelint/vowsrunner.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/node_modules/browserify/node_modules/http-browserify/node_modules/Base64/test/base64.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/node_modules/browserify/node_modules/module-deps/node_modules/detective/node_modules/escodegen/node_modules/esutils/test/code.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/node_modules/browserify/node_modules/module-deps/node_modules/detective/node_modules/escodegen/node_modules/esutils/test/keyword.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/test/resolver/cup.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/node_modules/browserify/node_modules/resolve/test/resolver/mug.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/node_modules/browserify/node_modules/umd/node_modules/rfile/node_modules/resolve/test/resolver/cup.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/node_modules/browserify/node_modules/umd/node_modules/rfile/node_modules/resolve/test/resolver/mug.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/node_modules/browserify/test/coffee_bin/main.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/node_modules/browserify/test/coffee_bin/x.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/node_modules/browserify/test/coffeeify/main.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/test/fixtures/trans_bar.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/test/fixtures/trans_foo.coffee.html create mode 100644 doc/file/node_modules/gulp-browserify/test/fixtures/transform.coffee.html create mode 100644 doc/file/node_modules/gulp-coffee/test/fixtures/grammar.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/node_modules/resolve/test/resolver/cup.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/node_modules/resolve/test/resolver/mug.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/ast_linter.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/base_linter.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/cache.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/coffeelint.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/commandline.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/configfinder.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/htmldoc.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/lexical_linter.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/line_linter.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/reporters/checkstyle.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/reporters/csv.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/reporters/default.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/reporters/jslint.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/reporters/raw.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/ruleLoader.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/arrow_spacing.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/camel_case_classes.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/colon_assignment_spacing.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/cyclomatic_complexity.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/duplicate_key.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/empty_constructor_needs_parens.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/indentation.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/line_endings.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/max_line_length.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/missing_fat_arrows.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/newlines_after_classes.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_backticks.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_debugger.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_empty_functions.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_empty_param_list.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_implicit_braces.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_implicit_parens.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_interpolation_in_single_quotes.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_plusplus.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_stand_alone_at.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_tabs.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_throwing_strings.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_trailing_semicolons.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_trailing_whitespace.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_unnecessary_double_quotes.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/no_unnecessary_fat_arrows.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/non_empty_constructor_needs_parens.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/src/rules/space_operators.coffee.html create mode 100644 doc/file/node_modules/gulp-coffeelint/node_modules/coffeelint/vowsrunner.coffee.html create mode 100644 doc/file/node_modules/gulp-git/node_modules/require-dir/test/simple/c.coffee.html create mode 100644 doc/file/node_modules/gulp/node_modules/liftoff/node_modules/resolve/test/resolver/cup.coffee.html create mode 100644 doc/file/node_modules/gulp/node_modules/liftoff/node_modules/resolve/test/resolver/mug.coffee.html create mode 100644 doc/file/node_modules/gulp/node_modules/vinyl-fs/node_modules/glob-stream/test/fixtures/test.coffee.html create mode 100644 doc/file/node_modules/gulp/node_modules/vinyl-fs/node_modules/glob-watcher/test/fixtures/test.coffee.html create mode 100644 doc/file/test/Yatta_test.coffee.html create mode 100644 doc/mixin/Concern.html create mode 100644 doc/mixin/Example/AngryAnimal.html create mode 100644 doc/mixin/Example/Mixins.Concern.html create mode 100644 doc/mixin/Foo.html create mode 100644 doc/mixin/Foo/Bar.html create mode 100644 doc/mixin/LookAndFeel.html create mode 100644 doc/mixin/Mixin.html create mode 100644 doc/mixin/Name/Space.MyMixin.html create mode 100644 doc/mixin/OverDocumentedMixin.html rename examples/{ => IwcJson}/IwcJson.xml (100%) rename examples/{IwcJson.md => IwcJson/README.md} (97%) rename examples/{IwcJson.js => IwcJson/index.js} (100%) create mode 100644 gulpfile.coffee create mode 100644 lib/index.coffee diff --git a/Gruntfile.coffee b/Gruntfile.coffee deleted file mode 100644 index 2a927d98..00000000 --- a/Gruntfile.coffee +++ /dev/null @@ -1,135 +0,0 @@ -"use strict" -module.exports = (grunt) -> - - # Project configuration. - grunt.initConfig - coffee: - lib: - options: - bare: true - sourceMap: true - expand: true - src: ["lib/**/*.coffee"] - dest: "dest/" - ext: ".js" - test: - #options: - #bare: true - expand: true - src: ["test/**/*.coffee"] - dest: "dest/" - ext: ".js" - - watch: - lib: - files: [ - "<%= coffee.lib.src %>" - ] - tasks: ["coffee:lib"] - test: - files: [ - "<%= coffee.lib.src %>" - "<%= coffee.test.src %>" - "examples/*" - ] - tasks: ["build"] - - simplemocha: - all: - src: ['test/**/*.coffee'] - options: - timeout: 9999999 - ignoreLeaks: false - ui: 'bdd' - reporter: 'list' - compilers: 'coffee:coffee-script' - - pkg: grunt.file.readJSON('package.json') - - coffeelint: - app: [ - 'lib/**/*.coffee' - 'test/**/.coffee' - "Gruntfile.coffee" - ] - options: - "indentation": - "level": "ignore" - "no_trailing_whitespace": - "level": "warn" - "max_line_length": - "level": "ignore" - #"line_endings": - # "level": "error" - codo: - options: - name: "Yatta!" - title: "Yatta! Documentation" - extras: ["LICENSE.txt", "examples/README.md", "examples/IwcJson.md"] - undocumented: yes - verbose: false - stats: true - src: ["./lib"] - browserify: - dest: - files: - 'dest/browser/test/Yatta_test.js': ['test/**/*.coffee'] - options: - transform: ['coffeeify'] - debug: true - bundleOptions: {debug: true} - # Serve files via http-server - lib: - files: - 'dest/browser/Frameworks/JsonIwcYatta.js': ['./lib/Frameworks/JsonYatta.coffee', './lib/Connectors/IwcConnector.coffee'] - options: - transform: ['coffeeify'] - debug: false - bundleOptions: {debug: false} - uglify: - browser: - files: [ - expand: true - cwd: './dest/browser/' - src: '**/*.js' - dest: './dest/browser' - ext: '.min.js' - ] - connect: - server: - options: - hostname: '*' - port: 1337 - base: './' - keepalive: true - middleware: (connect, options, middlewares)-> - middlewares.push (req, res, next)-> - if res.header? - res.header('Access-Control-Allow-Origin', "*") - res.header('Access-Control-Allow-Credentials', true) - res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept") - res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS') - res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0') - return next() - return middlewares - literate: - "examples/IwcJson.md": "examples/IwcJson.js" - options: - code: true - - # These plugins provide necessary tasks. - grunt.loadNpmTasks "grunt-browserify" - grunt.loadNpmTasks "grunt-contrib-uglify" - grunt.loadNpmTasks "grunt-contrib-coffee" - grunt.loadNpmTasks 'grunt-contrib-connect' - grunt.loadNpmTasks "grunt-contrib-watch" - grunt.loadNpmTasks "grunt-literate" - grunt.loadNpmTasks "grunt-simple-mocha" - grunt.loadNpmTasks "grunt-coffeelint" - grunt.loadNpmTasks "grunt-codo" - - grunt.registerTask "build", ["coffeelint", "codo", "browserify", "test"] - grunt.registerTask "production", ["test", "coffee","coffeelint", "literate", "browserify", "uglify", "codo"] - grunt.registerTask "default", ["build", "watch"] - grunt.registerTask "production", ["coffee"] - grunt.registerTask "test", ["simplemocha"] diff --git a/LICENSE.txt b/LICENSE.txt index 6665cf56..fa48ced3 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Kevin Jahns. +Copyright (c) 2014 Kevin Jahns . Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/bower.json b/bower.json index e5429f5f..076c44da 100644 --- a/bower.json +++ b/bower.json @@ -6,7 +6,7 @@ "Kevin Jahns " ], "description": "A Framework that enables Real-Time Collaboration on arbitrary data structures.", - "main": "./dest/browser/**", + "main": "./build/browser/**", "keywords": [ "OT", "collaboration", diff --git a/build/browser/Connectors/IwcConnector.js b/build/browser/Connectors/IwcConnector.js new file mode 100644 index 00000000..b46b4b4c --- /dev/null +++ b/build/browser/Connectors/IwcConnector.js @@ -0,0 +1,118 @@ +(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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { + return this.engine.applyOp(this.unexecuted[user].shift()); + } + }; + + TestConnector.prototype.flushOneRandom = function() { + return this.flushOne(_.random(0, user_list.length - 1)); + }; + + TestConnector.prototype.flushAll = function() { + var n, ops, _ref; + _ref = this.unexecuted; + for (n in _ref) { + ops = _ref[n]; + this.engine.applyOps(ops); + } + return this.unexecuted = {}; + }; + + return TestConnector; + + })(); +}; + + +},{"underscore":2}],2:[function(require,module,exports){ +// Underscore.js 1.6.0 +// http://underscorejs.org +// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `exports` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var + push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.6.0'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return obj; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, length = obj.length; i < length; i++) { + if (iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; + } + } + return obj; + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results.push(iterator.call(context, value, index, list)); + }); + return results; + }; + + var reduceError = 'Reduce of empty array with no initial value'; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, predicate, context) { + var result; + any(obj, function(value, index, list) { + if (predicate.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, predicate, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); + each(obj, function(value, index, list) { + if (predicate.call(context, value, index, list)) results.push(value); + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, predicate, context) { + return _.filter(obj, function(value, index, list) { + return !predicate.call(context, value, index, list); + }, context); + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, predicate, context) { + predicate || (predicate = _.identity); + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context); + each(obj, function(value, index, list) { + if (!(result = result && predicate.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, predicate, context) { + predicate || (predicate = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); + each(obj, function(value, index, list) { + if (result || (result = predicate.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + return any(obj, function(value) { + return value === target; + }); + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + return (isFunc ? method : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, _.property(key)); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs) { + return _.filter(obj, _.matches(attrs)); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.find(obj, _.matches(attrs)); + }; + + // Return the maximum element or (element-based computation). + // Can't optimize arrays of integers longer than 65,535 elements. + // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } + var result = -Infinity, lastComputed = -Infinity; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + if (computed > lastComputed) { + result = value; + lastComputed = computed; + } + }); + return result; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } + var result = Infinity, lastComputed = Infinity; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + if (computed < lastComputed) { + result = value; + lastComputed = computed; + } + }); + return result; + }; + + // Shuffle an array, using the modern version of the + // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). + _.shuffle = function(obj) { + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + + // Sample **n** random values from a collection. + // If **n** is not specified, returns a single random element. + // The internal `guard` argument allows it to work with `map`. + _.sample = function(obj, n, guard) { + if (n == null || guard) { + if (obj.length !== +obj.length) obj = _.values(obj); + return obj[_.random(obj.length - 1)]; + } + return _.shuffle(obj).slice(0, Math.max(0, n)); + }; + + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + if (value == null) return _.identity; + if (_.isFunction(value)) return value; + return _.property(value); + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, iterator, context) { + iterator = lookupIterator(iterator); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value: value, + index: index, + criteria: iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(behavior) { + return function(obj, iterator, context) { + var result = {}; + iterator = lookupIterator(iterator); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = group(function(result, key, value) { + _.has(result, key) ? result[key].push(value) : result[key] = [value]; + }); + + // Indexes the object's values by a criterion, similar to `groupBy`, but for + // when you know that your index values will be unique. + _.indexBy = group(function(result, key, value) { + result[key] = value; + }); + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = group(function(result, key) { + _.has(result, key) ? result[key]++ : result[key] = 1; + }); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator, context) { + iterator = lookupIterator(iterator); + var value = iterator.call(context, obj); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely create a real, live array from anything iterable. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + if ((n == null) || guard) return array[0]; + if (n < 0) return []; + return slice.call(array, 0, n); + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if ((n == null) || guard) return array[array.length - 1]; + return slice.call(array, Math.max(array.length - n, 0)); + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, output) { + if (shallow && _.every(input, _.isArray)) { + return concat.apply(output, input); + } + each(input, function(value) { + if (_.isArray(value) || _.isArguments(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + + // Flatten out an array, either recursively (by default), or just one level. + _.flatten = function(array, shallow) { + return flatten(array, shallow, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Split an array into two arrays: one whose elements all satisfy the given + // predicate, and one whose elements all do not satisfy the predicate. + _.partition = function(array, predicate) { + var pass = [], fail = []; + each(array, function(elem) { + (predicate(elem) ? pass : fail).push(elem); + }); + return [pass, fail]; + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); + } + }); + return results; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(_.flatten(arguments, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.contains(other, item); + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var length = _.max(_.pluck(arguments, 'length').concat(0)); + var results = new Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(arguments, '' + i); + } + return results; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, length = list.length; i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, length = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < length; i++) if (array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var hasIndex = from != null; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { + return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + } + var i = (hasIndex ? from : array.length); + while (i--) if (array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var length = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(length); + + while(idx < length) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + var args, bound; + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + ctor.prototype = null; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. _ acts + // as a placeholder, allowing any combination of arguments to be pre-filled. + _.partial = function(func) { + var boundArgs = slice.call(arguments, 1); + return function() { + var position = 0; + var args = boundArgs.slice(); + for (var i = 0, length = args.length; i < length; i++) { + if (args[i] === _) args[i] = arguments[position++]; + } + while (position < arguments.length) args.push(arguments[position++]); + return func.apply(this, args); + }; + }; + + // Bind a number of an object's methods to that object. Remaining arguments + // are the method names to be bound. Useful for ensuring that all callbacks + // defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length === 0) throw new Error('bindAll must be passed function names'); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function(func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + options || (options = {}); + var later = function() { + previous = options.leading === false ? 0 : _.now(); + timeout = null; + result = func.apply(context, args); + context = args = null; + }; + return function() { + var now = _.now(); + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, args, context, timestamp, result; + + var later = function() { + var last = _.now() - timestamp; + if (last < wait) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + context = args = null; + } + } + }; + + return function() { + context = this; + args = arguments; + timestamp = _.now(); + var callNow = immediate && !timeout; + if (!timeout) { + timeout = setTimeout(later, wait); + } + if (callNow) { + result = func.apply(context, args); + context = args = null; + } + + return result; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + memo = func.apply(this, arguments); + func = null; + return memo; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return _.partial(wrapper, func); + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = function(obj) { + if (!_.isObject(obj)) return []; + if (nativeKeys) return nativeKeys(obj); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = new Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; + } + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = new Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; + } + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + if (obj[prop] === void 0) obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) return bStack[length] == b; + } + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor)) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return result; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Optimize `isFunction` if appropriate. + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj != +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + _.constant = function(value) { + return function () { + return value; + }; + }; + + _.property = function(key) { + return function(obj) { + return obj[key]; + }; + }; + + // Returns a predicate for checking whether an object has a given set of `key:value` pairs. + _.matches = function(attrs) { + return function(obj) { + if (obj === attrs) return true; //avoid comparing an object to itself. + for (var key in attrs) { + if (attrs[key] !== obj[key]) + return false; + } + return true; + } + }; + + // Run a function **n** times. + _.times = function(n, iterator, context) { + var accum = Array(Math.max(0, n)); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // A (possibly faster) way to get the current timestamp as an integer. + _.now = Date.now || function() { return new Date().getTime(); }; + + // List of HTML entities for escaping. + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + + // Regexes containing the keys and values listed immediately above. + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + + // Functions for escaping and unescaping strings to/from HTML interpolation. + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + + // If the value of the named `property` is a function then invoke it with the + // `object` as context; otherwise, return it. + _.result = function(object, property) { + if (object == null) return void 0; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + each(_.functions(obj), function(name) { + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(text, data, settings) { + var render; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled function source as a convenience for precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + _.extend(_.prototype, { + + // Start chaining a wrapped Underscore object. + chain: function() { + this._chain = true; + return this; + }, + + // Extracts the result from a wrapped and chained object. + value: function() { + return this._wrapped; + } + + }); + + // AMD registration happens at the end for compatibility with AMD loaders + // that may not enforce next-turn semantics on modules. Even though general + // practice for AMD registration is to be anonymous, underscore registers + // as a named module because, like jQuery, it is a base library that is + // popular enough to be bundled in a third party lib, but not be part of + // an AMD load request. Those cases could generate an error when an + // anonymous define() is called outside of a loader request. + if (typeof define === 'function' && define.amd) { + define('underscore', [], function() { + return _; + }); + } +}).call(this); + +},{}]},{},[1]) +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL0Nvbm5lY3RvcnMvVGVzdENvbm5lY3Rvci5jb2ZmZWUiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbm9kZV9tb2R1bGVzL3VuZGVyc2NvcmUvdW5kZXJzY29yZS5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0NBLElBQUEsQ0FBQTs7QUFBQSxDQUFBLEdBQUksT0FBQSxDQUFRLFlBQVIsQ0FBSixDQUFBOztBQUFBLE1BRU0sQ0FBQyxPQUFQLEdBQWlCLFNBQUMsU0FBRCxHQUFBO0FBS2YsTUFBQSxhQUFBO1NBQU07QUFRUyxJQUFBLHVCQUFFLE1BQUYsRUFBVyxFQUFYLEVBQWdCLGtCQUFoQixHQUFBO0FBQ1gsVUFBQSxnQ0FBQTtBQUFBLE1BRFksSUFBQyxDQUFBLFNBQUEsTUFDYixDQUFBO0FBQUEsTUFEcUIsSUFBQyxDQUFBLEtBQUEsRUFDdEIsQ0FBQTtBQUFBLE1BRDBCLElBQUMsQ0FBQSxxQkFBQSxrQkFDM0IsQ0FBQTtBQUFBLE1BQUEsS0FBQSxHQUFRLENBQUEsU0FBQSxLQUFBLEdBQUE7ZUFBQSxTQUFDLENBQUQsR0FBQTtpQkFDTixLQUFDLENBQUEsSUFBRCxDQUFNLENBQU4sRUFETTtRQUFBLEVBQUE7TUFBQSxDQUFBLENBQUEsQ0FBQSxJQUFBLENBQVIsQ0FBQTtBQUFBLE1BRUEsSUFBQyxDQUFBLGtCQUFrQixDQUFDLElBQXBCLENBQXlCLEtBQXpCLENBRkEsQ0FBQTtBQUFBLE1BSUEsSUFBQyxDQUFBLGtCQUFELEdBQXNCLEVBSnRCLENBQUE7QUFBQSxNQUtBLHlCQUFBLEdBQTRCLENBQUEsU0FBQSxLQUFBLEdBQUE7ZUFBQSxTQUFDLENB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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKX12YXIgZj1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwoZi5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxmLGYuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiXG5fID0gcmVxdWlyZSBcInVuZGVyc2NvcmVcIlxuXG5tb2R1bGUuZXhwb3J0cyA9ICh1c2VyX2xpc3QpLT5cblxuICAjXG4gICMgQSB0cml2aWFsIENvbm5lY3RvciB0aGF0IHNpbXVsYXRlcyBuZXR3b3JrIGRlbGF5LlxuICAjXG4gIGNsYXNzIFRlc3RDb25uZWN0b3JcblxuICAgICNcbiAgICAjIEBwYXJhbSB7RW5naW5lfSBlbmdpbmUgVGhlIHRyYW5zZm9ybWF0aW9uIGVuZ2luZVxuICAgICMgQHBhcmFtIHtIaXN0b3J5QnVmZmVyfSBIQlxuICAgICMgQHBhcmFtIHtBcnJheTxGdW5jdGlvbj59IGV4ZWN1dGlvbl9saXN0ZW5lciBZb3UgbXVzdCBlbnN1cmUgdGhhdCB3aGVuZXZlciBhbiBvcGVyYXRpb24gaXMgZXhlY3V0ZWQsIGV2ZXJ5IGZ1bmN0aW9uIGluIHRoaXMgQXJyYXkgaXMgY2FsbGVkLlxuICAgICMgQHBhcmFtIHtZYXR0YX0geWF0dGEgVGhlIFlhdHRhIGZyYW1ld29yay5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6IChAZW5naW5lLCBASEIsIEBleGVjdXRpb25fbGlzdGVuZXIpLT5cbiAgICAgIHNlbmRfID0gKG8pPT5cbiAgICAgICAgQHNlbmQgb1xuICAgICAgQGV4ZWN1dGlvbl9saXN0ZW5lci5wdXNoIHNlbmRfXG5cbiAgICAgIEBhcHBsaWVkX29wZXJhdGlvbnMgPSBbXVxuICAgICAgYXBwbGllZE9wZXJhdGlvbnNMaXN0ZW5lciA9IChvKT0+XG4gICAgICAgIEBhcHBsaWVkX29wZXJhdGlvbnMucHVzaCBvXG4gICAgICBAZXhlY3V0aW9uX2xpc3RlbmVyLnB1c2ggYXBwbGllZE9wZXJhdGlvbnNMaXN0ZW5lclxuICAgICAgaWYgbm90ICh1c2VyX2xpc3Q/Lmxlbmd0aCBpcyAwKVxuICAgICAgICBAZW5naW5lLmFwcGx5T3BzIHVzZXJfbGlzdFswXS5nZXRIaXN0b3J5QnVmZmVyKCkuX2VuY29kZSgpXG5cbiAgICAgIEB1bmV4ZWN1dGVkID0ge31cblxuICAgICNcbiAgICAjIFRoaXMgZW5naW5lIGFwcGxpZWQgb3BlcmF0aW9ucyBpbiBhIHNwZWNpZmljIG9yZGVyLlxuICAgICMgR2V0IHRoZSBvcHMgaW4gdGhlIHJpZ2h0IG9yZGVyLlxuICAgICNcbiAgICBnZXRPcHNJbkV4ZWN1dGlvbk9yZGVyOiAoKS0+XG4gICAgICBAYXBwbGllZF9vcGVyYXRpb25zXG5cbiAgICAjXG4gICAgIyBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuZXZlciBhbiBvcGVyYXRpb24gd2FzIGV4ZWN1dGVkLlxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG8gVGhlIG9wZXJhdGlvbiB0aGF0IHdhcyBleGVjdXRlZC5cbiAgICAjXG4gICAgc2VuZDogKG8pLT5cbiAgICAgIGlmIChvLnVpZC5jcmVhdG9yIGlzIEBIQi5nZXRVc2VySWQoKSkgYW5kICh0eXBlb2Ygby51aWQub3BfbnVtYmVyIGlzbnQgXCJzdHJpbmdcIilcbiAgICAgICAgZm9yIHVzZXIgaW4gdXNlcl9saXN0XG4gICAgICAgICAgaWYgdXNlci5nZXRVc2VySWQoKSBpc250IEBIQi5nZXRVc2VySWQoKVxuICAgICAgICAgICAgdXNlci5nZXRDb25uZWN0b3IoKS5yZWNlaXZlKG8pXG5cbiAgICAjXG4gICAgIyBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuZXZlciBhbiBvcGVyYXRpb24gd2FzIHJlY2VpdmVkIGZyb20gYW5vdGhlciBwZWVyLlxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG8gVGhlIG9wZXJhdGlvbiB0aGF0IHdhcyByZWNlaXZlZC5cbiAgICAjXG4gICAgcmVjZWl2ZTogKG8pLT5cbiAgICAgIEB1bmV4ZWN1dGVkW28udWlkLmNyZWF0b3JdID89IFtdXG4gICAgICBAdW5leGVjdXRlZFtvLnVpZC5jcmVhdG9yXS5wdXNoIG9cblxuICAgICNcbiAgICAjIEZsdXNoIG9uZSBvcGVyYXRpb24gZnJvbSB0aGUgbGluZSBvZiBhIHNwZWNpZmljIHVzZXIuXG4gICAgI1xuICAgIGZsdXNoT25lOiAodXNlciktPlxuICAgICAgaWYgQHVuZXhlY3V0ZWRbdXNlcl0/Lmxlbmd0aCA+IDBcbiAgICAgICAgQGVuZ2luZS5hcHBseU9wIEB1bmV4ZWN1dGVkW3VzZXJdLnNoaWZ0KClcblxuICAgICNcbiAgICAjIEZsdXNoIG9uZSBvcGVyYXRpb24gb24gYSByYW5kb20gbGluZS5cbiAgICAjXG4gICAgZmx1c2hPbmVSYW5kb206ICgpLT5cbiAgICAgIEBmbHVzaE9uZSAoXy5yYW5kb20gMCwgKHVzZXJfbGlzdC5sZW5ndGgtMSkpXG5cbiAgICAjXG4gICAgIyBGbHVzaCBhbGwgb3BlcmF0aW9ucyBvbiBldmVyeSBsaW5lLlxuICAgICNcbiAgICBmbHVzaEFsbDogKCktPlxuICAgICAgZm9yIG4sb3BzIG9mIEB1bmV4ZWN1dGVkXG4gICAgICAgIEBlbmdpbmUuYXBwbHlPcHMgb3BzXG4gICAgICBAdW5leGVjdXRlZCA9IHt9XG5cbiIsIi8vICAgICBVbmRlcnNjb3JlLmpzIDEuNi4wXG4vLyAgICAgaHR0cDovL3VuZGVyc2NvcmVqcy5vcmdcbi8vICAgICAoYykgMjAwOS0yMDE0IEplcmVteSBBc2hrZW5hcywgRG9jdW1lbnRDbG91ZCBhbmQgSW52ZXN0aWdhdGl2ZSBSZXBvcnRlcnMgJiBFZGl0b3JzXG4vLyAgICAgVW5kZXJzY29yZSBtYXkgYmUgZnJlZWx5IGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBNSVQgbGljZW5zZS5cblxuKGZ1bmN0aW9uKCkge1xuXG4gIC8vIEJhc2VsaW5lIHNldHVwXG4gIC8vIC0tLS0tLS0tLS0tLS0tXG5cbiAgLy8gRXN0YWJsaXNoIHRoZSByb290IG9iamVjdCwgYHdpbmRvd2AgaW4gdGhlIGJyb3dzZXIsIG9yIGBleHBvcnRzYCBvbiB0aGUgc2VydmVyLlxuICB2YXIgcm9vdCA9IHRoaXM7XG5cbiAgLy8gU2F2ZSB0aGUgcHJldmlvdXMgdmFsdWUgb2YgdGhlIGBfYCB2YXJpYWJsZS5cbiAgdmFyIHByZXZpb3VzVW5kZXJzY29yZSA9IHJvb3QuXztcblxuICAvLyBFc3RhYmxpc2ggdGhlIG9iamVjdCB0aGF0IGdldHMgcmV0dXJuZWQgdG8gYnJlYWsgb3V0IG9mIGEgbG9vcCBpdGVyYXRpb24uXG4gIHZhciBicmVha2VyID0ge307XG5cbiAgLy8gU2F2ZSBieXRlcyBpbiB0aGUgbWluaWZpZWQgKGJ1dCBub3QgZ3ppcHBlZCkgdmVyc2lvbjpcbiAgdmFyIEFycmF5UHJvdG8gPSBBcnJheS5wcm90b3R5cGUsIE9ialByb3RvID0gT2JqZWN0LnByb3RvdHlwZSwgRnVuY1Byb3RvID0gRnVuY3Rpb24ucHJvdG90eXBlO1xuXG4gIC8vIENyZWF0ZSBxdWljayByZWZlcmVuY2UgdmFyaWFibGVzIGZvciBzcGVlZCBhY2Nlc3MgdG8gY29yZSBwcm90b3R5cGVzLlxuICB2YXJcbiAgICBwdXNoICAgICAgICAgICAgID0gQXJyYXlQcm90by5wdXNoLFxuICAgIHNsaWNlICAgICAgICAgICAgPSBBcnJheVByb3RvLnNsaWNlLFxuICAgIGNvbmNhdCAgICAgICAgICAgPSBBcnJheVByb3RvLmNvbmNhdCxcbiAgICB0b1N0cmluZyAgICAgICAgID0gT2JqUHJvdG8udG9TdHJpbmcsXG4gICAgaGFzT3duUHJvcGVydHkgICA9IE9ialByb3RvLmhhc093blByb3BlcnR5O1xuXG4gIC8vIEFsbCAqKkVDTUFTY3JpcHQgNSoqIG5hdGl2ZSBmdW5jdGlvbiBpbXBsZW1lbnRhdGlvbnMgdGhhdCB3ZSBob3BlIHRvIHVzZVxuICAvLyBhcmUgZGVjbGFyZWQgaGVyZS5cbiAgdmFyXG4gICAgbmF0aXZlRm9yRWFjaCAgICAgID0gQXJyYXlQcm90by5mb3JFYWNoLFxuICAgIG5hdGl2ZU1hcCAgICAgICAgICA9IEFycmF5UHJvdG8ubWFwLFxuICAgIG5hdGl2ZVJlZHVjZSAgICAgICA9IEFycmF5UHJvdG8ucmVkdWNlLFxuICAgIG5hdGl2ZVJlZHVjZVJpZ2h0ICA9IEFycmF5UHJvdG8ucmVkdWNlUmlnaHQsXG4gICAgbmF0aXZlRmlsdGVyICAgICAgID0gQXJyYXlQcm90by5maWx0ZXIsXG4gICAgbmF0aXZlRXZlcnkgICAgICAgID0gQXJyYXlQcm90by5ldmVyeSxcbiAgICBuYXRpdmVTb21lICAgICAgICAgPSBBcnJheVByb3RvLnNvbWUsXG4gICAgbmF0aXZlSW5kZXhPZiAgICAgID0gQXJyYXlQcm90by5pbmRleE9mLFxuICAgIG5hdGl2ZUxhc3RJbmRleE9mICA9IEFycmF5UHJvdG8ubGFzdEluZGV4T2YsXG4gICAgbmF0aXZlSXNBcnJheSAgICAgID0gQXJyYXkuaXNBcnJheSxcbiAgICBuYXRpdmVLZXlzICAgICAgICAgPSBPYmplY3Qua2V5cyxcbiAgICBuYXRpdmVCaW5kICAgICAgICAgPSBGdW5jUHJvdG8uYmluZDtcblxuICAvLyBDcmVhdGUgYSBzYWZlIHJlZmVyZW5jZSB0byB0aGUgVW5kZXJzY29yZSBvYmplY3QgZm9yIHVzZSBiZWxvdy5cbiAgdmFyIF8gPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAob2JqIGluc3RhbmNlb2YgXykgcmV0dXJuIG9iajtcbiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgXykpIHJldHVybiBuZXcgXyhvYmopO1xuICAgIHRoaXMuX3dyYXBwZWQgPSBvYmo7XG4gIH07XG5cbiAgLy8gRXhwb3J0IHRoZSBVbmRlcnNjb3JlIG9iamVjdCBmb3IgKipOb2RlLmpzKiosIHdpdGhcbiAgLy8gYmFja3dhcmRzLWNvbXBhdGliaWxpdHkgZm9yIHRoZSBvbGQgYHJlcXVpcmUoKWAgQVBJLiBJZiB3ZSdyZSBpblxuICAvLyB0aGUgYnJvd3NlciwgYWRkIGBfYCBhcyBhIGdsb2JhbCBvYmplY3QgdmlhIGEgc3RyaW5nIGlkZW50aWZpZXIsXG4gIC8vIGZvciBDbG9zdXJlIENvbXBpbGVyIFwiYWR2YW5jZWRcIiBtb2RlLlxuICBpZiAodHlwZW9mIGV4cG9ydHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgICBleHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSBfO1xuICAgIH1cbiAgICBleHBvcnRzLl8gPSBfO1xuICB9IGVsc2Uge1xuICAgIHJvb3QuXyA9IF87XG4gIH1cblxuICAvLyBDdXJyZW50IHZlcnNpb24uXG4gIF8uVkVSU0lPTiA9ICcxLjYuMCc7XG5cbiAgLy8gQ29sbGVjdGlvbiBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBUaGUgY29ybmVyc3RvbmUsIGFuIGBlYWNoYCBpbXBsZW1lbnRhdGlvbiwgYWthIGBmb3JFYWNoYC5cbiAgLy8gSGFuZGxlcyBvYmplY3RzIHdpdGggdGhlIGJ1aWx0LWluIGBmb3JFYWNoYCwgYXJyYXlzLCBhbmQgcmF3IG9iamVjdHMuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBmb3JFYWNoYCBpZiBhdmFpbGFibGUuXG4gIHZhciBlYWNoID0gXy5lYWNoID0gXy5mb3JFYWNoID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIG9iajtcbiAgICBpZiAobmF0aXZlRm9yRWFjaCAmJiBvYmouZm9yRWFjaCA9PT0gbmF0aXZlRm9yRWFjaCkge1xuICAgICAgb2JqLmZvckVhY2goaXRlcmF0b3IsIGNvbnRleHQpO1xuICAgIH0gZWxzZSBpZiAob2JqLmxlbmd0aCA9PT0gK29iai5sZW5ndGgpIHtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBvYmoubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqW2ldLCBpLCBvYmopID09PSBicmVha2VyKSByZXR1cm47XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0ga2V5cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoaXRlcmF0b3IuY2FsbChjb250ZXh0LCBvYmpba2V5c1tpXV0sIGtleXNbaV0sIG9iaikgPT09IGJyZWFrZXIpIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG9iajtcbiAgfTtcblxuICAvLyBSZXR1cm4gdGhlIHJlc3VsdHMgb2YgYXBwbHlpbmcgdGhlIGl0ZXJhdG9yIHRvIGVhY2ggZWxlbWVudC5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYG1hcGAgaWYgYXZhaWxhYmxlLlxuICBfLm1hcCA9IF8uY29sbGVjdCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIHJlc3VsdHM7XG4gICAgaWYgKG5hdGl2ZU1hcCAmJiBvYmoubWFwID09PSBuYXRpdmVNYXApIHJldHVybiBvYmoubWFwKGl0ZXJhdG9yLCBjb250ZXh0KTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICByZXN1bHRzLnB1c2goaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfTtcblxuICB2YXIgcmVkdWNlRXJyb3IgPSAnUmVkdWNlIG9mIGVtcHR5IGFycmF5IHdpdGggbm8gaW5pdGlhbCB2YWx1ZSc7XG5cbiAgLy8gKipSZWR1Y2UqKiBidWlsZHMgdXAgYSBzaW5nbGUgcmVzdWx0IGZyb20gYSBsaXN0IG9mIHZhbHVlcywgYWthIGBpbmplY3RgLFxuICAvLyBvciBgZm9sZGxgLiBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgcmVkdWNlYCBpZiBhdmFpbGFibGUuXG4gIF8ucmVkdWNlID0gXy5mb2xkbCA9IF8uaW5qZWN0ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgbWVtbywgY29udGV4dCkge1xuICAgIHZhciBpbml0aWFsID0gYXJndW1lbnRzLmxlbmd0aCA+IDI7XG4gICAgaWYgKG9iaiA9PSBudWxsKSBvYmogPSBbXTtcbiAgICBpZiAobmF0aXZlUmVkdWNlICYmIG9iai5yZWR1Y2UgPT09IG5hdGl2ZVJlZHVjZSkge1xuICAgICAgaWYgKGNvbnRleHQpIGl0ZXJhdG9yID0gXy5iaW5kKGl0ZXJhdG9yLCBjb250ZXh0KTtcbiAgICAgIHJldHVybiBpbml0aWFsID8gb2JqLnJlZHVjZShpdGVyYXRvciwgbWVtbykgOiBvYmoucmVkdWNlKGl0ZXJhdG9yKTtcbiAgICB9XG4gICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgaWYgKCFpbml0aWFsKSB7XG4gICAgICAgIG1lbW8gPSB2YWx1ZTtcbiAgICAgICAgaW5pdGlhbCA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBtZW1vID0gaXRlcmF0b3IuY2FsbChjb250ZXh0LCBtZW1vLCB2YWx1ZSwgaW5kZXgsIGxpc3QpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmICghaW5pdGlhbCkgdGhyb3cgbmV3IFR5cGVFcnJvcihyZWR1Y2VFcnJvcik7XG4gICAgcmV0dXJuIG1lbW87XG4gIH07XG5cbiAgLy8gVGhlIHJpZ2h0LWFzc29jaWF0aXZlIHZlcnNpb24gb2YgcmVkdWNlLCBhbHNvIGtub3duIGFzIGBmb2xkcmAuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGByZWR1Y2VSaWdodGAgaWYgYXZhaWxhYmxlLlxuICBfLnJlZHVjZVJpZ2h0ID0gXy5mb2xkciA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIG1lbW8sIGNvbnRleHQpIHtcbiAgICB2YXIgaW5pdGlhbCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyO1xuICAgIGlmIChvYmogPT0gbnVsbCkgb2JqID0gW107XG4gICAgaWYgKG5hdGl2ZVJlZHVjZVJpZ2h0ICYmIG9iai5yZWR1Y2VSaWdodCA9PT0gbmF0aXZlUmVkdWNlUmlnaHQpIHtcbiAgICAgIGlmIChjb250ZXh0KSBpdGVyYXRvciA9IF8uYmluZChpdGVyYXRvciwgY29udGV4dCk7XG4gICAgICByZXR1cm4gaW5pdGlhbCA/IG9iai5yZWR1Y2VSaWdodChpdGVyYXRvciwgbWVtbykgOiBvYmoucmVkdWNlUmlnaHQoaXRlcmF0b3IpO1xuICAgIH1cbiAgICB2YXIgbGVuZ3RoID0gb2JqLmxlbmd0aDtcbiAgICBpZiAobGVuZ3RoICE9PSArbGVuZ3RoKSB7XG4gICAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xuICAgICAgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XG4gICAgfVxuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIGluZGV4ID0ga2V5cyA/IGtleXNbLS1sZW5ndGhdIDogLS1sZW5ndGg7XG4gICAgICBpZiAoIWluaXRpYWwpIHtcbiAgICAgICAgbWVtbyA9IG9ialtpbmRleF07XG4gICAgICAgIGluaXRpYWwgPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWVtbyA9IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgbWVtbywgb2JqW2luZGV4XSwgaW5kZXgsIGxpc3QpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmICghaW5pdGlhbCkgdGhyb3cgbmV3IFR5cGVFcnJvcihyZWR1Y2VFcnJvcik7XG4gICAgcmV0dXJuIG1lbW87XG4gIH07XG5cbiAgLy8gUmV0dXJuIHRoZSBmaXJzdCB2YWx1ZSB3aGljaCBwYXNzZXMgYSB0cnV0aCB0ZXN0LiBBbGlhc2VkIGFzIGBkZXRlY3RgLlxuICBfLmZpbmQgPSBfLmRldGVjdCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgdmFyIHJlc3VsdDtcbiAgICBhbnkob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIGlmIChwcmVkaWNhdGUuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKSB7XG4gICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIHRoYXQgcGFzcyBhIHRydXRoIHRlc3QuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBmaWx0ZXJgIGlmIGF2YWlsYWJsZS5cbiAgLy8gQWxpYXNlZCBhcyBgc2VsZWN0YC5cbiAgXy5maWx0ZXIgPSBfLnNlbGVjdCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiByZXN1bHRzO1xuICAgIGlmIChuYXRpdmVGaWx0ZXIgJiYgb2JqLmZpbHRlciA9PT0gbmF0aXZlRmlsdGVyKSByZXR1cm4gb2JqLmZpbHRlcihwcmVkaWNhdGUsIGNvbnRleHQpO1xuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIGlmIChwcmVkaWNhdGUuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKSByZXN1bHRzLnB1c2godmFsdWUpO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9O1xuXG4gIC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIGZvciB3aGljaCBhIHRydXRoIHRlc3QgZmFpbHMuXG4gIF8ucmVqZWN0ID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcbiAgICByZXR1cm4gXy5maWx0ZXIob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIHJldHVybiAhcHJlZGljYXRlLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KTtcbiAgICB9LCBjb250ZXh0KTtcbiAgfTtcblxuICAvLyBEZXRlcm1pbmUgd2hldGhlciBhbGwgb2YgdGhlIGVsZW1lbnRzIG1hdGNoIGEgdHJ1dGggdGVzdC5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYGV2ZXJ5YCBpZiBhdmFpbGFibGUuXG4gIC8vIEFsaWFzZWQgYXMgYGFsbGAuXG4gIF8uZXZlcnkgPSBfLmFsbCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgcHJlZGljYXRlIHx8IChwcmVkaWNhdGUgPSBfLmlkZW50aXR5KTtcbiAgICB2YXIgcmVzdWx0ID0gdHJ1ZTtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiByZXN1bHQ7XG4gICAgaWYgKG5hdGl2ZUV2ZXJ5ICYmIG9iai5ldmVyeSA9PT0gbmF0aXZlRXZlcnkpIHJldHVybiBvYmouZXZlcnkocHJlZGljYXRlLCBjb250ZXh0KTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICBpZiAoIShyZXN1bHQgPSByZXN1bHQgJiYgcHJlZGljYXRlLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KSkpIHJldHVybiBicmVha2VyO1xuICAgIH0pO1xuICAgIHJldHVybiAhIXJlc3VsdDtcbiAgfTtcblxuICAvLyBEZXRlcm1pbmUgaWYgYXQgbGVhc3Qgb25lIGVsZW1lbnQgaW4gdGhlIG9iamVjdCBtYXRjaGVzIGEgdHJ1dGggdGVzdC5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYHNvbWVgIGlmIGF2YWlsYWJsZS5cbiAgLy8gQWxpYXNlZCBhcyBgYW55YC5cbiAgdmFyIGFueSA9IF8uc29tZSA9IF8uYW55ID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHtcbiAgICBwcmVkaWNhdGUgfHwgKHByZWRpY2F0ZSA9IF8uaWRlbnRpdHkpO1xuICAgIHZhciByZXN1bHQgPSBmYWxzZTtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiByZXN1bHQ7XG4gICAgaWYgKG5hdGl2ZVNvbWUgJiYgb2JqLnNvbWUgPT09IG5hdGl2ZVNvbWUpIHJldHVybiBvYmouc29tZShwcmVkaWNhdGUsIGNvbnRleHQpO1xuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIGlmIChyZXN1bHQgfHwgKHJlc3VsdCA9IHByZWRpY2F0ZS5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdCkpKSByZXR1cm4gYnJlYWtlcjtcbiAgICB9KTtcbiAgICByZXR1cm4gISFyZXN1bHQ7XG4gIH07XG5cbiAgLy8gRGV0ZXJtaW5lIGlmIHRoZSBhcnJheSBvciBvYmplY3QgY29udGFpbnMgYSBnaXZlbiB2YWx1ZSAodXNpbmcgYD09PWApLlxuICAvLyBBbGlhc2VkIGFzIGBpbmNsdWRlYC5cbiAgXy5jb250YWlucyA9IF8uaW5jbHVkZSA9IGZ1bmN0aW9uKG9iaiwgdGFyZ2V0KSB7XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gZmFsc2U7XG4gICAgaWYgKG5hdGl2ZUluZGV4T2YgJiYgb2JqLmluZGV4T2YgPT09IG5hdGl2ZUluZGV4T2YpIHJldHVybiBvYmouaW5kZXhPZih0YXJnZXQpICE9IC0xO1xuICAgIHJldHVybiBhbnkob2JqLCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmV0dXJuIHZhbHVlID09PSB0YXJnZXQ7XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gSW52b2tlIGEgbWV0aG9kICh3aXRoIGFyZ3VtZW50cykgb24gZXZlcnkgaXRlbSBpbiBhIGNvbGxlY3Rpb24uXG4gIF8uaW52b2tlID0gZnVuY3Rpb24ob2JqLCBtZXRob2QpIHtcbiAgICB2YXIgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICB2YXIgaXNGdW5jID0gXy5pc0Z1bmN0aW9uKG1ldGhvZCk7XG4gICAgcmV0dXJuIF8ubWFwKG9iaiwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJldHVybiAoaXNGdW5jID8gbWV0aG9kIDogdmFsdWVbbWV0aG9kXSkuYXBwbHkodmFsdWUsIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIENvbnZlbmllbmNlIHZlcnNpb24gb2YgYSBjb21tb24gdXNlIGNhc2Ugb2YgYG1hcGA6IGZldGNoaW5nIGEgcHJvcGVydHkuXG4gIF8ucGx1Y2sgPSBmdW5jdGlvbihvYmosIGtleSkge1xuICAgIHJldHVybiBfLm1hcChvYmosIF8ucHJvcGVydHkoa2V5KSk7XG4gIH07XG5cbiAgLy8gQ29udmVuaWVuY2UgdmVyc2lvbiBvZiBhIGNvbW1vbiB1c2UgY2FzZSBvZiBgZmlsdGVyYDogc2VsZWN0aW5nIG9ubHkgb2JqZWN0c1xuICAvLyBjb250YWluaW5nIHNwZWNpZmljIGBrZXk6dmFsdWVgIHBhaXJzLlxuICBfLndoZXJlID0gZnVuY3Rpb24ob2JqLCBhdHRycykge1xuICAgIHJldHVybiBfLmZpbHRlcihvYmosIF8ubWF0Y2hlcyhhdHRycykpO1xuICB9O1xuXG4gIC8vIENvbnZlbmllbmNlIHZlcnNpb24gb2YgYSBjb21tb24gdXNlIGNhc2Ugb2YgYGZpbmRgOiBnZXR0aW5nIHRoZSBmaXJzdCBvYmplY3RcbiAgLy8gY29udGFpbmluZyBzcGVjaWZpYyBga2V5OnZhbHVlYCBwYWlycy5cbiAgXy5maW5kV2hlcmUgPSBmdW5jdGlvbihvYmosIGF0dHJzKSB7XG4gICAgcmV0dXJuIF8uZmluZChvYmosIF8ubWF0Y2hlcyhhdHRycykpO1xuICB9O1xuXG4gIC8vIFJldHVybiB0aGUgbWF4aW11bSBlbGVtZW50IG9yIChlbGVtZW50LWJhc2VkIGNvbXB1dGF0aW9uKS5cbiAgLy8gQ2FuJ3Qgb3B0aW1pemUgYXJyYXlzIG9mIGludGVnZXJzIGxvbmdlciB0aGFuIDY1LDUzNSBlbGVtZW50cy5cbiAgLy8gU2VlIFtXZWJLaXQgQnVnIDgwNzk3XShodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9ODA3OTcpXG4gIF8ubWF4ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGlmICghaXRlcmF0b3IgJiYgXy5pc0FycmF5KG9iaikgJiYgb2JqWzBdID09PSArb2JqWzBdICYmIG9iai5sZW5ndGggPCA2NTUzNSkge1xuICAgICAgcmV0dXJuIE1hdGgubWF4LmFwcGx5KE1hdGgsIG9iaik7XG4gICAgfVxuICAgIHZhciByZXN1bHQgPSAtSW5maW5pdHksIGxhc3RDb21wdXRlZCA9IC1JbmZpbml0eTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICB2YXIgY29tcHV0ZWQgPSBpdGVyYXRvciA/IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KSA6IHZhbHVlO1xuICAgICAgaWYgKGNvbXB1dGVkID4gbGFzdENvbXB1dGVkKSB7XG4gICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICBsYXN0Q29tcHV0ZWQgPSBjb21wdXRlZDtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFJldHVybiB0aGUgbWluaW11bSBlbGVtZW50IChvciBlbGVtZW50LWJhc2VkIGNvbXB1dGF0aW9uKS5cbiAgXy5taW4gPSBmdW5jdGlvbihvYmosIGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgaWYgKCFpdGVyYXRvciAmJiBfLmlzQXJyYXkob2JqKSAmJiBvYmpbMF0gPT09ICtvYmpbMF0gJiYgb2JqLmxlbmd0aCA8IDY1NTM1KSB7XG4gICAgICByZXR1cm4gTWF0aC5taW4uYXBwbHkoTWF0aCwgb2JqKTtcbiAgICB9XG4gICAgdmFyIHJlc3VsdCA9IEluZmluaXR5LCBsYXN0Q29tcHV0ZWQgPSBJbmZpbml0eTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICB2YXIgY29tcHV0ZWQgPSBpdGVyYXRvciA/IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KSA6IHZhbHVlO1xuICAgICAgaWYgKGNvbXB1dGVkIDwgbGFzdENvbXB1dGVkKSB7XG4gICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICBsYXN0Q29tcHV0ZWQgPSBjb21wdXRlZDtcbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFNodWZmbGUgYW4gYXJyYXksIHVzaW5nIHRoZSBtb2Rlcm4gdmVyc2lvbiBvZiB0aGVcbiAgLy8gW0Zpc2hlci1ZYXRlcyBzaHVmZmxlXShodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Zpc2hlcuKAk1lhdGVzX3NodWZmbGUpLlxuICBfLnNodWZmbGUgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgcmFuZDtcbiAgICB2YXIgaW5kZXggPSAwO1xuICAgIHZhciBzaHVmZmxlZCA9IFtdO1xuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgcmFuZCA9IF8ucmFuZG9tKGluZGV4KyspO1xuICAgICAgc2h1ZmZsZWRbaW5kZXggLSAxXSA9IHNodWZmbGVkW3JhbmRdO1xuICAgICAgc2h1ZmZsZWRbcmFuZF0gPSB2YWx1ZTtcbiAgICB9KTtcbiAgICByZXR1cm4gc2h1ZmZsZWQ7XG4gIH07XG5cbiAgLy8gU2FtcGxlICoqbioqIHJhbmRvbSB2YWx1ZXMgZnJvbSBhIGNvbGxlY3Rpb24uXG4gIC8vIElmICoqbioqIGlzIG5vdCBzcGVjaWZpZWQsIHJldHVybnMgYSBzaW5nbGUgcmFuZG9tIGVsZW1lbnQuXG4gIC8vIFRoZSBpbnRlcm5hbCBgZ3VhcmRgIGFyZ3VtZW50IGFsbG93cyBpdCB0byB3b3JrIHdpdGggYG1hcGAuXG4gIF8uc2FtcGxlID0gZnVuY3Rpb24ob2JqLCBuLCBndWFyZCkge1xuICAgIGlmIChuID09IG51bGwgfHwgZ3VhcmQpIHtcbiAgICAgIGlmIChvYmoubGVuZ3RoICE9PSArb2JqLmxlbmd0aCkgb2JqID0gXy52YWx1ZXMob2JqKTtcbiAgICAgIHJldHVybiBvYmpbXy5yYW5kb20ob2JqLmxlbmd0aCAtIDEpXTtcbiAgICB9XG4gICAgcmV0dXJuIF8uc2h1ZmZsZShvYmopLnNsaWNlKDAsIE1hdGgubWF4KDAsIG4pKTtcbiAgfTtcblxuICAvLyBBbiBpbnRlcm5hbCBmdW5jdGlvbiB0byBnZW5lcmF0ZSBsb29rdXAgaXRlcmF0b3JzLlxuICB2YXIgbG9va3VwSXRlcmF0b3IgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIGlmICh2YWx1ZSA9PSBudWxsKSByZXR1cm4gXy5pZGVudGl0eTtcbiAgICBpZiAoXy5pc0Z1bmN0aW9uKHZhbHVlKSkgcmV0dXJuIHZhbHVlO1xuICAgIHJldHVybiBfLnByb3BlcnR5KHZhbHVlKTtcbiAgfTtcblxuICAvLyBTb3J0IHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24gcHJvZHVjZWQgYnkgYW4gaXRlcmF0b3IuXG4gIF8uc29ydEJ5ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGl0ZXJhdG9yID0gbG9va3VwSXRlcmF0b3IoaXRlcmF0b3IpO1xuICAgIHJldHVybiBfLnBsdWNrKF8ubWFwKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB2YWx1ZTogdmFsdWUsXG4gICAgICAgIGluZGV4OiBpbmRleCxcbiAgICAgICAgY3JpdGVyaWE6IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KVxuICAgICAgfTtcbiAgICB9KS5zb3J0KGZ1bmN0aW9uKGxlZnQsIHJpZ2h0KSB7XG4gICAgICB2YXIgYSA9IGxlZnQuY3JpdGVyaWE7XG4gICAgICB2YXIgYiA9IHJpZ2h0LmNyaXRlcmlhO1xuICAgICAgaWYgKGEgIT09IGIpIHtcbiAgICAgICAgaWYgKGEgPiBiIHx8IGEgPT09IHZvaWQgMCkgcmV0dXJuIDE7XG4gICAgICAgIGlmIChhIDwgYiB8fCBiID09PSB2b2lkIDApIHJldHVybiAtMTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBsZWZ0LmluZGV4IC0gcmlnaHQuaW5kZXg7XG4gICAgfSksICd2YWx1ZScpO1xuICB9O1xuXG4gIC8vIEFuIGludGVybmFsIGZ1bmN0aW9uIHVzZWQgZm9yIGFnZ3JlZ2F0ZSBcImdyb3VwIGJ5XCIgb3BlcmF0aW9ucy5cbiAgdmFyIGdyb3VwID0gZnVuY3Rpb24oYmVoYXZpb3IpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgaXRlcmF0b3IgPSBsb29rdXBJdGVyYXRvcihpdGVyYXRvcik7XG4gICAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICAgIHZhciBrZXkgPSBpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgb2JqKTtcbiAgICAgICAgYmVoYXZpb3IocmVzdWx0LCBrZXksIHZhbHVlKTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICB9O1xuXG4gIC8vIEdyb3VwcyB0aGUgb2JqZWN0J3MgdmFsdWVzIGJ5IGEgY3JpdGVyaW9uLiBQYXNzIGVpdGhlciBhIHN0cmluZyBhdHRyaWJ1dGVcbiAgLy8gdG8gZ3JvdXAgYnksIG9yIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZSBjcml0ZXJpb24uXG4gIF8uZ3JvdXBCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwga2V5LCB2YWx1ZSkge1xuICAgIF8uaGFzKHJlc3VsdCwga2V5KSA/IHJlc3VsdFtrZXldLnB1c2godmFsdWUpIDogcmVzdWx0W2tleV0gPSBbdmFsdWVdO1xuICB9KTtcblxuICAvLyBJbmRleGVzIHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24sIHNpbWlsYXIgdG8gYGdyb3VwQnlgLCBidXQgZm9yXG4gIC8vIHdoZW4geW91IGtub3cgdGhhdCB5b3VyIGluZGV4IHZhbHVlcyB3aWxsIGJlIHVuaXF1ZS5cbiAgXy5pbmRleEJ5ID0gZ3JvdXAoZnVuY3Rpb24ocmVzdWx0LCBrZXksIHZhbHVlKSB7XG4gICAgcmVzdWx0W2tleV0gPSB2YWx1ZTtcbiAgfSk7XG5cbiAgLy8gQ291bnRzIGluc3RhbmNlcyBvZiBhbiBvYmplY3QgdGhhdCBncm91cCBieSBhIGNlcnRhaW4gY3JpdGVyaW9uLiBQYXNzXG4gIC8vIGVpdGhlciBhIHN0cmluZyBhdHRyaWJ1dGUgdG8gY291bnQgYnksIG9yIGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIHRoZVxuICAvLyBjcml0ZXJpb24uXG4gIF8uY291bnRCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwga2V5KSB7XG4gICAgXy5oYXMocmVzdWx0LCBrZXkpID8gcmVzdWx0W2tleV0rKyA6IHJlc3VsdFtrZXldID0gMTtcbiAgfSk7XG5cbiAgLy8gVXNlIGEgY29tcGFyYXRvciBmdW5jdGlvbiB0byBmaWd1cmUgb3V0IHRoZSBzbWFsbGVzdCBpbmRleCBhdCB3aGljaFxuICAvLyBhbiBvYmplY3Qgc2hvdWxkIGJlIGluc2VydGVkIHNvIGFzIHRvIG1haW50YWluIG9yZGVyLiBVc2VzIGJpbmFyeSBzZWFyY2guXG4gIF8uc29ydGVkSW5kZXggPSBmdW5jdGlvbihhcnJheSwgb2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGl0ZXJhdG9yID0gbG9va3VwSXRlcmF0b3IoaXRlcmF0b3IpO1xuICAgIHZhciB2YWx1ZSA9IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqKTtcbiAgICB2YXIgbG93ID0gMCwgaGlnaCA9IGFycmF5Lmxlbmd0aDtcbiAgICB3aGlsZSAobG93IDwgaGlnaCkge1xuICAgICAgdmFyIG1pZCA9IChsb3cgKyBoaWdoKSA+Pj4gMTtcbiAgICAgIGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgYXJyYXlbbWlkXSkgPCB2YWx1ZSA/IGxvdyA9IG1pZCArIDEgOiBoaWdoID0gbWlkO1xuICAgIH1cbiAgICByZXR1cm4gbG93O1xuICB9O1xuXG4gIC8vIFNhZmVseSBjcmVhdGUgYSByZWFsLCBsaXZlIGFycmF5IGZyb20gYW55dGhpbmcgaXRlcmFibGUuXG4gIF8udG9BcnJheSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmICghb2JqKSByZXR1cm4gW107XG4gICAgaWYgKF8uaXNBcnJheShvYmopKSByZXR1cm4gc2xpY2UuY2FsbChvYmopO1xuICAgIGlmIChvYmoubGVuZ3RoID09PSArb2JqLmxlbmd0aCkgcmV0dXJuIF8ubWFwKG9iaiwgXy5pZGVudGl0eSk7XG4gICAgcmV0dXJuIF8udmFsdWVzKG9iaik7XG4gIH07XG5cbiAgLy8gUmV0dXJuIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gYW4gb2JqZWN0LlxuICBfLnNpemUgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiAwO1xuICAgIHJldHVybiAob2JqLmxlbmd0aCA9PT0gK29iai5sZW5ndGgpID8gb2JqLmxlbmd0aCA6IF8ua2V5cyhvYmopLmxlbmd0aDtcbiAgfTtcblxuICAvLyBBcnJheSBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tXG5cbiAgLy8gR2V0IHRoZSBmaXJzdCBlbGVtZW50IG9mIGFuIGFycmF5LiBQYXNzaW5nICoqbioqIHdpbGwgcmV0dXJuIHRoZSBmaXJzdCBOXG4gIC8vIHZhbHVlcyBpbiB0aGUgYXJyYXkuIEFsaWFzZWQgYXMgYGhlYWRgIGFuZCBgdGFrZWAuIFRoZSAqKmd1YXJkKiogY2hlY2tcbiAgLy8gYWxsb3dzIGl0IHRvIHdvcmsgd2l0aCBgXy5tYXBgLlxuICBfLmZpcnN0ID0gXy5oZWFkID0gXy50YWtlID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgaWYgKGFycmF5ID09IG51bGwpIHJldHVybiB2b2lkIDA7XG4gICAgaWYgKChuID09IG51bGwpIHx8IGd1YXJkKSByZXR1cm4gYXJyYXlbMF07XG4gICAgaWYgKG4gPCAwKSByZXR1cm4gW107XG4gICAgcmV0dXJuIHNsaWNlLmNhbGwoYXJyYXksIDAsIG4pO1xuICB9O1xuXG4gIC8vIFJldHVybnMgZXZlcnl0aGluZyBidXQgdGhlIGxhc3QgZW50cnkgb2YgdGhlIGFycmF5LiBFc3BlY2lhbGx5IHVzZWZ1bCBvblxuICAvLyB0aGUgYXJndW1lbnRzIG9iamVjdC4gUGFzc2luZyAqKm4qKiB3aWxsIHJldHVybiBhbGwgdGhlIHZhbHVlcyBpblxuICAvLyB0aGUgYXJyYXksIGV4Y2x1ZGluZyB0aGUgbGFzdCBOLiBUaGUgKipndWFyZCoqIGNoZWNrIGFsbG93cyBpdCB0byB3b3JrIHdpdGhcbiAgLy8gYF8ubWFwYC5cbiAgXy5pbml0aWFsID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgcmV0dXJuIHNsaWNlLmNhbGwoYXJyYXksIDAsIGFycmF5Lmxlbmd0aCAtICgobiA9PSBudWxsKSB8fCBndWFyZCA/IDEgOiBuKSk7XG4gIH07XG5cbiAgLy8gR2V0IHRoZSBsYXN0IGVsZW1lbnQgb2YgYW4gYXJyYXkuIFBhc3NpbmcgKipuKiogd2lsbCByZXR1cm4gdGhlIGxhc3QgTlxuICAvLyB2YWx1ZXMgaW4gdGhlIGFycmF5LiBUaGUgKipndWFyZCoqIGNoZWNrIGFsbG93cyBpdCB0byB3b3JrIHdpdGggYF8ubWFwYC5cbiAgXy5sYXN0ID0gZnVuY3Rpb24oYXJyYXksIG4sIGd1YXJkKSB7XG4gICAgaWYgKGFycmF5ID09IG51bGwpIHJldHVybiB2b2lkIDA7XG4gICAgaWYgKChuID09IG51bGwpIHx8IGd1YXJkKSByZXR1cm4gYXJyYXlbYXJyYXkubGVuZ3RoIC0gMV07XG4gICAgcmV0dXJuIHNsaWNlLmNhbGwoYXJyYXksIE1hdGgubWF4KGFycmF5Lmxlbmd0aCAtIG4sIDApKTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGV2ZXJ5dGhpbmcgYnV0IHRoZSBmaXJzdCBlbnRyeSBvZiB0aGUgYXJyYXkuIEFsaWFzZWQgYXMgYHRhaWxgIGFuZCBgZHJvcGAuXG4gIC8vIEVzcGVjaWFsbHkgdXNlZnVsIG9uIHRoZSBhcmd1bWVudHMgb2JqZWN0LiBQYXNzaW5nIGFuICoqbioqIHdpbGwgcmV0dXJuXG4gIC8vIHRoZSByZXN0IE4gdmFsdWVzIGluIHRoZSBhcnJheS4gVGhlICoqZ3VhcmQqKlxuICAvLyBjaGVjayBhbGxvd3MgaXQgdG8gd29yayB3aXRoIGBfLm1hcGAuXG4gIF8ucmVzdCA9IF8udGFpbCA9IF8uZHJvcCA9IGZ1bmN0aW9uKGFycmF5LCBuLCBndWFyZCkge1xuICAgIHJldHVybiBzbGljZS5jYWxsKGFycmF5LCAobiA9PSBudWxsKSB8fCBndWFyZCA/IDEgOiBuKTtcbiAgfTtcblxuICAvLyBUcmltIG91dCBhbGwgZmFsc3kgdmFsdWVzIGZyb20gYW4gYXJyYXkuXG4gIF8uY29tcGFjdCA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgcmV0dXJuIF8uZmlsdGVyKGFycmF5LCBfLmlkZW50aXR5KTtcbiAgfTtcblxuICAvLyBJbnRlcm5hbCBpbXBsZW1lbnRhdGlvbiBvZiBhIHJlY3Vyc2l2ZSBgZmxhdHRlbmAgZnVuY3Rpb24uXG4gIHZhciBmbGF0dGVuID0gZnVuY3Rpb24oaW5wdXQsIHNoYWxsb3csIG91dHB1dCkge1xuICAgIGlmIChzaGFsbG93ICYmIF8uZXZlcnkoaW5wdXQsIF8uaXNBcnJheSkpIHtcbiAgICAgIHJldHVybiBjb25jYXQuYXBwbHkob3V0cHV0LCBpbnB1dCk7XG4gICAgfVxuICAgIGVhY2goaW5wdXQsIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICBpZiAoXy5pc0FycmF5KHZhbHVlKSB8fCBfLmlzQXJndW1lbnRzKHZhbHVlKSkge1xuICAgICAgICBzaGFsbG93ID8gcHVzaC5hcHBseShvdXRwdXQsIHZhbHVlKSA6IGZsYXR0ZW4odmFsdWUsIHNoYWxsb3csIG91dHB1dCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvdXRwdXQucHVzaCh2YWx1ZSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG91dHB1dDtcbiAgfTtcblxuICAvLyBGbGF0dGVuIG91dCBhbiBhcnJheSwgZWl0aGVyIHJlY3Vyc2l2ZWx5IChieSBkZWZhdWx0KSwgb3IganVzdCBvbmUgbGV2ZWwuXG4gIF8uZmxhdHRlbiA9IGZ1bmN0aW9uKGFycmF5LCBzaGFsbG93KSB7XG4gICAgcmV0dXJuIGZsYXR0ZW4oYXJyYXksIHNoYWxsb3csIFtdKTtcbiAgfTtcblxuICAvLyBSZXR1cm4gYSB2ZXJzaW9uIG9mIHRoZSBhcnJheSB0aGF0IGRvZXMgbm90IGNvbnRhaW4gdGhlIHNwZWNpZmllZCB2YWx1ZShzKS5cbiAgXy53aXRob3V0ID0gZnVuY3Rpb24oYXJyYXkpIHtcbiAgICByZXR1cm4gXy5kaWZmZXJlbmNlKGFycmF5LCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICB9O1xuXG4gIC8vIFNwbGl0IGFuIGFycmF5IGludG8gdHdvIGFycmF5czogb25lIHdob3NlIGVsZW1lbnRzIGFsbCBzYXRpc2Z5IHRoZSBnaXZlblxuICAvLyBwcmVkaWNhdGUsIGFuZCBvbmUgd2hvc2UgZWxlbWVudHMgYWxsIGRvIG5vdCBzYXRpc2Z5IHRoZSBwcmVkaWNhdGUuXG4gIF8ucGFydGl0aW9uID0gZnVuY3Rpb24oYXJyYXksIHByZWRpY2F0ZSkge1xuICAgIHZhciBwYXNzID0gW10sIGZhaWwgPSBbXTtcbiAgICBlYWNoKGFycmF5LCBmdW5jdGlvbihlbGVtKSB7XG4gICAgICAocHJlZGljYXRlKGVsZW0pID8gcGFzcyA6IGZhaWwpLnB1c2goZWxlbSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIFtwYXNzLCBmYWlsXTtcbiAgfTtcblxuICAvLyBQcm9kdWNlIGEgZHVwbGljYXRlLWZyZWUgdmVyc2lvbiBvZiB0aGUgYXJyYXkuIElmIHRoZSBhcnJheSBoYXMgYWxyZWFkeVxuICAvLyBiZWVuIHNvcnRlZCwgeW91IGhhdmUgdGhlIG9wdGlvbiBvZiB1c2luZyBhIGZhc3RlciBhbGdvcml0aG0uXG4gIC8vIEFsaWFzZWQgYXMgYHVuaXF1ZWAuXG4gIF8udW5pcSA9IF8udW5pcXVlID0gZnVuY3Rpb24oYXJyYXksIGlzU29ydGVkLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGlmIChfLmlzRnVuY3Rpb24oaXNTb3J0ZWQpKSB7XG4gICAgICBjb250ZXh0ID0gaXRlcmF0b3I7XG4gICAgICBpdGVyYXRvciA9IGlzU29ydGVkO1xuICAgICAgaXNTb3J0ZWQgPSBmYWxzZTtcbiAgICB9XG4gICAgdmFyIGluaXRpYWwgPSBpdGVyYXRvciA/IF8ubWFwKGFycmF5LCBpdGVyYXRvciwgY29udGV4dCkgOiBhcnJheTtcbiAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgIHZhciBzZWVuID0gW107XG4gICAgZWFjaChpbml0aWFsLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgpIHtcbiAgICAgIGlmIChpc1NvcnRlZCA/ICghaW5kZXggfHwgc2VlbltzZWVuLmxlbmd0aCAtIDFdICE9PSB2YWx1ZSkgOiAhXy5jb250YWlucyhzZWVuLCB2YWx1ZSkpIHtcbiAgICAgICAgc2Vlbi5wdXNoKHZhbHVlKTtcbiAgICAgICAgcmVzdWx0cy5wdXNoKGFycmF5W2luZGV4XSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH07XG5cbiAgLy8gUHJvZHVjZSBhbiBhcnJheSB0aGF0IGNvbnRhaW5zIHRoZSB1bmlvbjogZWFjaCBkaXN0aW5jdCBlbGVtZW50IGZyb20gYWxsIG9mXG4gIC8vIHRoZSBwYXNzZWQtaW4gYXJyYXlzLlxuICBfLnVuaW9uID0gZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIF8udW5pcShfLmZsYXR0ZW4oYXJndW1lbnRzLCB0cnVlKSk7XG4gIH07XG5cbiAgLy8gUHJvZHVjZSBhbiBhcnJheSB0aGF0IGNvbnRhaW5zIGV2ZXJ5IGl0ZW0gc2hhcmVkIGJldHdlZW4gYWxsIHRoZVxuICAvLyBwYXNzZWQtaW4gYXJyYXlzLlxuICBfLmludGVyc2VjdGlvbiA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgdmFyIHJlc3QgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgcmV0dXJuIF8uZmlsdGVyKF8udW5pcShhcnJheSksIGZ1bmN0aW9uKGl0ZW0pIHtcbiAgICAgIHJldHVybiBfLmV2ZXJ5KHJlc3QsIGZ1bmN0aW9uKG90aGVyKSB7XG4gICAgICAgIHJldHVybiBfLmNvbnRhaW5zKG90aGVyLCBpdGVtKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIFRha2UgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBvbmUgYXJyYXkgYW5kIGEgbnVtYmVyIG9mIG90aGVyIGFycmF5cy5cbiAgLy8gT25seSB0aGUgZWxlbWVudHMgcHJlc2VudCBpbiBqdXN0IHRoZSBmaXJzdCBhcnJheSB3aWxsIHJlbWFpbi5cbiAgXy5kaWZmZXJlbmNlID0gZnVuY3Rpb24oYXJyYXkpIHtcbiAgICB2YXIgcmVzdCA9IGNvbmNhdC5hcHBseShBcnJheVByb3RvLCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICAgIHJldHVybiBfLmZpbHRlcihhcnJheSwgZnVuY3Rpb24odmFsdWUpeyByZXR1cm4gIV8uY29udGFpbnMocmVzdCwgdmFsdWUpOyB9KTtcbiAgfTtcblxuICAvLyBaaXAgdG9nZXRoZXIgbXVsdGlwbGUgbGlzdHMgaW50byBhIHNpbmdsZSBhcnJheSAtLSBlbGVtZW50cyB0aGF0IHNoYXJlXG4gIC8vIGFuIGluZGV4IGdvIHRvZ2V0aGVyLlxuICBfLnppcCA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBsZW5ndGggPSBfLm1heChfLnBsdWNrKGFyZ3VtZW50cywgJ2xlbmd0aCcpLmNvbmNhdCgwKSk7XG4gICAgdmFyIHJlc3VsdHMgPSBuZXcgQXJyYXkobGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICByZXN1bHRzW2ldID0gXy5wbHVjayhhcmd1bWVudHMsICcnICsgaSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRzO1xuICB9O1xuXG4gIC8vIENvbnZlcnRzIGxpc3RzIGludG8gb2JqZWN0cy4gUGFzcyBlaXRoZXIgYSBzaW5nbGUgYXJyYXkgb2YgYFtrZXksIHZhbHVlXWBcbiAgLy8gcGFpcnMsIG9yIHR3byBwYXJhbGxlbCBhcnJheXMgb2YgdGhlIHNhbWUgbGVuZ3RoIC0tIG9uZSBvZiBrZXlzLCBhbmQgb25lIG9mXG4gIC8vIHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlcy5cbiAgXy5vYmplY3QgPSBmdW5jdGlvbihsaXN0LCB2YWx1ZXMpIHtcbiAgICBpZiAobGlzdCA9PSBudWxsKSByZXR1cm4ge307XG4gICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBsaXN0Lmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodmFsdWVzKSB7XG4gICAgICAgIHJlc3VsdFtsaXN0W2ldXSA9IHZhbHVlc1tpXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdFtsaXN0W2ldWzBdXSA9IGxpc3RbaV1bMV07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gSWYgdGhlIGJyb3dzZXIgZG9lc24ndCBzdXBwbHkgdXMgd2l0aCBpbmRleE9mIChJJ20gbG9va2luZyBhdCB5b3UsICoqTVNJRSoqKSxcbiAgLy8gd2UgbmVlZCB0aGlzIGZ1bmN0aW9uLiBSZXR1cm4gdGhlIHBvc2l0aW9uIG9mIHRoZSBmaXJzdCBvY2N1cnJlbmNlIG9mIGFuXG4gIC8vIGl0ZW0gaW4gYW4gYXJyYXksIG9yIC0xIGlmIHRoZSBpdGVtIGlzIG5vdCBpbmNsdWRlZCBpbiB0aGUgYXJyYXkuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBpbmRleE9mYCBpZiBhdmFpbGFibGUuXG4gIC8vIElmIHRoZSBhcnJheSBpcyBsYXJnZSBhbmQgYWxyZWFkeSBpbiBzb3J0IG9yZGVyLCBwYXNzIGB0cnVlYFxuICAvLyBmb3IgKippc1NvcnRlZCoqIHRvIHVzZSBiaW5hcnkgc2VhcmNoLlxuICBfLmluZGV4T2YgPSBmdW5jdGlvbihhcnJheSwgaXRlbSwgaXNTb3J0ZWQpIHtcbiAgICBpZiAoYXJyYXkgPT0gbnVsbCkgcmV0dXJuIC0xO1xuICAgIHZhciBpID0gMCwgbGVuZ3RoID0gYXJyYXkubGVuZ3RoO1xuICAgIGlmIChpc1NvcnRlZCkge1xuICAgICAgaWYgKHR5cGVvZiBpc1NvcnRlZCA9PSAnbnVtYmVyJykge1xuICAgICAgICBpID0gKGlzU29ydGVkIDwgMCA/IE1hdGgubWF4KDAsIGxlbmd0aCArIGlzU29ydGVkKSA6IGlzU29ydGVkKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGkgPSBfLnNvcnRlZEluZGV4KGFycmF5LCBpdGVtKTtcbiAgICAgICAgcmV0dXJuIGFycmF5W2ldID09PSBpdGVtID8gaSA6IC0xO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAobmF0aXZlSW5kZXhPZiAmJiBhcnJheS5pbmRleE9mID09PSBuYXRpdmVJbmRleE9mKSByZXR1cm4gYXJyYXkuaW5kZXhPZihpdGVtLCBpc1NvcnRlZCk7XG4gICAgZm9yICg7IGkgPCBsZW5ndGg7IGkrKykgaWYgKGFycmF5W2ldID09PSBpdGVtKSByZXR1cm4gaTtcbiAgICByZXR1cm4gLTE7XG4gIH07XG5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYGxhc3RJbmRleE9mYCBpZiBhdmFpbGFibGUuXG4gIF8ubGFzdEluZGV4T2YgPSBmdW5jdGlvbihhcnJheSwgaXRlbSwgZnJvbSkge1xuICAgIGlmIChhcnJheSA9PSBudWxsKSByZXR1cm4gLTE7XG4gICAgdmFyIGhhc0luZGV4ID0gZnJvbSAhPSBudWxsO1xuICAgIGlmIChuYXRpdmVMYXN0SW5kZXhPZiAmJiBhcnJheS5sYXN0SW5kZXhPZiA9PT0gbmF0aXZlTGFzdEluZGV4T2YpIHtcbiAgICAgIHJldHVybiBoYXNJbmRleCA/IGFycmF5Lmxhc3RJbmRleE9mKGl0ZW0sIGZyb20pIDogYXJyYXkubGFzdEluZGV4T2YoaXRlbSk7XG4gICAgfVxuICAgIHZhciBpID0gKGhhc0luZGV4ID8gZnJvbSA6IGFycmF5Lmxlbmd0aCk7XG4gICAgd2hpbGUgKGktLSkgaWYgKGFycmF5W2ldID09PSBpdGVtKSByZXR1cm4gaTtcbiAgICByZXR1cm4gLTE7XG4gIH07XG5cbiAgLy8gR2VuZXJhdGUgYW4gaW50ZWdlciBBcnJheSBjb250YWluaW5nIGFuIGFyaXRobWV0aWMgcHJvZ3Jlc3Npb24uIEEgcG9ydCBvZlxuICAvLyB0aGUgbmF0aXZlIFB5dGhvbiBgcmFuZ2UoKWAgZnVuY3Rpb24uIFNlZVxuICAvLyBbdGhlIFB5dGhvbiBkb2N1bWVudGF0aW9uXShodHRwOi8vZG9jcy5weXRob24ub3JnL2xpYnJhcnkvZnVuY3Rpb25zLmh0bWwjcmFuZ2UpLlxuICBfLnJhbmdlID0gZnVuY3Rpb24oc3RhcnQsIHN0b3AsIHN0ZXApIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8PSAxKSB7XG4gICAgICBzdG9wID0gc3RhcnQgfHwgMDtcbiAgICAgIHN0YXJ0ID0gMDtcbiAgICB9XG4gICAgc3RlcCA9IGFyZ3VtZW50c1syXSB8fCAxO1xuXG4gICAgdmFyIGxlbmd0aCA9IE1hdGgubWF4KE1hdGguY2VpbCgoc3RvcCAtIHN0YXJ0KSAvIHN0ZXApLCAwKTtcbiAgICB2YXIgaWR4ID0gMDtcbiAgICB2YXIgcmFuZ2UgPSBuZXcgQXJyYXkobGVuZ3RoKTtcblxuICAgIHdoaWxlKGlkeCA8IGxlbmd0aCkge1xuICAgICAgcmFuZ2VbaWR4KytdID0gc3RhcnQ7XG4gICAgICBzdGFydCArPSBzdGVwO1xuICAgIH1cblxuICAgIHJldHVybiByYW5nZTtcbiAgfTtcblxuICAvLyBGdW5jdGlvbiAoYWhlbSkgRnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIFJldXNhYmxlIGNvbnN0cnVjdG9yIGZ1bmN0aW9uIGZvciBwcm90b3R5cGUgc2V0dGluZy5cbiAgdmFyIGN0b3IgPSBmdW5jdGlvbigpe307XG5cbiAgLy8gQ3JlYXRlIGEgZnVuY3Rpb24gYm91bmQgdG8gYSBnaXZlbiBvYmplY3QgKGFzc2lnbmluZyBgdGhpc2AsIGFuZCBhcmd1bWVudHMsXG4gIC8vIG9wdGlvbmFsbHkpLiBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgRnVuY3Rpb24uYmluZGAgaWZcbiAgLy8gYXZhaWxhYmxlLlxuICBfLmJpbmQgPSBmdW5jdGlvbihmdW5jLCBjb250ZXh0KSB7XG4gICAgdmFyIGFyZ3MsIGJvdW5kO1xuICAgIGlmIChuYXRpdmVCaW5kICYmIGZ1bmMuYmluZCA9PT0gbmF0aXZlQmluZCkgcmV0dXJuIG5hdGl2ZUJpbmQuYXBwbHkoZnVuYywgc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICBpZiAoIV8uaXNGdW5jdGlvbihmdW5jKSkgdGhyb3cgbmV3IFR5cGVFcnJvcjtcbiAgICBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpO1xuICAgIHJldHVybiBib3VuZCA9IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIGJvdW5kKSkgcmV0dXJuIGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncy5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMpKSk7XG4gICAgICBjdG9yLnByb3RvdHlwZSA9IGZ1bmMucHJvdG90eXBlO1xuICAgICAgdmFyIHNlbGYgPSBuZXcgY3RvcjtcbiAgICAgIGN0b3IucHJvdG90eXBlID0gbnVsbDtcbiAgICAgIHZhciByZXN1bHQgPSBmdW5jLmFwcGx5KHNlbGYsIGFyZ3MuY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzKSkpO1xuICAgICAgaWYgKE9iamVjdChyZXN1bHQpID09PSByZXN1bHQpIHJldHVybiByZXN1bHQ7XG4gICAgICByZXR1cm4gc2VsZjtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFBhcnRpYWxseSBhcHBseSBhIGZ1bmN0aW9uIGJ5IGNyZWF0aW5nIGEgdmVyc2lvbiB0aGF0IGhhcyBoYWQgc29tZSBvZiBpdHNcbiAgLy8gYXJndW1lbnRzIHByZS1maWxsZWQsIHdpdGhvdXQgY2hhbmdpbmcgaXRzIGR5bmFtaWMgYHRoaXNgIGNvbnRleHQuIF8gYWN0c1xuICAvLyBhcyBhIHBsYWNlaG9sZGVyLCBhbGxvd2luZyBhbnkgY29tYmluYXRpb24gb2YgYXJndW1lbnRzIHRvIGJlIHByZS1maWxsZWQuXG4gIF8ucGFydGlhbCA9IGZ1bmN0aW9uKGZ1bmMpIHtcbiAgICB2YXIgYm91bmRBcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBwb3NpdGlvbiA9IDA7XG4gICAgICB2YXIgYXJncyA9IGJvdW5kQXJncy5zbGljZSgpO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGFyZ3MubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGFyZ3NbaV0gPT09IF8pIGFyZ3NbaV0gPSBhcmd1bWVudHNbcG9zaXRpb24rK107XG4gICAgICB9XG4gICAgICB3aGlsZSAocG9zaXRpb24gPCBhcmd1bWVudHMubGVuZ3RoKSBhcmdzLnB1c2goYXJndW1lbnRzW3Bvc2l0aW9uKytdKTtcbiAgICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH07XG4gIH07XG5cbiAgLy8gQmluZCBhIG51bWJlciBvZiBhbiBvYmplY3QncyBtZXRob2RzIHRvIHRoYXQgb2JqZWN0LiBSZW1haW5pbmcgYXJndW1lbnRzXG4gIC8vIGFyZSB0aGUgbWV0aG9kIG5hbWVzIHRvIGJlIGJvdW5kLiBVc2VmdWwgZm9yIGVuc3VyaW5nIHRoYXQgYWxsIGNhbGxiYWNrc1xuICAvLyBkZWZpbmVkIG9uIGFuIG9iamVjdCBiZWxvbmcgdG8gaXQuXG4gIF8uYmluZEFsbCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBmdW5jcyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICBpZiAoZnVuY3MubGVuZ3RoID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoJ2JpbmRBbGwgbXVzdCBiZSBwYXNzZWQgZnVuY3Rpb24gbmFtZXMnKTtcbiAgICBlYWNoKGZ1bmNzLCBmdW5jdGlvbihmKSB7IG9ialtmXSA9IF8uYmluZChvYmpbZl0sIG9iaik7IH0pO1xuICAgIHJldHVybiBvYmo7XG4gIH07XG5cbiAgLy8gTWVtb2l6ZSBhbiBleHBlbnNpdmUgZnVuY3Rpb24gYnkgc3RvcmluZyBpdHMgcmVzdWx0cy5cbiAgXy5tZW1vaXplID0gZnVuY3Rpb24oZnVuYywgaGFzaGVyKSB7XG4gICAgdmFyIG1lbW8gPSB7fTtcbiAgICBoYXNoZXIgfHwgKGhhc2hlciA9IF8uaWRlbnRpdHkpO1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBrZXkgPSBoYXNoZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIHJldHVybiBfLmhhcyhtZW1vLCBrZXkpID8gbWVtb1trZXldIDogKG1lbW9ba2V5XSA9IGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKSk7XG4gICAgfTtcbiAgfTtcblxuICAvLyBEZWxheXMgYSBmdW5jdGlvbiBmb3IgdGhlIGdpdmVuIG51bWJlciBvZiBtaWxsaXNlY29uZHMsIGFuZCB0aGVuIGNhbGxzXG4gIC8vIGl0IHdpdGggdGhlIGFyZ3VtZW50cyBzdXBwbGllZC5cbiAgXy5kZWxheSA9IGZ1bmN0aW9uKGZ1bmMsIHdhaXQpIHtcbiAgICB2YXIgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICByZXR1cm4gc2V0VGltZW91dChmdW5jdGlvbigpeyByZXR1cm4gZnVuYy5hcHBseShudWxsLCBhcmdzKTsgfSwgd2FpdCk7XG4gIH07XG5cbiAgLy8gRGVmZXJzIGEgZnVuY3Rpb24sIHNjaGVkdWxpbmcgaXQgdG8gcnVuIGFmdGVyIHRoZSBjdXJyZW50IGNhbGwgc3RhY2sgaGFzXG4gIC8vIGNsZWFyZWQuXG4gIF8uZGVmZXIgPSBmdW5jdGlvbihmdW5jKSB7XG4gICAgcmV0dXJuIF8uZGVsYXkuYXBwbHkoXywgW2Z1bmMsIDFdLmNvbmNhdChzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpKTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24sIHRoYXQsIHdoZW4gaW52b2tlZCwgd2lsbCBvbmx5IGJlIHRyaWdnZXJlZCBhdCBtb3N0IG9uY2VcbiAgLy8gZHVyaW5nIGEgZ2l2ZW4gd2luZG93IG9mIHRpbWUuIE5vcm1hbGx5LCB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uIHdpbGwgcnVuXG4gIC8vIGFzIG11Y2ggYXMgaXQgY2FuLCB3aXRob3V0IGV2ZXIgZ29pbmcgbW9yZSB0aGFuIG9uY2UgcGVyIGB3YWl0YCBkdXJhdGlvbjtcbiAgLy8gYnV0IGlmIHlvdSdkIGxpa2UgdG8gZGlzYWJsZSB0aGUgZXhlY3V0aW9uIG9uIHRoZSBsZWFkaW5nIGVkZ2UsIHBhc3NcbiAgLy8gYHtsZWFkaW5nOiBmYWxzZX1gLiBUbyBkaXNhYmxlIGV4ZWN1dGlvbiBvbiB0aGUgdHJhaWxpbmcgZWRnZSwgZGl0dG8uXG4gIF8udGhyb3R0bGUgPSBmdW5jdGlvbihmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gICAgdmFyIGNvbnRleHQsIGFyZ3MsIHJlc3VsdDtcbiAgICB2YXIgdGltZW91dCA9IG51bGw7XG4gICAgdmFyIHByZXZpb3VzID0gMDtcbiAgICBvcHRpb25zIHx8IChvcHRpb25zID0ge30pO1xuICAgIHZhciBsYXRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgcHJldmlvdXMgPSBvcHRpb25zLmxlYWRpbmcgPT09IGZhbHNlID8gMCA6IF8ubm93KCk7XG4gICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICBjb250ZXh0ID0gYXJncyA9IG51bGw7XG4gICAgfTtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbm93ID0gXy5ub3coKTtcbiAgICAgIGlmICghcHJldmlvdXMgJiYgb3B0aW9ucy5sZWFkaW5nID09PSBmYWxzZSkgcHJldmlvdXMgPSBub3c7XG4gICAgICB2YXIgcmVtYWluaW5nID0gd2FpdCAtIChub3cgLSBwcmV2aW91cyk7XG4gICAgICBjb250ZXh0ID0gdGhpcztcbiAgICAgIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICBpZiAocmVtYWluaW5nIDw9IDApIHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgICAgcHJldmlvdXMgPSBub3c7XG4gICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcbiAgICAgIH0gZWxzZSBpZiAoIXRpbWVvdXQgJiYgb3B0aW9ucy50cmFpbGluZyAhPT0gZmFsc2UpIHtcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHJlbWFpbmluZyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uLCB0aGF0LCBhcyBsb25nIGFzIGl0IGNvbnRpbnVlcyB0byBiZSBpbnZva2VkLCB3aWxsIG5vdFxuICAvLyBiZSB0cmlnZ2VyZWQuIFRoZSBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBhZnRlciBpdCBzdG9wcyBiZWluZyBjYWxsZWQgZm9yXG4gIC8vIE4gbWlsbGlzZWNvbmRzLiBJZiBgaW1tZWRpYXRlYCBpcyBwYXNzZWQsIHRyaWdnZXIgdGhlIGZ1bmN0aW9uIG9uIHRoZVxuICAvLyBsZWFkaW5nIGVkZ2UsIGluc3RlYWQgb2YgdGhlIHRyYWlsaW5nLlxuICBfLmRlYm91bmNlID0gZnVuY3Rpb24oZnVuYywgd2FpdCwgaW1tZWRpYXRlKSB7XG4gICAgdmFyIHRpbWVvdXQsIGFyZ3MsIGNvbnRleHQsIHRpbWVzdGFtcCwgcmVzdWx0O1xuXG4gICAgdmFyIGxhdGVyID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgbGFzdCA9IF8ubm93KCkgLSB0aW1lc3RhbXA7XG4gICAgICBpZiAobGFzdCA8IHdhaXQpIHtcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQgLSBsYXN0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICBpZiAoIWltbWVkaWF0ZSkge1xuICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgICAgY29udGV4dCA9IGFyZ3MgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIGNvbnRleHQgPSB0aGlzO1xuICAgICAgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIHRpbWVzdGFtcCA9IF8ubm93KCk7XG4gICAgICB2YXIgY2FsbE5vdyA9IGltbWVkaWF0ZSAmJiAhdGltZW91dDtcbiAgICAgIGlmICghdGltZW91dCkge1xuICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgd2FpdCk7XG4gICAgICB9XG4gICAgICBpZiAoY2FsbE5vdykge1xuICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICBjb250ZXh0ID0gYXJncyA9IG51bGw7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCB3aWxsIGJlIGV4ZWN1dGVkIGF0IG1vc3Qgb25lIHRpbWUsIG5vIG1hdHRlciBob3dcbiAgLy8gb2Z0ZW4geW91IGNhbGwgaXQuIFVzZWZ1bCBmb3IgbGF6eSBpbml0aWFsaXphdGlvbi5cbiAgXy5vbmNlID0gZnVuY3Rpb24oZnVuYykge1xuICAgIHZhciByYW4gPSBmYWxzZSwgbWVtbztcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBpZiAocmFuKSByZXR1cm4gbWVtbztcbiAgICAgIHJhbiA9IHRydWU7XG4gICAgICBtZW1vID0gZnVuYy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgZnVuYyA9IG51bGw7XG4gICAgICByZXR1cm4gbWVtbztcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgdGhlIGZpcnN0IGZ1bmN0aW9uIHBhc3NlZCBhcyBhbiBhcmd1bWVudCB0byB0aGUgc2Vjb25kLFxuICAvLyBhbGxvd2luZyB5b3UgdG8gYWRqdXN0IGFyZ3VtZW50cywgcnVuIGNvZGUgYmVmb3JlIGFuZCBhZnRlciwgYW5kXG4gIC8vIGNvbmRpdGlvbmFsbHkgZXhlY3V0ZSB0aGUgb3JpZ2luYWwgZnVuY3Rpb24uXG4gIF8ud3JhcCA9IGZ1bmN0aW9uKGZ1bmMsIHdyYXBwZXIpIHtcbiAgICByZXR1cm4gXy5wYXJ0aWFsKHdyYXBwZXIsIGZ1bmMpO1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiB0aGF0IGlzIHRoZSBjb21wb3NpdGlvbiBvZiBhIGxpc3Qgb2YgZnVuY3Rpb25zLCBlYWNoXG4gIC8vIGNvbnN1bWluZyB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBmdW5jdGlvbiB0aGF0IGZvbGxvd3MuXG4gIF8uY29tcG9zZSA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciBmdW5jcyA9IGFyZ3VtZW50cztcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgIGZvciAodmFyIGkgPSBmdW5jcy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgICBhcmdzID0gW2Z1bmNzW2ldLmFwcGx5KHRoaXMsIGFyZ3MpXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBhcmdzWzBdO1xuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBvbmx5IGJlIGV4ZWN1dGVkIGFmdGVyIGJlaW5nIGNhbGxlZCBOIHRpbWVzLlxuICBfLmFmdGVyID0gZnVuY3Rpb24odGltZXMsIGZ1bmMpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBpZiAoLS10aW1lcyA8IDEpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIH1cbiAgICB9O1xuICB9O1xuXG4gIC8vIE9iamVjdCBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIFJldHJpZXZlIHRoZSBuYW1lcyBvZiBhbiBvYmplY3QncyBwcm9wZXJ0aWVzLlxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgT2JqZWN0LmtleXNgXG4gIF8ua2V5cyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmICghXy5pc09iamVjdChvYmopKSByZXR1cm4gW107XG4gICAgaWYgKG5hdGl2ZUtleXMpIHJldHVybiBuYXRpdmVLZXlzKG9iaik7XG4gICAgdmFyIGtleXMgPSBbXTtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSBpZiAoXy5oYXMob2JqLCBrZXkpKSBrZXlzLnB1c2goa2V5KTtcbiAgICByZXR1cm4ga2V5cztcbiAgfTtcblxuICAvLyBSZXRyaWV2ZSB0aGUgdmFsdWVzIG9mIGFuIG9iamVjdCdzIHByb3BlcnRpZXMuXG4gIF8udmFsdWVzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIGtleXMgPSBfLmtleXMob2JqKTtcbiAgICB2YXIgbGVuZ3RoID0ga2V5cy5sZW5ndGg7XG4gICAgdmFyIHZhbHVlcyA9IG5ldyBBcnJheShsZW5ndGgpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhbHVlc1tpXSA9IG9ialtrZXlzW2ldXTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlcztcbiAgfTtcblxuICAvLyBDb252ZXJ0IGFuIG9iamVjdCBpbnRvIGEgbGlzdCBvZiBgW2tleSwgdmFsdWVdYCBwYWlycy5cbiAgXy5wYWlycyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgIHZhciBwYWlycyA9IG5ldyBBcnJheShsZW5ndGgpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHBhaXJzW2ldID0gW2tleXNbaV0sIG9ialtrZXlzW2ldXV07XG4gICAgfVxuICAgIHJldHVybiBwYWlycztcbiAgfTtcblxuICAvLyBJbnZlcnQgdGhlIGtleXMgYW5kIHZhbHVlcyBvZiBhbiBvYmplY3QuIFRoZSB2YWx1ZXMgbXVzdCBiZSBzZXJpYWxpemFibGUuXG4gIF8uaW52ZXJ0ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHJlc3VsdFtvYmpba2V5c1tpXV1dID0ga2V5c1tpXTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBSZXR1cm4gYSBzb3J0ZWQgbGlzdCBvZiB0aGUgZnVuY3Rpb24gbmFtZXMgYXZhaWxhYmxlIG9uIHRoZSBvYmplY3QuXG4gIC8vIEFsaWFzZWQgYXMgYG1ldGhvZHNgXG4gIF8uZnVuY3Rpb25zID0gXy5tZXRob2RzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIG5hbWVzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgaWYgKF8uaXNGdW5jdGlvbihvYmpba2V5XSkpIG5hbWVzLnB1c2goa2V5KTtcbiAgICB9XG4gICAgcmV0dXJuIG5hbWVzLnNvcnQoKTtcbiAgfTtcblxuICAvLyBFeHRlbmQgYSBnaXZlbiBvYmplY3Qgd2l0aCBhbGwgdGhlIHByb3BlcnRpZXMgaW4gcGFzc2VkLWluIG9iamVjdChzKS5cbiAgXy5leHRlbmQgPSBmdW5jdGlvbihvYmopIHtcbiAgICBlYWNoKHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSwgZnVuY3Rpb24oc291cmNlKSB7XG4gICAgICBpZiAoc291cmNlKSB7XG4gICAgICAgIGZvciAodmFyIHByb3AgaW4gc291cmNlKSB7XG4gICAgICAgICAgb2JqW3Byb3BdID0gc291cmNlW3Byb3BdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG9iajtcbiAgfTtcblxuICAvLyBSZXR1cm4gYSBjb3B5IG9mIHRoZSBvYmplY3Qgb25seSBjb250YWluaW5nIHRoZSB3aGl0ZWxpc3RlZCBwcm9wZXJ0aWVzLlxuICBfLnBpY2sgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgY29weSA9IHt9O1xuICAgIHZhciBrZXlzID0gY29uY2F0LmFwcGx5KEFycmF5UHJvdG8sIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgZWFjaChrZXlzLCBmdW5jdGlvbihrZXkpIHtcbiAgICAgIGlmIChrZXkgaW4gb2JqKSBjb3B5W2tleV0gPSBvYmpba2V5XTtcbiAgICB9KTtcbiAgICByZXR1cm4gY29weTtcbiAgfTtcblxuICAgLy8gUmV0dXJuIGEgY29weSBvZiB0aGUgb2JqZWN0IHdpdGhvdXQgdGhlIGJsYWNrbGlzdGVkIHByb3BlcnRpZXMuXG4gIF8ub21pdCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBjb3B5ID0ge307XG4gICAgdmFyIGtleXMgPSBjb25jYXQuYXBwbHkoQXJyYXlQcm90bywgc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICBpZiAoIV8uY29udGFpbnMoa2V5cywga2V5KSkgY29weVtrZXldID0gb2JqW2tleV07XG4gICAgfVxuICAgIHJldHVybiBjb3B5O1xuICB9O1xuXG4gIC8vIEZpbGwgaW4gYSBnaXZlbiBvYmplY3Qgd2l0aCBkZWZhdWx0IHByb3BlcnRpZXMuXG4gIF8uZGVmYXVsdHMgPSBmdW5jdGlvbihvYmopIHtcbiAgICBlYWNoKHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSwgZnVuY3Rpb24oc291cmNlKSB7XG4gICAgICBpZiAoc291cmNlKSB7XG4gICAgICAgIGZvciAodmFyIHByb3AgaW4gc291cmNlKSB7XG4gICAgICAgICAgaWYgKG9ialtwcm9wXSA9PT0gdm9pZCAwKSBvYmpbcHJvcF0gPSBzb3VyY2VbcHJvcF07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gb2JqO1xuICB9O1xuXG4gIC8vIENyZWF0ZSBhIChzaGFsbG93LWNsb25lZCkgZHVwbGljYXRlIG9mIGFuIG9iamVjdC5cbiAgXy5jbG9uZSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmICghXy5pc09iamVjdChvYmopKSByZXR1cm4gb2JqO1xuICAgIHJldHVybiBfLmlzQXJyYXkob2JqKSA/IG9iai5zbGljZSgpIDogXy5leHRlbmQoe30sIG9iaik7XG4gIH07XG5cbiAgLy8gSW52b2tlcyBpbnRlcmNlcHRvciB3aXRoIHRoZSBvYmosIGFuZCB0aGVuIHJldHVybnMgb2JqLlxuICAvLyBUaGUgcHJpbWFyeSBwdXJwb3NlIG9mIHRoaXMgbWV0aG9kIGlzIHRvIFwidGFwIGludG9cIiBhIG1ldGhvZCBjaGFpbiwgaW5cbiAgLy8gb3JkZXIgdG8gcGVyZm9ybSBvcGVyYXRpb25zIG9uIGludGVybWVkaWF0ZSByZXN1bHRzIHdpdGhpbiB0aGUgY2hhaW4uXG4gIF8udGFwID0gZnVuY3Rpb24ob2JqLCBpbnRlcmNlcHRvcikge1xuICAgIGludGVyY2VwdG9yKG9iaik7XG4gICAgcmV0dXJuIG9iajtcbiAgfTtcblxuICAvLyBJbnRlcm5hbCByZWN1cnNpdmUgY29tcGFyaXNvbiBmdW5jdGlvbiBmb3IgYGlzRXF1YWxgLlxuICB2YXIgZXEgPSBmdW5jdGlvbihhLCBiLCBhU3RhY2ssIGJTdGFjaykge1xuICAgIC8vIElkZW50aWNhbCBvYmplY3RzIGFyZSBlcXVhbC4gYDAgPT09IC0wYCwgYnV0IHRoZXkgYXJlbid0IGlkZW50aWNhbC5cbiAgICAvLyBTZWUgdGhlIFtIYXJtb255IGBlZ2FsYCBwcm9wb3NhbF0oaHR0cDovL3dpa2kuZWNtYXNjcmlwdC5vcmcvZG9rdS5waHA/aWQ9aGFybW9ueTplZ2FsKS5cbiAgICBpZiAoYSA9PT0gYikgcmV0dXJuIGEgIT09IDAgfHwgMSAvIGEgPT0gMSAvIGI7XG4gICAgLy8gQSBzdHJpY3QgY29tcGFyaXNvbiBpcyBuZWNlc3NhcnkgYmVjYXVzZSBgbnVsbCA9PSB1bmRlZmluZWRgLlxuICAgIGlmIChhID09IG51bGwgfHwgYiA9PSBudWxsKSByZXR1cm4gYSA9PT0gYjtcbiAgICAvLyBVbndyYXAgYW55IHdyYXBwZWQgb2JqZWN0cy5cbiAgICBpZiAoYSBpbnN0YW5jZW9mIF8pIGEgPSBhLl93cmFwcGVkO1xuICAgIGlmIChiIGluc3RhbmNlb2YgXykgYiA9IGIuX3dyYXBwZWQ7XG4gICAgLy8gQ29tcGFyZSBgW1tDbGFzc11dYCBuYW1lcy5cbiAgICB2YXIgY2xhc3NOYW1lID0gdG9TdHJpbmcuY2FsbChhKTtcbiAgICBpZiAoY2xhc3NOYW1lICE9IHRvU3RyaW5nLmNhbGwoYikpIHJldHVybiBmYWxzZTtcbiAgICBzd2l0Y2ggKGNsYXNzTmFtZSkge1xuICAgICAgLy8gU3RyaW5ncywgbnVtYmVycywgZGF0ZXMsIGFuZCBib29sZWFucyBhcmUgY29tcGFyZWQgYnkgdmFsdWUuXG4gICAgICBjYXNlICdbb2JqZWN0IFN0cmluZ10nOlxuICAgICAgICAvLyBQcmltaXRpdmVzIGFuZCB0aGVpciBjb3JyZXNwb25kaW5nIG9iamVjdCB3cmFwcGVycyBhcmUgZXF1aXZhbGVudDsgdGh1cywgYFwiNVwiYCBpc1xuICAgICAgICAvLyBlcXVpdmFsZW50IHRvIGBuZXcgU3RyaW5nKFwiNVwiKWAuXG4gICAgICAgIHJldHVybiBhID09IFN0cmluZyhiKTtcbiAgICAgIGNhc2UgJ1tvYmplY3QgTnVtYmVyXSc6XG4gICAgICAgIC8vIGBOYU5gcyBhcmUgZXF1aXZhbGVudCwgYnV0IG5vbi1yZWZsZXhpdmUuIEFuIGBlZ2FsYCBjb21wYXJpc29uIGlzIHBlcmZvcm1lZCBmb3JcbiAgICAgICAgLy8gb3RoZXIgbnVtZXJpYyB2YWx1ZXMuXG4gICAgICAgIHJldHVybiBhICE9ICthID8gYiAhPSArYiA6IChhID09IDAgPyAxIC8gYSA9PSAxIC8gYiA6IGEgPT0gK2IpO1xuICAgICAgY2FzZSAnW29iamVjdCBEYXRlXSc6XG4gICAgICBjYXNlICdbb2JqZWN0IEJvb2xlYW5dJzpcbiAgICAgICAgLy8gQ29lcmNlIGRhdGVzIGFuZCBib29sZWFucyB0byBudW1lcmljIHByaW1pdGl2ZSB2YWx1ZXMuIERhdGVzIGFyZSBjb21wYXJlZCBieSB0aGVpclxuICAgICAgICAvLyBtaWxsaXNlY29uZCByZXByZXNlbnRhdGlvbnMuIE5vdGUgdGhhdCBpbnZhbGlkIGRhdGVzIHdpdGggbWlsbGlzZWNvbmQgcmVwcmVzZW50YXRpb25zXG4gICAgICAgIC8vIG9mIGBOYU5gIGFyZSBub3QgZXF1aXZhbGVudC5cbiAgICAgICAgcmV0dXJuICthID09ICtiO1xuICAgICAgLy8gUmVnRXhwcyBhcmUgY29tcGFyZWQgYnkgdGhlaXIgc291cmNlIHBhdHRlcm5zIGFuZCBmbGFncy5cbiAgICAgIGNhc2UgJ1tvYmplY3QgUmVnRXhwXSc6XG4gICAgICAgIHJldHVybiBhLnNvdXJjZSA9PSBiLnNvdXJjZSAmJlxuICAgICAgICAgICAgICAgYS5nbG9iYWwgPT0gYi5nbG9iYWwgJiZcbiAgICAgICAgICAgICAgIGEubXVsdGlsaW5lID09IGIubXVsdGlsaW5lICYmXG4gICAgICAgICAgICAgICBhLmlnbm9yZUNhc2UgPT0gYi5pZ25vcmVDYXNlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGEgIT0gJ29iamVjdCcgfHwgdHlwZW9mIGIgIT0gJ29iamVjdCcpIHJldHVybiBmYWxzZTtcbiAgICAvLyBBc3N1bWUgZXF1YWxpdHkgZm9yIGN5Y2xpYyBzdHJ1Y3R1cmVzLiBUaGUgYWxnb3JpdGhtIGZvciBkZXRlY3RpbmcgY3ljbGljXG4gICAgLy8gc3RydWN0dXJlcyBpcyBhZGFwdGVkIGZyb20gRVMgNS4xIHNlY3Rpb24gMTUuMTIuMywgYWJzdHJhY3Qgb3BlcmF0aW9uIGBKT2AuXG4gICAgdmFyIGxlbmd0aCA9IGFTdGFjay5sZW5ndGg7XG4gICAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgICAvLyBMaW5lYXIgc2VhcmNoLiBQZXJmb3JtYW5jZSBpcyBpbnZlcnNlbHkgcHJvcG9ydGlvbmFsIHRvIHRoZSBudW1iZXIgb2ZcbiAgICAgIC8vIHVuaXF1ZSBuZXN0ZWQgc3RydWN0dXJlcy5cbiAgICAgIGlmIChhU3RhY2tbbGVuZ3RoXSA9PSBhKSByZXR1cm4gYlN0YWNrW2xlbmd0aF0gPT0gYjtcbiAgICB9XG4gICAgLy8gT2JqZWN0cyB3aXRoIGRpZmZlcmVudCBjb25zdHJ1Y3RvcnMgYXJlIG5vdCBlcXVpdmFsZW50LCBidXQgYE9iamVjdGBzXG4gICAgLy8gZnJvbSBkaWZmZXJlbnQgZnJhbWVzIGFyZS5cbiAgICB2YXIgYUN0b3IgPSBhLmNvbnN0cnVjdG9yLCBiQ3RvciA9IGIuY29uc3RydWN0b3I7XG4gICAgaWYgKGFDdG9yICE9PSBiQ3RvciAmJiAhKF8uaXNGdW5jdGlvbihhQ3RvcikgJiYgKGFDdG9yIGluc3RhbmNlb2YgYUN0b3IpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIF8uaXNGdW5jdGlvbihiQ3RvcikgJiYgKGJDdG9yIGluc3RhbmNlb2YgYkN0b3IpKVxuICAgICAgICAgICAgICAgICAgICAgICAgJiYgKCdjb25zdHJ1Y3RvcicgaW4gYSAmJiAnY29uc3RydWN0b3InIGluIGIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIC8vIEFkZCB0aGUgZmlyc3Qgb2JqZWN0IHRvIHRoZSBzdGFjayBvZiB0cmF2ZXJzZWQgb2JqZWN0cy5cbiAgICBhU3RhY2sucHVzaChhKTtcbiAgICBiU3RhY2sucHVzaChiKTtcbiAgICB2YXIgc2l6ZSA9IDAsIHJlc3VsdCA9IHRydWU7XG4gICAgLy8gUmVjdXJzaXZlbHkgY29tcGFyZSBvYmplY3RzIGFuZCBhcnJheXMuXG4gICAgaWYgKGNsYXNzTmFtZSA9PSAnW29iamVjdCBBcnJheV0nKSB7XG4gICAgICAvLyBDb21wYXJlIGFycmF5IGxlbmd0aHMgdG8gZGV0ZXJtaW5lIGlmIGEgZGVlcCBjb21wYXJpc29uIGlzIG5lY2Vzc2FyeS5cbiAgICAgIHNpemUgPSBhLmxlbmd0aDtcbiAgICAgIHJlc3VsdCA9IHNpemUgPT0gYi5sZW5ndGg7XG4gICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgIC8vIERlZXAgY29tcGFyZSB0aGUgY29udGVudHMsIGlnbm9yaW5nIG5vbi1udW1lcmljIHByb3BlcnRpZXMuXG4gICAgICAgIHdoaWxlIChzaXplLS0pIHtcbiAgICAgICAgICBpZiAoIShyZXN1bHQgPSBlcShhW3NpemVdLCBiW3NpemVdLCBhU3RhY2ssIGJTdGFjaykpKSBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBEZWVwIGNvbXBhcmUgb2JqZWN0cy5cbiAgICAgIGZvciAodmFyIGtleSBpbiBhKSB7XG4gICAgICAgIGlmIChfLmhhcyhhLCBrZXkpKSB7XG4gICAgICAgICAgLy8gQ291bnQgdGhlIGV4cGVjdGVkIG51bWJlciBvZiBwcm9wZXJ0aWVzLlxuICAgICAgICAgIHNpemUrKztcbiAgICAgICAgICAvLyBEZWVwIGNvbXBhcmUgZWFjaCBtZW1iZXIuXG4gICAgICAgICAgaWYgKCEocmVzdWx0ID0gXy5oYXMoYiwga2V5KSAmJiBlcShhW2tleV0sIGJba2V5XSwgYVN0YWNrLCBiU3RhY2spKSkgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIEVuc3VyZSB0aGF0IGJvdGggb2JqZWN0cyBjb250YWluIHRoZSBzYW1lIG51bWJlciBvZiBwcm9wZXJ0aWVzLlxuICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICBmb3IgKGtleSBpbiBiKSB7XG4gICAgICAgICAgaWYgKF8uaGFzKGIsIGtleSkgJiYgIShzaXplLS0pKSBicmVhaztcbiAgICAgICAgfVxuICAgICAgICByZXN1bHQgPSAhc2l6ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gUmVtb3ZlIHRoZSBmaXJzdCBvYmplY3QgZnJvbSB0aGUgc3RhY2sgb2YgdHJhdmVyc2VkIG9iamVjdHMuXG4gICAgYVN0YWNrLnBvcCgpO1xuICAgIGJTdGFjay5wb3AoKTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFBlcmZvcm0gYSBkZWVwIGNvbXBhcmlzb24gdG8gY2hlY2sgaWYgdHdvIG9iamVjdHMgYXJlIGVxdWFsLlxuICBfLmlzRXF1YWwgPSBmdW5jdGlvbihhLCBiKSB7XG4gICAgcmV0dXJuIGVxKGEsIGIsIFtdLCBbXSk7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiBhcnJheSwgc3RyaW5nLCBvciBvYmplY3QgZW1wdHk/XG4gIC8vIEFuIFwiZW1wdHlcIiBvYmplY3QgaGFzIG5vIGVudW1lcmFibGUgb3duLXByb3BlcnRpZXMuXG4gIF8uaXNFbXB0eSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIHRydWU7XG4gICAgaWYgKF8uaXNBcnJheShvYmopIHx8IF8uaXNTdHJpbmcob2JqKSkgcmV0dXJuIG9iai5sZW5ndGggPT09IDA7XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikgaWYgKF8uaGFzKG9iaiwga2V5KSkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFsdWUgYSBET00gZWxlbWVudD9cbiAgXy5pc0VsZW1lbnQgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gISEob2JqICYmIG9iai5ub2RlVHlwZSA9PT0gMSk7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YWx1ZSBhbiBhcnJheT9cbiAgLy8gRGVsZWdhdGVzIHRvIEVDTUE1J3MgbmF0aXZlIEFycmF5LmlzQXJyYXlcbiAgXy5pc0FycmF5ID0gbmF0aXZlSXNBcnJheSB8fCBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09ICdbb2JqZWN0IEFycmF5XSc7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YXJpYWJsZSBhbiBvYmplY3Q/XG4gIF8uaXNPYmplY3QgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gb2JqID09PSBPYmplY3Qob2JqKTtcbiAgfTtcblxuICAvLyBBZGQgc29tZSBpc1R5cGUgbWV0aG9kczogaXNBcmd1bWVudHMsIGlzRnVuY3Rpb24sIGlzU3RyaW5nLCBpc051bWJlciwgaXNEYXRlLCBpc1JlZ0V4cC5cbiAgZWFjaChbJ0FyZ3VtZW50cycsICdGdW5jdGlvbicsICdTdHJpbmcnLCAnTnVtYmVyJywgJ0RhdGUnLCAnUmVnRXhwJ10sIGZ1bmN0aW9uKG5hbWUpIHtcbiAgICBfWydpcycgKyBuYW1lXSA9IGZ1bmN0aW9uKG9iaikge1xuICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PSAnW29iamVjdCAnICsgbmFtZSArICddJztcbiAgICB9O1xuICB9KTtcblxuICAvLyBEZWZpbmUgYSBmYWxsYmFjayB2ZXJzaW9uIG9mIHRoZSBtZXRob2QgaW4gYnJvd3NlcnMgKGFoZW0sIElFKSwgd2hlcmVcbiAgLy8gdGhlcmUgaXNuJ3QgYW55IGluc3BlY3RhYmxlIFwiQXJndW1lbnRzXCIgdHlwZS5cbiAgaWYgKCFfLmlzQXJndW1lbnRzKGFyZ3VtZW50cykpIHtcbiAgICBfLmlzQXJndW1lbnRzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gISEob2JqICYmIF8uaGFzKG9iaiwgJ2NhbGxlZScpKTtcbiAgICB9O1xuICB9XG5cbiAgLy8gT3B0aW1pemUgYGlzRnVuY3Rpb25gIGlmIGFwcHJvcHJpYXRlLlxuICBpZiAodHlwZW9mICgvLi8pICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgXy5pc0Z1bmN0aW9uID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gJ2Z1bmN0aW9uJztcbiAgICB9O1xuICB9XG5cbiAgLy8gSXMgYSBnaXZlbiBvYmplY3QgYSBmaW5pdGUgbnVtYmVyP1xuICBfLmlzRmluaXRlID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIGlzRmluaXRlKG9iaikgJiYgIWlzTmFOKHBhcnNlRmxvYXQob2JqKSk7XG4gIH07XG5cbiAgLy8gSXMgdGhlIGdpdmVuIHZhbHVlIGBOYU5gPyAoTmFOIGlzIHRoZSBvbmx5IG51bWJlciB3aGljaCBkb2VzIG5vdCBlcXVhbCBpdHNlbGYpLlxuICBfLmlzTmFOID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIF8uaXNOdW1iZXIob2JqKSAmJiBvYmogIT0gK29iajtcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhbHVlIGEgYm9vbGVhbj9cbiAgXy5pc0Jvb2xlYW4gPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gb2JqID09PSB0cnVlIHx8IG9iaiA9PT0gZmFsc2UgfHwgdG9TdHJpbmcuY2FsbChvYmopID09ICdbb2JqZWN0IEJvb2xlYW5dJztcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhbHVlIGVxdWFsIHRvIG51bGw/XG4gIF8uaXNOdWxsID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIG9iaiA9PT0gbnVsbDtcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhcmlhYmxlIHVuZGVmaW5lZD9cbiAgXy5pc1VuZGVmaW5lZCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBvYmogPT09IHZvaWQgMDtcbiAgfTtcblxuICAvLyBTaG9ydGN1dCBmdW5jdGlvbiBmb3IgY2hlY2tpbmcgaWYgYW4gb2JqZWN0IGhhcyBhIGdpdmVuIHByb3BlcnR5IGRpcmVjdGx5XG4gIC8vIG9uIGl0c2VsZiAoaW4gb3RoZXIgd29yZHMsIG5vdCBvbiBhIHByb3RvdHlwZSkuXG4gIF8uaGFzID0gZnVuY3Rpb24ob2JqLCBrZXkpIHtcbiAgICByZXR1cm4gaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGtleSk7XG4gIH07XG5cbiAgLy8gVXRpbGl0eSBGdW5jdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBSdW4gVW5kZXJzY29yZS5qcyBpbiAqbm9Db25mbGljdCogbW9kZSwgcmV0dXJuaW5nIHRoZSBgX2AgdmFyaWFibGUgdG8gaXRzXG4gIC8vIHByZXZpb3VzIG93bmVyLiBSZXR1cm5zIGEgcmVmZXJlbmNlIHRvIHRoZSBVbmRlcnNjb3JlIG9iamVjdC5cbiAgXy5ub0NvbmZsaWN0ID0gZnVuY3Rpb24oKSB7XG4gICAgcm9vdC5fID0gcHJldmlvdXNVbmRlcnNjb3JlO1xuICAgIHJldHVybiB0aGlzO1xuICB9O1xuXG4gIC8vIEtlZXAgdGhlIGlkZW50aXR5IGZ1bmN0aW9uIGFyb3VuZCBmb3IgZGVmYXVsdCBpdGVyYXRvcnMuXG4gIF8uaWRlbnRpdHkgPSBmdW5jdGlvbih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfTtcblxuICBfLmNvbnN0YW50ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH07XG4gIH07XG5cbiAgXy5wcm9wZXJ0eSA9IGZ1bmN0aW9uKGtleSkge1xuICAgIHJldHVybiBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiBvYmpba2V5XTtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBwcmVkaWNhdGUgZm9yIGNoZWNraW5nIHdoZXRoZXIgYW4gb2JqZWN0IGhhcyBhIGdpdmVuIHNldCBvZiBga2V5OnZhbHVlYCBwYWlycy5cbiAgXy5tYXRjaGVzID0gZnVuY3Rpb24oYXR0cnMpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ob2JqKSB7XG4gICAgICBpZiAob2JqID09PSBhdHRycykgcmV0dXJuIHRydWU7IC8vYXZvaWQgY29tcGFyaW5nIGFuIG9iamVjdCB0byBpdHNlbGYuXG4gICAgICBmb3IgKHZhciBrZXkgaW4gYXR0cnMpIHtcbiAgICAgICAgaWYgKGF0dHJzW2tleV0gIT09IG9ialtrZXldKVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfTtcblxuICAvLyBSdW4gYSBmdW5jdGlvbiAqKm4qKiB0aW1lcy5cbiAgXy50aW1lcyA9IGZ1bmN0aW9uKG4sIGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgdmFyIGFjY3VtID0gQXJyYXkoTWF0aC5tYXgoMCwgbikpO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSBhY2N1bVtpXSA9IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgaSk7XG4gICAgcmV0dXJuIGFjY3VtO1xuICB9O1xuXG4gIC8vIFJldHVybiBhIHJhbmRvbSBpbnRlZ2VyIGJldHdlZW4gbWluIGFuZCBtYXggKGluY2x1c2l2ZSkuXG4gIF8ucmFuZG9tID0gZnVuY3Rpb24obWluLCBtYXgpIHtcbiAgICBpZiAobWF4ID09IG51bGwpIHtcbiAgICAgIG1heCA9IG1pbjtcbiAgICAgIG1pbiA9IDA7XG4gICAgfVxuICAgIHJldHVybiBtaW4gKyBNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiAobWF4IC0gbWluICsgMSkpO1xuICB9O1xuXG4gIC8vIEEgKHBvc3NpYmx5IGZhc3Rlcikgd2F5IHRvIGdldCB0aGUgY3VycmVudCB0aW1lc3RhbXAgYXMgYW4gaW50ZWdlci5cbiAgXy5ub3cgPSBEYXRlLm5vdyB8fCBmdW5jdGlvbigpIHsgcmV0dXJuIG5ldyBEYXRlKCkuZ2V0VGltZSgpOyB9O1xuXG4gIC8vIExpc3Qgb2YgSFRNTCBlbnRpdGllcyBmb3IgZXNjYXBpbmcuXG4gIHZhciBlbnRpdHlNYXAgPSB7XG4gICAgZXNjYXBlOiB7XG4gICAgICAnJic6ICcmYW1wOycsXG4gICAgICAnPCc6ICcmbHQ7JyxcbiAgICAgICc+JzogJyZndDsnLFxuICAgICAgJ1wiJzogJyZxdW90OycsXG4gICAgICBcIidcIjogJyYjeDI3OydcbiAgICB9XG4gIH07XG4gIGVudGl0eU1hcC51bmVzY2FwZSA9IF8uaW52ZXJ0KGVudGl0eU1hcC5lc2NhcGUpO1xuXG4gIC8vIFJlZ2V4ZXMgY29udGFpbmluZyB0aGUga2V5cyBhbmQgdmFsdWVzIGxpc3RlZCBpbW1lZGlhdGVseSBhYm92ZS5cbiAgdmFyIGVudGl0eVJlZ2V4ZXMgPSB7XG4gICAgZXNjYXBlOiAgIG5ldyBSZWdFeHAoJ1snICsgXy5rZXlzKGVudGl0eU1hcC5lc2NhcGUpLmpvaW4oJycpICsgJ10nLCAnZycpLFxuICAgIHVuZXNjYXBlOiBuZXcgUmVnRXhwKCcoJyArIF8ua2V5cyhlbnRpdHlNYXAudW5lc2NhcGUpLmpvaW4oJ3wnKSArICcpJywgJ2cnKVxuICB9O1xuXG4gIC8vIEZ1bmN0aW9ucyBmb3IgZXNjYXBpbmcgYW5kIHVuZXNjYXBpbmcgc3RyaW5ncyB0by9mcm9tIEhUTUwgaW50ZXJwb2xhdGlvbi5cbiAgXy5lYWNoKFsnZXNjYXBlJywgJ3VuZXNjYXBlJ10sIGZ1bmN0aW9uKG1ldGhvZCkge1xuICAgIF9bbWV0aG9kXSA9IGZ1bmN0aW9uKHN0cmluZykge1xuICAgICAgaWYgKHN0cmluZyA9PSBudWxsKSByZXR1cm4gJyc7XG4gICAgICByZXR1cm4gKCcnICsgc3RyaW5nKS5yZXBsYWNlKGVudGl0eVJlZ2V4ZXNbbWV0aG9kXSwgZnVuY3Rpb24obWF0Y2gpIHtcbiAgICAgICAgcmV0dXJuIGVudGl0eU1hcFttZXRob2RdW21hdGNoXTtcbiAgICAgIH0pO1xuICAgIH07XG4gIH0pO1xuXG4gIC8vIElmIHRoZSB2YWx1ZSBvZiB0aGUgbmFtZWQgYHByb3BlcnR5YCBpcyBhIGZ1bmN0aW9uIHRoZW4gaW52b2tlIGl0IHdpdGggdGhlXG4gIC8vIGBvYmplY3RgIGFzIGNvbnRleHQ7IG90aGVyd2lzZSwgcmV0dXJuIGl0LlxuICBfLnJlc3VsdCA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHtcbiAgICBpZiAob2JqZWN0ID09IG51bGwpIHJldHVybiB2b2lkIDA7XG4gICAgdmFyIHZhbHVlID0gb2JqZWN0W3Byb3BlcnR5XTtcbiAgICByZXR1cm4gXy5pc0Z1bmN0aW9uKHZhbHVlKSA/IHZhbHVlLmNhbGwob2JqZWN0KSA6IHZhbHVlO1xuICB9O1xuXG4gIC8vIEFkZCB5b3VyIG93biBjdXN0b20gZnVuY3Rpb25zIHRvIHRoZSBVbmRlcnNjb3JlIG9iamVjdC5cbiAgXy5taXhpbiA9IGZ1bmN0aW9uKG9iaikge1xuICAgIGVhY2goXy5mdW5jdGlvbnMob2JqKSwgZnVuY3Rpb24obmFtZSkge1xuICAgICAgdmFyIGZ1bmMgPSBfW25hbWVdID0gb2JqW25hbWVdO1xuICAgICAgXy5wcm90b3R5cGVbbmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBbdGhpcy5fd3JhcHBlZF07XG4gICAgICAgIHB1c2guYXBwbHkoYXJncywgYXJndW1lbnRzKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdC5jYWxsKHRoaXMsIGZ1bmMuYXBwbHkoXywgYXJncykpO1xuICAgICAgfTtcbiAgICB9KTtcbiAgfTtcblxuICAvLyBHZW5lcmF0ZSBhIHVuaXF1ZSBpbnRlZ2VyIGlkICh1bmlxdWUgd2l0aGluIHRoZSBlbnRpcmUgY2xpZW50IHNlc3Npb24pLlxuICAvLyBVc2VmdWwgZm9yIHRlbXBvcmFyeSBET00gaWRzLlxuICB2YXIgaWRDb3VudGVyID0gMDtcbiAgXy51bmlxdWVJZCA9IGZ1bmN0aW9uKHByZWZpeCkge1xuICAgIHZhciBpZCA9ICsraWRDb3VudGVyICsgJyc7XG4gICAgcmV0dXJuIHByZWZpeCA/IHByZWZpeCArIGlkIDogaWQ7XG4gIH07XG5cbiAgLy8gQnkgZGVmYXVsdCwgVW5kZXJzY29yZSB1c2VzIEVSQi1zdHlsZSB0ZW1wbGF0ZSBkZWxpbWl0ZXJzLCBjaGFuZ2UgdGhlXG4gIC8vIGZvbGxvd2luZyB0ZW1wbGF0ZSBzZXR0aW5ncyB0byB1c2UgYWx0ZXJuYXRpdmUgZGVsaW1pdGVycy5cbiAgXy50ZW1wbGF0ZVNldHRpbmdzID0ge1xuICAgIGV2YWx1YXRlICAgIDogLzwlKFtcXHNcXFNdKz8pJT4vZyxcbiAgICBpbnRlcnBvbGF0ZSA6IC88JT0oW1xcc1xcU10rPyklPi9nLFxuICAgIGVzY2FwZSAgICAgIDogLzwlLShbXFxzXFxTXSs/KSU+L2dcbiAgfTtcblxuICAvLyBXaGVuIGN1c3RvbWl6aW5nIGB0ZW1wbGF0ZVNldHRpbmdzYCwgaWYgeW91IGRvbid0IHdhbnQgdG8gZGVmaW5lIGFuXG4gIC8vIGludGVycG9sYXRpb24sIGV2YWx1YXRpb24gb3IgZXNjYXBpbmcgcmVnZXgsIHdlIG5lZWQgb25lIHRoYXQgaXNcbiAgLy8gZ3VhcmFudGVlZCBub3QgdG8gbWF0Y2guXG4gIHZhciBub01hdGNoID0gLyguKV4vO1xuXG4gIC8vIENlcnRhaW4gY2hhcmFjdGVycyBuZWVkIHRvIGJlIGVzY2FwZWQgc28gdGhhdCB0aGV5IGNhbiBiZSBwdXQgaW50byBhXG4gIC8vIHN0cmluZyBsaXRlcmFsLlxuICB2YXIgZXNjYXBlcyA9IHtcbiAgICBcIidcIjogICAgICBcIidcIixcbiAgICAnXFxcXCc6ICAgICAnXFxcXCcsXG4gICAgJ1xccic6ICAgICAncicsXG4gICAgJ1xcbic6ICAgICAnbicsXG4gICAgJ1xcdCc6ICAgICAndCcsXG4gICAgJ1xcdTIwMjgnOiAndTIwMjgnLFxuICAgICdcXHUyMDI5JzogJ3UyMDI5J1xuICB9O1xuXG4gIHZhciBlc2NhcGVyID0gL1xcXFx8J3xcXHJ8XFxufFxcdHxcXHUyMDI4fFxcdTIwMjkvZztcblxuICAvLyBKYXZhU2NyaXB0IG1pY3JvLXRlbXBsYXRpbmcsIHNpbWlsYXIgdG8gSm9obiBSZXNpZydzIGltcGxlbWVudGF0aW9uLlxuICAvLyBVbmRlcnNjb3JlIHRlbXBsYXRpbmcgaGFuZGxlcyBhcmJpdHJhcnkgZGVsaW1pdGVycywgcHJlc2VydmVzIHdoaXRlc3BhY2UsXG4gIC8vIGFuZCBjb3JyZWN0bHkgZXNjYXBlcyBxdW90ZXMgd2l0aGluIGludGVycG9sYXRlZCBjb2RlLlxuICBfLnRlbXBsYXRlID0gZnVuY3Rpb24odGV4dCwgZGF0YSwgc2V0dGluZ3MpIHtcbiAgICB2YXIgcmVuZGVyO1xuICAgIHNldHRpbmdzID0gXy5kZWZhdWx0cyh7fSwgc2V0dGluZ3MsIF8udGVtcGxhdGVTZXR0aW5ncyk7XG5cbiAgICAvLyBDb21iaW5lIGRlbGltaXRlcnMgaW50byBvbmUgcmVndWxhciBleHByZXNzaW9uIHZpYSBhbHRlcm5hdGlvbi5cbiAgICB2YXIgbWF0Y2hlciA9IG5ldyBSZWdFeHAoW1xuICAgICAgKHNldHRpbmdzLmVzY2FwZSB8fCBub01hdGNoKS5zb3VyY2UsXG4gICAgICAoc2V0dGluZ3MuaW50ZXJwb2xhdGUgfHwgbm9NYXRjaCkuc291cmNlLFxuICAgICAgKHNldHRpbmdzLmV2YWx1YXRlIHx8IG5vTWF0Y2gpLnNvdXJjZVxuICAgIF0uam9pbignfCcpICsgJ3wkJywgJ2cnKTtcblxuICAgIC8vIENvbXBpbGUgdGhlIHRlbXBsYXRlIHNvdXJjZSwgZXNjYXBpbmcgc3RyaW5nIGxpdGVyYWxzIGFwcHJvcHJpYXRlbHkuXG4gICAgdmFyIGluZGV4ID0gMDtcbiAgICB2YXIgc291cmNlID0gXCJfX3ArPSdcIjtcbiAgICB0ZXh0LnJlcGxhY2UobWF0Y2hlciwgZnVuY3Rpb24obWF0Y2gsIGVzY2FwZSwgaW50ZXJwb2xhdGUsIGV2YWx1YXRlLCBvZmZzZXQpIHtcbiAgICAgIHNvdXJjZSArPSB0ZXh0LnNsaWNlKGluZGV4LCBvZmZzZXQpXG4gICAgICAgIC5yZXBsYWNlKGVzY2FwZXIsIGZ1bmN0aW9uKG1hdGNoKSB7IHJldHVybiAnXFxcXCcgKyBlc2NhcGVzW21hdGNoXTsgfSk7XG5cbiAgICAgIGlmIChlc2NhcGUpIHtcbiAgICAgICAgc291cmNlICs9IFwiJytcXG4oKF9fdD0oXCIgKyBlc2NhcGUgKyBcIikpPT1udWxsPycnOl8uZXNjYXBlKF9fdCkpK1xcbidcIjtcbiAgICAgIH1cbiAgICAgIGlmIChpbnRlcnBvbGF0ZSkge1xuICAgICAgICBzb3VyY2UgKz0gXCInK1xcbigoX190PShcIiArIGludGVycG9sYXRlICsgXCIpKT09bnVsbD8nJzpfX3QpK1xcbidcIjtcbiAgICAgIH1cbiAgICAgIGlmIChldmFsdWF0ZSkge1xuICAgICAgICBzb3VyY2UgKz0gXCInO1xcblwiICsgZXZhbHVhdGUgKyBcIlxcbl9fcCs9J1wiO1xuICAgICAgfVxuICAgICAgaW5kZXggPSBvZmZzZXQgKyBtYXRjaC5sZW5ndGg7XG4gICAgICByZXR1cm4gbWF0Y2g7XG4gICAgfSk7XG4gICAgc291cmNlICs9IFwiJztcXG5cIjtcblxuICAgIC8vIElmIGEgdmFyaWFibGUgaXMgbm90IHNwZWNpZmllZCwgcGxhY2UgZGF0YSB2YWx1ZXMgaW4gbG9jYWwgc2NvcGUuXG4gICAgaWYgKCFzZXR0aW5ncy52YXJpYWJsZSkgc291cmNlID0gJ3dpdGgob2JqfHx7fSl7XFxuJyArIHNvdXJjZSArICd9XFxuJztcblxuICAgIHNvdXJjZSA9IFwidmFyIF9fdCxfX3A9JycsX19qPUFycmF5LnByb3RvdHlwZS5qb2luLFwiICtcbiAgICAgIFwicHJpbnQ9ZnVuY3Rpb24oKXtfX3ArPV9fai5jYWxsKGFyZ3VtZW50cywnJyk7fTtcXG5cIiArXG4gICAgICBzb3VyY2UgKyBcInJldHVybiBfX3A7XFxuXCI7XG5cbiAgICB0cnkge1xuICAgICAgcmVuZGVyID0gbmV3IEZ1bmN0aW9uKHNldHRpbmdzLnZhcmlhYmxlIHx8ICdvYmonLCAnXycsIHNvdXJjZSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgZS5zb3VyY2UgPSBzb3VyY2U7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cblxuICAgIGlmIChkYXRhKSByZXR1cm4gcmVuZGVyKGRhdGEsIF8pO1xuICAgIHZhciB0ZW1wbGF0ZSA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgIHJldHVybiByZW5kZXIuY2FsbCh0aGlzLCBkYXRhLCBfKTtcbiAgICB9O1xuXG4gICAgLy8gUHJvdmlkZSB0aGUgY29tcGlsZWQgZnVuY3Rpb24gc291cmNlIGFzIGEgY29udmVuaWVuY2UgZm9yIHByZWNvbXBpbGF0aW9uLlxuICAgIHRlbXBsYXRlLnNvdXJjZSA9ICdmdW5jdGlvbignICsgKHNldHRpbmdzLnZhcmlhYmxlIHx8ICdvYmonKSArICcpe1xcbicgKyBzb3VyY2UgKyAnfSc7XG5cbiAgICByZXR1cm4gdGVtcGxhdGU7XG4gIH07XG5cbiAgLy8gQWRkIGEgXCJjaGFpblwiIGZ1bmN0aW9uLCB3aGljaCB3aWxsIGRlbGVnYXRlIHRvIHRoZSB3cmFwcGVyLlxuICBfLmNoYWluID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIF8ob2JqKS5jaGFpbigpO1xuICB9O1xuXG4gIC8vIE9PUFxuICAvLyAtLS0tLS0tLS0tLS0tLS1cbiAgLy8gSWYgVW5kZXJzY29yZSBpcyBjYWxsZWQgYXMgYSBmdW5jdGlvbiwgaXQgcmV0dXJucyBhIHdyYXBwZWQgb2JqZWN0IHRoYXRcbiAgLy8gY2FuIGJlIHVzZWQgT08tc3R5bGUuIFRoaXMgd3JhcHBlciBob2xkcyBhbHRlcmVkIHZlcnNpb25zIG9mIGFsbCB0aGVcbiAgLy8gdW5kZXJzY29yZSBmdW5jdGlvbnMuIFdyYXBwZWQgb2JqZWN0cyBtYXkgYmUgY2hhaW5lZC5cblxuICAvLyBIZWxwZXIgZnVuY3Rpb24gdG8gY29udGludWUgY2hhaW5pbmcgaW50ZXJtZWRpYXRlIHJlc3VsdHMuXG4gIHZhciByZXN1bHQgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gdGhpcy5fY2hhaW4gPyBfKG9iaikuY2hhaW4oKSA6IG9iajtcbiAgfTtcblxuICAvLyBBZGQgYWxsIG9mIHRoZSBVbmRlcnNjb3JlIGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlciBvYmplY3QuXG4gIF8ubWl4aW4oXyk7XG5cbiAgLy8gQWRkIGFsbCBtdXRhdG9yIEFycmF5IGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlci5cbiAgZWFjaChbJ3BvcCcsICdwdXNoJywgJ3JldmVyc2UnLCAnc2hpZnQnLCAnc29ydCcsICdzcGxpY2UnLCAndW5zaGlmdCddLCBmdW5jdGlvbihuYW1lKSB7XG4gICAgdmFyIG1ldGhvZCA9IEFycmF5UHJvdG9bbmFtZV07XG4gICAgXy5wcm90b3R5cGVbbmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgIHZhciBvYmogPSB0aGlzLl93cmFwcGVkO1xuICAgICAgbWV0aG9kLmFwcGx5KG9iaiwgYXJndW1lbnRzKTtcbiAgICAgIGlmICgobmFtZSA9PSAnc2hpZnQnIHx8IG5hbWUgPT0gJ3NwbGljZScpICYmIG9iai5sZW5ndGggPT09IDApIGRlbGV0ZSBvYmpbMF07XG4gICAgICByZXR1cm4gcmVzdWx0LmNhbGwodGhpcywgb2JqKTtcbiAgICB9O1xuICB9KTtcblxuICAvLyBBZGQgYWxsIGFjY2Vzc29yIEFycmF5IGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlci5cbiAgZWFjaChbJ2NvbmNhdCcsICdqb2luJywgJ3NsaWNlJ10sIGZ1bmN0aW9uKG5hbWUpIHtcbiAgICB2YXIgbWV0aG9kID0gQXJyYXlQcm90b1tuYW1lXTtcbiAgICBfLnByb3RvdHlwZVtuYW1lXSA9IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHJlc3VsdC5jYWxsKHRoaXMsIG1ldGhvZC5hcHBseSh0aGlzLl93cmFwcGVkLCBhcmd1bWVudHMpKTtcbiAgICB9O1xuICB9KTtcblxuICBfLmV4dGVuZChfLnByb3RvdHlwZSwge1xuXG4gICAgLy8gU3RhcnQgY2hhaW5pbmcgYSB3cmFwcGVkIFVuZGVyc2NvcmUgb2JqZWN0LlxuICAgIGNoYWluOiBmdW5jdGlvbigpIHtcbiAgICAgIHRoaXMuX2NoYWluID0gdHJ1ZTtcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICAvLyBFeHRyYWN0cyB0aGUgcmVzdWx0IGZyb20gYSB3cmFwcGVkIGFuZCBjaGFpbmVkIG9iamVjdC5cbiAgICB2YWx1ZTogZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gdGhpcy5fd3JhcHBlZDtcbiAgICB9XG5cbiAgfSk7XG5cbiAgLy8gQU1EIHJlZ2lzdHJhdGlvbiBoYXBwZW5zIGF0IHRoZSBlbmQgZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBBTUQgbG9hZGVyc1xuICAvLyB0aGF0IG1heSBub3QgZW5mb3JjZSBuZXh0LXR1cm4gc2VtYW50aWNzIG9uIG1vZHVsZXMuIEV2ZW4gdGhvdWdoIGdlbmVyYWxcbiAgLy8gcHJhY3RpY2UgZm9yIEFNRCByZWdpc3RyYXRpb24gaXMgdG8gYmUgYW5vbnltb3VzLCB1bmRlcnNjb3JlIHJlZ2lzdGVyc1xuICAvLyBhcyBhIG5hbWVkIG1vZHVsZSBiZWNhdXNlLCBsaWtlIGpRdWVyeSwgaXQgaXMgYSBiYXNlIGxpYnJhcnkgdGhhdCBpc1xuICAvLyBwb3B1bGFyIGVub3VnaCB0byBiZSBidW5kbGVkIGluIGEgdGhpcmQgcGFydHkgbGliLCBidXQgbm90IGJlIHBhcnQgb2ZcbiAgLy8gYW4gQU1EIGxvYWQgcmVxdWVzdC4gVGhvc2UgY2FzZXMgY291bGQgZ2VuZXJhdGUgYW4gZXJyb3Igd2hlbiBhblxuICAvLyBhbm9ueW1vdXMgZGVmaW5lKCkgaXMgY2FsbGVkIG91dHNpZGUgb2YgYSBsb2FkZXIgcmVxdWVzdC5cbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgIGRlZmluZSgndW5kZXJzY29yZScsIFtdLCBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBfO1xuICAgIH0pO1xuICB9XG59KS5jYWxsKHRoaXMpO1xuIl19 diff --git a/build/browser/Connectors/TestConnector.min.js b/build/browser/Connectors/TestConnector.min.js new file mode 100644 index 00000000..4886a389 --- /dev/null +++ b/build/browser/Connectors/TestConnector.min.js @@ -0,0 +1 @@ +!function n(t,r,e){function u(o,a){if(!r[o]){if(!t[o]){var c="function"==typeof require&&require;if(!a&&c)return c(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var l=r[o]={exports:{}};t[o][0].call(l.exports,function(n){var r=t[o][1][n];return u(r?r:n)},l,l.exports,n,t,r,e)}return r[o].exports}for(var i="function"==typeof require&&require,o=0;oe;e++)r=n[e],i.push(r.getUserId()!==this.HB.getUserId()?r.getConnector().receive(t):void 0);return i}},t.prototype.receive=function(n){var t,r;return null==(t=this.unexecuted)[r=n.uid.creator]&&(t[r]=[]),this.unexecuted[n.uid.creator].push(n)},t.prototype.flushOne=function(n){var t;return(null!=(t=this.unexecuted[n])?t.length:void 0)>0?this.engine.applyOp(this.unexecuted[n].shift()):void 0},t.prototype.flushOneRandom=function(){return this.flushOne(r.random(0,n.length-1))},t.prototype.flushAll=function(){var n,t,r;r=this.unexecuted;for(n in r)t=r[n],this.engine.applyOps(t);return this.unexecuted={}},t}()}},{underscore:2}],2:[function(n,t,r){(function(){var n=this,e=n._,u={},i=Array.prototype,o=Object.prototype,a=Function.prototype,c=i.push,l=i.slice,f=i.concat,s=o.toString,p=o.hasOwnProperty,h=i.forEach,v=i.map,d=i.reduce,g=i.reduceRight,y=i.filter,m=i.every,x=i.some,_=i.indexOf,b=i.lastIndexOf,w=Array.isArray,j=Object.keys,O=a.bind,A=function(n){return n instanceof A?n:this instanceof A?void(this._wrapped=n):new A(n)};"undefined"!=typeof r?("undefined"!=typeof t&&t.exports&&(r=t.exports=A),r._=A):n._=A,A.VERSION="1.6.0";var k=A.each=A.forEach=function(n,t,r){if(null==n)return n;if(h&&n.forEach===h)n.forEach(t,r);else if(n.length===+n.length){for(var e=0,i=n.length;i>e;e++)if(t.call(r,n[e],e,n)===u)return}else for(var o=A.keys(n),e=0,i=o.length;i>e;e++)if(t.call(r,n[o[e]],o[e],n)===u)return;return n};A.map=A.collect=function(n,t,r){var e=[];return null==n?e:v&&n.map===v?n.map(t,r):(k(n,function(n,u,i){e.push(t.call(r,n,u,i))}),e)};var E="Reduce of empty array with no initial value";A.reduce=A.foldl=A.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),d&&n.reduce===d)return e&&(t=A.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(k(n,function(n,i,o){u?r=t.call(e,r,n,i,o):(r=n,u=!0)}),!u)throw new TypeError(E);return r},A.reduceRight=A.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),g&&n.reduceRight===g)return e&&(t=A.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var o=A.keys(n);i=o.length}if(k(n,function(a,c,l){c=o?o[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(E);return r},A.find=A.detect=function(n,t,r){var e;return F(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},A.filter=A.select=function(n,t,r){var e=[];return null==n?e:y&&n.filter===y?n.filter(t,r):(k(n,function(n,u,i){t.call(r,n,u,i)&&e.push(n)}),e)},A.reject=function(n,t,r){return A.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},A.every=A.all=function(n,t,r){t||(t=A.identity);var e=!0;return null==n?e:m&&n.every===m?n.every(t,r):(k(n,function(n,i,o){return(e=e&&t.call(r,n,i,o))?void 0:u}),!!e)};var F=A.some=A.any=function(n,t,r){t||(t=A.identity);var e=!1;return null==n?e:x&&n.some===x?n.some(t,r):(k(n,function(n,i,o){return e||(e=t.call(r,n,i,o))?u:void 0}),!!e)};A.contains=A.include=function(n,t){return null==n?!1:_&&n.indexOf===_?-1!=n.indexOf(t):F(n,function(n){return n===t})},A.invoke=function(n,t){var r=l.call(arguments,2),e=A.isFunction(t);return A.map(n,function(n){return(e?t:n[t]).apply(n,r)})},A.pluck=function(n,t){return A.map(n,A.property(t))},A.where=function(n,t){return A.filter(n,A.matches(t))},A.findWhere=function(n,t){return A.find(n,A.matches(t))},A.max=function(n,t,r){if(!t&&A.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.max.apply(Math,n);var e=-1/0,u=-1/0;return k(n,function(n,i,o){var a=t?t.call(r,n,i,o):n;a>u&&(e=n,u=a)}),e},A.min=function(n,t,r){if(!t&&A.isArray(n)&&n[0]===+n[0]&&n.length<65535)return Math.min.apply(Math,n);var e=1/0,u=1/0;return k(n,function(n,i,o){var a=t?t.call(r,n,i,o):n;u>a&&(e=n,u=a)}),e},A.shuffle=function(n){var t,r=0,e=[];return k(n,function(n){t=A.random(r++),e[r-1]=e[t],e[t]=n}),e},A.sample=function(n,t,r){return null==t||r?(n.length!==+n.length&&(n=A.values(n)),n[A.random(n.length-1)]):A.shuffle(n).slice(0,Math.max(0,t))};var I=function(n){return null==n?A.identity:A.isFunction(n)?n:A.property(n)};A.sortBy=function(n,t,r){return t=I(t),A.pluck(A.map(n,function(n,e,u){return{value:n,index:e,criteria:t.call(r,n,e,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||void 0===r)return 1;if(e>r||void 0===e)return-1}return n.index-t.index}),"value")};var R=function(n){return function(t,r,e){var u={};return r=I(r),k(t,function(i,o){var a=r.call(e,i,o,t);n(u,a,i)}),u}};A.groupBy=R(function(n,t,r){A.has(n,t)?n[t].push(r):n[t]=[r]}),A.indexBy=R(function(n,t,r){n[t]=r}),A.countBy=R(function(n,t){A.has(n,t)?n[t]++:n[t]=1}),A.sortedIndex=function(n,t,r,e){r=I(r);for(var u=r.call(e,t),i=0,o=n.length;o>i;){var a=i+o>>>1;r.call(e,n[a])t?[]:l.call(n,0,t)},A.initial=function(n,t,r){return l.call(n,0,n.length-(null==t||r?1:t))},A.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:l.call(n,Math.max(n.length-t,0))},A.rest=A.tail=A.drop=function(n,t,r){return l.call(n,null==t||r?1:t)},A.compact=function(n){return A.filter(n,A.identity)};var M=function(n,t,r){return t&&A.every(n,A.isArray)?f.apply(r,n):(k(n,function(n){A.isArray(n)||A.isArguments(n)?t?c.apply(r,n):M(n,t,r):r.push(n)}),r)};A.flatten=function(n,t){return M(n,t,[])},A.without=function(n){return A.difference(n,l.call(arguments,1))},A.partition=function(n,t){var r=[],e=[];return k(n,function(n){(t(n)?r:e).push(n)}),[r,e]},A.uniq=A.unique=function(n,t,r,e){A.isFunction(t)&&(e=r,r=t,t=!1);var u=r?A.map(n,r,e):n,i=[],o=[];return k(u,function(r,e){(t?e&&o[o.length-1]===r:A.contains(o,r))||(o.push(r),i.push(n[e]))}),i},A.union=function(){return A.uniq(A.flatten(arguments,!0))},A.intersection=function(n){var t=l.call(arguments,1);return A.filter(A.uniq(n),function(n){return A.every(t,function(t){return A.contains(t,n)})})},A.difference=function(n){var t=f.apply(i,l.call(arguments,1));return A.filter(n,function(n){return!A.contains(t,n)})},A.zip=function(){for(var n=A.max(A.pluck(arguments,"length").concat(0)),t=new Array(n),r=0;n>r;r++)t[r]=A.pluck(arguments,""+r);return t},A.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},A.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=A.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(_&&n.indexOf===_)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},A.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},A.range=function(n,t,r){arguments.length<=1&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=new Array(e);e>u;)i[u++]=n,n+=r;return i};var q=function(){};A.bind=function(n,t){var r,e;if(O&&n.bind===O)return O.apply(n,l.call(arguments,1));if(!A.isFunction(n))throw new TypeError;return r=l.call(arguments,2),e=function(){if(!(this instanceof e))return n.apply(t,r.concat(l.call(arguments)));q.prototype=n.prototype;var u=new q;q.prototype=null;var i=n.apply(u,r.concat(l.call(arguments)));return Object(i)===i?i:u}},A.partial=function(n){var t=l.call(arguments,1);return function(){for(var r=0,e=t.slice(),u=0,i=e.length;i>u;u++)e[u]===A&&(e[u]=arguments[r++]);for(;r=f?(clearTimeout(o),o=null,a=l,i=n.apply(e,u),e=u=null):o||r.trailing===!1||(o=setTimeout(c,f)),i}},A.debounce=function(n,t,r){var e,u,i,o,a,c=function(){var l=A.now()-o;t>l?e=setTimeout(c,t-l):(e=null,r||(a=n.apply(i,u),i=u=null))};return function(){i=this,u=arguments,o=A.now();var l=r&&!e;return e||(e=setTimeout(c,t)),l&&(a=n.apply(i,u),i=u=null),a}},A.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},A.wrap=function(n,t){return A.partial(t,n)},A.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},A.after=function(n,t){return function(){return--n<1?t.apply(this,arguments):void 0}},A.keys=function(n){if(!A.isObject(n))return[];if(j)return j(n);var t=[];for(var r in n)A.has(n,r)&&t.push(r);return t},A.values=function(n){for(var t=A.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=n[t[u]];return e},A.pairs=function(n){for(var t=A.keys(n),r=t.length,e=new Array(r),u=0;r>u;u++)e[u]=[t[u],n[t[u]]];return e},A.invert=function(n){for(var t={},r=A.keys(n),e=0,u=r.length;u>e;e++)t[n[r[e]]]=r[e];return t},A.functions=A.methods=function(n){var t=[];for(var r in n)A.isFunction(n[r])&&t.push(r);return t.sort()},A.extend=function(n){return k(l.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},A.pick=function(n){var t={},r=f.apply(i,l.call(arguments,1));return k(r,function(r){r in n&&(t[r]=n[r])}),t},A.omit=function(n){var t={},r=f.apply(i,l.call(arguments,1));for(var e in n)A.contains(r,e)||(t[e]=n[e]);return t},A.defaults=function(n){return k(l.call(arguments,1),function(t){if(t)for(var r in t)void 0===n[r]&&(n[r]=t[r])}),n},A.clone=function(n){return A.isObject(n)?A.isArray(n)?n.slice():A.extend({},n):n},A.tap=function(n,t){return t(n),n};var B=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof A&&(n=n._wrapped),t instanceof A&&(t=t._wrapped);var u=s.call(n);if(u!=s.call(t))return!1;switch(u){case"[object String]":return n==String(t);case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;var o=n.constructor,a=t.constructor;if(o!==a&&!(A.isFunction(o)&&o instanceof o&&A.isFunction(a)&&a instanceof a)&&"constructor"in n&&"constructor"in t)return!1;r.push(n),e.push(t);var c=0,l=!0;if("[object Array]"==u){if(c=n.length,l=c==t.length)for(;c--&&(l=B(n[c],t[c],r,e)););}else{for(var f in n)if(A.has(n,f)&&(c++,!(l=A.has(t,f)&&B(n[f],t[f],r,e))))break;if(l){for(f in t)if(A.has(t,f)&&!c--)break;l=!c}}return r.pop(),e.pop(),l};A.isEqual=function(n,t){return B(n,t,[],[])},A.isEmpty=function(n){if(null==n)return!0;if(A.isArray(n)||A.isString(n))return 0===n.length;for(var t in n)if(A.has(n,t))return!1;return!0},A.isElement=function(n){return!(!n||1!==n.nodeType)},A.isArray=w||function(n){return"[object Array]"==s.call(n)},A.isObject=function(n){return n===Object(n)},k(["Arguments","Function","String","Number","Date","RegExp"],function(n){A["is"+n]=function(t){return s.call(t)=="[object "+n+"]"}}),A.isArguments(arguments)||(A.isArguments=function(n){return!(!n||!A.has(n,"callee"))}),"function"!=typeof/./&&(A.isFunction=function(n){return"function"==typeof n}),A.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},A.isNaN=function(n){return A.isNumber(n)&&n!=+n},A.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==s.call(n)},A.isNull=function(n){return null===n},A.isUndefined=function(n){return void 0===n},A.has=function(n,t){return p.call(n,t)},A.noConflict=function(){return n._=e,this},A.identity=function(n){return n},A.constant=function(n){return function(){return n}},A.property=function(n){return function(t){return t[n]}},A.matches=function(n){return function(t){if(t===n)return!0;for(var r in n)if(n[r]!==t[r])return!1;return!0}},A.times=function(n,t,r){for(var e=Array(Math.max(0,n)),u=0;n>u;u++)e[u]=t.call(r,u);return e},A.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))},A.now=Date.now||function(){return(new Date).getTime()};var S={escape:{"&":"&","<":"<",">":">",'"':""","'":"'"}};S.unescape=A.invert(S.escape);var T={escape:new RegExp("["+A.keys(S.escape).join("")+"]","g"),unescape:new RegExp("("+A.keys(S.unescape).join("|")+")","g")};A.each(["escape","unescape"],function(n){A[n]=function(t){return null==t?"":(""+t).replace(T[n],function(t){return S[n][t]})}}),A.result=function(n,t){if(null==n)return void 0;var r=n[t];return A.isFunction(r)?r.call(n):r},A.mixin=function(n){k(A.functions(n),function(t){var r=A[t]=n[t];A.prototype[t]=function(){var n=[this._wrapped];return c.apply(n,arguments),U.call(this,r.apply(A,n))}})};var N=0;A.uniqueId=function(n){var t=++N+"";return n?n+t:t},A.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var C=/(.)^/,D={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},H=/\\|'|\r|\n|\t|\u2028|\u2029/g;A.template=function(n,t,r){var e;r=A.defaults({},r,A.templateSettings);var u=new RegExp([(r.escape||C).source,(r.interpolate||C).source,(r.evaluate||C).source].join("|")+"|$","g"),i=0,o="__p+='";n.replace(u,function(t,r,e,u,a){return o+=n.slice(i,a).replace(H,function(n){return"\\"+D[n]}),r&&(o+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(o+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(o+="';\n"+u+"\n__p+='"),i=a+t.length,t}),o+="';\n",r.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{e=new Function(r.variable||"obj","_",o)}catch(a){throw a.source=o,a}if(t)return e(t,A);var c=function(n){return e.call(this,n,A)};return c.source="function("+(r.variable||"obj")+"){\n"+o+"}",c},A.chain=function(n){return A(n).chain()};var U=function(n){return this._chain?A(n).chain():n};A.mixin(A),k(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=i[n];A.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],U.call(this,r)}}),k(["concat","join","slice"],function(n){var t=i[n];A.prototype[n]=function(){return U.call(this,t.apply(this._wrapped,arguments))}}),A.extend(A.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}}),"function"==typeof define&&define.amd&&define("underscore",[],function(){return A})}).call(this)},{}]},{},[1]); \ No newline at end of file diff --git a/build/browser/Engine.js b/build/browser/Engine.js new file mode 100644 index 00000000..5b70f7fd --- /dev/null +++ b/build/browser/Engine.js @@ -0,0 +1,110 @@ +(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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;oo;o++)e=r[o],t.push(this.parseOperation(e));for(p=0,i=t.length;i>p;p++)e=t[p],this.HB.addOperation(e);for(n=0,u=t.length;u>n;n++)e=t[n],e.execute()||this.unprocessed_ops.push(e);return this.tryUnprocessed()},r.prototype.applyOpsCheckDouble=function(r){var e,t,o,p;for(p=[],t=0,o=r.length;o>t;t++)e=r[t],p.push(null!=this.HB.getOperation(e.uid)?this.applyOp(e):void 0);return p},r.prototype.applyOps=function(r){var e,t,o,p;for(p=[],t=0,o=r.length;o>t;t++)e=r[t],p.push(this.applyOp(e));return p},r.prototype.applyOp=function(r){var e;return e=this.parseOperation(r),this.HB.addToCounter(e),e.execute()?this.HB.addOperation(e):this.unprocessed_ops.push(e),this.tryUnprocessed()},r.prototype.tryUnprocessed=function(){var r,e,t,o,p,n,s;for(s=[];;){for(r=this.unprocessed_ops.length,t=[],n=this.unprocessed_ops,o=0,p=n.length;p>o;o++)e=n[o],e.execute()?this.HB.addOperation(e):t.push(e);if(this.unprocessed_ops=t,this.unprocessed_ops.length===r)break;s.push(void 0)}return s},r}(),e.exports=t},{}]},{},[1]); \ No newline at end of file diff --git a/build/browser/Frameworks/JsonYatta.js b/build/browser/Frameworks/JsonYatta.js new file mode 100644 index 00000000..62706747 --- /dev/null +++ b/build/browser/Frameworks/JsonYatta.js @@ -0,0 +1,1298 @@ +(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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0; + }; + + Insert.prototype.getDistanceToOrigin = function() { + var d, o; + d = 0; + o = this.prev_cl; + while (true) { + if (this.origin === o) { + break; + } + d++; + if (this === this.prev_cl) { + throw new Error("this should not happen ;) "); + } + o = o.prev_cl; + } + return d; + }; + + Insert.prototype.update_sl = function() { + var o; + o = this.prev_cl; + ({ + update: function(dest_cl, dest_sl) { + var _results; + _results = []; + while (true) { + if (o.isDeleted()) { + _results.push(o = o[dest_cl]); + } else { + this[dest_sl] = o; + break; + } + } + return _results; + } + }); + update("prev_cl", "prev_sl"); + return update("next_cl", "prev_sl"); + }; + + Insert.prototype.execute = function() { + var distance_to_origin, i, o, _ref, _ref1; + if (this.is_executed != null) { + return this; + } + if (!this.validateSavedOperations()) { + return false; + } else { + if (((_ref = this.prev_cl) != null ? _ref.validateSavedOperations() : void 0) && ((_ref1 = this.next_cl) != null ? _ref1.validateSavedOperations() : void 0) && this.prev_cl.next_cl !== this) { + distance_to_origin = 0; + o = this.prev_cl.next_cl; + i = 0; + while (true) { + if (o == null) { + console.log(JSON.stringify(this.prev_cl.getUid())); + console.log(JSON.stringify(this.next_cl.getUid())); + } + if (o !== this.next_cl) { + if (o.getDistanceToOrigin() === i) { + if (o.creator < this.creator) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else if (o.getDistanceToOrigin() < i) { + if (i - distance_to_origin <= o.getDistanceToOrigin()) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else { + break; + } + i++; + o = o.next_cl; + } else { + break; + } + } + this.next_cl = this.prev_cl.next_cl; + this.prev_cl.next_cl = this; + this.next_cl.prev_cl = this; + } + Insert.__super__.execute.apply(this, arguments); + return this; + } + }; + + return Insert; + + })(Operation); + ImmutableObject = (function(_super) { + __extends(ImmutableObject, _super); + + function ImmutableObject(uid, content, prev, next, origin) { + this.content = content; + ImmutableObject.__super__.constructor.call(this, uid, prev, next, origin); + } + + ImmutableObject.prototype.val = function() { + return this.content; + }; + + ImmutableObject.prototype._encode = function() { + var json; + json = { + 'type': "ImmutableObject", + 'uid': this.getUid(), + 'content': this.content + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ImmutableObject; + + })(Insert); + parser['ImmutableObject'] = function(json) { + var content, next, origin, prev, uid; + uid = json['uid'], content = json['content'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new ImmutableObject(uid, content, prev, next, origin); + }; + Delimiter = (function(_super) { + __extends(Delimiter, _super); + + function Delimiter(uid, prev_cl, next_cl, origin) { + this.saveOperation('prev_cl', prev_cl); + this.saveOperation('next_cl', next_cl); + this.saveOperation('origin', prev_cl); + Delimiter.__super__.constructor.call(this, uid); + } + + Delimiter.prototype.isDeleted = function() { + return false; + }; + + Delimiter.prototype.execute = function() { + var _ref, _ref1; + if (((_ref = this.unchecked) != null ? _ref['next_cl'] : void 0) != null) { + return Delimiter.__super__.execute.apply(this, arguments); + } else if ((_ref1 = this.unchecked) != null ? _ref1['prev_cl'] : void 0) { + if (this.validateSavedOperations()) { + if (this.prev_cl.next_cl != null) { + throw new Error("Probably duplicated operations"); + } + this.prev_cl.next_cl = this; + delete this.prev_cl.unchecked.next_cl; + return Delimiter.__super__.execute.apply(this, arguments); + } else { + return false; + } + } else if ((this.prev_cl != null) && (this.prev_cl.next_cl == null)) { + delete this.prev_cl.unchecked.next_cl; + return this.prev_cl.next_cl = this; + } else if ((this.prev_cl != null) || (this.next_cl != null)) { + return Delimiter.__super__.execute.apply(this, arguments); + } else { + throw new Error("Delimiter is unsufficient defined!"); + } + }; + + Delimiter.prototype._encode = function() { + var _ref, _ref1; + return { + 'type': "Delimiter", + 'uid': this.getUid(), + 'prev': (_ref = this.prev_cl) != null ? _ref.getUid() : void 0, + 'next': (_ref1 = this.next_cl) != null ? _ref1.getUid() : void 0 + }; + }; + + return Delimiter; + + })(Operation); + parser['Delimiter'] = function(json) { + var next, prev, uid; + uid = json['uid'], prev = json['prev'], next = json['next']; + return new Delimiter(uid, prev, next); + }; + return { + 'types': { + 'Delete': Delete, + 'Insert': Insert, + 'Delimiter': Delimiter, + 'Operation': Operation, + 'ImmutableObject': ImmutableObject + }, + 'parser': parser, + 'execution_listener': execution_listener + }; +}; + + +},{}],5:[function(require,module,exports){ +var text_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +text_types_uninitialized = require("./TextTypes"); + +module.exports = function(HB) { + var JsonType, createJsonWrapper, parser, text_types, types; + text_types = text_types_uninitialized(HB); + types = text_types.types; + parser = text_types.parser; + createJsonWrapper = function(_jsonType) { + var JsonWrapper; + JsonWrapper = (function() { + function JsonWrapper(jsonType) { + var name, obj, _fn, _ref; + _ref = jsonType.map; + _fn = function(name, obj) { + return Object.defineProperty(JsonWrapper.prototype, name, { + get: function() { + var x; + x = obj.val(); + if (x instanceof JsonType) { + return createJsonWrapper(x); + } else if (x instanceof types.ImmutableObject) { + return x.val(); + } else { + return x; + } + }, + set: function(o) { + var o_name, o_obj, overwrite, _results; + if (o.constructor === {}.constructor) { + overwrite = jsonType.val(name); + _results = []; + for (o_name in o) { + o_obj = o[o_name]; + _results.push(overwrite.val(o_name, o_obj, 'immutable')); + } + return _results; + } else { + return jsonType.val(name, o, 'immutable'); + } + }, + enumerable: true, + configurable: false + }); + }; + for (name in _ref) { + obj = _ref[name]; + _fn(name, obj); + } + } + + return JsonWrapper; + + })(); + return new JsonWrapper(_jsonType); + }; + JsonType = (function(_super) { + __extends(JsonType, _super); + + function JsonType(uid, initial_value, mutable) { + var name, o; + JsonType.__super__.constructor.call(this, uid); + if (initial_value != null) { + if (typeof initial_value !== "object") { + throw new Error("The initial value of JsonTypes must be of type Object! (current type: " + (typeof initial_value) + ")"); + } + for (name in initial_value) { + o = initial_value[name]; + this.val(name, o, mutable); + } + } + } + + JsonType.prototype.mutable_default = true; + + JsonType.prototype.setMutableDefault = function(mutable) { + if (mutable === true || mutable === 'mutable') { + JsonType.prototype.mutable_default = true; + } else if (mutable === false || mutable === 'immutable') { + JsonType.prototype.mutable_default = false; + } else { + throw new Error('Set mutable either "mutable" or "immutable"!'); + } + return 'OK'; + }; + + JsonType.prototype.val = function(name, content, mutable) { + var json, o, o_name, obj, word; + if (typeof name === 'object') { + for (o_name in name) { + o = name[o_name]; + this.val(o_name, o, content); + } + return this; + } else if ((name != null) && (content != null)) { + if (mutable != null) { + if (mutable === true || mutable === 'mutable') { + mutable = true; + } else { + mutable = false; + } + } else { + mutable = this.mutable_default; + } + if (typeof content === 'function') { + return this; + } else if (((!mutable) || typeof content === 'number') && content.constructor !== Object) { + obj = HB.addOperation(new types.ImmutableObject(void 0, content)).execute(); + return JsonType.__super__.val.call(this, name, obj); + } else { + if (typeof content === 'string') { + word = HB.addOperation(new types.Word(void 0)).execute(); + word.insertText(0, content); + return JsonType.__super__.val.call(this, name, word); + } else if (content.constructor === Object) { + json = HB.addOperation(new JsonType(void 0, content, mutable)).execute(); + return JsonType.__super__.val.call(this, name, json); + } else { + throw new Error("You must not set " + (typeof content) + "-types in collaborative Json-objects!"); + } + } + } else { + return JsonType.__super__.val.call(this, name, content); + } + }; + + Object.defineProperty(JsonType.prototype, 'value', { + get: function() { + return createJsonWrapper(this); + }, + set: function(o) { + var o_name, o_obj, _results; + if (o.constructor === {}.constructor) { + _results = []; + for (o_name in o) { + o_obj = o[o_name]; + _results.push(this.val(o_name, o_obj, 'immutable')); + } + return _results; + } else { + throw new Error("You must only set Object values!"); + } + } + }); + + JsonType.prototype._encode = function() { + return { + 'type': "JsonType", + 'uid': this.getUid() + }; + }; + + return JsonType; + + })(types.MapManager); + parser['JsonType'] = function(json) { + var uid; + uid = json['uid']; + return new JsonType(uid); + }; + types['JsonType'] = JsonType; + return text_types; +}; + + +},{"./TextTypes":7}],6:[function(require,module,exports){ +var basic_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +basic_types_uninitialized = require("./BasicTypes"); + +module.exports = function(HB) { + var AddName, ListManager, MapManager, ReplaceManager, Replaceable, basic_types, parser, types; + basic_types = basic_types_uninitialized(HB); + types = basic_types.types; + parser = basic_types.parser; + MapManager = (function(_super) { + __extends(MapManager, _super); + + function MapManager(uid) { + this.map = {}; + MapManager.__super__.constructor.call(this, uid); + } + + MapManager.prototype.val = function(name, content) { + var o, obj, result, _ref, _ref1; + if (content != null) { + if (this.map[name] == null) { + HB.addOperation(new AddName(void 0, this, name)).execute(); + } + this.map[name].replace(content); + return this; + } else if (name != null) { + obj = (_ref = this.map[name]) != null ? _ref.val() : void 0; + if (obj instanceof types.ImmutableObject) { + return obj.val(); + } else { + return obj; + } + } else { + result = {}; + _ref1 = this.map; + for (name in _ref1) { + o = _ref1[name]; + obj = o.val(); + if (obj instanceof types.ImmutableObject || obj instanceof MapManager) { + obj = obj.val(); + } + result[name] = obj; + } + return result; + } + }; + + return MapManager; + + })(types.Operation); + AddName = (function(_super) { + __extends(AddName, _super); + + function AddName(uid, map_manager, name) { + this.name = name; + this.saveOperation('map_manager', map_manager); + AddName.__super__.constructor.call(this, uid); + } + + AddName.prototype.execute = function() { + var beg, end, uid_beg, uid_end, uid_r; + if (!this.validateSavedOperations()) { + return false; + } else { + uid_r = this.map_manager.getUid(); + uid_r.op_number = "_" + uid_r.op_number + "_RM_" + this.name; + if (HB.getOperation(uid_r) == null) { + uid_beg = this.map_manager.getUid(); + uid_beg.op_number = "_" + uid_beg.op_number + "_RM_" + this.name + "_beginning"; + uid_end = this.map_manager.getUid(); + uid_end.op_number = "_" + uid_end.op_number + "_RM_" + this.name + "_end"; + beg = HB.addOperation(new types.Delimiter(uid_beg, void 0, uid_end)).execute(); + end = HB.addOperation(new types.Delimiter(uid_end, beg, void 0)).execute(); + this.map_manager.map[this.name] = HB.addOperation(new ReplaceManager(void 0, uid_r, beg, end)).execute(); + } + return AddName.__super__.execute.apply(this, arguments); + } + }; + + AddName.prototype._encode = function() { + return { + 'type': "AddName", + 'uid': this.getUid(), + 'map_manager': this.map_manager.getUid(), + 'name': this.name + }; + }; + + return AddName; + + })(types.Operation); + parser['AddName'] = function(json) { + var map_manager, name, uid; + map_manager = json['map_manager'], uid = json['uid'], name = json['name']; + return new AddName(uid, map_manager, name); + }; + ListManager = (function(_super) { + __extends(ListManager, _super); + + function ListManager(uid, beginning, end, prev, next, origin) { + if ((beginning != null) && (end != null)) { + this.saveOperation('beginning', beginning); + this.saveOperation('end', end); + } else { + this.beginning = HB.addOperation(new types.Delimiter(void 0, void 0, void 0)); + this.end = HB.addOperation(new types.Delimiter(void 0, this.beginning, void 0)); + this.beginning.next_cl = this.end; + this.beginning.execute(); + this.end.execute(); + } + ListManager.__super__.constructor.call(this, uid, prev, next, origin); + } + + ListManager.prototype.getLastOperation = function() { + return this.end.prev_cl; + }; + + ListManager.prototype.getFirstOperation = function() { + return this.beginning.next_cl; + }; + + ListManager.prototype.toArray = function() { + var o, result; + o = this.beginning.next_cl; + result = []; + while (o !== this.end) { + result.push(o); + o = o.next_cl; + } + return result; + }; + + ListManager.prototype.getOperationByPosition = function(position) { + var o; + o = this.beginning.next_cl; + if (position > 0) { + while (true) { + o = o.next_cl; + if (!o.isDeleted()) { + position -= 1; + } + if (position === 0) { + break; + } + if (o instanceof types.Delimiter) { + throw new Error("position parameter exceeded the length of the document!"); + } + } + } + return o; + }; + + return ListManager; + + })(types.Insert); + ReplaceManager = (function(_super) { + __extends(ReplaceManager, _super); + + function ReplaceManager(initial_content, uid, beginning, end, prev, next, origin) { + ReplaceManager.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + if (initial_content != null) { + this.replace(initial_content); + } + } + + ReplaceManager.prototype.replace = function(content) { + var o, op; + o = this.getLastOperation(); + op = new Replaceable(content, this, void 0, o, o.next_cl); + return HB.addOperation(op).execute(); + }; + + ReplaceManager.prototype.val = function() { + var o; + o = this.getLastOperation(); + if (o instanceof types.Delimiter) { + throw new Error("dtrn"); + } + return o.val(); + }; + + ReplaceManager.prototype._encode = function() { + var json; + json = { + 'type': "ReplaceManager", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if ((this.prev_cl != null) && (this.next_cl != null)) { + json['prev'] = this.prev_cl.getUid(); + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ReplaceManager; + + })(ListManager); + parser["ReplaceManager"] = function(json) { + var beginning, content, end, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], beginning = json['beginning'], end = json['end']; + return new ReplaceManager(content, uid, beginning, end, prev, next, origin); + }; + Replaceable = (function(_super) { + __extends(Replaceable, _super); + + function Replaceable(content, parent, uid, prev, next, origin) { + this.saveOperation('content', content); + this.saveOperation('parent', parent); + if (!((prev != null) && (next != null) && (content != null))) { + throw new Error("You must define content, prev, and next for Replaceable-types!"); + } + Replaceable.__super__.constructor.call(this, uid, prev, next, origin); + } + + Replaceable.prototype.val = function() { + return this.content; + }; + + Replaceable.prototype.replace = function(content) { + return this.parent.replace(content); + }; + + Replaceable.prototype.execute = function() { + var _base; + if (!this.validateSavedOperations()) { + return false; + } else { + if (typeof (_base = this.content).setReplaceManager === "function") { + _base.setReplaceManager(this.parent); + } + Replaceable.__super__.execute.apply(this, arguments); + return this; + } + }; + + Replaceable.prototype._encode = function() { + var json; + json = { + 'type': "Replaceable", + 'content': this.content.getUid(), + 'ReplaceManager': this.parent.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid(), + 'uid': this.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Replaceable; + + })(types.Insert); + parser["Replaceable"] = function(json) { + var content, next, origin, parent, prev, uid; + content = json['content'], parent = json['ReplaceManager'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Replaceable(content, parent, uid, prev, next, origin); + }; + types['ListManager'] = ListManager; + types['MapManager'] = MapManager; + types['ReplaceManager'] = ReplaceManager; + types['Replaceable'] = Replaceable; + return basic_types; +}; + + +},{"./BasicTypes":4}],7:[function(require,module,exports){ +var structured_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +structured_types_uninitialized = require("./StructuredTypes"); + +module.exports = function(HB) { + var TextDelete, TextInsert, Word, parser, structured_types, types; + structured_types = structured_types_uninitialized(HB); + types = structured_types.types; + parser = structured_types.parser; + TextDelete = (function(_super) { + __extends(TextDelete, _super); + + function TextDelete() { + return TextDelete.__super__.constructor.apply(this, arguments); + } + + return TextDelete; + + })(types.Delete); + parser["TextDelete"] = parser["Delete"]; + TextInsert = (function(_super) { + __extends(TextInsert, _super); + + function TextInsert(content, uid, prev, next, origin) { + this.content = content; + if (!((prev != null) && (next != null))) { + throw new Error("You must define prev, and next for TextInsert-types!"); + } + TextInsert.__super__.constructor.call(this, uid, prev, next, origin); + } + + TextInsert.prototype.getLength = function() { + if (this.isDeleted()) { + return 0; + } else { + return this.content.length; + } + }; + + TextInsert.prototype.val = function(current_position) { + if (this.isDeleted()) { + return ""; + } else { + return this.content; + } + }; + + TextInsert.prototype._encode = function() { + var json; + json = { + 'type': "TextInsert", + 'content': this.content, + 'uid': this.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return TextInsert; + + })(types.Insert); + parser["TextInsert"] = function(json) { + var content, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new TextInsert(content, uid, prev, next, origin); + }; + Word = (function(_super) { + __extends(Word, _super); + + function Word(uid, beginning, end, prev, next, origin) { + Word.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + } + + Word.prototype.insertText = function(position, content) { + var c, o, op, _i, _len, _results; + o = this.getOperationByPosition(position); + _results = []; + for (_i = 0, _len = content.length; _i < _len; _i++) { + c = content[_i]; + op = new TextInsert(c, void 0, o.prev_cl, o); + _results.push(HB.addOperation(op).execute()); + } + return _results; + }; + + Word.prototype.deleteText = function(position, length) { + var d, i, o, _i, _results; + o = this.getOperationByPosition(position); + _results = []; + for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) { + d = HB.addOperation(new TextDelete(void 0, o)).execute(); + o = o.next_cl; + while (o.isDeleted()) { + if (o instanceof types.Delimiter) { + throw new Error("You can't delete more than there is.."); + } + o = o.next_cl; + } + _results.push(d._encode()); + } + return _results; + }; + + Word.prototype.replaceText = function(text) { + var word; + if (this.replace_manager != null) { + word = HB.addOperation(new Word(void 0)).execute(); + word.insertText(0, text); + return this.replace_manager.replace(word); + } else { + throw new Error("This type is currently not maintained by a ReplaceManager!"); + } + }; + + Word.prototype.val = function() { + var c, o; + c = (function() { + var _i, _len, _ref, _results; + _ref = this.toArray(); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + o = _ref[_i]; + if (o.val != null) { + _results.push(o.val()); + } else { + _results.push(""); + } + } + return _results; + }).call(this); + return c.join(''); + }; + + Word.prototype.setReplaceManager = function(op) { + this.saveOperation('replace_manager', op); + return this.validateSavedOperations; + }; + + Word.prototype._encode = function() { + var json; + json = { + 'type': "Word", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Word; + + })(types.ListManager); + parser['Word'] = function(json) { + var beginning, end, next, origin, prev, uid; + uid = json['uid'], beginning = json['beginning'], end = json['end'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Word(uid, beginning, end, prev, next, origin); + }; + types['TextInsert'] = TextInsert; + types['TextDelete'] = TextDelete; + types['Word'] = Word; + return structured_types; +}; + + +},{"./StructuredTypes":6}]},{},[2]) +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL0VuZ2luZS5jb2ZmZWUiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL0ZyYW1ld29ya3MvSnNvbllhdHRhLmNvZmZlZSIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9saWIvSGlzdG9yeUJ1ZmZlci5jb2ZmZWUiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL1R5cGVzL0Jhc2ljVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9Kc29uVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9TdHJ1Y3R1cmVkVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9UZXh0VHlwZXMuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDSUEsSUFBQSxNQUFBOztBQUFBO0FBTWUsRUFBQSxnQkFBRSxFQUFGLEVBQU8sTUFBUCxHQUFBO0FBQ1gsSUFEWSxJQUFDLENBQUEsS0FBQSxFQUNiLENBQUE7QUFBQSxJQURpQixJQUFDLENBQUEsU0FBQSxNQUNsQixDQUFBO0FBQUEsSUFBQSxJQUFDLENBQUEsZUFBRCxHQUFtQixFQUFuQixDQURXO0VBQUEsQ0FBYjs7QUFBQSxtQkFNQSxjQUFBLEdBQWdCLFNBQUMsSUFBRCxHQUFBO0FBQ2QsUUFBQSxVQUFBO0FBQUEsSUFBQSxVQUFBLEdBQWEsSUFBQyxDQUFBLE1BQU8sQ0FBQSxJQUFJLENBQUMsSUFBTCxDQUFyQixDQUFBO0FBQ0EsSUFBQSxJQUFHLGtCQUFIO2FBQ0Us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R0FBc0IsVUF4S3RCLENBQUE7QUFBQSxFQXlLQSxLQUFNLENBQUEsWUFBQSxDQUFOLEdBQXNCLFVBekt0QixDQUFBO0FBQUEsRUEwS0EsS0FBTSxDQUFBLE1BQUEsQ0FBTixHQUFnQixJQTFLaEIsQ0FBQTtTQTJLQSxpQkE1S2U7QUFBQSxDQUZqQixDQUFBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3Rocm93IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIil9dmFyIGY9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGYuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sZixmLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIlxyXG4jXHJcbiMgVGhlIEVuZ2luZSBoYW5kbGVzIGhvdyBhbmQgaW4gd2hpY2ggb3JkZXIgdG8gZXhlY3V0ZSBvcGVyYXRpb25zIGFuZCBhZGQgb3BlcmF0aW9ucyB0byB0aGUgSGlzdG9yeUJ1ZmZlci5cclxuI1xyXG5jbGFzcyBFbmdpbmVcclxuXHJcbiAgI1xyXG4gICMgQHBhcmFtIHtIaXN0b3J5QnVmZmVyfSBIQlxyXG4gICMgQHBhcmFtIHtBcnJheX0gcGFyc2VyIERlZmluZXMgaG93IHRvIHBhcnNlIGVuY29kZWQgbWVzc2FnZXMuXHJcbiAgI1xyXG4gIGNvbnN0cnVjdG9yOiAoQEhCLCBAcGFyc2VyKS0+XHJcbiAgICBAdW5wcm9jZXNzZWRfb3BzID0gW11cclxuXHJcbiAgI1xyXG4gICMgUGFyc2VzIGFuIG9wZXJhdGlvIGZyb20gdGhlIGpzb24gZm9ybWF0LiBJdCB1c2VzIHRoZSBzcGVjaWZpZWQgcGFyc2VyIGluIHlvdXIgT3BlcmF0aW9uVHlwZSBtb2R1bGUuXHJcbiAgI1xyXG4gIHBhcnNlT3BlcmF0aW9uOiAoanNvbiktPlxyXG4gICAgdHlwZVBhcnNlciA9IEBwYXJzZXJbanNvbi50eXBlXVxyXG4gICAgaWYgdHlwZVBhcnNlcj9cclxuICAgICAgdHlwZVBhcnNlciBqc29uXHJcbiAgICBlbHNlXHJcbiAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBmb3Jnb3QgdG8gc3BlY2lmeSBhIHBhcnNlciBmb3IgdHlwZSAje2pzb24udHlwZX0uIFRoZSBtZXNzYWdlIGlzICN7SlNPTi5zdHJpbmdpZnkganNvbn0uXCJcclxuXHJcbiAgI1xyXG4gICMgQXBwbHkgYSBzZXQgb2Ygb3BlcmF0aW9ucy4gRS5nLiB0aGUgb3BlcmF0aW9ucyB5b3UgcmVjZWl2ZWQgZnJvbSBhbm90aGVyIHVzZXJzIEhCLnRvSnNvbigpLlxyXG4gICMgQG5vdGUgWW91IG11c3Qgbm90IHVzZSB0aGlzIG1ldGhvZCB3aGVuIHlvdSBhbHJlYWR5IGhhdmUgb3BzIGluIHlvdXIgSEIhXHJcbiAgI1xyXG4gIGFwcGx5T3BzQnVuZGxlOiAob3BzX2pzb24pLT5cclxuICAgIG9wcyA9IFtdXHJcbiAgICBmb3IgbyBpbiBvcHNfanNvblxyXG4gICAgICBvcHMucHVzaCBAcGFyc2VPcGVyYXRpb24gb1xyXG4gICAgZm9yIG8gaW4gb3BzXHJcbiAgICAgIEBIQi5hZGRPcGVyYXRpb24gb1xyXG4gICAgZm9yIG8gaW4gb3BzXHJcbiAgICAgIGlmIG5vdCBvLmV4ZWN1dGUoKVxyXG4gICAgICAgIEB1bnByb2Nlc3NlZF9vcHMucHVzaCBvXHJcbiAgICBAdHJ5VW5wcm9jZXNzZWQoKVxyXG5cclxuICAjXHJcbiAgIyBTYW1lIGFzIGFwcGx5T3BzIGJ1dCBvcGVyYXRpb25zIHRoYXQgYXJlIGFscmVhZHkgaW4gdGhlIEhCIGFyZSBub3QgYXBwbGllZC5cclxuICAjIEBzZWUgRW5naW5lLmFwcGx5T3BzXHJcbiAgI1xyXG4gIGFwcGx5T3BzQ2hlY2tEb3VibGU6IChvcHNfanNvbiktPlxyXG4gICAgZm9yIG8gaW4gb3BzX2pzb25cclxuICAgICAgaWYgQEhCLmdldE9wZXJhdGlvbihvLnVpZCk/XHJcbiAgICAgICAgQGFwcGx5T3Agb1xyXG5cclxuICAjXHJcbiAgIyBBcHBseSBhIHNldCBvZiBvcGVyYXRpb25zLiAoSGVscGVyIGZvciB1c2luZyBhcHBseU9wIG9uIEFycmF5cylcclxuICAjIEBzZWUgRW5naW5lLmFwcGx5T3BcclxuICBhcHBseU9wczogKG9wc19qc29uKS0+XHJcbiAgICBmb3IgbyBpbiBvcHNfanNvblxyXG4gICAgICBAYXBwbHlPcCBvXHJcblxyXG4gICNcclxuICAjIEFwcGx5IGFuIG9wZXJhdGlvbiB0aGF0IHlvdSByZWNlaXZlZCBmcm9tIGFub3RoZXIgcGVlci5cclxuICAjXHJcbiAgYXBwbHlPcDogKG9wX2pzb24pLT5cclxuICAgICMgJHBhcnNlX2FuZF9leGVjdXRlIHdpbGwgcmV0dXJuIGZhbHNlIGlmICRvX2pzb24gd2FzIHBhcnNlZCBhbmQgZXhlY3V0ZWQsIG90aGVyd2lzZSB0aGUgcGFyc2VkIG9wZXJhZGlvblxyXG4gICAgbyA9IEBwYXJzZU9wZXJhdGlvbiBvcF9qc29uXHJcbiAgICBASEIuYWRkVG9Db3VudGVyIG9cclxuICAgICMgQEhCLmFkZE9wZXJhdGlvbiBvXHJcbiAgICBpZiBub3Qgby5leGVjdXRlKClcclxuICAgICAgQHVucHJvY2Vzc2VkX29wcy5wdXNoIG9cclxuICAgIGVsc2VcclxuICAgICAgQEhCLmFkZE9wZXJhdGlvbiBvXHJcbiAgICBAdHJ5VW5wcm9jZXNzZWQoKVxyXG5cclxuICAjXHJcbiAgIyBDYWxsIHRoaXMgbWV0aG9kIHdoZW4geW91IGFwcGxpZWQgYSBuZXcgb3BlcmF0aW9uLlxyXG4gICMgSXQgY2hlY2tzIGlmIG9wZXJhdGlvbnMgdGhhdCB3ZXJlIHByZXZpb3VzbHkgbm90IGV4ZWN1dGFibGUgYXJlIG5vdyBleGVjdXRhYmxlLlxyXG4gICNcclxuICB0cnlVbnByb2Nlc3NlZDogKCktPlxyXG4gICAgd2hpbGUgdHJ1ZVxyXG4gICAgICBvbGRfbGVuZ3RoID0gQHVucHJvY2Vzc2VkX29wcy5sZW5ndGhcclxuICAgICAgdW5wcm9jZXNzZWQgPSBbXVxyXG4gICAgICBmb3Igb3AgaW4gQHVucHJvY2Vzc2VkX29wc1xyXG4gICAgICAgIGlmIG5vdCBvcC5leGVjdXRlKClcclxuICAgICAgICAgIHVucHJvY2Vzc2VkLnB1c2ggb3BcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICBASEIuYWRkT3BlcmF0aW9uIG9wXHJcbiAgICAgIEB1bnByb2Nlc3NlZF9vcHMgPSB1bnByb2Nlc3NlZFxyXG4gICAgICBpZiBAdW5wcm9jZXNzZWRfb3BzLmxlbmd0aCBpcyBvbGRfbGVuZ3RoXHJcbiAgICAgICAgYnJlYWtcclxuXHJcblxyXG5cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gRW5naW5lXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcbiIsIlxuanNvbl90eXBlc191bmluaXRpYWxpemVkID0gcmVxdWlyZSBcIi4uL1R5cGVzL0pzb25UeXBlc1wiXG5IaXN0b3J5QnVmZmVyID0gcmVxdWlyZSBcIi4uL0hpc3RvcnlCdWZmZXJcIlxuRW5naW5lID0gcmVxdWlyZSBcIi4uL0VuZ2luZVwiXG5cbiNcbiMgRnJhbWV3b3JrIGZvciBKc29uIGRhdGEtc3RydWN0dXJlcy5cbiMgS25vd24gdmFsdWVzIHRoYXQgYXJlIHN1cHBvcnRlZDpcbiMgKiBTdHJpbmdcbiMgKiBJbnRlZ2VyXG4jICogQXJyYXlcbiNcbmNsYXNzIEpzb25ZYXR0YVxuXG4gICNcbiAgIyBAcGFyYW0ge1N0cmluZ30gdXNlcl9pZCBVbmlxdWUgaWQgb2YgdGhlIHBlZXIuXG4gICMgQHBhcmFtIHtDb25uZWN0b3J9IENvbm5lY3RvciB0aGUgY29ubmVjdG9yIGNsYXNzLlxuICAjXG4gIGNvbnN0cnVjdG9yOiAodXNlcl9pZCwgQ29ubmVjdG9yKS0+XG4gICAgQEhCID0gbmV3IEhpc3RvcnlCdWZmZXIgdXNlcl9pZFxuICAgIGpzb25fdHlwZXMgPSBqc29uX3R5cGVzX3VuaW5pdGlhbGl6ZWQgQEhCXG4gICAgQGVuZ2luZSA9IG5ldyBFbmdpbmUgQEhCLCBqc29uX3R5cGVzLnBhcnNlclxuICAgIEBjb25uZWN0b3IgPSBuZXcgQ29ubmVjdG9yIEBlbmdpbmUsIEBIQiwganNvbl90eXBlcy5leGVjdXRpb25fbGlzdGVuZXIsIEBcblxuICAgIGZpcnN0X3dvcmQgPSBuZXcganNvbl90eXBlcy50eXBlcy5Kc29uVHlwZSBASEIuZ2V0UmVzZXJ2ZWRVbmlxdWVJZGVudGlmaWVyKClcbiAgICBASEIuYWRkT3BlcmF0aW9uKGZpcnN0X3dvcmQpLmV4ZWN1dGUoKVxuICAgIEByb290X2VsZW1lbnQgPSBmaXJzdF93b3JkXG5cbiAgI1xuICAjIEByZXN1bHQgSnNvblR5cGVcbiAgI1xuICBnZXRSb290RWxlbWVudDogKCktPlxuICAgIEByb290X2VsZW1lbnRcblxuICAjXG4gICMgQHNlZSBFbmdpbmVcbiAgI1xuICBnZXRFbmdpbmU6ICgpLT5cbiAgICBAZW5naW5lXG5cbiAgI1xuICAjIEdldCB0aGUgaW5pdGlhbGl6ZWQgY29ubmVjdG9yLlxuICAjXG4gIGdldENvbm5lY3RvcjogKCktPlxuICAgIEBjb25uZWN0b3JcblxuICAjXG4gICMgQHNlZSBIaXN0b3J5QnVmZmVyXG4gICNcbiAgZ2V0SGlzdG9yeUJ1ZmZlcjogKCktPlxuICAgIEBIQlxuXG4gICNcbiAgIyBAc2VlIEpzb25UeXBlLnNldE11dGFibGVEZWZhdWx0XG4gICNcbiAgc2V0TXV0YWJsZURlZmF1bHQ6IChtdXRhYmxlKS0+XG4gICAgQHJvb3RfZWxlbWVudC5zZXRNdXRhYmxlRGVmYXVsdChtdXRhYmxlKVxuXG4gICNcbiAgIyBHZXQgdGhlIFVzZXJJZCBmcm9tIHRoZSBIaXN0b3J5QnVmZmVyIG9iamVjdC5cbiAgIyBJbiBtb3N0IGNhc2VzIHRoaXMgd2lsbCBiZSB0aGUgc2FtZSBhcyB0aGUgdXNlcl9pZCB2YWx1ZSB3aXRoIHdoaWNoXG4gICMgSnNvbllhdHRhIHdhcyBpbml0aWFsaXplZCAoRGVwZW5kaW5nIG9uIHRoZSBIaXN0b3J5QnVmZmVyIGltcGxlbWVudGF0aW9uKS5cbiAgI1xuICBnZXRVc2VySWQ6ICgpLT5cbiAgICBASEIuZ2V0VXNlcklkKClcblxuICAjXG4gICMgQHNlZSBKc29uVHlwZS52YWxcbiAgI1xuICB2YWwgOiAobmFtZSwgY29udGVudCwgbXV0YWJsZSktPlxuICAgIEByb290X2VsZW1lbnQudmFsKG5hbWUsIGNvbnRlbnQsIG11dGFibGUpXG5cbiAgI1xuICAjIEBzZWUgSnNvblR5cGUudmFsdWVcbiAgI1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkgSnNvbllhdHRhLnByb3RvdHlwZSwgJ3ZhbHVlJyxcbiAgICBnZXQgOiAtPiBAcm9vdF9lbGVtZW50LnZhbHVlXG4gICAgc2V0IDogKG8pLT5cbiAgICAgIGlmIG8uY29uc3RydWN0b3IgaXMge30uY29uc3RydWN0b3JcbiAgICAgICAgZm9yIG9fbmFtZSxvX29iaiBvZiBvXG4gICAgICAgICAgQHZhbChvX25hbWUsIG9fb2JqLCAnaW1tdXRhYmxlJylcbiAgICAgIGVsc2VcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3Qgb25seSBzZXQgT2JqZWN0IHZhbHVlcyFcIlxud2luZG93Py5Kc29uWWF0dGEgPSBKc29uWWF0dGFcbm1vZHVsZS5leHBvcnRzID0gSnNvbllhdHRhXG4iLCJcbiNcbiMgQW4gb2JqZWN0IHRoYXQgaG9sZHMgYWxsIGFwcGxpZWQgb3BlcmF0aW9ucy5cbiNcbiMgQG5vdGUgVGhlIEhpc3RvcnlCdWZmZXIgaXMgY29tbW9ubHkgYWJicmV2aWF0ZWQgdG8gSEIuXG4jXG5jbGFzcyBIaXN0b3J5QnVmZmVyXG5cbiAgI1xuICAjIENyZWF0ZXMgYW4gZW1wdHkgSEIuXG4gICMgQHBhcmFtIHtPYmplY3R9IHVzZXJfaWQgQ3JlYXRvciBvZiB0aGUgSEIuXG4gICNcbiAgY29uc3RydWN0b3I6IChAdXNlcl9pZCktPlxuICAgIEBvcGVyYXRpb25fY291bnRlciA9IHt9XG4gICAgQGJ1ZmZlciA9IHt9XG4gICAgQGNoYW5nZV9saXN0ZW5lcnMgPSBbXVxuXG4gICNcbiAgIyBHZXQgdGhlIHVzZXIgaWQgd2l0aCB3aWNoIHRoZSBIaXN0b3J5IEJ1ZmZlciB3YXMgaW5pdGlhbGl6ZWQuXG4gICNcbiAgZ2V0VXNlcklkOiAoKS0+XG4gICAgQHVzZXJfaWRcblxuICAjXG4gICMgVGhlcmUgaXMgb25seSBvbmUgcmVzZXJ2ZWQgdW5pcXVlIGlkZW50aWZpZXIgKHVpZCksIHNvIHVzZSBpdCB3aXNlbHkuXG4gICMgSSBwcm9wb3NlIHRvIHVzZSBpdCBpbiB5b3VyIEZyYW1ld29yaywgdG8gY3JlYXRlIHNvbWV0aGluZyBsaWtlIGEgcm9vdCBlbGVtZW50LlxuICAjIEFuIG9wZXJhdGlvbiB3aXRoIHRoaXMgaWRlbnRpZmllciBpcyBub3QgcHJvcGFnYXRlZCB0byBvdGhlciBjbGllbnRzLlxuICAjIFRoaXMgaXMgd2h5IGV2ZXJ5Ym9kZSBtdXN0IGNyZWF0ZSB0aGUgc2FtZSBvcGVyYXRpb24gd2l0aCB0aGlzIHVpZC5cbiAgI1xuICBnZXRSZXNlcnZlZFVuaXF1ZUlkZW50aWZpZXI6ICgpLT5cbiAgICB7XG4gICAgICBjcmVhdG9yIDogJ18nXG4gICAgICBvcF9udW1iZXIgOiAnXydcbiAgICB9XG5cbiAgI1xuICAjIEdldCB0aGUgb3BlcmF0aW9uIGNvdW50ZXIgdGhhdCBkZXNjcmliZXMgdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIGRvY3VtZW50LlxuICAjXG4gIGdldE9wZXJhdGlvbkNvdW50ZXI6ICgpLT5cbiAgICByZXMgPSB7fVxuICAgIGZvciB1c2VyLGN0biBvZiBAb3BlcmF0aW9uX2NvdW50ZXJcbiAgICAgIHJlc1t1c2VyXSA9IGN0blxuICAgIHJlc1xuXG4gICNcbiAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAjXG4gIF9lbmNvZGU6IChzdGF0ZV92ZWN0b3I9e30pLT5cbiAgICBqc29uID0gW11cbiAgICB1bmtub3duID0gKHVzZXIsIG9fbnVtYmVyKS0+XG4gICAgICBpZiAobm90IHVzZXI/KSBvciAobm90IG9fbnVtYmVyPylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiZGFoIVwiXG4gICAgICBub3Qgc3RhdGVfdmVjdG9yW3VzZXJdPyBvciBzdGF0ZV92ZWN0b3JbdXNlcl0gPD0gb19udW1iZXJcblxuICAgIGZvciB1X25hbWUsdXNlciBvZiBAYnVmZmVyXG4gICAgICBmb3Igb19udW1iZXIsbyBvZiB1c2VyXG4gICAgICAgIGlmIG5vdCBpc05hTihwYXJzZUludChvX251bWJlcikpIGFuZCB1bmtub3duKHVfbmFtZSwgb19udW1iZXIpXG4gICAgICAgICAgb19qc29uID0gby5fZW5jb2RlKClcbiAgICAgICAgICBpZiBvLm5leHRfY2w/XG4gICAgICAgICAgICBvX25leHQgPSBvLm5leHRfY2xcbiAgICAgICAgICAgIHdoaWxlIG9fbmV4dC5uZXh0X2NsPyBhbmQgdW5rbm93bihvX25leHQuY3JlYXRvciwgb19uZXh0Lm9wX251bWJlcilcbiAgICAgICAgICAgICAgb19uZXh0ID0gb19uZXh0Lm5leHRfY2xcbiAgICAgICAgICAgIG9fanNvbi5uZXh0ID0gb19uZXh0LmdldFVpZCgpXG4gICAgICAgICAgZWxzZSBpZiBvLnByZXZfY2w/XG4gICAgICAgICAgICBvX3ByZXYgPSBvLnByZXZfY2xcbiAgICAgICAgICAgIHdoaWxlIG9fcHJldi5wcmV2X2NsPyBhbmQgdW5rbm93bihvX25leHQuY3JlYXRvciwgb19uZXh0Lm9wX251bWJlcilcbiAgICAgICAgICAgICAgb19wcmV2ID0gb19wcmV2LnByZXZfY2xcbiAgICAgICAgICAgIG9fanNvbi5wcmV2ID0gb19wcmV2LmdldFVpZCgpXG4gICAgICAgICAganNvbi5wdXNoIG9fanNvblxuXG4gICAganNvblxuXG4gICNcbiAgIyBHZXQgdGhlIG51bWJlciBvZiBvcGVyYXRpb25zIHRoYXQgd2VyZSBjcmVhdGVkIGJ5IGEgdXNlci5cbiAgIyBBY2NvcmRpbmdseSB5b3Ugd2lsbCBnZXQgdGhlIG5leHQgb3BlcmF0aW9uIG51bWJlciB0aGF0IGlzIGV4cGVjdGVkIGZyb20gdGhhdCB1c2VyLlxuICAjIFRoaXMgd2lsbCBpbmNyZW1lbnQgdGhlIG9wZXJhdGlvbiBjb3VudGVyLlxuICAjXG4gIGdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyOiAodXNlcl9pZCktPlxuICAgIGlmIG5vdCB1c2VyX2lkP1xuICAgICAgdXNlcl9pZCA9IEB1c2VyX2lkXG4gICAgaWYgbm90IEBvcGVyYXRpb25fY291bnRlclt1c2VyX2lkXT9cbiAgICAgIEBvcGVyYXRpb25fY291bnRlclt1c2VyX2lkXSA9IDBcbiAgICB1aWQgPVxuICAgICAgJ2NyZWF0b3InIDogdXNlcl9pZFxuICAgICAgJ29wX251bWJlcicgOiBAb3BlcmF0aW9uX2NvdW50ZXJbdXNlcl9pZF1cbiAgICBAb3BlcmF0aW9uX2NvdW50ZXJbdXNlcl9pZF0rK1xuICAgIHVpZFxuXG4gICNcbiAgIyBSZXRyaWV2ZSBhbiBvcGVyYXRpb24gZnJvbSBhIHVuaXF1ZSBpZC5cbiAgI1xuICBnZXRPcGVyYXRpb246ICh1aWQpLT5cbiAgICBpZiB1aWQgaW5zdGFuY2VvZiBPYmplY3RcbiAgICAgIEBidWZmZXJbdWlkLmNyZWF0b3JdP1t1aWQub3BfbnVtYmVyXVxuICAgIGVsc2UgaWYgbm90IHVpZD9cbiAgICBlbHNlXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJUaGlzIHR5cGUgb2YgdWlkIGlzIG5vdCBkZWZpbmVkIVwiXG4gICNcbiAgIyBBZGQgYW4gb3BlcmF0aW9uIHRvIHRoZSBIQi4gTm90ZSB0aGF0IHRoaXMgd2lsbCBub3QgbGluayBpdCBhZ2FpbnN0XG4gICMgb3RoZXIgb3BlcmF0aW9ucyAoaXQgd29udCBleGVjdXRlZClcbiAgI1xuICBhZGRPcGVyYXRpb246IChvKS0+XG4gICAgaWYgbm90IEBidWZmZXJbby5jcmVhdG9yXT9cbiAgICAgIEBidWZmZXJbby5jcmVhdG9yXSA9IHt9XG4gICAgaWYgQGJ1ZmZlcltvLmNyZWF0b3JdW28ub3BfbnVtYmVyXT9cbiAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBtdXN0IG5vdCBvdmVyd3JpdGUgb3BlcmF0aW9ucyFcIlxuICAgIEBidWZmZXJbby5jcmVhdG9yXVtvLm9wX251bWJlcl0gPSBvXG4gICAgb1xuXG4gICNcbiAgIyBJbmNyZW1lbnQgdGhlIG9wZXJhdGlvbl9jb3VudGVyIHRoYXQgZGVmaW5lcyB0aGUgY3VycmVudCBzdGF0ZSBvZiB0aGUgRW5naW5lLlxuICAjXG4gIGFkZFRvQ291bnRlcjogKG8pLT5cbiAgICBpZiBub3QgQG9wZXJhdGlvbl9jb3VudGVyW28uY3JlYXRvcl0/XG4gICAgICBAb3BlcmF0aW9uX2NvdW50ZXJbby5jcmVhdG9yXSA9IDBcbiAgICBpZiB0eXBlb2Ygby5vcF9udW1iZXIgaXMgJ251bWJlcicgYW5kIG8uY3JlYXRvciBpc250IEBnZXRVc2VySWQoKVxuICAgICAgQG9wZXJhdGlvbl9jb3VudGVyW28uY3JlYXRvcl0rK1xuICAgICNpZiBAb3BlcmF0aW9uX2NvdW50ZXJbby5jcmVhdG9yXSBpc250IChvLm9wX251bWJlciArIDEpXG4gICAgICAjY29uc29sZS5sb2cgKEBvcGVyYXRpb25fY291bnRlcltvLmNyZWF0b3JdIC0gKG8ub3BfbnVtYmVyICsgMSkpXG4gICAgICAjY29uc29sZS5sb2cgb1xuICAgICAgI3Rocm93IG5ldyBFcnJvciBcIllvdSBkb24ndCByZWNlaXZlIG9wZXJhdGlvbnMgaW4gdGhlIHByb3BlciBvcmRlci4gVHJ5IGNvdW50aW5nIGxpa2UgdGhpcyAwLDEsMiwzLDQsLi4gOylcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IEhpc3RvcnlCdWZmZXJcbiIsIm1vZHVsZS5leHBvcnRzID0gKEhCKS0+XG4gICMgQHNlZSBFbmdpbmUucGFyc2VcbiAgcGFyc2VyID0ge31cbiAgZXhlY3V0aW9uX2xpc3RlbmVyID0gW11cblxuICAjXG4gICMgQSBnZW5lcmljIGludGVyZmFjZSB0byBvcGVyYXRpb25zLlxuICAjXG4gICMgQW4gb3BlcmF0aW9uIGhhcyB0aGUgZm9sbG93aW5nIG1ldGhvZHM6XG4gICMgX2VuY29kZTogZW5jb2RlcyBhbiBvcGVyYXRpb24gKG5lZWRlZCBvbmx5IGlmIGluc3RhbmNlIG9mIHRoaXMgb3BlcmF0aW9uIGlzIHNlbnQpLlxuICAjIGV4ZWN1dGU6IGV4ZWN1dGUgdGhlIGVmZmVjdHMgb2YgdGhpcyBvcGVyYXRpb25zLiBHb29kIGV4YW1wbGVzIGFyZSBJbnNlcnQtdHlwZSBhbmQgQWRkTmFtZS10eXBlXG4gICMgdmFsOiBpbiB0aGUgY2FzZSB0aGF0IHRoZSBvcGVyYXRpb24gaG9sZHMgYSB2YWx1ZVxuICAjXG4gICMgRnVydGhlcm1vcmUgYW4gZW5jb2RhYmxlIG9wZXJhdGlvbiBoYXMgYSBwYXJzZXIuXG4gICNcbiAgY2xhc3MgT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAc2VlIEhpc3RvcnlCdWZmZXIuZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXJcbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQpLT5cbiAgICAgIGlmIG5vdCB1aWQ/XG4gICAgICAgIHVpZCA9IEhCLmdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyKClcbiAgICAgIHtcbiAgICAgICAgJ2NyZWF0b3InOiBAY3JlYXRvclxuICAgICAgICAnb3BfbnVtYmVyJyA6IEBvcF9udW1iZXJcbiAgICAgIH0gPSB1aWRcblxuICAgICNcbiAgICAjIEFkZCBhbiBldmVudCBsaXN0ZW5lci4gSXQgZGVwZW5kcyBvbiB0aGUgb3BlcmF0aW9uIHdoaWNoIGV2ZW50cyBhcmUgc3VwcG9ydGVkLlxuICAgICMgQHBhcmFtIHtTdHJpbmd9IGV2ZW50IE5hbWUgb2YgdGhlIGV2ZW50LlxuICAgICMgQHBhcmFtIHtGdW5jdGlvbn0gZiBmIGlzIGV4ZWN1dGVkIGluIGNhc2UgdGhlIGV2ZW50IGZpcmVzLlxuICAgICNcbiAgICBvbjogKGV2ZW50LCBmKS0+XG4gICAgICBAZXZlbnRfbGlzdGVuZXJzID89IHt9XG4gICAgICBAZXZlbnRfbGlzdGVuZXJzW2V2ZW50XSA/PSBbXVxuICAgICAgQGV2ZW50X2xpc3RlbmVyc1tldmVudF0ucHVzaCBmXG5cbiAgICAjXG4gICAgIyBGaXJlIGFuIGV2ZW50LlxuICAgICMgVE9ETzogRG8gc29tZXRoaW5nIHdpdGggdGltZW91dHMuIFlvdSBkb24ndCB3YW50IHRoaXMgdG8gZmlyZSBmb3IgZXZlcnkgb3BlcmF0aW9uIChlLmcuIGluc2VydCkuXG4gICAgI1xuICAgIGNhbGxFdmVudDogKGV2ZW50LCBhcmdzKS0+XG4gICAgICBpZiBAZXZlbnRfbGlzdGVuZXJzW2V2ZW50XT9cbiAgICAgICAgZm9yIGYgaW4gQGV2ZW50X2xpc3RlbmVyc1tldmVudF1cbiAgICAgICAgICBmLmNhbGwgQCwgZXZlbnQsIGFyZ3NcblxuICAgICNcbiAgICAjIFNldCB0aGUgcGFyZW50IG9mIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICBzZXRQYXJlbnQ6IChvKS0+XG4gICAgICBAcGFyZW50ID0gb1xuXG4gICAgI1xuICAgICMgQ29tcHV0ZXMgYSB1bmlxdWUgaWRlbnRpZmllciAodWlkKSB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uXG4gICAgI1xuICAgIGdldFVpZDogKCktPlxuICAgICAgeyAnY3JlYXRvcic6IEBjcmVhdG9yLCAnb3BfbnVtYmVyJzogQG9wX251bWJlciB9XG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgTm90aWZ5IHRoZSBhbGwgdGhlIGxpc3RlbmVycy5cbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgQGlzX2V4ZWN1dGVkID0gdHJ1ZVxuICAgICAgZm9yIGwgaW4gZXhlY3V0aW9uX2xpc3RlbmVyXG4gICAgICAgIGwgQF9lbmNvZGUoKVxuICAgICAgQFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIE9wZXJhdGlvbnMgbWF5IGRlcGVuZCBvbiBvdGhlciBvcGVyYXRpb25zIChsaW5rZWQgbGlzdHMsIGV0Yy4pLlxuICAgICMgVGhlIHNhdmVPcGVyYXRpb24gYW5kIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zIG1ldGhvZHMgcHJvdmlkZVxuICAgICMgYW4gZWFzeSB3YXkgdG8gcmVmZXIgdG8gdGhlc2Ugb3BlcmF0aW9ucyB2aWEgYW4gdWlkIG9yIG9iamVjdCByZWZlcmVuY2UuXG4gICAgI1xuICAgICMgRm9yIGV4YW1wbGU6IFdlIGNhbiBjcmVhdGUgYSBuZXcgRGVsZXRlIG9wZXJhdGlvbiB0aGF0IGRlbGV0ZXMgdGhlIG9wZXJhdGlvbiAkbyBsaWtlIHRoaXNcbiAgICAjICAgICAtIHZhciBkID0gbmV3IERlbGV0ZSh1aWQsICRvKTsgICBvclxuICAgICMgICAgIC0gdmFyIGQgPSBuZXcgRGVsZXRlKHVpZCwgJG8uZ2V0VWlkKCkpO1xuICAgICMgRWl0aGVyIHdheSB3ZSB3YW50IHRvIGFjY2VzcyAkbyB2aWEgZC5kZWxldGVzLiBJbiB0aGUgc2Vjb25kIGNhc2UgdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMgbXVzdCBiZSBjYWxsZWQgZmlyc3QuXG4gICAgI1xuICAgICMgQG92ZXJsb2FkIHNhdmVPcGVyYXRpb24obmFtZSwgb3BfdWlkKVxuICAgICMgICBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgb3BlcmF0aW9uLiBBZnRlciB2YWxpZGF0aW5nICh3aXRoIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKSB0aGUgaW5zdGFudGlhdGVkIG9wZXJhdGlvbiB3aWxsIGJlIGFjY2Vzc2libGUgdmlhIHRoaXNbbmFtZV0uXG4gICAgIyAgIEBwYXJhbSB7T2JqZWN0fSBvcF91aWQgQSB1aWQgdGhhdCByZWZlcnMgdG8gYW4gb3BlcmF0aW9uXG4gICAgIyBAb3ZlcmxvYWQgc2F2ZU9wZXJhdGlvbihuYW1lLCBvcClcbiAgICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGlvbi4gQWZ0ZXIgY2FsbGluZyB0aGlzIGZ1bmN0aW9uIG9wIGlzIGFjY2Vzc2libGUgdmlhIHRoaXNbbmFtZV0uXG4gICAgIyAgIEBwYXJhbSB7T3BlcmF0aW9ufSBvcCBBbiBPcGVyYXRpb24gb2JqZWN0XG4gICAgI1xuICAgIHNhdmVPcGVyYXRpb246IChuYW1lLCBvcCktPlxuXG4gICAgICAjXG4gICAgICAjIEV2ZXJ5IGluc3RhbmNlIG9mICRPcGVyYXRpb24gbXVzdCBoYXZlIGFuICRleGVjdXRlIGZ1bmN0aW9uLlxuICAgICAgIyBXZSB1c2UgZHVjay10eXBpbmcgdG8gY2hlY2sgaWYgb3AgaXMgaW5zdGFudGlhdGVkIHNpbmNlIHRoZXJlXG4gICAgICAjIGNvdWxkIGV4aXN0IG11bHRpcGxlIGNsYXNzZXMgb2YgJE9wZXJhdGlvblxuICAgICAgI1xuICAgICAgaWYgb3A/LmV4ZWN1dGU/XG4gICAgICAgICMgaXMgaW5zdGFudGlhdGVkXG4gICAgICAgIEBbbmFtZV0gPSBvcFxuICAgICAgZWxzZSBpZiBvcD9cbiAgICAgICAgIyBub3QgaW5pdGlhbGl6ZWQuIERvIGl0IHdoZW4gY2FsbGluZyAkdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICBAdW5jaGVja2VkID89IHt9XG4gICAgICAgIEB1bmNoZWNrZWRbbmFtZV0gPSBvcFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIEFmdGVyIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiBhbGwgbm90IGluc3RhbnRpYXRlZCBvcGVyYXRpb25zIHdpbGwgYmUgYWNjZXNzaWJsZS5cbiAgICAjIEBzZWUgT3BlcmF0aW9uLnNhdmVPcGVyYXRpb25cbiAgICAjXG4gICAgIyBAcmV0dXJuIFtCb29sZWFuXSBXaGV0aGVyIGl0IHdhcyBwb3NzaWJsZSB0byBpbnN0YW50aWF0ZSBhbGwgb3BlcmF0aW9ucy5cbiAgICAjXG4gICAgdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnM6ICgpLT5cbiAgICAgIHVuaW5zdGFudGlhdGVkID0ge31cbiAgICAgIHN1Y2Nlc3MgPSBAXG4gICAgICBmb3IgbmFtZSwgb3BfdWlkIG9mIEB1bmNoZWNrZWRcbiAgICAgICAgb3AgPSBIQi5nZXRPcGVyYXRpb24gb3BfdWlkXG4gICAgICAgIGlmIG9wXG4gICAgICAgICAgQFtuYW1lXSA9IG9wXG4gICAgICAgIGVsc2VcbiAgICAgICAgICB1bmluc3RhbnRpYXRlZFtuYW1lXSA9IG9wX3VpZFxuICAgICAgICAgIHN1Y2Nlc3MgPSBmYWxzZVxuICAgICAgZGVsZXRlIEB1bmNoZWNrZWRcbiAgICAgIGlmIG5vdCBzdWNjZXNzXG4gICAgICAgIEB1bmNoZWNrZWQgPSB1bmluc3RhbnRpYXRlZFxuICAgICAgc3VjY2Vzc1xuXG5cblxuICAjXG4gICMgQSBzaW1wbGUgRGVsZXRlLXR5cGUgb3BlcmF0aW9uIHRoYXQgZGVsZXRlcyBhbiBJbnNlcnQtdHlwZSBvcGVyYXRpb24uXG4gICNcbiAgY2xhc3MgRGVsZXRlIGV4dGVuZHMgT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gZGVsZXRlcyBVSUQgb3IgcmVmZXJlbmNlIG9mIHRoZSBvcGVyYXRpb24gdGhhdCB0aGlzIHRvIGJlIGRlbGV0ZWQuXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBkZWxldGVzKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnZGVsZXRlcycsIGRlbGV0ZXNcbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIENvbnZlcnQgYWxsIHJlbGV2YW50IGluZm9ybWF0aW9uIG9mIHRoaXMgb3BlcmF0aW9uIHRvIHRoZSBqc29uLWZvcm1hdC5cbiAgICAjIFRoaXMgcmVzdWx0IGNhbiBiZSBzZW50IHRvIG90aGVyIGNsaWVudHMuXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIHtcbiAgICAgICAgJ3R5cGUnOiBcIkRlbGV0ZVwiXG4gICAgICAgICd1aWQnOiBAZ2V0VWlkKClcbiAgICAgICAgJ2RlbGV0ZXMnOiBAZGVsZXRlcy5nZXRVaWQoKVxuICAgICAgfVxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIEFwcGx5IHRoZSBkZWxldGlvbi5cbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgQGRlbGV0ZXMuYXBwbHlEZWxldGUgQFxuICAgICAgICBzdXBlclxuICAgICAgICBAXG4gICAgICBlbHNlXG4gICAgICAgIGZhbHNlXG5cbiAgI1xuICAjIERlZmluZSBob3cgdG8gcGFyc2UgRGVsZXRlIG9wZXJhdGlvbnMuXG4gICNcbiAgcGFyc2VyWydEZWxldGUnXSA9IChvKS0+XG4gICAge1xuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdkZWxldGVzJzogZGVsZXRlc191aWRcbiAgICB9ID0gb1xuICAgIG5ldyBEZWxldGUgdWlkLCBkZWxldGVzX3VpZFxuXG4gICNcbiAgIyBBIHNpbXBsZSBpbnNlcnQtdHlwZSBvcGVyYXRpb24uXG4gICNcbiAgIyBBbiBpbnNlcnQgb3BlcmF0aW9uIGlzIGFsd2F5cyBwb3NpdGlvbmVkIGJldHdlZW4gdHdvIG90aGVyIGluc2VydCBvcGVyYXRpb25zLlxuICAjIEludGVybmFsbHkgdGhpcyBpcyByZWFsaXplZCBhcyBhc3NvY2lhdGl2ZSBsaXN0cywgd2hlcmVieSBlYWNoIGluc2VydCBvcGVyYXRpb24gaGFzIGEgcHJlZGVjZXNzb3IgYW5kIGEgc3VjY2Vzc29yLlxuICAjIEZvciB0aGUgc2FrZSBvZiBlZmZpY2llbmN5IHdlIG1haW50YWluIHR3byBsaXN0czpcbiAgIyAgIC0gVGhlIHNob3J0LWxpc3QgKGFiYnJldi4gc2wpIG1haW50YWlucyBvbmx5IHRoZSBvcGVyYXRpb25zIHRoYXQgYXJlIG5vdCBkZWxldGVkXG4gICMgICAtIFRoZSBjb21wbGV0ZS1saXN0IChhYmJyZXYuIGNsKSBtYWludGFpbnMgYWxsIG9wZXJhdGlvbnNcbiAgI1xuICBjbGFzcyBJbnNlcnQgZXh0ZW5kcyBPcGVyYXRpb25cblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBwcmV2X2NsIFRoZSBwcmVkZWNlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gbmV4dF9jbCBUaGUgc3VjY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcbiAgICAjXG4gICAgIyBAc2VlIEhpc3RvcnlCdWZmZXIuZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXJcbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIHByZXZfY2wsIG5leHRfY2wsIG9yaWdpbiktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ3ByZXZfY2wnLCBwcmV2X2NsXG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnbmV4dF9jbCcsIG5leHRfY2xcbiAgICAgIGlmIG9yaWdpbj9cbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ29yaWdpbicsIG9yaWdpblxuICAgICAgZWxzZVxuICAgICAgICBAc2F2ZU9wZXJhdGlvbiAnb3JpZ2luJywgcHJldl9jbFxuICAgICAgc3VwZXIgdWlkXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICNcbiAgICBhcHBseURlbGV0ZTogKG8pLT5cbiAgICAgIEBkZWxldGVkX2J5ID89IFtdXG4gICAgICBAZGVsZXRlZF9ieS5wdXNoIG9cblxuICAgICNcbiAgICAjIElmIGlzRGVsZXRlZCgpIGlzIHRydWUgdGhpcyBvcGVyYXRpb24gd29uJ3QgYmUgbWFpbnRhaW5lZCBpbiB0aGUgc2xcbiAgICAjXG4gICAgaXNEZWxldGVkOiAoKS0+XG4gICAgICBAZGVsZXRlZF9ieT8ubGVuZ3RoID4gMFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIFRoZSBhbW91bnQgb2YgcG9zaXRpb25zIHRoYXQgJHRoaXMgb3BlcmF0aW9uIHdhcyBtb3ZlZCB0byB0aGUgcmlnaHQuXG4gICAgI1xuICAgIGdldERpc3RhbmNlVG9PcmlnaW46ICgpLT5cbiAgICAgIGQgPSAwXG4gICAgICBvID0gQHByZXZfY2xcbiAgICAgIHdoaWxlIHRydWVcbiAgICAgICAgaWYgQG9yaWdpbiBpcyBvXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgZCsrXG4gICAgICAgICNUT0RPOiBkZWxldGUgdGhpc1xuICAgICAgICBpZiBAIGlzIEBwcmV2X2NsXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwidGhpcyBzaG91bGQgbm90IGhhcHBlbiA7KSBcIlxuICAgICAgICBvID0gby5wcmV2X2NsXG4gICAgICBkXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgVXBkYXRlIHRoZSBzaG9ydCBsaXN0XG4gICAgIyBUT0RPIChVbnVzZWQpXG4gICAgdXBkYXRlX3NsOiAoKS0+XG4gICAgICBvID0gQHByZXZfY2xcbiAgICAgIHVwZGF0ZTogKGRlc3RfY2wsZGVzdF9zbCktPlxuICAgICAgICB3aGlsZSB0cnVlXG4gICAgICAgICAgaWYgby5pc0RlbGV0ZWQoKVxuICAgICAgICAgICAgbyA9IG9bZGVzdF9jbF1cbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBAW2Rlc3Rfc2xdID0gb1xuXG4gICAgICAgICAgICBicmVha1xuICAgICAgdXBkYXRlIFwicHJldl9jbFwiLCBcInByZXZfc2xcIlxuICAgICAgdXBkYXRlIFwibmV4dF9jbFwiLCBcInByZXZfc2xcIlxuXG5cblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBJbmNsdWRlIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBhc3NvY2lhdGl2ZSBsaXN0cy5cbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgQGlzX2V4ZWN1dGVkP1xuICAgICAgICByZXR1cm4gQFxuICAgICAgaWYgbm90IEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgZWxzZVxuICAgICAgICBpZiBAcHJldl9jbD8udmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKSBhbmQgQG5leHRfY2w/LnZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKCkgYW5kIEBwcmV2X2NsLm5leHRfY2wgaXNudCBAXG4gICAgICAgICAgZGlzdGFuY2VfdG9fb3JpZ2luID0gMFxuICAgICAgICAgIG8gPSBAcHJldl9jbC5uZXh0X2NsXG4gICAgICAgICAgaSA9IDBcbiAgICAgICAgICAjICR0aGlzIGhhcyB0byBmaW5kIGEgdW5pcXVlIHBvc2l0aW9uIGJldHdlZW4gb3JpZ2luIGFuZCB0aGUgbmV4dCBrbm93biBjaGFyYWN0ZXJcbiAgICAgICAgICAjIGNhc2UgMTogJG9yaWdpbiBlcXVhbHMgJG8ub3JpZ2luOiB0aGUgJGNyZWF0b3IgcGFyYW1ldGVyIGRlY2lkZXMgaWYgbGVmdCBvciByaWdodFxuICAgICAgICAgICMgICAgICAgICBsZXQgJE9MPSBbbzEsbzIsbzMsbzRdLCB3aGVyZWJ5ICR0aGlzIGlzIHRvIGJlIGluc2VydGVkIGJldHdlZW4gbzEgYW5kIG80XG4gICAgICAgICAgIyAgICAgICAgIG8yLG8zIGFuZCBvNCBvcmlnaW4gaXMgMSAodGhlIHBvc2l0aW9uIG9mIG8yKVxuICAgICAgICAgICMgICAgICAgICB0aGVyZSBpcyB0aGUgY2FzZSB0aGF0ICR0aGlzLmNyZWF0b3IgPCBvMi5jcmVhdG9yLCBidXQgbzMuY3JlYXRvciA8ICR0aGlzLmNyZWF0b3JcbiAgICAgICAgICAjICAgICAgICAgdGhlbiBvMiBrbm93cyBvMy4gU2luY2Ugb24gYW5vdGhlciBjbGllbnQgJE9MIGNvdWxkIGJlIFtvMSxvMyxvNF0gdGhlIHByb2JsZW0gaXMgY29tcGxleFxuICAgICAgICAgICMgICAgICAgICB0aGVyZWZvcmUgJHRoaXMgd291bGQgYmUgYWx3YXlzIHRvIHRoZSByaWdodCBvZiBvM1xuICAgICAgICAgICMgY2FzZSAyOiAkb3JpZ2luIDwgJG8ub3JpZ2luXG4gICAgICAgICAgIyAgICAgICAgIGlmIGN1cnJlbnQgJHRoaXMgaW5zZXJ0X3Bvc2l0aW9uID4gJG8gb3JpZ2luOiAkdGhpcyBpbnNcbiAgICAgICAgICAjICAgICAgICAgZWxzZSAkaW5zZXJ0X3Bvc2l0aW9uIHdpbGwgbm90IGNoYW5nZSAobWF5YmUgd2UgZW5jb3VudGVyIGNhc2UgMSBsYXRlciwgdGhlbiB0aGlzIHdpbGwgYmUgdG8gdGhlIHJpZ2h0IG9mICRvKVxuICAgICAgICAgICMgY2FzZSAzOiAkb3JpZ2luID4gJG8ub3JpZ2luXG4gICAgICAgICAgIyAgICAgICAgICR0aGlzIGluc2VydF9wb3NpdGlvbiBpcyB0byB0aGUgbGVmdCBvZiAkbyAoZm9yZXZlciEpXG4gICAgICAgICAgd2hpbGUgdHJ1ZVxuICAgICAgICAgICAgaWYgbm90IG8/XG4gICAgICAgICAgICAgICMgVE9ETzogRGVidWdnaW5nXG4gICAgICAgICAgICAgIGNvbnNvbGUubG9nIEpTT04uc3RyaW5naWZ5IEBwcmV2X2NsLmdldFVpZCgpXG4gICAgICAgICAgICAgIGNvbnNvbGUubG9nIEpTT04uc3RyaW5naWZ5IEBuZXh0X2NsLmdldFVpZCgpXG4gICAgICAgICAgICBpZiBvIGlzbnQgQG5leHRfY2xcbiAgICAgICAgICAgICAgIyAkbyBoYXBwZW5lZCBjb25jdXJyZW50bHlcbiAgICAgICAgICAgICAgaWYgby5nZXREaXN0YW5jZVRvT3JpZ2luKCkgaXMgaVxuICAgICAgICAgICAgICAgICMgY2FzZSAxXG4gICAgICAgICAgICAgICAgaWYgby5jcmVhdG9yIDwgQGNyZWF0b3JcbiAgICAgICAgICAgICAgICAgIEBwcmV2X2NsID0gb1xuICAgICAgICAgICAgICAgICAgZGlzdGFuY2VfdG9fb3JpZ2luID0gaSArIDFcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAjIG5vcFxuICAgICAgICAgICAgICBlbHNlIGlmIG8uZ2V0RGlzdGFuY2VUb09yaWdpbigpIDwgaVxuICAgICAgICAgICAgICAgICMgY2FzZSAyXG4gICAgICAgICAgICAgICAgaWYgaSAtIGRpc3RhbmNlX3RvX29yaWdpbiA8PSBvLmdldERpc3RhbmNlVG9PcmlnaW4oKVxuICAgICAgICAgICAgICAgICAgQHByZXZfY2wgPSBvXG4gICAgICAgICAgICAgICAgICBkaXN0YW5jZV90b19vcmlnaW4gPSBpICsgMVxuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICNub3BcbiAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICMgY2FzZSAzXG4gICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgaSsrXG4gICAgICAgICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgIyAkdGhpcyBrbm93cyB0aGF0ICRvIGV4aXN0cyxcbiAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAjIG5vdyByZWNvbm5lY3QgZXZlcnl0aGluZ1xuICAgICAgICAgIEBuZXh0X2NsID0gQHByZXZfY2wubmV4dF9jbFxuICAgICAgICAgIEBwcmV2X2NsLm5leHRfY2wgPSBAXG4gICAgICAgICAgQG5leHRfY2wucHJldl9jbCA9IEBcbiAgICAgICAgc3VwZXIgIyBub3RpZnkgdGhlIGV4ZWN1dGlvbl9saXN0ZW5lcnNcbiAgICAgICAgQFxuXG4gICNcbiAgIyBEZWZpbmVzIGFuIG9iamVjdCB0aGF0IGlzIGNhbm5vdCBiZSBjaGFuZ2VkLiBZb3UgY2FuIHVzZSB0aGlzIHRvIHNldCBhbiBpbW11dGFibGUgc3RyaW5nLCBvciBhIG51bWJlci5cbiAgI1xuICBjbGFzcyBJbW11dGFibGVPYmplY3QgZXh0ZW5kcyBJbnNlcnRcblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSBjb250ZW50XG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBAY29udGVudCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBzdXBlciB1aWQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICAgI1xuICAgICMgQHJldHVybiBbU3RyaW5nXSBUaGUgY29udGVudCBvZiB0aGlzIG9wZXJhdGlvbi5cbiAgICAjXG4gICAgdmFsIDogKCktPlxuICAgICAgQGNvbnRlbnRcblxuICAgICNcbiAgICAjIEVuY29kZSB0aGlzIG9wZXJhdGlvbiBpbiBzdWNoIGEgd2F5IHRoYXQgaXQgY2FuIGJlIHBhcnNlZCBieSByZW1vdGUgcGVlcnMuXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIGpzb24gPSB7XG4gICAgICAgICd0eXBlJzogXCJJbW11dGFibGVPYmplY3RcIlxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAnY29udGVudCcgOiBAY29udGVudFxuICAgICAgfVxuICAgICAgaWYgQHByZXZfY2w/XG4gICAgICAgIGpzb25bJ3ByZXYnXSA9IEBwcmV2X2NsLmdldFVpZCgpXG4gICAgICBpZiBAbmV4dF9jbD9cbiAgICAgICAganNvblsnbmV4dCddID0gQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgIGlmIEBvcmlnaW4/IGFuZCBAb3JpZ2luIGlzbnQgQHByZXZfY2xcbiAgICAgICAganNvbltcIm9yaWdpblwiXSA9IEBvcmlnaW4uZ2V0VWlkKClcbiAgICAgIGpzb25cblxuICBwYXJzZXJbJ0ltbXV0YWJsZU9iamVjdCddID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ2NvbnRlbnQnIDogY29udGVudFxuICAgICAgJ3ByZXYnOiBwcmV2XG4gICAgICAnbmV4dCc6IG5leHRcbiAgICAgICdvcmlnaW4nIDogb3JpZ2luXG4gICAgfSA9IGpzb25cbiAgICBuZXcgSW1tdXRhYmxlT2JqZWN0IHVpZCwgY29udGVudCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cbiAgI1xuICAjIEEgZGVsaW1pdGVyIGlzIHBsYWNlZCBhdCB0aGUgZW5kIGFuZCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBhc3NvY2lhdGl2ZSBsaXN0cy5cbiAgIyBUaGlzIGlzIG5lY2Vzc2FyeSBpbiBvcmRlciB0byBoYXZlIGEgYmVnaW5uaW5nIGFuZCBhbiBlbmQgZXZlbiBpZiB0aGUgY29udGVudFxuICAjIG9mIHRoZSBFbmdpbmUgaXMgZW1wdHkuXG4gICNcbiAgY2xhc3MgRGVsaW1pdGVyIGV4dGVuZHMgT3BlcmF0aW9uXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IHByZXZfY2wgVGhlIHByZWRlY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBuZXh0X2NsIFRoZSBzdWNjZXNzb3Igb2YgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGNvbXBsZXRlLWxpc3QgKGNsKVxuICAgICNcbiAgICAjIEBzZWUgSGlzdG9yeUJ1ZmZlci5nZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllclxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgcHJldl9jbCwgbmV4dF9jbCwgb3JpZ2luKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncHJldl9jbCcsIHByZXZfY2xcbiAgICAgIEBzYXZlT3BlcmF0aW9uICduZXh0X2NsJywgbmV4dF9jbFxuICAgICAgQHNhdmVPcGVyYXRpb24gJ29yaWdpbicsIHByZXZfY2xcbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgSWYgaXNEZWxldGVkKCkgaXMgdHJ1ZSB0aGlzIG9wZXJhdGlvbiB3b24ndCBiZSBtYWludGFpbmVkIGluIHRoZSBzbFxuICAgICNcbiAgICBpc0RlbGV0ZWQ6ICgpLT5cbiAgICAgIGZhbHNlXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBAdW5jaGVja2VkP1snbmV4dF9jbCddP1xuICAgICAgICBzdXBlclxuICAgICAgZWxzZSBpZiBAdW5jaGVja2VkP1sncHJldl9jbCddXG4gICAgICAgIGlmIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgICAgaWYgQHByZXZfY2wubmV4dF9jbD9cbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcIlByb2JhYmx5IGR1cGxpY2F0ZWQgb3BlcmF0aW9uc1wiXG4gICAgICAgICAgQHByZXZfY2wubmV4dF9jbCA9IEBcbiAgICAgICAgICBkZWxldGUgQHByZXZfY2wudW5jaGVja2VkLm5leHRfY2xcbiAgICAgICAgICBzdXBlclxuICAgICAgICBlbHNlXG4gICAgICAgICAgZmFsc2VcbiAgICAgIGVsc2UgaWYgQHByZXZfY2w/IGFuZCBub3QgQHByZXZfY2wubmV4dF9jbD9cbiAgICAgICAgZGVsZXRlIEBwcmV2X2NsLnVuY2hlY2tlZC5uZXh0X2NsXG4gICAgICAgIEBwcmV2X2NsLm5leHRfY2wgPSBAXG4gICAgICBlbHNlIGlmIEBwcmV2X2NsPyBvciBAbmV4dF9jbD9cbiAgICAgICAgc3VwZXJcbiAgICAgIGVsc2VcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiRGVsaW1pdGVyIGlzIHVuc3VmZmljaWVudCBkZWZpbmVkIVwiXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICB7XG4gICAgICAgICd0eXBlJyA6IFwiRGVsaW1pdGVyXCJcbiAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgJ3ByZXYnIDogQHByZXZfY2w/LmdldFVpZCgpXG4gICAgICAgICduZXh0JyA6IEBuZXh0X2NsPy5nZXRVaWQoKVxuICAgICAgfVxuXG4gIHBhcnNlclsnRGVsaW1pdGVyJ10gPSAoanNvbiktPlxuICAgIHtcbiAgICAndWlkJyA6IHVpZFxuICAgICdwcmV2JyA6IHByZXZcbiAgICAnbmV4dCcgOiBuZXh0XG4gICAgfSA9IGpzb25cbiAgICBuZXcgRGVsaW1pdGVyIHVpZCwgcHJldiwgbmV4dFxuXG4gICMgVGhpcyBpcyB3aGF0IHRoaXMgbW9kdWxlIGV4cG9ydHMgYWZ0ZXIgaW5pdGlhbGl6aW5nIGl0IHdpdGggdGhlIEhpc3RvcnlCdWZmZXJcbiAge1xuICAgICd0eXBlcycgOlxuICAgICAgJ0RlbGV0ZScgOiBEZWxldGVcbiAgICAgICdJbnNlcnQnIDogSW5zZXJ0XG4gICAgICAnRGVsaW1pdGVyJzogRGVsaW1pdGVyXG4gICAgICAnT3BlcmF0aW9uJzogT3BlcmF0aW9uXG4gICAgICAnSW1tdXRhYmxlT2JqZWN0JyA6IEltbXV0YWJsZU9iamVjdFxuICAgICdwYXJzZXInIDogcGFyc2VyXG4gICAgJ2V4ZWN1dGlvbl9saXN0ZW5lcicgOiBleGVjdXRpb25fbGlzdGVuZXJcbiAgfVxuXG5cblxuXG4iLCJ0ZXh0X3R5cGVzX3VuaW5pdGlhbGl6ZWQgPSByZXF1aXJlIFwiLi9UZXh0VHlwZXNcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IChIQiktPlxuICB0ZXh0X3R5cGVzID0gdGV4dF90eXBlc191bmluaXRpYWxpemVkIEhCXG4gIHR5cGVzID0gdGV4dF90eXBlcy50eXBlc1xuICBwYXJzZXIgPSB0ZXh0X3R5cGVzLnBhcnNlclxuXG4gIGNyZWF0ZUpzb25XcmFwcGVyID0gKF9qc29uVHlwZSktPlxuXG4gICAgI1xuICAgICMgQSBKc29uV3JhcHBlciB3YXMgaW50ZW5kZWQgdG8gYmUgYSBjb252ZW5pZW50IHdyYXBwZXIgZm9yIHRoZSBKc29uVHlwZS5cbiAgICAjIEJ1dCBpdCBjYW4gbWFrZSB0aGluZ3MgbW9yZSBkaWZmaWN1bHQgdGhhbiB0aGV5IGFyZS5cbiAgICAjIEBzZWUgSnNvblR5cGVcbiAgICAjXG4gICAgIyBAZXhhbXBsZSBjcmVhdGUgYSBKc29uV3JhcHBlclxuICAgICMgICAjIFlvdSBnZXQgYSBKc29uV3JhcHBlciBmcm9tIGEgSnNvblR5cGUgYnkgY2FsbGluZ1xuICAgICMgICB3ID0geWF0dGEudmFsdWVcbiAgICAjXG4gICAgIyBJdCBjcmVhdGVzIEphdmFzY3JpcHRzIC1nZXR0ZXIgYW5kIC1zZXR0ZXIgbWV0aG9kcyBmb3IgZWFjaCBwcm9wZXJ0eSB0aGF0IEpzb25UeXBlIG1haW50YWlucy5cbiAgICAjIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvT2JqZWN0L2RlZmluZVByb3BlcnR5XG4gICAgI1xuICAgICMgQGV4YW1wbGUgR2V0dGVyIEV4YW1wbGVcbiAgICAjICAgIyB5b3UgY2FuIGFjY2VzcyB0aGUgeCBwcm9wZXJ0eSBvZiB5YXR0YSBieSBjYWxsaW5nXG4gICAgIyAgIHcueFxuICAgICMgICAjIGluc3RlYWQgb2ZcbiAgICAjICAgeWF0dGEudmFsKCd4JylcbiAgICAjXG4gICAgIyBAbm90ZSBZb3UgY2FuIG9ubHkgb3ZlcndyaXRlIGV4aXN0aW5nIHZhbHVlcyEgU2V0dGluZyBhIG5ldyBwcm9wZXJ0eSB3b24ndCBoYXZlIGFueSBlZmZlY3QhXG4gICAgI1xuICAgICMgQGV4YW1wbGUgU2V0dGVyIEV4YW1wbGVcbiAgICAjICAgIyB5b3UgY2FuIHNldCBhbiBleGlzdGluZyB4IHByb3BlcnR5IG9mIHlhdHRhIGJ5IGNhbGxpbmdcbiAgICAjICAgdy54ID0gXCJ0ZXh0XCJcbiAgICAjICAgIyBpbnN0ZWFkIG9mXG4gICAgIyAgIHlhdHRhLnZhbCgneCcsIFwidGV4dFwiKVxuICAgICNcbiAgICAjIEluIG9yZGVyIHRvIHNldCBhIG5ldyBwcm9wZXJ0eSB5b3UgaGF2ZSB0byBvdmVyd3JpdGUgYW4gZXhpc3RpbmcgcHJvcGVydHkuXG4gICAgIyBUaGVyZWZvcmUgdGhlIEpzb25XcmFwcGVyIHN1cHBvcnRzIGEgc3BlY2lhbCBmZWF0dXJlIHRoYXQgc2hvdWxkIG1ha2UgdGhpbmdzIG1vcmUgY29udmVuaWVudFxuICAgICMgKHdlIGNhbiBhcmd1ZSBhYm91dCB0aGF0LCB1c2UgdGhlIEpzb25UeXBlIGlmIHlvdSBkb24ndCBsaWtlIGl0IDspLlxuICAgICMgSWYgeW91IG92ZXJ3cml0ZSBhbiBvYmplY3QgcHJvcGVydHkgb2YgdGhlIEpzb25XcmFwcGVyIHdpdGggYSBuZXcgb2JqZWN0LCBpdCB3aWxsIHJlc3VsdCBpbiBhIG1lcmdlZCB2ZXJzaW9uIG9mIHRoZSBvYmplY3RzLlxuICAgICMgTGV0IHcucCB0aGUgcHJvcGVydHkgdGhhdCBpcyB0byBiZSBvdmVyd3JpdHRlbiBhbmQgbyB0aGUgbmV3IHZhbHVlLiBFLmcuIHcucCA9IG9cbiAgICAjICogVGhlIHJlc3VsdCBoYXMgYWxsIHByb3BlcnRpZXMgb2Ygb1xuICAgICMgKiBUaGUgcmVzdWx0IGhhcyBhbGwgcHJvcGVydGllcyBvZiB3LnAgaWYgdGhleSBkb24ndCBvY2N1ciB1bmRlciB0aGUgc2FtZSBwcm9wZXJ0eS1uYW1lIGluIG8uXG4gICAgI1xuICAgICMgQGV4YW1wbGUgQ29uZmxpY3QgRXhhbXBsZVxuICAgICMgICB5YXR0YS52YWx1ZSA9IHthIDogXCJzdHJpbmdcIn1cbiAgICAjICAgdyA9IHlhdHRhLnZhbHVlXG4gICAgIyAgIGNvbnNvbGUubG9nKHcpICMge2EgOiBcInN0cmluZ1wifVxuICAgICMgICB3LmEgPSB7YSA6IHtiIDogXCJzdHJpbmdcIn19XG4gICAgIyAgIGNvbnNvbGUubG9nKHcpICMge2EgOiB7YiA6IFwiU3RyaW5nXCJ9fVxuICAgICMgICB3LmEgPSB7YSA6IHtjIDogNH19XG4gICAgIyAgIGNvbnNvbGUubG9nKHcpICMge2EgOiB7YiA6IFwiU3RyaW5nXCIsIGMgOiA0fX1cbiAgICAjXG4gICAgIyBAZXhhbXBsZSBDb21tb24gUGl0ZmFsbHNcbiAgICAjICAgdyA9IHlhdHRhLnZhbHVlXG4gICAgIyAgICMgU2V0dGluZyBhIG5ldyBwcm9wZXJ0eVxuICAgICMgICB3Lm5ld1Byb3BlcnR5ID0gXCJBd2Vzb21lXCJcbiAgICAjICAgY29uc29sZS5sb2cody5uZXdQcm9wZXJ0eSA9PSBcIkF3ZXNvbWVcIikgIyBmYWxzZSwgdy5uZXdQcm9wZXJ0eSBpcyB1bmRlZmluZWRcbiAgICAjICAgIyBvdmVyd3JpdGUgdGhlIHcgb2JqZWN0XG4gICAgIyAgIHcgPSB7bmV3UHJvcGVydHkgOiBcIkF3ZXNvbWVcIn1cbiAgICAjICAgY29uc29sZS5sb2cody5uZXdQcm9wZXJ0eSA9PSBcIkF3ZXNvbWVcIikgIyB0cnVlISwgYnV0IC4uXG4gICAgIyAgIGNvbnNvbGUubG9nKHlhdHRhLnZhbHVlLm5ld1Byb3BlcnR5ID09IFwiQXdlc29tZVwiKSAjIGZhbHNlLCB5b3UgYXJlIG9ubHkgYWxsb3dlZCB0byBzZXQgcHJvcGVydGllcyFcbiAgICAjICAgIyBUaGUgc29sdXRpb25cbiAgICAjICAgeWF0dGEudmFsdWUgPSB7bmV3UHJvcGVydHkgOiBcIkF3ZXNvbWVcIn1cbiAgICAjICAgY29uc29sZS5sb2cody5uZXdQcm9wZXJ0eSA9PSBcIkF3ZXNvbWVcIikgIyB0cnVlIVxuICAgICNcbiAgICBjbGFzcyBKc29uV3JhcHBlclxuXG4gICAgICAjXG4gICAgICAjIEBwYXJhbSB7SnNvblR5cGV9IGpzb25UeXBlIEluc3RhbmNlIG9mIHRoZSBKc29uVHlwZSB0aGF0IHRoaXMgY2xhc3Mgd3JhcHBlcy5cbiAgICAgICNcbiAgICAgIGNvbnN0cnVjdG9yOiAoanNvblR5cGUpLT5cbiAgICAgICAgZm9yIG5hbWUsIG9iaiBvZiBqc29uVHlwZS5tYXBcbiAgICAgICAgICBkbyAobmFtZSwgb2JqKS0+XG4gICAgICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkgSnNvbldyYXBwZXIucHJvdG90eXBlLCBuYW1lLFxuICAgICAgICAgICAgICBnZXQgOiAtPlxuICAgICAgICAgICAgICAgIHggPSBvYmoudmFsKClcbiAgICAgICAgICAgICAgICBpZiB4IGluc3RhbmNlb2YgSnNvblR5cGVcbiAgICAgICAgICAgICAgICAgIGNyZWF0ZUpzb25XcmFwcGVyIHhcbiAgICAgICAgICAgICAgICBlbHNlIGlmIHggaW5zdGFuY2VvZiB0eXBlcy5JbW11dGFibGVPYmplY3RcbiAgICAgICAgICAgICAgICAgIHgudmFsKClcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICB4XG4gICAgICAgICAgICAgIHNldCA6IChvKS0+XG4gICAgICAgICAgICAgICAgaWYgby5jb25zdHJ1Y3RvciBpcyB7fS5jb25zdHJ1Y3RvclxuICAgICAgICAgICAgICAgICAgb3ZlcndyaXRlID0ganNvblR5cGUudmFsKG5hbWUpXG4gICAgICAgICAgICAgICAgICBmb3Igb19uYW1lLG9fb2JqIG9mIG9cbiAgICAgICAgICAgICAgICAgICAgb3ZlcndyaXRlLnZhbChvX25hbWUsIG9fb2JqLCAnaW1tdXRhYmxlJylcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICBqc29uVHlwZS52YWwobmFtZSwgbywgJ2ltbXV0YWJsZScpXG4gICAgICAgICAgICAgIGVudW1lcmFibGU6IHRydWVcbiAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZVxuICAgIG5ldyBKc29uV3JhcHBlciBfanNvblR5cGVcblxuICAjXG4gICMgTWFuYWdlcyBPYmplY3QtbGlrZSB2YWx1ZXMuXG4gICNcbiAgY2xhc3MgSnNvblR5cGUgZXh0ZW5kcyB0eXBlcy5NYXBNYW5hZ2VyXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gaW5pdGlhbF92YWx1ZSBDcmVhdGUgdGhpcyBvcGVyYXRpb24gd2l0aCBhbiBpbml0aWFsIHZhbHVlLlxuICAgICMgQHBhcmFtIHtTdHJpbmd8Qm9vbGVhbn0gV2hldGhlciB0aGUgaW5pdGlhbF92YWx1ZSBzaG91bGQgYmUgY3JlYXRlZCBhcyBtdXRhYmxlLiAoT3B0aW9uYWwgLSBzZWUgc2V0TXV0YWJsZURlZmF1bHQpXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBpbml0aWFsX3ZhbHVlLCBtdXRhYmxlKS0+XG4gICAgICBzdXBlciB1aWRcbiAgICAgIGlmIGluaXRpYWxfdmFsdWU/XG4gICAgICAgIGlmIHR5cGVvZiBpbml0aWFsX3ZhbHVlIGlzbnQgXCJvYmplY3RcIlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcIlRoZSBpbml0aWFsIHZhbHVlIG9mIEpzb25UeXBlcyBtdXN0IGJlIG9mIHR5cGUgT2JqZWN0ISAoY3VycmVudCB0eXBlOiAje3R5cGVvZiBpbml0aWFsX3ZhbHVlfSlcIlxuICAgICAgICBmb3IgbmFtZSxvIG9mIGluaXRpYWxfdmFsdWVcbiAgICAgICAgICBAdmFsIG5hbWUsIG8sIG11dGFibGVcblxuICAgICNcbiAgICAjIFdoZXRoZXIgdGhlIGRlZmF1bHQgaXMgJ211dGFibGUnICh0cnVlKSBvciAnaW1tdXRhYmxlJyAoZmFsc2UpXG4gICAgI1xuICAgIG11dGFibGVfZGVmYXVsdDpcbiAgICAgIHRydWVcblxuICAgICNcbiAgICAjIFNldCBpZiB0aGUgZGVmYXVsdCBpcyAnbXV0YWJsZScgb3IgJ2ltbXV0YWJsZSdcbiAgICAjIEBwYXJhbSB7U3RyaW5nfEJvb2xlYW59IG11dGFibGUgU2V0IGVpdGhlciAnbXV0YWJsZScgLyB0cnVlIG9yICdpbW11dGFibGUnIC8gZmFsc2VcbiAgICBzZXRNdXRhYmxlRGVmYXVsdDogKG11dGFibGUpLT5cbiAgICAgIGlmIG11dGFibGUgaXMgdHJ1ZSBvciBtdXRhYmxlIGlzICdtdXRhYmxlJ1xuICAgICAgICBKc29uVHlwZS5wcm90b3R5cGUubXV0YWJsZV9kZWZhdWx0ID0gdHJ1ZVxuICAgICAgZWxzZSBpZiBtdXRhYmxlIGlzIGZhbHNlIG9yIG11dGFibGUgaXMgJ2ltbXV0YWJsZSdcbiAgICAgICAgSnNvblR5cGUucHJvdG90eXBlLm11dGFibGVfZGVmYXVsdCA9IGZhbHNlXG4gICAgICBlbHNlXG4gICAgICAgIHRocm93IG5ldyBFcnJvciAnU2V0IG11dGFibGUgZWl0aGVyIFwibXV0YWJsZVwiIG9yIFwiaW1tdXRhYmxlXCIhJ1xuICAgICAgJ09LJ1xuXG4gICAgI1xuICAgICMgQG92ZXJsb2FkIHZhbCgpXG4gICAgIyAgIEdldCB0aGlzIGFzIGEgSnNvbiBvYmplY3QuXG4gICAgIyAgIEByZXR1cm4gW0pzb25dXG4gICAgI1xuICAgICMgQG92ZXJsb2FkIHZhbChuYW1lKVxuICAgICMgICBHZXQgdmFsdWUgb2YgYSBwcm9wZXJ0eS5cbiAgICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgb2JqZWN0IHByb3BlcnR5LlxuICAgICMgICBAcmV0dXJuIFtKc29uVHlwZXxXb3JkfFN0cmluZ3xPYmplY3RdIERlcGVuZGluZyBvbiB0aGUgdmFsdWUgb2YgdGhlIHByb3BlcnR5LiBJZiBtdXRhYmxlIGl0IHdpbGwgcmV0dXJuIGEgT3BlcmF0aW9uLXR5cGUgb2JqZWN0LCBpZiBpbW11dGFibGUgaXQgd2lsbCByZXR1cm4gU3RyaW5nL09iamVjdC5cbiAgICAjXG4gICAgIyBAb3ZlcmxvYWQgdmFsKG5hbWUsIGNvbnRlbnQpXG4gICAgIyAgIFNldCBhIG5ldyBwcm9wZXJ0eS5cbiAgICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgb2JqZWN0IHByb3BlcnR5LlxuICAgICMgICBAcGFyYW0ge09iamVjdHxTdHJpbmd9IGNvbnRlbnQgQ29udGVudCBvZiB0aGUgb2JqZWN0IHByb3BlcnR5LlxuICAgICMgICBAcmV0dXJuIFtKc29uVHlwZV0gVGhpcyBvYmplY3QuIChzdXBwb3J0cyBjaGFpbmluZylcbiAgICAjXG4gICAgdmFsOiAobmFtZSwgY29udGVudCwgbXV0YWJsZSktPlxuICAgICAgaWYgdHlwZW9mIG5hbWUgaXMgJ29iamVjdCdcbiAgICAgICAgIyBTcGVjaWFsIGNhc2UuIEZpcnN0IGFyZ3VtZW50IGlzIGFuIG9iamVjdC4gVGhlbiB0aGUgc2Vjb25kIGFyZyBpcyBtdXRhYmxlLlxuICAgICAgICAjIEtlZXAgdGhhdCBpbiBtaW5kIHdoZW4gcmVhZGluZyB0aGUgZm9sbG93aW5nLi5cbiAgICAgICAgZm9yIG9fbmFtZSxvIG9mIG5hbWVcbiAgICAgICAgICBAdmFsKG9fbmFtZSxvLGNvbnRlbnQpXG4gICAgICAgIEBcbiAgICAgIGVsc2UgaWYgbmFtZT8gYW5kIGNvbnRlbnQ/XG4gICAgICAgIGlmIG11dGFibGU/XG4gICAgICAgICAgaWYgbXV0YWJsZSBpcyB0cnVlIG9yIG11dGFibGUgaXMgJ211dGFibGUnXG4gICAgICAgICAgICBtdXRhYmxlID0gdHJ1ZVxuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIG11dGFibGUgPSBmYWxzZVxuICAgICAgICBlbHNlXG4gICAgICAgICAgbXV0YWJsZSA9IEBtdXRhYmxlX2RlZmF1bHRcbiAgICAgICAgaWYgdHlwZW9mIGNvbnRlbnQgaXMgJ2Z1bmN0aW9uJ1xuICAgICAgICAgIEAgIyBKdXN0IGRvIG5vdGhpbmdcbiAgICAgICAgZWxzZSBpZiAoKG5vdCBtdXRhYmxlKSBvciB0eXBlb2YgY29udGVudCBpcyAnbnVtYmVyJykgYW5kIGNvbnRlbnQuY29uc3RydWN0b3IgaXNudCBPYmplY3RcbiAgICAgICAgICBvYmogPSBIQi5hZGRPcGVyYXRpb24obmV3IHR5cGVzLkltbXV0YWJsZU9iamVjdCB1bmRlZmluZWQsIGNvbnRlbnQpLmV4ZWN1dGUoKVxuICAgICAgICAgIHN1cGVyIG5hbWUsIG9ialxuICAgICAgICBlbHNlXG4gICAgICAgICAgaWYgdHlwZW9mIGNvbnRlbnQgaXMgJ3N0cmluZydcbiAgICAgICAgICAgIHdvcmQgPSBIQi5hZGRPcGVyYXRpb24obmV3IHR5cGVzLldvcmQgdW5kZWZpbmVkKS5leGVjdXRlKClcbiAgICAgICAgICAgIHdvcmQuaW5zZXJ0VGV4dCAwLCBjb250ZW50XG4gICAgICAgICAgICBzdXBlciBuYW1lLCB3b3JkXG4gICAgICAgICAgZWxzZSBpZiBjb250ZW50LmNvbnN0cnVjdG9yIGlzIE9iamVjdFxuICAgICAgICAgICAganNvbiA9IEhCLmFkZE9wZXJhdGlvbihuZXcgSnNvblR5cGUgdW5kZWZpbmVkLCBjb250ZW50LCBtdXRhYmxlKS5leGVjdXRlKClcbiAgICAgICAgICAgIHN1cGVyIG5hbWUsIGpzb25cbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBub3Qgc2V0ICN7dHlwZW9mIGNvbnRlbnR9LXR5cGVzIGluIGNvbGxhYm9yYXRpdmUgSnNvbi1vYmplY3RzIVwiXG4gICAgICBlbHNlXG4gICAgICAgIHN1cGVyIG5hbWUsIGNvbnRlbnRcblxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSBKc29uVHlwZS5wcm90b3R5cGUsICd2YWx1ZScsXG4gICAgICBnZXQgOiAtPiBjcmVhdGVKc29uV3JhcHBlciBAXG4gICAgICBzZXQgOiAobyktPlxuICAgICAgICBpZiBvLmNvbnN0cnVjdG9yIGlzIHt9LmNvbnN0cnVjdG9yXG4gICAgICAgICAgZm9yIG9fbmFtZSxvX29iaiBvZiBvXG4gICAgICAgICAgICBAdmFsKG9fbmFtZSwgb19vYmosICdpbW11dGFibGUnKVxuICAgICAgICBlbHNlXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3Qgb25seSBzZXQgT2JqZWN0IHZhbHVlcyFcIlxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAge1xuICAgICAgICAndHlwZScgOiBcIkpzb25UeXBlXCJcbiAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgIH1cblxuICBwYXJzZXJbJ0pzb25UeXBlJ10gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICd1aWQnIDogdWlkXG4gICAgfSA9IGpzb25cbiAgICBuZXcgSnNvblR5cGUgdWlkXG5cblxuXG5cbiAgdHlwZXNbJ0pzb25UeXBlJ10gPSBKc29uVHlwZVxuXG4gIHRleHRfdHlwZXNcblxuXG4iLCJiYXNpY190eXBlc191bmluaXRpYWxpemVkID0gcmVxdWlyZSBcIi4vQmFzaWNUeXBlc1wiXG5cbm1vZHVsZS5leHBvcnRzID0gKEhCKS0+XG4gIGJhc2ljX3R5cGVzID0gYmFzaWNfdHlwZXNfdW5pbml0aWFsaXplZCBIQlxuICB0eXBlcyA9IGJhc2ljX3R5cGVzLnR5cGVzXG4gIHBhcnNlciA9IGJhc2ljX3R5cGVzLnBhcnNlclxuXG4gICNcbiAgIyBNYW5hZ2VzIG1hcCBsaWtlIG9iamVjdHMuIEUuZy4gSnNvbi1UeXBlIGFuZCBYTUwgYXR0cmlidXRlcy5cbiAgI1xuICBjbGFzcyBNYXBNYW5hZ2VyIGV4dGVuZHMgdHlwZXMuT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkKS0+XG4gICAgICBAbWFwID0ge31cbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgQHNlZSBKc29uVHlwZXMudmFsXG4gICAgI1xuICAgIHZhbDogKG5hbWUsIGNvbnRlbnQpLT5cbiAgICAgIGlmIGNvbnRlbnQ/XG4gICAgICAgIGlmIG5vdCBAbWFwW25hbWVdP1xuICAgICAgICAgIEhCLmFkZE9wZXJhdGlvbihuZXcgQWRkTmFtZSB1bmRlZmluZWQsIEAsIG5hbWUpLmV4ZWN1dGUoKVxuICAgICAgICBAbWFwW25hbWVdLnJlcGxhY2UgY29udGVudFxuICAgICAgICBAXG4gICAgICBlbHNlIGlmIG5hbWU/XG4gICAgICAgIG9iaiA9IEBtYXBbbmFtZV0/LnZhbCgpXG4gICAgICAgIGlmIG9iaiBpbnN0YW5jZW9mIHR5cGVzLkltbXV0YWJsZU9iamVjdFxuICAgICAgICAgIG9iai52YWwoKVxuICAgICAgICBlbHNlXG4gICAgICAgICAgb2JqXG4gICAgICBlbHNlXG4gICAgICAgIHJlc3VsdCA9IHt9XG4gICAgICAgIGZvciBuYW1lLG8gb2YgQG1hcFxuICAgICAgICAgIG9iaiA9IG8udmFsKClcbiAgICAgICAgICBpZiBvYmogaW5zdGFuY2VvZiB0eXBlcy5JbW11dGFibGVPYmplY3Qgb3Igb2JqIGluc3RhbmNlb2YgTWFwTWFuYWdlclxuICAgICAgICAgICAgb2JqID0gb2JqLnZhbCgpXG4gICAgICAgICAgcmVzdWx0W25hbWVdID0gb2JqXG4gICAgICAgIHJlc3VsdFxuXG4gICNcbiAgIyBXaGVuIGEgbmV3IHByb3BlcnR5IGluIGEgbWFwIG1hbmFnZXIgaXMgY3JlYXRlZCwgdGhlbiB0aGUgdWlkcyBvZiB0aGUgaW5zZXJ0ZWQgT3BlcmF0aW9uc1xuICAjIG11c3QgYmUgdW5pcXVlICh0aGluayBhYm91dCBjb25jdXJyZW50IG9wZXJhdGlvbnMpLiBUaGVyZWZvcmUgb25seSBhbiBBZGROYW1lIG9wZXJhdGlvbiBpcyBhbGxvd2VkIHRvXG4gICMgYWRkIGEgcHJvcGVydHkgaW4gYSBNYXBNYW5hZ2VyLiBJZiB0d28gQWRkTmFtZSBvcGVyYXRpb25zIG9uIHRoZSBzYW1lIE1hcE1hbmFnZXIgbmFtZSBoYXBwZW4gY29uY3VycmVudGx5XG4gICMgb25seSBvbmUgd2lsbCBBZGROYW1lIG9wZXJhdGlvbiB3aWxsIGJlIGV4ZWN1dGVkLlxuICAjXG4gIGNsYXNzIEFkZE5hbWUgZXh0ZW5kcyB0eXBlcy5PcGVyYXRpb25cblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSBtYXBfbWFuYWdlciBVaWQgb3IgcmVmZXJlbmNlIHRvIHRoZSBNYXBNYW5hZ2VyLlxuICAgICMgQHBhcmFtIHtTdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgcHJvcGVydHkgdGhhdCB3aWxsIGJlIGFkZGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgbWFwX21hbmFnZXIsIEBuYW1lKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnbWFwX21hbmFnZXInLCBtYXBfbWFuYWdlclxuICAgICAgc3VwZXIgdWlkXG5cbiAgICAjXG4gICAgIyBJZiBtYXBfbWFuYWdlciBkb2Vzbid0IGhhdmUgdGhlIHByb3BlcnR5IG5hbWUsIHRoZW4gYWRkIGl0LlxuICAgICMgVGhlIFJlcGxhY2VNYW5hZ2VyIHRoYXQgaXMgYmVpbmcgd3JpdHRlbiBvbiB0aGUgcHJvcGVydHkgaXMgdW5pcXVlXG4gICAgIyBpbiBzdWNoIGEgd2F5IHRoYXQgaWYgQWRkTmFtZSBpcyBleGVjdXRlZCAoZnJvbSBhbm90aGVyIHBlZXIpIGl0IHdpbGxcbiAgICAjIGFsd2F5cyBoYXZlIHRoZSBzYW1lIHJlc3VsdCAoUmVwbGFjZU1hbmFnZXIsIGFuZCBpdHMgYmVnaW5uaW5nIGFuZCBlbmQgYXJlIHRoZSBzYW1lKVxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBub3QgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICBlbHNlXG4gICAgICAgIHVpZF9yID0gQG1hcF9tYW5hZ2VyLmdldFVpZCgpXG4gICAgICAgIHVpZF9yLm9wX251bWJlciA9IFwiXyN7dWlkX3Iub3BfbnVtYmVyfV9STV8je0BuYW1lfVwiXG4gICAgICAgIGlmIG5vdCBIQi5nZXRPcGVyYXRpb24odWlkX3IpP1xuICAgICAgICAgIHVpZF9iZWcgPSBAbWFwX21hbmFnZXIuZ2V0VWlkKClcbiAgICAgICAgICB1aWRfYmVnLm9wX251bWJlciA9IFwiXyN7dWlkX2JlZy5vcF9udW1iZXJ9X1JNXyN7QG5hbWV9X2JlZ2lubmluZ1wiXG4gICAgICAgICAgdWlkX2VuZCA9IEBtYXBfbWFuYWdlci5nZXRVaWQoKVxuICAgICAgICAgIHVpZF9lbmQub3BfbnVtYmVyID0gXCJfI3t1aWRfZW5kLm9wX251bWJlcn1fUk1fI3tAbmFtZX1fZW5kXCJcbiAgICAgICAgICBiZWcgPSBIQi5hZGRPcGVyYXRpb24obmV3IHR5cGVzLkRlbGltaXRlciB1aWRfYmVnLCB1bmRlZmluZWQsIHVpZF9lbmQpLmV4ZWN1dGUoKVxuICAgICAgICAgIGVuZCA9IEhCLmFkZE9wZXJhdGlvbihuZXcgdHlwZXMuRGVsaW1pdGVyIHVpZF9lbmQsIGJlZywgdW5kZWZpbmVkKS5leGVjdXRlKClcbiAgICAgICAgICAjYmVnLmV4ZWN1dGUoKVxuICAgICAgICAgIEBtYXBfbWFuYWdlci5tYXBbQG5hbWVdID0gSEIuYWRkT3BlcmF0aW9uKG5ldyBSZXBsYWNlTWFuYWdlciB1bmRlZmluZWQsIHVpZF9yLCBiZWcsIGVuZCkuZXhlY3V0ZSgpXG4gICAgICAgIHN1cGVyXG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICB7XG4gICAgICAgICd0eXBlJyA6IFwiQWRkTmFtZVwiXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICdtYXBfbWFuYWdlcicgOiBAbWFwX21hbmFnZXIuZ2V0VWlkKClcbiAgICAgICAgJ25hbWUnIDogQG5hbWVcbiAgICAgIH1cblxuICBwYXJzZXJbJ0FkZE5hbWUnXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ21hcF9tYW5hZ2VyJyA6IG1hcF9tYW5hZ2VyXG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ25hbWUnIDogbmFtZVxuICAgIH0gPSBqc29uXG4gICAgbmV3IEFkZE5hbWUgdWlkLCBtYXBfbWFuYWdlciwgbmFtZVxuXG4gICNcbiAgIyBNYW5hZ2VzIGEgbGlzdCBvZiBJbnNlcnQtdHlwZSBvcGVyYXRpb25zLlxuICAjXG4gIGNsYXNzIExpc3RNYW5hZ2VyIGV4dGVuZHMgdHlwZXMuSW5zZXJ0XG5cbiAgICAjXG4gICAgIyBBIExpc3RNYW5hZ2VyIG1haW50YWlucyBhIG5vbi1lbXB0eSBsaXN0IHRoYXQgaGFzIGEgYmVnaW5uaW5nIGFuZCBhbiBlbmQgKGJvdGggRGVsaW1pdGVycyEpXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge0RlbGltaXRlcn0gYmVnaW5uaW5nIFJlZmVyZW5jZSBvciBPYmplY3QuXG4gICAgIyBAcGFyYW0ge0RlbGltaXRlcn0gZW5kIFJlZmVyZW5jZSBvciBPYmplY3QuXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIGlmIGJlZ2lubmluZz8gYW5kIGVuZD9cbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ2JlZ2lubmluZycsIGJlZ2lubmluZ1xuICAgICAgICBAc2F2ZU9wZXJhdGlvbiAnZW5kJywgZW5kXG4gICAgICBlbHNlXG4gICAgICAgIEBiZWdpbm5pbmcgPSBIQi5hZGRPcGVyYXRpb24gbmV3IHR5cGVzLkRlbGltaXRlciB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkXG4gICAgICAgIEBlbmQgPSAgICAgICBIQi5hZGRPcGVyYXRpb24gbmV3IHR5cGVzLkRlbGltaXRlciB1bmRlZmluZWQsIEBiZWdpbm5pbmcsIHVuZGVmaW5lZFxuICAgICAgICBAYmVnaW5uaW5nLm5leHRfY2wgPSBAZW5kXG4gICAgICAgIEBiZWdpbm5pbmcuZXhlY3V0ZSgpXG4gICAgICAgIEBlbmQuZXhlY3V0ZSgpXG4gICAgICBzdXBlciB1aWQsIHByZXYsIG5leHQsIG9yaWdpblxuXG5cbiAgICAjIEdldCB0aGUgZWxlbWVudCBwcmV2aW91cyB0byB0aGUgZGVsZW1pdGVyIGF0IHRoZSBlbmRcbiAgICBnZXRMYXN0T3BlcmF0aW9uOiAoKS0+XG4gICAgICBAZW5kLnByZXZfY2xcblxuICAgICMgc2ltaWxhciB0byB0aGUgYWJvdmVcbiAgICBnZXRGaXJzdE9wZXJhdGlvbjogKCktPlxuICAgICAgQGJlZ2lubmluZy5uZXh0X2NsXG5cbiAgICAjIFRyYW5zZm9ybXMgdGhlIHRoZSBsaXN0IHRvIGFuIGFycmF5XG4gICAgIyBEb2Vzbid0IHJldHVybiBsZWZ0LXJpZ2h0IGRlbGltaXRlci5cbiAgICB0b0FycmF5OiAoKS0+XG4gICAgICBvID0gQGJlZ2lubmluZy5uZXh0X2NsXG4gICAgICByZXN1bHQgPSBbXVxuICAgICAgd2hpbGUgbyBpc250IEBlbmRcbiAgICAgICAgcmVzdWx0LnB1c2ggb1xuICAgICAgICBvID0gby5uZXh0X2NsXG4gICAgICByZXN1bHRcblxuICAgICNcbiAgICAjIFJldHJpZXZlcyB0aGUgeC10aCBub3QgZGVsZXRlZCBlbGVtZW50LlxuICAgICNcbiAgICBnZXRPcGVyYXRpb25CeVBvc2l0aW9uOiAocG9zaXRpb24pLT5cbiAgICAgIG8gPSBAYmVnaW5uaW5nLm5leHRfY2xcbiAgICAgIGlmIHBvc2l0aW9uID4gMFxuICAgICAgICB3aGlsZSB0cnVlXG4gICAgICAgICAgbyA9IG8ubmV4dF9jbFxuICAgICAgICAgIGlmIG5vdCBvLmlzRGVsZXRlZCgpXG4gICAgICAgICAgICBwb3NpdGlvbiAtPSAxXG4gICAgICAgICAgaWYgcG9zaXRpb24gaXMgMFxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICBpZiBvIGluc3RhbmNlb2YgdHlwZXMuRGVsaW1pdGVyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJwb3NpdGlvbiBwYXJhbWV0ZXIgZXhjZWVkZWQgdGhlIGxlbmd0aCBvZiB0aGUgZG9jdW1lbnQhXCJcbiAgICAgIG9cblxuICAjXG4gICMgQWRkcyBzdXBwb3J0IGZvciByZXBsYWNlLiBUaGUgUmVwbGFjZU1hbmFnZXIgbWFuYWdlcyBSZXBsYWNlYWJsZSBvcGVyYXRpb25zLlxuICAjIEVhY2ggUmVwbGFjZWFibGUgaG9sZHMgYSB2YWx1ZSB0aGF0IGlzIG5vdyByZXBsYWNlYWJsZS5cbiAgI1xuICAjIFRoZSBXb3JkLXR5cGUgaGFzIGltcGxlbWVudGVkIHN1cHBvcnQgZm9yIHJlcGxhY2VcbiAgIyBAc2VlIFdvcmRcbiAgI1xuICBjbGFzcyBSZXBsYWNlTWFuYWdlciBleHRlbmRzIExpc3RNYW5hZ2VyXG4gICAgI1xuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IGluaXRpYWxfY29udGVudCBJbml0aWFsaXplIHRoaXMgd2l0aCBhIFJlcGxhY2VhYmxlIHRoYXQgaG9sZHMgdGhlIGluaXRpYWxfY29udGVudC5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7RGVsaW1pdGVyfSBiZWdpbm5pbmcgUmVmZXJlbmNlIG9yIE9iamVjdC5cbiAgICAjIEBwYXJhbSB7RGVsaW1pdGVyfSBlbmQgUmVmZXJlbmNlIG9yIE9iamVjdC5cbiAgICBjb25zdHJ1Y3RvcjogKGluaXRpYWxfY29udGVudCwgdWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBzdXBlciB1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW5cbiAgICAgIGlmIGluaXRpYWxfY29udGVudD9cbiAgICAgICAgQHJlcGxhY2UgaW5pdGlhbF9jb250ZW50XG5cbiAgICAjXG4gICAgIyBSZXBsYWNlIHRoZSBleGlzdGluZyB3b3JkIHdpdGggYSBuZXcgd29yZC5cbiAgICAjXG4gICAgcmVwbGFjZTogKGNvbnRlbnQpLT5cbiAgICAgIG8gPSBAZ2V0TGFzdE9wZXJhdGlvbigpXG4gICAgICBvcCA9IG5ldyBSZXBsYWNlYWJsZSBjb250ZW50LCBALCB1bmRlZmluZWQsIG8sIG8ubmV4dF9jbFxuICAgICAgSEIuYWRkT3BlcmF0aW9uKG9wKS5leGVjdXRlKClcblxuICAgICNcbiAgICAjIEdldCB0aGUgdmFsdWUgb2YgdGhpcyBXb3JkXG4gICAgIyBAcmV0dXJuIHtTdHJpbmd9XG4gICAgI1xuICAgIHZhbDogKCktPlxuICAgICAgbyA9IEBnZXRMYXN0T3BlcmF0aW9uKClcbiAgICAgIGlmIG8gaW5zdGFuY2VvZiB0eXBlcy5EZWxpbWl0ZXJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiZHRyblwiXG4gICAgICBvLnZhbCgpXG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID1cbiAgICAgICAge1xuICAgICAgICAgICd0eXBlJzogXCJSZXBsYWNlTWFuYWdlclwiXG4gICAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgICAnYmVnaW5uaW5nJyA6IEBiZWdpbm5pbmcuZ2V0VWlkKClcbiAgICAgICAgICAnZW5kJyA6IEBlbmQuZ2V0VWlkKClcbiAgICAgICAgfVxuICAgICAgaWYgQHByZXZfY2w/IGFuZCBAbmV4dF9jbD9cbiAgICAgICAganNvblsncHJldiddID0gQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgICAganNvblsnbmV4dCddID0gQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgIGlmIEBvcmlnaW4/IGFuZCBAb3JpZ2luIGlzbnQgQHByZXZfY2xcbiAgICAgICAganNvbltcIm9yaWdpblwiXSA9IEBvcmlnaW4uZ2V0VWlkKClcbiAgICAgIGpzb25cblxuICBwYXJzZXJbXCJSZXBsYWNlTWFuYWdlclwiXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ2NvbnRlbnQnIDogY29udGVudFxuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdwcmV2JzogcHJldlxuICAgICAgJ25leHQnOiBuZXh0XG4gICAgICAnb3JpZ2luJyA6IG9yaWdpblxuICAgICAgJ2JlZ2lubmluZycgOiBiZWdpbm5pbmdcbiAgICAgICdlbmQnIDogZW5kXG4gICAgfSA9IGpzb25cbiAgICBuZXcgUmVwbGFjZU1hbmFnZXIgY29udGVudCwgdWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cblxuICAjXG4gICMgVGhlIFJlcGxhY2VNYW5hZ2VyIG1hbmFnZXMgUmVwbGFjZWFibGVzLlxuICAjIEBzZWUgUmVwbGFjZU1hbmFnZXJcbiAgI1xuICBjbGFzcyBSZXBsYWNlYWJsZSBleHRlbmRzIHR5cGVzLkluc2VydFxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IGNvbnRlbnQgVGhlIHZhbHVlIHRoYXQgdGhpcyBSZXBsYWNlYWJsZSBob2xkcy5cbiAgICAjIEBwYXJhbSB7UmVwbGFjZU1hbmFnZXJ9IHBhcmVudCBVc2VkIHRvIHJlcGxhY2UgdGhpcyBSZXBsYWNlYWJsZSB3aXRoIGFub3RoZXIgb25lLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKGNvbnRlbnQsIHBhcmVudCwgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIEBzYXZlT3BlcmF0aW9uICdjb250ZW50JywgY29udGVudFxuICAgICAgQHNhdmVPcGVyYXRpb24gJ3BhcmVudCcsIHBhcmVudFxuICAgICAgaWYgbm90IChwcmV2PyBhbmQgbmV4dD8gYW5kIGNvbnRlbnQ/KVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBkZWZpbmUgY29udGVudCwgcHJldiwgYW5kIG5leHQgZm9yIFJlcGxhY2VhYmxlLXR5cGVzIVwiXG4gICAgICBzdXBlciB1aWQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICAgI1xuICAgICMgUmV0dXJuIHRoZSBjb250ZW50IHRoYXQgdGhpcyBvcGVyYXRpb24gaG9sZHMuXG4gICAgI1xuICAgIHZhbDogKCktPlxuICAgICAgQGNvbnRlbnRcblxuICAgICNcbiAgICAjIFJlcGxhY2UgdGhlIGNvbnRlbnQgb2YgdGhpcyByZXBsYWNlYWJsZSB3aXRoIG5ldyBjb250ZW50LlxuICAgICNcbiAgICByZXBsYWNlOiAoY29udGVudCktPlxuICAgICAgQHBhcmVudC5yZXBsYWNlIGNvbnRlbnRcblxuICAgICNcbiAgICAjIElmIHBvc3NpYmxlIHNldCB0aGUgcmVwbGFjZSBtYW5hZ2VyIGluIHRoZSBjb250ZW50LlxuICAgICMgQHNlZSBXb3JkLnNldFJlcGxhY2VNYW5hZ2VyXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIG5vdCBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIGVsc2VcbiAgICAgICAgQGNvbnRlbnQuc2V0UmVwbGFjZU1hbmFnZXI/KEBwYXJlbnQpXG4gICAgICAgIHN1cGVyXG4gICAgICAgIEBcblxuICAgICNcbiAgICAjIEVuY29kZSB0aGlzIG9wZXJhdGlvbiBpbiBzdWNoIGEgd2F5IHRoYXQgaXQgY2FuIGJlIHBhcnNlZCBieSByZW1vdGUgcGVlcnMuXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIGpzb24gPVxuICAgICAgICB7XG4gICAgICAgICAgJ3R5cGUnOiBcIlJlcGxhY2VhYmxlXCJcbiAgICAgICAgICAnY29udGVudCc6IEBjb250ZW50LmdldFVpZCgpXG4gICAgICAgICAgJ1JlcGxhY2VNYW5hZ2VyJyA6IEBwYXJlbnQuZ2V0VWlkKClcbiAgICAgICAgICAncHJldic6IEBwcmV2X2NsLmdldFVpZCgpXG4gICAgICAgICAgJ25leHQnOiBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgIH1cbiAgICAgIGlmIEBvcmlnaW4/IGFuZCBAb3JpZ2luIGlzbnQgQHByZXZfY2xcbiAgICAgICAganNvbltcIm9yaWdpblwiXSA9IEBvcmlnaW4uZ2V0VWlkKClcbiAgICAgIGpzb25cblxuICBwYXJzZXJbXCJSZXBsYWNlYWJsZVwiXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ2NvbnRlbnQnIDogY29udGVudFxuICAgICAgJ1JlcGxhY2VNYW5hZ2VyJyA6IHBhcmVudFxuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdwcmV2JzogcHJldlxuICAgICAgJ25leHQnOiBuZXh0XG4gICAgICAnb3JpZ2luJyA6IG9yaWdpblxuICAgIH0gPSBqc29uXG4gICAgbmV3IFJlcGxhY2VhYmxlIGNvbnRlbnQsIHBhcmVudCwgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuXG5cbiAgdHlwZXNbJ0xpc3RNYW5hZ2VyJ10gPSBMaXN0TWFuYWdlclxuICB0eXBlc1snTWFwTWFuYWdlciddID0gTWFwTWFuYWdlclxuICB0eXBlc1snUmVwbGFjZU1hbmFnZXInXSA9IFJlcGxhY2VNYW5hZ2VyXG4gIHR5cGVzWydSZXBsYWNlYWJsZSddID0gUmVwbGFjZWFibGVcblxuICBiYXNpY190eXBlc1xuXG5cblxuXG5cblxuIiwic3RydWN0dXJlZF90eXBlc191bmluaXRpYWxpemVkID0gcmVxdWlyZSBcIi4vU3RydWN0dXJlZFR5cGVzXCJcblxubW9kdWxlLmV4cG9ydHMgPSAoSEIpLT5cbiAgc3RydWN0dXJlZF90eXBlcyA9IHN0cnVjdHVyZWRfdHlwZXNfdW5pbml0aWFsaXplZCBIQlxuICB0eXBlcyA9IHN0cnVjdHVyZWRfdHlwZXMudHlwZXNcbiAgcGFyc2VyID0gc3RydWN0dXJlZF90eXBlcy5wYXJzZXJcblxuICAjXG4gICMgQXQgdGhlIG1vbWVudCBUZXh0RGVsZXRlIHR5cGUgZXF1YWxzIHRoZSBEZWxldGUgdHlwZSBpbiBCYXNpY1R5cGVzLlxuICAjIEBzZWUgQmFzaWNUeXBlcy5EZWxldGVcbiAgI1xuICBjbGFzcyBUZXh0RGVsZXRlIGV4dGVuZHMgdHlwZXMuRGVsZXRlXG4gIHBhcnNlcltcIlRleHREZWxldGVcIl0gPSBwYXJzZXJbXCJEZWxldGVcIl1cblxuICAjXG4gICMgIEV4dGVuZHMgdGhlIGJhc2ljIEluc2VydCB0eXBlIHRvIGFuIG9wZXJhdGlvbiB0aGF0IGhvbGRzIGEgdGV4dCB2YWx1ZVxuICAjXG4gIGNsYXNzIFRleHRJbnNlcnQgZXh0ZW5kcyB0eXBlcy5JbnNlcnRcbiAgICAjXG4gICAgIyBAcGFyYW0ge1N0cmluZ30gY29udGVudCBUaGUgY29udGVudCBvZiB0aGlzIEluc2VydC10eXBlIE9wZXJhdGlvbi4gVXN1YWxseSB5b3UgcmVzdHJpY3QgdGhlIGxlbmd0aCBvZiBjb250ZW50IHRvIHNpemUgMVxuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKEBjb250ZW50LCB1aWQsIHByZXYsIG5leHQsIG9yaWdpbiktPlxuICAgICAgaWYgbm90IChwcmV2PyBhbmQgbmV4dD8pXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBtdXN0IGRlZmluZSBwcmV2LCBhbmQgbmV4dCBmb3IgVGV4dEluc2VydC10eXBlcyFcIlxuICAgICAgc3VwZXIgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cbiAgICAjXG4gICAgIyBSZXRyaWV2ZSB0aGUgZWZmZWN0aXZlIGxlbmd0aCBvZiB0aGUgJGNvbnRlbnQgb2YgdGhpcyBvcGVyYXRpb24uXG4gICAgI1xuICAgIGdldExlbmd0aDogKCktPlxuICAgICAgaWYgQGlzRGVsZXRlZCgpXG4gICAgICAgIDBcbiAgICAgIGVsc2VcbiAgICAgICAgQGNvbnRlbnQubGVuZ3RoXG5cbiAgICAjXG4gICAgIyBUaGUgcmVzdWx0IHdpbGwgYmUgY29uY2F0ZW5hdGVkIHdpdGggdGhlIHJlc3VsdHMgZnJvbSB0aGUgb3RoZXIgaW5zZXJ0IG9wZXJhdGlvbnNcbiAgICAjIGluIG9yZGVyIHRvIHJldHJpZXZlIHRoZSBjb250ZW50IG9mIHRoZSBlbmdpbmUuXG4gICAgIyBAc2VlIEhpc3RvcnlCdWZmZXIudG9FeGVjdXRlZEFycmF5XG4gICAgI1xuICAgIHZhbDogKGN1cnJlbnRfcG9zaXRpb24pLT5cbiAgICAgIGlmIEBpc0RlbGV0ZWQoKVxuICAgICAgICBcIlwiXG4gICAgICBlbHNlXG4gICAgICAgIEBjb250ZW50XG5cbiAgICAjXG4gICAgIyBDb252ZXJ0IGFsbCByZWxldmFudCBpbmZvcm1hdGlvbiBvZiB0aGlzIG9wZXJhdGlvbiB0byB0aGUganNvbi1mb3JtYXQuXG4gICAgIyBUaGlzIHJlc3VsdCBjYW4gYmUgc2VuZCB0byBvdGhlciBjbGllbnRzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID1cbiAgICAgICAge1xuICAgICAgICAgICd0eXBlJzogXCJUZXh0SW5zZXJ0XCJcbiAgICAgICAgICAnY29udGVudCc6IEBjb250ZW50XG4gICAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgICAncHJldic6IEBwcmV2X2NsLmdldFVpZCgpXG4gICAgICAgICAgJ25leHQnOiBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgICB9XG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyW1wiVGV4dEluc2VydFwiXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ2NvbnRlbnQnIDogY29udGVudFxuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdwcmV2JzogcHJldlxuICAgICAgJ25leHQnOiBuZXh0XG4gICAgICAnb3JpZ2luJyA6IG9yaWdpblxuICAgIH0gPSBqc29uXG4gICAgbmV3IFRleHRJbnNlcnQgY29udGVudCwgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICAjXG4gICMgSGFuZGxlcyBhIFRleHQtbGlrZSBkYXRhIHN0cnVjdHVyZXMgd2l0aCBzdXBwb3J0IGZvciBpbnNlcnRUZXh0L2RlbGV0ZVRleHQgYXQgYSB3b3JkLXBvc2l0aW9uLlxuICAjXG4gIGNsYXNzIFdvcmQgZXh0ZW5kcyB0eXBlcy5MaXN0TWFuYWdlclxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpbiktPlxuICAgICAgc3VwZXIgdWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cbiAgICAjXG4gICAgIyBJbnNlcnRzIGEgc3RyaW5nIGludG8gdGhlIHdvcmRcbiAgICAjXG4gICAgaW5zZXJ0VGV4dDogKHBvc2l0aW9uLCBjb250ZW50KS0+XG4gICAgICBvID0gQGdldE9wZXJhdGlvbkJ5UG9zaXRpb24gcG9zaXRpb25cbiAgICAgIGZvciBjIGluIGNvbnRlbnRcbiAgICAgICAgb3AgPSBuZXcgVGV4dEluc2VydCBjLCB1bmRlZmluZWQsIG8ucHJldl9jbCwgb1xuICAgICAgICBIQi5hZGRPcGVyYXRpb24ob3ApLmV4ZWN1dGUoKVxuXG4gICAgI1xuICAgICMgRGVsZXRlcyBhIHBhcnQgb2YgdGhlIHdvcmQuXG4gICAgI1xuICAgIGRlbGV0ZVRleHQ6IChwb3NpdGlvbiwgbGVuZ3RoKS0+XG4gICAgICBvID0gQGdldE9wZXJhdGlvbkJ5UG9zaXRpb24gcG9zaXRpb25cblxuICAgICAgZm9yIGkgaW4gWzAuLi5sZW5ndGhdXG4gICAgICAgIGQgPSBIQi5hZGRPcGVyYXRpb24obmV3IFRleHREZWxldGUgdW5kZWZpbmVkLCBvKS5leGVjdXRlKClcbiAgICAgICAgbyA9IG8ubmV4dF9jbFxuICAgICAgICB3aGlsZSBvLmlzRGVsZXRlZCgpXG4gICAgICAgICAgaWYgbyBpbnN0YW5jZW9mIHR5cGVzLkRlbGltaXRlclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IGNhbid0IGRlbGV0ZSBtb3JlIHRoYW4gdGhlcmUgaXMuLlwiXG4gICAgICAgICAgbyA9IG8ubmV4dF9jbFxuICAgICAgICBkLl9lbmNvZGUoKVxuXG4gICAgI1xuICAgICMgUmVwbGFjZSB0aGUgY29udGVudCBvZiB0aGlzIHdvcmQgd2l0aCBhbm90aGVyIG9uZS4gQ29uY3VycmVudCByZXBsYWNlbWVudHMgYXJlIG5vdCBtZXJnZWQhXG4gICAgIyBPbmx5IG9uZSBvZiB0aGUgcmVwbGFjZW1lbnRzIHdpbGwgYmUgdXNlZC5cbiAgICAjXG4gICAgIyBDYW4gb25seSBiZSB1c2VkIGlmIHRoZSBSZXBsYWNlTWFuYWdlciB3YXMgc2V0IVxuICAgICMgQHNlZSBXb3JkLnNldFJlcGxhY2VNYW5hZ2VyXG4gICAgI1xuICAgIHJlcGxhY2VUZXh0OiAodGV4dCktPlxuICAgICAgaWYgQHJlcGxhY2VfbWFuYWdlcj9cbiAgICAgICAgd29yZCA9IEhCLmFkZE9wZXJhdGlvbihuZXcgV29yZCB1bmRlZmluZWQpLmV4ZWN1dGUoKVxuICAgICAgICB3b3JkLmluc2VydFRleHQgMCwgdGV4dFxuICAgICAgICBAcmVwbGFjZV9tYW5hZ2VyLnJlcGxhY2Uod29yZClcbiAgICAgIGVsc2VcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiVGhpcyB0eXBlIGlzIGN1cnJlbnRseSBub3QgbWFpbnRhaW5lZCBieSBhIFJlcGxhY2VNYW5hZ2VyIVwiXG5cbiAgICAjXG4gICAgIyBAcmV0dXJucyBbSnNvbl0gQSBKc29uIG9iamVjdC5cbiAgICAjXG4gICAgdmFsOiAoKS0+XG4gICAgICBjID0gZm9yIG8gaW4gQHRvQXJyYXkoKVxuICAgICAgICBpZiBvLnZhbD9cbiAgICAgICAgICBvLnZhbCgpXG4gICAgICAgIGVsc2VcbiAgICAgICAgICBcIlwiXG4gICAgICBjLmpvaW4oJycpXG5cbiAgICAjXG4gICAgIyBJbiBtb3N0IGNhc2VzIHlvdSB3b3VsZCBlbWJlZCBhIFdvcmQgaW4gYSBSZXBsYWNlYWJsZSwgd2ljaCBpcyBoYW5kbGVkIGJ5IHRoZSBSZXBsYWNlTWFuYWdlciBpbiBvcmRlclxuICAgICMgdG8gcHJvdmlkZSByZXBsYWNlIGZ1bmN0aW9uYWxpdHkuXG4gICAgI1xuICAgIHNldFJlcGxhY2VNYW5hZ2VyOiAob3ApLT5cbiAgICAgIEBzYXZlT3BlcmF0aW9uICdyZXBsYWNlX21hbmFnZXInLCBvcFxuICAgICAgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zXG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID0ge1xuICAgICAgICAndHlwZSc6IFwiV29yZFwiXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICdiZWdpbm5pbmcnIDogQGJlZ2lubmluZy5nZXRVaWQoKVxuICAgICAgICAnZW5kJyA6IEBlbmQuZ2V0VWlkKClcbiAgICAgIH1cbiAgICAgIGlmIEBwcmV2X2NsP1xuICAgICAgICBqc29uWydwcmV2J10gPSBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgaWYgQG5leHRfY2w/XG4gICAgICAgIGpzb25bJ25leHQnXSA9IEBuZXh0X2NsLmdldFVpZCgpXG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyWydXb3JkJ10gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAnYmVnaW5uaW5nJyA6IGJlZ2lubmluZ1xuICAgICAgJ2VuZCcgOiBlbmRcbiAgICAgICdwcmV2JzogcHJldlxuICAgICAgJ25leHQnOiBuZXh0XG4gICAgICAnb3JpZ2luJyA6IG9yaWdpblxuICAgIH0gPSBqc29uXG4gICAgbmV3IFdvcmQgdWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cbiAgdHlwZXNbJ1RleHRJbnNlcnQnXSA9IFRleHRJbnNlcnRcbiAgdHlwZXNbJ1RleHREZWxldGUnXSA9IFRleHREZWxldGVcbiAgdHlwZXNbJ1dvcmQnXSA9IFdvcmRcbiAgc3RydWN0dXJlZF90eXBlc1xuXG5cbiJdfQ== diff --git a/build/browser/Frameworks/JsonYatta.min.js b/build/browser/Frameworks/JsonYatta.min.js new file mode 100644 index 00000000..25bf891f --- /dev/null +++ b/build/browser/Frameworks/JsonYatta.min.js @@ -0,0 +1 @@ +!function t(e,n,r){function i(u,s){if(!n[u]){if(!e[u]){var p="function"==typeof require&&require;if(!s&&p)return p(u,!0);if(o)return o(u,!0);throw new Error("Cannot find module '"+u+"'")}var a=n[u]={exports:{}};e[u][0].call(a.exports,function(t){var n=e[u][1][t];return i(n?n:t)},a,a.exports,t,e,n,r)}return n[u].exports}for(var o="function"==typeof require&&require,u=0;ur;r++)e=t[r],n.push(this.parseOperation(e));for(i=0,s=n.length;s>i;i++)e=n[i],this.HB.addOperation(e);for(o=0,p=n.length;p>o;o++)e=n[o],e.execute()||this.unprocessed_ops.push(e);return this.tryUnprocessed()},t.prototype.applyOpsCheckDouble=function(t){var e,n,r,i;for(i=[],n=0,r=t.length;r>n;n++)e=t[n],i.push(null!=this.HB.getOperation(e.uid)?this.applyOp(e):void 0);return i},t.prototype.applyOps=function(t){var e,n,r,i;for(i=[],n=0,r=t.length;r>n;n++)e=t[n],i.push(this.applyOp(e));return i},t.prototype.applyOp=function(t){var e;return e=this.parseOperation(t),this.HB.addToCounter(e),e.execute()?this.HB.addOperation(e):this.unprocessed_ops.push(e),this.tryUnprocessed()},t.prototype.tryUnprocessed=function(){var t,e,n,r,i,o,u;for(u=[];;){for(t=this.unprocessed_ops.length,n=[],o=this.unprocessed_ops,r=0,i=o.length;i>r;r++)e=o[r],e.execute()?this.HB.addOperation(e):n.push(e);if(this.unprocessed_ops=n,this.unprocessed_ops.length===t)break;u.push(void 0)}return u},t}(),e.exports=n},{}],2:[function(t,e){var n,r,i,o;o=t("../Types/JsonTypes"),r=t("../HistoryBuffer"),n=t("../Engine"),i=function(){function t(t,e){var i,u;this.HB=new r(t),u=o(this.HB),this.engine=new n(this.HB,u.parser),this.connector=new e(this.engine,this.HB,u.execution_listener,this),i=new u.types.JsonType(this.HB.getReservedUniqueIdentifier()),this.HB.addOperation(i).execute(),this.root_element=i}return t.prototype.getRootElement=function(){return this.root_element},t.prototype.getEngine=function(){return this.engine},t.prototype.getConnector=function(){return this.connector},t.prototype.getHistoryBuffer=function(){return this.HB},t.prototype.setMutableDefault=function(t){return this.root_element.setMutableDefault(t)},t.prototype.getUserId=function(){return this.HB.getUserId()},t.prototype.val=function(t,e,n){return this.root_element.val(t,e,n)},Object.defineProperty(t.prototype,"value",{get:function(){return this.root_element.value},set:function(t){var e,n,r;if(t.constructor==={}.constructor){r=[];for(e in t)n=t[e],r.push(this.val(e,n,"immutable"));return r}throw new Error("You must only set Object values!")}}),t}(),"undefined"!=typeof window&&null!==window&&(window.JsonYatta=i),e.exports=i},{"../Engine":1,"../HistoryBuffer":3,"../Types/JsonTypes":5}],3:[function(t,e){var n;n=function(){function t(t){this.user_id=t,this.operation_counter={},this.buffer={},this.change_listeners=[]}return t.prototype.getUserId=function(){return this.user_id},t.prototype.getReservedUniqueIdentifier=function(){return{creator:"_",op_number:"_"}},t.prototype.getOperationCounter=function(){var t,e,n,r;e={},r=this.operation_counter;for(n in r)t=r[n],e[n]=t;return e},t.prototype._encode=function(t){var e,n,r,i,o,u,s,p,a,c;null==t&&(t={}),e=[],p=function(e,n){if(null==e||null==n)throw new Error("dah!");return null==t[e]||t[e]<=n},c=this.buffer;for(s in c){a=c[s];for(o in a)if(n=a[o],!isNaN(parseInt(o))&&p(s,o)){if(r=n._encode(),null!=n.next_cl){for(i=n.next_cl;null!=i.next_cl&&p(i.creator,i.op_number);)i=i.next_cl;r.next=i.getUid()}else if(null!=n.prev_cl){for(u=n.prev_cl;null!=u.prev_cl&&p(i.creator,i.op_number);)u=u.prev_cl;r.prev=u.getUid()}e.push(r)}}return e},t.prototype.getNextOperationIdentifier=function(t){var e;return null==t&&(t=this.user_id),null==this.operation_counter[t]&&(this.operation_counter[t]=0),e={creator:t,op_number:this.operation_counter[t]},this.operation_counter[t]++,e},t.prototype.getOperation=function(t){var e;if(t instanceof Object)return null!=(e=this.buffer[t.creator])?e[t.op_number]:void 0;if(null!=t)throw new Error("This type of uid is not defined!")},t.prototype.addOperation=function(t){if(null==this.buffer[t.creator]&&(this.buffer[t.creator]={}),null!=this.buffer[t.creator][t.op_number])throw new Error("You must not overwrite operations!");return this.buffer[t.creator][t.op_number]=t,t},t.prototype.addToCounter=function(t){return null==this.operation_counter[t.creator]&&(this.operation_counter[t.creator]=0),"number"==typeof t.op_number&&t.creator!==this.getUserId()?this.operation_counter[t.creator]++:void 0},t}(),e.exports=n},{}],4:[function(t,e){var n={}.hasOwnProperty,r=function(t,e){function r(){this.constructor=t}for(var i in e)n.call(e,i)&&(t[i]=e[i]);return r.prototype=e.prototype,t.prototype=new r,t.__super__=e.prototype,t};e.exports=function(t){var e,n,i,o,u,s,p;return p={},s=[],u=function(){function e(e){null==e&&(e=t.getNextOperationIdentifier()),this.creator=e.creator,this.op_number=e.op_number}return e.prototype.on=function(t,e){var n;return null==this.event_listeners&&(this.event_listeners={}),null==(n=this.event_listeners)[t]&&(n[t]=[]),this.event_listeners[t].push(e)},e.prototype.callEvent=function(t,e){var n,r,i,o,u;if(null!=this.event_listeners[t]){for(o=this.event_listeners[t],u=[],r=0,i=o.length;i>r;r++)n=o[r],u.push(n.call(this,t,e));return u}},e.prototype.setParent=function(t){return this.parent=t},e.prototype.getUid=function(){return{creator:this.creator,op_number:this.op_number}},e.prototype.execute=function(){var t,e,n;for(this.is_executed=!0,e=0,n=s.length;n>e;e++)(t=s[e])(this._encode());return this},e.prototype.saveOperation=function(t,e){return null!=(null!=e?e.execute:void 0)?this[t]=e:null!=e?(null==this.unchecked&&(this.unchecked={}),this.unchecked[t]=e):void 0},e.prototype.validateSavedOperations=function(){var e,n,r,i,o,u;o={},i=this,u=this.unchecked;for(e in u)r=u[e],n=t.getOperation(r),n?this[e]=n:(o[e]=r,i=!1);return delete this.unchecked,i||(this.unchecked=o),i},e}(),e=function(t){function e(t,n){this.saveOperation("deletes",n),e.__super__.constructor.call(this,t)}return r(e,t),e.prototype._encode=function(){return{type:"Delete",uid:this.getUid(),deletes:this.deletes.getUid()}},e.prototype.execute=function(){return this.validateSavedOperations()?(this.deletes.applyDelete(this),e.__super__.execute.apply(this,arguments),this):!1},e}(u),p.Delete=function(t){var n,r;return r=t.uid,n=t.deletes,new e(r,n)},o=function(t){function e(t,n,r,i){this.saveOperation("prev_cl",n),this.saveOperation("next_cl",r),null!=i?this.saveOperation("origin",i):this.saveOperation("origin",n),e.__super__.constructor.call(this,t)}return r(e,t),e.prototype.applyDelete=function(t){return null==this.deleted_by&&(this.deleted_by=[]),this.deleted_by.push(t)},e.prototype.isDeleted=function(){var t;return(null!=(t=this.deleted_by)?t.length:void 0)>0},e.prototype.getDistanceToOrigin=function(){var t,e;for(t=0,e=this.prev_cl;;){if(this.origin===e)break;if(t++,this===this.prev_cl)throw new Error("this should not happen ;) ");e=e.prev_cl}return t},e.prototype.update_sl=function(){var t;return t=this.prev_cl,update("prev_cl","prev_sl"),update("next_cl","prev_sl")},e.prototype.execute=function(){var t,n,r,i,o;if(null!=this.is_executed)return this;if(this.validateSavedOperations()){if((null!=(i=this.prev_cl)?i.validateSavedOperations():void 0)&&(null!=(o=this.next_cl)?o.validateSavedOperations():void 0)&&this.prev_cl.next_cl!==this){for(t=0,r=this.prev_cl.next_cl,n=0;;){if(null==r&&(console.log(JSON.stringify(this.prev_cl.getUid())),console.log(JSON.stringify(this.next_cl.getUid()))),r===this.next_cl)break;if(r.getDistanceToOrigin()===n)r.creator0)for(;;){if(e=e.next_cl,e.isDeleted()||(t-=1),0===t)break;if(e instanceof c.Delimiter)throw new Error("position parameter exceeded the length of the document!")}return e},n}(c.Insert),u=function(e){function n(t,e,r,i,o,u,s){n.__super__.constructor.call(this,e,r,i,o,u,s),null!=t&&this.replace(t)}return i(n,e),n.prototype.replace=function(e){var n,r;return n=this.getLastOperation(),r=new s(e,this,void 0,n,n.next_cl),t.addOperation(r).execute()},n.prototype.val=function(){var t;if(t=this.getLastOperation(),t instanceof c.Delimiter)throw new Error("dtrn");return t.val()},n.prototype._encode=function(){var t;return t={type:"ReplaceManager",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&null!=this.next_cl&&(t.prev=this.prev_cl.getUid(),t.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},n}(r),a.ReplaceManager=function(t){var e,n,r,i,o,s,p;return n=t.content,p=t.uid,s=t.prev,i=t.next,o=t.origin,e=t.beginning,r=t.end,new u(n,p,e,r,s,i,o)},s=function(t){function e(t,n,r,i,o,u){if(this.saveOperation("content",t),this.saveOperation("parent",n),null==i||null==o||null==t)throw new Error("You must define content, prev, and next for Replaceable-types!");e.__super__.constructor.call(this,r,i,o,u)}return i(e,t),e.prototype.val=function(){return this.content},e.prototype.replace=function(t){return this.parent.replace(t)},e.prototype.execute=function(){var t;return this.validateSavedOperations()?("function"==typeof(t=this.content).setReplaceManager&&t.setReplaceManager(this.parent),e.__super__.execute.apply(this,arguments),this):!1},e.prototype._encode=function(){var t;return t={type:"Replaceable",content:this.content.getUid(),ReplaceManager:this.parent.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid(),uid:this.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},e}(c.Insert),a.Replaceable=function(t){var e,n,r,i,o,u;return e=t.content,i=t.ReplaceManager,u=t.uid,o=t.prev,n=t.next,r=t.origin,new s(e,i,u,o,n,r)},c.ListManager=r,c.MapManager=o,c.ReplaceManager=u,c.Replaceable=s,p}},{"./BasicTypes":4}],7:[function(t,e){var n,r={}.hasOwnProperty,i=function(t,e){function n(){this.constructor=t}for(var i in e)r.call(e,i)&&(t[i]=e[i]);return n.prototype=e.prototype,t.prototype=new n,t.__super__=e.prototype,t};n=t("./StructuredTypes"),e.exports=function(t){var e,r,o,u,s,p;return s=n(t),p=s.types,u=s.parser,e=function(t){function e(){return e.__super__.constructor.apply(this,arguments)}return i(e,t),e}(p.Delete),u.TextDelete=u.Delete,r=function(t){function e(t,n,r,i,o){if(this.content=t,null==r||null==i)throw new Error("You must define prev, and next for TextInsert-types!");e.__super__.constructor.call(this,n,r,i,o)}return i(e,t),e.prototype.getLength=function(){return this.isDeleted()?0:this.content.length},e.prototype.val=function(){return this.isDeleted()?"":this.content},e.prototype._encode=function(){var t;return t={type:"TextInsert",content:this.content,uid:this.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},e}(p.Insert),u.TextInsert=function(t){var e,n,i,o,u;return e=t.content,u=t.uid,o=t.prev,n=t.next,i=t.origin,new r(e,u,o,n,i)},o=function(n){function o(t,e,n,r,i,u){o.__super__.constructor.call(this,t,e,n,r,i,u)}return i(o,n),o.prototype.insertText=function(e,n){var i,o,u,s,p,a;for(o=this.getOperationByPosition(e),a=[],s=0,p=n.length;p>s;s++)i=n[s],u=new r(i,void 0,o.prev_cl,o),a.push(t.addOperation(u).execute());return a},o.prototype.deleteText=function(n,r){var i,o,u,s,a;for(u=this.getOperationByPosition(n),a=[],o=s=0;r>=0?r>s:s>r;o=r>=0?++s:--s){for(i=t.addOperation(new e(void 0,u)).execute(),u=u.next_cl;u.isDeleted();){if(u instanceof p.Delimiter)throw new Error("You can't delete more than there is..");u=u.next_cl}a.push(i._encode())}return a},o.prototype.replaceText=function(e){var n;if(null!=this.replace_manager)return n=t.addOperation(new o(void 0)).execute(),n.insertText(0,e),this.replace_manager.replace(n);throw new Error("This type is currently not maintained by a ReplaceManager!")},o.prototype.val=function(){var t,e;return t=function(){var t,n,r,i;for(r=this.toArray(),i=[],t=0,n=r.length;n>t;t++)e=r[t],i.push(null!=e.val?e.val():"");return i}.call(this),t.join("")},o.prototype.setReplaceManager=function(t){return this.saveOperation("replace_manager",t),this.validateSavedOperations},o.prototype._encode=function(){var t;return t={type:"Word",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&(t.prev=this.prev_cl.getUid()),null!=this.next_cl&&(t.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},o}(p.ListManager),u.Word=function(t){var e,n,r,i,u,s;return s=t.uid,e=t.beginning,n=t.end,u=t.prev,r=t.next,i=t.origin,new o(s,e,n,u,r,i)},p.TextInsert=r,p.TextDelete=e,p.Word=o,s}},{"./StructuredTypes":6}]},{},[2]); \ No newline at end of file diff --git a/build/browser/Frameworks/TextYatta.js b/build/browser/Frameworks/TextYatta.js new file mode 100644 index 00000000..d5fbe431 --- /dev/null +++ b/build/browser/Frameworks/TextYatta.js @@ -0,0 +1,1114 @@ +(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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0; + }; + + Insert.prototype.getDistanceToOrigin = function() { + var d, o; + d = 0; + o = this.prev_cl; + while (true) { + if (this.origin === o) { + break; + } + d++; + if (this === this.prev_cl) { + throw new Error("this should not happen ;) "); + } + o = o.prev_cl; + } + return d; + }; + + Insert.prototype.update_sl = function() { + var o; + o = this.prev_cl; + ({ + update: function(dest_cl, dest_sl) { + var _results; + _results = []; + while (true) { + if (o.isDeleted()) { + _results.push(o = o[dest_cl]); + } else { + this[dest_sl] = o; + break; + } + } + return _results; + } + }); + update("prev_cl", "prev_sl"); + return update("next_cl", "prev_sl"); + }; + + Insert.prototype.execute = function() { + var distance_to_origin, i, o, _ref, _ref1; + if (this.is_executed != null) { + return this; + } + if (!this.validateSavedOperations()) { + return false; + } else { + if (((_ref = this.prev_cl) != null ? _ref.validateSavedOperations() : void 0) && ((_ref1 = this.next_cl) != null ? _ref1.validateSavedOperations() : void 0) && this.prev_cl.next_cl !== this) { + distance_to_origin = 0; + o = this.prev_cl.next_cl; + i = 0; + while (true) { + if (o == null) { + console.log(JSON.stringify(this.prev_cl.getUid())); + console.log(JSON.stringify(this.next_cl.getUid())); + } + if (o !== this.next_cl) { + if (o.getDistanceToOrigin() === i) { + if (o.creator < this.creator) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else if (o.getDistanceToOrigin() < i) { + if (i - distance_to_origin <= o.getDistanceToOrigin()) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else { + break; + } + i++; + o = o.next_cl; + } else { + break; + } + } + this.next_cl = this.prev_cl.next_cl; + this.prev_cl.next_cl = this; + this.next_cl.prev_cl = this; + } + Insert.__super__.execute.apply(this, arguments); + return this; + } + }; + + return Insert; + + })(Operation); + ImmutableObject = (function(_super) { + __extends(ImmutableObject, _super); + + function ImmutableObject(uid, content, prev, next, origin) { + this.content = content; + ImmutableObject.__super__.constructor.call(this, uid, prev, next, origin); + } + + ImmutableObject.prototype.val = function() { + return this.content; + }; + + ImmutableObject.prototype._encode = function() { + var json; + json = { + 'type': "ImmutableObject", + 'uid': this.getUid(), + 'content': this.content + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ImmutableObject; + + })(Insert); + parser['ImmutableObject'] = function(json) { + var content, next, origin, prev, uid; + uid = json['uid'], content = json['content'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new ImmutableObject(uid, content, prev, next, origin); + }; + Delimiter = (function(_super) { + __extends(Delimiter, _super); + + function Delimiter(uid, prev_cl, next_cl, origin) { + this.saveOperation('prev_cl', prev_cl); + this.saveOperation('next_cl', next_cl); + this.saveOperation('origin', prev_cl); + Delimiter.__super__.constructor.call(this, uid); + } + + Delimiter.prototype.isDeleted = function() { + return false; + }; + + Delimiter.prototype.execute = function() { + var _ref, _ref1; + if (((_ref = this.unchecked) != null ? _ref['next_cl'] : void 0) != null) { + return Delimiter.__super__.execute.apply(this, arguments); + } else if ((_ref1 = this.unchecked) != null ? _ref1['prev_cl'] : void 0) { + if (this.validateSavedOperations()) { + if (this.prev_cl.next_cl != null) { + throw new Error("Probably duplicated operations"); + } + this.prev_cl.next_cl = this; + delete this.prev_cl.unchecked.next_cl; + return Delimiter.__super__.execute.apply(this, arguments); + } else { + return false; + } + } else if ((this.prev_cl != null) && (this.prev_cl.next_cl == null)) { + delete this.prev_cl.unchecked.next_cl; + return this.prev_cl.next_cl = this; + } else if ((this.prev_cl != null) || (this.next_cl != null)) { + return Delimiter.__super__.execute.apply(this, arguments); + } else { + throw new Error("Delimiter is unsufficient defined!"); + } + }; + + Delimiter.prototype._encode = function() { + var _ref, _ref1; + return { + 'type': "Delimiter", + 'uid': this.getUid(), + 'prev': (_ref = this.prev_cl) != null ? _ref.getUid() : void 0, + 'next': (_ref1 = this.next_cl) != null ? _ref1.getUid() : void 0 + }; + }; + + return Delimiter; + + })(Operation); + parser['Delimiter'] = function(json) { + var next, prev, uid; + uid = json['uid'], prev = json['prev'], next = json['next']; + return new Delimiter(uid, prev, next); + }; + return { + 'types': { + 'Delete': Delete, + 'Insert': Insert, + 'Delimiter': Delimiter, + 'Operation': Operation, + 'ImmutableObject': ImmutableObject + }, + 'parser': parser, + 'execution_listener': execution_listener + }; +}; + + +},{}],5:[function(require,module,exports){ +var basic_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +basic_types_uninitialized = require("./BasicTypes"); + +module.exports = function(HB) { + var AddName, ListManager, MapManager, ReplaceManager, Replaceable, basic_types, parser, types; + basic_types = basic_types_uninitialized(HB); + types = basic_types.types; + parser = basic_types.parser; + MapManager = (function(_super) { + __extends(MapManager, _super); + + function MapManager(uid) { + this.map = {}; + MapManager.__super__.constructor.call(this, uid); + } + + MapManager.prototype.val = function(name, content) { + var o, obj, result, _ref, _ref1; + if (content != null) { + if (this.map[name] == null) { + HB.addOperation(new AddName(void 0, this, name)).execute(); + } + this.map[name].replace(content); + return this; + } else if (name != null) { + obj = (_ref = this.map[name]) != null ? _ref.val() : void 0; + if (obj instanceof types.ImmutableObject) { + return obj.val(); + } else { + return obj; + } + } else { + result = {}; + _ref1 = this.map; + for (name in _ref1) { + o = _ref1[name]; + obj = o.val(); + if (obj instanceof types.ImmutableObject || obj instanceof MapManager) { + obj = obj.val(); + } + result[name] = obj; + } + return result; + } + }; + + return MapManager; + + })(types.Operation); + AddName = (function(_super) { + __extends(AddName, _super); + + function AddName(uid, map_manager, name) { + this.name = name; + this.saveOperation('map_manager', map_manager); + AddName.__super__.constructor.call(this, uid); + } + + AddName.prototype.execute = function() { + var beg, end, uid_beg, uid_end, uid_r; + if (!this.validateSavedOperations()) { + return false; + } else { + uid_r = this.map_manager.getUid(); + uid_r.op_number = "_" + uid_r.op_number + "_RM_" + this.name; + if (HB.getOperation(uid_r) == null) { + uid_beg = this.map_manager.getUid(); + uid_beg.op_number = "_" + uid_beg.op_number + "_RM_" + this.name + "_beginning"; + uid_end = this.map_manager.getUid(); + uid_end.op_number = "_" + uid_end.op_number + "_RM_" + this.name + "_end"; + beg = HB.addOperation(new types.Delimiter(uid_beg, void 0, uid_end)).execute(); + end = HB.addOperation(new types.Delimiter(uid_end, beg, void 0)).execute(); + this.map_manager.map[this.name] = HB.addOperation(new ReplaceManager(void 0, uid_r, beg, end)).execute(); + } + return AddName.__super__.execute.apply(this, arguments); + } + }; + + AddName.prototype._encode = function() { + return { + 'type': "AddName", + 'uid': this.getUid(), + 'map_manager': this.map_manager.getUid(), + 'name': this.name + }; + }; + + return AddName; + + })(types.Operation); + parser['AddName'] = function(json) { + var map_manager, name, uid; + map_manager = json['map_manager'], uid = json['uid'], name = json['name']; + return new AddName(uid, map_manager, name); + }; + ListManager = (function(_super) { + __extends(ListManager, _super); + + function ListManager(uid, beginning, end, prev, next, origin) { + if ((beginning != null) && (end != null)) { + this.saveOperation('beginning', beginning); + this.saveOperation('end', end); + } else { + this.beginning = HB.addOperation(new types.Delimiter(void 0, void 0, void 0)); + this.end = HB.addOperation(new types.Delimiter(void 0, this.beginning, void 0)); + this.beginning.next_cl = this.end; + this.beginning.execute(); + this.end.execute(); + } + ListManager.__super__.constructor.call(this, uid, prev, next, origin); + } + + ListManager.prototype.getLastOperation = function() { + return this.end.prev_cl; + }; + + ListManager.prototype.getFirstOperation = function() { + return this.beginning.next_cl; + }; + + ListManager.prototype.toArray = function() { + var o, result; + o = this.beginning.next_cl; + result = []; + while (o !== this.end) { + result.push(o); + o = o.next_cl; + } + return result; + }; + + ListManager.prototype.getOperationByPosition = function(position) { + var o; + o = this.beginning.next_cl; + if (position > 0) { + while (true) { + o = o.next_cl; + if (!o.isDeleted()) { + position -= 1; + } + if (position === 0) { + break; + } + if (o instanceof types.Delimiter) { + throw new Error("position parameter exceeded the length of the document!"); + } + } + } + return o; + }; + + return ListManager; + + })(types.Insert); + ReplaceManager = (function(_super) { + __extends(ReplaceManager, _super); + + function ReplaceManager(initial_content, uid, beginning, end, prev, next, origin) { + ReplaceManager.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + if (initial_content != null) { + this.replace(initial_content); + } + } + + ReplaceManager.prototype.replace = function(content) { + var o, op; + o = this.getLastOperation(); + op = new Replaceable(content, this, void 0, o, o.next_cl); + return HB.addOperation(op).execute(); + }; + + ReplaceManager.prototype.val = function() { + var o; + o = this.getLastOperation(); + if (o instanceof types.Delimiter) { + throw new Error("dtrn"); + } + return o.val(); + }; + + ReplaceManager.prototype._encode = function() { + var json; + json = { + 'type': "ReplaceManager", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if ((this.prev_cl != null) && (this.next_cl != null)) { + json['prev'] = this.prev_cl.getUid(); + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ReplaceManager; + + })(ListManager); + parser["ReplaceManager"] = function(json) { + var beginning, content, end, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], beginning = json['beginning'], end = json['end']; + return new ReplaceManager(content, uid, beginning, end, prev, next, origin); + }; + Replaceable = (function(_super) { + __extends(Replaceable, _super); + + function Replaceable(content, parent, uid, prev, next, origin) { + this.saveOperation('content', content); + this.saveOperation('parent', parent); + if (!((prev != null) && (next != null) && (content != null))) { + throw new Error("You must define content, prev, and next for Replaceable-types!"); + } + Replaceable.__super__.constructor.call(this, uid, prev, next, origin); + } + + Replaceable.prototype.val = function() { + return this.content; + }; + + Replaceable.prototype.replace = function(content) { + return this.parent.replace(content); + }; + + Replaceable.prototype.execute = function() { + var _base; + if (!this.validateSavedOperations()) { + return false; + } else { + if (typeof (_base = this.content).setReplaceManager === "function") { + _base.setReplaceManager(this.parent); + } + Replaceable.__super__.execute.apply(this, arguments); + return this; + } + }; + + Replaceable.prototype._encode = function() { + var json; + json = { + 'type': "Replaceable", + 'content': this.content.getUid(), + 'ReplaceManager': this.parent.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid(), + 'uid': this.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Replaceable; + + })(types.Insert); + parser["Replaceable"] = function(json) { + var content, next, origin, parent, prev, uid; + content = json['content'], parent = json['ReplaceManager'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Replaceable(content, parent, uid, prev, next, origin); + }; + types['ListManager'] = ListManager; + types['MapManager'] = MapManager; + types['ReplaceManager'] = ReplaceManager; + types['Replaceable'] = Replaceable; + return basic_types; +}; + + +},{"./BasicTypes":4}],6:[function(require,module,exports){ +var structured_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +structured_types_uninitialized = require("./StructuredTypes"); + +module.exports = function(HB) { + var TextDelete, TextInsert, Word, parser, structured_types, types; + structured_types = structured_types_uninitialized(HB); + types = structured_types.types; + parser = structured_types.parser; + TextDelete = (function(_super) { + __extends(TextDelete, _super); + + function TextDelete() { + return TextDelete.__super__.constructor.apply(this, arguments); + } + + return TextDelete; + + })(types.Delete); + parser["TextDelete"] = parser["Delete"]; + TextInsert = (function(_super) { + __extends(TextInsert, _super); + + function TextInsert(content, uid, prev, next, origin) { + this.content = content; + if (!((prev != null) && (next != null))) { + throw new Error("You must define prev, and next for TextInsert-types!"); + } + TextInsert.__super__.constructor.call(this, uid, prev, next, origin); + } + + TextInsert.prototype.getLength = function() { + if (this.isDeleted()) { + return 0; + } else { + return this.content.length; + } + }; + + TextInsert.prototype.val = function(current_position) { + if (this.isDeleted()) { + return ""; + } else { + return this.content; + } + }; + + TextInsert.prototype._encode = function() { + var json; + json = { + 'type': "TextInsert", + 'content': this.content, + 'uid': this.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return TextInsert; + + })(types.Insert); + parser["TextInsert"] = function(json) { + var content, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new TextInsert(content, uid, prev, next, origin); + }; + Word = (function(_super) { + __extends(Word, _super); + + function Word(uid, beginning, end, prev, next, origin) { + Word.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + } + + Word.prototype.insertText = function(position, content) { + var c, o, op, _i, _len, _results; + o = this.getOperationByPosition(position); + _results = []; + for (_i = 0, _len = content.length; _i < _len; _i++) { + c = content[_i]; + op = new TextInsert(c, void 0, o.prev_cl, o); + _results.push(HB.addOperation(op).execute()); + } + return _results; + }; + + Word.prototype.deleteText = function(position, length) { + var d, i, o, _i, _results; + o = this.getOperationByPosition(position); + _results = []; + for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) { + d = HB.addOperation(new TextDelete(void 0, o)).execute(); + o = o.next_cl; + while (o.isDeleted()) { + if (o instanceof types.Delimiter) { + throw new Error("You can't delete more than there is.."); + } + o = o.next_cl; + } + _results.push(d._encode()); + } + return _results; + }; + + Word.prototype.replaceText = function(text) { + var word; + if (this.replace_manager != null) { + word = HB.addOperation(new Word(void 0)).execute(); + word.insertText(0, text); + return this.replace_manager.replace(word); + } else { + throw new Error("This type is currently not maintained by a ReplaceManager!"); + } + }; + + Word.prototype.val = function() { + var c, o; + c = (function() { + var _i, _len, _ref, _results; + _ref = this.toArray(); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + o = _ref[_i]; + if (o.val != null) { + _results.push(o.val()); + } else { + _results.push(""); + } + } + return _results; + }).call(this); + return c.join(''); + }; + + Word.prototype.setReplaceManager = function(op) { + this.saveOperation('replace_manager', op); + return this.validateSavedOperations; + }; + + Word.prototype._encode = function() { + var json; + json = { + 'type': "Word", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Word; + + })(types.ListManager); + parser['Word'] = function(json) { + var beginning, end, next, origin, prev, uid; + uid = json['uid'], beginning = json['beginning'], end = json['end'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Word(uid, beginning, end, prev, next, origin); + }; + types['TextInsert'] = TextInsert; + types['TextDelete'] = TextDelete; + types['Word'] = Word; + return structured_types; +}; + + +},{"./StructuredTypes":5}]},{},[2]) +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL0VuZ2luZS5jb2ZmZWUiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL0ZyYW1ld29ya3MvVGV4dFlhdHRhLmNvZmZlZSIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9saWIvSGlzdG9yeUJ1ZmZlci5jb2ZmZWUiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL1R5cGVzL0Jhc2ljVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9TdHJ1Y3R1cmVkVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9UZXh0VHlwZXMuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDSUEsSUFBQSxNQUFBOztBQUFBO0FBTWUsRUFBQSxnQkFBRSxFQUFGLEVBQU8sTUFBUCxHQUFBO0FBQ1gsSUFEWSxJQUFDLENBQUEsS0FBQSxFQUNiLENBQUE7QUFBQSxJQURpQixJQUFDLENBQUEsU0FBQSxNQUNsQixDQUFBO0FBQUEsSUFBQSxJQUFDLENBQUEsZUFBRCxHQUFtQixFQUFuQixDQURXO0VBQUEsQ0FBYjs7QUFBQSxtQkFNQSxjQUFBLEdBQWdCLFNBQUMsSUFBRCxHQUFBO0FBQ2QsUUFBQSxVQUFBO0FBQUEsSUFBQSxVQUFBLEdBQWEsSUFBQyxDQUFBLE1BQU8sQ0FBQSxJQUFJLENBQUMsSUFBTCxDQUFyQixDQUFBO0FBQ0EsSUFBQSxJQUFHLGtCQUFIO2FBQ0UsVUFBQSxDQUFXLElBQVgsRUFERjtLQUFBLE1BQUE7QUFHRSxZQUFVLElBQUEsS0FBQSxDQUFPLDBD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S0EsaUJBNUtlO0FBQUEsQ0FGakIsQ0FBQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpfXZhciBmPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChmLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGYsZi5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJcclxuI1xyXG4jIFRoZSBFbmdpbmUgaGFuZGxlcyBob3cgYW5kIGluIHdoaWNoIG9yZGVyIHRvIGV4ZWN1dGUgb3BlcmF0aW9ucyBhbmQgYWRkIG9wZXJhdGlvbnMgdG8gdGhlIEhpc3RvcnlCdWZmZXIuXHJcbiNcclxuY2xhc3MgRW5naW5lXHJcblxyXG4gICNcclxuICAjIEBwYXJhbSB7SGlzdG9yeUJ1ZmZlcn0gSEJcclxuICAjIEBwYXJhbSB7QXJyYXl9IHBhcnNlciBEZWZpbmVzIGhvdyB0byBwYXJzZSBlbmNvZGVkIG1lc3NhZ2VzLlxyXG4gICNcclxuICBjb25zdHJ1Y3RvcjogKEBIQiwgQHBhcnNlciktPlxyXG4gICAgQHVucHJvY2Vzc2VkX29wcyA9IFtdXHJcblxyXG4gICNcclxuICAjIFBhcnNlcyBhbiBvcGVyYXRpbyBmcm9tIHRoZSBqc29uIGZvcm1hdC4gSXQgdXNlcyB0aGUgc3BlY2lmaWVkIHBhcnNlciBpbiB5b3VyIE9wZXJhdGlvblR5cGUgbW9kdWxlLlxyXG4gICNcclxuICBwYXJzZU9wZXJhdGlvbjogKGpzb24pLT5cclxuICAgIHR5cGVQYXJzZXIgPSBAcGFyc2VyW2pzb24udHlwZV1cclxuICAgIGlmIHR5cGVQYXJzZXI/XHJcbiAgICAgIHR5cGVQYXJzZXIganNvblxyXG4gICAgZWxzZVxyXG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgZm9yZ290IHRvIHNwZWNpZnkgYSBwYXJzZXIgZm9yIHR5cGUgI3tqc29uLnR5cGV9LiBUaGUgbWVzc2FnZSBpcyAje0pTT04uc3RyaW5naWZ5IGpzb259LlwiXHJcblxyXG4gICNcclxuICAjIEFwcGx5IGEgc2V0IG9mIG9wZXJhdGlvbnMuIEUuZy4gdGhlIG9wZXJhdGlvbnMgeW91IHJlY2VpdmVkIGZyb20gYW5vdGhlciB1c2VycyBIQi50b0pzb24oKS5cclxuICAjIEBub3RlIFlvdSBtdXN0IG5vdCB1c2UgdGhpcyBtZXRob2Qgd2hlbiB5b3UgYWxyZWFkeSBoYXZlIG9wcyBpbiB5b3VyIEhCIVxyXG4gICNcclxuICBhcHBseU9wc0J1bmRsZTogKG9wc19qc29uKS0+XHJcbiAgICBvcHMgPSBbXVxyXG4gICAgZm9yIG8gaW4gb3BzX2pzb25cclxuICAgICAgb3BzLnB1c2ggQHBhcnNlT3BlcmF0aW9uIG9cclxuICAgIGZvciBvIGluIG9wc1xyXG4gICAgICBASEIuYWRkT3BlcmF0aW9uIG9cclxuICAgIGZvciBvIGluIG9wc1xyXG4gICAgICBpZiBub3Qgby5leGVjdXRlKClcclxuICAgICAgICBAdW5wcm9jZXNzZWRfb3BzLnB1c2ggb1xyXG4gICAgQHRyeVVucHJvY2Vzc2VkKClcclxuXHJcbiAgI1xyXG4gICMgU2FtZSBhcyBhcHBseU9wcyBidXQgb3BlcmF0aW9ucyB0aGF0IGFyZSBhbHJlYWR5IGluIHRoZSBIQiBhcmUgbm90IGFwcGxpZWQuXHJcbiAgIyBAc2VlIEVuZ2luZS5hcHBseU9wc1xyXG4gICNcclxuICBhcHBseU9wc0NoZWNrRG91YmxlOiAob3BzX2pzb24pLT5cclxuICAgIGZvciBvIGluIG9wc19qc29uXHJcbiAgICAgIGlmIEBIQi5nZXRPcGVyYXRpb24oby51aWQpP1xyXG4gICAgICAgIEBhcHBseU9wIG9cclxuXHJcbiAgI1xyXG4gICMgQXBwbHkgYSBzZXQgb2Ygb3BlcmF0aW9ucy4gKEhlbHBlciBmb3IgdXNpbmcgYXBwbHlPcCBvbiBBcnJheXMpXHJcbiAgIyBAc2VlIEVuZ2luZS5hcHBseU9wXHJcbiAgYXBwbHlPcHM6IChvcHNfanNvbiktPlxyXG4gICAgZm9yIG8gaW4gb3BzX2pzb25cclxuICAgICAgQGFwcGx5T3Agb1xyXG5cclxuICAjXHJcbiAgIyBBcHBseSBhbiBvcGVyYXRpb24gdGhhdCB5b3UgcmVjZWl2ZWQgZnJvbSBhbm90aGVyIHBlZXIuXHJcbiAgI1xyXG4gIGFwcGx5T3A6IChvcF9qc29uKS0+XHJcbiAgICAjICRwYXJzZV9hbmRfZXhlY3V0ZSB3aWxsIHJldHVybiBmYWxzZSBpZiAkb19qc29uIHdhcyBwYXJzZWQgYW5kIGV4ZWN1dGVkLCBvdGhlcndpc2UgdGhlIHBhcnNlZCBvcGVyYWRpb25cclxuICAgIG8gPSBAcGFyc2VPcGVyYXRpb24gb3BfanNvblxyXG4gICAgQEhCLmFkZFRvQ291bnRlciBvXHJcbiAgICAjIEBIQi5hZGRPcGVyYXRpb24gb1xyXG4gICAgaWYgbm90IG8uZXhlY3V0ZSgpXHJcbiAgICAgIEB1bnByb2Nlc3NlZF9vcHMucHVzaCBvXHJcbiAgICBlbHNlXHJcbiAgICAgIEBIQi5hZGRPcGVyYXRpb24gb1xyXG4gICAgQHRyeVVucHJvY2Vzc2VkKClcclxuXHJcbiAgI1xyXG4gICMgQ2FsbCB0aGlzIG1ldGhvZCB3aGVuIHlvdSBhcHBsaWVkIGEgbmV3IG9wZXJhdGlvbi5cclxuICAjIEl0IGNoZWNrcyBpZiBvcGVyYXRpb25zIHRoYXQgd2VyZSBwcmV2aW91c2x5IG5vdCBleGVjdXRhYmxlIGFyZSBub3cgZXhlY3V0YWJsZS5cclxuICAjXHJcbiAgdHJ5VW5wcm9jZXNzZWQ6ICgpLT5cclxuICAgIHdoaWxlIHRydWVcclxuICAgICAgb2xkX2xlbmd0aCA9IEB1bnByb2Nlc3NlZF9vcHMubGVuZ3RoXHJcbiAgICAgIHVucHJvY2Vzc2VkID0gW11cclxuICAgICAgZm9yIG9wIGluIEB1bnByb2Nlc3NlZF9vcHNcclxuICAgICAgICBpZiBub3Qgb3AuZXhlY3V0ZSgpXHJcbiAgICAgICAgICB1bnByb2Nlc3NlZC5wdXNoIG9wXHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgQEhCLmFkZE9wZXJhdGlvbiBvcFxyXG4gICAgICBAdW5wcm9jZXNzZWRfb3BzID0gdW5wcm9jZXNzZWRcclxuICAgICAgaWYgQHVucHJvY2Vzc2VkX29wcy5sZW5ndGggaXMgb2xkX2xlbmd0aFxyXG4gICAgICAgIGJyZWFrXHJcblxyXG5cclxuXHJcblxyXG5tb2R1bGUuZXhwb3J0cyA9IEVuZ2luZVxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG4iLCJcbnRleHRfdHlwZXNfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuLi9UeXBlcy9UZXh0VHlwZXNcIlxuSGlzdG9yeUJ1ZmZlciA9IHJlcXVpcmUgXCIuLi9IaXN0b3J5QnVmZmVyXCJcbkVuZ2luZSA9IHJlcXVpcmUgXCIuLi9FbmdpbmVcIlxuXG4jXG4jIEZyYW1ld29yayBmb3IgVGV4dCBEYXRhc3RydWN0dXJlcy5cbiNcbmNsYXNzIFRleHRZYXR0YVxuXG4gICNcbiAgIyBAcGFyYW0ge1N0cmluZ30gdXNlcl9pZCBVbmlxZSB1c2VyIGlkIHRoYXQgZGVmaW5lcyB0aGlzIHBlZXIuXG4gICMgQHBhcmFtIHtDb25uZWN0b3J9IENvbm5lY3RvciBUaGUgY29ubmVjdG9yIGRlZmluZXMgaG93IHlvdSBjb25uZWN0IHRvIHRoZSBvdGhlciBwZWVycy5cbiAgI1xuICBjb25zdHJ1Y3RvcjogKHVzZXJfaWQsIENvbm5lY3RvciktPlxuICAgIEBIQiA9IG5ldyBIaXN0b3J5QnVmZmVyIHVzZXJfaWRcbiAgICB0ZXh0X3R5cGVzID0gdGV4dF90eXBlc191bmluaXRpYWxpemVkIEBIQlxuICAgIEBlbmdpbmUgPSBuZXcgRW5naW5lIEBIQiwgdGV4dF90eXBlcy5wYXJzZXJcbiAgICBAY29ubmVjdG9yID0gbmV3IENvbm5lY3RvciBAZW5naW5lLCBASEIsIHRleHRfdHlwZXMuZXhlY3V0aW9uX2xpc3RlbmVyXG5cbiAgICBmaXJzdF93b3JkID0gbmV3IHRleHRfdHlwZXMudHlwZXMuV29yZCB1bmRlZmluZWRcbiAgICBASEIuYWRkT3BlcmF0aW9uKGZpcnN0X3dvcmQpLmV4ZWN1dGUoKVxuICAgIEByb290X2VsZW1lbnQgPSBmaXJzdF93b3JkXG5cbiAgI1xuICAjIEByZXN1bHQgV29yZFxuICAjXG4gIGdldFJvb3RFbGVtZW50OiAoKS0+XG4gICAgQHJvb3RfZWxlbWVudFxuXG4gICNcbiAgIyBAc2VlIEVuZ2luZVxuICAjXG4gIGdldEVuZ2luZTogKCktPlxuICAgIEBlbmdpbmVcblxuICAjXG4gICMgR2V0IHRoZSBpbml0aWFsaXplZCBjb25uZWN0b3IuXG4gICNcbiAgZ2V0Q29ubmVjdG9yOiAoKS0+XG4gICAgQGNvbm5lY3RvclxuXG4gICNcbiAgIyBAc2VlIEhpc3RvcnlCdWZmZXJcbiAgI1xuICBnZXRIaXN0b3J5QnVmZmVyOiAoKS0+XG4gICAgQEhCXG5cbiAgI1xuICAjIEdldCB0aGUgVXNlcklkIGZyb20gdGhlIEhpc3RvcnlCdWZmZXIgb2JqZWN0LlxuICAjIEluIG1vc3QgY2FzZXMgdGhpcyB3aWxsIGJlIHRoZSBzYW1lIGFzIHRoZSB1c2VyX2lkIHZhbHVlIHdpdGggd2hpY2hcbiAgIyBKc29uWWF0dGEgd2FzIGluaXRpYWxpemVkIChEZXBlbmRpbmcgb24gdGhlIEhpc3RvcnlCdWZmZXIgaW1wbGVtZW50YXRpb24pLlxuICAjXG4gIGdldFVzZXJJZDogKCktPlxuICAgIEBIQi5nZXRVc2VySWQoKVxuXG4gICNcbiAgIyBAc2VlIEpzb25UeXBlLnZhbFxuICAjXG4gIHZhbDogKCktPlxuICAgIEByb290X2VsZW1lbnQudmFsKClcblxuICAjXG4gICMgQHNlZSBXb3JkLmluc2VydFRleHRcbiAgI1xuICBpbnNlcnRUZXh0OiAocG9zLCBjb250ZW50KS0+XG4gICAgQHJvb3RfZWxlbWVudC5pbnNlcnRUZXh0IHBvcywgY29udGVudFxuXG4gICNcbiAgIyBAc2VlIFdvcmQuZGVsZXRlVGV4dFxuICAjXG4gIGRlbGV0ZVRleHQ6IChwb3MsIGxlbmd0aCktPlxuICAgIEByb290X2VsZW1lbnQuZGVsZXRlVGV4dCBwb3MsIGxlbmd0aFxuXG4gICNcbiAgIyBAc2VlIFdvcmQucmVwbGFjZVRleHRcbiAgI1xuICByZXBsYWNlVGV4dDogKHRleHQpLT5cbiAgICBAcm9vdF9lbGVtZW50LnJlcGxhY2VUZXh0IHRleHRcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFRleHRZYXR0YVxuIiwiXG4jXG4jIEFuIG9iamVjdCB0aGF0IGhvbGRzIGFsbCBhcHBsaWVkIG9wZXJhdGlvbnMuXG4jXG4jIEBub3RlIFRoZSBIaXN0b3J5QnVmZmVyIGlzIGNvbW1vbmx5IGFiYnJldmlhdGVkIHRvIEhCLlxuI1xuY2xhc3MgSGlzdG9yeUJ1ZmZlclxuXG4gICNcbiAgIyBDcmVhdGVzIGFuIGVtcHR5IEhCLlxuICAjIEBwYXJhbSB7T2JqZWN0fSB1c2VyX2lkIENyZWF0b3Igb2YgdGhlIEhCLlxuICAjXG4gIGNvbnN0cnVjdG9yOiAoQHVzZXJfaWQpLT5cbiAgICBAb3BlcmF0aW9uX2NvdW50ZXIgPSB7fVxuICAgIEBidWZmZXIgPSB7fVxuICAgIEBjaGFuZ2VfbGlzdGVuZXJzID0gW11cblxuICAjXG4gICMgR2V0IHRoZSB1c2VyIGlkIHdpdGggd2ljaCB0aGUgSGlzdG9yeSBCdWZmZXIgd2FzIGluaXRpYWxpemVkLlxuICAjXG4gIGdldFVzZXJJZDogKCktPlxuICAgIEB1c2VyX2lkXG5cbiAgI1xuICAjIFRoZXJlIGlzIG9ubHkgb25lIHJlc2VydmVkIHVuaXF1ZSBpZGVudGlmaWVyICh1aWQpLCBzbyB1c2UgaXQgd2lzZWx5LlxuICAjIEkgcHJvcG9zZSB0byB1c2UgaXQgaW4geW91ciBGcmFtZXdvcmssIHRvIGNyZWF0ZSBzb21ldGhpbmcgbGlrZSBhIHJvb3QgZWxlbWVudC5cbiAgIyBBbiBvcGVyYXRpb24gd2l0aCB0aGlzIGlkZW50aWZpZXIgaXMgbm90IHByb3BhZ2F0ZWQgdG8gb3RoZXIgY2xpZW50cy5cbiAgIyBUaGlzIGlzIHdoeSBldmVyeWJvZGUgbXVzdCBjcmVhdGUgdGhlIHNhbWUgb3BlcmF0aW9uIHdpdGggdGhpcyB1aWQuXG4gICNcbiAgZ2V0UmVzZXJ2ZWRVbmlxdWVJZGVudGlmaWVyOiAoKS0+XG4gICAge1xuICAgICAgY3JlYXRvciA6ICdfJ1xuICAgICAgb3BfbnVtYmVyIDogJ18nXG4gICAgfVxuXG4gICNcbiAgIyBHZXQgdGhlIG9wZXJhdGlvbiBjb3VudGVyIHRoYXQgZGVzY3JpYmVzIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBkb2N1bWVudC5cbiAgI1xuICBnZXRPcGVyYXRpb25Db3VudGVyOiAoKS0+XG4gICAgcmVzID0ge31cbiAgICBmb3IgdXNlcixjdG4gb2YgQG9wZXJhdGlvbl9jb3VudGVyXG4gICAgICByZXNbdXNlcl0gPSBjdG5cbiAgICByZXNcblxuICAjXG4gICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgI1xuICBfZW5jb2RlOiAoc3RhdGVfdmVjdG9yPXt9KS0+XG4gICAganNvbiA9IFtdXG4gICAgdW5rbm93biA9ICh1c2VyLCBvX251bWJlciktPlxuICAgICAgaWYgKG5vdCB1c2VyPykgb3IgKG5vdCBvX251bWJlcj8pXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcImRhaCFcIlxuICAgICAgbm90IHN0YXRlX3ZlY3Rvclt1c2VyXT8gb3Igc3RhdGVfdmVjdG9yW3VzZXJdIDw9IG9fbnVtYmVyXG5cbiAgICBmb3IgdV9uYW1lLHVzZXIgb2YgQGJ1ZmZlclxuICAgICAgZm9yIG9fbnVtYmVyLG8gb2YgdXNlclxuICAgICAgICBpZiBub3QgaXNOYU4ocGFyc2VJbnQob19udW1iZXIpKSBhbmQgdW5rbm93bih1X25hbWUsIG9fbnVtYmVyKVxuICAgICAgICAgIG9fanNvbiA9IG8uX2VuY29kZSgpXG4gICAgICAgICAgaWYgby5uZXh0X2NsP1xuICAgICAgICAgICAgb19uZXh0ID0gby5uZXh0X2NsXG4gICAgICAgICAgICB3aGlsZSBvX25leHQubmV4dF9jbD8gYW5kIHVua25vd24ob19uZXh0LmNyZWF0b3IsIG9fbmV4dC5vcF9udW1iZXIpXG4gICAgICAgICAgICAgIG9fbmV4dCA9IG9fbmV4dC5uZXh0X2NsXG4gICAgICAgICAgICBvX2pzb24ubmV4dCA9IG9fbmV4dC5nZXRVaWQoKVxuICAgICAgICAgIGVsc2UgaWYgby5wcmV2X2NsP1xuICAgICAgICAgICAgb19wcmV2ID0gby5wcmV2X2NsXG4gICAgICAgICAgICB3aGlsZSBvX3ByZXYucHJldl9jbD8gYW5kIHVua25vd24ob19uZXh0LmNyZWF0b3IsIG9fbmV4dC5vcF9udW1iZXIpXG4gICAgICAgICAgICAgIG9fcHJldiA9IG9fcHJldi5wcmV2X2NsXG4gICAgICAgICAgICBvX2pzb24ucHJldiA9IG9fcHJldi5nZXRVaWQoKVxuICAgICAgICAgIGpzb24ucHVzaCBvX2pzb25cblxuICAgIGpzb25cblxuICAjXG4gICMgR2V0IHRoZSBudW1iZXIgb2Ygb3BlcmF0aW9ucyB0aGF0IHdlcmUgY3JlYXRlZCBieSBhIHVzZXIuXG4gICMgQWNjb3JkaW5nbHkgeW91IHdpbGwgZ2V0IHRoZSBuZXh0IG9wZXJhdGlvbiBudW1iZXIgdGhhdCBpcyBleHBlY3RlZCBmcm9tIHRoYXQgdXNlci5cbiAgIyBUaGlzIHdpbGwgaW5jcmVtZW50IHRoZSBvcGVyYXRpb24gY291bnRlci5cbiAgI1xuICBnZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllcjogKHVzZXJfaWQpLT5cbiAgICBpZiBub3QgdXNlcl9pZD9cbiAgICAgIHVzZXJfaWQgPSBAdXNlcl9pZFxuICAgIGlmIG5vdCBAb3BlcmF0aW9uX2NvdW50ZXJbdXNlcl9pZF0/XG4gICAgICBAb3BlcmF0aW9uX2NvdW50ZXJbdXNlcl9pZF0gPSAwXG4gICAgdWlkID1cbiAgICAgICdjcmVhdG9yJyA6IHVzZXJfaWRcbiAgICAgICdvcF9udW1iZXInIDogQG9wZXJhdGlvbl9jb3VudGVyW3VzZXJfaWRdXG4gICAgQG9wZXJhdGlvbl9jb3VudGVyW3VzZXJfaWRdKytcbiAgICB1aWRcblxuICAjXG4gICMgUmV0cmlldmUgYW4gb3BlcmF0aW9uIGZyb20gYSB1bmlxdWUgaWQuXG4gICNcbiAgZ2V0T3BlcmF0aW9uOiAodWlkKS0+XG4gICAgaWYgdWlkIGluc3RhbmNlb2YgT2JqZWN0XG4gICAgICBAYnVmZmVyW3VpZC5jcmVhdG9yXT9bdWlkLm9wX251bWJlcl1cbiAgICBlbHNlIGlmIG5vdCB1aWQ/XG4gICAgZWxzZVxuICAgICAgdGhyb3cgbmV3IEVycm9yIFwiVGhpcyB0eXBlIG9mIHVpZCBpcyBub3QgZGVmaW5lZCFcIlxuICAjXG4gICMgQWRkIGFuIG9wZXJhdGlvbiB0byB0aGUgSEIuIE5vdGUgdGhhdCB0aGlzIHdpbGwgbm90IGxpbmsgaXQgYWdhaW5zdFxuICAjIG90aGVyIG9wZXJhdGlvbnMgKGl0IHdvbnQgZXhlY3V0ZWQpXG4gICNcbiAgYWRkT3BlcmF0aW9uOiAobyktPlxuICAgIGlmIG5vdCBAYnVmZmVyW28uY3JlYXRvcl0/XG4gICAgICBAYnVmZmVyW28uY3JlYXRvcl0gPSB7fVxuICAgIGlmIEBidWZmZXJbby5jcmVhdG9yXVtvLm9wX251bWJlcl0/XG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBub3Qgb3ZlcndyaXRlIG9wZXJhdGlvbnMhXCJcbiAgICBAYnVmZmVyW28uY3JlYXRvcl1bby5vcF9udW1iZXJdID0gb1xuICAgIG9cblxuICAjXG4gICMgSW5jcmVtZW50IHRoZSBvcGVyYXRpb25fY291bnRlciB0aGF0IGRlZmluZXMgdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIEVuZ2luZS5cbiAgI1xuICBhZGRUb0NvdW50ZXI6IChvKS0+XG4gICAgaWYgbm90IEBvcGVyYXRpb25fY291bnRlcltvLmNyZWF0b3JdP1xuICAgICAgQG9wZXJhdGlvbl9jb3VudGVyW28uY3JlYXRvcl0gPSAwXG4gICAgaWYgdHlwZW9mIG8ub3BfbnVtYmVyIGlzICdudW1iZXInIGFuZCBvLmNyZWF0b3IgaXNudCBAZ2V0VXNlcklkKClcbiAgICAgIEBvcGVyYXRpb25fY291bnRlcltvLmNyZWF0b3JdKytcbiAgICAjaWYgQG9wZXJhdGlvbl9jb3VudGVyW28uY3JlYXRvcl0gaXNudCAoby5vcF9udW1iZXIgKyAxKVxuICAgICAgI2NvbnNvbGUubG9nIChAb3BlcmF0aW9uX2NvdW50ZXJbby5jcmVhdG9yXSAtIChvLm9wX251bWJlciArIDEpKVxuICAgICAgI2NvbnNvbGUubG9nIG9cbiAgICAgICN0aHJvdyBuZXcgRXJyb3IgXCJZb3UgZG9uJ3QgcmVjZWl2ZSBvcGVyYXRpb25zIGluIHRoZSBwcm9wZXIgb3JkZXIuIFRyeSBjb3VudGluZyBsaWtlIHRoaXMgMCwxLDIsMyw0LC4uIDspXCJcblxubW9kdWxlLmV4cG9ydHMgPSBIaXN0b3J5QnVmZmVyXG4iLCJtb2R1bGUuZXhwb3J0cyA9IChIQiktPlxuICAjIEBzZWUgRW5naW5lLnBhcnNlXG4gIHBhcnNlciA9IHt9XG4gIGV4ZWN1dGlvbl9saXN0ZW5lciA9IFtdXG5cbiAgI1xuICAjIEEgZ2VuZXJpYyBpbnRlcmZhY2UgdG8gb3BlcmF0aW9ucy5cbiAgI1xuICAjIEFuIG9wZXJhdGlvbiBoYXMgdGhlIGZvbGxvd2luZyBtZXRob2RzOlxuICAjIF9lbmNvZGU6IGVuY29kZXMgYW4gb3BlcmF0aW9uIChuZWVkZWQgb25seSBpZiBpbnN0YW5jZSBvZiB0aGlzIG9wZXJhdGlvbiBpcyBzZW50KS5cbiAgIyBleGVjdXRlOiBleGVjdXRlIHRoZSBlZmZlY3RzIG9mIHRoaXMgb3BlcmF0aW9ucy4gR29vZCBleGFtcGxlcyBhcmUgSW5zZXJ0LXR5cGUgYW5kIEFkZE5hbWUtdHlwZVxuICAjIHZhbDogaW4gdGhlIGNhc2UgdGhhdCB0aGUgb3BlcmF0aW9uIGhvbGRzIGEgdmFsdWVcbiAgI1xuICAjIEZ1cnRoZXJtb3JlIGFuIGVuY29kYWJsZSBvcGVyYXRpb24gaGFzIGEgcGFyc2VyLlxuICAjXG4gIGNsYXNzIE9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHNlZSBIaXN0b3J5QnVmZmVyLmdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkKS0+XG4gICAgICBpZiBub3QgdWlkP1xuICAgICAgICB1aWQgPSBIQi5nZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllcigpXG4gICAgICB7XG4gICAgICAgICdjcmVhdG9yJzogQGNyZWF0b3JcbiAgICAgICAgJ29wX251bWJlcicgOiBAb3BfbnVtYmVyXG4gICAgICB9ID0gdWlkXG5cbiAgICAjXG4gICAgIyBBZGQgYW4gZXZlbnQgbGlzdGVuZXIuIEl0IGRlcGVuZHMgb24gdGhlIG9wZXJhdGlvbiB3aGljaCBldmVudHMgYXJlIHN1cHBvcnRlZC5cbiAgICAjIEBwYXJhbSB7U3RyaW5nfSBldmVudCBOYW1lIG9mIHRoZSBldmVudC5cbiAgICAjIEBwYXJhbSB7RnVuY3Rpb259IGYgZiBpcyBleGVjdXRlZCBpbiBjYXNlIHRoZSBldmVudCBmaXJlcy5cbiAgICAjXG4gICAgb246IChldmVudCwgZiktPlxuICAgICAgQGV2ZW50X2xpc3RlbmVycyA/PSB7fVxuICAgICAgQGV2ZW50X2xpc3RlbmVyc1tldmVudF0gPz0gW11cbiAgICAgIEBldmVudF9saXN0ZW5lcnNbZXZlbnRdLnB1c2ggZlxuXG4gICAgI1xuICAgICMgRmlyZSBhbiBldmVudC5cbiAgICAjIFRPRE86IERvIHNvbWV0aGluZyB3aXRoIHRpbWVvdXRzLiBZb3UgZG9uJ3Qgd2FudCB0aGlzIHRvIGZpcmUgZm9yIGV2ZXJ5IG9wZXJhdGlvbiAoZS5nLiBpbnNlcnQpLlxuICAgICNcbiAgICBjYWxsRXZlbnQ6IChldmVudCwgYXJncyktPlxuICAgICAgaWYgQGV2ZW50X2xpc3RlbmVyc1tldmVudF0/XG4gICAgICAgIGZvciBmIGluIEBldmVudF9saXN0ZW5lcnNbZXZlbnRdXG4gICAgICAgICAgZi5jYWxsIEAsIGV2ZW50LCBhcmdzXG5cbiAgICAjXG4gICAgIyBTZXQgdGhlIHBhcmVudCBvZiB0aGlzIG9wZXJhdGlvbi5cbiAgICAjXG4gICAgc2V0UGFyZW50OiAobyktPlxuICAgICAgQHBhcmVudCA9IG9cblxuICAgICNcbiAgICAjIENvbXB1dGVzIGEgdW5pcXVlIGlkZW50aWZpZXIgKHVpZCkgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICBnZXRVaWQ6ICgpLT5cbiAgICAgIHsgJ2NyZWF0b3InOiBAY3JlYXRvciwgJ29wX251bWJlcic6IEBvcF9udW1iZXIgfVxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIE5vdGlmeSB0aGUgYWxsIHRoZSBsaXN0ZW5lcnMuXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIEBpc19leGVjdXRlZCA9IHRydWVcbiAgICAgIGZvciBsIGluIGV4ZWN1dGlvbl9saXN0ZW5lclxuICAgICAgICBsIEBfZW5jb2RlKClcbiAgICAgIEBcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBPcGVyYXRpb25zIG1heSBkZXBlbmQgb24gb3RoZXIgb3BlcmF0aW9ucyAobGlua2VkIGxpc3RzLCBldGMuKS5cbiAgICAjIFRoZSBzYXZlT3BlcmF0aW9uIGFuZCB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucyBtZXRob2RzIHByb3ZpZGVcbiAgICAjIGFuIGVhc3kgd2F5IHRvIHJlZmVyIHRvIHRoZXNlIG9wZXJhdGlvbnMgdmlhIGFuIHVpZCBvciBvYmplY3QgcmVmZXJlbmNlLlxuICAgICNcbiAgICAjIEZvciBleGFtcGxlOiBXZSBjYW4gY3JlYXRlIGEgbmV3IERlbGV0ZSBvcGVyYXRpb24gdGhhdCBkZWxldGVzIHRoZSBvcGVyYXRpb24gJG8gbGlrZSB0aGlzXG4gICAgIyAgICAgLSB2YXIgZCA9IG5ldyBEZWxldGUodWlkLCAkbyk7ICAgb3JcbiAgICAjICAgICAtIHZhciBkID0gbmV3IERlbGV0ZSh1aWQsICRvLmdldFVpZCgpKTtcbiAgICAjIEVpdGhlciB3YXkgd2Ugd2FudCB0byBhY2Nlc3MgJG8gdmlhIGQuZGVsZXRlcy4gSW4gdGhlIHNlY29uZCBjYXNlIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zIG11c3QgYmUgY2FsbGVkIGZpcnN0LlxuICAgICNcbiAgICAjIEBvdmVybG9hZCBzYXZlT3BlcmF0aW9uKG5hbWUsIG9wX3VpZClcbiAgICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGlvbi4gQWZ0ZXIgdmFsaWRhdGluZyAod2l0aCB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucykgdGhlIGluc3RhbnRpYXRlZCBvcGVyYXRpb24gd2lsbCBiZSBhY2Nlc3NpYmxlIHZpYSB0aGlzW25hbWVdLlxuICAgICMgICBAcGFyYW0ge09iamVjdH0gb3BfdWlkIEEgdWlkIHRoYXQgcmVmZXJzIHRvIGFuIG9wZXJhdGlvblxuICAgICMgQG92ZXJsb2FkIHNhdmVPcGVyYXRpb24obmFtZSwgb3ApXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpb24uIEFmdGVyIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiBvcCBpcyBhY2Nlc3NpYmxlIHZpYSB0aGlzW25hbWVdLlxuICAgICMgICBAcGFyYW0ge09wZXJhdGlvbn0gb3AgQW4gT3BlcmF0aW9uIG9iamVjdFxuICAgICNcbiAgICBzYXZlT3BlcmF0aW9uOiAobmFtZSwgb3ApLT5cblxuICAgICAgI1xuICAgICAgIyBFdmVyeSBpbnN0YW5jZSBvZiAkT3BlcmF0aW9uIG11c3QgaGF2ZSBhbiAkZXhlY3V0ZSBmdW5jdGlvbi5cbiAgICAgICMgV2UgdXNlIGR1Y2stdHlwaW5nIHRvIGNoZWNrIGlmIG9wIGlzIGluc3RhbnRpYXRlZCBzaW5jZSB0aGVyZVxuICAgICAgIyBjb3VsZCBleGlzdCBtdWx0aXBsZSBjbGFzc2VzIG9mICRPcGVyYXRpb25cbiAgICAgICNcbiAgICAgIGlmIG9wPy5leGVjdXRlP1xuICAgICAgICAjIGlzIGluc3RhbnRpYXRlZFxuICAgICAgICBAW25hbWVdID0gb3BcbiAgICAgIGVsc2UgaWYgb3A/XG4gICAgICAgICMgbm90IGluaXRpYWxpemVkLiBEbyBpdCB3aGVuIGNhbGxpbmcgJHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgQHVuY2hlY2tlZCA/PSB7fVxuICAgICAgICBAdW5jaGVja2VkW25hbWVdID0gb3BcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBBZnRlciBjYWxsaW5nIHRoaXMgZnVuY3Rpb24gYWxsIG5vdCBpbnN0YW50aWF0ZWQgb3BlcmF0aW9ucyB3aWxsIGJlIGFjY2Vzc2libGUuXG4gICAgIyBAc2VlIE9wZXJhdGlvbi5zYXZlT3BlcmF0aW9uXG4gICAgI1xuICAgICMgQHJldHVybiBbQm9vbGVhbl0gV2hldGhlciBpdCB3YXMgcG9zc2libGUgdG8gaW5zdGFudGlhdGUgYWxsIG9wZXJhdGlvbnMuXG4gICAgI1xuICAgIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zOiAoKS0+XG4gICAgICB1bmluc3RhbnRpYXRlZCA9IHt9XG4gICAgICBzdWNjZXNzID0gQFxuICAgICAgZm9yIG5hbWUsIG9wX3VpZCBvZiBAdW5jaGVja2VkXG4gICAgICAgIG9wID0gSEIuZ2V0T3BlcmF0aW9uIG9wX3VpZFxuICAgICAgICBpZiBvcFxuICAgICAgICAgIEBbbmFtZV0gPSBvcFxuICAgICAgICBlbHNlXG4gICAgICAgICAgdW5pbnN0YW50aWF0ZWRbbmFtZV0gPSBvcF91aWRcbiAgICAgICAgICBzdWNjZXNzID0gZmFsc2VcbiAgICAgIGRlbGV0ZSBAdW5jaGVja2VkXG4gICAgICBpZiBub3Qgc3VjY2Vzc1xuICAgICAgICBAdW5jaGVja2VkID0gdW5pbnN0YW50aWF0ZWRcbiAgICAgIHN1Y2Nlc3NcblxuXG5cbiAgI1xuICAjIEEgc2ltcGxlIERlbGV0ZS10eXBlIG9wZXJhdGlvbiB0aGF0IGRlbGV0ZXMgYW4gSW5zZXJ0LXR5cGUgb3BlcmF0aW9uLlxuICAjXG4gIGNsYXNzIERlbGV0ZSBleHRlbmRzIE9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IGRlbGV0ZXMgVUlEIG9yIHJlZmVyZW5jZSBvZiB0aGUgb3BlcmF0aW9uIHRoYXQgdGhpcyB0byBiZSBkZWxldGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgZGVsZXRlcyktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ2RlbGV0ZXMnLCBkZWxldGVzXG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBDb252ZXJ0IGFsbCByZWxldmFudCBpbmZvcm1hdGlvbiBvZiB0aGlzIG9wZXJhdGlvbiB0byB0aGUganNvbi1mb3JtYXQuXG4gICAgIyBUaGlzIHJlc3VsdCBjYW4gYmUgc2VudCB0byBvdGhlciBjbGllbnRzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICB7XG4gICAgICAgICd0eXBlJzogXCJEZWxldGVcIlxuICAgICAgICAndWlkJzogQGdldFVpZCgpXG4gICAgICAgICdkZWxldGVzJzogQGRlbGV0ZXMuZ2V0VWlkKClcbiAgICAgIH1cblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBBcHBseSB0aGUgZGVsZXRpb24uXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIEBkZWxldGVzLmFwcGx5RGVsZXRlIEBcbiAgICAgICAgc3VwZXJcbiAgICAgICAgQFxuICAgICAgZWxzZVxuICAgICAgICBmYWxzZVxuXG4gICNcbiAgIyBEZWZpbmUgaG93IHRvIHBhcnNlIERlbGV0ZSBvcGVyYXRpb25zLlxuICAjXG4gIHBhcnNlclsnRGVsZXRlJ10gPSAobyktPlxuICAgIHtcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAnZGVsZXRlcyc6IGRlbGV0ZXNfdWlkXG4gICAgfSA9IG9cbiAgICBuZXcgRGVsZXRlIHVpZCwgZGVsZXRlc191aWRcblxuICAjXG4gICMgQSBzaW1wbGUgaW5zZXJ0LXR5cGUgb3BlcmF0aW9uLlxuICAjXG4gICMgQW4gaW5zZXJ0IG9wZXJhdGlvbiBpcyBhbHdheXMgcG9zaXRpb25lZCBiZXR3ZWVuIHR3byBvdGhlciBpbnNlcnQgb3BlcmF0aW9ucy5cbiAgIyBJbnRlcm5hbGx5IHRoaXMgaXMgcmVhbGl6ZWQgYXMgYXNzb2NpYXRpdmUgbGlzdHMsIHdoZXJlYnkgZWFjaCBpbnNlcnQgb3BlcmF0aW9uIGhhcyBhIHByZWRlY2Vzc29yIGFuZCBhIHN1Y2Nlc3Nvci5cbiAgIyBGb3IgdGhlIHNha2Ugb2YgZWZmaWNpZW5jeSB3ZSBtYWludGFpbiB0d28gbGlzdHM6XG4gICMgICAtIFRoZSBzaG9ydC1saXN0IChhYmJyZXYuIHNsKSBtYWludGFpbnMgb25seSB0aGUgb3BlcmF0aW9ucyB0aGF0IGFyZSBub3QgZGVsZXRlZFxuICAjICAgLSBUaGUgY29tcGxldGUtbGlzdCAoYWJicmV2LiBjbCkgbWFpbnRhaW5zIGFsbCBvcGVyYXRpb25zXG4gICNcbiAgY2xhc3MgSW5zZXJ0IGV4dGVuZHMgT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gcHJldl9jbCBUaGUgcHJlZGVjZXNzb3Igb2YgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGNvbXBsZXRlLWxpc3QgKGNsKVxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG5leHRfY2wgVGhlIHN1Y2Nlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgI1xuICAgICMgQHNlZSBIaXN0b3J5QnVmZmVyLmdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBwcmV2X2NsLCBuZXh0X2NsLCBvcmlnaW4pLT5cbiAgICAgIEBzYXZlT3BlcmF0aW9uICdwcmV2X2NsJywgcHJldl9jbFxuICAgICAgQHNhdmVPcGVyYXRpb24gJ25leHRfY2wnLCBuZXh0X2NsXG4gICAgICBpZiBvcmlnaW4/XG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBvcmlnaW5cbiAgICAgIGVsc2VcbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ29yaWdpbicsIHByZXZfY2xcbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjXG4gICAgYXBwbHlEZWxldGU6IChvKS0+XG4gICAgICBAZGVsZXRlZF9ieSA/PSBbXVxuICAgICAgQGRlbGV0ZWRfYnkucHVzaCBvXG5cbiAgICAjXG4gICAgIyBJZiBpc0RlbGV0ZWQoKSBpcyB0cnVlIHRoaXMgb3BlcmF0aW9uIHdvbid0IGJlIG1haW50YWluZWQgaW4gdGhlIHNsXG4gICAgI1xuICAgIGlzRGVsZXRlZDogKCktPlxuICAgICAgQGRlbGV0ZWRfYnk/Lmxlbmd0aCA+IDBcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBUaGUgYW1vdW50IG9mIHBvc2l0aW9ucyB0aGF0ICR0aGlzIG9wZXJhdGlvbiB3YXMgbW92ZWQgdG8gdGhlIHJpZ2h0LlxuICAgICNcbiAgICBnZXREaXN0YW5jZVRvT3JpZ2luOiAoKS0+XG4gICAgICBkID0gMFxuICAgICAgbyA9IEBwcmV2X2NsXG4gICAgICB3aGlsZSB0cnVlXG4gICAgICAgIGlmIEBvcmlnaW4gaXMgb1xuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGQrK1xuICAgICAgICAjVE9ETzogZGVsZXRlIHRoaXNcbiAgICAgICAgaWYgQCBpcyBAcHJldl9jbFxuICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcInRoaXMgc2hvdWxkIG5vdCBoYXBwZW4gOykgXCJcbiAgICAgICAgbyA9IG8ucHJldl9jbFxuICAgICAgZFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIFVwZGF0ZSB0aGUgc2hvcnQgbGlzdFxuICAgICMgVE9ETyAoVW51c2VkKVxuICAgIHVwZGF0ZV9zbDogKCktPlxuICAgICAgbyA9IEBwcmV2X2NsXG4gICAgICB1cGRhdGU6IChkZXN0X2NsLGRlc3Rfc2wpLT5cbiAgICAgICAgd2hpbGUgdHJ1ZVxuICAgICAgICAgIGlmIG8uaXNEZWxldGVkKClcbiAgICAgICAgICAgIG8gPSBvW2Rlc3RfY2xdXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgQFtkZXN0X3NsXSA9IG9cblxuICAgICAgICAgICAgYnJlYWtcbiAgICAgIHVwZGF0ZSBcInByZXZfY2xcIiwgXCJwcmV2X3NsXCJcbiAgICAgIHVwZGF0ZSBcIm5leHRfY2xcIiwgXCJwcmV2X3NsXCJcblxuXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgSW5jbHVkZSB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgYXNzb2NpYXRpdmUgbGlzdHMuXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEBpc19leGVjdXRlZD9cbiAgICAgICAgcmV0dXJuIEBcbiAgICAgIGlmIG5vdCBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIGVsc2VcbiAgICAgICAgaWYgQHByZXZfY2w/LnZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKCkgYW5kIEBuZXh0X2NsPy52YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpIGFuZCBAcHJldl9jbC5uZXh0X2NsIGlzbnQgQFxuICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IDBcbiAgICAgICAgICBvID0gQHByZXZfY2wubmV4dF9jbFxuICAgICAgICAgIGkgPSAwXG4gICAgICAgICAgIyAkdGhpcyBoYXMgdG8gZmluZCBhIHVuaXF1ZSBwb3NpdGlvbiBiZXR3ZWVuIG9yaWdpbiBhbmQgdGhlIG5leHQga25vd24gY2hhcmFjdGVyXG4gICAgICAgICAgIyBjYXNlIDE6ICRvcmlnaW4gZXF1YWxzICRvLm9yaWdpbjogdGhlICRjcmVhdG9yIHBhcmFtZXRlciBkZWNpZGVzIGlmIGxlZnQgb3IgcmlnaHRcbiAgICAgICAgICAjICAgICAgICAgbGV0ICRPTD0gW28xLG8yLG8zLG80XSwgd2hlcmVieSAkdGhpcyBpcyB0byBiZSBpbnNlcnRlZCBiZXR3ZWVuIG8xIGFuZCBvNFxuICAgICAgICAgICMgICAgICAgICBvMixvMyBhbmQgbzQgb3JpZ2luIGlzIDEgKHRoZSBwb3NpdGlvbiBvZiBvMilcbiAgICAgICAgICAjICAgICAgICAgdGhlcmUgaXMgdGhlIGNhc2UgdGhhdCAkdGhpcy5jcmVhdG9yIDwgbzIuY3JlYXRvciwgYnV0IG8zLmNyZWF0b3IgPCAkdGhpcy5jcmVhdG9yXG4gICAgICAgICAgIyAgICAgICAgIHRoZW4gbzIga25vd3MgbzMuIFNpbmNlIG9uIGFub3RoZXIgY2xpZW50ICRPTCBjb3VsZCBiZSBbbzEsbzMsbzRdIHRoZSBwcm9ibGVtIGlzIGNvbXBsZXhcbiAgICAgICAgICAjICAgICAgICAgdGhlcmVmb3JlICR0aGlzIHdvdWxkIGJlIGFsd2F5cyB0byB0aGUgcmlnaHQgb2YgbzNcbiAgICAgICAgICAjIGNhc2UgMjogJG9yaWdpbiA8ICRvLm9yaWdpblxuICAgICAgICAgICMgICAgICAgICBpZiBjdXJyZW50ICR0aGlzIGluc2VydF9wb3NpdGlvbiA+ICRvIG9yaWdpbjogJHRoaXMgaW5zXG4gICAgICAgICAgIyAgICAgICAgIGVsc2UgJGluc2VydF9wb3NpdGlvbiB3aWxsIG5vdCBjaGFuZ2UgKG1heWJlIHdlIGVuY291bnRlciBjYXNlIDEgbGF0ZXIsIHRoZW4gdGhpcyB3aWxsIGJlIHRvIHRoZSByaWdodCBvZiAkbylcbiAgICAgICAgICAjIGNhc2UgMzogJG9yaWdpbiA+ICRvLm9yaWdpblxuICAgICAgICAgICMgICAgICAgICAkdGhpcyBpbnNlcnRfcG9zaXRpb24gaXMgdG8gdGhlIGxlZnQgb2YgJG8gKGZvcmV2ZXIhKVxuICAgICAgICAgIHdoaWxlIHRydWVcbiAgICAgICAgICAgIGlmIG5vdCBvP1xuICAgICAgICAgICAgICAjIFRPRE86IERlYnVnZ2luZ1xuICAgICAgICAgICAgICBjb25zb2xlLmxvZyBKU09OLnN0cmluZ2lmeSBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICAgICAgICBjb25zb2xlLmxvZyBKU09OLnN0cmluZ2lmeSBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgICAgICAgaWYgbyBpc250IEBuZXh0X2NsXG4gICAgICAgICAgICAgICMgJG8gaGFwcGVuZWQgY29uY3VycmVudGx5XG4gICAgICAgICAgICAgIGlmIG8uZ2V0RGlzdGFuY2VUb09yaWdpbigpIGlzIGlcbiAgICAgICAgICAgICAgICAjIGNhc2UgMVxuICAgICAgICAgICAgICAgIGlmIG8uY3JlYXRvciA8IEBjcmVhdG9yXG4gICAgICAgICAgICAgICAgICBAcHJldl9jbCA9IG9cbiAgICAgICAgICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IGkgKyAxXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgIyBub3BcbiAgICAgICAgICAgICAgZWxzZSBpZiBvLmdldERpc3RhbmNlVG9PcmlnaW4oKSA8IGlcbiAgICAgICAgICAgICAgICAjIGNhc2UgMlxuICAgICAgICAgICAgICAgIGlmIGkgLSBkaXN0YW5jZV90b19vcmlnaW4gPD0gby5nZXREaXN0YW5jZVRvT3JpZ2luKClcbiAgICAgICAgICAgICAgICAgIEBwcmV2X2NsID0gb1xuICAgICAgICAgICAgICAgICAgZGlzdGFuY2VfdG9fb3JpZ2luID0gaSArIDFcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAjbm9wXG4gICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAjIGNhc2UgM1xuICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgIGkrK1xuICAgICAgICAgICAgICBvID0gby5uZXh0X2NsXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICMgJHRoaXMga25vd3MgdGhhdCAkbyBleGlzdHMsXG4gICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgIyBub3cgcmVjb25uZWN0IGV2ZXJ5dGhpbmdcbiAgICAgICAgICBAbmV4dF9jbCA9IEBwcmV2X2NsLm5leHRfY2xcbiAgICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxuICAgICAgICAgIEBuZXh0X2NsLnByZXZfY2wgPSBAXG4gICAgICAgIHN1cGVyICMgbm90aWZ5IHRoZSBleGVjdXRpb25fbGlzdGVuZXJzXG4gICAgICAgIEBcblxuICAjXG4gICMgRGVmaW5lcyBhbiBvYmplY3QgdGhhdCBpcyBjYW5ub3QgYmUgY2hhbmdlZC4gWW91IGNhbiB1c2UgdGhpcyB0byBzZXQgYW4gaW1tdXRhYmxlIHN0cmluZywgb3IgYSBudW1iZXIuXG4gICNcbiAgY2xhc3MgSW1tdXRhYmxlT2JqZWN0IGV4dGVuZHMgSW5zZXJ0XG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gY29udGVudFxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgQGNvbnRlbnQsIHByZXYsIG5leHQsIG9yaWdpbiktPlxuICAgICAgc3VwZXIgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICAgICNcbiAgICAjIEByZXR1cm4gW1N0cmluZ10gVGhlIGNvbnRlbnQgb2YgdGhpcyBvcGVyYXRpb24uXG4gICAgI1xuICAgIHZhbCA6ICgpLT5cbiAgICAgIEBjb250ZW50XG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID0ge1xuICAgICAgICAndHlwZSc6IFwiSW1tdXRhYmxlT2JqZWN0XCJcbiAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgJ2NvbnRlbnQnIDogQGNvbnRlbnRcbiAgICAgIH1cbiAgICAgIGlmIEBwcmV2X2NsP1xuICAgICAgICBqc29uWydwcmV2J10gPSBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgaWYgQG5leHRfY2w/XG4gICAgICAgIGpzb25bJ25leHQnXSA9IEBuZXh0X2NsLmdldFVpZCgpXG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyWydJbW11dGFibGVPYmplY3QnXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICdwcmV2JzogcHJldlxuICAgICAgJ25leHQnOiBuZXh0XG4gICAgICAnb3JpZ2luJyA6IG9yaWdpblxuICAgIH0gPSBqc29uXG4gICAgbmV3IEltbXV0YWJsZU9iamVjdCB1aWQsIGNvbnRlbnQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICNcbiAgIyBBIGRlbGltaXRlciBpcyBwbGFjZWQgYXQgdGhlIGVuZCBhbmQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgYXNzb2NpYXRpdmUgbGlzdHMuXG4gICMgVGhpcyBpcyBuZWNlc3NhcnkgaW4gb3JkZXIgdG8gaGF2ZSBhIGJlZ2lubmluZyBhbmQgYW4gZW5kIGV2ZW4gaWYgdGhlIGNvbnRlbnRcbiAgIyBvZiB0aGUgRW5naW5lIGlzIGVtcHR5LlxuICAjXG4gIGNsYXNzIERlbGltaXRlciBleHRlbmRzIE9wZXJhdGlvblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBwcmV2X2NsIFRoZSBwcmVkZWNlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gbmV4dF9jbCBUaGUgc3VjY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcbiAgICAjXG4gICAgIyBAc2VlIEhpc3RvcnlCdWZmZXIuZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXJcbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIHByZXZfY2wsIG5leHRfY2wsIG9yaWdpbiktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ3ByZXZfY2wnLCBwcmV2X2NsXG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnbmV4dF9jbCcsIG5leHRfY2xcbiAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBwcmV2X2NsXG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIElmIGlzRGVsZXRlZCgpIGlzIHRydWUgdGhpcyBvcGVyYXRpb24gd29uJ3QgYmUgbWFpbnRhaW5lZCBpbiB0aGUgc2xcbiAgICAjXG4gICAgaXNEZWxldGVkOiAoKS0+XG4gICAgICBmYWxzZVxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgQHVuY2hlY2tlZD9bJ25leHRfY2wnXT9cbiAgICAgICAgc3VwZXJcbiAgICAgIGVsc2UgaWYgQHVuY2hlY2tlZD9bJ3ByZXZfY2wnXVxuICAgICAgICBpZiBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICAgIGlmIEBwcmV2X2NsLm5leHRfY2w/XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJQcm9iYWJseSBkdXBsaWNhdGVkIG9wZXJhdGlvbnNcIlxuICAgICAgICAgIEBwcmV2X2NsLm5leHRfY2wgPSBAXG4gICAgICAgICAgZGVsZXRlIEBwcmV2X2NsLnVuY2hlY2tlZC5uZXh0X2NsXG4gICAgICAgICAgc3VwZXJcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGZhbHNlXG4gICAgICBlbHNlIGlmIEBwcmV2X2NsPyBhbmQgbm90IEBwcmV2X2NsLm5leHRfY2w/XG4gICAgICAgIGRlbGV0ZSBAcHJldl9jbC51bmNoZWNrZWQubmV4dF9jbFxuICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxuICAgICAgZWxzZSBpZiBAcHJldl9jbD8gb3IgQG5leHRfY2w/XG4gICAgICAgIHN1cGVyXG4gICAgICBlbHNlXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcIkRlbGltaXRlciBpcyB1bnN1ZmZpY2llbnQgZGVmaW5lZCFcIlxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAge1xuICAgICAgICAndHlwZScgOiBcIkRlbGltaXRlclwiXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICdwcmV2JyA6IEBwcmV2X2NsPy5nZXRVaWQoKVxuICAgICAgICAnbmV4dCcgOiBAbmV4dF9jbD8uZ2V0VWlkKClcbiAgICAgIH1cblxuICBwYXJzZXJbJ0RlbGltaXRlciddID0gKGpzb24pLT5cbiAgICB7XG4gICAgJ3VpZCcgOiB1aWRcbiAgICAncHJldicgOiBwcmV2XG4gICAgJ25leHQnIDogbmV4dFxuICAgIH0gPSBqc29uXG4gICAgbmV3IERlbGltaXRlciB1aWQsIHByZXYsIG5leHRcblxuICAjIFRoaXMgaXMgd2hhdCB0aGlzIG1vZHVsZSBleHBvcnRzIGFmdGVyIGluaXRpYWxpemluZyBpdCB3aXRoIHRoZSBIaXN0b3J5QnVmZmVyXG4gIHtcbiAgICAndHlwZXMnIDpcbiAgICAgICdEZWxldGUnIDogRGVsZXRlXG4gICAgICAnSW5zZXJ0JyA6IEluc2VydFxuICAgICAgJ0RlbGltaXRlcic6IERlbGltaXRlclxuICAgICAgJ09wZXJhdGlvbic6IE9wZXJhdGlvblxuICAgICAgJ0ltbXV0YWJsZU9iamVjdCcgOiBJbW11dGFibGVPYmplY3RcbiAgICAncGFyc2VyJyA6IHBhcnNlclxuICAgICdleGVjdXRpb25fbGlzdGVuZXInIDogZXhlY3V0aW9uX2xpc3RlbmVyXG4gIH1cblxuXG5cblxuIiwiYmFzaWNfdHlwZXNfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuL0Jhc2ljVHlwZXNcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IChIQiktPlxuICBiYXNpY190eXBlcyA9IGJhc2ljX3R5cGVzX3VuaW5pdGlhbGl6ZWQgSEJcbiAgdHlwZXMgPSBiYXNpY190eXBlcy50eXBlc1xuICBwYXJzZXIgPSBiYXNpY190eXBlcy5wYXJzZXJcblxuICAjXG4gICMgTWFuYWdlcyBtYXAgbGlrZSBvYmplY3RzLiBFLmcuIEpzb24tVHlwZSBhbmQgWE1MIGF0dHJpYnV0ZXMuXG4gICNcbiAgY2xhc3MgTWFwTWFuYWdlciBleHRlbmRzIHR5cGVzLk9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCktPlxuICAgICAgQG1hcCA9IHt9XG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIEBzZWUgSnNvblR5cGVzLnZhbFxuICAgICNcbiAgICB2YWw6IChuYW1lLCBjb250ZW50KS0+XG4gICAgICBpZiBjb250ZW50P1xuICAgICAgICBpZiBub3QgQG1hcFtuYW1lXT9cbiAgICAgICAgICBIQi5hZGRPcGVyYXRpb24obmV3IEFkZE5hbWUgdW5kZWZpbmVkLCBALCBuYW1lKS5leGVjdXRlKClcbiAgICAgICAgQG1hcFtuYW1lXS5yZXBsYWNlIGNvbnRlbnRcbiAgICAgICAgQFxuICAgICAgZWxzZSBpZiBuYW1lP1xuICAgICAgICBvYmogPSBAbWFwW25hbWVdPy52YWwoKVxuICAgICAgICBpZiBvYmogaW5zdGFuY2VvZiB0eXBlcy5JbW11dGFibGVPYmplY3RcbiAgICAgICAgICBvYmoudmFsKClcbiAgICAgICAgZWxzZVxuICAgICAgICAgIG9ialxuICAgICAgZWxzZVxuICAgICAgICByZXN1bHQgPSB7fVxuICAgICAgICBmb3IgbmFtZSxvIG9mIEBtYXBcbiAgICAgICAgICBvYmogPSBvLnZhbCgpXG4gICAgICAgICAgaWYgb2JqIGluc3RhbmNlb2YgdHlwZXMuSW1tdXRhYmxlT2JqZWN0IG9yIG9iaiBpbnN0YW5jZW9mIE1hcE1hbmFnZXJcbiAgICAgICAgICAgIG9iaiA9IG9iai52YWwoKVxuICAgICAgICAgIHJlc3VsdFtuYW1lXSA9IG9ialxuICAgICAgICByZXN1bHRcblxuICAjXG4gICMgV2hlbiBhIG5ldyBwcm9wZXJ0eSBpbiBhIG1hcCBtYW5hZ2VyIGlzIGNyZWF0ZWQsIHRoZW4gdGhlIHVpZHMgb2YgdGhlIGluc2VydGVkIE9wZXJhdGlvbnNcbiAgIyBtdXN0IGJlIHVuaXF1ZSAodGhpbmsgYWJvdXQgY29uY3VycmVudCBvcGVyYXRpb25zKS4gVGhlcmVmb3JlIG9ubHkgYW4gQWRkTmFtZSBvcGVyYXRpb24gaXMgYWxsb3dlZCB0b1xuICAjIGFkZCBhIHByb3BlcnR5IGluIGEgTWFwTWFuYWdlci4gSWYgdHdvIEFkZE5hbWUgb3BlcmF0aW9ucyBvbiB0aGUgc2FtZSBNYXBNYW5hZ2VyIG5hbWUgaGFwcGVuIGNvbmN1cnJlbnRseVxuICAjIG9ubHkgb25lIHdpbGwgQWRkTmFtZSBvcGVyYXRpb24gd2lsbCBiZSBleGVjdXRlZC5cbiAgI1xuICBjbGFzcyBBZGROYW1lIGV4dGVuZHMgdHlwZXMuT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gbWFwX21hbmFnZXIgVWlkIG9yIHJlZmVyZW5jZSB0byB0aGUgTWFwTWFuYWdlci5cbiAgICAjIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIHByb3BlcnR5IHRoYXQgd2lsbCBiZSBhZGRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIG1hcF9tYW5hZ2VyLCBAbmFtZSktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ21hcF9tYW5hZ2VyJywgbWFwX21hbmFnZXJcbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgSWYgbWFwX21hbmFnZXIgZG9lc24ndCBoYXZlIHRoZSBwcm9wZXJ0eSBuYW1lLCB0aGVuIGFkZCBpdC5cbiAgICAjIFRoZSBSZXBsYWNlTWFuYWdlciB0aGF0IGlzIGJlaW5nIHdyaXR0ZW4gb24gdGhlIHByb3BlcnR5IGlzIHVuaXF1ZVxuICAgICMgaW4gc3VjaCBhIHdheSB0aGF0IGlmIEFkZE5hbWUgaXMgZXhlY3V0ZWQgKGZyb20gYW5vdGhlciBwZWVyKSBpdCB3aWxsXG4gICAgIyBhbHdheXMgaGF2ZSB0aGUgc2FtZSByZXN1bHQgKFJlcGxhY2VNYW5hZ2VyLCBhbmQgaXRzIGJlZ2lubmluZyBhbmQgZW5kIGFyZSB0aGUgc2FtZSlcbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgbm90IEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgZWxzZVxuICAgICAgICB1aWRfciA9IEBtYXBfbWFuYWdlci5nZXRVaWQoKVxuICAgICAgICB1aWRfci5vcF9udW1iZXIgPSBcIl8je3VpZF9yLm9wX251bWJlcn1fUk1fI3tAbmFtZX1cIlxuICAgICAgICBpZiBub3QgSEIuZ2V0T3BlcmF0aW9uKHVpZF9yKT9cbiAgICAgICAgICB1aWRfYmVnID0gQG1hcF9tYW5hZ2VyLmdldFVpZCgpXG4gICAgICAgICAgdWlkX2JlZy5vcF9udW1iZXIgPSBcIl8je3VpZF9iZWcub3BfbnVtYmVyfV9STV8je0BuYW1lfV9iZWdpbm5pbmdcIlxuICAgICAgICAgIHVpZF9lbmQgPSBAbWFwX21hbmFnZXIuZ2V0VWlkKClcbiAgICAgICAgICB1aWRfZW5kLm9wX251bWJlciA9IFwiXyN7dWlkX2VuZC5vcF9udW1iZXJ9X1JNXyN7QG5hbWV9X2VuZFwiXG4gICAgICAgICAgYmVnID0gSEIuYWRkT3BlcmF0aW9uKG5ldyB0eXBlcy5EZWxpbWl0ZXIgdWlkX2JlZywgdW5kZWZpbmVkLCB1aWRfZW5kKS5leGVjdXRlKClcbiAgICAgICAgICBlbmQgPSBIQi5hZGRPcGVyYXRpb24obmV3IHR5cGVzLkRlbGltaXRlciB1aWRfZW5kLCBiZWcsIHVuZGVmaW5lZCkuZXhlY3V0ZSgpXG4gICAgICAgICAgI2JlZy5leGVjdXRlKClcbiAgICAgICAgICBAbWFwX21hbmFnZXIubWFwW0BuYW1lXSA9IEhCLmFkZE9wZXJhdGlvbihuZXcgUmVwbGFjZU1hbmFnZXIgdW5kZWZpbmVkLCB1aWRfciwgYmVnLCBlbmQpLmV4ZWN1dGUoKVxuICAgICAgICBzdXBlclxuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAge1xuICAgICAgICAndHlwZScgOiBcIkFkZE5hbWVcIlxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAnbWFwX21hbmFnZXInIDogQG1hcF9tYW5hZ2VyLmdldFVpZCgpXG4gICAgICAgICduYW1lJyA6IEBuYW1lXG4gICAgICB9XG5cbiAgcGFyc2VyWydBZGROYW1lJ10gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdtYXBfbWFuYWdlcicgOiBtYXBfbWFuYWdlclxuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICduYW1lJyA6IG5hbWVcbiAgICB9ID0ganNvblxuICAgIG5ldyBBZGROYW1lIHVpZCwgbWFwX21hbmFnZXIsIG5hbWVcblxuICAjXG4gICMgTWFuYWdlcyBhIGxpc3Qgb2YgSW5zZXJ0LXR5cGUgb3BlcmF0aW9ucy5cbiAgI1xuICBjbGFzcyBMaXN0TWFuYWdlciBleHRlbmRzIHR5cGVzLkluc2VydFxuXG4gICAgI1xuICAgICMgQSBMaXN0TWFuYWdlciBtYWludGFpbnMgYSBub24tZW1wdHkgbGlzdCB0aGF0IGhhcyBhIGJlZ2lubmluZyBhbmQgYW4gZW5kIChib3RoIERlbGltaXRlcnMhKVxuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGJlZ2lubmluZyBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGVuZCBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBpZiBiZWdpbm5pbmc/IGFuZCBlbmQ/XG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdiZWdpbm5pbmcnLCBiZWdpbm5pbmdcbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ2VuZCcsIGVuZFxuICAgICAgZWxzZVxuICAgICAgICBAYmVnaW5uaW5nID0gSEIuYWRkT3BlcmF0aW9uIG5ldyB0eXBlcy5EZWxpbWl0ZXIgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZFxuICAgICAgICBAZW5kID0gICAgICAgSEIuYWRkT3BlcmF0aW9uIG5ldyB0eXBlcy5EZWxpbWl0ZXIgdW5kZWZpbmVkLCBAYmVnaW5uaW5nLCB1bmRlZmluZWRcbiAgICAgICAgQGJlZ2lubmluZy5uZXh0X2NsID0gQGVuZFxuICAgICAgICBAYmVnaW5uaW5nLmV4ZWN1dGUoKVxuICAgICAgICBAZW5kLmV4ZWN1dGUoKVxuICAgICAgc3VwZXIgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuXG4gICAgIyBHZXQgdGhlIGVsZW1lbnQgcHJldmlvdXMgdG8gdGhlIGRlbGVtaXRlciBhdCB0aGUgZW5kXG4gICAgZ2V0TGFzdE9wZXJhdGlvbjogKCktPlxuICAgICAgQGVuZC5wcmV2X2NsXG5cbiAgICAjIHNpbWlsYXIgdG8gdGhlIGFib3ZlXG4gICAgZ2V0Rmlyc3RPcGVyYXRpb246ICgpLT5cbiAgICAgIEBiZWdpbm5pbmcubmV4dF9jbFxuXG4gICAgIyBUcmFuc2Zvcm1zIHRoZSB0aGUgbGlzdCB0byBhbiBhcnJheVxuICAgICMgRG9lc24ndCByZXR1cm4gbGVmdC1yaWdodCBkZWxpbWl0ZXIuXG4gICAgdG9BcnJheTogKCktPlxuICAgICAgbyA9IEBiZWdpbm5pbmcubmV4dF9jbFxuICAgICAgcmVzdWx0ID0gW11cbiAgICAgIHdoaWxlIG8gaXNudCBAZW5kXG4gICAgICAgIHJlc3VsdC5wdXNoIG9cbiAgICAgICAgbyA9IG8ubmV4dF9jbFxuICAgICAgcmVzdWx0XG5cbiAgICAjXG4gICAgIyBSZXRyaWV2ZXMgdGhlIHgtdGggbm90IGRlbGV0ZWQgZWxlbWVudC5cbiAgICAjXG4gICAgZ2V0T3BlcmF0aW9uQnlQb3NpdGlvbjogKHBvc2l0aW9uKS0+XG4gICAgICBvID0gQGJlZ2lubmluZy5uZXh0X2NsXG4gICAgICBpZiBwb3NpdGlvbiA+IDBcbiAgICAgICAgd2hpbGUgdHJ1ZVxuICAgICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgICBpZiBub3Qgby5pc0RlbGV0ZWQoKVxuICAgICAgICAgICAgcG9zaXRpb24gLT0gMVxuICAgICAgICAgIGlmIHBvc2l0aW9uIGlzIDBcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgaWYgbyBpbnN0YW5jZW9mIHR5cGVzLkRlbGltaXRlclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwicG9zaXRpb24gcGFyYW1ldGVyIGV4Y2VlZGVkIHRoZSBsZW5ndGggb2YgdGhlIGRvY3VtZW50IVwiXG4gICAgICBvXG5cbiAgI1xuICAjIEFkZHMgc3VwcG9ydCBmb3IgcmVwbGFjZS4gVGhlIFJlcGxhY2VNYW5hZ2VyIG1hbmFnZXMgUmVwbGFjZWFibGUgb3BlcmF0aW9ucy5cbiAgIyBFYWNoIFJlcGxhY2VhYmxlIGhvbGRzIGEgdmFsdWUgdGhhdCBpcyBub3cgcmVwbGFjZWFibGUuXG4gICNcbiAgIyBUaGUgV29yZC10eXBlIGhhcyBpbXBsZW1lbnRlZCBzdXBwb3J0IGZvciByZXBsYWNlXG4gICMgQHNlZSBXb3JkXG4gICNcbiAgY2xhc3MgUmVwbGFjZU1hbmFnZXIgZXh0ZW5kcyBMaXN0TWFuYWdlclxuICAgICNcbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBpbml0aWFsX2NvbnRlbnQgSW5pdGlhbGl6ZSB0aGlzIHdpdGggYSBSZXBsYWNlYWJsZSB0aGF0IGhvbGRzIHRoZSBpbml0aWFsX2NvbnRlbnQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge0RlbGltaXRlcn0gYmVnaW5uaW5nIFJlZmVyZW5jZSBvciBPYmplY3QuXG4gICAgIyBAcGFyYW0ge0RlbGltaXRlcn0gZW5kIFJlZmVyZW5jZSBvciBPYmplY3QuXG4gICAgY29uc3RydWN0b3I6IChpbml0aWFsX2NvbnRlbnQsIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpbiktPlxuICAgICAgc3VwZXIgdWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luXG4gICAgICBpZiBpbml0aWFsX2NvbnRlbnQ/XG4gICAgICAgIEByZXBsYWNlIGluaXRpYWxfY29udGVudFxuXG4gICAgI1xuICAgICMgUmVwbGFjZSB0aGUgZXhpc3Rpbmcgd29yZCB3aXRoIGEgbmV3IHdvcmQuXG4gICAgI1xuICAgIHJlcGxhY2U6IChjb250ZW50KS0+XG4gICAgICBvID0gQGdldExhc3RPcGVyYXRpb24oKVxuICAgICAgb3AgPSBuZXcgUmVwbGFjZWFibGUgY29udGVudCwgQCwgdW5kZWZpbmVkLCBvLCBvLm5leHRfY2xcbiAgICAgIEhCLmFkZE9wZXJhdGlvbihvcCkuZXhlY3V0ZSgpXG5cbiAgICAjXG4gICAgIyBHZXQgdGhlIHZhbHVlIG9mIHRoaXMgV29yZFxuICAgICMgQHJldHVybiB7U3RyaW5nfVxuICAgICNcbiAgICB2YWw6ICgpLT5cbiAgICAgIG8gPSBAZ2V0TGFzdE9wZXJhdGlvbigpXG4gICAgICBpZiBvIGluc3RhbmNlb2YgdHlwZXMuRGVsaW1pdGVyXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcImR0cm5cIlxuICAgICAgby52YWwoKVxuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9XG4gICAgICAgIHtcbiAgICAgICAgICAndHlwZSc6IFwiUmVwbGFjZU1hbmFnZXJcIlxuICAgICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICAgJ2JlZ2lubmluZycgOiBAYmVnaW5uaW5nLmdldFVpZCgpXG4gICAgICAgICAgJ2VuZCcgOiBAZW5kLmdldFVpZCgpXG4gICAgICAgIH1cbiAgICAgIGlmIEBwcmV2X2NsPyBhbmQgQG5leHRfY2w/XG4gICAgICAgIGpzb25bJ3ByZXYnXSA9IEBwcmV2X2NsLmdldFVpZCgpXG4gICAgICAgIGpzb25bJ25leHQnXSA9IEBuZXh0X2NsLmdldFVpZCgpXG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyW1wiUmVwbGFjZU1hbmFnZXJcIl0gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICAgICdiZWdpbm5pbmcnIDogYmVnaW5uaW5nXG4gICAgICAnZW5kJyA6IGVuZFxuICAgIH0gPSBqc29uXG4gICAgbmV3IFJlcGxhY2VNYW5hZ2VyIGNvbnRlbnQsIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpblxuXG5cbiAgI1xuICAjIFRoZSBSZXBsYWNlTWFuYWdlciBtYW5hZ2VzIFJlcGxhY2VhYmxlcy5cbiAgIyBAc2VlIFJlcGxhY2VNYW5hZ2VyXG4gICNcbiAgY2xhc3MgUmVwbGFjZWFibGUgZXh0ZW5kcyB0eXBlcy5JbnNlcnRcblxuICAgICNcbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBjb250ZW50IFRoZSB2YWx1ZSB0aGF0IHRoaXMgUmVwbGFjZWFibGUgaG9sZHMuXG4gICAgIyBAcGFyYW0ge1JlcGxhY2VNYW5hZ2VyfSBwYXJlbnQgVXNlZCB0byByZXBsYWNlIHRoaXMgUmVwbGFjZWFibGUgd2l0aCBhbm90aGVyIG9uZS5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6IChjb250ZW50LCBwYXJlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnY29udGVudCcsIGNvbnRlbnRcbiAgICAgIEBzYXZlT3BlcmF0aW9uICdwYXJlbnQnLCBwYXJlbnRcbiAgICAgIGlmIG5vdCAocHJldj8gYW5kIG5leHQ/IGFuZCBjb250ZW50PylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3QgZGVmaW5lIGNvbnRlbnQsIHByZXYsIGFuZCBuZXh0IGZvciBSZXBsYWNlYWJsZS10eXBlcyFcIlxuICAgICAgc3VwZXIgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICAgICNcbiAgICAjIFJldHVybiB0aGUgY29udGVudCB0aGF0IHRoaXMgb3BlcmF0aW9uIGhvbGRzLlxuICAgICNcbiAgICB2YWw6ICgpLT5cbiAgICAgIEBjb250ZW50XG5cbiAgICAjXG4gICAgIyBSZXBsYWNlIHRoZSBjb250ZW50IG9mIHRoaXMgcmVwbGFjZWFibGUgd2l0aCBuZXcgY29udGVudC5cbiAgICAjXG4gICAgcmVwbGFjZTogKGNvbnRlbnQpLT5cbiAgICAgIEBwYXJlbnQucmVwbGFjZSBjb250ZW50XG5cbiAgICAjXG4gICAgIyBJZiBwb3NzaWJsZSBzZXQgdGhlIHJlcGxhY2UgbWFuYWdlciBpbiB0aGUgY29udGVudC5cbiAgICAjIEBzZWUgV29yZC5zZXRSZXBsYWNlTWFuYWdlclxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBub3QgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICBlbHNlXG4gICAgICAgIEBjb250ZW50LnNldFJlcGxhY2VNYW5hZ2VyPyhAcGFyZW50KVxuICAgICAgICBzdXBlclxuICAgICAgICBAXG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID1cbiAgICAgICAge1xuICAgICAgICAgICd0eXBlJzogXCJSZXBsYWNlYWJsZVwiXG4gICAgICAgICAgJ2NvbnRlbnQnOiBAY29udGVudC5nZXRVaWQoKVxuICAgICAgICAgICdSZXBsYWNlTWFuYWdlcicgOiBAcGFyZW50LmdldFVpZCgpXG4gICAgICAgICAgJ3ByZXYnOiBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICAgICduZXh0JzogQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICB9XG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyW1wiUmVwbGFjZWFibGVcIl0gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICdSZXBsYWNlTWFuYWdlcicgOiBwYXJlbnRcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBSZXBsYWNlYWJsZSBjb250ZW50LCBwYXJlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cblxuXG4gIHR5cGVzWydMaXN0TWFuYWdlciddID0gTGlzdE1hbmFnZXJcbiAgdHlwZXNbJ01hcE1hbmFnZXInXSA9IE1hcE1hbmFnZXJcbiAgdHlwZXNbJ1JlcGxhY2VNYW5hZ2VyJ10gPSBSZXBsYWNlTWFuYWdlclxuICB0eXBlc1snUmVwbGFjZWFibGUnXSA9IFJlcGxhY2VhYmxlXG5cbiAgYmFzaWNfdHlwZXNcblxuXG5cblxuXG5cbiIsInN0cnVjdHVyZWRfdHlwZXNfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuL1N0cnVjdHVyZWRUeXBlc1wiXG5cbm1vZHVsZS5leHBvcnRzID0gKEhCKS0+XG4gIHN0cnVjdHVyZWRfdHlwZXMgPSBzdHJ1Y3R1cmVkX3R5cGVzX3VuaW5pdGlhbGl6ZWQgSEJcbiAgdHlwZXMgPSBzdHJ1Y3R1cmVkX3R5cGVzLnR5cGVzXG4gIHBhcnNlciA9IHN0cnVjdHVyZWRfdHlwZXMucGFyc2VyXG5cbiAgI1xuICAjIEF0IHRoZSBtb21lbnQgVGV4dERlbGV0ZSB0eXBlIGVxdWFscyB0aGUgRGVsZXRlIHR5cGUgaW4gQmFzaWNUeXBlcy5cbiAgIyBAc2VlIEJhc2ljVHlwZXMuRGVsZXRlXG4gICNcbiAgY2xhc3MgVGV4dERlbGV0ZSBleHRlbmRzIHR5cGVzLkRlbGV0ZVxuICBwYXJzZXJbXCJUZXh0RGVsZXRlXCJdID0gcGFyc2VyW1wiRGVsZXRlXCJdXG5cbiAgI1xuICAjICBFeHRlbmRzIHRoZSBiYXNpYyBJbnNlcnQgdHlwZSB0byBhbiBvcGVyYXRpb24gdGhhdCBob2xkcyBhIHRleHQgdmFsdWVcbiAgI1xuICBjbGFzcyBUZXh0SW5zZXJ0IGV4dGVuZHMgdHlwZXMuSW5zZXJ0XG4gICAgI1xuICAgICMgQHBhcmFtIHtTdHJpbmd9IGNvbnRlbnQgVGhlIGNvbnRlbnQgb2YgdGhpcyBJbnNlcnQtdHlwZSBPcGVyYXRpb24uIFVzdWFsbHkgeW91IHJlc3RyaWN0IHRoZSBsZW5ndGggb2YgY29udGVudCB0byBzaXplIDFcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6IChAY29udGVudCwgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIGlmIG5vdCAocHJldj8gYW5kIG5leHQ/KVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBkZWZpbmUgcHJldiwgYW5kIG5leHQgZm9yIFRleHRJbnNlcnQtdHlwZXMhXCJcbiAgICAgIHN1cGVyIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG4gICAgI1xuICAgICMgUmV0cmlldmUgdGhlIGVmZmVjdGl2ZSBsZW5ndGggb2YgdGhlICRjb250ZW50IG9mIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICBnZXRMZW5ndGg6ICgpLT5cbiAgICAgIGlmIEBpc0RlbGV0ZWQoKVxuICAgICAgICAwXG4gICAgICBlbHNlXG4gICAgICAgIEBjb250ZW50Lmxlbmd0aFxuXG4gICAgI1xuICAgICMgVGhlIHJlc3VsdCB3aWxsIGJlIGNvbmNhdGVuYXRlZCB3aXRoIHRoZSByZXN1bHRzIGZyb20gdGhlIG90aGVyIGluc2VydCBvcGVyYXRpb25zXG4gICAgIyBpbiBvcmRlciB0byByZXRyaWV2ZSB0aGUgY29udGVudCBvZiB0aGUgZW5naW5lLlxuICAgICMgQHNlZSBIaXN0b3J5QnVmZmVyLnRvRXhlY3V0ZWRBcnJheVxuICAgICNcbiAgICB2YWw6IChjdXJyZW50X3Bvc2l0aW9uKS0+XG4gICAgICBpZiBAaXNEZWxldGVkKClcbiAgICAgICAgXCJcIlxuICAgICAgZWxzZVxuICAgICAgICBAY29udGVudFxuXG4gICAgI1xuICAgICMgQ29udmVydCBhbGwgcmVsZXZhbnQgaW5mb3JtYXRpb24gb2YgdGhpcyBvcGVyYXRpb24gdG8gdGhlIGpzb24tZm9ybWF0LlxuICAgICMgVGhpcyByZXN1bHQgY2FuIGJlIHNlbmQgdG8gb3RoZXIgY2xpZW50cy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9XG4gICAgICAgIHtcbiAgICAgICAgICAndHlwZSc6IFwiVGV4dEluc2VydFwiXG4gICAgICAgICAgJ2NvbnRlbnQnOiBAY29udGVudFxuICAgICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICAgJ3ByZXYnOiBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICAgICduZXh0JzogQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgICAgfVxuICAgICAgaWYgQG9yaWdpbj8gYW5kIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uW1wib3JpZ2luXCJdID0gQG9yaWdpbi5nZXRVaWQoKVxuICAgICAganNvblxuXG4gIHBhcnNlcltcIlRleHRJbnNlcnRcIl0gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBUZXh0SW5zZXJ0IGNvbnRlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cbiAgI1xuICAjIEhhbmRsZXMgYSBUZXh0LWxpa2UgZGF0YSBzdHJ1Y3R1cmVzIHdpdGggc3VwcG9ydCBmb3IgaW5zZXJ0VGV4dC9kZWxldGVUZXh0IGF0IGEgd29yZC1wb3NpdGlvbi5cbiAgI1xuICBjbGFzcyBXb3JkIGV4dGVuZHMgdHlwZXMuTGlzdE1hbmFnZXJcblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIHN1cGVyIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICAgI1xuICAgICMgSW5zZXJ0cyBhIHN0cmluZyBpbnRvIHRoZSB3b3JkXG4gICAgI1xuICAgIGluc2VydFRleHQ6IChwb3NpdGlvbiwgY29udGVudCktPlxuICAgICAgbyA9IEBnZXRPcGVyYXRpb25CeVBvc2l0aW9uIHBvc2l0aW9uXG4gICAgICBmb3IgYyBpbiBjb250ZW50XG4gICAgICAgIG9wID0gbmV3IFRleHRJbnNlcnQgYywgdW5kZWZpbmVkLCBvLnByZXZfY2wsIG9cbiAgICAgICAgSEIuYWRkT3BlcmF0aW9uKG9wKS5leGVjdXRlKClcblxuICAgICNcbiAgICAjIERlbGV0ZXMgYSBwYXJ0IG9mIHRoZSB3b3JkLlxuICAgICNcbiAgICBkZWxldGVUZXh0OiAocG9zaXRpb24sIGxlbmd0aCktPlxuICAgICAgbyA9IEBnZXRPcGVyYXRpb25CeVBvc2l0aW9uIHBvc2l0aW9uXG5cbiAgICAgIGZvciBpIGluIFswLi4ubGVuZ3RoXVxuICAgICAgICBkID0gSEIuYWRkT3BlcmF0aW9uKG5ldyBUZXh0RGVsZXRlIHVuZGVmaW5lZCwgbykuZXhlY3V0ZSgpXG4gICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgd2hpbGUgby5pc0RlbGV0ZWQoKVxuICAgICAgICAgIGlmIG8gaW5zdGFuY2VvZiB0eXBlcy5EZWxpbWl0ZXJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBjYW4ndCBkZWxldGUgbW9yZSB0aGFuIHRoZXJlIGlzLi5cIlxuICAgICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgZC5fZW5jb2RlKClcblxuICAgICNcbiAgICAjIFJlcGxhY2UgdGhlIGNvbnRlbnQgb2YgdGhpcyB3b3JkIHdpdGggYW5vdGhlciBvbmUuIENvbmN1cnJlbnQgcmVwbGFjZW1lbnRzIGFyZSBub3QgbWVyZ2VkIVxuICAgICMgT25seSBvbmUgb2YgdGhlIHJlcGxhY2VtZW50cyB3aWxsIGJlIHVzZWQuXG4gICAgI1xuICAgICMgQ2FuIG9ubHkgYmUgdXNlZCBpZiB0aGUgUmVwbGFjZU1hbmFnZXIgd2FzIHNldCFcbiAgICAjIEBzZWUgV29yZC5zZXRSZXBsYWNlTWFuYWdlclxuICAgICNcbiAgICByZXBsYWNlVGV4dDogKHRleHQpLT5cbiAgICAgIGlmIEByZXBsYWNlX21hbmFnZXI/XG4gICAgICAgIHdvcmQgPSBIQi5hZGRPcGVyYXRpb24obmV3IFdvcmQgdW5kZWZpbmVkKS5leGVjdXRlKClcbiAgICAgICAgd29yZC5pbnNlcnRUZXh0IDAsIHRleHRcbiAgICAgICAgQHJlcGxhY2VfbWFuYWdlci5yZXBsYWNlKHdvcmQpXG4gICAgICBlbHNlXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcIlRoaXMgdHlwZSBpcyBjdXJyZW50bHkgbm90IG1haW50YWluZWQgYnkgYSBSZXBsYWNlTWFuYWdlciFcIlxuXG4gICAgI1xuICAgICMgQHJldHVybnMgW0pzb25dIEEgSnNvbiBvYmplY3QuXG4gICAgI1xuICAgIHZhbDogKCktPlxuICAgICAgYyA9IGZvciBvIGluIEB0b0FycmF5KClcbiAgICAgICAgaWYgby52YWw/XG4gICAgICAgICAgby52YWwoKVxuICAgICAgICBlbHNlXG4gICAgICAgICAgXCJcIlxuICAgICAgYy5qb2luKCcnKVxuXG4gICAgI1xuICAgICMgSW4gbW9zdCBjYXNlcyB5b3Ugd291bGQgZW1iZWQgYSBXb3JkIGluIGEgUmVwbGFjZWFibGUsIHdpY2ggaXMgaGFuZGxlZCBieSB0aGUgUmVwbGFjZU1hbmFnZXIgaW4gb3JkZXJcbiAgICAjIHRvIHByb3ZpZGUgcmVwbGFjZSBmdW5jdGlvbmFsaXR5LlxuICAgICNcbiAgICBzZXRSZXBsYWNlTWFuYWdlcjogKG9wKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncmVwbGFjZV9tYW5hZ2VyJywgb3BcbiAgICAgIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9uc1xuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9IHtcbiAgICAgICAgJ3R5cGUnOiBcIldvcmRcIlxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAnYmVnaW5uaW5nJyA6IEBiZWdpbm5pbmcuZ2V0VWlkKClcbiAgICAgICAgJ2VuZCcgOiBAZW5kLmdldFVpZCgpXG4gICAgICB9XG4gICAgICBpZiBAcHJldl9jbD9cbiAgICAgICAganNvblsncHJldiddID0gQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgIGlmIEBuZXh0X2NsP1xuICAgICAgICBqc29uWyduZXh0J10gPSBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgaWYgQG9yaWdpbj8gYW5kIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uW1wib3JpZ2luXCJdID0gQG9yaWdpbi5nZXRVaWQoKVxuICAgICAganNvblxuXG4gIHBhcnNlclsnV29yZCddID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ2JlZ2lubmluZycgOiBiZWdpbm5pbmdcbiAgICAgICdlbmQnIDogZW5kXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBXb3JkIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gIHR5cGVzWydUZXh0SW5zZXJ0J10gPSBUZXh0SW5zZXJ0XG4gIHR5cGVzWydUZXh0RGVsZXRlJ10gPSBUZXh0RGVsZXRlXG4gIHR5cGVzWydXb3JkJ10gPSBXb3JkXG4gIHN0cnVjdHVyZWRfdHlwZXNcblxuXG4iXX0= diff --git a/build/browser/Frameworks/TextYatta.min.js b/build/browser/Frameworks/TextYatta.min.js new file mode 100644 index 00000000..262d07b8 --- /dev/null +++ b/build/browser/Frameworks/TextYatta.min.js @@ -0,0 +1 @@ +!function e(t,n,r){function i(s,u){if(!n[s]){if(!t[s]){var p="function"==typeof require&&require;if(!u&&p)return p(s,!0);if(o)return o(s,!0);throw new Error("Cannot find module '"+s+"'")}var c=n[s]={exports:{}};t[s][0].call(c.exports,function(e){var n=t[s][1][e];return i(n?n:e)},c,c.exports,e,t,n,r)}return n[s].exports}for(var o="function"==typeof require&&require,s=0;sr;r++)t=e[r],n.push(this.parseOperation(t));for(i=0,u=n.length;u>i;i++)t=n[i],this.HB.addOperation(t);for(o=0,p=n.length;p>o;o++)t=n[o],t.execute()||this.unprocessed_ops.push(t);return this.tryUnprocessed()},e.prototype.applyOpsCheckDouble=function(e){var t,n,r,i;for(i=[],n=0,r=e.length;r>n;n++)t=e[n],i.push(null!=this.HB.getOperation(t.uid)?this.applyOp(t):void 0);return i},e.prototype.applyOps=function(e){var t,n,r,i;for(i=[],n=0,r=e.length;r>n;n++)t=e[n],i.push(this.applyOp(t));return i},e.prototype.applyOp=function(e){var t;return t=this.parseOperation(e),this.HB.addToCounter(t),t.execute()?this.HB.addOperation(t):this.unprocessed_ops.push(t),this.tryUnprocessed()},e.prototype.tryUnprocessed=function(){var e,t,n,r,i,o,s;for(s=[];;){for(e=this.unprocessed_ops.length,n=[],o=this.unprocessed_ops,r=0,i=o.length;i>r;r++)t=o[r],t.execute()?this.HB.addOperation(t):n.push(t);if(this.unprocessed_ops=n,this.unprocessed_ops.length===e)break;s.push(void 0)}return s},e}(),t.exports=n},{}],2:[function(e,t){var n,r,i,o;o=e("../Types/TextTypes"),r=e("../HistoryBuffer"),n=e("../Engine"),i=function(){function e(e,t){var i,s;this.HB=new r(e),s=o(this.HB),this.engine=new n(this.HB,s.parser),this.connector=new t(this.engine,this.HB,s.execution_listener),i=new s.types.Word(void 0),this.HB.addOperation(i).execute(),this.root_element=i}return e.prototype.getRootElement=function(){return this.root_element},e.prototype.getEngine=function(){return this.engine},e.prototype.getConnector=function(){return this.connector},e.prototype.getHistoryBuffer=function(){return this.HB},e.prototype.getUserId=function(){return this.HB.getUserId()},e.prototype.val=function(){return this.root_element.val()},e.prototype.insertText=function(e,t){return this.root_element.insertText(e,t)},e.prototype.deleteText=function(e,t){return this.root_element.deleteText(e,t)},e.prototype.replaceText=function(e){return this.root_element.replaceText(e)},e}(),t.exports=i},{"../Engine":1,"../HistoryBuffer":3,"../Types/TextTypes":6}],3:[function(e,t){var n;n=function(){function e(e){this.user_id=e,this.operation_counter={},this.buffer={},this.change_listeners=[]}return e.prototype.getUserId=function(){return this.user_id},e.prototype.getReservedUniqueIdentifier=function(){return{creator:"_",op_number:"_"}},e.prototype.getOperationCounter=function(){var e,t,n,r;t={},r=this.operation_counter;for(n in r)e=r[n],t[n]=e;return t},e.prototype._encode=function(e){var t,n,r,i,o,s,u,p,c,a;null==e&&(e={}),t=[],p=function(t,n){if(null==t||null==n)throw new Error("dah!");return null==e[t]||e[t]<=n},a=this.buffer;for(u in a){c=a[u];for(o in c)if(n=c[o],!isNaN(parseInt(o))&&p(u,o)){if(r=n._encode(),null!=n.next_cl){for(i=n.next_cl;null!=i.next_cl&&p(i.creator,i.op_number);)i=i.next_cl;r.next=i.getUid()}else if(null!=n.prev_cl){for(s=n.prev_cl;null!=s.prev_cl&&p(i.creator,i.op_number);)s=s.prev_cl;r.prev=s.getUid()}t.push(r)}}return t},e.prototype.getNextOperationIdentifier=function(e){var t;return null==e&&(e=this.user_id),null==this.operation_counter[e]&&(this.operation_counter[e]=0),t={creator:e,op_number:this.operation_counter[e]},this.operation_counter[e]++,t},e.prototype.getOperation=function(e){var t;if(e instanceof Object)return null!=(t=this.buffer[e.creator])?t[e.op_number]:void 0;if(null!=e)throw new Error("This type of uid is not defined!")},e.prototype.addOperation=function(e){if(null==this.buffer[e.creator]&&(this.buffer[e.creator]={}),null!=this.buffer[e.creator][e.op_number])throw new Error("You must not overwrite operations!");return this.buffer[e.creator][e.op_number]=e,e},e.prototype.addToCounter=function(e){return null==this.operation_counter[e.creator]&&(this.operation_counter[e.creator]=0),"number"==typeof e.op_number&&e.creator!==this.getUserId()?this.operation_counter[e.creator]++:void 0},e}(),t.exports=n},{}],4:[function(e,t){var n={}.hasOwnProperty,r=function(e,t){function r(){this.constructor=e}for(var i in t)n.call(t,i)&&(e[i]=t[i]);return r.prototype=t.prototype,e.prototype=new r,e.__super__=t.prototype,e};t.exports=function(e){var t,n,i,o,s,u,p;return p={},u=[],s=function(){function t(t){null==t&&(t=e.getNextOperationIdentifier()),this.creator=t.creator,this.op_number=t.op_number}return t.prototype.on=function(e,t){var n;return null==this.event_listeners&&(this.event_listeners={}),null==(n=this.event_listeners)[e]&&(n[e]=[]),this.event_listeners[e].push(t)},t.prototype.callEvent=function(e,t){var n,r,i,o,s;if(null!=this.event_listeners[e]){for(o=this.event_listeners[e],s=[],r=0,i=o.length;i>r;r++)n=o[r],s.push(n.call(this,e,t));return s}},t.prototype.setParent=function(e){return this.parent=e},t.prototype.getUid=function(){return{creator:this.creator,op_number:this.op_number}},t.prototype.execute=function(){var e,t,n;for(this.is_executed=!0,t=0,n=u.length;n>t;t++)(e=u[t])(this._encode());return this},t.prototype.saveOperation=function(e,t){return null!=(null!=t?t.execute:void 0)?this[e]=t:null!=t?(null==this.unchecked&&(this.unchecked={}),this.unchecked[e]=t):void 0},t.prototype.validateSavedOperations=function(){var t,n,r,i,o,s;o={},i=this,s=this.unchecked;for(t in s)r=s[t],n=e.getOperation(r),n?this[t]=n:(o[t]=r,i=!1);return delete this.unchecked,i||(this.unchecked=o),i},t}(),t=function(e){function t(e,n){this.saveOperation("deletes",n),t.__super__.constructor.call(this,e)}return r(t,e),t.prototype._encode=function(){return{type:"Delete",uid:this.getUid(),deletes:this.deletes.getUid()}},t.prototype.execute=function(){return this.validateSavedOperations()?(this.deletes.applyDelete(this),t.__super__.execute.apply(this,arguments),this):!1},t}(s),p.Delete=function(e){var n,r;return r=e.uid,n=e.deletes,new t(r,n)},o=function(e){function t(e,n,r,i){this.saveOperation("prev_cl",n),this.saveOperation("next_cl",r),null!=i?this.saveOperation("origin",i):this.saveOperation("origin",n),t.__super__.constructor.call(this,e)}return r(t,e),t.prototype.applyDelete=function(e){return null==this.deleted_by&&(this.deleted_by=[]),this.deleted_by.push(e)},t.prototype.isDeleted=function(){var e;return(null!=(e=this.deleted_by)?e.length:void 0)>0},t.prototype.getDistanceToOrigin=function(){var e,t;for(e=0,t=this.prev_cl;;){if(this.origin===t)break;if(e++,this===this.prev_cl)throw new Error("this should not happen ;) ");t=t.prev_cl}return e},t.prototype.update_sl=function(){var e;return e=this.prev_cl,update("prev_cl","prev_sl"),update("next_cl","prev_sl")},t.prototype.execute=function(){var e,n,r,i,o;if(null!=this.is_executed)return this;if(this.validateSavedOperations()){if((null!=(i=this.prev_cl)?i.validateSavedOperations():void 0)&&(null!=(o=this.next_cl)?o.validateSavedOperations():void 0)&&this.prev_cl.next_cl!==this){for(e=0,r=this.prev_cl.next_cl,n=0;;){if(null==r&&(console.log(JSON.stringify(this.prev_cl.getUid())),console.log(JSON.stringify(this.next_cl.getUid()))),r===this.next_cl)break;if(r.getDistanceToOrigin()===n)r.creator0)for(;;){if(t=t.next_cl,t.isDeleted()||(e-=1),0===e)break;if(t instanceof a.Delimiter)throw new Error("position parameter exceeded the length of the document!")}return t},n}(a.Insert),s=function(t){function n(e,t,r,i,o,s,u){n.__super__.constructor.call(this,t,r,i,o,s,u),null!=e&&this.replace(e)}return i(n,t),n.prototype.replace=function(t){var n,r;return n=this.getLastOperation(),r=new u(t,this,void 0,n,n.next_cl),e.addOperation(r).execute()},n.prototype.val=function(){var e;if(e=this.getLastOperation(),e instanceof a.Delimiter)throw new Error("dtrn");return e.val()},n.prototype._encode=function(){var e;return e={type:"ReplaceManager",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&null!=this.next_cl&&(e.prev=this.prev_cl.getUid(),e.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},n}(r),c.ReplaceManager=function(e){var t,n,r,i,o,u,p;return n=e.content,p=e.uid,u=e.prev,i=e.next,o=e.origin,t=e.beginning,r=e.end,new s(n,p,t,r,u,i,o)},u=function(e){function t(e,n,r,i,o,s){if(this.saveOperation("content",e),this.saveOperation("parent",n),null==i||null==o||null==e)throw new Error("You must define content, prev, and next for Replaceable-types!");t.__super__.constructor.call(this,r,i,o,s)}return i(t,e),t.prototype.val=function(){return this.content},t.prototype.replace=function(e){return this.parent.replace(e)},t.prototype.execute=function(){var e;return this.validateSavedOperations()?("function"==typeof(e=this.content).setReplaceManager&&e.setReplaceManager(this.parent),t.__super__.execute.apply(this,arguments),this):!1},t.prototype._encode=function(){var e;return e={type:"Replaceable",content:this.content.getUid(),ReplaceManager:this.parent.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid(),uid:this.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},t}(a.Insert),c.Replaceable=function(e){var t,n,r,i,o,s;return t=e.content,i=e.ReplaceManager,s=e.uid,o=e.prev,n=e.next,r=e.origin,new u(t,i,s,o,n,r)},a.ListManager=r,a.MapManager=o,a.ReplaceManager=s,a.Replaceable=u,p}},{"./BasicTypes":4}],6:[function(e,t){var n,r={}.hasOwnProperty,i=function(e,t){function n(){this.constructor=e}for(var i in t)r.call(t,i)&&(e[i]=t[i]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e};n=e("./StructuredTypes"),t.exports=function(e){var t,r,o,s,u,p;return u=n(e),p=u.types,s=u.parser,t=function(e){function t(){return t.__super__.constructor.apply(this,arguments)}return i(t,e),t}(p.Delete),s.TextDelete=s.Delete,r=function(e){function t(e,n,r,i,o){if(this.content=e,null==r||null==i)throw new Error("You must define prev, and next for TextInsert-types!");t.__super__.constructor.call(this,n,r,i,o)}return i(t,e),t.prototype.getLength=function(){return this.isDeleted()?0:this.content.length},t.prototype.val=function(){return this.isDeleted()?"":this.content},t.prototype._encode=function(){var e;return e={type:"TextInsert",content:this.content,uid:this.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},t}(p.Insert),s.TextInsert=function(e){var t,n,i,o,s;return t=e.content,s=e.uid,o=e.prev,n=e.next,i=e.origin,new r(t,s,o,n,i)},o=function(n){function o(e,t,n,r,i,s){o.__super__.constructor.call(this,e,t,n,r,i,s)}return i(o,n),o.prototype.insertText=function(t,n){var i,o,s,u,p,c;for(o=this.getOperationByPosition(t),c=[],u=0,p=n.length;p>u;u++)i=n[u],s=new r(i,void 0,o.prev_cl,o),c.push(e.addOperation(s).execute());return c},o.prototype.deleteText=function(n,r){var i,o,s,u,c;for(s=this.getOperationByPosition(n),c=[],o=u=0;r>=0?r>u:u>r;o=r>=0?++u:--u){for(i=e.addOperation(new t(void 0,s)).execute(),s=s.next_cl;s.isDeleted();){if(s instanceof p.Delimiter)throw new Error("You can't delete more than there is..");s=s.next_cl}c.push(i._encode())}return c},o.prototype.replaceText=function(t){var n;if(null!=this.replace_manager)return n=e.addOperation(new o(void 0)).execute(),n.insertText(0,t),this.replace_manager.replace(n);throw new Error("This type is currently not maintained by a ReplaceManager!")},o.prototype.val=function(){var e,t;return e=function(){var e,n,r,i;for(r=this.toArray(),i=[],e=0,n=r.length;n>e;e++)t=r[e],i.push(null!=t.val?t.val():"");return i}.call(this),e.join("")},o.prototype.setReplaceManager=function(e){return this.saveOperation("replace_manager",e),this.validateSavedOperations},o.prototype._encode=function(){var e;return e={type:"Word",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&(e.prev=this.prev_cl.getUid()),null!=this.next_cl&&(e.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},o}(p.ListManager),s.Word=function(e){var t,n,r,i,s,u;return u=e.uid,t=e.beginning,n=e.end,s=e.prev,r=e.next,i=e.origin,new o(u,t,n,s,r,i)},p.TextInsert=r,p.TextDelete=t,p.Word=o,u}},{"./StructuredTypes":5}]},{},[2]); \ No newline at end of file diff --git a/build/browser/HistoryBuffer.js b/build/browser/HistoryBuffer.js new file mode 100644 index 00000000..45f6f737 --- /dev/null +++ b/build/browser/HistoryBuffer.js @@ -0,0 +1,128 @@ +(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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0; + }; + + Insert.prototype.getDistanceToOrigin = function() { + var d, o; + d = 0; + o = this.prev_cl; + while (true) { + if (this.origin === o) { + break; + } + d++; + if (this === this.prev_cl) { + throw new Error("this should not happen ;) "); + } + o = o.prev_cl; + } + return d; + }; + + Insert.prototype.update_sl = function() { + var o; + o = this.prev_cl; + ({ + update: function(dest_cl, dest_sl) { + var _results; + _results = []; + while (true) { + if (o.isDeleted()) { + _results.push(o = o[dest_cl]); + } else { + this[dest_sl] = o; + break; + } + } + return _results; + } + }); + update("prev_cl", "prev_sl"); + return update("next_cl", "prev_sl"); + }; + + Insert.prototype.execute = function() { + var distance_to_origin, i, o, _ref, _ref1; + if (this.is_executed != null) { + return this; + } + if (!this.validateSavedOperations()) { + return false; + } else { + if (((_ref = this.prev_cl) != null ? _ref.validateSavedOperations() : void 0) && ((_ref1 = this.next_cl) != null ? _ref1.validateSavedOperations() : void 0) && this.prev_cl.next_cl !== this) { + distance_to_origin = 0; + o = this.prev_cl.next_cl; + i = 0; + while (true) { + if (o == null) { + console.log(JSON.stringify(this.prev_cl.getUid())); + console.log(JSON.stringify(this.next_cl.getUid())); + } + if (o !== this.next_cl) { + if (o.getDistanceToOrigin() === i) { + if (o.creator < this.creator) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else if (o.getDistanceToOrigin() < i) { + if (i - distance_to_origin <= o.getDistanceToOrigin()) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else { + break; + } + i++; + o = o.next_cl; + } else { + break; + } + } + this.next_cl = this.prev_cl.next_cl; + this.prev_cl.next_cl = this; + this.next_cl.prev_cl = this; + } + Insert.__super__.execute.apply(this, arguments); + return this; + } + }; + + return Insert; + + })(Operation); + ImmutableObject = (function(_super) { + __extends(ImmutableObject, _super); + + function ImmutableObject(uid, content, prev, next, origin) { + this.content = content; + ImmutableObject.__super__.constructor.call(this, uid, prev, next, origin); + } + + ImmutableObject.prototype.val = function() { + return this.content; + }; + + ImmutableObject.prototype._encode = function() { + var json; + json = { + 'type': "ImmutableObject", + 'uid': this.getUid(), + 'content': this.content + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ImmutableObject; + + })(Insert); + parser['ImmutableObject'] = function(json) { + var content, next, origin, prev, uid; + uid = json['uid'], content = json['content'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new ImmutableObject(uid, content, prev, next, origin); + }; + Delimiter = (function(_super) { + __extends(Delimiter, _super); + + function Delimiter(uid, prev_cl, next_cl, origin) { + this.saveOperation('prev_cl', prev_cl); + this.saveOperation('next_cl', next_cl); + this.saveOperation('origin', prev_cl); + Delimiter.__super__.constructor.call(this, uid); + } + + Delimiter.prototype.isDeleted = function() { + return false; + }; + + Delimiter.prototype.execute = function() { + var _ref, _ref1; + if (((_ref = this.unchecked) != null ? _ref['next_cl'] : void 0) != null) { + return Delimiter.__super__.execute.apply(this, arguments); + } else if ((_ref1 = this.unchecked) != null ? _ref1['prev_cl'] : void 0) { + if (this.validateSavedOperations()) { + if (this.prev_cl.next_cl != null) { + throw new Error("Probably duplicated operations"); + } + this.prev_cl.next_cl = this; + delete this.prev_cl.unchecked.next_cl; + return Delimiter.__super__.execute.apply(this, arguments); + } else { + return false; + } + } else if ((this.prev_cl != null) && (this.prev_cl.next_cl == null)) { + delete this.prev_cl.unchecked.next_cl; + return this.prev_cl.next_cl = this; + } else if ((this.prev_cl != null) || (this.next_cl != null)) { + return Delimiter.__super__.execute.apply(this, arguments); + } else { + throw new Error("Delimiter is unsufficient defined!"); + } + }; + + Delimiter.prototype._encode = function() { + var _ref, _ref1; + return { + 'type': "Delimiter", + 'uid': this.getUid(), + 'prev': (_ref = this.prev_cl) != null ? _ref.getUid() : void 0, + 'next': (_ref1 = this.next_cl) != null ? _ref1.getUid() : void 0 + }; + }; + + return Delimiter; + + })(Operation); + parser['Delimiter'] = function(json) { + var next, prev, uid; + uid = json['uid'], prev = json['prev'], next = json['next']; + return new Delimiter(uid, prev, next); + }; + return { + 'types': { + 'Delete': Delete, + 'Insert': Insert, + 'Delimiter': Delimiter, + 'Operation': Operation, + 'ImmutableObject': ImmutableObject + }, + 'parser': parser, + 'execution_listener': execution_listener + }; +}; + + +},{}]},{},[1]) +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL1R5cGVzL0Jhc2ljVHlwZXMuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUEsSUFBQTtpU0FBQTs7QUFBQSxNQUFNLENBQUMsT0FBUCxHQUFpQixTQUFDLEVBQUQsR0FBQTtBQUVmLE1BQUEsaUZBQUE7QUFBQSxFQUFBLE1BQUEsR0FBUyxFQUFULENBQUE7QUFBQSxFQUNBLGtCQUFBLEdBQXFCLEVBRHJCLENBQUE7QUFBQSxFQWFNO0FBTVMsSUFBQSxtQkFBQyxHQUFELEdBQUE7QUFDWCxNQUFBLElBQU8sV0FBUDtBQUNFLFFBQUEsR0FBQSxHQUFNLEVBQUUsQ0FBQywwQkFBSCxDQUFBLENBQU4sQ0FERjtPQUFBO0FBQUEsTUFHYSxJQUFDLENBQUEsY0FBWixVQURGLEVBRWdCLElBQUMsQ0FBQSxnQkFBZixZQUpGLENBRFc7SUFBQSxDQUFiOztBQUFBLHdCQWFBLEVBQUEsR0FBSSxTQUFDLEtBQUQsRUFBUSxDQUFSLEdBQUE7QUFDRixVQUFBLEtBQUE7O1FBQUEsSUFBQyxDQUFBLGtCQUFtQjtPQUFwQjs7YUFDaUIsQ0FBQSxLQUFBLElBQVU7T0FEM0I7YUFFQSxJQUFDLENBQUEsZUFBZ0IsQ0FBQSxLQUFBLENBQU0sQ0FBQyxJQUF4QixDQUE2QixDQUE3QixFQUhFO0lBQUEsQ0FiSixDQUFBOztBQUFBLHdCQXNCQSxTQUFBLEdBQVcsU0FBQyxLQUFELEVBQVEsSUFBUixHQUFBO0FBQ1QsVUFBQSwyQkFBQTtBQUFBLE1BQUEsSUFBRyxtQ0FBSDtBQUNFO0FBQUE7YUFBQSwyQ0FBQTt1QkFBQTtBQUNFLHdCQUFBLENBQUMsQ0FBQyxJQUFGLENBQU8sSUFBUCxF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R0UsTUFBQSxzQ0FBaUIsQ0FBRSxNQUFWLENBQUEsVUFIWDtBQUFBLFFBSUUsTUFBQSx3Q0FBaUIsQ0FBRSxNQUFWLENBQUEsVUFKWDtRQURPO0lBQUEsQ0F0Q1QsQ0FBQTs7cUJBQUE7O0tBUnNCLFVBeFd4QixDQUFBO0FBQUEsRUE4WkEsTUFBTyxDQUFBLFdBQUEsQ0FBUCxHQUFzQixTQUFDLElBQUQsR0FBQTtBQUNwQixRQUFBLGVBQUE7QUFBQSxJQUNRLFdBQVIsTUFEQSxFQUVTLFlBQVQsT0FGQSxFQUdTLFlBQVQsT0FIQSxDQUFBO1dBS0ksSUFBQSxTQUFBLENBQVUsR0FBVixFQUFlLElBQWYsRUFBcUIsSUFBckIsRUFOZ0I7RUFBQSxDQTladEIsQ0FBQTtTQXVhQTtBQUFBLElBQ0UsT0FBQSxFQUNFO0FBQUEsTUFBQSxRQUFBLEVBQVcsTUFBWDtBQUFBLE1BQ0EsUUFBQSxFQUFXLE1BRFg7QUFBQSxNQUVBLFdBQUEsRUFBYSxTQUZiO0FBQUEsTUFHQSxXQUFBLEVBQWEsU0FIYjtBQUFBLE1BSUEsaUJBQUEsRUFBb0IsZUFKcEI7S0FGSjtBQUFBLElBT0UsUUFBQSxFQUFXLE1BUGI7QUFBQSxJQVFFLG9CQUFBLEVBQXVCLGtCQVJ6QjtJQXphZTtBQUFBLENBQWpCLENBQUEiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKX12YXIgZj1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwoZi5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxmLGYuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwibW9kdWxlLmV4cG9ydHMgPSAoSEIpLT5cbiAgIyBAc2VlIEVuZ2luZS5wYXJzZVxuICBwYXJzZXIgPSB7fVxuICBleGVjdXRpb25fbGlzdGVuZXIgPSBbXVxuXG4gICNcbiAgIyBBIGdlbmVyaWMgaW50ZXJmYWNlIHRvIG9wZXJhdGlvbnMuXG4gICNcbiAgIyBBbiBvcGVyYXRpb24gaGFzIHRoZSBmb2xsb3dpbmcgbWV0aG9kczpcbiAgIyBfZW5jb2RlOiBlbmNvZGVzIGFuIG9wZXJhdGlvbiAobmVlZGVkIG9ubHkgaWYgaW5zdGFuY2Ugb2YgdGhpcyBvcGVyYXRpb24gaXMgc2VudCkuXG4gICMgZXhlY3V0ZTogZXhlY3V0ZSB0aGUgZWZmZWN0cyBvZiB0aGlzIG9wZXJhdGlvbnMuIEdvb2QgZXhhbXBsZXMgYXJlIEluc2VydC10eXBlIGFuZCBBZGROYW1lLXR5cGVcbiAgIyB2YWw6IGluIHRoZSBjYXNlIHRoYXQgdGhlIG9wZXJhdGlvbiBob2xkcyBhIHZhbHVlXG4gICNcbiAgIyBGdXJ0aGVybW9yZSBhbiBlbmNvZGFibGUgb3BlcmF0aW9uIGhhcyBhIHBhcnNlci5cbiAgI1xuICBjbGFzcyBPcGVyYXRpb25cblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBzZWUgSGlzdG9yeUJ1ZmZlci5nZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllclxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCktPlxuICAgICAgaWYgbm90IHVpZD9cbiAgICAgICAgdWlkID0gSEIuZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXIoKVxuICAgICAge1xuICAgICAgICAnY3JlYXRvcic6IEBjcmVhdG9yXG4gICAgICAgICdvcF9udW1iZXInIDogQG9wX251bWJlclxuICAgICAgfSA9IHVpZFxuXG4gICAgI1xuICAgICMgQWRkIGFuIGV2ZW50IGxpc3RlbmVyLiBJdCBkZXBlbmRzIG9uIHRoZSBvcGVyYXRpb24gd2hpY2ggZXZlbnRzIGFyZSBzdXBwb3J0ZWQuXG4gICAgIyBAcGFyYW0ge1N0cmluZ30gZXZlbnQgTmFtZSBvZiB0aGUgZXZlbnQuXG4gICAgIyBAcGFyYW0ge0Z1bmN0aW9ufSBmIGYgaXMgZXhlY3V0ZWQgaW4gY2FzZSB0aGUgZXZlbnQgZmlyZXMuXG4gICAgI1xuICAgIG9uOiAoZXZlbnQsIGYpLT5cbiAgICAgIEBldmVudF9saXN0ZW5lcnMgPz0ge31cbiAgICAgIEBldmVudF9saXN0ZW5lcnNbZXZlbnRdID89IFtdXG4gICAgICBAZXZlbnRfbGlzdGVuZXJzW2V2ZW50XS5wdXNoIGZcblxuICAgICNcbiAgICAjIEZpcmUgYW4gZXZlbnQuXG4gICAgIyBUT0RPOiBEbyBzb21ldGhpbmcgd2l0aCB0aW1lb3V0cy4gWW91IGRvbid0IHdhbnQgdGhpcyB0byBmaXJlIGZvciBldmVyeSBvcGVyYXRpb24gKGUuZy4gaW5zZXJ0KS5cbiAgICAjXG4gICAgY2FsbEV2ZW50OiAoZXZlbnQsIGFyZ3MpLT5cbiAgICAgIGlmIEBldmVudF9saXN0ZW5lcnNbZXZlbnRdP1xuICAgICAgICBmb3IgZiBpbiBAZXZlbnRfbGlzdGVuZXJzW2V2ZW50XVxuICAgICAgICAgIGYuY2FsbCBALCBldmVudCwgYXJnc1xuXG4gICAgI1xuICAgICMgU2V0IHRoZSBwYXJlbnQgb2YgdGhpcyBvcGVyYXRpb24uXG4gICAgI1xuICAgIHNldFBhcmVudDogKG8pLT5cbiAgICAgIEBwYXJlbnQgPSBvXG5cbiAgICAjXG4gICAgIyBDb21wdXRlcyBhIHVuaXF1ZSBpZGVudGlmaWVyICh1aWQpIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi5cbiAgICAjXG4gICAgZ2V0VWlkOiAoKS0+XG4gICAgICB7ICdjcmVhdG9yJzogQGNyZWF0b3IsICdvcF9udW1iZXInOiBAb3BfbnVtYmVyIH1cblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBOb3RpZnkgdGhlIGFsbCB0aGUgbGlzdGVuZXJzLlxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBAaXNfZXhlY3V0ZWQgPSB0cnVlXG4gICAgICBmb3IgbCBpbiBleGVjdXRpb25fbGlzdGVuZXJcbiAgICAgICAgbCBAX2VuY29kZSgpXG4gICAgICBAXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgT3BlcmF0aW9ucyBtYXkgZGVwZW5kIG9uIG90aGVyIG9wZXJhdGlvbnMgKGxpbmtlZCBsaXN0cywgZXRjLikuXG4gICAgIyBUaGUgc2F2ZU9wZXJhdGlvbiBhbmQgdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMgbWV0aG9kcyBwcm92aWRlXG4gICAgIyBhbiBlYXN5IHdheSB0byByZWZlciB0byB0aGVzZSBvcGVyYXRpb25zIHZpYSBhbiB1aWQgb3Igb2JqZWN0IHJlZmVyZW5jZS5cbiAgICAjXG4gICAgIyBGb3IgZXhhbXBsZTogV2UgY2FuIGNyZWF0ZSBhIG5ldyBEZWxldGUgb3BlcmF0aW9uIHRoYXQgZGVsZXRlcyB0aGUgb3BlcmF0aW9uICRvIGxpa2UgdGhpc1xuICAgICMgICAgIC0gdmFyIGQgPSBuZXcgRGVsZXRlKHVpZCwgJG8pOyAgIG9yXG4gICAgIyAgICAgLSB2YXIgZCA9IG5ldyBEZWxldGUodWlkLCAkby5nZXRVaWQoKSk7XG4gICAgIyBFaXRoZXIgd2F5IHdlIHdhbnQgdG8gYWNjZXNzICRvIHZpYSBkLmRlbGV0ZXMuIEluIHRoZSBzZWNvbmQgY2FzZSB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucyBtdXN0IGJlIGNhbGxlZCBmaXJzdC5cbiAgICAjXG4gICAgIyBAb3ZlcmxvYWQgc2F2ZU9wZXJhdGlvbihuYW1lLCBvcF91aWQpXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpb24uIEFmdGVyIHZhbGlkYXRpbmcgKHdpdGggdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMpIHRoZSBpbnN0YW50aWF0ZWQgb3BlcmF0aW9uIHdpbGwgYmUgYWNjZXNzaWJsZSB2aWEgdGhpc1tuYW1lXS5cbiAgICAjICAgQHBhcmFtIHtPYmplY3R9IG9wX3VpZCBBIHVpZCB0aGF0IHJlZmVycyB0byBhbiBvcGVyYXRpb25cbiAgICAjIEBvdmVybG9hZCBzYXZlT3BlcmF0aW9uKG5hbWUsIG9wKVxuICAgICMgICBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgb3BlcmF0aW9uLiBBZnRlciBjYWxsaW5nIHRoaXMgZnVuY3Rpb24gb3AgaXMgYWNjZXNzaWJsZSB2aWEgdGhpc1tuYW1lXS5cbiAgICAjICAgQHBhcmFtIHtPcGVyYXRpb259IG9wIEFuIE9wZXJhdGlvbiBvYmplY3RcbiAgICAjXG4gICAgc2F2ZU9wZXJhdGlvbjogKG5hbWUsIG9wKS0+XG5cbiAgICAgICNcbiAgICAgICMgRXZlcnkgaW5zdGFuY2Ugb2YgJE9wZXJhdGlvbiBtdXN0IGhhdmUgYW4gJGV4ZWN1dGUgZnVuY3Rpb24uXG4gICAgICAjIFdlIHVzZSBkdWNrLXR5cGluZyB0byBjaGVjayBpZiBvcCBpcyBpbnN0YW50aWF0ZWQgc2luY2UgdGhlcmVcbiAgICAgICMgY291bGQgZXhpc3QgbXVsdGlwbGUgY2xhc3NlcyBvZiAkT3BlcmF0aW9uXG4gICAgICAjXG4gICAgICBpZiBvcD8uZXhlY3V0ZT9cbiAgICAgICAgIyBpcyBpbnN0YW50aWF0ZWRcbiAgICAgICAgQFtuYW1lXSA9IG9wXG4gICAgICBlbHNlIGlmIG9wP1xuICAgICAgICAjIG5vdCBpbml0aWFsaXplZC4gRG8gaXQgd2hlbiBjYWxsaW5nICR2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIEB1bmNoZWNrZWQgPz0ge31cbiAgICAgICAgQHVuY2hlY2tlZFtuYW1lXSA9IG9wXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgQWZ0ZXIgY2FsbGluZyB0aGlzIGZ1bmN0aW9uIGFsbCBub3QgaW5zdGFudGlhdGVkIG9wZXJhdGlvbnMgd2lsbCBiZSBhY2Nlc3NpYmxlLlxuICAgICMgQHNlZSBPcGVyYXRpb24uc2F2ZU9wZXJhdGlvblxuICAgICNcbiAgICAjIEByZXR1cm4gW0Jvb2xlYW5dIFdoZXRoZXIgaXQgd2FzIHBvc3NpYmxlIHRvIGluc3RhbnRpYXRlIGFsbCBvcGVyYXRpb25zLlxuICAgICNcbiAgICB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9uczogKCktPlxuICAgICAgdW5pbnN0YW50aWF0ZWQgPSB7fVxuICAgICAgc3VjY2VzcyA9IEBcbiAgICAgIGZvciBuYW1lLCBvcF91aWQgb2YgQHVuY2hlY2tlZFxuICAgICAgICBvcCA9IEhCLmdldE9wZXJhdGlvbiBvcF91aWRcbiAgICAgICAgaWYgb3BcbiAgICAgICAgICBAW25hbWVdID0gb3BcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHVuaW5zdGFudGlhdGVkW25hbWVdID0gb3BfdWlkXG4gICAgICAgICAgc3VjY2VzcyA9IGZhbHNlXG4gICAgICBkZWxldGUgQHVuY2hlY2tlZFxuICAgICAgaWYgbm90IHN1Y2Nlc3NcbiAgICAgICAgQHVuY2hlY2tlZCA9IHVuaW5zdGFudGlhdGVkXG4gICAgICBzdWNjZXNzXG5cblxuXG4gICNcbiAgIyBBIHNpbXBsZSBEZWxldGUtdHlwZSBvcGVyYXRpb24gdGhhdCBkZWxldGVzIGFuIEluc2VydC10eXBlIG9wZXJhdGlvbi5cbiAgI1xuICBjbGFzcyBEZWxldGUgZXh0ZW5kcyBPcGVyYXRpb25cblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSBkZWxldGVzIFVJRCBvciByZWZlcmVuY2Ugb2YgdGhlIG9wZXJhdGlvbiB0aGF0IHRoaXMgdG8gYmUgZGVsZXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIGRlbGV0ZXMpLT5cbiAgICAgIEBzYXZlT3BlcmF0aW9uICdkZWxldGVzJywgZGVsZXRlc1xuICAgICAgc3VwZXIgdWlkXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgQ29udmVydCBhbGwgcmVsZXZhbnQgaW5mb3JtYXRpb24gb2YgdGhpcyBvcGVyYXRpb24gdG8gdGhlIGpzb24tZm9ybWF0LlxuICAgICMgVGhpcyByZXN1bHQgY2FuIGJlIHNlbnQgdG8gb3RoZXIgY2xpZW50cy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAge1xuICAgICAgICAndHlwZSc6IFwiRGVsZXRlXCJcbiAgICAgICAgJ3VpZCc6IEBnZXRVaWQoKVxuICAgICAgICAnZGVsZXRlcyc6IEBkZWxldGVzLmdldFVpZCgpXG4gICAgICB9XG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgQXBwbHkgdGhlIGRlbGV0aW9uLlxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICBAZGVsZXRlcy5hcHBseURlbGV0ZSBAXG4gICAgICAgIHN1cGVyXG4gICAgICAgIEBcbiAgICAgIGVsc2VcbiAgICAgICAgZmFsc2VcblxuICAjXG4gICMgRGVmaW5lIGhvdyB0byBwYXJzZSBEZWxldGUgb3BlcmF0aW9ucy5cbiAgI1xuICBwYXJzZXJbJ0RlbGV0ZSddID0gKG8pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ2RlbGV0ZXMnOiBkZWxldGVzX3VpZFxuICAgIH0gPSBvXG4gICAgbmV3IERlbGV0ZSB1aWQsIGRlbGV0ZXNfdWlkXG5cbiAgI1xuICAjIEEgc2ltcGxlIGluc2VydC10eXBlIG9wZXJhdGlvbi5cbiAgI1xuICAjIEFuIGluc2VydCBvcGVyYXRpb24gaXMgYWx3YXlzIHBvc2l0aW9uZWQgYmV0d2VlbiB0d28gb3RoZXIgaW5zZXJ0IG9wZXJhdGlvbnMuXG4gICMgSW50ZXJuYWxseSB0aGlzIGlzIHJlYWxpemVkIGFzIGFzc29jaWF0aXZlIGxpc3RzLCB3aGVyZWJ5IGVhY2ggaW5zZXJ0IG9wZXJhdGlvbiBoYXMgYSBwcmVkZWNlc3NvciBhbmQgYSBzdWNjZXNzb3IuXG4gICMgRm9yIHRoZSBzYWtlIG9mIGVmZmljaWVuY3kgd2UgbWFpbnRhaW4gdHdvIGxpc3RzOlxuICAjICAgLSBUaGUgc2hvcnQtbGlzdCAoYWJicmV2LiBzbCkgbWFpbnRhaW5zIG9ubHkgdGhlIG9wZXJhdGlvbnMgdGhhdCBhcmUgbm90IGRlbGV0ZWRcbiAgIyAgIC0gVGhlIGNvbXBsZXRlLWxpc3QgKGFiYnJldi4gY2wpIG1haW50YWlucyBhbGwgb3BlcmF0aW9uc1xuICAjXG4gIGNsYXNzIEluc2VydCBleHRlbmRzIE9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IHByZXZfY2wgVGhlIHByZWRlY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBuZXh0X2NsIFRoZSBzdWNjZXNzb3Igb2YgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGNvbXBsZXRlLWxpc3QgKGNsKVxuICAgICNcbiAgICAjIEBzZWUgSGlzdG9yeUJ1ZmZlci5nZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllclxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgcHJldl9jbCwgbmV4dF9jbCwgb3JpZ2luKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncHJldl9jbCcsIHByZXZfY2xcbiAgICAgIEBzYXZlT3BlcmF0aW9uICduZXh0X2NsJywgbmV4dF9jbFxuICAgICAgaWYgb3JpZ2luP1xuICAgICAgICBAc2F2ZU9wZXJhdGlvbiAnb3JpZ2luJywgb3JpZ2luXG4gICAgICBlbHNlXG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBwcmV2X2NsXG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgI1xuICAgIGFwcGx5RGVsZXRlOiAobyktPlxuICAgICAgQGRlbGV0ZWRfYnkgPz0gW11cbiAgICAgIEBkZWxldGVkX2J5LnB1c2ggb1xuXG4gICAgI1xuICAgICMgSWYgaXNEZWxldGVkKCkgaXMgdHJ1ZSB0aGlzIG9wZXJhdGlvbiB3b24ndCBiZSBtYWludGFpbmVkIGluIHRoZSBzbFxuICAgICNcbiAgICBpc0RlbGV0ZWQ6ICgpLT5cbiAgICAgIEBkZWxldGVkX2J5Py5sZW5ndGggPiAwXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgVGhlIGFtb3VudCBvZiBwb3NpdGlvbnMgdGhhdCAkdGhpcyBvcGVyYXRpb24gd2FzIG1vdmVkIHRvIHRoZSByaWdodC5cbiAgICAjXG4gICAgZ2V0RGlzdGFuY2VUb09yaWdpbjogKCktPlxuICAgICAgZCA9IDBcbiAgICAgIG8gPSBAcHJldl9jbFxuICAgICAgd2hpbGUgdHJ1ZVxuICAgICAgICBpZiBAb3JpZ2luIGlzIG9cbiAgICAgICAgICBicmVha1xuICAgICAgICBkKytcbiAgICAgICAgI1RPRE86IGRlbGV0ZSB0aGlzXG4gICAgICAgIGlmIEAgaXMgQHByZXZfY2xcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJ0aGlzIHNob3VsZCBub3QgaGFwcGVuIDspIFwiXG4gICAgICAgIG8gPSBvLnByZXZfY2xcbiAgICAgIGRcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBVcGRhdGUgdGhlIHNob3J0IGxpc3RcbiAgICAjIFRPRE8gKFVudXNlZClcbiAgICB1cGRhdGVfc2w6ICgpLT5cbiAgICAgIG8gPSBAcHJldl9jbFxuICAgICAgdXBkYXRlOiAoZGVzdF9jbCxkZXN0X3NsKS0+XG4gICAgICAgIHdoaWxlIHRydWVcbiAgICAgICAgICBpZiBvLmlzRGVsZXRlZCgpXG4gICAgICAgICAgICBvID0gb1tkZXN0X2NsXVxuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIEBbZGVzdF9zbF0gPSBvXG5cbiAgICAgICAgICAgIGJyZWFrXG4gICAgICB1cGRhdGUgXCJwcmV2X2NsXCIsIFwicHJldl9zbFwiXG4gICAgICB1cGRhdGUgXCJuZXh0X2NsXCIsIFwicHJldl9zbFwiXG5cblxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIEluY2x1ZGUgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGFzc29jaWF0aXZlIGxpc3RzLlxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBAaXNfZXhlY3V0ZWQ/XG4gICAgICAgIHJldHVybiBAXG4gICAgICBpZiBub3QgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICBlbHNlXG4gICAgICAgIGlmIEBwcmV2X2NsPy52YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpIGFuZCBAbmV4dF9jbD8udmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKSBhbmQgQHByZXZfY2wubmV4dF9jbCBpc250IEBcbiAgICAgICAgICBkaXN0YW5jZV90b19vcmlnaW4gPSAwXG4gICAgICAgICAgbyA9IEBwcmV2X2NsLm5leHRfY2xcbiAgICAgICAgICBpID0gMFxuICAgICAgICAgICMgJHRoaXMgaGFzIHRvIGZpbmQgYSB1bmlxdWUgcG9zaXRpb24gYmV0d2VlbiBvcmlnaW4gYW5kIHRoZSBuZXh0IGtub3duIGNoYXJhY3RlclxuICAgICAgICAgICMgY2FzZSAxOiAkb3JpZ2luIGVxdWFscyAkby5vcmlnaW46IHRoZSAkY3JlYXRvciBwYXJhbWV0ZXIgZGVjaWRlcyBpZiBsZWZ0IG9yIHJpZ2h0XG4gICAgICAgICAgIyAgICAgICAgIGxldCAkT0w9IFtvMSxvMixvMyxvNF0sIHdoZXJlYnkgJHRoaXMgaXMgdG8gYmUgaW5zZXJ0ZWQgYmV0d2VlbiBvMSBhbmQgbzRcbiAgICAgICAgICAjICAgICAgICAgbzIsbzMgYW5kIG80IG9yaWdpbiBpcyAxICh0aGUgcG9zaXRpb24gb2YgbzIpXG4gICAgICAgICAgIyAgICAgICAgIHRoZXJlIGlzIHRoZSBjYXNlIHRoYXQgJHRoaXMuY3JlYXRvciA8IG8yLmNyZWF0b3IsIGJ1dCBvMy5jcmVhdG9yIDwgJHRoaXMuY3JlYXRvclxuICAgICAgICAgICMgICAgICAgICB0aGVuIG8yIGtub3dzIG8zLiBTaW5jZSBvbiBhbm90aGVyIGNsaWVudCAkT0wgY291bGQgYmUgW28xLG8zLG80XSB0aGUgcHJvYmxlbSBpcyBjb21wbGV4XG4gICAgICAgICAgIyAgICAgICAgIHRoZXJlZm9yZSAkdGhpcyB3b3VsZCBiZSBhbHdheXMgdG8gdGhlIHJpZ2h0IG9mIG8zXG4gICAgICAgICAgIyBjYXNlIDI6ICRvcmlnaW4gPCAkby5vcmlnaW5cbiAgICAgICAgICAjICAgICAgICAgaWYgY3VycmVudCAkdGhpcyBpbnNlcnRfcG9zaXRpb24gPiAkbyBvcmlnaW46ICR0aGlzIGluc1xuICAgICAgICAgICMgICAgICAgICBlbHNlICRpbnNlcnRfcG9zaXRpb24gd2lsbCBub3QgY2hhbmdlIChtYXliZSB3ZSBlbmNvdW50ZXIgY2FzZSAxIGxhdGVyLCB0aGVuIHRoaXMgd2lsbCBiZSB0byB0aGUgcmlnaHQgb2YgJG8pXG4gICAgICAgICAgIyBjYXNlIDM6ICRvcmlnaW4gPiAkby5vcmlnaW5cbiAgICAgICAgICAjICAgICAgICAgJHRoaXMgaW5zZXJ0X3Bvc2l0aW9uIGlzIHRvIHRoZSBsZWZ0IG9mICRvIChmb3JldmVyISlcbiAgICAgICAgICB3aGlsZSB0cnVlXG4gICAgICAgICAgICBpZiBub3Qgbz9cbiAgICAgICAgICAgICAgIyBUT0RPOiBEZWJ1Z2dpbmdcbiAgICAgICAgICAgICAgY29uc29sZS5sb2cgSlNPTi5zdHJpbmdpZnkgQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgICAgICAgICAgY29uc29sZS5sb2cgSlNPTi5zdHJpbmdpZnkgQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgICAgICAgIGlmIG8gaXNudCBAbmV4dF9jbFxuICAgICAgICAgICAgICAjICRvIGhhcHBlbmVkIGNvbmN1cnJlbnRseVxuICAgICAgICAgICAgICBpZiBvLmdldERpc3RhbmNlVG9PcmlnaW4oKSBpcyBpXG4gICAgICAgICAgICAgICAgIyBjYXNlIDFcbiAgICAgICAgICAgICAgICBpZiBvLmNyZWF0b3IgPCBAY3JlYXRvclxuICAgICAgICAgICAgICAgICAgQHByZXZfY2wgPSBvXG4gICAgICAgICAgICAgICAgICBkaXN0YW5jZV90b19vcmlnaW4gPSBpICsgMVxuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICMgbm9wXG4gICAgICAgICAgICAgIGVsc2UgaWYgby5nZXREaXN0YW5jZVRvT3JpZ2luKCkgPCBpXG4gICAgICAgICAgICAgICAgIyBjYXNlIDJcbiAgICAgICAgICAgICAgICBpZiBpIC0gZGlzdGFuY2VfdG9fb3JpZ2luIDw9IG8uZ2V0RGlzdGFuY2VUb09yaWdpbigpXG4gICAgICAgICAgICAgICAgICBAcHJldl9jbCA9IG9cbiAgICAgICAgICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IGkgKyAxXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgI25vcFxuICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgIyBjYXNlIDNcbiAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICBpKytcbiAgICAgICAgICAgICAgbyA9IG8ubmV4dF9jbFxuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAjICR0aGlzIGtub3dzIHRoYXQgJG8gZXhpc3RzLFxuICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICMgbm93IHJlY29ubmVjdCBldmVyeXRoaW5nXG4gICAgICAgICAgQG5leHRfY2wgPSBAcHJldl9jbC5uZXh0X2NsXG4gICAgICAgICAgQHByZXZfY2wubmV4dF9jbCA9IEBcbiAgICAgICAgICBAbmV4dF9jbC5wcmV2X2NsID0gQFxuICAgICAgICBzdXBlciAjIG5vdGlmeSB0aGUgZXhlY3V0aW9uX2xpc3RlbmVyc1xuICAgICAgICBAXG5cbiAgI1xuICAjIERlZmluZXMgYW4gb2JqZWN0IHRoYXQgaXMgY2Fubm90IGJlIGNoYW5nZWQuIFlvdSBjYW4gdXNlIHRoaXMgdG8gc2V0IGFuIGltbXV0YWJsZSBzdHJpbmcsIG9yIGEgbnVtYmVyLlxuICAjXG4gIGNsYXNzIEltbXV0YWJsZU9iamVjdCBleHRlbmRzIEluc2VydFxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IGNvbnRlbnRcbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIEBjb250ZW50LCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIHN1cGVyIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cbiAgICAjXG4gICAgIyBAcmV0dXJuIFtTdHJpbmddIFRoZSBjb250ZW50IG9mIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICB2YWwgOiAoKS0+XG4gICAgICBAY29udGVudFxuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9IHtcbiAgICAgICAgJ3R5cGUnOiBcIkltbXV0YWJsZU9iamVjdFwiXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICdjb250ZW50JyA6IEBjb250ZW50XG4gICAgICB9XG4gICAgICBpZiBAcHJldl9jbD9cbiAgICAgICAganNvblsncHJldiddID0gQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgIGlmIEBuZXh0X2NsP1xuICAgICAgICBqc29uWyduZXh0J10gPSBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgaWYgQG9yaWdpbj8gYW5kIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uW1wib3JpZ2luXCJdID0gQG9yaWdpbi5nZXRVaWQoKVxuICAgICAganNvblxuXG4gIHBhcnNlclsnSW1tdXRhYmxlT2JqZWN0J10gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAnY29udGVudCcgOiBjb250ZW50XG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBJbW11dGFibGVPYmplY3QgdWlkLCBjb250ZW50LCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICAjXG4gICMgQSBkZWxpbWl0ZXIgaXMgcGxhY2VkIGF0IHRoZSBlbmQgYW5kIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFzc29jaWF0aXZlIGxpc3RzLlxuICAjIFRoaXMgaXMgbmVjZXNzYXJ5IGluIG9yZGVyIHRvIGhhdmUgYSBiZWdpbm5pbmcgYW5kIGFuIGVuZCBldmVuIGlmIHRoZSBjb250ZW50XG4gICMgb2YgdGhlIEVuZ2luZSBpcyBlbXB0eS5cbiAgI1xuICBjbGFzcyBEZWxpbWl0ZXIgZXh0ZW5kcyBPcGVyYXRpb25cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gcHJldl9jbCBUaGUgcHJlZGVjZXNzb3Igb2YgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGNvbXBsZXRlLWxpc3QgKGNsKVxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG5leHRfY2wgVGhlIHN1Y2Nlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgI1xuICAgICMgQHNlZSBIaXN0b3J5QnVmZmVyLmdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBwcmV2X2NsLCBuZXh0X2NsLCBvcmlnaW4pLT5cbiAgICAgIEBzYXZlT3BlcmF0aW9uICdwcmV2X2NsJywgcHJldl9jbFxuICAgICAgQHNhdmVPcGVyYXRpb24gJ25leHRfY2wnLCBuZXh0X2NsXG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnb3JpZ2luJywgcHJldl9jbFxuICAgICAgc3VwZXIgdWlkXG5cbiAgICAjXG4gICAgIyBJZiBpc0RlbGV0ZWQoKSBpcyB0cnVlIHRoaXMgb3BlcmF0aW9uIHdvbid0IGJlIG1haW50YWluZWQgaW4gdGhlIHNsXG4gICAgI1xuICAgIGlzRGVsZXRlZDogKCktPlxuICAgICAgZmFsc2VcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEB1bmNoZWNrZWQ/WyduZXh0X2NsJ10/XG4gICAgICAgIHN1cGVyXG4gICAgICBlbHNlIGlmIEB1bmNoZWNrZWQ/WydwcmV2X2NsJ11cbiAgICAgICAgaWYgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgICBpZiBAcHJldl9jbC5uZXh0X2NsP1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiUHJvYmFibHkgZHVwbGljYXRlZCBvcGVyYXRpb25zXCJcbiAgICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxuICAgICAgICAgIGRlbGV0ZSBAcHJldl9jbC51bmNoZWNrZWQubmV4dF9jbFxuICAgICAgICAgIHN1cGVyXG4gICAgICAgIGVsc2VcbiAgICAgICAgICBmYWxzZVxuICAgICAgZWxzZSBpZiBAcHJldl9jbD8gYW5kIG5vdCBAcHJldl9jbC5uZXh0X2NsP1xuICAgICAgICBkZWxldGUgQHByZXZfY2wudW5jaGVja2VkLm5leHRfY2xcbiAgICAgICAgQHByZXZfY2wubmV4dF9jbCA9IEBcbiAgICAgIGVsc2UgaWYgQHByZXZfY2w/IG9yIEBuZXh0X2NsP1xuICAgICAgICBzdXBlclxuICAgICAgZWxzZVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJEZWxpbWl0ZXIgaXMgdW5zdWZmaWNpZW50IGRlZmluZWQhXCJcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIHtcbiAgICAgICAgJ3R5cGUnIDogXCJEZWxpbWl0ZXJcIlxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAncHJldicgOiBAcHJldl9jbD8uZ2V0VWlkKClcbiAgICAgICAgJ25leHQnIDogQG5leHRfY2w/LmdldFVpZCgpXG4gICAgICB9XG5cbiAgcGFyc2VyWydEZWxpbWl0ZXInXSA9IChqc29uKS0+XG4gICAge1xuICAgICd1aWQnIDogdWlkXG4gICAgJ3ByZXYnIDogcHJldlxuICAgICduZXh0JyA6IG5leHRcbiAgICB9ID0ganNvblxuICAgIG5ldyBEZWxpbWl0ZXIgdWlkLCBwcmV2LCBuZXh0XG5cbiAgIyBUaGlzIGlzIHdoYXQgdGhpcyBtb2R1bGUgZXhwb3J0cyBhZnRlciBpbml0aWFsaXppbmcgaXQgd2l0aCB0aGUgSGlzdG9yeUJ1ZmZlclxuICB7XG4gICAgJ3R5cGVzJyA6XG4gICAgICAnRGVsZXRlJyA6IERlbGV0ZVxuICAgICAgJ0luc2VydCcgOiBJbnNlcnRcbiAgICAgICdEZWxpbWl0ZXInOiBEZWxpbWl0ZXJcbiAgICAgICdPcGVyYXRpb24nOiBPcGVyYXRpb25cbiAgICAgICdJbW11dGFibGVPYmplY3QnIDogSW1tdXRhYmxlT2JqZWN0XG4gICAgJ3BhcnNlcicgOiBwYXJzZXJcbiAgICAnZXhlY3V0aW9uX2xpc3RlbmVyJyA6IGV4ZWN1dGlvbl9saXN0ZW5lclxuICB9XG5cblxuXG5cbiJdfQ== diff --git a/build/browser/Types/BasicTypes.min.js b/build/browser/Types/BasicTypes.min.js new file mode 100644 index 00000000..fbc71d7f --- /dev/null +++ b/build/browser/Types/BasicTypes.min.js @@ -0,0 +1 @@ +!function e(t,n,r){function i(s,l){if(!n[s]){if(!t[s]){var u="function"==typeof require&&require;if(!l&&u)return u(s,!0);if(o)return o(s,!0);throw new Error("Cannot find module '"+s+"'")}var c=n[s]={exports:{}};t[s][0].call(c.exports,function(e){var n=t[s][1][e];return i(n?n:e)},c,c.exports,e,t,n,r)}return n[s].exports}for(var o="function"==typeof require&&require,s=0;sr;r++)n=o[r],s.push(n.call(this,e,t));return s}},t.prototype.setParent=function(e){return this.parent=e},t.prototype.getUid=function(){return{creator:this.creator,op_number:this.op_number}},t.prototype.execute=function(){var e,t,n;for(this.is_executed=!0,t=0,n=l.length;n>t;t++)(e=l[t])(this._encode());return this},t.prototype.saveOperation=function(e,t){return null!=(null!=t?t.execute:void 0)?this[e]=t:null!=t?(null==this.unchecked&&(this.unchecked={}),this.unchecked[e]=t):void 0},t.prototype.validateSavedOperations=function(){var t,n,r,i,o,s;o={},i=this,s=this.unchecked;for(t in s)r=s[t],n=e.getOperation(r),n?this[t]=n:(o[t]=r,i=!1);return delete this.unchecked,i||(this.unchecked=o),i},t}(),t=function(e){function t(e,n){this.saveOperation("deletes",n),t.__super__.constructor.call(this,e)}return r(t,e),t.prototype._encode=function(){return{type:"Delete",uid:this.getUid(),deletes:this.deletes.getUid()}},t.prototype.execute=function(){return this.validateSavedOperations()?(this.deletes.applyDelete(this),t.__super__.execute.apply(this,arguments),this):!1},t}(s),u.Delete=function(e){var n,r;return r=e.uid,n=e.deletes,new t(r,n)},o=function(e){function t(e,n,r,i){this.saveOperation("prev_cl",n),this.saveOperation("next_cl",r),null!=i?this.saveOperation("origin",i):this.saveOperation("origin",n),t.__super__.constructor.call(this,e)}return r(t,e),t.prototype.applyDelete=function(e){return null==this.deleted_by&&(this.deleted_by=[]),this.deleted_by.push(e)},t.prototype.isDeleted=function(){var e;return(null!=(e=this.deleted_by)?e.length:void 0)>0},t.prototype.getDistanceToOrigin=function(){var e,t;for(e=0,t=this.prev_cl;;){if(this.origin===t)break;if(e++,this===this.prev_cl)throw new Error("this should not happen ;) ");t=t.prev_cl}return e},t.prototype.update_sl=function(){var e;return e=this.prev_cl,update("prev_cl","prev_sl"),update("next_cl","prev_sl")},t.prototype.execute=function(){var e,n,r,i,o;if(null!=this.is_executed)return this;if(this.validateSavedOperations()){if((null!=(i=this.prev_cl)?i.validateSavedOperations():void 0)&&(null!=(o=this.next_cl)?o.validateSavedOperations():void 0)&&this.prev_cl.next_cl!==this){for(e=0,r=this.prev_cl.next_cl,n=0;;){if(null==r&&(console.log(JSON.stringify(this.prev_cl.getUid())),console.log(JSON.stringify(this.next_cl.getUid()))),r===this.next_cl)break;if(r.getDistanceToOrigin()===n)r.creator 0; + }; + + Insert.prototype.getDistanceToOrigin = function() { + var d, o; + d = 0; + o = this.prev_cl; + while (true) { + if (this.origin === o) { + break; + } + d++; + if (this === this.prev_cl) { + throw new Error("this should not happen ;) "); + } + o = o.prev_cl; + } + return d; + }; + + Insert.prototype.update_sl = function() { + var o; + o = this.prev_cl; + ({ + update: function(dest_cl, dest_sl) { + var _results; + _results = []; + while (true) { + if (o.isDeleted()) { + _results.push(o = o[dest_cl]); + } else { + this[dest_sl] = o; + break; + } + } + return _results; + } + }); + update("prev_cl", "prev_sl"); + return update("next_cl", "prev_sl"); + }; + + Insert.prototype.execute = function() { + var distance_to_origin, i, o, _ref, _ref1; + if (this.is_executed != null) { + return this; + } + if (!this.validateSavedOperations()) { + return false; + } else { + if (((_ref = this.prev_cl) != null ? _ref.validateSavedOperations() : void 0) && ((_ref1 = this.next_cl) != null ? _ref1.validateSavedOperations() : void 0) && this.prev_cl.next_cl !== this) { + distance_to_origin = 0; + o = this.prev_cl.next_cl; + i = 0; + while (true) { + if (o == null) { + console.log(JSON.stringify(this.prev_cl.getUid())); + console.log(JSON.stringify(this.next_cl.getUid())); + } + if (o !== this.next_cl) { + if (o.getDistanceToOrigin() === i) { + if (o.creator < this.creator) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else if (o.getDistanceToOrigin() < i) { + if (i - distance_to_origin <= o.getDistanceToOrigin()) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else { + break; + } + i++; + o = o.next_cl; + } else { + break; + } + } + this.next_cl = this.prev_cl.next_cl; + this.prev_cl.next_cl = this; + this.next_cl.prev_cl = this; + } + Insert.__super__.execute.apply(this, arguments); + return this; + } + }; + + return Insert; + + })(Operation); + ImmutableObject = (function(_super) { + __extends(ImmutableObject, _super); + + function ImmutableObject(uid, content, prev, next, origin) { + this.content = content; + ImmutableObject.__super__.constructor.call(this, uid, prev, next, origin); + } + + ImmutableObject.prototype.val = function() { + return this.content; + }; + + ImmutableObject.prototype._encode = function() { + var json; + json = { + 'type': "ImmutableObject", + 'uid': this.getUid(), + 'content': this.content + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ImmutableObject; + + })(Insert); + parser['ImmutableObject'] = function(json) { + var content, next, origin, prev, uid; + uid = json['uid'], content = json['content'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new ImmutableObject(uid, content, prev, next, origin); + }; + Delimiter = (function(_super) { + __extends(Delimiter, _super); + + function Delimiter(uid, prev_cl, next_cl, origin) { + this.saveOperation('prev_cl', prev_cl); + this.saveOperation('next_cl', next_cl); + this.saveOperation('origin', prev_cl); + Delimiter.__super__.constructor.call(this, uid); + } + + Delimiter.prototype.isDeleted = function() { + return false; + }; + + Delimiter.prototype.execute = function() { + var _ref, _ref1; + if (((_ref = this.unchecked) != null ? _ref['next_cl'] : void 0) != null) { + return Delimiter.__super__.execute.apply(this, arguments); + } else if ((_ref1 = this.unchecked) != null ? _ref1['prev_cl'] : void 0) { + if (this.validateSavedOperations()) { + if (this.prev_cl.next_cl != null) { + throw new Error("Probably duplicated operations"); + } + this.prev_cl.next_cl = this; + delete this.prev_cl.unchecked.next_cl; + return Delimiter.__super__.execute.apply(this, arguments); + } else { + return false; + } + } else if ((this.prev_cl != null) && (this.prev_cl.next_cl == null)) { + delete this.prev_cl.unchecked.next_cl; + return this.prev_cl.next_cl = this; + } else if ((this.prev_cl != null) || (this.next_cl != null)) { + return Delimiter.__super__.execute.apply(this, arguments); + } else { + throw new Error("Delimiter is unsufficient defined!"); + } + }; + + Delimiter.prototype._encode = function() { + var _ref, _ref1; + return { + 'type': "Delimiter", + 'uid': this.getUid(), + 'prev': (_ref = this.prev_cl) != null ? _ref.getUid() : void 0, + 'next': (_ref1 = this.next_cl) != null ? _ref1.getUid() : void 0 + }; + }; + + return Delimiter; + + })(Operation); + parser['Delimiter'] = function(json) { + var next, prev, uid; + uid = json['uid'], prev = json['prev'], next = json['next']; + return new Delimiter(uid, prev, next); + }; + return { + 'types': { + 'Delete': Delete, + 'Insert': Insert, + 'Delimiter': Delimiter, + 'Operation': Operation, + 'ImmutableObject': ImmutableObject + }, + 'parser': parser, + 'execution_listener': execution_listener + }; +}; + + +},{}],2:[function(require,module,exports){ +var text_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +text_types_uninitialized = require("./TextTypes"); + +module.exports = function(HB) { + var JsonType, createJsonWrapper, parser, text_types, types; + text_types = text_types_uninitialized(HB); + types = text_types.types; + parser = text_types.parser; + createJsonWrapper = function(_jsonType) { + var JsonWrapper; + JsonWrapper = (function() { + function JsonWrapper(jsonType) { + var name, obj, _fn, _ref; + _ref = jsonType.map; + _fn = function(name, obj) { + return Object.defineProperty(JsonWrapper.prototype, name, { + get: function() { + var x; + x = obj.val(); + if (x instanceof JsonType) { + return createJsonWrapper(x); + } else if (x instanceof types.ImmutableObject) { + return x.val(); + } else { + return x; + } + }, + set: function(o) { + var o_name, o_obj, overwrite, _results; + if (o.constructor === {}.constructor) { + overwrite = jsonType.val(name); + _results = []; + for (o_name in o) { + o_obj = o[o_name]; + _results.push(overwrite.val(o_name, o_obj, 'immutable')); + } + return _results; + } else { + return jsonType.val(name, o, 'immutable'); + } + }, + enumerable: true, + configurable: false + }); + }; + for (name in _ref) { + obj = _ref[name]; + _fn(name, obj); + } + } + + return JsonWrapper; + + })(); + return new JsonWrapper(_jsonType); + }; + JsonType = (function(_super) { + __extends(JsonType, _super); + + function JsonType(uid, initial_value, mutable) { + var name, o; + JsonType.__super__.constructor.call(this, uid); + if (initial_value != null) { + if (typeof initial_value !== "object") { + throw new Error("The initial value of JsonTypes must be of type Object! (current type: " + (typeof initial_value) + ")"); + } + for (name in initial_value) { + o = initial_value[name]; + this.val(name, o, mutable); + } + } + } + + JsonType.prototype.mutable_default = true; + + JsonType.prototype.setMutableDefault = function(mutable) { + if (mutable === true || mutable === 'mutable') { + JsonType.prototype.mutable_default = true; + } else if (mutable === false || mutable === 'immutable') { + JsonType.prototype.mutable_default = false; + } else { + throw new Error('Set mutable either "mutable" or "immutable"!'); + } + return 'OK'; + }; + + JsonType.prototype.val = function(name, content, mutable) { + var json, o, o_name, obj, word; + if (typeof name === 'object') { + for (o_name in name) { + o = name[o_name]; + this.val(o_name, o, content); + } + return this; + } else if ((name != null) && (content != null)) { + if (mutable != null) { + if (mutable === true || mutable === 'mutable') { + mutable = true; + } else { + mutable = false; + } + } else { + mutable = this.mutable_default; + } + if (typeof content === 'function') { + return this; + } else if (((!mutable) || typeof content === 'number') && content.constructor !== Object) { + obj = HB.addOperation(new types.ImmutableObject(void 0, content)).execute(); + return JsonType.__super__.val.call(this, name, obj); + } else { + if (typeof content === 'string') { + word = HB.addOperation(new types.Word(void 0)).execute(); + word.insertText(0, content); + return JsonType.__super__.val.call(this, name, word); + } else if (content.constructor === Object) { + json = HB.addOperation(new JsonType(void 0, content, mutable)).execute(); + return JsonType.__super__.val.call(this, name, json); + } else { + throw new Error("You must not set " + (typeof content) + "-types in collaborative Json-objects!"); + } + } + } else { + return JsonType.__super__.val.call(this, name, content); + } + }; + + Object.defineProperty(JsonType.prototype, 'value', { + get: function() { + return createJsonWrapper(this); + }, + set: function(o) { + var o_name, o_obj, _results; + if (o.constructor === {}.constructor) { + _results = []; + for (o_name in o) { + o_obj = o[o_name]; + _results.push(this.val(o_name, o_obj, 'immutable')); + } + return _results; + } else { + throw new Error("You must only set Object values!"); + } + } + }); + + JsonType.prototype._encode = function() { + return { + 'type': "JsonType", + 'uid': this.getUid() + }; + }; + + return JsonType; + + })(types.MapManager); + parser['JsonType'] = function(json) { + var uid; + uid = json['uid']; + return new JsonType(uid); + }; + types['JsonType'] = JsonType; + return text_types; +}; + + +},{"./TextTypes":4}],3:[function(require,module,exports){ +var basic_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +basic_types_uninitialized = require("./BasicTypes"); + +module.exports = function(HB) { + var AddName, ListManager, MapManager, ReplaceManager, Replaceable, basic_types, parser, types; + basic_types = basic_types_uninitialized(HB); + types = basic_types.types; + parser = basic_types.parser; + MapManager = (function(_super) { + __extends(MapManager, _super); + + function MapManager(uid) { + this.map = {}; + MapManager.__super__.constructor.call(this, uid); + } + + MapManager.prototype.val = function(name, content) { + var o, obj, result, _ref, _ref1; + if (content != null) { + if (this.map[name] == null) { + HB.addOperation(new AddName(void 0, this, name)).execute(); + } + this.map[name].replace(content); + return this; + } else if (name != null) { + obj = (_ref = this.map[name]) != null ? _ref.val() : void 0; + if (obj instanceof types.ImmutableObject) { + return obj.val(); + } else { + return obj; + } + } else { + result = {}; + _ref1 = this.map; + for (name in _ref1) { + o = _ref1[name]; + obj = o.val(); + if (obj instanceof types.ImmutableObject || obj instanceof MapManager) { + obj = obj.val(); + } + result[name] = obj; + } + return result; + } + }; + + return MapManager; + + })(types.Operation); + AddName = (function(_super) { + __extends(AddName, _super); + + function AddName(uid, map_manager, name) { + this.name = name; + this.saveOperation('map_manager', map_manager); + AddName.__super__.constructor.call(this, uid); + } + + AddName.prototype.execute = function() { + var beg, end, uid_beg, uid_end, uid_r; + if (!this.validateSavedOperations()) { + return false; + } else { + uid_r = this.map_manager.getUid(); + uid_r.op_number = "_" + uid_r.op_number + "_RM_" + this.name; + if (HB.getOperation(uid_r) == null) { + uid_beg = this.map_manager.getUid(); + uid_beg.op_number = "_" + uid_beg.op_number + "_RM_" + this.name + "_beginning"; + uid_end = this.map_manager.getUid(); + uid_end.op_number = "_" + uid_end.op_number + "_RM_" + this.name + "_end"; + beg = HB.addOperation(new types.Delimiter(uid_beg, void 0, uid_end)).execute(); + end = HB.addOperation(new types.Delimiter(uid_end, beg, void 0)).execute(); + this.map_manager.map[this.name] = HB.addOperation(new ReplaceManager(void 0, uid_r, beg, end)).execute(); + } + return AddName.__super__.execute.apply(this, arguments); + } + }; + + AddName.prototype._encode = function() { + return { + 'type': "AddName", + 'uid': this.getUid(), + 'map_manager': this.map_manager.getUid(), + 'name': this.name + }; + }; + + return AddName; + + })(types.Operation); + parser['AddName'] = function(json) { + var map_manager, name, uid; + map_manager = json['map_manager'], uid = json['uid'], name = json['name']; + return new AddName(uid, map_manager, name); + }; + ListManager = (function(_super) { + __extends(ListManager, _super); + + function ListManager(uid, beginning, end, prev, next, origin) { + if ((beginning != null) && (end != null)) { + this.saveOperation('beginning', beginning); + this.saveOperation('end', end); + } else { + this.beginning = HB.addOperation(new types.Delimiter(void 0, void 0, void 0)); + this.end = HB.addOperation(new types.Delimiter(void 0, this.beginning, void 0)); + this.beginning.next_cl = this.end; + this.beginning.execute(); + this.end.execute(); + } + ListManager.__super__.constructor.call(this, uid, prev, next, origin); + } + + ListManager.prototype.getLastOperation = function() { + return this.end.prev_cl; + }; + + ListManager.prototype.getFirstOperation = function() { + return this.beginning.next_cl; + }; + + ListManager.prototype.toArray = function() { + var o, result; + o = this.beginning.next_cl; + result = []; + while (o !== this.end) { + result.push(o); + o = o.next_cl; + } + return result; + }; + + ListManager.prototype.getOperationByPosition = function(position) { + var o; + o = this.beginning.next_cl; + if (position > 0) { + while (true) { + o = o.next_cl; + if (!o.isDeleted()) { + position -= 1; + } + if (position === 0) { + break; + } + if (o instanceof types.Delimiter) { + throw new Error("position parameter exceeded the length of the document!"); + } + } + } + return o; + }; + + return ListManager; + + })(types.Insert); + ReplaceManager = (function(_super) { + __extends(ReplaceManager, _super); + + function ReplaceManager(initial_content, uid, beginning, end, prev, next, origin) { + ReplaceManager.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + if (initial_content != null) { + this.replace(initial_content); + } + } + + ReplaceManager.prototype.replace = function(content) { + var o, op; + o = this.getLastOperation(); + op = new Replaceable(content, this, void 0, o, o.next_cl); + return HB.addOperation(op).execute(); + }; + + ReplaceManager.prototype.val = function() { + var o; + o = this.getLastOperation(); + if (o instanceof types.Delimiter) { + throw new Error("dtrn"); + } + return o.val(); + }; + + ReplaceManager.prototype._encode = function() { + var json; + json = { + 'type': "ReplaceManager", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if ((this.prev_cl != null) && (this.next_cl != null)) { + json['prev'] = this.prev_cl.getUid(); + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ReplaceManager; + + })(ListManager); + parser["ReplaceManager"] = function(json) { + var beginning, content, end, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], beginning = json['beginning'], end = json['end']; + return new ReplaceManager(content, uid, beginning, end, prev, next, origin); + }; + Replaceable = (function(_super) { + __extends(Replaceable, _super); + + function Replaceable(content, parent, uid, prev, next, origin) { + this.saveOperation('content', content); + this.saveOperation('parent', parent); + if (!((prev != null) && (next != null) && (content != null))) { + throw new Error("You must define content, prev, and next for Replaceable-types!"); + } + Replaceable.__super__.constructor.call(this, uid, prev, next, origin); + } + + Replaceable.prototype.val = function() { + return this.content; + }; + + Replaceable.prototype.replace = function(content) { + return this.parent.replace(content); + }; + + Replaceable.prototype.execute = function() { + var _base; + if (!this.validateSavedOperations()) { + return false; + } else { + if (typeof (_base = this.content).setReplaceManager === "function") { + _base.setReplaceManager(this.parent); + } + Replaceable.__super__.execute.apply(this, arguments); + return this; + } + }; + + Replaceable.prototype._encode = function() { + var json; + json = { + 'type': "Replaceable", + 'content': this.content.getUid(), + 'ReplaceManager': this.parent.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid(), + 'uid': this.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Replaceable; + + })(types.Insert); + parser["Replaceable"] = function(json) { + var content, next, origin, parent, prev, uid; + content = json['content'], parent = json['ReplaceManager'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Replaceable(content, parent, uid, prev, next, origin); + }; + types['ListManager'] = ListManager; + types['MapManager'] = MapManager; + types['ReplaceManager'] = ReplaceManager; + types['Replaceable'] = Replaceable; + return basic_types; +}; + + +},{"./BasicTypes":1}],4:[function(require,module,exports){ +var structured_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +structured_types_uninitialized = require("./StructuredTypes"); + +module.exports = function(HB) { + var TextDelete, TextInsert, Word, parser, structured_types, types; + structured_types = structured_types_uninitialized(HB); + types = structured_types.types; + parser = structured_types.parser; + TextDelete = (function(_super) { + __extends(TextDelete, _super); + + function TextDelete() { + return TextDelete.__super__.constructor.apply(this, arguments); + } + + return TextDelete; + + })(types.Delete); + parser["TextDelete"] = parser["Delete"]; + TextInsert = (function(_super) { + __extends(TextInsert, _super); + + function TextInsert(content, uid, prev, next, origin) { + this.content = content; + if (!((prev != null) && (next != null))) { + throw new Error("You must define prev, and next for TextInsert-types!"); + } + TextInsert.__super__.constructor.call(this, uid, prev, next, origin); + } + + TextInsert.prototype.getLength = function() { + if (this.isDeleted()) { + return 0; + } else { + return this.content.length; + } + }; + + TextInsert.prototype.val = function(current_position) { + if (this.isDeleted()) { + return ""; + } else { + return this.content; + } + }; + + TextInsert.prototype._encode = function() { + var json; + json = { + 'type': "TextInsert", + 'content': this.content, + 'uid': this.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return TextInsert; + + })(types.Insert); + parser["TextInsert"] = function(json) { + var content, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new TextInsert(content, uid, prev, next, origin); + }; + Word = (function(_super) { + __extends(Word, _super); + + function Word(uid, beginning, end, prev, next, origin) { + Word.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + } + + Word.prototype.insertText = function(position, content) { + var c, o, op, _i, _len, _results; + o = this.getOperationByPosition(position); + _results = []; + for (_i = 0, _len = content.length; _i < _len; _i++) { + c = content[_i]; + op = new TextInsert(c, void 0, o.prev_cl, o); + _results.push(HB.addOperation(op).execute()); + } + return _results; + }; + + Word.prototype.deleteText = function(position, length) { + var d, i, o, _i, _results; + o = this.getOperationByPosition(position); + _results = []; + for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) { + d = HB.addOperation(new TextDelete(void 0, o)).execute(); + o = o.next_cl; + while (o.isDeleted()) { + if (o instanceof types.Delimiter) { + throw new Error("You can't delete more than there is.."); + } + o = o.next_cl; + } + _results.push(d._encode()); + } + return _results; + }; + + Word.prototype.replaceText = function(text) { + var word; + if (this.replace_manager != null) { + word = HB.addOperation(new Word(void 0)).execute(); + word.insertText(0, text); + return this.replace_manager.replace(word); + } else { + throw new Error("This type is currently not maintained by a ReplaceManager!"); + } + }; + + Word.prototype.val = function() { + var c, o; + c = (function() { + var _i, _len, _ref, _results; + _ref = this.toArray(); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + o = _ref[_i]; + if (o.val != null) { + _results.push(o.val()); + } else { + _results.push(""); + } + } + return _results; + }).call(this); + return c.join(''); + }; + + Word.prototype.setReplaceManager = function(op) { + this.saveOperation('replace_manager', op); + return this.validateSavedOperations; + }; + + Word.prototype._encode = function() { + var json; + json = { + 'type': "Word", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Word; + + })(types.ListManager); + parser['Word'] = function(json) { + var beginning, end, next, origin, prev, uid; + uid = json['uid'], beginning = json['beginning'], end = json['end'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Word(uid, beginning, end, prev, next, origin); + }; + types['TextInsert'] = TextInsert; + types['TextDelete'] = TextDelete; + types['Word'] = Word; + return structured_types; +}; + + +},{"./StructuredTypes":3}]},{},[2]) +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL1R5cGVzL0Jhc2ljVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9Kc29uVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9TdHJ1Y3R1cmVkVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9UZXh0VHlwZXMuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUEsSUFBQTtpU0FBQTs7QUFBQSxNQUFNLENBQUMsT0FBUCxHQUFpQixTQUFDLEVBQUQsR0FBQTtBQUVmLE1BQUEsaUZBQUE7QUFBQSxFQUFBLE1BQUEsR0FBUyxFQUFULENBQUE7QUFBQSxFQUNBLGtCQUFBLEdBQXFCLEVBRHJCLENBQUE7QUFBQSxFQWFNO0FBTVMsSUFBQSxtQkFBQyxHQUFELEdBQUE7QUFDWCxNQUFBLElBQU8sV0FBUDtBQUNFLFFBQUEsR0FBQSxHQUFNLEVBQUUsQ0FBQywwQkFBSCxDQUFBLENBQU4sQ0FERjtPQUFBO0FBQUEsTUFHYSxJQUFDLENBQUEsY0FBWixVQURGLEVBRWdCLElBQUMsQ0FBQSxnQkFBZixZQUpGLENBRFc7SUFBQSxDQUFiOztBQUFBLHdCQWFBLEVBQUEsR0FBSSxTQUFDLEtBQUQsRUFBUSxDQUFSLEdBQUE7QUFDRixVQUFBLEtBQUE7O1FBQUEsSUFBQyxDQUFBLGtCQUFtQjtPQUFwQjs7YUFDaUIsQ0FBQSxLQUFBLElBQVU7T0FEM0I7YUFFQSxJQUFDLENBQUEsZUFBZ0IsQ0FBQSxLQUFBLENBQU0sQ0FBQyxJQUF4QixDQUE2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cmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpfXZhciBmPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChmLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGYsZi5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCJtb2R1bGUuZXhwb3J0cyA9IChIQiktPlxuICAjIEBzZWUgRW5naW5lLnBhcnNlXG4gIHBhcnNlciA9IHt9XG4gIGV4ZWN1dGlvbl9saXN0ZW5lciA9IFtdXG5cbiAgI1xuICAjIEEgZ2VuZXJpYyBpbnRlcmZhY2UgdG8gb3BlcmF0aW9ucy5cbiAgI1xuICAjIEFuIG9wZXJhdGlvbiBoYXMgdGhlIGZvbGxvd2luZyBtZXRob2RzOlxuICAjIF9lbmNvZGU6IGVuY29kZXMgYW4gb3BlcmF0aW9uIChuZWVkZWQgb25seSBpZiBpbnN0YW5jZSBvZiB0aGlzIG9wZXJhdGlvbiBpcyBzZW50KS5cbiAgIyBleGVjdXRlOiBleGVjdXRlIHRoZSBlZmZlY3RzIG9mIHRoaXMgb3BlcmF0aW9ucy4gR29vZCBleGFtcGxlcyBhcmUgSW5zZXJ0LXR5cGUgYW5kIEFkZE5hbWUtdHlwZVxuICAjIHZhbDogaW4gdGhlIGNhc2UgdGhhdCB0aGUgb3BlcmF0aW9uIGhvbGRzIGEgdmFsdWVcbiAgI1xuICAjIEZ1cnRoZXJtb3JlIGFuIGVuY29kYWJsZSBvcGVyYXRpb24gaGFzIGEgcGFyc2VyLlxuICAjXG4gIGNsYXNzIE9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHNlZSBIaXN0b3J5QnVmZmVyLmdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkKS0+XG4gICAgICBpZiBub3QgdWlkP1xuICAgICAgICB1aWQgPSBIQi5nZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllcigpXG4gICAgICB7XG4gICAgICAgICdjcmVhdG9yJzogQGNyZWF0b3JcbiAgICAgICAgJ29wX251bWJlcicgOiBAb3BfbnVtYmVyXG4gICAgICB9ID0gdWlkXG5cbiAgICAjXG4gICAgIyBBZGQgYW4gZXZlbnQgbGlzdGVuZXIuIEl0IGRlcGVuZHMgb24gdGhlIG9wZXJhdGlvbiB3aGljaCBldmVudHMgYXJlIHN1cHBvcnRlZC5cbiAgICAjIEBwYXJhbSB7U3RyaW5nfSBldmVudCBOYW1lIG9mIHRoZSBldmVudC5cbiAgICAjIEBwYXJhbSB7RnVuY3Rpb259IGYgZiBpcyBleGVjdXRlZCBpbiBjYXNlIHRoZSBldmVudCBmaXJlcy5cbiAgICAjXG4gICAgb246IChldmVudCwgZiktPlxuICAgICAgQGV2ZW50X2xpc3RlbmVycyA/PSB7fVxuICAgICAgQGV2ZW50X2xpc3RlbmVyc1tldmVudF0gPz0gW11cbiAgICAgIEBldmVudF9saXN0ZW5lcnNbZXZlbnRdLnB1c2ggZlxuXG4gICAgI1xuICAgICMgRmlyZSBhbiBldmVudC5cbiAgICAjIFRPRE86IERvIHNvbWV0aGluZyB3aXRoIHRpbWVvdXRzLiBZb3UgZG9uJ3Qgd2FudCB0aGlzIHRvIGZpcmUgZm9yIGV2ZXJ5IG9wZXJhdGlvbiAoZS5nLiBpbnNlcnQpLlxuICAgICNcbiAgICBjYWxsRXZlbnQ6IChldmVudCwgYXJncyktPlxuICAgICAgaWYgQGV2ZW50X2xpc3RlbmVyc1tldmVudF0/XG4gICAgICAgIGZvciBmIGluIEBldmVudF9saXN0ZW5lcnNbZXZlbnRdXG4gICAgICAgICAgZi5jYWxsIEAsIGV2ZW50LCBhcmdzXG5cbiAgICAjXG4gICAgIyBTZXQgdGhlIHBhcmVudCBvZiB0aGlzIG9wZXJhdGlvbi5cbiAgICAjXG4gICAgc2V0UGFyZW50OiAobyktPlxuICAgICAgQHBhcmVudCA9IG9cblxuICAgICNcbiAgICAjIENvbXB1dGVzIGEgdW5pcXVlIGlkZW50aWZpZXIgKHVpZCkgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICBnZXRVaWQ6ICgpLT5cbiAgICAgIHsgJ2NyZWF0b3InOiBAY3JlYXRvciwgJ29wX251bWJlcic6IEBvcF9udW1iZXIgfVxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIE5vdGlmeSB0aGUgYWxsIHRoZSBsaXN0ZW5lcnMuXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIEBpc19leGVjdXRlZCA9IHRydWVcbiAgICAgIGZvciBsIGluIGV4ZWN1dGlvbl9saXN0ZW5lclxuICAgICAgICBsIEBfZW5jb2RlKClcbiAgICAgIEBcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBPcGVyYXRpb25zIG1heSBkZXBlbmQgb24gb3RoZXIgb3BlcmF0aW9ucyAobGlua2VkIGxpc3RzLCBldGMuKS5cbiAgICAjIFRoZSBzYXZlT3BlcmF0aW9uIGFuZCB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucyBtZXRob2RzIHByb3ZpZGVcbiAgICAjIGFuIGVhc3kgd2F5IHRvIHJlZmVyIHRvIHRoZXNlIG9wZXJhdGlvbnMgdmlhIGFuIHVpZCBvciBvYmplY3QgcmVmZXJlbmNlLlxuICAgICNcbiAgICAjIEZvciBleGFtcGxlOiBXZSBjYW4gY3JlYXRlIGEgbmV3IERlbGV0ZSBvcGVyYXRpb24gdGhhdCBkZWxldGVzIHRoZSBvcGVyYXRpb24gJG8gbGlrZSB0aGlzXG4gICAgIyAgICAgLSB2YXIgZCA9IG5ldyBEZWxldGUodWlkLCAkbyk7ICAgb3JcbiAgICAjICAgICAtIHZhciBkID0gbmV3IERlbGV0ZSh1aWQsICRvLmdldFVpZCgpKTtcbiAgICAjIEVpdGhlciB3YXkgd2Ugd2FudCB0byBhY2Nlc3MgJG8gdmlhIGQuZGVsZXRlcy4gSW4gdGhlIHNlY29uZCBjYXNlIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zIG11c3QgYmUgY2FsbGVkIGZpcnN0LlxuICAgICNcbiAgICAjIEBvdmVybG9hZCBzYXZlT3BlcmF0aW9uKG5hbWUsIG9wX3VpZClcbiAgICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGlvbi4gQWZ0ZXIgdmFsaWRhdGluZyAod2l0aCB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucykgdGhlIGluc3RhbnRpYXRlZCBvcGVyYXRpb24gd2lsbCBiZSBhY2Nlc3NpYmxlIHZpYSB0aGlzW25hbWVdLlxuICAgICMgICBAcGFyYW0ge09iamVjdH0gb3BfdWlkIEEgdWlkIHRoYXQgcmVmZXJzIHRvIGFuIG9wZXJhdGlvblxuICAgICMgQG92ZXJsb2FkIHNhdmVPcGVyYXRpb24obmFtZSwgb3ApXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpb24uIEFmdGVyIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiBvcCBpcyBhY2Nlc3NpYmxlIHZpYSB0aGlzW25hbWVdLlxuICAgICMgICBAcGFyYW0ge09wZXJhdGlvbn0gb3AgQW4gT3BlcmF0aW9uIG9iamVjdFxuICAgICNcbiAgICBzYXZlT3BlcmF0aW9uOiAobmFtZSwgb3ApLT5cblxuICAgICAgI1xuICAgICAgIyBFdmVyeSBpbnN0YW5jZSBvZiAkT3BlcmF0aW9uIG11c3QgaGF2ZSBhbiAkZXhlY3V0ZSBmdW5jdGlvbi5cbiAgICAgICMgV2UgdXNlIGR1Y2stdHlwaW5nIHRvIGNoZWNrIGlmIG9wIGlzIGluc3RhbnRpYXRlZCBzaW5jZSB0aGVyZVxuICAgICAgIyBjb3VsZCBleGlzdCBtdWx0aXBsZSBjbGFzc2VzIG9mICRPcGVyYXRpb25cbiAgICAgICNcbiAgICAgIGlmIG9wPy5leGVjdXRlP1xuICAgICAgICAjIGlzIGluc3RhbnRpYXRlZFxuICAgICAgICBAW25hbWVdID0gb3BcbiAgICAgIGVsc2UgaWYgb3A/XG4gICAgICAgICMgbm90IGluaXRpYWxpemVkLiBEbyBpdCB3aGVuIGNhbGxpbmcgJHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgQHVuY2hlY2tlZCA/PSB7fVxuICAgICAgICBAdW5jaGVja2VkW25hbWVdID0gb3BcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBBZnRlciBjYWxsaW5nIHRoaXMgZnVuY3Rpb24gYWxsIG5vdCBpbnN0YW50aWF0ZWQgb3BlcmF0aW9ucyB3aWxsIGJlIGFjY2Vzc2libGUuXG4gICAgIyBAc2VlIE9wZXJhdGlvbi5zYXZlT3BlcmF0aW9uXG4gICAgI1xuICAgICMgQHJldHVybiBbQm9vbGVhbl0gV2hldGhlciBpdCB3YXMgcG9zc2libGUgdG8gaW5zdGFudGlhdGUgYWxsIG9wZXJhdGlvbnMuXG4gICAgI1xuICAgIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zOiAoKS0+XG4gICAgICB1bmluc3RhbnRpYXRlZCA9IHt9XG4gICAgICBzdWNjZXNzID0gQFxuICAgICAgZm9yIG5hbWUsIG9wX3VpZCBvZiBAdW5jaGVja2VkXG4gICAgICAgIG9wID0gSEIuZ2V0T3BlcmF0aW9uIG9wX3VpZFxuICAgICAgICBpZiBvcFxuICAgICAgICAgIEBbbmFtZV0gPSBvcFxuICAgICAgICBlbHNlXG4gICAgICAgICAgdW5pbnN0YW50aWF0ZWRbbmFtZV0gPSBvcF91aWRcbiAgICAgICAgICBzdWNjZXNzID0gZmFsc2VcbiAgICAgIGRlbGV0ZSBAdW5jaGVja2VkXG4gICAgICBpZiBub3Qgc3VjY2Vzc1xuICAgICAgICBAdW5jaGVja2VkID0gdW5pbnN0YW50aWF0ZWRcbiAgICAgIHN1Y2Nlc3NcblxuXG5cbiAgI1xuICAjIEEgc2ltcGxlIERlbGV0ZS10eXBlIG9wZXJhdGlvbiB0aGF0IGRlbGV0ZXMgYW4gSW5zZXJ0LXR5cGUgb3BlcmF0aW9uLlxuICAjXG4gIGNsYXNzIERlbGV0ZSBleHRlbmRzIE9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IGRlbGV0ZXMgVUlEIG9yIHJlZmVyZW5jZSBvZiB0aGUgb3BlcmF0aW9uIHRoYXQgdGhpcyB0byBiZSBkZWxldGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgZGVsZXRlcyktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ2RlbGV0ZXMnLCBkZWxldGVzXG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBDb252ZXJ0IGFsbCByZWxldmFudCBpbmZvcm1hdGlvbiBvZiB0aGlzIG9wZXJhdGlvbiB0byB0aGUganNvbi1mb3JtYXQuXG4gICAgIyBUaGlzIHJlc3VsdCBjYW4gYmUgc2VudCB0byBvdGhlciBjbGllbnRzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICB7XG4gICAgICAgICd0eXBlJzogXCJEZWxldGVcIlxuICAgICAgICAndWlkJzogQGdldFVpZCgpXG4gICAgICAgICdkZWxldGVzJzogQGRlbGV0ZXMuZ2V0VWlkKClcbiAgICAgIH1cblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBBcHBseSB0aGUgZGVsZXRpb24uXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIEBkZWxldGVzLmFwcGx5RGVsZXRlIEBcbiAgICAgICAgc3VwZXJcbiAgICAgICAgQFxuICAgICAgZWxzZVxuICAgICAgICBmYWxzZVxuXG4gICNcbiAgIyBEZWZpbmUgaG93IHRvIHBhcnNlIERlbGV0ZSBvcGVyYXRpb25zLlxuICAjXG4gIHBhcnNlclsnRGVsZXRlJ10gPSAobyktPlxuICAgIHtcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAnZGVsZXRlcyc6IGRlbGV0ZXNfdWlkXG4gICAgfSA9IG9cbiAgICBuZXcgRGVsZXRlIHVpZCwgZGVsZXRlc191aWRcblxuICAjXG4gICMgQSBzaW1wbGUgaW5zZXJ0LXR5cGUgb3BlcmF0aW9uLlxuICAjXG4gICMgQW4gaW5zZXJ0IG9wZXJhdGlvbiBpcyBhbHdheXMgcG9zaXRpb25lZCBiZXR3ZWVuIHR3byBvdGhlciBpbnNlcnQgb3BlcmF0aW9ucy5cbiAgIyBJbnRlcm5hbGx5IHRoaXMgaXMgcmVhbGl6ZWQgYXMgYXNzb2NpYXRpdmUgbGlzdHMsIHdoZXJlYnkgZWFjaCBpbnNlcnQgb3BlcmF0aW9uIGhhcyBhIHByZWRlY2Vzc29yIGFuZCBhIHN1Y2Nlc3Nvci5cbiAgIyBGb3IgdGhlIHNha2Ugb2YgZWZmaWNpZW5jeSB3ZSBtYWludGFpbiB0d28gbGlzdHM6XG4gICMgICAtIFRoZSBzaG9ydC1saXN0IChhYmJyZXYuIHNsKSBtYWludGFpbnMgb25seSB0aGUgb3BlcmF0aW9ucyB0aGF0IGFyZSBub3QgZGVsZXRlZFxuICAjICAgLSBUaGUgY29tcGxldGUtbGlzdCAoYWJicmV2LiBjbCkgbWFpbnRhaW5zIGFsbCBvcGVyYXRpb25zXG4gICNcbiAgY2xhc3MgSW5zZXJ0IGV4dGVuZHMgT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gcHJldl9jbCBUaGUgcHJlZGVjZXNzb3Igb2YgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGNvbXBsZXRlLWxpc3QgKGNsKVxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG5leHRfY2wgVGhlIHN1Y2Nlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgI1xuICAgICMgQHNlZSBIaXN0b3J5QnVmZmVyLmdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBwcmV2X2NsLCBuZXh0X2NsLCBvcmlnaW4pLT5cbiAgICAgIEBzYXZlT3BlcmF0aW9uICdwcmV2X2NsJywgcHJldl9jbFxuICAgICAgQHNhdmVPcGVyYXRpb24gJ25leHRfY2wnLCBuZXh0X2NsXG4gICAgICBpZiBvcmlnaW4/XG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBvcmlnaW5cbiAgICAgIGVsc2VcbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ29yaWdpbicsIHByZXZfY2xcbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjXG4gICAgYXBwbHlEZWxldGU6IChvKS0+XG4gICAgICBAZGVsZXRlZF9ieSA/PSBbXVxuICAgICAgQGRlbGV0ZWRfYnkucHVzaCBvXG5cbiAgICAjXG4gICAgIyBJZiBpc0RlbGV0ZWQoKSBpcyB0cnVlIHRoaXMgb3BlcmF0aW9uIHdvbid0IGJlIG1haW50YWluZWQgaW4gdGhlIHNsXG4gICAgI1xuICAgIGlzRGVsZXRlZDogKCktPlxuICAgICAgQGRlbGV0ZWRfYnk/Lmxlbmd0aCA+IDBcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBUaGUgYW1vdW50IG9mIHBvc2l0aW9ucyB0aGF0ICR0aGlzIG9wZXJhdGlvbiB3YXMgbW92ZWQgdG8gdGhlIHJpZ2h0LlxuICAgICNcbiAgICBnZXREaXN0YW5jZVRvT3JpZ2luOiAoKS0+XG4gICAgICBkID0gMFxuICAgICAgbyA9IEBwcmV2X2NsXG4gICAgICB3aGlsZSB0cnVlXG4gICAgICAgIGlmIEBvcmlnaW4gaXMgb1xuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGQrK1xuICAgICAgICAjVE9ETzogZGVsZXRlIHRoaXNcbiAgICAgICAgaWYgQCBpcyBAcHJldl9jbFxuICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcInRoaXMgc2hvdWxkIG5vdCBoYXBwZW4gOykgXCJcbiAgICAgICAgbyA9IG8ucHJldl9jbFxuICAgICAgZFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIFVwZGF0ZSB0aGUgc2hvcnQgbGlzdFxuICAgICMgVE9ETyAoVW51c2VkKVxuICAgIHVwZGF0ZV9zbDogKCktPlxuICAgICAgbyA9IEBwcmV2X2NsXG4gICAgICB1cGRhdGU6IChkZXN0X2NsLGRlc3Rfc2wpLT5cbiAgICAgICAgd2hpbGUgdHJ1ZVxuICAgICAgICAgIGlmIG8uaXNEZWxldGVkKClcbiAgICAgICAgICAgIG8gPSBvW2Rlc3RfY2xdXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgQFtkZXN0X3NsXSA9IG9cblxuICAgICAgICAgICAgYnJlYWtcbiAgICAgIHVwZGF0ZSBcInByZXZfY2xcIiwgXCJwcmV2X3NsXCJcbiAgICAgIHVwZGF0ZSBcIm5leHRfY2xcIiwgXCJwcmV2X3NsXCJcblxuXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgSW5jbHVkZSB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgYXNzb2NpYXRpdmUgbGlzdHMuXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEBpc19leGVjdXRlZD9cbiAgICAgICAgcmV0dXJuIEBcbiAgICAgIGlmIG5vdCBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIGVsc2VcbiAgICAgICAgaWYgQHByZXZfY2w/LnZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKCkgYW5kIEBuZXh0X2NsPy52YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpIGFuZCBAcHJldl9jbC5uZXh0X2NsIGlzbnQgQFxuICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IDBcbiAgICAgICAgICBvID0gQHByZXZfY2wubmV4dF9jbFxuICAgICAgICAgIGkgPSAwXG4gICAgICAgICAgIyAkdGhpcyBoYXMgdG8gZmluZCBhIHVuaXF1ZSBwb3NpdGlvbiBiZXR3ZWVuIG9yaWdpbiBhbmQgdGhlIG5leHQga25vd24gY2hhcmFjdGVyXG4gICAgICAgICAgIyBjYXNlIDE6ICRvcmlnaW4gZXF1YWxzICRvLm9yaWdpbjogdGhlICRjcmVhdG9yIHBhcmFtZXRlciBkZWNpZGVzIGlmIGxlZnQgb3IgcmlnaHRcbiAgICAgICAgICAjICAgICAgICAgbGV0ICRPTD0gW28xLG8yLG8zLG80XSwgd2hlcmVieSAkdGhpcyBpcyB0byBiZSBpbnNlcnRlZCBiZXR3ZWVuIG8xIGFuZCBvNFxuICAgICAgICAgICMgICAgICAgICBvMixvMyBhbmQgbzQgb3JpZ2luIGlzIDEgKHRoZSBwb3NpdGlvbiBvZiBvMilcbiAgICAgICAgICAjICAgICAgICAgdGhlcmUgaXMgdGhlIGNhc2UgdGhhdCAkdGhpcy5jcmVhdG9yIDwgbzIuY3JlYXRvciwgYnV0IG8zLmNyZWF0b3IgPCAkdGhpcy5jcmVhdG9yXG4gICAgICAgICAgIyAgICAgICAgIHRoZW4gbzIga25vd3MgbzMuIFNpbmNlIG9uIGFub3RoZXIgY2xpZW50ICRPTCBjb3VsZCBiZSBbbzEsbzMsbzRdIHRoZSBwcm9ibGVtIGlzIGNvbXBsZXhcbiAgICAgICAgICAjICAgICAgICAgdGhlcmVmb3JlICR0aGlzIHdvdWxkIGJlIGFsd2F5cyB0byB0aGUgcmlnaHQgb2YgbzNcbiAgICAgICAgICAjIGNhc2UgMjogJG9yaWdpbiA8ICRvLm9yaWdpblxuICAgICAgICAgICMgICAgICAgICBpZiBjdXJyZW50ICR0aGlzIGluc2VydF9wb3NpdGlvbiA+ICRvIG9yaWdpbjogJHRoaXMgaW5zXG4gICAgICAgICAgIyAgICAgICAgIGVsc2UgJGluc2VydF9wb3NpdGlvbiB3aWxsIG5vdCBjaGFuZ2UgKG1heWJlIHdlIGVuY291bnRlciBjYXNlIDEgbGF0ZXIsIHRoZW4gdGhpcyB3aWxsIGJlIHRvIHRoZSByaWdodCBvZiAkbylcbiAgICAgICAgICAjIGNhc2UgMzogJG9yaWdpbiA+ICRvLm9yaWdpblxuICAgICAgICAgICMgICAgICAgICAkdGhpcyBpbnNlcnRfcG9zaXRpb24gaXMgdG8gdGhlIGxlZnQgb2YgJG8gKGZvcmV2ZXIhKVxuICAgICAgICAgIHdoaWxlIHRydWVcbiAgICAgICAgICAgIGlmIG5vdCBvP1xuICAgICAgICAgICAgICAjIFRPRE86IERlYnVnZ2luZ1xuICAgICAgICAgICAgICBjb25zb2xlLmxvZyBKU09OLnN0cmluZ2lmeSBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICAgICAgICBjb25zb2xlLmxvZyBKU09OLnN0cmluZ2lmeSBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgICAgICAgaWYgbyBpc250IEBuZXh0X2NsXG4gICAgICAgICAgICAgICMgJG8gaGFwcGVuZWQgY29uY3VycmVudGx5XG4gICAgICAgICAgICAgIGlmIG8uZ2V0RGlzdGFuY2VUb09yaWdpbigpIGlzIGlcbiAgICAgICAgICAgICAgICAjIGNhc2UgMVxuICAgICAgICAgICAgICAgIGlmIG8uY3JlYXRvciA8IEBjcmVhdG9yXG4gICAgICAgICAgICAgICAgICBAcHJldl9jbCA9IG9cbiAgICAgICAgICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IGkgKyAxXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgIyBub3BcbiAgICAgICAgICAgICAgZWxzZSBpZiBvLmdldERpc3RhbmNlVG9PcmlnaW4oKSA8IGlcbiAgICAgICAgICAgICAgICAjIGNhc2UgMlxuICAgICAgICAgICAgICAgIGlmIGkgLSBkaXN0YW5jZV90b19vcmlnaW4gPD0gby5nZXREaXN0YW5jZVRvT3JpZ2luKClcbiAgICAgICAgICAgICAgICAgIEBwcmV2X2NsID0gb1xuICAgICAgICAgICAgICAgICAgZGlzdGFuY2VfdG9fb3JpZ2luID0gaSArIDFcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAjbm9wXG4gICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAjIGNhc2UgM1xuICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgIGkrK1xuICAgICAgICAgICAgICBvID0gby5uZXh0X2NsXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICMgJHRoaXMga25vd3MgdGhhdCAkbyBleGlzdHMsXG4gICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgIyBub3cgcmVjb25uZWN0IGV2ZXJ5dGhpbmdcbiAgICAgICAgICBAbmV4dF9jbCA9IEBwcmV2X2NsLm5leHRfY2xcbiAgICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxuICAgICAgICAgIEBuZXh0X2NsLnByZXZfY2wgPSBAXG4gICAgICAgIHN1cGVyICMgbm90aWZ5IHRoZSBleGVjdXRpb25fbGlzdGVuZXJzXG4gICAgICAgIEBcblxuICAjXG4gICMgRGVmaW5lcyBhbiBvYmplY3QgdGhhdCBpcyBjYW5ub3QgYmUgY2hhbmdlZC4gWW91IGNhbiB1c2UgdGhpcyB0byBzZXQgYW4gaW1tdXRhYmxlIHN0cmluZywgb3IgYSBudW1iZXIuXG4gICNcbiAgY2xhc3MgSW1tdXRhYmxlT2JqZWN0IGV4dGVuZHMgSW5zZXJ0XG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gY29udGVudFxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgQGNvbnRlbnQsIHByZXYsIG5leHQsIG9yaWdpbiktPlxuICAgICAgc3VwZXIgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICAgICNcbiAgICAjIEByZXR1cm4gW1N0cmluZ10gVGhlIGNvbnRlbnQgb2YgdGhpcyBvcGVyYXRpb24uXG4gICAgI1xuICAgIHZhbCA6ICgpLT5cbiAgICAgIEBjb250ZW50XG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID0ge1xuICAgICAgICAndHlwZSc6IFwiSW1tdXRhYmxlT2JqZWN0XCJcbiAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgJ2NvbnRlbnQnIDogQGNvbnRlbnRcbiAgICAgIH1cbiAgICAgIGlmIEBwcmV2X2NsP1xuICAgICAgICBqc29uWydwcmV2J10gPSBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgaWYgQG5leHRfY2w/XG4gICAgICAgIGpzb25bJ25leHQnXSA9IEBuZXh0X2NsLmdldFVpZCgpXG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyWydJbW11dGFibGVPYmplY3QnXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICdwcmV2JzogcHJldlxuICAgICAgJ25leHQnOiBuZXh0XG4gICAgICAnb3JpZ2luJyA6IG9yaWdpblxuICAgIH0gPSBqc29uXG4gICAgbmV3IEltbXV0YWJsZU9iamVjdCB1aWQsIGNvbnRlbnQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICNcbiAgIyBBIGRlbGltaXRlciBpcyBwbGFjZWQgYXQgdGhlIGVuZCBhbmQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgYXNzb2NpYXRpdmUgbGlzdHMuXG4gICMgVGhpcyBpcyBuZWNlc3NhcnkgaW4gb3JkZXIgdG8gaGF2ZSBhIGJlZ2lubmluZyBhbmQgYW4gZW5kIGV2ZW4gaWYgdGhlIGNvbnRlbnRcbiAgIyBvZiB0aGUgRW5naW5lIGlzIGVtcHR5LlxuICAjXG4gIGNsYXNzIERlbGltaXRlciBleHRlbmRzIE9wZXJhdGlvblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBwcmV2X2NsIFRoZSBwcmVkZWNlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gbmV4dF9jbCBUaGUgc3VjY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcbiAgICAjXG4gICAgIyBAc2VlIEhpc3RvcnlCdWZmZXIuZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXJcbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIHByZXZfY2wsIG5leHRfY2wsIG9yaWdpbiktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ3ByZXZfY2wnLCBwcmV2X2NsXG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnbmV4dF9jbCcsIG5leHRfY2xcbiAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBwcmV2X2NsXG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIElmIGlzRGVsZXRlZCgpIGlzIHRydWUgdGhpcyBvcGVyYXRpb24gd29uJ3QgYmUgbWFpbnRhaW5lZCBpbiB0aGUgc2xcbiAgICAjXG4gICAgaXNEZWxldGVkOiAoKS0+XG4gICAgICBmYWxzZVxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgQHVuY2hlY2tlZD9bJ25leHRfY2wnXT9cbiAgICAgICAgc3VwZXJcbiAgICAgIGVsc2UgaWYgQHVuY2hlY2tlZD9bJ3ByZXZfY2wnXVxuICAgICAgICBpZiBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICAgIGlmIEBwcmV2X2NsLm5leHRfY2w/XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJQcm9iYWJseSBkdXBsaWNhdGVkIG9wZXJhdGlvbnNcIlxuICAgICAgICAgIEBwcmV2X2NsLm5leHRfY2wgPSBAXG4gICAgICAgICAgZGVsZXRlIEBwcmV2X2NsLnVuY2hlY2tlZC5uZXh0X2NsXG4gICAgICAgICAgc3VwZXJcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGZhbHNlXG4gICAgICBlbHNlIGlmIEBwcmV2X2NsPyBhbmQgbm90IEBwcmV2X2NsLm5leHRfY2w/XG4gICAgICAgIGRlbGV0ZSBAcHJldl9jbC51bmNoZWNrZWQubmV4dF9jbFxuICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxuICAgICAgZWxzZSBpZiBAcHJldl9jbD8gb3IgQG5leHRfY2w/XG4gICAgICAgIHN1cGVyXG4gICAgICBlbHNlXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcIkRlbGltaXRlciBpcyB1bnN1ZmZpY2llbnQgZGVmaW5lZCFcIlxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAge1xuICAgICAgICAndHlwZScgOiBcIkRlbGltaXRlclwiXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICdwcmV2JyA6IEBwcmV2X2NsPy5nZXRVaWQoKVxuICAgICAgICAnbmV4dCcgOiBAbmV4dF9jbD8uZ2V0VWlkKClcbiAgICAgIH1cblxuICBwYXJzZXJbJ0RlbGltaXRlciddID0gKGpzb24pLT5cbiAgICB7XG4gICAgJ3VpZCcgOiB1aWRcbiAgICAncHJldicgOiBwcmV2XG4gICAgJ25leHQnIDogbmV4dFxuICAgIH0gPSBqc29uXG4gICAgbmV3IERlbGltaXRlciB1aWQsIHByZXYsIG5leHRcblxuICAjIFRoaXMgaXMgd2hhdCB0aGlzIG1vZHVsZSBleHBvcnRzIGFmdGVyIGluaXRpYWxpemluZyBpdCB3aXRoIHRoZSBIaXN0b3J5QnVmZmVyXG4gIHtcbiAgICAndHlwZXMnIDpcbiAgICAgICdEZWxldGUnIDogRGVsZXRlXG4gICAgICAnSW5zZXJ0JyA6IEluc2VydFxuICAgICAgJ0RlbGltaXRlcic6IERlbGltaXRlclxuICAgICAgJ09wZXJhdGlvbic6IE9wZXJhdGlvblxuICAgICAgJ0ltbXV0YWJsZU9iamVjdCcgOiBJbW11dGFibGVPYmplY3RcbiAgICAncGFyc2VyJyA6IHBhcnNlclxuICAgICdleGVjdXRpb25fbGlzdGVuZXInIDogZXhlY3V0aW9uX2xpc3RlbmVyXG4gIH1cblxuXG5cblxuIiwidGV4dF90eXBlc191bmluaXRpYWxpemVkID0gcmVxdWlyZSBcIi4vVGV4dFR5cGVzXCJcblxubW9kdWxlLmV4cG9ydHMgPSAoSEIpLT5cbiAgdGV4dF90eXBlcyA9IHRleHRfdHlwZXNfdW5pbml0aWFsaXplZCBIQlxuICB0eXBlcyA9IHRleHRfdHlwZXMudHlwZXNcbiAgcGFyc2VyID0gdGV4dF90eXBlcy5wYXJzZXJcblxuICBjcmVhdGVKc29uV3JhcHBlciA9IChfanNvblR5cGUpLT5cblxuICAgICNcbiAgICAjIEEgSnNvbldyYXBwZXIgd2FzIGludGVuZGVkIHRvIGJlIGEgY29udmVuaWVudCB3cmFwcGVyIGZvciB0aGUgSnNvblR5cGUuXG4gICAgIyBCdXQgaXQgY2FuIG1ha2UgdGhpbmdzIG1vcmUgZGlmZmljdWx0IHRoYW4gdGhleSBhcmUuXG4gICAgIyBAc2VlIEpzb25UeXBlXG4gICAgI1xuICAgICMgQGV4YW1wbGUgY3JlYXRlIGEgSnNvbldyYXBwZXJcbiAgICAjICAgIyBZb3UgZ2V0IGEgSnNvbldyYXBwZXIgZnJvbSBhIEpzb25UeXBlIGJ5IGNhbGxpbmdcbiAgICAjICAgdyA9IHlhdHRhLnZhbHVlXG4gICAgI1xuICAgICMgSXQgY3JlYXRlcyBKYXZhc2NyaXB0cyAtZ2V0dGVyIGFuZCAtc2V0dGVyIG1ldGhvZHMgZm9yIGVhY2ggcHJvcGVydHkgdGhhdCBKc29uVHlwZSBtYWludGFpbnMuXG4gICAgIyBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL09iamVjdC9kZWZpbmVQcm9wZXJ0eVxuICAgICNcbiAgICAjIEBleGFtcGxlIEdldHRlciBFeGFtcGxlXG4gICAgIyAgICMgeW91IGNhbiBhY2Nlc3MgdGhlIHggcHJvcGVydHkgb2YgeWF0dGEgYnkgY2FsbGluZ1xuICAgICMgICB3LnhcbiAgICAjICAgIyBpbnN0ZWFkIG9mXG4gICAgIyAgIHlhdHRhLnZhbCgneCcpXG4gICAgI1xuICAgICMgQG5vdGUgWW91IGNhbiBvbmx5IG92ZXJ3cml0ZSBleGlzdGluZyB2YWx1ZXMhIFNldHRpbmcgYSBuZXcgcHJvcGVydHkgd29uJ3QgaGF2ZSBhbnkgZWZmZWN0IVxuICAgICNcbiAgICAjIEBleGFtcGxlIFNldHRlciBFeGFtcGxlXG4gICAgIyAgICMgeW91IGNhbiBzZXQgYW4gZXhpc3RpbmcgeCBwcm9wZXJ0eSBvZiB5YXR0YSBieSBjYWxsaW5nXG4gICAgIyAgIHcueCA9IFwidGV4dFwiXG4gICAgIyAgICMgaW5zdGVhZCBvZlxuICAgICMgICB5YXR0YS52YWwoJ3gnLCBcInRleHRcIilcbiAgICAjXG4gICAgIyBJbiBvcmRlciB0byBzZXQgYSBuZXcgcHJvcGVydHkgeW91IGhhdmUgdG8gb3ZlcndyaXRlIGFuIGV4aXN0aW5nIHByb3BlcnR5LlxuICAgICMgVGhlcmVmb3JlIHRoZSBKc29uV3JhcHBlciBzdXBwb3J0cyBhIHNwZWNpYWwgZmVhdHVyZSB0aGF0IHNob3VsZCBtYWtlIHRoaW5ncyBtb3JlIGNvbnZlbmllbnRcbiAgICAjICh3ZSBjYW4gYXJndWUgYWJvdXQgdGhhdCwgdXNlIHRoZSBKc29uVHlwZSBpZiB5b3UgZG9uJ3QgbGlrZSBpdCA7KS5cbiAgICAjIElmIHlvdSBvdmVyd3JpdGUgYW4gb2JqZWN0IHByb3BlcnR5IG9mIHRoZSBKc29uV3JhcHBlciB3aXRoIGEgbmV3IG9iamVjdCwgaXQgd2lsbCByZXN1bHQgaW4gYSBtZXJnZWQgdmVyc2lvbiBvZiB0aGUgb2JqZWN0cy5cbiAgICAjIExldCB3LnAgdGhlIHByb3BlcnR5IHRoYXQgaXMgdG8gYmUgb3ZlcndyaXR0ZW4gYW5kIG8gdGhlIG5ldyB2YWx1ZS4gRS5nLiB3LnAgPSBvXG4gICAgIyAqIFRoZSByZXN1bHQgaGFzIGFsbCBwcm9wZXJ0aWVzIG9mIG9cbiAgICAjICogVGhlIHJlc3VsdCBoYXMgYWxsIHByb3BlcnRpZXMgb2Ygdy5wIGlmIHRoZXkgZG9uJ3Qgb2NjdXIgdW5kZXIgdGhlIHNhbWUgcHJvcGVydHktbmFtZSBpbiBvLlxuICAgICNcbiAgICAjIEBleGFtcGxlIENvbmZsaWN0IEV4YW1wbGVcbiAgICAjICAgeWF0dGEudmFsdWUgPSB7YSA6IFwic3RyaW5nXCJ9XG4gICAgIyAgIHcgPSB5YXR0YS52YWx1ZVxuICAgICMgICBjb25zb2xlLmxvZyh3KSAjIHthIDogXCJzdHJpbmdcIn1cbiAgICAjICAgdy5hID0ge2EgOiB7YiA6IFwic3RyaW5nXCJ9fVxuICAgICMgICBjb25zb2xlLmxvZyh3KSAjIHthIDoge2IgOiBcIlN0cmluZ1wifX1cbiAgICAjICAgdy5hID0ge2EgOiB7YyA6IDR9fVxuICAgICMgICBjb25zb2xlLmxvZyh3KSAjIHthIDoge2IgOiBcIlN0cmluZ1wiLCBjIDogNH19XG4gICAgI1xuICAgICMgQGV4YW1wbGUgQ29tbW9uIFBpdGZhbGxzXG4gICAgIyAgIHcgPSB5YXR0YS52YWx1ZVxuICAgICMgICAjIFNldHRpbmcgYSBuZXcgcHJvcGVydHlcbiAgICAjICAgdy5uZXdQcm9wZXJ0eSA9IFwiQXdlc29tZVwiXG4gICAgIyAgIGNvbnNvbGUubG9nKHcubmV3UHJvcGVydHkgPT0gXCJBd2Vzb21lXCIpICMgZmFsc2UsIHcubmV3UHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgIyAgICMgb3ZlcndyaXRlIHRoZSB3IG9iamVjdFxuICAgICMgICB3ID0ge25ld1Byb3BlcnR5IDogXCJBd2Vzb21lXCJ9XG4gICAgIyAgIGNvbnNvbGUubG9nKHcubmV3UHJvcGVydHkgPT0gXCJBd2Vzb21lXCIpICMgdHJ1ZSEsIGJ1dCAuLlxuICAgICMgICBjb25zb2xlLmxvZyh5YXR0YS52YWx1ZS5uZXdQcm9wZXJ0eSA9PSBcIkF3ZXNvbWVcIikgIyBmYWxzZSwgeW91IGFyZSBvbmx5IGFsbG93ZWQgdG8gc2V0IHByb3BlcnRpZXMhXG4gICAgIyAgICMgVGhlIHNvbHV0aW9uXG4gICAgIyAgIHlhdHRhLnZhbHVlID0ge25ld1Byb3BlcnR5IDogXCJBd2Vzb21lXCJ9XG4gICAgIyAgIGNvbnNvbGUubG9nKHcubmV3UHJvcGVydHkgPT0gXCJBd2Vzb21lXCIpICMgdHJ1ZSFcbiAgICAjXG4gICAgY2xhc3MgSnNvbldyYXBwZXJcblxuICAgICAgI1xuICAgICAgIyBAcGFyYW0ge0pzb25UeXBlfSBqc29uVHlwZSBJbnN0YW5jZSBvZiB0aGUgSnNvblR5cGUgdGhhdCB0aGlzIGNsYXNzIHdyYXBwZXMuXG4gICAgICAjXG4gICAgICBjb25zdHJ1Y3RvcjogKGpzb25UeXBlKS0+XG4gICAgICAgIGZvciBuYW1lLCBvYmogb2YganNvblR5cGUubWFwXG4gICAgICAgICAgZG8gKG5hbWUsIG9iaiktPlxuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5IEpzb25XcmFwcGVyLnByb3RvdHlwZSwgbmFtZSxcbiAgICAgICAgICAgICAgZ2V0IDogLT5cbiAgICAgICAgICAgICAgICB4ID0gb2JqLnZhbCgpXG4gICAgICAgICAgICAgICAgaWYgeCBpbnN0YW5jZW9mIEpzb25UeXBlXG4gICAgICAgICAgICAgICAgICBjcmVhdGVKc29uV3JhcHBlciB4XG4gICAgICAgICAgICAgICAgZWxzZSBpZiB4IGluc3RhbmNlb2YgdHlwZXMuSW1tdXRhYmxlT2JqZWN0XG4gICAgICAgICAgICAgICAgICB4LnZhbCgpXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgeFxuICAgICAgICAgICAgICBzZXQgOiAobyktPlxuICAgICAgICAgICAgICAgIGlmIG8uY29uc3RydWN0b3IgaXMge30uY29uc3RydWN0b3JcbiAgICAgICAgICAgICAgICAgIG92ZXJ3cml0ZSA9IGpzb25UeXBlLnZhbChuYW1lKVxuICAgICAgICAgICAgICAgICAgZm9yIG9fbmFtZSxvX29iaiBvZiBvXG4gICAgICAgICAgICAgICAgICAgIG92ZXJ3cml0ZS52YWwob19uYW1lLCBvX29iaiwgJ2ltbXV0YWJsZScpXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAganNvblR5cGUudmFsKG5hbWUsIG8sICdpbW11dGFibGUnKVxuICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2VcbiAgICBuZXcgSnNvbldyYXBwZXIgX2pzb25UeXBlXG5cbiAgI1xuICAjIE1hbmFnZXMgT2JqZWN0LWxpa2UgdmFsdWVzLlxuICAjXG4gIGNsYXNzIEpzb25UeXBlIGV4dGVuZHMgdHlwZXMuTWFwTWFuYWdlclxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IGluaXRpYWxfdmFsdWUgQ3JlYXRlIHRoaXMgb3BlcmF0aW9uIHdpdGggYW4gaW5pdGlhbCB2YWx1ZS5cbiAgICAjIEBwYXJhbSB7U3RyaW5nfEJvb2xlYW59IFdoZXRoZXIgdGhlIGluaXRpYWxfdmFsdWUgc2hvdWxkIGJlIGNyZWF0ZWQgYXMgbXV0YWJsZS4gKE9wdGlvbmFsIC0gc2VlIHNldE11dGFibGVEZWZhdWx0KVxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgaW5pdGlhbF92YWx1ZSwgbXV0YWJsZSktPlxuICAgICAgc3VwZXIgdWlkXG4gICAgICBpZiBpbml0aWFsX3ZhbHVlP1xuICAgICAgICBpZiB0eXBlb2YgaW5pdGlhbF92YWx1ZSBpc250IFwib2JqZWN0XCJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJUaGUgaW5pdGlhbCB2YWx1ZSBvZiBKc29uVHlwZXMgbXVzdCBiZSBvZiB0eXBlIE9iamVjdCEgKGN1cnJlbnQgdHlwZTogI3t0eXBlb2YgaW5pdGlhbF92YWx1ZX0pXCJcbiAgICAgICAgZm9yIG5hbWUsbyBvZiBpbml0aWFsX3ZhbHVlXG4gICAgICAgICAgQHZhbCBuYW1lLCBvLCBtdXRhYmxlXG5cbiAgICAjXG4gICAgIyBXaGV0aGVyIHRoZSBkZWZhdWx0IGlzICdtdXRhYmxlJyAodHJ1ZSkgb3IgJ2ltbXV0YWJsZScgKGZhbHNlKVxuICAgICNcbiAgICBtdXRhYmxlX2RlZmF1bHQ6XG4gICAgICB0cnVlXG5cbiAgICAjXG4gICAgIyBTZXQgaWYgdGhlIGRlZmF1bHQgaXMgJ211dGFibGUnIG9yICdpbW11dGFibGUnXG4gICAgIyBAcGFyYW0ge1N0cmluZ3xCb29sZWFufSBtdXRhYmxlIFNldCBlaXRoZXIgJ211dGFibGUnIC8gdHJ1ZSBvciAnaW1tdXRhYmxlJyAvIGZhbHNlXG4gICAgc2V0TXV0YWJsZURlZmF1bHQ6IChtdXRhYmxlKS0+XG4gICAgICBpZiBtdXRhYmxlIGlzIHRydWUgb3IgbXV0YWJsZSBpcyAnbXV0YWJsZSdcbiAgICAgICAgSnNvblR5cGUucHJvdG90eXBlLm11dGFibGVfZGVmYXVsdCA9IHRydWVcbiAgICAgIGVsc2UgaWYgbXV0YWJsZSBpcyBmYWxzZSBvciBtdXRhYmxlIGlzICdpbW11dGFibGUnXG4gICAgICAgIEpzb25UeXBlLnByb3RvdHlwZS5tdXRhYmxlX2RlZmF1bHQgPSBmYWxzZVxuICAgICAgZWxzZVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgJ1NldCBtdXRhYmxlIGVpdGhlciBcIm11dGFibGVcIiBvciBcImltbXV0YWJsZVwiISdcbiAgICAgICdPSydcblxuICAgICNcbiAgICAjIEBvdmVybG9hZCB2YWwoKVxuICAgICMgICBHZXQgdGhpcyBhcyBhIEpzb24gb2JqZWN0LlxuICAgICMgICBAcmV0dXJuIFtKc29uXVxuICAgICNcbiAgICAjIEBvdmVybG9hZCB2YWwobmFtZSlcbiAgICAjICAgR2V0IHZhbHVlIG9mIGEgcHJvcGVydHkuXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIG9iamVjdCBwcm9wZXJ0eS5cbiAgICAjICAgQHJldHVybiBbSnNvblR5cGV8V29yZHxTdHJpbmd8T2JqZWN0XSBEZXBlbmRpbmcgb24gdGhlIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eS4gSWYgbXV0YWJsZSBpdCB3aWxsIHJldHVybiBhIE9wZXJhdGlvbi10eXBlIG9iamVjdCwgaWYgaW1tdXRhYmxlIGl0IHdpbGwgcmV0dXJuIFN0cmluZy9PYmplY3QuXG4gICAgI1xuICAgICMgQG92ZXJsb2FkIHZhbChuYW1lLCBjb250ZW50KVxuICAgICMgICBTZXQgYSBuZXcgcHJvcGVydHkuXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIG9iamVjdCBwcm9wZXJ0eS5cbiAgICAjICAgQHBhcmFtIHtPYmplY3R8U3RyaW5nfSBjb250ZW50IENvbnRlbnQgb2YgdGhlIG9iamVjdCBwcm9wZXJ0eS5cbiAgICAjICAgQHJldHVybiBbSnNvblR5cGVdIFRoaXMgb2JqZWN0LiAoc3VwcG9ydHMgY2hhaW5pbmcpXG4gICAgI1xuICAgIHZhbDogKG5hbWUsIGNvbnRlbnQsIG11dGFibGUpLT5cbiAgICAgIGlmIHR5cGVvZiBuYW1lIGlzICdvYmplY3QnXG4gICAgICAgICMgU3BlY2lhbCBjYXNlLiBGaXJzdCBhcmd1bWVudCBpcyBhbiBvYmplY3QuIFRoZW4gdGhlIHNlY29uZCBhcmcgaXMgbXV0YWJsZS5cbiAgICAgICAgIyBLZWVwIHRoYXQgaW4gbWluZCB3aGVuIHJlYWRpbmcgdGhlIGZvbGxvd2luZy4uXG4gICAgICAgIGZvciBvX25hbWUsbyBvZiBuYW1lXG4gICAgICAgICAgQHZhbChvX25hbWUsbyxjb250ZW50KVxuICAgICAgICBAXG4gICAgICBlbHNlIGlmIG5hbWU/IGFuZCBjb250ZW50P1xuICAgICAgICBpZiBtdXRhYmxlP1xuICAgICAgICAgIGlmIG11dGFibGUgaXMgdHJ1ZSBvciBtdXRhYmxlIGlzICdtdXRhYmxlJ1xuICAgICAgICAgICAgbXV0YWJsZSA9IHRydWVcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBtdXRhYmxlID0gZmFsc2VcbiAgICAgICAgZWxzZVxuICAgICAgICAgIG11dGFibGUgPSBAbXV0YWJsZV9kZWZhdWx0XG4gICAgICAgIGlmIHR5cGVvZiBjb250ZW50IGlzICdmdW5jdGlvbidcbiAgICAgICAgICBAICMgSnVzdCBkbyBub3RoaW5nXG4gICAgICAgIGVsc2UgaWYgKChub3QgbXV0YWJsZSkgb3IgdHlwZW9mIGNvbnRlbnQgaXMgJ251bWJlcicpIGFuZCBjb250ZW50LmNvbnN0cnVjdG9yIGlzbnQgT2JqZWN0XG4gICAgICAgICAgb2JqID0gSEIuYWRkT3BlcmF0aW9uKG5ldyB0eXBlcy5JbW11dGFibGVPYmplY3QgdW5kZWZpbmVkLCBjb250ZW50KS5leGVjdXRlKClcbiAgICAgICAgICBzdXBlciBuYW1lLCBvYmpcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGlmIHR5cGVvZiBjb250ZW50IGlzICdzdHJpbmcnXG4gICAgICAgICAgICB3b3JkID0gSEIuYWRkT3BlcmF0aW9uKG5ldyB0eXBlcy5Xb3JkIHVuZGVmaW5lZCkuZXhlY3V0ZSgpXG4gICAgICAgICAgICB3b3JkLmluc2VydFRleHQgMCwgY29udGVudFxuICAgICAgICAgICAgc3VwZXIgbmFtZSwgd29yZFxuICAgICAgICAgIGVsc2UgaWYgY29udGVudC5jb25zdHJ1Y3RvciBpcyBPYmplY3RcbiAgICAgICAgICAgIGpzb24gPSBIQi5hZGRPcGVyYXRpb24obmV3IEpzb25UeXBlIHVuZGVmaW5lZCwgY29udGVudCwgbXV0YWJsZSkuZXhlY3V0ZSgpXG4gICAgICAgICAgICBzdXBlciBuYW1lLCBqc29uXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3Qgbm90IHNldCAje3R5cGVvZiBjb250ZW50fS10eXBlcyBpbiBjb2xsYWJvcmF0aXZlIEpzb24tb2JqZWN0cyFcIlxuICAgICAgZWxzZVxuICAgICAgICBzdXBlciBuYW1lLCBjb250ZW50XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkgSnNvblR5cGUucHJvdG90eXBlLCAndmFsdWUnLFxuICAgICAgZ2V0IDogLT4gY3JlYXRlSnNvbldyYXBwZXIgQFxuICAgICAgc2V0IDogKG8pLT5cbiAgICAgICAgaWYgby5jb25zdHJ1Y3RvciBpcyB7fS5jb25zdHJ1Y3RvclxuICAgICAgICAgIGZvciBvX25hbWUsb19vYmogb2Ygb1xuICAgICAgICAgICAgQHZhbChvX25hbWUsIG9fb2JqLCAnaW1tdXRhYmxlJylcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBtdXN0IG9ubHkgc2V0IE9iamVjdCB2YWx1ZXMhXCJcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIHtcbiAgICAgICAgJ3R5cGUnIDogXCJKc29uVHlwZVwiXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICB9XG5cbiAgcGFyc2VyWydKc29uVHlwZSddID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgIH0gPSBqc29uXG4gICAgbmV3IEpzb25UeXBlIHVpZFxuXG5cblxuXG4gIHR5cGVzWydKc29uVHlwZSddID0gSnNvblR5cGVcblxuICB0ZXh0X3R5cGVzXG5cblxuIiwiYmFzaWNfdHlwZXNfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuL0Jhc2ljVHlwZXNcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IChIQiktPlxuICBiYXNpY190eXBlcyA9IGJhc2ljX3R5cGVzX3VuaW5pdGlhbGl6ZWQgSEJcbiAgdHlwZXMgPSBiYXNpY190eXBlcy50eXBlc1xuICBwYXJzZXIgPSBiYXNpY190eXBlcy5wYXJzZXJcblxuICAjXG4gICMgTWFuYWdlcyBtYXAgbGlrZSBvYmplY3RzLiBFLmcuIEpzb24tVHlwZSBhbmQgWE1MIGF0dHJpYnV0ZXMuXG4gICNcbiAgY2xhc3MgTWFwTWFuYWdlciBleHRlbmRzIHR5cGVzLk9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCktPlxuICAgICAgQG1hcCA9IHt9XG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIEBzZWUgSnNvblR5cGVzLnZhbFxuICAgICNcbiAgICB2YWw6IChuYW1lLCBjb250ZW50KS0+XG4gICAgICBpZiBjb250ZW50P1xuICAgICAgICBpZiBub3QgQG1hcFtuYW1lXT9cbiAgICAgICAgICBIQi5hZGRPcGVyYXRpb24obmV3IEFkZE5hbWUgdW5kZWZpbmVkLCBALCBuYW1lKS5leGVjdXRlKClcbiAgICAgICAgQG1hcFtuYW1lXS5yZXBsYWNlIGNvbnRlbnRcbiAgICAgICAgQFxuICAgICAgZWxzZSBpZiBuYW1lP1xuICAgICAgICBvYmogPSBAbWFwW25hbWVdPy52YWwoKVxuICAgICAgICBpZiBvYmogaW5zdGFuY2VvZiB0eXBlcy5JbW11dGFibGVPYmplY3RcbiAgICAgICAgICBvYmoudmFsKClcbiAgICAgICAgZWxzZVxuICAgICAgICAgIG9ialxuICAgICAgZWxzZVxuICAgICAgICByZXN1bHQgPSB7fVxuICAgICAgICBmb3IgbmFtZSxvIG9mIEBtYXBcbiAgICAgICAgICBvYmogPSBvLnZhbCgpXG4gICAgICAgICAgaWYgb2JqIGluc3RhbmNlb2YgdHlwZXMuSW1tdXRhYmxlT2JqZWN0IG9yIG9iaiBpbnN0YW5jZW9mIE1hcE1hbmFnZXJcbiAgICAgICAgICAgIG9iaiA9IG9iai52YWwoKVxuICAgICAgICAgIHJlc3VsdFtuYW1lXSA9IG9ialxuICAgICAgICByZXN1bHRcblxuICAjXG4gICMgV2hlbiBhIG5ldyBwcm9wZXJ0eSBpbiBhIG1hcCBtYW5hZ2VyIGlzIGNyZWF0ZWQsIHRoZW4gdGhlIHVpZHMgb2YgdGhlIGluc2VydGVkIE9wZXJhdGlvbnNcbiAgIyBtdXN0IGJlIHVuaXF1ZSAodGhpbmsgYWJvdXQgY29uY3VycmVudCBvcGVyYXRpb25zKS4gVGhlcmVmb3JlIG9ubHkgYW4gQWRkTmFtZSBvcGVyYXRpb24gaXMgYWxsb3dlZCB0b1xuICAjIGFkZCBhIHByb3BlcnR5IGluIGEgTWFwTWFuYWdlci4gSWYgdHdvIEFkZE5hbWUgb3BlcmF0aW9ucyBvbiB0aGUgc2FtZSBNYXBNYW5hZ2VyIG5hbWUgaGFwcGVuIGNvbmN1cnJlbnRseVxuICAjIG9ubHkgb25lIHdpbGwgQWRkTmFtZSBvcGVyYXRpb24gd2lsbCBiZSBleGVjdXRlZC5cbiAgI1xuICBjbGFzcyBBZGROYW1lIGV4dGVuZHMgdHlwZXMuT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gbWFwX21hbmFnZXIgVWlkIG9yIHJlZmVyZW5jZSB0byB0aGUgTWFwTWFuYWdlci5cbiAgICAjIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIHByb3BlcnR5IHRoYXQgd2lsbCBiZSBhZGRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIG1hcF9tYW5hZ2VyLCBAbmFtZSktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ21hcF9tYW5hZ2VyJywgbWFwX21hbmFnZXJcbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgSWYgbWFwX21hbmFnZXIgZG9lc24ndCBoYXZlIHRoZSBwcm9wZXJ0eSBuYW1lLCB0aGVuIGFkZCBpdC5cbiAgICAjIFRoZSBSZXBsYWNlTWFuYWdlciB0aGF0IGlzIGJlaW5nIHdyaXR0ZW4gb24gdGhlIHByb3BlcnR5IGlzIHVuaXF1ZVxuICAgICMgaW4gc3VjaCBhIHdheSB0aGF0IGlmIEFkZE5hbWUgaXMgZXhlY3V0ZWQgKGZyb20gYW5vdGhlciBwZWVyKSBpdCB3aWxsXG4gICAgIyBhbHdheXMgaGF2ZSB0aGUgc2FtZSByZXN1bHQgKFJlcGxhY2VNYW5hZ2VyLCBhbmQgaXRzIGJlZ2lubmluZyBhbmQgZW5kIGFyZSB0aGUgc2FtZSlcbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgbm90IEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgZWxzZVxuICAgICAgICB1aWRfciA9IEBtYXBfbWFuYWdlci5nZXRVaWQoKVxuICAgICAgICB1aWRfci5vcF9udW1iZXIgPSBcIl8je3VpZF9yLm9wX251bWJlcn1fUk1fI3tAbmFtZX1cIlxuICAgICAgICBpZiBub3QgSEIuZ2V0T3BlcmF0aW9uKHVpZF9yKT9cbiAgICAgICAgICB1aWRfYmVnID0gQG1hcF9tYW5hZ2VyLmdldFVpZCgpXG4gICAgICAgICAgdWlkX2JlZy5vcF9udW1iZXIgPSBcIl8je3VpZF9iZWcub3BfbnVtYmVyfV9STV8je0BuYW1lfV9iZWdpbm5pbmdcIlxuICAgICAgICAgIHVpZF9lbmQgPSBAbWFwX21hbmFnZXIuZ2V0VWlkKClcbiAgICAgICAgICB1aWRfZW5kLm9wX251bWJlciA9IFwiXyN7dWlkX2VuZC5vcF9udW1iZXJ9X1JNXyN7QG5hbWV9X2VuZFwiXG4gICAgICAgICAgYmVnID0gSEIuYWRkT3BlcmF0aW9uKG5ldyB0eXBlcy5EZWxpbWl0ZXIgdWlkX2JlZywgdW5kZWZpbmVkLCB1aWRfZW5kKS5leGVjdXRlKClcbiAgICAgICAgICBlbmQgPSBIQi5hZGRPcGVyYXRpb24obmV3IHR5cGVzLkRlbGltaXRlciB1aWRfZW5kLCBiZWcsIHVuZGVmaW5lZCkuZXhlY3V0ZSgpXG4gICAgICAgICAgI2JlZy5leGVjdXRlKClcbiAgICAgICAgICBAbWFwX21hbmFnZXIubWFwW0BuYW1lXSA9IEhCLmFkZE9wZXJhdGlvbihuZXcgUmVwbGFjZU1hbmFnZXIgdW5kZWZpbmVkLCB1aWRfciwgYmVnLCBlbmQpLmV4ZWN1dGUoKVxuICAgICAgICBzdXBlclxuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAge1xuICAgICAgICAndHlwZScgOiBcIkFkZE5hbWVcIlxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAnbWFwX21hbmFnZXInIDogQG1hcF9tYW5hZ2VyLmdldFVpZCgpXG4gICAgICAgICduYW1lJyA6IEBuYW1lXG4gICAgICB9XG5cbiAgcGFyc2VyWydBZGROYW1lJ10gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdtYXBfbWFuYWdlcicgOiBtYXBfbWFuYWdlclxuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICduYW1lJyA6IG5hbWVcbiAgICB9ID0ganNvblxuICAgIG5ldyBBZGROYW1lIHVpZCwgbWFwX21hbmFnZXIsIG5hbWVcblxuICAjXG4gICMgTWFuYWdlcyBhIGxpc3Qgb2YgSW5zZXJ0LXR5cGUgb3BlcmF0aW9ucy5cbiAgI1xuICBjbGFzcyBMaXN0TWFuYWdlciBleHRlbmRzIHR5cGVzLkluc2VydFxuXG4gICAgI1xuICAgICMgQSBMaXN0TWFuYWdlciBtYWludGFpbnMgYSBub24tZW1wdHkgbGlzdCB0aGF0IGhhcyBhIGJlZ2lubmluZyBhbmQgYW4gZW5kIChib3RoIERlbGltaXRlcnMhKVxuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGJlZ2lubmluZyBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGVuZCBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBpZiBiZWdpbm5pbmc/IGFuZCBlbmQ/XG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdiZWdpbm5pbmcnLCBiZWdpbm5pbmdcbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ2VuZCcsIGVuZFxuICAgICAgZWxzZVxuICAgICAgICBAYmVnaW5uaW5nID0gSEIuYWRkT3BlcmF0aW9uIG5ldyB0eXBlcy5EZWxpbWl0ZXIgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZFxuICAgICAgICBAZW5kID0gICAgICAgSEIuYWRkT3BlcmF0aW9uIG5ldyB0eXBlcy5EZWxpbWl0ZXIgdW5kZWZpbmVkLCBAYmVnaW5uaW5nLCB1bmRlZmluZWRcbiAgICAgICAgQGJlZ2lubmluZy5uZXh0X2NsID0gQGVuZFxuICAgICAgICBAYmVnaW5uaW5nLmV4ZWN1dGUoKVxuICAgICAgICBAZW5kLmV4ZWN1dGUoKVxuICAgICAgc3VwZXIgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuXG4gICAgIyBHZXQgdGhlIGVsZW1lbnQgcHJldmlvdXMgdG8gdGhlIGRlbGVtaXRlciBhdCB0aGUgZW5kXG4gICAgZ2V0TGFzdE9wZXJhdGlvbjogKCktPlxuICAgICAgQGVuZC5wcmV2X2NsXG5cbiAgICAjIHNpbWlsYXIgdG8gdGhlIGFib3ZlXG4gICAgZ2V0Rmlyc3RPcGVyYXRpb246ICgpLT5cbiAgICAgIEBiZWdpbm5pbmcubmV4dF9jbFxuXG4gICAgIyBUcmFuc2Zvcm1zIHRoZSB0aGUgbGlzdCB0byBhbiBhcnJheVxuICAgICMgRG9lc24ndCByZXR1cm4gbGVmdC1yaWdodCBkZWxpbWl0ZXIuXG4gICAgdG9BcnJheTogKCktPlxuICAgICAgbyA9IEBiZWdpbm5pbmcubmV4dF9jbFxuICAgICAgcmVzdWx0ID0gW11cbiAgICAgIHdoaWxlIG8gaXNudCBAZW5kXG4gICAgICAgIHJlc3VsdC5wdXNoIG9cbiAgICAgICAgbyA9IG8ubmV4dF9jbFxuICAgICAgcmVzdWx0XG5cbiAgICAjXG4gICAgIyBSZXRyaWV2ZXMgdGhlIHgtdGggbm90IGRlbGV0ZWQgZWxlbWVudC5cbiAgICAjXG4gICAgZ2V0T3BlcmF0aW9uQnlQb3NpdGlvbjogKHBvc2l0aW9uKS0+XG4gICAgICBvID0gQGJlZ2lubmluZy5uZXh0X2NsXG4gICAgICBpZiBwb3NpdGlvbiA+IDBcbiAgICAgICAgd2hpbGUgdHJ1ZVxuICAgICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgICBpZiBub3Qgby5pc0RlbGV0ZWQoKVxuICAgICAgICAgICAgcG9zaXRpb24gLT0gMVxuICAgICAgICAgIGlmIHBvc2l0aW9uIGlzIDBcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgaWYgbyBpbnN0YW5jZW9mIHR5cGVzLkRlbGltaXRlclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwicG9zaXRpb24gcGFyYW1ldGVyIGV4Y2VlZGVkIHRoZSBsZW5ndGggb2YgdGhlIGRvY3VtZW50IVwiXG4gICAgICBvXG5cbiAgI1xuICAjIEFkZHMgc3VwcG9ydCBmb3IgcmVwbGFjZS4gVGhlIFJlcGxhY2VNYW5hZ2VyIG1hbmFnZXMgUmVwbGFjZWFibGUgb3BlcmF0aW9ucy5cbiAgIyBFYWNoIFJlcGxhY2VhYmxlIGhvbGRzIGEgdmFsdWUgdGhhdCBpcyBub3cgcmVwbGFjZWFibGUuXG4gICNcbiAgIyBUaGUgV29yZC10eXBlIGhhcyBpbXBsZW1lbnRlZCBzdXBwb3J0IGZvciByZXBsYWNlXG4gICMgQHNlZSBXb3JkXG4gICNcbiAgY2xhc3MgUmVwbGFjZU1hbmFnZXIgZXh0ZW5kcyBMaXN0TWFuYWdlclxuICAgICNcbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBpbml0aWFsX2NvbnRlbnQgSW5pdGlhbGl6ZSB0aGlzIHdpdGggYSBSZXBsYWNlYWJsZSB0aGF0IGhvbGRzIHRoZSBpbml0aWFsX2NvbnRlbnQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge0RlbGltaXRlcn0gYmVnaW5uaW5nIFJlZmVyZW5jZSBvciBPYmplY3QuXG4gICAgIyBAcGFyYW0ge0RlbGltaXRlcn0gZW5kIFJlZmVyZW5jZSBvciBPYmplY3QuXG4gICAgY29uc3RydWN0b3I6IChpbml0aWFsX2NvbnRlbnQsIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpbiktPlxuICAgICAgc3VwZXIgdWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luXG4gICAgICBpZiBpbml0aWFsX2NvbnRlbnQ/XG4gICAgICAgIEByZXBsYWNlIGluaXRpYWxfY29udGVudFxuXG4gICAgI1xuICAgICMgUmVwbGFjZSB0aGUgZXhpc3Rpbmcgd29yZCB3aXRoIGEgbmV3IHdvcmQuXG4gICAgI1xuICAgIHJlcGxhY2U6IChjb250ZW50KS0+XG4gICAgICBvID0gQGdldExhc3RPcGVyYXRpb24oKVxuICAgICAgb3AgPSBuZXcgUmVwbGFjZWFibGUgY29udGVudCwgQCwgdW5kZWZpbmVkLCBvLCBvLm5leHRfY2xcbiAgICAgIEhCLmFkZE9wZXJhdGlvbihvcCkuZXhlY3V0ZSgpXG5cbiAgICAjXG4gICAgIyBHZXQgdGhlIHZhbHVlIG9mIHRoaXMgV29yZFxuICAgICMgQHJldHVybiB7U3RyaW5nfVxuICAgICNcbiAgICB2YWw6ICgpLT5cbiAgICAgIG8gPSBAZ2V0TGFzdE9wZXJhdGlvbigpXG4gICAgICBpZiBvIGluc3RhbmNlb2YgdHlwZXMuRGVsaW1pdGVyXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcImR0cm5cIlxuICAgICAgby52YWwoKVxuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9XG4gICAgICAgIHtcbiAgICAgICAgICAndHlwZSc6IFwiUmVwbGFjZU1hbmFnZXJcIlxuICAgICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICAgJ2JlZ2lubmluZycgOiBAYmVnaW5uaW5nLmdldFVpZCgpXG4gICAgICAgICAgJ2VuZCcgOiBAZW5kLmdldFVpZCgpXG4gICAgICAgIH1cbiAgICAgIGlmIEBwcmV2X2NsPyBhbmQgQG5leHRfY2w/XG4gICAgICAgIGpzb25bJ3ByZXYnXSA9IEBwcmV2X2NsLmdldFVpZCgpXG4gICAgICAgIGpzb25bJ25leHQnXSA9IEBuZXh0X2NsLmdldFVpZCgpXG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyW1wiUmVwbGFjZU1hbmFnZXJcIl0gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICAgICdiZWdpbm5pbmcnIDogYmVnaW5uaW5nXG4gICAgICAnZW5kJyA6IGVuZFxuICAgIH0gPSBqc29uXG4gICAgbmV3IFJlcGxhY2VNYW5hZ2VyIGNvbnRlbnQsIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpblxuXG5cbiAgI1xuICAjIFRoZSBSZXBsYWNlTWFuYWdlciBtYW5hZ2VzIFJlcGxhY2VhYmxlcy5cbiAgIyBAc2VlIFJlcGxhY2VNYW5hZ2VyXG4gICNcbiAgY2xhc3MgUmVwbGFjZWFibGUgZXh0ZW5kcyB0eXBlcy5JbnNlcnRcblxuICAgICNcbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBjb250ZW50IFRoZSB2YWx1ZSB0aGF0IHRoaXMgUmVwbGFjZWFibGUgaG9sZHMuXG4gICAgIyBAcGFyYW0ge1JlcGxhY2VNYW5hZ2VyfSBwYXJlbnQgVXNlZCB0byByZXBsYWNlIHRoaXMgUmVwbGFjZWFibGUgd2l0aCBhbm90aGVyIG9uZS5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6IChjb250ZW50LCBwYXJlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnY29udGVudCcsIGNvbnRlbnRcbiAgICAgIEBzYXZlT3BlcmF0aW9uICdwYXJlbnQnLCBwYXJlbnRcbiAgICAgIGlmIG5vdCAocHJldj8gYW5kIG5leHQ/IGFuZCBjb250ZW50PylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3QgZGVmaW5lIGNvbnRlbnQsIHByZXYsIGFuZCBuZXh0IGZvciBSZXBsYWNlYWJsZS10eXBlcyFcIlxuICAgICAgc3VwZXIgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICAgICNcbiAgICAjIFJldHVybiB0aGUgY29udGVudCB0aGF0IHRoaXMgb3BlcmF0aW9uIGhvbGRzLlxuICAgICNcbiAgICB2YWw6ICgpLT5cbiAgICAgIEBjb250ZW50XG5cbiAgICAjXG4gICAgIyBSZXBsYWNlIHRoZSBjb250ZW50IG9mIHRoaXMgcmVwbGFjZWFibGUgd2l0aCBuZXcgY29udGVudC5cbiAgICAjXG4gICAgcmVwbGFjZTogKGNvbnRlbnQpLT5cbiAgICAgIEBwYXJlbnQucmVwbGFjZSBjb250ZW50XG5cbiAgICAjXG4gICAgIyBJZiBwb3NzaWJsZSBzZXQgdGhlIHJlcGxhY2UgbWFuYWdlciBpbiB0aGUgY29udGVudC5cbiAgICAjIEBzZWUgV29yZC5zZXRSZXBsYWNlTWFuYWdlclxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBub3QgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICBlbHNlXG4gICAgICAgIEBjb250ZW50LnNldFJlcGxhY2VNYW5hZ2VyPyhAcGFyZW50KVxuICAgICAgICBzdXBlclxuICAgICAgICBAXG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID1cbiAgICAgICAge1xuICAgICAgICAgICd0eXBlJzogXCJSZXBsYWNlYWJsZVwiXG4gICAgICAgICAgJ2NvbnRlbnQnOiBAY29udGVudC5nZXRVaWQoKVxuICAgICAgICAgICdSZXBsYWNlTWFuYWdlcicgOiBAcGFyZW50LmdldFVpZCgpXG4gICAgICAgICAgJ3ByZXYnOiBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICAgICduZXh0JzogQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICB9XG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyW1wiUmVwbGFjZWFibGVcIl0gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICdSZXBsYWNlTWFuYWdlcicgOiBwYXJlbnRcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBSZXBsYWNlYWJsZSBjb250ZW50LCBwYXJlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cblxuXG4gIHR5cGVzWydMaXN0TWFuYWdlciddID0gTGlzdE1hbmFnZXJcbiAgdHlwZXNbJ01hcE1hbmFnZXInXSA9IE1hcE1hbmFnZXJcbiAgdHlwZXNbJ1JlcGxhY2VNYW5hZ2VyJ10gPSBSZXBsYWNlTWFuYWdlclxuICB0eXBlc1snUmVwbGFjZWFibGUnXSA9IFJlcGxhY2VhYmxlXG5cbiAgYmFzaWNfdHlwZXNcblxuXG5cblxuXG5cbiIsInN0cnVjdHVyZWRfdHlwZXNfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuL1N0cnVjdHVyZWRUeXBlc1wiXG5cbm1vZHVsZS5leHBvcnRzID0gKEhCKS0+XG4gIHN0cnVjdHVyZWRfdHlwZXMgPSBzdHJ1Y3R1cmVkX3R5cGVzX3VuaW5pdGlhbGl6ZWQgSEJcbiAgdHlwZXMgPSBzdHJ1Y3R1cmVkX3R5cGVzLnR5cGVzXG4gIHBhcnNlciA9IHN0cnVjdHVyZWRfdHlwZXMucGFyc2VyXG5cbiAgI1xuICAjIEF0IHRoZSBtb21lbnQgVGV4dERlbGV0ZSB0eXBlIGVxdWFscyB0aGUgRGVsZXRlIHR5cGUgaW4gQmFzaWNUeXBlcy5cbiAgIyBAc2VlIEJhc2ljVHlwZXMuRGVsZXRlXG4gICNcbiAgY2xhc3MgVGV4dERlbGV0ZSBleHRlbmRzIHR5cGVzLkRlbGV0ZVxuICBwYXJzZXJbXCJUZXh0RGVsZXRlXCJdID0gcGFyc2VyW1wiRGVsZXRlXCJdXG5cbiAgI1xuICAjICBFeHRlbmRzIHRoZSBiYXNpYyBJbnNlcnQgdHlwZSB0byBhbiBvcGVyYXRpb24gdGhhdCBob2xkcyBhIHRleHQgdmFsdWVcbiAgI1xuICBjbGFzcyBUZXh0SW5zZXJ0IGV4dGVuZHMgdHlwZXMuSW5zZXJ0XG4gICAgI1xuICAgICMgQHBhcmFtIHtTdHJpbmd9IGNvbnRlbnQgVGhlIGNvbnRlbnQgb2YgdGhpcyBJbnNlcnQtdHlwZSBPcGVyYXRpb24uIFVzdWFsbHkgeW91IHJlc3RyaWN0IHRoZSBsZW5ndGggb2YgY29udGVudCB0byBzaXplIDFcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6IChAY29udGVudCwgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIGlmIG5vdCAocHJldj8gYW5kIG5leHQ/KVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBkZWZpbmUgcHJldiwgYW5kIG5leHQgZm9yIFRleHRJbnNlcnQtdHlwZXMhXCJcbiAgICAgIHN1cGVyIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG4gICAgI1xuICAgICMgUmV0cmlldmUgdGhlIGVmZmVjdGl2ZSBsZW5ndGggb2YgdGhlICRjb250ZW50IG9mIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICBnZXRMZW5ndGg6ICgpLT5cbiAgICAgIGlmIEBpc0RlbGV0ZWQoKVxuICAgICAgICAwXG4gICAgICBlbHNlXG4gICAgICAgIEBjb250ZW50Lmxlbmd0aFxuXG4gICAgI1xuICAgICMgVGhlIHJlc3VsdCB3aWxsIGJlIGNvbmNhdGVuYXRlZCB3aXRoIHRoZSByZXN1bHRzIGZyb20gdGhlIG90aGVyIGluc2VydCBvcGVyYXRpb25zXG4gICAgIyBpbiBvcmRlciB0byByZXRyaWV2ZSB0aGUgY29udGVudCBvZiB0aGUgZW5naW5lLlxuICAgICMgQHNlZSBIaXN0b3J5QnVmZmVyLnRvRXhlY3V0ZWRBcnJheVxuICAgICNcbiAgICB2YWw6IChjdXJyZW50X3Bvc2l0aW9uKS0+XG4gICAgICBpZiBAaXNEZWxldGVkKClcbiAgICAgICAgXCJcIlxuICAgICAgZWxzZVxuICAgICAgICBAY29udGVudFxuXG4gICAgI1xuICAgICMgQ29udmVydCBhbGwgcmVsZXZhbnQgaW5mb3JtYXRpb24gb2YgdGhpcyBvcGVyYXRpb24gdG8gdGhlIGpzb24tZm9ybWF0LlxuICAgICMgVGhpcyByZXN1bHQgY2FuIGJlIHNlbmQgdG8gb3RoZXIgY2xpZW50cy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9XG4gICAgICAgIHtcbiAgICAgICAgICAndHlwZSc6IFwiVGV4dEluc2VydFwiXG4gICAgICAgICAgJ2NvbnRlbnQnOiBAY29udGVudFxuICAgICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICAgJ3ByZXYnOiBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICAgICduZXh0JzogQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgICAgfVxuICAgICAgaWYgQG9yaWdpbj8gYW5kIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uW1wib3JpZ2luXCJdID0gQG9yaWdpbi5nZXRVaWQoKVxuICAgICAganNvblxuXG4gIHBhcnNlcltcIlRleHRJbnNlcnRcIl0gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBUZXh0SW5zZXJ0IGNvbnRlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cbiAgI1xuICAjIEhhbmRsZXMgYSBUZXh0LWxpa2UgZGF0YSBzdHJ1Y3R1cmVzIHdpdGggc3VwcG9ydCBmb3IgaW5zZXJ0VGV4dC9kZWxldGVUZXh0IGF0IGEgd29yZC1wb3NpdGlvbi5cbiAgI1xuICBjbGFzcyBXb3JkIGV4dGVuZHMgdHlwZXMuTGlzdE1hbmFnZXJcblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIHN1cGVyIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICAgI1xuICAgICMgSW5zZXJ0cyBhIHN0cmluZyBpbnRvIHRoZSB3b3JkXG4gICAgI1xuICAgIGluc2VydFRleHQ6IChwb3NpdGlvbiwgY29udGVudCktPlxuICAgICAgbyA9IEBnZXRPcGVyYXRpb25CeVBvc2l0aW9uIHBvc2l0aW9uXG4gICAgICBmb3IgYyBpbiBjb250ZW50XG4gICAgICAgIG9wID0gbmV3IFRleHRJbnNlcnQgYywgdW5kZWZpbmVkLCBvLnByZXZfY2wsIG9cbiAgICAgICAgSEIuYWRkT3BlcmF0aW9uKG9wKS5leGVjdXRlKClcblxuICAgICNcbiAgICAjIERlbGV0ZXMgYSBwYXJ0IG9mIHRoZSB3b3JkLlxuICAgICNcbiAgICBkZWxldGVUZXh0OiAocG9zaXRpb24sIGxlbmd0aCktPlxuICAgICAgbyA9IEBnZXRPcGVyYXRpb25CeVBvc2l0aW9uIHBvc2l0aW9uXG5cbiAgICAgIGZvciBpIGluIFswLi4ubGVuZ3RoXVxuICAgICAgICBkID0gSEIuYWRkT3BlcmF0aW9uKG5ldyBUZXh0RGVsZXRlIHVuZGVmaW5lZCwgbykuZXhlY3V0ZSgpXG4gICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgd2hpbGUgby5pc0RlbGV0ZWQoKVxuICAgICAgICAgIGlmIG8gaW5zdGFuY2VvZiB0eXBlcy5EZWxpbWl0ZXJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBjYW4ndCBkZWxldGUgbW9yZSB0aGFuIHRoZXJlIGlzLi5cIlxuICAgICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgZC5fZW5jb2RlKClcblxuICAgICNcbiAgICAjIFJlcGxhY2UgdGhlIGNvbnRlbnQgb2YgdGhpcyB3b3JkIHdpdGggYW5vdGhlciBvbmUuIENvbmN1cnJlbnQgcmVwbGFjZW1lbnRzIGFyZSBub3QgbWVyZ2VkIVxuICAgICMgT25seSBvbmUgb2YgdGhlIHJlcGxhY2VtZW50cyB3aWxsIGJlIHVzZWQuXG4gICAgI1xuICAgICMgQ2FuIG9ubHkgYmUgdXNlZCBpZiB0aGUgUmVwbGFjZU1hbmFnZXIgd2FzIHNldCFcbiAgICAjIEBzZWUgV29yZC5zZXRSZXBsYWNlTWFuYWdlclxuICAgICNcbiAgICByZXBsYWNlVGV4dDogKHRleHQpLT5cbiAgICAgIGlmIEByZXBsYWNlX21hbmFnZXI/XG4gICAgICAgIHdvcmQgPSBIQi5hZGRPcGVyYXRpb24obmV3IFdvcmQgdW5kZWZpbmVkKS5leGVjdXRlKClcbiAgICAgICAgd29yZC5pbnNlcnRUZXh0IDAsIHRleHRcbiAgICAgICAgQHJlcGxhY2VfbWFuYWdlci5yZXBsYWNlKHdvcmQpXG4gICAgICBlbHNlXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcIlRoaXMgdHlwZSBpcyBjdXJyZW50bHkgbm90IG1haW50YWluZWQgYnkgYSBSZXBsYWNlTWFuYWdlciFcIlxuXG4gICAgI1xuICAgICMgQHJldHVybnMgW0pzb25dIEEgSnNvbiBvYmplY3QuXG4gICAgI1xuICAgIHZhbDogKCktPlxuICAgICAgYyA9IGZvciBvIGluIEB0b0FycmF5KClcbiAgICAgICAgaWYgby52YWw/XG4gICAgICAgICAgby52YWwoKVxuICAgICAgICBlbHNlXG4gICAgICAgICAgXCJcIlxuICAgICAgYy5qb2luKCcnKVxuXG4gICAgI1xuICAgICMgSW4gbW9zdCBjYXNlcyB5b3Ugd291bGQgZW1iZWQgYSBXb3JkIGluIGEgUmVwbGFjZWFibGUsIHdpY2ggaXMgaGFuZGxlZCBieSB0aGUgUmVwbGFjZU1hbmFnZXIgaW4gb3JkZXJcbiAgICAjIHRvIHByb3ZpZGUgcmVwbGFjZSBmdW5jdGlvbmFsaXR5LlxuICAgICNcbiAgICBzZXRSZXBsYWNlTWFuYWdlcjogKG9wKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncmVwbGFjZV9tYW5hZ2VyJywgb3BcbiAgICAgIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9uc1xuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9IHtcbiAgICAgICAgJ3R5cGUnOiBcIldvcmRcIlxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAnYmVnaW5uaW5nJyA6IEBiZWdpbm5pbmcuZ2V0VWlkKClcbiAgICAgICAgJ2VuZCcgOiBAZW5kLmdldFVpZCgpXG4gICAgICB9XG4gICAgICBpZiBAcHJldl9jbD9cbiAgICAgICAganNvblsncHJldiddID0gQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgIGlmIEBuZXh0X2NsP1xuICAgICAgICBqc29uWyduZXh0J10gPSBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgaWYgQG9yaWdpbj8gYW5kIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uW1wib3JpZ2luXCJdID0gQG9yaWdpbi5nZXRVaWQoKVxuICAgICAganNvblxuXG4gIHBhcnNlclsnV29yZCddID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ2JlZ2lubmluZycgOiBiZWdpbm5pbmdcbiAgICAgICdlbmQnIDogZW5kXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBXb3JkIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gIHR5cGVzWydUZXh0SW5zZXJ0J10gPSBUZXh0SW5zZXJ0XG4gIHR5cGVzWydUZXh0RGVsZXRlJ10gPSBUZXh0RGVsZXRlXG4gIHR5cGVzWydXb3JkJ10gPSBXb3JkXG4gIHN0cnVjdHVyZWRfdHlwZXNcblxuXG4iXX0= diff --git a/build/browser/Types/JsonTypes.min.js b/build/browser/Types/JsonTypes.min.js new file mode 100644 index 00000000..d250a09a --- /dev/null +++ b/build/browser/Types/JsonTypes.min.js @@ -0,0 +1 @@ +!function t(e,n,r){function i(u,s){if(!n[u]){if(!e[u]){var a="function"==typeof require&&require;if(!s&&a)return a(u,!0);if(o)return o(u,!0);throw new Error("Cannot find module '"+u+"'")}var p=n[u]={exports:{}};e[u][0].call(p.exports,function(t){var n=e[u][1][t];return i(n?n:t)},p,p.exports,t,e,n,r)}return n[u].exports}for(var o="function"==typeof require&&require,u=0;ur;r++)n=o[r],u.push(n.call(this,t,e));return u}},e.prototype.setParent=function(t){return this.parent=t},e.prototype.getUid=function(){return{creator:this.creator,op_number:this.op_number}},e.prototype.execute=function(){var t,e,n;for(this.is_executed=!0,e=0,n=s.length;n>e;e++)(t=s[e])(this._encode());return this},e.prototype.saveOperation=function(t,e){return null!=(null!=e?e.execute:void 0)?this[t]=e:null!=e?(null==this.unchecked&&(this.unchecked={}),this.unchecked[t]=e):void 0},e.prototype.validateSavedOperations=function(){var e,n,r,i,o,u;o={},i=this,u=this.unchecked;for(e in u)r=u[e],n=t.getOperation(r),n?this[e]=n:(o[e]=r,i=!1);return delete this.unchecked,i||(this.unchecked=o),i},e}(),e=function(t){function e(t,n){this.saveOperation("deletes",n),e.__super__.constructor.call(this,t)}return r(e,t),e.prototype._encode=function(){return{type:"Delete",uid:this.getUid(),deletes:this.deletes.getUid()}},e.prototype.execute=function(){return this.validateSavedOperations()?(this.deletes.applyDelete(this),e.__super__.execute.apply(this,arguments),this):!1},e}(u),a.Delete=function(t){var n,r;return r=t.uid,n=t.deletes,new e(r,n)},o=function(t){function e(t,n,r,i){this.saveOperation("prev_cl",n),this.saveOperation("next_cl",r),null!=i?this.saveOperation("origin",i):this.saveOperation("origin",n),e.__super__.constructor.call(this,t)}return r(e,t),e.prototype.applyDelete=function(t){return null==this.deleted_by&&(this.deleted_by=[]),this.deleted_by.push(t)},e.prototype.isDeleted=function(){var t;return(null!=(t=this.deleted_by)?t.length:void 0)>0},e.prototype.getDistanceToOrigin=function(){var t,e;for(t=0,e=this.prev_cl;;){if(this.origin===e)break;if(t++,this===this.prev_cl)throw new Error("this should not happen ;) ");e=e.prev_cl}return t},e.prototype.update_sl=function(){var t;return t=this.prev_cl,update("prev_cl","prev_sl"),update("next_cl","prev_sl")},e.prototype.execute=function(){var t,n,r,i,o;if(null!=this.is_executed)return this;if(this.validateSavedOperations()){if((null!=(i=this.prev_cl)?i.validateSavedOperations():void 0)&&(null!=(o=this.next_cl)?o.validateSavedOperations():void 0)&&this.prev_cl.next_cl!==this){for(t=0,r=this.prev_cl.next_cl,n=0;;){if(null==r&&(console.log(JSON.stringify(this.prev_cl.getUid())),console.log(JSON.stringify(this.next_cl.getUid()))),r===this.next_cl)break;if(r.getDistanceToOrigin()===n)r.creator0)for(;;){if(e=e.next_cl,e.isDeleted()||(t-=1),0===t)break;if(e instanceof c.Delimiter)throw new Error("position parameter exceeded the length of the document!")}return e},n}(c.Insert),u=function(e){function n(t,e,r,i,o,u,s){n.__super__.constructor.call(this,e,r,i,o,u,s),null!=t&&this.replace(t)}return i(n,e),n.prototype.replace=function(e){var n,r;return n=this.getLastOperation(),r=new s(e,this,void 0,n,n.next_cl),t.addOperation(r).execute()},n.prototype.val=function(){var t;if(t=this.getLastOperation(),t instanceof c.Delimiter)throw new Error("dtrn");return t.val()},n.prototype._encode=function(){var t;return t={type:"ReplaceManager",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&null!=this.next_cl&&(t.prev=this.prev_cl.getUid(),t.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},n}(r),p.ReplaceManager=function(t){var e,n,r,i,o,s,a;return n=t.content,a=t.uid,s=t.prev,i=t.next,o=t.origin,e=t.beginning,r=t.end,new u(n,a,e,r,s,i,o)},s=function(t){function e(t,n,r,i,o,u){if(this.saveOperation("content",t),this.saveOperation("parent",n),null==i||null==o||null==t)throw new Error("You must define content, prev, and next for Replaceable-types!");e.__super__.constructor.call(this,r,i,o,u)}return i(e,t),e.prototype.val=function(){return this.content},e.prototype.replace=function(t){return this.parent.replace(t)},e.prototype.execute=function(){var t;return this.validateSavedOperations()?("function"==typeof(t=this.content).setReplaceManager&&t.setReplaceManager(this.parent),e.__super__.execute.apply(this,arguments),this):!1},e.prototype._encode=function(){var t;return t={type:"Replaceable",content:this.content.getUid(),ReplaceManager:this.parent.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid(),uid:this.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},e}(c.Insert),p.Replaceable=function(t){var e,n,r,i,o,u;return e=t.content,i=t.ReplaceManager,u=t.uid,o=t.prev,n=t.next,r=t.origin,new s(e,i,u,o,n,r)},c.ListManager=r,c.MapManager=o,c.ReplaceManager=u,c.Replaceable=s,a}},{"./BasicTypes":1}],4:[function(t,e){var n,r={}.hasOwnProperty,i=function(t,e){function n(){this.constructor=t}for(var i in e)r.call(e,i)&&(t[i]=e[i]);return n.prototype=e.prototype,t.prototype=new n,t.__super__=e.prototype,t};n=t("./StructuredTypes"),e.exports=function(t){var e,r,o,u,s,a;return s=n(t),a=s.types,u=s.parser,e=function(t){function e(){return e.__super__.constructor.apply(this,arguments)}return i(e,t),e}(a.Delete),u.TextDelete=u.Delete,r=function(t){function e(t,n,r,i,o){if(this.content=t,null==r||null==i)throw new Error("You must define prev, and next for TextInsert-types!");e.__super__.constructor.call(this,n,r,i,o)}return i(e,t),e.prototype.getLength=function(){return this.isDeleted()?0:this.content.length},e.prototype.val=function(){return this.isDeleted()?"":this.content},e.prototype._encode=function(){var t;return t={type:"TextInsert",content:this.content,uid:this.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},e}(a.Insert),u.TextInsert=function(t){var e,n,i,o,u;return e=t.content,u=t.uid,o=t.prev,n=t.next,i=t.origin,new r(e,u,o,n,i)},o=function(n){function o(t,e,n,r,i,u){o.__super__.constructor.call(this,t,e,n,r,i,u)}return i(o,n),o.prototype.insertText=function(e,n){var i,o,u,s,a,p;for(o=this.getOperationByPosition(e),p=[],s=0,a=n.length;a>s;s++)i=n[s],u=new r(i,void 0,o.prev_cl,o),p.push(t.addOperation(u).execute());return p},o.prototype.deleteText=function(n,r){var i,o,u,s,p;for(u=this.getOperationByPosition(n),p=[],o=s=0;r>=0?r>s:s>r;o=r>=0?++s:--s){for(i=t.addOperation(new e(void 0,u)).execute(),u=u.next_cl;u.isDeleted();){if(u instanceof a.Delimiter)throw new Error("You can't delete more than there is..");u=u.next_cl}p.push(i._encode())}return p},o.prototype.replaceText=function(e){var n;if(null!=this.replace_manager)return n=t.addOperation(new o(void 0)).execute(),n.insertText(0,e),this.replace_manager.replace(n);throw new Error("This type is currently not maintained by a ReplaceManager!")},o.prototype.val=function(){var t,e;return t=function(){var t,n,r,i;for(r=this.toArray(),i=[],t=0,n=r.length;n>t;t++)e=r[t],i.push(null!=e.val?e.val():"");return i}.call(this),t.join("")},o.prototype.setReplaceManager=function(t){return this.saveOperation("replace_manager",t),this.validateSavedOperations},o.prototype._encode=function(){var t;return t={type:"Word",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&(t.prev=this.prev_cl.getUid()),null!=this.next_cl&&(t.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},o}(a.ListManager),u.Word=function(t){var e,n,r,i,u,s;return s=t.uid,e=t.beginning,n=t.end,u=t.prev,r=t.next,i=t.origin,new o(s,e,n,u,r,i)},a.TextInsert=r,a.TextDelete=e,a.Word=o,s}},{"./StructuredTypes":3}]},{},[2]); \ No newline at end of file diff --git a/build/browser/Types/StructuredTypes.js b/build/browser/Types/StructuredTypes.js new file mode 100644 index 00000000..ae2763ef --- /dev/null +++ b/build/browser/Types/StructuredTypes.js @@ -0,0 +1,636 @@ +(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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0; + }; + + Insert.prototype.getDistanceToOrigin = function() { + var d, o; + d = 0; + o = this.prev_cl; + while (true) { + if (this.origin === o) { + break; + } + d++; + if (this === this.prev_cl) { + throw new Error("this should not happen ;) "); + } + o = o.prev_cl; + } + return d; + }; + + Insert.prototype.update_sl = function() { + var o; + o = this.prev_cl; + ({ + update: function(dest_cl, dest_sl) { + var _results; + _results = []; + while (true) { + if (o.isDeleted()) { + _results.push(o = o[dest_cl]); + } else { + this[dest_sl] = o; + break; + } + } + return _results; + } + }); + update("prev_cl", "prev_sl"); + return update("next_cl", "prev_sl"); + }; + + Insert.prototype.execute = function() { + var distance_to_origin, i, o, _ref, _ref1; + if (this.is_executed != null) { + return this; + } + if (!this.validateSavedOperations()) { + return false; + } else { + if (((_ref = this.prev_cl) != null ? _ref.validateSavedOperations() : void 0) && ((_ref1 = this.next_cl) != null ? _ref1.validateSavedOperations() : void 0) && this.prev_cl.next_cl !== this) { + distance_to_origin = 0; + o = this.prev_cl.next_cl; + i = 0; + while (true) { + if (o == null) { + console.log(JSON.stringify(this.prev_cl.getUid())); + console.log(JSON.stringify(this.next_cl.getUid())); + } + if (o !== this.next_cl) { + if (o.getDistanceToOrigin() === i) { + if (o.creator < this.creator) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else if (o.getDistanceToOrigin() < i) { + if (i - distance_to_origin <= o.getDistanceToOrigin()) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else { + break; + } + i++; + o = o.next_cl; + } else { + break; + } + } + this.next_cl = this.prev_cl.next_cl; + this.prev_cl.next_cl = this; + this.next_cl.prev_cl = this; + } + Insert.__super__.execute.apply(this, arguments); + return this; + } + }; + + return Insert; + + })(Operation); + ImmutableObject = (function(_super) { + __extends(ImmutableObject, _super); + + function ImmutableObject(uid, content, prev, next, origin) { + this.content = content; + ImmutableObject.__super__.constructor.call(this, uid, prev, next, origin); + } + + ImmutableObject.prototype.val = function() { + return this.content; + }; + + ImmutableObject.prototype._encode = function() { + var json; + json = { + 'type': "ImmutableObject", + 'uid': this.getUid(), + 'content': this.content + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ImmutableObject; + + })(Insert); + parser['ImmutableObject'] = function(json) { + var content, next, origin, prev, uid; + uid = json['uid'], content = json['content'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new ImmutableObject(uid, content, prev, next, origin); + }; + Delimiter = (function(_super) { + __extends(Delimiter, _super); + + function Delimiter(uid, prev_cl, next_cl, origin) { + this.saveOperation('prev_cl', prev_cl); + this.saveOperation('next_cl', next_cl); + this.saveOperation('origin', prev_cl); + Delimiter.__super__.constructor.call(this, uid); + } + + Delimiter.prototype.isDeleted = function() { + return false; + }; + + Delimiter.prototype.execute = function() { + var _ref, _ref1; + if (((_ref = this.unchecked) != null ? _ref['next_cl'] : void 0) != null) { + return Delimiter.__super__.execute.apply(this, arguments); + } else if ((_ref1 = this.unchecked) != null ? _ref1['prev_cl'] : void 0) { + if (this.validateSavedOperations()) { + if (this.prev_cl.next_cl != null) { + throw new Error("Probably duplicated operations"); + } + this.prev_cl.next_cl = this; + delete this.prev_cl.unchecked.next_cl; + return Delimiter.__super__.execute.apply(this, arguments); + } else { + return false; + } + } else if ((this.prev_cl != null) && (this.prev_cl.next_cl == null)) { + delete this.prev_cl.unchecked.next_cl; + return this.prev_cl.next_cl = this; + } else if ((this.prev_cl != null) || (this.next_cl != null)) { + return Delimiter.__super__.execute.apply(this, arguments); + } else { + throw new Error("Delimiter is unsufficient defined!"); + } + }; + + Delimiter.prototype._encode = function() { + var _ref, _ref1; + return { + 'type': "Delimiter", + 'uid': this.getUid(), + 'prev': (_ref = this.prev_cl) != null ? _ref.getUid() : void 0, + 'next': (_ref1 = this.next_cl) != null ? _ref1.getUid() : void 0 + }; + }; + + return Delimiter; + + })(Operation); + parser['Delimiter'] = function(json) { + var next, prev, uid; + uid = json['uid'], prev = json['prev'], next = json['next']; + return new Delimiter(uid, prev, next); + }; + return { + 'types': { + 'Delete': Delete, + 'Insert': Insert, + 'Delimiter': Delimiter, + 'Operation': Operation, + 'ImmutableObject': ImmutableObject + }, + 'parser': parser, + 'execution_listener': execution_listener + }; +}; + + +},{}],2:[function(require,module,exports){ +var basic_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +basic_types_uninitialized = require("./BasicTypes"); + +module.exports = function(HB) { + var AddName, ListManager, MapManager, ReplaceManager, Replaceable, basic_types, parser, types; + basic_types = basic_types_uninitialized(HB); + types = basic_types.types; + parser = basic_types.parser; + MapManager = (function(_super) { + __extends(MapManager, _super); + + function MapManager(uid) { + this.map = {}; + MapManager.__super__.constructor.call(this, uid); + } + + MapManager.prototype.val = function(name, content) { + var o, obj, result, _ref, _ref1; + if (content != null) { + if (this.map[name] == null) { + HB.addOperation(new AddName(void 0, this, name)).execute(); + } + this.map[name].replace(content); + return this; + } else if (name != null) { + obj = (_ref = this.map[name]) != null ? _ref.val() : void 0; + if (obj instanceof types.ImmutableObject) { + return obj.val(); + } else { + return obj; + } + } else { + result = {}; + _ref1 = this.map; + for (name in _ref1) { + o = _ref1[name]; + obj = o.val(); + if (obj instanceof types.ImmutableObject || obj instanceof MapManager) { + obj = obj.val(); + } + result[name] = obj; + } + return result; + } + }; + + return MapManager; + + })(types.Operation); + AddName = (function(_super) { + __extends(AddName, _super); + + function AddName(uid, map_manager, name) { + this.name = name; + this.saveOperation('map_manager', map_manager); + AddName.__super__.constructor.call(this, uid); + } + + AddName.prototype.execute = function() { + var beg, end, uid_beg, uid_end, uid_r; + if (!this.validateSavedOperations()) { + return false; + } else { + uid_r = this.map_manager.getUid(); + uid_r.op_number = "_" + uid_r.op_number + "_RM_" + this.name; + if (HB.getOperation(uid_r) == null) { + uid_beg = this.map_manager.getUid(); + uid_beg.op_number = "_" + uid_beg.op_number + "_RM_" + this.name + "_beginning"; + uid_end = this.map_manager.getUid(); + uid_end.op_number = "_" + uid_end.op_number + "_RM_" + this.name + "_end"; + beg = HB.addOperation(new types.Delimiter(uid_beg, void 0, uid_end)).execute(); + end = HB.addOperation(new types.Delimiter(uid_end, beg, void 0)).execute(); + this.map_manager.map[this.name] = HB.addOperation(new ReplaceManager(void 0, uid_r, beg, end)).execute(); + } + return AddName.__super__.execute.apply(this, arguments); + } + }; + + AddName.prototype._encode = function() { + return { + 'type': "AddName", + 'uid': this.getUid(), + 'map_manager': this.map_manager.getUid(), + 'name': this.name + }; + }; + + return AddName; + + })(types.Operation); + parser['AddName'] = function(json) { + var map_manager, name, uid; + map_manager = json['map_manager'], uid = json['uid'], name = json['name']; + return new AddName(uid, map_manager, name); + }; + ListManager = (function(_super) { + __extends(ListManager, _super); + + function ListManager(uid, beginning, end, prev, next, origin) { + if ((beginning != null) && (end != null)) { + this.saveOperation('beginning', beginning); + this.saveOperation('end', end); + } else { + this.beginning = HB.addOperation(new types.Delimiter(void 0, void 0, void 0)); + this.end = HB.addOperation(new types.Delimiter(void 0, this.beginning, void 0)); + this.beginning.next_cl = this.end; + this.beginning.execute(); + this.end.execute(); + } + ListManager.__super__.constructor.call(this, uid, prev, next, origin); + } + + ListManager.prototype.getLastOperation = function() { + return this.end.prev_cl; + }; + + ListManager.prototype.getFirstOperation = function() { + return this.beginning.next_cl; + }; + + ListManager.prototype.toArray = function() { + var o, result; + o = this.beginning.next_cl; + result = []; + while (o !== this.end) { + result.push(o); + o = o.next_cl; + } + return result; + }; + + ListManager.prototype.getOperationByPosition = function(position) { + var o; + o = this.beginning.next_cl; + if (position > 0) { + while (true) { + o = o.next_cl; + if (!o.isDeleted()) { + position -= 1; + } + if (position === 0) { + break; + } + if (o instanceof types.Delimiter) { + throw new Error("position parameter exceeded the length of the document!"); + } + } + } + return o; + }; + + return ListManager; + + })(types.Insert); + ReplaceManager = (function(_super) { + __extends(ReplaceManager, _super); + + function ReplaceManager(initial_content, uid, beginning, end, prev, next, origin) { + ReplaceManager.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + if (initial_content != null) { + this.replace(initial_content); + } + } + + ReplaceManager.prototype.replace = function(content) { + var o, op; + o = this.getLastOperation(); + op = new Replaceable(content, this, void 0, o, o.next_cl); + return HB.addOperation(op).execute(); + }; + + ReplaceManager.prototype.val = function() { + var o; + o = this.getLastOperation(); + if (o instanceof types.Delimiter) { + throw new Error("dtrn"); + } + return o.val(); + }; + + ReplaceManager.prototype._encode = function() { + var json; + json = { + 'type': "ReplaceManager", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if ((this.prev_cl != null) && (this.next_cl != null)) { + json['prev'] = this.prev_cl.getUid(); + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ReplaceManager; + + })(ListManager); + parser["ReplaceManager"] = function(json) { + var beginning, content, end, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], beginning = json['beginning'], end = json['end']; + return new ReplaceManager(content, uid, beginning, end, prev, next, origin); + }; + Replaceable = (function(_super) { + __extends(Replaceable, _super); + + function Replaceable(content, parent, uid, prev, next, origin) { + this.saveOperation('content', content); + this.saveOperation('parent', parent); + if (!((prev != null) && (next != null) && (content != null))) { + throw new Error("You must define content, prev, and next for Replaceable-types!"); + } + Replaceable.__super__.constructor.call(this, uid, prev, next, origin); + } + + Replaceable.prototype.val = function() { + return this.content; + }; + + Replaceable.prototype.replace = function(content) { + return this.parent.replace(content); + }; + + Replaceable.prototype.execute = function() { + var _base; + if (!this.validateSavedOperations()) { + return false; + } else { + if (typeof (_base = this.content).setReplaceManager === "function") { + _base.setReplaceManager(this.parent); + } + Replaceable.__super__.execute.apply(this, arguments); + return this; + } + }; + + Replaceable.prototype._encode = function() { + var json; + json = { + 'type': "Replaceable", + 'content': this.content.getUid(), + 'ReplaceManager': this.parent.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid(), + 'uid': this.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Replaceable; + + })(types.Insert); + parser["Replaceable"] = function(json) { + var content, next, origin, parent, prev, uid; + content = json['content'], parent = json['ReplaceManager'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Replaceable(content, parent, uid, prev, next, origin); + }; + types['ListManager'] = ListManager; + types['MapManager'] = MapManager; + types['ReplaceManager'] = ReplaceManager; + types['Replaceable'] = Replaceable; + return basic_types; +}; + + +},{"./BasicTypes":1}]},{},[2]) +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL1R5cGVzL0Jhc2ljVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9TdHJ1Y3R1cmVkVHlwZXMuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUEsSUFBQTtpU0FBQTs7QUFBQSxNQUFNLENBQUMsT0FBUCxHQUFpQixTQUFDLEVBQUQsR0FBQTtBQUVmLE1BQUEsaUZBQUE7QUFBQSxFQUFBLE1BQUEsR0FBUyxFQUFULENBQUE7QUFBQSxFQUNBLGtCQUFBLEdBQXFCLEVBRHJCLENBQUE7QUFBQSxFQWFNO0FBTVMsSUFBQSxtQkFBQyxHQUFELEdBQUE7QUFDWCxNQUFBLElBQU8sV0FBUDtBQUNFLFFBQUEsR0FBQSxHQUFNLEVBQUUsQ0FBQywwQkFBSCxDQUFBLENBQU4sQ0FERjtPQUFBO0FBQUEsTUFHYSxJQUFDLENBQUEsY0FBWixVQURGLEVBRWdCLElBQUMsQ0FBQSxnQkFBZixZQUpGLENBRFc7SUFBQSxDQUFiOztBQUFBLHdCQWFBLEVBQUEsR0FBSSxTQUFDLEtBQUQsRUFBUSxDQUFSLEdBQUE7QUFDRixVQUFBLEtBQUE7O1FBQUEsSUFBQyxDQUFBLGtCQUFtQjtPQUFwQjs7YUFDaUIsQ0FBQSxLQUFBLElBQVU7T0FEM0I7YUFFQSxJQUFDLENBQUEsZUFBZ0IsQ0FBQSxLQUFBLENBQU0sQ0FBQyxJQUF4QixDQUE2QixDQUE3QixFQUhFO0lBQUEsQ0FiSixDQUFBOztBQUFBLHdCQXNCQSxTQUFBLEdBQVcsU0FBQyxLQUFELEVBQVEsSUFBUixHQUFBO0FBQ1QsVUFBQSwyQkFBQTtBQUFBLE1BQUEsSUFBRyxtQ0FBSDtB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InNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3Rocm93IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIil9dmFyIGY9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGYuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sZixmLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIm1vZHVsZS5leHBvcnRzID0gKEhCKS0+XG4gICMgQHNlZSBFbmdpbmUucGFyc2VcbiAgcGFyc2VyID0ge31cbiAgZXhlY3V0aW9uX2xpc3RlbmVyID0gW11cblxuICAjXG4gICMgQSBnZW5lcmljIGludGVyZmFjZSB0byBvcGVyYXRpb25zLlxuICAjXG4gICMgQW4gb3BlcmF0aW9uIGhhcyB0aGUgZm9sbG93aW5nIG1ldGhvZHM6XG4gICMgX2VuY29kZTogZW5jb2RlcyBhbiBvcGVyYXRpb24gKG5lZWRlZCBvbmx5IGlmIGluc3RhbmNlIG9mIHRoaXMgb3BlcmF0aW9uIGlzIHNlbnQpLlxuICAjIGV4ZWN1dGU6IGV4ZWN1dGUgdGhlIGVmZmVjdHMgb2YgdGhpcyBvcGVyYXRpb25zLiBHb29kIGV4YW1wbGVzIGFyZSBJbnNlcnQtdHlwZSBhbmQgQWRkTmFtZS10eXBlXG4gICMgdmFsOiBpbiB0aGUgY2FzZSB0aGF0IHRoZSBvcGVyYXRpb24gaG9sZHMgYSB2YWx1ZVxuICAjXG4gICMgRnVydGhlcm1vcmUgYW4gZW5jb2RhYmxlIG9wZXJhdGlvbiBoYXMgYSBwYXJzZXIuXG4gICNcbiAgY2xhc3MgT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAc2VlIEhpc3RvcnlCdWZmZXIuZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXJcbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQpLT5cbiAgICAgIGlmIG5vdCB1aWQ/XG4gICAgICAgIHVpZCA9IEhCLmdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyKClcbiAgICAgIHtcbiAgICAgICAgJ2NyZWF0b3InOiBAY3JlYXRvclxuICAgICAgICAnb3BfbnVtYmVyJyA6IEBvcF9udW1iZXJcbiAgICAgIH0gPSB1aWRcblxuICAgICNcbiAgICAjIEFkZCBhbiBldmVudCBsaXN0ZW5lci4gSXQgZGVwZW5kcyBvbiB0aGUgb3BlcmF0aW9uIHdoaWNoIGV2ZW50cyBhcmUgc3VwcG9ydGVkLlxuICAgICMgQHBhcmFtIHtTdHJpbmd9IGV2ZW50IE5hbWUgb2YgdGhlIGV2ZW50LlxuICAgICMgQHBhcmFtIHtGdW5jdGlvbn0gZiBmIGlzIGV4ZWN1dGVkIGluIGNhc2UgdGhlIGV2ZW50IGZpcmVzLlxuICAgICNcbiAgICBvbjogKGV2ZW50LCBmKS0+XG4gICAgICBAZXZlbnRfbGlzdGVuZXJzID89IHt9XG4gICAgICBAZXZlbnRfbGlzdGVuZXJzW2V2ZW50XSA/PSBbXVxuICAgICAgQGV2ZW50X2xpc3RlbmVyc1tldmVudF0ucHVzaCBmXG5cbiAgICAjXG4gICAgIyBGaXJlIGFuIGV2ZW50LlxuICAgICMgVE9ETzogRG8gc29tZXRoaW5nIHdpdGggdGltZW91dHMuIFlvdSBkb24ndCB3YW50IHRoaXMgdG8gZmlyZSBmb3IgZXZlcnkgb3BlcmF0aW9uIChlLmcuIGluc2VydCkuXG4gICAgI1xuICAgIGNhbGxFdmVudDogKGV2ZW50LCBhcmdzKS0+XG4gICAgICBpZiBAZXZlbnRfbGlzdGVuZXJzW2V2ZW50XT9cbiAgICAgICAgZm9yIGYgaW4gQGV2ZW50X2xpc3RlbmVyc1tldmVudF1cbiAgICAgICAgICBmLmNhbGwgQCwgZXZlbnQsIGFyZ3NcblxuICAgICNcbiAgICAjIFNldCB0aGUgcGFyZW50IG9mIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICBzZXRQYXJlbnQ6IChvKS0+XG4gICAgICBAcGFyZW50ID0gb1xuXG4gICAgI1xuICAgICMgQ29tcHV0ZXMgYSB1bmlxdWUgaWRlbnRpZmllciAodWlkKSB0aGF0IGlkZW50aWZpZXMgdGhpcyBvcGVyYXRpb24uXG4gICAgI1xuICAgIGdldFVpZDogKCktPlxuICAgICAgeyAnY3JlYXRvcic6IEBjcmVhdG9yLCAnb3BfbnVtYmVyJzogQG9wX251bWJlciB9XG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgTm90aWZ5IHRoZSBhbGwgdGhlIGxpc3RlbmVycy5cbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgQGlzX2V4ZWN1dGVkID0gdHJ1ZVxuICAgICAgZm9yIGwgaW4gZXhlY3V0aW9uX2xpc3RlbmVyXG4gICAgICAgIGwgQF9lbmNvZGUoKVxuICAgICAgQFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIE9wZXJhdGlvbnMgbWF5IGRlcGVuZCBvbiBvdGhlciBvcGVyYXRpb25zIChsaW5rZWQgbGlzdHMsIGV0Yy4pLlxuICAgICMgVGhlIHNhdmVPcGVyYXRpb24gYW5kIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zIG1ldGhvZHMgcHJvdmlkZVxuICAgICMgYW4gZWFzeSB3YXkgdG8gcmVmZXIgdG8gdGhlc2Ugb3BlcmF0aW9ucyB2aWEgYW4gdWlkIG9yIG9iamVjdCByZWZlcmVuY2UuXG4gICAgI1xuICAgICMgRm9yIGV4YW1wbGU6IFdlIGNhbiBjcmVhdGUgYSBuZXcgRGVsZXRlIG9wZXJhdGlvbiB0aGF0IGRlbGV0ZXMgdGhlIG9wZXJhdGlvbiAkbyBsaWtlIHRoaXNcbiAgICAjICAgICAtIHZhciBkID0gbmV3IERlbGV0ZSh1aWQsICRvKTsgICBvclxuICAgICMgICAgIC0gdmFyIGQgPSBuZXcgRGVsZXRlKHVpZCwgJG8uZ2V0VWlkKCkpO1xuICAgICMgRWl0aGVyIHdheSB3ZSB3YW50IHRvIGFjY2VzcyAkbyB2aWEgZC5kZWxldGVzLiBJbiB0aGUgc2Vjb25kIGNhc2UgdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMgbXVzdCBiZSBjYWxsZWQgZmlyc3QuXG4gICAgI1xuICAgICMgQG92ZXJsb2FkIHNhdmVPcGVyYXRpb24obmFtZSwgb3BfdWlkKVxuICAgICMgICBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgb3BlcmF0aW9uLiBBZnRlciB2YWxpZGF0aW5nICh3aXRoIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKSB0aGUgaW5zdGFudGlhdGVkIG9wZXJhdGlvbiB3aWxsIGJlIGFjY2Vzc2libGUgdmlhIHRoaXNbbmFtZV0uXG4gICAgIyAgIEBwYXJhbSB7T2JqZWN0fSBvcF91aWQgQSB1aWQgdGhhdCByZWZlcnMgdG8gYW4gb3BlcmF0aW9uXG4gICAgIyBAb3ZlcmxvYWQgc2F2ZU9wZXJhdGlvbihuYW1lLCBvcClcbiAgICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGlvbi4gQWZ0ZXIgY2FsbGluZyB0aGlzIGZ1bmN0aW9uIG9wIGlzIGFjY2Vzc2libGUgdmlhIHRoaXNbbmFtZV0uXG4gICAgIyAgIEBwYXJhbSB7T3BlcmF0aW9ufSBvcCBBbiBPcGVyYXRpb24gb2JqZWN0XG4gICAgI1xuICAgIHNhdmVPcGVyYXRpb246IChuYW1lLCBvcCktPlxuXG4gICAgICAjXG4gICAgICAjIEV2ZXJ5IGluc3RhbmNlIG9mICRPcGVyYXRpb24gbXVzdCBoYXZlIGFuICRleGVjdXRlIGZ1bmN0aW9uLlxuICAgICAgIyBXZSB1c2UgZHVjay10eXBpbmcgdG8gY2hlY2sgaWYgb3AgaXMgaW5zdGFudGlhdGVkIHNpbmNlIHRoZXJlXG4gICAgICAjIGNvdWxkIGV4aXN0IG11bHRpcGxlIGNsYXNzZXMgb2YgJE9wZXJhdGlvblxuICAgICAgI1xuICAgICAgaWYgb3A/LmV4ZWN1dGU/XG4gICAgICAgICMgaXMgaW5zdGFudGlhdGVkXG4gICAgICAgIEBbbmFtZV0gPSBvcFxuICAgICAgZWxzZSBpZiBvcD9cbiAgICAgICAgIyBub3QgaW5pdGlhbGl6ZWQuIERvIGl0IHdoZW4gY2FsbGluZyAkdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICBAdW5jaGVja2VkID89IHt9XG4gICAgICAgIEB1bmNoZWNrZWRbbmFtZV0gPSBvcFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIEFmdGVyIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiBhbGwgbm90IGluc3RhbnRpYXRlZCBvcGVyYXRpb25zIHdpbGwgYmUgYWNjZXNzaWJsZS5cbiAgICAjIEBzZWUgT3BlcmF0aW9uLnNhdmVPcGVyYXRpb25cbiAgICAjXG4gICAgIyBAcmV0dXJuIFtCb29sZWFuXSBXaGV0aGVyIGl0IHdhcyBwb3NzaWJsZSB0byBpbnN0YW50aWF0ZSBhbGwgb3BlcmF0aW9ucy5cbiAgICAjXG4gICAgdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnM6ICgpLT5cbiAgICAgIHVuaW5zdGFudGlhdGVkID0ge31cbiAgICAgIHN1Y2Nlc3MgPSBAXG4gICAgICBmb3IgbmFtZSwgb3BfdWlkIG9mIEB1bmNoZWNrZWRcbiAgICAgICAgb3AgPSBIQi5nZXRPcGVyYXRpb24gb3BfdWlkXG4gICAgICAgIGlmIG9wXG4gICAgICAgICAgQFtuYW1lXSA9IG9wXG4gICAgICAgIGVsc2VcbiAgICAgICAgICB1bmluc3RhbnRpYXRlZFtuYW1lXSA9IG9wX3VpZFxuICAgICAgICAgIHN1Y2Nlc3MgPSBmYWxzZVxuICAgICAgZGVsZXRlIEB1bmNoZWNrZWRcbiAgICAgIGlmIG5vdCBzdWNjZXNzXG4gICAgICAgIEB1bmNoZWNrZWQgPSB1bmluc3RhbnRpYXRlZFxuICAgICAgc3VjY2Vzc1xuXG5cblxuICAjXG4gICMgQSBzaW1wbGUgRGVsZXRlLXR5cGUgb3BlcmF0aW9uIHRoYXQgZGVsZXRlcyBhbiBJbnNlcnQtdHlwZSBvcGVyYXRpb24uXG4gICNcbiAgY2xhc3MgRGVsZXRlIGV4dGVuZHMgT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gZGVsZXRlcyBVSUQgb3IgcmVmZXJlbmNlIG9mIHRoZSBvcGVyYXRpb24gdGhhdCB0aGlzIHRvIGJlIGRlbGV0ZWQuXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBkZWxldGVzKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnZGVsZXRlcycsIGRlbGV0ZXNcbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIENvbnZlcnQgYWxsIHJlbGV2YW50IGluZm9ybWF0aW9uIG9mIHRoaXMgb3BlcmF0aW9uIHRvIHRoZSBqc29uLWZvcm1hdC5cbiAgICAjIFRoaXMgcmVzdWx0IGNhbiBiZSBzZW50IHRvIG90aGVyIGNsaWVudHMuXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIHtcbiAgICAgICAgJ3R5cGUnOiBcIkRlbGV0ZVwiXG4gICAgICAgICd1aWQnOiBAZ2V0VWlkKClcbiAgICAgICAgJ2RlbGV0ZXMnOiBAZGVsZXRlcy5nZXRVaWQoKVxuICAgICAgfVxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIEFwcGx5IHRoZSBkZWxldGlvbi5cbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgQGRlbGV0ZXMuYXBwbHlEZWxldGUgQFxuICAgICAgICBzdXBlclxuICAgICAgICBAXG4gICAgICBlbHNlXG4gICAgICAgIGZhbHNlXG5cbiAgI1xuICAjIERlZmluZSBob3cgdG8gcGFyc2UgRGVsZXRlIG9wZXJhdGlvbnMuXG4gICNcbiAgcGFyc2VyWydEZWxldGUnXSA9IChvKS0+XG4gICAge1xuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdkZWxldGVzJzogZGVsZXRlc191aWRcbiAgICB9ID0gb1xuICAgIG5ldyBEZWxldGUgdWlkLCBkZWxldGVzX3VpZFxuXG4gICNcbiAgIyBBIHNpbXBsZSBpbnNlcnQtdHlwZSBvcGVyYXRpb24uXG4gICNcbiAgIyBBbiBpbnNlcnQgb3BlcmF0aW9uIGlzIGFsd2F5cyBwb3NpdGlvbmVkIGJldHdlZW4gdHdvIG90aGVyIGluc2VydCBvcGVyYXRpb25zLlxuICAjIEludGVybmFsbHkgdGhpcyBpcyByZWFsaXplZCBhcyBhc3NvY2lhdGl2ZSBsaXN0cywgd2hlcmVieSBlYWNoIGluc2VydCBvcGVyYXRpb24gaGFzIGEgcHJlZGVjZXNzb3IgYW5kIGEgc3VjY2Vzc29yLlxuICAjIEZvciB0aGUgc2FrZSBvZiBlZmZpY2llbmN5IHdlIG1haW50YWluIHR3byBsaXN0czpcbiAgIyAgIC0gVGhlIHNob3J0LWxpc3QgKGFiYnJldi4gc2wpIG1haW50YWlucyBvbmx5IHRoZSBvcGVyYXRpb25zIHRoYXQgYXJlIG5vdCBkZWxldGVkXG4gICMgICAtIFRoZSBjb21wbGV0ZS1saXN0IChhYmJyZXYuIGNsKSBtYWludGFpbnMgYWxsIG9wZXJhdGlvbnNcbiAgI1xuICBjbGFzcyBJbnNlcnQgZXh0ZW5kcyBPcGVyYXRpb25cblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBwcmV2X2NsIFRoZSBwcmVkZWNlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gbmV4dF9jbCBUaGUgc3VjY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcbiAgICAjXG4gICAgIyBAc2VlIEhpc3RvcnlCdWZmZXIuZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXJcbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIHByZXZfY2wsIG5leHRfY2wsIG9yaWdpbiktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ3ByZXZfY2wnLCBwcmV2X2NsXG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnbmV4dF9jbCcsIG5leHRfY2xcbiAgICAgIGlmIG9yaWdpbj9cbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ29yaWdpbicsIG9yaWdpblxuICAgICAgZWxzZVxuICAgICAgICBAc2F2ZU9wZXJhdGlvbiAnb3JpZ2luJywgcHJldl9jbFxuICAgICAgc3VwZXIgdWlkXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICNcbiAgICBhcHBseURlbGV0ZTogKG8pLT5cbiAgICAgIEBkZWxldGVkX2J5ID89IFtdXG4gICAgICBAZGVsZXRlZF9ieS5wdXNoIG9cblxuICAgICNcbiAgICAjIElmIGlzRGVsZXRlZCgpIGlzIHRydWUgdGhpcyBvcGVyYXRpb24gd29uJ3QgYmUgbWFpbnRhaW5lZCBpbiB0aGUgc2xcbiAgICAjXG4gICAgaXNEZWxldGVkOiAoKS0+XG4gICAgICBAZGVsZXRlZF9ieT8ubGVuZ3RoID4gMFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIFRoZSBhbW91bnQgb2YgcG9zaXRpb25zIHRoYXQgJHRoaXMgb3BlcmF0aW9uIHdhcyBtb3ZlZCB0byB0aGUgcmlnaHQuXG4gICAgI1xuICAgIGdldERpc3RhbmNlVG9PcmlnaW46ICgpLT5cbiAgICAgIGQgPSAwXG4gICAgICBvID0gQHByZXZfY2xcbiAgICAgIHdoaWxlIHRydWVcbiAgICAgICAgaWYgQG9yaWdpbiBpcyBvXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgZCsrXG4gICAgICAgICNUT0RPOiBkZWxldGUgdGhpc1xuICAgICAgICBpZiBAIGlzIEBwcmV2X2NsXG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwidGhpcyBzaG91bGQgbm90IGhhcHBlbiA7KSBcIlxuICAgICAgICBvID0gby5wcmV2X2NsXG4gICAgICBkXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgVXBkYXRlIHRoZSBzaG9ydCBsaXN0XG4gICAgIyBUT0RPIChVbnVzZWQpXG4gICAgdXBkYXRlX3NsOiAoKS0+XG4gICAgICBvID0gQHByZXZfY2xcbiAgICAgIHVwZGF0ZTogKGRlc3RfY2wsZGVzdF9zbCktPlxuICAgICAgICB3aGlsZSB0cnVlXG4gICAgICAgICAgaWYgby5pc0RlbGV0ZWQoKVxuICAgICAgICAgICAgbyA9IG9bZGVzdF9jbF1cbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBAW2Rlc3Rfc2xdID0gb1xuXG4gICAgICAgICAgICBicmVha1xuICAgICAgdXBkYXRlIFwicHJldl9jbFwiLCBcInByZXZfc2xcIlxuICAgICAgdXBkYXRlIFwibmV4dF9jbFwiLCBcInByZXZfc2xcIlxuXG5cblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBJbmNsdWRlIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBhc3NvY2lhdGl2ZSBsaXN0cy5cbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgQGlzX2V4ZWN1dGVkP1xuICAgICAgICByZXR1cm4gQFxuICAgICAgaWYgbm90IEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgZWxzZVxuICAgICAgICBpZiBAcHJldl9jbD8udmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKSBhbmQgQG5leHRfY2w/LnZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKCkgYW5kIEBwcmV2X2NsLm5leHRfY2wgaXNudCBAXG4gICAgICAgICAgZGlzdGFuY2VfdG9fb3JpZ2luID0gMFxuICAgICAgICAgIG8gPSBAcHJldl9jbC5uZXh0X2NsXG4gICAgICAgICAgaSA9IDBcbiAgICAgICAgICAjICR0aGlzIGhhcyB0byBmaW5kIGEgdW5pcXVlIHBvc2l0aW9uIGJldHdlZW4gb3JpZ2luIGFuZCB0aGUgbmV4dCBrbm93biBjaGFyYWN0ZXJcbiAgICAgICAgICAjIGNhc2UgMTogJG9yaWdpbiBlcXVhbHMgJG8ub3JpZ2luOiB0aGUgJGNyZWF0b3IgcGFyYW1ldGVyIGRlY2lkZXMgaWYgbGVmdCBvciByaWdodFxuICAgICAgICAgICMgICAgICAgICBsZXQgJE9MPSBbbzEsbzIsbzMsbzRdLCB3aGVyZWJ5ICR0aGlzIGlzIHRvIGJlIGluc2VydGVkIGJldHdlZW4gbzEgYW5kIG80XG4gICAgICAgICAgIyAgICAgICAgIG8yLG8zIGFuZCBvNCBvcmlnaW4gaXMgMSAodGhlIHBvc2l0aW9uIG9mIG8yKVxuICAgICAgICAgICMgICAgICAgICB0aGVyZSBpcyB0aGUgY2FzZSB0aGF0ICR0aGlzLmNyZWF0b3IgPCBvMi5jcmVhdG9yLCBidXQgbzMuY3JlYXRvciA8ICR0aGlzLmNyZWF0b3JcbiAgICAgICAgICAjICAgICAgICAgdGhlbiBvMiBrbm93cyBvMy4gU2luY2Ugb24gYW5vdGhlciBjbGllbnQgJE9MIGNvdWxkIGJlIFtvMSxvMyxvNF0gdGhlIHByb2JsZW0gaXMgY29tcGxleFxuICAgICAgICAgICMgICAgICAgICB0aGVyZWZvcmUgJHRoaXMgd291bGQgYmUgYWx3YXlzIHRvIHRoZSByaWdodCBvZiBvM1xuICAgICAgICAgICMgY2FzZSAyOiAkb3JpZ2luIDwgJG8ub3JpZ2luXG4gICAgICAgICAgIyAgICAgICAgIGlmIGN1cnJlbnQgJHRoaXMgaW5zZXJ0X3Bvc2l0aW9uID4gJG8gb3JpZ2luOiAkdGhpcyBpbnNcbiAgICAgICAgICAjICAgICAgICAgZWxzZSAkaW5zZXJ0X3Bvc2l0aW9uIHdpbGwgbm90IGNoYW5nZSAobWF5YmUgd2UgZW5jb3VudGVyIGNhc2UgMSBsYXRlciwgdGhlbiB0aGlzIHdpbGwgYmUgdG8gdGhlIHJpZ2h0IG9mICRvKVxuICAgICAgICAgICMgY2FzZSAzOiAkb3JpZ2luID4gJG8ub3JpZ2luXG4gICAgICAgICAgIyAgICAgICAgICR0aGlzIGluc2VydF9wb3NpdGlvbiBpcyB0byB0aGUgbGVmdCBvZiAkbyAoZm9yZXZlciEpXG4gICAgICAgICAgd2hpbGUgdHJ1ZVxuICAgICAgICAgICAgaWYgbm90IG8/XG4gICAgICAgICAgICAgICMgVE9ETzogRGVidWdnaW5nXG4gICAgICAgICAgICAgIGNvbnNvbGUubG9nIEpTT04uc3RyaW5naWZ5IEBwcmV2X2NsLmdldFVpZCgpXG4gICAgICAgICAgICAgIGNvbnNvbGUubG9nIEpTT04uc3RyaW5naWZ5IEBuZXh0X2NsLmdldFVpZCgpXG4gICAgICAgICAgICBpZiBvIGlzbnQgQG5leHRfY2xcbiAgICAgICAgICAgICAgIyAkbyBoYXBwZW5lZCBjb25jdXJyZW50bHlcbiAgICAgICAgICAgICAgaWYgby5nZXREaXN0YW5jZVRvT3JpZ2luKCkgaXMgaVxuICAgICAgICAgICAgICAgICMgY2FzZSAxXG4gICAgICAgICAgICAgICAgaWYgby5jcmVhdG9yIDwgQGNyZWF0b3JcbiAgICAgICAgICAgICAgICAgIEBwcmV2X2NsID0gb1xuICAgICAgICAgICAgICAgICAgZGlzdGFuY2VfdG9fb3JpZ2luID0gaSArIDFcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAjIG5vcFxuICAgICAgICAgICAgICBlbHNlIGlmIG8uZ2V0RGlzdGFuY2VUb09yaWdpbigpIDwgaVxuICAgICAgICAgICAgICAgICMgY2FzZSAyXG4gICAgICAgICAgICAgICAgaWYgaSAtIGRpc3RhbmNlX3RvX29yaWdpbiA8PSBvLmdldERpc3RhbmNlVG9PcmlnaW4oKVxuICAgICAgICAgICAgICAgICAgQHByZXZfY2wgPSBvXG4gICAgICAgICAgICAgICAgICBkaXN0YW5jZV90b19vcmlnaW4gPSBpICsgMVxuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICNub3BcbiAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICMgY2FzZSAzXG4gICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgaSsrXG4gICAgICAgICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgIyAkdGhpcyBrbm93cyB0aGF0ICRvIGV4aXN0cyxcbiAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAjIG5vdyByZWNvbm5lY3QgZXZlcnl0aGluZ1xuICAgICAgICAgIEBuZXh0X2NsID0gQHByZXZfY2wubmV4dF9jbFxuICAgICAgICAgIEBwcmV2X2NsLm5leHRfY2wgPSBAXG4gICAgICAgICAgQG5leHRfY2wucHJldl9jbCA9IEBcbiAgICAgICAgc3VwZXIgIyBub3RpZnkgdGhlIGV4ZWN1dGlvbl9saXN0ZW5lcnNcbiAgICAgICAgQFxuXG4gICNcbiAgIyBEZWZpbmVzIGFuIG9iamVjdCB0aGF0IGlzIGNhbm5vdCBiZSBjaGFuZ2VkLiBZb3UgY2FuIHVzZSB0aGlzIHRvIHNldCBhbiBpbW11dGFibGUgc3RyaW5nLCBvciBhIG51bWJlci5cbiAgI1xuICBjbGFzcyBJbW11dGFibGVPYmplY3QgZXh0ZW5kcyBJbnNlcnRcblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSBjb250ZW50XG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBAY29udGVudCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBzdXBlciB1aWQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICAgI1xuICAgICMgQHJldHVybiBbU3RyaW5nXSBUaGUgY29udGVudCBvZiB0aGlzIG9wZXJhdGlvbi5cbiAgICAjXG4gICAgdmFsIDogKCktPlxuICAgICAgQGNvbnRlbnRcblxuICAgICNcbiAgICAjIEVuY29kZSB0aGlzIG9wZXJhdGlvbiBpbiBzdWNoIGEgd2F5IHRoYXQgaXQgY2FuIGJlIHBhcnNlZCBieSByZW1vdGUgcGVlcnMuXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIGpzb24gPSB7XG4gICAgICAgICd0eXBlJzogXCJJbW11dGFibGVPYmplY3RcIlxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAnY29udGVudCcgOiBAY29udGVudFxuICAgICAgfVxuICAgICAgaWYgQHByZXZfY2w/XG4gICAgICAgIGpzb25bJ3ByZXYnXSA9IEBwcmV2X2NsLmdldFVpZCgpXG4gICAgICBpZiBAbmV4dF9jbD9cbiAgICAgICAganNvblsnbmV4dCddID0gQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgIGlmIEBvcmlnaW4/IGFuZCBAb3JpZ2luIGlzbnQgQHByZXZfY2xcbiAgICAgICAganNvbltcIm9yaWdpblwiXSA9IEBvcmlnaW4uZ2V0VWlkKClcbiAgICAgIGpzb25cblxuICBwYXJzZXJbJ0ltbXV0YWJsZU9iamVjdCddID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ2NvbnRlbnQnIDogY29udGVudFxuICAgICAgJ3ByZXYnOiBwcmV2XG4gICAgICAnbmV4dCc6IG5leHRcbiAgICAgICdvcmlnaW4nIDogb3JpZ2luXG4gICAgfSA9IGpzb25cbiAgICBuZXcgSW1tdXRhYmxlT2JqZWN0IHVpZCwgY29udGVudCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cbiAgI1xuICAjIEEgZGVsaW1pdGVyIGlzIHBsYWNlZCBhdCB0aGUgZW5kIGFuZCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBhc3NvY2lhdGl2ZSBsaXN0cy5cbiAgIyBUaGlzIGlzIG5lY2Vzc2FyeSBpbiBvcmRlciB0byBoYXZlIGEgYmVnaW5uaW5nIGFuZCBhbiBlbmQgZXZlbiBpZiB0aGUgY29udGVudFxuICAjIG9mIHRoZSBFbmdpbmUgaXMgZW1wdHkuXG4gICNcbiAgY2xhc3MgRGVsaW1pdGVyIGV4dGVuZHMgT3BlcmF0aW9uXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IHByZXZfY2wgVGhlIHByZWRlY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBuZXh0X2NsIFRoZSBzdWNjZXNzb3Igb2YgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGNvbXBsZXRlLWxpc3QgKGNsKVxuICAgICNcbiAgICAjIEBzZWUgSGlzdG9yeUJ1ZmZlci5nZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllclxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgcHJldl9jbCwgbmV4dF9jbCwgb3JpZ2luKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncHJldl9jbCcsIHByZXZfY2xcbiAgICAgIEBzYXZlT3BlcmF0aW9uICduZXh0X2NsJywgbmV4dF9jbFxuICAgICAgQHNhdmVPcGVyYXRpb24gJ29yaWdpbicsIHByZXZfY2xcbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgSWYgaXNEZWxldGVkKCkgaXMgdHJ1ZSB0aGlzIG9wZXJhdGlvbiB3b24ndCBiZSBtYWludGFpbmVkIGluIHRoZSBzbFxuICAgICNcbiAgICBpc0RlbGV0ZWQ6ICgpLT5cbiAgICAgIGZhbHNlXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBAdW5jaGVja2VkP1snbmV4dF9jbCddP1xuICAgICAgICBzdXBlclxuICAgICAgZWxzZSBpZiBAdW5jaGVja2VkP1sncHJldl9jbCddXG4gICAgICAgIGlmIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgICAgaWYgQHByZXZfY2wubmV4dF9jbD9cbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcIlByb2JhYmx5IGR1cGxpY2F0ZWQgb3BlcmF0aW9uc1wiXG4gICAgICAgICAgQHByZXZfY2wubmV4dF9jbCA9IEBcbiAgICAgICAgICBkZWxldGUgQHByZXZfY2wudW5jaGVja2VkLm5leHRfY2xcbiAgICAgICAgICBzdXBlclxuICAgICAgICBlbHNlXG4gICAgICAgICAgZmFsc2VcbiAgICAgIGVsc2UgaWYgQHByZXZfY2w/IGFuZCBub3QgQHByZXZfY2wubmV4dF9jbD9cbiAgICAgICAgZGVsZXRlIEBwcmV2X2NsLnVuY2hlY2tlZC5uZXh0X2NsXG4gICAgICAgIEBwcmV2X2NsLm5leHRfY2wgPSBAXG4gICAgICBlbHNlIGlmIEBwcmV2X2NsPyBvciBAbmV4dF9jbD9cbiAgICAgICAgc3VwZXJcbiAgICAgIGVsc2VcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiRGVsaW1pdGVyIGlzIHVuc3VmZmljaWVudCBkZWZpbmVkIVwiXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICB7XG4gICAgICAgICd0eXBlJyA6IFwiRGVsaW1pdGVyXCJcbiAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgJ3ByZXYnIDogQHByZXZfY2w/LmdldFVpZCgpXG4gICAgICAgICduZXh0JyA6IEBuZXh0X2NsPy5nZXRVaWQoKVxuICAgICAgfVxuXG4gIHBhcnNlclsnRGVsaW1pdGVyJ10gPSAoanNvbiktPlxuICAgIHtcbiAgICAndWlkJyA6IHVpZFxuICAgICdwcmV2JyA6IHByZXZcbiAgICAnbmV4dCcgOiBuZXh0XG4gICAgfSA9IGpzb25cbiAgICBuZXcgRGVsaW1pdGVyIHVpZCwgcHJldiwgbmV4dFxuXG4gICMgVGhpcyBpcyB3aGF0IHRoaXMgbW9kdWxlIGV4cG9ydHMgYWZ0ZXIgaW5pdGlhbGl6aW5nIGl0IHdpdGggdGhlIEhpc3RvcnlCdWZmZXJcbiAge1xuICAgICd0eXBlcycgOlxuICAgICAgJ0RlbGV0ZScgOiBEZWxldGVcbiAgICAgICdJbnNlcnQnIDogSW5zZXJ0XG4gICAgICAnRGVsaW1pdGVyJzogRGVsaW1pdGVyXG4gICAgICAnT3BlcmF0aW9uJzogT3BlcmF0aW9uXG4gICAgICAnSW1tdXRhYmxlT2JqZWN0JyA6IEltbXV0YWJsZU9iamVjdFxuICAgICdwYXJzZXInIDogcGFyc2VyXG4gICAgJ2V4ZWN1dGlvbl9saXN0ZW5lcicgOiBleGVjdXRpb25fbGlzdGVuZXJcbiAgfVxuXG5cblxuXG4iLCJiYXNpY190eXBlc191bmluaXRpYWxpemVkID0gcmVxdWlyZSBcIi4vQmFzaWNUeXBlc1wiXG5cbm1vZHVsZS5leHBvcnRzID0gKEhCKS0+XG4gIGJhc2ljX3R5cGVzID0gYmFzaWNfdHlwZXNfdW5pbml0aWFsaXplZCBIQlxuICB0eXBlcyA9IGJhc2ljX3R5cGVzLnR5cGVzXG4gIHBhcnNlciA9IGJhc2ljX3R5cGVzLnBhcnNlclxuXG4gICNcbiAgIyBNYW5hZ2VzIG1hcCBsaWtlIG9iamVjdHMuIEUuZy4gSnNvbi1UeXBlIGFuZCBYTUwgYXR0cmlidXRlcy5cbiAgI1xuICBjbGFzcyBNYXBNYW5hZ2VyIGV4dGVuZHMgdHlwZXMuT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkKS0+XG4gICAgICBAbWFwID0ge31cbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgQHNlZSBKc29uVHlwZXMudmFsXG4gICAgI1xuICAgIHZhbDogKG5hbWUsIGNvbnRlbnQpLT5cbiAgICAgIGlmIGNvbnRlbnQ/XG4gICAgICAgIGlmIG5vdCBAbWFwW25hbWVdP1xuICAgICAgICAgIEhCLmFkZE9wZXJhdGlvbihuZXcgQWRkTmFtZSB1bmRlZmluZWQsIEAsIG5hbWUpLmV4ZWN1dGUoKVxuICAgICAgICBAbWFwW25hbWVdLnJlcGxhY2UgY29udGVudFxuICAgICAgICBAXG4gICAgICBlbHNlIGlmIG5hbWU/XG4gICAgICAgIG9iaiA9IEBtYXBbbmFtZV0/LnZhbCgpXG4gICAgICAgIGlmIG9iaiBpbnN0YW5jZW9mIHR5cGVzLkltbXV0YWJsZU9iamVjdFxuICAgICAgICAgIG9iai52YWwoKVxuICAgICAgICBlbHNlXG4gICAgICAgICAgb2JqXG4gICAgICBlbHNlXG4gICAgICAgIHJlc3VsdCA9IHt9XG4gICAgICAgIGZvciBuYW1lLG8gb2YgQG1hcFxuICAgICAgICAgIG9iaiA9IG8udmFsKClcbiAgICAgICAgICBpZiBvYmogaW5zdGFuY2VvZiB0eXBlcy5JbW11dGFibGVPYmplY3Qgb3Igb2JqIGluc3RhbmNlb2YgTWFwTWFuYWdlclxuICAgICAgICAgICAgb2JqID0gb2JqLnZhbCgpXG4gICAgICAgICAgcmVzdWx0W25hbWVdID0gb2JqXG4gICAgICAgIHJlc3VsdFxuXG4gICNcbiAgIyBXaGVuIGEgbmV3IHByb3BlcnR5IGluIGEgbWFwIG1hbmFnZXIgaXMgY3JlYXRlZCwgdGhlbiB0aGUgdWlkcyBvZiB0aGUgaW5zZXJ0ZWQgT3BlcmF0aW9uc1xuICAjIG11c3QgYmUgdW5pcXVlICh0aGluayBhYm91dCBjb25jdXJyZW50IG9wZXJhdGlvbnMpLiBUaGVyZWZvcmUgb25seSBhbiBBZGROYW1lIG9wZXJhdGlvbiBpcyBhbGxvd2VkIHRvXG4gICMgYWRkIGEgcHJvcGVydHkgaW4gYSBNYXBNYW5hZ2VyLiBJZiB0d28gQWRkTmFtZSBvcGVyYXRpb25zIG9uIHRoZSBzYW1lIE1hcE1hbmFnZXIgbmFtZSBoYXBwZW4gY29uY3VycmVudGx5XG4gICMgb25seSBvbmUgd2lsbCBBZGROYW1lIG9wZXJhdGlvbiB3aWxsIGJlIGV4ZWN1dGVkLlxuICAjXG4gIGNsYXNzIEFkZE5hbWUgZXh0ZW5kcyB0eXBlcy5PcGVyYXRpb25cblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSBtYXBfbWFuYWdlciBVaWQgb3IgcmVmZXJlbmNlIHRvIHRoZSBNYXBNYW5hZ2VyLlxuICAgICMgQHBhcmFtIHtTdHJpbmd9IG5hbWUgTmFtZSBvZiB0aGUgcHJvcGVydHkgdGhhdCB3aWxsIGJlIGFkZGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgbWFwX21hbmFnZXIsIEBuYW1lKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnbWFwX21hbmFnZXInLCBtYXBfbWFuYWdlclxuICAgICAgc3VwZXIgdWlkXG5cbiAgICAjXG4gICAgIyBJZiBtYXBfbWFuYWdlciBkb2Vzbid0IGhhdmUgdGhlIHByb3BlcnR5IG5hbWUsIHRoZW4gYWRkIGl0LlxuICAgICMgVGhlIFJlcGxhY2VNYW5hZ2VyIHRoYXQgaXMgYmVpbmcgd3JpdHRlbiBvbiB0aGUgcHJvcGVydHkgaXMgdW5pcXVlXG4gICAgIyBpbiBzdWNoIGEgd2F5IHRoYXQgaWYgQWRkTmFtZSBpcyBleGVjdXRlZCAoZnJvbSBhbm90aGVyIHBlZXIpIGl0IHdpbGxcbiAgICAjIGFsd2F5cyBoYXZlIHRoZSBzYW1lIHJlc3VsdCAoUmVwbGFjZU1hbmFnZXIsIGFuZCBpdHMgYmVnaW5uaW5nIGFuZCBlbmQgYXJlIHRoZSBzYW1lKVxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBub3QgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICBlbHNlXG4gICAgICAgIHVpZF9yID0gQG1hcF9tYW5hZ2VyLmdldFVpZCgpXG4gICAgICAgIHVpZF9yLm9wX251bWJlciA9IFwiXyN7dWlkX3Iub3BfbnVtYmVyfV9STV8je0BuYW1lfVwiXG4gICAgICAgIGlmIG5vdCBIQi5nZXRPcGVyYXRpb24odWlkX3IpP1xuICAgICAgICAgIHVpZF9iZWcgPSBAbWFwX21hbmFnZXIuZ2V0VWlkKClcbiAgICAgICAgICB1aWRfYmVnLm9wX251bWJlciA9IFwiXyN7dWlkX2JlZy5vcF9udW1iZXJ9X1JNXyN7QG5hbWV9X2JlZ2lubmluZ1wiXG4gICAgICAgICAgdWlkX2VuZCA9IEBtYXBfbWFuYWdlci5nZXRVaWQoKVxuICAgICAgICAgIHVpZF9lbmQub3BfbnVtYmVyID0gXCJfI3t1aWRfZW5kLm9wX251bWJlcn1fUk1fI3tAbmFtZX1fZW5kXCJcbiAgICAgICAgICBiZWcgPSBIQi5hZGRPcGVyYXRpb24obmV3IHR5cGVzLkRlbGltaXRlciB1aWRfYmVnLCB1bmRlZmluZWQsIHVpZF9lbmQpLmV4ZWN1dGUoKVxuICAgICAgICAgIGVuZCA9IEhCLmFkZE9wZXJhdGlvbihuZXcgdHlwZXMuRGVsaW1pdGVyIHVpZF9lbmQsIGJlZywgdW5kZWZpbmVkKS5leGVjdXRlKClcbiAgICAgICAgICAjYmVnLmV4ZWN1dGUoKVxuICAgICAgICAgIEBtYXBfbWFuYWdlci5tYXBbQG5hbWVdID0gSEIuYWRkT3BlcmF0aW9uKG5ldyBSZXBsYWNlTWFuYWdlciB1bmRlZmluZWQsIHVpZF9yLCBiZWcsIGVuZCkuZXhlY3V0ZSgpXG4gICAgICAgIHN1cGVyXG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICB7XG4gICAgICAgICd0eXBlJyA6IFwiQWRkTmFtZVwiXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICdtYXBfbWFuYWdlcicgOiBAbWFwX21hbmFnZXIuZ2V0VWlkKClcbiAgICAgICAgJ25hbWUnIDogQG5hbWVcbiAgICAgIH1cblxuICBwYXJzZXJbJ0FkZE5hbWUnXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ21hcF9tYW5hZ2VyJyA6IG1hcF9tYW5hZ2VyXG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ25hbWUnIDogbmFtZVxuICAgIH0gPSBqc29uXG4gICAgbmV3IEFkZE5hbWUgdWlkLCBtYXBfbWFuYWdlciwgbmFtZVxuXG4gICNcbiAgIyBNYW5hZ2VzIGEgbGlzdCBvZiBJbnNlcnQtdHlwZSBvcGVyYXRpb25zLlxuICAjXG4gIGNsYXNzIExpc3RNYW5hZ2VyIGV4dGVuZHMgdHlwZXMuSW5zZXJ0XG5cbiAgICAjXG4gICAgIyBBIExpc3RNYW5hZ2VyIG1haW50YWlucyBhIG5vbi1lbXB0eSBsaXN0IHRoYXQgaGFzIGEgYmVnaW5uaW5nIGFuZCBhbiBlbmQgKGJvdGggRGVsaW1pdGVycyEpXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge0RlbGltaXRlcn0gYmVnaW5uaW5nIFJlZmVyZW5jZSBvciBPYmplY3QuXG4gICAgIyBAcGFyYW0ge0RlbGltaXRlcn0gZW5kIFJlZmVyZW5jZSBvciBPYmplY3QuXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIGlmIGJlZ2lubmluZz8gYW5kIGVuZD9cbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ2JlZ2lubmluZycsIGJlZ2lubmluZ1xuICAgICAgICBAc2F2ZU9wZXJhdGlvbiAnZW5kJywgZW5kXG4gICAgICBlbHNlXG4gICAgICAgIEBiZWdpbm5pbmcgPSBIQi5hZGRPcGVyYXRpb24gbmV3IHR5cGVzLkRlbGltaXRlciB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkXG4gICAgICAgIEBlbmQgPSAgICAgICBIQi5hZGRPcGVyYXRpb24gbmV3IHR5cGVzLkRlbGltaXRlciB1bmRlZmluZWQsIEBiZWdpbm5pbmcsIHVuZGVmaW5lZFxuICAgICAgICBAYmVnaW5uaW5nLm5leHRfY2wgPSBAZW5kXG4gICAgICAgIEBiZWdpbm5pbmcuZXhlY3V0ZSgpXG4gICAgICAgIEBlbmQuZXhlY3V0ZSgpXG4gICAgICBzdXBlciB1aWQsIHByZXYsIG5leHQsIG9yaWdpblxuXG5cbiAgICAjIEdldCB0aGUgZWxlbWVudCBwcmV2aW91cyB0byB0aGUgZGVsZW1pdGVyIGF0IHRoZSBlbmRcbiAgICBnZXRMYXN0T3BlcmF0aW9uOiAoKS0+XG4gICAgICBAZW5kLnByZXZfY2xcblxuICAgICMgc2ltaWxhciB0byB0aGUgYWJvdmVcbiAgICBnZXRGaXJzdE9wZXJhdGlvbjogKCktPlxuICAgICAgQGJlZ2lubmluZy5uZXh0X2NsXG5cbiAgICAjIFRyYW5zZm9ybXMgdGhlIHRoZSBsaXN0IHRvIGFuIGFycmF5XG4gICAgIyBEb2Vzbid0IHJldHVybiBsZWZ0LXJpZ2h0IGRlbGltaXRlci5cbiAgICB0b0FycmF5OiAoKS0+XG4gICAgICBvID0gQGJlZ2lubmluZy5uZXh0X2NsXG4gICAgICByZXN1bHQgPSBbXVxuICAgICAgd2hpbGUgbyBpc250IEBlbmRcbiAgICAgICAgcmVzdWx0LnB1c2ggb1xuICAgICAgICBvID0gby5uZXh0X2NsXG4gICAgICByZXN1bHRcblxuICAgICNcbiAgICAjIFJldHJpZXZlcyB0aGUgeC10aCBub3QgZGVsZXRlZCBlbGVtZW50LlxuICAgICNcbiAgICBnZXRPcGVyYXRpb25CeVBvc2l0aW9uOiAocG9zaXRpb24pLT5cbiAgICAgIG8gPSBAYmVnaW5uaW5nLm5leHRfY2xcbiAgICAgIGlmIHBvc2l0aW9uID4gMFxuICAgICAgICB3aGlsZSB0cnVlXG4gICAgICAgICAgbyA9IG8ubmV4dF9jbFxuICAgICAgICAgIGlmIG5vdCBvLmlzRGVsZXRlZCgpXG4gICAgICAgICAgICBwb3NpdGlvbiAtPSAxXG4gICAgICAgICAgaWYgcG9zaXRpb24gaXMgMFxuICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICBpZiBvIGluc3RhbmNlb2YgdHlwZXMuRGVsaW1pdGVyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJwb3NpdGlvbiBwYXJhbWV0ZXIgZXhjZWVkZWQgdGhlIGxlbmd0aCBvZiB0aGUgZG9jdW1lbnQhXCJcbiAgICAgIG9cblxuICAjXG4gICMgQWRkcyBzdXBwb3J0IGZvciByZXBsYWNlLiBUaGUgUmVwbGFjZU1hbmFnZXIgbWFuYWdlcyBSZXBsYWNlYWJsZSBvcGVyYXRpb25zLlxuICAjIEVhY2ggUmVwbGFjZWFibGUgaG9sZHMgYSB2YWx1ZSB0aGF0IGlzIG5vdyByZXBsYWNlYWJsZS5cbiAgI1xuICAjIFRoZSBXb3JkLXR5cGUgaGFzIGltcGxlbWVudGVkIHN1cHBvcnQgZm9yIHJlcGxhY2VcbiAgIyBAc2VlIFdvcmRcbiAgI1xuICBjbGFzcyBSZXBsYWNlTWFuYWdlciBleHRlbmRzIExpc3RNYW5hZ2VyXG4gICAgI1xuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IGluaXRpYWxfY29udGVudCBJbml0aWFsaXplIHRoaXMgd2l0aCBhIFJlcGxhY2VhYmxlIHRoYXQgaG9sZHMgdGhlIGluaXRpYWxfY29udGVudC5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7RGVsaW1pdGVyfSBiZWdpbm5pbmcgUmVmZXJlbmNlIG9yIE9iamVjdC5cbiAgICAjIEBwYXJhbSB7RGVsaW1pdGVyfSBlbmQgUmVmZXJlbmNlIG9yIE9iamVjdC5cbiAgICBjb25zdHJ1Y3RvcjogKGluaXRpYWxfY29udGVudCwgdWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBzdXBlciB1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW5cbiAgICAgIGlmIGluaXRpYWxfY29udGVudD9cbiAgICAgICAgQHJlcGxhY2UgaW5pdGlhbF9jb250ZW50XG5cbiAgICAjXG4gICAgIyBSZXBsYWNlIHRoZSBleGlzdGluZyB3b3JkIHdpdGggYSBuZXcgd29yZC5cbiAgICAjXG4gICAgcmVwbGFjZTogKGNvbnRlbnQpLT5cbiAgICAgIG8gPSBAZ2V0TGFzdE9wZXJhdGlvbigpXG4gICAgICBvcCA9IG5ldyBSZXBsYWNlYWJsZSBjb250ZW50LCBALCB1bmRlZmluZWQsIG8sIG8ubmV4dF9jbFxuICAgICAgSEIuYWRkT3BlcmF0aW9uKG9wKS5leGVjdXRlKClcblxuICAgICNcbiAgICAjIEdldCB0aGUgdmFsdWUgb2YgdGhpcyBXb3JkXG4gICAgIyBAcmV0dXJuIHtTdHJpbmd9XG4gICAgI1xuICAgIHZhbDogKCktPlxuICAgICAgbyA9IEBnZXRMYXN0T3BlcmF0aW9uKClcbiAgICAgIGlmIG8gaW5zdGFuY2VvZiB0eXBlcy5EZWxpbWl0ZXJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiZHRyblwiXG4gICAgICBvLnZhbCgpXG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID1cbiAgICAgICAge1xuICAgICAgICAgICd0eXBlJzogXCJSZXBsYWNlTWFuYWdlclwiXG4gICAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgICAnYmVnaW5uaW5nJyA6IEBiZWdpbm5pbmcuZ2V0VWlkKClcbiAgICAgICAgICAnZW5kJyA6IEBlbmQuZ2V0VWlkKClcbiAgICAgICAgfVxuICAgICAgaWYgQHByZXZfY2w/IGFuZCBAbmV4dF9jbD9cbiAgICAgICAganNvblsncHJldiddID0gQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgICAganNvblsnbmV4dCddID0gQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgIGlmIEBvcmlnaW4/IGFuZCBAb3JpZ2luIGlzbnQgQHByZXZfY2xcbiAgICAgICAganNvbltcIm9yaWdpblwiXSA9IEBvcmlnaW4uZ2V0VWlkKClcbiAgICAgIGpzb25cblxuICBwYXJzZXJbXCJSZXBsYWNlTWFuYWdlclwiXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ2NvbnRlbnQnIDogY29udGVudFxuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdwcmV2JzogcHJldlxuICAgICAgJ25leHQnOiBuZXh0XG4gICAgICAnb3JpZ2luJyA6IG9yaWdpblxuICAgICAgJ2JlZ2lubmluZycgOiBiZWdpbm5pbmdcbiAgICAgICdlbmQnIDogZW5kXG4gICAgfSA9IGpzb25cbiAgICBuZXcgUmVwbGFjZU1hbmFnZXIgY29udGVudCwgdWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cblxuICAjXG4gICMgVGhlIFJlcGxhY2VNYW5hZ2VyIG1hbmFnZXMgUmVwbGFjZWFibGVzLlxuICAjIEBzZWUgUmVwbGFjZU1hbmFnZXJcbiAgI1xuICBjbGFzcyBSZXBsYWNlYWJsZSBleHRlbmRzIHR5cGVzLkluc2VydFxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IGNvbnRlbnQgVGhlIHZhbHVlIHRoYXQgdGhpcyBSZXBsYWNlYWJsZSBob2xkcy5cbiAgICAjIEBwYXJhbSB7UmVwbGFjZU1hbmFnZXJ9IHBhcmVudCBVc2VkIHRvIHJlcGxhY2UgdGhpcyBSZXBsYWNlYWJsZSB3aXRoIGFub3RoZXIgb25lLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKGNvbnRlbnQsIHBhcmVudCwgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIEBzYXZlT3BlcmF0aW9uICdjb250ZW50JywgY29udGVudFxuICAgICAgQHNhdmVPcGVyYXRpb24gJ3BhcmVudCcsIHBhcmVudFxuICAgICAgaWYgbm90IChwcmV2PyBhbmQgbmV4dD8gYW5kIGNvbnRlbnQ/KVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBkZWZpbmUgY29udGVudCwgcHJldiwgYW5kIG5leHQgZm9yIFJlcGxhY2VhYmxlLXR5cGVzIVwiXG4gICAgICBzdXBlciB1aWQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICAgI1xuICAgICMgUmV0dXJuIHRoZSBjb250ZW50IHRoYXQgdGhpcyBvcGVyYXRpb24gaG9sZHMuXG4gICAgI1xuICAgIHZhbDogKCktPlxuICAgICAgQGNvbnRlbnRcblxuICAgICNcbiAgICAjIFJlcGxhY2UgdGhlIGNvbnRlbnQgb2YgdGhpcyByZXBsYWNlYWJsZSB3aXRoIG5ldyBjb250ZW50LlxuICAgICNcbiAgICByZXBsYWNlOiAoY29udGVudCktPlxuICAgICAgQHBhcmVudC5yZXBsYWNlIGNvbnRlbnRcblxuICAgICNcbiAgICAjIElmIHBvc3NpYmxlIHNldCB0aGUgcmVwbGFjZSBtYW5hZ2VyIGluIHRoZSBjb250ZW50LlxuICAgICMgQHNlZSBXb3JkLnNldFJlcGxhY2VNYW5hZ2VyXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIG5vdCBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIGVsc2VcbiAgICAgICAgQGNvbnRlbnQuc2V0UmVwbGFjZU1hbmFnZXI/KEBwYXJlbnQpXG4gICAgICAgIHN1cGVyXG4gICAgICAgIEBcblxuICAgICNcbiAgICAjIEVuY29kZSB0aGlzIG9wZXJhdGlvbiBpbiBzdWNoIGEgd2F5IHRoYXQgaXQgY2FuIGJlIHBhcnNlZCBieSByZW1vdGUgcGVlcnMuXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIGpzb24gPVxuICAgICAgICB7XG4gICAgICAgICAgJ3R5cGUnOiBcIlJlcGxhY2VhYmxlXCJcbiAgICAgICAgICAnY29udGVudCc6IEBjb250ZW50LmdldFVpZCgpXG4gICAgICAgICAgJ1JlcGxhY2VNYW5hZ2VyJyA6IEBwYXJlbnQuZ2V0VWlkKClcbiAgICAgICAgICAncHJldic6IEBwcmV2X2NsLmdldFVpZCgpXG4gICAgICAgICAgJ25leHQnOiBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgIH1cbiAgICAgIGlmIEBvcmlnaW4/IGFuZCBAb3JpZ2luIGlzbnQgQHByZXZfY2xcbiAgICAgICAganNvbltcIm9yaWdpblwiXSA9IEBvcmlnaW4uZ2V0VWlkKClcbiAgICAgIGpzb25cblxuICBwYXJzZXJbXCJSZXBsYWNlYWJsZVwiXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ2NvbnRlbnQnIDogY29udGVudFxuICAgICAgJ1JlcGxhY2VNYW5hZ2VyJyA6IHBhcmVudFxuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdwcmV2JzogcHJldlxuICAgICAgJ25leHQnOiBuZXh0XG4gICAgICAnb3JpZ2luJyA6IG9yaWdpblxuICAgIH0gPSBqc29uXG4gICAgbmV3IFJlcGxhY2VhYmxlIGNvbnRlbnQsIHBhcmVudCwgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuXG5cbiAgdHlwZXNbJ0xpc3RNYW5hZ2VyJ10gPSBMaXN0TWFuYWdlclxuICB0eXBlc1snTWFwTWFuYWdlciddID0gTWFwTWFuYWdlclxuICB0eXBlc1snUmVwbGFjZU1hbmFnZXInXSA9IFJlcGxhY2VNYW5hZ2VyXG4gIHR5cGVzWydSZXBsYWNlYWJsZSddID0gUmVwbGFjZWFibGVcblxuICBiYXNpY190eXBlc1xuXG5cblxuXG5cblxuIl19 diff --git a/build/browser/Types/StructuredTypes.min.js b/build/browser/Types/StructuredTypes.min.js new file mode 100644 index 00000000..04181320 --- /dev/null +++ b/build/browser/Types/StructuredTypes.min.js @@ -0,0 +1 @@ +!function e(t,n,i){function r(s,u){if(!n[s]){if(!t[s]){var a="function"==typeof require&&require;if(!u&&a)return a(s,!0);if(o)return o(s,!0);throw new Error("Cannot find module '"+s+"'")}var l=n[s]={exports:{}};t[s][0].call(l.exports,function(e){var n=t[s][1][e];return r(n?n:e)},l,l.exports,e,t,n,i)}return n[s].exports}for(var o="function"==typeof require&&require,s=0;si;i++)n=o[i],s.push(n.call(this,e,t));return s}},t.prototype.setParent=function(e){return this.parent=e},t.prototype.getUid=function(){return{creator:this.creator,op_number:this.op_number}},t.prototype.execute=function(){var e,t,n;for(this.is_executed=!0,t=0,n=u.length;n>t;t++)(e=u[t])(this._encode());return this},t.prototype.saveOperation=function(e,t){return null!=(null!=t?t.execute:void 0)?this[e]=t:null!=t?(null==this.unchecked&&(this.unchecked={}),this.unchecked[e]=t):void 0},t.prototype.validateSavedOperations=function(){var t,n,i,r,o,s;o={},r=this,s=this.unchecked;for(t in s)i=s[t],n=e.getOperation(i),n?this[t]=n:(o[t]=i,r=!1);return delete this.unchecked,r||(this.unchecked=o),r},t}(),t=function(e){function t(e,n){this.saveOperation("deletes",n),t.__super__.constructor.call(this,e)}return i(t,e),t.prototype._encode=function(){return{type:"Delete",uid:this.getUid(),deletes:this.deletes.getUid()}},t.prototype.execute=function(){return this.validateSavedOperations()?(this.deletes.applyDelete(this),t.__super__.execute.apply(this,arguments),this):!1},t}(s),a.Delete=function(e){var n,i;return i=e.uid,n=e.deletes,new t(i,n)},o=function(e){function t(e,n,i,r){this.saveOperation("prev_cl",n),this.saveOperation("next_cl",i),null!=r?this.saveOperation("origin",r):this.saveOperation("origin",n),t.__super__.constructor.call(this,e)}return i(t,e),t.prototype.applyDelete=function(e){return null==this.deleted_by&&(this.deleted_by=[]),this.deleted_by.push(e)},t.prototype.isDeleted=function(){var e;return(null!=(e=this.deleted_by)?e.length:void 0)>0},t.prototype.getDistanceToOrigin=function(){var e,t;for(e=0,t=this.prev_cl;;){if(this.origin===t)break;if(e++,this===this.prev_cl)throw new Error("this should not happen ;) ");t=t.prev_cl}return e},t.prototype.update_sl=function(){var e;return e=this.prev_cl,update("prev_cl","prev_sl"),update("next_cl","prev_sl")},t.prototype.execute=function(){var e,n,i,r,o;if(null!=this.is_executed)return this;if(this.validateSavedOperations()){if((null!=(r=this.prev_cl)?r.validateSavedOperations():void 0)&&(null!=(o=this.next_cl)?o.validateSavedOperations():void 0)&&this.prev_cl.next_cl!==this){for(e=0,i=this.prev_cl.next_cl,n=0;;){if(null==i&&(console.log(JSON.stringify(this.prev_cl.getUid())),console.log(JSON.stringify(this.next_cl.getUid()))),i===this.next_cl)break;if(i.getDistanceToOrigin()===n)i.creator0)for(;;){if(t=t.next_cl,t.isDeleted()||(e-=1),0===e)break;if(t instanceof p.Delimiter)throw new Error("position parameter exceeded the length of the document!")}return t},n}(p.Insert),s=function(t){function n(e,t,i,r,o,s,u){n.__super__.constructor.call(this,t,i,r,o,s,u),null!=e&&this.replace(e)}return r(n,t),n.prototype.replace=function(t){var n,i;return n=this.getLastOperation(),i=new u(t,this,void 0,n,n.next_cl),e.addOperation(i).execute()},n.prototype.val=function(){var e;if(e=this.getLastOperation(),e instanceof p.Delimiter)throw new Error("dtrn");return e.val()},n.prototype._encode=function(){var e;return e={type:"ReplaceManager",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&null!=this.next_cl&&(e.prev=this.prev_cl.getUid(),e.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},n}(i),l.ReplaceManager=function(e){var t,n,i,r,o,u,a;return n=e.content,a=e.uid,u=e.prev,r=e.next,o=e.origin,t=e.beginning,i=e.end,new s(n,a,t,i,u,r,o)},u=function(e){function t(e,n,i,r,o,s){if(this.saveOperation("content",e),this.saveOperation("parent",n),null==r||null==o||null==e)throw new Error("You must define content, prev, and next for Replaceable-types!");t.__super__.constructor.call(this,i,r,o,s)}return r(t,e),t.prototype.val=function(){return this.content},t.prototype.replace=function(e){return this.parent.replace(e)},t.prototype.execute=function(){var e;return this.validateSavedOperations()?("function"==typeof(e=this.content).setReplaceManager&&e.setReplaceManager(this.parent),t.__super__.execute.apply(this,arguments),this):!1},t.prototype._encode=function(){var e;return e={type:"Replaceable",content:this.content.getUid(),ReplaceManager:this.parent.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid(),uid:this.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},t}(p.Insert),l.Replaceable=function(e){var t,n,i,r,o,s;return t=e.content,r=e.ReplaceManager,s=e.uid,o=e.prev,n=e.next,i=e.origin,new u(t,r,s,o,n,i)},p.ListManager=i,p.MapManager=o,p.ReplaceManager=s,p.Replaceable=u,a}},{"./BasicTypes":1}]},{},[2]); \ No newline at end of file diff --git a/build/browser/Types/TextTypes.js b/build/browser/Types/TextTypes.js new file mode 100644 index 00000000..b022d279 --- /dev/null +++ b/build/browser/Types/TextTypes.js @@ -0,0 +1,816 @@ +(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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0; + }; + + Insert.prototype.getDistanceToOrigin = function() { + var d, o; + d = 0; + o = this.prev_cl; + while (true) { + if (this.origin === o) { + break; + } + d++; + if (this === this.prev_cl) { + throw new Error("this should not happen ;) "); + } + o = o.prev_cl; + } + return d; + }; + + Insert.prototype.update_sl = function() { + var o; + o = this.prev_cl; + ({ + update: function(dest_cl, dest_sl) { + var _results; + _results = []; + while (true) { + if (o.isDeleted()) { + _results.push(o = o[dest_cl]); + } else { + this[dest_sl] = o; + break; + } + } + return _results; + } + }); + update("prev_cl", "prev_sl"); + return update("next_cl", "prev_sl"); + }; + + Insert.prototype.execute = function() { + var distance_to_origin, i, o, _ref, _ref1; + if (this.is_executed != null) { + return this; + } + if (!this.validateSavedOperations()) { + return false; + } else { + if (((_ref = this.prev_cl) != null ? _ref.validateSavedOperations() : void 0) && ((_ref1 = this.next_cl) != null ? _ref1.validateSavedOperations() : void 0) && this.prev_cl.next_cl !== this) { + distance_to_origin = 0; + o = this.prev_cl.next_cl; + i = 0; + while (true) { + if (o == null) { + console.log(JSON.stringify(this.prev_cl.getUid())); + console.log(JSON.stringify(this.next_cl.getUid())); + } + if (o !== this.next_cl) { + if (o.getDistanceToOrigin() === i) { + if (o.creator < this.creator) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else if (o.getDistanceToOrigin() < i) { + if (i - distance_to_origin <= o.getDistanceToOrigin()) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else { + break; + } + i++; + o = o.next_cl; + } else { + break; + } + } + this.next_cl = this.prev_cl.next_cl; + this.prev_cl.next_cl = this; + this.next_cl.prev_cl = this; + } + Insert.__super__.execute.apply(this, arguments); + return this; + } + }; + + return Insert; + + })(Operation); + ImmutableObject = (function(_super) { + __extends(ImmutableObject, _super); + + function ImmutableObject(uid, content, prev, next, origin) { + this.content = content; + ImmutableObject.__super__.constructor.call(this, uid, prev, next, origin); + } + + ImmutableObject.prototype.val = function() { + return this.content; + }; + + ImmutableObject.prototype._encode = function() { + var json; + json = { + 'type': "ImmutableObject", + 'uid': this.getUid(), + 'content': this.content + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ImmutableObject; + + })(Insert); + parser['ImmutableObject'] = function(json) { + var content, next, origin, prev, uid; + uid = json['uid'], content = json['content'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new ImmutableObject(uid, content, prev, next, origin); + }; + Delimiter = (function(_super) { + __extends(Delimiter, _super); + + function Delimiter(uid, prev_cl, next_cl, origin) { + this.saveOperation('prev_cl', prev_cl); + this.saveOperation('next_cl', next_cl); + this.saveOperation('origin', prev_cl); + Delimiter.__super__.constructor.call(this, uid); + } + + Delimiter.prototype.isDeleted = function() { + return false; + }; + + Delimiter.prototype.execute = function() { + var _ref, _ref1; + if (((_ref = this.unchecked) != null ? _ref['next_cl'] : void 0) != null) { + return Delimiter.__super__.execute.apply(this, arguments); + } else if ((_ref1 = this.unchecked) != null ? _ref1['prev_cl'] : void 0) { + if (this.validateSavedOperations()) { + if (this.prev_cl.next_cl != null) { + throw new Error("Probably duplicated operations"); + } + this.prev_cl.next_cl = this; + delete this.prev_cl.unchecked.next_cl; + return Delimiter.__super__.execute.apply(this, arguments); + } else { + return false; + } + } else if ((this.prev_cl != null) && (this.prev_cl.next_cl == null)) { + delete this.prev_cl.unchecked.next_cl; + return this.prev_cl.next_cl = this; + } else if ((this.prev_cl != null) || (this.next_cl != null)) { + return Delimiter.__super__.execute.apply(this, arguments); + } else { + throw new Error("Delimiter is unsufficient defined!"); + } + }; + + Delimiter.prototype._encode = function() { + var _ref, _ref1; + return { + 'type': "Delimiter", + 'uid': this.getUid(), + 'prev': (_ref = this.prev_cl) != null ? _ref.getUid() : void 0, + 'next': (_ref1 = this.next_cl) != null ? _ref1.getUid() : void 0 + }; + }; + + return Delimiter; + + })(Operation); + parser['Delimiter'] = function(json) { + var next, prev, uid; + uid = json['uid'], prev = json['prev'], next = json['next']; + return new Delimiter(uid, prev, next); + }; + return { + 'types': { + 'Delete': Delete, + 'Insert': Insert, + 'Delimiter': Delimiter, + 'Operation': Operation, + 'ImmutableObject': ImmutableObject + }, + 'parser': parser, + 'execution_listener': execution_listener + }; +}; + + +},{}],2:[function(require,module,exports){ +var basic_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +basic_types_uninitialized = require("./BasicTypes"); + +module.exports = function(HB) { + var AddName, ListManager, MapManager, ReplaceManager, Replaceable, basic_types, parser, types; + basic_types = basic_types_uninitialized(HB); + types = basic_types.types; + parser = basic_types.parser; + MapManager = (function(_super) { + __extends(MapManager, _super); + + function MapManager(uid) { + this.map = {}; + MapManager.__super__.constructor.call(this, uid); + } + + MapManager.prototype.val = function(name, content) { + var o, obj, result, _ref, _ref1; + if (content != null) { + if (this.map[name] == null) { + HB.addOperation(new AddName(void 0, this, name)).execute(); + } + this.map[name].replace(content); + return this; + } else if (name != null) { + obj = (_ref = this.map[name]) != null ? _ref.val() : void 0; + if (obj instanceof types.ImmutableObject) { + return obj.val(); + } else { + return obj; + } + } else { + result = {}; + _ref1 = this.map; + for (name in _ref1) { + o = _ref1[name]; + obj = o.val(); + if (obj instanceof types.ImmutableObject || obj instanceof MapManager) { + obj = obj.val(); + } + result[name] = obj; + } + return result; + } + }; + + return MapManager; + + })(types.Operation); + AddName = (function(_super) { + __extends(AddName, _super); + + function AddName(uid, map_manager, name) { + this.name = name; + this.saveOperation('map_manager', map_manager); + AddName.__super__.constructor.call(this, uid); + } + + AddName.prototype.execute = function() { + var beg, end, uid_beg, uid_end, uid_r; + if (!this.validateSavedOperations()) { + return false; + } else { + uid_r = this.map_manager.getUid(); + uid_r.op_number = "_" + uid_r.op_number + "_RM_" + this.name; + if (HB.getOperation(uid_r) == null) { + uid_beg = this.map_manager.getUid(); + uid_beg.op_number = "_" + uid_beg.op_number + "_RM_" + this.name + "_beginning"; + uid_end = this.map_manager.getUid(); + uid_end.op_number = "_" + uid_end.op_number + "_RM_" + this.name + "_end"; + beg = HB.addOperation(new types.Delimiter(uid_beg, void 0, uid_end)).execute(); + end = HB.addOperation(new types.Delimiter(uid_end, beg, void 0)).execute(); + this.map_manager.map[this.name] = HB.addOperation(new ReplaceManager(void 0, uid_r, beg, end)).execute(); + } + return AddName.__super__.execute.apply(this, arguments); + } + }; + + AddName.prototype._encode = function() { + return { + 'type': "AddName", + 'uid': this.getUid(), + 'map_manager': this.map_manager.getUid(), + 'name': this.name + }; + }; + + return AddName; + + })(types.Operation); + parser['AddName'] = function(json) { + var map_manager, name, uid; + map_manager = json['map_manager'], uid = json['uid'], name = json['name']; + return new AddName(uid, map_manager, name); + }; + ListManager = (function(_super) { + __extends(ListManager, _super); + + function ListManager(uid, beginning, end, prev, next, origin) { + if ((beginning != null) && (end != null)) { + this.saveOperation('beginning', beginning); + this.saveOperation('end', end); + } else { + this.beginning = HB.addOperation(new types.Delimiter(void 0, void 0, void 0)); + this.end = HB.addOperation(new types.Delimiter(void 0, this.beginning, void 0)); + this.beginning.next_cl = this.end; + this.beginning.execute(); + this.end.execute(); + } + ListManager.__super__.constructor.call(this, uid, prev, next, origin); + } + + ListManager.prototype.getLastOperation = function() { + return this.end.prev_cl; + }; + + ListManager.prototype.getFirstOperation = function() { + return this.beginning.next_cl; + }; + + ListManager.prototype.toArray = function() { + var o, result; + o = this.beginning.next_cl; + result = []; + while (o !== this.end) { + result.push(o); + o = o.next_cl; + } + return result; + }; + + ListManager.prototype.getOperationByPosition = function(position) { + var o; + o = this.beginning.next_cl; + if (position > 0) { + while (true) { + o = o.next_cl; + if (!o.isDeleted()) { + position -= 1; + } + if (position === 0) { + break; + } + if (o instanceof types.Delimiter) { + throw new Error("position parameter exceeded the length of the document!"); + } + } + } + return o; + }; + + return ListManager; + + })(types.Insert); + ReplaceManager = (function(_super) { + __extends(ReplaceManager, _super); + + function ReplaceManager(initial_content, uid, beginning, end, prev, next, origin) { + ReplaceManager.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + if (initial_content != null) { + this.replace(initial_content); + } + } + + ReplaceManager.prototype.replace = function(content) { + var o, op; + o = this.getLastOperation(); + op = new Replaceable(content, this, void 0, o, o.next_cl); + return HB.addOperation(op).execute(); + }; + + ReplaceManager.prototype.val = function() { + var o; + o = this.getLastOperation(); + if (o instanceof types.Delimiter) { + throw new Error("dtrn"); + } + return o.val(); + }; + + ReplaceManager.prototype._encode = function() { + var json; + json = { + 'type': "ReplaceManager", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if ((this.prev_cl != null) && (this.next_cl != null)) { + json['prev'] = this.prev_cl.getUid(); + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ReplaceManager; + + })(ListManager); + parser["ReplaceManager"] = function(json) { + var beginning, content, end, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], beginning = json['beginning'], end = json['end']; + return new ReplaceManager(content, uid, beginning, end, prev, next, origin); + }; + Replaceable = (function(_super) { + __extends(Replaceable, _super); + + function Replaceable(content, parent, uid, prev, next, origin) { + this.saveOperation('content', content); + this.saveOperation('parent', parent); + if (!((prev != null) && (next != null) && (content != null))) { + throw new Error("You must define content, prev, and next for Replaceable-types!"); + } + Replaceable.__super__.constructor.call(this, uid, prev, next, origin); + } + + Replaceable.prototype.val = function() { + return this.content; + }; + + Replaceable.prototype.replace = function(content) { + return this.parent.replace(content); + }; + + Replaceable.prototype.execute = function() { + var _base; + if (!this.validateSavedOperations()) { + return false; + } else { + if (typeof (_base = this.content).setReplaceManager === "function") { + _base.setReplaceManager(this.parent); + } + Replaceable.__super__.execute.apply(this, arguments); + return this; + } + }; + + Replaceable.prototype._encode = function() { + var json; + json = { + 'type': "Replaceable", + 'content': this.content.getUid(), + 'ReplaceManager': this.parent.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid(), + 'uid': this.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Replaceable; + + })(types.Insert); + parser["Replaceable"] = function(json) { + var content, next, origin, parent, prev, uid; + content = json['content'], parent = json['ReplaceManager'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Replaceable(content, parent, uid, prev, next, origin); + }; + types['ListManager'] = ListManager; + types['MapManager'] = MapManager; + types['ReplaceManager'] = ReplaceManager; + types['Replaceable'] = Replaceable; + return basic_types; +}; + + +},{"./BasicTypes":1}],3:[function(require,module,exports){ +var structured_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +structured_types_uninitialized = require("./StructuredTypes"); + +module.exports = function(HB) { + var TextDelete, TextInsert, Word, parser, structured_types, types; + structured_types = structured_types_uninitialized(HB); + types = structured_types.types; + parser = structured_types.parser; + TextDelete = (function(_super) { + __extends(TextDelete, _super); + + function TextDelete() { + return TextDelete.__super__.constructor.apply(this, arguments); + } + + return TextDelete; + + })(types.Delete); + parser["TextDelete"] = parser["Delete"]; + TextInsert = (function(_super) { + __extends(TextInsert, _super); + + function TextInsert(content, uid, prev, next, origin) { + this.content = content; + if (!((prev != null) && (next != null))) { + throw new Error("You must define prev, and next for TextInsert-types!"); + } + TextInsert.__super__.constructor.call(this, uid, prev, next, origin); + } + + TextInsert.prototype.getLength = function() { + if (this.isDeleted()) { + return 0; + } else { + return this.content.length; + } + }; + + TextInsert.prototype.val = function(current_position) { + if (this.isDeleted()) { + return ""; + } else { + return this.content; + } + }; + + TextInsert.prototype._encode = function() { + var json; + json = { + 'type': "TextInsert", + 'content': this.content, + 'uid': this.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return TextInsert; + + })(types.Insert); + parser["TextInsert"] = function(json) { + var content, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new TextInsert(content, uid, prev, next, origin); + }; + Word = (function(_super) { + __extends(Word, _super); + + function Word(uid, beginning, end, prev, next, origin) { + Word.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + } + + Word.prototype.insertText = function(position, content) { + var c, o, op, _i, _len, _results; + o = this.getOperationByPosition(position); + _results = []; + for (_i = 0, _len = content.length; _i < _len; _i++) { + c = content[_i]; + op = new TextInsert(c, void 0, o.prev_cl, o); + _results.push(HB.addOperation(op).execute()); + } + return _results; + }; + + Word.prototype.deleteText = function(position, length) { + var d, i, o, _i, _results; + o = this.getOperationByPosition(position); + _results = []; + for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) { + d = HB.addOperation(new TextDelete(void 0, o)).execute(); + o = o.next_cl; + while (o.isDeleted()) { + if (o instanceof types.Delimiter) { + throw new Error("You can't delete more than there is.."); + } + o = o.next_cl; + } + _results.push(d._encode()); + } + return _results; + }; + + Word.prototype.replaceText = function(text) { + var word; + if (this.replace_manager != null) { + word = HB.addOperation(new Word(void 0)).execute(); + word.insertText(0, text); + return this.replace_manager.replace(word); + } else { + throw new Error("This type is currently not maintained by a ReplaceManager!"); + } + }; + + Word.prototype.val = function() { + var c, o; + c = (function() { + var _i, _len, _ref, _results; + _ref = this.toArray(); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + o = _ref[_i]; + if (o.val != null) { + _results.push(o.val()); + } else { + _results.push(""); + } + } + return _results; + }).call(this); + return c.join(''); + }; + + Word.prototype.setReplaceManager = function(op) { + this.saveOperation('replace_manager', op); + return this.validateSavedOperations; + }; + + Word.prototype._encode = function() { + var json; + json = { + 'type': "Word", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Word; + + })(types.ListManager); + parser['Word'] = function(json) { + var beginning, end, next, origin, prev, uid; + uid = json['uid'], beginning = json['beginning'], end = json['end'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Word(uid, beginning, end, prev, next, origin); + }; + types['TextInsert'] = TextInsert; + types['TextDelete'] = TextDelete; + types['Word'] = Word; + return structured_types; +}; + + +},{"./StructuredTypes":2}]},{},[3]) +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL1R5cGVzL0Jhc2ljVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9TdHJ1Y3R1cmVkVHlwZXMuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9UZXh0VHlwZXMuY29mZmVlIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUEsSUFBQTtpU0FBQTs7QUFBQSxNQUFNLENBQUMsT0FBUCxHQUFpQixTQUFDLEVBQUQsR0FBQTtBQUVmLE1BQUEsaUZBQUE7QUFBQSxFQUFBLE1BQUEsR0FBUyxFQUFULENBQUE7QUFBQSxFQUNBLGtCQUFBLEdBQXFCLEVBRHJCLENBQUE7QUFBQSxFQWFNO0FBTVMsSUFBQSxtQkFBQyxHQUFELEdBQUE7QUFDWCxNQUFBLElBQU8sV0FBUDtBQUNFLFFBQUEsR0FBQSxHQUFNLEVBQUUsQ0FBQywwQkFBSCxDQUFBLENBQU4sQ0FERjtPQUFBO0FBQUEsTUFHYSxJQUFDLENBQUEsY0FBWixVQURGLEVBRWdCLElBQUMsQ0FBQSxnQkFBZixZQUpGLENBRFc7SUFBQSxDQUFiOztBQUFBLHdCQWFBLEVBQUEsR0FBSSxTQUFDLEtBQUQsRUFBUSxDQUFSLEdBQUE7QUFDRixVQUFBLEtBQUE7O1FBQUEsSUFBQyxDQUFBLGtCQUFtQjtPQUFwQjs7YUFDaUIsQ0FBQSxLQUFBLElBQVU7T0FEM0I7YUFFQSxJQUFDLENBQUEsZUFBZ0IsQ0FBQSxLQUFBLENBQU0sQ0FBQyxJQUF4QixDQUE2QixDQUE3QixFQUhFO0lBQUEsQ0FiSixDQUFBOztBQUFBLHdCQXNCQSxTQUFBLEdBQVcsU0FBQyxL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LENBN0pqQixDQUFBO0FBQUEsRUF3S0EsS0FBTSxDQUFBLFlBQUEsQ0FBTixHQUFzQixVQXhLdEIsQ0FBQTtBQUFBLEVBeUtBLEtBQU0sQ0FBQSxZQUFBLENBQU4sR0FBc0IsVUF6S3RCLENBQUE7QUFBQSxFQTBLQSxLQUFNLENBQUEsTUFBQSxDQUFOLEdBQWdCLElBMUtoQixDQUFBO1NBMktBLGlCQTVLZTtBQUFBLENBRmpCLENBQUEiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKX12YXIgZj1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwoZi5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxmLGYuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwibW9kdWxlLmV4cG9ydHMgPSAoSEIpLT5cbiAgIyBAc2VlIEVuZ2luZS5wYXJzZVxuICBwYXJzZXIgPSB7fVxuICBleGVjdXRpb25fbGlzdGVuZXIgPSBbXVxuXG4gICNcbiAgIyBBIGdlbmVyaWMgaW50ZXJmYWNlIHRvIG9wZXJhdGlvbnMuXG4gICNcbiAgIyBBbiBvcGVyYXRpb24gaGFzIHRoZSBmb2xsb3dpbmcgbWV0aG9kczpcbiAgIyBfZW5jb2RlOiBlbmNvZGVzIGFuIG9wZXJhdGlvbiAobmVlZGVkIG9ubHkgaWYgaW5zdGFuY2Ugb2YgdGhpcyBvcGVyYXRpb24gaXMgc2VudCkuXG4gICMgZXhlY3V0ZTogZXhlY3V0ZSB0aGUgZWZmZWN0cyBvZiB0aGlzIG9wZXJhdGlvbnMuIEdvb2QgZXhhbXBsZXMgYXJlIEluc2VydC10eXBlIGFuZCBBZGROYW1lLXR5cGVcbiAgIyB2YWw6IGluIHRoZSBjYXNlIHRoYXQgdGhlIG9wZXJhdGlvbiBob2xkcyBhIHZhbHVlXG4gICNcbiAgIyBGdXJ0aGVybW9yZSBhbiBlbmNvZGFibGUgb3BlcmF0aW9uIGhhcyBhIHBhcnNlci5cbiAgI1xuICBjbGFzcyBPcGVyYXRpb25cblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBzZWUgSGlzdG9yeUJ1ZmZlci5nZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllclxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCktPlxuICAgICAgaWYgbm90IHVpZD9cbiAgICAgICAgdWlkID0gSEIuZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXIoKVxuICAgICAge1xuICAgICAgICAnY3JlYXRvcic6IEBjcmVhdG9yXG4gICAgICAgICdvcF9udW1iZXInIDogQG9wX251bWJlclxuICAgICAgfSA9IHVpZFxuXG4gICAgI1xuICAgICMgQWRkIGFuIGV2ZW50IGxpc3RlbmVyLiBJdCBkZXBlbmRzIG9uIHRoZSBvcGVyYXRpb24gd2hpY2ggZXZlbnRzIGFyZSBzdXBwb3J0ZWQuXG4gICAgIyBAcGFyYW0ge1N0cmluZ30gZXZlbnQgTmFtZSBvZiB0aGUgZXZlbnQuXG4gICAgIyBAcGFyYW0ge0Z1bmN0aW9ufSBmIGYgaXMgZXhlY3V0ZWQgaW4gY2FzZSB0aGUgZXZlbnQgZmlyZXMuXG4gICAgI1xuICAgIG9uOiAoZXZlbnQsIGYpLT5cbiAgICAgIEBldmVudF9saXN0ZW5lcnMgPz0ge31cbiAgICAgIEBldmVudF9saXN0ZW5lcnNbZXZlbnRdID89IFtdXG4gICAgICBAZXZlbnRfbGlzdGVuZXJzW2V2ZW50XS5wdXNoIGZcblxuICAgICNcbiAgICAjIEZpcmUgYW4gZXZlbnQuXG4gICAgIyBUT0RPOiBEbyBzb21ldGhpbmcgd2l0aCB0aW1lb3V0cy4gWW91IGRvbid0IHdhbnQgdGhpcyB0byBmaXJlIGZvciBldmVyeSBvcGVyYXRpb24gKGUuZy4gaW5zZXJ0KS5cbiAgICAjXG4gICAgY2FsbEV2ZW50OiAoZXZlbnQsIGFyZ3MpLT5cbiAgICAgIGlmIEBldmVudF9saXN0ZW5lcnNbZXZlbnRdP1xuICAgICAgICBmb3IgZiBpbiBAZXZlbnRfbGlzdGVuZXJzW2V2ZW50XVxuICAgICAgICAgIGYuY2FsbCBALCBldmVudCwgYXJnc1xuXG4gICAgI1xuICAgICMgU2V0IHRoZSBwYXJlbnQgb2YgdGhpcyBvcGVyYXRpb24uXG4gICAgI1xuICAgIHNldFBhcmVudDogKG8pLT5cbiAgICAgIEBwYXJlbnQgPSBvXG5cbiAgICAjXG4gICAgIyBDb21wdXRlcyBhIHVuaXF1ZSBpZGVudGlmaWVyICh1aWQpIHRoYXQgaWRlbnRpZmllcyB0aGlzIG9wZXJhdGlvbi5cbiAgICAjXG4gICAgZ2V0VWlkOiAoKS0+XG4gICAgICB7ICdjcmVhdG9yJzogQGNyZWF0b3IsICdvcF9udW1iZXInOiBAb3BfbnVtYmVyIH1cblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBOb3RpZnkgdGhlIGFsbCB0aGUgbGlzdGVuZXJzLlxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBAaXNfZXhlY3V0ZWQgPSB0cnVlXG4gICAgICBmb3IgbCBpbiBleGVjdXRpb25fbGlzdGVuZXJcbiAgICAgICAgbCBAX2VuY29kZSgpXG4gICAgICBAXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgT3BlcmF0aW9ucyBtYXkgZGVwZW5kIG9uIG90aGVyIG9wZXJhdGlvbnMgKGxpbmtlZCBsaXN0cywgZXRjLikuXG4gICAgIyBUaGUgc2F2ZU9wZXJhdGlvbiBhbmQgdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMgbWV0aG9kcyBwcm92aWRlXG4gICAgIyBhbiBlYXN5IHdheSB0byByZWZlciB0byB0aGVzZSBvcGVyYXRpb25zIHZpYSBhbiB1aWQgb3Igb2JqZWN0IHJlZmVyZW5jZS5cbiAgICAjXG4gICAgIyBGb3IgZXhhbXBsZTogV2UgY2FuIGNyZWF0ZSBhIG5ldyBEZWxldGUgb3BlcmF0aW9uIHRoYXQgZGVsZXRlcyB0aGUgb3BlcmF0aW9uICRvIGxpa2UgdGhpc1xuICAgICMgICAgIC0gdmFyIGQgPSBuZXcgRGVsZXRlKHVpZCwgJG8pOyAgIG9yXG4gICAgIyAgICAgLSB2YXIgZCA9IG5ldyBEZWxldGUodWlkLCAkby5nZXRVaWQoKSk7XG4gICAgIyBFaXRoZXIgd2F5IHdlIHdhbnQgdG8gYWNjZXNzICRvIHZpYSBkLmRlbGV0ZXMuIEluIHRoZSBzZWNvbmQgY2FzZSB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucyBtdXN0IGJlIGNhbGxlZCBmaXJzdC5cbiAgICAjXG4gICAgIyBAb3ZlcmxvYWQgc2F2ZU9wZXJhdGlvbihuYW1lLCBvcF91aWQpXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpb24uIEFmdGVyIHZhbGlkYXRpbmcgKHdpdGggdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMpIHRoZSBpbnN0YW50aWF0ZWQgb3BlcmF0aW9uIHdpbGwgYmUgYWNjZXNzaWJsZSB2aWEgdGhpc1tuYW1lXS5cbiAgICAjICAgQHBhcmFtIHtPYmplY3R9IG9wX3VpZCBBIHVpZCB0aGF0IHJlZmVycyB0byBhbiBvcGVyYXRpb25cbiAgICAjIEBvdmVybG9hZCBzYXZlT3BlcmF0aW9uKG5hbWUsIG9wKVxuICAgICMgICBAcGFyYW0ge1N0cmluZ30gbmFtZSBUaGUgbmFtZSBvZiB0aGUgb3BlcmF0aW9uLiBBZnRlciBjYWxsaW5nIHRoaXMgZnVuY3Rpb24gb3AgaXMgYWNjZXNzaWJsZSB2aWEgdGhpc1tuYW1lXS5cbiAgICAjICAgQHBhcmFtIHtPcGVyYXRpb259IG9wIEFuIE9wZXJhdGlvbiBvYmplY3RcbiAgICAjXG4gICAgc2F2ZU9wZXJhdGlvbjogKG5hbWUsIG9wKS0+XG5cbiAgICAgICNcbiAgICAgICMgRXZlcnkgaW5zdGFuY2Ugb2YgJE9wZXJhdGlvbiBtdXN0IGhhdmUgYW4gJGV4ZWN1dGUgZnVuY3Rpb24uXG4gICAgICAjIFdlIHVzZSBkdWNrLXR5cGluZyB0byBjaGVjayBpZiBvcCBpcyBpbnN0YW50aWF0ZWQgc2luY2UgdGhlcmVcbiAgICAgICMgY291bGQgZXhpc3QgbXVsdGlwbGUgY2xhc3NlcyBvZiAkT3BlcmF0aW9uXG4gICAgICAjXG4gICAgICBpZiBvcD8uZXhlY3V0ZT9cbiAgICAgICAgIyBpcyBpbnN0YW50aWF0ZWRcbiAgICAgICAgQFtuYW1lXSA9IG9wXG4gICAgICBlbHNlIGlmIG9wP1xuICAgICAgICAjIG5vdCBpbml0aWFsaXplZC4gRG8gaXQgd2hlbiBjYWxsaW5nICR2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIEB1bmNoZWNrZWQgPz0ge31cbiAgICAgICAgQHVuY2hlY2tlZFtuYW1lXSA9IG9wXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgQWZ0ZXIgY2FsbGluZyB0aGlzIGZ1bmN0aW9uIGFsbCBub3QgaW5zdGFudGlhdGVkIG9wZXJhdGlvbnMgd2lsbCBiZSBhY2Nlc3NpYmxlLlxuICAgICMgQHNlZSBPcGVyYXRpb24uc2F2ZU9wZXJhdGlvblxuICAgICNcbiAgICAjIEByZXR1cm4gW0Jvb2xlYW5dIFdoZXRoZXIgaXQgd2FzIHBvc3NpYmxlIHRvIGluc3RhbnRpYXRlIGFsbCBvcGVyYXRpb25zLlxuICAgICNcbiAgICB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9uczogKCktPlxuICAgICAgdW5pbnN0YW50aWF0ZWQgPSB7fVxuICAgICAgc3VjY2VzcyA9IEBcbiAgICAgIGZvciBuYW1lLCBvcF91aWQgb2YgQHVuY2hlY2tlZFxuICAgICAgICBvcCA9IEhCLmdldE9wZXJhdGlvbiBvcF91aWRcbiAgICAgICAgaWYgb3BcbiAgICAgICAgICBAW25hbWVdID0gb3BcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHVuaW5zdGFudGlhdGVkW25hbWVdID0gb3BfdWlkXG4gICAgICAgICAgc3VjY2VzcyA9IGZhbHNlXG4gICAgICBkZWxldGUgQHVuY2hlY2tlZFxuICAgICAgaWYgbm90IHN1Y2Nlc3NcbiAgICAgICAgQHVuY2hlY2tlZCA9IHVuaW5zdGFudGlhdGVkXG4gICAgICBzdWNjZXNzXG5cblxuXG4gICNcbiAgIyBBIHNpbXBsZSBEZWxldGUtdHlwZSBvcGVyYXRpb24gdGhhdCBkZWxldGVzIGFuIEluc2VydC10eXBlIG9wZXJhdGlvbi5cbiAgI1xuICBjbGFzcyBEZWxldGUgZXh0ZW5kcyBPcGVyYXRpb25cblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSBkZWxldGVzIFVJRCBvciByZWZlcmVuY2Ugb2YgdGhlIG9wZXJhdGlvbiB0aGF0IHRoaXMgdG8gYmUgZGVsZXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIGRlbGV0ZXMpLT5cbiAgICAgIEBzYXZlT3BlcmF0aW9uICdkZWxldGVzJywgZGVsZXRlc1xuICAgICAgc3VwZXIgdWlkXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgQ29udmVydCBhbGwgcmVsZXZhbnQgaW5mb3JtYXRpb24gb2YgdGhpcyBvcGVyYXRpb24gdG8gdGhlIGpzb24tZm9ybWF0LlxuICAgICMgVGhpcyByZXN1bHQgY2FuIGJlIHNlbnQgdG8gb3RoZXIgY2xpZW50cy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAge1xuICAgICAgICAndHlwZSc6IFwiRGVsZXRlXCJcbiAgICAgICAgJ3VpZCc6IEBnZXRVaWQoKVxuICAgICAgICAnZGVsZXRlcyc6IEBkZWxldGVzLmdldFVpZCgpXG4gICAgICB9XG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgQXBwbHkgdGhlIGRlbGV0aW9uLlxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICBAZGVsZXRlcy5hcHBseURlbGV0ZSBAXG4gICAgICAgIHN1cGVyXG4gICAgICAgIEBcbiAgICAgIGVsc2VcbiAgICAgICAgZmFsc2VcblxuICAjXG4gICMgRGVmaW5lIGhvdyB0byBwYXJzZSBEZWxldGUgb3BlcmF0aW9ucy5cbiAgI1xuICBwYXJzZXJbJ0RlbGV0ZSddID0gKG8pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ2RlbGV0ZXMnOiBkZWxldGVzX3VpZFxuICAgIH0gPSBvXG4gICAgbmV3IERlbGV0ZSB1aWQsIGRlbGV0ZXNfdWlkXG5cbiAgI1xuICAjIEEgc2ltcGxlIGluc2VydC10eXBlIG9wZXJhdGlvbi5cbiAgI1xuICAjIEFuIGluc2VydCBvcGVyYXRpb24gaXMgYWx3YXlzIHBvc2l0aW9uZWQgYmV0d2VlbiB0d28gb3RoZXIgaW5zZXJ0IG9wZXJhdGlvbnMuXG4gICMgSW50ZXJuYWxseSB0aGlzIGlzIHJlYWxpemVkIGFzIGFzc29jaWF0aXZlIGxpc3RzLCB3aGVyZWJ5IGVhY2ggaW5zZXJ0IG9wZXJhdGlvbiBoYXMgYSBwcmVkZWNlc3NvciBhbmQgYSBzdWNjZXNzb3IuXG4gICMgRm9yIHRoZSBzYWtlIG9mIGVmZmljaWVuY3kgd2UgbWFpbnRhaW4gdHdvIGxpc3RzOlxuICAjICAgLSBUaGUgc2hvcnQtbGlzdCAoYWJicmV2LiBzbCkgbWFpbnRhaW5zIG9ubHkgdGhlIG9wZXJhdGlvbnMgdGhhdCBhcmUgbm90IGRlbGV0ZWRcbiAgIyAgIC0gVGhlIGNvbXBsZXRlLWxpc3QgKGFiYnJldi4gY2wpIG1haW50YWlucyBhbGwgb3BlcmF0aW9uc1xuICAjXG4gIGNsYXNzIEluc2VydCBleHRlbmRzIE9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IHByZXZfY2wgVGhlIHByZWRlY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBuZXh0X2NsIFRoZSBzdWNjZXNzb3Igb2YgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGNvbXBsZXRlLWxpc3QgKGNsKVxuICAgICNcbiAgICAjIEBzZWUgSGlzdG9yeUJ1ZmZlci5nZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllclxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgcHJldl9jbCwgbmV4dF9jbCwgb3JpZ2luKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncHJldl9jbCcsIHByZXZfY2xcbiAgICAgIEBzYXZlT3BlcmF0aW9uICduZXh0X2NsJywgbmV4dF9jbFxuICAgICAgaWYgb3JpZ2luP1xuICAgICAgICBAc2F2ZU9wZXJhdGlvbiAnb3JpZ2luJywgb3JpZ2luXG4gICAgICBlbHNlXG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBwcmV2X2NsXG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgI1xuICAgIGFwcGx5RGVsZXRlOiAobyktPlxuICAgICAgQGRlbGV0ZWRfYnkgPz0gW11cbiAgICAgIEBkZWxldGVkX2J5LnB1c2ggb1xuXG4gICAgI1xuICAgICMgSWYgaXNEZWxldGVkKCkgaXMgdHJ1ZSB0aGlzIG9wZXJhdGlvbiB3b24ndCBiZSBtYWludGFpbmVkIGluIHRoZSBzbFxuICAgICNcbiAgICBpc0RlbGV0ZWQ6ICgpLT5cbiAgICAgIEBkZWxldGVkX2J5Py5sZW5ndGggPiAwXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgVGhlIGFtb3VudCBvZiBwb3NpdGlvbnMgdGhhdCAkdGhpcyBvcGVyYXRpb24gd2FzIG1vdmVkIHRvIHRoZSByaWdodC5cbiAgICAjXG4gICAgZ2V0RGlzdGFuY2VUb09yaWdpbjogKCktPlxuICAgICAgZCA9IDBcbiAgICAgIG8gPSBAcHJldl9jbFxuICAgICAgd2hpbGUgdHJ1ZVxuICAgICAgICBpZiBAb3JpZ2luIGlzIG9cbiAgICAgICAgICBicmVha1xuICAgICAgICBkKytcbiAgICAgICAgI1RPRE86IGRlbGV0ZSB0aGlzXG4gICAgICAgIGlmIEAgaXMgQHByZXZfY2xcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJ0aGlzIHNob3VsZCBub3QgaGFwcGVuIDspIFwiXG4gICAgICAgIG8gPSBvLnByZXZfY2xcbiAgICAgIGRcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBVcGRhdGUgdGhlIHNob3J0IGxpc3RcbiAgICAjIFRPRE8gKFVudXNlZClcbiAgICB1cGRhdGVfc2w6ICgpLT5cbiAgICAgIG8gPSBAcHJldl9jbFxuICAgICAgdXBkYXRlOiAoZGVzdF9jbCxkZXN0X3NsKS0+XG4gICAgICAgIHdoaWxlIHRydWVcbiAgICAgICAgICBpZiBvLmlzRGVsZXRlZCgpXG4gICAgICAgICAgICBvID0gb1tkZXN0X2NsXVxuICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgIEBbZGVzdF9zbF0gPSBvXG5cbiAgICAgICAgICAgIGJyZWFrXG4gICAgICB1cGRhdGUgXCJwcmV2X2NsXCIsIFwicHJldl9zbFwiXG4gICAgICB1cGRhdGUgXCJuZXh0X2NsXCIsIFwicHJldl9zbFwiXG5cblxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIEluY2x1ZGUgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGFzc29jaWF0aXZlIGxpc3RzLlxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBAaXNfZXhlY3V0ZWQ/XG4gICAgICAgIHJldHVybiBAXG4gICAgICBpZiBub3QgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICBlbHNlXG4gICAgICAgIGlmIEBwcmV2X2NsPy52YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpIGFuZCBAbmV4dF9jbD8udmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKSBhbmQgQHByZXZfY2wubmV4dF9jbCBpc250IEBcbiAgICAgICAgICBkaXN0YW5jZV90b19vcmlnaW4gPSAwXG4gICAgICAgICAgbyA9IEBwcmV2X2NsLm5leHRfY2xcbiAgICAgICAgICBpID0gMFxuICAgICAgICAgICMgJHRoaXMgaGFzIHRvIGZpbmQgYSB1bmlxdWUgcG9zaXRpb24gYmV0d2VlbiBvcmlnaW4gYW5kIHRoZSBuZXh0IGtub3duIGNoYXJhY3RlclxuICAgICAgICAgICMgY2FzZSAxOiAkb3JpZ2luIGVxdWFscyAkby5vcmlnaW46IHRoZSAkY3JlYXRvciBwYXJhbWV0ZXIgZGVjaWRlcyBpZiBsZWZ0IG9yIHJpZ2h0XG4gICAgICAgICAgIyAgICAgICAgIGxldCAkT0w9IFtvMSxvMixvMyxvNF0sIHdoZXJlYnkgJHRoaXMgaXMgdG8gYmUgaW5zZXJ0ZWQgYmV0d2VlbiBvMSBhbmQgbzRcbiAgICAgICAgICAjICAgICAgICAgbzIsbzMgYW5kIG80IG9yaWdpbiBpcyAxICh0aGUgcG9zaXRpb24gb2YgbzIpXG4gICAgICAgICAgIyAgICAgICAgIHRoZXJlIGlzIHRoZSBjYXNlIHRoYXQgJHRoaXMuY3JlYXRvciA8IG8yLmNyZWF0b3IsIGJ1dCBvMy5jcmVhdG9yIDwgJHRoaXMuY3JlYXRvclxuICAgICAgICAgICMgICAgICAgICB0aGVuIG8yIGtub3dzIG8zLiBTaW5jZSBvbiBhbm90aGVyIGNsaWVudCAkT0wgY291bGQgYmUgW28xLG8zLG80XSB0aGUgcHJvYmxlbSBpcyBjb21wbGV4XG4gICAgICAgICAgIyAgICAgICAgIHRoZXJlZm9yZSAkdGhpcyB3b3VsZCBiZSBhbHdheXMgdG8gdGhlIHJpZ2h0IG9mIG8zXG4gICAgICAgICAgIyBjYXNlIDI6ICRvcmlnaW4gPCAkby5vcmlnaW5cbiAgICAgICAgICAjICAgICAgICAgaWYgY3VycmVudCAkdGhpcyBpbnNlcnRfcG9zaXRpb24gPiAkbyBvcmlnaW46ICR0aGlzIGluc1xuICAgICAgICAgICMgICAgICAgICBlbHNlICRpbnNlcnRfcG9zaXRpb24gd2lsbCBub3QgY2hhbmdlIChtYXliZSB3ZSBlbmNvdW50ZXIgY2FzZSAxIGxhdGVyLCB0aGVuIHRoaXMgd2lsbCBiZSB0byB0aGUgcmlnaHQgb2YgJG8pXG4gICAgICAgICAgIyBjYXNlIDM6ICRvcmlnaW4gPiAkby5vcmlnaW5cbiAgICAgICAgICAjICAgICAgICAgJHRoaXMgaW5zZXJ0X3Bvc2l0aW9uIGlzIHRvIHRoZSBsZWZ0IG9mICRvIChmb3JldmVyISlcbiAgICAgICAgICB3aGlsZSB0cnVlXG4gICAgICAgICAgICBpZiBub3Qgbz9cbiAgICAgICAgICAgICAgIyBUT0RPOiBEZWJ1Z2dpbmdcbiAgICAgICAgICAgICAgY29uc29sZS5sb2cgSlNPTi5zdHJpbmdpZnkgQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgICAgICAgICAgY29uc29sZS5sb2cgSlNPTi5zdHJpbmdpZnkgQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgICAgICAgIGlmIG8gaXNudCBAbmV4dF9jbFxuICAgICAgICAgICAgICAjICRvIGhhcHBlbmVkIGNvbmN1cnJlbnRseVxuICAgICAgICAgICAgICBpZiBvLmdldERpc3RhbmNlVG9PcmlnaW4oKSBpcyBpXG4gICAgICAgICAgICAgICAgIyBjYXNlIDFcbiAgICAgICAgICAgICAgICBpZiBvLmNyZWF0b3IgPCBAY3JlYXRvclxuICAgICAgICAgICAgICAgICAgQHByZXZfY2wgPSBvXG4gICAgICAgICAgICAgICAgICBkaXN0YW5jZV90b19vcmlnaW4gPSBpICsgMVxuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICMgbm9wXG4gICAgICAgICAgICAgIGVsc2UgaWYgby5nZXREaXN0YW5jZVRvT3JpZ2luKCkgPCBpXG4gICAgICAgICAgICAgICAgIyBjYXNlIDJcbiAgICAgICAgICAgICAgICBpZiBpIC0gZGlzdGFuY2VfdG9fb3JpZ2luIDw9IG8uZ2V0RGlzdGFuY2VUb09yaWdpbigpXG4gICAgICAgICAgICAgICAgICBAcHJldl9jbCA9IG9cbiAgICAgICAgICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IGkgKyAxXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgI25vcFxuICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgIyBjYXNlIDNcbiAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICBpKytcbiAgICAgICAgICAgICAgbyA9IG8ubmV4dF9jbFxuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAjICR0aGlzIGtub3dzIHRoYXQgJG8gZXhpc3RzLFxuICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICMgbm93IHJlY29ubmVjdCBldmVyeXRoaW5nXG4gICAgICAgICAgQG5leHRfY2wgPSBAcHJldl9jbC5uZXh0X2NsXG4gICAgICAgICAgQHByZXZfY2wubmV4dF9jbCA9IEBcbiAgICAgICAgICBAbmV4dF9jbC5wcmV2X2NsID0gQFxuICAgICAgICBzdXBlciAjIG5vdGlmeSB0aGUgZXhlY3V0aW9uX2xpc3RlbmVyc1xuICAgICAgICBAXG5cbiAgI1xuICAjIERlZmluZXMgYW4gb2JqZWN0IHRoYXQgaXMgY2Fubm90IGJlIGNoYW5nZWQuIFlvdSBjYW4gdXNlIHRoaXMgdG8gc2V0IGFuIGltbXV0YWJsZSBzdHJpbmcsIG9yIGEgbnVtYmVyLlxuICAjXG4gIGNsYXNzIEltbXV0YWJsZU9iamVjdCBleHRlbmRzIEluc2VydFxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IGNvbnRlbnRcbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIEBjb250ZW50LCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIHN1cGVyIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cbiAgICAjXG4gICAgIyBAcmV0dXJuIFtTdHJpbmddIFRoZSBjb250ZW50IG9mIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICB2YWwgOiAoKS0+XG4gICAgICBAY29udGVudFxuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9IHtcbiAgICAgICAgJ3R5cGUnOiBcIkltbXV0YWJsZU9iamVjdFwiXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICdjb250ZW50JyA6IEBjb250ZW50XG4gICAgICB9XG4gICAgICBpZiBAcHJldl9jbD9cbiAgICAgICAganNvblsncHJldiddID0gQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgIGlmIEBuZXh0X2NsP1xuICAgICAgICBqc29uWyduZXh0J10gPSBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgaWYgQG9yaWdpbj8gYW5kIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uW1wib3JpZ2luXCJdID0gQG9yaWdpbi5nZXRVaWQoKVxuICAgICAganNvblxuXG4gIHBhcnNlclsnSW1tdXRhYmxlT2JqZWN0J10gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAnY29udGVudCcgOiBjb250ZW50XG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBJbW11dGFibGVPYmplY3QgdWlkLCBjb250ZW50LCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICAjXG4gICMgQSBkZWxpbWl0ZXIgaXMgcGxhY2VkIGF0IHRoZSBlbmQgYW5kIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGFzc29jaWF0aXZlIGxpc3RzLlxuICAjIFRoaXMgaXMgbmVjZXNzYXJ5IGluIG9yZGVyIHRvIGhhdmUgYSBiZWdpbm5pbmcgYW5kIGFuIGVuZCBldmVuIGlmIHRoZSBjb250ZW50XG4gICMgb2YgdGhlIEVuZ2luZSBpcyBlbXB0eS5cbiAgI1xuICBjbGFzcyBEZWxpbWl0ZXIgZXh0ZW5kcyBPcGVyYXRpb25cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gcHJldl9jbCBUaGUgcHJlZGVjZXNzb3Igb2YgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGNvbXBsZXRlLWxpc3QgKGNsKVxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG5leHRfY2wgVGhlIHN1Y2Nlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgI1xuICAgICMgQHNlZSBIaXN0b3J5QnVmZmVyLmdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBwcmV2X2NsLCBuZXh0X2NsLCBvcmlnaW4pLT5cbiAgICAgIEBzYXZlT3BlcmF0aW9uICdwcmV2X2NsJywgcHJldl9jbFxuICAgICAgQHNhdmVPcGVyYXRpb24gJ25leHRfY2wnLCBuZXh0X2NsXG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnb3JpZ2luJywgcHJldl9jbFxuICAgICAgc3VwZXIgdWlkXG5cbiAgICAjXG4gICAgIyBJZiBpc0RlbGV0ZWQoKSBpcyB0cnVlIHRoaXMgb3BlcmF0aW9uIHdvbid0IGJlIG1haW50YWluZWQgaW4gdGhlIHNsXG4gICAgI1xuICAgIGlzRGVsZXRlZDogKCktPlxuICAgICAgZmFsc2VcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEB1bmNoZWNrZWQ/WyduZXh0X2NsJ10/XG4gICAgICAgIHN1cGVyXG4gICAgICBlbHNlIGlmIEB1bmNoZWNrZWQ/WydwcmV2X2NsJ11cbiAgICAgICAgaWYgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgICBpZiBAcHJldl9jbC5uZXh0X2NsP1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiUHJvYmFibHkgZHVwbGljYXRlZCBvcGVyYXRpb25zXCJcbiAgICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxuICAgICAgICAgIGRlbGV0ZSBAcHJldl9jbC51bmNoZWNrZWQubmV4dF9jbFxuICAgICAgICAgIHN1cGVyXG4gICAgICAgIGVsc2VcbiAgICAgICAgICBmYWxzZVxuICAgICAgZWxzZSBpZiBAcHJldl9jbD8gYW5kIG5vdCBAcHJldl9jbC5uZXh0X2NsP1xuICAgICAgICBkZWxldGUgQHByZXZfY2wudW5jaGVja2VkLm5leHRfY2xcbiAgICAgICAgQHByZXZfY2wubmV4dF9jbCA9IEBcbiAgICAgIGVsc2UgaWYgQHByZXZfY2w/IG9yIEBuZXh0X2NsP1xuICAgICAgICBzdXBlclxuICAgICAgZWxzZVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJEZWxpbWl0ZXIgaXMgdW5zdWZmaWNpZW50IGRlZmluZWQhXCJcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIHtcbiAgICAgICAgJ3R5cGUnIDogXCJEZWxpbWl0ZXJcIlxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAncHJldicgOiBAcHJldl9jbD8uZ2V0VWlkKClcbiAgICAgICAgJ25leHQnIDogQG5leHRfY2w/LmdldFVpZCgpXG4gICAgICB9XG5cbiAgcGFyc2VyWydEZWxpbWl0ZXInXSA9IChqc29uKS0+XG4gICAge1xuICAgICd1aWQnIDogdWlkXG4gICAgJ3ByZXYnIDogcHJldlxuICAgICduZXh0JyA6IG5leHRcbiAgICB9ID0ganNvblxuICAgIG5ldyBEZWxpbWl0ZXIgdWlkLCBwcmV2LCBuZXh0XG5cbiAgIyBUaGlzIGlzIHdoYXQgdGhpcyBtb2R1bGUgZXhwb3J0cyBhZnRlciBpbml0aWFsaXppbmcgaXQgd2l0aCB0aGUgSGlzdG9yeUJ1ZmZlclxuICB7XG4gICAgJ3R5cGVzJyA6XG4gICAgICAnRGVsZXRlJyA6IERlbGV0ZVxuICAgICAgJ0luc2VydCcgOiBJbnNlcnRcbiAgICAgICdEZWxpbWl0ZXInOiBEZWxpbWl0ZXJcbiAgICAgICdPcGVyYXRpb24nOiBPcGVyYXRpb25cbiAgICAgICdJbW11dGFibGVPYmplY3QnIDogSW1tdXRhYmxlT2JqZWN0XG4gICAgJ3BhcnNlcicgOiBwYXJzZXJcbiAgICAnZXhlY3V0aW9uX2xpc3RlbmVyJyA6IGV4ZWN1dGlvbl9saXN0ZW5lclxuICB9XG5cblxuXG5cbiIsImJhc2ljX3R5cGVzX3VuaW5pdGlhbGl6ZWQgPSByZXF1aXJlIFwiLi9CYXNpY1R5cGVzXCJcblxubW9kdWxlLmV4cG9ydHMgPSAoSEIpLT5cbiAgYmFzaWNfdHlwZXMgPSBiYXNpY190eXBlc191bmluaXRpYWxpemVkIEhCXG4gIHR5cGVzID0gYmFzaWNfdHlwZXMudHlwZXNcbiAgcGFyc2VyID0gYmFzaWNfdHlwZXMucGFyc2VyXG5cbiAgI1xuICAjIE1hbmFnZXMgbWFwIGxpa2Ugb2JqZWN0cy4gRS5nLiBKc29uLVR5cGUgYW5kIFhNTCBhdHRyaWJ1dGVzLlxuICAjXG4gIGNsYXNzIE1hcE1hbmFnZXIgZXh0ZW5kcyB0eXBlcy5PcGVyYXRpb25cblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQpLT5cbiAgICAgIEBtYXAgPSB7fVxuICAgICAgc3VwZXIgdWlkXG5cbiAgICAjXG4gICAgIyBAc2VlIEpzb25UeXBlcy52YWxcbiAgICAjXG4gICAgdmFsOiAobmFtZSwgY29udGVudCktPlxuICAgICAgaWYgY29udGVudD9cbiAgICAgICAgaWYgbm90IEBtYXBbbmFtZV0/XG4gICAgICAgICAgSEIuYWRkT3BlcmF0aW9uKG5ldyBBZGROYW1lIHVuZGVmaW5lZCwgQCwgbmFtZSkuZXhlY3V0ZSgpXG4gICAgICAgIEBtYXBbbmFtZV0ucmVwbGFjZSBjb250ZW50XG4gICAgICAgIEBcbiAgICAgIGVsc2UgaWYgbmFtZT9cbiAgICAgICAgb2JqID0gQG1hcFtuYW1lXT8udmFsKClcbiAgICAgICAgaWYgb2JqIGluc3RhbmNlb2YgdHlwZXMuSW1tdXRhYmxlT2JqZWN0XG4gICAgICAgICAgb2JqLnZhbCgpXG4gICAgICAgIGVsc2VcbiAgICAgICAgICBvYmpcbiAgICAgIGVsc2VcbiAgICAgICAgcmVzdWx0ID0ge31cbiAgICAgICAgZm9yIG5hbWUsbyBvZiBAbWFwXG4gICAgICAgICAgb2JqID0gby52YWwoKVxuICAgICAgICAgIGlmIG9iaiBpbnN0YW5jZW9mIHR5cGVzLkltbXV0YWJsZU9iamVjdCBvciBvYmogaW5zdGFuY2VvZiBNYXBNYW5hZ2VyXG4gICAgICAgICAgICBvYmogPSBvYmoudmFsKClcbiAgICAgICAgICByZXN1bHRbbmFtZV0gPSBvYmpcbiAgICAgICAgcmVzdWx0XG5cbiAgI1xuICAjIFdoZW4gYSBuZXcgcHJvcGVydHkgaW4gYSBtYXAgbWFuYWdlciBpcyBjcmVhdGVkLCB0aGVuIHRoZSB1aWRzIG9mIHRoZSBpbnNlcnRlZCBPcGVyYXRpb25zXG4gICMgbXVzdCBiZSB1bmlxdWUgKHRoaW5rIGFib3V0IGNvbmN1cnJlbnQgb3BlcmF0aW9ucykuIFRoZXJlZm9yZSBvbmx5IGFuIEFkZE5hbWUgb3BlcmF0aW9uIGlzIGFsbG93ZWQgdG9cbiAgIyBhZGQgYSBwcm9wZXJ0eSBpbiBhIE1hcE1hbmFnZXIuIElmIHR3byBBZGROYW1lIG9wZXJhdGlvbnMgb24gdGhlIHNhbWUgTWFwTWFuYWdlciBuYW1lIGhhcHBlbiBjb25jdXJyZW50bHlcbiAgIyBvbmx5IG9uZSB3aWxsIEFkZE5hbWUgb3BlcmF0aW9uIHdpbGwgYmUgZXhlY3V0ZWQuXG4gICNcbiAgY2xhc3MgQWRkTmFtZSBleHRlbmRzIHR5cGVzLk9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IG1hcF9tYW5hZ2VyIFVpZCBvciByZWZlcmVuY2UgdG8gdGhlIE1hcE1hbmFnZXIuXG4gICAgIyBAcGFyYW0ge1N0cmluZ30gbmFtZSBOYW1lIG9mIHRoZSBwcm9wZXJ0eSB0aGF0IHdpbGwgYmUgYWRkZWQuXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBtYXBfbWFuYWdlciwgQG5hbWUpLT5cbiAgICAgIEBzYXZlT3BlcmF0aW9uICdtYXBfbWFuYWdlcicsIG1hcF9tYW5hZ2VyXG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIElmIG1hcF9tYW5hZ2VyIGRvZXNuJ3QgaGF2ZSB0aGUgcHJvcGVydHkgbmFtZSwgdGhlbiBhZGQgaXQuXG4gICAgIyBUaGUgUmVwbGFjZU1hbmFnZXIgdGhhdCBpcyBiZWluZyB3cml0dGVuIG9uIHRoZSBwcm9wZXJ0eSBpcyB1bmlxdWVcbiAgICAjIGluIHN1Y2ggYSB3YXkgdGhhdCBpZiBBZGROYW1lIGlzIGV4ZWN1dGVkIChmcm9tIGFub3RoZXIgcGVlcikgaXQgd2lsbFxuICAgICMgYWx3YXlzIGhhdmUgdGhlIHNhbWUgcmVzdWx0IChSZXBsYWNlTWFuYWdlciwgYW5kIGl0cyBiZWdpbm5pbmcgYW5kIGVuZCBhcmUgdGhlIHNhbWUpXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIG5vdCBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIGVsc2VcbiAgICAgICAgdWlkX3IgPSBAbWFwX21hbmFnZXIuZ2V0VWlkKClcbiAgICAgICAgdWlkX3Iub3BfbnVtYmVyID0gXCJfI3t1aWRfci5vcF9udW1iZXJ9X1JNXyN7QG5hbWV9XCJcbiAgICAgICAgaWYgbm90IEhCLmdldE9wZXJhdGlvbih1aWRfcik/XG4gICAgICAgICAgdWlkX2JlZyA9IEBtYXBfbWFuYWdlci5nZXRVaWQoKVxuICAgICAgICAgIHVpZF9iZWcub3BfbnVtYmVyID0gXCJfI3t1aWRfYmVnLm9wX251bWJlcn1fUk1fI3tAbmFtZX1fYmVnaW5uaW5nXCJcbiAgICAgICAgICB1aWRfZW5kID0gQG1hcF9tYW5hZ2VyLmdldFVpZCgpXG4gICAgICAgICAgdWlkX2VuZC5vcF9udW1iZXIgPSBcIl8je3VpZF9lbmQub3BfbnVtYmVyfV9STV8je0BuYW1lfV9lbmRcIlxuICAgICAgICAgIGJlZyA9IEhCLmFkZE9wZXJhdGlvbihuZXcgdHlwZXMuRGVsaW1pdGVyIHVpZF9iZWcsIHVuZGVmaW5lZCwgdWlkX2VuZCkuZXhlY3V0ZSgpXG4gICAgICAgICAgZW5kID0gSEIuYWRkT3BlcmF0aW9uKG5ldyB0eXBlcy5EZWxpbWl0ZXIgdWlkX2VuZCwgYmVnLCB1bmRlZmluZWQpLmV4ZWN1dGUoKVxuICAgICAgICAgICNiZWcuZXhlY3V0ZSgpXG4gICAgICAgICAgQG1hcF9tYW5hZ2VyLm1hcFtAbmFtZV0gPSBIQi5hZGRPcGVyYXRpb24obmV3IFJlcGxhY2VNYW5hZ2VyIHVuZGVmaW5lZCwgdWlkX3IsIGJlZywgZW5kKS5leGVjdXRlKClcbiAgICAgICAgc3VwZXJcblxuICAgICNcbiAgICAjIEVuY29kZSB0aGlzIG9wZXJhdGlvbiBpbiBzdWNoIGEgd2F5IHRoYXQgaXQgY2FuIGJlIHBhcnNlZCBieSByZW1vdGUgcGVlcnMuXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIHtcbiAgICAgICAgJ3R5cGUnIDogXCJBZGROYW1lXCJcbiAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgJ21hcF9tYW5hZ2VyJyA6IEBtYXBfbWFuYWdlci5nZXRVaWQoKVxuICAgICAgICAnbmFtZScgOiBAbmFtZVxuICAgICAgfVxuXG4gIHBhcnNlclsnQWRkTmFtZSddID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAnbWFwX21hbmFnZXInIDogbWFwX21hbmFnZXJcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAnbmFtZScgOiBuYW1lXG4gICAgfSA9IGpzb25cbiAgICBuZXcgQWRkTmFtZSB1aWQsIG1hcF9tYW5hZ2VyLCBuYW1lXG5cbiAgI1xuICAjIE1hbmFnZXMgYSBsaXN0IG9mIEluc2VydC10eXBlIG9wZXJhdGlvbnMuXG4gICNcbiAgY2xhc3MgTGlzdE1hbmFnZXIgZXh0ZW5kcyB0eXBlcy5JbnNlcnRcblxuICAgICNcbiAgICAjIEEgTGlzdE1hbmFnZXIgbWFpbnRhaW5zIGEgbm9uLWVtcHR5IGxpc3QgdGhhdCBoYXMgYSBiZWdpbm5pbmcgYW5kIGFuIGVuZCAoYm90aCBEZWxpbWl0ZXJzISlcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7RGVsaW1pdGVyfSBiZWdpbm5pbmcgUmVmZXJlbmNlIG9yIE9iamVjdC5cbiAgICAjIEBwYXJhbSB7RGVsaW1pdGVyfSBlbmQgUmVmZXJlbmNlIG9yIE9iamVjdC5cbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpbiktPlxuICAgICAgaWYgYmVnaW5uaW5nPyBhbmQgZW5kP1xuICAgICAgICBAc2F2ZU9wZXJhdGlvbiAnYmVnaW5uaW5nJywgYmVnaW5uaW5nXG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdlbmQnLCBlbmRcbiAgICAgIGVsc2VcbiAgICAgICAgQGJlZ2lubmluZyA9IEhCLmFkZE9wZXJhdGlvbiBuZXcgdHlwZXMuRGVsaW1pdGVyIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWRcbiAgICAgICAgQGVuZCA9ICAgICAgIEhCLmFkZE9wZXJhdGlvbiBuZXcgdHlwZXMuRGVsaW1pdGVyIHVuZGVmaW5lZCwgQGJlZ2lubmluZywgdW5kZWZpbmVkXG4gICAgICAgIEBiZWdpbm5pbmcubmV4dF9jbCA9IEBlbmRcbiAgICAgICAgQGJlZ2lubmluZy5leGVjdXRlKClcbiAgICAgICAgQGVuZC5leGVjdXRlKClcbiAgICAgIHN1cGVyIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cblxuICAgICMgR2V0IHRoZSBlbGVtZW50IHByZXZpb3VzIHRvIHRoZSBkZWxlbWl0ZXIgYXQgdGhlIGVuZFxuICAgIGdldExhc3RPcGVyYXRpb246ICgpLT5cbiAgICAgIEBlbmQucHJldl9jbFxuXG4gICAgIyBzaW1pbGFyIHRvIHRoZSBhYm92ZVxuICAgIGdldEZpcnN0T3BlcmF0aW9uOiAoKS0+XG4gICAgICBAYmVnaW5uaW5nLm5leHRfY2xcblxuICAgICMgVHJhbnNmb3JtcyB0aGUgdGhlIGxpc3QgdG8gYW4gYXJyYXlcbiAgICAjIERvZXNuJ3QgcmV0dXJuIGxlZnQtcmlnaHQgZGVsaW1pdGVyLlxuICAgIHRvQXJyYXk6ICgpLT5cbiAgICAgIG8gPSBAYmVnaW5uaW5nLm5leHRfY2xcbiAgICAgIHJlc3VsdCA9IFtdXG4gICAgICB3aGlsZSBvIGlzbnQgQGVuZFxuICAgICAgICByZXN1bHQucHVzaCBvXG4gICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgIHJlc3VsdFxuXG4gICAgI1xuICAgICMgUmV0cmlldmVzIHRoZSB4LXRoIG5vdCBkZWxldGVkIGVsZW1lbnQuXG4gICAgI1xuICAgIGdldE9wZXJhdGlvbkJ5UG9zaXRpb246IChwb3NpdGlvbiktPlxuICAgICAgbyA9IEBiZWdpbm5pbmcubmV4dF9jbFxuICAgICAgaWYgcG9zaXRpb24gPiAwXG4gICAgICAgIHdoaWxlIHRydWVcbiAgICAgICAgICBvID0gby5uZXh0X2NsXG4gICAgICAgICAgaWYgbm90IG8uaXNEZWxldGVkKClcbiAgICAgICAgICAgIHBvc2l0aW9uIC09IDFcbiAgICAgICAgICBpZiBwb3NpdGlvbiBpcyAwXG4gICAgICAgICAgICBicmVha1xuICAgICAgICAgIGlmIG8gaW5zdGFuY2VvZiB0eXBlcy5EZWxpbWl0ZXJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcInBvc2l0aW9uIHBhcmFtZXRlciBleGNlZWRlZCB0aGUgbGVuZ3RoIG9mIHRoZSBkb2N1bWVudCFcIlxuICAgICAgb1xuXG4gICNcbiAgIyBBZGRzIHN1cHBvcnQgZm9yIHJlcGxhY2UuIFRoZSBSZXBsYWNlTWFuYWdlciBtYW5hZ2VzIFJlcGxhY2VhYmxlIG9wZXJhdGlvbnMuXG4gICMgRWFjaCBSZXBsYWNlYWJsZSBob2xkcyBhIHZhbHVlIHRoYXQgaXMgbm93IHJlcGxhY2VhYmxlLlxuICAjXG4gICMgVGhlIFdvcmQtdHlwZSBoYXMgaW1wbGVtZW50ZWQgc3VwcG9ydCBmb3IgcmVwbGFjZVxuICAjIEBzZWUgV29yZFxuICAjXG4gIGNsYXNzIFJlcGxhY2VNYW5hZ2VyIGV4dGVuZHMgTGlzdE1hbmFnZXJcbiAgICAjXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gaW5pdGlhbF9jb250ZW50IEluaXRpYWxpemUgdGhpcyB3aXRoIGEgUmVwbGFjZWFibGUgdGhhdCBob2xkcyB0aGUgaW5pdGlhbF9jb250ZW50LlxuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGJlZ2lubmluZyBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGVuZCBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxuICAgIGNvbnN0cnVjdG9yOiAoaW5pdGlhbF9jb250ZW50LCB1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIHN1cGVyIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpblxuICAgICAgaWYgaW5pdGlhbF9jb250ZW50P1xuICAgICAgICBAcmVwbGFjZSBpbml0aWFsX2NvbnRlbnRcblxuICAgICNcbiAgICAjIFJlcGxhY2UgdGhlIGV4aXN0aW5nIHdvcmQgd2l0aCBhIG5ldyB3b3JkLlxuICAgICNcbiAgICByZXBsYWNlOiAoY29udGVudCktPlxuICAgICAgbyA9IEBnZXRMYXN0T3BlcmF0aW9uKClcbiAgICAgIG9wID0gbmV3IFJlcGxhY2VhYmxlIGNvbnRlbnQsIEAsIHVuZGVmaW5lZCwgbywgby5uZXh0X2NsXG4gICAgICBIQi5hZGRPcGVyYXRpb24ob3ApLmV4ZWN1dGUoKVxuXG4gICAgI1xuICAgICMgR2V0IHRoZSB2YWx1ZSBvZiB0aGlzIFdvcmRcbiAgICAjIEByZXR1cm4ge1N0cmluZ31cbiAgICAjXG4gICAgdmFsOiAoKS0+XG4gICAgICBvID0gQGdldExhc3RPcGVyYXRpb24oKVxuICAgICAgaWYgbyBpbnN0YW5jZW9mIHR5cGVzLkRlbGltaXRlclxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJkdHJuXCJcbiAgICAgIG8udmFsKClcblxuICAgICNcbiAgICAjIEVuY29kZSB0aGlzIG9wZXJhdGlvbiBpbiBzdWNoIGEgd2F5IHRoYXQgaXQgY2FuIGJlIHBhcnNlZCBieSByZW1vdGUgcGVlcnMuXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIGpzb24gPVxuICAgICAgICB7XG4gICAgICAgICAgJ3R5cGUnOiBcIlJlcGxhY2VNYW5hZ2VyXCJcbiAgICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAgICdiZWdpbm5pbmcnIDogQGJlZ2lubmluZy5nZXRVaWQoKVxuICAgICAgICAgICdlbmQnIDogQGVuZC5nZXRVaWQoKVxuICAgICAgICB9XG4gICAgICBpZiBAcHJldl9jbD8gYW5kIEBuZXh0X2NsP1xuICAgICAgICBqc29uWydwcmV2J10gPSBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICBqc29uWyduZXh0J10gPSBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgaWYgQG9yaWdpbj8gYW5kIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uW1wib3JpZ2luXCJdID0gQG9yaWdpbi5nZXRVaWQoKVxuICAgICAganNvblxuXG4gIHBhcnNlcltcIlJlcGxhY2VNYW5hZ2VyXCJdID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAnY29udGVudCcgOiBjb250ZW50XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ3ByZXYnOiBwcmV2XG4gICAgICAnbmV4dCc6IG5leHRcbiAgICAgICdvcmlnaW4nIDogb3JpZ2luXG4gICAgICAnYmVnaW5uaW5nJyA6IGJlZ2lubmluZ1xuICAgICAgJ2VuZCcgOiBlbmRcbiAgICB9ID0ganNvblxuICAgIG5ldyBSZXBsYWNlTWFuYWdlciBjb250ZW50LCB1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuXG4gICNcbiAgIyBUaGUgUmVwbGFjZU1hbmFnZXIgbWFuYWdlcyBSZXBsYWNlYWJsZXMuXG4gICMgQHNlZSBSZXBsYWNlTWFuYWdlclxuICAjXG4gIGNsYXNzIFJlcGxhY2VhYmxlIGV4dGVuZHMgdHlwZXMuSW5zZXJ0XG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gY29udGVudCBUaGUgdmFsdWUgdGhhdCB0aGlzIFJlcGxhY2VhYmxlIGhvbGRzLlxuICAgICMgQHBhcmFtIHtSZXBsYWNlTWFuYWdlcn0gcGFyZW50IFVzZWQgdG8gcmVwbGFjZSB0aGlzIFJlcGxhY2VhYmxlIHdpdGggYW5vdGhlciBvbmUuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAoY29udGVudCwgcGFyZW50LCB1aWQsIHByZXYsIG5leHQsIG9yaWdpbiktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ2NvbnRlbnQnLCBjb250ZW50XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncGFyZW50JywgcGFyZW50XG4gICAgICBpZiBub3QgKHByZXY/IGFuZCBuZXh0PyBhbmQgY29udGVudD8pXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBtdXN0IGRlZmluZSBjb250ZW50LCBwcmV2LCBhbmQgbmV4dCBmb3IgUmVwbGFjZWFibGUtdHlwZXMhXCJcbiAgICAgIHN1cGVyIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cbiAgICAjXG4gICAgIyBSZXR1cm4gdGhlIGNvbnRlbnQgdGhhdCB0aGlzIG9wZXJhdGlvbiBob2xkcy5cbiAgICAjXG4gICAgdmFsOiAoKS0+XG4gICAgICBAY29udGVudFxuXG4gICAgI1xuICAgICMgUmVwbGFjZSB0aGUgY29udGVudCBvZiB0aGlzIHJlcGxhY2VhYmxlIHdpdGggbmV3IGNvbnRlbnQuXG4gICAgI1xuICAgIHJlcGxhY2U6IChjb250ZW50KS0+XG4gICAgICBAcGFyZW50LnJlcGxhY2UgY29udGVudFxuXG4gICAgI1xuICAgICMgSWYgcG9zc2libGUgc2V0IHRoZSByZXBsYWNlIG1hbmFnZXIgaW4gdGhlIGNvbnRlbnQuXG4gICAgIyBAc2VlIFdvcmQuc2V0UmVwbGFjZU1hbmFnZXJcbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgbm90IEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgZWxzZVxuICAgICAgICBAY29udGVudC5zZXRSZXBsYWNlTWFuYWdlcj8oQHBhcmVudClcbiAgICAgICAgc3VwZXJcbiAgICAgICAgQFxuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9XG4gICAgICAgIHtcbiAgICAgICAgICAndHlwZSc6IFwiUmVwbGFjZWFibGVcIlxuICAgICAgICAgICdjb250ZW50JzogQGNvbnRlbnQuZ2V0VWlkKClcbiAgICAgICAgICAnUmVwbGFjZU1hbmFnZXInIDogQHBhcmVudC5nZXRVaWQoKVxuICAgICAgICAgICdwcmV2JzogQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgICAgICAnbmV4dCc6IEBuZXh0X2NsLmdldFVpZCgpXG4gICAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgfVxuICAgICAgaWYgQG9yaWdpbj8gYW5kIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uW1wib3JpZ2luXCJdID0gQG9yaWdpbi5nZXRVaWQoKVxuICAgICAganNvblxuXG4gIHBhcnNlcltcIlJlcGxhY2VhYmxlXCJdID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAnY29udGVudCcgOiBjb250ZW50XG4gICAgICAnUmVwbGFjZU1hbmFnZXInIDogcGFyZW50XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ3ByZXYnOiBwcmV2XG4gICAgICAnbmV4dCc6IG5leHRcbiAgICAgICdvcmlnaW4nIDogb3JpZ2luXG4gICAgfSA9IGpzb25cbiAgICBuZXcgUmVwbGFjZWFibGUgY29udGVudCwgcGFyZW50LCB1aWQsIHByZXYsIG5leHQsIG9yaWdpblxuXG5cblxuICB0eXBlc1snTGlzdE1hbmFnZXInXSA9IExpc3RNYW5hZ2VyXG4gIHR5cGVzWydNYXBNYW5hZ2VyJ10gPSBNYXBNYW5hZ2VyXG4gIHR5cGVzWydSZXBsYWNlTWFuYWdlciddID0gUmVwbGFjZU1hbmFnZXJcbiAgdHlwZXNbJ1JlcGxhY2VhYmxlJ10gPSBSZXBsYWNlYWJsZVxuXG4gIGJhc2ljX3R5cGVzXG5cblxuXG5cblxuXG4iLCJzdHJ1Y3R1cmVkX3R5cGVzX3VuaW5pdGlhbGl6ZWQgPSByZXF1aXJlIFwiLi9TdHJ1Y3R1cmVkVHlwZXNcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IChIQiktPlxuICBzdHJ1Y3R1cmVkX3R5cGVzID0gc3RydWN0dXJlZF90eXBlc191bmluaXRpYWxpemVkIEhCXG4gIHR5cGVzID0gc3RydWN0dXJlZF90eXBlcy50eXBlc1xuICBwYXJzZXIgPSBzdHJ1Y3R1cmVkX3R5cGVzLnBhcnNlclxuXG4gICNcbiAgIyBBdCB0aGUgbW9tZW50IFRleHREZWxldGUgdHlwZSBlcXVhbHMgdGhlIERlbGV0ZSB0eXBlIGluIEJhc2ljVHlwZXMuXG4gICMgQHNlZSBCYXNpY1R5cGVzLkRlbGV0ZVxuICAjXG4gIGNsYXNzIFRleHREZWxldGUgZXh0ZW5kcyB0eXBlcy5EZWxldGVcbiAgcGFyc2VyW1wiVGV4dERlbGV0ZVwiXSA9IHBhcnNlcltcIkRlbGV0ZVwiXVxuXG4gICNcbiAgIyAgRXh0ZW5kcyB0aGUgYmFzaWMgSW5zZXJ0IHR5cGUgdG8gYW4gb3BlcmF0aW9uIHRoYXQgaG9sZHMgYSB0ZXh0IHZhbHVlXG4gICNcbiAgY2xhc3MgVGV4dEluc2VydCBleHRlbmRzIHR5cGVzLkluc2VydFxuICAgICNcbiAgICAjIEBwYXJhbSB7U3RyaW5nfSBjb250ZW50IFRoZSBjb250ZW50IG9mIHRoaXMgSW5zZXJ0LXR5cGUgT3BlcmF0aW9uLiBVc3VhbGx5IHlvdSByZXN0cmljdCB0aGUgbGVuZ3RoIG9mIGNvbnRlbnQgdG8gc2l6ZSAxXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAoQGNvbnRlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBpZiBub3QgKHByZXY/IGFuZCBuZXh0PylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3QgZGVmaW5lIHByZXYsIGFuZCBuZXh0IGZvciBUZXh0SW5zZXJ0LXR5cGVzIVwiXG4gICAgICBzdXBlciB1aWQsIHByZXYsIG5leHQsIG9yaWdpblxuICAgICNcbiAgICAjIFJldHJpZXZlIHRoZSBlZmZlY3RpdmUgbGVuZ3RoIG9mIHRoZSAkY29udGVudCBvZiB0aGlzIG9wZXJhdGlvbi5cbiAgICAjXG4gICAgZ2V0TGVuZ3RoOiAoKS0+XG4gICAgICBpZiBAaXNEZWxldGVkKClcbiAgICAgICAgMFxuICAgICAgZWxzZVxuICAgICAgICBAY29udGVudC5sZW5ndGhcblxuICAgICNcbiAgICAjIFRoZSByZXN1bHQgd2lsbCBiZSBjb25jYXRlbmF0ZWQgd2l0aCB0aGUgcmVzdWx0cyBmcm9tIHRoZSBvdGhlciBpbnNlcnQgb3BlcmF0aW9uc1xuICAgICMgaW4gb3JkZXIgdG8gcmV0cmlldmUgdGhlIGNvbnRlbnQgb2YgdGhlIGVuZ2luZS5cbiAgICAjIEBzZWUgSGlzdG9yeUJ1ZmZlci50b0V4ZWN1dGVkQXJyYXlcbiAgICAjXG4gICAgdmFsOiAoY3VycmVudF9wb3NpdGlvbiktPlxuICAgICAgaWYgQGlzRGVsZXRlZCgpXG4gICAgICAgIFwiXCJcbiAgICAgIGVsc2VcbiAgICAgICAgQGNvbnRlbnRcblxuICAgICNcbiAgICAjIENvbnZlcnQgYWxsIHJlbGV2YW50IGluZm9ybWF0aW9uIG9mIHRoaXMgb3BlcmF0aW9uIHRvIHRoZSBqc29uLWZvcm1hdC5cbiAgICAjIFRoaXMgcmVzdWx0IGNhbiBiZSBzZW5kIHRvIG90aGVyIGNsaWVudHMuXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIGpzb24gPVxuICAgICAgICB7XG4gICAgICAgICAgJ3R5cGUnOiBcIlRleHRJbnNlcnRcIlxuICAgICAgICAgICdjb250ZW50JzogQGNvbnRlbnRcbiAgICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAgICdwcmV2JzogQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgICAgICAnbmV4dCc6IEBuZXh0X2NsLmdldFVpZCgpXG4gICAgICAgIH1cbiAgICAgIGlmIEBvcmlnaW4/IGFuZCBAb3JpZ2luIGlzbnQgQHByZXZfY2xcbiAgICAgICAganNvbltcIm9yaWdpblwiXSA9IEBvcmlnaW4uZ2V0VWlkKClcbiAgICAgIGpzb25cblxuICBwYXJzZXJbXCJUZXh0SW5zZXJ0XCJdID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAnY29udGVudCcgOiBjb250ZW50XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ3ByZXYnOiBwcmV2XG4gICAgICAnbmV4dCc6IG5leHRcbiAgICAgICdvcmlnaW4nIDogb3JpZ2luXG4gICAgfSA9IGpzb25cbiAgICBuZXcgVGV4dEluc2VydCBjb250ZW50LCB1aWQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICNcbiAgIyBIYW5kbGVzIGEgVGV4dC1saWtlIGRhdGEgc3RydWN0dXJlcyB3aXRoIHN1cHBvcnQgZm9yIGluc2VydFRleHQvZGVsZXRlVGV4dCBhdCBhIHdvcmQtcG9zaXRpb24uXG4gICNcbiAgY2xhc3MgV29yZCBleHRlbmRzIHR5cGVzLkxpc3RNYW5hZ2VyXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBzdXBlciB1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICAgICNcbiAgICAjIEluc2VydHMgYSBzdHJpbmcgaW50byB0aGUgd29yZFxuICAgICNcbiAgICBpbnNlcnRUZXh0OiAocG9zaXRpb24sIGNvbnRlbnQpLT5cbiAgICAgIG8gPSBAZ2V0T3BlcmF0aW9uQnlQb3NpdGlvbiBwb3NpdGlvblxuICAgICAgZm9yIGMgaW4gY29udGVudFxuICAgICAgICBvcCA9IG5ldyBUZXh0SW5zZXJ0IGMsIHVuZGVmaW5lZCwgby5wcmV2X2NsLCBvXG4gICAgICAgIEhCLmFkZE9wZXJhdGlvbihvcCkuZXhlY3V0ZSgpXG5cbiAgICAjXG4gICAgIyBEZWxldGVzIGEgcGFydCBvZiB0aGUgd29yZC5cbiAgICAjXG4gICAgZGVsZXRlVGV4dDogKHBvc2l0aW9uLCBsZW5ndGgpLT5cbiAgICAgIG8gPSBAZ2V0T3BlcmF0aW9uQnlQb3NpdGlvbiBwb3NpdGlvblxuXG4gICAgICBmb3IgaSBpbiBbMC4uLmxlbmd0aF1cbiAgICAgICAgZCA9IEhCLmFkZE9wZXJhdGlvbihuZXcgVGV4dERlbGV0ZSB1bmRlZmluZWQsIG8pLmV4ZWN1dGUoKVxuICAgICAgICBvID0gby5uZXh0X2NsXG4gICAgICAgIHdoaWxlIG8uaXNEZWxldGVkKClcbiAgICAgICAgICBpZiBvIGluc3RhbmNlb2YgdHlwZXMuRGVsaW1pdGVyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgY2FuJ3QgZGVsZXRlIG1vcmUgdGhhbiB0aGVyZSBpcy4uXCJcbiAgICAgICAgICBvID0gby5uZXh0X2NsXG4gICAgICAgIGQuX2VuY29kZSgpXG5cbiAgICAjXG4gICAgIyBSZXBsYWNlIHRoZSBjb250ZW50IG9mIHRoaXMgd29yZCB3aXRoIGFub3RoZXIgb25lLiBDb25jdXJyZW50IHJlcGxhY2VtZW50cyBhcmUgbm90IG1lcmdlZCFcbiAgICAjIE9ubHkgb25lIG9mIHRoZSByZXBsYWNlbWVudHMgd2lsbCBiZSB1c2VkLlxuICAgICNcbiAgICAjIENhbiBvbmx5IGJlIHVzZWQgaWYgdGhlIFJlcGxhY2VNYW5hZ2VyIHdhcyBzZXQhXG4gICAgIyBAc2VlIFdvcmQuc2V0UmVwbGFjZU1hbmFnZXJcbiAgICAjXG4gICAgcmVwbGFjZVRleHQ6ICh0ZXh0KS0+XG4gICAgICBpZiBAcmVwbGFjZV9tYW5hZ2VyP1xuICAgICAgICB3b3JkID0gSEIuYWRkT3BlcmF0aW9uKG5ldyBXb3JkIHVuZGVmaW5lZCkuZXhlY3V0ZSgpXG4gICAgICAgIHdvcmQuaW5zZXJ0VGV4dCAwLCB0ZXh0XG4gICAgICAgIEByZXBsYWNlX21hbmFnZXIucmVwbGFjZSh3b3JkKVxuICAgICAgZWxzZVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJUaGlzIHR5cGUgaXMgY3VycmVudGx5IG5vdCBtYWludGFpbmVkIGJ5IGEgUmVwbGFjZU1hbmFnZXIhXCJcblxuICAgICNcbiAgICAjIEByZXR1cm5zIFtKc29uXSBBIEpzb24gb2JqZWN0LlxuICAgICNcbiAgICB2YWw6ICgpLT5cbiAgICAgIGMgPSBmb3IgbyBpbiBAdG9BcnJheSgpXG4gICAgICAgIGlmIG8udmFsP1xuICAgICAgICAgIG8udmFsKClcbiAgICAgICAgZWxzZVxuICAgICAgICAgIFwiXCJcbiAgICAgIGMuam9pbignJylcblxuICAgICNcbiAgICAjIEluIG1vc3QgY2FzZXMgeW91IHdvdWxkIGVtYmVkIGEgV29yZCBpbiBhIFJlcGxhY2VhYmxlLCB3aWNoIGlzIGhhbmRsZWQgYnkgdGhlIFJlcGxhY2VNYW5hZ2VyIGluIG9yZGVyXG4gICAgIyB0byBwcm92aWRlIHJlcGxhY2UgZnVuY3Rpb25hbGl0eS5cbiAgICAjXG4gICAgc2V0UmVwbGFjZU1hbmFnZXI6IChvcCktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ3JlcGxhY2VfbWFuYWdlcicsIG9wXG4gICAgICBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnNcblxuICAgICNcbiAgICAjIEVuY29kZSB0aGlzIG9wZXJhdGlvbiBpbiBzdWNoIGEgd2F5IHRoYXQgaXQgY2FuIGJlIHBhcnNlZCBieSByZW1vdGUgcGVlcnMuXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIGpzb24gPSB7XG4gICAgICAgICd0eXBlJzogXCJXb3JkXCJcbiAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgJ2JlZ2lubmluZycgOiBAYmVnaW5uaW5nLmdldFVpZCgpXG4gICAgICAgICdlbmQnIDogQGVuZC5nZXRVaWQoKVxuICAgICAgfVxuICAgICAgaWYgQHByZXZfY2w/XG4gICAgICAgIGpzb25bJ3ByZXYnXSA9IEBwcmV2X2NsLmdldFVpZCgpXG4gICAgICBpZiBAbmV4dF9jbD9cbiAgICAgICAganNvblsnbmV4dCddID0gQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgIGlmIEBvcmlnaW4/IGFuZCBAb3JpZ2luIGlzbnQgQHByZXZfY2xcbiAgICAgICAganNvbltcIm9yaWdpblwiXSA9IEBvcmlnaW4uZ2V0VWlkKClcbiAgICAgIGpzb25cblxuICBwYXJzZXJbJ1dvcmQnXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdiZWdpbm5pbmcnIDogYmVnaW5uaW5nXG4gICAgICAnZW5kJyA6IGVuZFxuICAgICAgJ3ByZXYnOiBwcmV2XG4gICAgICAnbmV4dCc6IG5leHRcbiAgICAgICdvcmlnaW4nIDogb3JpZ2luXG4gICAgfSA9IGpzb25cbiAgICBuZXcgV29yZCB1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICB0eXBlc1snVGV4dEluc2VydCddID0gVGV4dEluc2VydFxuICB0eXBlc1snVGV4dERlbGV0ZSddID0gVGV4dERlbGV0ZVxuICB0eXBlc1snV29yZCddID0gV29yZFxuICBzdHJ1Y3R1cmVkX3R5cGVzXG5cblxuIl19 diff --git a/build/browser/Types/TextTypes.min.js b/build/browser/Types/TextTypes.min.js new file mode 100644 index 00000000..b4dac6b6 --- /dev/null +++ b/build/browser/Types/TextTypes.min.js @@ -0,0 +1 @@ +!function e(t,n,r){function i(s,u){if(!n[s]){if(!t[s]){var p="function"==typeof require&&require;if(!u&&p)return p(s,!0);if(o)return o(s,!0);throw new Error("Cannot find module '"+s+"'")}var a=n[s]={exports:{}};t[s][0].call(a.exports,function(e){var n=t[s][1][e];return i(n?n:e)},a,a.exports,e,t,n,r)}return n[s].exports}for(var o="function"==typeof require&&require,s=0;sr;r++)n=o[r],s.push(n.call(this,e,t));return s}},t.prototype.setParent=function(e){return this.parent=e},t.prototype.getUid=function(){return{creator:this.creator,op_number:this.op_number}},t.prototype.execute=function(){var e,t,n;for(this.is_executed=!0,t=0,n=u.length;n>t;t++)(e=u[t])(this._encode());return this},t.prototype.saveOperation=function(e,t){return null!=(null!=t?t.execute:void 0)?this[e]=t:null!=t?(null==this.unchecked&&(this.unchecked={}),this.unchecked[e]=t):void 0},t.prototype.validateSavedOperations=function(){var t,n,r,i,o,s;o={},i=this,s=this.unchecked;for(t in s)r=s[t],n=e.getOperation(r),n?this[t]=n:(o[t]=r,i=!1);return delete this.unchecked,i||(this.unchecked=o),i},t}(),t=function(e){function t(e,n){this.saveOperation("deletes",n),t.__super__.constructor.call(this,e)}return r(t,e),t.prototype._encode=function(){return{type:"Delete",uid:this.getUid(),deletes:this.deletes.getUid()}},t.prototype.execute=function(){return this.validateSavedOperations()?(this.deletes.applyDelete(this),t.__super__.execute.apply(this,arguments),this):!1},t}(s),p.Delete=function(e){var n,r;return r=e.uid,n=e.deletes,new t(r,n)},o=function(e){function t(e,n,r,i){this.saveOperation("prev_cl",n),this.saveOperation("next_cl",r),null!=i?this.saveOperation("origin",i):this.saveOperation("origin",n),t.__super__.constructor.call(this,e)}return r(t,e),t.prototype.applyDelete=function(e){return null==this.deleted_by&&(this.deleted_by=[]),this.deleted_by.push(e)},t.prototype.isDeleted=function(){var e;return(null!=(e=this.deleted_by)?e.length:void 0)>0},t.prototype.getDistanceToOrigin=function(){var e,t;for(e=0,t=this.prev_cl;;){if(this.origin===t)break;if(e++,this===this.prev_cl)throw new Error("this should not happen ;) ");t=t.prev_cl}return e},t.prototype.update_sl=function(){var e;return e=this.prev_cl,update("prev_cl","prev_sl"),update("next_cl","prev_sl")},t.prototype.execute=function(){var e,n,r,i,o;if(null!=this.is_executed)return this;if(this.validateSavedOperations()){if((null!=(i=this.prev_cl)?i.validateSavedOperations():void 0)&&(null!=(o=this.next_cl)?o.validateSavedOperations():void 0)&&this.prev_cl.next_cl!==this){for(e=0,r=this.prev_cl.next_cl,n=0;;){if(null==r&&(console.log(JSON.stringify(this.prev_cl.getUid())),console.log(JSON.stringify(this.next_cl.getUid()))),r===this.next_cl)break;if(r.getDistanceToOrigin()===n)r.creator0)for(;;){if(t=t.next_cl,t.isDeleted()||(e-=1),0===e)break;if(t instanceof c.Delimiter)throw new Error("position parameter exceeded the length of the document!")}return t},n}(c.Insert),s=function(t){function n(e,t,r,i,o,s,u){n.__super__.constructor.call(this,t,r,i,o,s,u),null!=e&&this.replace(e)}return i(n,t),n.prototype.replace=function(t){var n,r;return n=this.getLastOperation(),r=new u(t,this,void 0,n,n.next_cl),e.addOperation(r).execute()},n.prototype.val=function(){var e;if(e=this.getLastOperation(),e instanceof c.Delimiter)throw new Error("dtrn");return e.val()},n.prototype._encode=function(){var e;return e={type:"ReplaceManager",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&null!=this.next_cl&&(e.prev=this.prev_cl.getUid(),e.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},n}(r),a.ReplaceManager=function(e){var t,n,r,i,o,u,p;return n=e.content,p=e.uid,u=e.prev,i=e.next,o=e.origin,t=e.beginning,r=e.end,new s(n,p,t,r,u,i,o)},u=function(e){function t(e,n,r,i,o,s){if(this.saveOperation("content",e),this.saveOperation("parent",n),null==i||null==o||null==e)throw new Error("You must define content, prev, and next for Replaceable-types!");t.__super__.constructor.call(this,r,i,o,s)}return i(t,e),t.prototype.val=function(){return this.content},t.prototype.replace=function(e){return this.parent.replace(e)},t.prototype.execute=function(){var e;return this.validateSavedOperations()?("function"==typeof(e=this.content).setReplaceManager&&e.setReplaceManager(this.parent),t.__super__.execute.apply(this,arguments),this):!1},t.prototype._encode=function(){var e;return e={type:"Replaceable",content:this.content.getUid(),ReplaceManager:this.parent.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid(),uid:this.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},t}(c.Insert),a.Replaceable=function(e){var t,n,r,i,o,s;return t=e.content,i=e.ReplaceManager,s=e.uid,o=e.prev,n=e.next,r=e.origin,new u(t,i,s,o,n,r)},c.ListManager=r,c.MapManager=o,c.ReplaceManager=s,c.Replaceable=u,p}},{"./BasicTypes":1}],3:[function(e,t){var n,r={}.hasOwnProperty,i=function(e,t){function n(){this.constructor=e}for(var i in t)r.call(t,i)&&(e[i]=t[i]);return n.prototype=t.prototype,e.prototype=new n,e.__super__=t.prototype,e};n=e("./StructuredTypes"),t.exports=function(e){var t,r,o,s,u,p;return u=n(e),p=u.types,s=u.parser,t=function(e){function t(){return t.__super__.constructor.apply(this,arguments)}return i(t,e),t}(p.Delete),s.TextDelete=s.Delete,r=function(e){function t(e,n,r,i,o){if(this.content=e,null==r||null==i)throw new Error("You must define prev, and next for TextInsert-types!");t.__super__.constructor.call(this,n,r,i,o)}return i(t,e),t.prototype.getLength=function(){return this.isDeleted()?0:this.content.length},t.prototype.val=function(){return this.isDeleted()?"":this.content},t.prototype._encode=function(){var e;return e={type:"TextInsert",content:this.content,uid:this.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},t}(p.Insert),s.TextInsert=function(e){var t,n,i,o,s;return t=e.content,s=e.uid,o=e.prev,n=e.next,i=e.origin,new r(t,s,o,n,i)},o=function(n){function o(e,t,n,r,i,s){o.__super__.constructor.call(this,e,t,n,r,i,s)}return i(o,n),o.prototype.insertText=function(t,n){var i,o,s,u,p,a;for(o=this.getOperationByPosition(t),a=[],u=0,p=n.length;p>u;u++)i=n[u],s=new r(i,void 0,o.prev_cl,o),a.push(e.addOperation(s).execute());return a},o.prototype.deleteText=function(n,r){var i,o,s,u,a;for(s=this.getOperationByPosition(n),a=[],o=u=0;r>=0?r>u:u>r;o=r>=0?++u:--u){for(i=e.addOperation(new t(void 0,s)).execute(),s=s.next_cl;s.isDeleted();){if(s instanceof p.Delimiter)throw new Error("You can't delete more than there is..");s=s.next_cl}a.push(i._encode())}return a},o.prototype.replaceText=function(t){var n;if(null!=this.replace_manager)return n=e.addOperation(new o(void 0)).execute(),n.insertText(0,t),this.replace_manager.replace(n);throw new Error("This type is currently not maintained by a ReplaceManager!")},o.prototype.val=function(){var e,t;return e=function(){var e,n,r,i;for(r=this.toArray(),i=[],e=0,n=r.length;n>e;e++)t=r[e],i.push(null!=t.val?t.val():"");return i}.call(this),e.join("")},o.prototype.setReplaceManager=function(e){return this.saveOperation("replace_manager",e),this.validateSavedOperations},o.prototype._encode=function(){var e;return e={type:"Word",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&(e.prev=this.prev_cl.getUid()),null!=this.next_cl&&(e.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},o}(p.ListManager),s.Word=function(e){var t,n,r,i,s,u;return u=e.uid,t=e.beginning,n=e.end,s=e.prev,r=e.next,i=e.origin,new o(u,t,n,s,r,i)},p.TextInsert=r,p.TextDelete=t,p.Word=o,u}},{"./StructuredTypes":2}]},{},[3]); \ No newline at end of file diff --git a/build/browser/Types/XmlTypes.js b/build/browser/Types/XmlTypes.js new file mode 100644 index 00000000..a32351de --- /dev/null +++ b/build/browser/Types/XmlTypes.js @@ -0,0 +1,6 @@ +(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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { + return this.engine.applyOp(this.unexecuted[user].shift()); + } + }; + + TestConnector.prototype.flushOneRandom = function() { + return this.flushOne(_.random(0, user_list.length - 1)); + }; + + TestConnector.prototype.flushAll = function() { + var n, ops, _ref; + _ref = this.unexecuted; + for (n in _ref) { + ops = _ref[n]; + this.engine.applyOps(ops); + } + return this.unexecuted = {}; + }; + + return TestConnector; + + })(); +}; + + +},{"underscore":12}],3:[function(require,module,exports){ +var Engine; + +Engine = (function() { + function Engine(HB, parser) { + this.HB = HB; + this.parser = parser; + this.unprocessed_ops = []; + } + + Engine.prototype.parseOperation = function(json) { + var typeParser; + typeParser = this.parser[json.type]; + if (typeParser != null) { + return typeParser(json); + } else { + throw new Error("You forgot to specify a parser for type " + json.type + ". The message is " + (JSON.stringify(json)) + "."); + } + }; + + Engine.prototype.applyOpsBundle = function(ops_json) { + var o, ops, _i, _j, _k, _len, _len1, _len2; + ops = []; + for (_i = 0, _len = ops_json.length; _i < _len; _i++) { + o = ops_json[_i]; + ops.push(this.parseOperation(o)); + } + for (_j = 0, _len1 = ops.length; _j < _len1; _j++) { + o = ops[_j]; + this.HB.addOperation(o); + } + for (_k = 0, _len2 = ops.length; _k < _len2; _k++) { + o = ops[_k]; + if (!o.execute()) { + this.unprocessed_ops.push(o); + } + } + return this.tryUnprocessed(); + }; + + Engine.prototype.applyOpsCheckDouble = function(ops_json) { + var o, _i, _len, _results; + _results = []; + for (_i = 0, _len = ops_json.length; _i < _len; _i++) { + o = ops_json[_i]; + if (this.HB.getOperation(o.uid) != null) { + _results.push(this.applyOp(o)); + } else { + _results.push(void 0); + } + } + return _results; + }; + + Engine.prototype.applyOps = function(ops_json) { + var o, _i, _len, _results; + _results = []; + for (_i = 0, _len = ops_json.length; _i < _len; _i++) { + o = ops_json[_i]; + _results.push(this.applyOp(o)); + } + return _results; + }; + + Engine.prototype.applyOp = function(op_json) { + var o; + o = this.parseOperation(op_json); + this.HB.addToCounter(o); + if (!o.execute()) { + this.unprocessed_ops.push(o); + } else { + this.HB.addOperation(o); + } + return this.tryUnprocessed(); + }; + + Engine.prototype.tryUnprocessed = function() { + var old_length, op, unprocessed, _i, _len, _ref, _results; + _results = []; + while (true) { + old_length = this.unprocessed_ops.length; + unprocessed = []; + _ref = this.unprocessed_ops; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + op = _ref[_i]; + if (!op.execute()) { + unprocessed.push(op); + } else { + this.HB.addOperation(op); + } + } + this.unprocessed_ops = unprocessed; + if (this.unprocessed_ops.length === old_length) { + break; + } else { + _results.push(void 0); + } + } + return _results; + }; + + return Engine; + +})(); + +module.exports = Engine; + + +},{}],4:[function(require,module,exports){ +var Engine, HistoryBuffer, JsonYatta, json_types_uninitialized; + +json_types_uninitialized = require("../Types/JsonTypes"); + +HistoryBuffer = require("../HistoryBuffer"); + +Engine = require("../Engine"); + +JsonYatta = (function() { + function JsonYatta(user_id, Connector) { + var first_word, json_types; + this.HB = new HistoryBuffer(user_id); + json_types = json_types_uninitialized(this.HB); + this.engine = new Engine(this.HB, json_types.parser); + this.connector = new Connector(this.engine, this.HB, json_types.execution_listener, this); + first_word = new json_types.types.JsonType(this.HB.getReservedUniqueIdentifier()); + this.HB.addOperation(first_word).execute(); + this.root_element = first_word; + } + + JsonYatta.prototype.getRootElement = function() { + return this.root_element; + }; + + JsonYatta.prototype.getEngine = function() { + return this.engine; + }; + + JsonYatta.prototype.getConnector = function() { + return this.connector; + }; + + JsonYatta.prototype.getHistoryBuffer = function() { + return this.HB; + }; + + JsonYatta.prototype.setMutableDefault = function(mutable) { + return this.root_element.setMutableDefault(mutable); + }; + + JsonYatta.prototype.getUserId = function() { + return this.HB.getUserId(); + }; + + JsonYatta.prototype.val = function(name, content, mutable) { + return this.root_element.val(name, content, mutable); + }; + + Object.defineProperty(JsonYatta.prototype, 'value', { + get: function() { + return this.root_element.value; + }, + set: function(o) { + var o_name, o_obj, _results; + if (o.constructor === {}.constructor) { + _results = []; + for (o_name in o) { + o_obj = o[o_name]; + _results.push(this.val(o_name, o_obj, 'immutable')); + } + return _results; + } else { + throw new Error("You must only set Object values!"); + } + } + }); + + return JsonYatta; + +})(); + +if (typeof window !== "undefined" && window !== null) { + window.JsonYatta = JsonYatta; +} + +module.exports = JsonYatta; + + +},{"../Engine":3,"../HistoryBuffer":6,"../Types/JsonTypes":8}],5:[function(require,module,exports){ +var Engine, HistoryBuffer, TextYatta, text_types_uninitialized; + +text_types_uninitialized = require("../Types/TextTypes"); + +HistoryBuffer = require("../HistoryBuffer"); + +Engine = require("../Engine"); + +TextYatta = (function() { + function TextYatta(user_id, Connector) { + var first_word, text_types; + this.HB = new HistoryBuffer(user_id); + text_types = text_types_uninitialized(this.HB); + this.engine = new Engine(this.HB, text_types.parser); + this.connector = new Connector(this.engine, this.HB, text_types.execution_listener); + first_word = new text_types.types.Word(void 0); + this.HB.addOperation(first_word).execute(); + this.root_element = first_word; + } + + TextYatta.prototype.getRootElement = function() { + return this.root_element; + }; + + TextYatta.prototype.getEngine = function() { + return this.engine; + }; + + TextYatta.prototype.getConnector = function() { + return this.connector; + }; + + TextYatta.prototype.getHistoryBuffer = function() { + return this.HB; + }; + + TextYatta.prototype.getUserId = function() { + return this.HB.getUserId(); + }; + + TextYatta.prototype.val = function() { + return this.root_element.val(); + }; + + TextYatta.prototype.insertText = function(pos, content) { + return this.root_element.insertText(pos, content); + }; + + TextYatta.prototype.deleteText = function(pos, length) { + return this.root_element.deleteText(pos, length); + }; + + TextYatta.prototype.replaceText = function(text) { + return this.root_element.replaceText(text); + }; + + return TextYatta; + +})(); + +module.exports = TextYatta; + + +},{"../Engine":3,"../HistoryBuffer":6,"../Types/TextTypes":10}],6:[function(require,module,exports){ +var HistoryBuffer; + +HistoryBuffer = (function() { + function HistoryBuffer(user_id) { + this.user_id = user_id; + this.operation_counter = {}; + this.buffer = {}; + this.change_listeners = []; + } + + HistoryBuffer.prototype.getUserId = function() { + return this.user_id; + }; + + HistoryBuffer.prototype.getReservedUniqueIdentifier = function() { + return { + creator: '_', + op_number: '_' + }; + }; + + HistoryBuffer.prototype.getOperationCounter = function() { + var ctn, res, user, _ref; + res = {}; + _ref = this.operation_counter; + for (user in _ref) { + ctn = _ref[user]; + res[user] = ctn; + } + return res; + }; + + HistoryBuffer.prototype._encode = function(state_vector) { + var json, o, o_json, o_next, o_number, o_prev, u_name, unknown, user, _ref; + if (state_vector == null) { + state_vector = {}; + } + json = []; + unknown = function(user, o_number) { + if ((user == null) || (o_number == null)) { + throw new Error("dah!"); + } + return (state_vector[user] == null) || state_vector[user] <= o_number; + }; + _ref = this.buffer; + for (u_name in _ref) { + user = _ref[u_name]; + for (o_number in user) { + o = user[o_number]; + if (!isNaN(parseInt(o_number)) && unknown(u_name, o_number)) { + o_json = o._encode(); + if (o.next_cl != null) { + o_next = o.next_cl; + while ((o_next.next_cl != null) && unknown(o_next.creator, o_next.op_number)) { + o_next = o_next.next_cl; + } + o_json.next = o_next.getUid(); + } else if (o.prev_cl != null) { + o_prev = o.prev_cl; + while ((o_prev.prev_cl != null) && unknown(o_next.creator, o_next.op_number)) { + o_prev = o_prev.prev_cl; + } + o_json.prev = o_prev.getUid(); + } + json.push(o_json); + } + } + } + return json; + }; + + HistoryBuffer.prototype.getNextOperationIdentifier = function(user_id) { + var uid; + if (user_id == null) { + user_id = this.user_id; + } + if (this.operation_counter[user_id] == null) { + this.operation_counter[user_id] = 0; + } + uid = { + 'creator': user_id, + 'op_number': this.operation_counter[user_id] + }; + this.operation_counter[user_id]++; + return uid; + }; + + HistoryBuffer.prototype.getOperation = function(uid) { + var _ref; + if (uid instanceof Object) { + return (_ref = this.buffer[uid.creator]) != null ? _ref[uid.op_number] : void 0; + } else if (uid == null) { + + } else { + throw new Error("This type of uid is not defined!"); + } + }; + + HistoryBuffer.prototype.addOperation = function(o) { + if (this.buffer[o.creator] == null) { + this.buffer[o.creator] = {}; + } + if (this.buffer[o.creator][o.op_number] != null) { + throw new Error("You must not overwrite operations!"); + } + this.buffer[o.creator][o.op_number] = o; + return o; + }; + + HistoryBuffer.prototype.addToCounter = function(o) { + if (this.operation_counter[o.creator] == null) { + this.operation_counter[o.creator] = 0; + } + if (typeof o.op_number === 'number' && o.creator !== this.getUserId()) { + return this.operation_counter[o.creator]++; + } + }; + + return HistoryBuffer; + +})(); + +module.exports = HistoryBuffer; + + +},{}],7:[function(require,module,exports){ +var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +module.exports = function(HB) { + var Delete, Delimiter, ImmutableObject, Insert, Operation, execution_listener, parser; + parser = {}; + execution_listener = []; + Operation = (function() { + function Operation(uid) { + if (uid == null) { + uid = HB.getNextOperationIdentifier(); + } + this.creator = uid['creator'], this.op_number = uid['op_number']; + } + + Operation.prototype.on = function(event, f) { + var _base; + if (this.event_listeners == null) { + this.event_listeners = {}; + } + if ((_base = this.event_listeners)[event] == null) { + _base[event] = []; + } + return this.event_listeners[event].push(f); + }; + + Operation.prototype.callEvent = function(event, args) { + var f, _i, _len, _ref, _results; + if (this.event_listeners[event] != null) { + _ref = this.event_listeners[event]; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + f = _ref[_i]; + _results.push(f.call(this, event, args)); + } + return _results; + } + }; + + Operation.prototype.setParent = function(o) { + return this.parent = o; + }; + + Operation.prototype.getUid = function() { + return { + 'creator': this.creator, + 'op_number': this.op_number + }; + }; + + Operation.prototype.execute = function() { + var l, _i, _len; + this.is_executed = true; + for (_i = 0, _len = execution_listener.length; _i < _len; _i++) { + l = execution_listener[_i]; + l(this._encode()); + } + return this; + }; + + Operation.prototype.saveOperation = function(name, op) { + if ((op != null ? op.execute : void 0) != null) { + return this[name] = op; + } else if (op != null) { + if (this.unchecked == null) { + this.unchecked = {}; + } + return this.unchecked[name] = op; + } + }; + + Operation.prototype.validateSavedOperations = function() { + var name, op, op_uid, success, uninstantiated, _ref; + uninstantiated = {}; + success = this; + _ref = this.unchecked; + for (name in _ref) { + op_uid = _ref[name]; + op = HB.getOperation(op_uid); + if (op) { + this[name] = op; + } else { + uninstantiated[name] = op_uid; + success = false; + } + } + delete this.unchecked; + if (!success) { + this.unchecked = uninstantiated; + } + return success; + }; + + return Operation; + + })(); + Delete = (function(_super) { + __extends(Delete, _super); + + function Delete(uid, deletes) { + this.saveOperation('deletes', deletes); + Delete.__super__.constructor.call(this, uid); + } + + Delete.prototype._encode = function() { + return { + 'type': "Delete", + 'uid': this.getUid(), + 'deletes': this.deletes.getUid() + }; + }; + + Delete.prototype.execute = function() { + if (this.validateSavedOperations()) { + this.deletes.applyDelete(this); + Delete.__super__.execute.apply(this, arguments); + return this; + } else { + return false; + } + }; + + return Delete; + + })(Operation); + parser['Delete'] = function(o) { + var deletes_uid, uid; + uid = o['uid'], deletes_uid = o['deletes']; + return new Delete(uid, deletes_uid); + }; + Insert = (function(_super) { + __extends(Insert, _super); + + function Insert(uid, prev_cl, next_cl, origin) { + this.saveOperation('prev_cl', prev_cl); + this.saveOperation('next_cl', next_cl); + if (origin != null) { + this.saveOperation('origin', origin); + } else { + this.saveOperation('origin', prev_cl); + } + Insert.__super__.constructor.call(this, uid); + } + + Insert.prototype.applyDelete = function(o) { + if (this.deleted_by == null) { + this.deleted_by = []; + } + return this.deleted_by.push(o); + }; + + Insert.prototype.isDeleted = function() { + var _ref; + return ((_ref = this.deleted_by) != null ? _ref.length : void 0) > 0; + }; + + Insert.prototype.getDistanceToOrigin = function() { + var d, o; + d = 0; + o = this.prev_cl; + while (true) { + if (this.origin === o) { + break; + } + d++; + if (this === this.prev_cl) { + throw new Error("this should not happen ;) "); + } + o = o.prev_cl; + } + return d; + }; + + Insert.prototype.update_sl = function() { + var o; + o = this.prev_cl; + ({ + update: function(dest_cl, dest_sl) { + var _results; + _results = []; + while (true) { + if (o.isDeleted()) { + _results.push(o = o[dest_cl]); + } else { + this[dest_sl] = o; + break; + } + } + return _results; + } + }); + update("prev_cl", "prev_sl"); + return update("next_cl", "prev_sl"); + }; + + Insert.prototype.execute = function() { + var distance_to_origin, i, o, _ref, _ref1; + if (this.is_executed != null) { + return this; + } + if (!this.validateSavedOperations()) { + return false; + } else { + if (((_ref = this.prev_cl) != null ? _ref.validateSavedOperations() : void 0) && ((_ref1 = this.next_cl) != null ? _ref1.validateSavedOperations() : void 0) && this.prev_cl.next_cl !== this) { + distance_to_origin = 0; + o = this.prev_cl.next_cl; + i = 0; + while (true) { + if (o == null) { + console.log(JSON.stringify(this.prev_cl.getUid())); + console.log(JSON.stringify(this.next_cl.getUid())); + } + if (o !== this.next_cl) { + if (o.getDistanceToOrigin() === i) { + if (o.creator < this.creator) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else if (o.getDistanceToOrigin() < i) { + if (i - distance_to_origin <= o.getDistanceToOrigin()) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else { + break; + } + i++; + o = o.next_cl; + } else { + break; + } + } + this.next_cl = this.prev_cl.next_cl; + this.prev_cl.next_cl = this; + this.next_cl.prev_cl = this; + } + Insert.__super__.execute.apply(this, arguments); + return this; + } + }; + + return Insert; + + })(Operation); + ImmutableObject = (function(_super) { + __extends(ImmutableObject, _super); + + function ImmutableObject(uid, content, prev, next, origin) { + this.content = content; + ImmutableObject.__super__.constructor.call(this, uid, prev, next, origin); + } + + ImmutableObject.prototype.val = function() { + return this.content; + }; + + ImmutableObject.prototype._encode = function() { + var json; + json = { + 'type': "ImmutableObject", + 'uid': this.getUid(), + 'content': this.content + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ImmutableObject; + + })(Insert); + parser['ImmutableObject'] = function(json) { + var content, next, origin, prev, uid; + uid = json['uid'], content = json['content'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new ImmutableObject(uid, content, prev, next, origin); + }; + Delimiter = (function(_super) { + __extends(Delimiter, _super); + + function Delimiter(uid, prev_cl, next_cl, origin) { + this.saveOperation('prev_cl', prev_cl); + this.saveOperation('next_cl', next_cl); + this.saveOperation('origin', prev_cl); + Delimiter.__super__.constructor.call(this, uid); + } + + Delimiter.prototype.isDeleted = function() { + return false; + }; + + Delimiter.prototype.execute = function() { + var _ref, _ref1; + if (((_ref = this.unchecked) != null ? _ref['next_cl'] : void 0) != null) { + return Delimiter.__super__.execute.apply(this, arguments); + } else if ((_ref1 = this.unchecked) != null ? _ref1['prev_cl'] : void 0) { + if (this.validateSavedOperations()) { + if (this.prev_cl.next_cl != null) { + throw new Error("Probably duplicated operations"); + } + this.prev_cl.next_cl = this; + delete this.prev_cl.unchecked.next_cl; + return Delimiter.__super__.execute.apply(this, arguments); + } else { + return false; + } + } else if ((this.prev_cl != null) && (this.prev_cl.next_cl == null)) { + delete this.prev_cl.unchecked.next_cl; + return this.prev_cl.next_cl = this; + } else if ((this.prev_cl != null) || (this.next_cl != null)) { + return Delimiter.__super__.execute.apply(this, arguments); + } else { + throw new Error("Delimiter is unsufficient defined!"); + } + }; + + Delimiter.prototype._encode = function() { + var _ref, _ref1; + return { + 'type': "Delimiter", + 'uid': this.getUid(), + 'prev': (_ref = this.prev_cl) != null ? _ref.getUid() : void 0, + 'next': (_ref1 = this.next_cl) != null ? _ref1.getUid() : void 0 + }; + }; + + return Delimiter; + + })(Operation); + parser['Delimiter'] = function(json) { + var next, prev, uid; + uid = json['uid'], prev = json['prev'], next = json['next']; + return new Delimiter(uid, prev, next); + }; + return { + 'types': { + 'Delete': Delete, + 'Insert': Insert, + 'Delimiter': Delimiter, + 'Operation': Operation, + 'ImmutableObject': ImmutableObject + }, + 'parser': parser, + 'execution_listener': execution_listener + }; +}; + + +},{}],8:[function(require,module,exports){ +var text_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +text_types_uninitialized = require("./TextTypes"); + +module.exports = function(HB) { + var JsonType, createJsonWrapper, parser, text_types, types; + text_types = text_types_uninitialized(HB); + types = text_types.types; + parser = text_types.parser; + createJsonWrapper = function(_jsonType) { + var JsonWrapper; + JsonWrapper = (function() { + function JsonWrapper(jsonType) { + var name, obj, _fn, _ref; + _ref = jsonType.map; + _fn = function(name, obj) { + return Object.defineProperty(JsonWrapper.prototype, name, { + get: function() { + var x; + x = obj.val(); + if (x instanceof JsonType) { + return createJsonWrapper(x); + } else if (x instanceof types.ImmutableObject) { + return x.val(); + } else { + return x; + } + }, + set: function(o) { + var o_name, o_obj, overwrite, _results; + if (o.constructor === {}.constructor) { + overwrite = jsonType.val(name); + _results = []; + for (o_name in o) { + o_obj = o[o_name]; + _results.push(overwrite.val(o_name, o_obj, 'immutable')); + } + return _results; + } else { + return jsonType.val(name, o, 'immutable'); + } + }, + enumerable: true, + configurable: false + }); + }; + for (name in _ref) { + obj = _ref[name]; + _fn(name, obj); + } + } + + return JsonWrapper; + + })(); + return new JsonWrapper(_jsonType); + }; + JsonType = (function(_super) { + __extends(JsonType, _super); + + function JsonType(uid, initial_value, mutable) { + var name, o; + JsonType.__super__.constructor.call(this, uid); + if (initial_value != null) { + if (typeof initial_value !== "object") { + throw new Error("The initial value of JsonTypes must be of type Object! (current type: " + (typeof initial_value) + ")"); + } + for (name in initial_value) { + o = initial_value[name]; + this.val(name, o, mutable); + } + } + } + + JsonType.prototype.mutable_default = true; + + JsonType.prototype.setMutableDefault = function(mutable) { + if (mutable === true || mutable === 'mutable') { + JsonType.prototype.mutable_default = true; + } else if (mutable === false || mutable === 'immutable') { + JsonType.prototype.mutable_default = false; + } else { + throw new Error('Set mutable either "mutable" or "immutable"!'); + } + return 'OK'; + }; + + JsonType.prototype.val = function(name, content, mutable) { + var json, o, o_name, obj, word; + if (typeof name === 'object') { + for (o_name in name) { + o = name[o_name]; + this.val(o_name, o, content); + } + return this; + } else if ((name != null) && (content != null)) { + if (mutable != null) { + if (mutable === true || mutable === 'mutable') { + mutable = true; + } else { + mutable = false; + } + } else { + mutable = this.mutable_default; + } + if (typeof content === 'function') { + return this; + } else if (((!mutable) || typeof content === 'number') && content.constructor !== Object) { + obj = HB.addOperation(new types.ImmutableObject(void 0, content)).execute(); + return JsonType.__super__.val.call(this, name, obj); + } else { + if (typeof content === 'string') { + word = HB.addOperation(new types.Word(void 0)).execute(); + word.insertText(0, content); + return JsonType.__super__.val.call(this, name, word); + } else if (content.constructor === Object) { + json = HB.addOperation(new JsonType(void 0, content, mutable)).execute(); + return JsonType.__super__.val.call(this, name, json); + } else { + throw new Error("You must not set " + (typeof content) + "-types in collaborative Json-objects!"); + } + } + } else { + return JsonType.__super__.val.call(this, name, content); + } + }; + + Object.defineProperty(JsonType.prototype, 'value', { + get: function() { + return createJsonWrapper(this); + }, + set: function(o) { + var o_name, o_obj, _results; + if (o.constructor === {}.constructor) { + _results = []; + for (o_name in o) { + o_obj = o[o_name]; + _results.push(this.val(o_name, o_obj, 'immutable')); + } + return _results; + } else { + throw new Error("You must only set Object values!"); + } + } + }); + + JsonType.prototype._encode = function() { + return { + 'type': "JsonType", + 'uid': this.getUid() + }; + }; + + return JsonType; + + })(types.MapManager); + parser['JsonType'] = function(json) { + var uid; + uid = json['uid']; + return new JsonType(uid); + }; + types['JsonType'] = JsonType; + return text_types; +}; + + +},{"./TextTypes":10}],9:[function(require,module,exports){ +var basic_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +basic_types_uninitialized = require("./BasicTypes"); + +module.exports = function(HB) { + var AddName, ListManager, MapManager, ReplaceManager, Replaceable, basic_types, parser, types; + basic_types = basic_types_uninitialized(HB); + types = basic_types.types; + parser = basic_types.parser; + MapManager = (function(_super) { + __extends(MapManager, _super); + + function MapManager(uid) { + this.map = {}; + MapManager.__super__.constructor.call(this, uid); + } + + MapManager.prototype.val = function(name, content) { + var o, obj, result, _ref, _ref1; + if (content != null) { + if (this.map[name] == null) { + HB.addOperation(new AddName(void 0, this, name)).execute(); + } + this.map[name].replace(content); + return this; + } else if (name != null) { + obj = (_ref = this.map[name]) != null ? _ref.val() : void 0; + if (obj instanceof types.ImmutableObject) { + return obj.val(); + } else { + return obj; + } + } else { + result = {}; + _ref1 = this.map; + for (name in _ref1) { + o = _ref1[name]; + obj = o.val(); + if (obj instanceof types.ImmutableObject || obj instanceof MapManager) { + obj = obj.val(); + } + result[name] = obj; + } + return result; + } + }; + + return MapManager; + + })(types.Operation); + AddName = (function(_super) { + __extends(AddName, _super); + + function AddName(uid, map_manager, name) { + this.name = name; + this.saveOperation('map_manager', map_manager); + AddName.__super__.constructor.call(this, uid); + } + + AddName.prototype.execute = function() { + var beg, end, uid_beg, uid_end, uid_r; + if (!this.validateSavedOperations()) { + return false; + } else { + uid_r = this.map_manager.getUid(); + uid_r.op_number = "_" + uid_r.op_number + "_RM_" + this.name; + if (HB.getOperation(uid_r) == null) { + uid_beg = this.map_manager.getUid(); + uid_beg.op_number = "_" + uid_beg.op_number + "_RM_" + this.name + "_beginning"; + uid_end = this.map_manager.getUid(); + uid_end.op_number = "_" + uid_end.op_number + "_RM_" + this.name + "_end"; + beg = HB.addOperation(new types.Delimiter(uid_beg, void 0, uid_end)).execute(); + end = HB.addOperation(new types.Delimiter(uid_end, beg, void 0)).execute(); + this.map_manager.map[this.name] = HB.addOperation(new ReplaceManager(void 0, uid_r, beg, end)).execute(); + } + return AddName.__super__.execute.apply(this, arguments); + } + }; + + AddName.prototype._encode = function() { + return { + 'type': "AddName", + 'uid': this.getUid(), + 'map_manager': this.map_manager.getUid(), + 'name': this.name + }; + }; + + return AddName; + + })(types.Operation); + parser['AddName'] = function(json) { + var map_manager, name, uid; + map_manager = json['map_manager'], uid = json['uid'], name = json['name']; + return new AddName(uid, map_manager, name); + }; + ListManager = (function(_super) { + __extends(ListManager, _super); + + function ListManager(uid, beginning, end, prev, next, origin) { + if ((beginning != null) && (end != null)) { + this.saveOperation('beginning', beginning); + this.saveOperation('end', end); + } else { + this.beginning = HB.addOperation(new types.Delimiter(void 0, void 0, void 0)); + this.end = HB.addOperation(new types.Delimiter(void 0, this.beginning, void 0)); + this.beginning.next_cl = this.end; + this.beginning.execute(); + this.end.execute(); + } + ListManager.__super__.constructor.call(this, uid, prev, next, origin); + } + + ListManager.prototype.getLastOperation = function() { + return this.end.prev_cl; + }; + + ListManager.prototype.getFirstOperation = function() { + return this.beginning.next_cl; + }; + + ListManager.prototype.toArray = function() { + var o, result; + o = this.beginning.next_cl; + result = []; + while (o !== this.end) { + result.push(o); + o = o.next_cl; + } + return result; + }; + + ListManager.prototype.getOperationByPosition = function(position) { + var o; + o = this.beginning.next_cl; + if (position > 0) { + while (true) { + o = o.next_cl; + if (!o.isDeleted()) { + position -= 1; + } + if (position === 0) { + break; + } + if (o instanceof types.Delimiter) { + throw new Error("position parameter exceeded the length of the document!"); + } + } + } + return o; + }; + + return ListManager; + + })(types.Insert); + ReplaceManager = (function(_super) { + __extends(ReplaceManager, _super); + + function ReplaceManager(initial_content, uid, beginning, end, prev, next, origin) { + ReplaceManager.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + if (initial_content != null) { + this.replace(initial_content); + } + } + + ReplaceManager.prototype.replace = function(content) { + var o, op; + o = this.getLastOperation(); + op = new Replaceable(content, this, void 0, o, o.next_cl); + return HB.addOperation(op).execute(); + }; + + ReplaceManager.prototype.val = function() { + var o; + o = this.getLastOperation(); + if (o instanceof types.Delimiter) { + throw new Error("dtrn"); + } + return o.val(); + }; + + ReplaceManager.prototype._encode = function() { + var json; + json = { + 'type': "ReplaceManager", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if ((this.prev_cl != null) && (this.next_cl != null)) { + json['prev'] = this.prev_cl.getUid(); + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ReplaceManager; + + })(ListManager); + parser["ReplaceManager"] = function(json) { + var beginning, content, end, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], beginning = json['beginning'], end = json['end']; + return new ReplaceManager(content, uid, beginning, end, prev, next, origin); + }; + Replaceable = (function(_super) { + __extends(Replaceable, _super); + + function Replaceable(content, parent, uid, prev, next, origin) { + this.saveOperation('content', content); + this.saveOperation('parent', parent); + if (!((prev != null) && (next != null) && (content != null))) { + throw new Error("You must define content, prev, and next for Replaceable-types!"); + } + Replaceable.__super__.constructor.call(this, uid, prev, next, origin); + } + + Replaceable.prototype.val = function() { + return this.content; + }; + + Replaceable.prototype.replace = function(content) { + return this.parent.replace(content); + }; + + Replaceable.prototype.execute = function() { + var _base; + if (!this.validateSavedOperations()) { + return false; + } else { + if (typeof (_base = this.content).setReplaceManager === "function") { + _base.setReplaceManager(this.parent); + } + Replaceable.__super__.execute.apply(this, arguments); + return this; + } + }; + + Replaceable.prototype._encode = function() { + var json; + json = { + 'type': "Replaceable", + 'content': this.content.getUid(), + 'ReplaceManager': this.parent.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid(), + 'uid': this.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Replaceable; + + })(types.Insert); + parser["Replaceable"] = function(json) { + var content, next, origin, parent, prev, uid; + content = json['content'], parent = json['ReplaceManager'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Replaceable(content, parent, uid, prev, next, origin); + }; + types['ListManager'] = ListManager; + types['MapManager'] = MapManager; + types['ReplaceManager'] = ReplaceManager; + types['Replaceable'] = Replaceable; + return basic_types; +}; + + +},{"./BasicTypes":7}],10:[function(require,module,exports){ +var structured_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +structured_types_uninitialized = require("./StructuredTypes"); + +module.exports = function(HB) { + var TextDelete, TextInsert, Word, parser, structured_types, types; + structured_types = structured_types_uninitialized(HB); + types = structured_types.types; + parser = structured_types.parser; + TextDelete = (function(_super) { + __extends(TextDelete, _super); + + function TextDelete() { + return TextDelete.__super__.constructor.apply(this, arguments); + } + + return TextDelete; + + })(types.Delete); + parser["TextDelete"] = parser["Delete"]; + TextInsert = (function(_super) { + __extends(TextInsert, _super); + + function TextInsert(content, uid, prev, next, origin) { + this.content = content; + if (!((prev != null) && (next != null))) { + throw new Error("You must define prev, and next for TextInsert-types!"); + } + TextInsert.__super__.constructor.call(this, uid, prev, next, origin); + } + + TextInsert.prototype.getLength = function() { + if (this.isDeleted()) { + return 0; + } else { + return this.content.length; + } + }; + + TextInsert.prototype.val = function(current_position) { + if (this.isDeleted()) { + return ""; + } else { + return this.content; + } + }; + + TextInsert.prototype._encode = function() { + var json; + json = { + 'type': "TextInsert", + 'content': this.content, + 'uid': this.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return TextInsert; + + })(types.Insert); + parser["TextInsert"] = function(json) { + var content, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new TextInsert(content, uid, prev, next, origin); + }; + Word = (function(_super) { + __extends(Word, _super); + + function Word(uid, beginning, end, prev, next, origin) { + Word.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + } + + Word.prototype.insertText = function(position, content) { + var c, o, op, _i, _len, _results; + o = this.getOperationByPosition(position); + _results = []; + for (_i = 0, _len = content.length; _i < _len; _i++) { + c = content[_i]; + op = new TextInsert(c, void 0, o.prev_cl, o); + _results.push(HB.addOperation(op).execute()); + } + return _results; + }; + + Word.prototype.deleteText = function(position, length) { + var d, i, o, _i, _results; + o = this.getOperationByPosition(position); + _results = []; + for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) { + d = HB.addOperation(new TextDelete(void 0, o)).execute(); + o = o.next_cl; + while (o.isDeleted()) { + if (o instanceof types.Delimiter) { + throw new Error("You can't delete more than there is.."); + } + o = o.next_cl; + } + _results.push(d._encode()); + } + return _results; + }; + + Word.prototype.replaceText = function(text) { + var word; + if (this.replace_manager != null) { + word = HB.addOperation(new Word(void 0)).execute(); + word.insertText(0, text); + return this.replace_manager.replace(word); + } else { + throw new Error("This type is currently not maintained by a ReplaceManager!"); + } + }; + + Word.prototype.val = function() { + var c, o; + c = (function() { + var _i, _len, _ref, _results; + _ref = this.toArray(); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + o = _ref[_i]; + if (o.val != null) { + _results.push(o.val()); + } else { + _results.push(""); + } + } + return _results; + }).call(this); + return c.join(''); + }; + + Word.prototype.setReplaceManager = function(op) { + this.saveOperation('replace_manager', op); + return this.validateSavedOperations; + }; + + Word.prototype._encode = function() { + var json; + json = { + 'type': "Word", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Word; + + })(types.ListManager); + parser['Word'] = function(json) { + var beginning, end, next, origin, prev, uid; + uid = json['uid'], beginning = json['beginning'], end = json['end'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Word(uid, beginning, end, prev, next, origin); + }; + types['TextInsert'] = TextInsert; + types['TextDelete'] = TextDelete; + types['Word'] = Word; + return structured_types; +}; + + +},{"./StructuredTypes":9}],11:[function(require,module,exports){ +exports['IwcConnector'] = require('./Connectors/IwcConnector'); + +exports['TestConnector'] = require('./Connectors/TestConnector'); + +exports['JsonYatta'] = require('./Frameworks/JsonYatta'); + +exports['TextYatta'] = require('./Frameworks/TextYatta'); + + +},{"./Connectors/IwcConnector":1,"./Connectors/TestConnector":2,"./Frameworks/JsonYatta":4,"./Frameworks/TextYatta":5}],12:[function(require,module,exports){ +// Underscore.js 1.6.0 +// http://underscorejs.org +// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors +// Underscore may be freely distributed under the MIT license. + +(function() { + + // Baseline setup + // -------------- + + // Establish the root object, `window` in the browser, or `exports` on the server. + var root = this; + + // Save the previous value of the `_` variable. + var previousUnderscore = root._; + + // Establish the object that gets returned to break out of a loop iteration. + var breaker = {}; + + // Save bytes in the minified (but not gzipped) version: + var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; + + // Create quick reference variables for speed access to core prototypes. + var + push = ArrayProto.push, + slice = ArrayProto.slice, + concat = ArrayProto.concat, + toString = ObjProto.toString, + hasOwnProperty = ObjProto.hasOwnProperty; + + // All **ECMAScript 5** native function implementations that we hope to use + // are declared here. + var + nativeForEach = ArrayProto.forEach, + nativeMap = ArrayProto.map, + nativeReduce = ArrayProto.reduce, + nativeReduceRight = ArrayProto.reduceRight, + nativeFilter = ArrayProto.filter, + nativeEvery = ArrayProto.every, + nativeSome = ArrayProto.some, + nativeIndexOf = ArrayProto.indexOf, + nativeLastIndexOf = ArrayProto.lastIndexOf, + nativeIsArray = Array.isArray, + nativeKeys = Object.keys, + nativeBind = FuncProto.bind; + + // Create a safe reference to the Underscore object for use below. + var _ = function(obj) { + if (obj instanceof _) return obj; + if (!(this instanceof _)) return new _(obj); + this._wrapped = obj; + }; + + // Export the Underscore object for **Node.js**, with + // backwards-compatibility for the old `require()` API. If we're in + // the browser, add `_` as a global object via a string identifier, + // for Closure Compiler "advanced" mode. + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = _; + } + exports._ = _; + } else { + root._ = _; + } + + // Current version. + _.VERSION = '1.6.0'; + + // Collection Functions + // -------------------- + + // The cornerstone, an `each` implementation, aka `forEach`. + // Handles objects with the built-in `forEach`, arrays, and raw objects. + // Delegates to **ECMAScript 5**'s native `forEach` if available. + var each = _.each = _.forEach = function(obj, iterator, context) { + if (obj == null) return obj; + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, length = obj.length; i < length; i++) { + if (iterator.call(context, obj[i], i, obj) === breaker) return; + } + } else { + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; + } + } + return obj; + }; + + // Return the results of applying the iterator to each element. + // Delegates to **ECMAScript 5**'s native `map` if available. + _.map = _.collect = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + each(obj, function(value, index, list) { + results.push(iterator.call(context, value, index, list)); + }); + return results; + }; + + var reduceError = 'Reduce of empty array with no initial value'; + + // **Reduce** builds up a single result from a list of values, aka `inject`, + // or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. + _.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduce && obj.reduce === nativeReduce) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); + } + each(obj, function(value, index, list) { + if (!initial) { + memo = value; + initial = true; + } else { + memo = iterator.call(context, memo, value, index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // The right-associative version of reduce, also known as `foldr`. + // Delegates to **ECMAScript 5**'s native `reduceRight` if available. + _.reduceRight = _.foldr = function(obj, iterator, memo, context) { + var initial = arguments.length > 2; + if (obj == null) obj = []; + if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { + if (context) iterator = _.bind(iterator, context); + return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); + } + var length = obj.length; + if (length !== +length) { + var keys = _.keys(obj); + length = keys.length; + } + each(obj, function(value, index, list) { + index = keys ? keys[--length] : --length; + if (!initial) { + memo = obj[index]; + initial = true; + } else { + memo = iterator.call(context, memo, obj[index], index, list); + } + }); + if (!initial) throw new TypeError(reduceError); + return memo; + }; + + // Return the first value which passes a truth test. Aliased as `detect`. + _.find = _.detect = function(obj, predicate, context) { + var result; + any(obj, function(value, index, list) { + if (predicate.call(context, value, index, list)) { + result = value; + return true; + } + }); + return result; + }; + + // Return all the elements that pass a truth test. + // Delegates to **ECMAScript 5**'s native `filter` if available. + // Aliased as `select`. + _.filter = _.select = function(obj, predicate, context) { + var results = []; + if (obj == null) return results; + if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); + each(obj, function(value, index, list) { + if (predicate.call(context, value, index, list)) results.push(value); + }); + return results; + }; + + // Return all the elements for which a truth test fails. + _.reject = function(obj, predicate, context) { + return _.filter(obj, function(value, index, list) { + return !predicate.call(context, value, index, list); + }, context); + }; + + // Determine whether all of the elements match a truth test. + // Delegates to **ECMAScript 5**'s native `every` if available. + // Aliased as `all`. + _.every = _.all = function(obj, predicate, context) { + predicate || (predicate = _.identity); + var result = true; + if (obj == null) return result; + if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context); + each(obj, function(value, index, list) { + if (!(result = result && predicate.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if at least one element in the object matches a truth test. + // Delegates to **ECMAScript 5**'s native `some` if available. + // Aliased as `any`. + var any = _.some = _.any = function(obj, predicate, context) { + predicate || (predicate = _.identity); + var result = false; + if (obj == null) return result; + if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); + each(obj, function(value, index, list) { + if (result || (result = predicate.call(context, value, index, list))) return breaker; + }); + return !!result; + }; + + // Determine if the array or object contains a given value (using `===`). + // Aliased as `include`. + _.contains = _.include = function(obj, target) { + if (obj == null) return false; + if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; + return any(obj, function(value) { + return value === target; + }); + }; + + // Invoke a method (with arguments) on every item in a collection. + _.invoke = function(obj, method) { + var args = slice.call(arguments, 2); + var isFunc = _.isFunction(method); + return _.map(obj, function(value) { + return (isFunc ? method : value[method]).apply(value, args); + }); + }; + + // Convenience version of a common use case of `map`: fetching a property. + _.pluck = function(obj, key) { + return _.map(obj, _.property(key)); + }; + + // Convenience version of a common use case of `filter`: selecting only objects + // containing specific `key:value` pairs. + _.where = function(obj, attrs) { + return _.filter(obj, _.matches(attrs)); + }; + + // Convenience version of a common use case of `find`: getting the first object + // containing specific `key:value` pairs. + _.findWhere = function(obj, attrs) { + return _.find(obj, _.matches(attrs)); + }; + + // Return the maximum element or (element-based computation). + // Can't optimize arrays of integers longer than 65,535 elements. + // See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) + _.max = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.max.apply(Math, obj); + } + var result = -Infinity, lastComputed = -Infinity; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + if (computed > lastComputed) { + result = value; + lastComputed = computed; + } + }); + return result; + }; + + // Return the minimum element (or element-based computation). + _.min = function(obj, iterator, context) { + if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { + return Math.min.apply(Math, obj); + } + var result = Infinity, lastComputed = Infinity; + each(obj, function(value, index, list) { + var computed = iterator ? iterator.call(context, value, index, list) : value; + if (computed < lastComputed) { + result = value; + lastComputed = computed; + } + }); + return result; + }; + + // Shuffle an array, using the modern version of the + // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). + _.shuffle = function(obj) { + var rand; + var index = 0; + var shuffled = []; + each(obj, function(value) { + rand = _.random(index++); + shuffled[index - 1] = shuffled[rand]; + shuffled[rand] = value; + }); + return shuffled; + }; + + // Sample **n** random values from a collection. + // If **n** is not specified, returns a single random element. + // The internal `guard` argument allows it to work with `map`. + _.sample = function(obj, n, guard) { + if (n == null || guard) { + if (obj.length !== +obj.length) obj = _.values(obj); + return obj[_.random(obj.length - 1)]; + } + return _.shuffle(obj).slice(0, Math.max(0, n)); + }; + + // An internal function to generate lookup iterators. + var lookupIterator = function(value) { + if (value == null) return _.identity; + if (_.isFunction(value)) return value; + return _.property(value); + }; + + // Sort the object's values by a criterion produced by an iterator. + _.sortBy = function(obj, iterator, context) { + iterator = lookupIterator(iterator); + return _.pluck(_.map(obj, function(value, index, list) { + return { + value: value, + index: index, + criteria: iterator.call(context, value, index, list) + }; + }).sort(function(left, right) { + var a = left.criteria; + var b = right.criteria; + if (a !== b) { + if (a > b || a === void 0) return 1; + if (a < b || b === void 0) return -1; + } + return left.index - right.index; + }), 'value'); + }; + + // An internal function used for aggregate "group by" operations. + var group = function(behavior) { + return function(obj, iterator, context) { + var result = {}; + iterator = lookupIterator(iterator); + each(obj, function(value, index) { + var key = iterator.call(context, value, index, obj); + behavior(result, key, value); + }); + return result; + }; + }; + + // Groups the object's values by a criterion. Pass either a string attribute + // to group by, or a function that returns the criterion. + _.groupBy = group(function(result, key, value) { + _.has(result, key) ? result[key].push(value) : result[key] = [value]; + }); + + // Indexes the object's values by a criterion, similar to `groupBy`, but for + // when you know that your index values will be unique. + _.indexBy = group(function(result, key, value) { + result[key] = value; + }); + + // Counts instances of an object that group by a certain criterion. Pass + // either a string attribute to count by, or a function that returns the + // criterion. + _.countBy = group(function(result, key) { + _.has(result, key) ? result[key]++ : result[key] = 1; + }); + + // Use a comparator function to figure out the smallest index at which + // an object should be inserted so as to maintain order. Uses binary search. + _.sortedIndex = function(array, obj, iterator, context) { + iterator = lookupIterator(iterator); + var value = iterator.call(context, obj); + var low = 0, high = array.length; + while (low < high) { + var mid = (low + high) >>> 1; + iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; + } + return low; + }; + + // Safely create a real, live array from anything iterable. + _.toArray = function(obj) { + if (!obj) return []; + if (_.isArray(obj)) return slice.call(obj); + if (obj.length === +obj.length) return _.map(obj, _.identity); + return _.values(obj); + }; + + // Return the number of elements in an object. + _.size = function(obj) { + if (obj == null) return 0; + return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; + }; + + // Array Functions + // --------------- + + // Get the first element of an array. Passing **n** will return the first N + // values in the array. Aliased as `head` and `take`. The **guard** check + // allows it to work with `_.map`. + _.first = _.head = _.take = function(array, n, guard) { + if (array == null) return void 0; + if ((n == null) || guard) return array[0]; + if (n < 0) return []; + return slice.call(array, 0, n); + }; + + // Returns everything but the last entry of the array. Especially useful on + // the arguments object. Passing **n** will return all the values in + // the array, excluding the last N. The **guard** check allows it to work with + // `_.map`. + _.initial = function(array, n, guard) { + return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); + }; + + // Get the last element of an array. Passing **n** will return the last N + // values in the array. The **guard** check allows it to work with `_.map`. + _.last = function(array, n, guard) { + if (array == null) return void 0; + if ((n == null) || guard) return array[array.length - 1]; + return slice.call(array, Math.max(array.length - n, 0)); + }; + + // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. + // Especially useful on the arguments object. Passing an **n** will return + // the rest N values in the array. The **guard** + // check allows it to work with `_.map`. + _.rest = _.tail = _.drop = function(array, n, guard) { + return slice.call(array, (n == null) || guard ? 1 : n); + }; + + // Trim out all falsy values from an array. + _.compact = function(array) { + return _.filter(array, _.identity); + }; + + // Internal implementation of a recursive `flatten` function. + var flatten = function(input, shallow, output) { + if (shallow && _.every(input, _.isArray)) { + return concat.apply(output, input); + } + each(input, function(value) { + if (_.isArray(value) || _.isArguments(value)) { + shallow ? push.apply(output, value) : flatten(value, shallow, output); + } else { + output.push(value); + } + }); + return output; + }; + + // Flatten out an array, either recursively (by default), or just one level. + _.flatten = function(array, shallow) { + return flatten(array, shallow, []); + }; + + // Return a version of the array that does not contain the specified value(s). + _.without = function(array) { + return _.difference(array, slice.call(arguments, 1)); + }; + + // Split an array into two arrays: one whose elements all satisfy the given + // predicate, and one whose elements all do not satisfy the predicate. + _.partition = function(array, predicate) { + var pass = [], fail = []; + each(array, function(elem) { + (predicate(elem) ? pass : fail).push(elem); + }); + return [pass, fail]; + }; + + // Produce a duplicate-free version of the array. If the array has already + // been sorted, you have the option of using a faster algorithm. + // Aliased as `unique`. + _.uniq = _.unique = function(array, isSorted, iterator, context) { + if (_.isFunction(isSorted)) { + context = iterator; + iterator = isSorted; + isSorted = false; + } + var initial = iterator ? _.map(array, iterator, context) : array; + var results = []; + var seen = []; + each(initial, function(value, index) { + if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { + seen.push(value); + results.push(array[index]); + } + }); + return results; + }; + + // Produce an array that contains the union: each distinct element from all of + // the passed-in arrays. + _.union = function() { + return _.uniq(_.flatten(arguments, true)); + }; + + // Produce an array that contains every item shared between all the + // passed-in arrays. + _.intersection = function(array) { + var rest = slice.call(arguments, 1); + return _.filter(_.uniq(array), function(item) { + return _.every(rest, function(other) { + return _.contains(other, item); + }); + }); + }; + + // Take the difference between one array and a number of other arrays. + // Only the elements present in just the first array will remain. + _.difference = function(array) { + var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); + return _.filter(array, function(value){ return !_.contains(rest, value); }); + }; + + // Zip together multiple lists into a single array -- elements that share + // an index go together. + _.zip = function() { + var length = _.max(_.pluck(arguments, 'length').concat(0)); + var results = new Array(length); + for (var i = 0; i < length; i++) { + results[i] = _.pluck(arguments, '' + i); + } + return results; + }; + + // Converts lists into objects. Pass either a single array of `[key, value]` + // pairs, or two parallel arrays of the same length -- one of keys, and one of + // the corresponding values. + _.object = function(list, values) { + if (list == null) return {}; + var result = {}; + for (var i = 0, length = list.length; i < length; i++) { + if (values) { + result[list[i]] = values[i]; + } else { + result[list[i][0]] = list[i][1]; + } + } + return result; + }; + + // If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), + // we need this function. Return the position of the first occurrence of an + // item in an array, or -1 if the item is not included in the array. + // Delegates to **ECMAScript 5**'s native `indexOf` if available. + // If the array is large and already in sort order, pass `true` + // for **isSorted** to use binary search. + _.indexOf = function(array, item, isSorted) { + if (array == null) return -1; + var i = 0, length = array.length; + if (isSorted) { + if (typeof isSorted == 'number') { + i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); + } else { + i = _.sortedIndex(array, item); + return array[i] === item ? i : -1; + } + } + if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); + for (; i < length; i++) if (array[i] === item) return i; + return -1; + }; + + // Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. + _.lastIndexOf = function(array, item, from) { + if (array == null) return -1; + var hasIndex = from != null; + if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { + return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); + } + var i = (hasIndex ? from : array.length); + while (i--) if (array[i] === item) return i; + return -1; + }; + + // Generate an integer Array containing an arithmetic progression. A port of + // the native Python `range()` function. See + // [the Python documentation](http://docs.python.org/library/functions.html#range). + _.range = function(start, stop, step) { + if (arguments.length <= 1) { + stop = start || 0; + start = 0; + } + step = arguments[2] || 1; + + var length = Math.max(Math.ceil((stop - start) / step), 0); + var idx = 0; + var range = new Array(length); + + while(idx < length) { + range[idx++] = start; + start += step; + } + + return range; + }; + + // Function (ahem) Functions + // ------------------ + + // Reusable constructor function for prototype setting. + var ctor = function(){}; + + // Create a function bound to a given object (assigning `this`, and arguments, + // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if + // available. + _.bind = function(func, context) { + var args, bound; + if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); + if (!_.isFunction(func)) throw new TypeError; + args = slice.call(arguments, 2); + return bound = function() { + if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); + ctor.prototype = func.prototype; + var self = new ctor; + ctor.prototype = null; + var result = func.apply(self, args.concat(slice.call(arguments))); + if (Object(result) === result) return result; + return self; + }; + }; + + // Partially apply a function by creating a version that has had some of its + // arguments pre-filled, without changing its dynamic `this` context. _ acts + // as a placeholder, allowing any combination of arguments to be pre-filled. + _.partial = function(func) { + var boundArgs = slice.call(arguments, 1); + return function() { + var position = 0; + var args = boundArgs.slice(); + for (var i = 0, length = args.length; i < length; i++) { + if (args[i] === _) args[i] = arguments[position++]; + } + while (position < arguments.length) args.push(arguments[position++]); + return func.apply(this, args); + }; + }; + + // Bind a number of an object's methods to that object. Remaining arguments + // are the method names to be bound. Useful for ensuring that all callbacks + // defined on an object belong to it. + _.bindAll = function(obj) { + var funcs = slice.call(arguments, 1); + if (funcs.length === 0) throw new Error('bindAll must be passed function names'); + each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); + return obj; + }; + + // Memoize an expensive function by storing its results. + _.memoize = function(func, hasher) { + var memo = {}; + hasher || (hasher = _.identity); + return function() { + var key = hasher.apply(this, arguments); + return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); + }; + }; + + // Delays a function for the given number of milliseconds, and then calls + // it with the arguments supplied. + _.delay = function(func, wait) { + var args = slice.call(arguments, 2); + return setTimeout(function(){ return func.apply(null, args); }, wait); + }; + + // Defers a function, scheduling it to run after the current call stack has + // cleared. + _.defer = function(func) { + return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); + }; + + // Returns a function, that, when invoked, will only be triggered at most once + // during a given window of time. Normally, the throttled function will run + // as much as it can, without ever going more than once per `wait` duration; + // but if you'd like to disable the execution on the leading edge, pass + // `{leading: false}`. To disable execution on the trailing edge, ditto. + _.throttle = function(func, wait, options) { + var context, args, result; + var timeout = null; + var previous = 0; + options || (options = {}); + var later = function() { + previous = options.leading === false ? 0 : _.now(); + timeout = null; + result = func.apply(context, args); + context = args = null; + }; + return function() { + var now = _.now(); + if (!previous && options.leading === false) previous = now; + var remaining = wait - (now - previous); + context = this; + args = arguments; + if (remaining <= 0) { + clearTimeout(timeout); + timeout = null; + previous = now; + result = func.apply(context, args); + context = args = null; + } else if (!timeout && options.trailing !== false) { + timeout = setTimeout(later, remaining); + } + return result; + }; + }; + + // Returns a function, that, as long as it continues to be invoked, will not + // be triggered. The function will be called after it stops being called for + // N milliseconds. If `immediate` is passed, trigger the function on the + // leading edge, instead of the trailing. + _.debounce = function(func, wait, immediate) { + var timeout, args, context, timestamp, result; + + var later = function() { + var last = _.now() - timestamp; + if (last < wait) { + timeout = setTimeout(later, wait - last); + } else { + timeout = null; + if (!immediate) { + result = func.apply(context, args); + context = args = null; + } + } + }; + + return function() { + context = this; + args = arguments; + timestamp = _.now(); + var callNow = immediate && !timeout; + if (!timeout) { + timeout = setTimeout(later, wait); + } + if (callNow) { + result = func.apply(context, args); + context = args = null; + } + + return result; + }; + }; + + // Returns a function that will be executed at most one time, no matter how + // often you call it. Useful for lazy initialization. + _.once = function(func) { + var ran = false, memo; + return function() { + if (ran) return memo; + ran = true; + memo = func.apply(this, arguments); + func = null; + return memo; + }; + }; + + // Returns the first function passed as an argument to the second, + // allowing you to adjust arguments, run code before and after, and + // conditionally execute the original function. + _.wrap = function(func, wrapper) { + return _.partial(wrapper, func); + }; + + // Returns a function that is the composition of a list of functions, each + // consuming the return value of the function that follows. + _.compose = function() { + var funcs = arguments; + return function() { + var args = arguments; + for (var i = funcs.length - 1; i >= 0; i--) { + args = [funcs[i].apply(this, args)]; + } + return args[0]; + }; + }; + + // Returns a function that will only be executed after being called N times. + _.after = function(times, func) { + return function() { + if (--times < 1) { + return func.apply(this, arguments); + } + }; + }; + + // Object Functions + // ---------------- + + // Retrieve the names of an object's properties. + // Delegates to **ECMAScript 5**'s native `Object.keys` + _.keys = function(obj) { + if (!_.isObject(obj)) return []; + if (nativeKeys) return nativeKeys(obj); + var keys = []; + for (var key in obj) if (_.has(obj, key)) keys.push(key); + return keys; + }; + + // Retrieve the values of an object's properties. + _.values = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var values = new Array(length); + for (var i = 0; i < length; i++) { + values[i] = obj[keys[i]]; + } + return values; + }; + + // Convert an object into a list of `[key, value]` pairs. + _.pairs = function(obj) { + var keys = _.keys(obj); + var length = keys.length; + var pairs = new Array(length); + for (var i = 0; i < length; i++) { + pairs[i] = [keys[i], obj[keys[i]]]; + } + return pairs; + }; + + // Invert the keys and values of an object. The values must be serializable. + _.invert = function(obj) { + var result = {}; + var keys = _.keys(obj); + for (var i = 0, length = keys.length; i < length; i++) { + result[obj[keys[i]]] = keys[i]; + } + return result; + }; + + // Return a sorted list of the function names available on the object. + // Aliased as `methods` + _.functions = _.methods = function(obj) { + var names = []; + for (var key in obj) { + if (_.isFunction(obj[key])) names.push(key); + } + return names.sort(); + }; + + // Extend a given object with all the properties in passed-in object(s). + _.extend = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Return a copy of the object only containing the whitelisted properties. + _.pick = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + each(keys, function(key) { + if (key in obj) copy[key] = obj[key]; + }); + return copy; + }; + + // Return a copy of the object without the blacklisted properties. + _.omit = function(obj) { + var copy = {}; + var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); + for (var key in obj) { + if (!_.contains(keys, key)) copy[key] = obj[key]; + } + return copy; + }; + + // Fill in a given object with default properties. + _.defaults = function(obj) { + each(slice.call(arguments, 1), function(source) { + if (source) { + for (var prop in source) { + if (obj[prop] === void 0) obj[prop] = source[prop]; + } + } + }); + return obj; + }; + + // Create a (shallow-cloned) duplicate of an object. + _.clone = function(obj) { + if (!_.isObject(obj)) return obj; + return _.isArray(obj) ? obj.slice() : _.extend({}, obj); + }; + + // Invokes interceptor with the obj, and then returns obj. + // The primary purpose of this method is to "tap into" a method chain, in + // order to perform operations on intermediate results within the chain. + _.tap = function(obj, interceptor) { + interceptor(obj); + return obj; + }; + + // Internal recursive comparison function for `isEqual`. + var eq = function(a, b, aStack, bStack) { + // Identical objects are equal. `0 === -0`, but they aren't identical. + // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). + if (a === b) return a !== 0 || 1 / a == 1 / b; + // A strict comparison is necessary because `null == undefined`. + if (a == null || b == null) return a === b; + // Unwrap any wrapped objects. + if (a instanceof _) a = a._wrapped; + if (b instanceof _) b = b._wrapped; + // Compare `[[Class]]` names. + var className = toString.call(a); + if (className != toString.call(b)) return false; + switch (className) { + // Strings, numbers, dates, and booleans are compared by value. + case '[object String]': + // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is + // equivalent to `new String("5")`. + return a == String(b); + case '[object Number]': + // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for + // other numeric values. + return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); + case '[object Date]': + case '[object Boolean]': + // Coerce dates and booleans to numeric primitive values. Dates are compared by their + // millisecond representations. Note that invalid dates with millisecond representations + // of `NaN` are not equivalent. + return +a == +b; + // RegExps are compared by their source patterns and flags. + case '[object RegExp]': + return a.source == b.source && + a.global == b.global && + a.multiline == b.multiline && + a.ignoreCase == b.ignoreCase; + } + if (typeof a != 'object' || typeof b != 'object') return false; + // Assume equality for cyclic structures. The algorithm for detecting cyclic + // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. + var length = aStack.length; + while (length--) { + // Linear search. Performance is inversely proportional to the number of + // unique nested structures. + if (aStack[length] == a) return bStack[length] == b; + } + // Objects with different constructors are not equivalent, but `Object`s + // from different frames are. + var aCtor = a.constructor, bCtor = b.constructor; + if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && + _.isFunction(bCtor) && (bCtor instanceof bCtor)) + && ('constructor' in a && 'constructor' in b)) { + return false; + } + // Add the first object to the stack of traversed objects. + aStack.push(a); + bStack.push(b); + var size = 0, result = true; + // Recursively compare objects and arrays. + if (className == '[object Array]') { + // Compare array lengths to determine if a deep comparison is necessary. + size = a.length; + result = size == b.length; + if (result) { + // Deep compare the contents, ignoring non-numeric properties. + while (size--) { + if (!(result = eq(a[size], b[size], aStack, bStack))) break; + } + } + } else { + // Deep compare objects. + for (var key in a) { + if (_.has(a, key)) { + // Count the expected number of properties. + size++; + // Deep compare each member. + if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; + } + } + // Ensure that both objects contain the same number of properties. + if (result) { + for (key in b) { + if (_.has(b, key) && !(size--)) break; + } + result = !size; + } + } + // Remove the first object from the stack of traversed objects. + aStack.pop(); + bStack.pop(); + return result; + }; + + // Perform a deep comparison to check if two objects are equal. + _.isEqual = function(a, b) { + return eq(a, b, [], []); + }; + + // Is a given array, string, or object empty? + // An "empty" object has no enumerable own-properties. + _.isEmpty = function(obj) { + if (obj == null) return true; + if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; + for (var key in obj) if (_.has(obj, key)) return false; + return true; + }; + + // Is a given value a DOM element? + _.isElement = function(obj) { + return !!(obj && obj.nodeType === 1); + }; + + // Is a given value an array? + // Delegates to ECMA5's native Array.isArray + _.isArray = nativeIsArray || function(obj) { + return toString.call(obj) == '[object Array]'; + }; + + // Is a given variable an object? + _.isObject = function(obj) { + return obj === Object(obj); + }; + + // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. + each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { + _['is' + name] = function(obj) { + return toString.call(obj) == '[object ' + name + ']'; + }; + }); + + // Define a fallback version of the method in browsers (ahem, IE), where + // there isn't any inspectable "Arguments" type. + if (!_.isArguments(arguments)) { + _.isArguments = function(obj) { + return !!(obj && _.has(obj, 'callee')); + }; + } + + // Optimize `isFunction` if appropriate. + if (typeof (/./) !== 'function') { + _.isFunction = function(obj) { + return typeof obj === 'function'; + }; + } + + // Is a given object a finite number? + _.isFinite = function(obj) { + return isFinite(obj) && !isNaN(parseFloat(obj)); + }; + + // Is the given value `NaN`? (NaN is the only number which does not equal itself). + _.isNaN = function(obj) { + return _.isNumber(obj) && obj != +obj; + }; + + // Is a given value a boolean? + _.isBoolean = function(obj) { + return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; + }; + + // Is a given value equal to null? + _.isNull = function(obj) { + return obj === null; + }; + + // Is a given variable undefined? + _.isUndefined = function(obj) { + return obj === void 0; + }; + + // Shortcut function for checking if an object has a given property directly + // on itself (in other words, not on a prototype). + _.has = function(obj, key) { + return hasOwnProperty.call(obj, key); + }; + + // Utility Functions + // ----------------- + + // Run Underscore.js in *noConflict* mode, returning the `_` variable to its + // previous owner. Returns a reference to the Underscore object. + _.noConflict = function() { + root._ = previousUnderscore; + return this; + }; + + // Keep the identity function around for default iterators. + _.identity = function(value) { + return value; + }; + + _.constant = function(value) { + return function () { + return value; + }; + }; + + _.property = function(key) { + return function(obj) { + return obj[key]; + }; + }; + + // Returns a predicate for checking whether an object has a given set of `key:value` pairs. + _.matches = function(attrs) { + return function(obj) { + if (obj === attrs) return true; //avoid comparing an object to itself. + for (var key in attrs) { + if (attrs[key] !== obj[key]) + return false; + } + return true; + } + }; + + // Run a function **n** times. + _.times = function(n, iterator, context) { + var accum = Array(Math.max(0, n)); + for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); + return accum; + }; + + // Return a random integer between min and max (inclusive). + _.random = function(min, max) { + if (max == null) { + max = min; + min = 0; + } + return min + Math.floor(Math.random() * (max - min + 1)); + }; + + // A (possibly faster) way to get the current timestamp as an integer. + _.now = Date.now || function() { return new Date().getTime(); }; + + // List of HTML entities for escaping. + var entityMap = { + escape: { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' + } + }; + entityMap.unescape = _.invert(entityMap.escape); + + // Regexes containing the keys and values listed immediately above. + var entityRegexes = { + escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), + unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') + }; + + // Functions for escaping and unescaping strings to/from HTML interpolation. + _.each(['escape', 'unescape'], function(method) { + _[method] = function(string) { + if (string == null) return ''; + return ('' + string).replace(entityRegexes[method], function(match) { + return entityMap[method][match]; + }); + }; + }); + + // If the value of the named `property` is a function then invoke it with the + // `object` as context; otherwise, return it. + _.result = function(object, property) { + if (object == null) return void 0; + var value = object[property]; + return _.isFunction(value) ? value.call(object) : value; + }; + + // Add your own custom functions to the Underscore object. + _.mixin = function(obj) { + each(_.functions(obj), function(name) { + var func = _[name] = obj[name]; + _.prototype[name] = function() { + var args = [this._wrapped]; + push.apply(args, arguments); + return result.call(this, func.apply(_, args)); + }; + }); + }; + + // Generate a unique integer id (unique within the entire client session). + // Useful for temporary DOM ids. + var idCounter = 0; + _.uniqueId = function(prefix) { + var id = ++idCounter + ''; + return prefix ? prefix + id : id; + }; + + // By default, Underscore uses ERB-style template delimiters, change the + // following template settings to use alternative delimiters. + _.templateSettings = { + evaluate : /<%([\s\S]+?)%>/g, + interpolate : /<%=([\s\S]+?)%>/g, + escape : /<%-([\s\S]+?)%>/g + }; + + // When customizing `templateSettings`, if you don't want to define an + // interpolation, evaluation or escaping regex, we need one that is + // guaranteed not to match. + var noMatch = /(.)^/; + + // Certain characters need to be escaped so that they can be put into a + // string literal. + var escapes = { + "'": "'", + '\\': '\\', + '\r': 'r', + '\n': 'n', + '\t': 't', + '\u2028': 'u2028', + '\u2029': 'u2029' + }; + + var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; + + // JavaScript micro-templating, similar to John Resig's implementation. + // Underscore templating handles arbitrary delimiters, preserves whitespace, + // and correctly escapes quotes within interpolated code. + _.template = function(text, data, settings) { + var render; + settings = _.defaults({}, settings, _.templateSettings); + + // Combine delimiters into one regular expression via alternation. + var matcher = new RegExp([ + (settings.escape || noMatch).source, + (settings.interpolate || noMatch).source, + (settings.evaluate || noMatch).source + ].join('|') + '|$', 'g'); + + // Compile the template source, escaping string literals appropriately. + var index = 0; + var source = "__p+='"; + text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { + source += text.slice(index, offset) + .replace(escaper, function(match) { return '\\' + escapes[match]; }); + + if (escape) { + source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; + } + if (interpolate) { + source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; + } + if (evaluate) { + source += "';\n" + evaluate + "\n__p+='"; + } + index = offset + match.length; + return match; + }); + source += "';\n"; + + // If a variable is not specified, place data values in local scope. + if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; + + source = "var __t,__p='',__j=Array.prototype.join," + + "print=function(){__p+=__j.call(arguments,'');};\n" + + source + "return __p;\n"; + + try { + render = new Function(settings.variable || 'obj', '_', source); + } catch (e) { + e.source = source; + throw e; + } + + if (data) return render(data, _); + var template = function(data) { + return render.call(this, data, _); + }; + + // Provide the compiled function source as a convenience for precompilation. + template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; + + return template; + }; + + // Add a "chain" function, which will delegate to the wrapper. + _.chain = function(obj) { + return _(obj).chain(); + }; + + // OOP + // --------------- + // If Underscore is called as a function, it returns a wrapped object that + // can be used OO-style. This wrapper holds altered versions of all the + // underscore functions. Wrapped objects may be chained. + + // Helper function to continue chaining intermediate results. + var result = function(obj) { + return this._chain ? _(obj).chain() : obj; + }; + + // Add all of the Underscore functions to the wrapper object. + _.mixin(_); + + // Add all mutator Array functions to the wrapper. + each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + var obj = this._wrapped; + method.apply(obj, arguments); + if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; + return result.call(this, obj); + }; + }); + + // Add all accessor Array functions to the wrapper. + each(['concat', 'join', 'slice'], function(name) { + var method = ArrayProto[name]; + _.prototype[name] = function() { + return result.call(this, method.apply(this._wrapped, arguments)); + }; + }); + + _.extend(_.prototype, { + + // Start chaining a wrapped Underscore object. + chain: function() { + this._chain = true; + return this; + }, + + // Extracts the result from a wrapped and chained object. + value: function() { + return this._wrapped; + } + + }); + + // AMD registration happens at the end for compatibility with AMD loaders + // that may not enforce next-turn semantics on modules. Even though general + // practice for AMD registration is to be anonymous, underscore registers + // as a named module because, like jQuery, it is a base library that is + // popular enough to be bundled in a third party lib, but not be part of + // an AMD load request. Those cases could generate an error when an + // anonymous define() is called outside of a loader request. + if (typeof define === 'function' && define.amd) { + define('underscore', [], function() { + return _; + }); + } +}).call(this); + +},{}]},{},[11]) +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9ub2RlX21vZHVsZXMvZ3VscC1icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL0Nvbm5lY3RvcnMvSXdjQ29ubmVjdG9yLmNvZmZlZSIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9saWIvQ29ubmVjdG9ycy9UZXN0Q29ubmVjdG9yLmNvZmZlZSIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9saWIvRW5naW5lLmNvZmZlZSIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9saWIvRnJhbWV3b3Jrcy9Kc29uWWF0dGEuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9GcmFtZXdvcmtzL1RleHRZYXR0YS5jb2ZmZWUiLCIvaG9tZS9kbW9uYWQvRHJvcGJveC9ZYXR0YSEvbGliL0hpc3RvcnlCdWZmZXIuY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL2xpYi9UeXBlcy9CYXNpY1R5cGVzLmNvZmZlZSIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9saWIvVHlwZXMvSnNvblR5cGVzLmNvZmZlZSIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9saWIvVHlwZXMvU3RydWN0dXJlZFR5cGVzLmNvZmZlZSIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9saWIvVHlwZXMvVGV4dFR5cGVzLmNvZmZlZSIsIi9ob21lL2Rtb25hZC9Ecm9wYm94L1lhdHRhIS9saWIvaW5kZXguY29mZmVlIiwiL2hvbWUvZG1vbmFkL0Ryb3Bib3gvWWF0dGEhL25vZGVfbW9kdWxlcy91bmRlcnNjb3JlL3VuZGVyc2NvcmUuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNJQSxJQUFBLGtCQUFBOztB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Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKX12YXIgZj1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwoZi5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxmLGYuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiXG4jXG4jIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrIFRoZSBjYWxsYmFjayBpcyBjYWxsZWQgd2hlbiB0aGUgY29ubmVjdG9yIGlzIGluaXRpYWxpemVkLlxuI1xuY3JlYXRlSXdjQ29ubmVjdG9yID0gKGNhbGxiYWNrKS0+XG4gIGl3Y0hhbmRsZXIgPSB7fVxuICBkdWlDbGllbnQgPSBuZXcgRFVJQ2xpZW50KClcbiAgI0BkdWlDbGllbnQgPSBuZXcgaXdjLkNsaWVudCgpXG4gIGR1aUNsaWVudC5jb25uZWN0IChpbnRlbnQpLT5cbiAgICAjY29uc29sZS5sb2cgXCJpbnRlbnQgcmVjZWl2ZWQgaXdjOiAje0pTT04uc3RyaW5naWZ5KGludGVudCl9XCJcbiAgICAjY29uc29sZS5sb2cgXCIje0pTT04uc3RyaW5naWZ5KEBpd2NIYW5kbGVyKX1cIlxuICAgIGl3Y0hhbmRsZXJbaW50ZW50LmFjdGlvbl0/Lm1hcCAoZiktPlxuICAgICAgc2V0VGltZW91dCAoKS0+XG4gICAgICAgIGYgaW50ZW50XG4gICAgICAsIDBcblxuICBkdWlDbGllbnQuaW5pdE9LKClcblxuICByZWNlaXZlZF9IQiA9IG51bGxcblxuICAjXG4gICMgVGhlIEl3YyBDb25uZWN0b3IgYWRkcyBzdXBwb3J0IGZvciB0aGUgSW50ZXItV2lkZ2V0LUNvbW11bmljYXRpb24gcHJvdG9jb2wgdGhhdCBpcyB1c2VkIGluIHRoZSBSb2xlLVNESy5cbiAgIyBAc2VlIGh0dHA6Ly9kYmlzLnJ3dGgtYWFjaGVuLmRlL2Ntcy9wcm9qZWN0cy90aGUteG1wcC1leHBlcmllbmNlI2ludGVyd2lkZ2V0LWNvbW11bmljYXRpb25cbiAgIyBAc2VlIGh0dHA6Ly9kYmlzLnJ3dGgtYWFjaGVuLmRlL2Ntcy9wcm9qZWN0cy9ST0xFXG4gICNcbiAgY2xhc3MgSXdjQ29ubmVjdG9yXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge0VuZ2luZX0gZW5naW5lIFRoZSB0cmFuc2Zvcm1hdGlvbiBlbmdpbmVcbiAgICAjIEBwYXJhbSB7SGlzdG9yeUJ1ZmZlcn0gSEJcbiAgICAjIEBwYXJhbSB7QXJyYXk8RnVuY3Rpb24+fSBleGVjdXRpb25fbGlzdGVuZXIgWW91IG11c3QgZW5zdXJlIHRoYXQgd2hlbmV2ZXIgYW4gb3BlcmF0aW9uIGlzIGV4ZWN1dGVkLCBldmVyeSBmdW5jdGlvbiBpbiB0aGlzIEFycmF5IGlzIGNhbGxlZC5cbiAgICAjIEBwYXJhbSB7WWF0dGF9IHlhdHRhIFRoZSBZYXR0YSBmcmFtZXdvcmsuXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAoQGVuZ2luZSwgQEhCLCBAZXhlY3V0aW9uX2xpc3RlbmVyLCBAeWF0dGEpLT5cbiAgICAgIEBkdWlDbGllbnQgPSBkdWlDbGllbnRcbiAgICAgIEBpd2NIYW5kbGVyID0gaXdjSGFuZGxlclxuXG4gICAgICBzZW5kXyA9IChvKT0+XG4gICAgICAgIEBzZW5kIG9cbiAgICAgIEBleGVjdXRpb25fbGlzdGVuZXIucHVzaCBzZW5kX1xuXG4gICAgICByZWNlaXZlXyA9IChpbnRlbnQpPT5cbiAgICAgICAgbyA9IGludGVudC5leHRyYXNcbiAgICAgICAgQHJlY2VpdmUgb1xuICAgICAgQGl3Y0hhbmRsZXJbXCJZYXR0YV9uZXdfb3BlcmF0aW9uXCJdID0gW3JlY2VpdmVfXVxuXG4gICAgICBpZiByZWNlaXZlZF9IQj9cbiAgICAgICAgQGVuZ2luZS5hcHBseU9wc0NoZWNrRG91YmxlIHJlY2VpdmVkX0hCXG5cbiAgICAgIHNlbmRIaXN0b3J5QnVmZmVyID0gKCk9PlxuICAgICAgICBqc29uID1cbiAgICAgICAgICBIQiA6IEB5YXR0YS5nZXRIaXN0b3J5QnVmZmVyKCkuX2VuY29kZSgpXG4gICAgICAgIEBzZW5kSXdjSW50ZW50IFwiWWF0dGFfcHVzaF9IQl9lbGVtZW50XCIsIGpzb25cbiAgICAgIEBpd2NIYW5kbGVyW1wiWWF0dGFfZ2V0X0hCX2VsZW1lbnRcIl0gPSBbc2VuZEhpc3RvcnlCdWZmZXJdXG5cbiAgICAjXG4gICAgIyBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuZXZlciBhbiBvcGVyYXRpb24gd2FzIGV4ZWN1dGVkLlxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG8gVGhlIG9wZXJhdGlvbiB0aGF0IHdhcyBleGVjdXRlZC5cbiAgICAjXG4gICAgc2VuZDogKG8pLT5cbiAgICAgIGlmIG8udWlkLmNyZWF0b3IgaXMgQEhCLmdldFVzZXJJZCgpIGFuZCAodHlwZW9mIG8udWlkLm9wX251bWJlciBpc250IFwic3RyaW5nXCIpXG4gICAgICAgIEBzZW5kSXdjSW50ZW50IFwiWWF0dGFfbmV3X29wZXJhdGlvblwiLCBvXG5cbiAgICAjXG4gICAgIyBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuZXZlciBhbiBvcGVyYXRpb24gd2FzIHJlY2VpdmVkIGZyb20gYW5vdGhlciBwZWVyLlxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG8gVGhlIG9wZXJhdGlvbiB0aGF0IHdhcyByZWNlaXZlZC5cbiAgICAjXG4gICAgcmVjZWl2ZTogKG8pLT5cbiAgICAgIGlmIG8udWlkLmNyZWF0b3IgaXNudCBASEIuZ2V0VXNlcklkKClcbiAgICAgICAgQGVuZ2luZS5hcHBseU9wIG9cblxuICAgICNcbiAgICAjIEhlbHBlciBmb3Igc2VuZGluZyBpd2MgaW50ZW50cy5cbiAgICAjIEBwYXJhbSB7U3RyaW5nfSBhY3Rpb25fbmFtZSBUaGUgbmFtZSBvZiB0aGUgYWN0aW9uIHRoYXQgaXMgZ29pbmcgdG8gYmUgc2VuZC5cbiAgICAjIEBwYXJhbSB7U3RyaW5nfSBjb250ZW50IFRoZSBjb250ZW50IHRoYXQgaXMgYXR0ZWNoZWQgdG8gdGhlIGludGVudC5cbiAgICAjXG4gICAgc2VuZEl3Y0ludGVudDogKGFjdGlvbl9uYW1lLCBjb250ZW50KS0+XG4gICAgICBpbnRlbnQgPVxuICAgICAgICBhY3Rpb246IGFjdGlvbl9uYW1lXG4gICAgICAgIGNvbXBvbmVudDogXCJcIlxuICAgICAgICBkYXRhOiBcIlwiXG4gICAgICAgIGRhdGFUeXBlOiBcIlwiXG4gICAgICAgIGV4dHJhczogY29udGVudFxuXG4gICAgICBAZHVpQ2xpZW50LnNlbmRJbnRlbnQoaW50ZW50KVxuXG4gIGdldF9IQl9pbnRlbnQgPVxuICAgIGFjdGlvbjogXCJZYXR0YV9nZXRfSEJfZWxlbWVudFwiXG4gICAgY29tcG9uZW50OiBcIlwiXG4gICAgZGF0YTogXCJcIlxuICAgIGRhdGFUeXBlOiBcIlwiXG4gICAgZXh0cmFzOiB7fVxuXG4gIGluaXQgPSAoKS0+XG4gICAgZHVpQ2xpZW50LnNlbmRJbnRlbnQoZ2V0X0hCX2ludGVudClcblxuICAgIGlzX2luaXRpYWxpemVkID0gZmFsc2VcbiAgICByZWNlaXZlSEIgPSAoanNvbiktPlxuICAgICAgcHJvcG9zZWRfdXNlcl9pZCA9IGR1aUNsaWVudC5nZXRJd2NDbGllbnQoKS5fY29tcG9uZW50TmFtZVxuICAgICAgcmVjZWl2ZWRfSEIgPSBqc29uPy5leHRyYXMuSEJcbiAgICAgIGlmIG5vdCBpc19pbml0aWFsaXplZFxuICAgICAgICBpc19pbml0aWFsaXplZCA9IHRydWVcbiAgICAgICAgY2FsbGJhY2sgSXdjQ29ubmVjdG9yLCBwcm9wb3NlZF91c2VyX2lkXG4gICAgaXdjSGFuZGxlcltcIllhdHRhX3B1c2hfSEJfZWxlbWVudFwiXSA9IFtyZWNlaXZlSEJdXG4gICAgc2V0VGltZW91dCByZWNlaXZlSEIsIDBcblxuICBzZXRUaW1lb3V0IGluaXQsIChNYXRoLnJhbmRvbSgpKjApXG5cbiAgdW5kZWZpbmVkXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUl3Y0Nvbm5lY3Rvclxud2luZG93Py5jcmVhdGVDb25uZWN0b3IgPSBjcmVhdGVJd2NDb25uZWN0b3JcblxuIiwiXG5fID0gcmVxdWlyZSBcInVuZGVyc2NvcmVcIlxuXG5tb2R1bGUuZXhwb3J0cyA9ICh1c2VyX2xpc3QpLT5cblxuICAjXG4gICMgQSB0cml2aWFsIENvbm5lY3RvciB0aGF0IHNpbXVsYXRlcyBuZXR3b3JrIGRlbGF5LlxuICAjXG4gIGNsYXNzIFRlc3RDb25uZWN0b3JcblxuICAgICNcbiAgICAjIEBwYXJhbSB7RW5naW5lfSBlbmdpbmUgVGhlIHRyYW5zZm9ybWF0aW9uIGVuZ2luZVxuICAgICMgQHBhcmFtIHtIaXN0b3J5QnVmZmVyfSBIQlxuICAgICMgQHBhcmFtIHtBcnJheTxGdW5jdGlvbj59IGV4ZWN1dGlvbl9saXN0ZW5lciBZb3UgbXVzdCBlbnN1cmUgdGhhdCB3aGVuZXZlciBhbiBvcGVyYXRpb24gaXMgZXhlY3V0ZWQsIGV2ZXJ5IGZ1bmN0aW9uIGluIHRoaXMgQXJyYXkgaXMgY2FsbGVkLlxuICAgICMgQHBhcmFtIHtZYXR0YX0geWF0dGEgVGhlIFlhdHRhIGZyYW1ld29yay5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6IChAZW5naW5lLCBASEIsIEBleGVjdXRpb25fbGlzdGVuZXIpLT5cbiAgICAgIHNlbmRfID0gKG8pPT5cbiAgICAgICAgQHNlbmQgb1xuICAgICAgQGV4ZWN1dGlvbl9saXN0ZW5lci5wdXNoIHNlbmRfXG5cbiAgICAgIEBhcHBsaWVkX29wZXJhdGlvbnMgPSBbXVxuICAgICAgYXBwbGllZE9wZXJhdGlvbnNMaXN0ZW5lciA9IChvKT0+XG4gICAgICAgIEBhcHBsaWVkX29wZXJhdGlvbnMucHVzaCBvXG4gICAgICBAZXhlY3V0aW9uX2xpc3RlbmVyLnB1c2ggYXBwbGllZE9wZXJhdGlvbnNMaXN0ZW5lclxuICAgICAgaWYgbm90ICh1c2VyX2xpc3Q/Lmxlbmd0aCBpcyAwKVxuICAgICAgICBAZW5naW5lLmFwcGx5T3BzIHVzZXJfbGlzdFswXS5nZXRIaXN0b3J5QnVmZmVyKCkuX2VuY29kZSgpXG5cbiAgICAgIEB1bmV4ZWN1dGVkID0ge31cblxuICAgICNcbiAgICAjIFRoaXMgZW5naW5lIGFwcGxpZWQgb3BlcmF0aW9ucyBpbiBhIHNwZWNpZmljIG9yZGVyLlxuICAgICMgR2V0IHRoZSBvcHMgaW4gdGhlIHJpZ2h0IG9yZGVyLlxuICAgICNcbiAgICBnZXRPcHNJbkV4ZWN1dGlvbk9yZGVyOiAoKS0+XG4gICAgICBAYXBwbGllZF9vcGVyYXRpb25zXG5cbiAgICAjXG4gICAgIyBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuZXZlciBhbiBvcGVyYXRpb24gd2FzIGV4ZWN1dGVkLlxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG8gVGhlIG9wZXJhdGlvbiB0aGF0IHdhcyBleGVjdXRlZC5cbiAgICAjXG4gICAgc2VuZDogKG8pLT5cbiAgICAgIGlmIChvLnVpZC5jcmVhdG9yIGlzIEBIQi5nZXRVc2VySWQoKSkgYW5kICh0eXBlb2Ygby51aWQub3BfbnVtYmVyIGlzbnQgXCJzdHJpbmdcIilcbiAgICAgICAgZm9yIHVzZXIgaW4gdXNlcl9saXN0XG4gICAgICAgICAgaWYgdXNlci5nZXRVc2VySWQoKSBpc250IEBIQi5nZXRVc2VySWQoKVxuICAgICAgICAgICAgdXNlci5nZXRDb25uZWN0b3IoKS5yZWNlaXZlKG8pXG5cbiAgICAjXG4gICAgIyBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aGVuZXZlciBhbiBvcGVyYXRpb24gd2FzIHJlY2VpdmVkIGZyb20gYW5vdGhlciBwZWVyLlxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG8gVGhlIG9wZXJhdGlvbiB0aGF0IHdhcyByZWNlaXZlZC5cbiAgICAjXG4gICAgcmVjZWl2ZTogKG8pLT5cbiAgICAgIEB1bmV4ZWN1dGVkW28udWlkLmNyZWF0b3JdID89IFtdXG4gICAgICBAdW5leGVjdXRlZFtvLnVpZC5jcmVhdG9yXS5wdXNoIG9cblxuICAgICNcbiAgICAjIEZsdXNoIG9uZSBvcGVyYXRpb24gZnJvbSB0aGUgbGluZSBvZiBhIHNwZWNpZmljIHVzZXIuXG4gICAgI1xuICAgIGZsdXNoT25lOiAodXNlciktPlxuICAgICAgaWYgQHVuZXhlY3V0ZWRbdXNlcl0/Lmxlbmd0aCA+IDBcbiAgICAgICAgQGVuZ2luZS5hcHBseU9wIEB1bmV4ZWN1dGVkW3VzZXJdLnNoaWZ0KClcblxuICAgICNcbiAgICAjIEZsdXNoIG9uZSBvcGVyYXRpb24gb24gYSByYW5kb20gbGluZS5cbiAgICAjXG4gICAgZmx1c2hPbmVSYW5kb206ICgpLT5cbiAgICAgIEBmbHVzaE9uZSAoXy5yYW5kb20gMCwgKHVzZXJfbGlzdC5sZW5ndGgtMSkpXG5cbiAgICAjXG4gICAgIyBGbHVzaCBhbGwgb3BlcmF0aW9ucyBvbiBldmVyeSBsaW5lLlxuICAgICNcbiAgICBmbHVzaEFsbDogKCktPlxuICAgICAgZm9yIG4sb3BzIG9mIEB1bmV4ZWN1dGVkXG4gICAgICAgIEBlbmdpbmUuYXBwbHlPcHMgb3BzXG4gICAgICBAdW5leGVjdXRlZCA9IHt9XG5cbiIsIlxyXG4jXHJcbiMgVGhlIEVuZ2luZSBoYW5kbGVzIGhvdyBhbmQgaW4gd2hpY2ggb3JkZXIgdG8gZXhlY3V0ZSBvcGVyYXRpb25zIGFuZCBhZGQgb3BlcmF0aW9ucyB0byB0aGUgSGlzdG9yeUJ1ZmZlci5cclxuI1xyXG5jbGFzcyBFbmdpbmVcclxuXHJcbiAgI1xyXG4gICMgQHBhcmFtIHtIaXN0b3J5QnVmZmVyfSBIQlxyXG4gICMgQHBhcmFtIHtBcnJheX0gcGFyc2VyIERlZmluZXMgaG93IHRvIHBhcnNlIGVuY29kZWQgbWVzc2FnZXMuXHJcbiAgI1xyXG4gIGNvbnN0cnVjdG9yOiAoQEhCLCBAcGFyc2VyKS0+XHJcbiAgICBAdW5wcm9jZXNzZWRfb3BzID0gW11cclxuXHJcbiAgI1xyXG4gICMgUGFyc2VzIGFuIG9wZXJhdGlvIGZyb20gdGhlIGpzb24gZm9ybWF0LiBJdCB1c2VzIHRoZSBzcGVjaWZpZWQgcGFyc2VyIGluIHlvdXIgT3BlcmF0aW9uVHlwZSBtb2R1bGUuXHJcbiAgI1xyXG4gIHBhcnNlT3BlcmF0aW9uOiAoanNvbiktPlxyXG4gICAgdHlwZVBhcnNlciA9IEBwYXJzZXJbanNvbi50eXBlXVxyXG4gICAgaWYgdHlwZVBhcnNlcj9cclxuICAgICAgdHlwZVBhcnNlciBqc29uXHJcbiAgICBlbHNlXHJcbiAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBmb3Jnb3QgdG8gc3BlY2lmeSBhIHBhcnNlciBmb3IgdHlwZSAje2pzb24udHlwZX0uIFRoZSBtZXNzYWdlIGlzICN7SlNPTi5zdHJpbmdpZnkganNvbn0uXCJcclxuXHJcbiAgI1xyXG4gICMgQXBwbHkgYSBzZXQgb2Ygb3BlcmF0aW9ucy4gRS5nLiB0aGUgb3BlcmF0aW9ucyB5b3UgcmVjZWl2ZWQgZnJvbSBhbm90aGVyIHVzZXJzIEhCLnRvSnNvbigpLlxyXG4gICMgQG5vdGUgWW91IG11c3Qgbm90IHVzZSB0aGlzIG1ldGhvZCB3aGVuIHlvdSBhbHJlYWR5IGhhdmUgb3BzIGluIHlvdXIgSEIhXHJcbiAgI1xyXG4gIGFwcGx5T3BzQnVuZGxlOiAob3BzX2pzb24pLT5cclxuICAgIG9wcyA9IFtdXHJcbiAgICBmb3IgbyBpbiBvcHNfanNvblxyXG4gICAgICBvcHMucHVzaCBAcGFyc2VPcGVyYXRpb24gb1xyXG4gICAgZm9yIG8gaW4gb3BzXHJcbiAgICAgIEBIQi5hZGRPcGVyYXRpb24gb1xyXG4gICAgZm9yIG8gaW4gb3BzXHJcbiAgICAgIGlmIG5vdCBvLmV4ZWN1dGUoKVxyXG4gICAgICAgIEB1bnByb2Nlc3NlZF9vcHMucHVzaCBvXHJcbiAgICBAdHJ5VW5wcm9jZXNzZWQoKVxyXG5cclxuICAjXHJcbiAgIyBTYW1lIGFzIGFwcGx5T3BzIGJ1dCBvcGVyYXRpb25zIHRoYXQgYXJlIGFscmVhZHkgaW4gdGhlIEhCIGFyZSBub3QgYXBwbGllZC5cclxuICAjIEBzZWUgRW5naW5lLmFwcGx5T3BzXHJcbiAgI1xyXG4gIGFwcGx5T3BzQ2hlY2tEb3VibGU6IChvcHNfanNvbiktPlxyXG4gICAgZm9yIG8gaW4gb3BzX2pzb25cclxuICAgICAgaWYgQEhCLmdldE9wZXJhdGlvbihvLnVpZCk/XHJcbiAgICAgICAgQGFwcGx5T3Agb1xyXG5cclxuICAjXHJcbiAgIyBBcHBseSBhIHNldCBvZiBvcGVyYXRpb25zLiAoSGVscGVyIGZvciB1c2luZyBhcHBseU9wIG9uIEFycmF5cylcclxuICAjIEBzZWUgRW5naW5lLmFwcGx5T3BcclxuICBhcHBseU9wczogKG9wc19qc29uKS0+XHJcbiAgICBmb3IgbyBpbiBvcHNfanNvblxyXG4gICAgICBAYXBwbHlPcCBvXHJcblxyXG4gICNcclxuICAjIEFwcGx5IGFuIG9wZXJhdGlvbiB0aGF0IHlvdSByZWNlaXZlZCBmcm9tIGFub3RoZXIgcGVlci5cclxuICAjXHJcbiAgYXBwbHlPcDogKG9wX2pzb24pLT5cclxuICAgICMgJHBhcnNlX2FuZF9leGVjdXRlIHdpbGwgcmV0dXJuIGZhbHNlIGlmICRvX2pzb24gd2FzIHBhcnNlZCBhbmQgZXhlY3V0ZWQsIG90aGVyd2lzZSB0aGUgcGFyc2VkIG9wZXJhZGlvblxyXG4gICAgbyA9IEBwYXJzZU9wZXJhdGlvbiBvcF9qc29uXHJcbiAgICBASEIuYWRkVG9Db3VudGVyIG9cclxuICAgICMgQEhCLmFkZE9wZXJhdGlvbiBvXHJcbiAgICBpZiBub3Qgby5leGVjdXRlKClcclxuICAgICAgQHVucHJvY2Vzc2VkX29wcy5wdXNoIG9cclxuICAgIGVsc2VcclxuICAgICAgQEhCLmFkZE9wZXJhdGlvbiBvXHJcbiAgICBAdHJ5VW5wcm9jZXNzZWQoKVxyXG5cclxuICAjXHJcbiAgIyBDYWxsIHRoaXMgbWV0aG9kIHdoZW4geW91IGFwcGxpZWQgYSBuZXcgb3BlcmF0aW9uLlxyXG4gICMgSXQgY2hlY2tzIGlmIG9wZXJhdGlvbnMgdGhhdCB3ZXJlIHByZXZpb3VzbHkgbm90IGV4ZWN1dGFibGUgYXJlIG5vdyBleGVjdXRhYmxlLlxyXG4gICNcclxuICB0cnlVbnByb2Nlc3NlZDogKCktPlxyXG4gICAgd2hpbGUgdHJ1ZVxyXG4gICAgICBvbGRfbGVuZ3RoID0gQHVucHJvY2Vzc2VkX29wcy5sZW5ndGhcclxuICAgICAgdW5wcm9jZXNzZWQgPSBbXVxyXG4gICAgICBmb3Igb3AgaW4gQHVucHJvY2Vzc2VkX29wc1xyXG4gICAgICAgIGlmIG5vdCBvcC5leGVjdXRlKClcclxuICAgICAgICAgIHVucHJvY2Vzc2VkLnB1c2ggb3BcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICBASEIuYWRkT3BlcmF0aW9uIG9wXHJcbiAgICAgIEB1bnByb2Nlc3NlZF9vcHMgPSB1bnByb2Nlc3NlZFxyXG4gICAgICBpZiBAdW5wcm9jZXNzZWRfb3BzLmxlbmd0aCBpcyBvbGRfbGVuZ3RoXHJcbiAgICAgICAgYnJlYWtcclxuXHJcblxyXG5cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gRW5naW5lXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcblxyXG5cclxuXHJcbiIsIlxuanNvbl90eXBlc191bmluaXRpYWxpemVkID0gcmVxdWlyZSBcIi4uL1R5cGVzL0pzb25UeXBlc1wiXG5IaXN0b3J5QnVmZmVyID0gcmVxdWlyZSBcIi4uL0hpc3RvcnlCdWZmZXJcIlxuRW5naW5lID0gcmVxdWlyZSBcIi4uL0VuZ2luZVwiXG5cbiNcbiMgRnJhbWV3b3JrIGZvciBKc29uIGRhdGEtc3RydWN0dXJlcy5cbiMgS25vd24gdmFsdWVzIHRoYXQgYXJlIHN1cHBvcnRlZDpcbiMgKiBTdHJpbmdcbiMgKiBJbnRlZ2VyXG4jICogQXJyYXlcbiNcbmNsYXNzIEpzb25ZYXR0YVxuXG4gICNcbiAgIyBAcGFyYW0ge1N0cmluZ30gdXNlcl9pZCBVbmlxdWUgaWQgb2YgdGhlIHBlZXIuXG4gICMgQHBhcmFtIHtDb25uZWN0b3J9IENvbm5lY3RvciB0aGUgY29ubmVjdG9yIGNsYXNzLlxuICAjXG4gIGNvbnN0cnVjdG9yOiAodXNlcl9pZCwgQ29ubmVjdG9yKS0+XG4gICAgQEhCID0gbmV3IEhpc3RvcnlCdWZmZXIgdXNlcl9pZFxuICAgIGpzb25fdHlwZXMgPSBqc29uX3R5cGVzX3VuaW5pdGlhbGl6ZWQgQEhCXG4gICAgQGVuZ2luZSA9IG5ldyBFbmdpbmUgQEhCLCBqc29uX3R5cGVzLnBhcnNlclxuICAgIEBjb25uZWN0b3IgPSBuZXcgQ29ubmVjdG9yIEBlbmdpbmUsIEBIQiwganNvbl90eXBlcy5leGVjdXRpb25fbGlzdGVuZXIsIEBcblxuICAgIGZpcnN0X3dvcmQgPSBuZXcganNvbl90eXBlcy50eXBlcy5Kc29uVHlwZSBASEIuZ2V0UmVzZXJ2ZWRVbmlxdWVJZGVudGlmaWVyKClcbiAgICBASEIuYWRkT3BlcmF0aW9uKGZpcnN0X3dvcmQpLmV4ZWN1dGUoKVxuICAgIEByb290X2VsZW1lbnQgPSBmaXJzdF93b3JkXG5cbiAgI1xuICAjIEByZXN1bHQgSnNvblR5cGVcbiAgI1xuICBnZXRSb290RWxlbWVudDogKCktPlxuICAgIEByb290X2VsZW1lbnRcblxuICAjXG4gICMgQHNlZSBFbmdpbmVcbiAgI1xuICBnZXRFbmdpbmU6ICgpLT5cbiAgICBAZW5naW5lXG5cbiAgI1xuICAjIEdldCB0aGUgaW5pdGlhbGl6ZWQgY29ubmVjdG9yLlxuICAjXG4gIGdldENvbm5lY3RvcjogKCktPlxuICAgIEBjb25uZWN0b3JcblxuICAjXG4gICMgQHNlZSBIaXN0b3J5QnVmZmVyXG4gICNcbiAgZ2V0SGlzdG9yeUJ1ZmZlcjogKCktPlxuICAgIEBIQlxuXG4gICNcbiAgIyBAc2VlIEpzb25UeXBlLnNldE11dGFibGVEZWZhdWx0XG4gICNcbiAgc2V0TXV0YWJsZURlZmF1bHQ6IChtdXRhYmxlKS0+XG4gICAgQHJvb3RfZWxlbWVudC5zZXRNdXRhYmxlRGVmYXVsdChtdXRhYmxlKVxuXG4gICNcbiAgIyBHZXQgdGhlIFVzZXJJZCBmcm9tIHRoZSBIaXN0b3J5QnVmZmVyIG9iamVjdC5cbiAgIyBJbiBtb3N0IGNhc2VzIHRoaXMgd2lsbCBiZSB0aGUgc2FtZSBhcyB0aGUgdXNlcl9pZCB2YWx1ZSB3aXRoIHdoaWNoXG4gICMgSnNvbllhdHRhIHdhcyBpbml0aWFsaXplZCAoRGVwZW5kaW5nIG9uIHRoZSBIaXN0b3J5QnVmZmVyIGltcGxlbWVudGF0aW9uKS5cbiAgI1xuICBnZXRVc2VySWQ6ICgpLT5cbiAgICBASEIuZ2V0VXNlcklkKClcblxuICAjXG4gICMgQHNlZSBKc29uVHlwZS52YWxcbiAgI1xuICB2YWwgOiAobmFtZSwgY29udGVudCwgbXV0YWJsZSktPlxuICAgIEByb290X2VsZW1lbnQudmFsKG5hbWUsIGNvbnRlbnQsIG11dGFibGUpXG5cbiAgI1xuICAjIEBzZWUgSnNvblR5cGUudmFsdWVcbiAgI1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkgSnNvbllhdHRhLnByb3RvdHlwZSwgJ3ZhbHVlJyxcbiAgICBnZXQgOiAtPiBAcm9vdF9lbGVtZW50LnZhbHVlXG4gICAgc2V0IDogKG8pLT5cbiAgICAgIGlmIG8uY29uc3RydWN0b3IgaXMge30uY29uc3RydWN0b3JcbiAgICAgICAgZm9yIG9fbmFtZSxvX29iaiBvZiBvXG4gICAgICAgICAgQHZhbChvX25hbWUsIG9fb2JqLCAnaW1tdXRhYmxlJylcbiAgICAgIGVsc2VcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3Qgb25seSBzZXQgT2JqZWN0IHZhbHVlcyFcIlxud2luZG93Py5Kc29uWWF0dGEgPSBKc29uWWF0dGFcbm1vZHVsZS5leHBvcnRzID0gSnNvbllhdHRhXG4iLCJcbnRleHRfdHlwZXNfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuLi9UeXBlcy9UZXh0VHlwZXNcIlxuSGlzdG9yeUJ1ZmZlciA9IHJlcXVpcmUgXCIuLi9IaXN0b3J5QnVmZmVyXCJcbkVuZ2luZSA9IHJlcXVpcmUgXCIuLi9FbmdpbmVcIlxuXG4jXG4jIEZyYW1ld29yayBmb3IgVGV4dCBEYXRhc3RydWN0dXJlcy5cbiNcbmNsYXNzIFRleHRZYXR0YVxuXG4gICNcbiAgIyBAcGFyYW0ge1N0cmluZ30gdXNlcl9pZCBVbmlxZSB1c2VyIGlkIHRoYXQgZGVmaW5lcyB0aGlzIHBlZXIuXG4gICMgQHBhcmFtIHtDb25uZWN0b3J9IENvbm5lY3RvciBUaGUgY29ubmVjdG9yIGRlZmluZXMgaG93IHlvdSBjb25uZWN0IHRvIHRoZSBvdGhlciBwZWVycy5cbiAgI1xuICBjb25zdHJ1Y3RvcjogKHVzZXJfaWQsIENvbm5lY3RvciktPlxuICAgIEBIQiA9IG5ldyBIaXN0b3J5QnVmZmVyIHVzZXJfaWRcbiAgICB0ZXh0X3R5cGVzID0gdGV4dF90eXBlc191bmluaXRpYWxpemVkIEBIQlxuICAgIEBlbmdpbmUgPSBuZXcgRW5naW5lIEBIQiwgdGV4dF90eXBlcy5wYXJzZXJcbiAgICBAY29ubmVjdG9yID0gbmV3IENvbm5lY3RvciBAZW5naW5lLCBASEIsIHRleHRfdHlwZXMuZXhlY3V0aW9uX2xpc3RlbmVyXG5cbiAgICBmaXJzdF93b3JkID0gbmV3IHRleHRfdHlwZXMudHlwZXMuV29yZCB1bmRlZmluZWRcbiAgICBASEIuYWRkT3BlcmF0aW9uKGZpcnN0X3dvcmQpLmV4ZWN1dGUoKVxuICAgIEByb290X2VsZW1lbnQgPSBmaXJzdF93b3JkXG5cbiAgI1xuICAjIEByZXN1bHQgV29yZFxuICAjXG4gIGdldFJvb3RFbGVtZW50OiAoKS0+XG4gICAgQHJvb3RfZWxlbWVudFxuXG4gICNcbiAgIyBAc2VlIEVuZ2luZVxuICAjXG4gIGdldEVuZ2luZTogKCktPlxuICAgIEBlbmdpbmVcblxuICAjXG4gICMgR2V0IHRoZSBpbml0aWFsaXplZCBjb25uZWN0b3IuXG4gICNcbiAgZ2V0Q29ubmVjdG9yOiAoKS0+XG4gICAgQGNvbm5lY3RvclxuXG4gICNcbiAgIyBAc2VlIEhpc3RvcnlCdWZmZXJcbiAgI1xuICBnZXRIaXN0b3J5QnVmZmVyOiAoKS0+XG4gICAgQEhCXG5cbiAgI1xuICAjIEdldCB0aGUgVXNlcklkIGZyb20gdGhlIEhpc3RvcnlCdWZmZXIgb2JqZWN0LlxuICAjIEluIG1vc3QgY2FzZXMgdGhpcyB3aWxsIGJlIHRoZSBzYW1lIGFzIHRoZSB1c2VyX2lkIHZhbHVlIHdpdGggd2hpY2hcbiAgIyBKc29uWWF0dGEgd2FzIGluaXRpYWxpemVkIChEZXBlbmRpbmcgb24gdGhlIEhpc3RvcnlCdWZmZXIgaW1wbGVtZW50YXRpb24pLlxuICAjXG4gIGdldFVzZXJJZDogKCktPlxuICAgIEBIQi5nZXRVc2VySWQoKVxuXG4gICNcbiAgIyBAc2VlIEpzb25UeXBlLnZhbFxuICAjXG4gIHZhbDogKCktPlxuICAgIEByb290X2VsZW1lbnQudmFsKClcblxuICAjXG4gICMgQHNlZSBXb3JkLmluc2VydFRleHRcbiAgI1xuICBpbnNlcnRUZXh0OiAocG9zLCBjb250ZW50KS0+XG4gICAgQHJvb3RfZWxlbWVudC5pbnNlcnRUZXh0IHBvcywgY29udGVudFxuXG4gICNcbiAgIyBAc2VlIFdvcmQuZGVsZXRlVGV4dFxuICAjXG4gIGRlbGV0ZVRleHQ6IChwb3MsIGxlbmd0aCktPlxuICAgIEByb290X2VsZW1lbnQuZGVsZXRlVGV4dCBwb3MsIGxlbmd0aFxuXG4gICNcbiAgIyBAc2VlIFdvcmQucmVwbGFjZVRleHRcbiAgI1xuICByZXBsYWNlVGV4dDogKHRleHQpLT5cbiAgICBAcm9vdF9lbGVtZW50LnJlcGxhY2VUZXh0IHRleHRcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFRleHRZYXR0YVxuIiwiXG4jXG4jIEFuIG9iamVjdCB0aGF0IGhvbGRzIGFsbCBhcHBsaWVkIG9wZXJhdGlvbnMuXG4jXG4jIEBub3RlIFRoZSBIaXN0b3J5QnVmZmVyIGlzIGNvbW1vbmx5IGFiYnJldmlhdGVkIHRvIEhCLlxuI1xuY2xhc3MgSGlzdG9yeUJ1ZmZlclxuXG4gICNcbiAgIyBDcmVhdGVzIGFuIGVtcHR5IEhCLlxuICAjIEBwYXJhbSB7T2JqZWN0fSB1c2VyX2lkIENyZWF0b3Igb2YgdGhlIEhCLlxuICAjXG4gIGNvbnN0cnVjdG9yOiAoQHVzZXJfaWQpLT5cbiAgICBAb3BlcmF0aW9uX2NvdW50ZXIgPSB7fVxuICAgIEBidWZmZXIgPSB7fVxuICAgIEBjaGFuZ2VfbGlzdGVuZXJzID0gW11cblxuICAjXG4gICMgR2V0IHRoZSB1c2VyIGlkIHdpdGggd2ljaCB0aGUgSGlzdG9yeSBCdWZmZXIgd2FzIGluaXRpYWxpemVkLlxuICAjXG4gIGdldFVzZXJJZDogKCktPlxuICAgIEB1c2VyX2lkXG5cbiAgI1xuICAjIFRoZXJlIGlzIG9ubHkgb25lIHJlc2VydmVkIHVuaXF1ZSBpZGVudGlmaWVyICh1aWQpLCBzbyB1c2UgaXQgd2lzZWx5LlxuICAjIEkgcHJvcG9zZSB0byB1c2UgaXQgaW4geW91ciBGcmFtZXdvcmssIHRvIGNyZWF0ZSBzb21ldGhpbmcgbGlrZSBhIHJvb3QgZWxlbWVudC5cbiAgIyBBbiBvcGVyYXRpb24gd2l0aCB0aGlzIGlkZW50aWZpZXIgaXMgbm90IHByb3BhZ2F0ZWQgdG8gb3RoZXIgY2xpZW50cy5cbiAgIyBUaGlzIGlzIHdoeSBldmVyeWJvZGUgbXVzdCBjcmVhdGUgdGhlIHNhbWUgb3BlcmF0aW9uIHdpdGggdGhpcyB1aWQuXG4gICNcbiAgZ2V0UmVzZXJ2ZWRVbmlxdWVJZGVudGlmaWVyOiAoKS0+XG4gICAge1xuICAgICAgY3JlYXRvciA6ICdfJ1xuICAgICAgb3BfbnVtYmVyIDogJ18nXG4gICAgfVxuXG4gICNcbiAgIyBHZXQgdGhlIG9wZXJhdGlvbiBjb3VudGVyIHRoYXQgZGVzY3JpYmVzIHRoZSBjdXJyZW50IHN0YXRlIG9mIHRoZSBkb2N1bWVudC5cbiAgI1xuICBnZXRPcGVyYXRpb25Db3VudGVyOiAoKS0+XG4gICAgcmVzID0ge31cbiAgICBmb3IgdXNlcixjdG4gb2YgQG9wZXJhdGlvbl9jb3VudGVyXG4gICAgICByZXNbdXNlcl0gPSBjdG5cbiAgICByZXNcblxuICAjXG4gICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgI1xuICBfZW5jb2RlOiAoc3RhdGVfdmVjdG9yPXt9KS0+XG4gICAganNvbiA9IFtdXG4gICAgdW5rbm93biA9ICh1c2VyLCBvX251bWJlciktPlxuICAgICAgaWYgKG5vdCB1c2VyPykgb3IgKG5vdCBvX251bWJlcj8pXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcImRhaCFcIlxuICAgICAgbm90IHN0YXRlX3ZlY3Rvclt1c2VyXT8gb3Igc3RhdGVfdmVjdG9yW3VzZXJdIDw9IG9fbnVtYmVyXG5cbiAgICBmb3IgdV9uYW1lLHVzZXIgb2YgQGJ1ZmZlclxuICAgICAgZm9yIG9fbnVtYmVyLG8gb2YgdXNlclxuICAgICAgICBpZiBub3QgaXNOYU4ocGFyc2VJbnQob19udW1iZXIpKSBhbmQgdW5rbm93bih1X25hbWUsIG9fbnVtYmVyKVxuICAgICAgICAgIG9fanNvbiA9IG8uX2VuY29kZSgpXG4gICAgICAgICAgaWYgby5uZXh0X2NsP1xuICAgICAgICAgICAgb19uZXh0ID0gby5uZXh0X2NsXG4gICAgICAgICAgICB3aGlsZSBvX25leHQubmV4dF9jbD8gYW5kIHVua25vd24ob19uZXh0LmNyZWF0b3IsIG9fbmV4dC5vcF9udW1iZXIpXG4gICAgICAgICAgICAgIG9fbmV4dCA9IG9fbmV4dC5uZXh0X2NsXG4gICAgICAgICAgICBvX2pzb24ubmV4dCA9IG9fbmV4dC5nZXRVaWQoKVxuICAgICAgICAgIGVsc2UgaWYgby5wcmV2X2NsP1xuICAgICAgICAgICAgb19wcmV2ID0gby5wcmV2X2NsXG4gICAgICAgICAgICB3aGlsZSBvX3ByZXYucHJldl9jbD8gYW5kIHVua25vd24ob19uZXh0LmNyZWF0b3IsIG9fbmV4dC5vcF9udW1iZXIpXG4gICAgICAgICAgICAgIG9fcHJldiA9IG9fcHJldi5wcmV2X2NsXG4gICAgICAgICAgICBvX2pzb24ucHJldiA9IG9fcHJldi5nZXRVaWQoKVxuICAgICAgICAgIGpzb24ucHVzaCBvX2pzb25cblxuICAgIGpzb25cblxuICAjXG4gICMgR2V0IHRoZSBudW1iZXIgb2Ygb3BlcmF0aW9ucyB0aGF0IHdlcmUgY3JlYXRlZCBieSBhIHVzZXIuXG4gICMgQWNjb3JkaW5nbHkgeW91IHdpbGwgZ2V0IHRoZSBuZXh0IG9wZXJhdGlvbiBudW1iZXIgdGhhdCBpcyBleHBlY3RlZCBmcm9tIHRoYXQgdXNlci5cbiAgIyBUaGlzIHdpbGwgaW5jcmVtZW50IHRoZSBvcGVyYXRpb24gY291bnRlci5cbiAgI1xuICBnZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllcjogKHVzZXJfaWQpLT5cbiAgICBpZiBub3QgdXNlcl9pZD9cbiAgICAgIHVzZXJfaWQgPSBAdXNlcl9pZFxuICAgIGlmIG5vdCBAb3BlcmF0aW9uX2NvdW50ZXJbdXNlcl9pZF0/XG4gICAgICBAb3BlcmF0aW9uX2NvdW50ZXJbdXNlcl9pZF0gPSAwXG4gICAgdWlkID1cbiAgICAgICdjcmVhdG9yJyA6IHVzZXJfaWRcbiAgICAgICdvcF9udW1iZXInIDogQG9wZXJhdGlvbl9jb3VudGVyW3VzZXJfaWRdXG4gICAgQG9wZXJhdGlvbl9jb3VudGVyW3VzZXJfaWRdKytcbiAgICB1aWRcblxuICAjXG4gICMgUmV0cmlldmUgYW4gb3BlcmF0aW9uIGZyb20gYSB1bmlxdWUgaWQuXG4gICNcbiAgZ2V0T3BlcmF0aW9uOiAodWlkKS0+XG4gICAgaWYgdWlkIGluc3RhbmNlb2YgT2JqZWN0XG4gICAgICBAYnVmZmVyW3VpZC5jcmVhdG9yXT9bdWlkLm9wX251bWJlcl1cbiAgICBlbHNlIGlmIG5vdCB1aWQ/XG4gICAgZWxzZVxuICAgICAgdGhyb3cgbmV3IEVycm9yIFwiVGhpcyB0eXBlIG9mIHVpZCBpcyBub3QgZGVmaW5lZCFcIlxuICAjXG4gICMgQWRkIGFuIG9wZXJhdGlvbiB0byB0aGUgSEIuIE5vdGUgdGhhdCB0aGlzIHdpbGwgbm90IGxpbmsgaXQgYWdhaW5zdFxuICAjIG90aGVyIG9wZXJhdGlvbnMgKGl0IHdvbnQgZXhlY3V0ZWQpXG4gICNcbiAgYWRkT3BlcmF0aW9uOiAobyktPlxuICAgIGlmIG5vdCBAYnVmZmVyW28uY3JlYXRvcl0/XG4gICAgICBAYnVmZmVyW28uY3JlYXRvcl0gPSB7fVxuICAgIGlmIEBidWZmZXJbby5jcmVhdG9yXVtvLm9wX251bWJlcl0/XG4gICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBub3Qgb3ZlcndyaXRlIG9wZXJhdGlvbnMhXCJcbiAgICBAYnVmZmVyW28uY3JlYXRvcl1bby5vcF9udW1iZXJdID0gb1xuICAgIG9cblxuICAjXG4gICMgSW5jcmVtZW50IHRoZSBvcGVyYXRpb25fY291bnRlciB0aGF0IGRlZmluZXMgdGhlIGN1cnJlbnQgc3RhdGUgb2YgdGhlIEVuZ2luZS5cbiAgI1xuICBhZGRUb0NvdW50ZXI6IChvKS0+XG4gICAgaWYgbm90IEBvcGVyYXRpb25fY291bnRlcltvLmNyZWF0b3JdP1xuICAgICAgQG9wZXJhdGlvbl9jb3VudGVyW28uY3JlYXRvcl0gPSAwXG4gICAgaWYgdHlwZW9mIG8ub3BfbnVtYmVyIGlzICdudW1iZXInIGFuZCBvLmNyZWF0b3IgaXNudCBAZ2V0VXNlcklkKClcbiAgICAgIEBvcGVyYXRpb25fY291bnRlcltvLmNyZWF0b3JdKytcbiAgICAjaWYgQG9wZXJhdGlvbl9jb3VudGVyW28uY3JlYXRvcl0gaXNudCAoby5vcF9udW1iZXIgKyAxKVxuICAgICAgI2NvbnNvbGUubG9nIChAb3BlcmF0aW9uX2NvdW50ZXJbby5jcmVhdG9yXSAtIChvLm9wX251bWJlciArIDEpKVxuICAgICAgI2NvbnNvbGUubG9nIG9cbiAgICAgICN0aHJvdyBuZXcgRXJyb3IgXCJZb3UgZG9uJ3QgcmVjZWl2ZSBvcGVyYXRpb25zIGluIHRoZSBwcm9wZXIgb3JkZXIuIFRyeSBjb3VudGluZyBsaWtlIHRoaXMgMCwxLDIsMyw0LC4uIDspXCJcblxubW9kdWxlLmV4cG9ydHMgPSBIaXN0b3J5QnVmZmVyXG4iLCJtb2R1bGUuZXhwb3J0cyA9IChIQiktPlxuICAjIEBzZWUgRW5naW5lLnBhcnNlXG4gIHBhcnNlciA9IHt9XG4gIGV4ZWN1dGlvbl9saXN0ZW5lciA9IFtdXG5cbiAgI1xuICAjIEEgZ2VuZXJpYyBpbnRlcmZhY2UgdG8gb3BlcmF0aW9ucy5cbiAgI1xuICAjIEFuIG9wZXJhdGlvbiBoYXMgdGhlIGZvbGxvd2luZyBtZXRob2RzOlxuICAjIF9lbmNvZGU6IGVuY29kZXMgYW4gb3BlcmF0aW9uIChuZWVkZWQgb25seSBpZiBpbnN0YW5jZSBvZiB0aGlzIG9wZXJhdGlvbiBpcyBzZW50KS5cbiAgIyBleGVjdXRlOiBleGVjdXRlIHRoZSBlZmZlY3RzIG9mIHRoaXMgb3BlcmF0aW9ucy4gR29vZCBleGFtcGxlcyBhcmUgSW5zZXJ0LXR5cGUgYW5kIEFkZE5hbWUtdHlwZVxuICAjIHZhbDogaW4gdGhlIGNhc2UgdGhhdCB0aGUgb3BlcmF0aW9uIGhvbGRzIGEgdmFsdWVcbiAgI1xuICAjIEZ1cnRoZXJtb3JlIGFuIGVuY29kYWJsZSBvcGVyYXRpb24gaGFzIGEgcGFyc2VyLlxuICAjXG4gIGNsYXNzIE9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHNlZSBIaXN0b3J5QnVmZmVyLmdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkKS0+XG4gICAgICBpZiBub3QgdWlkP1xuICAgICAgICB1aWQgPSBIQi5nZXROZXh0T3BlcmF0aW9uSWRlbnRpZmllcigpXG4gICAgICB7XG4gICAgICAgICdjcmVhdG9yJzogQGNyZWF0b3JcbiAgICAgICAgJ29wX251bWJlcicgOiBAb3BfbnVtYmVyXG4gICAgICB9ID0gdWlkXG5cbiAgICAjXG4gICAgIyBBZGQgYW4gZXZlbnQgbGlzdGVuZXIuIEl0IGRlcGVuZHMgb24gdGhlIG9wZXJhdGlvbiB3aGljaCBldmVudHMgYXJlIHN1cHBvcnRlZC5cbiAgICAjIEBwYXJhbSB7U3RyaW5nfSBldmVudCBOYW1lIG9mIHRoZSBldmVudC5cbiAgICAjIEBwYXJhbSB7RnVuY3Rpb259IGYgZiBpcyBleGVjdXRlZCBpbiBjYXNlIHRoZSBldmVudCBmaXJlcy5cbiAgICAjXG4gICAgb246IChldmVudCwgZiktPlxuICAgICAgQGV2ZW50X2xpc3RlbmVycyA/PSB7fVxuICAgICAgQGV2ZW50X2xpc3RlbmVyc1tldmVudF0gPz0gW11cbiAgICAgIEBldmVudF9saXN0ZW5lcnNbZXZlbnRdLnB1c2ggZlxuXG4gICAgI1xuICAgICMgRmlyZSBhbiBldmVudC5cbiAgICAjIFRPRE86IERvIHNvbWV0aGluZyB3aXRoIHRpbWVvdXRzLiBZb3UgZG9uJ3Qgd2FudCB0aGlzIHRvIGZpcmUgZm9yIGV2ZXJ5IG9wZXJhdGlvbiAoZS5nLiBpbnNlcnQpLlxuICAgICNcbiAgICBjYWxsRXZlbnQ6IChldmVudCwgYXJncyktPlxuICAgICAgaWYgQGV2ZW50X2xpc3RlbmVyc1tldmVudF0/XG4gICAgICAgIGZvciBmIGluIEBldmVudF9saXN0ZW5lcnNbZXZlbnRdXG4gICAgICAgICAgZi5jYWxsIEAsIGV2ZW50LCBhcmdzXG5cbiAgICAjXG4gICAgIyBTZXQgdGhlIHBhcmVudCBvZiB0aGlzIG9wZXJhdGlvbi5cbiAgICAjXG4gICAgc2V0UGFyZW50OiAobyktPlxuICAgICAgQHBhcmVudCA9IG9cblxuICAgICNcbiAgICAjIENvbXB1dGVzIGEgdW5pcXVlIGlkZW50aWZpZXIgKHVpZCkgdGhhdCBpZGVudGlmaWVzIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICBnZXRVaWQ6ICgpLT5cbiAgICAgIHsgJ2NyZWF0b3InOiBAY3JlYXRvciwgJ29wX251bWJlcic6IEBvcF9udW1iZXIgfVxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIE5vdGlmeSB0aGUgYWxsIHRoZSBsaXN0ZW5lcnMuXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIEBpc19leGVjdXRlZCA9IHRydWVcbiAgICAgIGZvciBsIGluIGV4ZWN1dGlvbl9saXN0ZW5lclxuICAgICAgICBsIEBfZW5jb2RlKClcbiAgICAgIEBcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBPcGVyYXRpb25zIG1heSBkZXBlbmQgb24gb3RoZXIgb3BlcmF0aW9ucyAobGlua2VkIGxpc3RzLCBldGMuKS5cbiAgICAjIFRoZSBzYXZlT3BlcmF0aW9uIGFuZCB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucyBtZXRob2RzIHByb3ZpZGVcbiAgICAjIGFuIGVhc3kgd2F5IHRvIHJlZmVyIHRvIHRoZXNlIG9wZXJhdGlvbnMgdmlhIGFuIHVpZCBvciBvYmplY3QgcmVmZXJlbmNlLlxuICAgICNcbiAgICAjIEZvciBleGFtcGxlOiBXZSBjYW4gY3JlYXRlIGEgbmV3IERlbGV0ZSBvcGVyYXRpb24gdGhhdCBkZWxldGVzIHRoZSBvcGVyYXRpb24gJG8gbGlrZSB0aGlzXG4gICAgIyAgICAgLSB2YXIgZCA9IG5ldyBEZWxldGUodWlkLCAkbyk7ICAgb3JcbiAgICAjICAgICAtIHZhciBkID0gbmV3IERlbGV0ZSh1aWQsICRvLmdldFVpZCgpKTtcbiAgICAjIEVpdGhlciB3YXkgd2Ugd2FudCB0byBhY2Nlc3MgJG8gdmlhIGQuZGVsZXRlcy4gSW4gdGhlIHNlY29uZCBjYXNlIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zIG11c3QgYmUgY2FsbGVkIGZpcnN0LlxuICAgICNcbiAgICAjIEBvdmVybG9hZCBzYXZlT3BlcmF0aW9uKG5hbWUsIG9wX3VpZClcbiAgICAjICAgQHBhcmFtIHtTdHJpbmd9IG5hbWUgVGhlIG5hbWUgb2YgdGhlIG9wZXJhdGlvbi4gQWZ0ZXIgdmFsaWRhdGluZyAod2l0aCB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucykgdGhlIGluc3RhbnRpYXRlZCBvcGVyYXRpb24gd2lsbCBiZSBhY2Nlc3NpYmxlIHZpYSB0aGlzW25hbWVdLlxuICAgICMgICBAcGFyYW0ge09iamVjdH0gb3BfdWlkIEEgdWlkIHRoYXQgcmVmZXJzIHRvIGFuIG9wZXJhdGlvblxuICAgICMgQG92ZXJsb2FkIHNhdmVPcGVyYXRpb24obmFtZSwgb3ApXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBvcGVyYXRpb24uIEFmdGVyIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiBvcCBpcyBhY2Nlc3NpYmxlIHZpYSB0aGlzW25hbWVdLlxuICAgICMgICBAcGFyYW0ge09wZXJhdGlvbn0gb3AgQW4gT3BlcmF0aW9uIG9iamVjdFxuICAgICNcbiAgICBzYXZlT3BlcmF0aW9uOiAobmFtZSwgb3ApLT5cblxuICAgICAgI1xuICAgICAgIyBFdmVyeSBpbnN0YW5jZSBvZiAkT3BlcmF0aW9uIG11c3QgaGF2ZSBhbiAkZXhlY3V0ZSBmdW5jdGlvbi5cbiAgICAgICMgV2UgdXNlIGR1Y2stdHlwaW5nIHRvIGNoZWNrIGlmIG9wIGlzIGluc3RhbnRpYXRlZCBzaW5jZSB0aGVyZVxuICAgICAgIyBjb3VsZCBleGlzdCBtdWx0aXBsZSBjbGFzc2VzIG9mICRPcGVyYXRpb25cbiAgICAgICNcbiAgICAgIGlmIG9wPy5leGVjdXRlP1xuICAgICAgICAjIGlzIGluc3RhbnRpYXRlZFxuICAgICAgICBAW25hbWVdID0gb3BcbiAgICAgIGVsc2UgaWYgb3A/XG4gICAgICAgICMgbm90IGluaXRpYWxpemVkLiBEbyBpdCB3aGVuIGNhbGxpbmcgJHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgQHVuY2hlY2tlZCA/PSB7fVxuICAgICAgICBAdW5jaGVja2VkW25hbWVdID0gb3BcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBBZnRlciBjYWxsaW5nIHRoaXMgZnVuY3Rpb24gYWxsIG5vdCBpbnN0YW50aWF0ZWQgb3BlcmF0aW9ucyB3aWxsIGJlIGFjY2Vzc2libGUuXG4gICAgIyBAc2VlIE9wZXJhdGlvbi5zYXZlT3BlcmF0aW9uXG4gICAgI1xuICAgICMgQHJldHVybiBbQm9vbGVhbl0gV2hldGhlciBpdCB3YXMgcG9zc2libGUgdG8gaW5zdGFudGlhdGUgYWxsIG9wZXJhdGlvbnMuXG4gICAgI1xuICAgIHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zOiAoKS0+XG4gICAgICB1bmluc3RhbnRpYXRlZCA9IHt9XG4gICAgICBzdWNjZXNzID0gQFxuICAgICAgZm9yIG5hbWUsIG9wX3VpZCBvZiBAdW5jaGVja2VkXG4gICAgICAgIG9wID0gSEIuZ2V0T3BlcmF0aW9uIG9wX3VpZFxuICAgICAgICBpZiBvcFxuICAgICAgICAgIEBbbmFtZV0gPSBvcFxuICAgICAgICBlbHNlXG4gICAgICAgICAgdW5pbnN0YW50aWF0ZWRbbmFtZV0gPSBvcF91aWRcbiAgICAgICAgICBzdWNjZXNzID0gZmFsc2VcbiAgICAgIGRlbGV0ZSBAdW5jaGVja2VkXG4gICAgICBpZiBub3Qgc3VjY2Vzc1xuICAgICAgICBAdW5jaGVja2VkID0gdW5pbnN0YW50aWF0ZWRcbiAgICAgIHN1Y2Nlc3NcblxuXG5cbiAgI1xuICAjIEEgc2ltcGxlIERlbGV0ZS10eXBlIG9wZXJhdGlvbiB0aGF0IGRlbGV0ZXMgYW4gSW5zZXJ0LXR5cGUgb3BlcmF0aW9uLlxuICAjXG4gIGNsYXNzIERlbGV0ZSBleHRlbmRzIE9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IGRlbGV0ZXMgVUlEIG9yIHJlZmVyZW5jZSBvZiB0aGUgb3BlcmF0aW9uIHRoYXQgdGhpcyB0byBiZSBkZWxldGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgZGVsZXRlcyktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ2RlbGV0ZXMnLCBkZWxldGVzXG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBDb252ZXJ0IGFsbCByZWxldmFudCBpbmZvcm1hdGlvbiBvZiB0aGlzIG9wZXJhdGlvbiB0byB0aGUganNvbi1mb3JtYXQuXG4gICAgIyBUaGlzIHJlc3VsdCBjYW4gYmUgc2VudCB0byBvdGhlciBjbGllbnRzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICB7XG4gICAgICAgICd0eXBlJzogXCJEZWxldGVcIlxuICAgICAgICAndWlkJzogQGdldFVpZCgpXG4gICAgICAgICdkZWxldGVzJzogQGRlbGV0ZXMuZ2V0VWlkKClcbiAgICAgIH1cblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBBcHBseSB0aGUgZGVsZXRpb24uXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIEBkZWxldGVzLmFwcGx5RGVsZXRlIEBcbiAgICAgICAgc3VwZXJcbiAgICAgICAgQFxuICAgICAgZWxzZVxuICAgICAgICBmYWxzZVxuXG4gICNcbiAgIyBEZWZpbmUgaG93IHRvIHBhcnNlIERlbGV0ZSBvcGVyYXRpb25zLlxuICAjXG4gIHBhcnNlclsnRGVsZXRlJ10gPSAobyktPlxuICAgIHtcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAnZGVsZXRlcyc6IGRlbGV0ZXNfdWlkXG4gICAgfSA9IG9cbiAgICBuZXcgRGVsZXRlIHVpZCwgZGVsZXRlc191aWRcblxuICAjXG4gICMgQSBzaW1wbGUgaW5zZXJ0LXR5cGUgb3BlcmF0aW9uLlxuICAjXG4gICMgQW4gaW5zZXJ0IG9wZXJhdGlvbiBpcyBhbHdheXMgcG9zaXRpb25lZCBiZXR3ZWVuIHR3byBvdGhlciBpbnNlcnQgb3BlcmF0aW9ucy5cbiAgIyBJbnRlcm5hbGx5IHRoaXMgaXMgcmVhbGl6ZWQgYXMgYXNzb2NpYXRpdmUgbGlzdHMsIHdoZXJlYnkgZWFjaCBpbnNlcnQgb3BlcmF0aW9uIGhhcyBhIHByZWRlY2Vzc29yIGFuZCBhIHN1Y2Nlc3Nvci5cbiAgIyBGb3IgdGhlIHNha2Ugb2YgZWZmaWNpZW5jeSB3ZSBtYWludGFpbiB0d28gbGlzdHM6XG4gICMgICAtIFRoZSBzaG9ydC1saXN0IChhYmJyZXYuIHNsKSBtYWludGFpbnMgb25seSB0aGUgb3BlcmF0aW9ucyB0aGF0IGFyZSBub3QgZGVsZXRlZFxuICAjICAgLSBUaGUgY29tcGxldGUtbGlzdCAoYWJicmV2LiBjbCkgbWFpbnRhaW5zIGFsbCBvcGVyYXRpb25zXG4gICNcbiAgY2xhc3MgSW5zZXJ0IGV4dGVuZHMgT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gcHJldl9jbCBUaGUgcHJlZGVjZXNzb3Igb2YgdGhpcyBvcGVyYXRpb24gaW4gdGhlIGNvbXBsZXRlLWxpc3QgKGNsKVxuICAgICMgQHBhcmFtIHtPcGVyYXRpb259IG5leHRfY2wgVGhlIHN1Y2Nlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgI1xuICAgICMgQHNlZSBIaXN0b3J5QnVmZmVyLmdldE5leHRPcGVyYXRpb25JZGVudGlmaWVyXG4gICAgI1xuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBwcmV2X2NsLCBuZXh0X2NsLCBvcmlnaW4pLT5cbiAgICAgIEBzYXZlT3BlcmF0aW9uICdwcmV2X2NsJywgcHJldl9jbFxuICAgICAgQHNhdmVPcGVyYXRpb24gJ25leHRfY2wnLCBuZXh0X2NsXG4gICAgICBpZiBvcmlnaW4/XG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBvcmlnaW5cbiAgICAgIGVsc2VcbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ29yaWdpbicsIHByZXZfY2xcbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjXG4gICAgYXBwbHlEZWxldGU6IChvKS0+XG4gICAgICBAZGVsZXRlZF9ieSA/PSBbXVxuICAgICAgQGRlbGV0ZWRfYnkucHVzaCBvXG5cbiAgICAjXG4gICAgIyBJZiBpc0RlbGV0ZWQoKSBpcyB0cnVlIHRoaXMgb3BlcmF0aW9uIHdvbid0IGJlIG1haW50YWluZWQgaW4gdGhlIHNsXG4gICAgI1xuICAgIGlzRGVsZXRlZDogKCktPlxuICAgICAgQGRlbGV0ZWRfYnk/Lmxlbmd0aCA+IDBcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgIyBUaGUgYW1vdW50IG9mIHBvc2l0aW9ucyB0aGF0ICR0aGlzIG9wZXJhdGlvbiB3YXMgbW92ZWQgdG8gdGhlIHJpZ2h0LlxuICAgICNcbiAgICBnZXREaXN0YW5jZVRvT3JpZ2luOiAoKS0+XG4gICAgICBkID0gMFxuICAgICAgbyA9IEBwcmV2X2NsXG4gICAgICB3aGlsZSB0cnVlXG4gICAgICAgIGlmIEBvcmlnaW4gaXMgb1xuICAgICAgICAgIGJyZWFrXG4gICAgICAgIGQrK1xuICAgICAgICAjVE9ETzogZGVsZXRlIHRoaXNcbiAgICAgICAgaWYgQCBpcyBAcHJldl9jbFxuICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcInRoaXMgc2hvdWxkIG5vdCBoYXBwZW4gOykgXCJcbiAgICAgICAgbyA9IG8ucHJldl9jbFxuICAgICAgZFxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjIFVwZGF0ZSB0aGUgc2hvcnQgbGlzdFxuICAgICMgVE9ETyAoVW51c2VkKVxuICAgIHVwZGF0ZV9zbDogKCktPlxuICAgICAgbyA9IEBwcmV2X2NsXG4gICAgICB1cGRhdGU6IChkZXN0X2NsLGRlc3Rfc2wpLT5cbiAgICAgICAgd2hpbGUgdHJ1ZVxuICAgICAgICAgIGlmIG8uaXNEZWxldGVkKClcbiAgICAgICAgICAgIG8gPSBvW2Rlc3RfY2xdXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgQFtkZXN0X3NsXSA9IG9cblxuICAgICAgICAgICAgYnJlYWtcbiAgICAgIHVwZGF0ZSBcInByZXZfY2xcIiwgXCJwcmV2X3NsXCJcbiAgICAgIHVwZGF0ZSBcIm5leHRfY2xcIiwgXCJwcmV2X3NsXCJcblxuXG5cbiAgICAjXG4gICAgIyBAcHJpdmF0ZVxuICAgICMgSW5jbHVkZSB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgYXNzb2NpYXRpdmUgbGlzdHMuXG4gICAgI1xuICAgIGV4ZWN1dGU6ICgpLT5cbiAgICAgIGlmIEBpc19leGVjdXRlZD9cbiAgICAgICAgcmV0dXJuIEBcbiAgICAgIGlmIG5vdCBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICByZXR1cm4gZmFsc2VcbiAgICAgIGVsc2VcbiAgICAgICAgaWYgQHByZXZfY2w/LnZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKCkgYW5kIEBuZXh0X2NsPy52YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpIGFuZCBAcHJldl9jbC5uZXh0X2NsIGlzbnQgQFxuICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IDBcbiAgICAgICAgICBvID0gQHByZXZfY2wubmV4dF9jbFxuICAgICAgICAgIGkgPSAwXG4gICAgICAgICAgIyAkdGhpcyBoYXMgdG8gZmluZCBhIHVuaXF1ZSBwb3NpdGlvbiBiZXR3ZWVuIG9yaWdpbiBhbmQgdGhlIG5leHQga25vd24gY2hhcmFjdGVyXG4gICAgICAgICAgIyBjYXNlIDE6ICRvcmlnaW4gZXF1YWxzICRvLm9yaWdpbjogdGhlICRjcmVhdG9yIHBhcmFtZXRlciBkZWNpZGVzIGlmIGxlZnQgb3IgcmlnaHRcbiAgICAgICAgICAjICAgICAgICAgbGV0ICRPTD0gW28xLG8yLG8zLG80XSwgd2hlcmVieSAkdGhpcyBpcyB0byBiZSBpbnNlcnRlZCBiZXR3ZWVuIG8xIGFuZCBvNFxuICAgICAgICAgICMgICAgICAgICBvMixvMyBhbmQgbzQgb3JpZ2luIGlzIDEgKHRoZSBwb3NpdGlvbiBvZiBvMilcbiAgICAgICAgICAjICAgICAgICAgdGhlcmUgaXMgdGhlIGNhc2UgdGhhdCAkdGhpcy5jcmVhdG9yIDwgbzIuY3JlYXRvciwgYnV0IG8zLmNyZWF0b3IgPCAkdGhpcy5jcmVhdG9yXG4gICAgICAgICAgIyAgICAgICAgIHRoZW4gbzIga25vd3MgbzMuIFNpbmNlIG9uIGFub3RoZXIgY2xpZW50ICRPTCBjb3VsZCBiZSBbbzEsbzMsbzRdIHRoZSBwcm9ibGVtIGlzIGNvbXBsZXhcbiAgICAgICAgICAjICAgICAgICAgdGhlcmVmb3JlICR0aGlzIHdvdWxkIGJlIGFsd2F5cyB0byB0aGUgcmlnaHQgb2YgbzNcbiAgICAgICAgICAjIGNhc2UgMjogJG9yaWdpbiA8ICRvLm9yaWdpblxuICAgICAgICAgICMgICAgICAgICBpZiBjdXJyZW50ICR0aGlzIGluc2VydF9wb3NpdGlvbiA+ICRvIG9yaWdpbjogJHRoaXMgaW5zXG4gICAgICAgICAgIyAgICAgICAgIGVsc2UgJGluc2VydF9wb3NpdGlvbiB3aWxsIG5vdCBjaGFuZ2UgKG1heWJlIHdlIGVuY291bnRlciBjYXNlIDEgbGF0ZXIsIHRoZW4gdGhpcyB3aWxsIGJlIHRvIHRoZSByaWdodCBvZiAkbylcbiAgICAgICAgICAjIGNhc2UgMzogJG9yaWdpbiA+ICRvLm9yaWdpblxuICAgICAgICAgICMgICAgICAgICAkdGhpcyBpbnNlcnRfcG9zaXRpb24gaXMgdG8gdGhlIGxlZnQgb2YgJG8gKGZvcmV2ZXIhKVxuICAgICAgICAgIHdoaWxlIHRydWVcbiAgICAgICAgICAgIGlmIG5vdCBvP1xuICAgICAgICAgICAgICAjIFRPRE86IERlYnVnZ2luZ1xuICAgICAgICAgICAgICBjb25zb2xlLmxvZyBKU09OLnN0cmluZ2lmeSBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICAgICAgICBjb25zb2xlLmxvZyBKU09OLnN0cmluZ2lmeSBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgICAgICAgaWYgbyBpc250IEBuZXh0X2NsXG4gICAgICAgICAgICAgICMgJG8gaGFwcGVuZWQgY29uY3VycmVudGx5XG4gICAgICAgICAgICAgIGlmIG8uZ2V0RGlzdGFuY2VUb09yaWdpbigpIGlzIGlcbiAgICAgICAgICAgICAgICAjIGNhc2UgMVxuICAgICAgICAgICAgICAgIGlmIG8uY3JlYXRvciA8IEBjcmVhdG9yXG4gICAgICAgICAgICAgICAgICBAcHJldl9jbCA9IG9cbiAgICAgICAgICAgICAgICAgIGRpc3RhbmNlX3RvX29yaWdpbiA9IGkgKyAxXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgIyBub3BcbiAgICAgICAgICAgICAgZWxzZSBpZiBvLmdldERpc3RhbmNlVG9PcmlnaW4oKSA8IGlcbiAgICAgICAgICAgICAgICAjIGNhc2UgMlxuICAgICAgICAgICAgICAgIGlmIGkgLSBkaXN0YW5jZV90b19vcmlnaW4gPD0gby5nZXREaXN0YW5jZVRvT3JpZ2luKClcbiAgICAgICAgICAgICAgICAgIEBwcmV2X2NsID0gb1xuICAgICAgICAgICAgICAgICAgZGlzdGFuY2VfdG9fb3JpZ2luID0gaSArIDFcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAjbm9wXG4gICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAjIGNhc2UgM1xuICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgIGkrK1xuICAgICAgICAgICAgICBvID0gby5uZXh0X2NsXG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICMgJHRoaXMga25vd3MgdGhhdCAkbyBleGlzdHMsXG4gICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgIyBub3cgcmVjb25uZWN0IGV2ZXJ5dGhpbmdcbiAgICAgICAgICBAbmV4dF9jbCA9IEBwcmV2X2NsLm5leHRfY2xcbiAgICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxuICAgICAgICAgIEBuZXh0X2NsLnByZXZfY2wgPSBAXG4gICAgICAgIHN1cGVyICMgbm90aWZ5IHRoZSBleGVjdXRpb25fbGlzdGVuZXJzXG4gICAgICAgIEBcblxuICAjXG4gICMgRGVmaW5lcyBhbiBvYmplY3QgdGhhdCBpcyBjYW5ub3QgYmUgY2hhbmdlZC4gWW91IGNhbiB1c2UgdGhpcyB0byBzZXQgYW4gaW1tdXRhYmxlIHN0cmluZywgb3IgYSBudW1iZXIuXG4gICNcbiAgY2xhc3MgSW1tdXRhYmxlT2JqZWN0IGV4dGVuZHMgSW5zZXJ0XG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gY29udGVudFxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgQGNvbnRlbnQsIHByZXYsIG5leHQsIG9yaWdpbiktPlxuICAgICAgc3VwZXIgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICAgICNcbiAgICAjIEByZXR1cm4gW1N0cmluZ10gVGhlIGNvbnRlbnQgb2YgdGhpcyBvcGVyYXRpb24uXG4gICAgI1xuICAgIHZhbCA6ICgpLT5cbiAgICAgIEBjb250ZW50XG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID0ge1xuICAgICAgICAndHlwZSc6IFwiSW1tdXRhYmxlT2JqZWN0XCJcbiAgICAgICAgJ3VpZCcgOiBAZ2V0VWlkKClcbiAgICAgICAgJ2NvbnRlbnQnIDogQGNvbnRlbnRcbiAgICAgIH1cbiAgICAgIGlmIEBwcmV2X2NsP1xuICAgICAgICBqc29uWydwcmV2J10gPSBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgaWYgQG5leHRfY2w/XG4gICAgICAgIGpzb25bJ25leHQnXSA9IEBuZXh0X2NsLmdldFVpZCgpXG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyWydJbW11dGFibGVPYmplY3QnXSA9IChqc29uKS0+XG4gICAge1xuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICdwcmV2JzogcHJldlxuICAgICAgJ25leHQnOiBuZXh0XG4gICAgICAnb3JpZ2luJyA6IG9yaWdpblxuICAgIH0gPSBqc29uXG4gICAgbmV3IEltbXV0YWJsZU9iamVjdCB1aWQsIGNvbnRlbnQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICNcbiAgIyBBIGRlbGltaXRlciBpcyBwbGFjZWQgYXQgdGhlIGVuZCBhbmQgYXQgdGhlIGJlZ2lubmluZyBvZiB0aGUgYXNzb2NpYXRpdmUgbGlzdHMuXG4gICMgVGhpcyBpcyBuZWNlc3NhcnkgaW4gb3JkZXIgdG8gaGF2ZSBhIGJlZ2lubmluZyBhbmQgYW4gZW5kIGV2ZW4gaWYgdGhlIGNvbnRlbnRcbiAgIyBvZiB0aGUgRW5naW5lIGlzIGVtcHR5LlxuICAjXG4gIGNsYXNzIERlbGltaXRlciBleHRlbmRzIE9wZXJhdGlvblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBwcmV2X2NsIFRoZSBwcmVkZWNlc3NvciBvZiB0aGlzIG9wZXJhdGlvbiBpbiB0aGUgY29tcGxldGUtbGlzdCAoY2wpXG4gICAgIyBAcGFyYW0ge09wZXJhdGlvbn0gbmV4dF9jbCBUaGUgc3VjY2Vzc29yIG9mIHRoaXMgb3BlcmF0aW9uIGluIHRoZSBjb21wbGV0ZS1saXN0IChjbClcbiAgICAjXG4gICAgIyBAc2VlIEhpc3RvcnlCdWZmZXIuZ2V0TmV4dE9wZXJhdGlvbklkZW50aWZpZXJcbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIHByZXZfY2wsIG5leHRfY2wsIG9yaWdpbiktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ3ByZXZfY2wnLCBwcmV2X2NsXG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnbmV4dF9jbCcsIG5leHRfY2xcbiAgICAgIEBzYXZlT3BlcmF0aW9uICdvcmlnaW4nLCBwcmV2X2NsXG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIElmIGlzRGVsZXRlZCgpIGlzIHRydWUgdGhpcyBvcGVyYXRpb24gd29uJ3QgYmUgbWFpbnRhaW5lZCBpbiB0aGUgc2xcbiAgICAjXG4gICAgaXNEZWxldGVkOiAoKS0+XG4gICAgICBmYWxzZVxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgQHVuY2hlY2tlZD9bJ25leHRfY2wnXT9cbiAgICAgICAgc3VwZXJcbiAgICAgIGVsc2UgaWYgQHVuY2hlY2tlZD9bJ3ByZXZfY2wnXVxuICAgICAgICBpZiBAdmFsaWRhdGVTYXZlZE9wZXJhdGlvbnMoKVxuICAgICAgICAgIGlmIEBwcmV2X2NsLm5leHRfY2w/XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJQcm9iYWJseSBkdXBsaWNhdGVkIG9wZXJhdGlvbnNcIlxuICAgICAgICAgIEBwcmV2X2NsLm5leHRfY2wgPSBAXG4gICAgICAgICAgZGVsZXRlIEBwcmV2X2NsLnVuY2hlY2tlZC5uZXh0X2NsXG4gICAgICAgICAgc3VwZXJcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGZhbHNlXG4gICAgICBlbHNlIGlmIEBwcmV2X2NsPyBhbmQgbm90IEBwcmV2X2NsLm5leHRfY2w/XG4gICAgICAgIGRlbGV0ZSBAcHJldl9jbC51bmNoZWNrZWQubmV4dF9jbFxuICAgICAgICBAcHJldl9jbC5uZXh0X2NsID0gQFxuICAgICAgZWxzZSBpZiBAcHJldl9jbD8gb3IgQG5leHRfY2w/XG4gICAgICAgIHN1cGVyXG4gICAgICBlbHNlXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcIkRlbGltaXRlciBpcyB1bnN1ZmZpY2llbnQgZGVmaW5lZCFcIlxuXG4gICAgI1xuICAgICMgQHByaXZhdGVcbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAge1xuICAgICAgICAndHlwZScgOiBcIkRlbGltaXRlclwiXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICdwcmV2JyA6IEBwcmV2X2NsPy5nZXRVaWQoKVxuICAgICAgICAnbmV4dCcgOiBAbmV4dF9jbD8uZ2V0VWlkKClcbiAgICAgIH1cblxuICBwYXJzZXJbJ0RlbGltaXRlciddID0gKGpzb24pLT5cbiAgICB7XG4gICAgJ3VpZCcgOiB1aWRcbiAgICAncHJldicgOiBwcmV2XG4gICAgJ25leHQnIDogbmV4dFxuICAgIH0gPSBqc29uXG4gICAgbmV3IERlbGltaXRlciB1aWQsIHByZXYsIG5leHRcblxuICAjIFRoaXMgaXMgd2hhdCB0aGlzIG1vZHVsZSBleHBvcnRzIGFmdGVyIGluaXRpYWxpemluZyBpdCB3aXRoIHRoZSBIaXN0b3J5QnVmZmVyXG4gIHtcbiAgICAndHlwZXMnIDpcbiAgICAgICdEZWxldGUnIDogRGVsZXRlXG4gICAgICAnSW5zZXJ0JyA6IEluc2VydFxuICAgICAgJ0RlbGltaXRlcic6IERlbGltaXRlclxuICAgICAgJ09wZXJhdGlvbic6IE9wZXJhdGlvblxuICAgICAgJ0ltbXV0YWJsZU9iamVjdCcgOiBJbW11dGFibGVPYmplY3RcbiAgICAncGFyc2VyJyA6IHBhcnNlclxuICAgICdleGVjdXRpb25fbGlzdGVuZXInIDogZXhlY3V0aW9uX2xpc3RlbmVyXG4gIH1cblxuXG5cblxuIiwidGV4dF90eXBlc191bmluaXRpYWxpemVkID0gcmVxdWlyZSBcIi4vVGV4dFR5cGVzXCJcblxubW9kdWxlLmV4cG9ydHMgPSAoSEIpLT5cbiAgdGV4dF90eXBlcyA9IHRleHRfdHlwZXNfdW5pbml0aWFsaXplZCBIQlxuICB0eXBlcyA9IHRleHRfdHlwZXMudHlwZXNcbiAgcGFyc2VyID0gdGV4dF90eXBlcy5wYXJzZXJcblxuICBjcmVhdGVKc29uV3JhcHBlciA9IChfanNvblR5cGUpLT5cblxuICAgICNcbiAgICAjIEEgSnNvbldyYXBwZXIgd2FzIGludGVuZGVkIHRvIGJlIGEgY29udmVuaWVudCB3cmFwcGVyIGZvciB0aGUgSnNvblR5cGUuXG4gICAgIyBCdXQgaXQgY2FuIG1ha2UgdGhpbmdzIG1vcmUgZGlmZmljdWx0IHRoYW4gdGhleSBhcmUuXG4gICAgIyBAc2VlIEpzb25UeXBlXG4gICAgI1xuICAgICMgQGV4YW1wbGUgY3JlYXRlIGEgSnNvbldyYXBwZXJcbiAgICAjICAgIyBZb3UgZ2V0IGEgSnNvbldyYXBwZXIgZnJvbSBhIEpzb25UeXBlIGJ5IGNhbGxpbmdcbiAgICAjICAgdyA9IHlhdHRhLnZhbHVlXG4gICAgI1xuICAgICMgSXQgY3JlYXRlcyBKYXZhc2NyaXB0cyAtZ2V0dGVyIGFuZCAtc2V0dGVyIG1ldGhvZHMgZm9yIGVhY2ggcHJvcGVydHkgdGhhdCBKc29uVHlwZSBtYWludGFpbnMuXG4gICAgIyBAc2VlIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL09iamVjdC9kZWZpbmVQcm9wZXJ0eVxuICAgICNcbiAgICAjIEBleGFtcGxlIEdldHRlciBFeGFtcGxlXG4gICAgIyAgICMgeW91IGNhbiBhY2Nlc3MgdGhlIHggcHJvcGVydHkgb2YgeWF0dGEgYnkgY2FsbGluZ1xuICAgICMgICB3LnhcbiAgICAjICAgIyBpbnN0ZWFkIG9mXG4gICAgIyAgIHlhdHRhLnZhbCgneCcpXG4gICAgI1xuICAgICMgQG5vdGUgWW91IGNhbiBvbmx5IG92ZXJ3cml0ZSBleGlzdGluZyB2YWx1ZXMhIFNldHRpbmcgYSBuZXcgcHJvcGVydHkgd29uJ3QgaGF2ZSBhbnkgZWZmZWN0IVxuICAgICNcbiAgICAjIEBleGFtcGxlIFNldHRlciBFeGFtcGxlXG4gICAgIyAgICMgeW91IGNhbiBzZXQgYW4gZXhpc3RpbmcgeCBwcm9wZXJ0eSBvZiB5YXR0YSBieSBjYWxsaW5nXG4gICAgIyAgIHcueCA9IFwidGV4dFwiXG4gICAgIyAgICMgaW5zdGVhZCBvZlxuICAgICMgICB5YXR0YS52YWwoJ3gnLCBcInRleHRcIilcbiAgICAjXG4gICAgIyBJbiBvcmRlciB0byBzZXQgYSBuZXcgcHJvcGVydHkgeW91IGhhdmUgdG8gb3ZlcndyaXRlIGFuIGV4aXN0aW5nIHByb3BlcnR5LlxuICAgICMgVGhlcmVmb3JlIHRoZSBKc29uV3JhcHBlciBzdXBwb3J0cyBhIHNwZWNpYWwgZmVhdHVyZSB0aGF0IHNob3VsZCBtYWtlIHRoaW5ncyBtb3JlIGNvbnZlbmllbnRcbiAgICAjICh3ZSBjYW4gYXJndWUgYWJvdXQgdGhhdCwgdXNlIHRoZSBKc29uVHlwZSBpZiB5b3UgZG9uJ3QgbGlrZSBpdCA7KS5cbiAgICAjIElmIHlvdSBvdmVyd3JpdGUgYW4gb2JqZWN0IHByb3BlcnR5IG9mIHRoZSBKc29uV3JhcHBlciB3aXRoIGEgbmV3IG9iamVjdCwgaXQgd2lsbCByZXN1bHQgaW4gYSBtZXJnZWQgdmVyc2lvbiBvZiB0aGUgb2JqZWN0cy5cbiAgICAjIExldCB3LnAgdGhlIHByb3BlcnR5IHRoYXQgaXMgdG8gYmUgb3ZlcndyaXR0ZW4gYW5kIG8gdGhlIG5ldyB2YWx1ZS4gRS5nLiB3LnAgPSBvXG4gICAgIyAqIFRoZSByZXN1bHQgaGFzIGFsbCBwcm9wZXJ0aWVzIG9mIG9cbiAgICAjICogVGhlIHJlc3VsdCBoYXMgYWxsIHByb3BlcnRpZXMgb2Ygdy5wIGlmIHRoZXkgZG9uJ3Qgb2NjdXIgdW5kZXIgdGhlIHNhbWUgcHJvcGVydHktbmFtZSBpbiBvLlxuICAgICNcbiAgICAjIEBleGFtcGxlIENvbmZsaWN0IEV4YW1wbGVcbiAgICAjICAgeWF0dGEudmFsdWUgPSB7YSA6IFwic3RyaW5nXCJ9XG4gICAgIyAgIHcgPSB5YXR0YS52YWx1ZVxuICAgICMgICBjb25zb2xlLmxvZyh3KSAjIHthIDogXCJzdHJpbmdcIn1cbiAgICAjICAgdy5hID0ge2EgOiB7YiA6IFwic3RyaW5nXCJ9fVxuICAgICMgICBjb25zb2xlLmxvZyh3KSAjIHthIDoge2IgOiBcIlN0cmluZ1wifX1cbiAgICAjICAgdy5hID0ge2EgOiB7YyA6IDR9fVxuICAgICMgICBjb25zb2xlLmxvZyh3KSAjIHthIDoge2IgOiBcIlN0cmluZ1wiLCBjIDogNH19XG4gICAgI1xuICAgICMgQGV4YW1wbGUgQ29tbW9uIFBpdGZhbGxzXG4gICAgIyAgIHcgPSB5YXR0YS52YWx1ZVxuICAgICMgICAjIFNldHRpbmcgYSBuZXcgcHJvcGVydHlcbiAgICAjICAgdy5uZXdQcm9wZXJ0eSA9IFwiQXdlc29tZVwiXG4gICAgIyAgIGNvbnNvbGUubG9nKHcubmV3UHJvcGVydHkgPT0gXCJBd2Vzb21lXCIpICMgZmFsc2UsIHcubmV3UHJvcGVydHkgaXMgdW5kZWZpbmVkXG4gICAgIyAgICMgb3ZlcndyaXRlIHRoZSB3IG9iamVjdFxuICAgICMgICB3ID0ge25ld1Byb3BlcnR5IDogXCJBd2Vzb21lXCJ9XG4gICAgIyAgIGNvbnNvbGUubG9nKHcubmV3UHJvcGVydHkgPT0gXCJBd2Vzb21lXCIpICMgdHJ1ZSEsIGJ1dCAuLlxuICAgICMgICBjb25zb2xlLmxvZyh5YXR0YS52YWx1ZS5uZXdQcm9wZXJ0eSA9PSBcIkF3ZXNvbWVcIikgIyBmYWxzZSwgeW91IGFyZSBvbmx5IGFsbG93ZWQgdG8gc2V0IHByb3BlcnRpZXMhXG4gICAgIyAgICMgVGhlIHNvbHV0aW9uXG4gICAgIyAgIHlhdHRhLnZhbHVlID0ge25ld1Byb3BlcnR5IDogXCJBd2Vzb21lXCJ9XG4gICAgIyAgIGNvbnNvbGUubG9nKHcubmV3UHJvcGVydHkgPT0gXCJBd2Vzb21lXCIpICMgdHJ1ZSFcbiAgICAjXG4gICAgY2xhc3MgSnNvbldyYXBwZXJcblxuICAgICAgI1xuICAgICAgIyBAcGFyYW0ge0pzb25UeXBlfSBqc29uVHlwZSBJbnN0YW5jZSBvZiB0aGUgSnNvblR5cGUgdGhhdCB0aGlzIGNsYXNzIHdyYXBwZXMuXG4gICAgICAjXG4gICAgICBjb25zdHJ1Y3RvcjogKGpzb25UeXBlKS0+XG4gICAgICAgIGZvciBuYW1lLCBvYmogb2YganNvblR5cGUubWFwXG4gICAgICAgICAgZG8gKG5hbWUsIG9iaiktPlxuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5IEpzb25XcmFwcGVyLnByb3RvdHlwZSwgbmFtZSxcbiAgICAgICAgICAgICAgZ2V0IDogLT5cbiAgICAgICAgICAgICAgICB4ID0gb2JqLnZhbCgpXG4gICAgICAgICAgICAgICAgaWYgeCBpbnN0YW5jZW9mIEpzb25UeXBlXG4gICAgICAgICAgICAgICAgICBjcmVhdGVKc29uV3JhcHBlciB4XG4gICAgICAgICAgICAgICAgZWxzZSBpZiB4IGluc3RhbmNlb2YgdHlwZXMuSW1tdXRhYmxlT2JqZWN0XG4gICAgICAgICAgICAgICAgICB4LnZhbCgpXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgeFxuICAgICAgICAgICAgICBzZXQgOiAobyktPlxuICAgICAgICAgICAgICAgIGlmIG8uY29uc3RydWN0b3IgaXMge30uY29uc3RydWN0b3JcbiAgICAgICAgICAgICAgICAgIG92ZXJ3cml0ZSA9IGpzb25UeXBlLnZhbChuYW1lKVxuICAgICAgICAgICAgICAgICAgZm9yIG9fbmFtZSxvX29iaiBvZiBvXG4gICAgICAgICAgICAgICAgICAgIG92ZXJ3cml0ZS52YWwob19uYW1lLCBvX29iaiwgJ2ltbXV0YWJsZScpXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAganNvblR5cGUudmFsKG5hbWUsIG8sICdpbW11dGFibGUnKVxuICAgICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlXG4gICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2VcbiAgICBuZXcgSnNvbldyYXBwZXIgX2pzb25UeXBlXG5cbiAgI1xuICAjIE1hbmFnZXMgT2JqZWN0LWxpa2UgdmFsdWVzLlxuICAjXG4gIGNsYXNzIEpzb25UeXBlIGV4dGVuZHMgdHlwZXMuTWFwTWFuYWdlclxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtPYmplY3R9IGluaXRpYWxfdmFsdWUgQ3JlYXRlIHRoaXMgb3BlcmF0aW9uIHdpdGggYW4gaW5pdGlhbCB2YWx1ZS5cbiAgICAjIEBwYXJhbSB7U3RyaW5nfEJvb2xlYW59IFdoZXRoZXIgdGhlIGluaXRpYWxfdmFsdWUgc2hvdWxkIGJlIGNyZWF0ZWQgYXMgbXV0YWJsZS4gKE9wdGlvbmFsIC0gc2VlIHNldE11dGFibGVEZWZhdWx0KVxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCwgaW5pdGlhbF92YWx1ZSwgbXV0YWJsZSktPlxuICAgICAgc3VwZXIgdWlkXG4gICAgICBpZiBpbml0aWFsX3ZhbHVlP1xuICAgICAgICBpZiB0eXBlb2YgaW5pdGlhbF92YWx1ZSBpc250IFwib2JqZWN0XCJcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJUaGUgaW5pdGlhbCB2YWx1ZSBvZiBKc29uVHlwZXMgbXVzdCBiZSBvZiB0eXBlIE9iamVjdCEgKGN1cnJlbnQgdHlwZTogI3t0eXBlb2YgaW5pdGlhbF92YWx1ZX0pXCJcbiAgICAgICAgZm9yIG5hbWUsbyBvZiBpbml0aWFsX3ZhbHVlXG4gICAgICAgICAgQHZhbCBuYW1lLCBvLCBtdXRhYmxlXG5cbiAgICAjXG4gICAgIyBXaGV0aGVyIHRoZSBkZWZhdWx0IGlzICdtdXRhYmxlJyAodHJ1ZSkgb3IgJ2ltbXV0YWJsZScgKGZhbHNlKVxuICAgICNcbiAgICBtdXRhYmxlX2RlZmF1bHQ6XG4gICAgICB0cnVlXG5cbiAgICAjXG4gICAgIyBTZXQgaWYgdGhlIGRlZmF1bHQgaXMgJ211dGFibGUnIG9yICdpbW11dGFibGUnXG4gICAgIyBAcGFyYW0ge1N0cmluZ3xCb29sZWFufSBtdXRhYmxlIFNldCBlaXRoZXIgJ211dGFibGUnIC8gdHJ1ZSBvciAnaW1tdXRhYmxlJyAvIGZhbHNlXG4gICAgc2V0TXV0YWJsZURlZmF1bHQ6IChtdXRhYmxlKS0+XG4gICAgICBpZiBtdXRhYmxlIGlzIHRydWUgb3IgbXV0YWJsZSBpcyAnbXV0YWJsZSdcbiAgICAgICAgSnNvblR5cGUucHJvdG90eXBlLm11dGFibGVfZGVmYXVsdCA9IHRydWVcbiAgICAgIGVsc2UgaWYgbXV0YWJsZSBpcyBmYWxzZSBvciBtdXRhYmxlIGlzICdpbW11dGFibGUnXG4gICAgICAgIEpzb25UeXBlLnByb3RvdHlwZS5tdXRhYmxlX2RlZmF1bHQgPSBmYWxzZVxuICAgICAgZWxzZVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgJ1NldCBtdXRhYmxlIGVpdGhlciBcIm11dGFibGVcIiBvciBcImltbXV0YWJsZVwiISdcbiAgICAgICdPSydcblxuICAgICNcbiAgICAjIEBvdmVybG9hZCB2YWwoKVxuICAgICMgICBHZXQgdGhpcyBhcyBhIEpzb24gb2JqZWN0LlxuICAgICMgICBAcmV0dXJuIFtKc29uXVxuICAgICNcbiAgICAjIEBvdmVybG9hZCB2YWwobmFtZSlcbiAgICAjICAgR2V0IHZhbHVlIG9mIGEgcHJvcGVydHkuXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIG9iamVjdCBwcm9wZXJ0eS5cbiAgICAjICAgQHJldHVybiBbSnNvblR5cGV8V29yZHxTdHJpbmd8T2JqZWN0XSBEZXBlbmRpbmcgb24gdGhlIHZhbHVlIG9mIHRoZSBwcm9wZXJ0eS4gSWYgbXV0YWJsZSBpdCB3aWxsIHJldHVybiBhIE9wZXJhdGlvbi10eXBlIG9iamVjdCwgaWYgaW1tdXRhYmxlIGl0IHdpbGwgcmV0dXJuIFN0cmluZy9PYmplY3QuXG4gICAgI1xuICAgICMgQG92ZXJsb2FkIHZhbChuYW1lLCBjb250ZW50KVxuICAgICMgICBTZXQgYSBuZXcgcHJvcGVydHkuXG4gICAgIyAgIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIG9iamVjdCBwcm9wZXJ0eS5cbiAgICAjICAgQHBhcmFtIHtPYmplY3R8U3RyaW5nfSBjb250ZW50IENvbnRlbnQgb2YgdGhlIG9iamVjdCBwcm9wZXJ0eS5cbiAgICAjICAgQHJldHVybiBbSnNvblR5cGVdIFRoaXMgb2JqZWN0LiAoc3VwcG9ydHMgY2hhaW5pbmcpXG4gICAgI1xuICAgIHZhbDogKG5hbWUsIGNvbnRlbnQsIG11dGFibGUpLT5cbiAgICAgIGlmIHR5cGVvZiBuYW1lIGlzICdvYmplY3QnXG4gICAgICAgICMgU3BlY2lhbCBjYXNlLiBGaXJzdCBhcmd1bWVudCBpcyBhbiBvYmplY3QuIFRoZW4gdGhlIHNlY29uZCBhcmcgaXMgbXV0YWJsZS5cbiAgICAgICAgIyBLZWVwIHRoYXQgaW4gbWluZCB3aGVuIHJlYWRpbmcgdGhlIGZvbGxvd2luZy4uXG4gICAgICAgIGZvciBvX25hbWUsbyBvZiBuYW1lXG4gICAgICAgICAgQHZhbChvX25hbWUsbyxjb250ZW50KVxuICAgICAgICBAXG4gICAgICBlbHNlIGlmIG5hbWU/IGFuZCBjb250ZW50P1xuICAgICAgICBpZiBtdXRhYmxlP1xuICAgICAgICAgIGlmIG11dGFibGUgaXMgdHJ1ZSBvciBtdXRhYmxlIGlzICdtdXRhYmxlJ1xuICAgICAgICAgICAgbXV0YWJsZSA9IHRydWVcbiAgICAgICAgICBlbHNlXG4gICAgICAgICAgICBtdXRhYmxlID0gZmFsc2VcbiAgICAgICAgZWxzZVxuICAgICAgICAgIG11dGFibGUgPSBAbXV0YWJsZV9kZWZhdWx0XG4gICAgICAgIGlmIHR5cGVvZiBjb250ZW50IGlzICdmdW5jdGlvbidcbiAgICAgICAgICBAICMgSnVzdCBkbyBub3RoaW5nXG4gICAgICAgIGVsc2UgaWYgKChub3QgbXV0YWJsZSkgb3IgdHlwZW9mIGNvbnRlbnQgaXMgJ251bWJlcicpIGFuZCBjb250ZW50LmNvbnN0cnVjdG9yIGlzbnQgT2JqZWN0XG4gICAgICAgICAgb2JqID0gSEIuYWRkT3BlcmF0aW9uKG5ldyB0eXBlcy5JbW11dGFibGVPYmplY3QgdW5kZWZpbmVkLCBjb250ZW50KS5leGVjdXRlKClcbiAgICAgICAgICBzdXBlciBuYW1lLCBvYmpcbiAgICAgICAgZWxzZVxuICAgICAgICAgIGlmIHR5cGVvZiBjb250ZW50IGlzICdzdHJpbmcnXG4gICAgICAgICAgICB3b3JkID0gSEIuYWRkT3BlcmF0aW9uKG5ldyB0eXBlcy5Xb3JkIHVuZGVmaW5lZCkuZXhlY3V0ZSgpXG4gICAgICAgICAgICB3b3JkLmluc2VydFRleHQgMCwgY29udGVudFxuICAgICAgICAgICAgc3VwZXIgbmFtZSwgd29yZFxuICAgICAgICAgIGVsc2UgaWYgY29udGVudC5jb25zdHJ1Y3RvciBpcyBPYmplY3RcbiAgICAgICAgICAgIGpzb24gPSBIQi5hZGRPcGVyYXRpb24obmV3IEpzb25UeXBlIHVuZGVmaW5lZCwgY29udGVudCwgbXV0YWJsZSkuZXhlY3V0ZSgpXG4gICAgICAgICAgICBzdXBlciBuYW1lLCBqc29uXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3Qgbm90IHNldCAje3R5cGVvZiBjb250ZW50fS10eXBlcyBpbiBjb2xsYWJvcmF0aXZlIEpzb24tb2JqZWN0cyFcIlxuICAgICAgZWxzZVxuICAgICAgICBzdXBlciBuYW1lLCBjb250ZW50XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkgSnNvblR5cGUucHJvdG90eXBlLCAndmFsdWUnLFxuICAgICAgZ2V0IDogLT4gY3JlYXRlSnNvbldyYXBwZXIgQFxuICAgICAgc2V0IDogKG8pLT5cbiAgICAgICAgaWYgby5jb25zdHJ1Y3RvciBpcyB7fS5jb25zdHJ1Y3RvclxuICAgICAgICAgIGZvciBvX25hbWUsb19vYmogb2Ygb1xuICAgICAgICAgICAgQHZhbChvX25hbWUsIG9fb2JqLCAnaW1tdXRhYmxlJylcbiAgICAgICAgZWxzZVxuICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBtdXN0IG9ubHkgc2V0IE9iamVjdCB2YWx1ZXMhXCJcblxuICAgICNcbiAgICAjIEBwcml2YXRlXG4gICAgI1xuICAgIF9lbmNvZGU6ICgpLT5cbiAgICAgIHtcbiAgICAgICAgJ3R5cGUnIDogXCJKc29uVHlwZVwiXG4gICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICB9XG5cbiAgcGFyc2VyWydKc29uVHlwZSddID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgIH0gPSBqc29uXG4gICAgbmV3IEpzb25UeXBlIHVpZFxuXG5cblxuXG4gIHR5cGVzWydKc29uVHlwZSddID0gSnNvblR5cGVcblxuICB0ZXh0X3R5cGVzXG5cblxuIiwiYmFzaWNfdHlwZXNfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuL0Jhc2ljVHlwZXNcIlxuXG5tb2R1bGUuZXhwb3J0cyA9IChIQiktPlxuICBiYXNpY190eXBlcyA9IGJhc2ljX3R5cGVzX3VuaW5pdGlhbGl6ZWQgSEJcbiAgdHlwZXMgPSBiYXNpY190eXBlcy50eXBlc1xuICBwYXJzZXIgPSBiYXNpY190eXBlcy5wYXJzZXJcblxuICAjXG4gICMgTWFuYWdlcyBtYXAgbGlrZSBvYmplY3RzLiBFLmcuIEpzb24tVHlwZSBhbmQgWE1MIGF0dHJpYnV0ZXMuXG4gICNcbiAgY2xhc3MgTWFwTWFuYWdlciBleHRlbmRzIHR5cGVzLk9wZXJhdGlvblxuXG4gICAgI1xuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICNcbiAgICBjb25zdHJ1Y3RvcjogKHVpZCktPlxuICAgICAgQG1hcCA9IHt9XG4gICAgICBzdXBlciB1aWRcblxuICAgICNcbiAgICAjIEBzZWUgSnNvblR5cGVzLnZhbFxuICAgICNcbiAgICB2YWw6IChuYW1lLCBjb250ZW50KS0+XG4gICAgICBpZiBjb250ZW50P1xuICAgICAgICBpZiBub3QgQG1hcFtuYW1lXT9cbiAgICAgICAgICBIQi5hZGRPcGVyYXRpb24obmV3IEFkZE5hbWUgdW5kZWZpbmVkLCBALCBuYW1lKS5leGVjdXRlKClcbiAgICAgICAgQG1hcFtuYW1lXS5yZXBsYWNlIGNvbnRlbnRcbiAgICAgICAgQFxuICAgICAgZWxzZSBpZiBuYW1lP1xuICAgICAgICBvYmogPSBAbWFwW25hbWVdPy52YWwoKVxuICAgICAgICBpZiBvYmogaW5zdGFuY2VvZiB0eXBlcy5JbW11dGFibGVPYmplY3RcbiAgICAgICAgICBvYmoudmFsKClcbiAgICAgICAgZWxzZVxuICAgICAgICAgIG9ialxuICAgICAgZWxzZVxuICAgICAgICByZXN1bHQgPSB7fVxuICAgICAgICBmb3IgbmFtZSxvIG9mIEBtYXBcbiAgICAgICAgICBvYmogPSBvLnZhbCgpXG4gICAgICAgICAgaWYgb2JqIGluc3RhbmNlb2YgdHlwZXMuSW1tdXRhYmxlT2JqZWN0IG9yIG9iaiBpbnN0YW5jZW9mIE1hcE1hbmFnZXJcbiAgICAgICAgICAgIG9iaiA9IG9iai52YWwoKVxuICAgICAgICAgIHJlc3VsdFtuYW1lXSA9IG9ialxuICAgICAgICByZXN1bHRcblxuICAjXG4gICMgV2hlbiBhIG5ldyBwcm9wZXJ0eSBpbiBhIG1hcCBtYW5hZ2VyIGlzIGNyZWF0ZWQsIHRoZW4gdGhlIHVpZHMgb2YgdGhlIGluc2VydGVkIE9wZXJhdGlvbnNcbiAgIyBtdXN0IGJlIHVuaXF1ZSAodGhpbmsgYWJvdXQgY29uY3VycmVudCBvcGVyYXRpb25zKS4gVGhlcmVmb3JlIG9ubHkgYW4gQWRkTmFtZSBvcGVyYXRpb24gaXMgYWxsb3dlZCB0b1xuICAjIGFkZCBhIHByb3BlcnR5IGluIGEgTWFwTWFuYWdlci4gSWYgdHdvIEFkZE5hbWUgb3BlcmF0aW9ucyBvbiB0aGUgc2FtZSBNYXBNYW5hZ2VyIG5hbWUgaGFwcGVuIGNvbmN1cnJlbnRseVxuICAjIG9ubHkgb25lIHdpbGwgQWRkTmFtZSBvcGVyYXRpb24gd2lsbCBiZSBleGVjdXRlZC5cbiAgI1xuICBjbGFzcyBBZGROYW1lIGV4dGVuZHMgdHlwZXMuT3BlcmF0aW9uXG5cbiAgICAjXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gbWFwX21hbmFnZXIgVWlkIG9yIHJlZmVyZW5jZSB0byB0aGUgTWFwTWFuYWdlci5cbiAgICAjIEBwYXJhbSB7U3RyaW5nfSBuYW1lIE5hbWUgb2YgdGhlIHByb3BlcnR5IHRoYXQgd2lsbCBiZSBhZGRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIG1hcF9tYW5hZ2VyLCBAbmFtZSktPlxuICAgICAgQHNhdmVPcGVyYXRpb24gJ21hcF9tYW5hZ2VyJywgbWFwX21hbmFnZXJcbiAgICAgIHN1cGVyIHVpZFxuXG4gICAgI1xuICAgICMgSWYgbWFwX21hbmFnZXIgZG9lc24ndCBoYXZlIHRoZSBwcm9wZXJ0eSBuYW1lLCB0aGVuIGFkZCBpdC5cbiAgICAjIFRoZSBSZXBsYWNlTWFuYWdlciB0aGF0IGlzIGJlaW5nIHdyaXR0ZW4gb24gdGhlIHByb3BlcnR5IGlzIHVuaXF1ZVxuICAgICMgaW4gc3VjaCBhIHdheSB0aGF0IGlmIEFkZE5hbWUgaXMgZXhlY3V0ZWQgKGZyb20gYW5vdGhlciBwZWVyKSBpdCB3aWxsXG4gICAgIyBhbHdheXMgaGF2ZSB0aGUgc2FtZSByZXN1bHQgKFJlcGxhY2VNYW5hZ2VyLCBhbmQgaXRzIGJlZ2lubmluZyBhbmQgZW5kIGFyZSB0aGUgc2FtZSlcbiAgICAjXG4gICAgZXhlY3V0ZTogKCktPlxuICAgICAgaWYgbm90IEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9ucygpXG4gICAgICAgIHJldHVybiBmYWxzZVxuICAgICAgZWxzZVxuICAgICAgICB1aWRfciA9IEBtYXBfbWFuYWdlci5nZXRVaWQoKVxuICAgICAgICB1aWRfci5vcF9udW1iZXIgPSBcIl8je3VpZF9yLm9wX251bWJlcn1fUk1fI3tAbmFtZX1cIlxuICAgICAgICBpZiBub3QgSEIuZ2V0T3BlcmF0aW9uKHVpZF9yKT9cbiAgICAgICAgICB1aWRfYmVnID0gQG1hcF9tYW5hZ2VyLmdldFVpZCgpXG4gICAgICAgICAgdWlkX2JlZy5vcF9udW1iZXIgPSBcIl8je3VpZF9iZWcub3BfbnVtYmVyfV9STV8je0BuYW1lfV9iZWdpbm5pbmdcIlxuICAgICAgICAgIHVpZF9lbmQgPSBAbWFwX21hbmFnZXIuZ2V0VWlkKClcbiAgICAgICAgICB1aWRfZW5kLm9wX251bWJlciA9IFwiXyN7dWlkX2VuZC5vcF9udW1iZXJ9X1JNXyN7QG5hbWV9X2VuZFwiXG4gICAgICAgICAgYmVnID0gSEIuYWRkT3BlcmF0aW9uKG5ldyB0eXBlcy5EZWxpbWl0ZXIgdWlkX2JlZywgdW5kZWZpbmVkLCB1aWRfZW5kKS5leGVjdXRlKClcbiAgICAgICAgICBlbmQgPSBIQi5hZGRPcGVyYXRpb24obmV3IHR5cGVzLkRlbGltaXRlciB1aWRfZW5kLCBiZWcsIHVuZGVmaW5lZCkuZXhlY3V0ZSgpXG4gICAgICAgICAgI2JlZy5leGVjdXRlKClcbiAgICAgICAgICBAbWFwX21hbmFnZXIubWFwW0BuYW1lXSA9IEhCLmFkZE9wZXJhdGlvbihuZXcgUmVwbGFjZU1hbmFnZXIgdW5kZWZpbmVkLCB1aWRfciwgYmVnLCBlbmQpLmV4ZWN1dGUoKVxuICAgICAgICBzdXBlclxuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAge1xuICAgICAgICAndHlwZScgOiBcIkFkZE5hbWVcIlxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAnbWFwX21hbmFnZXInIDogQG1hcF9tYW5hZ2VyLmdldFVpZCgpXG4gICAgICAgICduYW1lJyA6IEBuYW1lXG4gICAgICB9XG5cbiAgcGFyc2VyWydBZGROYW1lJ10gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdtYXBfbWFuYWdlcicgOiBtYXBfbWFuYWdlclxuICAgICAgJ3VpZCcgOiB1aWRcbiAgICAgICduYW1lJyA6IG5hbWVcbiAgICB9ID0ganNvblxuICAgIG5ldyBBZGROYW1lIHVpZCwgbWFwX21hbmFnZXIsIG5hbWVcblxuICAjXG4gICMgTWFuYWdlcyBhIGxpc3Qgb2YgSW5zZXJ0LXR5cGUgb3BlcmF0aW9ucy5cbiAgI1xuICBjbGFzcyBMaXN0TWFuYWdlciBleHRlbmRzIHR5cGVzLkluc2VydFxuXG4gICAgI1xuICAgICMgQSBMaXN0TWFuYWdlciBtYWludGFpbnMgYSBub24tZW1wdHkgbGlzdCB0aGF0IGhhcyBhIGJlZ2lubmluZyBhbmQgYW4gZW5kIChib3RoIERlbGltaXRlcnMhKVxuICAgICMgQHBhcmFtIHtPYmplY3R9IHVpZCBBIHVuaXF1ZSBpZGVudGlmaWVyLiBJZiB1aWQgaXMgdW5kZWZpbmVkLCBhIG5ldyB1aWQgd2lsbCBiZSBjcmVhdGVkLlxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGJlZ2lubmluZyBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxuICAgICMgQHBhcmFtIHtEZWxpbWl0ZXJ9IGVuZCBSZWZlcmVuY2Ugb3IgT2JqZWN0LlxuICAgIGNvbnN0cnVjdG9yOiAodWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBpZiBiZWdpbm5pbmc/IGFuZCBlbmQ/XG4gICAgICAgIEBzYXZlT3BlcmF0aW9uICdiZWdpbm5pbmcnLCBiZWdpbm5pbmdcbiAgICAgICAgQHNhdmVPcGVyYXRpb24gJ2VuZCcsIGVuZFxuICAgICAgZWxzZVxuICAgICAgICBAYmVnaW5uaW5nID0gSEIuYWRkT3BlcmF0aW9uIG5ldyB0eXBlcy5EZWxpbWl0ZXIgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZFxuICAgICAgICBAZW5kID0gICAgICAgSEIuYWRkT3BlcmF0aW9uIG5ldyB0eXBlcy5EZWxpbWl0ZXIgdW5kZWZpbmVkLCBAYmVnaW5uaW5nLCB1bmRlZmluZWRcbiAgICAgICAgQGJlZ2lubmluZy5uZXh0X2NsID0gQGVuZFxuICAgICAgICBAYmVnaW5uaW5nLmV4ZWN1dGUoKVxuICAgICAgICBAZW5kLmV4ZWN1dGUoKVxuICAgICAgc3VwZXIgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuXG4gICAgIyBHZXQgdGhlIGVsZW1lbnQgcHJldmlvdXMgdG8gdGhlIGRlbGVtaXRlciBhdCB0aGUgZW5kXG4gICAgZ2V0TGFzdE9wZXJhdGlvbjogKCktPlxuICAgICAgQGVuZC5wcmV2X2NsXG5cbiAgICAjIHNpbWlsYXIgdG8gdGhlIGFib3ZlXG4gICAgZ2V0Rmlyc3RPcGVyYXRpb246ICgpLT5cbiAgICAgIEBiZWdpbm5pbmcubmV4dF9jbFxuXG4gICAgIyBUcmFuc2Zvcm1zIHRoZSB0aGUgbGlzdCB0byBhbiBhcnJheVxuICAgICMgRG9lc24ndCByZXR1cm4gbGVmdC1yaWdodCBkZWxpbWl0ZXIuXG4gICAgdG9BcnJheTogKCktPlxuICAgICAgbyA9IEBiZWdpbm5pbmcubmV4dF9jbFxuICAgICAgcmVzdWx0ID0gW11cbiAgICAgIHdoaWxlIG8gaXNudCBAZW5kXG4gICAgICAgIHJlc3VsdC5wdXNoIG9cbiAgICAgICAgbyA9IG8ubmV4dF9jbFxuICAgICAgcmVzdWx0XG5cbiAgICAjXG4gICAgIyBSZXRyaWV2ZXMgdGhlIHgtdGggbm90IGRlbGV0ZWQgZWxlbWVudC5cbiAgICAjXG4gICAgZ2V0T3BlcmF0aW9uQnlQb3NpdGlvbjogKHBvc2l0aW9uKS0+XG4gICAgICBvID0gQGJlZ2lubmluZy5uZXh0X2NsXG4gICAgICBpZiBwb3NpdGlvbiA+IDBcbiAgICAgICAgd2hpbGUgdHJ1ZVxuICAgICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgICBpZiBub3Qgby5pc0RlbGV0ZWQoKVxuICAgICAgICAgICAgcG9zaXRpb24gLT0gMVxuICAgICAgICAgIGlmIHBvc2l0aW9uIGlzIDBcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgaWYgbyBpbnN0YW5jZW9mIHR5cGVzLkRlbGltaXRlclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwicG9zaXRpb24gcGFyYW1ldGVyIGV4Y2VlZGVkIHRoZSBsZW5ndGggb2YgdGhlIGRvY3VtZW50IVwiXG4gICAgICBvXG5cbiAgI1xuICAjIEFkZHMgc3VwcG9ydCBmb3IgcmVwbGFjZS4gVGhlIFJlcGxhY2VNYW5hZ2VyIG1hbmFnZXMgUmVwbGFjZWFibGUgb3BlcmF0aW9ucy5cbiAgIyBFYWNoIFJlcGxhY2VhYmxlIGhvbGRzIGEgdmFsdWUgdGhhdCBpcyBub3cgcmVwbGFjZWFibGUuXG4gICNcbiAgIyBUaGUgV29yZC10eXBlIGhhcyBpbXBsZW1lbnRlZCBzdXBwb3J0IGZvciByZXBsYWNlXG4gICMgQHNlZSBXb3JkXG4gICNcbiAgY2xhc3MgUmVwbGFjZU1hbmFnZXIgZXh0ZW5kcyBMaXN0TWFuYWdlclxuICAgICNcbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBpbml0aWFsX2NvbnRlbnQgSW5pdGlhbGl6ZSB0aGlzIHdpdGggYSBSZXBsYWNlYWJsZSB0aGF0IGhvbGRzIHRoZSBpbml0aWFsX2NvbnRlbnQuXG4gICAgIyBAcGFyYW0ge09iamVjdH0gdWlkIEEgdW5pcXVlIGlkZW50aWZpZXIuIElmIHVpZCBpcyB1bmRlZmluZWQsIGEgbmV3IHVpZCB3aWxsIGJlIGNyZWF0ZWQuXG4gICAgIyBAcGFyYW0ge0RlbGltaXRlcn0gYmVnaW5uaW5nIFJlZmVyZW5jZSBvciBPYmplY3QuXG4gICAgIyBAcGFyYW0ge0RlbGltaXRlcn0gZW5kIFJlZmVyZW5jZSBvciBPYmplY3QuXG4gICAgY29uc3RydWN0b3I6IChpbml0aWFsX2NvbnRlbnQsIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpbiktPlxuICAgICAgc3VwZXIgdWlkLCBiZWdpbm5pbmcsIGVuZCwgcHJldiwgbmV4dCwgb3JpZ2luXG4gICAgICBpZiBpbml0aWFsX2NvbnRlbnQ/XG4gICAgICAgIEByZXBsYWNlIGluaXRpYWxfY29udGVudFxuXG4gICAgI1xuICAgICMgUmVwbGFjZSB0aGUgZXhpc3Rpbmcgd29yZCB3aXRoIGEgbmV3IHdvcmQuXG4gICAgI1xuICAgIHJlcGxhY2U6IChjb250ZW50KS0+XG4gICAgICBvID0gQGdldExhc3RPcGVyYXRpb24oKVxuICAgICAgb3AgPSBuZXcgUmVwbGFjZWFibGUgY29udGVudCwgQCwgdW5kZWZpbmVkLCBvLCBvLm5leHRfY2xcbiAgICAgIEhCLmFkZE9wZXJhdGlvbihvcCkuZXhlY3V0ZSgpXG5cbiAgICAjXG4gICAgIyBHZXQgdGhlIHZhbHVlIG9mIHRoaXMgV29yZFxuICAgICMgQHJldHVybiB7U3RyaW5nfVxuICAgICNcbiAgICB2YWw6ICgpLT5cbiAgICAgIG8gPSBAZ2V0TGFzdE9wZXJhdGlvbigpXG4gICAgICBpZiBvIGluc3RhbmNlb2YgdHlwZXMuRGVsaW1pdGVyXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcImR0cm5cIlxuICAgICAgby52YWwoKVxuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9XG4gICAgICAgIHtcbiAgICAgICAgICAndHlwZSc6IFwiUmVwbGFjZU1hbmFnZXJcIlxuICAgICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICAgJ2JlZ2lubmluZycgOiBAYmVnaW5uaW5nLmdldFVpZCgpXG4gICAgICAgICAgJ2VuZCcgOiBAZW5kLmdldFVpZCgpXG4gICAgICAgIH1cbiAgICAgIGlmIEBwcmV2X2NsPyBhbmQgQG5leHRfY2w/XG4gICAgICAgIGpzb25bJ3ByZXYnXSA9IEBwcmV2X2NsLmdldFVpZCgpXG4gICAgICAgIGpzb25bJ25leHQnXSA9IEBuZXh0X2NsLmdldFVpZCgpXG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyW1wiUmVwbGFjZU1hbmFnZXJcIl0gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICAgICdiZWdpbm5pbmcnIDogYmVnaW5uaW5nXG4gICAgICAnZW5kJyA6IGVuZFxuICAgIH0gPSBqc29uXG4gICAgbmV3IFJlcGxhY2VNYW5hZ2VyIGNvbnRlbnQsIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpblxuXG5cbiAgI1xuICAjIFRoZSBSZXBsYWNlTWFuYWdlciBtYW5hZ2VzIFJlcGxhY2VhYmxlcy5cbiAgIyBAc2VlIFJlcGxhY2VNYW5hZ2VyXG4gICNcbiAgY2xhc3MgUmVwbGFjZWFibGUgZXh0ZW5kcyB0eXBlcy5JbnNlcnRcblxuICAgICNcbiAgICAjIEBwYXJhbSB7T3BlcmF0aW9ufSBjb250ZW50IFRoZSB2YWx1ZSB0aGF0IHRoaXMgUmVwbGFjZWFibGUgaG9sZHMuXG4gICAgIyBAcGFyYW0ge1JlcGxhY2VNYW5hZ2VyfSBwYXJlbnQgVXNlZCB0byByZXBsYWNlIHRoaXMgUmVwbGFjZWFibGUgd2l0aCBhbm90aGVyIG9uZS5cbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6IChjb250ZW50LCBwYXJlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAnY29udGVudCcsIGNvbnRlbnRcbiAgICAgIEBzYXZlT3BlcmF0aW9uICdwYXJlbnQnLCBwYXJlbnRcbiAgICAgIGlmIG5vdCAocHJldj8gYW5kIG5leHQ/IGFuZCBjb250ZW50PylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yIFwiWW91IG11c3QgZGVmaW5lIGNvbnRlbnQsIHByZXYsIGFuZCBuZXh0IGZvciBSZXBsYWNlYWJsZS10eXBlcyFcIlxuICAgICAgc3VwZXIgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW5cblxuICAgICNcbiAgICAjIFJldHVybiB0aGUgY29udGVudCB0aGF0IHRoaXMgb3BlcmF0aW9uIGhvbGRzLlxuICAgICNcbiAgICB2YWw6ICgpLT5cbiAgICAgIEBjb250ZW50XG5cbiAgICAjXG4gICAgIyBSZXBsYWNlIHRoZSBjb250ZW50IG9mIHRoaXMgcmVwbGFjZWFibGUgd2l0aCBuZXcgY29udGVudC5cbiAgICAjXG4gICAgcmVwbGFjZTogKGNvbnRlbnQpLT5cbiAgICAgIEBwYXJlbnQucmVwbGFjZSBjb250ZW50XG5cbiAgICAjXG4gICAgIyBJZiBwb3NzaWJsZSBzZXQgdGhlIHJlcGxhY2UgbWFuYWdlciBpbiB0aGUgY29udGVudC5cbiAgICAjIEBzZWUgV29yZC5zZXRSZXBsYWNlTWFuYWdlclxuICAgICNcbiAgICBleGVjdXRlOiAoKS0+XG4gICAgICBpZiBub3QgQHZhbGlkYXRlU2F2ZWRPcGVyYXRpb25zKClcbiAgICAgICAgcmV0dXJuIGZhbHNlXG4gICAgICBlbHNlXG4gICAgICAgIEBjb250ZW50LnNldFJlcGxhY2VNYW5hZ2VyPyhAcGFyZW50KVxuICAgICAgICBzdXBlclxuICAgICAgICBAXG5cbiAgICAjXG4gICAgIyBFbmNvZGUgdGhpcyBvcGVyYXRpb24gaW4gc3VjaCBhIHdheSB0aGF0IGl0IGNhbiBiZSBwYXJzZWQgYnkgcmVtb3RlIHBlZXJzLlxuICAgICNcbiAgICBfZW5jb2RlOiAoKS0+XG4gICAgICBqc29uID1cbiAgICAgICAge1xuICAgICAgICAgICd0eXBlJzogXCJSZXBsYWNlYWJsZVwiXG4gICAgICAgICAgJ2NvbnRlbnQnOiBAY29udGVudC5nZXRVaWQoKVxuICAgICAgICAgICdSZXBsYWNlTWFuYWdlcicgOiBAcGFyZW50LmdldFVpZCgpXG4gICAgICAgICAgJ3ByZXYnOiBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICAgICduZXh0JzogQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICB9XG4gICAgICBpZiBAb3JpZ2luPyBhbmQgQG9yaWdpbiBpc250IEBwcmV2X2NsXG4gICAgICAgIGpzb25bXCJvcmlnaW5cIl0gPSBAb3JpZ2luLmdldFVpZCgpXG4gICAgICBqc29uXG5cbiAgcGFyc2VyW1wiUmVwbGFjZWFibGVcIl0gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICdSZXBsYWNlTWFuYWdlcicgOiBwYXJlbnRcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBSZXBsYWNlYWJsZSBjb250ZW50LCBwYXJlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cblxuXG4gIHR5cGVzWydMaXN0TWFuYWdlciddID0gTGlzdE1hbmFnZXJcbiAgdHlwZXNbJ01hcE1hbmFnZXInXSA9IE1hcE1hbmFnZXJcbiAgdHlwZXNbJ1JlcGxhY2VNYW5hZ2VyJ10gPSBSZXBsYWNlTWFuYWdlclxuICB0eXBlc1snUmVwbGFjZWFibGUnXSA9IFJlcGxhY2VhYmxlXG5cbiAgYmFzaWNfdHlwZXNcblxuXG5cblxuXG5cbiIsInN0cnVjdHVyZWRfdHlwZXNfdW5pbml0aWFsaXplZCA9IHJlcXVpcmUgXCIuL1N0cnVjdHVyZWRUeXBlc1wiXG5cbm1vZHVsZS5leHBvcnRzID0gKEhCKS0+XG4gIHN0cnVjdHVyZWRfdHlwZXMgPSBzdHJ1Y3R1cmVkX3R5cGVzX3VuaW5pdGlhbGl6ZWQgSEJcbiAgdHlwZXMgPSBzdHJ1Y3R1cmVkX3R5cGVzLnR5cGVzXG4gIHBhcnNlciA9IHN0cnVjdHVyZWRfdHlwZXMucGFyc2VyXG5cbiAgI1xuICAjIEF0IHRoZSBtb21lbnQgVGV4dERlbGV0ZSB0eXBlIGVxdWFscyB0aGUgRGVsZXRlIHR5cGUgaW4gQmFzaWNUeXBlcy5cbiAgIyBAc2VlIEJhc2ljVHlwZXMuRGVsZXRlXG4gICNcbiAgY2xhc3MgVGV4dERlbGV0ZSBleHRlbmRzIHR5cGVzLkRlbGV0ZVxuICBwYXJzZXJbXCJUZXh0RGVsZXRlXCJdID0gcGFyc2VyW1wiRGVsZXRlXCJdXG5cbiAgI1xuICAjICBFeHRlbmRzIHRoZSBiYXNpYyBJbnNlcnQgdHlwZSB0byBhbiBvcGVyYXRpb24gdGhhdCBob2xkcyBhIHRleHQgdmFsdWVcbiAgI1xuICBjbGFzcyBUZXh0SW5zZXJ0IGV4dGVuZHMgdHlwZXMuSW5zZXJ0XG4gICAgI1xuICAgICMgQHBhcmFtIHtTdHJpbmd9IGNvbnRlbnQgVGhlIGNvbnRlbnQgb2YgdGhpcyBJbnNlcnQtdHlwZSBPcGVyYXRpb24uIFVzdWFsbHkgeW91IHJlc3RyaWN0IHRoZSBsZW5ndGggb2YgY29udGVudCB0byBzaXplIDFcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6IChAY29udGVudCwgdWlkLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIGlmIG5vdCAocHJldj8gYW5kIG5leHQ/KVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IgXCJZb3UgbXVzdCBkZWZpbmUgcHJldiwgYW5kIG5leHQgZm9yIFRleHRJbnNlcnQtdHlwZXMhXCJcbiAgICAgIHN1cGVyIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG4gICAgI1xuICAgICMgUmV0cmlldmUgdGhlIGVmZmVjdGl2ZSBsZW5ndGggb2YgdGhlICRjb250ZW50IG9mIHRoaXMgb3BlcmF0aW9uLlxuICAgICNcbiAgICBnZXRMZW5ndGg6ICgpLT5cbiAgICAgIGlmIEBpc0RlbGV0ZWQoKVxuICAgICAgICAwXG4gICAgICBlbHNlXG4gICAgICAgIEBjb250ZW50Lmxlbmd0aFxuXG4gICAgI1xuICAgICMgVGhlIHJlc3VsdCB3aWxsIGJlIGNvbmNhdGVuYXRlZCB3aXRoIHRoZSByZXN1bHRzIGZyb20gdGhlIG90aGVyIGluc2VydCBvcGVyYXRpb25zXG4gICAgIyBpbiBvcmRlciB0byByZXRyaWV2ZSB0aGUgY29udGVudCBvZiB0aGUgZW5naW5lLlxuICAgICMgQHNlZSBIaXN0b3J5QnVmZmVyLnRvRXhlY3V0ZWRBcnJheVxuICAgICNcbiAgICB2YWw6IChjdXJyZW50X3Bvc2l0aW9uKS0+XG4gICAgICBpZiBAaXNEZWxldGVkKClcbiAgICAgICAgXCJcIlxuICAgICAgZWxzZVxuICAgICAgICBAY29udGVudFxuXG4gICAgI1xuICAgICMgQ29udmVydCBhbGwgcmVsZXZhbnQgaW5mb3JtYXRpb24gb2YgdGhpcyBvcGVyYXRpb24gdG8gdGhlIGpzb24tZm9ybWF0LlxuICAgICMgVGhpcyByZXN1bHQgY2FuIGJlIHNlbmQgdG8gb3RoZXIgY2xpZW50cy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9XG4gICAgICAgIHtcbiAgICAgICAgICAndHlwZSc6IFwiVGV4dEluc2VydFwiXG4gICAgICAgICAgJ2NvbnRlbnQnOiBAY29udGVudFxuICAgICAgICAgICd1aWQnIDogQGdldFVpZCgpXG4gICAgICAgICAgJ3ByZXYnOiBAcHJldl9jbC5nZXRVaWQoKVxuICAgICAgICAgICduZXh0JzogQG5leHRfY2wuZ2V0VWlkKClcbiAgICAgICAgfVxuICAgICAgaWYgQG9yaWdpbj8gYW5kIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uW1wib3JpZ2luXCJdID0gQG9yaWdpbi5nZXRVaWQoKVxuICAgICAganNvblxuXG4gIHBhcnNlcltcIlRleHRJbnNlcnRcIl0gPSAoanNvbiktPlxuICAgIHtcbiAgICAgICdjb250ZW50JyA6IGNvbnRlbnRcbiAgICAgICd1aWQnIDogdWlkXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBUZXh0SW5zZXJ0IGNvbnRlbnQsIHVpZCwgcHJldiwgbmV4dCwgb3JpZ2luXG5cbiAgI1xuICAjIEhhbmRsZXMgYSBUZXh0LWxpa2UgZGF0YSBzdHJ1Y3R1cmVzIHdpdGggc3VwcG9ydCBmb3IgaW5zZXJ0VGV4dC9kZWxldGVUZXh0IGF0IGEgd29yZC1wb3NpdGlvbi5cbiAgI1xuICBjbGFzcyBXb3JkIGV4dGVuZHMgdHlwZXMuTGlzdE1hbmFnZXJcblxuICAgICNcbiAgICAjIEBwYXJhbSB7T2JqZWN0fSB1aWQgQSB1bmlxdWUgaWRlbnRpZmllci4gSWYgdWlkIGlzIHVuZGVmaW5lZCwgYSBuZXcgdWlkIHdpbGwgYmUgY3JlYXRlZC5cbiAgICAjXG4gICAgY29uc3RydWN0b3I6ICh1aWQsIGJlZ2lubmluZywgZW5kLCBwcmV2LCBuZXh0LCBvcmlnaW4pLT5cbiAgICAgIHN1cGVyIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gICAgI1xuICAgICMgSW5zZXJ0cyBhIHN0cmluZyBpbnRvIHRoZSB3b3JkXG4gICAgI1xuICAgIGluc2VydFRleHQ6IChwb3NpdGlvbiwgY29udGVudCktPlxuICAgICAgbyA9IEBnZXRPcGVyYXRpb25CeVBvc2l0aW9uIHBvc2l0aW9uXG4gICAgICBmb3IgYyBpbiBjb250ZW50XG4gICAgICAgIG9wID0gbmV3IFRleHRJbnNlcnQgYywgdW5kZWZpbmVkLCBvLnByZXZfY2wsIG9cbiAgICAgICAgSEIuYWRkT3BlcmF0aW9uKG9wKS5leGVjdXRlKClcblxuICAgICNcbiAgICAjIERlbGV0ZXMgYSBwYXJ0IG9mIHRoZSB3b3JkLlxuICAgICNcbiAgICBkZWxldGVUZXh0OiAocG9zaXRpb24sIGxlbmd0aCktPlxuICAgICAgbyA9IEBnZXRPcGVyYXRpb25CeVBvc2l0aW9uIHBvc2l0aW9uXG5cbiAgICAgIGZvciBpIGluIFswLi4ubGVuZ3RoXVxuICAgICAgICBkID0gSEIuYWRkT3BlcmF0aW9uKG5ldyBUZXh0RGVsZXRlIHVuZGVmaW5lZCwgbykuZXhlY3V0ZSgpXG4gICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgd2hpbGUgby5pc0RlbGV0ZWQoKVxuICAgICAgICAgIGlmIG8gaW5zdGFuY2VvZiB0eXBlcy5EZWxpbWl0ZXJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvciBcIllvdSBjYW4ndCBkZWxldGUgbW9yZSB0aGFuIHRoZXJlIGlzLi5cIlxuICAgICAgICAgIG8gPSBvLm5leHRfY2xcbiAgICAgICAgZC5fZW5jb2RlKClcblxuICAgICNcbiAgICAjIFJlcGxhY2UgdGhlIGNvbnRlbnQgb2YgdGhpcyB3b3JkIHdpdGggYW5vdGhlciBvbmUuIENvbmN1cnJlbnQgcmVwbGFjZW1lbnRzIGFyZSBub3QgbWVyZ2VkIVxuICAgICMgT25seSBvbmUgb2YgdGhlIHJlcGxhY2VtZW50cyB3aWxsIGJlIHVzZWQuXG4gICAgI1xuICAgICMgQ2FuIG9ubHkgYmUgdXNlZCBpZiB0aGUgUmVwbGFjZU1hbmFnZXIgd2FzIHNldCFcbiAgICAjIEBzZWUgV29yZC5zZXRSZXBsYWNlTWFuYWdlclxuICAgICNcbiAgICByZXBsYWNlVGV4dDogKHRleHQpLT5cbiAgICAgIGlmIEByZXBsYWNlX21hbmFnZXI/XG4gICAgICAgIHdvcmQgPSBIQi5hZGRPcGVyYXRpb24obmV3IFdvcmQgdW5kZWZpbmVkKS5leGVjdXRlKClcbiAgICAgICAgd29yZC5pbnNlcnRUZXh0IDAsIHRleHRcbiAgICAgICAgQHJlcGxhY2VfbWFuYWdlci5yZXBsYWNlKHdvcmQpXG4gICAgICBlbHNlXG4gICAgICAgIHRocm93IG5ldyBFcnJvciBcIlRoaXMgdHlwZSBpcyBjdXJyZW50bHkgbm90IG1haW50YWluZWQgYnkgYSBSZXBsYWNlTWFuYWdlciFcIlxuXG4gICAgI1xuICAgICMgQHJldHVybnMgW0pzb25dIEEgSnNvbiBvYmplY3QuXG4gICAgI1xuICAgIHZhbDogKCktPlxuICAgICAgYyA9IGZvciBvIGluIEB0b0FycmF5KClcbiAgICAgICAgaWYgby52YWw/XG4gICAgICAgICAgby52YWwoKVxuICAgICAgICBlbHNlXG4gICAgICAgICAgXCJcIlxuICAgICAgYy5qb2luKCcnKVxuXG4gICAgI1xuICAgICMgSW4gbW9zdCBjYXNlcyB5b3Ugd291bGQgZW1iZWQgYSBXb3JkIGluIGEgUmVwbGFjZWFibGUsIHdpY2ggaXMgaGFuZGxlZCBieSB0aGUgUmVwbGFjZU1hbmFnZXIgaW4gb3JkZXJcbiAgICAjIHRvIHByb3ZpZGUgcmVwbGFjZSBmdW5jdGlvbmFsaXR5LlxuICAgICNcbiAgICBzZXRSZXBsYWNlTWFuYWdlcjogKG9wKS0+XG4gICAgICBAc2F2ZU9wZXJhdGlvbiAncmVwbGFjZV9tYW5hZ2VyJywgb3BcbiAgICAgIEB2YWxpZGF0ZVNhdmVkT3BlcmF0aW9uc1xuXG4gICAgI1xuICAgICMgRW5jb2RlIHRoaXMgb3BlcmF0aW9uIGluIHN1Y2ggYSB3YXkgdGhhdCBpdCBjYW4gYmUgcGFyc2VkIGJ5IHJlbW90ZSBwZWVycy5cbiAgICAjXG4gICAgX2VuY29kZTogKCktPlxuICAgICAganNvbiA9IHtcbiAgICAgICAgJ3R5cGUnOiBcIldvcmRcIlxuICAgICAgICAndWlkJyA6IEBnZXRVaWQoKVxuICAgICAgICAnYmVnaW5uaW5nJyA6IEBiZWdpbm5pbmcuZ2V0VWlkKClcbiAgICAgICAgJ2VuZCcgOiBAZW5kLmdldFVpZCgpXG4gICAgICB9XG4gICAgICBpZiBAcHJldl9jbD9cbiAgICAgICAganNvblsncHJldiddID0gQHByZXZfY2wuZ2V0VWlkKClcbiAgICAgIGlmIEBuZXh0X2NsP1xuICAgICAgICBqc29uWyduZXh0J10gPSBAbmV4dF9jbC5nZXRVaWQoKVxuICAgICAgaWYgQG9yaWdpbj8gYW5kIEBvcmlnaW4gaXNudCBAcHJldl9jbFxuICAgICAgICBqc29uW1wib3JpZ2luXCJdID0gQG9yaWdpbi5nZXRVaWQoKVxuICAgICAganNvblxuXG4gIHBhcnNlclsnV29yZCddID0gKGpzb24pLT5cbiAgICB7XG4gICAgICAndWlkJyA6IHVpZFxuICAgICAgJ2JlZ2lubmluZycgOiBiZWdpbm5pbmdcbiAgICAgICdlbmQnIDogZW5kXG4gICAgICAncHJldic6IHByZXZcbiAgICAgICduZXh0JzogbmV4dFxuICAgICAgJ29yaWdpbicgOiBvcmlnaW5cbiAgICB9ID0ganNvblxuICAgIG5ldyBXb3JkIHVpZCwgYmVnaW5uaW5nLCBlbmQsIHByZXYsIG5leHQsIG9yaWdpblxuXG4gIHR5cGVzWydUZXh0SW5zZXJ0J10gPSBUZXh0SW5zZXJ0XG4gIHR5cGVzWydUZXh0RGVsZXRlJ10gPSBUZXh0RGVsZXRlXG4gIHR5cGVzWydXb3JkJ10gPSBXb3JkXG4gIHN0cnVjdHVyZWRfdHlwZXNcblxuXG4iLCJcbmV4cG9ydHNbJ0l3Y0Nvbm5lY3RvciddID1cbiAgcmVxdWlyZSAnLi9Db25uZWN0b3JzL0l3Y0Nvbm5lY3RvcidcbmV4cG9ydHNbJ1Rlc3RDb25uZWN0b3InXSA9XG4gIHJlcXVpcmUgJy4vQ29ubmVjdG9ycy9UZXN0Q29ubmVjdG9yJ1xuZXhwb3J0c1snSnNvbllhdHRhJ10gPVxuICByZXF1aXJlICcuL0ZyYW1ld29ya3MvSnNvbllhdHRhJ1xuZXhwb3J0c1snVGV4dFlhdHRhJ10gPVxuICByZXF1aXJlICcuL0ZyYW1ld29ya3MvVGV4dFlhdHRhJ1xuXG4iLCIvLyAgICAgVW5kZXJzY29yZS5qcyAxLjYuMFxuLy8gICAgIGh0dHA6Ly91bmRlcnNjb3JlanMub3JnXG4vLyAgICAgKGMpIDIwMDktMjAxNCBKZXJlbXkgQXNoa2VuYXMsIERvY3VtZW50Q2xvdWQgYW5kIEludmVzdGlnYXRpdmUgUmVwb3J0ZXJzICYgRWRpdG9yc1xuLy8gICAgIFVuZGVyc2NvcmUgbWF5IGJlIGZyZWVseSBkaXN0cmlidXRlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UuXG5cbihmdW5jdGlvbigpIHtcblxuICAvLyBCYXNlbGluZSBzZXR1cFxuICAvLyAtLS0tLS0tLS0tLS0tLVxuXG4gIC8vIEVzdGFibGlzaCB0aGUgcm9vdCBvYmplY3QsIGB3aW5kb3dgIGluIHRoZSBicm93c2VyLCBvciBgZXhwb3J0c2Agb24gdGhlIHNlcnZlci5cbiAgdmFyIHJvb3QgPSB0aGlzO1xuXG4gIC8vIFNhdmUgdGhlIHByZXZpb3VzIHZhbHVlIG9mIHRoZSBgX2AgdmFyaWFibGUuXG4gIHZhciBwcmV2aW91c1VuZGVyc2NvcmUgPSByb290Ll87XG5cbiAgLy8gRXN0YWJsaXNoIHRoZSBvYmplY3QgdGhhdCBnZXRzIHJldHVybmVkIHRvIGJyZWFrIG91dCBvZiBhIGxvb3AgaXRlcmF0aW9uLlxuICB2YXIgYnJlYWtlciA9IHt9O1xuXG4gIC8vIFNhdmUgYnl0ZXMgaW4gdGhlIG1pbmlmaWVkIChidXQgbm90IGd6aXBwZWQpIHZlcnNpb246XG4gIHZhciBBcnJheVByb3RvID0gQXJyYXkucHJvdG90eXBlLCBPYmpQcm90byA9IE9iamVjdC5wcm90b3R5cGUsIEZ1bmNQcm90byA9IEZ1bmN0aW9uLnByb3RvdHlwZTtcblxuICAvLyBDcmVhdGUgcXVpY2sgcmVmZXJlbmNlIHZhcmlhYmxlcyBmb3Igc3BlZWQgYWNjZXNzIHRvIGNvcmUgcHJvdG90eXBlcy5cbiAgdmFyXG4gICAgcHVzaCAgICAgICAgICAgICA9IEFycmF5UHJvdG8ucHVzaCxcbiAgICBzbGljZSAgICAgICAgICAgID0gQXJyYXlQcm90by5zbGljZSxcbiAgICBjb25jYXQgICAgICAgICAgID0gQXJyYXlQcm90by5jb25jYXQsXG4gICAgdG9TdHJpbmcgICAgICAgICA9IE9ialByb3RvLnRvU3RyaW5nLFxuICAgIGhhc093blByb3BlcnR5ICAgPSBPYmpQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuICAvLyBBbGwgKipFQ01BU2NyaXB0IDUqKiBuYXRpdmUgZnVuY3Rpb24gaW1wbGVtZW50YXRpb25zIHRoYXQgd2UgaG9wZSB0byB1c2VcbiAgLy8gYXJlIGRlY2xhcmVkIGhlcmUuXG4gIHZhclxuICAgIG5hdGl2ZUZvckVhY2ggICAgICA9IEFycmF5UHJvdG8uZm9yRWFjaCxcbiAgICBuYXRpdmVNYXAgICAgICAgICAgPSBBcnJheVByb3RvLm1hcCxcbiAgICBuYXRpdmVSZWR1Y2UgICAgICAgPSBBcnJheVByb3RvLnJlZHVjZSxcbiAgICBuYXRpdmVSZWR1Y2VSaWdodCAgPSBBcnJheVByb3RvLnJlZHVjZVJpZ2h0LFxuICAgIG5hdGl2ZUZpbHRlciAgICAgICA9IEFycmF5UHJvdG8uZmlsdGVyLFxuICAgIG5hdGl2ZUV2ZXJ5ICAgICAgICA9IEFycmF5UHJvdG8uZXZlcnksXG4gICAgbmF0aXZlU29tZSAgICAgICAgID0gQXJyYXlQcm90by5zb21lLFxuICAgIG5hdGl2ZUluZGV4T2YgICAgICA9IEFycmF5UHJvdG8uaW5kZXhPZixcbiAgICBuYXRpdmVMYXN0SW5kZXhPZiAgPSBBcnJheVByb3RvLmxhc3RJbmRleE9mLFxuICAgIG5hdGl2ZUlzQXJyYXkgICAgICA9IEFycmF5LmlzQXJyYXksXG4gICAgbmF0aXZlS2V5cyAgICAgICAgID0gT2JqZWN0LmtleXMsXG4gICAgbmF0aXZlQmluZCAgICAgICAgID0gRnVuY1Byb3RvLmJpbmQ7XG5cbiAgLy8gQ3JlYXRlIGEgc2FmZSByZWZlcmVuY2UgdG8gdGhlIFVuZGVyc2NvcmUgb2JqZWN0IGZvciB1c2UgYmVsb3cuXG4gIHZhciBfID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYgKG9iaiBpbnN0YW5jZW9mIF8pIHJldHVybiBvYmo7XG4gICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIF8pKSByZXR1cm4gbmV3IF8ob2JqKTtcbiAgICB0aGlzLl93cmFwcGVkID0gb2JqO1xuICB9O1xuXG4gIC8vIEV4cG9ydCB0aGUgVW5kZXJzY29yZSBvYmplY3QgZm9yICoqTm9kZS5qcyoqLCB3aXRoXG4gIC8vIGJhY2t3YXJkcy1jb21wYXRpYmlsaXR5IGZvciB0aGUgb2xkIGByZXF1aXJlKClgIEFQSS4gSWYgd2UncmUgaW5cbiAgLy8gdGhlIGJyb3dzZXIsIGFkZCBgX2AgYXMgYSBnbG9iYWwgb2JqZWN0IHZpYSBhIHN0cmluZyBpZGVudGlmaWVyLFxuICAvLyBmb3IgQ2xvc3VyZSBDb21waWxlciBcImFkdmFuY2VkXCIgbW9kZS5cbiAgaWYgKHR5cGVvZiBleHBvcnRzICE9PSAndW5kZWZpbmVkJykge1xuICAgIGlmICh0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgICAgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gXztcbiAgICB9XG4gICAgZXhwb3J0cy5fID0gXztcbiAgfSBlbHNlIHtcbiAgICByb290Ll8gPSBfO1xuICB9XG5cbiAgLy8gQ3VycmVudCB2ZXJzaW9uLlxuICBfLlZFUlNJT04gPSAnMS42LjAnO1xuXG4gIC8vIENvbGxlY3Rpb24gRnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLy8gVGhlIGNvcm5lcnN0b25lLCBhbiBgZWFjaGAgaW1wbGVtZW50YXRpb24sIGFrYSBgZm9yRWFjaGAuXG4gIC8vIEhhbmRsZXMgb2JqZWN0cyB3aXRoIHRoZSBidWlsdC1pbiBgZm9yRWFjaGAsIGFycmF5cywgYW5kIHJhdyBvYmplY3RzLlxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgZm9yRWFjaGAgaWYgYXZhaWxhYmxlLlxuICB2YXIgZWFjaCA9IF8uZWFjaCA9IF8uZm9yRWFjaCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiBvYmo7XG4gICAgaWYgKG5hdGl2ZUZvckVhY2ggJiYgb2JqLmZvckVhY2ggPT09IG5hdGl2ZUZvckVhY2gpIHtcbiAgICAgIG9iai5mb3JFYWNoKGl0ZXJhdG9yLCBjb250ZXh0KTtcbiAgICB9IGVsc2UgaWYgKG9iai5sZW5ndGggPT09ICtvYmoubGVuZ3RoKSB7XG4gICAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gb2JqLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChpdGVyYXRvci5jYWxsKGNvbnRleHQsIG9ialtpXSwgaSwgb2JqKSA9PT0gYnJlYWtlcikgcmV0dXJuO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xuICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgb2JqW2tleXNbaV1dLCBrZXlzW2ldLCBvYmopID09PSBicmVha2VyKSByZXR1cm47XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBvYmo7XG4gIH07XG5cbiAgLy8gUmV0dXJuIHRoZSByZXN1bHRzIG9mIGFwcGx5aW5nIHRoZSBpdGVyYXRvciB0byBlYWNoIGVsZW1lbnQuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBtYXBgIGlmIGF2YWlsYWJsZS5cbiAgXy5tYXAgPSBfLmNvbGxlY3QgPSBmdW5jdGlvbihvYmosIGl0ZXJhdG9yLCBjb250ZXh0KSB7XG4gICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiByZXN1bHRzO1xuICAgIGlmIChuYXRpdmVNYXAgJiYgb2JqLm1hcCA9PT0gbmF0aXZlTWFwKSByZXR1cm4gb2JqLm1hcChpdGVyYXRvciwgY29udGV4dCk7XG4gICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgcmVzdWx0cy5wdXNoKGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KSk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH07XG5cbiAgdmFyIHJlZHVjZUVycm9yID0gJ1JlZHVjZSBvZiBlbXB0eSBhcnJheSB3aXRoIG5vIGluaXRpYWwgdmFsdWUnO1xuXG4gIC8vICoqUmVkdWNlKiogYnVpbGRzIHVwIGEgc2luZ2xlIHJlc3VsdCBmcm9tIGEgbGlzdCBvZiB2YWx1ZXMsIGFrYSBgaW5qZWN0YCxcbiAgLy8gb3IgYGZvbGRsYC4gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYHJlZHVjZWAgaWYgYXZhaWxhYmxlLlxuICBfLnJlZHVjZSA9IF8uZm9sZGwgPSBfLmluamVjdCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIG1lbW8sIGNvbnRleHQpIHtcbiAgICB2YXIgaW5pdGlhbCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyO1xuICAgIGlmIChvYmogPT0gbnVsbCkgb2JqID0gW107XG4gICAgaWYgKG5hdGl2ZVJlZHVjZSAmJiBvYmoucmVkdWNlID09PSBuYXRpdmVSZWR1Y2UpIHtcbiAgICAgIGlmIChjb250ZXh0KSBpdGVyYXRvciA9IF8uYmluZChpdGVyYXRvciwgY29udGV4dCk7XG4gICAgICByZXR1cm4gaW5pdGlhbCA/IG9iai5yZWR1Y2UoaXRlcmF0b3IsIG1lbW8pIDogb2JqLnJlZHVjZShpdGVyYXRvcik7XG4gICAgfVxuICAgIGVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwgaW5kZXgsIGxpc3QpIHtcbiAgICAgIGlmICghaW5pdGlhbCkge1xuICAgICAgICBtZW1vID0gdmFsdWU7XG4gICAgICAgIGluaXRpYWwgPSB0cnVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWVtbyA9IGl0ZXJhdG9yLmNhbGwoY29udGV4dCwgbWVtbywgdmFsdWUsIGluZGV4LCBsaXN0KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoIWluaXRpYWwpIHRocm93IG5ldyBUeXBlRXJyb3IocmVkdWNlRXJyb3IpO1xuICAgIHJldHVybiBtZW1vO1xuICB9O1xuXG4gIC8vIFRoZSByaWdodC1hc3NvY2lhdGl2ZSB2ZXJzaW9uIG9mIHJlZHVjZSwgYWxzbyBrbm93biBhcyBgZm9sZHJgLlxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgcmVkdWNlUmlnaHRgIGlmIGF2YWlsYWJsZS5cbiAgXy5yZWR1Y2VSaWdodCA9IF8uZm9sZHIgPSBmdW5jdGlvbihvYmosIGl0ZXJhdG9yLCBtZW1vLCBjb250ZXh0KSB7XG4gICAgdmFyIGluaXRpYWwgPSBhcmd1bWVudHMubGVuZ3RoID4gMjtcbiAgICBpZiAob2JqID09IG51bGwpIG9iaiA9IFtdO1xuICAgIGlmIChuYXRpdmVSZWR1Y2VSaWdodCAmJiBvYmoucmVkdWNlUmlnaHQgPT09IG5hdGl2ZVJlZHVjZVJpZ2h0KSB7XG4gICAgICBpZiAoY29udGV4dCkgaXRlcmF0b3IgPSBfLmJpbmQoaXRlcmF0b3IsIGNvbnRleHQpO1xuICAgICAgcmV0dXJuIGluaXRpYWwgPyBvYmoucmVkdWNlUmlnaHQoaXRlcmF0b3IsIG1lbW8pIDogb2JqLnJlZHVjZVJpZ2h0KGl0ZXJhdG9yKTtcbiAgICB9XG4gICAgdmFyIGxlbmd0aCA9IG9iai5sZW5ndGg7XG4gICAgaWYgKGxlbmd0aCAhPT0gK2xlbmd0aCkge1xuICAgICAgdmFyIGtleXMgPSBfLmtleXMob2JqKTtcbiAgICAgIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgIH1cbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICBpbmRleCA9IGtleXMgPyBrZXlzWy0tbGVuZ3RoXSA6IC0tbGVuZ3RoO1xuICAgICAgaWYgKCFpbml0aWFsKSB7XG4gICAgICAgIG1lbW8gPSBvYmpbaW5kZXhdO1xuICAgICAgICBpbml0aWFsID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1lbW8gPSBpdGVyYXRvci5jYWxsKGNvbnRleHQsIG1lbW8sIG9ialtpbmRleF0sIGluZGV4LCBsaXN0KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoIWluaXRpYWwpIHRocm93IG5ldyBUeXBlRXJyb3IocmVkdWNlRXJyb3IpO1xuICAgIHJldHVybiBtZW1vO1xuICB9O1xuXG4gIC8vIFJldHVybiB0aGUgZmlyc3QgdmFsdWUgd2hpY2ggcGFzc2VzIGEgdHJ1dGggdGVzdC4gQWxpYXNlZCBhcyBgZGV0ZWN0YC5cbiAgXy5maW5kID0gXy5kZXRlY3QgPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkge1xuICAgIHZhciByZXN1bHQ7XG4gICAgYW55KG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICBpZiAocHJlZGljYXRlLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KSkge1xuICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBSZXR1cm4gYWxsIHRoZSBlbGVtZW50cyB0aGF0IHBhc3MgYSB0cnV0aCB0ZXN0LlxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgZmlsdGVyYCBpZiBhdmFpbGFibGUuXG4gIC8vIEFsaWFzZWQgYXMgYHNlbGVjdGAuXG4gIF8uZmlsdGVyID0gXy5zZWxlY3QgPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkge1xuICAgIHZhciByZXN1bHRzID0gW107XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gcmVzdWx0cztcbiAgICBpZiAobmF0aXZlRmlsdGVyICYmIG9iai5maWx0ZXIgPT09IG5hdGl2ZUZpbHRlcikgcmV0dXJuIG9iai5maWx0ZXIocHJlZGljYXRlLCBjb250ZXh0KTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICBpZiAocHJlZGljYXRlLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBsaXN0KSkgcmVzdWx0cy5wdXNoKHZhbHVlKTtcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfTtcblxuICAvLyBSZXR1cm4gYWxsIHRoZSBlbGVtZW50cyBmb3Igd2hpY2ggYSB0cnV0aCB0ZXN0IGZhaWxzLlxuICBfLnJlamVjdCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgcmV0dXJuIF8uZmlsdGVyKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICByZXR1cm4gIXByZWRpY2F0ZS5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdCk7XG4gICAgfSwgY29udGV4dCk7XG4gIH07XG5cbiAgLy8gRGV0ZXJtaW5lIHdoZXRoZXIgYWxsIG9mIHRoZSBlbGVtZW50cyBtYXRjaCBhIHRydXRoIHRlc3QuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBldmVyeWAgaWYgYXZhaWxhYmxlLlxuICAvLyBBbGlhc2VkIGFzIGBhbGxgLlxuICBfLmV2ZXJ5ID0gXy5hbGwgPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkge1xuICAgIHByZWRpY2F0ZSB8fCAocHJlZGljYXRlID0gXy5pZGVudGl0eSk7XG4gICAgdmFyIHJlc3VsdCA9IHRydWU7XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gcmVzdWx0O1xuICAgIGlmIChuYXRpdmVFdmVyeSAmJiBvYmouZXZlcnkgPT09IG5hdGl2ZUV2ZXJ5KSByZXR1cm4gb2JqLmV2ZXJ5KHByZWRpY2F0ZSwgY29udGV4dCk7XG4gICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgaWYgKCEocmVzdWx0ID0gcmVzdWx0ICYmIHByZWRpY2F0ZS5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdCkpKSByZXR1cm4gYnJlYWtlcjtcbiAgICB9KTtcbiAgICByZXR1cm4gISFyZXN1bHQ7XG4gIH07XG5cbiAgLy8gRGV0ZXJtaW5lIGlmIGF0IGxlYXN0IG9uZSBlbGVtZW50IGluIHRoZSBvYmplY3QgbWF0Y2hlcyBhIHRydXRoIHRlc3QuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBzb21lYCBpZiBhdmFpbGFibGUuXG4gIC8vIEFsaWFzZWQgYXMgYGFueWAuXG4gIHZhciBhbnkgPSBfLnNvbWUgPSBfLmFueSA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7XG4gICAgcHJlZGljYXRlIHx8IChwcmVkaWNhdGUgPSBfLmlkZW50aXR5KTtcbiAgICB2YXIgcmVzdWx0ID0gZmFsc2U7XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gcmVzdWx0O1xuICAgIGlmIChuYXRpdmVTb21lICYmIG9iai5zb21lID09PSBuYXRpdmVTb21lKSByZXR1cm4gb2JqLnNvbWUocHJlZGljYXRlLCBjb250ZXh0KTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7XG4gICAgICBpZiAocmVzdWx0IHx8IChyZXN1bHQgPSBwcmVkaWNhdGUuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIGxpc3QpKSkgcmV0dXJuIGJyZWFrZXI7XG4gICAgfSk7XG4gICAgcmV0dXJuICEhcmVzdWx0O1xuICB9O1xuXG4gIC8vIERldGVybWluZSBpZiB0aGUgYXJyYXkgb3Igb2JqZWN0IGNvbnRhaW5zIGEgZ2l2ZW4gdmFsdWUgKHVzaW5nIGA9PT1gKS5cbiAgLy8gQWxpYXNlZCBhcyBgaW5jbHVkZWAuXG4gIF8uY29udGFpbnMgPSBfLmluY2x1ZGUgPSBmdW5jdGlvbihvYmosIHRhcmdldCkge1xuICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIGZhbHNlO1xuICAgIGlmIChuYXRpdmVJbmRleE9mICYmIG9iai5pbmRleE9mID09PSBuYXRpdmVJbmRleE9mKSByZXR1cm4gb2JqLmluZGV4T2YodGFyZ2V0KSAhPSAtMTtcbiAgICByZXR1cm4gYW55KG9iaiwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJldHVybiB2YWx1ZSA9PT0gdGFyZ2V0O1xuICAgIH0pO1xuICB9O1xuXG4gIC8vIEludm9rZSBhIG1ldGhvZCAod2l0aCBhcmd1bWVudHMpIG9uIGV2ZXJ5IGl0ZW0gaW4gYSBjb2xsZWN0aW9uLlxuICBfLmludm9rZSA9IGZ1bmN0aW9uKG9iaiwgbWV0aG9kKSB7XG4gICAgdmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgdmFyIGlzRnVuYyA9IF8uaXNGdW5jdGlvbihtZXRob2QpO1xuICAgIHJldHVybiBfLm1hcChvYmosIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXR1cm4gKGlzRnVuYyA/IG1ldGhvZCA6IHZhbHVlW21ldGhvZF0pLmFwcGx5KHZhbHVlLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcblxuICAvLyBDb252ZW5pZW5jZSB2ZXJzaW9uIG9mIGEgY29tbW9uIHVzZSBjYXNlIG9mIGBtYXBgOiBmZXRjaGluZyBhIHByb3BlcnR5LlxuICBfLnBsdWNrID0gZnVuY3Rpb24ob2JqLCBrZXkpIHtcbiAgICByZXR1cm4gXy5tYXAob2JqLCBfLnByb3BlcnR5KGtleSkpO1xuICB9O1xuXG4gIC8vIENvbnZlbmllbmNlIHZlcnNpb24gb2YgYSBjb21tb24gdXNlIGNhc2Ugb2YgYGZpbHRlcmA6IHNlbGVjdGluZyBvbmx5IG9iamVjdHNcbiAgLy8gY29udGFpbmluZyBzcGVjaWZpYyBga2V5OnZhbHVlYCBwYWlycy5cbiAgXy53aGVyZSA9IGZ1bmN0aW9uKG9iaiwgYXR0cnMpIHtcbiAgICByZXR1cm4gXy5maWx0ZXIob2JqLCBfLm1hdGNoZXMoYXR0cnMpKTtcbiAgfTtcblxuICAvLyBDb252ZW5pZW5jZSB2ZXJzaW9uIG9mIGEgY29tbW9uIHVzZSBjYXNlIG9mIGBmaW5kYDogZ2V0dGluZyB0aGUgZmlyc3Qgb2JqZWN0XG4gIC8vIGNvbnRhaW5pbmcgc3BlY2lmaWMgYGtleTp2YWx1ZWAgcGFpcnMuXG4gIF8uZmluZFdoZXJlID0gZnVuY3Rpb24ob2JqLCBhdHRycykge1xuICAgIHJldHVybiBfLmZpbmQob2JqLCBfLm1hdGNoZXMoYXR0cnMpKTtcbiAgfTtcblxuICAvLyBSZXR1cm4gdGhlIG1heGltdW0gZWxlbWVudCBvciAoZWxlbWVudC1iYXNlZCBjb21wdXRhdGlvbikuXG4gIC8vIENhbid0IG9wdGltaXplIGFycmF5cyBvZiBpbnRlZ2VycyBsb25nZXIgdGhhbiA2NSw1MzUgZWxlbWVudHMuXG4gIC8vIFNlZSBbV2ViS2l0IEJ1ZyA4MDc5N10oaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTgwNzk3KVxuICBfLm1heCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICBpZiAoIWl0ZXJhdG9yICYmIF8uaXNBcnJheShvYmopICYmIG9ialswXSA9PT0gK29ialswXSAmJiBvYmoubGVuZ3RoIDwgNjU1MzUpIHtcbiAgICAgIHJldHVybiBNYXRoLm1heC5hcHBseShNYXRoLCBvYmopO1xuICAgIH1cbiAgICB2YXIgcmVzdWx0ID0gLUluZmluaXR5LCBsYXN0Q29tcHV0ZWQgPSAtSW5maW5pdHk7XG4gICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgdmFyIGNvbXB1dGVkID0gaXRlcmF0b3IgPyBpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdCkgOiB2YWx1ZTtcbiAgICAgIGlmIChjb21wdXRlZCA+IGxhc3RDb21wdXRlZCkge1xuICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgbGFzdENvbXB1dGVkID0gY29tcHV0ZWQ7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBSZXR1cm4gdGhlIG1pbmltdW0gZWxlbWVudCAob3IgZWxlbWVudC1iYXNlZCBjb21wdXRhdGlvbikuXG4gIF8ubWluID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIGlmICghaXRlcmF0b3IgJiYgXy5pc0FycmF5KG9iaikgJiYgb2JqWzBdID09PSArb2JqWzBdICYmIG9iai5sZW5ndGggPCA2NTUzNSkge1xuICAgICAgcmV0dXJuIE1hdGgubWluLmFwcGx5KE1hdGgsIG9iaik7XG4gICAgfVxuICAgIHZhciByZXN1bHQgPSBJbmZpbml0eSwgbGFzdENvbXB1dGVkID0gSW5maW5pdHk7XG4gICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgdmFyIGNvbXB1dGVkID0gaXRlcmF0b3IgPyBpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdCkgOiB2YWx1ZTtcbiAgICAgIGlmIChjb21wdXRlZCA8IGxhc3RDb21wdXRlZCkge1xuICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgbGFzdENvbXB1dGVkID0gY29tcHV0ZWQ7XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBTaHVmZmxlIGFuIGFycmF5LCB1c2luZyB0aGUgbW9kZXJuIHZlcnNpb24gb2YgdGhlXG4gIC8vIFtGaXNoZXItWWF0ZXMgc2h1ZmZsZV0oaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9GaXNoZXLigJNZYXRlc19zaHVmZmxlKS5cbiAgXy5zaHVmZmxlID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIHJhbmQ7XG4gICAgdmFyIGluZGV4ID0gMDtcbiAgICB2YXIgc2h1ZmZsZWQgPSBbXTtcbiAgICBlYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgIHJhbmQgPSBfLnJhbmRvbShpbmRleCsrKTtcbiAgICAgIHNodWZmbGVkW2luZGV4IC0gMV0gPSBzaHVmZmxlZFtyYW5kXTtcbiAgICAgIHNodWZmbGVkW3JhbmRdID0gdmFsdWU7XG4gICAgfSk7XG4gICAgcmV0dXJuIHNodWZmbGVkO1xuICB9O1xuXG4gIC8vIFNhbXBsZSAqKm4qKiByYW5kb20gdmFsdWVzIGZyb20gYSBjb2xsZWN0aW9uLlxuICAvLyBJZiAqKm4qKiBpcyBub3Qgc3BlY2lmaWVkLCByZXR1cm5zIGEgc2luZ2xlIHJhbmRvbSBlbGVtZW50LlxuICAvLyBUaGUgaW50ZXJuYWwgYGd1YXJkYCBhcmd1bWVudCBhbGxvd3MgaXQgdG8gd29yayB3aXRoIGBtYXBgLlxuICBfLnNhbXBsZSA9IGZ1bmN0aW9uKG9iaiwgbiwgZ3VhcmQpIHtcbiAgICBpZiAobiA9PSBudWxsIHx8IGd1YXJkKSB7XG4gICAgICBpZiAob2JqLmxlbmd0aCAhPT0gK29iai5sZW5ndGgpIG9iaiA9IF8udmFsdWVzKG9iaik7XG4gICAgICByZXR1cm4gb2JqW18ucmFuZG9tKG9iai5sZW5ndGggLSAxKV07XG4gICAgfVxuICAgIHJldHVybiBfLnNodWZmbGUob2JqKS5zbGljZSgwLCBNYXRoLm1heCgwLCBuKSk7XG4gIH07XG5cbiAgLy8gQW4gaW50ZXJuYWwgZnVuY3Rpb24gdG8gZ2VuZXJhdGUgbG9va3VwIGl0ZXJhdG9ycy5cbiAgdmFyIGxvb2t1cEl0ZXJhdG9yID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkgcmV0dXJuIF8uaWRlbnRpdHk7XG4gICAgaWYgKF8uaXNGdW5jdGlvbih2YWx1ZSkpIHJldHVybiB2YWx1ZTtcbiAgICByZXR1cm4gXy5wcm9wZXJ0eSh2YWx1ZSk7XG4gIH07XG5cbiAgLy8gU29ydCB0aGUgb2JqZWN0J3MgdmFsdWVzIGJ5IGEgY3JpdGVyaW9uIHByb2R1Y2VkIGJ5IGFuIGl0ZXJhdG9yLlxuICBfLnNvcnRCeSA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICBpdGVyYXRvciA9IGxvb2t1cEl0ZXJhdG9yKGl0ZXJhdG9yKTtcbiAgICByZXR1cm4gXy5wbHVjayhfLm1hcChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgICBpbmRleDogaW5kZXgsXG4gICAgICAgIGNyaXRlcmlhOiBpdGVyYXRvci5jYWxsKGNvbnRleHQsIHZhbHVlLCBpbmRleCwgbGlzdClcbiAgICAgIH07XG4gICAgfSkuc29ydChmdW5jdGlvbihsZWZ0LCByaWdodCkge1xuICAgICAgdmFyIGEgPSBsZWZ0LmNyaXRlcmlhO1xuICAgICAgdmFyIGIgPSByaWdodC5jcml0ZXJpYTtcbiAgICAgIGlmIChhICE9PSBiKSB7XG4gICAgICAgIGlmIChhID4gYiB8fCBhID09PSB2b2lkIDApIHJldHVybiAxO1xuICAgICAgICBpZiAoYSA8IGIgfHwgYiA9PT0gdm9pZCAwKSByZXR1cm4gLTE7XG4gICAgICB9XG4gICAgICByZXR1cm4gbGVmdC5pbmRleCAtIHJpZ2h0LmluZGV4O1xuICAgIH0pLCAndmFsdWUnKTtcbiAgfTtcblxuICAvLyBBbiBpbnRlcm5hbCBmdW5jdGlvbiB1c2VkIGZvciBhZ2dyZWdhdGUgXCJncm91cCBieVwiIG9wZXJhdGlvbnMuXG4gIHZhciBncm91cCA9IGZ1bmN0aW9uKGJlaGF2aW9yKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICAgIGl0ZXJhdG9yID0gbG9va3VwSXRlcmF0b3IoaXRlcmF0b3IpO1xuICAgICAgZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCkge1xuICAgICAgICB2YXIga2V5ID0gaXRlcmF0b3IuY2FsbChjb250ZXh0LCB2YWx1ZSwgaW5kZXgsIG9iaik7XG4gICAgICAgIGJlaGF2aW9yKHJlc3VsdCwga2V5LCB2YWx1ZSk7XG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgfTtcblxuICAvLyBHcm91cHMgdGhlIG9iamVjdCdzIHZhbHVlcyBieSBhIGNyaXRlcmlvbi4gUGFzcyBlaXRoZXIgYSBzdHJpbmcgYXR0cmlidXRlXG4gIC8vIHRvIGdyb3VwIGJ5LCBvciBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgY3JpdGVyaW9uLlxuICBfLmdyb3VwQnkgPSBncm91cChmdW5jdGlvbihyZXN1bHQsIGtleSwgdmFsdWUpIHtcbiAgICBfLmhhcyhyZXN1bHQsIGtleSkgPyByZXN1bHRba2V5XS5wdXNoKHZhbHVlKSA6IHJlc3VsdFtrZXldID0gW3ZhbHVlXTtcbiAgfSk7XG5cbiAgLy8gSW5kZXhlcyB0aGUgb2JqZWN0J3MgdmFsdWVzIGJ5IGEgY3JpdGVyaW9uLCBzaW1pbGFyIHRvIGBncm91cEJ5YCwgYnV0IGZvclxuICAvLyB3aGVuIHlvdSBrbm93IHRoYXQgeW91ciBpbmRleCB2YWx1ZXMgd2lsbCBiZSB1bmlxdWUuXG4gIF8uaW5kZXhCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwga2V5LCB2YWx1ZSkge1xuICAgIHJlc3VsdFtrZXldID0gdmFsdWU7XG4gIH0pO1xuXG4gIC8vIENvdW50cyBpbnN0YW5jZXMgb2YgYW4gb2JqZWN0IHRoYXQgZ3JvdXAgYnkgYSBjZXJ0YWluIGNyaXRlcmlvbi4gUGFzc1xuICAvLyBlaXRoZXIgYSBzdHJpbmcgYXR0cmlidXRlIHRvIGNvdW50IGJ5LCBvciBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGVcbiAgLy8gY3JpdGVyaW9uLlxuICBfLmNvdW50QnkgPSBncm91cChmdW5jdGlvbihyZXN1bHQsIGtleSkge1xuICAgIF8uaGFzKHJlc3VsdCwga2V5KSA/IHJlc3VsdFtrZXldKysgOiByZXN1bHRba2V5XSA9IDE7XG4gIH0pO1xuXG4gIC8vIFVzZSBhIGNvbXBhcmF0b3IgZnVuY3Rpb24gdG8gZmlndXJlIG91dCB0aGUgc21hbGxlc3QgaW5kZXggYXQgd2hpY2hcbiAgLy8gYW4gb2JqZWN0IHNob3VsZCBiZSBpbnNlcnRlZCBzbyBhcyB0byBtYWludGFpbiBvcmRlci4gVXNlcyBiaW5hcnkgc2VhcmNoLlxuICBfLnNvcnRlZEluZGV4ID0gZnVuY3Rpb24oYXJyYXksIG9iaiwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICBpdGVyYXRvciA9IGxvb2t1cEl0ZXJhdG9yKGl0ZXJhdG9yKTtcbiAgICB2YXIgdmFsdWUgPSBpdGVyYXRvci5jYWxsKGNvbnRleHQsIG9iaik7XG4gICAgdmFyIGxvdyA9IDAsIGhpZ2ggPSBhcnJheS5sZW5ndGg7XG4gICAgd2hpbGUgKGxvdyA8IGhpZ2gpIHtcbiAgICAgIHZhciBtaWQgPSAobG93ICsgaGlnaCkgPj4+IDE7XG4gICAgICBpdGVyYXRvci5jYWxsKGNvbnRleHQsIGFycmF5W21pZF0pIDwgdmFsdWUgPyBsb3cgPSBtaWQgKyAxIDogaGlnaCA9IG1pZDtcbiAgICB9XG4gICAgcmV0dXJuIGxvdztcbiAgfTtcblxuICAvLyBTYWZlbHkgY3JlYXRlIGEgcmVhbCwgbGl2ZSBhcnJheSBmcm9tIGFueXRoaW5nIGl0ZXJhYmxlLlxuICBfLnRvQXJyYXkgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAoIW9iaikgcmV0dXJuIFtdO1xuICAgIGlmIChfLmlzQXJyYXkob2JqKSkgcmV0dXJuIHNsaWNlLmNhbGwob2JqKTtcbiAgICBpZiAob2JqLmxlbmd0aCA9PT0gK29iai5sZW5ndGgpIHJldHVybiBfLm1hcChvYmosIF8uaWRlbnRpdHkpO1xuICAgIHJldHVybiBfLnZhbHVlcyhvYmopO1xuICB9O1xuXG4gIC8vIFJldHVybiB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIGluIGFuIG9iamVjdC5cbiAgXy5zaXplID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gMDtcbiAgICByZXR1cm4gKG9iai5sZW5ndGggPT09ICtvYmoubGVuZ3RoKSA/IG9iai5sZW5ndGggOiBfLmtleXMob2JqKS5sZW5ndGg7XG4gIH07XG5cbiAgLy8gQXJyYXkgRnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLVxuXG4gIC8vIEdldCB0aGUgZmlyc3QgZWxlbWVudCBvZiBhbiBhcnJheS4gUGFzc2luZyAqKm4qKiB3aWxsIHJldHVybiB0aGUgZmlyc3QgTlxuICAvLyB2YWx1ZXMgaW4gdGhlIGFycmF5LiBBbGlhc2VkIGFzIGBoZWFkYCBhbmQgYHRha2VgLiBUaGUgKipndWFyZCoqIGNoZWNrXG4gIC8vIGFsbG93cyBpdCB0byB3b3JrIHdpdGggYF8ubWFwYC5cbiAgXy5maXJzdCA9IF8uaGVhZCA9IF8udGFrZSA9IGZ1bmN0aW9uKGFycmF5LCBuLCBndWFyZCkge1xuICAgIGlmIChhcnJheSA9PSBudWxsKSByZXR1cm4gdm9pZCAwO1xuICAgIGlmICgobiA9PSBudWxsKSB8fCBndWFyZCkgcmV0dXJuIGFycmF5WzBdO1xuICAgIGlmIChuIDwgMCkgcmV0dXJuIFtdO1xuICAgIHJldHVybiBzbGljZS5jYWxsKGFycmF5LCAwLCBuKTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGV2ZXJ5dGhpbmcgYnV0IHRoZSBsYXN0IGVudHJ5IG9mIHRoZSBhcnJheS4gRXNwZWNpYWxseSB1c2VmdWwgb25cbiAgLy8gdGhlIGFyZ3VtZW50cyBvYmplY3QuIFBhc3NpbmcgKipuKiogd2lsbCByZXR1cm4gYWxsIHRoZSB2YWx1ZXMgaW5cbiAgLy8gdGhlIGFycmF5LCBleGNsdWRpbmcgdGhlIGxhc3QgTi4gVGhlICoqZ3VhcmQqKiBjaGVjayBhbGxvd3MgaXQgdG8gd29yayB3aXRoXG4gIC8vIGBfLm1hcGAuXG4gIF8uaW5pdGlhbCA9IGZ1bmN0aW9uKGFycmF5LCBuLCBndWFyZCkge1xuICAgIHJldHVybiBzbGljZS5jYWxsKGFycmF5LCAwLCBhcnJheS5sZW5ndGggLSAoKG4gPT0gbnVsbCkgfHwgZ3VhcmQgPyAxIDogbikpO1xuICB9O1xuXG4gIC8vIEdldCB0aGUgbGFzdCBlbGVtZW50IG9mIGFuIGFycmF5LiBQYXNzaW5nICoqbioqIHdpbGwgcmV0dXJuIHRoZSBsYXN0IE5cbiAgLy8gdmFsdWVzIGluIHRoZSBhcnJheS4gVGhlICoqZ3VhcmQqKiBjaGVjayBhbGxvd3MgaXQgdG8gd29yayB3aXRoIGBfLm1hcGAuXG4gIF8ubGFzdCA9IGZ1bmN0aW9uKGFycmF5LCBuLCBndWFyZCkge1xuICAgIGlmIChhcnJheSA9PSBudWxsKSByZXR1cm4gdm9pZCAwO1xuICAgIGlmICgobiA9PSBudWxsKSB8fCBndWFyZCkgcmV0dXJuIGFycmF5W2FycmF5Lmxlbmd0aCAtIDFdO1xuICAgIHJldHVybiBzbGljZS5jYWxsKGFycmF5LCBNYXRoLm1heChhcnJheS5sZW5ndGggLSBuLCAwKSk7XG4gIH07XG5cbiAgLy8gUmV0dXJucyBldmVyeXRoaW5nIGJ1dCB0aGUgZmlyc3QgZW50cnkgb2YgdGhlIGFycmF5LiBBbGlhc2VkIGFzIGB0YWlsYCBhbmQgYGRyb3BgLlxuICAvLyBFc3BlY2lhbGx5IHVzZWZ1bCBvbiB0aGUgYXJndW1lbnRzIG9iamVjdC4gUGFzc2luZyBhbiAqKm4qKiB3aWxsIHJldHVyblxuICAvLyB0aGUgcmVzdCBOIHZhbHVlcyBpbiB0aGUgYXJyYXkuIFRoZSAqKmd1YXJkKipcbiAgLy8gY2hlY2sgYWxsb3dzIGl0IHRvIHdvcmsgd2l0aCBgXy5tYXBgLlxuICBfLnJlc3QgPSBfLnRhaWwgPSBfLmRyb3AgPSBmdW5jdGlvbihhcnJheSwgbiwgZ3VhcmQpIHtcbiAgICByZXR1cm4gc2xpY2UuY2FsbChhcnJheSwgKG4gPT0gbnVsbCkgfHwgZ3VhcmQgPyAxIDogbik7XG4gIH07XG5cbiAgLy8gVHJpbSBvdXQgYWxsIGZhbHN5IHZhbHVlcyBmcm9tIGFuIGFycmF5LlxuICBfLmNvbXBhY3QgPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHJldHVybiBfLmZpbHRlcihhcnJheSwgXy5pZGVudGl0eSk7XG4gIH07XG5cbiAgLy8gSW50ZXJuYWwgaW1wbGVtZW50YXRpb24gb2YgYSByZWN1cnNpdmUgYGZsYXR0ZW5gIGZ1bmN0aW9uLlxuICB2YXIgZmxhdHRlbiA9IGZ1bmN0aW9uKGlucHV0LCBzaGFsbG93LCBvdXRwdXQpIHtcbiAgICBpZiAoc2hhbGxvdyAmJiBfLmV2ZXJ5KGlucHV0LCBfLmlzQXJyYXkpKSB7XG4gICAgICByZXR1cm4gY29uY2F0LmFwcGx5KG91dHB1dCwgaW5wdXQpO1xuICAgIH1cbiAgICBlYWNoKGlucHV0LCBmdW5jdGlvbih2YWx1ZSkge1xuICAgICAgaWYgKF8uaXNBcnJheSh2YWx1ZSkgfHwgXy5pc0FyZ3VtZW50cyh2YWx1ZSkpIHtcbiAgICAgICAgc2hhbGxvdyA/IHB1c2guYXBwbHkob3V0cHV0LCB2YWx1ZSkgOiBmbGF0dGVuKHZhbHVlLCBzaGFsbG93LCBvdXRwdXQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3V0cHV0LnB1c2godmFsdWUpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBvdXRwdXQ7XG4gIH07XG5cbiAgLy8gRmxhdHRlbiBvdXQgYW4gYXJyYXksIGVpdGhlciByZWN1cnNpdmVseSAoYnkgZGVmYXVsdCksIG9yIGp1c3Qgb25lIGxldmVsLlxuICBfLmZsYXR0ZW4gPSBmdW5jdGlvbihhcnJheSwgc2hhbGxvdykge1xuICAgIHJldHVybiBmbGF0dGVuKGFycmF5LCBzaGFsbG93LCBbXSk7XG4gIH07XG5cbiAgLy8gUmV0dXJuIGEgdmVyc2lvbiBvZiB0aGUgYXJyYXkgdGhhdCBkb2VzIG5vdCBjb250YWluIHRoZSBzcGVjaWZpZWQgdmFsdWUocykuXG4gIF8ud2l0aG91dCA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgcmV0dXJuIF8uZGlmZmVyZW5jZShhcnJheSwgc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgfTtcblxuICAvLyBTcGxpdCBhbiBhcnJheSBpbnRvIHR3byBhcnJheXM6IG9uZSB3aG9zZSBlbGVtZW50cyBhbGwgc2F0aXNmeSB0aGUgZ2l2ZW5cbiAgLy8gcHJlZGljYXRlLCBhbmQgb25lIHdob3NlIGVsZW1lbnRzIGFsbCBkbyBub3Qgc2F0aXNmeSB0aGUgcHJlZGljYXRlLlxuICBfLnBhcnRpdGlvbiA9IGZ1bmN0aW9uKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgICB2YXIgcGFzcyA9IFtdLCBmYWlsID0gW107XG4gICAgZWFjaChhcnJheSwgZnVuY3Rpb24oZWxlbSkge1xuICAgICAgKHByZWRpY2F0ZShlbGVtKSA/IHBhc3MgOiBmYWlsKS5wdXNoKGVsZW0pO1xuICAgIH0pO1xuICAgIHJldHVybiBbcGFzcywgZmFpbF07XG4gIH07XG5cbiAgLy8gUHJvZHVjZSBhIGR1cGxpY2F0ZS1mcmVlIHZlcnNpb24gb2YgdGhlIGFycmF5LiBJZiB0aGUgYXJyYXkgaGFzIGFscmVhZHlcbiAgLy8gYmVlbiBzb3J0ZWQsIHlvdSBoYXZlIHRoZSBvcHRpb24gb2YgdXNpbmcgYSBmYXN0ZXIgYWxnb3JpdGhtLlxuICAvLyBBbGlhc2VkIGFzIGB1bmlxdWVgLlxuICBfLnVuaXEgPSBfLnVuaXF1ZSA9IGZ1bmN0aW9uKGFycmF5LCBpc1NvcnRlZCwgaXRlcmF0b3IsIGNvbnRleHQpIHtcbiAgICBpZiAoXy5pc0Z1bmN0aW9uKGlzU29ydGVkKSkge1xuICAgICAgY29udGV4dCA9IGl0ZXJhdG9yO1xuICAgICAgaXRlcmF0b3IgPSBpc1NvcnRlZDtcbiAgICAgIGlzU29ydGVkID0gZmFsc2U7XG4gICAgfVxuICAgIHZhciBpbml0aWFsID0gaXRlcmF0b3IgPyBfLm1hcChhcnJheSwgaXRlcmF0b3IsIGNvbnRleHQpIDogYXJyYXk7XG4gICAgdmFyIHJlc3VsdHMgPSBbXTtcbiAgICB2YXIgc2VlbiA9IFtdO1xuICAgIGVhY2goaW5pdGlhbCwgZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7XG4gICAgICBpZiAoaXNTb3J0ZWQgPyAoIWluZGV4IHx8IHNlZW5bc2Vlbi5sZW5ndGggLSAxXSAhPT0gdmFsdWUpIDogIV8uY29udGFpbnMoc2VlbiwgdmFsdWUpKSB7XG4gICAgICAgIHNlZW4ucHVzaCh2YWx1ZSk7XG4gICAgICAgIHJlc3VsdHMucHVzaChhcnJheVtpbmRleF0pO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHRzO1xuICB9O1xuXG4gIC8vIFByb2R1Y2UgYW4gYXJyYXkgdGhhdCBjb250YWlucyB0aGUgdW5pb246IGVhY2ggZGlzdGluY3QgZWxlbWVudCBmcm9tIGFsbCBvZlxuICAvLyB0aGUgcGFzc2VkLWluIGFycmF5cy5cbiAgXy51bmlvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBfLnVuaXEoXy5mbGF0dGVuKGFyZ3VtZW50cywgdHJ1ZSkpO1xuICB9O1xuXG4gIC8vIFByb2R1Y2UgYW4gYXJyYXkgdGhhdCBjb250YWlucyBldmVyeSBpdGVtIHNoYXJlZCBiZXR3ZWVuIGFsbCB0aGVcbiAgLy8gcGFzc2VkLWluIGFycmF5cy5cbiAgXy5pbnRlcnNlY3Rpb24gPSBmdW5jdGlvbihhcnJheSkge1xuICAgIHZhciByZXN0ID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgIHJldHVybiBfLmZpbHRlcihfLnVuaXEoYXJyYXkpLCBmdW5jdGlvbihpdGVtKSB7XG4gICAgICByZXR1cm4gXy5ldmVyeShyZXN0LCBmdW5jdGlvbihvdGhlcikge1xuICAgICAgICByZXR1cm4gXy5jb250YWlucyhvdGhlciwgaXRlbSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICAvLyBUYWtlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gb25lIGFycmF5IGFuZCBhIG51bWJlciBvZiBvdGhlciBhcnJheXMuXG4gIC8vIE9ubHkgdGhlIGVsZW1lbnRzIHByZXNlbnQgaW4ganVzdCB0aGUgZmlyc3QgYXJyYXkgd2lsbCByZW1haW4uXG4gIF8uZGlmZmVyZW5jZSA9IGZ1bmN0aW9uKGFycmF5KSB7XG4gICAgdmFyIHJlc3QgPSBjb25jYXQuYXBwbHkoQXJyYXlQcm90bywgc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICByZXR1cm4gXy5maWx0ZXIoYXJyYXksIGZ1bmN0aW9uKHZhbHVlKXsgcmV0dXJuICFfLmNvbnRhaW5zKHJlc3QsIHZhbHVlKTsgfSk7XG4gIH07XG5cbiAgLy8gWmlwIHRvZ2V0aGVyIG11bHRpcGxlIGxpc3RzIGludG8gYSBzaW5nbGUgYXJyYXkgLS0gZWxlbWVudHMgdGhhdCBzaGFyZVxuICAvLyBhbiBpbmRleCBnbyB0b2dldGhlci5cbiAgXy56aXAgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgbGVuZ3RoID0gXy5tYXgoXy5wbHVjayhhcmd1bWVudHMsICdsZW5ndGgnKS5jb25jYXQoMCkpO1xuICAgIHZhciByZXN1bHRzID0gbmV3IEFycmF5KGxlbmd0aCk7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgcmVzdWx0c1tpXSA9IF8ucGx1Y2soYXJndW1lbnRzLCAnJyArIGkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfTtcblxuICAvLyBDb252ZXJ0cyBsaXN0cyBpbnRvIG9iamVjdHMuIFBhc3MgZWl0aGVyIGEgc2luZ2xlIGFycmF5IG9mIGBba2V5LCB2YWx1ZV1gXG4gIC8vIHBhaXJzLCBvciB0d28gcGFyYWxsZWwgYXJyYXlzIG9mIHRoZSBzYW1lIGxlbmd0aCAtLSBvbmUgb2Yga2V5cywgYW5kIG9uZSBvZlxuICAvLyB0aGUgY29ycmVzcG9uZGluZyB2YWx1ZXMuXG4gIF8ub2JqZWN0ID0gZnVuY3Rpb24obGlzdCwgdmFsdWVzKSB7XG4gICAgaWYgKGxpc3QgPT0gbnVsbCkgcmV0dXJuIHt9O1xuICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0gbGlzdC5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHZhbHVlcykge1xuICAgICAgICByZXN1bHRbbGlzdFtpXV0gPSB2YWx1ZXNbaV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXN1bHRbbGlzdFtpXVswXV0gPSBsaXN0W2ldWzFdO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIElmIHRoZSBicm93c2VyIGRvZXNuJ3Qgc3VwcGx5IHVzIHdpdGggaW5kZXhPZiAoSSdtIGxvb2tpbmcgYXQgeW91LCAqKk1TSUUqKiksXG4gIC8vIHdlIG5lZWQgdGhpcyBmdW5jdGlvbi4gUmV0dXJuIHRoZSBwb3NpdGlvbiBvZiB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBhblxuICAvLyBpdGVtIGluIGFuIGFycmF5LCBvciAtMSBpZiB0aGUgaXRlbSBpcyBub3QgaW5jbHVkZWQgaW4gdGhlIGFycmF5LlxuICAvLyBEZWxlZ2F0ZXMgdG8gKipFQ01BU2NyaXB0IDUqKidzIG5hdGl2ZSBgaW5kZXhPZmAgaWYgYXZhaWxhYmxlLlxuICAvLyBJZiB0aGUgYXJyYXkgaXMgbGFyZ2UgYW5kIGFscmVhZHkgaW4gc29ydCBvcmRlciwgcGFzcyBgdHJ1ZWBcbiAgLy8gZm9yICoqaXNTb3J0ZWQqKiB0byB1c2UgYmluYXJ5IHNlYXJjaC5cbiAgXy5pbmRleE9mID0gZnVuY3Rpb24oYXJyYXksIGl0ZW0sIGlzU29ydGVkKSB7XG4gICAgaWYgKGFycmF5ID09IG51bGwpIHJldHVybiAtMTtcbiAgICB2YXIgaSA9IDAsIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcbiAgICBpZiAoaXNTb3J0ZWQpIHtcbiAgICAgIGlmICh0eXBlb2YgaXNTb3J0ZWQgPT0gJ251bWJlcicpIHtcbiAgICAgICAgaSA9IChpc1NvcnRlZCA8IDAgPyBNYXRoLm1heCgwLCBsZW5ndGggKyBpc1NvcnRlZCkgOiBpc1NvcnRlZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpID0gXy5zb3J0ZWRJbmRleChhcnJheSwgaXRlbSk7XG4gICAgICAgIHJldHVybiBhcnJheVtpXSA9PT0gaXRlbSA/IGkgOiAtMTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKG5hdGl2ZUluZGV4T2YgJiYgYXJyYXkuaW5kZXhPZiA9PT0gbmF0aXZlSW5kZXhPZikgcmV0dXJuIGFycmF5LmluZGV4T2YoaXRlbSwgaXNTb3J0ZWQpO1xuICAgIGZvciAoOyBpIDwgbGVuZ3RoOyBpKyspIGlmIChhcnJheVtpXSA9PT0gaXRlbSkgcmV0dXJuIGk7XG4gICAgcmV0dXJuIC0xO1xuICB9O1xuXG4gIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBsYXN0SW5kZXhPZmAgaWYgYXZhaWxhYmxlLlxuICBfLmxhc3RJbmRleE9mID0gZnVuY3Rpb24oYXJyYXksIGl0ZW0sIGZyb20pIHtcbiAgICBpZiAoYXJyYXkgPT0gbnVsbCkgcmV0dXJuIC0xO1xuICAgIHZhciBoYXNJbmRleCA9IGZyb20gIT0gbnVsbDtcbiAgICBpZiAobmF0aXZlTGFzdEluZGV4T2YgJiYgYXJyYXkubGFzdEluZGV4T2YgPT09IG5hdGl2ZUxhc3RJbmRleE9mKSB7XG4gICAgICByZXR1cm4gaGFzSW5kZXggPyBhcnJheS5sYXN0SW5kZXhPZihpdGVtLCBmcm9tKSA6IGFycmF5Lmxhc3RJbmRleE9mKGl0ZW0pO1xuICAgIH1cbiAgICB2YXIgaSA9IChoYXNJbmRleCA/IGZyb20gOiBhcnJheS5sZW5ndGgpO1xuICAgIHdoaWxlIChpLS0pIGlmIChhcnJheVtpXSA9PT0gaXRlbSkgcmV0dXJuIGk7XG4gICAgcmV0dXJuIC0xO1xuICB9O1xuXG4gIC8vIEdlbmVyYXRlIGFuIGludGVnZXIgQXJyYXkgY29udGFpbmluZyBhbiBhcml0aG1ldGljIHByb2dyZXNzaW9uLiBBIHBvcnQgb2ZcbiAgLy8gdGhlIG5hdGl2ZSBQeXRob24gYHJhbmdlKClgIGZ1bmN0aW9uLiBTZWVcbiAgLy8gW3RoZSBQeXRob24gZG9jdW1lbnRhdGlvbl0oaHR0cDovL2RvY3MucHl0aG9uLm9yZy9saWJyYXJ5L2Z1bmN0aW9ucy5odG1sI3JhbmdlKS5cbiAgXy5yYW5nZSA9IGZ1bmN0aW9uKHN0YXJ0LCBzdG9wLCBzdGVwKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPD0gMSkge1xuICAgICAgc3RvcCA9IHN0YXJ0IHx8IDA7XG4gICAgICBzdGFydCA9IDA7XG4gICAgfVxuICAgIHN0ZXAgPSBhcmd1bWVudHNbMl0gfHwgMTtcblxuICAgIHZhciBsZW5ndGggPSBNYXRoLm1heChNYXRoLmNlaWwoKHN0b3AgLSBzdGFydCkgLyBzdGVwKSwgMCk7XG4gICAgdmFyIGlkeCA9IDA7XG4gICAgdmFyIHJhbmdlID0gbmV3IEFycmF5KGxlbmd0aCk7XG5cbiAgICB3aGlsZShpZHggPCBsZW5ndGgpIHtcbiAgICAgIHJhbmdlW2lkeCsrXSA9IHN0YXJ0O1xuICAgICAgc3RhcnQgKz0gc3RlcDtcbiAgICB9XG5cbiAgICByZXR1cm4gcmFuZ2U7XG4gIH07XG5cbiAgLy8gRnVuY3Rpb24gKGFoZW0pIEZ1bmN0aW9uc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBSZXVzYWJsZSBjb25zdHJ1Y3RvciBmdW5jdGlvbiBmb3IgcHJvdG90eXBlIHNldHRpbmcuXG4gIHZhciBjdG9yID0gZnVuY3Rpb24oKXt9O1xuXG4gIC8vIENyZWF0ZSBhIGZ1bmN0aW9uIGJvdW5kIHRvIGEgZ2l2ZW4gb2JqZWN0IChhc3NpZ25pbmcgYHRoaXNgLCBhbmQgYXJndW1lbnRzLFxuICAvLyBvcHRpb25hbGx5KS4gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYEZ1bmN0aW9uLmJpbmRgIGlmXG4gIC8vIGF2YWlsYWJsZS5cbiAgXy5iaW5kID0gZnVuY3Rpb24oZnVuYywgY29udGV4dCkge1xuICAgIHZhciBhcmdzLCBib3VuZDtcbiAgICBpZiAobmF0aXZlQmluZCAmJiBmdW5jLmJpbmQgPT09IG5hdGl2ZUJpbmQpIHJldHVybiBuYXRpdmVCaW5kLmFwcGx5KGZ1bmMsIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgaWYgKCFfLmlzRnVuY3Rpb24oZnVuYykpIHRocm93IG5ldyBUeXBlRXJyb3I7XG4gICAgYXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAyKTtcbiAgICByZXR1cm4gYm91bmQgPSBmdW5jdGlvbigpIHtcbiAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBib3VuZCkpIHJldHVybiBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MuY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzKSkpO1xuICAgICAgY3Rvci5wcm90b3R5cGUgPSBmdW5jLnByb3RvdHlwZTtcbiAgICAgIHZhciBzZWxmID0gbmV3IGN0b3I7XG4gICAgICBjdG9yLnByb3RvdHlwZSA9IG51bGw7XG4gICAgICB2YXIgcmVzdWx0ID0gZnVuYy5hcHBseShzZWxmLCBhcmdzLmNvbmNhdChzbGljZS5jYWxsKGFyZ3VtZW50cykpKTtcbiAgICAgIGlmIChPYmplY3QocmVzdWx0KSA9PT0gcmVzdWx0KSByZXR1cm4gcmVzdWx0O1xuICAgICAgcmV0dXJuIHNlbGY7XG4gICAgfTtcbiAgfTtcblxuICAvLyBQYXJ0aWFsbHkgYXBwbHkgYSBmdW5jdGlvbiBieSBjcmVhdGluZyBhIHZlcnNpb24gdGhhdCBoYXMgaGFkIHNvbWUgb2YgaXRzXG4gIC8vIGFyZ3VtZW50cyBwcmUtZmlsbGVkLCB3aXRob3V0IGNoYW5naW5nIGl0cyBkeW5hbWljIGB0aGlzYCBjb250ZXh0LiBfIGFjdHNcbiAgLy8gYXMgYSBwbGFjZWhvbGRlciwgYWxsb3dpbmcgYW55IGNvbWJpbmF0aW9uIG9mIGFyZ3VtZW50cyB0byBiZSBwcmUtZmlsbGVkLlxuICBfLnBhcnRpYWwgPSBmdW5jdGlvbihmdW5jKSB7XG4gICAgdmFyIGJvdW5kQXJncyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgcG9zaXRpb24gPSAwO1xuICAgICAgdmFyIGFyZ3MgPSBib3VuZEFyZ3Muc2xpY2UoKTtcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBhcmdzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChhcmdzW2ldID09PSBfKSBhcmdzW2ldID0gYXJndW1lbnRzW3Bvc2l0aW9uKytdO1xuICAgICAgfVxuICAgICAgd2hpbGUgKHBvc2l0aW9uIDwgYXJndW1lbnRzLmxlbmd0aCkgYXJncy5wdXNoKGFyZ3VtZW50c1twb3NpdGlvbisrXSk7XG4gICAgICByZXR1cm4gZnVuYy5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICB9O1xuICB9O1xuXG4gIC8vIEJpbmQgYSBudW1iZXIgb2YgYW4gb2JqZWN0J3MgbWV0aG9kcyB0byB0aGF0IG9iamVjdC4gUmVtYWluaW5nIGFyZ3VtZW50c1xuICAvLyBhcmUgdGhlIG1ldGhvZCBuYW1lcyB0byBiZSBib3VuZC4gVXNlZnVsIGZvciBlbnN1cmluZyB0aGF0IGFsbCBjYWxsYmFja3NcbiAgLy8gZGVmaW5lZCBvbiBhbiBvYmplY3QgYmVsb25nIHRvIGl0LlxuICBfLmJpbmRBbGwgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgZnVuY3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgaWYgKGZ1bmNzLmxlbmd0aCA9PT0gMCkgdGhyb3cgbmV3IEVycm9yKCdiaW5kQWxsIG11c3QgYmUgcGFzc2VkIGZ1bmN0aW9uIG5hbWVzJyk7XG4gICAgZWFjaChmdW5jcywgZnVuY3Rpb24oZikgeyBvYmpbZl0gPSBfLmJpbmQob2JqW2ZdLCBvYmopOyB9KTtcbiAgICByZXR1cm4gb2JqO1xuICB9O1xuXG4gIC8vIE1lbW9pemUgYW4gZXhwZW5zaXZlIGZ1bmN0aW9uIGJ5IHN0b3JpbmcgaXRzIHJlc3VsdHMuXG4gIF8ubWVtb2l6ZSA9IGZ1bmN0aW9uKGZ1bmMsIGhhc2hlcikge1xuICAgIHZhciBtZW1vID0ge307XG4gICAgaGFzaGVyIHx8IChoYXNoZXIgPSBfLmlkZW50aXR5KTtcbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIga2V5ID0gaGFzaGVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICByZXR1cm4gXy5oYXMobWVtbywga2V5KSA/IG1lbW9ba2V5XSA6IChtZW1vW2tleV0gPSBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykpO1xuICAgIH07XG4gIH07XG5cbiAgLy8gRGVsYXlzIGEgZnVuY3Rpb24gZm9yIHRoZSBnaXZlbiBudW1iZXIgb2YgbWlsbGlzZWNvbmRzLCBhbmQgdGhlbiBjYWxsc1xuICAvLyBpdCB3aXRoIHRoZSBhcmd1bWVudHMgc3VwcGxpZWQuXG4gIF8uZGVsYXkgPSBmdW5jdGlvbihmdW5jLCB3YWl0KSB7XG4gICAgdmFyIGFyZ3MgPSBzbGljZS5jYWxsKGFyZ3VtZW50cywgMik7XG4gICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuY3Rpb24oKXsgcmV0dXJuIGZ1bmMuYXBwbHkobnVsbCwgYXJncyk7IH0sIHdhaXQpO1xuICB9O1xuXG4gIC8vIERlZmVycyBhIGZ1bmN0aW9uLCBzY2hlZHVsaW5nIGl0IHRvIHJ1biBhZnRlciB0aGUgY3VycmVudCBjYWxsIHN0YWNrIGhhc1xuICAvLyBjbGVhcmVkLlxuICBfLmRlZmVyID0gZnVuY3Rpb24oZnVuYykge1xuICAgIHJldHVybiBfLmRlbGF5LmFwcGx5KF8sIFtmdW5jLCAxXS5jb25jYXQoc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKSk7XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uLCB0aGF0LCB3aGVuIGludm9rZWQsIHdpbGwgb25seSBiZSB0cmlnZ2VyZWQgYXQgbW9zdCBvbmNlXG4gIC8vIGR1cmluZyBhIGdpdmVuIHdpbmRvdyBvZiB0aW1lLiBOb3JtYWxseSwgdGhlIHRocm90dGxlZCBmdW5jdGlvbiB3aWxsIHJ1blxuICAvLyBhcyBtdWNoIGFzIGl0IGNhbiwgd2l0aG91dCBldmVyIGdvaW5nIG1vcmUgdGhhbiBvbmNlIHBlciBgd2FpdGAgZHVyYXRpb247XG4gIC8vIGJ1dCBpZiB5b3UnZCBsaWtlIHRvIGRpc2FibGUgdGhlIGV4ZWN1dGlvbiBvbiB0aGUgbGVhZGluZyBlZGdlLCBwYXNzXG4gIC8vIGB7bGVhZGluZzogZmFsc2V9YC4gVG8gZGlzYWJsZSBleGVjdXRpb24gb24gdGhlIHRyYWlsaW5nIGVkZ2UsIGRpdHRvLlxuICBfLnRocm90dGxlID0gZnVuY3Rpb24oZnVuYywgd2FpdCwgb3B0aW9ucykge1xuICAgIHZhciBjb250ZXh0LCBhcmdzLCByZXN1bHQ7XG4gICAgdmFyIHRpbWVvdXQgPSBudWxsO1xuICAgIHZhciBwcmV2aW91cyA9IDA7XG4gICAgb3B0aW9ucyB8fCAob3B0aW9ucyA9IHt9KTtcbiAgICB2YXIgbGF0ZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgIHByZXZpb3VzID0gb3B0aW9ucy5sZWFkaW5nID09PSBmYWxzZSA/IDAgOiBfLm5vdygpO1xuICAgICAgdGltZW91dCA9IG51bGw7XG4gICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgY29udGV4dCA9IGFyZ3MgPSBudWxsO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIG5vdyA9IF8ubm93KCk7XG4gICAgICBpZiAoIXByZXZpb3VzICYmIG9wdGlvbnMubGVhZGluZyA9PT0gZmFsc2UpIHByZXZpb3VzID0gbm93O1xuICAgICAgdmFyIHJlbWFpbmluZyA9IHdhaXQgLSAobm93IC0gcHJldmlvdXMpO1xuICAgICAgY29udGV4dCA9IHRoaXM7XG4gICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgaWYgKHJlbWFpbmluZyA8PSAwKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgdGltZW91dCA9IG51bGw7XG4gICAgICAgIHByZXZpb3VzID0gbm93O1xuICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICBjb250ZXh0ID0gYXJncyA9IG51bGw7XG4gICAgICB9IGVsc2UgaWYgKCF0aW1lb3V0ICYmIG9wdGlvbnMudHJhaWxpbmcgIT09IGZhbHNlKSB7XG4gICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCByZW1haW5pbmcpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiwgdGhhdCwgYXMgbG9uZyBhcyBpdCBjb250aW51ZXMgdG8gYmUgaW52b2tlZCwgd2lsbCBub3RcbiAgLy8gYmUgdHJpZ2dlcmVkLiBUaGUgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgYWZ0ZXIgaXQgc3RvcHMgYmVpbmcgY2FsbGVkIGZvclxuICAvLyBOIG1pbGxpc2Vjb25kcy4gSWYgYGltbWVkaWF0ZWAgaXMgcGFzc2VkLCB0cmlnZ2VyIHRoZSBmdW5jdGlvbiBvbiB0aGVcbiAgLy8gbGVhZGluZyBlZGdlLCBpbnN0ZWFkIG9mIHRoZSB0cmFpbGluZy5cbiAgXy5kZWJvdW5jZSA9IGZ1bmN0aW9uKGZ1bmMsIHdhaXQsIGltbWVkaWF0ZSkge1xuICAgIHZhciB0aW1lb3V0LCBhcmdzLCBjb250ZXh0LCB0aW1lc3RhbXAsIHJlc3VsdDtcblxuICAgIHZhciBsYXRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGxhc3QgPSBfLm5vdygpIC0gdGltZXN0YW1wO1xuICAgICAgaWYgKGxhc3QgPCB3YWl0KSB7XG4gICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCB3YWl0IC0gbGFzdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aW1lb3V0ID0gbnVsbDtcbiAgICAgICAgaWYgKCFpbW1lZGlhdGUpIHtcbiAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgIGNvbnRleHQgPSBhcmdzID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICBjb250ZXh0ID0gdGhpcztcbiAgICAgIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICB0aW1lc3RhbXAgPSBfLm5vdygpO1xuICAgICAgdmFyIGNhbGxOb3cgPSBpbW1lZGlhdGUgJiYgIXRpbWVvdXQ7XG4gICAgICBpZiAoIXRpbWVvdXQpIHtcbiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQpO1xuICAgICAgfVxuICAgICAgaWYgKGNhbGxOb3cpIHtcbiAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTtcbiAgICAgICAgY29udGV4dCA9IGFyZ3MgPSBudWxsO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gIH07XG5cbiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBleGVjdXRlZCBhdCBtb3N0IG9uZSB0aW1lLCBubyBtYXR0ZXIgaG93XG4gIC8vIG9mdGVuIHlvdSBjYWxsIGl0LiBVc2VmdWwgZm9yIGxhenkgaW5pdGlhbGl6YXRpb24uXG4gIF8ub25jZSA9IGZ1bmN0aW9uKGZ1bmMpIHtcbiAgICB2YXIgcmFuID0gZmFsc2UsIG1lbW87XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKHJhbikgcmV0dXJuIG1lbW87XG4gICAgICByYW4gPSB0cnVlO1xuICAgICAgbWVtbyA9IGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIGZ1bmMgPSBudWxsO1xuICAgICAgcmV0dXJuIG1lbW87XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIHRoZSBmaXJzdCBmdW5jdGlvbiBwYXNzZWQgYXMgYW4gYXJndW1lbnQgdG8gdGhlIHNlY29uZCxcbiAgLy8gYWxsb3dpbmcgeW91IHRvIGFkanVzdCBhcmd1bWVudHMsIHJ1biBjb2RlIGJlZm9yZSBhbmQgYWZ0ZXIsIGFuZFxuICAvLyBjb25kaXRpb25hbGx5IGV4ZWN1dGUgdGhlIG9yaWdpbmFsIGZ1bmN0aW9uLlxuICBfLndyYXAgPSBmdW5jdGlvbihmdW5jLCB3cmFwcGVyKSB7XG4gICAgcmV0dXJuIF8ucGFydGlhbCh3cmFwcGVyLCBmdW5jKTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBpcyB0aGUgY29tcG9zaXRpb24gb2YgYSBsaXN0IG9mIGZ1bmN0aW9ucywgZWFjaFxuICAvLyBjb25zdW1pbmcgdGhlIHJldHVybiB2YWx1ZSBvZiB0aGUgZnVuY3Rpb24gdGhhdCBmb2xsb3dzLlxuICBfLmNvbXBvc2UgPSBmdW5jdGlvbigpIHtcbiAgICB2YXIgZnVuY3MgPSBhcmd1bWVudHM7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gICAgICBmb3IgKHZhciBpID0gZnVuY3MubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgYXJncyA9IFtmdW5jc1tpXS5hcHBseSh0aGlzLCBhcmdzKV07XG4gICAgICB9XG4gICAgICByZXR1cm4gYXJnc1swXTtcbiAgICB9O1xuICB9O1xuXG4gIC8vIFJldHVybnMgYSBmdW5jdGlvbiB0aGF0IHdpbGwgb25seSBiZSBleGVjdXRlZCBhZnRlciBiZWluZyBjYWxsZWQgTiB0aW1lcy5cbiAgXy5hZnRlciA9IGZ1bmN0aW9uKHRpbWVzLCBmdW5jKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKC0tdGltZXMgPCAxKSB7XG4gICAgICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICB9XG4gICAgfTtcbiAgfTtcblxuICAvLyBPYmplY3QgRnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS1cblxuICAvLyBSZXRyaWV2ZSB0aGUgbmFtZXMgb2YgYW4gb2JqZWN0J3MgcHJvcGVydGllcy5cbiAgLy8gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYE9iamVjdC5rZXlzYFxuICBfLmtleXMgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAoIV8uaXNPYmplY3Qob2JqKSkgcmV0dXJuIFtdO1xuICAgIGlmIChuYXRpdmVLZXlzKSByZXR1cm4gbmF0aXZlS2V5cyhvYmopO1xuICAgIHZhciBrZXlzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikgaWYgKF8uaGFzKG9iaiwga2V5KSkga2V5cy5wdXNoKGtleSk7XG4gICAgcmV0dXJuIGtleXM7XG4gIH07XG5cbiAgLy8gUmV0cmlldmUgdGhlIHZhbHVlcyBvZiBhbiBvYmplY3QncyBwcm9wZXJ0aWVzLlxuICBfLnZhbHVlcyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7XG4gICAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoO1xuICAgIHZhciB2YWx1ZXMgPSBuZXcgQXJyYXkobGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICB2YWx1ZXNbaV0gPSBvYmpba2V5c1tpXV07XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZXM7XG4gIH07XG5cbiAgLy8gQ29udmVydCBhbiBvYmplY3QgaW50byBhIGxpc3Qgb2YgYFtrZXksIHZhbHVlXWAgcGFpcnMuXG4gIF8ucGFpcnMgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xuICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgICB2YXIgcGFpcnMgPSBuZXcgQXJyYXkobGVuZ3RoKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICBwYWlyc1tpXSA9IFtrZXlzW2ldLCBvYmpba2V5c1tpXV1dO1xuICAgIH1cbiAgICByZXR1cm4gcGFpcnM7XG4gIH07XG5cbiAgLy8gSW52ZXJ0IHRoZSBrZXlzIGFuZCB2YWx1ZXMgb2YgYW4gb2JqZWN0LiBUaGUgdmFsdWVzIG11c3QgYmUgc2VyaWFsaXphYmxlLlxuICBfLmludmVydCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciByZXN1bHQgPSB7fTtcbiAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopO1xuICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBrZXlzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICByZXN1bHRbb2JqW2tleXNbaV1dXSA9IGtleXNbaV07XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgLy8gUmV0dXJuIGEgc29ydGVkIGxpc3Qgb2YgdGhlIGZ1bmN0aW9uIG5hbWVzIGF2YWlsYWJsZSBvbiB0aGUgb2JqZWN0LlxuICAvLyBBbGlhc2VkIGFzIGBtZXRob2RzYFxuICBfLmZ1bmN0aW9ucyA9IF8ubWV0aG9kcyA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHZhciBuYW1lcyA9IFtdO1xuICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgIGlmIChfLmlzRnVuY3Rpb24ob2JqW2tleV0pKSBuYW1lcy5wdXNoKGtleSk7XG4gICAgfVxuICAgIHJldHVybiBuYW1lcy5zb3J0KCk7XG4gIH07XG5cbiAgLy8gRXh0ZW5kIGEgZ2l2ZW4gb2JqZWN0IHdpdGggYWxsIHRoZSBwcm9wZXJ0aWVzIGluIHBhc3NlZC1pbiBvYmplY3QocykuXG4gIF8uZXh0ZW5kID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgZWFjaChzbGljZS5jYWxsKGFyZ3VtZW50cywgMSksIGZ1bmN0aW9uKHNvdXJjZSkge1xuICAgICAgaWYgKHNvdXJjZSkge1xuICAgICAgICBmb3IgKHZhciBwcm9wIGluIHNvdXJjZSkge1xuICAgICAgICAgIG9ialtwcm9wXSA9IHNvdXJjZVtwcm9wXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBvYmo7XG4gIH07XG5cbiAgLy8gUmV0dXJuIGEgY29weSBvZiB0aGUgb2JqZWN0IG9ubHkgY29udGFpbmluZyB0aGUgd2hpdGVsaXN0ZWQgcHJvcGVydGllcy5cbiAgXy5waWNrID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgdmFyIGNvcHkgPSB7fTtcbiAgICB2YXIga2V5cyA9IGNvbmNhdC5hcHBseShBcnJheVByb3RvLCBzbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuICAgIGVhY2goa2V5cywgZnVuY3Rpb24oa2V5KSB7XG4gICAgICBpZiAoa2V5IGluIG9iaikgY29weVtrZXldID0gb2JqW2tleV07XG4gICAgfSk7XG4gICAgcmV0dXJuIGNvcHk7XG4gIH07XG5cbiAgIC8vIFJldHVybiBhIGNvcHkgb2YgdGhlIG9iamVjdCB3aXRob3V0IHRoZSBibGFja2xpc3RlZCBwcm9wZXJ0aWVzLlxuICBfLm9taXQgPSBmdW5jdGlvbihvYmopIHtcbiAgICB2YXIgY29weSA9IHt9O1xuICAgIHZhciBrZXlzID0gY29uY2F0LmFwcGx5KEFycmF5UHJvdG8sIHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgaWYgKCFfLmNvbnRhaW5zKGtleXMsIGtleSkpIGNvcHlba2V5XSA9IG9ialtrZXldO1xuICAgIH1cbiAgICByZXR1cm4gY29weTtcbiAgfTtcblxuICAvLyBGaWxsIGluIGEgZ2l2ZW4gb2JqZWN0IHdpdGggZGVmYXVsdCBwcm9wZXJ0aWVzLlxuICBfLmRlZmF1bHRzID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgZWFjaChzbGljZS5jYWxsKGFyZ3VtZW50cywgMSksIGZ1bmN0aW9uKHNvdXJjZSkge1xuICAgICAgaWYgKHNvdXJjZSkge1xuICAgICAgICBmb3IgKHZhciBwcm9wIGluIHNvdXJjZSkge1xuICAgICAgICAgIGlmIChvYmpbcHJvcF0gPT09IHZvaWQgMCkgb2JqW3Byb3BdID0gc291cmNlW3Byb3BdO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIG9iajtcbiAgfTtcblxuICAvLyBDcmVhdGUgYSAoc2hhbGxvdy1jbG9uZWQpIGR1cGxpY2F0ZSBvZiBhbiBvYmplY3QuXG4gIF8uY2xvbmUgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAoIV8uaXNPYmplY3Qob2JqKSkgcmV0dXJuIG9iajtcbiAgICByZXR1cm4gXy5pc0FycmF5KG9iaikgPyBvYmouc2xpY2UoKSA6IF8uZXh0ZW5kKHt9LCBvYmopO1xuICB9O1xuXG4gIC8vIEludm9rZXMgaW50ZXJjZXB0b3Igd2l0aCB0aGUgb2JqLCBhbmQgdGhlbiByZXR1cm5zIG9iai5cbiAgLy8gVGhlIHByaW1hcnkgcHVycG9zZSBvZiB0aGlzIG1ldGhvZCBpcyB0byBcInRhcCBpbnRvXCIgYSBtZXRob2QgY2hhaW4sIGluXG4gIC8vIG9yZGVyIHRvIHBlcmZvcm0gb3BlcmF0aW9ucyBvbiBpbnRlcm1lZGlhdGUgcmVzdWx0cyB3aXRoaW4gdGhlIGNoYWluLlxuICBfLnRhcCA9IGZ1bmN0aW9uKG9iaiwgaW50ZXJjZXB0b3IpIHtcbiAgICBpbnRlcmNlcHRvcihvYmopO1xuICAgIHJldHVybiBvYmo7XG4gIH07XG5cbiAgLy8gSW50ZXJuYWwgcmVjdXJzaXZlIGNvbXBhcmlzb24gZnVuY3Rpb24gZm9yIGBpc0VxdWFsYC5cbiAgdmFyIGVxID0gZnVuY3Rpb24oYSwgYiwgYVN0YWNrLCBiU3RhY2spIHtcbiAgICAvLyBJZGVudGljYWwgb2JqZWN0cyBhcmUgZXF1YWwuIGAwID09PSAtMGAsIGJ1dCB0aGV5IGFyZW4ndCBpZGVudGljYWwuXG4gICAgLy8gU2VlIHRoZSBbSGFybW9ueSBgZWdhbGAgcHJvcG9zYWxdKGh0dHA6Ly93aWtpLmVjbWFzY3JpcHQub3JnL2Rva3UucGhwP2lkPWhhcm1vbnk6ZWdhbCkuXG4gICAgaWYgKGEgPT09IGIpIHJldHVybiBhICE9PSAwIHx8IDEgLyBhID09IDEgLyBiO1xuICAgIC8vIEEgc3RyaWN0IGNvbXBhcmlzb24gaXMgbmVjZXNzYXJ5IGJlY2F1c2UgYG51bGwgPT0gdW5kZWZpbmVkYC5cbiAgICBpZiAoYSA9PSBudWxsIHx8IGIgPT0gbnVsbCkgcmV0dXJuIGEgPT09IGI7XG4gICAgLy8gVW53cmFwIGFueSB3cmFwcGVkIG9iamVjdHMuXG4gICAgaWYgKGEgaW5zdGFuY2VvZiBfKSBhID0gYS5fd3JhcHBlZDtcbiAgICBpZiAoYiBpbnN0YW5jZW9mIF8pIGIgPSBiLl93cmFwcGVkO1xuICAgIC8vIENvbXBhcmUgYFtbQ2xhc3NdXWAgbmFtZXMuXG4gICAgdmFyIGNsYXNzTmFtZSA9IHRvU3RyaW5nLmNhbGwoYSk7XG4gICAgaWYgKGNsYXNzTmFtZSAhPSB0b1N0cmluZy5jYWxsKGIpKSByZXR1cm4gZmFsc2U7XG4gICAgc3dpdGNoIChjbGFzc05hbWUpIHtcbiAgICAgIC8vIFN0cmluZ3MsIG51bWJlcnMsIGRhdGVzLCBhbmQgYm9vbGVhbnMgYXJlIGNvbXBhcmVkIGJ5IHZhbHVlLlxuICAgICAgY2FzZSAnW29iamVjdCBTdHJpbmddJzpcbiAgICAgICAgLy8gUHJpbWl0aXZlcyBhbmQgdGhlaXIgY29ycmVzcG9uZGluZyBvYmplY3Qgd3JhcHBlcnMgYXJlIGVxdWl2YWxlbnQ7IHRodXMsIGBcIjVcImAgaXNcbiAgICAgICAgLy8gZXF1aXZhbGVudCB0byBgbmV3IFN0cmluZyhcIjVcIilgLlxuICAgICAgICByZXR1cm4gYSA9PSBTdHJpbmcoYik7XG4gICAgICBjYXNlICdbb2JqZWN0IE51bWJlcl0nOlxuICAgICAgICAvLyBgTmFOYHMgYXJlIGVxdWl2YWxlbnQsIGJ1dCBub24tcmVmbGV4aXZlLiBBbiBgZWdhbGAgY29tcGFyaXNvbiBpcyBwZXJmb3JtZWQgZm9yXG4gICAgICAgIC8vIG90aGVyIG51bWVyaWMgdmFsdWVzLlxuICAgICAgICByZXR1cm4gYSAhPSArYSA/IGIgIT0gK2IgOiAoYSA9PSAwID8gMSAvIGEgPT0gMSAvIGIgOiBhID09ICtiKTtcbiAgICAgIGNhc2UgJ1tvYmplY3QgRGF0ZV0nOlxuICAgICAgY2FzZSAnW29iamVjdCBCb29sZWFuXSc6XG4gICAgICAgIC8vIENvZXJjZSBkYXRlcyBhbmQgYm9vbGVhbnMgdG8gbnVtZXJpYyBwcmltaXRpdmUgdmFsdWVzLiBEYXRlcyBhcmUgY29tcGFyZWQgYnkgdGhlaXJcbiAgICAgICAgLy8gbWlsbGlzZWNvbmQgcmVwcmVzZW50YXRpb25zLiBOb3RlIHRoYXQgaW52YWxpZCBkYXRlcyB3aXRoIG1pbGxpc2Vjb25kIHJlcHJlc2VudGF0aW9uc1xuICAgICAgICAvLyBvZiBgTmFOYCBhcmUgbm90IGVxdWl2YWxlbnQuXG4gICAgICAgIHJldHVybiArYSA9PSArYjtcbiAgICAgIC8vIFJlZ0V4cHMgYXJlIGNvbXBhcmVkIGJ5IHRoZWlyIHNvdXJjZSBwYXR0ZXJucyBhbmQgZmxhZ3MuXG4gICAgICBjYXNlICdbb2JqZWN0IFJlZ0V4cF0nOlxuICAgICAgICByZXR1cm4gYS5zb3VyY2UgPT0gYi5zb3VyY2UgJiZcbiAgICAgICAgICAgICAgIGEuZ2xvYmFsID09IGIuZ2xvYmFsICYmXG4gICAgICAgICAgICAgICBhLm11bHRpbGluZSA9PSBiLm11bHRpbGluZSAmJlxuICAgICAgICAgICAgICAgYS5pZ25vcmVDYXNlID09IGIuaWdub3JlQ2FzZTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBhICE9ICdvYmplY3QnIHx8IHR5cGVvZiBiICE9ICdvYmplY3QnKSByZXR1cm4gZmFsc2U7XG4gICAgLy8gQXNzdW1lIGVxdWFsaXR5IGZvciBjeWNsaWMgc3RydWN0dXJlcy4gVGhlIGFsZ29yaXRobSBmb3IgZGV0ZWN0aW5nIGN5Y2xpY1xuICAgIC8vIHN0cnVjdHVyZXMgaXMgYWRhcHRlZCBmcm9tIEVTIDUuMSBzZWN0aW9uIDE1LjEyLjMsIGFic3RyYWN0IG9wZXJhdGlvbiBgSk9gLlxuICAgIHZhciBsZW5ndGggPSBhU3RhY2subGVuZ3RoO1xuICAgIHdoaWxlIChsZW5ndGgtLSkge1xuICAgICAgLy8gTGluZWFyIHNlYXJjaC4gUGVyZm9ybWFuY2UgaXMgaW52ZXJzZWx5IHByb3BvcnRpb25hbCB0byB0aGUgbnVtYmVyIG9mXG4gICAgICAvLyB1bmlxdWUgbmVzdGVkIHN0cnVjdHVyZXMuXG4gICAgICBpZiAoYVN0YWNrW2xlbmd0aF0gPT0gYSkgcmV0dXJuIGJTdGFja1tsZW5ndGhdID09IGI7XG4gICAgfVxuICAgIC8vIE9iamVjdHMgd2l0aCBkaWZmZXJlbnQgY29uc3RydWN0b3JzIGFyZSBub3QgZXF1aXZhbGVudCwgYnV0IGBPYmplY3Rgc1xuICAgIC8vIGZyb20gZGlmZmVyZW50IGZyYW1lcyBhcmUuXG4gICAgdmFyIGFDdG9yID0gYS5jb25zdHJ1Y3RvciwgYkN0b3IgPSBiLmNvbnN0cnVjdG9yO1xuICAgIGlmIChhQ3RvciAhPT0gYkN0b3IgJiYgIShfLmlzRnVuY3Rpb24oYUN0b3IpICYmIChhQ3RvciBpbnN0YW5jZW9mIGFDdG9yKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfLmlzRnVuY3Rpb24oYkN0b3IpICYmIChiQ3RvciBpbnN0YW5jZW9mIGJDdG9yKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICYmICgnY29uc3RydWN0b3InIGluIGEgJiYgJ2NvbnN0cnVjdG9yJyBpbiBiKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICAvLyBBZGQgdGhlIGZpcnN0IG9iamVjdCB0byB0aGUgc3RhY2sgb2YgdHJhdmVyc2VkIG9iamVjdHMuXG4gICAgYVN0YWNrLnB1c2goYSk7XG4gICAgYlN0YWNrLnB1c2goYik7XG4gICAgdmFyIHNpemUgPSAwLCByZXN1bHQgPSB0cnVlO1xuICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbXBhcmUgb2JqZWN0cyBhbmQgYXJyYXlzLlxuICAgIGlmIChjbGFzc05hbWUgPT0gJ1tvYmplY3QgQXJyYXldJykge1xuICAgICAgLy8gQ29tcGFyZSBhcnJheSBsZW5ndGhzIHRvIGRldGVybWluZSBpZiBhIGRlZXAgY29tcGFyaXNvbiBpcyBuZWNlc3NhcnkuXG4gICAgICBzaXplID0gYS5sZW5ndGg7XG4gICAgICByZXN1bHQgPSBzaXplID09IGIubGVuZ3RoO1xuICAgICAgaWYgKHJlc3VsdCkge1xuICAgICAgICAvLyBEZWVwIGNvbXBhcmUgdGhlIGNvbnRlbnRzLCBpZ25vcmluZyBub24tbnVtZXJpYyBwcm9wZXJ0aWVzLlxuICAgICAgICB3aGlsZSAoc2l6ZS0tKSB7XG4gICAgICAgICAgaWYgKCEocmVzdWx0ID0gZXEoYVtzaXplXSwgYltzaXplXSwgYVN0YWNrLCBiU3RhY2spKSkgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gRGVlcCBjb21wYXJlIG9iamVjdHMuXG4gICAgICBmb3IgKHZhciBrZXkgaW4gYSkge1xuICAgICAgICBpZiAoXy5oYXMoYSwga2V5KSkge1xuICAgICAgICAgIC8vIENvdW50IHRoZSBleHBlY3RlZCBudW1iZXIgb2YgcHJvcGVydGllcy5cbiAgICAgICAgICBzaXplKys7XG4gICAgICAgICAgLy8gRGVlcCBjb21wYXJlIGVhY2ggbWVtYmVyLlxuICAgICAgICAgIGlmICghKHJlc3VsdCA9IF8uaGFzKGIsIGtleSkgJiYgZXEoYVtrZXldLCBiW2tleV0sIGFTdGFjaywgYlN0YWNrKSkpIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICAvLyBFbnN1cmUgdGhhdCBib3RoIG9iamVjdHMgY29udGFpbiB0aGUgc2FtZSBudW1iZXIgb2YgcHJvcGVydGllcy5cbiAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgZm9yIChrZXkgaW4gYikge1xuICAgICAgICAgIGlmIChfLmhhcyhiLCBrZXkpICYmICEoc2l6ZS0tKSkgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0ID0gIXNpemU7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFJlbW92ZSB0aGUgZmlyc3Qgb2JqZWN0IGZyb20gdGhlIHN0YWNrIG9mIHRyYXZlcnNlZCBvYmplY3RzLlxuICAgIGFTdGFjay5wb3AoKTtcbiAgICBiU3RhY2sucG9wKCk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcblxuICAvLyBQZXJmb3JtIGEgZGVlcCBjb21wYXJpc29uIHRvIGNoZWNrIGlmIHR3byBvYmplY3RzIGFyZSBlcXVhbC5cbiAgXy5pc0VxdWFsID0gZnVuY3Rpb24oYSwgYikge1xuICAgIHJldHVybiBlcShhLCBiLCBbXSwgW10pO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gYXJyYXksIHN0cmluZywgb3Igb2JqZWN0IGVtcHR5P1xuICAvLyBBbiBcImVtcHR5XCIgb2JqZWN0IGhhcyBubyBlbnVtZXJhYmxlIG93bi1wcm9wZXJ0aWVzLlxuICBfLmlzRW1wdHkgPSBmdW5jdGlvbihvYmopIHtcbiAgICBpZiAob2JqID09IG51bGwpIHJldHVybiB0cnVlO1xuICAgIGlmIChfLmlzQXJyYXkob2JqKSB8fCBfLmlzU3RyaW5nKG9iaikpIHJldHVybiBvYmoubGVuZ3RoID09PSAwO1xuICAgIGZvciAodmFyIGtleSBpbiBvYmopIGlmIChfLmhhcyhvYmosIGtleSkpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcblxuICAvLyBJcyBhIGdpdmVuIHZhbHVlIGEgRE9NIGVsZW1lbnQ/XG4gIF8uaXNFbGVtZW50ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuICEhKG9iaiAmJiBvYmoubm9kZVR5cGUgPT09IDEpO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFsdWUgYW4gYXJyYXk/XG4gIC8vIERlbGVnYXRlcyB0byBFQ01BNSdzIG5hdGl2ZSBBcnJheS5pc0FycmF5XG4gIF8uaXNBcnJheSA9IG5hdGl2ZUlzQXJyYXkgfHwgZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PSAnW29iamVjdCBBcnJheV0nO1xuICB9O1xuXG4gIC8vIElzIGEgZ2l2ZW4gdmFyaWFibGUgYW4gb2JqZWN0P1xuICBfLmlzT2JqZWN0ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIG9iaiA9PT0gT2JqZWN0KG9iaik7XG4gIH07XG5cbiAgLy8gQWRkIHNvbWUgaXNUeXBlIG1ldGhvZHM6IGlzQXJndW1lbnRzLCBpc0Z1bmN0aW9uLCBpc1N0cmluZywgaXNOdW1iZXIsIGlzRGF0ZSwgaXNSZWdFeHAuXG4gIGVhY2goWydBcmd1bWVudHMnLCAnRnVuY3Rpb24nLCAnU3RyaW5nJywgJ051bWJlcicsICdEYXRlJywgJ1JlZ0V4cCddLCBmdW5jdGlvbihuYW1lKSB7XG4gICAgX1snaXMnICsgbmFtZV0gPSBmdW5jdGlvbihvYmopIHtcbiAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT0gJ1tvYmplY3QgJyArIG5hbWUgKyAnXSc7XG4gICAgfTtcbiAgfSk7XG5cbiAgLy8gRGVmaW5lIGEgZmFsbGJhY2sgdmVyc2lvbiBvZiB0aGUgbWV0aG9kIGluIGJyb3dzZXJzIChhaGVtLCBJRSksIHdoZXJlXG4gIC8vIHRoZXJlIGlzbid0IGFueSBpbnNwZWN0YWJsZSBcIkFyZ3VtZW50c1wiIHR5cGUuXG4gIGlmICghXy5pc0FyZ3VtZW50cyhhcmd1bWVudHMpKSB7XG4gICAgXy5pc0FyZ3VtZW50cyA9IGZ1bmN0aW9uKG9iaikge1xuICAgICAgcmV0dXJuICEhKG9iaiAmJiBfLmhhcyhvYmosICdjYWxsZWUnKSk7XG4gICAgfTtcbiAgfVxuXG4gIC8vIE9wdGltaXplIGBpc0Z1bmN0aW9uYCBpZiBhcHByb3ByaWF0ZS5cbiAgaWYgKHR5cGVvZiAoLy4vKSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIF8uaXNGdW5jdGlvbiA9IGZ1bmN0aW9uKG9iaikge1xuICAgICAgcmV0dXJuIHR5cGVvZiBvYmogPT09ICdmdW5jdGlvbic7XG4gICAgfTtcbiAgfVxuXG4gIC8vIElzIGEgZ2l2ZW4gb2JqZWN0IGEgZmluaXRlIG51bWJlcj9cbiAgXy5pc0Zpbml0ZSA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBpc0Zpbml0ZShvYmopICYmICFpc05hTihwYXJzZUZsb2F0KG9iaikpO1xuICB9O1xuXG4gIC8vIElzIHRoZSBnaXZlbiB2YWx1ZSBgTmFOYD8gKE5hTiBpcyB0aGUgb25seSBudW1iZXIgd2hpY2ggZG9lcyBub3QgZXF1YWwgaXRzZWxmKS5cbiAgXy5pc05hTiA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBfLmlzTnVtYmVyKG9iaikgJiYgb2JqICE9ICtvYmo7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YWx1ZSBhIGJvb2xlYW4/XG4gIF8uaXNCb29sZWFuID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIG9iaiA9PT0gdHJ1ZSB8fCBvYmogPT09IGZhbHNlIHx8IHRvU3RyaW5nLmNhbGwob2JqKSA9PSAnW29iamVjdCBCb29sZWFuXSc7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YWx1ZSBlcXVhbCB0byBudWxsP1xuICBfLmlzTnVsbCA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBvYmogPT09IG51bGw7XG4gIH07XG5cbiAgLy8gSXMgYSBnaXZlbiB2YXJpYWJsZSB1bmRlZmluZWQ/XG4gIF8uaXNVbmRlZmluZWQgPSBmdW5jdGlvbihvYmopIHtcbiAgICByZXR1cm4gb2JqID09PSB2b2lkIDA7XG4gIH07XG5cbiAgLy8gU2hvcnRjdXQgZnVuY3Rpb24gZm9yIGNoZWNraW5nIGlmIGFuIG9iamVjdCBoYXMgYSBnaXZlbiBwcm9wZXJ0eSBkaXJlY3RseVxuICAvLyBvbiBpdHNlbGYgKGluIG90aGVyIHdvcmRzLCBub3Qgb24gYSBwcm90b3R5cGUpLlxuICBfLmhhcyA9IGZ1bmN0aW9uKG9iaiwga2V5KSB7XG4gICAgcmV0dXJuIGhhc093blByb3BlcnR5LmNhbGwob2JqLCBrZXkpO1xuICB9O1xuXG4gIC8vIFV0aWxpdHkgRnVuY3Rpb25zXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLy8gUnVuIFVuZGVyc2NvcmUuanMgaW4gKm5vQ29uZmxpY3QqIG1vZGUsIHJldHVybmluZyB0aGUgYF9gIHZhcmlhYmxlIHRvIGl0c1xuICAvLyBwcmV2aW91cyBvd25lci4gUmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGUgVW5kZXJzY29yZSBvYmplY3QuXG4gIF8ubm9Db25mbGljdCA9IGZ1bmN0aW9uKCkge1xuICAgIHJvb3QuXyA9IHByZXZpb3VzVW5kZXJzY29yZTtcbiAgICByZXR1cm4gdGhpcztcbiAgfTtcblxuICAvLyBLZWVwIHRoZSBpZGVudGl0eSBmdW5jdGlvbiBhcm91bmQgZm9yIGRlZmF1bHQgaXRlcmF0b3JzLlxuICBfLmlkZW50aXR5ID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH07XG5cbiAgXy5jb25zdGFudCA9IGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9O1xuICB9O1xuXG4gIF8ucHJvcGVydHkgPSBmdW5jdGlvbihrZXkpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24ob2JqKSB7XG4gICAgICByZXR1cm4gb2JqW2tleV07XG4gICAgfTtcbiAgfTtcblxuICAvLyBSZXR1cm5zIGEgcHJlZGljYXRlIGZvciBjaGVja2luZyB3aGV0aGVyIGFuIG9iamVjdCBoYXMgYSBnaXZlbiBzZXQgb2YgYGtleTp2YWx1ZWAgcGFpcnMuXG4gIF8ubWF0Y2hlcyA9IGZ1bmN0aW9uKGF0dHJzKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uKG9iaikge1xuICAgICAgaWYgKG9iaiA9PT0gYXR0cnMpIHJldHVybiB0cnVlOyAvL2F2b2lkIGNvbXBhcmluZyBhbiBvYmplY3QgdG8gaXRzZWxmLlxuICAgICAgZm9yICh2YXIga2V5IGluIGF0dHJzKSB7XG4gICAgICAgIGlmIChhdHRyc1trZXldICE9PSBvYmpba2V5XSlcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH07XG5cbiAgLy8gUnVuIGEgZnVuY3Rpb24gKipuKiogdGltZXMuXG4gIF8udGltZXMgPSBmdW5jdGlvbihuLCBpdGVyYXRvciwgY29udGV4dCkge1xuICAgIHZhciBhY2N1bSA9IEFycmF5KE1hdGgubWF4KDAsIG4pKTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykgYWNjdW1baV0gPSBpdGVyYXRvci5jYWxsKGNvbnRleHQsIGkpO1xuICAgIHJldHVybiBhY2N1bTtcbiAgfTtcblxuICAvLyBSZXR1cm4gYSByYW5kb20gaW50ZWdlciBiZXR3ZWVuIG1pbiBhbmQgbWF4IChpbmNsdXNpdmUpLlxuICBfLnJhbmRvbSA9IGZ1bmN0aW9uKG1pbiwgbWF4KSB7XG4gICAgaWYgKG1heCA9PSBudWxsKSB7XG4gICAgICBtYXggPSBtaW47XG4gICAgICBtaW4gPSAwO1xuICAgIH1cbiAgICByZXR1cm4gbWluICsgTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogKG1heCAtIG1pbiArIDEpKTtcbiAgfTtcblxuICAvLyBBIChwb3NzaWJseSBmYXN0ZXIpIHdheSB0byBnZXQgdGhlIGN1cnJlbnQgdGltZXN0YW1wIGFzIGFuIGludGVnZXIuXG4gIF8ubm93ID0gRGF0ZS5ub3cgfHwgZnVuY3Rpb24oKSB7IHJldHVybiBuZXcgRGF0ZSgpLmdldFRpbWUoKTsgfTtcblxuICAvLyBMaXN0IG9mIEhUTUwgZW50aXRpZXMgZm9yIGVzY2FwaW5nLlxuICB2YXIgZW50aXR5TWFwID0ge1xuICAgIGVzY2FwZToge1xuICAgICAgJyYnOiAnJmFtcDsnLFxuICAgICAgJzwnOiAnJmx0OycsXG4gICAgICAnPic6ICcmZ3Q7JyxcbiAgICAgICdcIic6ICcmcXVvdDsnLFxuICAgICAgXCInXCI6ICcmI3gyNzsnXG4gICAgfVxuICB9O1xuICBlbnRpdHlNYXAudW5lc2NhcGUgPSBfLmludmVydChlbnRpdHlNYXAuZXNjYXBlKTtcblxuICAvLyBSZWdleGVzIGNvbnRhaW5pbmcgdGhlIGtleXMgYW5kIHZhbHVlcyBsaXN0ZWQgaW1tZWRpYXRlbHkgYWJvdmUuXG4gIHZhciBlbnRpdHlSZWdleGVzID0ge1xuICAgIGVzY2FwZTogICBuZXcgUmVnRXhwKCdbJyArIF8ua2V5cyhlbnRpdHlNYXAuZXNjYXBlKS5qb2luKCcnKSArICddJywgJ2cnKSxcbiAgICB1bmVzY2FwZTogbmV3IFJlZ0V4cCgnKCcgKyBfLmtleXMoZW50aXR5TWFwLnVuZXNjYXBlKS5qb2luKCd8JykgKyAnKScsICdnJylcbiAgfTtcblxuICAvLyBGdW5jdGlvbnMgZm9yIGVzY2FwaW5nIGFuZCB1bmVzY2FwaW5nIHN0cmluZ3MgdG8vZnJvbSBIVE1MIGludGVycG9sYXRpb24uXG4gIF8uZWFjaChbJ2VzY2FwZScsICd1bmVzY2FwZSddLCBmdW5jdGlvbihtZXRob2QpIHtcbiAgICBfW21ldGhvZF0gPSBmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgIGlmIChzdHJpbmcgPT0gbnVsbCkgcmV0dXJuICcnO1xuICAgICAgcmV0dXJuICgnJyArIHN0cmluZykucmVwbGFjZShlbnRpdHlSZWdleGVzW21ldGhvZF0sIGZ1bmN0aW9uKG1hdGNoKSB7XG4gICAgICAgIHJldHVybiBlbnRpdHlNYXBbbWV0aG9kXVttYXRjaF07XG4gICAgICB9KTtcbiAgICB9O1xuICB9KTtcblxuICAvLyBJZiB0aGUgdmFsdWUgb2YgdGhlIG5hbWVkIGBwcm9wZXJ0eWAgaXMgYSBmdW5jdGlvbiB0aGVuIGludm9rZSBpdCB3aXRoIHRoZVxuICAvLyBgb2JqZWN0YCBhcyBjb250ZXh0OyBvdGhlcndpc2UsIHJldHVybiBpdC5cbiAgXy5yZXN1bHQgPSBmdW5jdGlvbihvYmplY3QsIHByb3BlcnR5KSB7XG4gICAgaWYgKG9iamVjdCA9PSBudWxsKSByZXR1cm4gdm9pZCAwO1xuICAgIHZhciB2YWx1ZSA9IG9iamVjdFtwcm9wZXJ0eV07XG4gICAgcmV0dXJuIF8uaXNGdW5jdGlvbih2YWx1ZSkgPyB2YWx1ZS5jYWxsKG9iamVjdCkgOiB2YWx1ZTtcbiAgfTtcblxuICAvLyBBZGQgeW91ciBvd24gY3VzdG9tIGZ1bmN0aW9ucyB0byB0aGUgVW5kZXJzY29yZSBvYmplY3QuXG4gIF8ubWl4aW4gPSBmdW5jdGlvbihvYmopIHtcbiAgICBlYWNoKF8uZnVuY3Rpb25zKG9iaiksIGZ1bmN0aW9uKG5hbWUpIHtcbiAgICAgIHZhciBmdW5jID0gX1tuYW1lXSA9IG9ialtuYW1lXTtcbiAgICAgIF8ucHJvdG90eXBlW25hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBhcmdzID0gW3RoaXMuX3dyYXBwZWRdO1xuICAgICAgICBwdXNoLmFwcGx5KGFyZ3MsIGFyZ3VtZW50cyk7XG4gICAgICAgIHJldHVybiByZXN1bHQuY2FsbCh0aGlzLCBmdW5jLmFwcGx5KF8sIGFyZ3MpKTtcbiAgICAgIH07XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gR2VuZXJhdGUgYSB1bmlxdWUgaW50ZWdlciBpZCAodW5pcXVlIHdpdGhpbiB0aGUgZW50aXJlIGNsaWVudCBzZXNzaW9uKS5cbiAgLy8gVXNlZnVsIGZvciB0ZW1wb3JhcnkgRE9NIGlkcy5cbiAgdmFyIGlkQ291bnRlciA9IDA7XG4gIF8udW5pcXVlSWQgPSBmdW5jdGlvbihwcmVmaXgpIHtcbiAgICB2YXIgaWQgPSArK2lkQ291bnRlciArICcnO1xuICAgIHJldHVybiBwcmVmaXggPyBwcmVmaXggKyBpZCA6IGlkO1xuICB9O1xuXG4gIC8vIEJ5IGRlZmF1bHQsIFVuZGVyc2NvcmUgdXNlcyBFUkItc3R5bGUgdGVtcGxhdGUgZGVsaW1pdGVycywgY2hhbmdlIHRoZVxuICAvLyBmb2xsb3dpbmcgdGVtcGxhdGUgc2V0dGluZ3MgdG8gdXNlIGFsdGVybmF0aXZlIGRlbGltaXRlcnMuXG4gIF8udGVtcGxhdGVTZXR0aW5ncyA9IHtcbiAgICBldmFsdWF0ZSAgICA6IC88JShbXFxzXFxTXSs/KSU+L2csXG4gICAgaW50ZXJwb2xhdGUgOiAvPCU9KFtcXHNcXFNdKz8pJT4vZyxcbiAgICBlc2NhcGUgICAgICA6IC88JS0oW1xcc1xcU10rPyklPi9nXG4gIH07XG5cbiAgLy8gV2hlbiBjdXN0b21pemluZyBgdGVtcGxhdGVTZXR0aW5nc2AsIGlmIHlvdSBkb24ndCB3YW50IHRvIGRlZmluZSBhblxuICAvLyBpbnRlcnBvbGF0aW9uLCBldmFsdWF0aW9uIG9yIGVzY2FwaW5nIHJlZ2V4LCB3ZSBuZWVkIG9uZSB0aGF0IGlzXG4gIC8vIGd1YXJhbnRlZWQgbm90IHRvIG1hdGNoLlxuICB2YXIgbm9NYXRjaCA9IC8oLileLztcblxuICAvLyBDZXJ0YWluIGNoYXJhY3RlcnMgbmVlZCB0byBiZSBlc2NhcGVkIHNvIHRoYXQgdGhleSBjYW4gYmUgcHV0IGludG8gYVxuICAvLyBzdHJpbmcgbGl0ZXJhbC5cbiAgdmFyIGVzY2FwZXMgPSB7XG4gICAgXCInXCI6ICAgICAgXCInXCIsXG4gICAgJ1xcXFwnOiAgICAgJ1xcXFwnLFxuICAgICdcXHInOiAgICAgJ3InLFxuICAgICdcXG4nOiAgICAgJ24nLFxuICAgICdcXHQnOiAgICAgJ3QnLFxuICAgICdcXHUyMDI4JzogJ3UyMDI4JyxcbiAgICAnXFx1MjAyOSc6ICd1MjAyOSdcbiAgfTtcblxuICB2YXIgZXNjYXBlciA9IC9cXFxcfCd8XFxyfFxcbnxcXHR8XFx1MjAyOHxcXHUyMDI5L2c7XG5cbiAgLy8gSmF2YVNjcmlwdCBtaWNyby10ZW1wbGF0aW5nLCBzaW1pbGFyIHRvIEpvaG4gUmVzaWcncyBpbXBsZW1lbnRhdGlvbi5cbiAgLy8gVW5kZXJzY29yZSB0ZW1wbGF0aW5nIGhhbmRsZXMgYXJiaXRyYXJ5IGRlbGltaXRlcnMsIHByZXNlcnZlcyB3aGl0ZXNwYWNlLFxuICAvLyBhbmQgY29ycmVjdGx5IGVzY2FwZXMgcXVvdGVzIHdpdGhpbiBpbnRlcnBvbGF0ZWQgY29kZS5cbiAgXy50ZW1wbGF0ZSA9IGZ1bmN0aW9uKHRleHQsIGRhdGEsIHNldHRpbmdzKSB7XG4gICAgdmFyIHJlbmRlcjtcbiAgICBzZXR0aW5ncyA9IF8uZGVmYXVsdHMoe30sIHNldHRpbmdzLCBfLnRlbXBsYXRlU2V0dGluZ3MpO1xuXG4gICAgLy8gQ29tYmluZSBkZWxpbWl0ZXJzIGludG8gb25lIHJlZ3VsYXIgZXhwcmVzc2lvbiB2aWEgYWx0ZXJuYXRpb24uXG4gICAgdmFyIG1hdGNoZXIgPSBuZXcgUmVnRXhwKFtcbiAgICAgIChzZXR0aW5ncy5lc2NhcGUgfHwgbm9NYXRjaCkuc291cmNlLFxuICAgICAgKHNldHRpbmdzLmludGVycG9sYXRlIHx8IG5vTWF0Y2gpLnNvdXJjZSxcbiAgICAgIChzZXR0aW5ncy5ldmFsdWF0ZSB8fCBub01hdGNoKS5zb3VyY2VcbiAgICBdLmpvaW4oJ3wnKSArICd8JCcsICdnJyk7XG5cbiAgICAvLyBDb21waWxlIHRoZSB0ZW1wbGF0ZSBzb3VyY2UsIGVzY2FwaW5nIHN0cmluZyBsaXRlcmFscyBhcHByb3ByaWF0ZWx5LlxuICAgIHZhciBpbmRleCA9IDA7XG4gICAgdmFyIHNvdXJjZSA9IFwiX19wKz0nXCI7XG4gICAgdGV4dC5yZXBsYWNlKG1hdGNoZXIsIGZ1bmN0aW9uKG1hdGNoLCBlc2NhcGUsIGludGVycG9sYXRlLCBldmFsdWF0ZSwgb2Zmc2V0KSB7XG4gICAgICBzb3VyY2UgKz0gdGV4dC5zbGljZShpbmRleCwgb2Zmc2V0KVxuICAgICAgICAucmVwbGFjZShlc2NhcGVyLCBmdW5jdGlvbihtYXRjaCkgeyByZXR1cm4gJ1xcXFwnICsgZXNjYXBlc1ttYXRjaF07IH0pO1xuXG4gICAgICBpZiAoZXNjYXBlKSB7XG4gICAgICAgIHNvdXJjZSArPSBcIicrXFxuKChfX3Q9KFwiICsgZXNjYXBlICsgXCIpKT09bnVsbD8nJzpfLmVzY2FwZShfX3QpKStcXG4nXCI7XG4gICAgICB9XG4gICAgICBpZiAoaW50ZXJwb2xhdGUpIHtcbiAgICAgICAgc291cmNlICs9IFwiJytcXG4oKF9fdD0oXCIgKyBpbnRlcnBvbGF0ZSArIFwiKSk9PW51bGw/Jyc6X190KStcXG4nXCI7XG4gICAgICB9XG4gICAgICBpZiAoZXZhbHVhdGUpIHtcbiAgICAgICAgc291cmNlICs9IFwiJztcXG5cIiArIGV2YWx1YXRlICsgXCJcXG5fX3ArPSdcIjtcbiAgICAgIH1cbiAgICAgIGluZGV4ID0gb2Zmc2V0ICsgbWF0Y2gubGVuZ3RoO1xuICAgICAgcmV0dXJuIG1hdGNoO1xuICAgIH0pO1xuICAgIHNvdXJjZSArPSBcIic7XFxuXCI7XG5cbiAgICAvLyBJZiBhIHZhcmlhYmxlIGlzIG5vdCBzcGVjaWZpZWQsIHBsYWNlIGRhdGEgdmFsdWVzIGluIGxvY2FsIHNjb3BlLlxuICAgIGlmICghc2V0dGluZ3MudmFyaWFibGUpIHNvdXJjZSA9ICd3aXRoKG9ianx8e30pe1xcbicgKyBzb3VyY2UgKyAnfVxcbic7XG5cbiAgICBzb3VyY2UgPSBcInZhciBfX3QsX19wPScnLF9faj1BcnJheS5wcm90b3R5cGUuam9pbixcIiArXG4gICAgICBcInByaW50PWZ1bmN0aW9uKCl7X19wKz1fX2ouY2FsbChhcmd1bWVudHMsJycpO307XFxuXCIgK1xuICAgICAgc291cmNlICsgXCJyZXR1cm4gX19wO1xcblwiO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlbmRlciA9IG5ldyBGdW5jdGlvbihzZXR0aW5ncy52YXJpYWJsZSB8fCAnb2JqJywgJ18nLCBzb3VyY2UpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGUuc291cmNlID0gc291cmNlO1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG5cbiAgICBpZiAoZGF0YSkgcmV0dXJuIHJlbmRlcihkYXRhLCBfKTtcbiAgICB2YXIgdGVtcGxhdGUgPSBmdW5jdGlvbihkYXRhKSB7XG4gICAgICByZXR1cm4gcmVuZGVyLmNhbGwodGhpcywgZGF0YSwgXyk7XG4gICAgfTtcblxuICAgIC8vIFByb3ZpZGUgdGhlIGNvbXBpbGVkIGZ1bmN0aW9uIHNvdXJjZSBhcyBhIGNvbnZlbmllbmNlIGZvciBwcmVjb21waWxhdGlvbi5cbiAgICB0ZW1wbGF0ZS5zb3VyY2UgPSAnZnVuY3Rpb24oJyArIChzZXR0aW5ncy52YXJpYWJsZSB8fCAnb2JqJykgKyAnKXtcXG4nICsgc291cmNlICsgJ30nO1xuXG4gICAgcmV0dXJuIHRlbXBsYXRlO1xuICB9O1xuXG4gIC8vIEFkZCBhIFwiY2hhaW5cIiBmdW5jdGlvbiwgd2hpY2ggd2lsbCBkZWxlZ2F0ZSB0byB0aGUgd3JhcHBlci5cbiAgXy5jaGFpbiA9IGZ1bmN0aW9uKG9iaikge1xuICAgIHJldHVybiBfKG9iaikuY2hhaW4oKTtcbiAgfTtcblxuICAvLyBPT1BcbiAgLy8gLS0tLS0tLS0tLS0tLS0tXG4gIC8vIElmIFVuZGVyc2NvcmUgaXMgY2FsbGVkIGFzIGEgZnVuY3Rpb24sIGl0IHJldHVybnMgYSB3cmFwcGVkIG9iamVjdCB0aGF0XG4gIC8vIGNhbiBiZSB1c2VkIE9PLXN0eWxlLiBUaGlzIHdyYXBwZXIgaG9sZHMgYWx0ZXJlZCB2ZXJzaW9ucyBvZiBhbGwgdGhlXG4gIC8vIHVuZGVyc2NvcmUgZnVuY3Rpb25zLiBXcmFwcGVkIG9iamVjdHMgbWF5IGJlIGNoYWluZWQuXG5cbiAgLy8gSGVscGVyIGZ1bmN0aW9uIHRvIGNvbnRpbnVlIGNoYWluaW5nIGludGVybWVkaWF0ZSByZXN1bHRzLlxuICB2YXIgcmVzdWx0ID0gZnVuY3Rpb24ob2JqKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NoYWluID8gXyhvYmopLmNoYWluKCkgOiBvYmo7XG4gIH07XG5cbiAgLy8gQWRkIGFsbCBvZiB0aGUgVW5kZXJzY29yZSBmdW5jdGlvbnMgdG8gdGhlIHdyYXBwZXIgb2JqZWN0LlxuICBfLm1peGluKF8pO1xuXG4gIC8vIEFkZCBhbGwgbXV0YXRvciBBcnJheSBmdW5jdGlvbnMgdG8gdGhlIHdyYXBwZXIuXG4gIGVhY2goWydwb3AnLCAncHVzaCcsICdyZXZlcnNlJywgJ3NoaWZ0JywgJ3NvcnQnLCAnc3BsaWNlJywgJ3Vuc2hpZnQnXSwgZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBtZXRob2QgPSBBcnJheVByb3RvW25hbWVdO1xuICAgIF8ucHJvdG90eXBlW25hbWVdID0gZnVuY3Rpb24oKSB7XG4gICAgICB2YXIgb2JqID0gdGhpcy5fd3JhcHBlZDtcbiAgICAgIG1ldGhvZC5hcHBseShvYmosIGFyZ3VtZW50cyk7XG4gICAgICBpZiAoKG5hbWUgPT0gJ3NoaWZ0JyB8fCBuYW1lID09ICdzcGxpY2UnKSAmJiBvYmoubGVuZ3RoID09PSAwKSBkZWxldGUgb2JqWzBdO1xuICAgICAgcmV0dXJuIHJlc3VsdC5jYWxsKHRoaXMsIG9iaik7XG4gICAgfTtcbiAgfSk7XG5cbiAgLy8gQWRkIGFsbCBhY2Nlc3NvciBBcnJheSBmdW5jdGlvbnMgdG8gdGhlIHdyYXBwZXIuXG4gIGVhY2goWydjb25jYXQnLCAnam9pbicsICdzbGljZSddLCBmdW5jdGlvbihuYW1lKSB7XG4gICAgdmFyIG1ldGhvZCA9IEFycmF5UHJvdG9bbmFtZV07XG4gICAgXy5wcm90b3R5cGVbbmFtZV0gPSBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiByZXN1bHQuY2FsbCh0aGlzLCBtZXRob2QuYXBwbHkodGhpcy5fd3JhcHBlZCwgYXJndW1lbnRzKSk7XG4gICAgfTtcbiAgfSk7XG5cbiAgXy5leHRlbmQoXy5wcm90b3R5cGUsIHtcblxuICAgIC8vIFN0YXJ0IGNoYWluaW5nIGEgd3JhcHBlZCBVbmRlcnNjb3JlIG9iamVjdC5cbiAgICBjaGFpbjogZnVuY3Rpb24oKSB7XG4gICAgICB0aGlzLl9jaGFpbiA9IHRydWU7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgLy8gRXh0cmFjdHMgdGhlIHJlc3VsdCBmcm9tIGEgd3JhcHBlZCBhbmQgY2hhaW5lZCBvYmplY3QuXG4gICAgdmFsdWU6IGZ1bmN0aW9uKCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3dyYXBwZWQ7XG4gICAgfVxuXG4gIH0pO1xuXG4gIC8vIEFNRCByZWdpc3RyYXRpb24gaGFwcGVucyBhdCB0aGUgZW5kIGZvciBjb21wYXRpYmlsaXR5IHdpdGggQU1EIGxvYWRlcnNcbiAgLy8gdGhhdCBtYXkgbm90IGVuZm9yY2UgbmV4dC10dXJuIHNlbWFudGljcyBvbiBtb2R1bGVzLiBFdmVuIHRob3VnaCBnZW5lcmFsXG4gIC8vIHByYWN0aWNlIGZvciBBTUQgcmVnaXN0cmF0aW9uIGlzIHRvIGJlIGFub255bW91cywgdW5kZXJzY29yZSByZWdpc3RlcnNcbiAgLy8gYXMgYSBuYW1lZCBtb2R1bGUgYmVjYXVzZSwgbGlrZSBqUXVlcnksIGl0IGlzIGEgYmFzZSBsaWJyYXJ5IHRoYXQgaXNcbiAgLy8gcG9wdWxhciBlbm91Z2ggdG8gYmUgYnVuZGxlZCBpbiBhIHRoaXJkIHBhcnR5IGxpYiwgYnV0IG5vdCBiZSBwYXJ0IG9mXG4gIC8vIGFuIEFNRCBsb2FkIHJlcXVlc3QuIFRob3NlIGNhc2VzIGNvdWxkIGdlbmVyYXRlIGFuIGVycm9yIHdoZW4gYW5cbiAgLy8gYW5vbnltb3VzIGRlZmluZSgpIGlzIGNhbGxlZCBvdXRzaWRlIG9mIGEgbG9hZGVyIHJlcXVlc3QuXG4gIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICBkZWZpbmUoJ3VuZGVyc2NvcmUnLCBbXSwgZnVuY3Rpb24oKSB7XG4gICAgICByZXR1cm4gXztcbiAgICB9KTtcbiAgfVxufSkuY2FsbCh0aGlzKTtcbiJdfQ== diff --git a/build/browser/index.min.js b/build/browser/index.min.js new file mode 100644 index 00000000..a8a0e0aa --- /dev/null +++ b/build/browser/index.min.js @@ -0,0 +1,2 @@ +!function t(e,n,r){function i(u,a){if(!n[u]){if(!e[u]){var s="function"==typeof require&&require;if(!a&&s)return s(u,!0);if(o)return o(u,!0);throw new Error("Cannot find module '"+u+"'")}var c=n[u]={exports:{}};e[u][0].call(c.exports,function(t){var n=e[u][1][t];return i(n?n:t)},c,c.exports,t,e,n,r)}return n[u].exports}for(var o="function"==typeof require&&require,u=0;ur;r++)n=t[r],o.push(n.getUserId()!==this.HB.getUserId()?n.getConnector().receive(e):void 0);return o}},e.prototype.receive=function(t){var e,n;return null==(e=this.unexecuted)[n=t.uid.creator]&&(e[n]=[]),this.unexecuted[t.uid.creator].push(t)},e.prototype.flushOne=function(t){var e;return(null!=(e=this.unexecuted[t])?e.length:void 0)>0?this.engine.applyOp(this.unexecuted[t].shift()):void 0},e.prototype.flushOneRandom=function(){return this.flushOne(n.random(0,t.length-1))},e.prototype.flushAll=function(){var t,e,n;n=this.unexecuted;for(t in n)e=n[t],this.engine.applyOps(e);return this.unexecuted={}},e}()}},{underscore:12}],3:[function(t,e){var n;n=function(){function t(t,e){this.HB=t,this.parser=e,this.unprocessed_ops=[]}return t.prototype.parseOperation=function(t){var e;if(e=this.parser[t.type],null!=e)return e(t);throw new Error("You forgot to specify a parser for type "+t.type+". The message is "+JSON.stringify(t)+".")},t.prototype.applyOpsBundle=function(t){var e,n,r,i,o,u,a,s;for(n=[],r=0,u=t.length;u>r;r++)e=t[r],n.push(this.parseOperation(e));for(i=0,a=n.length;a>i;i++)e=n[i],this.HB.addOperation(e);for(o=0,s=n.length;s>o;o++)e=n[o],e.execute()||this.unprocessed_ops.push(e);return this.tryUnprocessed()},t.prototype.applyOpsCheckDouble=function(t){var e,n,r,i;for(i=[],n=0,r=t.length;r>n;n++)e=t[n],i.push(null!=this.HB.getOperation(e.uid)?this.applyOp(e):void 0);return i},t.prototype.applyOps=function(t){var e,n,r,i;for(i=[],n=0,r=t.length;r>n;n++)e=t[n],i.push(this.applyOp(e));return i},t.prototype.applyOp=function(t){var e;return e=this.parseOperation(t),this.HB.addToCounter(e),e.execute()?this.HB.addOperation(e):this.unprocessed_ops.push(e),this.tryUnprocessed()},t.prototype.tryUnprocessed=function(){var t,e,n,r,i,o,u;for(u=[];;){for(t=this.unprocessed_ops.length,n=[],o=this.unprocessed_ops,r=0,i=o.length;i>r;r++)e=o[r],e.execute()?this.HB.addOperation(e):n.push(e);if(this.unprocessed_ops=n,this.unprocessed_ops.length===t)break;u.push(void 0)}return u},t}(),e.exports=n},{}],4:[function(t,e){var n,r,i,o;o=t("../Types/JsonTypes"),r=t("../HistoryBuffer"),n=t("../Engine"),i=function(){function t(t,e){var i,u;this.HB=new r(t),u=o(this.HB),this.engine=new n(this.HB,u.parser),this.connector=new e(this.engine,this.HB,u.execution_listener,this),i=new u.types.JsonType(this.HB.getReservedUniqueIdentifier()),this.HB.addOperation(i).execute(),this.root_element=i}return t.prototype.getRootElement=function(){return this.root_element},t.prototype.getEngine=function(){return this.engine},t.prototype.getConnector=function(){return this.connector},t.prototype.getHistoryBuffer=function(){return this.HB},t.prototype.setMutableDefault=function(t){return this.root_element.setMutableDefault(t)},t.prototype.getUserId=function(){return this.HB.getUserId()},t.prototype.val=function(t,e,n){return this.root_element.val(t,e,n)},Object.defineProperty(t.prototype,"value",{get:function(){return this.root_element.value},set:function(t){var e,n,r;if(t.constructor==={}.constructor){r=[];for(e in t)n=t[e],r.push(this.val(e,n,"immutable"));return r}throw new Error("You must only set Object values!")}}),t}(),"undefined"!=typeof window&&null!==window&&(window.JsonYatta=i),e.exports=i},{"../Engine":3,"../HistoryBuffer":6,"../Types/JsonTypes":8}],5:[function(t,e){var n,r,i,o;o=t("../Types/TextTypes"),r=t("../HistoryBuffer"),n=t("../Engine"),i=function(){function t(t,e){var i,u;this.HB=new r(t),u=o(this.HB),this.engine=new n(this.HB,u.parser),this.connector=new e(this.engine,this.HB,u.execution_listener),i=new u.types.Word(void 0),this.HB.addOperation(i).execute(),this.root_element=i}return t.prototype.getRootElement=function(){return this.root_element},t.prototype.getEngine=function(){return this.engine},t.prototype.getConnector=function(){return this.connector},t.prototype.getHistoryBuffer=function(){return this.HB},t.prototype.getUserId=function(){return this.HB.getUserId()},t.prototype.val=function(){return this.root_element.val()},t.prototype.insertText=function(t,e){return this.root_element.insertText(t,e)},t.prototype.deleteText=function(t,e){return this.root_element.deleteText(t,e)},t.prototype.replaceText=function(t){return this.root_element.replaceText(t)},t}(),e.exports=i},{"../Engine":3,"../HistoryBuffer":6,"../Types/TextTypes":10}],6:[function(t,e){var n;n=function(){function t(t){this.user_id=t,this.operation_counter={},this.buffer={},this.change_listeners=[]}return t.prototype.getUserId=function(){return this.user_id},t.prototype.getReservedUniqueIdentifier=function(){return{creator:"_",op_number:"_"}},t.prototype.getOperationCounter=function(){var t,e,n,r;e={},r=this.operation_counter;for(n in r)t=r[n],e[n]=t;return e},t.prototype._encode=function(t){var e,n,r,i,o,u,a,s,c,l;null==t&&(t={}),e=[],s=function(e,n){if(null==e||null==n)throw new Error("dah!");return null==t[e]||t[e]<=n},l=this.buffer;for(a in l){c=l[a];for(o in c)if(n=c[o],!isNaN(parseInt(o))&&s(a,o)){if(r=n._encode(),null!=n.next_cl){for(i=n.next_cl;null!=i.next_cl&&s(i.creator,i.op_number);)i=i.next_cl;r.next=i.getUid()}else if(null!=n.prev_cl){for(u=n.prev_cl;null!=u.prev_cl&&s(i.creator,i.op_number);)u=u.prev_cl;r.prev=u.getUid()}e.push(r)}}return e},t.prototype.getNextOperationIdentifier=function(t){var e;return null==t&&(t=this.user_id),null==this.operation_counter[t]&&(this.operation_counter[t]=0),e={creator:t,op_number:this.operation_counter[t]},this.operation_counter[t]++,e},t.prototype.getOperation=function(t){var e;if(t instanceof Object)return null!=(e=this.buffer[t.creator])?e[t.op_number]:void 0;if(null!=t)throw new Error("This type of uid is not defined!")},t.prototype.addOperation=function(t){if(null==this.buffer[t.creator]&&(this.buffer[t.creator]={}),null!=this.buffer[t.creator][t.op_number])throw new Error("You must not overwrite operations!");return this.buffer[t.creator][t.op_number]=t,t},t.prototype.addToCounter=function(t){return null==this.operation_counter[t.creator]&&(this.operation_counter[t.creator]=0),"number"==typeof t.op_number&&t.creator!==this.getUserId()?this.operation_counter[t.creator]++:void 0},t}(),e.exports=n},{}],7:[function(t,e){var n={}.hasOwnProperty,r=function(t,e){function r(){this.constructor=t}for(var i in e)n.call(e,i)&&(t[i]=e[i]);return r.prototype=e.prototype,t.prototype=new r,t.__super__=e.prototype,t};e.exports=function(t){var e,n,i,o,u,a,s;return s={},a=[],u=function(){function e(e){null==e&&(e=t.getNextOperationIdentifier()),this.creator=e.creator,this.op_number=e.op_number}return e.prototype.on=function(t,e){var n;return null==this.event_listeners&&(this.event_listeners={}),null==(n=this.event_listeners)[t]&&(n[t]=[]),this.event_listeners[t].push(e)},e.prototype.callEvent=function(t,e){var n,r,i,o,u;if(null!=this.event_listeners[t]){for(o=this.event_listeners[t],u=[],r=0,i=o.length;i>r;r++)n=o[r],u.push(n.call(this,t,e));return u}},e.prototype.setParent=function(t){return this.parent=t},e.prototype.getUid=function(){return{creator:this.creator,op_number:this.op_number}},e.prototype.execute=function(){var t,e,n;for(this.is_executed=!0,e=0,n=a.length;n>e;e++)(t=a[e])(this._encode());return this},e.prototype.saveOperation=function(t,e){return null!=(null!=e?e.execute:void 0)?this[t]=e:null!=e?(null==this.unchecked&&(this.unchecked={}),this.unchecked[t]=e):void 0},e.prototype.validateSavedOperations=function(){var e,n,r,i,o,u;o={},i=this,u=this.unchecked;for(e in u)r=u[e],n=t.getOperation(r),n?this[e]=n:(o[e]=r,i=!1);return delete this.unchecked,i||(this.unchecked=o),i},e}(),e=function(t){function e(t,n){this.saveOperation("deletes",n),e.__super__.constructor.call(this,t)}return r(e,t),e.prototype._encode=function(){return{type:"Delete",uid:this.getUid(),deletes:this.deletes.getUid()}},e.prototype.execute=function(){return this.validateSavedOperations()?(this.deletes.applyDelete(this),e.__super__.execute.apply(this,arguments),this):!1},e}(u),s.Delete=function(t){var n,r;return r=t.uid,n=t.deletes,new e(r,n)},o=function(t){function e(t,n,r,i){this.saveOperation("prev_cl",n),this.saveOperation("next_cl",r),null!=i?this.saveOperation("origin",i):this.saveOperation("origin",n),e.__super__.constructor.call(this,t)}return r(e,t),e.prototype.applyDelete=function(t){return null==this.deleted_by&&(this.deleted_by=[]),this.deleted_by.push(t)},e.prototype.isDeleted=function(){var t;return(null!=(t=this.deleted_by)?t.length:void 0)>0},e.prototype.getDistanceToOrigin=function(){var t,e;for(t=0,e=this.prev_cl;;){if(this.origin===e)break;if(t++,this===this.prev_cl)throw new Error("this should not happen ;) ");e=e.prev_cl}return t},e.prototype.update_sl=function(){var t;return t=this.prev_cl,update("prev_cl","prev_sl"),update("next_cl","prev_sl")},e.prototype.execute=function(){var t,n,r,i,o;if(null!=this.is_executed)return this;if(this.validateSavedOperations()){if((null!=(i=this.prev_cl)?i.validateSavedOperations():void 0)&&(null!=(o=this.next_cl)?o.validateSavedOperations():void 0)&&this.prev_cl.next_cl!==this){for(t=0,r=this.prev_cl.next_cl,n=0;;){if(null==r&&(console.log(JSON.stringify(this.prev_cl.getUid())),console.log(JSON.stringify(this.next_cl.getUid()))),r===this.next_cl)break;if(r.getDistanceToOrigin()===n)r.creator0)for(;;){if(e=e.next_cl,e.isDeleted()||(t-=1),0===t)break;if(e instanceof l.Delimiter)throw new Error("position parameter exceeded the length of the document!")}return e},n}(l.Insert),u=function(e){function n(t,e,r,i,o,u,a){n.__super__.constructor.call(this,e,r,i,o,u,a),null!=t&&this.replace(t)}return i(n,e),n.prototype.replace=function(e){var n,r;return n=this.getLastOperation(),r=new a(e,this,void 0,n,n.next_cl),t.addOperation(r).execute()},n.prototype.val=function(){var t;if(t=this.getLastOperation(),t instanceof l.Delimiter)throw new Error("dtrn");return t.val()},n.prototype._encode=function(){var t;return t={type:"ReplaceManager",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&null!=this.next_cl&&(t.prev=this.prev_cl.getUid(),t.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},n}(r),c.ReplaceManager=function(t){var e,n,r,i,o,a,s;return n=t.content,s=t.uid,a=t.prev,i=t.next,o=t.origin,e=t.beginning,r=t.end,new u(n,s,e,r,a,i,o)},a=function(t){function e(t,n,r,i,o,u){if(this.saveOperation("content",t),this.saveOperation("parent",n),null==i||null==o||null==t)throw new Error("You must define content, prev, and next for Replaceable-types!");e.__super__.constructor.call(this,r,i,o,u)}return i(e,t),e.prototype.val=function(){return this.content},e.prototype.replace=function(t){return this.parent.replace(t)},e.prototype.execute=function(){var t;return this.validateSavedOperations()?("function"==typeof(t=this.content).setReplaceManager&&t.setReplaceManager(this.parent),e.__super__.execute.apply(this,arguments),this):!1},e.prototype._encode=function(){var t;return t={type:"Replaceable",content:this.content.getUid(),ReplaceManager:this.parent.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid(),uid:this.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},e}(l.Insert),c.Replaceable=function(t){var e,n,r,i,o,u;return e=t.content,i=t.ReplaceManager,u=t.uid,o=t.prev,n=t.next,r=t.origin,new a(e,i,u,o,n,r)},l.ListManager=r,l.MapManager=o,l.ReplaceManager=u,l.Replaceable=a,s}},{"./BasicTypes":7}],10:[function(t,e){var n,r={}.hasOwnProperty,i=function(t,e){function n(){this.constructor=t}for(var i in e)r.call(e,i)&&(t[i]=e[i]);return n.prototype=e.prototype,t.prototype=new n,t.__super__=e.prototype,t};n=t("./StructuredTypes"),e.exports=function(t){var e,r,o,u,a,s;return a=n(t),s=a.types,u=a.parser,e=function(t){function e(){return e.__super__.constructor.apply(this,arguments)}return i(e,t),e}(s.Delete),u.TextDelete=u.Delete,r=function(t){function e(t,n,r,i,o){if(this.content=t,null==r||null==i)throw new Error("You must define prev, and next for TextInsert-types!");e.__super__.constructor.call(this,n,r,i,o)}return i(e,t),e.prototype.getLength=function(){return this.isDeleted()?0:this.content.length},e.prototype.val=function(){return this.isDeleted()?"":this.content},e.prototype._encode=function(){var t;return t={type:"TextInsert",content:this.content,uid:this.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},e}(s.Insert),u.TextInsert=function(t){var e,n,i,o,u;return e=t.content,u=t.uid,o=t.prev,n=t.next,i=t.origin,new r(e,u,o,n,i)},o=function(n){function o(t,e,n,r,i,u){o.__super__.constructor.call(this,t,e,n,r,i,u)}return i(o,n),o.prototype.insertText=function(e,n){var i,o,u,a,s,c;for(o=this.getOperationByPosition(e),c=[],a=0,s=n.length;s>a;a++)i=n[a],u=new r(i,void 0,o.prev_cl,o),c.push(t.addOperation(u).execute());return c},o.prototype.deleteText=function(n,r){var i,o,u,a,c;for(u=this.getOperationByPosition(n),c=[],o=a=0;r>=0?r>a:a>r;o=r>=0?++a:--a){for(i=t.addOperation(new e(void 0,u)).execute(),u=u.next_cl;u.isDeleted();){if(u instanceof s.Delimiter)throw new Error("You can't delete more than there is..");u=u.next_cl}c.push(i._encode())}return c},o.prototype.replaceText=function(e){var n;if(null!=this.replace_manager)return n=t.addOperation(new o(void 0)).execute(),n.insertText(0,e),this.replace_manager.replace(n);throw new Error("This type is currently not maintained by a ReplaceManager!")},o.prototype.val=function(){var t,e;return t=function(){var t,n,r,i;for(r=this.toArray(),i=[],t=0,n=r.length;n>t;t++)e=r[t],i.push(null!=e.val?e.val():"");return i}.call(this),t.join("")},o.prototype.setReplaceManager=function(t){return this.saveOperation("replace_manager",t),this.validateSavedOperations},o.prototype._encode=function(){var t;return t={type:"Word",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&(t.prev=this.prev_cl.getUid()),null!=this.next_cl&&(t.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},o}(s.ListManager),u.Word=function(t){var e,n,r,i,u,a;return a=t.uid,e=t.beginning,n=t.end,u=t.prev,r=t.next,i=t.origin,new o(a,e,n,u,r,i)},s.TextInsert=r,s.TextDelete=e,s.Word=o,a}},{"./StructuredTypes":9}],11:[function(t,e,n){n.IwcConnector=t("./Connectors/IwcConnector"),n.TestConnector=t("./Connectors/TestConnector"),n.JsonYatta=t("./Frameworks/JsonYatta"),n.TextYatta=t("./Frameworks/TextYatta")},{"./Connectors/IwcConnector":1,"./Connectors/TestConnector":2,"./Frameworks/JsonYatta":4,"./Frameworks/TextYatta":5}],12:[function(t,e,n){(function(){var t=this,r=t._,i={},o=Array.prototype,u=Object.prototype,a=Function.prototype,s=o.push,c=o.slice,l=o.concat,p=u.toString,f=u.hasOwnProperty,h=o.forEach,d=o.map,v=o.reduce,_=o.reduceRight,g=o.filter,y=o.every,m=o.some,x=o.indexOf,b=o.lastIndexOf,w=Array.isArray,O=Object.keys,T=a.bind,U=function(t){return t instanceof U?t:this instanceof U?void(this._wrapped=t):new U(t)};"undefined"!=typeof n?("undefined"!=typeof e&&e.exports&&(n=e.exports=U),n._=U):t._=U,U.VERSION="1.6.0";var B=U.each=U.forEach=function(t,e,n){if(null==t)return t;if(h&&t.forEach===h)t.forEach(e,n);else if(t.length===+t.length){for(var r=0,o=t.length;o>r;r++)if(e.call(n,t[r],r,t)===i)return}else for(var u=U.keys(t),r=0,o=u.length;o>r;r++)if(e.call(n,t[u[r]],u[r],t)===i)return;return t};U.map=U.collect=function(t,e,n){var r=[];return null==t?r:d&&t.map===d?t.map(e,n):(B(t,function(t,i,o){r.push(e.call(n,t,i,o))}),r)};var I="Reduce of empty array with no initial value";U.reduce=U.foldl=U.inject=function(t,e,n,r){var i=arguments.length>2;if(null==t&&(t=[]),v&&t.reduce===v)return r&&(e=U.bind(e,r)),i?t.reduce(e,n):t.reduce(e);if(B(t,function(t,o,u){i?n=e.call(r,n,t,o,u):(n=t,i=!0)}),!i)throw new TypeError(I);return n},U.reduceRight=U.foldr=function(t,e,n,r){var i=arguments.length>2;if(null==t&&(t=[]),_&&t.reduceRight===_)return r&&(e=U.bind(e,r)),i?t.reduceRight(e,n):t.reduceRight(e);var o=t.length;if(o!==+o){var u=U.keys(t);o=u.length}if(B(t,function(a,s,c){s=u?u[--o]:--o,i?n=e.call(r,n,t[s],s,c):(n=t[s],i=!0)}),!i)throw new TypeError(I);return n},U.find=U.detect=function(t,e,n){var r;return j(t,function(t,i,o){return e.call(n,t,i,o)?(r=t,!0):void 0}),r},U.filter=U.select=function(t,e,n){var r=[];return null==t?r:g&&t.filter===g?t.filter(e,n):(B(t,function(t,i,o){e.call(n,t,i,o)&&r.push(t)}),r)},U.reject=function(t,e,n){return U.filter(t,function(t,r,i){return!e.call(n,t,r,i)},n)},U.every=U.all=function(t,e,n){e||(e=U.identity);var r=!0;return null==t?r:y&&t.every===y?t.every(e,n):(B(t,function(t,o,u){return(r=r&&e.call(n,t,o,u))?void 0:i}),!!r)};var j=U.some=U.any=function(t,e,n){e||(e=U.identity);var r=!1;return null==t?r:m&&t.some===m?t.some(e,n):(B(t,function(t,o,u){return r||(r=e.call(n,t,o,u))?i:void 0}),!!r)};U.contains=U.include=function(t,e){return null==t?!1:x&&t.indexOf===x?-1!=t.indexOf(e):j(t,function(t){return t===e})},U.invoke=function(t,e){var n=c.call(arguments,2),r=U.isFunction(e);return U.map(t,function(t){return(r?e:t[e]).apply(t,n)})},U.pluck=function(t,e){return U.map(t,U.property(e))},U.where=function(t,e){return U.filter(t,U.matches(e))},U.findWhere=function(t,e){return U.find(t,U.matches(e))},U.max=function(t,e,n){if(!e&&U.isArray(t)&&t[0]===+t[0]&&t.length<65535)return Math.max.apply(Math,t);var r=-1/0,i=-1/0;return B(t,function(t,o,u){var a=e?e.call(n,t,o,u):t;a>i&&(r=t,i=a)}),r},U.min=function(t,e,n){if(!e&&U.isArray(t)&&t[0]===+t[0]&&t.length<65535)return Math.min.apply(Math,t);var r=1/0,i=1/0;return B(t,function(t,o,u){var a=e?e.call(n,t,o,u):t;i>a&&(r=t,i=a)}),r},U.shuffle=function(t){var e,n=0,r=[];return B(t,function(t){e=U.random(n++),r[n-1]=r[e],r[e]=t}),r},U.sample=function(t,e,n){return null==e||n?(t.length!==+t.length&&(t=U.values(t)),t[U.random(t.length-1)]):U.shuffle(t).slice(0,Math.max(0,e))};var E=function(t){return null==t?U.identity:U.isFunction(t)?t:U.property(t)};U.sortBy=function(t,e,n){return e=E(e),U.pluck(U.map(t,function(t,r,i){return{value:t,index:r,criteria:e.call(n,t,r,i)}}).sort(function(t,e){var n=t.criteria,r=e.criteria;if(n!==r){if(n>r||void 0===n)return 1;if(r>n||void 0===r)return-1}return t.index-e.index}),"value")};var H=function(t){return function(e,n,r){var i={};return n=E(n),B(e,function(o,u){var a=n.call(r,o,u,e);t(i,a,o)}),i}};U.groupBy=H(function(t,e,n){U.has(t,e)?t[e].push(n):t[e]=[n]}),U.indexBy=H(function(t,e,n){t[e]=n}),U.countBy=H(function(t,e){U.has(t,e)?t[e]++:t[e]=1}),U.sortedIndex=function(t,e,n,r){n=E(n);for(var i=n.call(r,e),o=0,u=t.length;u>o;){var a=o+u>>>1;n.call(r,t[a])e?[]:c.call(t,0,e)},U.initial=function(t,e,n){return c.call(t,0,t.length-(null==e||n?1:e))},U.last=function(t,e,n){return null==t?void 0:null==e||n?t[t.length-1]:c.call(t,Math.max(t.length-e,0))},U.rest=U.tail=U.drop=function(t,e,n){return c.call(t,null==e||n?1:e)},U.compact=function(t){return U.filter(t,U.identity)};var k=function(t,e,n){return e&&U.every(t,U.isArray)?l.apply(n,t):(B(t,function(t){U.isArray(t)||U.isArguments(t)?e?s.apply(n,t):k(t,e,n):n.push(t)}),n)};U.flatten=function(t,e){return k(t,e,[])},U.without=function(t){return U.difference(t,c.call(arguments,1))},U.partition=function(t,e){var n=[],r=[];return B(t,function(t){(e(t)?n:r).push(t)}),[n,r]},U.uniq=U.unique=function(t,e,n,r){U.isFunction(e)&&(r=n,n=e,e=!1);var i=n?U.map(t,n,r):t,o=[],u=[];return B(i,function(n,r){(e?r&&u[u.length-1]===n:U.contains(u,n))||(u.push(n),o.push(t[r]))}),o},U.union=function(){return U.uniq(U.flatten(arguments,!0))},U.intersection=function(t){var e=c.call(arguments,1);return U.filter(U.uniq(t),function(t){return U.every(e,function(e){return U.contains(e,t)})})},U.difference=function(t){var e=l.apply(o,c.call(arguments,1));return U.filter(t,function(t){return!U.contains(e,t)})},U.zip=function(){for(var t=U.max(U.pluck(arguments,"length").concat(0)),e=new Array(t),n=0;t>n;n++)e[n]=U.pluck(arguments,""+n);return e},U.object=function(t,e){if(null==t)return{};for(var n={},r=0,i=t.length;i>r;r++)e?n[t[r]]=e[r]:n[t[r][0]]=t[r][1];return n},U.indexOf=function(t,e,n){if(null==t)return-1;var r=0,i=t.length;if(n){if("number"!=typeof n)return r=U.sortedIndex(t,e),t[r]===e?r:-1;r=0>n?Math.max(0,i+n):n}if(x&&t.indexOf===x)return t.indexOf(e,n);for(;i>r;r++)if(t[r]===e)return r;return-1},U.lastIndexOf=function(t,e,n){if(null==t)return-1;var r=null!=n;if(b&&t.lastIndexOf===b)return r?t.lastIndexOf(e,n):t.lastIndexOf(e);for(var i=r?n:t.length;i--;)if(t[i]===e)return i;return-1},U.range=function(t,e,n){arguments.length<=1&&(e=t||0,t=0),n=arguments[2]||1;for(var r=Math.max(Math.ceil((e-t)/n),0),i=0,o=new Array(r);r>i;)o[i++]=t,t+=n;return o};var D=function(){};U.bind=function(t,e){var n,r;if(T&&t.bind===T)return T.apply(t,c.call(arguments,1));if(!U.isFunction(t))throw new TypeError;return n=c.call(arguments,2),r=function(){if(!(this instanceof r))return t.apply(e,n.concat(c.call(arguments)));D.prototype=t.prototype;var i=new D;D.prototype=null;var o=t.apply(i,n.concat(c.call(arguments)));return Object(o)===o?o:i}},U.partial=function(t){var e=c.call(arguments,1);return function(){for(var n=0,r=e.slice(),i=0,o=r.length;o>i;i++)r[i]===U&&(r[i]=arguments[n++]);for(;n=l?(clearTimeout(u),u=null,a=c,o=t.apply(r,i),r=i=null):u||n.trailing===!1||(u=setTimeout(s,l)),o}},U.debounce=function(t,e,n){var r,i,o,u,a,s=function(){var c=U.now()-u;e>c?r=setTimeout(s,e-c):(r=null,n||(a=t.apply(o,i),o=i=null))};return function(){o=this,i=arguments,u=U.now();var c=n&&!r;return r||(r=setTimeout(s,e)),c&&(a=t.apply(o,i),o=i=null),a}},U.once=function(t){var e,n=!1;return function(){return n?e:(n=!0,e=t.apply(this,arguments),t=null,e)}},U.wrap=function(t,e){return U.partial(e,t)},U.compose=function(){var t=arguments;return function(){for(var e=arguments,n=t.length-1;n>=0;n--)e=[t[n].apply(this,e)];return e[0]}},U.after=function(t,e){return function(){return--t<1?e.apply(this,arguments):void 0}},U.keys=function(t){if(!U.isObject(t))return[];if(O)return O(t);var e=[];for(var n in t)U.has(t,n)&&e.push(n);return e},U.values=function(t){for(var e=U.keys(t),n=e.length,r=new Array(n),i=0;n>i;i++)r[i]=t[e[i]];return r},U.pairs=function(t){for(var e=U.keys(t),n=e.length,r=new Array(n),i=0;n>i;i++)r[i]=[e[i],t[e[i]]];return r},U.invert=function(t){for(var e={},n=U.keys(t),r=0,i=n.length;i>r;r++)e[t[n[r]]]=n[r];return e},U.functions=U.methods=function(t){var e=[];for(var n in t)U.isFunction(t[n])&&e.push(n);return e.sort()},U.extend=function(t){return B(c.call(arguments,1),function(e){if(e)for(var n in e)t[n]=e[n]}),t},U.pick=function(t){var e={},n=l.apply(o,c.call(arguments,1));return B(n,function(n){n in t&&(e[n]=t[n])}),e},U.omit=function(t){var e={},n=l.apply(o,c.call(arguments,1));for(var r in t)U.contains(n,r)||(e[r]=t[r]);return e},U.defaults=function(t){return B(c.call(arguments,1),function(e){if(e)for(var n in e)void 0===t[n]&&(t[n]=e[n])}),t},U.clone=function(t){return U.isObject(t)?U.isArray(t)?t.slice():U.extend({},t):t},U.tap=function(t,e){return e(t),t};var M=function(t,e,n,r){if(t===e)return 0!==t||1/t==1/e;if(null==t||null==e)return t===e;t instanceof U&&(t=t._wrapped),e instanceof U&&(e=e._wrapped);var i=p.call(t);if(i!=p.call(e))return!1;switch(i){case"[object String]":return t==String(e);case"[object Number]":return t!=+t?e!=+e:0==t?1/t==1/e:t==+e;case"[object Date]":case"[object Boolean]":return+t==+e;case"[object RegExp]":return t.source==e.source&&t.global==e.global&&t.multiline==e.multiline&&t.ignoreCase==e.ignoreCase}if("object"!=typeof t||"object"!=typeof e)return!1;for(var o=n.length;o--;)if(n[o]==t)return r[o]==e;var u=t.constructor,a=e.constructor;if(u!==a&&!(U.isFunction(u)&&u instanceof u&&U.isFunction(a)&&a instanceof a)&&"constructor"in t&&"constructor"in e)return!1;n.push(t),r.push(e);var s=0,c=!0;if("[object Array]"==i){if(s=t.length,c=s==e.length)for(;s--&&(c=M(t[s],e[s],n,r)););}else{for(var l in t)if(U.has(t,l)&&(s++,!(c=U.has(e,l)&&M(t[l],e[l],n,r))))break;if(c){for(l in e)if(U.has(e,l)&&!s--)break;c=!s}}return n.pop(),r.pop(),c};U.isEqual=function(t,e){return M(t,e,[],[])},U.isEmpty=function(t){if(null==t)return!0;if(U.isArray(t)||U.isString(t))return 0===t.length;for(var e in t)if(U.has(t,e))return!1;return!0},U.isElement=function(t){return!(!t||1!==t.nodeType)},U.isArray=w||function(t){return"[object Array]"==p.call(t)},U.isObject=function(t){return t===Object(t)},B(["Arguments","Function","String","Number","Date","RegExp"],function(t){U["is"+t]=function(e){return p.call(e)=="[object "+t+"]"}}),U.isArguments(arguments)||(U.isArguments=function(t){return!(!t||!U.has(t,"callee"))}),"function"!=typeof/./&&(U.isFunction=function(t){return"function"==typeof t}),U.isFinite=function(t){return isFinite(t)&&!isNaN(parseFloat(t))},U.isNaN=function(t){return U.isNumber(t)&&t!=+t},U.isBoolean=function(t){return t===!0||t===!1||"[object Boolean]"==p.call(t)},U.isNull=function(t){return null===t},U.isUndefined=function(t){return void 0===t},U.has=function(t,e){return f.call(t,e)},U.noConflict=function(){return t._=r,this},U.identity=function(t){return t},U.constant=function(t){return function(){return t}},U.property=function(t){return function(e){return e[t]}},U.matches=function(t){return function(e){if(e===t)return!0;for(var n in t)if(t[n]!==e[n])return!1;return!0}},U.times=function(t,e,n){for(var r=Array(Math.max(0,t)),i=0;t>i;i++)r[i]=e.call(n,i);return r},U.random=function(t,e){return null==e&&(e=t,t=0),t+Math.floor(Math.random()*(e-t+1))},U.now=Date.now||function(){return(new Date).getTime()};var R={escape:{"&":"&","<":"<",">":">",'"':""","'":"'"}};R.unescape=U.invert(R.escape);var A={escape:new RegExp("["+U.keys(R.escape).join("")+"]","g"),unescape:new RegExp("("+U.keys(R.unescape).join("|")+")","g")};U.each(["escape","unescape"],function(t){U[t]=function(e){return null==e?"":(""+e).replace(A[t],function(e){return R[t][e]})}}),U.result=function(t,e){if(null==t)return void 0;var n=t[e];return U.isFunction(n)?n.call(t):n},U.mixin=function(t){B(U.functions(t),function(e){var n=U[e]=t[e];U.prototype[e]=function(){var t=[this._wrapped];return s.apply(t,arguments),N.call(this,n.apply(U,t))}})};var C=0;U.uniqueId=function(t){var e=++C+"";return t?t+e:e},U.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var S=/(.)^/,Y={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},F=/\\|'|\r|\n|\t|\u2028|\u2029/g;U.template=function(t,e,n){var r;n=U.defaults({},n,U.templateSettings);var i=new RegExp([(n.escape||S).source,(n.interpolate||S).source,(n.evaluate||S).source].join("|")+"|$","g"),o=0,u="__p+='";t.replace(i,function(e,n,r,i,a){return u+=t.slice(o,a).replace(F,function(t){return"\\"+Y[t]}),n&&(u+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(u+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(u+="';\n"+i+"\n__p+='"),o=a+e.length,e}),u+="';\n",n.variable||(u="with(obj||{}){\n"+u+"}\n"),u="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+u+"return __p;\n";try{r=new Function(n.variable||"obj","_",u)}catch(a){throw a.source=u,a}if(e)return r(e,U);var s=function(t){return r.call(this,t,U)};return s.source="function("+(n.variable||"obj")+"){\n"+u+"}",s},U.chain=function(t){return U(t).chain()};var N=function(t){return this._chain?U(t).chain():t};U.mixin(U),B(["pop","push","reverse","shift","sort","splice","unshift"],function(t){var e=o[t];U.prototype[t]=function(){var n=this._wrapped;return e.apply(n,arguments),"shift"!=t&&"splice"!=t||0!==n.length||delete n[0],N.call(this,n)}}),B(["concat","join","slice"],function(t){var e=o[t];U.prototype[t]=function(){return N.call(this,e.apply(this._wrapped,arguments))}}),U.extend(U.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}}),"function"==typeof define&&define.amd&&define("underscore",[],function(){return U})}).call(this)},{}]},{},[11]); \ No newline at end of file diff --git a/build/node/Connectors/IwcConnector.coffee b/build/node/Connectors/IwcConnector.coffee new file mode 100644 index 00000000..b89c1b88 --- /dev/null +++ b/build/node/Connectors/IwcConnector.coffee @@ -0,0 +1,112 @@ + +# +# @param {Function} callback The callback is called when the connector is initialized. +# +createIwcConnector = (callback)-> + iwcHandler = {} + duiClient = new DUIClient() + #@duiClient = new iwc.Client() + duiClient.connect (intent)-> + #console.log "intent received iwc: #{JSON.stringify(intent)}" + #console.log "#{JSON.stringify(@iwcHandler)}" + iwcHandler[intent.action]?.map (f)-> + setTimeout ()-> + f intent + , 0 + + duiClient.initOK() + + received_HB = null + + # + # The Iwc Connector adds support for the Inter-Widget-Communication protocol that is used in the Role-SDK. + # @see http://dbis.rwth-aachen.de/cms/projects/the-xmpp-experience#interwidget-communication + # @see http://dbis.rwth-aachen.de/cms/projects/ROLE + # + class IwcConnector + + # + # @param {Engine} engine The transformation engine + # @param {HistoryBuffer} HB + # @param {Array} execution_listener You must ensure that whenever an operation is executed, every function in this Array is called. + # @param {Yatta} yatta The Yatta framework. + # + constructor: (@engine, @HB, @execution_listener, @yatta)-> + @duiClient = duiClient + @iwcHandler = iwcHandler + + send_ = (o)=> + @send o + @execution_listener.push send_ + + receive_ = (intent)=> + o = intent.extras + @receive o + @iwcHandler["Yatta_new_operation"] = [receive_] + + if received_HB? + @engine.applyOpsCheckDouble received_HB + + sendHistoryBuffer = ()=> + json = + HB : @yatta.getHistoryBuffer()._encode() + @sendIwcIntent "Yatta_push_HB_element", json + @iwcHandler["Yatta_get_HB_element"] = [sendHistoryBuffer] + + # + # This function is called whenever an operation was executed. + # @param {Operation} o The operation that was executed. + # + send: (o)-> + if o.uid.creator is @HB.getUserId() and (typeof o.uid.op_number isnt "string") + @sendIwcIntent "Yatta_new_operation", o + + # + # This function is called whenever an operation was received from another peer. + # @param {Operation} o The operation that was received. + # + receive: (o)-> + if o.uid.creator isnt @HB.getUserId() + @engine.applyOp o + + # + # Helper for sending iwc intents. + # @param {String} action_name The name of the action that is going to be send. + # @param {String} content The content that is atteched to the intent. + # + sendIwcIntent: (action_name, content)-> + intent = + action: action_name + component: "" + data: "" + dataType: "" + extras: content + + @duiClient.sendIntent(intent) + + get_HB_intent = + action: "Yatta_get_HB_element" + component: "" + data: "" + dataType: "" + extras: {} + + init = ()-> + duiClient.sendIntent(get_HB_intent) + + is_initialized = false + receiveHB = (json)-> + proposed_user_id = duiClient.getIwcClient()._componentName + received_HB = json?.extras.HB + if not is_initialized + is_initialized = true + callback IwcConnector, proposed_user_id + iwcHandler["Yatta_push_HB_element"] = [receiveHB] + setTimeout receiveHB, 0 + + setTimeout init, (Math.random()*0) + + undefined +module.exports = createIwcConnector +window?.createConnector = createIwcConnector + diff --git a/build/node/Connectors/IwcConnector.coffee.map b/build/node/Connectors/IwcConnector.coffee.map new file mode 100755 index 00000000..14552ec9 --- /dev/null +++ b/build/node/Connectors/IwcConnector.coffee.map @@ -0,0 +1 @@ +{"version":3,"file":"Connectors/IwcConnector.coffee","names":[],"mappings":"","sources":["Connectors/IwcConnector.coffee"],"sourcesContent":["\n#\n# @param {Function} callback The callback is called when the connector is initialized.\n#\ncreateIwcConnector = (callback)->\n iwcHandler = {}\n duiClient = new DUIClient()\n #@duiClient = new iwc.Client()\n duiClient.connect (intent)->\n #console.log \"intent received iwc: #{JSON.stringify(intent)}\"\n #console.log \"#{JSON.stringify(@iwcHandler)}\"\n iwcHandler[intent.action]?.map (f)->\n setTimeout ()->\n f intent\n , 0\n\n duiClient.initOK()\n\n received_HB = null\n\n #\n # The Iwc Connector adds support for the Inter-Widget-Communication protocol that is used in the Role-SDK.\n # @see http://dbis.rwth-aachen.de/cms/projects/the-xmpp-experience#interwidget-communication\n # @see http://dbis.rwth-aachen.de/cms/projects/ROLE\n #\n class IwcConnector\n\n #\n # @param {Engine} engine The transformation engine\n # @param {HistoryBuffer} HB\n # @param {Array} execution_listener You must ensure that whenever an operation is executed, every function in this Array is called.\n # @param {Yatta} yatta The Yatta framework.\n #\n constructor: (@engine, @HB, @execution_listener, @yatta)->\n @duiClient = duiClient\n @iwcHandler = iwcHandler\n\n send_ = (o)=>\n @send o\n @execution_listener.push send_\n\n receive_ = (intent)=>\n o = intent.extras\n @receive o\n @iwcHandler[\"Yatta_new_operation\"] = [receive_]\n\n if received_HB?\n @engine.applyOpsCheckDouble received_HB\n\n sendHistoryBuffer = ()=>\n json =\n HB : @yatta.getHistoryBuffer()._encode()\n @sendIwcIntent \"Yatta_push_HB_element\", json\n @iwcHandler[\"Yatta_get_HB_element\"] = [sendHistoryBuffer]\n\n #\n # This function is called whenever an operation was executed.\n # @param {Operation} o The operation that was executed.\n #\n send: (o)->\n if o.uid.creator is @HB.getUserId() and (typeof o.uid.op_number isnt \"string\")\n @sendIwcIntent \"Yatta_new_operation\", o\n\n #\n # This function is called whenever an operation was received from another peer.\n # @param {Operation} o The operation that was received.\n #\n receive: (o)->\n if o.uid.creator isnt @HB.getUserId()\n @engine.applyOp o\n\n #\n # Helper for sending iwc intents.\n # @param {String} action_name The name of the action that is going to be send.\n # @param {String} content The content that is atteched to the intent.\n #\n sendIwcIntent: (action_name, content)->\n intent =\n action: action_name\n component: \"\"\n data: \"\"\n dataType: \"\"\n extras: content\n\n @duiClient.sendIntent(intent)\n\n get_HB_intent =\n action: \"Yatta_get_HB_element\"\n component: \"\"\n data: \"\"\n dataType: \"\"\n extras: {}\n\n init = ()->\n duiClient.sendIntent(get_HB_intent)\n\n is_initialized = false\n receiveHB = (json)->\n proposed_user_id = duiClient.getIwcClient()._componentName\n received_HB = json?.extras.HB\n if not is_initialized\n is_initialized = true\n callback IwcConnector, proposed_user_id\n iwcHandler[\"Yatta_push_HB_element\"] = [receiveHB]\n setTimeout receiveHB, 0\n\n setTimeout init, (Math.random()*0)\n\n undefined\nmodule.exports = createIwcConnector\nwindow?.createConnector = createIwcConnector\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Connectors/IwcConnector.js b/build/node/Connectors/IwcConnector.js new file mode 100644 index 00000000..0dd656ce --- /dev/null +++ b/build/node/Connectors/IwcConnector.js @@ -0,0 +1,2 @@ +(function(){var t;t=function(t){var n,e,i,r,o,u;return o={},e=new DUIClient,e.connect(function(t){var n;return null!=(n=o[t.action])?n.map(function(n){return setTimeout(function(){return n(t)},0)}):void 0}),e.initOK(),u=null,n=function(){function t(t,n,i,r){var a,c,s;this.engine=t,this.HB=n,this.execution_listener=i,this.yatta=r,this.duiClient=e,this.iwcHandler=o,s=function(t){return function(n){return t.send(n)}}(this),this.execution_listener.push(s),a=function(t){return function(n){var e;return e=n.extras,t.receive(e)}}(this),this.iwcHandler.Yatta_new_operation=[a],null!=u&&this.engine.applyOpsCheckDouble(u),c=function(t){return function(){var n;return n={HB:t.yatta.getHistoryBuffer()._encode()},t.sendIwcIntent("Yatta_push_HB_element",n)}}(this),this.iwcHandler.Yatta_get_HB_element=[c]}return t.prototype.send=function(t){return t.uid.creator===this.HB.getUserId()&&"string"!=typeof t.uid.op_number?this.sendIwcIntent("Yatta_new_operation",t):void 0},t.prototype.receive=function(t){return t.uid.creator!==this.HB.getUserId()?this.engine.applyOp(t):void 0},t.prototype.sendIwcIntent=function(t,n){var e;return e={action:t,component:"",data:"",dataType:"",extras:n},this.duiClient.sendIntent(e)},t}(),i={action:"Yatta_get_HB_element",component:"",data:"",dataType:"",extras:{}},r=function(){var r,a;return e.sendIntent(i),r=!1,a=function(i){var o;return o=e.getIwcClient()._componentName,u=null!=i?i.extras.HB:void 0,r?void 0:(r=!0,t(n,o))},o.Yatta_push_HB_element=[a],setTimeout(a,0)},void setTimeout(r,0*Math.random())},module.exports=t,"undefined"!=typeof window&&null!==window&&(window.createConnector=t)}).call(this); +//# sourceMappingURL=../Connectors/IwcConnector.js.map \ No newline at end of file diff --git a/build/node/Connectors/IwcConnector.js.map b/build/node/Connectors/IwcConnector.js.map new file mode 100755 index 00000000..4edc02c7 --- /dev/null +++ b/build/node/Connectors/IwcConnector.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Connectors/IwcConnector.js","sources":["Connectors/IwcConnector.coffee"],"names":[],"mappings":"CAIA,WAAA,GAAA,EAAA,GAAqB,SAAC,GACpB,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,QAAA,MACA,EAAgB,GAAA,WAEhB,EAAU,QAAQ,SAAC,GAGjB,GAAA,kCAA2B,IAAI,SAAC,SAC9B,YAAW,iBACT,GAAE,IACF,KAHJ,SAKF,EAAU,SAEV,EAAc,KAOR,EAAA,WAQS,QAAA,GAAE,EAAS,EAAK,EAAqB,GAChD,GAAA,GAAA,EAAA,CADY,MAAC,OAAA,EAAQ,KAAC,GAAA,EAAI,KAAC,mBAAA,EAAoB,KAAC,MAAA,EAChD,KAAC,UAAY,EACb,KAAC,WAAa,EAEd,EAAQ,SAAA,SAAA,UAAC,SACP,GAAC,KAAK,KADA,MAER,KAAC,mBAAmB,KAAK,GAEzB,EAAW,SAAA,SAAA,UAAC,GACV,GAAA,SAAA,GAAI,EAAO,OACX,EAAC,QAAQ,KAFA,MAGX,KAAC,WAAW,qBAA0B,GAEnC,MAAA,GACD,KAAC,OAAO,oBAAoB,GAE9B,EAAoB,SAAA,SAAA,YAClB,GAAA,SAAA,IACE,GAAK,EAAC,MAAM,mBAAmB,WACjC,EAAC,cAAc,wBAAyB,KAHtB,MAIpB,KAAC,WAAW,sBAA2B,SApBzC,GAAA,UA0BA,KAAM,SAAC,GACL,MAAG,GAAE,IAAI,UAAW,KAAC,GAAG,aAA6C,gBAA5B,GAAS,IAAI,UACpD,KAAC,cAAc,sBAAuB,GADxC,QA3BF,EAAA,UAkCA,QAAS,SAAC,GACR,MAAG,GAAE,IAAI,UAAa,KAAC,GAAG,YACxB,KAAC,OAAO,QAAQ,GADlB,QAnCF,EAAA,UA2CA,cAAe,SAAC,EAAa,GAC3B,GAAA,SAAA,IACE,OAAQ,EACR,UAAW,GACX,KAAM,GACN,SAAU,GACV,OAAQ,GAEV,KAAC,UAAU,WAAW,SAE1B,GACE,OAAQ,uBACR,UAAW,GACX,KAAM,GACN,SAAU,GACV,WAEF,EAAO,WACL,GAAA,GAAA,QAAA,GAAU,WAAW,GAErB,GAAiB,EACjB,EAAY,SAAC,GACX,GAAA,EAEA,OAFA,GAAmB,EAAU,eAAe,eAC5C,EAAA,MAAA,EAAc,EAAM,OAAO,GAAA,OACxB,EAAH,QACE,GAAiB,EACjB,EAAS,EAAc,KAC3B,EAAW,uBAA4B,GACvC,WAAW,EAAW,QAExB,YAAW,EAAqB,EAAd,KAAK,WAGzB,OAAO,QAAU,8CACjB,OAAQ,gBAAkB","sourcesContent":["\n#\n# @param {Function} callback The callback is called when the connector is initialized.\n#\ncreateIwcConnector = (callback)->\n iwcHandler = {}\n duiClient = new DUIClient()\n #@duiClient = new iwc.Client()\n duiClient.connect (intent)->\n #console.log \"intent received iwc: #{JSON.stringify(intent)}\"\n #console.log \"#{JSON.stringify(@iwcHandler)}\"\n iwcHandler[intent.action]?.map (f)->\n setTimeout ()->\n f intent\n , 0\n\n duiClient.initOK()\n\n received_HB = null\n\n #\n # The Iwc Connector adds support for the Inter-Widget-Communication protocol that is used in the Role-SDK.\n # @see http://dbis.rwth-aachen.de/cms/projects/the-xmpp-experience#interwidget-communication\n # @see http://dbis.rwth-aachen.de/cms/projects/ROLE\n #\n class IwcConnector\n\n #\n # @param {Engine} engine The transformation engine\n # @param {HistoryBuffer} HB\n # @param {Array} execution_listener You must ensure that whenever an operation is executed, every function in this Array is called.\n # @param {Yatta} yatta The Yatta framework.\n #\n constructor: (@engine, @HB, @execution_listener, @yatta)->\n @duiClient = duiClient\n @iwcHandler = iwcHandler\n\n send_ = (o)=>\n @send o\n @execution_listener.push send_\n\n receive_ = (intent)=>\n o = intent.extras\n @receive o\n @iwcHandler[\"Yatta_new_operation\"] = [receive_]\n\n if received_HB?\n @engine.applyOpsCheckDouble received_HB\n\n sendHistoryBuffer = ()=>\n json =\n HB : @yatta.getHistoryBuffer()._encode()\n @sendIwcIntent \"Yatta_push_HB_element\", json\n @iwcHandler[\"Yatta_get_HB_element\"] = [sendHistoryBuffer]\n\n #\n # This function is called whenever an operation was executed.\n # @param {Operation} o The operation that was executed.\n #\n send: (o)->\n if o.uid.creator is @HB.getUserId() and (typeof o.uid.op_number isnt \"string\")\n @sendIwcIntent \"Yatta_new_operation\", o\n\n #\n # This function is called whenever an operation was received from another peer.\n # @param {Operation} o The operation that was received.\n #\n receive: (o)->\n if o.uid.creator isnt @HB.getUserId()\n @engine.applyOp o\n\n #\n # Helper for sending iwc intents.\n # @param {String} action_name The name of the action that is going to be send.\n # @param {String} content The content that is atteched to the intent.\n #\n sendIwcIntent: (action_name, content)->\n intent =\n action: action_name\n component: \"\"\n data: \"\"\n dataType: \"\"\n extras: content\n\n @duiClient.sendIntent(intent)\n\n get_HB_intent =\n action: \"Yatta_get_HB_element\"\n component: \"\"\n data: \"\"\n dataType: \"\"\n extras: {}\n\n init = ()->\n duiClient.sendIntent(get_HB_intent)\n\n is_initialized = false\n receiveHB = (json)->\n proposed_user_id = duiClient.getIwcClient()._componentName\n received_HB = json?.extras.HB\n if not is_initialized\n is_initialized = true\n callback IwcConnector, proposed_user_id\n iwcHandler[\"Yatta_push_HB_element\"] = [receiveHB]\n setTimeout receiveHB, 0\n\n setTimeout init, (Math.random()*0)\n\n undefined\nmodule.exports = createIwcConnector\nwindow?.createConnector = createIwcConnector\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Connectors/TestConnector.coffee b/build/node/Connectors/TestConnector.coffee new file mode 100644 index 00000000..0a5ff669 --- /dev/null +++ b/build/node/Connectors/TestConnector.coffee @@ -0,0 +1,76 @@ + +_ = require "underscore" + +module.exports = (user_list)-> + + # + # A trivial Connector that simulates network delay. + # + class TestConnector + + # + # @param {Engine} engine The transformation engine + # @param {HistoryBuffer} HB + # @param {Array} execution_listener You must ensure that whenever an operation is executed, every function in this Array is called. + # @param {Yatta} yatta The Yatta framework. + # + constructor: (@engine, @HB, @execution_listener)-> + send_ = (o)=> + @send o + @execution_listener.push send_ + + @applied_operations = [] + appliedOperationsListener = (o)=> + @applied_operations.push o + @execution_listener.push appliedOperationsListener + if not (user_list?.length is 0) + @engine.applyOps user_list[0].getHistoryBuffer()._encode() + + @unexecuted = {} + + # + # This engine applied operations in a specific order. + # Get the ops in the right order. + # + getOpsInExecutionOrder: ()-> + @applied_operations + + # + # This function is called whenever an operation was executed. + # @param {Operation} o The operation that was executed. + # + send: (o)-> + if (o.uid.creator is @HB.getUserId()) and (typeof o.uid.op_number isnt "string") + for user in user_list + if user.getUserId() isnt @HB.getUserId() + user.getConnector().receive(o) + + # + # This function is called whenever an operation was received from another peer. + # @param {Operation} o The operation that was received. + # + receive: (o)-> + @unexecuted[o.uid.creator] ?= [] + @unexecuted[o.uid.creator].push o + + # + # Flush one operation from the line of a specific user. + # + flushOne: (user)-> + if @unexecuted[user]?.length > 0 + @engine.applyOp @unexecuted[user].shift() + + # + # Flush one operation on a random line. + # + flushOneRandom: ()-> + @flushOne (_.random 0, (user_list.length-1)) + + # + # Flush all operations on every line. + # + flushAll: ()-> + for n,ops of @unexecuted + @engine.applyOps ops + @unexecuted = {} + diff --git a/build/node/Connectors/TestConnector.coffee.map b/build/node/Connectors/TestConnector.coffee.map new file mode 100755 index 00000000..ce39556d --- /dev/null +++ b/build/node/Connectors/TestConnector.coffee.map @@ -0,0 +1 @@ +{"version":3,"file":"Connectors/TestConnector.coffee","names":[],"mappings":"","sources":["Connectors/TestConnector.coffee"],"sourcesContent":["\n_ = require \"underscore\"\n\nmodule.exports = (user_list)->\n\n #\n # A trivial Connector that simulates network delay.\n #\n class TestConnector\n\n #\n # @param {Engine} engine The transformation engine\n # @param {HistoryBuffer} HB\n # @param {Array} execution_listener You must ensure that whenever an operation is executed, every function in this Array is called.\n # @param {Yatta} yatta The Yatta framework.\n #\n constructor: (@engine, @HB, @execution_listener)->\n send_ = (o)=>\n @send o\n @execution_listener.push send_\n\n @applied_operations = []\n appliedOperationsListener = (o)=>\n @applied_operations.push o\n @execution_listener.push appliedOperationsListener\n if not (user_list?.length is 0)\n @engine.applyOps user_list[0].getHistoryBuffer()._encode()\n\n @unexecuted = {}\n\n #\n # This engine applied operations in a specific order.\n # Get the ops in the right order.\n #\n getOpsInExecutionOrder: ()->\n @applied_operations\n\n #\n # This function is called whenever an operation was executed.\n # @param {Operation} o The operation that was executed.\n #\n send: (o)->\n if (o.uid.creator is @HB.getUserId()) and (typeof o.uid.op_number isnt \"string\")\n for user in user_list\n if user.getUserId() isnt @HB.getUserId()\n user.getConnector().receive(o)\n\n #\n # This function is called whenever an operation was received from another peer.\n # @param {Operation} o The operation that was received.\n #\n receive: (o)->\n @unexecuted[o.uid.creator] ?= []\n @unexecuted[o.uid.creator].push o\n\n #\n # Flush one operation from the line of a specific user.\n #\n flushOne: (user)->\n if @unexecuted[user]?.length > 0\n @engine.applyOp @unexecuted[user].shift()\n\n #\n # Flush one operation on a random line.\n #\n flushOneRandom: ()->\n @flushOne (_.random 0, (user_list.length-1))\n\n #\n # Flush all operations on every line.\n #\n flushAll: ()->\n for n,ops of @unexecuted\n @engine.applyOps ops\n @unexecuted = {}\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Connectors/TestConnector.js b/build/node/Connectors/TestConnector.js new file mode 100644 index 00000000..2fada495 --- /dev/null +++ b/build/node/Connectors/TestConnector.js @@ -0,0 +1,2 @@ +(function(){var e;e=require("underscore"),module.exports=function(t){var n;return n=function(){function n(e,n,i){var r,u;this.engine=e,this.HB=n,this.execution_listener=i,u=function(e){return function(t){return e.send(t)}}(this),this.execution_listener.push(u),this.applied_operations=[],r=function(e){return function(t){return e.applied_operations.push(t)}}(this),this.execution_listener.push(r),0!==(null!=t?t.length:void 0)&&this.engine.applyOps(t[0].getHistoryBuffer()._encode()),this.unexecuted={}}return n.prototype.getOpsInExecutionOrder=function(){return this.applied_operations},n.prototype.send=function(e){var n,i,r,u;if(e.uid.creator===this.HB.getUserId()&&"string"!=typeof e.uid.op_number){for(u=[],i=0,r=t.length;r>i;i++)n=t[i],u.push(n.getUserId()!==this.HB.getUserId()?n.getConnector().receive(e):void 0);return u}},n.prototype.receive=function(e){var t,n;return null==(t=this.unexecuted)[n=e.uid.creator]&&(t[n]=[]),this.unexecuted[e.uid.creator].push(e)},n.prototype.flushOne=function(e){var t;return(null!=(t=this.unexecuted[e])?t.length:void 0)>0?this.engine.applyOp(this.unexecuted[e].shift()):void 0},n.prototype.flushOneRandom=function(){return this.flushOne(e.random(0,t.length-1))},n.prototype.flushAll=function(){var e,t,n;n=this.unexecuted;for(e in n)t=n[e],this.engine.applyOps(t);return this.unexecuted={}},n}()}}).call(this); +//# sourceMappingURL=../Connectors/TestConnector.js.map \ No newline at end of file diff --git a/build/node/Connectors/TestConnector.js.map b/build/node/Connectors/TestConnector.js.map new file mode 100755 index 00000000..721a4eed --- /dev/null +++ b/build/node/Connectors/TestConnector.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Connectors/TestConnector.js","sources":["Connectors/TestConnector.coffee"],"names":[],"mappings":"CACA,WAAA,GAAA,EAAA,GAAI,QAAQ,cAEZ,OAAO,QAAU,SAAC,GAKhB,GAAA,SAAM,GAAA,WAQS,QAAA,GAAE,EAAS,EAAK,GAC3B,GAAA,GAAA,CADY,MAAC,OAAA,EAAQ,KAAC,GAAA,EAAI,KAAC,mBAAA,EAC3B,EAAQ,SAAA,SAAA,UAAC,SACP,GAAC,KAAK,KADA,MAER,KAAC,mBAAmB,KAAK,GAEzB,KAAC,sBACD,EAA4B,SAAA,SAAA,UAAC,SAC3B,GAAC,mBAAmB,KAAK,KADC,MAE5B,KAAC,mBAAmB,KAAK,GACI,KAA1B,MAAA,EAAK,EAAW,OAAA,SACjB,KAAC,OAAO,SAAS,EAAU,GAAG,mBAAmB,WAEnD,KAAC,oBAZH,GAAA,UAkBA,uBAAwB,iBACtB,MAAC,oBAnBH,EAAA,UAyBA,KAAM,SAAC,GACL,GAAA,GAAA,EAAA,EAAA,CAAA,IAAI,EAAE,IAAI,UAAW,KAAC,GAAG,aAA8C,gBAA5B,GAAS,IAAI,UAAxD,KACE,KAAA,EAAA,EAAA,EAAA,EAAA,OAAA,EAAA,EAAA,kBACK,EAAK,cAAiB,KAAC,GAAG,YAC3B,EAAK,eAAe,QAAQ,sBA7BpC,EAAA,UAmCA,QAAS,SAAC,GACR,GAAA,GAAA,+DACA,KAAC,WAAW,EAAE,IAAI,SAAS,KAAK,IArClC,EAAA,UA0CA,SAAU,SAAC,GACT,GAAA,EAAA,QAAA,OAAA,EAAA,KAAA,WAAA,IAAA,EAAsB,OAAA,QAAS,EAC7B,KAAC,OAAO,QAAQ,KAAC,WAAW,GAAM,SADpC,QA3CF,EAAA,UAiDA,eAAgB,iBACd,MAAC,SAAU,EAAE,OAAO,EAAI,EAAU,OAAO,KAlD3C,EAAA,UAuDA,SAAU,WACR,GAAA,GAAA,EAAA,CAAA,GAAA,KAAA,UAAA,KAAA,IAAA,UACE,KAAC,OAAO,SAAS,SACnB,MAAC","sourcesContent":["\n_ = require \"underscore\"\n\nmodule.exports = (user_list)->\n\n #\n # A trivial Connector that simulates network delay.\n #\n class TestConnector\n\n #\n # @param {Engine} engine The transformation engine\n # @param {HistoryBuffer} HB\n # @param {Array} execution_listener You must ensure that whenever an operation is executed, every function in this Array is called.\n # @param {Yatta} yatta The Yatta framework.\n #\n constructor: (@engine, @HB, @execution_listener)->\n send_ = (o)=>\n @send o\n @execution_listener.push send_\n\n @applied_operations = []\n appliedOperationsListener = (o)=>\n @applied_operations.push o\n @execution_listener.push appliedOperationsListener\n if not (user_list?.length is 0)\n @engine.applyOps user_list[0].getHistoryBuffer()._encode()\n\n @unexecuted = {}\n\n #\n # This engine applied operations in a specific order.\n # Get the ops in the right order.\n #\n getOpsInExecutionOrder: ()->\n @applied_operations\n\n #\n # This function is called whenever an operation was executed.\n # @param {Operation} o The operation that was executed.\n #\n send: (o)->\n if (o.uid.creator is @HB.getUserId()) and (typeof o.uid.op_number isnt \"string\")\n for user in user_list\n if user.getUserId() isnt @HB.getUserId()\n user.getConnector().receive(o)\n\n #\n # This function is called whenever an operation was received from another peer.\n # @param {Operation} o The operation that was received.\n #\n receive: (o)->\n @unexecuted[o.uid.creator] ?= []\n @unexecuted[o.uid.creator].push o\n\n #\n # Flush one operation from the line of a specific user.\n #\n flushOne: (user)->\n if @unexecuted[user]?.length > 0\n @engine.applyOp @unexecuted[user].shift()\n\n #\n # Flush one operation on a random line.\n #\n flushOneRandom: ()->\n @flushOne (_.random 0, (user_list.length-1))\n\n #\n # Flush all operations on every line.\n #\n flushAll: ()->\n for n,ops of @unexecuted\n @engine.applyOps ops\n @unexecuted = {}\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Engine.coffee b/build/node/Engine.coffee new file mode 100644 index 00000000..55e3d99b --- /dev/null +++ b/build/node/Engine.coffee @@ -0,0 +1,101 @@ + +# +# The Engine handles how and in which order to execute operations and add operations to the HistoryBuffer. +# +class Engine + + # + # @param {HistoryBuffer} HB + # @param {Array} parser Defines how to parse encoded messages. + # + constructor: (@HB, @parser)-> + @unprocessed_ops = [] + + # + # Parses an operatio from the json format. It uses the specified parser in your OperationType module. + # + parseOperation: (json)-> + typeParser = @parser[json.type] + if typeParser? + typeParser json + else + throw new Error "You forgot to specify a parser for type #{json.type}. The message is #{JSON.stringify json}." + + # + # Apply a set of operations. E.g. the operations you received from another users HB.toJson(). + # @note You must not use this method when you already have ops in your HB! + # + applyOpsBundle: (ops_json)-> + ops = [] + for o in ops_json + ops.push @parseOperation o + for o in ops + @HB.addOperation o + for o in ops + if not o.execute() + @unprocessed_ops.push o + @tryUnprocessed() + + # + # Same as applyOps but operations that are already in the HB are not applied. + # @see Engine.applyOps + # + applyOpsCheckDouble: (ops_json)-> + for o in ops_json + if @HB.getOperation(o.uid)? + @applyOp o + + # + # Apply a set of operations. (Helper for using applyOp on Arrays) + # @see Engine.applyOp + applyOps: (ops_json)-> + for o in ops_json + @applyOp o + + # + # Apply an operation that you received from another peer. + # + applyOp: (op_json)-> + # $parse_and_execute will return false if $o_json was parsed and executed, otherwise the parsed operadion + o = @parseOperation op_json + @HB.addToCounter o + # @HB.addOperation o + if not o.execute() + @unprocessed_ops.push o + else + @HB.addOperation o + @tryUnprocessed() + + # + # Call this method when you applied a new operation. + # It checks if operations that were previously not executable are now executable. + # + tryUnprocessed: ()-> + while true + old_length = @unprocessed_ops.length + unprocessed = [] + for op in @unprocessed_ops + if not op.execute() + unprocessed.push op + else + @HB.addOperation op + @unprocessed_ops = unprocessed + if @unprocessed_ops.length is old_length + break + + + + +module.exports = Engine + + + + + + + + + + + + diff --git a/build/node/Engine.js b/build/node/Engine.js new file mode 100644 index 00000000..57ea9744 --- /dev/null +++ b/build/node/Engine.js @@ -0,0 +1,2 @@ +(function(){var t;t=function(){function t(t,e){this.HB=t,this.parser=e,this.unprocessed_ops=[]}return t.prototype.parseOperation=function(t){var e;if(e=this.parser[t.type],null!=e)return e(t);throw new Error("You forgot to specify a parser for type "+t.type+". The message is "+JSON.stringify(t)+".")},t.prototype.applyOpsBundle=function(t){var e,r,p,s,o,n,i,u;for(r=[],p=0,n=t.length;n>p;p++)e=t[p],r.push(this.parseOperation(e));for(s=0,i=r.length;i>s;s++)e=r[s],this.HB.addOperation(e);for(o=0,u=r.length;u>o;o++)e=r[o],e.execute()||this.unprocessed_ops.push(e);return this.tryUnprocessed()},t.prototype.applyOpsCheckDouble=function(t){var e,r,p,s;for(s=[],r=0,p=t.length;p>r;r++)e=t[r],s.push(null!=this.HB.getOperation(e.uid)?this.applyOp(e):void 0);return s},t.prototype.applyOps=function(t){var e,r,p,s;for(s=[],r=0,p=t.length;p>r;r++)e=t[r],s.push(this.applyOp(e));return s},t.prototype.applyOp=function(t){var e;return e=this.parseOperation(t),this.HB.addToCounter(e),e.execute()?this.HB.addOperation(e):this.unprocessed_ops.push(e),this.tryUnprocessed()},t.prototype.tryUnprocessed=function(){var t,e,r,p,s,o,n;for(n=[];;){for(t=this.unprocessed_ops.length,r=[],o=this.unprocessed_ops,p=0,s=o.length;s>p;p++)e=o[p],e.execute()?this.HB.addOperation(e):r.push(e);if(this.unprocessed_ops=r,this.unprocessed_ops.length===t)break;n.push(void 0)}return n},t}(),module.exports=t}).call(this); +//# sourceMappingURL=Engine.js.map \ No newline at end of file diff --git a/build/node/Frameworks/JsonYatta.coffee b/build/node/Frameworks/JsonYatta.coffee new file mode 100644 index 00000000..68258437 --- /dev/null +++ b/build/node/Frameworks/JsonYatta.coffee @@ -0,0 +1,85 @@ + +json_types_uninitialized = require "../Types/JsonTypes" +HistoryBuffer = require "../HistoryBuffer" +Engine = require "../Engine" + +# +# Framework for Json data-structures. +# Known values that are supported: +# * String +# * Integer +# * Array +# +class JsonYatta + + # + # @param {String} user_id Unique id of the peer. + # @param {Connector} Connector the connector class. + # + constructor: (user_id, Connector)-> + @HB = new HistoryBuffer user_id + json_types = json_types_uninitialized @HB + @engine = new Engine @HB, json_types.parser + @connector = new Connector @engine, @HB, json_types.execution_listener, @ + + first_word = new json_types.types.JsonType @HB.getReservedUniqueIdentifier() + @HB.addOperation(first_word).execute() + @root_element = first_word + + # + # @result JsonType + # + getRootElement: ()-> + @root_element + + # + # @see Engine + # + getEngine: ()-> + @engine + + # + # Get the initialized connector. + # + getConnector: ()-> + @connector + + # + # @see HistoryBuffer + # + getHistoryBuffer: ()-> + @HB + + # + # @see JsonType.setMutableDefault + # + setMutableDefault: (mutable)-> + @root_element.setMutableDefault(mutable) + + # + # Get the UserId from the HistoryBuffer object. + # In most cases this will be the same as the user_id value with which + # JsonYatta was initialized (Depending on the HistoryBuffer implementation). + # + getUserId: ()-> + @HB.getUserId() + + # + # @see JsonType.val + # + val : (name, content, mutable)-> + @root_element.val(name, content, mutable) + + # + # @see JsonType.value + # + Object.defineProperty JsonYatta.prototype, 'value', + get : -> @root_element.value + set : (o)-> + if o.constructor is {}.constructor + for o_name,o_obj of o + @val(o_name, o_obj, 'immutable') + else + throw new Error "You must only set Object values!" +window?.JsonYatta = JsonYatta +module.exports = JsonYatta diff --git a/build/node/Frameworks/JsonYatta.coffee.map b/build/node/Frameworks/JsonYatta.coffee.map new file mode 100755 index 00000000..f0dfa358 --- /dev/null +++ b/build/node/Frameworks/JsonYatta.coffee.map @@ -0,0 +1 @@ +{"version":3,"file":"Frameworks/JsonYatta.coffee","names":[],"mappings":"","sources":["Frameworks/JsonYatta.coffee"],"sourcesContent":["\njson_types_uninitialized = require \"../Types/JsonTypes\"\nHistoryBuffer = require \"../HistoryBuffer\"\nEngine = require \"../Engine\"\n\n#\n# Framework for Json data-structures.\n# Known values that are supported:\n# * String\n# * Integer\n# * Array\n#\nclass JsonYatta\n\n #\n # @param {String} user_id Unique id of the peer.\n # @param {Connector} Connector the connector class.\n #\n constructor: (user_id, Connector)->\n @HB = new HistoryBuffer user_id\n json_types = json_types_uninitialized @HB\n @engine = new Engine @HB, json_types.parser\n @connector = new Connector @engine, @HB, json_types.execution_listener, @\n\n first_word = new json_types.types.JsonType @HB.getReservedUniqueIdentifier()\n @HB.addOperation(first_word).execute()\n @root_element = first_word\n\n #\n # @result JsonType\n #\n getRootElement: ()->\n @root_element\n\n #\n # @see Engine\n #\n getEngine: ()->\n @engine\n\n #\n # Get the initialized connector.\n #\n getConnector: ()->\n @connector\n\n #\n # @see HistoryBuffer\n #\n getHistoryBuffer: ()->\n @HB\n\n #\n # @see JsonType.setMutableDefault\n #\n setMutableDefault: (mutable)->\n @root_element.setMutableDefault(mutable)\n\n #\n # Get the UserId from the HistoryBuffer object.\n # In most cases this will be the same as the user_id value with which\n # JsonYatta was initialized (Depending on the HistoryBuffer implementation).\n #\n getUserId: ()->\n @HB.getUserId()\n\n #\n # @see JsonType.val\n #\n val : (name, content, mutable)->\n @root_element.val(name, content, mutable)\n\n #\n # @see JsonType.value\n #\n Object.defineProperty JsonYatta.prototype, 'value',\n get : -> @root_element.value\n set : (o)->\n if o.constructor is {}.constructor\n for o_name,o_obj of o\n @val(o_name, o_obj, 'immutable')\n else\n throw new Error \"You must only set Object values!\"\nwindow?.JsonYatta = JsonYatta\nmodule.exports = JsonYatta\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Frameworks/JsonYatta.js b/build/node/Frameworks/JsonYatta.js new file mode 100644 index 00000000..4b2b4bac --- /dev/null +++ b/build/node/Frameworks/JsonYatta.js @@ -0,0 +1,2 @@ +(function(){var t,e,n,o;o=require("../Types/JsonTypes"),e=require("../HistoryBuffer"),t=require("../Engine"),n=function(){function n(n,r){var i,u;this.HB=new e(n),u=o(this.HB),this.engine=new t(this.HB,u.parser),this.connector=new r(this.engine,this.HB,u.execution_listener,this),i=new u.types.JsonType(this.HB.getReservedUniqueIdentifier()),this.HB.addOperation(i).execute(),this.root_element=i}return n.prototype.getRootElement=function(){return this.root_element},n.prototype.getEngine=function(){return this.engine},n.prototype.getConnector=function(){return this.connector},n.prototype.getHistoryBuffer=function(){return this.HB},n.prototype.setMutableDefault=function(t){return this.root_element.setMutableDefault(t)},n.prototype.getUserId=function(){return this.HB.getUserId()},n.prototype.val=function(t,e,n){return this.root_element.val(t,e,n)},Object.defineProperty(n.prototype,"value",{get:function(){return this.root_element.value},set:function(t){var e,n,o;if(t.constructor==={}.constructor){o=[];for(e in t)n=t[e],o.push(this.val(e,n,"immutable"));return o}throw new Error("You must only set Object values!")}}),n}(),"undefined"!=typeof window&&null!==window&&(window.JsonYatta=n),module.exports=n}).call(this); +//# sourceMappingURL=../Frameworks/JsonYatta.js.map \ No newline at end of file diff --git a/build/node/Frameworks/JsonYatta.js.map b/build/node/Frameworks/JsonYatta.js.map new file mode 100755 index 00000000..ebc4b4e7 --- /dev/null +++ b/build/node/Frameworks/JsonYatta.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Frameworks/JsonYatta.js","sources":["Frameworks/JsonYatta.coffee"],"names":[],"mappings":"CACA,WAAA,GAAA,GAAA,EAAA,EAAA,CAAA,GAA2B,QAAQ,sBACnC,EAAgB,QAAQ,oBACxB,EAAS,QAAQ,aASX,EAAA,WAMS,QAAA,GAAC,EAAS,GACrB,GAAA,GAAA,CAAA,MAAC,GAAS,GAAA,GAAc,GACxB,EAAa,EAAyB,KAAC,IACvC,KAAC,OAAa,GAAA,GAAO,KAAC,GAAI,EAAW,QACrC,KAAC,UAAgB,GAAA,GAAU,KAAC,OAAQ,KAAC,GAAI,EAAW,mBAAoB,MAExE,EAAiB,GAAA,GAAW,MAAM,SAAS,KAAC,GAAG,+BAC/C,KAAC,GAAG,aAAa,GAAY,UAC7B,KAAC,aAAe,QARlB,GAAA,UAaA,eAAgB,iBACd,MAAC,cAdH,EAAA,UAmBA,UAAW,iBACT,MAAC,QApBH,EAAA,UAyBA,aAAc,iBACZ,MAAC,WA1BH,EAAA,UA+BA,iBAAkB,iBAChB,MAAC,IAhCH,EAAA,UAqCA,kBAAmB,SAAC,SAClB,MAAC,aAAa,kBAAkB,IAtClC,EAAA,UA6CA,UAAW,iBACT,MAAC,GAAG,aA9CN,EAAA,UAmDA,IAAM,SAAC,EAAM,EAAS,SACpB,MAAC,aAAa,IAAI,EAAM,EAAS,IAKnC,OAAO,eAAe,EAAU,UAAW,SACzC,IAAM,iBAAG,MAAC,aAAa,OACvB,IAAM,SAAC,GACL,GAAA,GAAA,EAAA,CAAA,IAAG,EAAE,iBAAkB,YAAvB,CACE,SAAA,IAAA,UACE,EAAA,KAAA,KAAC,IAAI,EAAQ,EAAO,uBAEtB,KAAU,IAAA,OAAM,wFACxB,OAAQ,UAAY,GACpB,OAAO,QAAU","sourcesContent":["\njson_types_uninitialized = require \"../Types/JsonTypes\"\nHistoryBuffer = require \"../HistoryBuffer\"\nEngine = require \"../Engine\"\n\n#\n# Framework for Json data-structures.\n# Known values that are supported:\n# * String\n# * Integer\n# * Array\n#\nclass JsonYatta\n\n #\n # @param {String} user_id Unique id of the peer.\n # @param {Connector} Connector the connector class.\n #\n constructor: (user_id, Connector)->\n @HB = new HistoryBuffer user_id\n json_types = json_types_uninitialized @HB\n @engine = new Engine @HB, json_types.parser\n @connector = new Connector @engine, @HB, json_types.execution_listener, @\n\n first_word = new json_types.types.JsonType @HB.getReservedUniqueIdentifier()\n @HB.addOperation(first_word).execute()\n @root_element = first_word\n\n #\n # @result JsonType\n #\n getRootElement: ()->\n @root_element\n\n #\n # @see Engine\n #\n getEngine: ()->\n @engine\n\n #\n # Get the initialized connector.\n #\n getConnector: ()->\n @connector\n\n #\n # @see HistoryBuffer\n #\n getHistoryBuffer: ()->\n @HB\n\n #\n # @see JsonType.setMutableDefault\n #\n setMutableDefault: (mutable)->\n @root_element.setMutableDefault(mutable)\n\n #\n # Get the UserId from the HistoryBuffer object.\n # In most cases this will be the same as the user_id value with which\n # JsonYatta was initialized (Depending on the HistoryBuffer implementation).\n #\n getUserId: ()->\n @HB.getUserId()\n\n #\n # @see JsonType.val\n #\n val : (name, content, mutable)->\n @root_element.val(name, content, mutable)\n\n #\n # @see JsonType.value\n #\n Object.defineProperty JsonYatta.prototype, 'value',\n get : -> @root_element.value\n set : (o)->\n if o.constructor is {}.constructor\n for o_name,o_obj of o\n @val(o_name, o_obj, 'immutable')\n else\n throw new Error \"You must only set Object values!\"\nwindow?.JsonYatta = JsonYatta\nmodule.exports = JsonYatta\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Frameworks/TextYatta.coffee b/build/node/Frameworks/TextYatta.coffee new file mode 100644 index 00000000..f3839987 --- /dev/null +++ b/build/node/Frameworks/TextYatta.coffee @@ -0,0 +1,82 @@ + +text_types_uninitialized = require "../Types/TextTypes" +HistoryBuffer = require "../HistoryBuffer" +Engine = require "../Engine" + +# +# Framework for Text Datastructures. +# +class TextYatta + + # + # @param {String} user_id Uniqe user id that defines this peer. + # @param {Connector} Connector The connector defines how you connect to the other peers. + # + constructor: (user_id, Connector)-> + @HB = new HistoryBuffer user_id + text_types = text_types_uninitialized @HB + @engine = new Engine @HB, text_types.parser + @connector = new Connector @engine, @HB, text_types.execution_listener + + first_word = new text_types.types.Word undefined + @HB.addOperation(first_word).execute() + @root_element = first_word + + # + # @result Word + # + getRootElement: ()-> + @root_element + + # + # @see Engine + # + getEngine: ()-> + @engine + + # + # Get the initialized connector. + # + getConnector: ()-> + @connector + + # + # @see HistoryBuffer + # + getHistoryBuffer: ()-> + @HB + + # + # Get the UserId from the HistoryBuffer object. + # In most cases this will be the same as the user_id value with which + # JsonYatta was initialized (Depending on the HistoryBuffer implementation). + # + getUserId: ()-> + @HB.getUserId() + + # + # @see JsonType.val + # + val: ()-> + @root_element.val() + + # + # @see Word.insertText + # + insertText: (pos, content)-> + @root_element.insertText pos, content + + # + # @see Word.deleteText + # + deleteText: (pos, length)-> + @root_element.deleteText pos, length + + # + # @see Word.replaceText + # + replaceText: (text)-> + @root_element.replaceText text + + +module.exports = TextYatta diff --git a/build/node/Frameworks/TextYatta.coffee.map b/build/node/Frameworks/TextYatta.coffee.map new file mode 100755 index 00000000..fd3403d8 --- /dev/null +++ b/build/node/Frameworks/TextYatta.coffee.map @@ -0,0 +1 @@ +{"version":3,"file":"Frameworks/TextYatta.coffee","names":[],"mappings":"","sources":["Frameworks/TextYatta.coffee"],"sourcesContent":["\ntext_types_uninitialized = require \"../Types/TextTypes\"\nHistoryBuffer = require \"../HistoryBuffer\"\nEngine = require \"../Engine\"\n\n#\n# Framework for Text Datastructures.\n#\nclass TextYatta\n\n #\n # @param {String} user_id Uniqe user id that defines this peer.\n # @param {Connector} Connector The connector defines how you connect to the other peers.\n #\n constructor: (user_id, Connector)->\n @HB = new HistoryBuffer user_id\n text_types = text_types_uninitialized @HB\n @engine = new Engine @HB, text_types.parser\n @connector = new Connector @engine, @HB, text_types.execution_listener\n\n first_word = new text_types.types.Word undefined\n @HB.addOperation(first_word).execute()\n @root_element = first_word\n\n #\n # @result Word\n #\n getRootElement: ()->\n @root_element\n\n #\n # @see Engine\n #\n getEngine: ()->\n @engine\n\n #\n # Get the initialized connector.\n #\n getConnector: ()->\n @connector\n\n #\n # @see HistoryBuffer\n #\n getHistoryBuffer: ()->\n @HB\n\n #\n # Get the UserId from the HistoryBuffer object.\n # In most cases this will be the same as the user_id value with which\n # JsonYatta was initialized (Depending on the HistoryBuffer implementation).\n #\n getUserId: ()->\n @HB.getUserId()\n\n #\n # @see JsonType.val\n #\n val: ()->\n @root_element.val()\n\n #\n # @see Word.insertText\n #\n insertText: (pos, content)->\n @root_element.insertText pos, content\n\n #\n # @see Word.deleteText\n #\n deleteText: (pos, length)->\n @root_element.deleteText pos, length\n\n #\n # @see Word.replaceText\n #\n replaceText: (text)->\n @root_element.replaceText text\n\n\nmodule.exports = TextYatta\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Frameworks/TextYatta.js b/build/node/Frameworks/TextYatta.js new file mode 100644 index 00000000..17832273 --- /dev/null +++ b/build/node/Frameworks/TextYatta.js @@ -0,0 +1,2 @@ +(function(){var e,t,n,r;r=require("../Types/TextTypes"),t=require("../HistoryBuffer"),e=require("../Engine"),n=function(){function n(n,o){var i,s;this.HB=new t(n),s=r(this.HB),this.engine=new e(this.HB,s.parser),this.connector=new o(this.engine,this.HB,s.execution_listener),i=new s.types.Word(void 0),this.HB.addOperation(i).execute(),this.root_element=i}return n.prototype.getRootElement=function(){return this.root_element},n.prototype.getEngine=function(){return this.engine},n.prototype.getConnector=function(){return this.connector},n.prototype.getHistoryBuffer=function(){return this.HB},n.prototype.getUserId=function(){return this.HB.getUserId()},n.prototype.val=function(){return this.root_element.val()},n.prototype.insertText=function(e,t){return this.root_element.insertText(e,t)},n.prototype.deleteText=function(e,t){return this.root_element.deleteText(e,t)},n.prototype.replaceText=function(e){return this.root_element.replaceText(e)},n}(),module.exports=n}).call(this); +//# sourceMappingURL=../Frameworks/TextYatta.js.map \ No newline at end of file diff --git a/build/node/Frameworks/TextYatta.js.map b/build/node/Frameworks/TextYatta.js.map new file mode 100755 index 00000000..d23790b2 --- /dev/null +++ b/build/node/Frameworks/TextYatta.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Frameworks/TextYatta.js","sources":["Frameworks/TextYatta.coffee"],"names":[],"mappings":"CACA,WAAA,GAAA,GAAA,EAAA,EAAA,CAAA,GAA2B,QAAQ,sBACnC,EAAgB,QAAQ,oBACxB,EAAS,QAAQ,aAKX,EAAA,WAMS,QAAA,GAAC,EAAS,GACrB,GAAA,GAAA,CAAA,MAAC,GAAS,GAAA,GAAc,GACxB,EAAa,EAAyB,KAAC,IACvC,KAAC,OAAa,GAAA,GAAO,KAAC,GAAI,EAAW,QACrC,KAAC,UAAgB,GAAA,GAAU,KAAC,OAAQ,KAAC,GAAI,EAAW,oBAEpD,EAAiB,GAAA,GAAW,MAAM,KAAK,QACvC,KAAC,GAAG,aAAa,GAAY,UAC7B,KAAC,aAAe,QARlB,GAAA,UAaA,eAAgB,iBACd,MAAC,cAdH,EAAA,UAmBA,UAAW,iBACT,MAAC,QApBH,EAAA,UAyBA,aAAc,iBACZ,MAAC,WA1BH,EAAA,UA+BA,iBAAkB,iBAChB,MAAC,IAhCH,EAAA,UAuCA,UAAW,iBACT,MAAC,GAAG,aAxCN,EAAA,UA6CA,IAAK,iBACH,MAAC,aAAa,OA9ChB,EAAA,UAmDA,WAAY,SAAC,EAAK,SAChB,MAAC,aAAa,WAAW,EAAK,IApDhC,EAAA,UAyDA,WAAY,SAAC,EAAK,SAChB,MAAC,aAAa,WAAW,EAAK,IA1DhC,EAAA,UA+DA,YAAa,SAAC,SACZ,MAAC,aAAa,YAAY,SAG9B,OAAO,QAAU","sourcesContent":["\ntext_types_uninitialized = require \"../Types/TextTypes\"\nHistoryBuffer = require \"../HistoryBuffer\"\nEngine = require \"../Engine\"\n\n#\n# Framework for Text Datastructures.\n#\nclass TextYatta\n\n #\n # @param {String} user_id Uniqe user id that defines this peer.\n # @param {Connector} Connector The connector defines how you connect to the other peers.\n #\n constructor: (user_id, Connector)->\n @HB = new HistoryBuffer user_id\n text_types = text_types_uninitialized @HB\n @engine = new Engine @HB, text_types.parser\n @connector = new Connector @engine, @HB, text_types.execution_listener\n\n first_word = new text_types.types.Word undefined\n @HB.addOperation(first_word).execute()\n @root_element = first_word\n\n #\n # @result Word\n #\n getRootElement: ()->\n @root_element\n\n #\n # @see Engine\n #\n getEngine: ()->\n @engine\n\n #\n # Get the initialized connector.\n #\n getConnector: ()->\n @connector\n\n #\n # @see HistoryBuffer\n #\n getHistoryBuffer: ()->\n @HB\n\n #\n # Get the UserId from the HistoryBuffer object.\n # In most cases this will be the same as the user_id value with which\n # JsonYatta was initialized (Depending on the HistoryBuffer implementation).\n #\n getUserId: ()->\n @HB.getUserId()\n\n #\n # @see JsonType.val\n #\n val: ()->\n @root_element.val()\n\n #\n # @see Word.insertText\n #\n insertText: (pos, content)->\n @root_element.insertText pos, content\n\n #\n # @see Word.deleteText\n #\n deleteText: (pos, length)->\n @root_element.deleteText pos, length\n\n #\n # @see Word.replaceText\n #\n replaceText: (text)->\n @root_element.replaceText text\n\n\nmodule.exports = TextYatta\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/HistoryBuffer.coffee b/build/node/HistoryBuffer.coffee new file mode 100644 index 00000000..e9aa5032 --- /dev/null +++ b/build/node/HistoryBuffer.coffee @@ -0,0 +1,123 @@ + +# +# An object that holds all applied operations. +# +# @note The HistoryBuffer is commonly abbreviated to HB. +# +class HistoryBuffer + + # + # Creates an empty HB. + # @param {Object} user_id Creator of the HB. + # + constructor: (@user_id)-> + @operation_counter = {} + @buffer = {} + @change_listeners = [] + + # + # Get the user id with wich the History Buffer was initialized. + # + getUserId: ()-> + @user_id + + # + # There is only one reserved unique identifier (uid), so use it wisely. + # I propose to use it in your Framework, to create something like a root element. + # An operation with this identifier is not propagated to other clients. + # This is why everybode must create the same operation with this uid. + # + getReservedUniqueIdentifier: ()-> + { + creator : '_' + op_number : '_' + } + + # + # Get the operation counter that describes the current state of the document. + # + getOperationCounter: ()-> + res = {} + for user,ctn of @operation_counter + res[user] = ctn + res + + # + # Encode this operation in such a way that it can be parsed by remote peers. + # + _encode: (state_vector={})-> + json = [] + unknown = (user, o_number)-> + if (not user?) or (not o_number?) + throw new Error "dah!" + not state_vector[user]? or state_vector[user] <= o_number + + for u_name,user of @buffer + for o_number,o of user + if not isNaN(parseInt(o_number)) and unknown(u_name, o_number) + o_json = o._encode() + if o.next_cl? + o_next = o.next_cl + while o_next.next_cl? and unknown(o_next.creator, o_next.op_number) + o_next = o_next.next_cl + o_json.next = o_next.getUid() + else if o.prev_cl? + o_prev = o.prev_cl + while o_prev.prev_cl? and unknown(o_next.creator, o_next.op_number) + o_prev = o_prev.prev_cl + o_json.prev = o_prev.getUid() + json.push o_json + + json + + # + # Get the number of operations that were created by a user. + # Accordingly you will get the next operation number that is expected from that user. + # This will increment the operation counter. + # + getNextOperationIdentifier: (user_id)-> + if not user_id? + user_id = @user_id + if not @operation_counter[user_id]? + @operation_counter[user_id] = 0 + uid = + 'creator' : user_id + 'op_number' : @operation_counter[user_id] + @operation_counter[user_id]++ + uid + + # + # Retrieve an operation from a unique id. + # + getOperation: (uid)-> + if uid instanceof Object + @buffer[uid.creator]?[uid.op_number] + else if not uid? + else + throw new Error "This type of uid is not defined!" + # + # Add an operation to the HB. Note that this will not link it against + # other operations (it wont executed) + # + addOperation: (o)-> + if not @buffer[o.creator]? + @buffer[o.creator] = {} + if @buffer[o.creator][o.op_number]? + throw new Error "You must not overwrite operations!" + @buffer[o.creator][o.op_number] = o + o + + # + # Increment the operation_counter that defines the current state of the Engine. + # + addToCounter: (o)-> + if not @operation_counter[o.creator]? + @operation_counter[o.creator] = 0 + if typeof o.op_number is 'number' and o.creator isnt @getUserId() + @operation_counter[o.creator]++ + #if @operation_counter[o.creator] isnt (o.op_number + 1) + #console.log (@operation_counter[o.creator] - (o.op_number + 1)) + #console.log o + #throw new Error "You don't receive operations in the proper order. Try counting like this 0,1,2,3,4,.. ;)" + +module.exports = HistoryBuffer diff --git a/build/node/HistoryBuffer.js b/build/node/HistoryBuffer.js new file mode 100644 index 00000000..523dc44a --- /dev/null +++ b/build/node/HistoryBuffer.js @@ -0,0 +1,2 @@ +(function(){var r;r=function(){function r(r){this.user_id=r,this.operation_counter={},this.buffer={},this.change_listeners=[]}return r.prototype.getUserId=function(){return this.user_id},r.prototype.getReservedUniqueIdentifier=function(){return{creator:"_",op_number:"_"}},r.prototype.getOperationCounter=function(){var r,t,e,o;t={},o=this.operation_counter;for(e in o)r=o[e],t[e]=r;return t},r.prototype._encode=function(r){var t,e,o,n,i,u,c,p,f,l;null==r&&(r={}),t=[],p=function(t,e){if(null==t||null==e)throw new Error("dah!");return null==r[t]||r[t]<=e},l=this.buffer;for(c in l){f=l[c];for(i in f)if(e=f[i],!isNaN(parseInt(i))&&p(c,i)){if(o=e._encode(),null!=e.next_cl){for(n=e.next_cl;null!=n.next_cl&&p(n.creator,n.op_number);)n=n.next_cl;o.next=n.getUid()}else if(null!=e.prev_cl){for(u=e.prev_cl;null!=u.prev_cl&&p(n.creator,n.op_number);)u=u.prev_cl;o.prev=u.getUid()}t.push(o)}}return t},r.prototype.getNextOperationIdentifier=function(r){var t;return null==r&&(r=this.user_id),null==this.operation_counter[r]&&(this.operation_counter[r]=0),t={creator:r,op_number:this.operation_counter[r]},this.operation_counter[r]++,t},r.prototype.getOperation=function(r){var t;if(r instanceof Object)return null!=(t=this.buffer[r.creator])?t[r.op_number]:void 0;if(null!=r)throw new Error("This type of uid is not defined!")},r.prototype.addOperation=function(r){if(null==this.buffer[r.creator]&&(this.buffer[r.creator]={}),null!=this.buffer[r.creator][r.op_number])throw new Error("You must not overwrite operations!");return this.buffer[r.creator][r.op_number]=r,r},r.prototype.addToCounter=function(r){return null==this.operation_counter[r.creator]&&(this.operation_counter[r.creator]=0),"number"==typeof r.op_number&&r.creator!==this.getUserId()?this.operation_counter[r.creator]++:void 0},r}(),module.exports=r}).call(this); +//# sourceMappingURL=HistoryBuffer.js.map \ No newline at end of file diff --git a/build/node/HistoryBuffer.js.map b/build/node/HistoryBuffer.js.map new file mode 100755 index 00000000..5e3061ff --- /dev/null +++ b/build/node/HistoryBuffer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"HistoryBuffer.js","sources":["HistoryBuffer.coffee"],"names":[],"mappings":"CAMA,WAAA,GAAA,EAAM,GAAA,WAMS,QAAA,GAAE,GAAD,KAAC,QAAA,EACb,KAAC,qBACD,KAAC,UACD,KAAC,0BAHH,GAAA,UAQA,UAAW,iBACT,MAAC,SATH,EAAA,UAiBA,4BAA6B,kBAEzB,QAAU,IACV,UAAY,MApBhB,EAAA,UA0BA,oBAAqB,WACnB,GAAA,GAAA,EAAA,EAAA,CAAA,MACA,EAAA,KAAA,iBAAA,KAAA,IAAA,UACE,EAAI,GAAQ,QACd,IA9BF,EAAA,UAmCA,QAAS,SAAC,GACR,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,YADQ,MACR,KACA,EAAU,SAAC,EAAM,GACf,GAAQ,MAAA,GAAe,MAAA,EACrB,KAAU,IAAA,OAAM,cACd,OAAA,EAAA,IAAuB,EAAa,IAAS,GAEnD,EAAA,KAAA,MAAA,KAAA,IAAA,GAAA,OACE,KAAA,IAAA,GACE,WAAG,MAAU,SAAS,KAAe,EAAQ,EAAQ,GAArD,CAEE,GADA,EAAS,EAAE,UACR,MAAA,EAAA,QAAH,CAEE,IADA,EAAS,EAAE,QACL,MAAA,EAAA,SAAoB,EAAQ,EAAO,QAAS,EAAO,YACvD,EAAS,EAAO,OAClB,GAAO,KAAO,EAAO,aAClB,IAAG,MAAA,EAAA,QAAH,CAEH,IADA,EAAS,EAAE,QACL,MAAA,EAAA,SAAoB,EAAQ,EAAO,QAAS,EAAO,YACvD,EAAS,EAAO,OAClB,GAAO,KAAO,EAAO,SACvB,EAAK,KAAK,UAEhB,IA1DF,EAAA,UAiEA,2BAA4B,SAAC,GAC3B,GAAA,SAAO,OAAA,IACL,EAAU,KAAC,SACN,MAAA,KAAA,kBAAA,KACL,KAAC,kBAAkB,GAAW,GAChC,GACE,QAAY,EACZ,UAAc,KAAC,kBAAkB,IACnC,KAAC,kBAAkB,KACnB,GA1EF,EAAA,UA+EA,aAAc,SAAC,GACb,GAAA,EAAA,IAAG,YAAe,kDACM,EAAI,WAAJ,MACnB,IAAO,MAAA,EAEV,KAAU,IAAA,OAAM,qCApFpB,EAAA,UAyFA,aAAc,SAAC,GAGb,GAFO,MAAA,KAAA,OAAA,EAAA,WACL,KAAC,OAAO,EAAE,aACT,MAAA,KAAA,OAAA,EAAA,SAAA,EAAA,WACD,KAAU,IAAA,OAAM,4CAClB,MAAC,OAAO,EAAE,SAAS,EAAE,WAAa,EAClC,GA/FF,EAAA,UAoGA,aAAc,SAAC,GAGb,MAFO,OAAA,KAAA,kBAAA,EAAA,WACL,KAAC,kBAAkB,EAAE,SAAW,GACT,gBAAtB,GAAS,WAA0B,EAAE,UAAa,KAAC,YACpD,KAAC,kBAAkB,EAAE,WADvB,aAOJ,OAAO,QAAU","sourcesContent":["\n#\n# An object that holds all applied operations.\n#\n# @note The HistoryBuffer is commonly abbreviated to HB.\n#\nclass HistoryBuffer\n\n #\n # Creates an empty HB.\n # @param {Object} user_id Creator of the HB.\n #\n constructor: (@user_id)->\n @operation_counter = {}\n @buffer = {}\n @change_listeners = []\n\n #\n # Get the user id with wich the History Buffer was initialized.\n #\n getUserId: ()->\n @user_id\n\n #\n # There is only one reserved unique identifier (uid), so use it wisely.\n # I propose to use it in your Framework, to create something like a root element.\n # An operation with this identifier is not propagated to other clients.\n # This is why everybode must create the same operation with this uid.\n #\n getReservedUniqueIdentifier: ()->\n {\n creator : '_'\n op_number : '_'\n }\n\n #\n # Get the operation counter that describes the current state of the document.\n #\n getOperationCounter: ()->\n res = {}\n for user,ctn of @operation_counter\n res[user] = ctn\n res\n\n #\n # Encode this operation in such a way that it can be parsed by remote peers.\n #\n _encode: (state_vector={})->\n json = []\n unknown = (user, o_number)->\n if (not user?) or (not o_number?)\n throw new Error \"dah!\"\n not state_vector[user]? or state_vector[user] <= o_number\n\n for u_name,user of @buffer\n for o_number,o of user\n if not isNaN(parseInt(o_number)) and unknown(u_name, o_number)\n o_json = o._encode()\n if o.next_cl?\n o_next = o.next_cl\n while o_next.next_cl? and unknown(o_next.creator, o_next.op_number)\n o_next = o_next.next_cl\n o_json.next = o_next.getUid()\n else if o.prev_cl?\n o_prev = o.prev_cl\n while o_prev.prev_cl? and unknown(o_next.creator, o_next.op_number)\n o_prev = o_prev.prev_cl\n o_json.prev = o_prev.getUid()\n json.push o_json\n\n json\n\n #\n # Get the number of operations that were created by a user.\n # Accordingly you will get the next operation number that is expected from that user.\n # This will increment the operation counter.\n #\n getNextOperationIdentifier: (user_id)->\n if not user_id?\n user_id = @user_id\n if not @operation_counter[user_id]?\n @operation_counter[user_id] = 0\n uid =\n 'creator' : user_id\n 'op_number' : @operation_counter[user_id]\n @operation_counter[user_id]++\n uid\n\n #\n # Retrieve an operation from a unique id.\n #\n getOperation: (uid)->\n if uid instanceof Object\n @buffer[uid.creator]?[uid.op_number]\n else if not uid?\n else\n throw new Error \"This type of uid is not defined!\"\n #\n # Add an operation to the HB. Note that this will not link it against\n # other operations (it wont executed)\n #\n addOperation: (o)->\n if not @buffer[o.creator]?\n @buffer[o.creator] = {}\n if @buffer[o.creator][o.op_number]?\n throw new Error \"You must not overwrite operations!\"\n @buffer[o.creator][o.op_number] = o\n o\n\n #\n # Increment the operation_counter that defines the current state of the Engine.\n #\n addToCounter: (o)->\n if not @operation_counter[o.creator]?\n @operation_counter[o.creator] = 0\n if typeof o.op_number is 'number' and o.creator isnt @getUserId()\n @operation_counter[o.creator]++\n #if @operation_counter[o.creator] isnt (o.op_number + 1)\n #console.log (@operation_counter[o.creator] - (o.op_number + 1))\n #console.log o\n #throw new Error \"You don't receive operations in the proper order. Try counting like this 0,1,2,3,4,.. ;)\"\n\nmodule.exports = HistoryBuffer\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Types/BasicTypes.coffee b/build/node/Types/BasicTypes.coffee new file mode 100644 index 00000000..eeeb6bca --- /dev/null +++ b/build/node/Types/BasicTypes.coffee @@ -0,0 +1,439 @@ +module.exports = (HB)-> + # @see Engine.parse + parser = {} + execution_listener = [] + + # + # A generic interface to operations. + # + # An operation has the following methods: + # _encode: encodes an operation (needed only if instance of this operation is sent). + # execute: execute the effects of this operations. Good examples are Insert-type and AddName-type + # val: in the case that the operation holds a value + # + # Furthermore an encodable operation has a parser. + # + class Operation + + # + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # @see HistoryBuffer.getNextOperationIdentifier + # + constructor: (uid)-> + if not uid? + uid = HB.getNextOperationIdentifier() + { + 'creator': @creator + 'op_number' : @op_number + } = uid + + # + # Add an event listener. It depends on the operation which events are supported. + # @param {String} event Name of the event. + # @param {Function} f f is executed in case the event fires. + # + on: (event, f)-> + @event_listeners ?= {} + @event_listeners[event] ?= [] + @event_listeners[event].push f + + # + # Fire an event. + # TODO: Do something with timeouts. You don't want this to fire for every operation (e.g. insert). + # + callEvent: (event, args)-> + if @event_listeners[event]? + for f in @event_listeners[event] + f.call @, event, args + + # + # Set the parent of this operation. + # + setParent: (o)-> + @parent = o + + # + # Computes a unique identifier (uid) that identifies this operation. + # + getUid: ()-> + { 'creator': @creator, 'op_number': @op_number } + + # + # @private + # Notify the all the listeners. + # + execute: ()-> + @is_executed = true + for l in execution_listener + l @_encode() + @ + + # + # @private + # Operations may depend on other operations (linked lists, etc.). + # The saveOperation and validateSavedOperations methods provide + # an easy way to refer to these operations via an uid or object reference. + # + # For example: We can create a new Delete operation that deletes the operation $o like this + # - var d = new Delete(uid, $o); or + # - var d = new Delete(uid, $o.getUid()); + # Either way we want to access $o via d.deletes. In the second case validateSavedOperations must be called first. + # + # @overload saveOperation(name, op_uid) + # @param {String} name The name of the operation. After validating (with validateSavedOperations) the instantiated operation will be accessible via this[name]. + # @param {Object} op_uid A uid that refers to an operation + # @overload saveOperation(name, op) + # @param {String} name The name of the operation. After calling this function op is accessible via this[name]. + # @param {Operation} op An Operation object + # + saveOperation: (name, op)-> + + # + # Every instance of $Operation must have an $execute function. + # We use duck-typing to check if op is instantiated since there + # could exist multiple classes of $Operation + # + if op?.execute? + # is instantiated + @[name] = op + else if op? + # not initialized. Do it when calling $validateSavedOperations() + @unchecked ?= {} + @unchecked[name] = op + + # + # @private + # After calling this function all not instantiated operations will be accessible. + # @see Operation.saveOperation + # + # @return [Boolean] Whether it was possible to instantiate all operations. + # + validateSavedOperations: ()-> + uninstantiated = {} + success = @ + for name, op_uid of @unchecked + op = HB.getOperation op_uid + if op + @[name] = op + else + uninstantiated[name] = op_uid + success = false + delete @unchecked + if not success + @unchecked = uninstantiated + success + + + + # + # A simple Delete-type operation that deletes an Insert-type operation. + # + class Delete extends Operation + + # + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # @param {Object} deletes UID or reference of the operation that this to be deleted. + # + constructor: (uid, deletes)-> + @saveOperation 'deletes', deletes + super uid + + # + # @private + # Convert all relevant information of this operation to the json-format. + # This result can be sent to other clients. + # + _encode: ()-> + { + 'type': "Delete" + 'uid': @getUid() + 'deletes': @deletes.getUid() + } + + # + # @private + # Apply the deletion. + # + execute: ()-> + if @validateSavedOperations() + @deletes.applyDelete @ + super + @ + else + false + + # + # Define how to parse Delete operations. + # + parser['Delete'] = (o)-> + { + 'uid' : uid + 'deletes': deletes_uid + } = o + new Delete uid, deletes_uid + + # + # A simple insert-type operation. + # + # An insert operation is always positioned between two other insert operations. + # Internally this is realized as associative lists, whereby each insert operation has a predecessor and a successor. + # For the sake of efficiency we maintain two lists: + # - The short-list (abbrev. sl) maintains only the operations that are not deleted + # - The complete-list (abbrev. cl) maintains all operations + # + class Insert extends Operation + + # + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # @param {Operation} prev_cl The predecessor of this operation in the complete-list (cl) + # @param {Operation} next_cl The successor of this operation in the complete-list (cl) + # + # @see HistoryBuffer.getNextOperationIdentifier + # + constructor: (uid, prev_cl, next_cl, origin)-> + @saveOperation 'prev_cl', prev_cl + @saveOperation 'next_cl', next_cl + if origin? + @saveOperation 'origin', origin + else + @saveOperation 'origin', prev_cl + super uid + + # + # @private + # + applyDelete: (o)-> + @deleted_by ?= [] + @deleted_by.push o + + # + # If isDeleted() is true this operation won't be maintained in the sl + # + isDeleted: ()-> + @deleted_by?.length > 0 + + # + # @private + # The amount of positions that $this operation was moved to the right. + # + getDistanceToOrigin: ()-> + d = 0 + o = @prev_cl + while true + if @origin is o + break + d++ + #TODO: delete this + if @ is @prev_cl + throw new Error "this should not happen ;) " + o = o.prev_cl + d + + # + # @private + # Update the short list + # TODO (Unused) + update_sl: ()-> + o = @prev_cl + update: (dest_cl,dest_sl)-> + while true + if o.isDeleted() + o = o[dest_cl] + else + @[dest_sl] = o + + break + update "prev_cl", "prev_sl" + update "next_cl", "prev_sl" + + + + # + # @private + # Include this operation in the associative lists. + # + execute: ()-> + if @is_executed? + return @ + if not @validateSavedOperations() + return false + else + if @prev_cl?.validateSavedOperations() and @next_cl?.validateSavedOperations() and @prev_cl.next_cl isnt @ + distance_to_origin = 0 + o = @prev_cl.next_cl + i = 0 + # $this has to find a unique position between origin and the next known character + # case 1: $origin equals $o.origin: the $creator parameter decides if left or right + # let $OL= [o1,o2,o3,o4], whereby $this is to be inserted between o1 and o4 + # o2,o3 and o4 origin is 1 (the position of o2) + # there is the case that $this.creator < o2.creator, but o3.creator < $this.creator + # then o2 knows o3. Since on another client $OL could be [o1,o3,o4] the problem is complex + # therefore $this would be always to the right of o3 + # case 2: $origin < $o.origin + # if current $this insert_position > $o origin: $this ins + # else $insert_position will not change (maybe we encounter case 1 later, then this will be to the right of $o) + # case 3: $origin > $o.origin + # $this insert_position is to the left of $o (forever!) + while true + if not o? + # TODO: Debugging + console.log JSON.stringify @prev_cl.getUid() + console.log JSON.stringify @next_cl.getUid() + if o isnt @next_cl + # $o happened concurrently + if o.getDistanceToOrigin() is i + # case 1 + if o.creator < @creator + @prev_cl = o + distance_to_origin = i + 1 + else + # nop + else if o.getDistanceToOrigin() < i + # case 2 + if i - distance_to_origin <= o.getDistanceToOrigin() + @prev_cl = o + distance_to_origin = i + 1 + else + #nop + else + # case 3 + break + i++ + o = o.next_cl + else + # $this knows that $o exists, + break + # now reconnect everything + @next_cl = @prev_cl.next_cl + @prev_cl.next_cl = @ + @next_cl.prev_cl = @ + super # notify the execution_listeners + @ + + # + # Defines an object that is cannot be changed. You can use this to set an immutable string, or a number. + # + class ImmutableObject extends Insert + + # + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # @param {Object} content + # + constructor: (uid, @content, prev, next, origin)-> + super uid, prev, next, origin + + # + # @return [String] The content of this operation. + # + val : ()-> + @content + + # + # Encode this operation in such a way that it can be parsed by remote peers. + # + _encode: ()-> + json = { + 'type': "ImmutableObject" + 'uid' : @getUid() + 'content' : @content + } + if @prev_cl? + json['prev'] = @prev_cl.getUid() + if @next_cl? + json['next'] = @next_cl.getUid() + if @origin? and @origin isnt @prev_cl + json["origin"] = @origin.getUid() + json + + parser['ImmutableObject'] = (json)-> + { + 'uid' : uid + 'content' : content + 'prev': prev + 'next': next + 'origin' : origin + } = json + new ImmutableObject uid, content, prev, next, origin + + # + # A delimiter is placed at the end and at the beginning of the associative lists. + # This is necessary in order to have a beginning and an end even if the content + # of the Engine is empty. + # + class Delimiter extends Operation + # + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # @param {Operation} prev_cl The predecessor of this operation in the complete-list (cl) + # @param {Operation} next_cl The successor of this operation in the complete-list (cl) + # + # @see HistoryBuffer.getNextOperationIdentifier + # + constructor: (uid, prev_cl, next_cl, origin)-> + @saveOperation 'prev_cl', prev_cl + @saveOperation 'next_cl', next_cl + @saveOperation 'origin', prev_cl + super uid + + # + # If isDeleted() is true this operation won't be maintained in the sl + # + isDeleted: ()-> + false + + # + # @private + # + execute: ()-> + if @unchecked?['next_cl']? + super + else if @unchecked?['prev_cl'] + if @validateSavedOperations() + if @prev_cl.next_cl? + throw new Error "Probably duplicated operations" + @prev_cl.next_cl = @ + delete @prev_cl.unchecked.next_cl + super + else + false + else if @prev_cl? and not @prev_cl.next_cl? + delete @prev_cl.unchecked.next_cl + @prev_cl.next_cl = @ + else if @prev_cl? or @next_cl? + super + else + throw new Error "Delimiter is unsufficient defined!" + + # + # @private + # + _encode: ()-> + { + 'type' : "Delimiter" + 'uid' : @getUid() + 'prev' : @prev_cl?.getUid() + 'next' : @next_cl?.getUid() + } + + parser['Delimiter'] = (json)-> + { + 'uid' : uid + 'prev' : prev + 'next' : next + } = json + new Delimiter uid, prev, next + + # This is what this module exports after initializing it with the HistoryBuffer + { + 'types' : + 'Delete' : Delete + 'Insert' : Insert + 'Delimiter': Delimiter + 'Operation': Operation + 'ImmutableObject' : ImmutableObject + 'parser' : parser + 'execution_listener' : execution_listener + } + + + + diff --git a/build/node/Types/BasicTypes.coffee.map b/build/node/Types/BasicTypes.coffee.map new file mode 100755 index 00000000..1ae7af8c --- /dev/null +++ b/build/node/Types/BasicTypes.coffee.map @@ -0,0 +1 @@ +{"version":3,"file":"Types/BasicTypes.coffee","names":[],"mappings":"","sources":["Types/BasicTypes.coffee"],"sourcesContent":["module.exports = (HB)->\n # @see Engine.parse\n parser = {}\n execution_listener = []\n\n #\n # A generic interface to operations.\n #\n # An operation has the following methods:\n # _encode: encodes an operation (needed only if instance of this operation is sent).\n # execute: execute the effects of this operations. Good examples are Insert-type and AddName-type\n # val: in the case that the operation holds a value\n #\n # Furthermore an encodable operation has a parser.\n #\n class Operation\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @see HistoryBuffer.getNextOperationIdentifier\n #\n constructor: (uid)->\n if not uid?\n uid = HB.getNextOperationIdentifier()\n {\n 'creator': @creator\n 'op_number' : @op_number\n } = uid\n\n #\n # Add an event listener. It depends on the operation which events are supported.\n # @param {String} event Name of the event.\n # @param {Function} f f is executed in case the event fires.\n #\n on: (event, f)->\n @event_listeners ?= {}\n @event_listeners[event] ?= []\n @event_listeners[event].push f\n\n #\n # Fire an event.\n # TODO: Do something with timeouts. You don't want this to fire for every operation (e.g. insert).\n #\n callEvent: (event, args)->\n if @event_listeners[event]?\n for f in @event_listeners[event]\n f.call @, event, args\n\n #\n # Set the parent of this operation.\n #\n setParent: (o)->\n @parent = o\n\n #\n # Computes a unique identifier (uid) that identifies this operation.\n #\n getUid: ()->\n { 'creator': @creator, 'op_number': @op_number }\n\n #\n # @private\n # Notify the all the listeners.\n #\n execute: ()->\n @is_executed = true\n for l in execution_listener\n l @_encode()\n @\n\n #\n # @private\n # Operations may depend on other operations (linked lists, etc.).\n # The saveOperation and validateSavedOperations methods provide\n # an easy way to refer to these operations via an uid or object reference.\n #\n # For example: We can create a new Delete operation that deletes the operation $o like this\n # - var d = new Delete(uid, $o); or\n # - var d = new Delete(uid, $o.getUid());\n # Either way we want to access $o via d.deletes. In the second case validateSavedOperations must be called first.\n #\n # @overload saveOperation(name, op_uid)\n # @param {String} name The name of the operation. After validating (with validateSavedOperations) the instantiated operation will be accessible via this[name].\n # @param {Object} op_uid A uid that refers to an operation\n # @overload saveOperation(name, op)\n # @param {String} name The name of the operation. After calling this function op is accessible via this[name].\n # @param {Operation} op An Operation object\n #\n saveOperation: (name, op)->\n\n #\n # Every instance of $Operation must have an $execute function.\n # We use duck-typing to check if op is instantiated since there\n # could exist multiple classes of $Operation\n #\n if op?.execute?\n # is instantiated\n @[name] = op\n else if op?\n # not initialized. Do it when calling $validateSavedOperations()\n @unchecked ?= {}\n @unchecked[name] = op\n\n #\n # @private\n # After calling this function all not instantiated operations will be accessible.\n # @see Operation.saveOperation\n #\n # @return [Boolean] Whether it was possible to instantiate all operations.\n #\n validateSavedOperations: ()->\n uninstantiated = {}\n success = @\n for name, op_uid of @unchecked\n op = HB.getOperation op_uid\n if op\n @[name] = op\n else\n uninstantiated[name] = op_uid\n success = false\n delete @unchecked\n if not success\n @unchecked = uninstantiated\n success\n\n\n\n #\n # A simple Delete-type operation that deletes an Insert-type operation.\n #\n class Delete extends Operation\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Object} deletes UID or reference of the operation that this to be deleted.\n #\n constructor: (uid, deletes)->\n @saveOperation 'deletes', deletes\n super uid\n\n #\n # @private\n # Convert all relevant information of this operation to the json-format.\n # This result can be sent to other clients.\n #\n _encode: ()->\n {\n 'type': \"Delete\"\n 'uid': @getUid()\n 'deletes': @deletes.getUid()\n }\n\n #\n # @private\n # Apply the deletion.\n #\n execute: ()->\n if @validateSavedOperations()\n @deletes.applyDelete @\n super\n @\n else\n false\n\n #\n # Define how to parse Delete operations.\n #\n parser['Delete'] = (o)->\n {\n 'uid' : uid\n 'deletes': deletes_uid\n } = o\n new Delete uid, deletes_uid\n\n #\n # A simple insert-type operation.\n #\n # An insert operation is always positioned between two other insert operations.\n # Internally this is realized as associative lists, whereby each insert operation has a predecessor and a successor.\n # For the sake of efficiency we maintain two lists:\n # - The short-list (abbrev. sl) maintains only the operations that are not deleted\n # - The complete-list (abbrev. cl) maintains all operations\n #\n class Insert extends Operation\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Operation} prev_cl The predecessor of this operation in the complete-list (cl)\n # @param {Operation} next_cl The successor of this operation in the complete-list (cl)\n #\n # @see HistoryBuffer.getNextOperationIdentifier\n #\n constructor: (uid, prev_cl, next_cl, origin)->\n @saveOperation 'prev_cl', prev_cl\n @saveOperation 'next_cl', next_cl\n if origin?\n @saveOperation 'origin', origin\n else\n @saveOperation 'origin', prev_cl\n super uid\n\n #\n # @private\n #\n applyDelete: (o)->\n @deleted_by ?= []\n @deleted_by.push o\n\n #\n # If isDeleted() is true this operation won't be maintained in the sl\n #\n isDeleted: ()->\n @deleted_by?.length > 0\n\n #\n # @private\n # The amount of positions that $this operation was moved to the right.\n #\n getDistanceToOrigin: ()->\n d = 0\n o = @prev_cl\n while true\n if @origin is o\n break\n d++\n #TODO: delete this\n if @ is @prev_cl\n throw new Error \"this should not happen ;) \"\n o = o.prev_cl\n d\n\n #\n # @private\n # Update the short list\n # TODO (Unused)\n update_sl: ()->\n o = @prev_cl\n update: (dest_cl,dest_sl)->\n while true\n if o.isDeleted()\n o = o[dest_cl]\n else\n @[dest_sl] = o\n\n break\n update \"prev_cl\", \"prev_sl\"\n update \"next_cl\", \"prev_sl\"\n\n\n\n #\n # @private\n # Include this operation in the associative lists.\n #\n execute: ()->\n if @is_executed?\n return @\n if not @validateSavedOperations()\n return false\n else\n if @prev_cl?.validateSavedOperations() and @next_cl?.validateSavedOperations() and @prev_cl.next_cl isnt @\n distance_to_origin = 0\n o = @prev_cl.next_cl\n i = 0\n # $this has to find a unique position between origin and the next known character\n # case 1: $origin equals $o.origin: the $creator parameter decides if left or right\n # let $OL= [o1,o2,o3,o4], whereby $this is to be inserted between o1 and o4\n # o2,o3 and o4 origin is 1 (the position of o2)\n # there is the case that $this.creator < o2.creator, but o3.creator < $this.creator\n # then o2 knows o3. Since on another client $OL could be [o1,o3,o4] the problem is complex\n # therefore $this would be always to the right of o3\n # case 2: $origin < $o.origin\n # if current $this insert_position > $o origin: $this ins\n # else $insert_position will not change (maybe we encounter case 1 later, then this will be to the right of $o)\n # case 3: $origin > $o.origin\n # $this insert_position is to the left of $o (forever!)\n while true\n if not o?\n # TODO: Debugging\n console.log JSON.stringify @prev_cl.getUid()\n console.log JSON.stringify @next_cl.getUid()\n if o isnt @next_cl\n # $o happened concurrently\n if o.getDistanceToOrigin() is i\n # case 1\n if o.creator < @creator\n @prev_cl = o\n distance_to_origin = i + 1\n else\n # nop\n else if o.getDistanceToOrigin() < i\n # case 2\n if i - distance_to_origin <= o.getDistanceToOrigin()\n @prev_cl = o\n distance_to_origin = i + 1\n else\n #nop\n else\n # case 3\n break\n i++\n o = o.next_cl\n else\n # $this knows that $o exists,\n break\n # now reconnect everything\n @next_cl = @prev_cl.next_cl\n @prev_cl.next_cl = @\n @next_cl.prev_cl = @\n super # notify the execution_listeners\n @\n\n #\n # Defines an object that is cannot be changed. You can use this to set an immutable string, or a number.\n #\n class ImmutableObject extends Insert\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Object} content\n #\n constructor: (uid, @content, prev, next, origin)->\n super uid, prev, next, origin\n\n #\n # @return [String] The content of this operation.\n #\n val : ()->\n @content\n\n #\n # Encode this operation in such a way that it can be parsed by remote peers.\n #\n _encode: ()->\n json = {\n 'type': \"ImmutableObject\"\n 'uid' : @getUid()\n 'content' : @content\n }\n if @prev_cl?\n json['prev'] = @prev_cl.getUid()\n if @next_cl?\n json['next'] = @next_cl.getUid()\n if @origin? and @origin isnt @prev_cl\n json[\"origin\"] = @origin.getUid()\n json\n\n parser['ImmutableObject'] = (json)->\n {\n 'uid' : uid\n 'content' : content\n 'prev': prev\n 'next': next\n 'origin' : origin\n } = json\n new ImmutableObject uid, content, prev, next, origin\n\n #\n # A delimiter is placed at the end and at the beginning of the associative lists.\n # This is necessary in order to have a beginning and an end even if the content\n # of the Engine is empty.\n #\n class Delimiter extends Operation\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Operation} prev_cl The predecessor of this operation in the complete-list (cl)\n # @param {Operation} next_cl The successor of this operation in the complete-list (cl)\n #\n # @see HistoryBuffer.getNextOperationIdentifier\n #\n constructor: (uid, prev_cl, next_cl, origin)->\n @saveOperation 'prev_cl', prev_cl\n @saveOperation 'next_cl', next_cl\n @saveOperation 'origin', prev_cl\n super uid\n\n #\n # If isDeleted() is true this operation won't be maintained in the sl\n #\n isDeleted: ()->\n false\n\n #\n # @private\n #\n execute: ()->\n if @unchecked?['next_cl']?\n super\n else if @unchecked?['prev_cl']\n if @validateSavedOperations()\n if @prev_cl.next_cl?\n throw new Error \"Probably duplicated operations\"\n @prev_cl.next_cl = @\n delete @prev_cl.unchecked.next_cl\n super\n else\n false\n else if @prev_cl? and not @prev_cl.next_cl?\n delete @prev_cl.unchecked.next_cl\n @prev_cl.next_cl = @\n else if @prev_cl? or @next_cl?\n super\n else\n throw new Error \"Delimiter is unsufficient defined!\"\n\n #\n # @private\n #\n _encode: ()->\n {\n 'type' : \"Delimiter\"\n 'uid' : @getUid()\n 'prev' : @prev_cl?.getUid()\n 'next' : @next_cl?.getUid()\n }\n\n parser['Delimiter'] = (json)->\n {\n 'uid' : uid\n 'prev' : prev\n 'next' : next\n } = json\n new Delimiter uid, prev, next\n\n # This is what this module exports after initializing it with the HistoryBuffer\n {\n 'types' :\n 'Delete' : Delete\n 'Insert' : Insert\n 'Delimiter': Delimiter\n 'Operation': Operation\n 'ImmutableObject' : ImmutableObject\n 'parser' : parser\n 'execution_listener' : execution_listener\n }\n\n\n\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Types/BasicTypes.js b/build/node/Types/BasicTypes.js new file mode 100644 index 00000000..ecbf7b03 --- /dev/null +++ b/build/node/Types/BasicTypes.js @@ -0,0 +1,2 @@ +(function(){var e={}.hasOwnProperty,t=function(t,n){function i(){this.constructor=t}for(var r in n)e.call(n,r)&&(t[r]=n[r]);return i.prototype=n.prototype,t.prototype=new i,t.__super__=n.prototype,t};module.exports=function(e){var n,i,r,s,l,o,c;return c={},o=[],l=function(){function t(t){null==t&&(t=e.getNextOperationIdentifier()),this.creator=t.creator,this.op_number=t.op_number}return t.prototype.on=function(e,t){var n;return null==this.event_listeners&&(this.event_listeners={}),null==(n=this.event_listeners)[e]&&(n[e]=[]),this.event_listeners[e].push(t)},t.prototype.callEvent=function(e,t){var n,i,r,s,l;if(null!=this.event_listeners[e]){for(s=this.event_listeners[e],l=[],i=0,r=s.length;r>i;i++)n=s[i],l.push(n.call(this,e,t));return l}},t.prototype.setParent=function(e){return this.parent=e},t.prototype.getUid=function(){return{creator:this.creator,op_number:this.op_number}},t.prototype.execute=function(){var e,t,n;for(this.is_executed=!0,t=0,n=o.length;n>t;t++)(e=o[t])(this._encode());return this},t.prototype.saveOperation=function(e,t){return null!=(null!=t?t.execute:void 0)?this[e]=t:null!=t?(null==this.unchecked&&(this.unchecked={}),this.unchecked[e]=t):void 0},t.prototype.validateSavedOperations=function(){var t,n,i,r,s,l;s={},r=this,l=this.unchecked;for(t in l)i=l[t],n=e.getOperation(i),n?this[t]=n:(s[t]=i,r=!1);return delete this.unchecked,r||(this.unchecked=s),r},t}(),n=function(e){function n(e,t){this.saveOperation("deletes",t),n.__super__.constructor.call(this,e)}return t(n,e),n.prototype._encode=function(){return{type:"Delete",uid:this.getUid(),deletes:this.deletes.getUid()}},n.prototype.execute=function(){return this.validateSavedOperations()?(this.deletes.applyDelete(this),n.__super__.execute.apply(this,arguments),this):!1},n}(l),c.Delete=function(e){var t,i;return i=e.uid,t=e.deletes,new n(i,t)},s=function(e){function n(e,t,i,r){this.saveOperation("prev_cl",t),this.saveOperation("next_cl",i),null!=r?this.saveOperation("origin",r):this.saveOperation("origin",t),n.__super__.constructor.call(this,e)}return t(n,e),n.prototype.applyDelete=function(e){return null==this.deleted_by&&(this.deleted_by=[]),this.deleted_by.push(e)},n.prototype.isDeleted=function(){var e;return(null!=(e=this.deleted_by)?e.length:void 0)>0},n.prototype.getDistanceToOrigin=function(){var e,t;for(e=0,t=this.prev_cl;;){if(this.origin===t)break;if(e++,this===this.prev_cl)throw new Error("this should not happen ;) ");t=t.prev_cl}return e},n.prototype.update_sl=function(){var e;return e=this.prev_cl,update("prev_cl","prev_sl"),update("next_cl","prev_sl")},n.prototype.execute=function(){var e,t,i,r,s;if(null!=this.is_executed)return this;if(this.validateSavedOperations()){if((null!=(r=this.prev_cl)?r.validateSavedOperations():void 0)&&(null!=(s=this.next_cl)?s.validateSavedOperations():void 0)&&this.prev_cl.next_cl!==this){for(e=0,i=this.prev_cl.next_cl,t=0;;){if(null==i&&(console.log(JSON.stringify(this.prev_cl.getUid())),console.log(JSON.stringify(this.next_cl.getUid()))),i===this.next_cl)break;if(i.getDistanceToOrigin()===t)i.creator\n # @see Engine.parse\n parser = {}\n execution_listener = []\n\n #\n # A generic interface to operations.\n #\n # An operation has the following methods:\n # _encode: encodes an operation (needed only if instance of this operation is sent).\n # execute: execute the effects of this operations. Good examples are Insert-type and AddName-type\n # val: in the case that the operation holds a value\n #\n # Furthermore an encodable operation has a parser.\n #\n class Operation\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @see HistoryBuffer.getNextOperationIdentifier\n #\n constructor: (uid)->\n if not uid?\n uid = HB.getNextOperationIdentifier()\n {\n 'creator': @creator\n 'op_number' : @op_number\n } = uid\n\n #\n # Add an event listener. It depends on the operation which events are supported.\n # @param {String} event Name of the event.\n # @param {Function} f f is executed in case the event fires.\n #\n on: (event, f)->\n @event_listeners ?= {}\n @event_listeners[event] ?= []\n @event_listeners[event].push f\n\n #\n # Fire an event.\n # TODO: Do something with timeouts. You don't want this to fire for every operation (e.g. insert).\n #\n callEvent: (event, args)->\n if @event_listeners[event]?\n for f in @event_listeners[event]\n f.call @, event, args\n\n #\n # Set the parent of this operation.\n #\n setParent: (o)->\n @parent = o\n\n #\n # Computes a unique identifier (uid) that identifies this operation.\n #\n getUid: ()->\n { 'creator': @creator, 'op_number': @op_number }\n\n #\n # @private\n # Notify the all the listeners.\n #\n execute: ()->\n @is_executed = true\n for l in execution_listener\n l @_encode()\n @\n\n #\n # @private\n # Operations may depend on other operations (linked lists, etc.).\n # The saveOperation and validateSavedOperations methods provide\n # an easy way to refer to these operations via an uid or object reference.\n #\n # For example: We can create a new Delete operation that deletes the operation $o like this\n # - var d = new Delete(uid, $o); or\n # - var d = new Delete(uid, $o.getUid());\n # Either way we want to access $o via d.deletes. In the second case validateSavedOperations must be called first.\n #\n # @overload saveOperation(name, op_uid)\n # @param {String} name The name of the operation. After validating (with validateSavedOperations) the instantiated operation will be accessible via this[name].\n # @param {Object} op_uid A uid that refers to an operation\n # @overload saveOperation(name, op)\n # @param {String} name The name of the operation. After calling this function op is accessible via this[name].\n # @param {Operation} op An Operation object\n #\n saveOperation: (name, op)->\n\n #\n # Every instance of $Operation must have an $execute function.\n # We use duck-typing to check if op is instantiated since there\n # could exist multiple classes of $Operation\n #\n if op?.execute?\n # is instantiated\n @[name] = op\n else if op?\n # not initialized. Do it when calling $validateSavedOperations()\n @unchecked ?= {}\n @unchecked[name] = op\n\n #\n # @private\n # After calling this function all not instantiated operations will be accessible.\n # @see Operation.saveOperation\n #\n # @return [Boolean] Whether it was possible to instantiate all operations.\n #\n validateSavedOperations: ()->\n uninstantiated = {}\n success = @\n for name, op_uid of @unchecked\n op = HB.getOperation op_uid\n if op\n @[name] = op\n else\n uninstantiated[name] = op_uid\n success = false\n delete @unchecked\n if not success\n @unchecked = uninstantiated\n success\n\n\n\n #\n # A simple Delete-type operation that deletes an Insert-type operation.\n #\n class Delete extends Operation\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Object} deletes UID or reference of the operation that this to be deleted.\n #\n constructor: (uid, deletes)->\n @saveOperation 'deletes', deletes\n super uid\n\n #\n # @private\n # Convert all relevant information of this operation to the json-format.\n # This result can be sent to other clients.\n #\n _encode: ()->\n {\n 'type': \"Delete\"\n 'uid': @getUid()\n 'deletes': @deletes.getUid()\n }\n\n #\n # @private\n # Apply the deletion.\n #\n execute: ()->\n if @validateSavedOperations()\n @deletes.applyDelete @\n super\n @\n else\n false\n\n #\n # Define how to parse Delete operations.\n #\n parser['Delete'] = (o)->\n {\n 'uid' : uid\n 'deletes': deletes_uid\n } = o\n new Delete uid, deletes_uid\n\n #\n # A simple insert-type operation.\n #\n # An insert operation is always positioned between two other insert operations.\n # Internally this is realized as associative lists, whereby each insert operation has a predecessor and a successor.\n # For the sake of efficiency we maintain two lists:\n # - The short-list (abbrev. sl) maintains only the operations that are not deleted\n # - The complete-list (abbrev. cl) maintains all operations\n #\n class Insert extends Operation\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Operation} prev_cl The predecessor of this operation in the complete-list (cl)\n # @param {Operation} next_cl The successor of this operation in the complete-list (cl)\n #\n # @see HistoryBuffer.getNextOperationIdentifier\n #\n constructor: (uid, prev_cl, next_cl, origin)->\n @saveOperation 'prev_cl', prev_cl\n @saveOperation 'next_cl', next_cl\n if origin?\n @saveOperation 'origin', origin\n else\n @saveOperation 'origin', prev_cl\n super uid\n\n #\n # @private\n #\n applyDelete: (o)->\n @deleted_by ?= []\n @deleted_by.push o\n\n #\n # If isDeleted() is true this operation won't be maintained in the sl\n #\n isDeleted: ()->\n @deleted_by?.length > 0\n\n #\n # @private\n # The amount of positions that $this operation was moved to the right.\n #\n getDistanceToOrigin: ()->\n d = 0\n o = @prev_cl\n while true\n if @origin is o\n break\n d++\n #TODO: delete this\n if @ is @prev_cl\n throw new Error \"this should not happen ;) \"\n o = o.prev_cl\n d\n\n #\n # @private\n # Update the short list\n # TODO (Unused)\n update_sl: ()->\n o = @prev_cl\n update: (dest_cl,dest_sl)->\n while true\n if o.isDeleted()\n o = o[dest_cl]\n else\n @[dest_sl] = o\n\n break\n update \"prev_cl\", \"prev_sl\"\n update \"next_cl\", \"prev_sl\"\n\n\n\n #\n # @private\n # Include this operation in the associative lists.\n #\n execute: ()->\n if @is_executed?\n return @\n if not @validateSavedOperations()\n return false\n else\n if @prev_cl?.validateSavedOperations() and @next_cl?.validateSavedOperations() and @prev_cl.next_cl isnt @\n distance_to_origin = 0\n o = @prev_cl.next_cl\n i = 0\n # $this has to find a unique position between origin and the next known character\n # case 1: $origin equals $o.origin: the $creator parameter decides if left or right\n # let $OL= [o1,o2,o3,o4], whereby $this is to be inserted between o1 and o4\n # o2,o3 and o4 origin is 1 (the position of o2)\n # there is the case that $this.creator < o2.creator, but o3.creator < $this.creator\n # then o2 knows o3. Since on another client $OL could be [o1,o3,o4] the problem is complex\n # therefore $this would be always to the right of o3\n # case 2: $origin < $o.origin\n # if current $this insert_position > $o origin: $this ins\n # else $insert_position will not change (maybe we encounter case 1 later, then this will be to the right of $o)\n # case 3: $origin > $o.origin\n # $this insert_position is to the left of $o (forever!)\n while true\n if not o?\n # TODO: Debugging\n console.log JSON.stringify @prev_cl.getUid()\n console.log JSON.stringify @next_cl.getUid()\n if o isnt @next_cl\n # $o happened concurrently\n if o.getDistanceToOrigin() is i\n # case 1\n if o.creator < @creator\n @prev_cl = o\n distance_to_origin = i + 1\n else\n # nop\n else if o.getDistanceToOrigin() < i\n # case 2\n if i - distance_to_origin <= o.getDistanceToOrigin()\n @prev_cl = o\n distance_to_origin = i + 1\n else\n #nop\n else\n # case 3\n break\n i++\n o = o.next_cl\n else\n # $this knows that $o exists,\n break\n # now reconnect everything\n @next_cl = @prev_cl.next_cl\n @prev_cl.next_cl = @\n @next_cl.prev_cl = @\n super # notify the execution_listeners\n @\n\n #\n # Defines an object that is cannot be changed. You can use this to set an immutable string, or a number.\n #\n class ImmutableObject extends Insert\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Object} content\n #\n constructor: (uid, @content, prev, next, origin)->\n super uid, prev, next, origin\n\n #\n # @return [String] The content of this operation.\n #\n val : ()->\n @content\n\n #\n # Encode this operation in such a way that it can be parsed by remote peers.\n #\n _encode: ()->\n json = {\n 'type': \"ImmutableObject\"\n 'uid' : @getUid()\n 'content' : @content\n }\n if @prev_cl?\n json['prev'] = @prev_cl.getUid()\n if @next_cl?\n json['next'] = @next_cl.getUid()\n if @origin? and @origin isnt @prev_cl\n json[\"origin\"] = @origin.getUid()\n json\n\n parser['ImmutableObject'] = (json)->\n {\n 'uid' : uid\n 'content' : content\n 'prev': prev\n 'next': next\n 'origin' : origin\n } = json\n new ImmutableObject uid, content, prev, next, origin\n\n #\n # A delimiter is placed at the end and at the beginning of the associative lists.\n # This is necessary in order to have a beginning and an end even if the content\n # of the Engine is empty.\n #\n class Delimiter extends Operation\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Operation} prev_cl The predecessor of this operation in the complete-list (cl)\n # @param {Operation} next_cl The successor of this operation in the complete-list (cl)\n #\n # @see HistoryBuffer.getNextOperationIdentifier\n #\n constructor: (uid, prev_cl, next_cl, origin)->\n @saveOperation 'prev_cl', prev_cl\n @saveOperation 'next_cl', next_cl\n @saveOperation 'origin', prev_cl\n super uid\n\n #\n # If isDeleted() is true this operation won't be maintained in the sl\n #\n isDeleted: ()->\n false\n\n #\n # @private\n #\n execute: ()->\n if @unchecked?['next_cl']?\n super\n else if @unchecked?['prev_cl']\n if @validateSavedOperations()\n if @prev_cl.next_cl?\n throw new Error \"Probably duplicated operations\"\n @prev_cl.next_cl = @\n delete @prev_cl.unchecked.next_cl\n super\n else\n false\n else if @prev_cl? and not @prev_cl.next_cl?\n delete @prev_cl.unchecked.next_cl\n @prev_cl.next_cl = @\n else if @prev_cl? or @next_cl?\n super\n else\n throw new Error \"Delimiter is unsufficient defined!\"\n\n #\n # @private\n #\n _encode: ()->\n {\n 'type' : \"Delimiter\"\n 'uid' : @getUid()\n 'prev' : @prev_cl?.getUid()\n 'next' : @next_cl?.getUid()\n }\n\n parser['Delimiter'] = (json)->\n {\n 'uid' : uid\n 'prev' : prev\n 'next' : next\n } = json\n new Delimiter uid, prev, next\n\n # This is what this module exports after initializing it with the HistoryBuffer\n {\n 'types' :\n 'Delete' : Delete\n 'Insert' : Insert\n 'Delimiter': Delimiter\n 'Operation': Operation\n 'ImmutableObject' : ImmutableObject\n 'parser' : parser\n 'execution_listener' : execution_listener\n }\n\n\n\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Types/JsonTypes.coffee b/build/node/Types/JsonTypes.coffee new file mode 100644 index 00000000..727e57a4 --- /dev/null +++ b/build/node/Types/JsonTypes.coffee @@ -0,0 +1,210 @@ +text_types_uninitialized = require "./TextTypes" + +module.exports = (HB)-> + text_types = text_types_uninitialized HB + types = text_types.types + parser = text_types.parser + + createJsonWrapper = (_jsonType)-> + + # + # A JsonWrapper was intended to be a convenient wrapper for the JsonType. + # But it can make things more difficult than they are. + # @see JsonType + # + # @example create a JsonWrapper + # # You get a JsonWrapper from a JsonType by calling + # w = yatta.value + # + # It creates Javascripts -getter and -setter methods for each property that JsonType maintains. + # @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty + # + # @example Getter Example + # # you can access the x property of yatta by calling + # w.x + # # instead of + # yatta.val('x') + # + # @note You can only overwrite existing values! Setting a new property won't have any effect! + # + # @example Setter Example + # # you can set an existing x property of yatta by calling + # w.x = "text" + # # instead of + # yatta.val('x', "text") + # + # In order to set a new property you have to overwrite an existing property. + # Therefore the JsonWrapper supports a special feature that should make things more convenient + # (we can argue about that, use the JsonType if you don't like it ;). + # If you overwrite an object property of the JsonWrapper with a new object, it will result in a merged version of the objects. + # Let w.p the property that is to be overwritten and o the new value. E.g. w.p = o + # * The result has all properties of o + # * The result has all properties of w.p if they don't occur under the same property-name in o. + # + # @example Conflict Example + # yatta.value = {a : "string"} + # w = yatta.value + # console.log(w) # {a : "string"} + # w.a = {a : {b : "string"}} + # console.log(w) # {a : {b : "String"}} + # w.a = {a : {c : 4}} + # console.log(w) # {a : {b : "String", c : 4}} + # + # @example Common Pitfalls + # w = yatta.value + # # Setting a new property + # w.newProperty = "Awesome" + # console.log(w.newProperty == "Awesome") # false, w.newProperty is undefined + # # overwrite the w object + # w = {newProperty : "Awesome"} + # console.log(w.newProperty == "Awesome") # true!, but .. + # console.log(yatta.value.newProperty == "Awesome") # false, you are only allowed to set properties! + # # The solution + # yatta.value = {newProperty : "Awesome"} + # console.log(w.newProperty == "Awesome") # true! + # + class JsonWrapper + + # + # @param {JsonType} jsonType Instance of the JsonType that this class wrappes. + # + constructor: (jsonType)-> + for name, obj of jsonType.map + do (name, obj)-> + Object.defineProperty JsonWrapper.prototype, name, + get : -> + x = obj.val() + if x instanceof JsonType + createJsonWrapper x + else if x instanceof types.ImmutableObject + x.val() + else + x + set : (o)-> + if o.constructor is {}.constructor + overwrite = jsonType.val(name) + for o_name,o_obj of o + overwrite.val(o_name, o_obj, 'immutable') + else + jsonType.val(name, o, 'immutable') + enumerable: true + configurable: false + new JsonWrapper _jsonType + + # + # Manages Object-like values. + # + class JsonType extends types.MapManager + + # + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # @param {Object} initial_value Create this operation with an initial value. + # @param {String|Boolean} Whether the initial_value should be created as mutable. (Optional - see setMutableDefault) + # + constructor: (uid, initial_value, mutable)-> + super uid + if initial_value? + if typeof initial_value isnt "object" + throw new Error "The initial value of JsonTypes must be of type Object! (current type: #{typeof initial_value})" + for name,o of initial_value + @val name, o, mutable + + # + # Whether the default is 'mutable' (true) or 'immutable' (false) + # + mutable_default: + true + + # + # Set if the default is 'mutable' or 'immutable' + # @param {String|Boolean} mutable Set either 'mutable' / true or 'immutable' / false + setMutableDefault: (mutable)-> + if mutable is true or mutable is 'mutable' + JsonType.prototype.mutable_default = true + else if mutable is false or mutable is 'immutable' + JsonType.prototype.mutable_default = false + else + throw new Error 'Set mutable either "mutable" or "immutable"!' + 'OK' + + # + # @overload val() + # Get this as a Json object. + # @return [Json] + # + # @overload val(name) + # Get value of a property. + # @param {String} name Name of the object property. + # @return [JsonType|Word|String|Object] Depending on the value of the property. If mutable it will return a Operation-type object, if immutable it will return String/Object. + # + # @overload val(name, content) + # Set a new property. + # @param {String} name Name of the object property. + # @param {Object|String} content Content of the object property. + # @return [JsonType] This object. (supports chaining) + # + val: (name, content, mutable)-> + if typeof name is 'object' + # Special case. First argument is an object. Then the second arg is mutable. + # Keep that in mind when reading the following.. + for o_name,o of name + @val(o_name,o,content) + @ + else if name? and content? + if mutable? + if mutable is true or mutable is 'mutable' + mutable = true + else + mutable = false + else + mutable = @mutable_default + if typeof content is 'function' + @ # Just do nothing + else if ((not mutable) or typeof content is 'number') and content.constructor isnt Object + obj = HB.addOperation(new types.ImmutableObject undefined, content).execute() + super name, obj + else + if typeof content is 'string' + word = HB.addOperation(new types.Word undefined).execute() + word.insertText 0, content + super name, word + else if content.constructor is Object + json = HB.addOperation(new JsonType undefined, content, mutable).execute() + super name, json + else + throw new Error "You must not set #{typeof content}-types in collaborative Json-objects!" + else + super name, content + + Object.defineProperty JsonType.prototype, 'value', + get : -> createJsonWrapper @ + set : (o)-> + if o.constructor is {}.constructor + for o_name,o_obj of o + @val(o_name, o_obj, 'immutable') + else + throw new Error "You must only set Object values!" + + # + # @private + # + _encode: ()-> + { + 'type' : "JsonType" + 'uid' : @getUid() + } + + parser['JsonType'] = (json)-> + { + 'uid' : uid + } = json + new JsonType uid + + + + + types['JsonType'] = JsonType + + text_types + + diff --git a/build/node/Types/JsonTypes.coffee.map b/build/node/Types/JsonTypes.coffee.map new file mode 100755 index 00000000..97662532 --- /dev/null +++ b/build/node/Types/JsonTypes.coffee.map @@ -0,0 +1 @@ +{"version":3,"file":"Types/JsonTypes.coffee","names":[],"mappings":"","sources":["Types/JsonTypes.coffee"],"sourcesContent":["text_types_uninitialized = require \"./TextTypes\"\n\nmodule.exports = (HB)->\n text_types = text_types_uninitialized HB\n types = text_types.types\n parser = text_types.parser\n\n createJsonWrapper = (_jsonType)->\n\n #\n # A JsonWrapper was intended to be a convenient wrapper for the JsonType.\n # But it can make things more difficult than they are.\n # @see JsonType\n #\n # @example create a JsonWrapper\n # # You get a JsonWrapper from a JsonType by calling\n # w = yatta.value\n #\n # It creates Javascripts -getter and -setter methods for each property that JsonType maintains.\n # @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\n #\n # @example Getter Example\n # # you can access the x property of yatta by calling\n # w.x\n # # instead of\n # yatta.val('x')\n #\n # @note You can only overwrite existing values! Setting a new property won't have any effect!\n #\n # @example Setter Example\n # # you can set an existing x property of yatta by calling\n # w.x = \"text\"\n # # instead of\n # yatta.val('x', \"text\")\n #\n # In order to set a new property you have to overwrite an existing property.\n # Therefore the JsonWrapper supports a special feature that should make things more convenient\n # (we can argue about that, use the JsonType if you don't like it ;).\n # If you overwrite an object property of the JsonWrapper with a new object, it will result in a merged version of the objects.\n # Let w.p the property that is to be overwritten and o the new value. E.g. w.p = o\n # * The result has all properties of o\n # * The result has all properties of w.p if they don't occur under the same property-name in o.\n #\n # @example Conflict Example\n # yatta.value = {a : \"string\"}\n # w = yatta.value\n # console.log(w) # {a : \"string\"}\n # w.a = {a : {b : \"string\"}}\n # console.log(w) # {a : {b : \"String\"}}\n # w.a = {a : {c : 4}}\n # console.log(w) # {a : {b : \"String\", c : 4}}\n #\n # @example Common Pitfalls\n # w = yatta.value\n # # Setting a new property\n # w.newProperty = \"Awesome\"\n # console.log(w.newProperty == \"Awesome\") # false, w.newProperty is undefined\n # # overwrite the w object\n # w = {newProperty : \"Awesome\"}\n # console.log(w.newProperty == \"Awesome\") # true!, but ..\n # console.log(yatta.value.newProperty == \"Awesome\") # false, you are only allowed to set properties!\n # # The solution\n # yatta.value = {newProperty : \"Awesome\"}\n # console.log(w.newProperty == \"Awesome\") # true!\n #\n class JsonWrapper\n\n #\n # @param {JsonType} jsonType Instance of the JsonType that this class wrappes.\n #\n constructor: (jsonType)->\n for name, obj of jsonType.map\n do (name, obj)->\n Object.defineProperty JsonWrapper.prototype, name,\n get : ->\n x = obj.val()\n if x instanceof JsonType\n createJsonWrapper x\n else if x instanceof types.ImmutableObject\n x.val()\n else\n x\n set : (o)->\n if o.constructor is {}.constructor\n overwrite = jsonType.val(name)\n for o_name,o_obj of o\n overwrite.val(o_name, o_obj, 'immutable')\n else\n jsonType.val(name, o, 'immutable')\n enumerable: true\n configurable: false\n new JsonWrapper _jsonType\n\n #\n # Manages Object-like values.\n #\n class JsonType extends types.MapManager\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Object} initial_value Create this operation with an initial value.\n # @param {String|Boolean} Whether the initial_value should be created as mutable. (Optional - see setMutableDefault)\n #\n constructor: (uid, initial_value, mutable)->\n super uid\n if initial_value?\n if typeof initial_value isnt \"object\"\n throw new Error \"The initial value of JsonTypes must be of type Object! (current type: #{typeof initial_value})\"\n for name,o of initial_value\n @val name, o, mutable\n\n #\n # Whether the default is 'mutable' (true) or 'immutable' (false)\n #\n mutable_default:\n true\n\n #\n # Set if the default is 'mutable' or 'immutable'\n # @param {String|Boolean} mutable Set either 'mutable' / true or 'immutable' / false\n setMutableDefault: (mutable)->\n if mutable is true or mutable is 'mutable'\n JsonType.prototype.mutable_default = true\n else if mutable is false or mutable is 'immutable'\n JsonType.prototype.mutable_default = false\n else\n throw new Error 'Set mutable either \"mutable\" or \"immutable\"!'\n 'OK'\n\n #\n # @overload val()\n # Get this as a Json object.\n # @return [Json]\n #\n # @overload val(name)\n # Get value of a property.\n # @param {String} name Name of the object property.\n # @return [JsonType|Word|String|Object] Depending on the value of the property. If mutable it will return a Operation-type object, if immutable it will return String/Object.\n #\n # @overload val(name, content)\n # Set a new property.\n # @param {String} name Name of the object property.\n # @param {Object|String} content Content of the object property.\n # @return [JsonType] This object. (supports chaining)\n #\n val: (name, content, mutable)->\n if typeof name is 'object'\n # Special case. First argument is an object. Then the second arg is mutable.\n # Keep that in mind when reading the following..\n for o_name,o of name\n @val(o_name,o,content)\n @\n else if name? and content?\n if mutable?\n if mutable is true or mutable is 'mutable'\n mutable = true\n else\n mutable = false\n else\n mutable = @mutable_default\n if typeof content is 'function'\n @ # Just do nothing\n else if ((not mutable) or typeof content is 'number') and content.constructor isnt Object\n obj = HB.addOperation(new types.ImmutableObject undefined, content).execute()\n super name, obj\n else\n if typeof content is 'string'\n word = HB.addOperation(new types.Word undefined).execute()\n word.insertText 0, content\n super name, word\n else if content.constructor is Object\n json = HB.addOperation(new JsonType undefined, content, mutable).execute()\n super name, json\n else\n throw new Error \"You must not set #{typeof content}-types in collaborative Json-objects!\"\n else\n super name, content\n\n Object.defineProperty JsonType.prototype, 'value',\n get : -> createJsonWrapper @\n set : (o)->\n if o.constructor is {}.constructor\n for o_name,o_obj of o\n @val(o_name, o_obj, 'immutable')\n else\n throw new Error \"You must only set Object values!\"\n\n #\n # @private\n #\n _encode: ()->\n {\n 'type' : \"JsonType\"\n 'uid' : @getUid()\n }\n\n parser['JsonType'] = (json)->\n {\n 'uid' : uid\n } = json\n new JsonType uid\n\n\n\n\n types['JsonType'] = JsonType\n\n text_types\n\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Types/JsonTypes.js b/build/node/Types/JsonTypes.js new file mode 100644 index 00000000..348aca50 --- /dev/null +++ b/build/node/Types/JsonTypes.js @@ -0,0 +1,2 @@ +(function(){var t,e={}.hasOwnProperty,r=function(t,r){function n(){this.constructor=t}for(var o in r)e.call(r,o)&&(t[o]=r[o]);return n.prototype=r.prototype,t.prototype=new n,t.__super__=r.prototype,t};t=require("./TextTypes"),module.exports=function(e){var n,o,u,i,a;return i=t(e),a=i.types,u=i.parser,o=function(t){var e;return new(e=function(){function t(e){var r,u,i,l;l=e.map,i=function(r,u){return Object.defineProperty(t.prototype,r,{get:function(){var t;return t=u.val(),t instanceof n?o(t):t instanceof a.ImmutableObject?t.val():t},set:function(t){var n,o,u,i;if(t.constructor==={}.constructor){u=e.val(r),i=[];for(n in t)o=t[n],i.push(u.val(n,o,"immutable"));return i}return e.val(r,t,"immutable")},enumerable:!0,configurable:!1})};for(r in l)u=l[r],i(r,u)}return t}())(t)},n=function(t){function n(t,e,r){var o,u;if(n.__super__.constructor.call(this,t),null!=e){if("object"!=typeof e)throw new Error("The initial value of JsonTypes must be of type Object! (current type: "+typeof e+")");for(o in e)u=e[o],this.val(o,u,r)}}return r(n,t),n.prototype.mutable_default=!0,n.prototype.setMutableDefault=function(t){if(t===!0||"mutable"===t)n.prototype.mutable_default=!0;else{if(t!==!1&&"immutable"!==t)throw new Error('Set mutable either "mutable" or "immutable"!');n.prototype.mutable_default=!1}return"OK"},n.prototype.val=function(t,r,o){var u,i,l,c,p;if("object"==typeof t){for(l in t)i=t[l],this.val(l,i,r);return this}if(null!=t&&null!=r){if(o=null!=o?o===!0||"mutable"===o?!0:!1:this.mutable_default,"function"==typeof r)return this;if(o&&"number"!=typeof r||r.constructor===Object){if("string"==typeof r)return p=e.addOperation(new a.Word(void 0)).execute(),p.insertText(0,r),n.__super__.val.call(this,t,p);if(r.constructor===Object)return u=e.addOperation(new n(void 0,r,o)).execute(),n.__super__.val.call(this,t,u);throw new Error("You must not set "+typeof r+"-types in collaborative Json-objects!")}return c=e.addOperation(new a.ImmutableObject(void 0,r)).execute(),n.__super__.val.call(this,t,c)}return n.__super__.val.call(this,t,r)},Object.defineProperty(n.prototype,"value",{get:function(){return o(this)},set:function(t){var e,r,n;if(t.constructor==={}.constructor){n=[];for(e in t)r=t[e],n.push(this.val(e,r,"immutable"));return n}throw new Error("You must only set Object values!")}}),n.prototype._encode=function(){return{type:"JsonType",uid:this.getUid()}},n}(a.MapManager),u.JsonType=function(t){var e;return e=t.uid,new n(e)},a.JsonType=n,i}}).call(this); +//# sourceMappingURL=../Types/JsonTypes.js.map \ No newline at end of file diff --git a/build/node/Types/JsonTypes.js.map b/build/node/Types/JsonTypes.js.map new file mode 100755 index 00000000..ca7b0aac --- /dev/null +++ b/build/node/Types/JsonTypes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Types/JsonTypes.js","sources":["Types/JsonTypes.coffee"],"names":[],"mappings":"CAAA,WAAA,GAAA,GAAA,KAAA,kLAAA,GAA2B,QAAQ,eAEnC,OAAO,QAAU,SAAC,GAChB,GAAA,GAAA,EAAA,EAAA,EAAA,QAAA,GAAa,EAAyB,GACtC,EAAQ,EAAW,MACnB,EAAS,EAAW,OAEpB,EAAoB,SAAC,GA0DnB,GAAA,SA0BI,KA1BE,EAAA,WAKS,QAAA,GAAC,GACZ,GAAA,GAAA,EAAA,EAAA,CAAA,GAAA,EAAA,IAAA,EACK,SAAC,EAAM,SACR,QAAO,eAAe,EAAY,UAAW,GAC3C,IAAM,WACJ,GAAA,EACA,OADA,GAAI,EAAI,MACL,YAAa,GACd,EAAkB,GACZ,YAAa,GAAM,gBACzB,EAAE,MAEF,GACJ,IAAM,SAAC,GACL,GAAA,GAAA,EAAA,EAAA,CAAA,IAAG,EAAE,iBAAkB,YAAvB,CACE,EAAY,EAAS,IAAI,GACzB,SAAA,IAAA,UACE,EAAA,KAAA,EAAU,IAAI,EAAQ,EAAO,6BAE/B,GAAS,IAAI,EAAM,EAAG,cAC1B,YAAY,EACZ,cAAc,IAnBpB,KAAA,IAAA,UACE,EAAI,EAAM,gBAmBA,IAKZ,EAAA,SAAA,GAOS,QAAA,GAAC,EAAK,EAAe,GAChC,GAAA,GAAA,CACA,IADA,EAAA,UAAA,YAAA,KAAA,KAAM,GACH,MAAA,EAAH,CACE,GAA6B,gBAA1B,GACD,KAAU,IAAA,OAAO,+EAAuE,GAAsB,IAChH,KAAA,IAAA,UACE,KAAC,IAAI,EAAM,EAAG,UANpB,GAAA,EAAA,GAAA,EAAA,UAWA,iBACE,EAZF,EAAA,UAiBA,kBAAmB,SAAC,GAClB,GAAG,KAAW,GAAmB,YAAX,EACpB,EAAS,UAAU,iBAAkB,MAClC,CAAA,GAAG,KAAW,GAAoB,cAAX,EAG1B,KAAU,IAAA,OAAM,+CAFhB,GAAS,UAAU,iBAAkB,QAGvC,MAxBF,EAAA,UA0CA,IAAK,SAAC,EAAM,EAAS,GACnB,GAAA,GAAA,EAAA,EAAA,EAAA,CAAA,IAAkB,gBAAf,GAAH,CAGE,IAAA,IAAA,UACE,KAAC,IAAI,EAAO,EAAE,SAChB,MACG,GAAG,MAAA,GAAU,MAAA,EAAb,CAQH,GALI,EAFD,MAAA,EACE,KAAW,GAAmB,YAAX,GACV,GAEA,EAEF,KAAC,gBACQ,kBAAlB,SACD,KACG,IAAK,GAAkC,gBAAlB,IAAgC,EAAQ,cAAiB,OAA9E,CAIH,GAAqB,gBAAlB,SACD,GAAO,EAAG,aAAiB,GAAA,GAAM,KAAK,SAAW,UACjD,EAAK,WAAW,EAAG,GACnB,EAAA,UAAA,IAAA,KAAA,KAAM,EAAM,EACT,IAAG,EAAQ,cAAe,aAC7B,GAAO,EAAG,aAAiB,GAAA,GAAS,OAAW,EAAS,IAAS,UACjE,EAAA,UAAA,IAAA,KAAA,KAAM,EAAM,EAEZ,MAAU,IAAA,OAAO,0BAAkB,GAAgB,+CAXrD,GAAM,EAAG,aAAiB,GAAA,GAAM,gBAAgB,OAAW,IAAS,UACpE,EAAA,UAAA,IAAA,KAAA,KAAM,EAAM,SAYd,GAAA,UAAA,IAAA,KAAA,KAAM,EAAM,IAEhB,OAAO,eAAe,EAAS,UAAW,SACxC,IAAM,iBAAG,GAAkB,OAC3B,IAAM,SAAC,GACL,GAAA,GAAA,EAAA,CAAA,IAAG,EAAE,iBAAkB,YAAvB,CACE,SAAA,IAAA,UACE,EAAA,KAAA,KAAC,IAAI,EAAQ,EAAO,uBAEtB,KAAU,IAAA,OAAM,uCAlFtB,EAAA,UAuFA,QAAS,kBAEL,KAAS,WACT,IAAQ,KAAC,cAjGQ,EAAM,YAoG7B,EAAO,SAAc,SAAC,GACpB,GAAA,SACU,GACN,EADF,IAEE,GAAA,GAAS,IAKf,EAAM,SAAc,EAEpB","sourcesContent":["text_types_uninitialized = require \"./TextTypes\"\n\nmodule.exports = (HB)->\n text_types = text_types_uninitialized HB\n types = text_types.types\n parser = text_types.parser\n\n createJsonWrapper = (_jsonType)->\n\n #\n # A JsonWrapper was intended to be a convenient wrapper for the JsonType.\n # But it can make things more difficult than they are.\n # @see JsonType\n #\n # @example create a JsonWrapper\n # # You get a JsonWrapper from a JsonType by calling\n # w = yatta.value\n #\n # It creates Javascripts -getter and -setter methods for each property that JsonType maintains.\n # @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty\n #\n # @example Getter Example\n # # you can access the x property of yatta by calling\n # w.x\n # # instead of\n # yatta.val('x')\n #\n # @note You can only overwrite existing values! Setting a new property won't have any effect!\n #\n # @example Setter Example\n # # you can set an existing x property of yatta by calling\n # w.x = \"text\"\n # # instead of\n # yatta.val('x', \"text\")\n #\n # In order to set a new property you have to overwrite an existing property.\n # Therefore the JsonWrapper supports a special feature that should make things more convenient\n # (we can argue about that, use the JsonType if you don't like it ;).\n # If you overwrite an object property of the JsonWrapper with a new object, it will result in a merged version of the objects.\n # Let w.p the property that is to be overwritten and o the new value. E.g. w.p = o\n # * The result has all properties of o\n # * The result has all properties of w.p if they don't occur under the same property-name in o.\n #\n # @example Conflict Example\n # yatta.value = {a : \"string\"}\n # w = yatta.value\n # console.log(w) # {a : \"string\"}\n # w.a = {a : {b : \"string\"}}\n # console.log(w) # {a : {b : \"String\"}}\n # w.a = {a : {c : 4}}\n # console.log(w) # {a : {b : \"String\", c : 4}}\n #\n # @example Common Pitfalls\n # w = yatta.value\n # # Setting a new property\n # w.newProperty = \"Awesome\"\n # console.log(w.newProperty == \"Awesome\") # false, w.newProperty is undefined\n # # overwrite the w object\n # w = {newProperty : \"Awesome\"}\n # console.log(w.newProperty == \"Awesome\") # true!, but ..\n # console.log(yatta.value.newProperty == \"Awesome\") # false, you are only allowed to set properties!\n # # The solution\n # yatta.value = {newProperty : \"Awesome\"}\n # console.log(w.newProperty == \"Awesome\") # true!\n #\n class JsonWrapper\n\n #\n # @param {JsonType} jsonType Instance of the JsonType that this class wrappes.\n #\n constructor: (jsonType)->\n for name, obj of jsonType.map\n do (name, obj)->\n Object.defineProperty JsonWrapper.prototype, name,\n get : ->\n x = obj.val()\n if x instanceof JsonType\n createJsonWrapper x\n else if x instanceof types.ImmutableObject\n x.val()\n else\n x\n set : (o)->\n if o.constructor is {}.constructor\n overwrite = jsonType.val(name)\n for o_name,o_obj of o\n overwrite.val(o_name, o_obj, 'immutable')\n else\n jsonType.val(name, o, 'immutable')\n enumerable: true\n configurable: false\n new JsonWrapper _jsonType\n\n #\n # Manages Object-like values.\n #\n class JsonType extends types.MapManager\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Object} initial_value Create this operation with an initial value.\n # @param {String|Boolean} Whether the initial_value should be created as mutable. (Optional - see setMutableDefault)\n #\n constructor: (uid, initial_value, mutable)->\n super uid\n if initial_value?\n if typeof initial_value isnt \"object\"\n throw new Error \"The initial value of JsonTypes must be of type Object! (current type: #{typeof initial_value})\"\n for name,o of initial_value\n @val name, o, mutable\n\n #\n # Whether the default is 'mutable' (true) or 'immutable' (false)\n #\n mutable_default:\n true\n\n #\n # Set if the default is 'mutable' or 'immutable'\n # @param {String|Boolean} mutable Set either 'mutable' / true or 'immutable' / false\n setMutableDefault: (mutable)->\n if mutable is true or mutable is 'mutable'\n JsonType.prototype.mutable_default = true\n else if mutable is false or mutable is 'immutable'\n JsonType.prototype.mutable_default = false\n else\n throw new Error 'Set mutable either \"mutable\" or \"immutable\"!'\n 'OK'\n\n #\n # @overload val()\n # Get this as a Json object.\n # @return [Json]\n #\n # @overload val(name)\n # Get value of a property.\n # @param {String} name Name of the object property.\n # @return [JsonType|Word|String|Object] Depending on the value of the property. If mutable it will return a Operation-type object, if immutable it will return String/Object.\n #\n # @overload val(name, content)\n # Set a new property.\n # @param {String} name Name of the object property.\n # @param {Object|String} content Content of the object property.\n # @return [JsonType] This object. (supports chaining)\n #\n val: (name, content, mutable)->\n if typeof name is 'object'\n # Special case. First argument is an object. Then the second arg is mutable.\n # Keep that in mind when reading the following..\n for o_name,o of name\n @val(o_name,o,content)\n @\n else if name? and content?\n if mutable?\n if mutable is true or mutable is 'mutable'\n mutable = true\n else\n mutable = false\n else\n mutable = @mutable_default\n if typeof content is 'function'\n @ # Just do nothing\n else if ((not mutable) or typeof content is 'number') and content.constructor isnt Object\n obj = HB.addOperation(new types.ImmutableObject undefined, content).execute()\n super name, obj\n else\n if typeof content is 'string'\n word = HB.addOperation(new types.Word undefined).execute()\n word.insertText 0, content\n super name, word\n else if content.constructor is Object\n json = HB.addOperation(new JsonType undefined, content, mutable).execute()\n super name, json\n else\n throw new Error \"You must not set #{typeof content}-types in collaborative Json-objects!\"\n else\n super name, content\n\n Object.defineProperty JsonType.prototype, 'value',\n get : -> createJsonWrapper @\n set : (o)->\n if o.constructor is {}.constructor\n for o_name,o_obj of o\n @val(o_name, o_obj, 'immutable')\n else\n throw new Error \"You must only set Object values!\"\n\n #\n # @private\n #\n _encode: ()->\n {\n 'type' : \"JsonType\"\n 'uid' : @getUid()\n }\n\n parser['JsonType'] = (json)->\n {\n 'uid' : uid\n } = json\n new JsonType uid\n\n\n\n\n types['JsonType'] = JsonType\n\n text_types\n\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Types/StructuredTypes.coffee b/build/node/Types/StructuredTypes.coffee new file mode 100644 index 00000000..f51e7461 --- /dev/null +++ b/build/node/Types/StructuredTypes.coffee @@ -0,0 +1,310 @@ +basic_types_uninitialized = require "./BasicTypes" + +module.exports = (HB)-> + basic_types = basic_types_uninitialized HB + types = basic_types.types + parser = basic_types.parser + + # + # Manages map like objects. E.g. Json-Type and XML attributes. + # + class MapManager extends types.Operation + + # + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # + constructor: (uid)-> + @map = {} + super uid + + # + # @see JsonTypes.val + # + val: (name, content)-> + if content? + if not @map[name]? + HB.addOperation(new AddName undefined, @, name).execute() + @map[name].replace content + @ + else if name? + obj = @map[name]?.val() + if obj instanceof types.ImmutableObject + obj.val() + else + obj + else + result = {} + for name,o of @map + obj = o.val() + if obj instanceof types.ImmutableObject or obj instanceof MapManager + obj = obj.val() + result[name] = obj + result + + # + # When a new property in a map manager is created, then the uids of the inserted Operations + # must be unique (think about concurrent operations). Therefore only an AddName operation is allowed to + # add a property in a MapManager. If two AddName operations on the same MapManager name happen concurrently + # only one will AddName operation will be executed. + # + class AddName extends types.Operation + + # + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # @param {Object} map_manager Uid or reference to the MapManager. + # @param {String} name Name of the property that will be added. + # + constructor: (uid, map_manager, @name)-> + @saveOperation 'map_manager', map_manager + super uid + + # + # If map_manager doesn't have the property name, then add it. + # The ReplaceManager that is being written on the property is unique + # in such a way that if AddName is executed (from another peer) it will + # always have the same result (ReplaceManager, and its beginning and end are the same) + # + execute: ()-> + if not @validateSavedOperations() + return false + else + uid_r = @map_manager.getUid() + uid_r.op_number = "_#{uid_r.op_number}_RM_#{@name}" + if not HB.getOperation(uid_r)? + uid_beg = @map_manager.getUid() + uid_beg.op_number = "_#{uid_beg.op_number}_RM_#{@name}_beginning" + uid_end = @map_manager.getUid() + uid_end.op_number = "_#{uid_end.op_number}_RM_#{@name}_end" + beg = HB.addOperation(new types.Delimiter uid_beg, undefined, uid_end).execute() + end = HB.addOperation(new types.Delimiter uid_end, beg, undefined).execute() + #beg.execute() + @map_manager.map[@name] = HB.addOperation(new ReplaceManager undefined, uid_r, beg, end).execute() + super + + # + # Encode this operation in such a way that it can be parsed by remote peers. + # + _encode: ()-> + { + 'type' : "AddName" + 'uid' : @getUid() + 'map_manager' : @map_manager.getUid() + 'name' : @name + } + + parser['AddName'] = (json)-> + { + 'map_manager' : map_manager + 'uid' : uid + 'name' : name + } = json + new AddName uid, map_manager, name + + # + # Manages a list of Insert-type operations. + # + class ListManager extends types.Insert + + # + # A ListManager maintains a non-empty list that has a beginning and an end (both Delimiters!) + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # @param {Delimiter} beginning Reference or Object. + # @param {Delimiter} end Reference or Object. + constructor: (uid, beginning, end, prev, next, origin)-> + if beginning? and end? + @saveOperation 'beginning', beginning + @saveOperation 'end', end + else + @beginning = HB.addOperation new types.Delimiter undefined, undefined, undefined + @end = HB.addOperation new types.Delimiter undefined, @beginning, undefined + @beginning.next_cl = @end + @beginning.execute() + @end.execute() + super uid, prev, next, origin + + + # Get the element previous to the delemiter at the end + getLastOperation: ()-> + @end.prev_cl + + # similar to the above + getFirstOperation: ()-> + @beginning.next_cl + + # Transforms the the list to an array + # Doesn't return left-right delimiter. + toArray: ()-> + o = @beginning.next_cl + result = [] + while o isnt @end + result.push o + o = o.next_cl + result + + # + # Retrieves the x-th not deleted element. + # + getOperationByPosition: (position)-> + o = @beginning.next_cl + if position > 0 + while true + o = o.next_cl + if not o.isDeleted() + position -= 1 + if position is 0 + break + if o instanceof types.Delimiter + throw new Error "position parameter exceeded the length of the document!" + o + + # + # Adds support for replace. The ReplaceManager manages Replaceable operations. + # Each Replaceable holds a value that is now replaceable. + # + # The Word-type has implemented support for replace + # @see Word + # + class ReplaceManager extends ListManager + # + # @param {Operation} initial_content Initialize this with a Replaceable that holds the initial_content. + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # @param {Delimiter} beginning Reference or Object. + # @param {Delimiter} end Reference or Object. + constructor: (initial_content, uid, beginning, end, prev, next, origin)-> + super uid, beginning, end, prev, next, origin + if initial_content? + @replace initial_content + + # + # Replace the existing word with a new word. + # + replace: (content)-> + o = @getLastOperation() + op = new Replaceable content, @, undefined, o, o.next_cl + HB.addOperation(op).execute() + + # + # Get the value of this Word + # @return {String} + # + val: ()-> + o = @getLastOperation() + if o instanceof types.Delimiter + throw new Error "dtrn" + o.val() + + # + # Encode this operation in such a way that it can be parsed by remote peers. + # + _encode: ()-> + json = + { + 'type': "ReplaceManager" + 'uid' : @getUid() + 'beginning' : @beginning.getUid() + 'end' : @end.getUid() + } + if @prev_cl? and @next_cl? + json['prev'] = @prev_cl.getUid() + json['next'] = @next_cl.getUid() + if @origin? and @origin isnt @prev_cl + json["origin"] = @origin.getUid() + json + + parser["ReplaceManager"] = (json)-> + { + 'content' : content + 'uid' : uid + 'prev': prev + 'next': next + 'origin' : origin + 'beginning' : beginning + 'end' : end + } = json + new ReplaceManager content, uid, beginning, end, prev, next, origin + + + # + # The ReplaceManager manages Replaceables. + # @see ReplaceManager + # + class Replaceable extends types.Insert + + # + # @param {Operation} content The value that this Replaceable holds. + # @param {ReplaceManager} parent Used to replace this Replaceable with another one. + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # + constructor: (content, parent, uid, prev, next, origin)-> + @saveOperation 'content', content + @saveOperation 'parent', parent + if not (prev? and next? and content?) + throw new Error "You must define content, prev, and next for Replaceable-types!" + super uid, prev, next, origin + + # + # Return the content that this operation holds. + # + val: ()-> + @content + + # + # Replace the content of this replaceable with new content. + # + replace: (content)-> + @parent.replace content + + # + # If possible set the replace manager in the content. + # @see Word.setReplaceManager + # + execute: ()-> + if not @validateSavedOperations() + return false + else + @content.setReplaceManager?(@parent) + super + @ + + # + # Encode this operation in such a way that it can be parsed by remote peers. + # + _encode: ()-> + json = + { + 'type': "Replaceable" + 'content': @content.getUid() + 'ReplaceManager' : @parent.getUid() + 'prev': @prev_cl.getUid() + 'next': @next_cl.getUid() + 'uid' : @getUid() + } + if @origin? and @origin isnt @prev_cl + json["origin"] = @origin.getUid() + json + + parser["Replaceable"] = (json)-> + { + 'content' : content + 'ReplaceManager' : parent + 'uid' : uid + 'prev': prev + 'next': next + 'origin' : origin + } = json + new Replaceable content, parent, uid, prev, next, origin + + + + types['ListManager'] = ListManager + types['MapManager'] = MapManager + types['ReplaceManager'] = ReplaceManager + types['Replaceable'] = Replaceable + + basic_types + + + + + + diff --git a/build/node/Types/StructuredTypes.coffee.map b/build/node/Types/StructuredTypes.coffee.map new file mode 100755 index 00000000..ecb02e1c --- /dev/null +++ b/build/node/Types/StructuredTypes.coffee.map @@ -0,0 +1 @@ +{"version":3,"file":"Types/StructuredTypes.coffee","names":[],"mappings":"","sources":["Types/StructuredTypes.coffee"],"sourcesContent":["basic_types_uninitialized = require \"./BasicTypes\"\n\nmodule.exports = (HB)->\n basic_types = basic_types_uninitialized HB\n types = basic_types.types\n parser = basic_types.parser\n\n #\n # Manages map like objects. E.g. Json-Type and XML attributes.\n #\n class MapManager extends types.Operation\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n #\n constructor: (uid)->\n @map = {}\n super uid\n\n #\n # @see JsonTypes.val\n #\n val: (name, content)->\n if content?\n if not @map[name]?\n HB.addOperation(new AddName undefined, @, name).execute()\n @map[name].replace content\n @\n else if name?\n obj = @map[name]?.val()\n if obj instanceof types.ImmutableObject\n obj.val()\n else\n obj\n else\n result = {}\n for name,o of @map\n obj = o.val()\n if obj instanceof types.ImmutableObject or obj instanceof MapManager\n obj = obj.val()\n result[name] = obj\n result\n\n #\n # When a new property in a map manager is created, then the uids of the inserted Operations\n # must be unique (think about concurrent operations). Therefore only an AddName operation is allowed to\n # add a property in a MapManager. If two AddName operations on the same MapManager name happen concurrently\n # only one will AddName operation will be executed.\n #\n class AddName extends types.Operation\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Object} map_manager Uid or reference to the MapManager.\n # @param {String} name Name of the property that will be added.\n #\n constructor: (uid, map_manager, @name)->\n @saveOperation 'map_manager', map_manager\n super uid\n\n #\n # If map_manager doesn't have the property name, then add it.\n # The ReplaceManager that is being written on the property is unique\n # in such a way that if AddName is executed (from another peer) it will\n # always have the same result (ReplaceManager, and its beginning and end are the same)\n #\n execute: ()->\n if not @validateSavedOperations()\n return false\n else\n uid_r = @map_manager.getUid()\n uid_r.op_number = \"_#{uid_r.op_number}_RM_#{@name}\"\n if not HB.getOperation(uid_r)?\n uid_beg = @map_manager.getUid()\n uid_beg.op_number = \"_#{uid_beg.op_number}_RM_#{@name}_beginning\"\n uid_end = @map_manager.getUid()\n uid_end.op_number = \"_#{uid_end.op_number}_RM_#{@name}_end\"\n beg = HB.addOperation(new types.Delimiter uid_beg, undefined, uid_end).execute()\n end = HB.addOperation(new types.Delimiter uid_end, beg, undefined).execute()\n #beg.execute()\n @map_manager.map[@name] = HB.addOperation(new ReplaceManager undefined, uid_r, beg, end).execute()\n super\n\n #\n # Encode this operation in such a way that it can be parsed by remote peers.\n #\n _encode: ()->\n {\n 'type' : \"AddName\"\n 'uid' : @getUid()\n 'map_manager' : @map_manager.getUid()\n 'name' : @name\n }\n\n parser['AddName'] = (json)->\n {\n 'map_manager' : map_manager\n 'uid' : uid\n 'name' : name\n } = json\n new AddName uid, map_manager, name\n\n #\n # Manages a list of Insert-type operations.\n #\n class ListManager extends types.Insert\n\n #\n # A ListManager maintains a non-empty list that has a beginning and an end (both Delimiters!)\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Delimiter} beginning Reference or Object.\n # @param {Delimiter} end Reference or Object.\n constructor: (uid, beginning, end, prev, next, origin)->\n if beginning? and end?\n @saveOperation 'beginning', beginning\n @saveOperation 'end', end\n else\n @beginning = HB.addOperation new types.Delimiter undefined, undefined, undefined\n @end = HB.addOperation new types.Delimiter undefined, @beginning, undefined\n @beginning.next_cl = @end\n @beginning.execute()\n @end.execute()\n super uid, prev, next, origin\n\n\n # Get the element previous to the delemiter at the end\n getLastOperation: ()->\n @end.prev_cl\n\n # similar to the above\n getFirstOperation: ()->\n @beginning.next_cl\n\n # Transforms the the list to an array\n # Doesn't return left-right delimiter.\n toArray: ()->\n o = @beginning.next_cl\n result = []\n while o isnt @end\n result.push o\n o = o.next_cl\n result\n\n #\n # Retrieves the x-th not deleted element.\n #\n getOperationByPosition: (position)->\n o = @beginning.next_cl\n if position > 0\n while true\n o = o.next_cl\n if not o.isDeleted()\n position -= 1\n if position is 0\n break\n if o instanceof types.Delimiter\n throw new Error \"position parameter exceeded the length of the document!\"\n o\n\n #\n # Adds support for replace. The ReplaceManager manages Replaceable operations.\n # Each Replaceable holds a value that is now replaceable.\n #\n # The Word-type has implemented support for replace\n # @see Word\n #\n class ReplaceManager extends ListManager\n #\n # @param {Operation} initial_content Initialize this with a Replaceable that holds the initial_content.\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Delimiter} beginning Reference or Object.\n # @param {Delimiter} end Reference or Object.\n constructor: (initial_content, uid, beginning, end, prev, next, origin)->\n super uid, beginning, end, prev, next, origin\n if initial_content?\n @replace initial_content\n\n #\n # Replace the existing word with a new word.\n #\n replace: (content)->\n o = @getLastOperation()\n op = new Replaceable content, @, undefined, o, o.next_cl\n HB.addOperation(op).execute()\n\n #\n # Get the value of this Word\n # @return {String}\n #\n val: ()->\n o = @getLastOperation()\n if o instanceof types.Delimiter\n throw new Error \"dtrn\"\n o.val()\n\n #\n # Encode this operation in such a way that it can be parsed by remote peers.\n #\n _encode: ()->\n json =\n {\n 'type': \"ReplaceManager\"\n 'uid' : @getUid()\n 'beginning' : @beginning.getUid()\n 'end' : @end.getUid()\n }\n if @prev_cl? and @next_cl?\n json['prev'] = @prev_cl.getUid()\n json['next'] = @next_cl.getUid()\n if @origin? and @origin isnt @prev_cl\n json[\"origin\"] = @origin.getUid()\n json\n\n parser[\"ReplaceManager\"] = (json)->\n {\n 'content' : content\n 'uid' : uid\n 'prev': prev\n 'next': next\n 'origin' : origin\n 'beginning' : beginning\n 'end' : end\n } = json\n new ReplaceManager content, uid, beginning, end, prev, next, origin\n\n\n #\n # The ReplaceManager manages Replaceables.\n # @see ReplaceManager\n #\n class Replaceable extends types.Insert\n\n #\n # @param {Operation} content The value that this Replaceable holds.\n # @param {ReplaceManager} parent Used to replace this Replaceable with another one.\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n #\n constructor: (content, parent, uid, prev, next, origin)->\n @saveOperation 'content', content\n @saveOperation 'parent', parent\n if not (prev? and next? and content?)\n throw new Error \"You must define content, prev, and next for Replaceable-types!\"\n super uid, prev, next, origin\n\n #\n # Return the content that this operation holds.\n #\n val: ()->\n @content\n\n #\n # Replace the content of this replaceable with new content.\n #\n replace: (content)->\n @parent.replace content\n\n #\n # If possible set the replace manager in the content.\n # @see Word.setReplaceManager\n #\n execute: ()->\n if not @validateSavedOperations()\n return false\n else\n @content.setReplaceManager?(@parent)\n super\n @\n\n #\n # Encode this operation in such a way that it can be parsed by remote peers.\n #\n _encode: ()->\n json =\n {\n 'type': \"Replaceable\"\n 'content': @content.getUid()\n 'ReplaceManager' : @parent.getUid()\n 'prev': @prev_cl.getUid()\n 'next': @next_cl.getUid()\n 'uid' : @getUid()\n }\n if @origin? and @origin isnt @prev_cl\n json[\"origin\"] = @origin.getUid()\n json\n\n parser[\"Replaceable\"] = (json)->\n {\n 'content' : content\n 'ReplaceManager' : parent\n 'uid' : uid\n 'prev': prev\n 'next': next\n 'origin' : origin\n } = json\n new Replaceable content, parent, uid, prev, next, origin\n\n\n\n types['ListManager'] = ListManager\n types['MapManager'] = MapManager\n types['ReplaceManager'] = ReplaceManager\n types['Replaceable'] = Replaceable\n\n basic_types\n\n\n\n\n\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Types/StructuredTypes.js b/build/node/Types/StructuredTypes.js new file mode 100644 index 00000000..d6c0d4de --- /dev/null +++ b/build/node/Types/StructuredTypes.js @@ -0,0 +1,2 @@ +(function(){var e,t={}.hasOwnProperty,n=function(e,n){function i(){this.constructor=e}for(var r in n)t.call(n,r)&&(e[r]=n[r]);return i.prototype=n.prototype,e.prototype=new i,e.__super__=n.prototype,e};e=require("./BasicTypes"),module.exports=function(t){var i,r,a,o,p,s,u,c;return s=e(t),c=s.types,u=s.parser,a=function(e){function r(e){this.map={},r.__super__.constructor.call(this,e)}return n(r,e),r.prototype.val=function(e,n){var a,o,p,s,u;if(null!=n)return null==this.map[e]&&t.addOperation(new i(void 0,this,e)).execute(),this.map[e].replace(n),this;if(null!=e)return o=null!=(s=this.map[e])?s.val():void 0,o instanceof c.ImmutableObject?o.val():o;p={},u=this.map;for(e in u)a=u[e],o=a.val(),(o instanceof c.ImmutableObject||o instanceof r)&&(o=o.val()),p[e]=o;return p},r}(c.Operation),i=function(e){function i(e,t,n){this.name=n,this.saveOperation("map_manager",t),i.__super__.constructor.call(this,e)}return n(i,e),i.prototype.execute=function(){var e,n,r,a,p;return this.validateSavedOperations()?(p=this.map_manager.getUid(),p.op_number="_"+p.op_number+"_RM_"+this.name,null==t.getOperation(p)&&(r=this.map_manager.getUid(),r.op_number="_"+r.op_number+"_RM_"+this.name+"_beginning",a=this.map_manager.getUid(),a.op_number="_"+a.op_number+"_RM_"+this.name+"_end",e=t.addOperation(new c.Delimiter(r,void 0,a)).execute(),n=t.addOperation(new c.Delimiter(a,e,void 0)).execute(),this.map_manager.map[this.name]=t.addOperation(new o(void 0,p,e,n)).execute()),i.__super__.execute.apply(this,arguments)):!1},i.prototype._encode=function(){return{type:"AddName",uid:this.getUid(),map_manager:this.map_manager.getUid(),name:this.name}},i}(c.Operation),u.AddName=function(e){var t,n,r;return t=e.map_manager,r=e.uid,n=e.name,new i(r,t,n)},r=function(e){function i(e,n,r,a,o,p){null!=n&&null!=r?(this.saveOperation("beginning",n),this.saveOperation("end",r)):(this.beginning=t.addOperation(new c.Delimiter(void 0,void 0,void 0)),this.end=t.addOperation(new c.Delimiter(void 0,this.beginning,void 0)),this.beginning.next_cl=this.end,this.beginning.execute(),this.end.execute()),i.__super__.constructor.call(this,e,a,o,p)}return n(i,e),i.prototype.getLastOperation=function(){return this.end.prev_cl},i.prototype.getFirstOperation=function(){return this.beginning.next_cl},i.prototype.toArray=function(){var e,t;for(e=this.beginning.next_cl,t=[];e!==this.end;)t.push(e),e=e.next_cl;return t},i.prototype.getOperationByPosition=function(e){var t;if(t=this.beginning.next_cl,e>0)for(;;){if(t=t.next_cl,t.isDeleted()||(e-=1),0===e)break;if(t instanceof c.Delimiter)throw new Error("position parameter exceeded the length of the document!")}return t},i}(c.Insert),o=function(e){function i(e,t,n,r,a,o,p){i.__super__.constructor.call(this,t,n,r,a,o,p),null!=e&&this.replace(e)}return n(i,e),i.prototype.replace=function(e){var n,i;return n=this.getLastOperation(),i=new p(e,this,void 0,n,n.next_cl),t.addOperation(i).execute()},i.prototype.val=function(){var e;if(e=this.getLastOperation(),e instanceof c.Delimiter)throw new Error("dtrn");return e.val()},i.prototype._encode=function(){var e;return e={type:"ReplaceManager",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&null!=this.next_cl&&(e.prev=this.prev_cl.getUid(),e.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},i}(r),u.ReplaceManager=function(e){var t,n,i,r,a,p,s;return n=e.content,s=e.uid,p=e.prev,r=e.next,a=e.origin,t=e.beginning,i=e.end,new o(n,s,t,i,p,r,a)},p=function(e){function t(e,n,i,r,a,o){if(this.saveOperation("content",e),this.saveOperation("parent",n),null==r||null==a||null==e)throw new Error("You must define content, prev, and next for Replaceable-types!");t.__super__.constructor.call(this,i,r,a,o)}return n(t,e),t.prototype.val=function(){return this.content},t.prototype.replace=function(e){return this.parent.replace(e)},t.prototype.execute=function(){var e;return this.validateSavedOperations()?("function"==typeof(e=this.content).setReplaceManager&&e.setReplaceManager(this.parent),t.__super__.execute.apply(this,arguments),this):!1},t.prototype._encode=function(){var e;return e={type:"Replaceable",content:this.content.getUid(),ReplaceManager:this.parent.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid(),uid:this.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(e.origin=this.origin.getUid()),e},t}(c.Insert),u.Replaceable=function(e){var t,n,i,r,a,o;return t=e.content,r=e.ReplaceManager,o=e.uid,a=e.prev,n=e.next,i=e.origin,new p(t,r,o,a,n,i)},c.ListManager=r,c.MapManager=a,c.ReplaceManager=o,c.Replaceable=p,s}}).call(this); +//# sourceMappingURL=../Types/StructuredTypes.js.map \ No newline at end of file diff --git a/build/node/Types/StructuredTypes.js.map b/build/node/Types/StructuredTypes.js.map new file mode 100755 index 00000000..f0ac3b3d --- /dev/null +++ b/build/node/Types/StructuredTypes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Types/StructuredTypes.js","sources":["Types/StructuredTypes.coffee"],"names":[],"mappings":"CAAA,WAAA,GAAA,GAAA,KAAA,kLAAA,GAA4B,QAAQ,gBAEpC,OAAO,QAAU,SAAC,GAChB,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,EAAA,EAAA,QAAA,GAAc,EAA0B,GACxC,EAAQ,EAAY,MACpB,EAAS,EAAY,OAKf,EAAA,SAAA,GAKS,QAAA,GAAC,GACZ,KAAC,OACD,EAAA,UAAA,YAAA,KAAA,KAAM,SAFR,GAAA,EAAA,GAAA,EAAA,UAOA,IAAK,SAAC,EAAM,GACV,GAAA,GAAA,EAAA,EAAA,EAAA,CAAA,IAAG,MAAA,QACM,OAAA,KAAA,IAAA,IACL,EAAG,aAAiB,GAAA,GAAQ,OAAW,KAAG,IAAM,UAClD,KAAC,IAAI,GAAM,QAAQ,GACnB,IACG,IAAG,MAAA,EAEN,MADA,GAAA,OAAA,EAAA,KAAA,IAAA,IAAA,EAAkB,MAAZ,OACH,YAAe,GAAM,gBACtB,EAAI,MAEJ,CAEF,MACA,EAAA,KAAA,GAAA,KAAA,IAAA,UACE,EAAM,EAAE,OACL,YAAe,GAAM,iBAAmB,YAAe,MACxD,EAAM,EAAI,OACZ,EAAO,GAAQ,QACjB,OA/BmB,EAAM,WAuCzB,EAAA,SAAA,GAOS,QAAA,GAAC,EAAK,EAAc,GAAD,KAAC,KAAA,EAC/B,KAAC,cAAc,cAAe,GAC9B,EAAA,UAAA,YAAA,KAAA,KAAM,SAFR,GAAA,EAAA,GAAA,EAAA,UAUA,QAAS,WACP,GAAA,GAAA,EAAA,EAAA,EAAA,CAAA,OAAG,MAAK,2BAGN,EAAQ,KAAC,YAAY,SACrB,EAAM,UAAa,IAAE,EAAM,UAAW,OAAK,KAAC,KACrC,MAAA,EAAA,aAAA,KACL,EAAU,KAAC,YAAY,SACvB,EAAQ,UAAa,IAAE,EAAQ,UAAW,OAAK,KAAC,KAAM,aACtD,EAAU,KAAC,YAAY,SACvB,EAAQ,UAAa,IAAE,EAAQ,UAAW,OAAK,KAAC,KAAM,OACtD,EAAM,EAAG,aAAiB,GAAA,GAAM,UAAU,EAAS,OAAW,IAAS,UACvE,EAAM,EAAG,aAAiB,GAAA,GAAM,UAAU,EAAS,EAAK,SAAW,UAEnE,KAAC,YAAY,IAAI,KAAC,MAAQ,EAAG,aAAiB,GAAA,GAAe,OAAW,EAAO,EAAK,IAAK,WAC3F,EAAA,UAAA,QAAA,MAAA,KAAA,aAbO,GAZX,EAAA,UA8BA,QAAS,kBAEL,KAAS,UACT,IAAQ,KAAC,SACT,YAAgB,KAAC,YAAY,SAC7B,KAAS,KAAC,UA1CM,EAAM,WA6C5B,EAAO,QAAa,SAAC,GACnB,GAAA,GAAA,EAAA,QACkB,GAAA,EAAhB,YACQ,EAAA,EAAR,IACS,EAAA,EAAT,KAEE,GAAA,GAAQ,EAAK,EAAa,IAK1B,EAAA,SAAA,GAOS,QAAA,GAAC,EAAK,EAAW,EAAK,EAAM,EAAM,GAC1C,MAAA,GAAe,MAAA,GAChB,KAAC,cAAc,YAAa,GAC5B,KAAC,cAAc,MAAO,KAEtB,KAAC,UAAY,EAAG,aAAiB,GAAA,GAAM,UAAU,OAAW,OAAW,SACvE,KAAC,IAAY,EAAG,aAAiB,GAAA,GAAM,UAAU,OAAW,KAAC,UAAW,SACxE,KAAC,UAAU,QAAU,KAAC,IACtB,KAAC,UAAU,UACX,KAAC,IAAI,WACP,EAAA,UAAA,YAAA,KAAA,KAAM,EAAK,EAAM,EAAM,SAVzB,GAAA,EAAA,GAAA,EAAA,UAcA,iBAAkB,iBAChB,MAAC,IAAI,SAfP,EAAA,UAkBA,kBAAmB,iBACjB,MAAC,UAAU,SAnBb,EAAA,UAuBA,QAAS,WACP,GAAA,GAAA,CAEA,KAFA,EAAI,KAAC,UAAU,QACf,KACM,IAAO,KAAC,KACZ,EAAO,KAAK,GACZ,EAAI,EAAE,cACR,IA7BF,EAAA,UAkCA,uBAAwB,SAAC,GACvB,GAAA,EACA,IADA,EAAI,KAAC,UAAU,QACZ,EAAW,EACZ,OAAA,CAIE,GAHA,EAAI,EAAE,QACH,EAAM,cACP,GAAY,GACC,IAAZ,EACD,KACF,IAAG,YAAa,GAAM,UACpB,KAAU,IAAA,OAAM,iEACtB,OApDsB,EAAM,QA6D1B,EAAA,SAAA,GAMS,QAAA,GAAC,EAAiB,EAAK,EAAW,EAAK,EAAM,EAAM,GAC9D,EAAA,UAAA,YAAA,KAAA,KAAM,EAAK,EAAW,EAAK,EAAM,EAAM,GACpC,MAAA,GACD,KAAC,QAAQ,SAHb,GAAA,EAAA,GAAA,EAAA,UAQA,QAAS,SAAC,GACR,GAAA,GAAA,QAAA,GAAI,KAAC,mBACL,EAAS,GAAA,GAAY,EAAS,KAAG,OAAW,EAAG,EAAE,SACjD,EAAG,aAAa,GAAI,WAXtB,EAAA,UAiBA,IAAK,WACH,GAAA,EACA,IADA,EAAI,KAAC,mBACF,YAAa,GAAM,UACpB,KAAU,IAAA,OAAM,cAClB,GAAE,OArBJ,EAAA,UA0BA,QAAS,WACP,GAAA,SAAA,IAEI,KAAQ,iBACR,IAAQ,KAAC,SACT,UAAc,KAAC,UAAU,SACzB,IAAQ,KAAC,IAAI,UAEd,MAAA,KAAA,SAAc,MAAA,KAAA,UACf,EAAK,KAAU,KAAC,QAAQ,SACxB,EAAK,KAAU,KAAC,QAAQ,UACvB,MAAA,KAAA,QAAa,KAAC,SAAY,KAAC,UAC5B,EAAK,OAAY,KAAC,OAAO,UAC3B,MA7CyB,GA+C7B,EAAO,eAAoB,SAAC,GAC1B,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,EAAA,QACc,GAAA,EAAZ,QACQ,EAAA,EAAR,IACQ,EAAA,EAAR,KACQ,EAAA,EAAR,KACW,EAAA,EAAX,OACc,EAAA,EAAd,UACQ,EAAA,EAAR,IAEE,GAAA,GAAe,EAAS,EAAK,EAAW,EAAK,EAAM,EAAM,IAOzD,EAAA,SAAA,GAOS,QAAA,GAAC,EAAS,EAAQ,EAAK,EAAM,EAAM,GAG9C,GAFA,KAAC,cAAc,UAAW,GAC1B,KAAC,cAAc,SAAU,GACjB,MAAA,GAAU,MAAA,GAAU,MAAA,EAC1B,KAAU,IAAA,OAAM,iEAClB,GAAA,UAAA,YAAA,KAAA,KAAM,EAAK,EAAM,EAAM,SALzB,GAAA,EAAA,GAAA,EAAA,UAUA,IAAK,iBACH,MAAC,SAXH,EAAA,UAgBA,QAAS,SAAC,SACR,MAAC,OAAO,QAAQ,IAjBlB,EAAA,UAuBA,QAAS,WACP,GAAA,EAAA,OAAG,MAAK,mFAGG,kBAAmB,KAAC,QAC7B,EAAA,UAAA,QAAA,MAAA,KAAA,WACA,OAJO,GAzBX,EAAA,UAkCA,QAAS,WACP,GAAA,SAAA,IAEI,KAAQ,cACR,QAAW,KAAC,QAAQ,SACpB,eAAmB,KAAC,OAAO,SAC3B,KAAQ,KAAC,QAAQ,SACjB,KAAQ,KAAC,QAAQ,SACjB,IAAQ,KAAC,UAEV,MAAA,KAAA,QAAa,KAAC,SAAY,KAAC,UAC5B,EAAK,OAAY,KAAC,OAAO,UAC3B,MArDsB,EAAM,QAuDhC,EAAO,YAAiB,SAAC,GACvB,GAAA,GAAA,EAAA,EAAA,EAAA,EAAA,QACc,GAAA,EAAZ,QACmB,EAAA,EAAnB,eACQ,EAAA,EAAR,IACQ,EAAA,EAAR,KACQ,EAAA,EAAR,KACW,EAAA,EAAX,OAEE,GAAA,GAAY,EAAS,EAAQ,EAAK,EAAM,EAAM,IAIpD,EAAM,YAAiB,EACvB,EAAM,WAAgB,EACtB,EAAM,eAAoB,EAC1B,EAAM,YAAiB,EAEvB","sourcesContent":["basic_types_uninitialized = require \"./BasicTypes\"\n\nmodule.exports = (HB)->\n basic_types = basic_types_uninitialized HB\n types = basic_types.types\n parser = basic_types.parser\n\n #\n # Manages map like objects. E.g. Json-Type and XML attributes.\n #\n class MapManager extends types.Operation\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n #\n constructor: (uid)->\n @map = {}\n super uid\n\n #\n # @see JsonTypes.val\n #\n val: (name, content)->\n if content?\n if not @map[name]?\n HB.addOperation(new AddName undefined, @, name).execute()\n @map[name].replace content\n @\n else if name?\n obj = @map[name]?.val()\n if obj instanceof types.ImmutableObject\n obj.val()\n else\n obj\n else\n result = {}\n for name,o of @map\n obj = o.val()\n if obj instanceof types.ImmutableObject or obj instanceof MapManager\n obj = obj.val()\n result[name] = obj\n result\n\n #\n # When a new property in a map manager is created, then the uids of the inserted Operations\n # must be unique (think about concurrent operations). Therefore only an AddName operation is allowed to\n # add a property in a MapManager. If two AddName operations on the same MapManager name happen concurrently\n # only one will AddName operation will be executed.\n #\n class AddName extends types.Operation\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Object} map_manager Uid or reference to the MapManager.\n # @param {String} name Name of the property that will be added.\n #\n constructor: (uid, map_manager, @name)->\n @saveOperation 'map_manager', map_manager\n super uid\n\n #\n # If map_manager doesn't have the property name, then add it.\n # The ReplaceManager that is being written on the property is unique\n # in such a way that if AddName is executed (from another peer) it will\n # always have the same result (ReplaceManager, and its beginning and end are the same)\n #\n execute: ()->\n if not @validateSavedOperations()\n return false\n else\n uid_r = @map_manager.getUid()\n uid_r.op_number = \"_#{uid_r.op_number}_RM_#{@name}\"\n if not HB.getOperation(uid_r)?\n uid_beg = @map_manager.getUid()\n uid_beg.op_number = \"_#{uid_beg.op_number}_RM_#{@name}_beginning\"\n uid_end = @map_manager.getUid()\n uid_end.op_number = \"_#{uid_end.op_number}_RM_#{@name}_end\"\n beg = HB.addOperation(new types.Delimiter uid_beg, undefined, uid_end).execute()\n end = HB.addOperation(new types.Delimiter uid_end, beg, undefined).execute()\n #beg.execute()\n @map_manager.map[@name] = HB.addOperation(new ReplaceManager undefined, uid_r, beg, end).execute()\n super\n\n #\n # Encode this operation in such a way that it can be parsed by remote peers.\n #\n _encode: ()->\n {\n 'type' : \"AddName\"\n 'uid' : @getUid()\n 'map_manager' : @map_manager.getUid()\n 'name' : @name\n }\n\n parser['AddName'] = (json)->\n {\n 'map_manager' : map_manager\n 'uid' : uid\n 'name' : name\n } = json\n new AddName uid, map_manager, name\n\n #\n # Manages a list of Insert-type operations.\n #\n class ListManager extends types.Insert\n\n #\n # A ListManager maintains a non-empty list that has a beginning and an end (both Delimiters!)\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Delimiter} beginning Reference or Object.\n # @param {Delimiter} end Reference or Object.\n constructor: (uid, beginning, end, prev, next, origin)->\n if beginning? and end?\n @saveOperation 'beginning', beginning\n @saveOperation 'end', end\n else\n @beginning = HB.addOperation new types.Delimiter undefined, undefined, undefined\n @end = HB.addOperation new types.Delimiter undefined, @beginning, undefined\n @beginning.next_cl = @end\n @beginning.execute()\n @end.execute()\n super uid, prev, next, origin\n\n\n # Get the element previous to the delemiter at the end\n getLastOperation: ()->\n @end.prev_cl\n\n # similar to the above\n getFirstOperation: ()->\n @beginning.next_cl\n\n # Transforms the the list to an array\n # Doesn't return left-right delimiter.\n toArray: ()->\n o = @beginning.next_cl\n result = []\n while o isnt @end\n result.push o\n o = o.next_cl\n result\n\n #\n # Retrieves the x-th not deleted element.\n #\n getOperationByPosition: (position)->\n o = @beginning.next_cl\n if position > 0\n while true\n o = o.next_cl\n if not o.isDeleted()\n position -= 1\n if position is 0\n break\n if o instanceof types.Delimiter\n throw new Error \"position parameter exceeded the length of the document!\"\n o\n\n #\n # Adds support for replace. The ReplaceManager manages Replaceable operations.\n # Each Replaceable holds a value that is now replaceable.\n #\n # The Word-type has implemented support for replace\n # @see Word\n #\n class ReplaceManager extends ListManager\n #\n # @param {Operation} initial_content Initialize this with a Replaceable that holds the initial_content.\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n # @param {Delimiter} beginning Reference or Object.\n # @param {Delimiter} end Reference or Object.\n constructor: (initial_content, uid, beginning, end, prev, next, origin)->\n super uid, beginning, end, prev, next, origin\n if initial_content?\n @replace initial_content\n\n #\n # Replace the existing word with a new word.\n #\n replace: (content)->\n o = @getLastOperation()\n op = new Replaceable content, @, undefined, o, o.next_cl\n HB.addOperation(op).execute()\n\n #\n # Get the value of this Word\n # @return {String}\n #\n val: ()->\n o = @getLastOperation()\n if o instanceof types.Delimiter\n throw new Error \"dtrn\"\n o.val()\n\n #\n # Encode this operation in such a way that it can be parsed by remote peers.\n #\n _encode: ()->\n json =\n {\n 'type': \"ReplaceManager\"\n 'uid' : @getUid()\n 'beginning' : @beginning.getUid()\n 'end' : @end.getUid()\n }\n if @prev_cl? and @next_cl?\n json['prev'] = @prev_cl.getUid()\n json['next'] = @next_cl.getUid()\n if @origin? and @origin isnt @prev_cl\n json[\"origin\"] = @origin.getUid()\n json\n\n parser[\"ReplaceManager\"] = (json)->\n {\n 'content' : content\n 'uid' : uid\n 'prev': prev\n 'next': next\n 'origin' : origin\n 'beginning' : beginning\n 'end' : end\n } = json\n new ReplaceManager content, uid, beginning, end, prev, next, origin\n\n\n #\n # The ReplaceManager manages Replaceables.\n # @see ReplaceManager\n #\n class Replaceable extends types.Insert\n\n #\n # @param {Operation} content The value that this Replaceable holds.\n # @param {ReplaceManager} parent Used to replace this Replaceable with another one.\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n #\n constructor: (content, parent, uid, prev, next, origin)->\n @saveOperation 'content', content\n @saveOperation 'parent', parent\n if not (prev? and next? and content?)\n throw new Error \"You must define content, prev, and next for Replaceable-types!\"\n super uid, prev, next, origin\n\n #\n # Return the content that this operation holds.\n #\n val: ()->\n @content\n\n #\n # Replace the content of this replaceable with new content.\n #\n replace: (content)->\n @parent.replace content\n\n #\n # If possible set the replace manager in the content.\n # @see Word.setReplaceManager\n #\n execute: ()->\n if not @validateSavedOperations()\n return false\n else\n @content.setReplaceManager?(@parent)\n super\n @\n\n #\n # Encode this operation in such a way that it can be parsed by remote peers.\n #\n _encode: ()->\n json =\n {\n 'type': \"Replaceable\"\n 'content': @content.getUid()\n 'ReplaceManager' : @parent.getUid()\n 'prev': @prev_cl.getUid()\n 'next': @next_cl.getUid()\n 'uid' : @getUid()\n }\n if @origin? and @origin isnt @prev_cl\n json[\"origin\"] = @origin.getUid()\n json\n\n parser[\"Replaceable\"] = (json)->\n {\n 'content' : content\n 'ReplaceManager' : parent\n 'uid' : uid\n 'prev': prev\n 'next': next\n 'origin' : origin\n } = json\n new Replaceable content, parent, uid, prev, next, origin\n\n\n\n types['ListManager'] = ListManager\n types['MapManager'] = MapManager\n types['ReplaceManager'] = ReplaceManager\n types['Replaceable'] = Replaceable\n\n basic_types\n\n\n\n\n\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Types/TextTypes.coffee b/build/node/Types/TextTypes.coffee new file mode 100644 index 00000000..65ced20e --- /dev/null +++ b/build/node/Types/TextTypes.coffee @@ -0,0 +1,177 @@ +structured_types_uninitialized = require "./StructuredTypes" + +module.exports = (HB)-> + structured_types = structured_types_uninitialized HB + types = structured_types.types + parser = structured_types.parser + + # + # At the moment TextDelete type equals the Delete type in BasicTypes. + # @see BasicTypes.Delete + # + class TextDelete extends types.Delete + parser["TextDelete"] = parser["Delete"] + + # + # Extends the basic Insert type to an operation that holds a text value + # + class TextInsert extends types.Insert + # + # @param {String} content The content of this Insert-type Operation. Usually you restrict the length of content to size 1 + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # + constructor: (@content, uid, prev, next, origin)-> + if not (prev? and next?) + throw new Error "You must define prev, and next for TextInsert-types!" + super uid, prev, next, origin + # + # Retrieve the effective length of the $content of this operation. + # + getLength: ()-> + if @isDeleted() + 0 + else + @content.length + + # + # The result will be concatenated with the results from the other insert operations + # in order to retrieve the content of the engine. + # @see HistoryBuffer.toExecutedArray + # + val: (current_position)-> + if @isDeleted() + "" + else + @content + + # + # Convert all relevant information of this operation to the json-format. + # This result can be send to other clients. + # + _encode: ()-> + json = + { + 'type': "TextInsert" + 'content': @content + 'uid' : @getUid() + 'prev': @prev_cl.getUid() + 'next': @next_cl.getUid() + } + if @origin? and @origin isnt @prev_cl + json["origin"] = @origin.getUid() + json + + parser["TextInsert"] = (json)-> + { + 'content' : content + 'uid' : uid + 'prev': prev + 'next': next + 'origin' : origin + } = json + new TextInsert content, uid, prev, next, origin + + # + # Handles a Text-like data structures with support for insertText/deleteText at a word-position. + # + class Word extends types.ListManager + + # + # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created. + # + constructor: (uid, beginning, end, prev, next, origin)-> + super uid, beginning, end, prev, next, origin + + # + # Inserts a string into the word + # + insertText: (position, content)-> + o = @getOperationByPosition position + for c in content + op = new TextInsert c, undefined, o.prev_cl, o + HB.addOperation(op).execute() + + # + # Deletes a part of the word. + # + deleteText: (position, length)-> + o = @getOperationByPosition position + + for i in [0...length] + d = HB.addOperation(new TextDelete undefined, o).execute() + o = o.next_cl + while o.isDeleted() + if o instanceof types.Delimiter + throw new Error "You can't delete more than there is.." + o = o.next_cl + d._encode() + + # + # Replace the content of this word with another one. Concurrent replacements are not merged! + # Only one of the replacements will be used. + # + # Can only be used if the ReplaceManager was set! + # @see Word.setReplaceManager + # + replaceText: (text)-> + if @replace_manager? + word = HB.addOperation(new Word undefined).execute() + word.insertText 0, text + @replace_manager.replace(word) + else + throw new Error "This type is currently not maintained by a ReplaceManager!" + + # + # @returns [Json] A Json object. + # + val: ()-> + c = for o in @toArray() + if o.val? + o.val() + else + "" + c.join('') + + # + # In most cases you would embed a Word in a Replaceable, wich is handled by the ReplaceManager in order + # to provide replace functionality. + # + setReplaceManager: (op)-> + @saveOperation 'replace_manager', op + @validateSavedOperations + + # + # Encode this operation in such a way that it can be parsed by remote peers. + # + _encode: ()-> + json = { + 'type': "Word" + 'uid' : @getUid() + 'beginning' : @beginning.getUid() + 'end' : @end.getUid() + } + if @prev_cl? + json['prev'] = @prev_cl.getUid() + if @next_cl? + json['next'] = @next_cl.getUid() + if @origin? and @origin isnt @prev_cl + json["origin"] = @origin.getUid() + json + + parser['Word'] = (json)-> + { + 'uid' : uid + 'beginning' : beginning + 'end' : end + 'prev': prev + 'next': next + 'origin' : origin + } = json + new Word uid, beginning, end, prev, next, origin + + types['TextInsert'] = TextInsert + types['TextDelete'] = TextDelete + types['Word'] = Word + structured_types + + diff --git a/build/node/Types/TextTypes.coffee.map b/build/node/Types/TextTypes.coffee.map new file mode 100755 index 00000000..c69357e8 --- /dev/null +++ b/build/node/Types/TextTypes.coffee.map @@ -0,0 +1 @@ +{"version":3,"file":"Types/TextTypes.coffee","names":[],"mappings":"","sources":["Types/TextTypes.coffee"],"sourcesContent":["structured_types_uninitialized = require \"./StructuredTypes\"\n\nmodule.exports = (HB)->\n structured_types = structured_types_uninitialized HB\n types = structured_types.types\n parser = structured_types.parser\n\n #\n # At the moment TextDelete type equals the Delete type in BasicTypes.\n # @see BasicTypes.Delete\n #\n class TextDelete extends types.Delete\n parser[\"TextDelete\"] = parser[\"Delete\"]\n\n #\n # Extends the basic Insert type to an operation that holds a text value\n #\n class TextInsert extends types.Insert\n #\n # @param {String} content The content of this Insert-type Operation. Usually you restrict the length of content to size 1\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n #\n constructor: (@content, uid, prev, next, origin)->\n if not (prev? and next?)\n throw new Error \"You must define prev, and next for TextInsert-types!\"\n super uid, prev, next, origin\n #\n # Retrieve the effective length of the $content of this operation.\n #\n getLength: ()->\n if @isDeleted()\n 0\n else\n @content.length\n\n #\n # The result will be concatenated with the results from the other insert operations\n # in order to retrieve the content of the engine.\n # @see HistoryBuffer.toExecutedArray\n #\n val: (current_position)->\n if @isDeleted()\n \"\"\n else\n @content\n\n #\n # Convert all relevant information of this operation to the json-format.\n # This result can be send to other clients.\n #\n _encode: ()->\n json =\n {\n 'type': \"TextInsert\"\n 'content': @content\n 'uid' : @getUid()\n 'prev': @prev_cl.getUid()\n 'next': @next_cl.getUid()\n }\n if @origin? and @origin isnt @prev_cl\n json[\"origin\"] = @origin.getUid()\n json\n\n parser[\"TextInsert\"] = (json)->\n {\n 'content' : content\n 'uid' : uid\n 'prev': prev\n 'next': next\n 'origin' : origin\n } = json\n new TextInsert content, uid, prev, next, origin\n\n #\n # Handles a Text-like data structures with support for insertText/deleteText at a word-position.\n #\n class Word extends types.ListManager\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n #\n constructor: (uid, beginning, end, prev, next, origin)->\n super uid, beginning, end, prev, next, origin\n\n #\n # Inserts a string into the word\n #\n insertText: (position, content)->\n o = @getOperationByPosition position\n for c in content\n op = new TextInsert c, undefined, o.prev_cl, o\n HB.addOperation(op).execute()\n\n #\n # Deletes a part of the word.\n #\n deleteText: (position, length)->\n o = @getOperationByPosition position\n\n for i in [0...length]\n d = HB.addOperation(new TextDelete undefined, o).execute()\n o = o.next_cl\n while o.isDeleted()\n if o instanceof types.Delimiter\n throw new Error \"You can't delete more than there is..\"\n o = o.next_cl\n d._encode()\n\n #\n # Replace the content of this word with another one. Concurrent replacements are not merged!\n # Only one of the replacements will be used.\n #\n # Can only be used if the ReplaceManager was set!\n # @see Word.setReplaceManager\n #\n replaceText: (text)->\n if @replace_manager?\n word = HB.addOperation(new Word undefined).execute()\n word.insertText 0, text\n @replace_manager.replace(word)\n else\n throw new Error \"This type is currently not maintained by a ReplaceManager!\"\n\n #\n # @returns [Json] A Json object.\n #\n val: ()->\n c = for o in @toArray()\n if o.val?\n o.val()\n else\n \"\"\n c.join('')\n\n #\n # In most cases you would embed a Word in a Replaceable, wich is handled by the ReplaceManager in order\n # to provide replace functionality.\n #\n setReplaceManager: (op)->\n @saveOperation 'replace_manager', op\n @validateSavedOperations\n\n #\n # Encode this operation in such a way that it can be parsed by remote peers.\n #\n _encode: ()->\n json = {\n 'type': \"Word\"\n 'uid' : @getUid()\n 'beginning' : @beginning.getUid()\n 'end' : @end.getUid()\n }\n if @prev_cl?\n json['prev'] = @prev_cl.getUid()\n if @next_cl?\n json['next'] = @next_cl.getUid()\n if @origin? and @origin isnt @prev_cl\n json[\"origin\"] = @origin.getUid()\n json\n\n parser['Word'] = (json)->\n {\n 'uid' : uid\n 'beginning' : beginning\n 'end' : end\n 'prev': prev\n 'next': next\n 'origin' : origin\n } = json\n new Word uid, beginning, end, prev, next, origin\n\n types['TextInsert'] = TextInsert\n types['TextDelete'] = TextDelete\n types['Word'] = Word\n structured_types\n\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Types/TextTypes.js b/build/node/Types/TextTypes.js new file mode 100644 index 00000000..3eefed59 --- /dev/null +++ b/build/node/Types/TextTypes.js @@ -0,0 +1,2 @@ +(function(){var t,e={}.hasOwnProperty,n=function(t,n){function r(){this.constructor=t}for(var i in n)e.call(n,i)&&(t[i]=n[i]);return r.prototype=n.prototype,t.prototype=new r,t.__super__=n.prototype,t};t=require("./StructuredTypes"),module.exports=function(e){var r,i,o,s,u,c;return u=t(e),c=u.types,s=u.parser,r=function(t){function e(){return e.__super__.constructor.apply(this,arguments)}return n(e,t),e}(c.Delete),s.TextDelete=s.Delete,i=function(t){function e(t,n,r,i,o){if(this.content=t,null==r||null==i)throw new Error("You must define prev, and next for TextInsert-types!");e.__super__.constructor.call(this,n,r,i,o)}return n(e,t),e.prototype.getLength=function(){return this.isDeleted()?0:this.content.length},e.prototype.val=function(){return this.isDeleted()?"":this.content},e.prototype._encode=function(){var t;return t={type:"TextInsert",content:this.content,uid:this.getUid(),prev:this.prev_cl.getUid(),next:this.next_cl.getUid()},null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},e}(c.Insert),s.TextInsert=function(t){var e,n,r,o,s;return e=t.content,s=t.uid,o=t.prev,n=t.next,r=t.origin,new i(e,s,o,n,r)},o=function(t){function o(t,e,n,r,i,s){o.__super__.constructor.call(this,t,e,n,r,i,s)}return n(o,t),o.prototype.insertText=function(t,n){var r,o,s,u,c,p;for(o=this.getOperationByPosition(t),p=[],u=0,c=n.length;c>u;u++)r=n[u],s=new i(r,void 0,o.prev_cl,o),p.push(e.addOperation(s).execute());return p},o.prototype.deleteText=function(t,n){var i,o,s,u,p;for(s=this.getOperationByPosition(t),p=[],o=u=0;n>=0?n>u:u>n;o=n>=0?++u:--u){for(i=e.addOperation(new r(void 0,s)).execute(),s=s.next_cl;s.isDeleted();){if(s instanceof c.Delimiter)throw new Error("You can't delete more than there is..");s=s.next_cl}p.push(i._encode())}return p},o.prototype.replaceText=function(t){var n;if(null!=this.replace_manager)return n=e.addOperation(new o(void 0)).execute(),n.insertText(0,t),this.replace_manager.replace(n);throw new Error("This type is currently not maintained by a ReplaceManager!")},o.prototype.val=function(){var t,e;return t=function(){var t,n,r,i;for(r=this.toArray(),i=[],t=0,n=r.length;n>t;t++)e=r[t],i.push(null!=e.val?e.val():"");return i}.call(this),t.join("")},o.prototype.setReplaceManager=function(t){return this.saveOperation("replace_manager",t),this.validateSavedOperations},o.prototype._encode=function(){var t;return t={type:"Word",uid:this.getUid(),beginning:this.beginning.getUid(),end:this.end.getUid()},null!=this.prev_cl&&(t.prev=this.prev_cl.getUid()),null!=this.next_cl&&(t.next=this.next_cl.getUid()),null!=this.origin&&this.origin!==this.prev_cl&&(t.origin=this.origin.getUid()),t},o}(c.ListManager),s.Word=function(t){var e,n,r,i,s,u;return u=t.uid,e=t.beginning,n=t.end,s=t.prev,r=t.next,i=t.origin,new o(u,e,n,s,r,i)},c.TextInsert=i,c.TextDelete=r,c.Word=o,u}}).call(this); +//# sourceMappingURL=../Types/TextTypes.js.map \ No newline at end of file diff --git a/build/node/Types/TextTypes.js.map b/build/node/Types/TextTypes.js.map new file mode 100755 index 00000000..6fe6d50b --- /dev/null +++ b/build/node/Types/TextTypes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Types/TextTypes.js","sources":["Types/TextTypes.coffee"],"names":[],"mappings":"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","sourcesContent":["structured_types_uninitialized = require \"./StructuredTypes\"\n\nmodule.exports = (HB)->\n structured_types = structured_types_uninitialized HB\n types = structured_types.types\n parser = structured_types.parser\n\n #\n # At the moment TextDelete type equals the Delete type in BasicTypes.\n # @see BasicTypes.Delete\n #\n class TextDelete extends types.Delete\n parser[\"TextDelete\"] = parser[\"Delete\"]\n\n #\n # Extends the basic Insert type to an operation that holds a text value\n #\n class TextInsert extends types.Insert\n #\n # @param {String} content The content of this Insert-type Operation. Usually you restrict the length of content to size 1\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n #\n constructor: (@content, uid, prev, next, origin)->\n if not (prev? and next?)\n throw new Error \"You must define prev, and next for TextInsert-types!\"\n super uid, prev, next, origin\n #\n # Retrieve the effective length of the $content of this operation.\n #\n getLength: ()->\n if @isDeleted()\n 0\n else\n @content.length\n\n #\n # The result will be concatenated with the results from the other insert operations\n # in order to retrieve the content of the engine.\n # @see HistoryBuffer.toExecutedArray\n #\n val: (current_position)->\n if @isDeleted()\n \"\"\n else\n @content\n\n #\n # Convert all relevant information of this operation to the json-format.\n # This result can be send to other clients.\n #\n _encode: ()->\n json =\n {\n 'type': \"TextInsert\"\n 'content': @content\n 'uid' : @getUid()\n 'prev': @prev_cl.getUid()\n 'next': @next_cl.getUid()\n }\n if @origin? and @origin isnt @prev_cl\n json[\"origin\"] = @origin.getUid()\n json\n\n parser[\"TextInsert\"] = (json)->\n {\n 'content' : content\n 'uid' : uid\n 'prev': prev\n 'next': next\n 'origin' : origin\n } = json\n new TextInsert content, uid, prev, next, origin\n\n #\n # Handles a Text-like data structures with support for insertText/deleteText at a word-position.\n #\n class Word extends types.ListManager\n\n #\n # @param {Object} uid A unique identifier. If uid is undefined, a new uid will be created.\n #\n constructor: (uid, beginning, end, prev, next, origin)->\n super uid, beginning, end, prev, next, origin\n\n #\n # Inserts a string into the word\n #\n insertText: (position, content)->\n o = @getOperationByPosition position\n for c in content\n op = new TextInsert c, undefined, o.prev_cl, o\n HB.addOperation(op).execute()\n\n #\n # Deletes a part of the word.\n #\n deleteText: (position, length)->\n o = @getOperationByPosition position\n\n for i in [0...length]\n d = HB.addOperation(new TextDelete undefined, o).execute()\n o = o.next_cl\n while o.isDeleted()\n if o instanceof types.Delimiter\n throw new Error \"You can't delete more than there is..\"\n o = o.next_cl\n d._encode()\n\n #\n # Replace the content of this word with another one. Concurrent replacements are not merged!\n # Only one of the replacements will be used.\n #\n # Can only be used if the ReplaceManager was set!\n # @see Word.setReplaceManager\n #\n replaceText: (text)->\n if @replace_manager?\n word = HB.addOperation(new Word undefined).execute()\n word.insertText 0, text\n @replace_manager.replace(word)\n else\n throw new Error \"This type is currently not maintained by a ReplaceManager!\"\n\n #\n # @returns [Json] A Json object.\n #\n val: ()->\n c = for o in @toArray()\n if o.val?\n o.val()\n else\n \"\"\n c.join('')\n\n #\n # In most cases you would embed a Word in a Replaceable, wich is handled by the ReplaceManager in order\n # to provide replace functionality.\n #\n setReplaceManager: (op)->\n @saveOperation 'replace_manager', op\n @validateSavedOperations\n\n #\n # Encode this operation in such a way that it can be parsed by remote peers.\n #\n _encode: ()->\n json = {\n 'type': \"Word\"\n 'uid' : @getUid()\n 'beginning' : @beginning.getUid()\n 'end' : @end.getUid()\n }\n if @prev_cl?\n json['prev'] = @prev_cl.getUid()\n if @next_cl?\n json['next'] = @next_cl.getUid()\n if @origin? and @origin isnt @prev_cl\n json[\"origin\"] = @origin.getUid()\n json\n\n parser['Word'] = (json)->\n {\n 'uid' : uid\n 'beginning' : beginning\n 'end' : end\n 'prev': prev\n 'next': next\n 'origin' : origin\n } = json\n new Word uid, beginning, end, prev, next, origin\n\n types['TextInsert'] = TextInsert\n types['TextDelete'] = TextDelete\n types['Word'] = Word\n structured_types\n\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Types/XmlTypes.coffee b/build/node/Types/XmlTypes.coffee new file mode 100644 index 00000000..e69de29b diff --git a/build/node/Types/XmlTypes.coffee.map b/build/node/Types/XmlTypes.coffee.map new file mode 100755 index 00000000..006520eb --- /dev/null +++ b/build/node/Types/XmlTypes.coffee.map @@ -0,0 +1 @@ +{"version":3,"file":"Types/XmlTypes.coffee","names":[],"mappings":"","sources":["Types/XmlTypes.coffee"],"sourcesContent":[""],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/Types/XmlTypes.js b/build/node/Types/XmlTypes.js new file mode 100644 index 00000000..854b5b6c --- /dev/null +++ b/build/node/Types/XmlTypes.js @@ -0,0 +1,2 @@ +(function(){}).call(this); +//# sourceMappingURL=../Types/XmlTypes.js.map \ No newline at end of file diff --git a/build/node/Types/XmlTypes.js.map b/build/node/Types/XmlTypes.js.map new file mode 100755 index 00000000..dd91a270 --- /dev/null +++ b/build/node/Types/XmlTypes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Types/XmlTypes.js","sources":["Types/XmlTypes.coffee"],"names":[],"mappings":"CA8KkB","sourcesContent":[""],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/node/index.coffee b/build/node/index.coffee new file mode 100644 index 00000000..fb653355 --- /dev/null +++ b/build/node/index.coffee @@ -0,0 +1,10 @@ + +exports['IwcConnector'] = + require './Connectors/IwcConnector' +exports['TestConnector'] = + require './Connectors/TestConnector' +exports['JsonYatta'] = + require './Frameworks/JsonYatta' +exports['TextYatta'] = + require './Frameworks/TextYatta' + diff --git a/build/node/index.js b/build/node/index.js new file mode 100644 index 00000000..bf1fd1a8 --- /dev/null +++ b/build/node/index.js @@ -0,0 +1,2 @@ +(function(){exports.IwcConnector=require("./Connectors/IwcConnector"),exports.TestConnector=require("./Connectors/TestConnector"),exports.JsonYatta=require("./Frameworks/JsonYatta"),exports.TextYatta=require("./Frameworks/TextYatta")}).call(this); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/node/index.js.map b/build/node/index.js.map new file mode 100755 index 00000000..a9aac5bb --- /dev/null +++ b/build/node/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["index.coffee"],"names":[],"mappings":"CACA,WAAA,QAAQ,aACN,QAAQ,6BACV,QAAQ,cACN,QAAQ,8BACV,QAAQ,UACN,QAAQ,0BACV,QAAQ,UACN,QAAQ","sourcesContent":["\nexports['IwcConnector'] =\n require './Connectors/IwcConnector'\nexports['TestConnector'] =\n require './Connectors/TestConnector'\nexports['JsonYatta'] =\n require './Frameworks/JsonYatta'\nexports['TextYatta'] =\n require './Frameworks/TextYatta'\n\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/build/test/Yatta_test.js b/build/test/Yatta_test.js new file mode 100644 index 00000000..a8279b73 --- /dev/null +++ b/build/test/Yatta_test.js @@ -0,0 +1,13748 @@ +(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);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { + return this.engine.applyOp(this.unexecuted[user].shift()); + } + }; + + TestConnector.prototype.flushOneRandom = function() { + return this.flushOne(_.random(0, user_list.length - 1)); + }; + + TestConnector.prototype.flushAll = function() { + var n, ops, _ref; + _ref = this.unexecuted; + for (n in _ref) { + ops = _ref[n]; + this.engine.applyOps(ops); + } + return this.unexecuted = {}; + }; + + return TestConnector; + + })(); +}; + + +},{"underscore":64}],2:[function(require,module,exports){ +var Engine; + +Engine = (function() { + function Engine(HB, parser) { + this.HB = HB; + this.parser = parser; + this.unprocessed_ops = []; + } + + Engine.prototype.parseOperation = function(json) { + var typeParser; + typeParser = this.parser[json.type]; + if (typeParser != null) { + return typeParser(json); + } else { + throw new Error("You forgot to specify a parser for type " + json.type + ". The message is " + (JSON.stringify(json)) + "."); + } + }; + + Engine.prototype.applyOpsBundle = function(ops_json) { + var o, ops, _i, _j, _k, _len, _len1, _len2; + ops = []; + for (_i = 0, _len = ops_json.length; _i < _len; _i++) { + o = ops_json[_i]; + ops.push(this.parseOperation(o)); + } + for (_j = 0, _len1 = ops.length; _j < _len1; _j++) { + o = ops[_j]; + this.HB.addOperation(o); + } + for (_k = 0, _len2 = ops.length; _k < _len2; _k++) { + o = ops[_k]; + if (!o.execute()) { + this.unprocessed_ops.push(o); + } + } + return this.tryUnprocessed(); + }; + + Engine.prototype.applyOpsCheckDouble = function(ops_json) { + var o, _i, _len, _results; + _results = []; + for (_i = 0, _len = ops_json.length; _i < _len; _i++) { + o = ops_json[_i]; + if (this.HB.getOperation(o.uid) != null) { + _results.push(this.applyOp(o)); + } else { + _results.push(void 0); + } + } + return _results; + }; + + Engine.prototype.applyOps = function(ops_json) { + var o, _i, _len, _results; + _results = []; + for (_i = 0, _len = ops_json.length; _i < _len; _i++) { + o = ops_json[_i]; + _results.push(this.applyOp(o)); + } + return _results; + }; + + Engine.prototype.applyOp = function(op_json) { + var o; + o = this.parseOperation(op_json); + this.HB.addToCounter(o); + if (!o.execute()) { + this.unprocessed_ops.push(o); + } else { + this.HB.addOperation(o); + } + return this.tryUnprocessed(); + }; + + Engine.prototype.tryUnprocessed = function() { + var old_length, op, unprocessed, _i, _len, _ref, _results; + _results = []; + while (true) { + old_length = this.unprocessed_ops.length; + unprocessed = []; + _ref = this.unprocessed_ops; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + op = _ref[_i]; + if (!op.execute()) { + unprocessed.push(op); + } else { + this.HB.addOperation(op); + } + } + this.unprocessed_ops = unprocessed; + if (this.unprocessed_ops.length === old_length) { + break; + } else { + _results.push(void 0); + } + } + return _results; + }; + + return Engine; + +})(); + +module.exports = Engine; + + +},{}],3:[function(require,module,exports){ +var Engine, HistoryBuffer, JsonYatta, json_types_uninitialized; + +json_types_uninitialized = require("../Types/JsonTypes"); + +HistoryBuffer = require("../HistoryBuffer"); + +Engine = require("../Engine"); + +JsonYatta = (function() { + function JsonYatta(user_id, Connector) { + var first_word, json_types; + this.HB = new HistoryBuffer(user_id); + json_types = json_types_uninitialized(this.HB); + this.engine = new Engine(this.HB, json_types.parser); + this.connector = new Connector(this.engine, this.HB, json_types.execution_listener, this); + first_word = new json_types.types.JsonType(this.HB.getReservedUniqueIdentifier()); + this.HB.addOperation(first_word).execute(); + this.root_element = first_word; + } + + JsonYatta.prototype.getRootElement = function() { + return this.root_element; + }; + + JsonYatta.prototype.getEngine = function() { + return this.engine; + }; + + JsonYatta.prototype.getConnector = function() { + return this.connector; + }; + + JsonYatta.prototype.getHistoryBuffer = function() { + return this.HB; + }; + + JsonYatta.prototype.setMutableDefault = function(mutable) { + return this.root_element.setMutableDefault(mutable); + }; + + JsonYatta.prototype.getUserId = function() { + return this.HB.getUserId(); + }; + + JsonYatta.prototype.val = function(name, content, mutable) { + return this.root_element.val(name, content, mutable); + }; + + Object.defineProperty(JsonYatta.prototype, 'value', { + get: function() { + return this.root_element.value; + }, + set: function(o) { + var o_name, o_obj, _results; + if (o.constructor === {}.constructor) { + _results = []; + for (o_name in o) { + o_obj = o[o_name]; + _results.push(this.val(o_name, o_obj, 'immutable')); + } + return _results; + } else { + throw new Error("You must only set Object values!"); + } + } + }); + + return JsonYatta; + +})(); + +if (typeof window !== "undefined" && window !== null) { + window.JsonYatta = JsonYatta; +} + +module.exports = JsonYatta; + + +},{"../Engine":2,"../HistoryBuffer":4,"../Types/JsonTypes":6}],4:[function(require,module,exports){ +var HistoryBuffer; + +HistoryBuffer = (function() { + function HistoryBuffer(user_id) { + this.user_id = user_id; + this.operation_counter = {}; + this.buffer = {}; + this.change_listeners = []; + } + + HistoryBuffer.prototype.getUserId = function() { + return this.user_id; + }; + + HistoryBuffer.prototype.getReservedUniqueIdentifier = function() { + return { + creator: '_', + op_number: '_' + }; + }; + + HistoryBuffer.prototype.getOperationCounter = function() { + var ctn, res, user, _ref; + res = {}; + _ref = this.operation_counter; + for (user in _ref) { + ctn = _ref[user]; + res[user] = ctn; + } + return res; + }; + + HistoryBuffer.prototype._encode = function(state_vector) { + var json, o, o_json, o_next, o_number, o_prev, u_name, unknown, user, _ref; + if (state_vector == null) { + state_vector = {}; + } + json = []; + unknown = function(user, o_number) { + if ((user == null) || (o_number == null)) { + throw new Error("dah!"); + } + return (state_vector[user] == null) || state_vector[user] <= o_number; + }; + _ref = this.buffer; + for (u_name in _ref) { + user = _ref[u_name]; + for (o_number in user) { + o = user[o_number]; + if (!isNaN(parseInt(o_number)) && unknown(u_name, o_number)) { + o_json = o._encode(); + if (o.next_cl != null) { + o_next = o.next_cl; + while ((o_next.next_cl != null) && unknown(o_next.creator, o_next.op_number)) { + o_next = o_next.next_cl; + } + o_json.next = o_next.getUid(); + } else if (o.prev_cl != null) { + o_prev = o.prev_cl; + while ((o_prev.prev_cl != null) && unknown(o_next.creator, o_next.op_number)) { + o_prev = o_prev.prev_cl; + } + o_json.prev = o_prev.getUid(); + } + json.push(o_json); + } + } + } + return json; + }; + + HistoryBuffer.prototype.getNextOperationIdentifier = function(user_id) { + var uid; + if (user_id == null) { + user_id = this.user_id; + } + if (this.operation_counter[user_id] == null) { + this.operation_counter[user_id] = 0; + } + uid = { + 'creator': user_id, + 'op_number': this.operation_counter[user_id] + }; + this.operation_counter[user_id]++; + return uid; + }; + + HistoryBuffer.prototype.getOperation = function(uid) { + var _ref; + if (uid instanceof Object) { + return (_ref = this.buffer[uid.creator]) != null ? _ref[uid.op_number] : void 0; + } else if (uid == null) { + + } else { + throw new Error("This type of uid is not defined!"); + } + }; + + HistoryBuffer.prototype.addOperation = function(o) { + if (this.buffer[o.creator] == null) { + this.buffer[o.creator] = {}; + } + if (this.buffer[o.creator][o.op_number] != null) { + throw new Error("You must not overwrite operations!"); + } + this.buffer[o.creator][o.op_number] = o; + return o; + }; + + HistoryBuffer.prototype.addToCounter = function(o) { + if (this.operation_counter[o.creator] == null) { + this.operation_counter[o.creator] = 0; + } + if (typeof o.op_number === 'number' && o.creator !== this.getUserId()) { + return this.operation_counter[o.creator]++; + } + }; + + return HistoryBuffer; + +})(); + +module.exports = HistoryBuffer; + + +},{}],5:[function(require,module,exports){ +var __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +module.exports = function(HB) { + var Delete, Delimiter, ImmutableObject, Insert, Operation, execution_listener, parser; + parser = {}; + execution_listener = []; + Operation = (function() { + function Operation(uid) { + if (uid == null) { + uid = HB.getNextOperationIdentifier(); + } + this.creator = uid['creator'], this.op_number = uid['op_number']; + } + + Operation.prototype.on = function(event, f) { + var _base; + if (this.event_listeners == null) { + this.event_listeners = {}; + } + if ((_base = this.event_listeners)[event] == null) { + _base[event] = []; + } + return this.event_listeners[event].push(f); + }; + + Operation.prototype.callEvent = function(event, args) { + var f, _i, _len, _ref, _results; + if (this.event_listeners[event] != null) { + _ref = this.event_listeners[event]; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + f = _ref[_i]; + _results.push(f.call(this, event, args)); + } + return _results; + } + }; + + Operation.prototype.setParent = function(o) { + return this.parent = o; + }; + + Operation.prototype.getUid = function() { + return { + 'creator': this.creator, + 'op_number': this.op_number + }; + }; + + Operation.prototype.execute = function() { + var l, _i, _len; + this.is_executed = true; + for (_i = 0, _len = execution_listener.length; _i < _len; _i++) { + l = execution_listener[_i]; + l(this._encode()); + } + return this; + }; + + Operation.prototype.saveOperation = function(name, op) { + if ((op != null ? op.execute : void 0) != null) { + return this[name] = op; + } else if (op != null) { + if (this.unchecked == null) { + this.unchecked = {}; + } + return this.unchecked[name] = op; + } + }; + + Operation.prototype.validateSavedOperations = function() { + var name, op, op_uid, success, uninstantiated, _ref; + uninstantiated = {}; + success = this; + _ref = this.unchecked; + for (name in _ref) { + op_uid = _ref[name]; + op = HB.getOperation(op_uid); + if (op) { + this[name] = op; + } else { + uninstantiated[name] = op_uid; + success = false; + } + } + delete this.unchecked; + if (!success) { + this.unchecked = uninstantiated; + } + return success; + }; + + return Operation; + + })(); + Delete = (function(_super) { + __extends(Delete, _super); + + function Delete(uid, deletes) { + this.saveOperation('deletes', deletes); + Delete.__super__.constructor.call(this, uid); + } + + Delete.prototype._encode = function() { + return { + 'type': "Delete", + 'uid': this.getUid(), + 'deletes': this.deletes.getUid() + }; + }; + + Delete.prototype.execute = function() { + if (this.validateSavedOperations()) { + this.deletes.applyDelete(this); + Delete.__super__.execute.apply(this, arguments); + return this; + } else { + return false; + } + }; + + return Delete; + + })(Operation); + parser['Delete'] = function(o) { + var deletes_uid, uid; + uid = o['uid'], deletes_uid = o['deletes']; + return new Delete(uid, deletes_uid); + }; + Insert = (function(_super) { + __extends(Insert, _super); + + function Insert(uid, prev_cl, next_cl, origin) { + this.saveOperation('prev_cl', prev_cl); + this.saveOperation('next_cl', next_cl); + if (origin != null) { + this.saveOperation('origin', origin); + } else { + this.saveOperation('origin', prev_cl); + } + Insert.__super__.constructor.call(this, uid); + } + + Insert.prototype.applyDelete = function(o) { + if (this.deleted_by == null) { + this.deleted_by = []; + } + return this.deleted_by.push(o); + }; + + Insert.prototype.isDeleted = function() { + var _ref; + return ((_ref = this.deleted_by) != null ? _ref.length : void 0) > 0; + }; + + Insert.prototype.getDistanceToOrigin = function() { + var d, o; + d = 0; + o = this.prev_cl; + while (true) { + if (this.origin === o) { + break; + } + d++; + if (this === this.prev_cl) { + throw new Error("this should not happen ;) "); + } + o = o.prev_cl; + } + return d; + }; + + Insert.prototype.update_sl = function() { + var o; + o = this.prev_cl; + ({ + update: function(dest_cl, dest_sl) { + var _results; + _results = []; + while (true) { + if (o.isDeleted()) { + _results.push(o = o[dest_cl]); + } else { + this[dest_sl] = o; + break; + } + } + return _results; + } + }); + update("prev_cl", "prev_sl"); + return update("next_cl", "prev_sl"); + }; + + Insert.prototype.execute = function() { + var distance_to_origin, i, o, _ref, _ref1; + if (this.is_executed != null) { + return this; + } + if (!this.validateSavedOperations()) { + return false; + } else { + if (((_ref = this.prev_cl) != null ? _ref.validateSavedOperations() : void 0) && ((_ref1 = this.next_cl) != null ? _ref1.validateSavedOperations() : void 0) && this.prev_cl.next_cl !== this) { + distance_to_origin = 0; + o = this.prev_cl.next_cl; + i = 0; + while (true) { + if (o == null) { + console.log(JSON.stringify(this.prev_cl.getUid())); + console.log(JSON.stringify(this.next_cl.getUid())); + } + if (o !== this.next_cl) { + if (o.getDistanceToOrigin() === i) { + if (o.creator < this.creator) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else if (o.getDistanceToOrigin() < i) { + if (i - distance_to_origin <= o.getDistanceToOrigin()) { + this.prev_cl = o; + distance_to_origin = i + 1; + } else { + + } + } else { + break; + } + i++; + o = o.next_cl; + } else { + break; + } + } + this.next_cl = this.prev_cl.next_cl; + this.prev_cl.next_cl = this; + this.next_cl.prev_cl = this; + } + Insert.__super__.execute.apply(this, arguments); + return this; + } + }; + + return Insert; + + })(Operation); + ImmutableObject = (function(_super) { + __extends(ImmutableObject, _super); + + function ImmutableObject(uid, content, prev, next, origin) { + this.content = content; + ImmutableObject.__super__.constructor.call(this, uid, prev, next, origin); + } + + ImmutableObject.prototype.val = function() { + return this.content; + }; + + ImmutableObject.prototype._encode = function() { + var json; + json = { + 'type': "ImmutableObject", + 'uid': this.getUid(), + 'content': this.content + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ImmutableObject; + + })(Insert); + parser['ImmutableObject'] = function(json) { + var content, next, origin, prev, uid; + uid = json['uid'], content = json['content'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new ImmutableObject(uid, content, prev, next, origin); + }; + Delimiter = (function(_super) { + __extends(Delimiter, _super); + + function Delimiter(uid, prev_cl, next_cl, origin) { + this.saveOperation('prev_cl', prev_cl); + this.saveOperation('next_cl', next_cl); + this.saveOperation('origin', prev_cl); + Delimiter.__super__.constructor.call(this, uid); + } + + Delimiter.prototype.isDeleted = function() { + return false; + }; + + Delimiter.prototype.execute = function() { + var _ref, _ref1; + if (((_ref = this.unchecked) != null ? _ref['next_cl'] : void 0) != null) { + return Delimiter.__super__.execute.apply(this, arguments); + } else if ((_ref1 = this.unchecked) != null ? _ref1['prev_cl'] : void 0) { + if (this.validateSavedOperations()) { + if (this.prev_cl.next_cl != null) { + throw new Error("Probably duplicated operations"); + } + this.prev_cl.next_cl = this; + delete this.prev_cl.unchecked.next_cl; + return Delimiter.__super__.execute.apply(this, arguments); + } else { + return false; + } + } else if ((this.prev_cl != null) && (this.prev_cl.next_cl == null)) { + delete this.prev_cl.unchecked.next_cl; + return this.prev_cl.next_cl = this; + } else if ((this.prev_cl != null) || (this.next_cl != null)) { + return Delimiter.__super__.execute.apply(this, arguments); + } else { + throw new Error("Delimiter is unsufficient defined!"); + } + }; + + Delimiter.prototype._encode = function() { + var _ref, _ref1; + return { + 'type': "Delimiter", + 'uid': this.getUid(), + 'prev': (_ref = this.prev_cl) != null ? _ref.getUid() : void 0, + 'next': (_ref1 = this.next_cl) != null ? _ref1.getUid() : void 0 + }; + }; + + return Delimiter; + + })(Operation); + parser['Delimiter'] = function(json) { + var next, prev, uid; + uid = json['uid'], prev = json['prev'], next = json['next']; + return new Delimiter(uid, prev, next); + }; + return { + 'types': { + 'Delete': Delete, + 'Insert': Insert, + 'Delimiter': Delimiter, + 'Operation': Operation, + 'ImmutableObject': ImmutableObject + }, + 'parser': parser, + 'execution_listener': execution_listener + }; +}; + + +},{}],6:[function(require,module,exports){ +var text_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +text_types_uninitialized = require("./TextTypes"); + +module.exports = function(HB) { + var JsonType, createJsonWrapper, parser, text_types, types; + text_types = text_types_uninitialized(HB); + types = text_types.types; + parser = text_types.parser; + createJsonWrapper = function(_jsonType) { + var JsonWrapper; + JsonWrapper = (function() { + function JsonWrapper(jsonType) { + var name, obj, _fn, _ref; + _ref = jsonType.map; + _fn = function(name, obj) { + return Object.defineProperty(JsonWrapper.prototype, name, { + get: function() { + var x; + x = obj.val(); + if (x instanceof JsonType) { + return createJsonWrapper(x); + } else if (x instanceof types.ImmutableObject) { + return x.val(); + } else { + return x; + } + }, + set: function(o) { + var o_name, o_obj, overwrite, _results; + if (o.constructor === {}.constructor) { + overwrite = jsonType.val(name); + _results = []; + for (o_name in o) { + o_obj = o[o_name]; + _results.push(overwrite.val(o_name, o_obj, 'immutable')); + } + return _results; + } else { + return jsonType.val(name, o, 'immutable'); + } + }, + enumerable: true, + configurable: false + }); + }; + for (name in _ref) { + obj = _ref[name]; + _fn(name, obj); + } + } + + return JsonWrapper; + + })(); + return new JsonWrapper(_jsonType); + }; + JsonType = (function(_super) { + __extends(JsonType, _super); + + function JsonType(uid, initial_value, mutable) { + var name, o; + JsonType.__super__.constructor.call(this, uid); + if (initial_value != null) { + if (typeof initial_value !== "object") { + throw new Error("The initial value of JsonTypes must be of type Object! (current type: " + (typeof initial_value) + ")"); + } + for (name in initial_value) { + o = initial_value[name]; + this.val(name, o, mutable); + } + } + } + + JsonType.prototype.mutable_default = true; + + JsonType.prototype.setMutableDefault = function(mutable) { + if (mutable === true || mutable === 'mutable') { + JsonType.prototype.mutable_default = true; + } else if (mutable === false || mutable === 'immutable') { + JsonType.prototype.mutable_default = false; + } else { + throw new Error('Set mutable either "mutable" or "immutable"!'); + } + return 'OK'; + }; + + JsonType.prototype.val = function(name, content, mutable) { + var json, o, o_name, obj, word; + if (typeof name === 'object') { + for (o_name in name) { + o = name[o_name]; + this.val(o_name, o, content); + } + return this; + } else if ((name != null) && (content != null)) { + if (mutable != null) { + if (mutable === true || mutable === 'mutable') { + mutable = true; + } else { + mutable = false; + } + } else { + mutable = this.mutable_default; + } + if (typeof content === 'function') { + return this; + } else if (((!mutable) || typeof content === 'number') && content.constructor !== Object) { + obj = HB.addOperation(new types.ImmutableObject(void 0, content)).execute(); + return JsonType.__super__.val.call(this, name, obj); + } else { + if (typeof content === 'string') { + word = HB.addOperation(new types.Word(void 0)).execute(); + word.insertText(0, content); + return JsonType.__super__.val.call(this, name, word); + } else if (content.constructor === Object) { + json = HB.addOperation(new JsonType(void 0, content, mutable)).execute(); + return JsonType.__super__.val.call(this, name, json); + } else { + throw new Error("You must not set " + (typeof content) + "-types in collaborative Json-objects!"); + } + } + } else { + return JsonType.__super__.val.call(this, name, content); + } + }; + + Object.defineProperty(JsonType.prototype, 'value', { + get: function() { + return createJsonWrapper(this); + }, + set: function(o) { + var o_name, o_obj, _results; + if (o.constructor === {}.constructor) { + _results = []; + for (o_name in o) { + o_obj = o[o_name]; + _results.push(this.val(o_name, o_obj, 'immutable')); + } + return _results; + } else { + throw new Error("You must only set Object values!"); + } + } + }); + + JsonType.prototype._encode = function() { + return { + 'type': "JsonType", + 'uid': this.getUid() + }; + }; + + return JsonType; + + })(types.MapManager); + parser['JsonType'] = function(json) { + var uid; + uid = json['uid']; + return new JsonType(uid); + }; + types['JsonType'] = JsonType; + return text_types; +}; + + +},{"./TextTypes":8}],7:[function(require,module,exports){ +var basic_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +basic_types_uninitialized = require("./BasicTypes"); + +module.exports = function(HB) { + var AddName, ListManager, MapManager, ReplaceManager, Replaceable, basic_types, parser, types; + basic_types = basic_types_uninitialized(HB); + types = basic_types.types; + parser = basic_types.parser; + MapManager = (function(_super) { + __extends(MapManager, _super); + + function MapManager(uid) { + this.map = {}; + MapManager.__super__.constructor.call(this, uid); + } + + MapManager.prototype.val = function(name, content) { + var o, obj, result, _ref, _ref1; + if (content != null) { + if (this.map[name] == null) { + HB.addOperation(new AddName(void 0, this, name)).execute(); + } + this.map[name].replace(content); + return this; + } else if (name != null) { + obj = (_ref = this.map[name]) != null ? _ref.val() : void 0; + if (obj instanceof types.ImmutableObject) { + return obj.val(); + } else { + return obj; + } + } else { + result = {}; + _ref1 = this.map; + for (name in _ref1) { + o = _ref1[name]; + obj = o.val(); + if (obj instanceof types.ImmutableObject || obj instanceof MapManager) { + obj = obj.val(); + } + result[name] = obj; + } + return result; + } + }; + + return MapManager; + + })(types.Operation); + AddName = (function(_super) { + __extends(AddName, _super); + + function AddName(uid, map_manager, name) { + this.name = name; + this.saveOperation('map_manager', map_manager); + AddName.__super__.constructor.call(this, uid); + } + + AddName.prototype.execute = function() { + var beg, end, uid_beg, uid_end, uid_r; + if (!this.validateSavedOperations()) { + return false; + } else { + uid_r = this.map_manager.getUid(); + uid_r.op_number = "_" + uid_r.op_number + "_RM_" + this.name; + if (HB.getOperation(uid_r) == null) { + uid_beg = this.map_manager.getUid(); + uid_beg.op_number = "_" + uid_beg.op_number + "_RM_" + this.name + "_beginning"; + uid_end = this.map_manager.getUid(); + uid_end.op_number = "_" + uid_end.op_number + "_RM_" + this.name + "_end"; + beg = HB.addOperation(new types.Delimiter(uid_beg, void 0, uid_end)).execute(); + end = HB.addOperation(new types.Delimiter(uid_end, beg, void 0)).execute(); + this.map_manager.map[this.name] = HB.addOperation(new ReplaceManager(void 0, uid_r, beg, end)).execute(); + } + return AddName.__super__.execute.apply(this, arguments); + } + }; + + AddName.prototype._encode = function() { + return { + 'type': "AddName", + 'uid': this.getUid(), + 'map_manager': this.map_manager.getUid(), + 'name': this.name + }; + }; + + return AddName; + + })(types.Operation); + parser['AddName'] = function(json) { + var map_manager, name, uid; + map_manager = json['map_manager'], uid = json['uid'], name = json['name']; + return new AddName(uid, map_manager, name); + }; + ListManager = (function(_super) { + __extends(ListManager, _super); + + function ListManager(uid, beginning, end, prev, next, origin) { + if ((beginning != null) && (end != null)) { + this.saveOperation('beginning', beginning); + this.saveOperation('end', end); + } else { + this.beginning = HB.addOperation(new types.Delimiter(void 0, void 0, void 0)); + this.end = HB.addOperation(new types.Delimiter(void 0, this.beginning, void 0)); + this.beginning.next_cl = this.end; + this.beginning.execute(); + this.end.execute(); + } + ListManager.__super__.constructor.call(this, uid, prev, next, origin); + } + + ListManager.prototype.getLastOperation = function() { + return this.end.prev_cl; + }; + + ListManager.prototype.getFirstOperation = function() { + return this.beginning.next_cl; + }; + + ListManager.prototype.toArray = function() { + var o, result; + o = this.beginning.next_cl; + result = []; + while (o !== this.end) { + result.push(o); + o = o.next_cl; + } + return result; + }; + + ListManager.prototype.getOperationByPosition = function(position) { + var o; + o = this.beginning.next_cl; + if (position > 0) { + while (true) { + o = o.next_cl; + if (!o.isDeleted()) { + position -= 1; + } + if (position === 0) { + break; + } + if (o instanceof types.Delimiter) { + throw new Error("position parameter exceeded the length of the document!"); + } + } + } + return o; + }; + + return ListManager; + + })(types.Insert); + ReplaceManager = (function(_super) { + __extends(ReplaceManager, _super); + + function ReplaceManager(initial_content, uid, beginning, end, prev, next, origin) { + ReplaceManager.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + if (initial_content != null) { + this.replace(initial_content); + } + } + + ReplaceManager.prototype.replace = function(content) { + var o, op; + o = this.getLastOperation(); + op = new Replaceable(content, this, void 0, o, o.next_cl); + return HB.addOperation(op).execute(); + }; + + ReplaceManager.prototype.val = function() { + var o; + o = this.getLastOperation(); + if (o instanceof types.Delimiter) { + throw new Error("dtrn"); + } + return o.val(); + }; + + ReplaceManager.prototype._encode = function() { + var json; + json = { + 'type': "ReplaceManager", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if ((this.prev_cl != null) && (this.next_cl != null)) { + json['prev'] = this.prev_cl.getUid(); + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return ReplaceManager; + + })(ListManager); + parser["ReplaceManager"] = function(json) { + var beginning, content, end, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin'], beginning = json['beginning'], end = json['end']; + return new ReplaceManager(content, uid, beginning, end, prev, next, origin); + }; + Replaceable = (function(_super) { + __extends(Replaceable, _super); + + function Replaceable(content, parent, uid, prev, next, origin) { + this.saveOperation('content', content); + this.saveOperation('parent', parent); + if (!((prev != null) && (next != null) && (content != null))) { + throw new Error("You must define content, prev, and next for Replaceable-types!"); + } + Replaceable.__super__.constructor.call(this, uid, prev, next, origin); + } + + Replaceable.prototype.val = function() { + return this.content; + }; + + Replaceable.prototype.replace = function(content) { + return this.parent.replace(content); + }; + + Replaceable.prototype.execute = function() { + var _base; + if (!this.validateSavedOperations()) { + return false; + } else { + if (typeof (_base = this.content).setReplaceManager === "function") { + _base.setReplaceManager(this.parent); + } + Replaceable.__super__.execute.apply(this, arguments); + return this; + } + }; + + Replaceable.prototype._encode = function() { + var json; + json = { + 'type': "Replaceable", + 'content': this.content.getUid(), + 'ReplaceManager': this.parent.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid(), + 'uid': this.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Replaceable; + + })(types.Insert); + parser["Replaceable"] = function(json) { + var content, next, origin, parent, prev, uid; + content = json['content'], parent = json['ReplaceManager'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Replaceable(content, parent, uid, prev, next, origin); + }; + types['ListManager'] = ListManager; + types['MapManager'] = MapManager; + types['ReplaceManager'] = ReplaceManager; + types['Replaceable'] = Replaceable; + return basic_types; +}; + + +},{"./BasicTypes":5}],8:[function(require,module,exports){ +var structured_types_uninitialized, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; + +structured_types_uninitialized = require("./StructuredTypes"); + +module.exports = function(HB) { + var TextDelete, TextInsert, Word, parser, structured_types, types; + structured_types = structured_types_uninitialized(HB); + types = structured_types.types; + parser = structured_types.parser; + TextDelete = (function(_super) { + __extends(TextDelete, _super); + + function TextDelete() { + return TextDelete.__super__.constructor.apply(this, arguments); + } + + return TextDelete; + + })(types.Delete); + parser["TextDelete"] = parser["Delete"]; + TextInsert = (function(_super) { + __extends(TextInsert, _super); + + function TextInsert(content, uid, prev, next, origin) { + this.content = content; + if (!((prev != null) && (next != null))) { + throw new Error("You must define prev, and next for TextInsert-types!"); + } + TextInsert.__super__.constructor.call(this, uid, prev, next, origin); + } + + TextInsert.prototype.getLength = function() { + if (this.isDeleted()) { + return 0; + } else { + return this.content.length; + } + }; + + TextInsert.prototype.val = function(current_position) { + if (this.isDeleted()) { + return ""; + } else { + return this.content; + } + }; + + TextInsert.prototype._encode = function() { + var json; + json = { + 'type': "TextInsert", + 'content': this.content, + 'uid': this.getUid(), + 'prev': this.prev_cl.getUid(), + 'next': this.next_cl.getUid() + }; + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return TextInsert; + + })(types.Insert); + parser["TextInsert"] = function(json) { + var content, next, origin, prev, uid; + content = json['content'], uid = json['uid'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new TextInsert(content, uid, prev, next, origin); + }; + Word = (function(_super) { + __extends(Word, _super); + + function Word(uid, beginning, end, prev, next, origin) { + Word.__super__.constructor.call(this, uid, beginning, end, prev, next, origin); + } + + Word.prototype.insertText = function(position, content) { + var c, o, op, _i, _len, _results; + o = this.getOperationByPosition(position); + _results = []; + for (_i = 0, _len = content.length; _i < _len; _i++) { + c = content[_i]; + op = new TextInsert(c, void 0, o.prev_cl, o); + _results.push(HB.addOperation(op).execute()); + } + return _results; + }; + + Word.prototype.deleteText = function(position, length) { + var d, i, o, _i, _results; + o = this.getOperationByPosition(position); + _results = []; + for (i = _i = 0; 0 <= length ? _i < length : _i > length; i = 0 <= length ? ++_i : --_i) { + d = HB.addOperation(new TextDelete(void 0, o)).execute(); + o = o.next_cl; + while (o.isDeleted()) { + if (o instanceof types.Delimiter) { + throw new Error("You can't delete more than there is.."); + } + o = o.next_cl; + } + _results.push(d._encode()); + } + return _results; + }; + + Word.prototype.replaceText = function(text) { + var word; + if (this.replace_manager != null) { + word = HB.addOperation(new Word(void 0)).execute(); + word.insertText(0, text); + return this.replace_manager.replace(word); + } else { + throw new Error("This type is currently not maintained by a ReplaceManager!"); + } + }; + + Word.prototype.val = function() { + var c, o; + c = (function() { + var _i, _len, _ref, _results; + _ref = this.toArray(); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + o = _ref[_i]; + if (o.val != null) { + _results.push(o.val()); + } else { + _results.push(""); + } + } + return _results; + }).call(this); + return c.join(''); + }; + + Word.prototype.setReplaceManager = function(op) { + this.saveOperation('replace_manager', op); + return this.validateSavedOperations; + }; + + Word.prototype._encode = function() { + var json; + json = { + 'type': "Word", + 'uid': this.getUid(), + 'beginning': this.beginning.getUid(), + 'end': this.end.getUid() + }; + if (this.prev_cl != null) { + json['prev'] = this.prev_cl.getUid(); + } + if (this.next_cl != null) { + json['next'] = this.next_cl.getUid(); + } + if ((this.origin != null) && this.origin !== this.prev_cl) { + json["origin"] = this.origin.getUid(); + } + return json; + }; + + return Word; + + })(types.ListManager); + parser['Word'] = function(json) { + var beginning, end, next, origin, prev, uid; + uid = json['uid'], beginning = json['beginning'], end = json['end'], prev = json['prev'], next = json['next'], origin = json['origin']; + return new Word(uid, beginning, end, prev, next, origin); + }; + types['TextInsert'] = TextInsert; + types['TextDelete'] = TextDelete; + types['Word'] = Word; + return structured_types; +}; + + +},{"./StructuredTypes":7}],9:[function(require,module,exports){ +module.exports = require('./lib/chai'); + +},{"./lib/chai":10}],10:[function(require,module,exports){ +/*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ + +var used = [] + , exports = module.exports = {}; + +/*! + * Chai version + */ + +exports.version = '1.9.1'; + +/*! + * Assertion Error + */ + +exports.AssertionError = require('assertion-error'); + +/*! + * Utils for plugins (not exported) + */ + +var util = require('./chai/utils'); + +/** + * # .use(function) + * + * Provides a way to extend the internals of Chai + * + * @param {Function} + * @returns {this} for chaining + * @api public + */ + +exports.use = function (fn) { + if (!~used.indexOf(fn)) { + fn(this, util); + used.push(fn); + } + + return this; +}; + +/*! + * Configuration + */ + +var config = require('./chai/config'); +exports.config = config; + +/*! + * Primary `Assertion` prototype + */ + +var assertion = require('./chai/assertion'); +exports.use(assertion); + +/*! + * Core Assertions + */ + +var core = require('./chai/core/assertions'); +exports.use(core); + +/*! + * Expect interface + */ + +var expect = require('./chai/interface/expect'); +exports.use(expect); + +/*! + * Should interface + */ + +var should = require('./chai/interface/should'); +exports.use(should); + +/*! + * Assert interface + */ + +var assert = require('./chai/interface/assert'); +exports.use(assert); + +},{"./chai/assertion":11,"./chai/config":12,"./chai/core/assertions":13,"./chai/interface/assert":14,"./chai/interface/expect":15,"./chai/interface/should":16,"./chai/utils":27,"assertion-error":36}],11:[function(require,module,exports){ +/*! + * chai + * http://chaijs.com + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ + +var config = require('./config'); + +module.exports = function (_chai, util) { + /*! + * Module dependencies. + */ + + var AssertionError = _chai.AssertionError + , flag = util.flag; + + /*! + * Module export. + */ + + _chai.Assertion = Assertion; + + /*! + * Assertion Constructor + * + * Creates object for chaining. + * + * @api private + */ + + function Assertion (obj, msg, stack) { + flag(this, 'ssfi', stack || arguments.callee); + flag(this, 'object', obj); + flag(this, 'message', msg); + } + + Object.defineProperty(Assertion, 'includeStack', { + get: function() { + console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); + return config.includeStack; + }, + set: function(value) { + console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.'); + config.includeStack = value; + } + }); + + Object.defineProperty(Assertion, 'showDiff', { + get: function() { + console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); + return config.showDiff; + }, + set: function(value) { + console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.'); + config.showDiff = value; + } + }); + + Assertion.addProperty = function (name, fn) { + util.addProperty(this.prototype, name, fn); + }; + + Assertion.addMethod = function (name, fn) { + util.addMethod(this.prototype, name, fn); + }; + + Assertion.addChainableMethod = function (name, fn, chainingBehavior) { + util.addChainableMethod(this.prototype, name, fn, chainingBehavior); + }; + + Assertion.overwriteProperty = function (name, fn) { + util.overwriteProperty(this.prototype, name, fn); + }; + + Assertion.overwriteMethod = function (name, fn) { + util.overwriteMethod(this.prototype, name, fn); + }; + + Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) { + util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior); + }; + + /*! + * ### .assert(expression, message, negateMessage, expected, actual) + * + * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass. + * + * @name assert + * @param {Philosophical} expression to be tested + * @param {String} message to display if fails + * @param {String} negatedMessage to display if negated expression fails + * @param {Mixed} expected value (remember to check for negation) + * @param {Mixed} actual (optional) will default to `this.obj` + * @api private + */ + + Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) { + var ok = util.test(this, arguments); + if (true !== showDiff) showDiff = false; + if (true !== config.showDiff) showDiff = false; + + if (!ok) { + var msg = util.getMessage(this, arguments) + , actual = util.getActual(this, arguments); + throw new AssertionError(msg, { + actual: actual + , expected: expected + , showDiff: showDiff + }, (config.includeStack) ? this.assert : flag(this, 'ssfi')); + } + }; + + /*! + * ### ._obj + * + * Quick reference to stored `actual` value for plugin developers. + * + * @api private + */ + + Object.defineProperty(Assertion.prototype, '_obj', + { get: function () { + return flag(this, 'object'); + } + , set: function (val) { + flag(this, 'object', val); + } + }); +}; + +},{"./config":12}],12:[function(require,module,exports){ +module.exports = { + + /** + * ### config.includeStack + * + * User configurable property, influences whether stack trace + * is included in Assertion error message. Default of false + * suppresses stack trace in the error message. + * + * chai.config.includeStack = true; // enable stack on error + * + * @param {Boolean} + * @api public + */ + + includeStack: false, + + /** + * ### config.showDiff + * + * User configurable property, influences whether or not + * the `showDiff` flag should be included in the thrown + * AssertionErrors. `false` will always be `false`; `true` + * will be true when the assertion has requested a diff + * be shown. + * + * @param {Boolean} + * @api public + */ + + showDiff: true, + + /** + * ### config.truncateThreshold + * + * User configurable property, sets length threshold for actual and + * expected values in assertion errors. If this threshold is exceeded, + * the value is truncated. + * + * Set it to zero if you want to disable truncating altogether. + * + * chai.config.truncateThreshold = 0; // disable truncating + * + * @param {Number} + * @api public + */ + + truncateThreshold: 40 + +}; + +},{}],13:[function(require,module,exports){ +/*! + * chai + * http://chaijs.com + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ + +module.exports = function (chai, _) { + var Assertion = chai.Assertion + , toString = Object.prototype.toString + , flag = _.flag; + + /** + * ### Language Chains + * + * The following are provided as chainable getters to + * improve the readability of your assertions. They + * do not provide testing capabilities unless they + * have been overwritten by a plugin. + * + * **Chains** + * + * - to + * - be + * - been + * - is + * - that + * - and + * - has + * - have + * - with + * - at + * - of + * - same + * + * @name language chains + * @api public + */ + + [ 'to', 'be', 'been' + , 'is', 'and', 'has', 'have' + , 'with', 'that', 'at' + , 'of', 'same' ].forEach(function (chain) { + Assertion.addProperty(chain, function () { + return this; + }); + }); + + /** + * ### .not + * + * Negates any of assertions following in the chain. + * + * expect(foo).to.not.equal('bar'); + * expect(goodFn).to.not.throw(Error); + * expect({ foo: 'baz' }).to.have.property('foo') + * .and.not.equal('bar'); + * + * @name not + * @api public + */ + + Assertion.addProperty('not', function () { + flag(this, 'negate', true); + }); + + /** + * ### .deep + * + * Sets the `deep` flag, later used by the `equal` and + * `property` assertions. + * + * expect(foo).to.deep.equal({ bar: 'baz' }); + * expect({ foo: { bar: { baz: 'quux' } } }) + * .to.have.deep.property('foo.bar.baz', 'quux'); + * + * @name deep + * @api public + */ + + Assertion.addProperty('deep', function () { + flag(this, 'deep', true); + }); + + /** + * ### .a(type) + * + * The `a` and `an` assertions are aliases that can be + * used either as language chains or to assert a value's + * type. + * + * // typeof + * expect('test').to.be.a('string'); + * expect({ foo: 'bar' }).to.be.an('object'); + * expect(null).to.be.a('null'); + * expect(undefined).to.be.an('undefined'); + * + * // language chain + * expect(foo).to.be.an.instanceof(Foo); + * + * @name a + * @alias an + * @param {String} type + * @param {String} message _optional_ + * @api public + */ + + function an (type, msg) { + if (msg) flag(this, 'message', msg); + type = type.toLowerCase(); + var obj = flag(this, 'object') + , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a '; + + this.assert( + type === _.type(obj) + , 'expected #{this} to be ' + article + type + , 'expected #{this} not to be ' + article + type + ); + } + + Assertion.addChainableMethod('an', an); + Assertion.addChainableMethod('a', an); + + /** + * ### .include(value) + * + * The `include` and `contain` assertions can be used as either property + * based language chains or as methods to assert the inclusion of an object + * in an array or a substring in a string. When used as language chains, + * they toggle the `contain` flag for the `keys` assertion. + * + * expect([1,2,3]).to.include(2); + * expect('foobar').to.contain('foo'); + * expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo'); + * + * @name include + * @alias contain + * @param {Object|String|Number} obj + * @param {String} message _optional_ + * @api public + */ + + function includeChainingBehavior () { + flag(this, 'contains', true); + } + + function include (val, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + var expected = false; + if (_.type(obj) === 'array' && _.type(val) === 'object') { + for (var i in obj) { + if (_.eql(obj[i], val)) { + expected = true; + break; + } + } + } else if (_.type(val) === 'object') { + if (!flag(this, 'negate')) { + for (var k in val) new Assertion(obj).property(k, val[k]); + return; + } + var subset = {} + for (var k in val) subset[k] = obj[k] + expected = _.eql(subset, val); + } else { + expected = obj && ~obj.indexOf(val) + } + this.assert( + expected + , 'expected #{this} to include ' + _.inspect(val) + , 'expected #{this} to not include ' + _.inspect(val)); + } + + Assertion.addChainableMethod('include', include, includeChainingBehavior); + Assertion.addChainableMethod('contain', include, includeChainingBehavior); + + /** + * ### .ok + * + * Asserts that the target is truthy. + * + * expect('everthing').to.be.ok; + * expect(1).to.be.ok; + * expect(false).to.not.be.ok; + * expect(undefined).to.not.be.ok; + * expect(null).to.not.be.ok; + * + * @name ok + * @api public + */ + + Assertion.addProperty('ok', function () { + this.assert( + flag(this, 'object') + , 'expected #{this} to be truthy' + , 'expected #{this} to be falsy'); + }); + + /** + * ### .true + * + * Asserts that the target is `true`. + * + * expect(true).to.be.true; + * expect(1).to.not.be.true; + * + * @name true + * @api public + */ + + Assertion.addProperty('true', function () { + this.assert( + true === flag(this, 'object') + , 'expected #{this} to be true' + , 'expected #{this} to be false' + , this.negate ? false : true + ); + }); + + /** + * ### .false + * + * Asserts that the target is `false`. + * + * expect(false).to.be.false; + * expect(0).to.not.be.false; + * + * @name false + * @api public + */ + + Assertion.addProperty('false', function () { + this.assert( + false === flag(this, 'object') + , 'expected #{this} to be false' + , 'expected #{this} to be true' + , this.negate ? true : false + ); + }); + + /** + * ### .null + * + * Asserts that the target is `null`. + * + * expect(null).to.be.null; + * expect(undefined).not.to.be.null; + * + * @name null + * @api public + */ + + Assertion.addProperty('null', function () { + this.assert( + null === flag(this, 'object') + , 'expected #{this} to be null' + , 'expected #{this} not to be null' + ); + }); + + /** + * ### .undefined + * + * Asserts that the target is `undefined`. + * + * expect(undefined).to.be.undefined; + * expect(null).to.not.be.undefined; + * + * @name undefined + * @api public + */ + + Assertion.addProperty('undefined', function () { + this.assert( + undefined === flag(this, 'object') + , 'expected #{this} to be undefined' + , 'expected #{this} not to be undefined' + ); + }); + + /** + * ### .exist + * + * Asserts that the target is neither `null` nor `undefined`. + * + * var foo = 'hi' + * , bar = null + * , baz; + * + * expect(foo).to.exist; + * expect(bar).to.not.exist; + * expect(baz).to.not.exist; + * + * @name exist + * @api public + */ + + Assertion.addProperty('exist', function () { + this.assert( + null != flag(this, 'object') + , 'expected #{this} to exist' + , 'expected #{this} to not exist' + ); + }); + + + /** + * ### .empty + * + * Asserts that the target's length is `0`. For arrays, it checks + * the `length` property. For objects, it gets the count of + * enumerable keys. + * + * expect([]).to.be.empty; + * expect('').to.be.empty; + * expect({}).to.be.empty; + * + * @name empty + * @api public + */ + + Assertion.addProperty('empty', function () { + var obj = flag(this, 'object') + , expected = obj; + + if (Array.isArray(obj) || 'string' === typeof object) { + expected = obj.length; + } else if (typeof obj === 'object') { + expected = Object.keys(obj).length; + } + + this.assert( + !expected + , 'expected #{this} to be empty' + , 'expected #{this} not to be empty' + ); + }); + + /** + * ### .arguments + * + * Asserts that the target is an arguments object. + * + * function test () { + * expect(arguments).to.be.arguments; + * } + * + * @name arguments + * @alias Arguments + * @api public + */ + + function checkArguments () { + var obj = flag(this, 'object') + , type = Object.prototype.toString.call(obj); + this.assert( + '[object Arguments]' === type + , 'expected #{this} to be arguments but got ' + type + , 'expected #{this} to not be arguments' + ); + } + + Assertion.addProperty('arguments', checkArguments); + Assertion.addProperty('Arguments', checkArguments); + + /** + * ### .equal(value) + * + * Asserts that the target is strictly equal (`===`) to `value`. + * Alternately, if the `deep` flag is set, asserts that + * the target is deeply equal to `value`. + * + * expect('hello').to.equal('hello'); + * expect(42).to.equal(42); + * expect(1).to.not.equal(true); + * expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' }); + * expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' }); + * + * @name equal + * @alias equals + * @alias eq + * @alias deep.equal + * @param {Mixed} value + * @param {String} message _optional_ + * @api public + */ + + function assertEqual (val, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + if (flag(this, 'deep')) { + return this.eql(val); + } else { + this.assert( + val === obj + , 'expected #{this} to equal #{exp}' + , 'expected #{this} to not equal #{exp}' + , val + , this._obj + , true + ); + } + } + + Assertion.addMethod('equal', assertEqual); + Assertion.addMethod('equals', assertEqual); + Assertion.addMethod('eq', assertEqual); + + /** + * ### .eql(value) + * + * Asserts that the target is deeply equal to `value`. + * + * expect({ foo: 'bar' }).to.eql({ foo: 'bar' }); + * expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]); + * + * @name eql + * @alias eqls + * @param {Mixed} value + * @param {String} message _optional_ + * @api public + */ + + function assertEql(obj, msg) { + if (msg) flag(this, 'message', msg); + this.assert( + _.eql(obj, flag(this, 'object')) + , 'expected #{this} to deeply equal #{exp}' + , 'expected #{this} to not deeply equal #{exp}' + , obj + , this._obj + , true + ); + } + + Assertion.addMethod('eql', assertEql); + Assertion.addMethod('eqls', assertEql); + + /** + * ### .above(value) + * + * Asserts that the target is greater than `value`. + * + * expect(10).to.be.above(5); + * + * Can also be used in conjunction with `length` to + * assert a minimum length. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.above(2); + * expect([ 1, 2, 3 ]).to.have.length.above(2); + * + * @name above + * @alias gt + * @alias greaterThan + * @param {Number} value + * @param {String} message _optional_ + * @api public + */ + + function assertAbove (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + if (flag(this, 'doLength')) { + new Assertion(obj, msg).to.have.property('length'); + var len = obj.length; + this.assert( + len > n + , 'expected #{this} to have a length above #{exp} but got #{act}' + , 'expected #{this} to not have a length above #{exp}' + , n + , len + ); + } else { + this.assert( + obj > n + , 'expected #{this} to be above ' + n + , 'expected #{this} to be at most ' + n + ); + } + } + + Assertion.addMethod('above', assertAbove); + Assertion.addMethod('gt', assertAbove); + Assertion.addMethod('greaterThan', assertAbove); + + /** + * ### .least(value) + * + * Asserts that the target is greater than or equal to `value`. + * + * expect(10).to.be.at.least(10); + * + * Can also be used in conjunction with `length` to + * assert a minimum length. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.of.at.least(2); + * expect([ 1, 2, 3 ]).to.have.length.of.at.least(3); + * + * @name least + * @alias gte + * @param {Number} value + * @param {String} message _optional_ + * @api public + */ + + function assertLeast (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + if (flag(this, 'doLength')) { + new Assertion(obj, msg).to.have.property('length'); + var len = obj.length; + this.assert( + len >= n + , 'expected #{this} to have a length at least #{exp} but got #{act}' + , 'expected #{this} to have a length below #{exp}' + , n + , len + ); + } else { + this.assert( + obj >= n + , 'expected #{this} to be at least ' + n + , 'expected #{this} to be below ' + n + ); + } + } + + Assertion.addMethod('least', assertLeast); + Assertion.addMethod('gte', assertLeast); + + /** + * ### .below(value) + * + * Asserts that the target is less than `value`. + * + * expect(5).to.be.below(10); + * + * Can also be used in conjunction with `length` to + * assert a maximum length. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.below(4); + * expect([ 1, 2, 3 ]).to.have.length.below(4); + * + * @name below + * @alias lt + * @alias lessThan + * @param {Number} value + * @param {String} message _optional_ + * @api public + */ + + function assertBelow (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + if (flag(this, 'doLength')) { + new Assertion(obj, msg).to.have.property('length'); + var len = obj.length; + this.assert( + len < n + , 'expected #{this} to have a length below #{exp} but got #{act}' + , 'expected #{this} to not have a length below #{exp}' + , n + , len + ); + } else { + this.assert( + obj < n + , 'expected #{this} to be below ' + n + , 'expected #{this} to be at least ' + n + ); + } + } + + Assertion.addMethod('below', assertBelow); + Assertion.addMethod('lt', assertBelow); + Assertion.addMethod('lessThan', assertBelow); + + /** + * ### .most(value) + * + * Asserts that the target is less than or equal to `value`. + * + * expect(5).to.be.at.most(5); + * + * Can also be used in conjunction with `length` to + * assert a maximum length. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.of.at.most(4); + * expect([ 1, 2, 3 ]).to.have.length.of.at.most(3); + * + * @name most + * @alias lte + * @param {Number} value + * @param {String} message _optional_ + * @api public + */ + + function assertMost (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + if (flag(this, 'doLength')) { + new Assertion(obj, msg).to.have.property('length'); + var len = obj.length; + this.assert( + len <= n + , 'expected #{this} to have a length at most #{exp} but got #{act}' + , 'expected #{this} to have a length above #{exp}' + , n + , len + ); + } else { + this.assert( + obj <= n + , 'expected #{this} to be at most ' + n + , 'expected #{this} to be above ' + n + ); + } + } + + Assertion.addMethod('most', assertMost); + Assertion.addMethod('lte', assertMost); + + /** + * ### .within(start, finish) + * + * Asserts that the target is within a range. + * + * expect(7).to.be.within(5,10); + * + * Can also be used in conjunction with `length` to + * assert a length range. The benefit being a + * more informative error message than if the length + * was supplied directly. + * + * expect('foo').to.have.length.within(2,4); + * expect([ 1, 2, 3 ]).to.have.length.within(2,4); + * + * @name within + * @param {Number} start lowerbound inclusive + * @param {Number} finish upperbound inclusive + * @param {String} message _optional_ + * @api public + */ + + Assertion.addMethod('within', function (start, finish, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , range = start + '..' + finish; + if (flag(this, 'doLength')) { + new Assertion(obj, msg).to.have.property('length'); + var len = obj.length; + this.assert( + len >= start && len <= finish + , 'expected #{this} to have a length within ' + range + , 'expected #{this} to not have a length within ' + range + ); + } else { + this.assert( + obj >= start && obj <= finish + , 'expected #{this} to be within ' + range + , 'expected #{this} to not be within ' + range + ); + } + }); + + /** + * ### .instanceof(constructor) + * + * Asserts that the target is an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , Chai = new Tea('chai'); + * + * expect(Chai).to.be.an.instanceof(Tea); + * expect([ 1, 2, 3 ]).to.be.instanceof(Array); + * + * @name instanceof + * @param {Constructor} constructor + * @param {String} message _optional_ + * @alias instanceOf + * @api public + */ + + function assertInstanceOf (constructor, msg) { + if (msg) flag(this, 'message', msg); + var name = _.getName(constructor); + this.assert( + flag(this, 'object') instanceof constructor + , 'expected #{this} to be an instance of ' + name + , 'expected #{this} to not be an instance of ' + name + ); + }; + + Assertion.addMethod('instanceof', assertInstanceOf); + Assertion.addMethod('instanceOf', assertInstanceOf); + + /** + * ### .property(name, [value]) + * + * Asserts that the target has a property `name`, optionally asserting that + * the value of that property is strictly equal to `value`. + * If the `deep` flag is set, you can use dot- and bracket-notation for deep + * references into objects and arrays. + * + * // simple referencing + * var obj = { foo: 'bar' }; + * expect(obj).to.have.property('foo'); + * expect(obj).to.have.property('foo', 'bar'); + * + * // deep referencing + * var deepObj = { + * green: { tea: 'matcha' } + * , teas: [ 'chai', 'matcha', { tea: 'konacha' } ] + * }; + + * expect(deepObj).to.have.deep.property('green.tea', 'matcha'); + * expect(deepObj).to.have.deep.property('teas[1]', 'matcha'); + * expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha'); + * + * You can also use an array as the starting point of a `deep.property` + * assertion, or traverse nested arrays. + * + * var arr = [ + * [ 'chai', 'matcha', 'konacha' ] + * , [ { tea: 'chai' } + * , { tea: 'matcha' } + * , { tea: 'konacha' } ] + * ]; + * + * expect(arr).to.have.deep.property('[0][1]', 'matcha'); + * expect(arr).to.have.deep.property('[1][2].tea', 'konacha'); + * + * Furthermore, `property` changes the subject of the assertion + * to be the value of that property from the original object. This + * permits for further chainable assertions on that property. + * + * expect(obj).to.have.property('foo') + * .that.is.a('string'); + * expect(deepObj).to.have.property('green') + * .that.is.an('object') + * .that.deep.equals({ tea: 'matcha' }); + * expect(deepObj).to.have.property('teas') + * .that.is.an('array') + * .with.deep.property('[2]') + * .that.deep.equals({ tea: 'konacha' }); + * + * @name property + * @alias deep.property + * @param {String} name + * @param {Mixed} value (optional) + * @param {String} message _optional_ + * @returns value of property for chaining + * @api public + */ + + Assertion.addMethod('property', function (name, val, msg) { + if (msg) flag(this, 'message', msg); + + var descriptor = flag(this, 'deep') ? 'deep property ' : 'property ' + , negate = flag(this, 'negate') + , obj = flag(this, 'object') + , value = flag(this, 'deep') + ? _.getPathValue(name, obj) + : obj[name]; + + if (negate && undefined !== val) { + if (undefined === value) { + msg = (msg != null) ? msg + ': ' : ''; + throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name)); + } + } else { + this.assert( + undefined !== value + , 'expected #{this} to have a ' + descriptor + _.inspect(name) + , 'expected #{this} to not have ' + descriptor + _.inspect(name)); + } + + if (undefined !== val) { + this.assert( + val === value + , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}' + , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}' + , val + , value + ); + } + + flag(this, 'object', value); + }); + + + /** + * ### .ownProperty(name) + * + * Asserts that the target has an own property `name`. + * + * expect('test').to.have.ownProperty('length'); + * + * @name ownProperty + * @alias haveOwnProperty + * @param {String} name + * @param {String} message _optional_ + * @api public + */ + + function assertOwnProperty (name, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + this.assert( + obj.hasOwnProperty(name) + , 'expected #{this} to have own property ' + _.inspect(name) + , 'expected #{this} to not have own property ' + _.inspect(name) + ); + } + + Assertion.addMethod('ownProperty', assertOwnProperty); + Assertion.addMethod('haveOwnProperty', assertOwnProperty); + + /** + * ### .length(value) + * + * Asserts that the target's `length` property has + * the expected value. + * + * expect([ 1, 2, 3]).to.have.length(3); + * expect('foobar').to.have.length(6); + * + * Can also be used as a chain precursor to a value + * comparison for the length property. + * + * expect('foo').to.have.length.above(2); + * expect([ 1, 2, 3 ]).to.have.length.above(2); + * expect('foo').to.have.length.below(4); + * expect([ 1, 2, 3 ]).to.have.length.below(4); + * expect('foo').to.have.length.within(2,4); + * expect([ 1, 2, 3 ]).to.have.length.within(2,4); + * + * @name length + * @alias lengthOf + * @param {Number} length + * @param {String} message _optional_ + * @api public + */ + + function assertLengthChain () { + flag(this, 'doLength', true); + } + + function assertLength (n, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + new Assertion(obj, msg).to.have.property('length'); + var len = obj.length; + + this.assert( + len == n + , 'expected #{this} to have a length of #{exp} but got #{act}' + , 'expected #{this} to not have a length of #{act}' + , n + , len + ); + } + + Assertion.addChainableMethod('length', assertLength, assertLengthChain); + Assertion.addMethod('lengthOf', assertLength, assertLengthChain); + + /** + * ### .match(regexp) + * + * Asserts that the target matches a regular expression. + * + * expect('foobar').to.match(/^foo/); + * + * @name match + * @param {RegExp} RegularExpression + * @param {String} message _optional_ + * @api public + */ + + Assertion.addMethod('match', function (re, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + this.assert( + re.exec(obj) + , 'expected #{this} to match ' + re + , 'expected #{this} not to match ' + re + ); + }); + + /** + * ### .string(string) + * + * Asserts that the string target contains another string. + * + * expect('foobar').to.have.string('bar'); + * + * @name string + * @param {String} string + * @param {String} message _optional_ + * @api public + */ + + Assertion.addMethod('string', function (str, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + new Assertion(obj, msg).is.a('string'); + + this.assert( + ~obj.indexOf(str) + , 'expected #{this} to contain ' + _.inspect(str) + , 'expected #{this} to not contain ' + _.inspect(str) + ); + }); + + + /** + * ### .keys(key1, [key2], [...]) + * + * Asserts that the target has exactly the given keys, or + * asserts the inclusion of some keys when using the + * `include` or `contain` modifiers. + * + * expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']); + * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar'); + * + * @name keys + * @alias key + * @param {String...|Array} keys + * @api public + */ + + function assertKeys (keys) { + var obj = flag(this, 'object') + , str + , ok = true; + + keys = keys instanceof Array + ? keys + : Array.prototype.slice.call(arguments); + + if (!keys.length) throw new Error('keys required'); + + var actual = Object.keys(obj) + , len = keys.length; + + // Inclusion + ok = keys.every(function(key){ + return ~actual.indexOf(key); + }); + + // Strict + if (!flag(this, 'negate') && !flag(this, 'contains')) { + ok = ok && keys.length == actual.length; + } + + // Key string + if (len > 1) { + keys = keys.map(function(key){ + return _.inspect(key); + }); + var last = keys.pop(); + str = keys.join(', ') + ', and ' + last; + } else { + str = _.inspect(keys[0]); + } + + // Form + str = (len > 1 ? 'keys ' : 'key ') + str; + + // Have / include + str = (flag(this, 'contains') ? 'contain ' : 'have ') + str; + + // Assertion + this.assert( + ok + , 'expected #{this} to ' + str + , 'expected #{this} to not ' + str + ); + } + + Assertion.addMethod('keys', assertKeys); + Assertion.addMethod('key', assertKeys); + + /** + * ### .throw(constructor) + * + * Asserts that the function target will throw a specific error, or specific type of error + * (as determined using `instanceof`), optionally with a RegExp or string inclusion test + * for the error's message. + * + * var err = new ReferenceError('This is a bad function.'); + * var fn = function () { throw err; } + * expect(fn).to.throw(ReferenceError); + * expect(fn).to.throw(Error); + * expect(fn).to.throw(/bad function/); + * expect(fn).to.not.throw('good function'); + * expect(fn).to.throw(ReferenceError, /bad function/); + * expect(fn).to.throw(err); + * expect(fn).to.not.throw(new RangeError('Out of range.')); + * + * Please note that when a throw expectation is negated, it will check each + * parameter independently, starting with error constructor type. The appropriate way + * to check for the existence of a type of error but for a message that does not match + * is to use `and`. + * + * expect(fn).to.throw(ReferenceError) + * .and.not.throw(/good function/); + * + * @name throw + * @alias throws + * @alias Throw + * @param {ErrorConstructor} constructor + * @param {String|RegExp} expected error message + * @param {String} message _optional_ + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @returns error for chaining (null if no error) + * @api public + */ + + function assertThrows (constructor, errMsg, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + new Assertion(obj, msg).is.a('function'); + + var thrown = false + , desiredError = null + , name = null + , thrownError = null; + + if (arguments.length === 0) { + errMsg = null; + constructor = null; + } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) { + errMsg = constructor; + constructor = null; + } else if (constructor && constructor instanceof Error) { + desiredError = constructor; + constructor = null; + errMsg = null; + } else if (typeof constructor === 'function') { + name = constructor.prototype.name || constructor.name; + if (name === 'Error' && constructor !== Error) { + name = (new constructor()).name; + } + } else { + constructor = null; + } + + try { + obj(); + } catch (err) { + // first, check desired error + if (desiredError) { + this.assert( + err === desiredError + , 'expected #{this} to throw #{exp} but #{act} was thrown' + , 'expected #{this} to not throw #{exp}' + , (desiredError instanceof Error ? desiredError.toString() : desiredError) + , (err instanceof Error ? err.toString() : err) + ); + + flag(this, 'object', err); + return this; + } + + // next, check constructor + if (constructor) { + this.assert( + err instanceof constructor + , 'expected #{this} to throw #{exp} but #{act} was thrown' + , 'expected #{this} to not throw #{exp} but #{act} was thrown' + , name + , (err instanceof Error ? err.toString() : err) + ); + + if (!errMsg) { + flag(this, 'object', err); + return this; + } + } + + // next, check message + var message = 'object' === _.type(err) && "message" in err + ? err.message + : '' + err; + + if ((message != null) && errMsg && errMsg instanceof RegExp) { + this.assert( + errMsg.exec(message) + , 'expected #{this} to throw error matching #{exp} but got #{act}' + , 'expected #{this} to throw error not matching #{exp}' + , errMsg + , message + ); + + flag(this, 'object', err); + return this; + } else if ((message != null) && errMsg && 'string' === typeof errMsg) { + this.assert( + ~message.indexOf(errMsg) + , 'expected #{this} to throw error including #{exp} but got #{act}' + , 'expected #{this} to throw error not including #{act}' + , errMsg + , message + ); + + flag(this, 'object', err); + return this; + } else { + thrown = true; + thrownError = err; + } + } + + var actuallyGot = '' + , expectedThrown = name !== null + ? name + : desiredError + ? '#{exp}' //_.inspect(desiredError) + : 'an error'; + + if (thrown) { + actuallyGot = ' but #{act} was thrown' + } + + this.assert( + thrown === true + , 'expected #{this} to throw ' + expectedThrown + actuallyGot + , 'expected #{this} to not throw ' + expectedThrown + actuallyGot + , (desiredError instanceof Error ? desiredError.toString() : desiredError) + , (thrownError instanceof Error ? thrownError.toString() : thrownError) + ); + + flag(this, 'object', thrownError); + }; + + Assertion.addMethod('throw', assertThrows); + Assertion.addMethod('throws', assertThrows); + Assertion.addMethod('Throw', assertThrows); + + /** + * ### .respondTo(method) + * + * Asserts that the object or class target will respond to a method. + * + * Klass.prototype.bar = function(){}; + * expect(Klass).to.respondTo('bar'); + * expect(obj).to.respondTo('bar'); + * + * To check if a constructor will respond to a static function, + * set the `itself` flag. + * + * Klass.baz = function(){}; + * expect(Klass).itself.to.respondTo('baz'); + * + * @name respondTo + * @param {String} method + * @param {String} message _optional_ + * @api public + */ + + Assertion.addMethod('respondTo', function (method, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object') + , itself = flag(this, 'itself') + , context = ('function' === _.type(obj) && !itself) + ? obj.prototype[method] + : obj[method]; + + this.assert( + 'function' === typeof context + , 'expected #{this} to respond to ' + _.inspect(method) + , 'expected #{this} to not respond to ' + _.inspect(method) + ); + }); + + /** + * ### .itself + * + * Sets the `itself` flag, later used by the `respondTo` assertion. + * + * function Foo() {} + * Foo.bar = function() {} + * Foo.prototype.baz = function() {} + * + * expect(Foo).itself.to.respondTo('bar'); + * expect(Foo).itself.not.to.respondTo('baz'); + * + * @name itself + * @api public + */ + + Assertion.addProperty('itself', function () { + flag(this, 'itself', true); + }); + + /** + * ### .satisfy(method) + * + * Asserts that the target passes a given truth test. + * + * expect(1).to.satisfy(function(num) { return num > 0; }); + * + * @name satisfy + * @param {Function} matcher + * @param {String} message _optional_ + * @api public + */ + + Assertion.addMethod('satisfy', function (matcher, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + this.assert( + matcher(obj) + , 'expected #{this} to satisfy ' + _.objDisplay(matcher) + , 'expected #{this} to not satisfy' + _.objDisplay(matcher) + , this.negate ? false : true + , matcher(obj) + ); + }); + + /** + * ### .closeTo(expected, delta) + * + * Asserts that the target is equal `expected`, to within a +/- `delta` range. + * + * expect(1.5).to.be.closeTo(1, 0.5); + * + * @name closeTo + * @param {Number} expected + * @param {Number} delta + * @param {String} message _optional_ + * @api public + */ + + Assertion.addMethod('closeTo', function (expected, delta, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + this.assert( + Math.abs(obj - expected) <= delta + , 'expected #{this} to be close to ' + expected + ' +/- ' + delta + , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta + ); + }); + + function isSubsetOf(subset, superset, cmp) { + return subset.every(function(elem) { + if (!cmp) return superset.indexOf(elem) !== -1; + + return superset.some(function(elem2) { + return cmp(elem, elem2); + }); + }) + } + + /** + * ### .members(set) + * + * Asserts that the target is a superset of `set`, + * or that the target and `set` have the same strictly-equal (===) members. + * Alternately, if the `deep` flag is set, set members are compared for deep + * equality. + * + * expect([1, 2, 3]).to.include.members([3, 2]); + * expect([1, 2, 3]).to.not.include.members([3, 2, 8]); + * + * expect([4, 2]).to.have.members([2, 4]); + * expect([5, 2]).to.not.have.members([5, 2, 1]); + * + * expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]); + * + * @name members + * @param {Array} set + * @param {String} message _optional_ + * @api public + */ + + Assertion.addMethod('members', function (subset, msg) { + if (msg) flag(this, 'message', msg); + var obj = flag(this, 'object'); + + new Assertion(obj).to.be.an('array'); + new Assertion(subset).to.be.an('array'); + + var cmp = flag(this, 'deep') ? _.eql : undefined; + + if (flag(this, 'contains')) { + return this.assert( + isSubsetOf(subset, obj, cmp) + , 'expected #{this} to be a superset of #{act}' + , 'expected #{this} to not be a superset of #{act}' + , obj + , subset + ); + } + + this.assert( + isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp) + , 'expected #{this} to have the same members as #{act}' + , 'expected #{this} to not have the same members as #{act}' + , obj + , subset + ); + }); +}; + +},{}],14:[function(require,module,exports){ +/*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ + + +module.exports = function (chai, util) { + + /*! + * Chai dependencies. + */ + + var Assertion = chai.Assertion + , flag = util.flag; + + /*! + * Module export. + */ + + /** + * ### assert(expression, message) + * + * Write your own test expressions. + * + * assert('foo' !== 'bar', 'foo is not bar'); + * assert(Array.isArray([]), 'empty arrays are arrays'); + * + * @param {Mixed} expression to test for truthiness + * @param {String} message to display on error + * @name assert + * @api public + */ + + var assert = chai.assert = function (express, errmsg) { + var test = new Assertion(null, null, chai.assert); + test.assert( + express + , errmsg + , '[ negation message unavailable ]' + ); + }; + + /** + * ### .fail(actual, expected, [message], [operator]) + * + * Throw a failure. Node.js `assert` module-compatible. + * + * @name fail + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @param {String} operator + * @api public + */ + + assert.fail = function (actual, expected, message, operator) { + message = message || 'assert.fail()'; + throw new chai.AssertionError(message, { + actual: actual + , expected: expected + , operator: operator + }, assert.fail); + }; + + /** + * ### .ok(object, [message]) + * + * Asserts that `object` is truthy. + * + * assert.ok('everything', 'everything is ok'); + * assert.ok(false, 'this will fail'); + * + * @name ok + * @param {Mixed} object to test + * @param {String} message + * @api public + */ + + assert.ok = function (val, msg) { + new Assertion(val, msg).is.ok; + }; + + /** + * ### .notOk(object, [message]) + * + * Asserts that `object` is falsy. + * + * assert.notOk('everything', 'this will fail'); + * assert.notOk(false, 'this will pass'); + * + * @name notOk + * @param {Mixed} object to test + * @param {String} message + * @api public + */ + + assert.notOk = function (val, msg) { + new Assertion(val, msg).is.not.ok; + }; + + /** + * ### .equal(actual, expected, [message]) + * + * Asserts non-strict equality (`==`) of `actual` and `expected`. + * + * assert.equal(3, '3', '== coerces values to strings'); + * + * @name equal + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.equal = function (act, exp, msg) { + var test = new Assertion(act, msg, assert.equal); + + test.assert( + exp == flag(test, 'object') + , 'expected #{this} to equal #{exp}' + , 'expected #{this} to not equal #{act}' + , exp + , act + ); + }; + + /** + * ### .notEqual(actual, expected, [message]) + * + * Asserts non-strict inequality (`!=`) of `actual` and `expected`. + * + * assert.notEqual(3, 4, 'these numbers are not equal'); + * + * @name notEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.notEqual = function (act, exp, msg) { + var test = new Assertion(act, msg, assert.notEqual); + + test.assert( + exp != flag(test, 'object') + , 'expected #{this} to not equal #{exp}' + , 'expected #{this} to equal #{act}' + , exp + , act + ); + }; + + /** + * ### .strictEqual(actual, expected, [message]) + * + * Asserts strict equality (`===`) of `actual` and `expected`. + * + * assert.strictEqual(true, true, 'these booleans are strictly equal'); + * + * @name strictEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.strictEqual = function (act, exp, msg) { + new Assertion(act, msg).to.equal(exp); + }; + + /** + * ### .notStrictEqual(actual, expected, [message]) + * + * Asserts strict inequality (`!==`) of `actual` and `expected`. + * + * assert.notStrictEqual(3, '3', 'no coercion for strict equality'); + * + * @name notStrictEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.notStrictEqual = function (act, exp, msg) { + new Assertion(act, msg).to.not.equal(exp); + }; + + /** + * ### .deepEqual(actual, expected, [message]) + * + * Asserts that `actual` is deeply equal to `expected`. + * + * assert.deepEqual({ tea: 'green' }, { tea: 'green' }); + * + * @name deepEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.deepEqual = function (act, exp, msg) { + new Assertion(act, msg).to.eql(exp); + }; + + /** + * ### .notDeepEqual(actual, expected, [message]) + * + * Assert that `actual` is not deeply equal to `expected`. + * + * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' }); + * + * @name notDeepEqual + * @param {Mixed} actual + * @param {Mixed} expected + * @param {String} message + * @api public + */ + + assert.notDeepEqual = function (act, exp, msg) { + new Assertion(act, msg).to.not.eql(exp); + }; + + /** + * ### .isTrue(value, [message]) + * + * Asserts that `value` is true. + * + * var teaServed = true; + * assert.isTrue(teaServed, 'the tea has been served'); + * + * @name isTrue + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isTrue = function (val, msg) { + new Assertion(val, msg).is['true']; + }; + + /** + * ### .isFalse(value, [message]) + * + * Asserts that `value` is false. + * + * var teaServed = false; + * assert.isFalse(teaServed, 'no tea yet? hmm...'); + * + * @name isFalse + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isFalse = function (val, msg) { + new Assertion(val, msg).is['false']; + }; + + /** + * ### .isNull(value, [message]) + * + * Asserts that `value` is null. + * + * assert.isNull(err, 'there was no error'); + * + * @name isNull + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNull = function (val, msg) { + new Assertion(val, msg).to.equal(null); + }; + + /** + * ### .isNotNull(value, [message]) + * + * Asserts that `value` is not null. + * + * var tea = 'tasty chai'; + * assert.isNotNull(tea, 'great, time for tea!'); + * + * @name isNotNull + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotNull = function (val, msg) { + new Assertion(val, msg).to.not.equal(null); + }; + + /** + * ### .isUndefined(value, [message]) + * + * Asserts that `value` is `undefined`. + * + * var tea; + * assert.isUndefined(tea, 'no tea defined'); + * + * @name isUndefined + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isUndefined = function (val, msg) { + new Assertion(val, msg).to.equal(undefined); + }; + + /** + * ### .isDefined(value, [message]) + * + * Asserts that `value` is not `undefined`. + * + * var tea = 'cup of chai'; + * assert.isDefined(tea, 'tea has been defined'); + * + * @name isDefined + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isDefined = function (val, msg) { + new Assertion(val, msg).to.not.equal(undefined); + }; + + /** + * ### .isFunction(value, [message]) + * + * Asserts that `value` is a function. + * + * function serveTea() { return 'cup of tea'; }; + * assert.isFunction(serveTea, 'great, we can have tea now'); + * + * @name isFunction + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isFunction = function (val, msg) { + new Assertion(val, msg).to.be.a('function'); + }; + + /** + * ### .isNotFunction(value, [message]) + * + * Asserts that `value` is _not_ a function. + * + * var serveTea = [ 'heat', 'pour', 'sip' ]; + * assert.isNotFunction(serveTea, 'great, we have listed the steps'); + * + * @name isNotFunction + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotFunction = function (val, msg) { + new Assertion(val, msg).to.not.be.a('function'); + }; + + /** + * ### .isObject(value, [message]) + * + * Asserts that `value` is an object (as revealed by + * `Object.prototype.toString`). + * + * var selection = { name: 'Chai', serve: 'with spices' }; + * assert.isObject(selection, 'tea selection is an object'); + * + * @name isObject + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isObject = function (val, msg) { + new Assertion(val, msg).to.be.a('object'); + }; + + /** + * ### .isNotObject(value, [message]) + * + * Asserts that `value` is _not_ an object. + * + * var selection = 'chai' + * assert.isNotObject(selection, 'tea selection is not an object'); + * assert.isNotObject(null, 'null is not an object'); + * + * @name isNotObject + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotObject = function (val, msg) { + new Assertion(val, msg).to.not.be.a('object'); + }; + + /** + * ### .isArray(value, [message]) + * + * Asserts that `value` is an array. + * + * var menu = [ 'green', 'chai', 'oolong' ]; + * assert.isArray(menu, 'what kind of tea do we want?'); + * + * @name isArray + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isArray = function (val, msg) { + new Assertion(val, msg).to.be.an('array'); + }; + + /** + * ### .isNotArray(value, [message]) + * + * Asserts that `value` is _not_ an array. + * + * var menu = 'green|chai|oolong'; + * assert.isNotArray(menu, 'what kind of tea do we want?'); + * + * @name isNotArray + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotArray = function (val, msg) { + new Assertion(val, msg).to.not.be.an('array'); + }; + + /** + * ### .isString(value, [message]) + * + * Asserts that `value` is a string. + * + * var teaOrder = 'chai'; + * assert.isString(teaOrder, 'order placed'); + * + * @name isString + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isString = function (val, msg) { + new Assertion(val, msg).to.be.a('string'); + }; + + /** + * ### .isNotString(value, [message]) + * + * Asserts that `value` is _not_ a string. + * + * var teaOrder = 4; + * assert.isNotString(teaOrder, 'order placed'); + * + * @name isNotString + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotString = function (val, msg) { + new Assertion(val, msg).to.not.be.a('string'); + }; + + /** + * ### .isNumber(value, [message]) + * + * Asserts that `value` is a number. + * + * var cups = 2; + * assert.isNumber(cups, 'how many cups'); + * + * @name isNumber + * @param {Number} value + * @param {String} message + * @api public + */ + + assert.isNumber = function (val, msg) { + new Assertion(val, msg).to.be.a('number'); + }; + + /** + * ### .isNotNumber(value, [message]) + * + * Asserts that `value` is _not_ a number. + * + * var cups = '2 cups please'; + * assert.isNotNumber(cups, 'how many cups'); + * + * @name isNotNumber + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotNumber = function (val, msg) { + new Assertion(val, msg).to.not.be.a('number'); + }; + + /** + * ### .isBoolean(value, [message]) + * + * Asserts that `value` is a boolean. + * + * var teaReady = true + * , teaServed = false; + * + * assert.isBoolean(teaReady, 'is the tea ready'); + * assert.isBoolean(teaServed, 'has tea been served'); + * + * @name isBoolean + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isBoolean = function (val, msg) { + new Assertion(val, msg).to.be.a('boolean'); + }; + + /** + * ### .isNotBoolean(value, [message]) + * + * Asserts that `value` is _not_ a boolean. + * + * var teaReady = 'yep' + * , teaServed = 'nope'; + * + * assert.isNotBoolean(teaReady, 'is the tea ready'); + * assert.isNotBoolean(teaServed, 'has tea been served'); + * + * @name isNotBoolean + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.isNotBoolean = function (val, msg) { + new Assertion(val, msg).to.not.be.a('boolean'); + }; + + /** + * ### .typeOf(value, name, [message]) + * + * Asserts that `value`'s type is `name`, as determined by + * `Object.prototype.toString`. + * + * assert.typeOf({ tea: 'chai' }, 'object', 'we have an object'); + * assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array'); + * assert.typeOf('tea', 'string', 'we have a string'); + * assert.typeOf(/tea/, 'regexp', 'we have a regular expression'); + * assert.typeOf(null, 'null', 'we have a null'); + * assert.typeOf(undefined, 'undefined', 'we have an undefined'); + * + * @name typeOf + * @param {Mixed} value + * @param {String} name + * @param {String} message + * @api public + */ + + assert.typeOf = function (val, type, msg) { + new Assertion(val, msg).to.be.a(type); + }; + + /** + * ### .notTypeOf(value, name, [message]) + * + * Asserts that `value`'s type is _not_ `name`, as determined by + * `Object.prototype.toString`. + * + * assert.notTypeOf('tea', 'number', 'strings are not numbers'); + * + * @name notTypeOf + * @param {Mixed} value + * @param {String} typeof name + * @param {String} message + * @api public + */ + + assert.notTypeOf = function (val, type, msg) { + new Assertion(val, msg).to.not.be.a(type); + }; + + /** + * ### .instanceOf(object, constructor, [message]) + * + * Asserts that `value` is an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , chai = new Tea('chai'); + * + * assert.instanceOf(chai, Tea, 'chai is an instance of tea'); + * + * @name instanceOf + * @param {Object} object + * @param {Constructor} constructor + * @param {String} message + * @api public + */ + + assert.instanceOf = function (val, type, msg) { + new Assertion(val, msg).to.be.instanceOf(type); + }; + + /** + * ### .notInstanceOf(object, constructor, [message]) + * + * Asserts `value` is not an instance of `constructor`. + * + * var Tea = function (name) { this.name = name; } + * , chai = new String('chai'); + * + * assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea'); + * + * @name notInstanceOf + * @param {Object} object + * @param {Constructor} constructor + * @param {String} message + * @api public + */ + + assert.notInstanceOf = function (val, type, msg) { + new Assertion(val, msg).to.not.be.instanceOf(type); + }; + + /** + * ### .include(haystack, needle, [message]) + * + * Asserts that `haystack` includes `needle`. Works + * for strings and arrays. + * + * assert.include('foobar', 'bar', 'foobar contains string "bar"'); + * assert.include([ 1, 2, 3 ], 3, 'array contains value'); + * + * @name include + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @api public + */ + + assert.include = function (exp, inc, msg) { + new Assertion(exp, msg, assert.include).include(inc); + }; + + /** + * ### .notInclude(haystack, needle, [message]) + * + * Asserts that `haystack` does not include `needle`. Works + * for strings and arrays. + *i + * assert.notInclude('foobar', 'baz', 'string not include substring'); + * assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value'); + * + * @name notInclude + * @param {Array|String} haystack + * @param {Mixed} needle + * @param {String} message + * @api public + */ + + assert.notInclude = function (exp, inc, msg) { + new Assertion(exp, msg, assert.notInclude).not.include(inc); + }; + + /** + * ### .match(value, regexp, [message]) + * + * Asserts that `value` matches the regular expression `regexp`. + * + * assert.match('foobar', /^foo/, 'regexp matches'); + * + * @name match + * @param {Mixed} value + * @param {RegExp} regexp + * @param {String} message + * @api public + */ + + assert.match = function (exp, re, msg) { + new Assertion(exp, msg).to.match(re); + }; + + /** + * ### .notMatch(value, regexp, [message]) + * + * Asserts that `value` does not match the regular expression `regexp`. + * + * assert.notMatch('foobar', /^foo/, 'regexp does not match'); + * + * @name notMatch + * @param {Mixed} value + * @param {RegExp} regexp + * @param {String} message + * @api public + */ + + assert.notMatch = function (exp, re, msg) { + new Assertion(exp, msg).to.not.match(re); + }; + + /** + * ### .property(object, property, [message]) + * + * Asserts that `object` has a property named by `property`. + * + * assert.property({ tea: { green: 'matcha' }}, 'tea'); + * + * @name property + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ + + assert.property = function (obj, prop, msg) { + new Assertion(obj, msg).to.have.property(prop); + }; + + /** + * ### .notProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a property named by `property`. + * + * assert.notProperty({ tea: { green: 'matcha' }}, 'coffee'); + * + * @name notProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ + + assert.notProperty = function (obj, prop, msg) { + new Assertion(obj, msg).to.not.have.property(prop); + }; + + /** + * ### .deepProperty(object, property, [message]) + * + * Asserts that `object` has a property named by `property`, which can be a + * string using dot- and bracket-notation for deep reference. + * + * assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green'); + * + * @name deepProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ + + assert.deepProperty = function (obj, prop, msg) { + new Assertion(obj, msg).to.have.deep.property(prop); + }; + + /** + * ### .notDeepProperty(object, property, [message]) + * + * Asserts that `object` does _not_ have a property named by `property`, which + * can be a string using dot- and bracket-notation for deep reference. + * + * assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong'); + * + * @name notDeepProperty + * @param {Object} object + * @param {String} property + * @param {String} message + * @api public + */ + + assert.notDeepProperty = function (obj, prop, msg) { + new Assertion(obj, msg).to.not.have.deep.property(prop); + }; + + /** + * ### .propertyVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property` with value given + * by `value`. + * + * assert.propertyVal({ tea: 'is good' }, 'tea', 'is good'); + * + * @name propertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.propertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.have.property(prop, val); + }; + + /** + * ### .propertyNotVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property`, but with a value + * different from that given by `value`. + * + * assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad'); + * + * @name propertyNotVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.propertyNotVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.not.have.property(prop, val); + }; + + /** + * ### .deepPropertyVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property` with value given + * by `value`. `property` can use dot- and bracket-notation for deep + * reference. + * + * assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha'); + * + * @name deepPropertyVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.deepPropertyVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.have.deep.property(prop, val); + }; + + /** + * ### .deepPropertyNotVal(object, property, value, [message]) + * + * Asserts that `object` has a property named by `property`, but with a value + * different from that given by `value`. `property` can use dot- and + * bracket-notation for deep reference. + * + * assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha'); + * + * @name deepPropertyNotVal + * @param {Object} object + * @param {String} property + * @param {Mixed} value + * @param {String} message + * @api public + */ + + assert.deepPropertyNotVal = function (obj, prop, val, msg) { + new Assertion(obj, msg).to.not.have.deep.property(prop, val); + }; + + /** + * ### .lengthOf(object, length, [message]) + * + * Asserts that `object` has a `length` property with the expected value. + * + * assert.lengthOf([1,2,3], 3, 'array has length of 3'); + * assert.lengthOf('foobar', 5, 'string has length of 6'); + * + * @name lengthOf + * @param {Mixed} object + * @param {Number} length + * @param {String} message + * @api public + */ + + assert.lengthOf = function (exp, len, msg) { + new Assertion(exp, msg).to.have.length(len); + }; + + /** + * ### .throws(function, [constructor/string/regexp], [string/regexp], [message]) + * + * Asserts that `function` will throw an error that is an instance of + * `constructor`, or alternately that it will throw an error with message + * matching `regexp`. + * + * assert.throw(fn, 'function throws a reference error'); + * assert.throw(fn, /function throws a reference error/); + * assert.throw(fn, ReferenceError); + * assert.throw(fn, ReferenceError, 'function throws a reference error'); + * assert.throw(fn, ReferenceError, /function throws a reference error/); + * + * @name throws + * @alias throw + * @alias Throw + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @api public + */ + + assert.Throw = function (fn, errt, errs, msg) { + if ('string' === typeof errt || errt instanceof RegExp) { + errs = errt; + errt = null; + } + + var assertErr = new Assertion(fn, msg).to.Throw(errt, errs); + return flag(assertErr, 'object'); + }; + + /** + * ### .doesNotThrow(function, [constructor/regexp], [message]) + * + * Asserts that `function` will _not_ throw an error that is an instance of + * `constructor`, or alternately that it will not throw an error with message + * matching `regexp`. + * + * assert.doesNotThrow(fn, Error, 'function does not throw'); + * + * @name doesNotThrow + * @param {Function} function + * @param {ErrorConstructor} constructor + * @param {RegExp} regexp + * @param {String} message + * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types + * @api public + */ + + assert.doesNotThrow = function (fn, type, msg) { + if ('string' === typeof type) { + msg = type; + type = null; + } + + new Assertion(fn, msg).to.not.Throw(type); + }; + + /** + * ### .operator(val1, operator, val2, [message]) + * + * Compares two values using `operator`. + * + * assert.operator(1, '<', 2, 'everything is ok'); + * assert.operator(1, '>', 2, 'this will fail'); + * + * @name operator + * @param {Mixed} val1 + * @param {String} operator + * @param {Mixed} val2 + * @param {String} message + * @api public + */ + + assert.operator = function (val, operator, val2, msg) { + if (!~['==', '===', '>', '>=', '<', '<=', '!=', '!=='].indexOf(operator)) { + throw new Error('Invalid operator "' + operator + '"'); + } + var test = new Assertion(eval(val + operator + val2), msg); + test.assert( + true === flag(test, 'object') + , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2) + , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) ); + }; + + /** + * ### .closeTo(actual, expected, delta, [message]) + * + * Asserts that the target is equal `expected`, to within a +/- `delta` range. + * + * assert.closeTo(1.5, 1, 0.5, 'numbers are close'); + * + * @name closeTo + * @param {Number} actual + * @param {Number} expected + * @param {Number} delta + * @param {String} message + * @api public + */ + + assert.closeTo = function (act, exp, delta, msg) { + new Assertion(act, msg).to.be.closeTo(exp, delta); + }; + + /** + * ### .sameMembers(set1, set2, [message]) + * + * Asserts that `set1` and `set2` have the same members. + * Order is not taken into account. + * + * assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members'); + * + * @name sameMembers + * @param {Array} superset + * @param {Array} subset + * @param {String} message + * @api public + */ + + assert.sameMembers = function (set1, set2, msg) { + new Assertion(set1, msg).to.have.same.members(set2); + } + + /** + * ### .includeMembers(superset, subset, [message]) + * + * Asserts that `subset` is included in `superset`. + * Order is not taken into account. + * + * assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members'); + * + * @name includeMembers + * @param {Array} superset + * @param {Array} subset + * @param {String} message + * @api public + */ + + assert.includeMembers = function (superset, subset, msg) { + new Assertion(superset, msg).to.include.members(subset); + } + + /*! + * Undocumented / untested + */ + + assert.ifError = function (val, msg) { + new Assertion(val, msg).to.not.be.ok; + }; + + /*! + * Aliases. + */ + + (function alias(name, as){ + assert[as] = assert[name]; + return alias; + }) + ('Throw', 'throw') + ('Throw', 'throws'); +}; + +},{}],15:[function(require,module,exports){ +/*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ + +module.exports = function (chai, util) { + chai.expect = function (val, message) { + return new chai.Assertion(val, message); + }; +}; + + +},{}],16:[function(require,module,exports){ +/*! + * chai + * Copyright(c) 2011-2014 Jake Luer + * MIT Licensed + */ + +module.exports = function (chai, util) { + var Assertion = chai.Assertion; + + function loadShould () { + // explicitly define this method as function as to have it's name to include as `ssfi` + function shouldGetter() { + if (this instanceof String || this instanceof Number) { + return new Assertion(this.constructor(this), null, shouldGetter); + } else if (this instanceof Boolean) { + return new Assertion(this == true, null, shouldGetter); + } + return new Assertion(this, null, shouldGetter); + } + function shouldSetter(value) { + // See https://github.com/chaijs/chai/issues/86: this makes + // `whatever.should = someValue` actually set `someValue`, which is + // especially useful for `global.should = require('chai').should()`. + // + // Note that we have to use [[DefineProperty]] instead of [[Put]] + // since otherwise we would trigger this very setter! + Object.defineProperty(this, 'should', { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } + // modify Object.prototype to have `should` + Object.defineProperty(Object.prototype, 'should', { + set: shouldSetter + , get: shouldGetter + , configurable: true + }); + + var should = {}; + + should.equal = function (val1, val2, msg) { + new Assertion(val1, msg).to.equal(val2); + }; + + should.Throw = function (fn, errt, errs, msg) { + new Assertion(fn, msg).to.Throw(errt, errs); + }; + + should.exist = function (val, msg) { + new Assertion(val, msg).to.exist; + } + + // negation + should.not = {} + + should.not.equal = function (val1, val2, msg) { + new Assertion(val1, msg).to.not.equal(val2); + }; + + should.not.Throw = function (fn, errt, errs, msg) { + new Assertion(fn, msg).to.not.Throw(errt, errs); + }; + + should.not.exist = function (val, msg) { + new Assertion(val, msg).to.not.exist; + } + + should['throw'] = should['Throw']; + should.not['throw'] = should.not['Throw']; + + return should; + }; + + chai.should = loadShould; + chai.Should = loadShould; +}; + +},{}],17:[function(require,module,exports){ +/*! + * Chai - addChainingMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/*! + * Module dependencies + */ + +var transferFlags = require('./transferFlags'); +var flag = require('./flag'); +var config = require('../config'); + +/*! + * Module variables + */ + +// Check whether `__proto__` is supported +var hasProtoSupport = '__proto__' in Object; + +// Without `__proto__` support, this module will need to add properties to a function. +// However, some Function.prototype methods cannot be overwritten, +// and there seems no easy cross-platform way to detect them (@see chaijs/chai/issues/69). +var excludeNames = /^(?:length|name|arguments|caller)$/; + +// Cache `Function` properties +var call = Function.prototype.call, + apply = Function.prototype.apply; + +/** + * ### addChainableMethod (ctx, name, method, chainingBehavior) + * + * Adds a method to an object, such that the method can also be chained. + * + * utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.equal(str); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addChainableMethod('foo', fn, chainingBehavior); + * + * The result can then be used as both a method assertion, executing both `method` and + * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`. + * + * expect(fooStr).to.be.foo('bar'); + * expect(fooStr).to.be.foo.equal('foo'); + * + * @param {Object} ctx object to which the method is added + * @param {String} name of method to add + * @param {Function} method function to be used for `name`, when called + * @param {Function} chainingBehavior function to be called every time the property is accessed + * @name addChainableMethod + * @api public + */ + +module.exports = function (ctx, name, method, chainingBehavior) { + if (typeof chainingBehavior !== 'function') { + chainingBehavior = function () { }; + } + + var chainableBehavior = { + method: method + , chainingBehavior: chainingBehavior + }; + + // save the methods so we can overwrite them later, if we need to. + if (!ctx.__methods) { + ctx.__methods = {}; + } + ctx.__methods[name] = chainableBehavior; + + Object.defineProperty(ctx, name, + { get: function () { + chainableBehavior.chainingBehavior.call(this); + + var assert = function assert() { + var old_ssfi = flag(this, 'ssfi'); + if (old_ssfi && config.includeStack === false) + flag(this, 'ssfi', assert); + var result = chainableBehavior.method.apply(this, arguments); + return result === undefined ? this : result; + }; + + // Use `__proto__` if available + if (hasProtoSupport) { + // Inherit all properties from the object by replacing the `Function` prototype + var prototype = assert.__proto__ = Object.create(this); + // Restore the `call` and `apply` methods from `Function` + prototype.call = call; + prototype.apply = apply; + } + // Otherwise, redefine all properties (slow!) + else { + var asserterNames = Object.getOwnPropertyNames(ctx); + asserterNames.forEach(function (asserterName) { + if (!excludeNames.test(asserterName)) { + var pd = Object.getOwnPropertyDescriptor(ctx, asserterName); + Object.defineProperty(assert, asserterName, pd); + } + }); + } + + transferFlags(this, assert); + return assert; + } + , configurable: true + }); +}; + +},{"../config":12,"./flag":20,"./transferFlags":34}],18:[function(require,module,exports){ +/*! + * Chai - addMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +var config = require('../config'); + +/** + * ### .addMethod (ctx, name, method) + * + * Adds a method to the prototype of an object. + * + * utils.addMethod(chai.Assertion.prototype, 'foo', function (str) { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.equal(str); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addMethod('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(fooStr).to.be.foo('bar'); + * + * @param {Object} ctx object to which the method is added + * @param {String} name of method to add + * @param {Function} method function to be used for name + * @name addMethod + * @api public + */ +var flag = require('./flag'); + +module.exports = function (ctx, name, method) { + ctx[name] = function () { + var old_ssfi = flag(this, 'ssfi'); + if (old_ssfi && config.includeStack === false) + flag(this, 'ssfi', ctx[name]); + var result = method.apply(this, arguments); + return result === undefined ? this : result; + }; +}; + +},{"../config":12,"./flag":20}],19:[function(require,module,exports){ +/*! + * Chai - addProperty utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### addProperty (ctx, name, getter) + * + * Adds a property to the prototype of an object. + * + * utils.addProperty(chai.Assertion.prototype, 'foo', function () { + * var obj = utils.flag(this, 'object'); + * new chai.Assertion(obj).to.be.instanceof(Foo); + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.addProperty('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.be.foo; + * + * @param {Object} ctx object to which the property is added + * @param {String} name of property to add + * @param {Function} getter function to be used for name + * @name addProperty + * @api public + */ + +module.exports = function (ctx, name, getter) { + Object.defineProperty(ctx, name, + { get: function () { + var result = getter.call(this); + return result === undefined ? this : result; + } + , configurable: true + }); +}; + +},{}],20:[function(require,module,exports){ +/*! + * Chai - flag utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### flag(object ,key, [value]) + * + * Get or set a flag value on an object. If a + * value is provided it will be set, else it will + * return the currently set value or `undefined` if + * the value is not set. + * + * utils.flag(this, 'foo', 'bar'); // setter + * utils.flag(this, 'foo'); // getter, returns `bar` + * + * @param {Object} object (constructed Assertion + * @param {String} key + * @param {Mixed} value (optional) + * @name flag + * @api private + */ + +module.exports = function (obj, key, value) { + var flags = obj.__flags || (obj.__flags = Object.create(null)); + if (arguments.length === 3) { + flags[key] = value; + } else { + return flags[key]; + } +}; + +},{}],21:[function(require,module,exports){ +/*! + * Chai - getActual utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * # getActual(object, [actual]) + * + * Returns the `actual` value for an Assertion + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + */ + +module.exports = function (obj, args) { + return args.length > 4 ? args[4] : obj._obj; +}; + +},{}],22:[function(require,module,exports){ +/*! + * Chai - getEnumerableProperties utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### .getEnumerableProperties(object) + * + * This allows the retrieval of enumerable property names of an object, + * inherited or not. + * + * @param {Object} object + * @returns {Array} + * @name getEnumerableProperties + * @api public + */ + +module.exports = function getEnumerableProperties(object) { + var result = []; + for (var name in object) { + result.push(name); + } + return result; +}; + +},{}],23:[function(require,module,exports){ +/*! + * Chai - message composition utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/*! + * Module dependancies + */ + +var flag = require('./flag') + , getActual = require('./getActual') + , inspect = require('./inspect') + , objDisplay = require('./objDisplay'); + +/** + * ### .getMessage(object, message, negateMessage) + * + * Construct the error message based on flags + * and template tags. Template tags will return + * a stringified inspection of the object referenced. + * + * Message template tags: + * - `#{this}` current asserted object + * - `#{act}` actual value + * - `#{exp}` expected value + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + * @name getMessage + * @api public + */ + +module.exports = function (obj, args) { + var negate = flag(obj, 'negate') + , val = flag(obj, 'object') + , expected = args[3] + , actual = getActual(obj, args) + , msg = negate ? args[2] : args[1] + , flagMsg = flag(obj, 'message'); + + msg = msg || ''; + msg = msg + .replace(/#{this}/g, objDisplay(val)) + .replace(/#{act}/g, objDisplay(actual)) + .replace(/#{exp}/g, objDisplay(expected)); + + return flagMsg ? flagMsg + ': ' + msg : msg; +}; + +},{"./flag":20,"./getActual":21,"./inspect":28,"./objDisplay":29}],24:[function(require,module,exports){ +/*! + * Chai - getName utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * # getName(func) + * + * Gets the name of a function, in a cross-browser way. + * + * @param {Function} a function (usually a constructor) + */ + +module.exports = function (func) { + if (func.name) return func.name; + + var match = /^\s?function ([^(]*)\(/.exec(func); + return match && match[1] ? match[1] : ""; +}; + +},{}],25:[function(require,module,exports){ +/*! + * Chai - getPathValue utility + * Copyright(c) 2012-2014 Jake Luer + * @see https://github.com/logicalparadox/filtr + * MIT Licensed + */ + +/** + * ### .getPathValue(path, object) + * + * This allows the retrieval of values in an + * object given a string path. + * + * var obj = { + * prop1: { + * arr: ['a', 'b', 'c'] + * , str: 'Hello' + * } + * , prop2: { + * arr: [ { nested: 'Universe' } ] + * , str: 'Hello again!' + * } + * } + * + * The following would be the results. + * + * getPathValue('prop1.str', obj); // Hello + * getPathValue('prop1.att[2]', obj); // b + * getPathValue('prop2.arr[0].nested', obj); // Universe + * + * @param {String} path + * @param {Object} object + * @returns {Object} value or `undefined` + * @name getPathValue + * @api public + */ + +var getPathValue = module.exports = function (path, obj) { + var parsed = parsePath(path); + return _getPathValue(parsed, obj); +}; + +/*! + * ## parsePath(path) + * + * Helper function used to parse string object + * paths. Use in conjunction with `_getPathValue`. + * + * var parsed = parsePath('myobject.property.subprop'); + * + * ### Paths: + * + * * Can be as near infinitely deep and nested + * * Arrays are also valid using the formal `myobject.document[3].property`. + * + * @param {String} path + * @returns {Object} parsed + * @api private + */ + +function parsePath (path) { + var str = path.replace(/\[/g, '.[') + , parts = str.match(/(\\\.|[^.]+?)+/g); + return parts.map(function (value) { + var re = /\[(\d+)\]$/ + , mArr = re.exec(value) + if (mArr) return { i: parseFloat(mArr[1]) }; + else return { p: value }; + }); +}; + +/*! + * ## _getPathValue(parsed, obj) + * + * Helper companion function for `.parsePath` that returns + * the value located at the parsed address. + * + * var value = getPathValue(parsed, obj); + * + * @param {Object} parsed definition from `parsePath`. + * @param {Object} object to search against + * @returns {Object|Undefined} value + * @api private + */ + +function _getPathValue (parsed, obj) { + var tmp = obj + , res; + for (var i = 0, l = parsed.length; i < l; i++) { + var part = parsed[i]; + if (tmp) { + if ('undefined' !== typeof part.p) + tmp = tmp[part.p]; + else if ('undefined' !== typeof part.i) + tmp = tmp[part.i]; + if (i == (l - 1)) res = tmp; + } else { + res = undefined; + } + } + return res; +}; + +},{}],26:[function(require,module,exports){ +/*! + * Chai - getProperties utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### .getProperties(object) + * + * This allows the retrieval of property names of an object, enumerable or not, + * inherited or not. + * + * @param {Object} object + * @returns {Array} + * @name getProperties + * @api public + */ + +module.exports = function getProperties(object) { + var result = Object.getOwnPropertyNames(subject); + + function addProperty(property) { + if (result.indexOf(property) === -1) { + result.push(property); + } + } + + var proto = Object.getPrototypeOf(subject); + while (proto !== null) { + Object.getOwnPropertyNames(proto).forEach(addProperty); + proto = Object.getPrototypeOf(proto); + } + + return result; +}; + +},{}],27:[function(require,module,exports){ +/*! + * chai + * Copyright(c) 2011 Jake Luer + * MIT Licensed + */ + +/*! + * Main exports + */ + +var exports = module.exports = {}; + +/*! + * test utility + */ + +exports.test = require('./test'); + +/*! + * type utility + */ + +exports.type = require('./type'); + +/*! + * message utility + */ + +exports.getMessage = require('./getMessage'); + +/*! + * actual utility + */ + +exports.getActual = require('./getActual'); + +/*! + * Inspect util + */ + +exports.inspect = require('./inspect'); + +/*! + * Object Display util + */ + +exports.objDisplay = require('./objDisplay'); + +/*! + * Flag utility + */ + +exports.flag = require('./flag'); + +/*! + * Flag transferring utility + */ + +exports.transferFlags = require('./transferFlags'); + +/*! + * Deep equal utility + */ + +exports.eql = require('deep-eql'); + +/*! + * Deep path value + */ + +exports.getPathValue = require('./getPathValue'); + +/*! + * Function name + */ + +exports.getName = require('./getName'); + +/*! + * add Property + */ + +exports.addProperty = require('./addProperty'); + +/*! + * add Method + */ + +exports.addMethod = require('./addMethod'); + +/*! + * overwrite Property + */ + +exports.overwriteProperty = require('./overwriteProperty'); + +/*! + * overwrite Method + */ + +exports.overwriteMethod = require('./overwriteMethod'); + +/*! + * Add a chainable method + */ + +exports.addChainableMethod = require('./addChainableMethod'); + +/*! + * Overwrite chainable method + */ + +exports.overwriteChainableMethod = require('./overwriteChainableMethod'); + + +},{"./addChainableMethod":17,"./addMethod":18,"./addProperty":19,"./flag":20,"./getActual":21,"./getMessage":23,"./getName":24,"./getPathValue":25,"./inspect":28,"./objDisplay":29,"./overwriteChainableMethod":30,"./overwriteMethod":31,"./overwriteProperty":32,"./test":33,"./transferFlags":34,"./type":35,"deep-eql":37}],28:[function(require,module,exports){ +// This is (almost) directly from Node.js utils +// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js + +var getName = require('./getName'); +var getProperties = require('./getProperties'); +var getEnumerableProperties = require('./getEnumerableProperties'); + +module.exports = inspect; + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Boolean} showHidden Flag that shows hidden (not enumerable) + * properties of objects. + * @param {Number} depth Depth in which to descend in object. Default is 2. + * @param {Boolean} colors Flag to turn on ANSI escape codes to color the + * output. Default is false (no coloring). + */ +function inspect(obj, showHidden, depth, colors) { + var ctx = { + showHidden: showHidden, + seen: [], + stylize: function (str) { return str; } + }; + return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth)); +} + +// https://gist.github.com/1044128/ +var getOuterHTML = function(element) { + if ('outerHTML' in element) return element.outerHTML; + var ns = "http://www.w3.org/1999/xhtml"; + var container = document.createElementNS(ns, '_'); + var elemProto = (window.HTMLElement || window.Element).prototype; + var xmlSerializer = new XMLSerializer(); + var html; + if (document.xmlVersion) { + return xmlSerializer.serializeToString(element); + } else { + container.appendChild(element.cloneNode(false)); + html = container.innerHTML.replace('><', '>' + element.innerHTML + '<'); + container.innerHTML = ''; + return html; + } +}; + +// Returns true if object is a DOM element. +var isDOMElement = function (object) { + if (typeof HTMLElement === 'object') { + return object instanceof HTMLElement; + } else { + return object && + typeof object === 'object' && + object.nodeType === 1 && + typeof object.nodeName === 'string'; + } +}; + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (value && typeof value.inspect === 'function' && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes); + if (typeof ret !== 'string') { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // If it's DOM elem, get outer HTML. + if (isDOMElement(value)) { + return getOuterHTML(value); + } + + // Look up the keys of the object. + var visibleKeys = getEnumerableProperties(value); + var keys = ctx.showHidden ? getProperties(value) : visibleKeys; + + // Some type of object without properties can be shortcutted. + // In IE, errors have a single `stack` property, or if they are vanilla `Error`, + // a `stack` plus `description` property; ignore those for consistency. + if (keys.length === 0 || (isError(value) && ( + (keys.length === 1 && keys[0] === 'stack') || + (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack') + ))) { + if (typeof value === 'function') { + var name = getName(value); + var nameSuffix = name ? ': ' + name : ''; + return ctx.stylize('[Function' + nameSuffix + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toUTCString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (typeof value === 'function') { + var name = getName(value); + var nameSuffix = name ? ': ' + name : ''; + base = ' [Function' + nameSuffix + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + return formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + switch (typeof value) { + case 'undefined': + return ctx.stylize('undefined', 'undefined'); + + case 'string': + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + + case 'number': + return ctx.stylize('' + value, 'number'); + + case 'boolean': + return ctx.stylize('' + value, 'boolean'); + } + // For some reason typeof null is "object", so special case here. + if (value === null) { + return ctx.stylize('null', 'null'); + } +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (Object.prototype.hasOwnProperty.call(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str; + if (value.__lookupGetter__) { + if (value.__lookupGetter__(key)) { + if (value.__lookupSetter__(key)) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (value.__lookupSetter__(key)) { + str = ctx.stylize('[Setter]', 'special'); + } + } + } + if (visibleKeys.indexOf(key) < 0) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(value[key]) < 0) { + if (recurseTimes === null) { + str = formatValue(ctx, value[key], null); + } else { + str = formatValue(ctx, value[key], recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (typeof name === 'undefined') { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + +function isArray(ar) { + return Array.isArray(ar) || + (typeof ar === 'object' && objectToString(ar) === '[object Array]'); +} + +function isRegExp(re) { + return typeof re === 'object' && objectToString(re) === '[object RegExp]'; +} + +function isDate(d) { + return typeof d === 'object' && objectToString(d) === '[object Date]'; +} + +function isError(e) { + return typeof e === 'object' && objectToString(e) === '[object Error]'; +} + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +},{"./getEnumerableProperties":22,"./getName":24,"./getProperties":26}],29:[function(require,module,exports){ +/*! + * Chai - flag utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/*! + * Module dependancies + */ + +var inspect = require('./inspect'); +var config = require('../config'); + +/** + * ### .objDisplay (object) + * + * Determines if an object or an array matches + * criteria to be inspected in-line for error + * messages or should be truncated. + * + * @param {Mixed} javascript object to inspect + * @name objDisplay + * @api public + */ + +module.exports = function (obj) { + var str = inspect(obj) + , type = Object.prototype.toString.call(obj); + + if (config.truncateThreshold && str.length >= config.truncateThreshold) { + if (type === '[object Function]') { + return !obj.name || obj.name === '' + ? '[Function]' + : '[Function: ' + obj.name + ']'; + } else if (type === '[object Array]') { + return '[ Array(' + obj.length + ') ]'; + } else if (type === '[object Object]') { + var keys = Object.keys(obj) + , kstr = keys.length > 2 + ? keys.splice(0, 2).join(', ') + ', ...' + : keys.join(', '); + return '{ Object (' + kstr + ') }'; + } else { + return str; + } + } else { + return str; + } +}; + +},{"../config":12,"./inspect":28}],30:[function(require,module,exports){ +/*! + * Chai - overwriteChainableMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### overwriteChainableMethod (ctx, name, fn) + * + * Overwites an already existing chainable method + * and provides access to the previous function or + * property. Must return functions to be used for + * name. + * + * utils.overwriteChainableMethod(chai.Assertion.prototype, 'length', + * function (_super) { + * } + * , function (_super) { + * } + * ); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteChainableMethod('foo', fn, fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.have.length(3); + * expect(myFoo).to.have.length.above(3); + * + * @param {Object} ctx object whose method / property is to be overwritten + * @param {String} name of method / property to overwrite + * @param {Function} method function that returns a function to be used for name + * @param {Function} chainingBehavior function that returns a function to be used for property + * @name overwriteChainableMethod + * @api public + */ + +module.exports = function (ctx, name, method, chainingBehavior) { + var chainableBehavior = ctx.__methods[name]; + + var _chainingBehavior = chainableBehavior.chainingBehavior; + chainableBehavior.chainingBehavior = function () { + var result = chainingBehavior(_chainingBehavior).call(this); + return result === undefined ? this : result; + }; + + var _method = chainableBehavior.method; + chainableBehavior.method = function () { + var result = method(_method).apply(this, arguments); + return result === undefined ? this : result; + }; +}; + +},{}],31:[function(require,module,exports){ +/*! + * Chai - overwriteMethod utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### overwriteMethod (ctx, name, fn) + * + * Overwites an already existing method and provides + * access to previous function. Must return function + * to be used for name. + * + * utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) { + * return function (str) { + * var obj = utils.flag(this, 'object'); + * if (obj instanceof Foo) { + * new chai.Assertion(obj.value).to.equal(str); + * } else { + * _super.apply(this, arguments); + * } + * } + * }); + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteMethod('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.equal('bar'); + * + * @param {Object} ctx object whose method is to be overwritten + * @param {String} name of method to overwrite + * @param {Function} method function that returns a function to be used for name + * @name overwriteMethod + * @api public + */ + +module.exports = function (ctx, name, method) { + var _method = ctx[name] + , _super = function () { return this; }; + + if (_method && 'function' === typeof _method) + _super = _method; + + ctx[name] = function () { + var result = method(_super).apply(this, arguments); + return result === undefined ? this : result; + } +}; + +},{}],32:[function(require,module,exports){ +/*! + * Chai - overwriteProperty utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### overwriteProperty (ctx, name, fn) + * + * Overwites an already existing property getter and provides + * access to previous value. Must return function to use as getter. + * + * utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) { + * return function () { + * var obj = utils.flag(this, 'object'); + * if (obj instanceof Foo) { + * new chai.Assertion(obj.name).to.equal('bar'); + * } else { + * _super.call(this); + * } + * } + * }); + * + * + * Can also be accessed directly from `chai.Assertion`. + * + * chai.Assertion.overwriteProperty('foo', fn); + * + * Then can be used as any other assertion. + * + * expect(myFoo).to.be.ok; + * + * @param {Object} ctx object whose property is to be overwritten + * @param {String} name of property to overwrite + * @param {Function} getter function that returns a getter function to be used for name + * @name overwriteProperty + * @api public + */ + +module.exports = function (ctx, name, getter) { + var _get = Object.getOwnPropertyDescriptor(ctx, name) + , _super = function () {}; + + if (_get && 'function' === typeof _get.get) + _super = _get.get + + Object.defineProperty(ctx, name, + { get: function () { + var result = getter(_super).call(this); + return result === undefined ? this : result; + } + , configurable: true + }); +}; + +},{}],33:[function(require,module,exports){ +/*! + * Chai - test utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/*! + * Module dependancies + */ + +var flag = require('./flag'); + +/** + * # test(object, expression) + * + * Test and object for expression. + * + * @param {Object} object (constructed Assertion) + * @param {Arguments} chai.Assertion.prototype.assert arguments + */ + +module.exports = function (obj, args) { + var negate = flag(obj, 'negate') + , expr = args[0]; + return negate ? !expr : expr; +}; + +},{"./flag":20}],34:[function(require,module,exports){ +/*! + * Chai - transferFlags utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/** + * ### transferFlags(assertion, object, includeAll = true) + * + * Transfer all the flags for `assertion` to `object`. If + * `includeAll` is set to `false`, then the base Chai + * assertion flags (namely `object`, `ssfi`, and `message`) + * will not be transferred. + * + * + * var newAssertion = new Assertion(); + * utils.transferFlags(assertion, newAssertion); + * + * var anotherAsseriton = new Assertion(myObj); + * utils.transferFlags(assertion, anotherAssertion, false); + * + * @param {Assertion} assertion the assertion to transfer the flags from + * @param {Object} object the object to transfer the flags too; usually a new assertion + * @param {Boolean} includeAll + * @name getAllFlags + * @api private + */ + +module.exports = function (assertion, object, includeAll) { + var flags = assertion.__flags || (assertion.__flags = Object.create(null)); + + if (!object.__flags) { + object.__flags = Object.create(null); + } + + includeAll = arguments.length === 3 ? includeAll : true; + + for (var flag in flags) { + if (includeAll || + (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) { + object.__flags[flag] = flags[flag]; + } + } +}; + +},{}],35:[function(require,module,exports){ +/*! + * Chai - type utility + * Copyright(c) 2012-2014 Jake Luer + * MIT Licensed + */ + +/*! + * Detectable javascript natives + */ + +var natives = { + '[object Arguments]': 'arguments' + , '[object Array]': 'array' + , '[object Date]': 'date' + , '[object Function]': 'function' + , '[object Number]': 'number' + , '[object RegExp]': 'regexp' + , '[object String]': 'string' +}; + +/** + * ### type(object) + * + * Better implementation of `typeof` detection that can + * be used cross-browser. Handles the inconsistencies of + * Array, `null`, and `undefined` detection. + * + * utils.type({}) // 'object' + * utils.type(null) // `null' + * utils.type(undefined) // `undefined` + * utils.type([]) // `array` + * + * @param {Mixed} object to detect type of + * @name type + * @api private + */ + +module.exports = function (obj) { + var str = Object.prototype.toString.call(obj); + if (natives[str]) return natives[str]; + if (obj === null) return 'null'; + if (obj === undefined) return 'undefined'; + if (obj === Object(obj)) return 'object'; + return typeof obj; +}; + +},{}],36:[function(require,module,exports){ +/*! + * assertion-error + * Copyright(c) 2013 Jake Luer + * MIT Licensed + */ + +/*! + * Return a function that will copy properties from + * one object to another excluding any originally + * listed. Returned function will create a new `{}`. + * + * @param {String} excluded properties ... + * @return {Function} + */ + +function exclude () { + var excludes = [].slice.call(arguments); + + function excludeProps (res, obj) { + Object.keys(obj).forEach(function (key) { + if (!~excludes.indexOf(key)) res[key] = obj[key]; + }); + } + + return function extendExclude () { + var args = [].slice.call(arguments) + , i = 0 + , res = {}; + + for (; i < args.length; i++) { + excludeProps(res, args[i]); + } + + return res; + }; +}; + +/*! + * Primary Exports + */ + +module.exports = AssertionError; + +/** + * ### AssertionError + * + * An extension of the JavaScript `Error` constructor for + * assertion and validation scenarios. + * + * @param {String} message + * @param {Object} properties to include (optional) + * @param {callee} start stack function (optional) + */ + +function AssertionError (message, _props, ssf) { + var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON') + , props = extend(_props || {}); + + // default values + this.message = message || 'Unspecified AssertionError'; + this.showDiff = false; + + // copy from properties + for (var key in props) { + this[key] = props[key]; + } + + // capture stack trace + ssf = ssf || arguments.callee; + if (ssf && Error.captureStackTrace) { + Error.captureStackTrace(this, ssf); + } +} + +/*! + * Inherit from Error.prototype + */ + +AssertionError.prototype = Object.create(Error.prototype); + +/*! + * Statically set name + */ + +AssertionError.prototype.name = 'AssertionError'; + +/*! + * Ensure correct constructor + */ + +AssertionError.prototype.constructor = AssertionError; + +/** + * Allow errors to be converted to JSON for static transfer. + * + * @param {Boolean} include stack (default: `true`) + * @return {Object} object that can be `JSON.stringify` + */ + +AssertionError.prototype.toJSON = function (stack) { + var extend = exclude('constructor', 'toJSON', 'stack') + , props = extend({ name: this.name }, this); + + // include stack if exists and not turned off + if (false !== stack && this.stack) { + props.stack = this.stack; + } + + return props; +}; + +},{}],37:[function(require,module,exports){ +module.exports = require('./lib/eql'); + +},{"./lib/eql":38}],38:[function(require,module,exports){ +/*! + * deep-eql + * Copyright(c) 2013 Jake Luer + * MIT Licensed + */ + +/*! + * Module dependencies + */ + +var type = require('type-detect'); + +/*! + * Buffer.isBuffer browser shim + */ + +var Buffer; +try { Buffer = require('buffer').Buffer; } +catch(ex) { + Buffer = {}; + Buffer.isBuffer = function() { return false; } +} + +/*! + * Primary Export + */ + +module.exports = deepEqual; + +/** + * Assert super-strict (egal) equality between + * two objects of any type. + * + * @param {Mixed} a + * @param {Mixed} b + * @param {Array} memoised (optional) + * @return {Boolean} equal match + */ + +function deepEqual(a, b, m) { + if (sameValue(a, b)) { + return true; + } else if ('date' === type(a)) { + return dateEqual(a, b); + } else if ('regexp' === type(a)) { + return regexpEqual(a, b); + } else if (Buffer.isBuffer(a)) { + return bufferEqual(a, b); + } else if ('arguments' === type(a)) { + return argumentsEqual(a, b, m); + } else if (!typeEqual(a, b)) { + return false; + } else if (('object' !== type(a) && 'object' !== type(b)) + && ('array' !== type(a) && 'array' !== type(b))) { + return sameValue(a, b); + } else { + return objectEqual(a, b, m); + } +} + +/*! + * Strict (egal) equality test. Ensures that NaN always + * equals NaN and `-0` does not equal `+0`. + * + * @param {Mixed} a + * @param {Mixed} b + * @return {Boolean} equal match + */ + +function sameValue(a, b) { + if (a === b) return a !== 0 || 1 / a === 1 / b; + return a !== a && b !== b; +} + +/*! + * Compare the types of two given objects and + * return if they are equal. Note that an Array + * has a type of `array` (not `object`) and arguments + * have a type of `arguments` (not `array`/`object`). + * + * @param {Mixed} a + * @param {Mixed} b + * @return {Boolean} result + */ + +function typeEqual(a, b) { + return type(a) === type(b); +} + +/*! + * Compare two Date objects by asserting that + * the time values are equal using `saveValue`. + * + * @param {Date} a + * @param {Date} b + * @return {Boolean} result + */ + +function dateEqual(a, b) { + if ('date' !== type(b)) return false; + return sameValue(a.getTime(), b.getTime()); +} + +/*! + * Compare two regular expressions by converting them + * to string and checking for `sameValue`. + * + * @param {RegExp} a + * @param {RegExp} b + * @return {Boolean} result + */ + +function regexpEqual(a, b) { + if ('regexp' !== type(b)) return false; + return sameValue(a.toString(), b.toString()); +} + +/*! + * Assert deep equality of two `arguments` objects. + * Unfortunately, these must be sliced to arrays + * prior to test to ensure no bad behavior. + * + * @param {Arguments} a + * @param {Arguments} b + * @param {Array} memoize (optional) + * @return {Boolean} result + */ + +function argumentsEqual(a, b, m) { + if ('arguments' !== type(b)) return false; + a = [].slice.call(a); + b = [].slice.call(b); + return deepEqual(a, b, m); +} + +/*! + * Get enumerable properties of a given object. + * + * @param {Object} a + * @return {Array} property names + */ + +function enumerable(a) { + var res = []; + for (var key in a) res.push(key); + return res; +} + +/*! + * Simple equality for flat iterable objects + * such as Arrays or Node.js buffers. + * + * @param {Iterable} a + * @param {Iterable} b + * @return {Boolean} result + */ + +function iterableEqual(a, b) { + if (a.length !== b.length) return false; + + var i = 0; + var match = true; + + for (; i < a.length; i++) { + if (a[i] !== b[i]) { + match = false; + break; + } + } + + return match; +} + +/*! + * Extension to `iterableEqual` specifically + * for Node.js Buffers. + * + * @param {Buffer} a + * @param {Mixed} b + * @return {Boolean} result + */ + +function bufferEqual(a, b) { + if (!Buffer.isBuffer(b)) return false; + return iterableEqual(a, b); +} + +/*! + * Block for `objectEqual` ensuring non-existing + * values don't get in. + * + * @param {Mixed} object + * @return {Boolean} result + */ + +function isValue(a) { + return a !== null && a !== undefined; +} + +/*! + * Recursively check the equality of two objects. + * Once basic sameness has been established it will + * defer to `deepEqual` for each enumerable key + * in the object. + * + * @param {Mixed} a + * @param {Mixed} b + * @return {Boolean} result + */ + +function objectEqual(a, b, m) { + if (!isValue(a) || !isValue(b)) { + return false; + } + + if (a.prototype !== b.prototype) { + return false; + } + + var i; + if (m) { + for (i = 0; i < m.length; i++) { + if ((m[i][0] === a && m[i][1] === b) + || (m[i][0] === b && m[i][1] === a)) { + return true; + } + } + } else { + m = []; + } + + try { + var ka = enumerable(a); + var kb = enumerable(b); + } catch (ex) { + return false; + } + + ka.sort(); + kb.sort(); + + if (!iterableEqual(ka, kb)) { + return false; + } + + m.push([ a, b ]); + + var key; + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!deepEqual(a[key], b[key], m)) { + return false; + } + } + + return true; +} + +},{"buffer":41,"type-detect":39}],39:[function(require,module,exports){ +module.exports = require('./lib/type'); + +},{"./lib/type":40}],40:[function(require,module,exports){ +/*! + * type-detect + * Copyright(c) 2013 jake luer + * MIT Licensed + */ + +/*! + * Primary Exports + */ + +var exports = module.exports = getType; + +/*! + * Detectable javascript natives + */ + +var natives = { + '[object Array]': 'array' + , '[object RegExp]': 'regexp' + , '[object Function]': 'function' + , '[object Arguments]': 'arguments' + , '[object Date]': 'date' +}; + +/** + * ### typeOf (obj) + * + * Use several different techniques to determine + * the type of object being tested. + * + * + * @param {Mixed} object + * @return {String} object type + * @api public + */ + +function getType (obj) { + var str = Object.prototype.toString.call(obj); + if (natives[str]) return natives[str]; + if (obj === null) return 'null'; + if (obj === undefined) return 'undefined'; + if (obj === Object(obj)) return 'object'; + return typeof obj; +} + +exports.Library = Library; + +/** + * ### Library + * + * Create a repository for custom type detection. + * + * ```js + * var lib = new type.Library; + * ``` + * + */ + +function Library () { + this.tests = {}; +} + +/** + * #### .of (obj) + * + * Expose replacement `typeof` detection to the library. + * + * ```js + * if ('string' === lib.of('hello world')) { + * // ... + * } + * ``` + * + * @param {Mixed} object to test + * @return {String} type + */ + +Library.prototype.of = getType; + +/** + * #### .define (type, test) + * + * Add a test to for the `.test()` assertion. + * + * Can be defined as a regular expression: + * + * ```js + * lib.define('int', /^[0-9]+$/); + * ``` + * + * ... or as a function: + * + * ```js + * lib.define('bln', function (obj) { + * if ('boolean' === lib.of(obj)) return true; + * var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ]; + * if ('string' === lib.of(obj)) obj = obj.toLowerCase(); + * return !! ~blns.indexOf(obj); + * }); + * ``` + * + * @param {String} type + * @param {RegExp|Function} test + * @api public + */ + +Library.prototype.define = function (type, test) { + if (arguments.length === 1) return this.tests[type]; + this.tests[type] = test; + return this; +}; + +/** + * #### .test (obj, test) + * + * Assert that an object is of type. Will first + * check natives, and if that does not pass it will + * use the user defined custom tests. + * + * ```js + * assert(lib.test('1', 'int')); + * assert(lib.test('yes', 'bln')); + * ``` + * + * @param {Mixed} object + * @param {String} type + * @return {Boolean} result + * @api public + */ + +Library.prototype.test = function (obj, type) { + if (type === getType(obj)) return true; + var test = this.tests[type]; + + if (test && 'regexp' === getType(test)) { + return test.test(obj); + } else if (test && 'function' === getType(test)) { + return test(obj); + } else { + throw new ReferenceError('Type test "' + type + '" not defined or invalid.'); + } +}; + +},{}],41:[function(require,module,exports){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +var base64 = require('base64-js') +var ieee754 = require('ieee754') + +exports.Buffer = Buffer +exports.SlowBuffer = Buffer +exports.INSPECT_MAX_BYTES = 50 +Buffer.poolSize = 8192 + +/** + * If `Buffer._useTypedArrays`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (compatible down to IE6) + */ +Buffer._useTypedArrays = (function () { + // Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+, + // Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding + // properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support + // because we need to be able to add all the node Buffer API methods. This is an issue + // in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438 + try { + var buf = new ArrayBuffer(0) + var arr = new Uint8Array(buf) + arr.foo = function () { return 42 } + return 42 === arr.foo() && + typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray` + } catch (e) { + return false + } +})() + +/** + * Class: Buffer + * ============= + * + * The Buffer constructor returns instances of `Uint8Array` that are augmented + * with function properties for all the node `Buffer` API functions. We use + * `Uint8Array` so that square bracket notation works as expected -- it returns + * a single octet. + * + * By augmenting the instances, we can avoid modifying the `Uint8Array` + * prototype. + */ +function Buffer (subject, encoding, noZero) { + if (!(this instanceof Buffer)) + return new Buffer(subject, encoding, noZero) + + var type = typeof subject + + // Workaround: node's base64 implementation allows for non-padded strings + // while base64-js does not. + if (encoding === 'base64' && type === 'string') { + subject = stringtrim(subject) + while (subject.length % 4 !== 0) { + subject = subject + '=' + } + } + + // Find the length + var length + if (type === 'number') + length = coerce(subject) + else if (type === 'string') + length = Buffer.byteLength(subject, encoding) + else if (type === 'object') + length = coerce(subject.length) // assume that object is array-like + else + throw new Error('First argument needs to be a number, array or string.') + + var buf + if (Buffer._useTypedArrays) { + // Preferred: Return an augmented `Uint8Array` instance for best performance + buf = Buffer._augment(new Uint8Array(length)) + } else { + // Fallback: Return THIS instance of Buffer (created by `new`) + buf = this + buf.length = length + buf._isBuffer = true + } + + var i + if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') { + // Speed optimization -- use set if we're copying from a typed array + buf._set(subject) + } else if (isArrayish(subject)) { + // Treat array-ish objects as a byte array + for (i = 0; i < length; i++) { + if (Buffer.isBuffer(subject)) + buf[i] = subject.readUInt8(i) + else + buf[i] = subject[i] + } + } else if (type === 'string') { + buf.write(subject, 0, encoding) + } else if (type === 'number' && !Buffer._useTypedArrays && !noZero) { + for (i = 0; i < length; i++) { + buf[i] = 0 + } + } + + return buf +} + +// STATIC METHODS +// ============== + +Buffer.isEncoding = function (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'binary': + case 'base64': + case 'raw': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.isBuffer = function (b) { + return !!(b !== null && b !== undefined && b._isBuffer) +} + +Buffer.byteLength = function (str, encoding) { + var ret + str = str + '' + switch (encoding || 'utf8') { + case 'hex': + ret = str.length / 2 + break + case 'utf8': + case 'utf-8': + ret = utf8ToBytes(str).length + break + case 'ascii': + case 'binary': + case 'raw': + ret = str.length + break + case 'base64': + ret = base64ToBytes(str).length + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = str.length * 2 + break + default: + throw new Error('Unknown encoding') + } + return ret +} + +Buffer.concat = function (list, totalLength) { + assert(isArray(list), 'Usage: Buffer.concat(list, [totalLength])\n' + + 'list should be an Array.') + + if (list.length === 0) { + return new Buffer(0) + } else if (list.length === 1) { + return list[0] + } + + var i + if (typeof totalLength !== 'number') { + totalLength = 0 + for (i = 0; i < list.length; i++) { + totalLength += list[i].length + } + } + + var buf = new Buffer(totalLength) + var pos = 0 + for (i = 0; i < list.length; i++) { + var item = list[i] + item.copy(buf, pos) + pos += item.length + } + return buf +} + +// BUFFER INSTANCE METHODS +// ======================= + +function _hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + assert(strLen % 2 === 0, 'Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; i++) { + var byte = parseInt(string.substr(i * 2, 2), 16) + assert(!isNaN(byte), 'Invalid hex string') + buf[offset + i] = byte + } + Buffer._charsWritten = i * 2 + return i +} + +function _utf8Write (buf, string, offset, length) { + var charsWritten = Buffer._charsWritten = + blitBuffer(utf8ToBytes(string), buf, offset, length) + return charsWritten +} + +function _asciiWrite (buf, string, offset, length) { + var charsWritten = Buffer._charsWritten = + blitBuffer(asciiToBytes(string), buf, offset, length) + return charsWritten +} + +function _binaryWrite (buf, string, offset, length) { + return _asciiWrite(buf, string, offset, length) +} + +function _base64Write (buf, string, offset, length) { + var charsWritten = Buffer._charsWritten = + blitBuffer(base64ToBytes(string), buf, offset, length) + return charsWritten +} + +function _utf16leWrite (buf, string, offset, length) { + var charsWritten = Buffer._charsWritten = + blitBuffer(utf16leToBytes(string), buf, offset, length) + return charsWritten +} + +Buffer.prototype.write = function (string, offset, length, encoding) { + // Support both (string, offset, length, encoding) + // and the legacy (string, encoding, offset, length) + if (isFinite(offset)) { + if (!isFinite(length)) { + encoding = length + length = undefined + } + } else { // legacy + var swap = encoding + encoding = offset + offset = length + length = swap + } + + offset = Number(offset) || 0 + var remaining = this.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + encoding = String(encoding || 'utf8').toLowerCase() + + var ret + switch (encoding) { + case 'hex': + ret = _hexWrite(this, string, offset, length) + break + case 'utf8': + case 'utf-8': + ret = _utf8Write(this, string, offset, length) + break + case 'ascii': + ret = _asciiWrite(this, string, offset, length) + break + case 'binary': + ret = _binaryWrite(this, string, offset, length) + break + case 'base64': + ret = _base64Write(this, string, offset, length) + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = _utf16leWrite(this, string, offset, length) + break + default: + throw new Error('Unknown encoding') + } + return ret +} + +Buffer.prototype.toString = function (encoding, start, end) { + var self = this + + encoding = String(encoding || 'utf8').toLowerCase() + start = Number(start) || 0 + end = (end !== undefined) + ? Number(end) + : end = self.length + + // Fastpath empty strings + if (end === start) + return '' + + var ret + switch (encoding) { + case 'hex': + ret = _hexSlice(self, start, end) + break + case 'utf8': + case 'utf-8': + ret = _utf8Slice(self, start, end) + break + case 'ascii': + ret = _asciiSlice(self, start, end) + break + case 'binary': + ret = _binarySlice(self, start, end) + break + case 'base64': + ret = _base64Slice(self, start, end) + break + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + ret = _utf16leSlice(self, start, end) + break + default: + throw new Error('Unknown encoding') + } + return ret +} + +Buffer.prototype.toJSON = function () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function (target, target_start, start, end) { + var source = this + + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (!target_start) target_start = 0 + + // Copy 0 bytes; we're done + if (end === start) return + if (target.length === 0 || source.length === 0) return + + // Fatal error conditions + assert(end >= start, 'sourceEnd < sourceStart') + assert(target_start >= 0 && target_start < target.length, + 'targetStart out of bounds') + assert(start >= 0 && start < source.length, 'sourceStart out of bounds') + assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) + end = this.length + if (target.length - target_start < end - start) + end = target.length - target_start + start + + var len = end - start + + if (len < 100 || !Buffer._useTypedArrays) { + for (var i = 0; i < len; i++) + target[i + target_start] = this[i + start] + } else { + target._set(this.subarray(start, start + len), target_start) + } +} + +function _base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function _utf8Slice (buf, start, end) { + var res = '' + var tmp = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) { + if (buf[i] <= 0x7F) { + res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) + tmp = '' + } else { + tmp += '%' + buf[i].toString(16) + } + } + + return res + decodeUtf8Char(tmp) +} + +function _asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; i++) + ret += String.fromCharCode(buf[i]) + return ret +} + +function _binarySlice (buf, start, end) { + return _asciiSlice(buf, start, end) +} + +function _hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; i++) { + out += toHex(buf[i]) + } + return out +} + +function _utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i+1] * 256) + } + return res +} + +Buffer.prototype.slice = function (start, end) { + var len = this.length + start = clamp(start, len, 0) + end = clamp(end, len, len) + + if (Buffer._useTypedArrays) { + return Buffer._augment(this.subarray(start, end)) + } else { + var sliceLen = end - start + var newBuf = new Buffer(sliceLen, undefined, true) + for (var i = 0; i < sliceLen; i++) { + newBuf[i] = this[i + start] + } + return newBuf + } +} + +// `get` will be removed in Node 0.13+ +Buffer.prototype.get = function (offset) { + console.log('.get() is deprecated. Access using array indexes instead.') + return this.readUInt8(offset) +} + +// `set` will be removed in Node 0.13+ +Buffer.prototype.set = function (v, offset) { + console.log('.set() is deprecated. Access using array indexes instead.') + return this.writeUInt8(v, offset) +} + +Buffer.prototype.readUInt8 = function (offset, noAssert) { + if (!noAssert) { + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset < this.length, 'Trying to read beyond buffer length') + } + + if (offset >= this.length) + return + + return this[offset] +} + +function _readUInt16 (buf, offset, littleEndian, noAssert) { + if (!noAssert) { + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') + } + + var len = buf.length + if (offset >= len) + return + + var val + if (littleEndian) { + val = buf[offset] + if (offset + 1 < len) + val |= buf[offset + 1] << 8 + } else { + val = buf[offset] << 8 + if (offset + 1 < len) + val |= buf[offset + 1] + } + return val +} + +Buffer.prototype.readUInt16LE = function (offset, noAssert) { + return _readUInt16(this, offset, true, noAssert) +} + +Buffer.prototype.readUInt16BE = function (offset, noAssert) { + return _readUInt16(this, offset, false, noAssert) +} + +function _readUInt32 (buf, offset, littleEndian, noAssert) { + if (!noAssert) { + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') + } + + var len = buf.length + if (offset >= len) + return + + var val + if (littleEndian) { + if (offset + 2 < len) + val = buf[offset + 2] << 16 + if (offset + 1 < len) + val |= buf[offset + 1] << 8 + val |= buf[offset] + if (offset + 3 < len) + val = val + (buf[offset + 3] << 24 >>> 0) + } else { + if (offset + 1 < len) + val = buf[offset + 1] << 16 + if (offset + 2 < len) + val |= buf[offset + 2] << 8 + if (offset + 3 < len) + val |= buf[offset + 3] + val = val + (buf[offset] << 24 >>> 0) + } + return val +} + +Buffer.prototype.readUInt32LE = function (offset, noAssert) { + return _readUInt32(this, offset, true, noAssert) +} + +Buffer.prototype.readUInt32BE = function (offset, noAssert) { + return _readUInt32(this, offset, false, noAssert) +} + +Buffer.prototype.readInt8 = function (offset, noAssert) { + if (!noAssert) { + assert(offset !== undefined && offset !== null, + 'missing offset') + assert(offset < this.length, 'Trying to read beyond buffer length') + } + + if (offset >= this.length) + return + + var neg = this[offset] & 0x80 + if (neg) + return (0xff - this[offset] + 1) * -1 + else + return this[offset] +} + +function _readInt16 (buf, offset, littleEndian, noAssert) { + if (!noAssert) { + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') + } + + var len = buf.length + if (offset >= len) + return + + var val = _readUInt16(buf, offset, littleEndian, true) + var neg = val & 0x8000 + if (neg) + return (0xffff - val + 1) * -1 + else + return val +} + +Buffer.prototype.readInt16LE = function (offset, noAssert) { + return _readInt16(this, offset, true, noAssert) +} + +Buffer.prototype.readInt16BE = function (offset, noAssert) { + return _readInt16(this, offset, false, noAssert) +} + +function _readInt32 (buf, offset, littleEndian, noAssert) { + if (!noAssert) { + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') + } + + var len = buf.length + if (offset >= len) + return + + var val = _readUInt32(buf, offset, littleEndian, true) + var neg = val & 0x80000000 + if (neg) + return (0xffffffff - val + 1) * -1 + else + return val +} + +Buffer.prototype.readInt32LE = function (offset, noAssert) { + return _readInt32(this, offset, true, noAssert) +} + +Buffer.prototype.readInt32BE = function (offset, noAssert) { + return _readInt32(this, offset, false, noAssert) +} + +function _readFloat (buf, offset, littleEndian, noAssert) { + if (!noAssert) { + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') + } + + return ieee754.read(buf, offset, littleEndian, 23, 4) +} + +Buffer.prototype.readFloatLE = function (offset, noAssert) { + return _readFloat(this, offset, true, noAssert) +} + +Buffer.prototype.readFloatBE = function (offset, noAssert) { + return _readFloat(this, offset, false, noAssert) +} + +function _readDouble (buf, offset, littleEndian, noAssert) { + if (!noAssert) { + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset + 7 < buf.length, 'Trying to read beyond buffer length') + } + + return ieee754.read(buf, offset, littleEndian, 52, 8) +} + +Buffer.prototype.readDoubleLE = function (offset, noAssert) { + return _readDouble(this, offset, true, noAssert) +} + +Buffer.prototype.readDoubleBE = function (offset, noAssert) { + return _readDouble(this, offset, false, noAssert) +} + +Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { + if (!noAssert) { + assert(value !== undefined && value !== null, 'missing value') + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset < this.length, 'trying to write beyond buffer length') + verifuint(value, 0xff) + } + + if (offset >= this.length) return + + this[offset] = value +} + +function _writeUInt16 (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + assert(value !== undefined && value !== null, 'missing value') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset + 1 < buf.length, 'trying to write beyond buffer length') + verifuint(value, 0xffff) + } + + var len = buf.length + if (offset >= len) + return + + for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) { + buf[offset + i] = + (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } +} + +Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { + _writeUInt16(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { + _writeUInt16(this, value, offset, false, noAssert) +} + +function _writeUInt32 (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + assert(value !== undefined && value !== null, 'missing value') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset + 3 < buf.length, 'trying to write beyond buffer length') + verifuint(value, 0xffffffff) + } + + var len = buf.length + if (offset >= len) + return + + for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) { + buf[offset + i] = + (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } +} + +Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { + _writeUInt32(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { + _writeUInt32(this, value, offset, false, noAssert) +} + +Buffer.prototype.writeInt8 = function (value, offset, noAssert) { + if (!noAssert) { + assert(value !== undefined && value !== null, 'missing value') + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset < this.length, 'Trying to write beyond buffer length') + verifsint(value, 0x7f, -0x80) + } + + if (offset >= this.length) + return + + if (value >= 0) + this.writeUInt8(value, offset, noAssert) + else + this.writeUInt8(0xff + value + 1, offset, noAssert) +} + +function _writeInt16 (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + assert(value !== undefined && value !== null, 'missing value') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset + 1 < buf.length, 'Trying to write beyond buffer length') + verifsint(value, 0x7fff, -0x8000) + } + + var len = buf.length + if (offset >= len) + return + + if (value >= 0) + _writeUInt16(buf, value, offset, littleEndian, noAssert) + else + _writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert) +} + +Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { + _writeInt16(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { + _writeInt16(this, value, offset, false, noAssert) +} + +function _writeInt32 (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + assert(value !== undefined && value !== null, 'missing value') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') + verifsint(value, 0x7fffffff, -0x80000000) + } + + var len = buf.length + if (offset >= len) + return + + if (value >= 0) + _writeUInt32(buf, value, offset, littleEndian, noAssert) + else + _writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert) +} + +Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { + _writeInt32(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { + _writeInt32(this, value, offset, false, noAssert) +} + +function _writeFloat (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + assert(value !== undefined && value !== null, 'missing value') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') + verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + + var len = buf.length + if (offset >= len) + return + + ieee754.write(buf, value, offset, littleEndian, 23, 4) +} + +Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { + _writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { + _writeFloat(this, value, offset, false, noAssert) +} + +function _writeDouble (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + assert(value !== undefined && value !== null, 'missing value') + assert(typeof littleEndian === 'boolean', 'missing or invalid endian') + assert(offset !== undefined && offset !== null, 'missing offset') + assert(offset + 7 < buf.length, + 'Trying to write beyond buffer length') + verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + + var len = buf.length + if (offset >= len) + return + + ieee754.write(buf, value, offset, littleEndian, 52, 8) +} + +Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { + _writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { + _writeDouble(this, value, offset, false, noAssert) +} + +// fill(value, start=0, end=buffer.length) +Buffer.prototype.fill = function (value, start, end) { + if (!value) value = 0 + if (!start) start = 0 + if (!end) end = this.length + + if (typeof value === 'string') { + value = value.charCodeAt(0) + } + + assert(typeof value === 'number' && !isNaN(value), 'value is not a number') + assert(end >= start, 'end < start') + + // Fill 0 bytes; we're done + if (end === start) return + if (this.length === 0) return + + assert(start >= 0 && start < this.length, 'start out of bounds') + assert(end >= 0 && end <= this.length, 'end out of bounds') + + for (var i = start; i < end; i++) { + this[i] = value + } +} + +Buffer.prototype.inspect = function () { + var out = [] + var len = this.length + for (var i = 0; i < len; i++) { + out[i] = toHex(this[i]) + if (i === exports.INSPECT_MAX_BYTES) { + out[i + 1] = '...' + break + } + } + return '' +} + +/** + * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. + * Added in Node 0.12. Only available in browsers that support ArrayBuffer. + */ +Buffer.prototype.toArrayBuffer = function () { + if (typeof Uint8Array !== 'undefined') { + if (Buffer._useTypedArrays) { + return (new Buffer(this)).buffer + } else { + var buf = new Uint8Array(this.length) + for (var i = 0, len = buf.length; i < len; i += 1) + buf[i] = this[i] + return buf.buffer + } + } else { + throw new Error('Buffer.toArrayBuffer not supported in this browser') + } +} + +// HELPER FUNCTIONS +// ================ + +function stringtrim (str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') +} + +var BP = Buffer.prototype + +/** + * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods + */ +Buffer._augment = function (arr) { + arr._isBuffer = true + + // save reference to original Uint8Array get/set methods before overwriting + arr._get = arr.get + arr._set = arr.set + + // deprecated, will be removed in node 0.13+ + arr.get = BP.get + arr.set = BP.set + + arr.write = BP.write + arr.toString = BP.toString + arr.toLocaleString = BP.toString + arr.toJSON = BP.toJSON + arr.copy = BP.copy + arr.slice = BP.slice + arr.readUInt8 = BP.readUInt8 + arr.readUInt16LE = BP.readUInt16LE + arr.readUInt16BE = BP.readUInt16BE + arr.readUInt32LE = BP.readUInt32LE + arr.readUInt32BE = BP.readUInt32BE + arr.readInt8 = BP.readInt8 + arr.readInt16LE = BP.readInt16LE + arr.readInt16BE = BP.readInt16BE + arr.readInt32LE = BP.readInt32LE + arr.readInt32BE = BP.readInt32BE + arr.readFloatLE = BP.readFloatLE + arr.readFloatBE = BP.readFloatBE + arr.readDoubleLE = BP.readDoubleLE + arr.readDoubleBE = BP.readDoubleBE + arr.writeUInt8 = BP.writeUInt8 + arr.writeUInt16LE = BP.writeUInt16LE + arr.writeUInt16BE = BP.writeUInt16BE + arr.writeUInt32LE = BP.writeUInt32LE + arr.writeUInt32BE = BP.writeUInt32BE + arr.writeInt8 = BP.writeInt8 + arr.writeInt16LE = BP.writeInt16LE + arr.writeInt16BE = BP.writeInt16BE + arr.writeInt32LE = BP.writeInt32LE + arr.writeInt32BE = BP.writeInt32BE + arr.writeFloatLE = BP.writeFloatLE + arr.writeFloatBE = BP.writeFloatBE + arr.writeDoubleLE = BP.writeDoubleLE + arr.writeDoubleBE = BP.writeDoubleBE + arr.fill = BP.fill + arr.inspect = BP.inspect + arr.toArrayBuffer = BP.toArrayBuffer + + return arr +} + +// slice(start, end) +function clamp (index, len, defaultValue) { + if (typeof index !== 'number') return defaultValue + index = ~~index; // Coerce to integer. + if (index >= len) return len + if (index >= 0) return index + index += len + if (index >= 0) return index + return 0 +} + +function coerce (length) { + // Coerce length to a number (possibly NaN), round up + // in case it's fractional (e.g. 123.456) then do a + // double negate to coerce a NaN to 0. Easy, right? + length = ~~Math.ceil(+length) + return length < 0 ? 0 : length +} + +function isArray (subject) { + return (Array.isArray || function (subject) { + return Object.prototype.toString.call(subject) === '[object Array]' + })(subject) +} + +function isArrayish (subject) { + return isArray(subject) || Buffer.isBuffer(subject) || + subject && typeof subject === 'object' && + typeof subject.length === 'number' +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + var b = str.charCodeAt(i) + if (b <= 0x7F) + byteArray.push(str.charCodeAt(i)) + else { + var start = i + if (b >= 0xD800 && b <= 0xDFFF) i++ + var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%') + for (var j = 0; j < h.length; j++) + byteArray.push(parseInt(h[j], 16)) + } + } + return byteArray +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; i++) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; i++) { + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(str) +} + +function blitBuffer (src, dst, offset, length) { + var pos + for (var i = 0; i < length; i++) { + if ((i + offset >= dst.length) || (i >= src.length)) + break + dst[i + offset] = src[i] + } + return i +} + +function decodeUtf8Char (str) { + try { + return decodeURIComponent(str) + } catch (err) { + return String.fromCharCode(0xFFFD) // UTF 8 invalid char + } +} + +/* + * We have to make sure that the value is a valid integer. This means that it + * is non-negative. It has no fractional component and that it does not + * exceed the maximum allowed value. + */ +function verifuint (value, max) { + assert(typeof value === 'number', 'cannot write a non-number as a number') + assert(value >= 0, 'specified a negative value for writing an unsigned value') + assert(value <= max, 'value is larger than maximum value for type') + assert(Math.floor(value) === value, 'value has a fractional component') +} + +function verifsint (value, max, min) { + assert(typeof value === 'number', 'cannot write a non-number as a number') + assert(value <= max, 'value larger than maximum allowed value') + assert(value >= min, 'value smaller than minimum allowed value') + assert(Math.floor(value) === value, 'value has a fractional component') +} + +function verifIEEE754 (value, max, min) { + assert(typeof value === 'number', 'cannot write a non-number as a number') + assert(value <= max, 'value larger than maximum allowed value') + assert(value >= min, 'value smaller than minimum allowed value') +} + +function assert (test, message) { + if (!test) throw new Error(message || 'Failed assertion') +} + +},{"base64-js":42,"ieee754":43}],42:[function(require,module,exports){ +var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + +;(function (exports) { + 'use strict'; + + var Arr = (typeof Uint8Array !== 'undefined') + ? Uint8Array + : Array + + var PLUS = '+'.charCodeAt(0) + var SLASH = '/'.charCodeAt(0) + var NUMBER = '0'.charCodeAt(0) + var LOWER = 'a'.charCodeAt(0) + var UPPER = 'A'.charCodeAt(0) + + function decode (elt) { + var code = elt.charCodeAt(0) + if (code === PLUS) + return 62 // '+' + if (code === SLASH) + return 63 // '/' + if (code < NUMBER) + return -1 //no match + if (code < NUMBER + 10) + return code - NUMBER + 26 + 26 + if (code < UPPER + 26) + return code - UPPER + if (code < LOWER + 26) + return code - LOWER + 26 + } + + function b64ToByteArray (b64) { + var i, j, l, tmp, placeHolders, arr + + if (b64.length % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + var len = b64.length + placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 + + // base64 is 4/3 + up to two characters of the original data + arr = new Arr(b64.length * 3 / 4 - placeHolders) + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length + + var L = 0 + + function push (v) { + arr[L++] = v + } + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) + push((tmp & 0xFF0000) >> 16) + push((tmp & 0xFF00) >> 8) + push(tmp & 0xFF) + } + + if (placeHolders === 2) { + tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) + push(tmp & 0xFF) + } else if (placeHolders === 1) { + tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) + push((tmp >> 8) & 0xFF) + push(tmp & 0xFF) + } + + return arr + } + + function uint8ToBase64 (uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length + + function encode (num) { + return lookup.charAt(num) + } + + function tripletToBase64 (num) { + return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) + } + + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + output += tripletToBase64(temp) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1] + output += encode(temp >> 2) + output += encode((temp << 4) & 0x3F) + output += '==' + break + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) + output += encode(temp >> 10) + output += encode((temp >> 4) & 0x3F) + output += encode((temp << 2) & 0x3F) + output += '=' + break + } + + return output + } + + exports.toByteArray = b64ToByteArray + exports.fromByteArray = uint8ToBase64 +}(typeof exports === 'undefined' ? (this.base64js = {}) : exports)) + +},{}],43:[function(require,module,exports){ +exports.read = function(buffer, offset, isLE, mLen, nBytes) { + var e, m, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + nBits = -7, + i = isLE ? (nBytes - 1) : 0, + d = isLE ? -1 : 1, + s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity); + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; + +exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), + i = isLE ? 0 : (nBytes - 1), + d = isLE ? 1 : -1, + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e + eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); + + buffer[offset + i - d] |= s * 128; +}; + +},{}],44:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],45:[function(require,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; + +process.nextTick = (function () { + var canSetImmediate = typeof window !== 'undefined' + && window.setImmediate; + var canPost = typeof window !== 'undefined' + && window.postMessage && window.addEventListener + ; + + if (canSetImmediate) { + return function (f) { return window.setImmediate(f) }; + } + + if (canPost) { + var queue = []; + window.addEventListener('message', function (ev) { + var source = ev.source; + if ((source === window || source === null) && ev.data === 'process-tick') { + ev.stopPropagation(); + if (queue.length > 0) { + var fn = queue.shift(); + fn(); + } + } + }, true); + + return function nextTick(fn) { + queue.push(fn); + window.postMessage('process-tick', '*'); + }; + } + + return function nextTick(fn) { + setTimeout(fn, 0); + }; +})(); + +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +} + +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; + +},{}],46:[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],47:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = require('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = require('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,require("1YiZ5S"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":46,"1YiZ5S":45,"inherits":44}],48:[function(require,module,exports){ +(function (sinonChai) { + "use strict"; + + // Module systems magic dance. + + if (typeof require === "function" && typeof exports === "object" && typeof module === "object") { + // NodeJS + module.exports = sinonChai; + } else if (typeof define === "function" && define.amd) { + // AMD + define(function () { + return sinonChai; + }); + } else { + // Other environment (usually + - - - - - - - -

awesomewidget

- ]]> - diff --git a/dest/browser/Widgets/CollaborationWidget2.xml b/dest/browser/Widgets/CollaborationWidget2.xml deleted file mode 100644 index 0bb6946c..00000000 --- a/dest/browser/Widgets/CollaborationWidget2.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - -

awesomewidget

- ]]>
-
diff --git a/dest/browser/Widgets/iwc-teststub.xml b/dest/browser/Widgets/iwc-teststub.xml deleted file mode 100644 index d691c914..00000000 --- a/dest/browser/Widgets/iwc-teststub.xml +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - - - * { - font-family: Verdana; - font-size: 8pt; - } - - #accordion { - overflow: auto; - height: 310px; - } - - #pubform, .entry { - border: 1pt solid black - width: 100%; - } - - tr td.ui-state-default{ - width: 20%; - } - - tr td.input, tr td.ui-widget-content { - width: 80%; - } - - #pub_form tr td input { - width: 100%; - } - - #pub_form tr td textarea { - width: 100%; - } - - - - - - - - - - - - -

Received Intents

-
-
- -
- - - - - - - - - - -
Publisher
Source
Component
Action
Data
Data Type
Flags
Categories
Extras